Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_time_propagator_pic_vm_1d2v_trafo_helper.F90
Go to the documentation of this file.
1 
6  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 #include "sll_assert.h"
8 #include "sll_errors.h"
9 #include "sll_memory.h"
10 #include "sll_working_precision.h"
11 
12  use sll_m_collective, only: &
16 
19 
20  use sll_m_mapping_3d, only: &
22 
23  use sll_m_matrix_csr, only: &
25 
26  use sll_m_maxwell_1d_base, only: &
28 
29  use mpi, only: &
30  mpi_sum, &
31  mpi_max
32 
33  use sll_m_particle_group_base, only: &
35 
36  use sll_m_particle_mass_1d_base, only: &
38 
41 
44 
47 
50 
51  use sll_m_linear_solver_cg, only : &
53 
54  use sll_m_spline_fem_utilities, only : &
56 
59 
65 
66 
67  implicit none
68 
69  public :: &
71 
72  private
73  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
74 
77  class(sll_c_maxwell_1d_base), pointer :: maxwell_solver
78  class(sll_c_particle_mesh_coupling_1d), pointer :: kernel_smoother_0
79  class(sll_c_particle_mesh_coupling_1d), pointer :: kernel_smoother_1
80  class(sll_t_particle_array), pointer :: particle_group
81 
82  class( sll_c_particle_mass_1d_base ), allocatable :: particle_mass_1
83  class( sll_c_particle_mass_1d_base ), allocatable :: particle_mass_0
84  type( sll_t_linear_operator_schur_ev_1d ) :: linear_operator_1
85  type(sll_t_linear_solver_cg) :: linear_solver_1
86  type( sll_t_linear_operator_schur_ev_1d ) :: linear_operator_0
87  type(sll_t_linear_solver_cg) :: linear_solver_0
88 
89  type(sll_t_mapping_3d), pointer :: map
90 
91  sll_int32 :: spline_degree
92  sll_real64 :: lx
93  sll_real64 :: x_min
94  sll_int32 :: n_cells
95  sll_int32 :: n_dofs0
96  sll_int32 :: n_dofs1
97 
98  sll_real64, pointer :: efield_dofs(:,:)
99  sll_real64, pointer :: bfield_dofs(:)
100  sll_real64, allocatable :: j_dofs(:,:)
101  sll_real64, allocatable :: j_dofs_local(:,:)
102  sll_real64, allocatable :: particle_mass_0_local(:,:)
103  sll_real64, allocatable :: particle_mass_1_local(:,:)
104 
105  sll_int32 :: n_particles_max
106  sll_real64, allocatable :: xnew(:,:)
107  sll_real64, allocatable :: vnew(:,:,:)
108  sll_real64, allocatable :: efield_dofs_new(:,:)
109  sll_real64, allocatable :: efield_dofs_work(:,:)
110 
111  sll_int32 :: boundary_particles = 100
112  sll_int32 :: counter_left = 0
113  sll_int32 :: counter_right = 0
114  logical :: boundary = .false.
115  sll_real64, pointer :: rhob(:) => null()
116  sll_real64 :: force_sign = 1._f64
117  logical :: jmean = .false.
118 
119  sll_real64 :: solver_tolerance = 1d-12
120 
121 
122  sll_int32 :: max_iter = 10
123  sll_real64 :: iter_tolerance = 1d-10
124 
125  sll_int32 :: n_failed = 0
126  sll_int32 :: iter_counter = 0
127  sll_int32 :: niter(100000)
128 
129  contains
130  procedure :: advect_x => advect_x_pic_vm_1d2v_trafo
131  procedure :: advect_vb => advect_vb_pic_vm_1d2v_trafo
132  procedure :: advect_eb => advect_eb_pic_vm_1d2v_trafo
133  procedure :: advect_e => advect_e_pic_vm_1d2v_trafo
134  procedure :: advect_ex => advect_ex_pic_vm_1d2v_trafo
135 
136  procedure :: init => initialize_pic_vm_1d2v_trafo
137  procedure :: init_from_file => initialize_file_pic_vm_1d2v_trafo
138  procedure :: free => delete_pic_vm_1d2v_trafo
139 
141 
142 contains
143 
144 
145  !---------------------------------------------------------------------------!
148  subroutine advect_x_pic_vm_1d2v_trafo ( self, dt )
149  class(sll_t_time_propagator_pic_vm_1d2v_trafo_helper), intent( inout ) :: self
150  sll_real64, intent( in ) :: dt
151  !local variables
152  sll_int32 :: i_part, i_sp, i
153  sll_real64 :: xi(3), xnew(3), vi(3), vt, matrix(3,3), xs
154  sll_real64 :: err
155 
156  do i_sp=1,self%particle_group%n_species
157  do i_part=1,self%particle_group%group(i_sp)%n_particles
158  ! Read out particle position and velocity
159  xi = self%particle_group%group(i_sp)%get_x(i_part)
160  vi = self%particle_group%group(i_sp)%get_v(i_part)
161 
162  matrix=self%map%jacobian_matrix_inverse( [xi(1), 0._f64, 0._f64] )
163  !Transformation of the v_1 coordinate
164  vt = matrix(1,1) * vi(1)
165  !x^\star=\mod(x^n+dt*DF^{-1}(x^n)v^n,1)
166  xs = xi(1) + dt * vt
167  xnew = xi
168  xnew(1) = xs
169  i = 0
170  err= abs(xi(1) - xs)
171  do while(i < self%max_iter .and. err > self%iter_tolerance)
172  call compute_particle_boundary( self, xi(1), xs, vi(2) )
173  matrix=self%map%jacobian_matrix_inverse( [xs, 0._f64, 0._f64] )
174  xs = xi(1) + 0.5_f64 * dt * (vt + matrix(1,1) * vi(1) )
175  err = abs(xs - xnew(1))
176  xnew(1) = xs
177  i = i + 1
178  end do
179  call compute_particle_boundary( self, xi(1), xnew(1), vi(1) )
180 
181  call self%particle_group%group(i_sp)%set_x ( i_part, xnew )
182  call self%particle_group%group(i_sp)%set_v ( i_part, vi )
183  end do
184  end do
185 
186  end subroutine advect_x_pic_vm_1d2v_trafo
187 
188 
190  subroutine compute_particle_boundary( self, xold, xnew, vi )
191  class(sll_t_time_propagator_pic_vm_1d2v_trafo_helper), intent( inout ) :: self
192  sll_real64, intent( inout ) :: xold
193  sll_real64, intent( inout ) :: xnew
194  sll_real64, intent( inout ) :: vi
195  !local variables
196  sll_real64 :: xmid, xbar, dx
197 
198  if(xnew < -1._f64 .or. xnew > 2._f64)then
199  print*, xnew
200  sll_error("particle boundary", "particle out of bound")
201  else if(xnew < 0._f64 .or. xnew > 1._f64 )then
202  if(xnew < 0._f64 )then
203  xbar = 0._f64
204  self%counter_left = self%counter_left+1
205  else if(xnew > 1._f64)then
206  xbar = 1._f64
207  self%counter_right = self%counter_right+1
208  end if
209  dx = (xbar- xold)/(xnew-xold)
210  xmid = xold + dx * (xnew-xold)
211  xmid = xbar
212 
213  select case(self%boundary_particles)
215  vi = -vi
216  xnew = 2._f64*xbar-xnew
219  xnew = modulo(xnew, 1._f64)
220  case default
221  xnew = modulo(xnew, 1._f64)
222  end select
223  end if
224 
225  end subroutine compute_particle_boundary
226 
227 
228  !---------------------------------------------------------------------------!
231  subroutine advect_vb_pic_vm_1d2v_trafo ( self, dt )
232  class(sll_t_time_propagator_pic_vm_1d2v_trafo_helper), intent( inout ) :: self
233  sll_real64, intent( in ) :: dt
234  !local variables
235  sll_int32 :: i_part, i_sp
236  sll_real64 :: qmdt
237  sll_real64 :: vi(3), vnew(3), xi(3), factor(3,3)
238  sll_real64 :: bfield, cs, sn
239 
240  do i_sp=1,self%particle_group%n_species
241  qmdt = self%particle_group%group(i_sp)%species%q_over_m()*dt;
242 
243  do i_part = 1, self%particle_group%group(i_sp)%n_particles
244  vi = self%particle_group%group(i_sp)%get_v(i_part)
245  xi = self%particle_group%group(i_sp)%get_x(i_part)
246 
247  call self%kernel_smoother_1%evaluate(xi(1), self%bfield_dofs, bfield)
248 
249  factor=self%map%jacobian_matrix( [xi(1), 0._f64, 0._f64])/self%map%jacobian( [xi(1), 0._f64, 0._f64])*qmdt
250 
251  cs = cos(factor(3,3)*bfield)
252  sn = sin(factor(3,3)*bfield)
253 
254  vnew(1) = cs * vi(1) + sn * vi(2)
255  vnew(2) = -sn* vi(1) + cs * vi(2)
256 
257  call self%particle_group%group(i_sp)%set_v( i_part, vnew )
258  end do
259  end do
260 
261  end subroutine advect_vb_pic_vm_1d2v_trafo
262 
263 
264  !---------------------------------------------------------------------------!
269  subroutine advect_eb_pic_vm_1d2v_trafo ( self, dt )
270  class(sll_t_time_propagator_pic_vm_1d2v_trafo_helper), intent( inout ) :: self
271  sll_real64, intent( in ) :: dt
272 
273  call self%maxwell_solver%compute_curl_part( dt, self%efield_dofs(:,2), self%bfield_dofs )
274 
275 
276  end subroutine advect_eb_pic_vm_1d2v_trafo
277 
278 
279  !---------------------------------------------------------------------------!
284  subroutine advect_e_pic_vm_1d2v_trafo ( self, dt )
285  class(sll_t_time_propagator_pic_vm_1d2v_trafo_helper), intent( inout ) :: self
286  sll_real64, intent( in ) :: dt
287  ! local variables
288  sll_int32 :: i_part, i_sp, j
289  sll_real64 :: vi(3), xi(3), wi(1)
290  sll_real64 :: qoverm, jmat(3,3), metric, factor
291  sll_real64 :: efield(2)
292  sll_real64 :: rhs0(self%n_dofs0)
293  sll_real64 :: rhs1(self%n_dofs1)
294 
295  ! Set to zero
296  self%j_dofs_local = 0.0_f64
297  self%particle_mass_1_local = 0.0_f64
298  self%particle_mass_0_local = 0.0_f64
299 
300  ! First particle loop
301  do i_sp = 1, self%particle_group%n_species
302  qoverm = self%particle_group%group(i_sp)%species%q_over_m();
303  factor = dt**2 * 0.25_f64* qoverm
304  do i_part = 1, self%particle_group%group(i_sp)%n_particles
305  vi = self%particle_group%group(i_sp)%get_v(i_part)
306  xi = self%particle_group%group(i_sp)%get_x(i_part)
307 
308  ! Get charge for accumulation of j
309  wi = self%particle_group%group(i_sp)%get_charge(i_part)
310 
311  metric= self%map%metric_inverse_single( [xi(1), 0._f64, 0._f64], 1, 1 )
312  jmat=self%map%jacobian_matrix_inverse( [xi(1), 0._f64, 0._f64] )
313 
314  ! Accumulate the particle mass matrix diagonals
315  call self%kernel_smoother_1%add_particle_mass_full( xi(1), wi(1) * metric * factor, &
316  self%particle_mass_1_local )
317  call self%kernel_smoother_0%add_particle_mass_full( xi(1), wi(1) * factor , &
318  self%particle_mass_0_local )
319 
320  ! Accumulate jx
321  call self%kernel_smoother_1%add_charge( xi(1), wi(1)*jmat(1,1)*vi(1), &
322  self%j_dofs_local(1:self%n_dofs1,1) )
323  ! Accumulate jy
324  call self%kernel_smoother_0%add_charge( xi(1), wi(1)*vi(2), &
325  self%j_dofs_local(:,2) )
326 
327  ! Evaulate E_x and E_y at particle position and propagate v a half step
328  call self%kernel_smoother_1%evaluate &
329  ( xi(1), self%efield_dofs(1:self%n_dofs1,1), efield(1) )
330  call self%kernel_smoother_0%evaluate &
331  ( xi(1), self%efield_dofs(:,2), efield(2))
332 
333  ! velocity update with jacobian matrix, matrix is not transposed
334  do j= 1, 2
335  vi(j) = vi(j) + dt* 0.5_f64* qoverm *(jmat(1,j)* efield(1)+jmat(2,j)* efield(2))
336  end do
337 
338  call self%particle_group%group(i_sp)%set_v( i_part, vi )
339  end do
340  end do
341 
342  self%j_dofs = 0.0_f64
343  self%particle_mass_0%particle_mass = 0.0_f64
344  self%particle_mass_1%particle_mass = 0.0_f64
345 
346  ! MPI to sum up contributions from each processor
347  call sll_o_collective_allreduce( sll_v_world_collective, self%j_dofs_local(1:self%n_dofs1,1), &
348  self%n_dofs1, mpi_sum, self%j_dofs(1:self%n_dofs1,1) )
349  call sll_o_collective_allreduce( sll_v_world_collective, self%j_dofs_local(:,2), &
350  self%n_dofs0, mpi_sum, self%j_dofs(:,2) )
351 
352  call sll_o_collective_allreduce( sll_v_world_collective, self%particle_mass_1_local, &
353  self%n_dofs1*(2*self%spline_degree-1), mpi_sum, self%particle_mass_1%particle_mass)
354  call sll_o_collective_allreduce( sll_v_world_collective, self%particle_mass_0_local, &
355  self%n_dofs0*(2*self%spline_degree+1), mpi_sum, self%particle_mass_0%particle_mass)
356 
357 
358  if ( self%jmean ) then
359  self%j_dofs(:,1) = self%j_dofs(:,1) - sum(self%j_dofs(:,1))/real(self%n_dofs1, f64)
360  end if
361 
362  ! Compute rhs
363  self%linear_operator_1%sign = -self%force_sign
364  call self%linear_operator_1%dot(self%efield_dofs(1:self%n_dofs1,1) , rhs1 )
365  rhs1 = rhs1 - dt * self%force_sign * self%j_dofs(1:self%n_dofs1,1)
366  ! Solve the Schur complement
367  self%linear_operator_1%sign = self%force_sign
368  call self%linear_solver_1%set_guess(self%efield_dofs(1:self%n_dofs1,1))
369  call self%linear_solver_1%solve( rhs1 , self%efield_dofs(1:self%n_dofs1,1) )
370 
371  ! Compute rhs
372  self%linear_operator_0%sign = -self%force_sign
373  call self%linear_operator_0%dot(self%efield_dofs(:,2) , rhs0 )
374  rhs0 = rhs0 - self%force_sign * dt * self%j_dofs(:,2)
375 
376  ! Solve the Schur complement
377  self%linear_operator_0%sign = self%force_sign
378  call self%linear_solver_0%set_guess(self%efield_dofs(:,2))
379  call self%linear_solver_0%solve( rhs0 , self%efield_dofs(:,2) )
380 
381  if( self%boundary ) then!perfect conductor boundary
382  self%efield_dofs(1,2) = 0._f64
383  self%efield_dofs(self%n_dofs0,2) = 0._f64
384  end if
385 
386  ! Second particle loop (second half step of particle propagation)
387  do i_sp = 1, self%particle_group%n_species
388  qoverm = self%particle_group%group(i_sp)%species%q_over_m();
389  do i_part = 1, self%particle_group%group(i_sp)%n_particles
390  vi = self%particle_group%group(i_sp)%get_v(i_part)
391  xi = self%particle_group%group(i_sp)%get_x(i_part)
392 
393  ! Evaulate E_x and E_y at particle position and propagate v a half step
394  call self%kernel_smoother_1%evaluate &
395  ( xi(1), self%efield_dofs(1:self%n_dofs1,1), efield(1))
396  call self%kernel_smoother_0%evaluate &
397  ( xi(1), self%efield_dofs(:,2), efield(2))
398 
399  jmat = self%map%jacobian_matrix_inverse_transposed( [xi(1), 0._f64, 0._f64] )
400 
401  do j = 1, 2
402  vi(j) = vi(j) + dt* 0.5_f64* qoverm *(jmat(j,1)*efield(1) + jmat(j,2)*efield(2))
403  end do
404 
405  call self%particle_group%group(i_sp)%set_v( i_part, vi )
406  end do
407  end do
408 
409  end subroutine advect_e_pic_vm_1d2v_trafo
410 
411 
412  !---------------------------------------------------------------------------!
417  subroutine advect_ex_pic_vm_1d2v_trafo ( self, dt )
418  class(sll_t_time_propagator_pic_vm_1d2v_trafo_helper), intent( inout ) :: self
419  sll_real64, intent( in ) :: dt
420  ! local variables
421  sll_int32 :: i_part, i_sp, j
422  sll_real64 :: vi(3), xi(3), wi(1), xnew(3), vbar(2)
423  sll_real64 :: qoverm
424  sll_real64 :: jmat(3,3), jmatrix(3,3), efield(2)
425  sll_int32 :: niter
426  sll_real64 :: residual(1), residual_local(1)
427  sll_real64 :: xmid(1), xbar
428 
429  self%efield_dofs_new = self%efield_dofs
430  do i_sp=1,self%particle_group%n_species
431  do i_part = 1,self%particle_group%group(i_sp)%n_particles
432  vi = self%particle_group%group(i_sp)%get_v(i_part)
433  xnew = self%particle_group%group(i_sp)%get_x(i_part)
434  self%vnew(i_sp,:, i_part) = vi(1:2)
435  self%xnew(i_sp, i_part) = xnew(1)
436  end do
437  end do
438 
439  niter = 0
440  residual = 1.0_f64
441  do while ( (residual(1) > self%iter_tolerance) .and. niter < self%max_iter )
442  niter = niter+1
443 
444  self%efield_dofs_work = 0.5_f64*( self%efield_dofs + self%efield_dofs_new )
445  self%j_dofs_local = 0.0_f64
446 
447  ! Particle loop
448  do i_sp=1,self%particle_group%n_species
449  qoverm = self%particle_group%group(i_sp)%species%q_over_m();
450  do i_part = 1,self%particle_group%group(i_sp)%n_particles
451  vi = self%particle_group%group(i_sp)%get_v(i_part)
452  xi = self%particle_group%group(i_sp)%get_x(i_part)
453 
454  ! Get charge for accumulation of j
455  wi = self%particle_group%group(i_sp)%get_charge(i_part)
456 
457  vbar = 0.5_f64 * (self%vnew(i_sp,:, i_part)+vi(1:2))
458  xnew(1) = self%xnew(i_sp, i_part)
459 
460  jmat = self%map%jacobian_matrix_inverse_transposed( [xi(1), 0._f64, 0._f64] )
461  jmatrix=self%map%jacobian_matrix_inverse_transposed( [xnew(1), 0._f64, 0._f64] )
462  vbar(1) = 0.5_f64 * (jmatrix(1,1)+jmat(1,1))*vbar(1)
463  xnew(1) = xi(1) + dt * vbar(1)
464 
465  if(xnew(1) < -1._f64 .or. xnew(1) > 2._f64)then
466  print*, xnew
467  sll_error("particle boundary", "particle out of bound")
468  else if(xnew(1) < 0._f64 .or. xnew(1) > 1._f64 )then
469  if(xnew(1) < 0._f64 )then
470  xbar = 0._f64
471  else if(xnew(1) > 1._f64)then
472  xbar = 1._f64
473  end if
474 
475  xmid = xbar
476  if ( abs(vbar(1)) > 1.0d-16 ) then
477  call self%kernel_smoother_1%add_current_evaluate &
478  ( xi(1), xmid(1), wi(1), vbar(1), self%efield_dofs_work(1:self%n_dofs1,1), self%j_dofs_local(1:self%n_dofs1,1), &
479  efield(1) )
480  call self%kernel_smoother_0%add_current_evaluate &
481  ( xi(1), xmid(1), wi(1)*vbar(2)/vbar(1), vbar(1), &
482  self%efield_dofs_work(:,2), self%j_dofs_local(:,2), &
483  efield(2) )
484  else
485  call self%kernel_smoother_1%evaluate &
486  (xi(1), self%efield_dofs_work(1:self%n_dofs1,1), efield(1) )
487  efield(1) = efield(1)*dt
488  call self%kernel_smoother_0%add_charge( xi(1), &
489  wi(1)* vbar(2)*dt, self%j_dofs_local(:,2) )
490  call self%kernel_smoother_0%evaluate &
491  (xi(1), self%efield_dofs_work(:,2), efield(2) )
492  efield(2) = efield(2)*dt
493  end if
494 
495  jmatrix = self%map%jacobian_matrix_inverse_transposed( [xmid(1), 0._f64, 0._f64] )
496  do j = 1, 2
497  vi(j) = vi(j) + qoverm *0.5_f64*((jmatrix(j,1)+jmat(j,1))*efield(1) + (jmatrix(j,2)+jmat(j,2))*efield(2))
498  end do
499 
500  select case(self%boundary_particles)
502  xnew = 2._f64*xbar-xnew
503  vi(1) = -vi(1)
504  vbar(1) = -vbar(1)
506  call self%kernel_smoother_0%add_charge(xmid, wi(1), self%rhob)
508  call self%kernel_smoother_0%add_charge(xmid, wi(1), self%rhob)
509  xnew = modulo(xnew, 1._f64)
510  xmid = 1._f64-xbar
511  call self%kernel_smoother_0%add_charge(xmid, -wi(1), self%rhob)
512  case default
513  xnew = modulo(xnew, 1._f64)
514  xmid = 1._f64-xbar
515  end select
516  if ( abs(vbar(1)) > 1.0d-16 ) then
517  call self%kernel_smoother_1%add_current_evaluate &
518  ( xmid(1), xnew(1), wi(1), vbar(1), self%efield_dofs_work(1:self%n_dofs1,1), self%j_dofs_local(1:self%n_dofs1,1), &
519  efield(1) )
520  call self%kernel_smoother_0%add_current_evaluate &
521  ( xmid(1), xnew(1), wi(1)*vbar(2)/vbar(1), vbar(1), &
522  self%efield_dofs_work(:,2), self%j_dofs_local(:,2), &
523  efield(2) )
524  jmatrix = self%map%jacobian_matrix_inverse_transposed( [xnew(1), 0._f64, 0._f64] )
525  do j = 1, 2
526  vi(j) = vi(j) + qoverm *0.5_f64*((jmatrix(j,1)+jmat(j,1))*efield(1) + (jmatrix(j,2)+jmat(j,2))*efield(2))
527  end do
528  end if
529  if(self%boundary_particles == sll_p_boundary_particles_reflection) then
530  vi(1) = - vi(1)
531  end if
532  else
533  if ( abs(vbar(1)) > 1.0d-16 ) then
534  call self%kernel_smoother_1%add_current_evaluate &
535  ( xi(1), xnew(1), wi(1), vbar(1), self%efield_dofs_work(1:self%n_dofs1,1), self%j_dofs_local(1:self%n_dofs1,1), &
536  efield(1) )
537  call self%kernel_smoother_0%add_current_evaluate &
538  ( xi(1), xnew(1), wi(1)*vbar(2)/vbar(1), vbar(1), &
539  self%efield_dofs_work(:,2), self%j_dofs_local(:,2), &
540  efield(2) )
541  else
542  call self%kernel_smoother_1%evaluate &
543  (xi(1), self%efield_dofs_work(1:self%n_dofs1,1), efield(1) )
544  efield(1) = efield(1)*dt
545  call self%kernel_smoother_0%add_charge( xi(1), &
546  wi(1)* vbar(2)*dt, self%j_dofs_local(:,2) )
547  call self%kernel_smoother_0%evaluate &
548  (xi(1), self%efield_dofs_work(:,2), efield(2) )
549  efield(2) = efield(2)*dt
550  end if
551  jmatrix = self%map%jacobian_matrix_inverse_transposed( [xnew(1), 0._f64, 0._f64] )
552  do j = 1, 2
553  vi(j) = vi(j) + qoverm *0.5_f64*((jmatrix(j,1)+jmat(j,1))*efield(1) + (jmatrix(j,2)+jmat(j,2))*efield(2))
554  end do
555  end if
556 
557  self%xnew(i_sp,i_part) = xnew(1)
558  self%vnew(i_sp,:,i_part) = vi(1:2)
559  end do
560  end do
561 
562  self%j_dofs = 0.0_f64
563  ! MPI to sum up contributions from each processor
564  call sll_o_collective_allreduce( sll_v_world_collective, self%j_dofs_local(1:self%n_dofs1,1), &
565  self%n_dofs1, mpi_sum, self%j_dofs(1:self%n_dofs1,1) )
566  call sll_o_collective_allreduce( sll_v_world_collective, self%j_dofs_local(:,2), &
567  self%n_dofs0, mpi_sum, self%j_dofs(:,2) )
568 
569  self%efield_dofs_work = self%efield_dofs
570  call self%maxwell_solver%compute_E_from_j(self%j_dofs(1:self%n_dofs1,1), 1, self%efield_dofs_work(1:self%n_dofs1,1) )
571  call self%maxwell_solver%compute_E_from_j(self%j_dofs(:,2), 2, self%efield_dofs_work(:,2) )
572 
573  ! Compute residual based on e
574  residual_local = (sum((self%efield_dofs_work-self%efield_dofs_new)**2))*self%maxwell_solver%delta_x
575  call sll_o_collective_allreduce( sll_v_world_collective, residual_local, 1, mpi_max, residual )
576  residual = sqrt(residual)
577  self%efield_dofs_new = self%efield_dofs_work
578  end do
579 
580  if ( residual(1) > self%iter_tolerance ) then
581  print*, 'Warning: Iteration no.', self%iter_counter+1 ,'did not converge.', residual, niter
582  self%n_failed = self%n_failed+1
583  end if
584 
585  self%efield_dofs_work = 0.5_f64*( self%efield_dofs + self%efield_dofs_new )
586  self%j_dofs_local = 0.0_f64
587 
588  ! Particle loop
589  do i_sp=1,self%particle_group%n_species
590  qoverm = self%particle_group%group(i_sp)%species%q_over_m();
591  do i_part = 1,self%particle_group%group(i_sp)%n_particles
592  vi = self%particle_group%group(i_sp)%get_v(i_part)
593  xi = self%particle_group%group(i_sp)%get_x(i_part)
594 
595  ! Get charge for accumulation of j
596  wi = self%particle_group%group(i_sp)%get_charge(i_part)
597 
598  vbar = 0.5_f64 * (self%vnew(i_sp,:, i_part)+vi(1:2))
599  xnew(1) = self%xnew(i_sp, i_part)
600 
601  jmat = self%map%jacobian_matrix_inverse_transposed( [xi(1), 0._f64, 0._f64] )
602  jmatrix=self%map%jacobian_matrix_inverse_transposed( [xnew(1), 0._f64, 0._f64] )
603  vbar(1) = 0.5_f64 * (jmatrix(1,1)+jmat(1,1))*vbar(1)
604  xnew(1) = xi(1) + dt * vbar(1)
605  call compute_particle_boundary_current_evaluate( self, xi, xnew, vi, vbar, wi, qoverm, dt )
606 
607  call self%particle_group%group(i_sp)%set_x( i_part, xnew )
608  call self%particle_group%group(i_sp)%set_v( i_part, vi )
609  end do
610  end do
611 
612  self%j_dofs = 0.0_f64
613  ! MPI to sum up contributions from each processor
614  call sll_o_collective_allreduce( sll_v_world_collective, self%j_dofs_local(1:self%n_dofs1,1), &
615  self%n_dofs1, mpi_sum, self%j_dofs(1:self%n_dofs1,1) )
616  call sll_o_collective_allreduce( sll_v_world_collective, self%j_dofs_local(:,2), &
617  self%n_dofs0, mpi_sum, self%j_dofs(:,2) )
618 
619  call self%maxwell_solver%compute_E_from_j(self%j_dofs(1:self%n_dofs1,1), 1, self%efield_dofs(1:self%n_dofs1,1) )
620  call self%maxwell_solver%compute_E_from_j(self%j_dofs(:,2), 2, self%efield_dofs(:,2) )
621 
622  self%iter_counter = self%iter_counter + 1
623  self%niter(self%iter_counter) = niter
624 
625  end subroutine advect_ex_pic_vm_1d2v_trafo
626 
627 
629  subroutine compute_particle_boundary_current_evaluate( self, xi, xnew, vi, vbar, wi, qoverm, dt )
630  class(sll_t_time_propagator_pic_vm_1d2v_trafo_helper), intent( inout ) :: self
631  sll_real64, intent( in ) :: xi(1)
632  sll_real64, intent( inout ) :: xnew(1)
633  sll_real64, intent( inout ) :: vi(2)
634  sll_real64, intent( inout ) :: vbar(2)
635  sll_real64, intent( in ) :: wi(1)
636  sll_real64, intent( in ) :: qoverm
637  sll_real64, intent( in ) :: dt
638  !local variables
639  sll_real64 :: xmid(1), xbar
640  sll_real64 :: jmatrix(3,3), jmat(3,3), efield(2)
641  sll_int32 :: j
642 
643 
644  jmat = self%map%jacobian_matrix_inverse_transposed( [xi(1), 0._f64, 0._f64] )
645 
646  if(xnew(1) < -1._f64 .or. xnew(1) > 2._f64)then
647  print*, xnew
648  sll_error("particle boundary", "particle out of bound")
649  else if(xnew(1) < 0._f64 .or. xnew(1) > 1._f64 )then
650  if(xnew(1) < 0._f64 )then
651  xbar = 0._f64
652  self%counter_left = self%counter_left+1
653  else if(xnew(1) > 1._f64)then
654  xbar = 1._f64
655  self%counter_right = self%counter_right+1
656  end if
657 
658  xmid = xbar
659  if ( abs(vbar(1)) > 1.0d-16 ) then
660  call self%kernel_smoother_1%add_current_evaluate &
661  ( xi(1), xmid(1), wi(1), vbar(1), self%efield_dofs_work(1:self%n_dofs1,1), self%j_dofs_local(1:self%n_dofs1,1), &
662  efield(1) )
663  call self%kernel_smoother_0%add_current_evaluate &
664  ( xi(1), xmid(1), wi(1)*vbar(2)/vbar(1), vbar(1), &
665  self%efield_dofs_work(:,2), self%j_dofs_local(:,2), &
666  efield(2) )
667  else
668  call self%kernel_smoother_1%evaluate &
669  (xi(1), self%efield_dofs_work(1:self%n_dofs1,1), efield(1) )
670  efield(1) = efield(1)*dt
671  call self%kernel_smoother_0%add_charge( xi(1), &
672  wi(1)* vbar(2)*dt, self%j_dofs_local(:,2) )
673  call self%kernel_smoother_0%evaluate &
674  (xi(1), self%efield_dofs_work(:,2), efield(2) )
675  efield(2) = efield(2)*dt
676  end if
677  jmatrix = self%map%jacobian_matrix_inverse_transposed( [xmid(1), 0._f64, 0._f64] )
678  do j = 1, 2
679  vi(j) = vi(j) + qoverm *0.5_f64*((jmatrix(j,1)+jmat(j,1))*efield(1) + (jmatrix(j,2)+jmat(j,2))*efield(2))
680  end do
681 
682  select case(self%boundary_particles)
684  xnew = 2._f64*xbar-xnew
685  vi(1) = -vi(1)
686  vbar(1) = -vbar(1)
688  call self%kernel_smoother_0%add_charge(xmid, wi(1), self%rhob)
690  call self%kernel_smoother_0%add_charge(xmid, wi(1), self%rhob)
691  xnew = modulo(xnew, 1._f64)
692  xmid = 1._f64-xbar
693  call self%kernel_smoother_0%add_charge(xmid, -wi(1), self%rhob)
694  case default
695  xnew = modulo(xnew, 1._f64)
696  xmid = 1._f64-xbar
697  end select
698  if ( abs(vbar(1)) > 1.0d-16 ) then
699  call self%kernel_smoother_1%add_current_evaluate &
700  ( xmid(1), xnew(1), wi(1), vbar(1), self%efield_dofs_work(1:self%n_dofs1,1), self%j_dofs_local(1:self%n_dofs1,1), &
701  efield(1) )
702  call self%kernel_smoother_0%add_current_evaluate &
703  ( xmid(1), xnew(1), wi(1)*vbar(2)/vbar(1), vbar(1), &
704  self%efield_dofs_work(:,2), self%j_dofs_local(:,2), &
705  efield(2) )
706  jmatrix = self%map%jacobian_matrix_inverse_transposed( [xnew(1), 0._f64, 0._f64] )
707  do j = 1, 2
708  vi(j) = vi(j) + qoverm *0.5_f64*((jmatrix(j,1)+jmat(j,1))*efield(1) + (jmatrix(j,2)+jmat(j,2))*efield(2))
709  end do
710  end if
711  else
712  if ( abs(vbar(1)) > 1.0d-16 ) then
713  call self%kernel_smoother_1%add_current_evaluate &
714  ( xi(1), xnew(1), wi(1), vbar(1), self%efield_dofs_work(1:self%n_dofs1,1), self%j_dofs_local(1:self%n_dofs1,1), &
715  efield(1) )
716  call self%kernel_smoother_0%add_current_evaluate &
717  ( xi(1), xnew(1), wi(1)*vbar(2)/vbar(1), vbar(1), &
718  self%efield_dofs_work(:,2), self%j_dofs_local(:,2), &
719  efield(2) )
720  else
721  call self%kernel_smoother_1%evaluate &
722  (xi(1), self%efield_dofs_work(1:self%n_dofs1,1), efield(1) )
723  efield(1) = efield(1)*dt
724  call self%kernel_smoother_0%add_charge( xi(1), &
725  wi(1)* vbar(2)*dt, self%j_dofs_local(:,2) )
726  call self%kernel_smoother_0%evaluate &
727  (xi(1), self%efield_dofs_work(:,2), efield(2) )
728  efield(2) = efield(2)*dt
729  end if
730  jmatrix = self%map%jacobian_matrix_inverse_transposed( [xnew(1), 0._f64, 0._f64] )
731  do j = 1, 2
732  vi(j) = vi(j) + qoverm *0.5_f64*((jmatrix(j,1)+jmat(j,1))*efield(1) + (jmatrix(j,2)+jmat(j,2))*efield(2))
733  end do
734  end if
735 
737 
738 
739  !---------------------------------------------------------------------------!
742  self, &
743  maxwell_solver, &
744  kernel_smoother_0, &
745  kernel_smoother_1, &
746  particle_group, &
747  efield_dofs, &
748  bfield_dofs, &
749  x_min, &
750  Lx, &
751  map, &
752  boundary_particles, &
753  solver_tolerance, &
754  iter_tolerance, max_iter, &
755  force_sign, &
756  rhob, &
757  jmean)
758  class(sll_t_time_propagator_pic_vm_1d2v_trafo_helper), intent( out ) :: self
759  class(sll_c_maxwell_1d_base), target, intent( in ) :: maxwell_solver
760  class(sll_c_particle_mesh_coupling_1d), target, intent( in ) :: kernel_smoother_0
761  class(sll_c_particle_mesh_coupling_1d), target, intent( in ) :: kernel_smoother_1
762  class(sll_t_particle_array), target, intent( in ) :: particle_group
763  sll_real64, target, intent( in ) :: efield_dofs(:,:)
764  sll_real64, target, intent( in ) :: bfield_dofs(:)
765  sll_real64, intent( in ) :: x_min
766  sll_real64, intent( in ) :: lx
767  type(sll_t_mapping_3d), target, intent( in ) :: map
768  sll_int32, optional, intent( in ) :: boundary_particles
769  sll_real64, optional, intent( in ) :: solver_tolerance
770  sll_real64, optional, intent( in ) :: iter_tolerance
771  sll_int32, optional, intent( in ) :: max_iter
772  sll_real64, optional, intent( in ) :: force_sign
773  sll_real64, optional, target, intent( in ) :: rhob(:)
774  logical, optional, intent( in ) :: jmean
775  !local variables
776  sll_int32 :: ierr, j
777 
778  if (present(boundary_particles) ) then
779  self%boundary_particles = boundary_particles
780  end if
781 
782  if (present(solver_tolerance) ) then
783  self%solver_tolerance = solver_tolerance
784  end if
785 
786  if( present(force_sign) )then
787  self%force_sign = force_sign
788  end if
789 
790  if (present(jmean)) then
791  self%jmean = jmean
792  end if
793 
794  if (present(iter_tolerance) ) then
795  self%iter_tolerance = iter_tolerance
796  end if
797 
798  if (present(max_iter) ) then
799  self%max_iter = max_iter
800  end if
801 
802  self%maxwell_solver => maxwell_solver
803  self%kernel_smoother_0 => kernel_smoother_0
804  self%kernel_smoother_1 => kernel_smoother_1
805  self%particle_group => particle_group
806  self%efield_dofs => efield_dofs
807  self%bfield_dofs => bfield_dofs
808  self%map => map
809 
810  ! Check that n_dofs is the same for both kernel smoothers.
811  sll_assert( self%kernel_smoother_0%n_cells == self%kernel_smoother_1%n_cells )
812  sll_assert( self%kernel_smoother_0%n_cells == self%maxwell_solver%n_cells )
813 
814 
815  self%n_cells = self%maxwell_solver%n_cells
816  self%n_dofs0 = self%maxwell_solver%n_dofs0
817  self%n_dofs1 = self%maxwell_solver%n_dofs1
818  self%spline_degree = self%kernel_smoother_0%spline_degree
819 
820  sll_allocate( self%j_dofs(self%n_dofs0,2), ierr )
821  sll_allocate( self%j_dofs_local(self%n_dofs0,2), ierr )
822  sll_allocate( self%particle_mass_1_local(2*self%spline_degree-1, self%n_dofs1), ierr )
823  sll_allocate( self%particle_mass_0_local(2*self%spline_degree+1, self%n_dofs0), ierr )
824  self%j_dofs = 0.0_f64
825  self%j_dofs_local = 0.0_f64
826  self%particle_mass_1_local = 0.0_f64
827  self%particle_mass_0_local = 0.0_f64
828 
829  if( self%n_cells+self%spline_degree == self%maxwell_solver%n_dofs0 ) then
830  self%boundary = .true.
831  allocate( sll_t_linear_operator_particle_mass_cl_1d :: self%particle_mass_1 )
832  select type ( q => self%particle_mass_1 )
834  call q%create( self%spline_degree-1, self%n_dofs1 )
835  end select
836 
837  allocate( sll_t_linear_operator_particle_mass_cl_1d :: self%particle_mass_0 )
838  select type ( q => self%particle_mass_0 )
840  call q%create( self%spline_degree, self%n_dofs0 )
841  end select
842  else if ( self%n_cells == self%maxwell_solver%n_dofs0 ) then
843  allocate( sll_t_linear_operator_particle_mass_1d :: self%particle_mass_1 )
844  select type ( q => self%particle_mass_1 )
846  call q%create( self%spline_degree-1, self%n_dofs1 )
847  end select
848 
849  allocate( sll_t_linear_operator_particle_mass_1d :: self%particle_mass_0 )
850  select type ( q => self%particle_mass_0 )
852  call q%create( self%spline_degree, self%n_dofs0 )
853  end select
854  end if
855 
856  call self%linear_operator_1%create( self%maxwell_solver, self%particle_mass_1, self%n_dofs1, self%maxwell_solver%s_deg_1 )
857  call self%linear_solver_1%create( self%linear_operator_1 )
858  self%linear_solver_1%atol = self%solver_tolerance/lx
859  !self%linear_solver_1%verbose = .true.
860 
861  call self%linear_operator_0%create( self%maxwell_solver, self%particle_mass_0, self%n_dofs0, self%maxwell_solver%s_deg_0 )
862  call self%linear_solver_0%create( self%linear_operator_0 )
863  self%linear_solver_0%atol = self%solver_tolerance
864  !self%linear_solver_0%verbose = .true.
865 
866  self%n_particles_max = self%particle_group%group(1)%n_particles
867  do j = 2,self%particle_group%n_species
868  self%n_particles_max = max(self%n_particles_max, self%particle_group%group(j)%n_particles )
869  end do
870 
871  sll_allocate( self%xnew(self%particle_group%n_species,self%n_particles_max), ierr )
872  sll_allocate( self%vnew(self%particle_group%n_species,2,self%n_particles_max), ierr )
873  sll_allocate( self%efield_dofs_new(self%n_dofs0,2), ierr )
874  sll_allocate( self%efield_dofs_work(self%n_dofs0,2), ierr )
875 
876  if( present(rhob) )then
877  self%rhob => rhob
878  end if
879 
880  end subroutine initialize_pic_vm_1d2v_trafo
881 
882 
885  self, &
886  maxwell_solver, &
887  kernel_smoother_0, &
888  kernel_smoother_1, &
889  particle_group, &
890  efield_dofs, &
891  bfield_dofs, &
892  x_min, &
893  Lx, &
894  map, &
895  filename, &
896  boundary_particles, &
897  force_sign, &
898  rhob, &
899  jmean)
900  class(sll_t_time_propagator_pic_vm_1d2v_trafo_helper), intent( out ) :: self
901  class(sll_c_maxwell_1d_base), target, intent( in ) :: maxwell_solver
902  class(sll_c_particle_mesh_coupling_1d), target, intent( in ) :: kernel_smoother_0
903  class(sll_c_particle_mesh_coupling_1d), target, intent( in ) :: kernel_smoother_1
904  class(sll_t_particle_array), target, intent( in ) :: particle_group
905  sll_real64, target, intent( in ) :: efield_dofs(:,:)
906  sll_real64, target, intent( in ) :: bfield_dofs(:)
907  sll_real64, intent( in ) :: x_min
908  sll_real64, intent( in ) :: lx
909  type(sll_t_mapping_3d), target, intent( in ) :: map
910  character(len=*), intent( in ) :: filename
911  sll_int32, optional, intent( in ) :: boundary_particles
912  sll_real64, optional, intent(in) :: force_sign
913  sll_real64, optional, target, intent( in ) :: rhob(:)
914  logical, optional, intent(in) :: jmean
915  !local variables
916  character(len=256) :: file_prefix
917  sll_int32 :: input_file, rank
918  sll_int32 :: io_stat, io_stat0, io_stat1, file_id, boundary_particles_set, max_iter
919  sll_real64 :: maxwell_tolerance, force_sign_set, iter_tolerance
920  logical :: jmean_set
921 
922  namelist /output/ file_prefix
923  namelist /time_solver/ maxwell_tolerance
924  namelist /time_iterate/ iter_tolerance, max_iter
925 
927 
928  if (present(boundary_particles)) then
929  boundary_particles_set = boundary_particles
930  else
931  boundary_particles_set = 100
932  end if
933 
934  if( present(force_sign) )then
935  force_sign_set = force_sign
936  else
937  force_sign_set = 1._f64
938  end if
939 
940  if (present(jmean)) then
941  jmean_set = jmean
942  else
943  jmean_set = .false.
944  end if
945 
946  ! Read in solver tolerance
947  open(newunit = input_file, file=filename, status='old',iostat=io_stat)
948  if (io_stat /= 0) then
949  if (rank == 0 ) then
950  print*, 'sll_m_time_propagator_pic_vm_1d2v_trafo_helper: Input file does not exist. Set default tolerance.'
951  open(newunit=file_id, file=trim(file_prefix)//'_parameters_used.dat', position = 'append', status='old', action='write', iostat=io_stat)
952  write(file_id, *) 'solver tolerance:', 1d-12
953  write(file_id, *) 'iter_tolerance:', 1d-10
954  write(file_id, *) 'max_iter:', 10
955  write(file_id, *) 'force_sign:', force_sign_set
956  close(file_id)
957  end if
958  call self%init( maxwell_solver, &
959  kernel_smoother_0, &
960  kernel_smoother_1, &
961  particle_group, &
962  efield_dofs, &
963  bfield_dofs, &
964  x_min, &
965  lx, &
966  map,&
967  boundary_particles = boundary_particles_set, &
968  force_sign=force_sign_set, &
969  rhob = rhob, &
970  jmean=jmean_set)
971  else
972  read(input_file, output, iostat=io_stat0)
973  read(input_file, time_solver,iostat=io_stat)
974  read(input_file, time_iterate,iostat=io_stat1)
975  if (io_stat /= 0 .and. io_stat1 /= 0) then
976  if (rank == 0 ) then
977  print*, 'sll_m_time_propagator_pic_vm_1d2v_trafo_helper: Tolerance not given. Set default tolerance.'
978  open(newunit=file_id, file=trim(file_prefix)//'_parameters_used.dat', position = 'append', status='old', action='write', iostat=io_stat)
979  write(file_id, *) 'solver tolerance:', 1d-12
980  write(file_id, *) 'iter_tolerance:', 1d-10
981  write(file_id, *) 'max_iter:', 10
982  write(file_id, *) 'force_sign:', force_sign_set
983  close(file_id)
984  end if
985  call self%init( maxwell_solver, &
986  kernel_smoother_0, &
987  kernel_smoother_1, &
988  particle_group, &
989  efield_dofs, &
990  bfield_dofs, &
991  x_min, &
992  lx, &
993  map,&
994  boundary_particles = boundary_particles_set, &
995  force_sign=force_sign_set, &
996  rhob = rhob, &
997  jmean=jmean_set)
998  else if (io_stat == 0 .and. io_stat1 /= 0) then
999  if (rank == 0 ) then
1000  open(newunit=file_id, file=trim(file_prefix)//'_parameters_used.dat', position = 'append', status='old', action='write', iostat=io_stat)
1001  write(file_id, *) 'solver tolerance:', maxwell_tolerance
1002  write(file_id, *) 'iter_tolerance:', 1d-10
1003  write(file_id, *) 'max_iter:', 10
1004  write(file_id, *) 'force_sign:', force_sign_set
1005  close(file_id)
1006  end if
1007  call self%init( maxwell_solver, &
1008  kernel_smoother_0, &
1009  kernel_smoother_1, &
1010  particle_group, &
1011  efield_dofs, &
1012  bfield_dofs, &
1013  x_min, &
1014  lx, &
1015  map, &
1016  boundary_particles = boundary_particles_set, &
1017  solver_tolerance=maxwell_tolerance,&
1018  force_sign=force_sign_set, &
1019  rhob = rhob, &
1020  jmean=jmean_set)
1021  else if (io_stat /= 0 .and. io_stat1 == 0) then
1022  if (rank == 0 ) then
1023  open(newunit=file_id, file=trim(file_prefix)//'_parameters_used.dat', position = 'append', status='old', action='write', iostat=io_stat)
1024  write(file_id, *) 'solver tolerance:', 1d-12
1025  write(file_id, *) 'iter_tolerance:', iter_tolerance
1026  write(file_id, *) 'max_iter:', max_iter
1027  write(file_id, *) 'force_sign:', force_sign_set
1028  close(file_id)
1029  end if
1030  call self%init( maxwell_solver, &
1031  kernel_smoother_0, &
1032  kernel_smoother_1, &
1033  particle_group, &
1034  efield_dofs, &
1035  bfield_dofs, &
1036  x_min, &
1037  lx, &
1038  map, &
1039  boundary_particles = boundary_particles_set, &
1040  iter_tolerance=iter_tolerance, max_iter=max_iter, &
1041  force_sign=force_sign_set, &
1042  rhob = rhob, &
1043  jmean=jmean_set)
1044  else
1045  if (rank == 0 ) then
1046  open(newunit=file_id, file=trim(file_prefix)//'_parameters_used.dat', position = 'append', status='old', action='write', iostat=io_stat)
1047  write(file_id, *) 'solver tolerance:', maxwell_tolerance
1048  write(file_id, *) 'force_sign:', force_sign_set
1049  write(file_id, *) 'iter_tolerance:', iter_tolerance
1050  write(file_id, *) 'max_iter:', max_iter
1051  close(file_id)
1052  end if
1053  call self%init( maxwell_solver, &
1054  kernel_smoother_0, &
1055  kernel_smoother_1, &
1056  particle_group, &
1057  efield_dofs, &
1058  bfield_dofs, &
1059  x_min, &
1060  lx, &
1061  map, &
1062  boundary_particles = boundary_particles_set, &
1063  solver_tolerance=maxwell_tolerance,&
1064  iter_tolerance=iter_tolerance, max_iter=max_iter, &
1065  force_sign=force_sign_set, &
1066  rhob = rhob, &
1067  jmean=jmean_set)
1068  end if
1069  close(input_file)
1070  end if
1071 
1072 
1073  end subroutine initialize_file_pic_vm_1d2v_trafo
1074 
1075  !---------------------------------------------------------------------------!
1077  subroutine delete_pic_vm_1d2v_trafo(self)
1078  class(sll_t_time_propagator_pic_vm_1d2v_trafo_helper), intent( inout ) :: self
1079 
1080  if( self%boundary ) then
1081  print*, 'left boundary', self%counter_left
1082  print*, 'right boundary', self%counter_right
1083  end if
1084 
1085  call self%linear_solver_1%free()
1086  call self%linear_operator_1%free()
1087  call self%particle_mass_1%free()
1088 
1089  call self%linear_solver_0%free()
1090  call self%linear_operator_0%free()
1091  call self%particle_mass_0%free()
1092 
1093  deallocate( self%j_dofs )
1094  deallocate( self%j_dofs_local )
1095  deallocate( self%particle_mass_1_local )
1096  deallocate( self%particle_mass_0_local )
1097  self%maxwell_solver => null()
1098  self%kernel_smoother_0 => null()
1099  self%kernel_smoother_1 => null()
1100  self%particle_group => null()
1101  self%efield_dofs => null()
1102  self%bfield_dofs => null()
1103  self%map=> null()
1104 
1105  end subroutine delete_pic_vm_1d2v_trafo
1106 
1107 
Combines values from all processes and distributes the result back to all processes.
Parallelizing facility.
integer(kind=i32) function, public sll_f_get_collective_rank(col)
Determines the rank of the calling process in the communicator.
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.
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 conjugate gradient method in pure form
Module interfaces for coordinate transformation.
module for Compressed Sparse Row Matrix (CSR)
Module interface to solve Maxwell's equations in 1D.
Base class for kernel smoothers for accumulation and field evaluation in PIC.
Utilites for Maxwell solver's with spline finite elements using sparse matrix linear solvers.
subroutine, public sll_s_spline_fem_sparsity_mass(degree, n_cells, spmat)
Helper function to create sparsity pattern of the mass matrix.
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.
Particle pusher based on antisymmetric splitting with AVF for 1d2v Vlasov-Poisson with coordinate tra...
subroutine advect_e_pic_vm_1d2v_trafo(self, dt)
advect_e: Equations to be solved Solution with Schur complement: $ S_{+}=M_1+\frac{\Delta t^2 q^2}{4 ...
subroutine initialize_pic_vm_1d2v_trafo(self, maxwell_solver, kernel_smoother_0, kernel_smoother_1, particle_group, efield_dofs, bfield_dofs, x_min, Lx, map, boundary_particles, solver_tolerance, iter_tolerance, max_iter, force_sign, rhob, jmean)
Constructor.
subroutine compute_particle_boundary_current_evaluate(self, xi, xnew, vi, vbar, wi, qoverm, dt)
Helper function for advect_ex.
subroutine compute_particle_boundary(self, xold, xnew, vi)
Helper function for advect_x.
subroutine advect_eb_pic_vm_1d2v_trafo(self, dt)
advect_eb: Equations to be solved Solution with Schur complement: $ S=M_1+\frac{\Delta t^2}{4} D^\top...
subroutine initialize_file_pic_vm_1d2v_trafo(self, maxwell_solver, kernel_smoother_0, kernel_smoother_1, particle_group, efield_dofs, bfield_dofs, x_min, Lx, map, filename, boundary_particles, force_sign, rhob, jmean)
Constructor.
subroutine advect_ex_pic_vm_1d2v_trafo(self, dt)
advect_ex: Equations to be solved $\frac{\Xi^{n+1}-\Xi^n}{\Delta t}=\frac{DF^{-1}(\Xi^{n+1})+DF^{-1}(...
subroutine advect_vb_pic_vm_1d2v_trafo(self, dt)
advect_vb: Equations to be solved $V^{n+1}= (\cos(DF/J_F B)&\sin(DF/J_F B) \ -\sin(DF/J_F B) &\cos(DF...
Particle pusher based on antisymmetric splitting with AVF for 3d3v Vlasov-Maxwell with coordinate tra...
type collecting functions for analytical coordinate mapping
    Report Typos and Errors