7 #include "sll_assert.h"
8 #include "sll_memory.h"
9 #include "sll_working_precision.h"
25 sll_s_uniform_bsplines_eval_basis
58 sll_int32 :: spline_degree
61 sll_real64 :: domain(2)
65 sll_real64 :: cell_integrals_0(4)
66 sll_real64 :: cell_integrals_1(3)
69 sll_real64,
pointer :: efield_dofs(:,:)
70 sll_real64,
allocatable :: efield_dofs_local(:)
71 sll_real64,
pointer :: bfield_dofs(:)
72 sll_real64,
allocatable :: j_dofs(:,:)
73 sll_real64,
allocatable :: j_dofs_local(:,:)
74 sll_real64,
allocatable :: rho_dofs(:)
75 sll_real64,
allocatable :: rho_dofs_local(:)
78 sll_real64,
allocatable :: mass_line_0(:)
79 sll_real64,
allocatable :: mass_line_1(:)
81 sll_real64,
allocatable :: m1(:,:),m2(:,:),m4(:,:)
82 sll_real64,
allocatable :: m1_local(:,:),m2_local(:,:),m4_local(:,:)
106 sll_real64,
intent(in) :: dt
107 sll_int32,
intent(in) :: number_steps
111 do i_step = 1, number_steps
112 call self%advect_x(dt*0.5_f64)
113 call self%advect_eb(dt*0.5_f64)
114 call self%advect_ev(dt)
115 call self%advect_eb(dt*0.5_f64)
116 call self%advect_x(dt*0.5_f64)
126 sll_real64,
intent(in) :: dt
127 sll_int32,
intent(in) :: number_steps
131 do i_step = 1, number_steps
132 call self%advect_x(dt)
133 call self%advect_eb(dt)
134 call self%advect_ev(dt)
143 sll_real64,
intent(in) :: dt
144 sll_int32,
intent(in) :: number_steps
148 do i_step = 1, number_steps
149 call self%advect_ev(dt)
150 call self%advect_eb(dt)
151 call self%advect_x(dt)
159 sll_real64,
intent(in) :: dt
161 sll_int32 :: i_part, i_sp
162 sll_real64 :: xi(3), vi(3)
164 do i_sp = 1,self%particle_group%n_species
165 do i_part=1,self%particle_group%group(i_sp)%n_particles
167 xi = self%particle_group%group(i_sp)%get_x(i_part)
168 vi = self%particle_group%group(i_sp)%get_v(i_part)
170 xi(1) = xi(1) + dt * vi(1)
171 xi(1) = modulo(xi(1), self%Lx)
172 call self%particle_group%group(i_sp)%set_x ( i_part, xi )
181 sll_real64,
intent(in) :: dt
182 sll_real64 :: rhs(2*self%n_dofs)
183 sll_real64 :: scratch(2*self%n_dofs)
184 self%linear_operator_eb%dt=dt
185 self%linear_operator_eb%dx=self%delta_x
189 call self%linear_solver_eb%set_guess([self%efield_dofs(:,2),self%bfield_dofs])
190 call self%linear_solver_eb%solve(rhs, scratch)
192 self%efield_dofs(:,2)=scratch(1:self%n_dofs)
193 self%bfield_dofs= scratch(self%n_dofs+1:2*self%n_dofs)
201 sll_real64,
intent(in) :: dt
203 sll_int32 :: i_part, i_sp
204 sll_real64 :: vi(3),v_new(3), xi(3), wi
205 sll_real64 :: qm, beta
207 sll_real64 :: efield(2), bfield
208 sll_real64 :: scratch(2*self%n_dofs)
209 sll_real64 :: rhs(2*self%n_dofs)
211 self%linear_operator_ev%dt=dt
212 self%linear_operator_ev%dx=self%delta_x
214 self%j_dofs_local = 0.0_f64
215 self%j_dofs = 0.0_f64
216 self%rho_dofs_local = 0.0_f64
217 self%rho_dofs = 0.0_f64
221 self%m1_local=0.0_f64
222 self%m2_local=0.0_f64
223 self%m4_local=0.0_f64
230 do i_sp = 1, self%particle_group%n_species
231 qm = self%particle_group%group(i_sp)%species%q_over_m();
233 do i_part = 1,self%particle_group%group(i_sp)%n_particles
235 vi = self%particle_group%group(i_sp)%get_v(i_part)
236 xi = self%particle_group%group(i_sp)%get_x(i_part)
239 wi = self%particle_group%group(i_sp)%get_charge(i_part)
240 call self%kernel_smoother_1%evaluate &
241 (xi(1), self%bfield_dofs, bfield)
242 mu=(1+(beta*bfield)**2.0_f64)
245 call self%kernel_smoother_1%add_charge( xi(1), wi*(vi(1)+vi(2)*beta* bfield)/mu, self%j_dofs_local(:,1) )
248 call self%kernel_smoother_0%add_charge( xi(1), wi*(vi(2)-vi(1)*beta* bfield)/mu, self%j_dofs_local(:,2) )
251 call self%kernel_smoother_1%add_particle_mass( xi(1), (beta*wi)/mu,self%m1_local)
253 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)
255 call self%kernel_smoother_0%add_particle_mass( xi(1), (beta*wi)/mu,self%m4_local)
262 self%kernel_smoother_1%n_dofs, mpi_sum, self%j_dofs(:,1) )
264 self%kernel_smoother_1%n_dofs, mpi_sum, self%j_dofs(:,2) )
266 self%kernel_smoother_1%n_dofs*self%spline_degree, mpi_sum, self%m1 )
268 self%kernel_smoother_0%n_dofs*2*self%spline_degree, mpi_sum, self%m2 )
270 self%kernel_smoother_0%n_dofs* (self%spline_degree+1), mpi_sum, self%m4 )
274 call self%linear_solver_ev%set_guess([self%efield_dofs(:,1),self%efield_dofs(:,2)])
275 call self%linear_solver_ev%solve(rhs, scratch)
278 self%efield_dofs(:,1)=0.5_f64*(scratch(1:self%n_dofs)+self%efield_dofs(:,1))
279 self%efield_dofs(:,2)=0.5_f64*(scratch(self%n_dofs+1:2*self%n_dofs)+self%efield_dofs(:,2))
283 do i_sp = 1, self%particle_group%n_species
284 qm = self%particle_group%group(i_sp)%species%q_over_m();
286 do i_part = 1,self%particle_group%group(i_sp)%n_particles
288 vi = self%particle_group%group(i_sp)%get_v(i_part)
289 xi = self%particle_group%group(i_sp)%get_x(i_part)
291 call self%kernel_smoother_1%evaluate &
292 (xi(1), self%bfield_dofs, bfield)
293 mu=1+(beta*bfield)**2.0_f64
294 call self%kernel_smoother_1%evaluate &
295 (xi(1), self%efield_dofs(:,1), efield(1))
296 call self%kernel_smoother_0%evaluate &
297 (xi(1), self%efield_dofs(:,2), efield(2))
300 v_new(1)=(vi(1)+beta*efield(1)+beta*bfield*(vi(2)+beta*efield(2)))/mu
301 v_new(2)=(vi(2)+beta*efield(2)-beta*bfield*(vi(1)+beta*efield(1)))/mu
304 v_new(1)=2.0_f64*v_new(1)-vi(1)
305 v_new(2)=2.0_f64*v_new(2)-vi(2)
307 call self%particle_group%group(i_sp)%set_v(i_part, v_new)
312 self%efield_dofs(:,1)= scratch(1:self%n_dofs)
313 self%efield_dofs(:,2)= scratch(self%n_dofs+1:2*self%n_dofs)
323 sll_int32,
intent( in ) :: degree1
324 sll_int32,
intent( in ) :: degree2
325 sll_real64,
intent( in ) :: position(self%kernel_smoother_1%dim)
326 sll_real64,
intent( in ) :: marker_charge
327 sll_real64,
intent( inout ) :: particle_mass(:,:)
329 sll_int32 :: i1, column
330 sll_int32 :: index1d, index
332 sll_real64 :: spline_val1(degree1+1)
333 sll_real64 :: spline_val2(degree2+1)
335 sll_assert(
size(particle_mass,1) == degree1+degree2+1 )
336 sll_assert(
size(particle_mass,2) == kernel_smoother%n_dofs )
338 xi(1) = (position(1) - self%x_min)/self%delta_x
339 index = ceiling(xi(1))
340 xi(1) = xi(1) - real(index-1, f64)
341 index = index - degree1
344 call sll_s_uniform_bsplines_eval_basis(degree1, xi(1), spline_val1)
345 call sll_s_uniform_bsplines_eval_basis(degree2, xi(1), spline_val2)
348 index1d = modulo(index+i1-2,kernel_smoother%n_cells)+1
349 do column = 1, degree2+1
350 particle_mass(column+degree1+1-i1, index1d) = particle_mass(column+degree1+1-i1, index1d)+ &
351 marker_charge * spline_val1(i1) * spline_val2(column)
360 sll_real64,
intent(in) :: dt
361 sll_real64,
intent(out):: rhs(2*self%n_dofs)
363 sll_int32 :: row, column
364 sll_real64 :: scratch(self%n_dofs+1)
367 do row=1, self%n_dofs
369 rhs(row)= self%mass_line_0(1)*self%efield_dofs(row,2)
370 scratch(row)=self%mass_line_1(1)*self%bfield_dofs(row)
371 do column = 2, self%spline_degree
372 scratch(row)=scratch(row)+&
373 self%mass_line_1(column) * &
374 (self%bfield_dofs(modulo(row+column-2,self%n_dofs)+1) +&
375 self%bfield_dofs(modulo(row-column,self%n_dofs)+1))
377 do column = 2, self%spline_degree+1
378 rhs(row) = rhs(row) +&
379 self%mass_line_0(column) * &
380 (self%efield_dofs(modulo(row+column-2,self%n_dofs)+1,2) +&
381 self%efield_dofs(modulo(row-column,self%n_dofs)+1,2))
385 scratch(self%n_dofs+1)=scratch(1)
386 do row=1, self%n_dofs
389 0.5_f64*dt/self%delta_x*(scratch(row)-scratch(row+1))
391 rhs(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))
402 sll_real64,
intent(in) :: dt
403 sll_real64,
intent(out):: rhs(2*self%n_dofs)
405 sll_int32 :: row, column
407 do row=1, self%n_dofs
409 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)
410 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)
412 do column = 2, self%spline_degree
413 rhs(row) = rhs(row) +&
414 self%mass_line_1(column) * &
415 (self%efield_dofs(modulo(row+column-2,self%n_dofs)+1,1) +&
416 self%efield_dofs(modulo(row-column,self%n_dofs)+1,1))-&
417 0.5_f64*dt*self%m1(column,row) * &
418 self%efield_dofs(modulo(row+column-2,self%n_dofs)+1,1)-&
419 0.5_f64*dt*self%m1(column,modulo(row-column,self%n_dofs)+1) * &
420 self%efield_dofs(modulo(row-column,self%n_dofs)+1,1)
423 do column = 2, self%spline_degree+1
424 rhs(self%n_dofs+row) = rhs(self%n_dofs+row) +&
425 self%mass_line_0(column) * &
426 (self%efield_dofs(modulo(row+column-2,self%n_dofs)+1,2) +&
427 self%efield_dofs(modulo(row-column,self%n_dofs)+1,2))-&
428 0.5_f64*dt*self%m4(column,row)*&
429 self%efield_dofs(modulo(row+column-2,self%n_dofs)+1,2)-&
430 0.5_f64*dt*self%m4(column,modulo(row-column,self%n_dofs)+1)*&
431 self%efield_dofs(modulo(row-column,self%n_dofs)+1,2)
434 do column = 1, 2*self%spline_degree
435 rhs(row) = rhs(row) + &
436 0.5_f64*dt*self%m2(7-column,modulo(column-4+row-1,self%n_dofs)+1) *&
437 self%efield_dofs(modulo(row+column-self%spline_degree-2,self%n_dofs)+1,2)
438 rhs(row+self%n_dofs) = rhs(row+self%n_dofs) - &
439 0.5_f64*dt*self%m2(column,row) *&
440 self%efield_dofs(modulo(row+column-self%spline_degree-1,self%n_dofs)+1,1)
465 sll_real64,
target,
intent(in) :: efield_dofs(:,:)
466 sll_real64,
target,
intent(in) :: bfield_dofs(:)
467 sll_real64,
intent(in) :: x_min
468 sll_real64,
intent(in) :: lx
469 sll_real64,
intent(in),
optional :: solver_tolerance
474 self%kernel_smoother_0 => kernel_smoother_0
475 self%kernel_smoother_1 => kernel_smoother_1
476 self%particle_group => particle_group
477 self%efield_dofs => efield_dofs
478 self%bfield_dofs => bfield_dofs
481 sll_assert( self%kernel_smoother_0%n_dofs == self%kernel_smoother_1%n_dofs )
482 sll_allocate(self%j_dofs(self%kernel_smoother_0%n_dofs,2), ierr)
483 sll_allocate(self%j_dofs_local(self%kernel_smoother_0%n_dofs,2), ierr)
485 self%spline_degree = self%kernel_smoother_0%spline_degree
488 self%domain=[x_min,x_min+lx]
489 self%delta_x = self%Lx/real(self%kernel_smoother_1%n_dofs,f64)
490 self%n_dofs=self%kernel_smoother_1%n_dofs
492 self%cell_integrals_1 = [0.5_f64, 2.0_f64, 0.5_f64]
493 self%cell_integrals_1 = self%cell_integrals_1 / 3.0_f64
495 self%cell_integrals_0 = [1.0_f64,11.0_f64,11.0_f64,1.0_f64]
496 self%cell_integrals_0 = self%cell_integrals_0 / 24.0_f64
499 allocate( self%mass_line_0( self%spline_degree +1) )
500 allocate( self%mass_line_1( self%spline_degree ) )
505 self%mass_line_0 = self%mass_line_0 * self%delta_x
506 self%mass_line_1 = self%mass_line_1 * self%delta_x
509 sll_allocate(self%rho_dofs(self%kernel_smoother_0%n_dofs), ierr)
510 sll_allocate(self%rho_dofs_local(self%kernel_smoother_0%n_dofs), ierr)
511 sll_allocate(self%efield_dofs_local(self%kernel_smoother_1%n_dofs), ierr)
513 allocate(self%m1(self%spline_degree,self%kernel_smoother_1%n_dofs))
514 allocate(self%m2(2*self%spline_degree,self%kernel_smoother_0%n_dofs))
515 allocate(self%m4(self%spline_degree+1,self%kernel_smoother_0%n_dofs))
516 allocate(self%m1_local(self%spline_degree,self%kernel_smoother_1%n_dofs))
517 allocate(self%m2_local(2*self%spline_degree,self%kernel_smoother_0%n_dofs))
518 allocate(self%m4_local(self%spline_degree+1,self%kernel_smoother_0%n_dofs))
520 call self%linear_operator_eb%create(self%n_dofs, self%spline_degree, &
521 self%mass_line_0,self%mass_line_1)
522 call self%linear_operator_ev%create(self%n_dofs, self%spline_degree, &
523 self%mass_line_0,self%mass_line_1, self%m1, self%m2, self%m4)
525 call self%linear_solver_eb%create(self%linear_operator_eb)
526 call self%linear_solver_ev%create(self%linear_operator_ev)
528 if (
present(solver_tolerance))
then
529 self%linear_solver_eb%rtol= solver_tolerance
530 self%linear_solver_eb%atol= solver_tolerance
531 self%linear_solver_ev%rtol= solver_tolerance
532 self%linear_solver_ev%atol= solver_tolerance
534 self%linear_solver_eb%rtol= 1e-14_f64
535 self%linear_solver_eb%atol= 1e-14_f64
536 self%linear_solver_ev%rtol= 1e-14_f64
537 self%linear_solver_ev%atol= 1e-14_f64
548 deallocate(self%j_dofs)
549 deallocate(self%j_dofs_local)
553 deallocate(self%m1_local)
554 deallocate(self%m2_local)
555 deallocate(self%m4_local)
556 self%kernel_smoother_0 => null()
557 self%kernel_smoother_1 => null()
558 self%particle_group => null()
559 self%efield_dofs => null()
560 self%bfield_dofs => null()
562 call self%linear_operator_eb%free()
563 call self%linear_solver_eb%free()
564 call self%linear_operator_ev%free()
565 call self%linear_solver_ev%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 advect_x_pic_vm_1d2v_ecsim2o(self, dt)
subroutine advect_ev_pic_vm_1d2v_ecsim2o(self, dt)
subroutine delete_pic_vm_1d2v_ecsim2o(self)
Destructor.
subroutine righthandside_ev(self, dt, rhs)
calculation of the righthandside of the system of maxwellequations
subroutine initialize_pic_vm_1d2v_ecsim2o(self, kernel_smoother_0, kernel_smoother_1, particle_group, efield_dofs, bfield_dofs, x_min, Lx, solver_tolerance)
Constructor.
subroutine advect_eb_pic_vm_1d2v_ecsim2o(self, dt)
subroutine lie_splitting_back_pic_vm_1d2v_ecsim2o(self, dt, number_steps)
Lie splitting.
subroutine strang_splitting_pic_vm_1d2v_ecsim2o(self, dt, number_steps)
Finalization.
subroutine lie_splitting_pic_vm_1d2v_ecsim2o(self, dt, number_steps)
Lie splitting.
subroutine righthandside_eb(self, dt, rhs)
calculation of the righthandside of the system of maxwellequations
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.
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.