8 #include "sll_assert.h"
9 #include "sll_memory.h"
10 #include "sll_working_precision.h"
52 sll_int32 :: spline_degree
61 sll_int32 :: boundary_particles = 0
62 sll_int32 :: counter_left = 0
63 sll_int32 :: counter_right = 0
64 logical :: boundary = .false.
65 sll_real64,
pointer :: rhob(:) => null()
67 logical :: electrostatic = .false.
69 sll_real64,
pointer :: efield_dofs(:,:)
70 sll_real64,
pointer :: bfield_dofs(:)
71 sll_real64,
allocatable :: j_dofs(:,:)
72 sll_real64,
allocatable :: j_dofs_local(:,:)
93 sll_real64,
intent(in) :: dt
94 sll_int32,
intent(in) :: number_steps
98 do i_step = 1, number_steps
99 call self%operatorHB(0.5_f64*dt)
100 call self%operatorHE(0.5_f64*dt)
101 call self%operatorHp(dt)
102 call self%operatorHE(0.5_f64*dt)
103 call self%operatorHB(0.5_f64*dt)
113 sll_real64,
intent(in) :: dt
114 sll_int32,
intent(in) :: number_steps
118 do i_step = 1,number_steps
119 call self%operatorHE(dt)
120 call self%operatorHB(dt)
121 call self%operatorHp(dt)
130 sll_real64,
intent(in) :: dt
131 sll_int32,
intent(in) :: number_steps
135 do i_step = 1,number_steps
136 call self%operatorHp(dt)
137 call self%operatorHB(dt)
138 call self%operatorHE(dt)
153 sll_real64,
intent(in) :: dt
155 sll_int32 :: i_part, i_sp
156 sll_real64 :: xnew(3), vi(3), wi(1), xi(3)
158 self%j_dofs_local = 0.0_f64
159 do i_sp = 1, self%particle_group%n_species
160 do i_part=1,self%particle_group%group(i_sp)%n_particles
162 xi = self%particle_group%group(i_sp)%get_x(i_part)
163 vi = self%particle_group%group(i_sp)%get_v(i_part)
169 wi = self%particle_group%group(i_sp)%get_charge(i_part)
172 call self%particle_group%group(i_sp)%set_x(i_part, xnew)
176 self%j_dofs = 0.0_f64
179 self%n_total1, mpi_sum, self%j_dofs(1:self%n_total1,1))
181 call self%maxwell_solver%compute_E_from_j(self%j_dofs(1:self%n_total1,1), 1, self%efield_dofs(1:self%n_total1,1))
185 self%n_total0, mpi_sum, self%j_dofs(:,2))
187 call self%maxwell_solver%compute_E_from_j(self%j_dofs(:,2), 2, self%efield_dofs(:,2))
195 sll_real64,
intent( in ) :: xold(1)
196 sll_real64,
intent( inout ) :: xnew(1)
197 sll_real64,
intent( inout ) :: vi(2)
198 sll_real64,
intent( in ) :: wi(1)
199 sll_real64,
intent( in ) :: dt
201 sll_real64 :: xmid(1), vh, xbar
203 if(xnew(1) < self%x_min .or. xnew(1) > self%x_max )
then
204 if(xnew(1) < self%x_min )
then
206 self%counter_left = self%counter_left+1
207 else if(xnew(1) > self%x_max)
then
209 self%counter_right = self%counter_right+1
215 call self%kernel_smoother_1%add_current( xold, xmid, wi(1), self%j_dofs_local(1:self%n_total1,1))
216 call self%kernel_smoother_0%add_current( xold, xmid, wi(1)*vh, self%j_dofs_local(:,2))
218 select case(self%boundary_particles)
220 xnew = 2._f64*xbar-xnew
223 call self%kernel_smoother_0%add_charge(xmid, wi(1), self%rhob)
225 call self%kernel_smoother_0%add_charge(xmid, wi(1), self%rhob)
226 xnew = self%x_min + modulo(xnew-self%x_min, self%Lx)
227 xmid = self%x_max+self%x_min-xbar
228 call self%kernel_smoother_0%add_charge(xmid, -wi(1), self%rhob)
230 call self%kernel_smoother_0%add_charge(xmid, wi(1), self%rhob)
231 xnew = self%x_min + modulo(xnew-self%x_min, self%Lx)
232 xmid = self%x_max+self%x_min-xbar
233 call self%kernel_smoother_0%add_charge(xmid, -wi(1), self%rhob)
235 if (xnew(1) >= self%x_min .and. xnew(1) <= self%x_max)
then
237 call self%kernel_smoother_1%add_current( xmid, xnew, wi(1), self%j_dofs_local(1:self%n_total1,1))
238 call self%kernel_smoother_0%add_current( xmid, xnew, wi(1)*vh, self%j_dofs_local(:,2))
241 if ( abs(vi(1))> 1d-16 )
then
243 call self%kernel_smoother_1%add_current( xold, xnew, wi(1), self%j_dofs_local(1:self%n_total1,1))
244 call self%kernel_smoother_0%add_current( xold, xnew, wi(1)*vi(2)/vi(1), self%j_dofs_local(:,2))
260 sll_real64,
intent(in) :: dt
262 sll_int32 :: i_part, i_sp
263 sll_real64 :: vi(3), xi(3)
264 sll_real64 :: efield(2)
267 do i_sp = 1, self%particle_group%n_species
268 qm = self%particle_group%group(i_sp)%species%q_over_m();
269 do i_part=1,self%particle_group%group(i_sp)%n_particles
270 vi = self%particle_group%group(i_sp)%get_v(i_part)
272 xi = self%particle_group%group(i_sp)%get_x(i_part)
273 call self%kernel_smoother_1%evaluate &
274 (xi(1), self%efield_dofs(1:self%n_total1,1), efield(1))
275 call self%kernel_smoother_0%evaluate &
276 (xi(1), self%efield_dofs(:,2), efield(2))
277 vi = self%particle_group%group(i_sp)%get_v(i_part)
279 vi(1:2) = vi(1:2) + dt* qm * efield
281 call self%particle_group%group(i_sp)%set_v(i_part, vi)
285 if(self%electrostatic .eqv. .false.)
then
287 call self%maxwell_solver%compute_B_from_E( &
288 dt, self%efield_dofs(:,2), self%bfield_dofs)
302 sll_real64,
intent(in) :: dt
304 sll_int32 :: i_part, i_sp
306 sll_real64 :: vi(3), v_new(3), xi(3)
307 sll_real64 :: bfield, cs, sn
310 do i_sp = 1, self%particle_group%n_species
311 qmdt = self%particle_group%group(i_sp)%species%q_over_m()*dt;
312 do i_part = 1, self%particle_group%group(i_sp)%n_particles
313 vi = self%particle_group%group(i_sp)%get_v(i_part)
314 xi = self%particle_group%group(i_sp)%get_x(i_part)
315 call self%kernel_smoother_1%evaluate &
316 (xi(1), self%bfield_dofs, bfield)
323 v_new(1) = cs * vi(1) + sn * vi(2)
324 v_new(2) = -sn* vi(1) + cs * vi(2)
326 call self%particle_group%group(i_sp)%set_v( i_part, v_new )
330 if(self%electrostatic .eqv. .false.)
then
332 call self%maxwell_solver%compute_E_from_B(&
333 dt, self%bfield_dofs, self%efield_dofs(:,2))
351 boundary_particles, &
359 sll_real64,
target,
intent(in) :: efield_dofs(:,:)
360 sll_real64,
target,
intent(in) :: bfield_dofs(:)
361 sll_real64,
intent(in) :: x_min
362 sll_real64,
intent(in) :: lx
363 sll_int32,
optional,
intent( in ) :: boundary_particles
364 logical,
optional,
intent( in ) :: electrostatic
365 sll_real64,
optional,
target,
intent( in ) :: rhob(:)
369 self%maxwell_solver => maxwell_solver
370 self%kernel_smoother_0 => kernel_smoother_0
371 self%kernel_smoother_1 => kernel_smoother_1
372 self%particle_group => particle_group
373 self%efield_dofs => efield_dofs
374 self%bfield_dofs => bfield_dofs
376 self%spline_degree = self%kernel_smoother_0%spline_degree
378 self%x_max = x_min + lx
380 self%delta_x = self%Lx/real(self%maxwell_solver%n_cells, f64)
382 self%n_cells = self%maxwell_solver%n_cells
383 self%n_total0 = self%maxwell_solver%n_dofs0
384 self%n_total1 = self%maxwell_solver%n_dofs1
387 sll_assert( self%kernel_smoother_0%n_cells == self%kernel_smoother_1%n_cells )
388 sll_assert( self%kernel_smoother_0%n_cells == self%maxwell_solver%n_cells )
390 sll_allocate(self%j_dofs(self%n_total0, 2), ierr)
391 sll_allocate(self%j_dofs_local(self%n_total0, 2), ierr)
393 if( self%n_cells+self%spline_degree == self%maxwell_solver%n_dofs0 )
then
394 self%boundary = .true.
395 self%boundary_particles = boundary_particles
398 if(
present(electrostatic) )
then
399 self%electrostatic = electrostatic
402 if(
present(rhob) )
then
413 if( self%boundary )
then
414 print*,
'left boundary', self%counter_left
415 print*,
'right boundary', self%counter_right
418 deallocate(self%j_dofs)
419 deallocate(self%j_dofs_local)
420 self%maxwell_solver => null()
421 self%kernel_smoother_0 => null()
422 self%kernel_smoother_1 => null()
423 self%particle_group => null()
424 self%efield_dofs => null()
425 self%bfield_dofs => null()
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.
Module interface to solve Maxwell's equations in 1D.
Base class for kernel smoothers for accumulation and field evaluation in PIC.
Base class for Hamiltonian splittings.
Particle pusher based on Hamiltonian splitting proposed by Crouseilles, Einkemmer,...
subroutine operatorhp_pic_vm_1d2v(self, dt)
Push Hp1: Equations to solve are \partial_t f + v_1 \partial_{x_1} f = 0 -> X_new = X_old + dt V_1 V_...
subroutine compute_particle_boundary_current(self, xold, xnew, vi, wi, dt)
Helper function for operatorHp.
subroutine lie_splitting_back_pic_vm_1d2v(self, dt, number_steps)
Lie splitting (oposite ordering)
subroutine strang_splitting_pic_vm_1d2v(self, dt, number_steps)
Finalization.
subroutine operatorhb_pic_vm_1d2v(self, dt)
Push H_B: Equations to be solved V_new = V_old \partial_t E_1 = 0 -> E_{1,new} = E_{1,...
subroutine operatorhe_pic_vm_1d2v(self, dt)
Push H_E: Equations to be solved \partial_t f + E_1 \partial_{v_1} f + E_2 \partial_{v_2} f = 0 -> V_...
subroutine initialize_pic_vm_1d2v(self, maxwell_solver, kernel_smoother_0, kernel_smoother_1, particle_group, efield_dofs, bfield_dofs, x_min, Lx, boundary_particles, electrostatic, rhob)
Constructor.
subroutine lie_splitting_pic_vm_1d2v(self, dt, number_steps)
Lie splitting.
subroutine delete_pic_vm_1d2v(self)
Destructor.
Particle pusher based on antisymmetric splitting with AVF for 3d3v Vlasov-Maxwell with coordinate tra...
integer(kind=i32), parameter, public sll_p_boundary_particles_periodic
integer(kind=i32), parameter, public sll_p_boundary_particles_reflection
integer(kind=i32), parameter, public sll_p_boundary_particles_absorption
integer(kind=i32), parameter, public sll_p_boundary_particles_singular
Basic type of a kernel smoother used for PIC simulations.
Type for Hamiltonian splittings.
Hamiltonian splitting type for Vlasov-Maxwell 1d2v.