7 #include "sll_assert.h"
8 #include "sll_memory.h"
9 #include "sll_working_precision.h"
25 sll_s_uniform_bsplines_eval_basis
55 sll_int32 :: spline_degree
58 sll_real64 :: domain(2)
62 sll_real64 :: cell_integrals_0(4)
63 sll_real64 :: cell_integrals_1(3)
66 sll_real64,
pointer :: efield_dofs(:,:)
67 sll_real64,
allocatable :: efield_dofs_local(:)
68 sll_real64,
pointer :: bfield_dofs(:)
69 sll_real64,
allocatable :: j_dofs(:,:)
70 sll_real64,
allocatable :: j_dofs_local(:,:)
71 sll_real64,
allocatable :: rho_dofs(:)
72 sll_real64,
allocatable :: rho_dofs_local(:)
75 sll_real64,
allocatable :: mass_line_0(:)
76 sll_real64,
allocatable :: mass_line_1(:)
78 sll_real64,
allocatable :: m1(:,:),m2(:,:),m4(:,:)
79 sll_real64,
allocatable :: m1_local(:,:),m2_local(:,:),m4_local(:,:)
103 sll_real64,
intent(in) :: dt
104 sll_int32,
intent(in) :: number_steps
108 do i_step = 1, number_steps
109 call self%advect_x(dt*0.5_f64)
110 call self%advect_e(dt)
111 call self%advect_x(dt*0.5_f64)
121 sll_real64,
intent(in) :: dt
122 sll_int32,
intent(in) :: number_steps
126 do i_step = 1, number_steps
127 call self%advect_x(dt)
128 call self%advect_e(dt)
137 sll_real64,
intent(in) :: dt
138 sll_int32,
intent(in) :: number_steps
142 do i_step = 1, number_steps
143 call self%advect_e(dt)
144 call self%advect_x(dt)
152 sll_real64,
intent(in) :: dt
154 sll_int32 :: i_part, i_sp
155 sll_real64 :: xi(3), vi(3)
157 do i_sp = 1,self%particle_group%n_species
158 do i_part=1,self%particle_group%group(i_sp)%n_particles
160 xi = self%particle_group%group(i_sp)%get_x(i_part)
161 vi = self%particle_group%group(i_sp)%get_v(i_part)
163 xi(1) = xi(1) + dt * vi(1)
164 xi(1) = modulo(xi(1), self%Lx)
165 call self%particle_group%group(i_sp)%set_x ( i_part, xi )
174 sll_real64,
intent(in) :: dt
176 sll_int32 :: i_part, i_sp
177 sll_real64 :: vi(3),v_new(3), xi(3), wi
178 sll_real64 :: qm, beta
180 sll_real64 :: efield(2), bfield
181 sll_real64 :: scratch(3*self%n_dofs)
182 sll_real64 :: rhs(3*self%n_dofs)
185 self%linear_operator%dt=dt
186 self%linear_operator%dx=self%delta_x
188 self%j_dofs_local = 0.0_f64
189 self%j_dofs = 0.0_f64
190 self%rho_dofs_local = 0.0_f64
191 self%rho_dofs = 0.0_f64
195 self%m1_local=0.0_f64
196 self%m2_local=0.0_f64
197 self%m4_local=0.0_f64
204 do i_sp = 1, self%particle_group%n_species
205 qm = self%particle_group%group(i_sp)%species%q_over_m();
207 do i_part = 1,self%particle_group%group(i_sp)%n_particles
209 vi = self%particle_group%group(i_sp)%get_v(i_part)
210 xi = self%particle_group%group(i_sp)%get_x(i_part)
213 wi = self%particle_group%group(i_sp)%get_charge(i_part)
214 call self%kernel_smoother_1%evaluate &
215 (xi(1), self%bfield_dofs, bfield)
216 mu=(1+(beta*bfield)**2.0_f64)
219 call self%kernel_smoother_1%add_charge( xi(1), wi*(vi(1)+vi(2)*beta* bfield)/mu, self%j_dofs_local(:,1) )
222 call self%kernel_smoother_0%add_charge( xi(1), wi*(vi(2)-vi(1)*beta* bfield)/mu, self%j_dofs_local(:,2) )
225 call self%kernel_smoother_1%add_particle_mass( xi(1), (beta*wi)/mu,self%m1_local)
227 call add_particle_mass_mixed_spline_1d(self, self%kernel_smoother_0, self%spline_degree, self%spline_degree-1, xi(1), -(beta**2.0_f64*wi*bfield)/mu,self%m2_local)
229 call self%kernel_smoother_0%add_particle_mass( xi(1), (beta*wi)/mu,self%m4_local)
238 self%kernel_smoother_1%n_dofs, mpi_sum, self%j_dofs(:,1) )
240 self%kernel_smoother_1%n_dofs, mpi_sum, self%j_dofs(:,2) )
242 self%kernel_smoother_1%n_dofs*self%spline_degree, mpi_sum, self%m1 )
244 self%kernel_smoother_0%n_dofs*2*self%spline_degree, mpi_sum, self%m2 )
246 self%kernel_smoother_0%n_dofs* (self%spline_degree+1), mpi_sum, self%m4 )
250 call self%linear_solver%set_guess([self%efield_dofs(:,1),self%efield_dofs(:,2),self%bfield_dofs])
251 call self%linear_solver%solve(rhs, scratch)
254 self%efield_dofs(:,1)=0.5_f64*(scratch(1:self%n_dofs)+self%efield_dofs(:,1))
255 self%efield_dofs(:,2)=0.5_f64*(scratch(self%n_dofs+1:2*self%n_dofs)+self%efield_dofs(:,2))
259 do i_sp = 1, self%particle_group%n_species
260 qm = self%particle_group%group(i_sp)%species%q_over_m();
262 do i_part = 1,self%particle_group%group(i_sp)%n_particles
264 vi = self%particle_group%group(i_sp)%get_v(i_part)
265 xi = self%particle_group%group(i_sp)%get_x(i_part)
267 call self%kernel_smoother_1%evaluate &
268 (xi(1), self%bfield_dofs, bfield)
269 mu=1+(beta*bfield)**2.0_f64
270 call self%kernel_smoother_1%evaluate &
271 (xi(1), self%efield_dofs(:,1), efield(1))
272 call self%kernel_smoother_0%evaluate &
273 (xi(1), self%efield_dofs(:,2), efield(2))
276 v_new(1)=(vi(1)+beta*efield(1)+beta*bfield*(vi(2)+beta*efield(2)))/mu
277 v_new(2)=(vi(2)+beta*efield(2)-beta*bfield*(vi(1)+beta*efield(1)))/mu
280 v_new(1)=2.0_f64*v_new(1)-vi(1)
281 v_new(2)=2.0_f64*v_new(2)-vi(2)
283 call self%particle_group%group(i_sp)%set_v(i_part, v_new)
288 self%efield_dofs(:,1)= scratch(1:self%n_dofs)
289 self%efield_dofs(:,2)= scratch(self%n_dofs+1:2*self%n_dofs)
290 self%bfield_dofs= scratch(2*self%n_dofs+1:3*self%n_dofs)
300 sll_int32,
intent( in ) :: degree1
301 sll_int32,
intent( in ) :: degree2
302 sll_real64,
intent( in ) :: position(self%kernel_smoother_1%dim)
303 sll_real64,
intent( in ) :: marker_charge
304 sll_real64,
intent( inout ) :: particle_mass(:,:)
306 sll_int32 :: i1, column
307 sll_int32 :: index1d, index
309 sll_real64 :: spline_val1(degree1+1)
310 sll_real64 :: spline_val2(degree2+1)
312 sll_assert(
size(particle_mass,1) == degree1+degree2+1 )
313 sll_assert(
size(particle_mass,2) == kernel_smoother%n_dofs )
315 xi(1) = (position(1) - self%x_min)/self%delta_x
316 index = ceiling(xi(1))
317 xi(1) = xi(1) - real(index-1, f64)
318 index = index - degree1
321 call sll_s_uniform_bsplines_eval_basis(degree1, xi(1), spline_val1)
322 call sll_s_uniform_bsplines_eval_basis(degree2, xi(1), spline_val2)
325 index1d = modulo(index+i1-2,kernel_smoother%n_cells)+1
326 do column = 1, degree2+1
327 particle_mass(column+degree1+1-i1, index1d) = particle_mass(column+degree1+1-i1, index1d)+ &
328 marker_charge * spline_val1(i1) * spline_val2(column)
338 sll_real64,
intent(in) :: dt
339 sll_real64,
intent(out):: rhs(3*self%n_dofs)
341 sll_int32 :: row, column
342 sll_real64 :: scratch(self%n_dofs+1)
345 do row=1, self%n_dofs
347 rhs(row) = (self%mass_line_1(1)-0.5_f64*dt*self%m1(1,row))*self%efield_dofs(row,1)-dt*self%j_dofs(row,1)
348 rhs(self%n_dofs+row)= (self%mass_line_0(1)-0.5_f64*dt*self%m4(1,row))*self%efield_dofs(row,2)-dt*self%j_dofs(row,2)
349 scratch(row)=self%mass_line_1(1)*self%bfield_dofs(row)
350 do column = 2, self%spline_degree
351 rhs(row) = rhs(row) +&
352 self%mass_line_1(column) * &
353 (self%efield_dofs(modulo(row+column-2,self%n_dofs)+1,1) +&
354 self%efield_dofs(modulo(row-column,self%n_dofs)+1,1))-&
355 0.5_f64*dt*self%m1(column,row) * &
356 self%efield_dofs(modulo(row+column-2,self%n_dofs)+1,1)-&
357 0.5_f64*dt*self%m1(column,modulo(row-column,self%n_dofs)+1) * &
358 self%efield_dofs(modulo(row-column,self%n_dofs)+1,1)
360 scratch(row)=scratch(row)+&
361 self%mass_line_1(column) * &
362 (self%bfield_dofs(modulo(row+column-2,self%n_dofs)+1) +&
363 self%bfield_dofs(modulo(row-column,self%n_dofs)+1))
365 do column = 2, self%spline_degree+1
366 rhs(self%n_dofs+row) = rhs(self%n_dofs+row) +&
367 self%mass_line_0(column) * &
368 (self%efield_dofs(modulo(row+column-2,self%n_dofs)+1,2) +&
369 self%efield_dofs(modulo(row-column,self%n_dofs)+1,2))-&
370 0.5_f64*dt*self%m4(column,row)*&
371 self%efield_dofs(modulo(row+column-2,self%n_dofs)+1,2)-&
372 0.5_f64*dt*self%m4(column,modulo(row-column,self%n_dofs)+1)*&
373 self%efield_dofs(modulo(row-column,self%n_dofs)+1,2)
376 do column = 1, 2*self%spline_degree
377 rhs(row) = rhs(row) + &
378 0.5_f64*dt*self%m2(7-column,modulo(column-4+row-1,self%n_dofs)+1) *&
379 self%efield_dofs(modulo(row+column-self%spline_degree-2,self%n_dofs)+1,2)
380 rhs(row+self%n_dofs) = rhs(row+self%n_dofs) - &
381 0.5_f64*dt*self%m2(column,row) *&
382 self%efield_dofs(modulo(row+column-self%spline_degree-1,self%n_dofs)+1,1)
385 scratch(self%n_dofs+1)=scratch(1)
386 do row=1, self%n_dofs
388 rhs(self%n_dofs+row)= rhs(self%n_dofs+row)+&
389 0.5_f64*dt/self%delta_x*(scratch(row)-scratch(row+1))
391 rhs(2*self%n_dofs+row)=self%bfield_dofs(row)-&
392 0.5_f64*dt/self%delta_x*(self%efield_dofs(row,2)-self%efield_dofs(modulo(row-2,self%n_dofs)+1,2))
413 sll_real64,
target,
intent(in) :: efield_dofs(:,:)
414 sll_real64,
target,
intent(in) :: bfield_dofs(:)
415 sll_real64,
intent(in) :: x_min
416 sll_real64,
intent(in) :: lx
417 character(len=*),
intent(in) :: filename
419 sll_int32 :: input_file
421 sll_real64 :: maxwell_tolerance
423 namelist /time_solver/ maxwell_tolerance
426 open(newunit = input_file, file=filename, status=
'old',iostat=io_stat)
427 if (io_stat /= 0)
then
428 print*,
'sll_m_time_propagator_pic_vm_1d2v_ecsim: Input file does not exist. Set default tolerance.'
429 call self%init( kernel_smoother_0, &
437 read(input_file, time_solver)
438 call self%init( kernel_smoother_0, &
445 solver_tolerance=maxwell_tolerance)
469 sll_real64,
target,
intent(in) :: efield_dofs(:,:)
470 sll_real64,
target,
intent(in) :: bfield_dofs(:)
471 sll_real64,
intent(in) :: x_min
472 sll_real64,
intent(in) :: lx
473 sll_real64,
intent(in),
optional :: solver_tolerance
478 self%kernel_smoother_0 => kernel_smoother_0
479 self%kernel_smoother_1 => kernel_smoother_1
480 self%particle_group => particle_group
481 self%efield_dofs => efield_dofs
482 self%bfield_dofs => bfield_dofs
485 sll_assert( self%kernel_smoother_0%n_dofs == self%kernel_smoother_1%n_dofs )
486 sll_allocate(self%j_dofs(self%kernel_smoother_0%n_dofs,2), ierr)
487 sll_allocate(self%j_dofs_local(self%kernel_smoother_0%n_dofs,2), ierr)
489 self%spline_degree = self%kernel_smoother_0%spline_degree
492 self%domain=[x_min,x_min+lx]
493 self%delta_x = self%Lx/real(self%kernel_smoother_1%n_dofs, f64)
494 self%n_dofs=self%kernel_smoother_1%n_dofs
496 self%cell_integrals_1 = [0.5_f64, 2.0_f64, 0.5_f64]
497 self%cell_integrals_1 = self%cell_integrals_1 / 3.0_f64
499 self%cell_integrals_0 = [1.0_f64,11.0_f64,11.0_f64,1.0_f64]
500 self%cell_integrals_0 = self%cell_integrals_0 / 24.0_f64
503 allocate( self%mass_line_0( self%spline_degree +1) )
504 allocate( self%mass_line_1( self%spline_degree ) )
509 self%mass_line_0 = self%mass_line_0 * self%delta_x
510 self%mass_line_1 = self%mass_line_1 * self%delta_x
513 sll_allocate(self%rho_dofs(self%kernel_smoother_0%n_dofs), ierr)
514 sll_allocate(self%rho_dofs_local(self%kernel_smoother_0%n_dofs), ierr)
515 sll_allocate(self%efield_dofs_local(self%kernel_smoother_1%n_dofs), ierr)
517 allocate(self%m1(self%spline_degree,self%kernel_smoother_1%n_dofs))
518 allocate(self%m2(2*self%spline_degree,self%kernel_smoother_0%n_dofs))
519 allocate(self%m4(self%spline_degree+1,self%kernel_smoother_0%n_dofs))
520 allocate(self%m1_local(self%spline_degree,self%kernel_smoother_1%n_dofs))
521 allocate(self%m2_local(2*self%spline_degree,self%kernel_smoother_0%n_dofs))
522 allocate(self%m4_local(self%spline_degree+1,self%kernel_smoother_0%n_dofs))
523 call self%linear_operator%create(self%n_dofs, self%spline_degree, self%mass_line_0,self%mass_line_1, self%m1, self%m2, self%m4)
526 call self%linear_solver%create(self%linear_operator)
527 if (
present(solver_tolerance))
then
528 self%linear_solver%rtol= solver_tolerance
529 self%linear_solver%atol= solver_tolerance
531 self%linear_solver%rtol= 1d-12
532 self%linear_solver%atol= 1d-12
542 deallocate(self%j_dofs)
543 deallocate(self%j_dofs_local)
547 deallocate(self%m1_local)
548 deallocate(self%m2_local)
549 deallocate(self%m4_local)
550 self%kernel_smoother_0 => null()
551 self%kernel_smoother_1 => null()
552 self%particle_group => null()
553 self%efield_dofs => null()
554 self%bfield_dofs => null()
557 call self%linear_operator%free()
558 call self%linear_solver%free()
Combines values from all processes and distributes the result back to all processes.
type(sll_t_collective_t), pointer, public sll_v_world_collective
Control of subset assignment. Processes with the same color are in the same new communicator.
Gauss-Legendre integration.
real(kind=f64) function, dimension(2, 1:npoints), public sll_f_gauss_legendre_points_and_weights(npoints, a, b)
Returns a 2d array of size (2,npoints) containing gauss-legendre points and weights in the interval [...
module for a sequential gmres
Low level arbitrary degree splines.
Base class for kernel smoothers for accumulation and field evaluation in PIC.
Utilites for Maxwell solver's with spline finite elements.
subroutine, public sll_s_spline_fem_mass_line(degree, mass_line)
Computes the mass line for a mass matrix with degree splines.
Base class for Hamiltonian splittings.
Particle pusher based on Lapentas splitting in Ecsim for 1d2v Vlasov-Poisson.
subroutine initialize_pic_vm_1d2v_ecsim(self, kernel_smoother_0, kernel_smoother_1, particle_group, efield_dofs, bfield_dofs, x_min, Lx, solver_tolerance)
Constructor.
subroutine righthandside(self, dt, rhs)
calculation of the righthandside of the system of maxwellequations for halftimestep
subroutine lie_splitting_pic_vm_1d2v_ecsim(self, dt, number_steps)
Lie splitting.
subroutine strang_splitting_pic_vm_1d2v_ecsim(self, dt, number_steps)
Finalization.
subroutine add_particle_mass_mixed_spline_1d(self, kernel_smoother, degree1, degree2, position, marker_charge, particle_mass)
Add charge of one particle for splines of different degrees.
subroutine initialize_file_pic_vm_1d2v_ecsim(self, kernel_smoother_0, kernel_smoother_1, particle_group, efield_dofs, bfield_dofs, x_min, Lx, filename)
Constructor.
subroutine advect_x_pic_vm_1d2v_ecsim(self, dt)
subroutine lie_splitting_back_pic_vm_1d2v_ecsim(self, dt, number_steps)
Lie splitting.
subroutine advect_e_pic_vm_1d2v_ecsim(self, dt)
subroutine delete_pic_vm_1d2v_ecsim(self)
Destructor.
class for a sequential gmres linear solver
Basic type of a kernel smoother used for PIC simulations.
Type for Hamiltonian splittings.
Hamiltonian splitting type for Vlasov-Maxwell 1d2v.