7 #include "sll_assert.h"
8 #include "sll_errors.h"
9 #include "sll_memory.h"
10 #include "sll_working_precision.h"
100 sll_int32 :: spline_degree(3)
102 sll_real64 :: x_min(3)
103 sll_real64 :: x_max(3)
104 sll_int32 :: n_total0
105 sll_int32 :: n_total1
106 sll_int32 :: nspan(3)
107 sll_real64 :: betar(2) = 1._f64
109 sll_real64,
pointer :: phi_dofs(:)
110 sll_real64,
pointer :: efield_dofs(:)
111 sll_real64,
pointer :: bfield_dofs(:)
112 sll_real64,
allocatable :: j_dofs(:)
113 sll_real64,
allocatable :: j_dofs_local(:)
114 sll_real64,
allocatable :: particle_mass_1_local(:,:)
115 sll_real64,
allocatable :: particle_mass_2_local(:,:)
116 sll_real64,
allocatable :: particle_mass_3_local(:,:)
118 sll_real64 :: solver_tolerance = 1d-12
119 sll_real64 :: iter_tolerance = 1d-10
120 sll_int32 :: max_iter = 10
122 sll_int32 :: boundary_particles = 100
123 sll_int32 :: counter_left = 0
124 sll_int32 :: counter_right = 0
125 sll_real64,
pointer :: rhob(:) => null()
126 sll_real64 :: force_sign = 1._f64
127 logical :: adiabatic_electrons = .false.
128 logical :: jmean = .false.
129 logical :: boundary = .false.
131 sll_int32 :: n_particles_max
132 sll_real64,
allocatable :: xnew(:,:,:)
133 sll_real64,
allocatable :: vnew(:,:,:)
134 sll_real64,
allocatable :: efield_dofs_new(:)
135 sll_real64,
allocatable :: efield_dofs_work(:)
136 sll_real64,
allocatable :: phi_dofs_new(:)
137 sll_real64,
allocatable :: phi_dofs_work(:)
139 sll_int32 :: n_failed = 0
140 sll_int32 :: iter_counter = 0
141 sll_int32 :: niter(100000)
145 sll_int32 :: i_weight = 1
148 sll_real64,
allocatable :: efield_filter(:)
149 sll_real64,
allocatable :: bfield_filter(:)
174 sll_real64,
intent(in) :: dt
176 sll_int32 :: i_part, i_sp
177 sll_real64 :: xi(3), xnew(3), vi(3), wall(3)
179 do i_sp = 1, self%particle_group%n_species
180 do i_part=1,self%particle_group%group(i_sp)%n_particles
182 xi = self%particle_group%group(i_sp)%get_x(i_part)
183 vi = self%particle_group%group(i_sp)%get_v(i_part)
189 call self%particle_group%group(i_sp)%set_x ( i_part, xnew )
190 call self%particle_group%group(i_sp)%set_v ( i_part, vi )
192 if (self%particle_group%group(i_sp)%n_weights == 3 )
then
193 wall = self%particle_group%group(i_sp)%get_weights(i_part)
194 wall(3) = self%control_variate%cv(i_sp)%update_df_weight( xnew, vi, 0.0_f64, wall(1), wall(2) )
195 call self%particle_group%group(i_sp)%set_weights( i_part, wall )
206 sll_real64,
intent( inout ) :: xold(3)
207 sll_real64,
intent( inout ) :: xnew(3)
208 sll_real64,
intent( inout ) :: vi(3)
212 if(xnew(1) < -self%x_max(1) .or. xnew(1) > 2._f64*self%x_max(1) )
then
214 sll_error(
"particle boundary",
"particle out of bound")
215 else if(xnew(1) < self%x_min(1) .or. xnew(1) > self%x_max(1) )
then
216 if(xnew(1) < self%x_min(1) )
then
218 self%counter_left = self%counter_left+1
219 else if(xnew(1) > self%x_max(1))
then
221 self%counter_right = self%counter_right+1
224 select case(self%boundary_particles)
226 xnew(1) = 2._f64*xbar-xnew(1)
230 xnew(1) = self%x_min(1) + modulo(xnew(1)-self%x_min(1), self%Lx(1))
232 xnew(1) = self%x_min(1) + modulo(xnew(1)-self%x_min(1), self%Lx(1))
235 xnew(2:3) = self%x_min(2:3) + modulo(xnew(2:3)-self%x_min(2:3), self%Lx(2:3))
245 sll_real64,
intent(in) :: dt
247 sll_int32 :: i_part, i_sp
249 sll_real64 :: vi(3), vnew(3), xi(3), wall(3)
250 sll_real64 :: bfield(3), bsq(3), denom
252 self%bfield_filter = self%bfield_dofs
253 call self%filter%apply_inplace(self%bfield_filter(1:self%n_total0))
254 call self%filter%apply_inplace(self%bfield_filter(self%n_total0+1:self%n_total0+self%n_total1))
255 call self%filter%apply_inplace(self%bfield_filter(self%n_total0+self%n_total1+1:self%n_total0+2*self%n_total1))
257 do i_sp = 1, self%particle_group%n_species
258 qmdt = self%particle_group%group(i_sp)%species%q_over_m()*dt*0.5_f64;
259 do i_part = 1, self%particle_group%group(i_sp)%n_particles
260 vi = self%particle_group%group(i_sp)%get_v(i_part)
261 xi = self%particle_group%group(i_sp)%get_x(i_part)
262 call self%particle_mesh_coupling%evaluate &
263 (xi, [self%spline_degree(1), self%spline_degree(2)-1, self%spline_degree(3)-1], self%bfield_filter(1:self%n_total0), bfield(1))
264 call self%particle_mesh_coupling%evaluate &
265 (xi, [self%spline_degree(1)-1, self%spline_degree(2), self%spline_degree(3)-1],self%bfield_filter(self%n_total0+1:self%n_total0+self%n_total1), bfield(2))
266 call self%particle_mesh_coupling%evaluate &
267 (xi, [self%spline_degree(1)-1, self%spline_degree(2)-1, self%spline_degree(3)],self%bfield_filter(self%n_total0+self%n_total1+1:self%n_total0+2*self%n_total1), bfield(3))
272 denom = sum(bsq)+1.0_f64
274 vnew(1) = ( (bsq(1)-bsq(2)-bsq(3)+1.0_f64)*vi(1) + &
275 2.0_f64*(bfield(1)*bfield(2)+bfield(3))*vi(2) + &
276 2.0_f64*(bfield(1)*bfield(3)-bfield(2))*vi(3) )/denom
277 vnew(2) = ( 2.0_f64*(bfield(1)*bfield(2)-bfield(3))*vi(1) + &
278 (-bsq(1)+bsq(2)-bsq(3)+1.0_f64)*vi(2) + &
279 2.0_f64*(bfield(2)*bfield(3)+bfield(1))*vi(3) )/denom
280 vnew(3) = ( 2.0_f64*(bfield(1)*bfield(3)+bfield(2))*vi(1) + &
281 2.0_f64*(bfield(2)*bfield(3)-bfield(1))*vi(2) + &
282 (-bsq(1)-bsq(2)+bsq(3)+1.0_f64)*vi(3) )/denom
285 call self%particle_group%group(i_sp)%set_v( i_part, vnew )
288 if (self%particle_group%group(i_sp)%n_weights == 3 )
then
289 wall = self%particle_group%group(i_sp)%get_weights(i_part)
290 wall(3) = self%control_variate%cv(i_sp)%update_df_weight( xi, vnew, 0.0_f64, wall(1), wall(2) )
291 call self%particle_group%group(i_sp)%set_weights( i_part, wall )
306 sll_real64,
intent(in) :: dt
308 call self%maxwell_solver%compute_curl_part( dt, self%efield_dofs, self%bfield_dofs, self%betar(1) )
321 sll_real64,
intent(in) :: dt
323 sll_int32 :: i_part, i_sp, j
324 sll_real64 :: vi(3), xi(3), wi(1), wall(3)
325 sll_real64 :: qoverm, factor
326 sll_real64 :: efield(3)
327 sll_real64 :: rhs(self%n_total1+2*self%n_total0)
330 self%j_dofs_local = 0.0_f64
331 self%particle_mass_1_local = 0.0_f64
332 self%particle_mass_2_local = 0.0_f64
333 self%particle_mass_3_local = 0.0_f64
335 self%efield_filter = self%efield_dofs
336 call self%filter%apply_inplace(self%efield_filter(1:self%n_total1))
337 call self%filter%apply_inplace(self%efield_filter(self%n_total1+1:self%n_total1+self%n_total0))
338 call self%filter%apply_inplace(self%efield_filter(self%n_total1+self%n_total0+1:self%n_total1+2*self%n_total0))
342 do i_sp = 1, self%particle_group%n_species
343 qoverm = self%particle_group%group(i_sp)%species%q_over_m();
344 if( self%adiabatic_electrons )
then
345 factor = dt**2 * 0.25_f64* qoverm
347 factor = dt**2 * 0.25_f64* qoverm*self%betar(2)
349 do i_part = 1, self%particle_group%group(i_sp)%n_particles
350 vi = self%particle_group%group(i_sp)%get_v(i_part)
351 xi = self%particle_group%group(i_sp)%get_x(i_part)
354 wi = self%particle_group%group(i_sp)%get_charge(i_part, self%i_weight)
357 call self%particle_mesh_coupling%add_particle_mass( xi, wi(1) * factor, &
358 [self%spline_degree(1)-1, self%spline_degree(2), self%spline_degree(3)], &
359 self%particle_mass_1_local )
360 call self%particle_mesh_coupling%add_particle_mass( xi, wi(1) * factor, &
361 [self%spline_degree(1), self%spline_degree(2)-1, self%spline_degree(3)], &
362 self%particle_mass_2_local )
363 call self%particle_mesh_coupling%add_particle_mass( xi, wi(1) * factor, &
364 [self%spline_degree(1), self%spline_degree(2), self%spline_degree(3)-1], &
365 self%particle_mass_3_local )
368 call self%particle_mesh_coupling%add_charge( xi, wi(1)*vi(1), &
369 [self%spline_degree(1)-1, self%spline_degree(2), self%spline_degree(3)], &
370 self%j_dofs_local(1:self%n_total1) )
371 call self%particle_mesh_coupling%add_charge( xi, wi(1)*vi(2), &
372 [self%spline_degree(1), self%spline_degree(2)-1, self%spline_degree(3)], &
373 self%j_dofs_local(1+self%n_total1:self%n_total1+self%n_total0) )
374 call self%particle_mesh_coupling%add_charge( xi, wi(1)*vi(3), &
375 [self%spline_degree(1), self%spline_degree(2), self%spline_degree(3)-1], &
376 self%j_dofs_local(1+self%n_total1+self%n_total0:self%n_total1+2*self%n_total0) )
379 call self%particle_mesh_coupling%evaluate &
380 (xi, [self%spline_degree(1)-1, self%spline_degree(2), self%spline_degree(3)], &
381 self%efield_filter(1:self%n_total1), efield(1))
382 call self%particle_mesh_coupling%evaluate &
383 (xi, [self%spline_degree(1), self%spline_degree(2)-1, self%spline_degree(3)], &
384 self%efield_filter(self%n_total1+1:self%n_total1+self%n_total0), efield(2))
385 call self%particle_mesh_coupling%evaluate &
386 (xi, [self%spline_degree(1), self%spline_degree(2), self%spline_degree(3)-1], &
387 self%efield_filter(self%n_total1+self%n_total0+1:self%n_total1+2*self%n_total0), efield(3))
390 vi = vi + dt* 0.5_f64* qoverm * efield
391 call self%particle_group%group(i_sp)%set_v( i_part, vi )
393 if (self%particle_group%group(i_sp)%n_weights == 3 )
then
394 wall = self%particle_group%group(i_sp)%get_weights(i_part)
395 wall(3) = self%control_variate%cv(i_sp)%update_df_weight( xi, vi, 0.0_f64, wall(1), wall(2) )
396 call self%particle_group%group(i_sp)%set_weights( i_part, wall )
401 self%j_dofs = 0.0_f64
402 self%particle_mass_1%particle_mass = 0.0_f64
403 self%particle_mass_2%particle_mass = 0.0_f64
404 self%particle_mass_3%particle_mass = 0.0_f64
407 self%n_total1+self%n_total0*2, mpi_sum, self%j_dofs )
409 if ( self%jmean )
then
410 self%j_dofs(1:self%n_total1) = self%j_dofs(1:self%n_total1) - sum(self%j_dofs(1:self%n_total1))/real(self%n_total1, f64)
411 self%j_dofs(1+self%n_total1:self%n_total1+self%n_total0) = self%j_dofs(1+self%n_total1:self%n_total1+self%n_total0) - sum(self%j_dofs(1+self%n_total1:self%n_total1+self%n_total0))/real(self%n_total0, f64)
412 self%j_dofs(1+self%n_total1+self%n_total0:self%n_total1+2*self%n_total0) = self%j_dofs(1+self%n_total1+self%n_total0:self%n_total1+2*self%n_total0) - sum(self%j_dofs(1+self%n_total1+self%n_total0:self%n_total1+2*self%n_total0))/real(self%n_total0, f64)
415 call self%filter%apply_inplace(self%j_dofs(1:self%n_total1))
416 call self%filter%apply_inplace(self%j_dofs(self%n_total1+1:self%n_total1+self%n_total0))
417 call self%filter%apply_inplace(self%j_dofs(self%n_total1+self%n_total0+1:self%n_total1+2*self%n_total0))
422 self%n_total1*self%nspan(1) , mpi_sum, self%particle_mass_1%particle_mass)
424 self%n_total0*self%nspan(2) , mpi_sum, self%particle_mass_2%particle_mass)
426 self%n_total0*self%nspan(3) , mpi_sum, self%particle_mass_3%particle_mass)
429 call self%particle_mass_op%set( 1, 1, self%particle_mass_1 )
430 call self%particle_mass_op%set( 2, 2, self%particle_mass_2 )
431 call self%particle_mass_op%set( 3, 3, self%particle_mass_3 )
433 if( self%adiabatic_electrons )
then
435 self%linear_op_schur_phiv%sign = -1._f64
436 call self%linear_op_schur_phiv%dot(self%phi_dofs, rhs(1: self%n_total0 ))
437 call self%maxwell_solver%multiply_gt( self%j_dofs, rhs(self%n_total0+1: 2*self%n_total0 ) )
438 rhs(1: self%n_total0 ) = rhs(1: self%n_total0 ) + dt * rhs(self%n_total0+1: 2*self%n_total0 )
441 self%linear_op_schur_phiv%sign = 1._f64
442 call self%linear_solver_schur_phiv%set_guess(self%phi_dofs)
443 call self%linear_solver_schur_phiv%solve( rhs(1: self%n_total0 ), self%phi_dofs )
444 if( self%boundary )
then
445 do j = 1, self%maxwell_solver%n_dofs(2)*self%maxwell_solver%n_dofs(3)
446 self%phi_dofs(1+(j-1)*self%maxwell_solver%n_dofs(1)) = 0._f64
447 self%phi_dofs(j*self%maxwell_solver%n_dofs(1)) = 0._f64
450 call self%maxwell_solver%multiply_g( self%phi_dofs, self%efield_dofs )
451 self%efield_dofs = -self%efield_dofs
454 self%linear_op_schur_ev%sign = -self%force_sign
455 call self%linear_op_schur_ev%dot(self%efield_dofs, rhs)
456 rhs = rhs - self%force_sign *dt * self%betar(2) * self%j_dofs
459 self%linear_op_schur_ev%sign = self%force_sign
460 call self%linear_solver_schur_ev%set_guess(self%efield_dofs)
461 call self%linear_solver_schur_ev%solve(rhs, self%efield_dofs)
465 if( self%boundary )
then
466 do j = 1, self%maxwell_solver%n_dofs(2)*self%maxwell_solver%n_dofs(3)
467 self%efield_dofs(self%n_total1+1+(j-1)*self%maxwell_solver%n_dofs(1)) = 0._f64
468 self%efield_dofs(self%n_total1+j*self%maxwell_solver%n_dofs(1)) = 0._f64
469 self%efield_dofs(self%n_total1+self%n_total0+1+(j-1)*self%maxwell_solver%n_dofs(1)) = 0._f64
470 self%efield_dofs(self%n_total1+self%n_total0+j*self%maxwell_solver%n_dofs(1)) = 0._f64
474 self%efield_filter = self%efield_dofs
475 call self%filter%apply_inplace(self%efield_filter(1:self%n_total1))
476 call self%filter%apply_inplace(self%efield_filter(self%n_total1+1:self%n_total1+self%n_total0))
477 call self%filter%apply_inplace(self%efield_filter(self%n_total1+self%n_total0+1:self%n_total1+2*self%n_total0))
482 do i_sp = 1, self%particle_group%n_species
483 qoverm = self%particle_group%group(i_sp)%species%q_over_m();
484 do i_part = 1, self%particle_group%group(i_sp)%n_particles
485 vi = self%particle_group%group(i_sp)%get_v(i_part)
486 xi = self%particle_group%group(i_sp)%get_x(i_part)
489 call self%particle_mesh_coupling%evaluate &
490 (xi, [self%spline_degree(1)-1, self%spline_degree(2), self%spline_degree(3)], &
491 self%efield_filter(1:self%n_total1), efield(1))
492 call self%particle_mesh_coupling%evaluate &
493 (xi, [self%spline_degree(1), self%spline_degree(2)-1, self%spline_degree(3)], &
494 self%efield_filter(self%n_total1+1:self%n_total1+self%n_total0), efield(2))
495 call self%particle_mesh_coupling%evaluate &
496 (xi, [self%spline_degree(1), self%spline_degree(2), self%spline_degree(3)-1], &
497 self%efield_filter(self%n_total1+self%n_total0+1:self%n_total1+2*self%n_total0), efield(3))
499 vi = vi + dt* 0.5_f64* qoverm * efield
501 call self%particle_group%group(i_sp)%set_v( i_part, vi )
502 if (self%particle_group%group(i_sp)%n_weights == 3 )
then
504 wall = self%particle_group%group(i_sp)%get_weights(i_part)
505 wall(3) = self%control_variate%cv(i_sp)%update_df_weight( xi, vi, 0.0_f64, wall(1), wall(2) )
506 call self%particle_group%group(i_sp)%set_weights( i_part, wall )
523 sll_real64,
intent(in) :: dt
525 sll_int32 :: i_part, i_sp
526 sll_real64 :: vi(3), xi(3), wi(1), mi(1), xnew(3), vbar(3), vh(3), xmid(3), xbar, dx
527 sll_real64 :: sign, wall(3)
528 sll_real64 :: efield(3)
530 sll_real64 :: residual(8), residual_local(8)
532 self%efield_dofs_new = self%efield_dofs
533 self%phi_dofs_new = self%phi_dofs
534 do i_sp=1,self%particle_group%n_species
535 do i_part = 1,self%particle_group%group(i_sp)%n_particles
536 self%vnew(i_sp,:, i_part) = self%particle_group%group(i_sp)%get_v(i_part)
537 self%xnew(i_sp,:, i_part) = self%particle_group%group(i_sp)%get_x(i_part)
544 do while ( (residual(7) > self%iter_tolerance) .and. niter < self%max_iter )
547 self%efield_dofs_work = 0.5_f64*( self%efield_dofs + self%efield_dofs_new )
548 self%j_dofs_local = 0.0_f64
549 residual_local = 0._f64
551 do i_sp=1,self%particle_group%n_species
552 sign = dt*self%particle_group%group(i_sp)%species%q_over_m();
553 do i_part = 1,self%particle_group%group(i_sp)%n_particles
554 vi = self%particle_group%group(i_sp)%get_v(i_part)
555 xi = self%particle_group%group(i_sp)%get_x(i_part)
558 wi = self%particle_group%group(i_sp)%get_charge(i_part, self%i_weight)
559 mi = self%particle_group%group(i_sp)%get_mass(i_part, self%i_weight)
561 vbar = 0.5_f64*(vi+self%vnew(i_sp,:, i_part))
563 xnew = xi + dt * vbar
564 if(xnew(1) < -self%x_max(1) .or. xnew(1) > 2._f64*self%x_max(1) )
then
566 sll_error(
"particle boundary",
"particle out of bound")
567 else if(xnew(1) < self%x_min(1) .or. xnew(1) > self%x_max(1) )
then
568 if(xnew(1) < self%x_min(1) )
then
570 else if(xnew(1) > self%x_max(1))
then
573 dx = (xbar- xi(1))/(xnew(1)-xi(1))
574 xmid = xi + dx * (xnew-xi)
577 vh = (xmid - xi)*wi(1)
578 call self%particle_mesh_coupling%add_current_evaluate( xi, xmid, vh, self%efield_dofs_work, &
579 self%j_dofs_local, efield )
580 vi = vi + dx* sign* efield
582 select case(self%boundary_particles)
584 xnew(1) = 2._f64*xbar-xnew(1)
587 call self%particle_mesh_coupling%add_charge(xmid, wi(1), self%spline_degree, self%rhob)
588 xnew(1) = xmid(1) + ((xbar-self%x_min(1))/self%Lx(1)-0.5_f64) * 1.9_f64*self%iter_tolerance
590 xnew(1) = self%x_min(1) + modulo(xnew(1)-self%x_min(1), self%Lx(1))
591 xmid(1) = self%x_max(1)+self%x_min(1)-xbar
593 xnew(1) = self%x_min(1) + modulo(xnew(1)-self%x_min(1), self%Lx(1))
594 xmid(1) = self%x_max(1)+self%x_min(1)-xbar
596 vh = (xnew - xmid)*wi(1)
597 call self%particle_mesh_coupling%add_current_evaluate( xmid, xnew, vh, self%efield_dofs_work, &
598 self%j_dofs_local, efield )
599 vi = vi + (1._f64-dx) * sign * efield
604 vh = (xnew - xi)*wi(1)
605 call self%particle_mesh_coupling%add_current_evaluate( xi, xnew, vh, self%efield_dofs_work, &
606 self%j_dofs_local, efield )
607 vi = vi + sign * efield
609 xnew(2:3) = self%x_min(2:3) + modulo(xnew(2:3)-self%x_min(2:3), self%Lx(2:3))
611 residual_local(1) = residual_local(1) + (xnew(1)/self%Lx(1)-self%xnew(i_sp,1,i_part)/self%Lx(1))**2*abs(wi(1))
612 residual_local(2) = residual_local(2) + (xnew(2)/self%Lx(2)-self%xnew(i_sp,2,i_part)/self%Lx(2))**2*abs(wi(1))
613 residual_local(3) = residual_local(3) + (xnew(3)/self%Lx(3)-self%xnew(i_sp,3,i_part)/self%Lx(3))**2*abs(wi(1))
615 residual_local(4) = residual_local(4) + (vi(1)-self%vnew(i_sp,1,i_part))**2*abs(wi(1))
616 residual_local(5) = residual_local(5) + (vi(2)-self%vnew(i_sp,2,i_part))**2*abs(wi(1))
617 residual_local(6) = residual_local(6) + (vi(3)-self%vnew(i_sp,3,i_part))**2*abs(wi(1))
619 residual_local(8) = residual_local(8) + mi(1)*0.5_f64*( vi(1)**2 + vi(2)**2 + vi(3)**2-self%vnew(i_sp,1,i_part)**2 -self%vnew(i_sp,2,i_part)**2 -self%vnew(i_sp,3,i_part)**2 )
621 self%xnew(i_sp, :, i_part) = xnew
622 self%vnew(i_sp, :, i_part) = vi
626 self%j_dofs = 0.0_f64
629 self%n_total1+self%n_total0*2, mpi_sum, self%j_dofs )
631 if( self%adiabatic_electrons)
then
632 self%phi_dofs_work = self%phi_dofs
633 call self%maxwell_solver%compute_phi_from_j( self%j_dofs, self%phi_dofs_work, self%efield_dofs_work )
636 residual_local(8) = residual_local(8) + 0.5_f64*(self%maxwell_solver%inner_product( self%phi_dofs_work, self%phi_dofs_work, 0 ) - self%maxwell_solver%inner_product( self%phi_dofs_new, self%phi_dofs_new, 0 ) )
637 residual_local(7) = (sum((self%phi_dofs_work-self%phi_dofs_new)**2))*product(self%particle_mesh_coupling%delta_x)
639 self%efield_dofs_work = self%efield_dofs
640 self%j_dofs=self%j_dofs*self%betar(2)
641 call self%maxwell_solver%compute_E_from_j( self%j_dofs, self%efield_dofs_work )
644 residual_local(8) = residual_local(8) + 0.5_f64*(self%maxwell_solver%L2norm_squared( self%efield_dofs_work(1:self%n_total1), 1, 1 ) + self%maxwell_solver%L2norm_squared( self%efield_dofs_work(1+self%n_total1:self%n_total1+self%n_total0), 1, 2 ) +self%maxwell_solver%L2norm_squared( self%efield_dofs_work(1+self%n_total1 +self%n_total0:self%n_total1+2*self%n_total0), 1, 3 ) - self%maxwell_solver%L2norm_squared( self%efield_dofs_work(1:self%n_total1), 1, 1 ) + self%maxwell_solver%L2norm_squared( self%efield_dofs_new(1+self%n_total1:self%n_total1+self%n_total0), 1, 2 ) + self%maxwell_solver%L2norm_squared( self%efield_dofs_new(1+self%n_total1 +self%n_total0:self%n_total1+2*self%n_total0), 1, 3 ) )
646 residual_local(7) = (sum((self%efield_dofs_work-self%efield_dofs_new)**2))*product(self%particle_mesh_coupling%delta_x)
650 residual(1:7) = sqrt(residual(1:7))
651 residual(8) = abs(residual(8))
652 self%phi_dofs_new = self%phi_dofs_work
653 self%efield_dofs_new = self%efield_dofs_work
656 if ( residual(7) > self%iter_tolerance )
then
658 print*,
'Warning: Iteration no.', self%iter_counter+1 ,
'did not converge.', residual, niter
659 self%n_failed = self%n_failed+1
662 self%efield_dofs_work = 0.5_f64*( self%efield_dofs + self%efield_dofs_new )
663 self%j_dofs_local = 0.0_f64
666 do i_sp=1,self%particle_group%n_species
667 sign = dt*self%particle_group%group(i_sp)%species%q_over_m();
668 do i_part = 1,self%particle_group%group(i_sp)%n_particles
669 vi = self%particle_group%group(i_sp)%get_v(i_part)
670 xi = self%particle_group%group(i_sp)%get_x(i_part)
673 wi = self%particle_group%group(i_sp)%get_charge(i_part, self%i_weight)
674 vbar = 0.5_f64*(vi+self%vnew(i_sp,:, i_part))
676 xnew = xi + dt * vbar
679 call self%particle_group%group(i_sp)%set_v( i_part, vi )
680 call self%particle_group%group(i_sp)%set_x( i_part, xnew )
682 if (self%particle_group%group(i_sp)%n_weights == 3 )
then
683 wall = self%particle_group%group(i_sp)%get_weights(i_part)
684 wall(3) = self%control_variate%cv(i_sp)%update_df_weight( xnew, vi, 0.0_f64, wall(1), wall(2) )
685 call self%particle_group%group(i_sp)%set_weights( i_part, wall )
690 self%j_dofs = 0.0_f64
693 self%n_total1+self%n_total0*2, mpi_sum, self%j_dofs )
695 if( self%adiabatic_electrons)
then
696 call self%maxwell_solver%compute_phi_from_j( self%j_dofs, self%phi_dofs, self%efield_dofs )
698 self%j_dofs=self%j_dofs*self%betar(2)
699 call self%maxwell_solver%compute_E_from_j( self%j_dofs, self%efield_dofs )
703 self%iter_counter = self%iter_counter + 1
704 self%niter(self%iter_counter) = niter
712 sll_real64,
intent( in ) :: xi(3)
713 sll_real64,
intent( inout ) :: xnew(3)
714 sll_real64,
intent( inout ) :: vi(3)
715 sll_real64,
intent( in ) :: wi(1)
716 sll_real64,
intent( in ) :: sign
718 sll_real64 :: xmid(3), vh(3), xbar, dx, efield(3)
721 if(xnew(1) < -self%x_max(1) .or. xnew(1) > 2._f64*self%x_max(1) )
then
723 sll_error(
"particle boundary",
"particle out of bound")
724 else if(xnew(1) < self%x_min(1) .or. xnew(1) > self%x_max(1) )
then
725 if(xnew(1) < self%x_min(1) )
then
727 self%counter_left = self%counter_left+1
728 else if(xnew(1) > self%x_max(1))
then
730 self%counter_right = self%counter_right+1
732 dx = (xbar- xi(1))/(xnew(1)-xi(1))
733 xmid = xi + dx * (xnew-xi)
736 vh = (xmid - xi)*wi(1)
737 call self%particle_mesh_coupling%add_current_evaluate( xi, xmid, vh, self%efield_dofs_work, &
738 self%j_dofs_local, efield )
739 vi = vi + sign* dx* efield
740 select case(self%boundary_particles)
742 xnew(1) = 2._f64*xbar-xnew(1)
745 call self%particle_mesh_coupling%add_charge(xmid, wi(1), self%spline_degree, self%rhob)
747 xnew(1) = self%x_min(1) + modulo(xnew(1)-self%x_min(1), self%Lx(1))
748 xmid(1) = self%x_max(1)+self%x_min(1)-xbar
750 xnew(1) = self%x_min(1) + modulo(xnew(1)-self%x_min(1), self%Lx(1))
751 xmid(1) = self%x_max(1)+self%x_min(1)-xbar
753 vh = (xnew - xmid)*wi(1)
754 call self%particle_mesh_coupling%add_current_evaluate( xmid, xnew, vh, self%efield_dofs_work, &
755 self%j_dofs_local, efield )
756 vi = vi + sign * (1._f64-dx)* efield
758 vh = (xnew - xi)*wi(1)
759 call self%particle_mesh_coupling%add_current_evaluate( xi, xnew, vh, self%efield_dofs_work, &
760 self%j_dofs_local, efield )
761 vi = vi + sign * efield
763 xnew(2:3) = self%x_min(2:3) + modulo(xnew(2:3)-self%x_min(2:3), self%Lx(2:3))
773 sll_real64,
intent(in) :: dt
775 sll_int32 :: i_part, i_sp
776 sll_real64 :: vi(3), xi(3), wi(1)
778 sll_real64 :: efield(3)
781 self%j_dofs_local = 0.0_f64
782 self%particle_mass_1_local = 0.0_f64
783 self%particle_mass_2_local = 0.0_f64
784 self%particle_mass_3_local = 0.0_f64
788 do i_sp = 1, self%particle_group%n_species
789 qoverm = self%particle_group%group(i_sp)%species%q_over_m();
790 do i_part = 1,self%particle_group%group(i_sp)%n_particles
791 vi = self%particle_group%group(i_sp)%get_v(i_part)
792 xi = self%particle_group%group(i_sp)%get_x(i_part)
795 wi = self%particle_group%group(i_sp)%get_charge(i_part, self%i_weight)
798 call self%particle_mesh_coupling%add_charge( xi, wi(1)*vi(1), &
799 [self%spline_degree(1)-1, self%spline_degree(2), self%spline_degree(3)], &
800 self%j_dofs_local(1:self%n_total1) )
801 call self%particle_mesh_coupling%add_charge( xi, wi(1)*vi(2), &
802 [self%spline_degree(1), self%spline_degree(2)-1, self%spline_degree(3)], &
803 self%j_dofs_local(1+self%n_total1:self%n_total1+self%n_total0) )
804 call self%particle_mesh_coupling%add_charge( xi, wi(1)*vi(3), &
805 [self%spline_degree(1), self%spline_degree(2), self%spline_degree(3)-1], &
806 self%j_dofs_local(1+self%n_total1+self%n_total0:self%n_total1+2*self%n_total0) )
810 call self%particle_mesh_coupling%evaluate &
811 (xi, [self%spline_degree(1)-1, self%spline_degree(2), self%spline_degree(3)], self%efield_dofs(1:self%n_total1), efield(1))
812 call self%particle_mesh_coupling%evaluate &
813 (xi, [self%spline_degree(1), self%spline_degree(2)-1, self%spline_degree(3)],self%efield_dofs(self%n_total1+1:self%n_total1+self%n_total0), efield(2))
814 call self%particle_mesh_coupling%evaluate &
815 (xi, [self%spline_degree(1), self%spline_degree(2), self%spline_degree(3)-1],self%efield_dofs(self%n_total1+self%n_total0+1:self%n_total1+2*self%n_total0), efield(3))
817 vi = vi + dt* 0.5_f64* qoverm * efield
818 call self%particle_group%group(i_sp)%set_v( i_part, vi )
823 self%j_dofs = 0.0_f64
826 self%n_total1+self%n_total0*2, mpi_sum, self%j_dofs )
831 call self%maxwell_solver%multiply_mass( [2,1,1], &
832 self%efield_dofs(1:self%n_total1 ), self%j_dofs_local(1:self%n_total1) )
833 self%j_dofs_local( 1:self%n_total1 ) = (1.0_f64-dt**2*0.25_f64*qoverm)*&
834 self%j_dofs_local( 1:self%n_total1 ) - dt* self%j_dofs( 1:self%n_total1 )
838 call self%maxwell_solver%multiply_mass( [1,2,1], &
839 self%efield_dofs(1+self%n_total1:self%n_total1+self%n_total0 ), self%j_dofs_local(1+self%n_total1:self%n_total1+self%n_total0) )
840 self%j_dofs_local( 1+self%n_total1:self%n_total1+self%n_total0 ) = (1.0_f64-dt**2*0.25_f64*qoverm)*&
841 self%j_dofs_local( 1+self%n_total1:self%n_total1+self%n_total0 ) - dt* self%j_dofs( 1+self%n_total1:self%n_total1+self%n_total0 )
845 call self%maxwell_solver%multiply_mass( [1,1,2], self%efield_dofs(1+self%n_total1+self%n_total0:self%n_total1+2*self%n_total0 ), &
846 self%j_dofs_local(1+self%n_total1+self%n_total0:self%n_total1+2*self%n_total0) )
847 self%j_dofs_local( 1+self%n_total1+self%n_total0:self%n_total1+2*self%n_total0 ) = (1.0_f64-dt**2*0.25_f64*qoverm)*&
848 self%j_dofs_local( 1+self%n_total1+self%n_total0:self%n_total1+2*self%n_total0 ) - dt* self%j_dofs( 1+self%n_total1+self%n_total0:self%n_total1+2*self%n_total0 )
852 call self%maxwell_solver%multiply_mass_inverse( 1, self%j_dofs_local, self%efield_dofs )
855 do i_sp = 1, self%particle_group%n_species
856 do i_part = 1, self%particle_group%group(i_sp)%n_particles
858 vi = self%particle_group%group(i_sp)%get_v(i_part)
859 xi = self%particle_group%group(i_sp)%get_x(i_part)
861 call self%particle_mesh_coupling%evaluate &
862 (xi, [self%spline_degree(1)-1, self%spline_degree(2), self%spline_degree(3)], self%efield_dofs(1:self%n_total1), efield(1))
863 call self%particle_mesh_coupling%evaluate &
864 (xi, [self%spline_degree(1), self%spline_degree(2)-1, self%spline_degree(3)],self%efield_dofs(self%n_total1+1:self%n_total1+self%n_total0), efield(2))
865 call self%particle_mesh_coupling%evaluate &
866 (xi, [self%spline_degree(1), self%spline_degree(2), self%spline_degree(3)-1],self%efield_dofs(self%n_total1+self%n_total0+1:self%n_total1+2*self%n_total0), efield(3))
868 vi = vi + dt* 0.5_f64* qoverm * efield
869 call self%particle_group%group(i_sp)%set_v( i_part, vi )
882 particle_mesh_coupling, &
890 boundary_particles, &
892 iter_tolerance, max_iter, &
902 sll_real64,
target,
intent( in ) :: phi_dofs(:)
903 sll_real64,
target,
intent( in ) :: efield_dofs(:)
904 sll_real64,
target,
intent( in ) :: bfield_dofs(:)
905 sll_real64,
intent( in ) :: x_min(3)
906 sll_real64,
intent( in ) :: lx(3)
908 sll_int32,
optional,
intent( in ) :: boundary_particles
909 sll_real64,
optional,
intent( in ) :: solver_tolerance
910 sll_real64,
optional,
intent( in ) :: iter_tolerance
911 sll_int32,
optional,
intent( in ) :: max_iter
912 sll_real64,
optional,
intent(in) :: betar(2)
913 sll_real64,
optional,
intent(in) :: force_sign
914 sll_real64,
optional,
target,
intent( in ) :: rhob(:)
916 logical,
optional,
intent(in) :: jmean
918 sll_int32 :: ierr, i_sp, j
919 sll_real64,
allocatable :: vec1(:)
920 sll_real64,
allocatable :: vec2(:)
922 if (
present(solver_tolerance) )
then
923 self%solver_tolerance = solver_tolerance
926 if (
present(iter_tolerance) )
then
927 self%iter_tolerance = iter_tolerance
928 self%max_iter = max_iter
931 if(
present(force_sign) )
then
932 self%force_sign = force_sign
935 if (self%force_sign == 1._f64)
then
936 if( particle_group%group(1)%species%q > 0._f64) self%adiabatic_electrons = .true.
939 if (
present(jmean))
then
943 if (
present(boundary_particles) )
then
944 self%boundary_particles = boundary_particles
947 if(
present(rhob) )
then
951 self%maxwell_solver => maxwell_solver
952 self%particle_mesh_coupling => particle_mesh_coupling
953 self%particle_group => particle_group
954 self%phi_dofs => phi_dofs
955 self%efield_dofs => efield_dofs
956 self%bfield_dofs => bfield_dofs
957 self%n_total0 = self%maxwell_solver%n_total0
958 self%n_total1 = self%maxwell_solver%n_total1
959 self%spline_degree = self%particle_mesh_coupling%spline_degree
961 self%x_max = x_min + lx
963 self%filter => filter
965 self%nspan(1) = (2*self%spline_degree(1)-1)*(2*self%spline_degree(2)+1)*(2*self%spline_degree(3)+1)
966 self%nspan(2) = (2*self%spline_degree(1)+1)*(2*self%spline_degree(2)-1)*(2*self%spline_degree(3)+1)
967 self%nspan(3) = (2*self%spline_degree(1)+1)*(2*self%spline_degree(2)+1)*(2*self%spline_degree(3)-1)
969 sll_allocate( vec1(1:self%n_total1+self%n_total0*2), ierr )
970 sll_allocate( vec2(1:self%n_total1+self%n_total0*2), ierr )
974 sll_allocate( self%j_dofs(1:self%n_total1+self%n_total0*2), ierr )
975 sll_allocate( self%j_dofs_local(1:self%n_total1+self%n_total0*2), ierr )
977 sll_allocate(self%particle_mass_1_local(self%nspan(1), self%n_total0), ierr )
978 sll_allocate(self%particle_mass_2_local(self%nspan(2), self%n_total0), ierr )
979 sll_allocate(self%particle_mass_3_local(self%nspan(3), self%n_total0), ierr )
980 self%j_dofs = 0.0_f64
981 self%j_dofs_local = 0.0_f64
982 self%particle_mass_1_local = 0.0_f64
983 self%particle_mass_2_local = 0.0_f64
984 self%particle_mass_3_local = 0.0_f64
986 if( self%particle_mesh_coupling%n_cells(1)+self%spline_degree(1) == self%maxwell_solver%n_dofs(1) )
then
987 self%boundary = .true.
997 call self%particle_mass_1%create( self%particle_mesh_coupling%n_cells, [self%spline_degree(1)-1, self%spline_degree(2), self%spline_degree(3)] )
998 call self%particle_mass_2%create( self%particle_mesh_coupling%n_cells, [self%spline_degree(1), self%spline_degree(2)-1, self%spline_degree(3)] )
999 call self%particle_mass_3%create( self%particle_mesh_coupling%n_cells, [self%spline_degree(1), self%spline_degree(2), self%spline_degree(3)-1] )
1001 call self%particle_mass_op%create( 3, 3 )
1002 if( self%adiabatic_electrons )
then
1003 call self%linear_op_schur_phiv%create( self%maxwell_solver, self%particle_mass_op )
1004 call self%linear_solver_schur_phiv%create( self%linear_op_schur_phiv )
1005 self%linear_solver_schur_phiv%atol = self%solver_tolerance
1008 call self%linear_op_schur_ev%create( self%maxwell_solver, self%particle_mass_op)
1009 call self%preconditioner_fft%init( self%maxwell_solver%Lx, self%maxwell_solver%n_cells, self%maxwell_solver%s_deg_0, self%boundary )
1010 if( self%boundary )
then
1012 call self%maxwell_solver%multiply_mass( [1], vec1, vec2 )
1013 do j = 1, self%maxwell_solver%n_dofs(2)*self%maxwell_solver%n_dofs(3)
1014 vec2(self%n_total1+1+(j-1)*self%maxwell_solver%n_dofs(1)) = 1._f64
1015 vec2(self%n_total1+j*self%maxwell_solver%n_dofs(1)) = 1._f64
1016 vec2(self%n_total1+self%n_total0+1+(j-1)*self%maxwell_solver%n_dofs(1)) = 1._f64
1017 vec2(self%n_total1+self%n_total0+j*self%maxwell_solver%n_dofs(1)) = 1._f64
1019 vec2 = 1._f64/sqrt(abs(vec2))
1021 call self%preconditioner1%create( self%preconditioner_fft%inverse_mass1_3d, vec2, 2*self%n_total0+self%n_total1 )
1023 call self%linear_solver_schur_ev%create( self%linear_op_schur_ev, self%preconditioner1)
1025 call self%linear_solver_schur_ev%create( self%linear_op_schur_ev )
1027 self%linear_solver_schur_ev%atol = self%solver_tolerance
1029 self%linear_solver_schur_ev%n_maxiter = 2000
1033 if (
present(betar))
then
1038 self%n_particles_max = self%particle_group%group(1)%n_particles
1039 do i_sp = 2,self%particle_group%n_species
1040 self%n_particles_max = max(self%n_particles_max, self%particle_group%group(i_sp)%n_particles )
1043 sll_allocate( self%xnew(self%particle_group%n_species,3,self%n_particles_max), ierr )
1044 sll_allocate( self%vnew(self%particle_group%n_species,3,self%n_particles_max), ierr )
1045 sll_allocate( self%efield_dofs_new(self%n_total1+2*self%n_total0), ierr )
1046 sll_allocate( self%efield_dofs_work(self%n_total1+2*self%n_total0), ierr )
1047 sll_allocate( self%phi_dofs_work(self%n_total0), ierr )
1048 sll_allocate( self%phi_dofs_new(self%n_total0), ierr )
1049 sll_allocate(self%efield_filter(self%n_total1+2*self%n_total0), ierr)
1050 sll_allocate(self%bfield_filter(self%n_total0+2*self%n_total1), ierr)
1052 if (
present(control_variate))
then
1053 allocate(self%control_variate )
1054 allocate(self%control_variate%cv(self%particle_group%n_species) )
1055 self%control_variate => control_variate
1056 self%i_weight = self%particle_group%group(1)%n_weights
1067 particle_mesh_coupling, &
1076 boundary_particles, &
1086 sll_real64,
target,
intent( in ) :: phi_dofs(:)
1087 sll_real64,
target,
intent( in ) :: efield_dofs(:)
1088 sll_real64,
target,
intent( in ) :: bfield_dofs(:)
1089 sll_real64,
intent( in ) :: x_min(3)
1090 sll_real64,
intent( in ) :: lx(3)
1091 character(len=*),
intent( in ) :: filename
1093 sll_int32,
optional,
intent( in ) :: boundary_particles
1094 sll_real64,
optional,
intent( in ) :: betar(2)
1095 sll_real64,
optional,
intent(in) :: force_sign
1096 sll_real64,
optional,
target,
intent( in ) :: rhob(:)
1098 logical,
optional,
intent(in) :: jmean
1100 character(len=256) :: file_prefix
1101 sll_int32 :: input_file, rank
1102 sll_int32 :: io_stat, io_stat0, io_stat1, file_id
1103 sll_real64 :: maxwell_tolerance, iter_tolerance, betar_set(2), force_sign_set
1104 sll_int32 :: max_iter, boundary_particles_set
1105 logical :: jmean_set
1107 namelist /output/ file_prefix
1108 namelist /time_solver/ maxwell_tolerance
1109 namelist /time_iterate/ iter_tolerance, max_iter
1113 if(
present(boundary_particles) )
then
1114 boundary_particles_set = boundary_particles
1116 boundary_particles_set = 100
1119 if(
present(betar) )
then
1125 if(
present(force_sign) )
then
1126 force_sign_set = force_sign
1128 force_sign_set = 1._f64
1131 if (
present(jmean))
then
1137 if(
present(control_variate) )
then
1139 open(newunit = input_file, file=filename, status=
'old',iostat=io_stat)
1140 if (io_stat /= 0)
then
1141 if (rank == 0 )
then
1142 print*,
'sll_m_time_propagator_pic_vm_3d3v_helper: Input file does not exist. Set default tolerance.'
1143 open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position =
'append', status=
'old', action=
'write', iostat=io_stat)
1144 write(file_id, *)
'field solver tolerance:', 1d-12
1145 write(file_id, *)
'iter_tolerance:', 1d-10
1146 write(file_id, *)
'max_iter:', 20
1147 write(file_id, *)
'control_variate:', .true.
1150 call self%init( maxwell_solver, &
1151 particle_mesh_coupling, &
1159 boundary_particles = boundary_particles_set, &
1161 force_sign=force_sign_set, &
1163 control_variate = control_variate,&
1166 read(input_file, output,iostat=io_stat0)
1167 read(input_file, time_solver,iostat=io_stat)
1168 read(input_file, time_iterate,iostat=io_stat1)
1169 if (io_stat /= 0.and. io_stat1 /= 0)
then
1170 if (rank == 0 )
then
1171 print*,
'sll_m_time_propagator_pic_vm_3d3v_helper: Input parameter does not exist. Set default tolerance.'
1172 open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position =
'append', status=
'old', action=
'write', iostat=io_stat)
1173 write(file_id, *)
'field solver tolerance:', 1d-12
1174 write(file_id, *)
'iter_tolerance:', 1d-10
1175 write(file_id, *)
'max_iter:', 20
1176 write(file_id, *)
'control_variate:', .true.
1179 call self%init( maxwell_solver, &
1180 particle_mesh_coupling, &
1188 boundary_particles = boundary_particles_set, &
1190 force_sign=force_sign_set, &
1192 control_variate = control_variate,&
1194 else if (io_stat == 0 .and. io_stat1 /= 0)
then
1195 if (rank == 0 )
then
1196 open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position =
'append', status=
'old', action=
'write', iostat=io_stat)
1197 write(file_id, *)
'field solver tolerance:', maxwell_tolerance
1198 write(file_id, *)
'iter_tolerance:', 1d-10
1199 write(file_id, *)
'max_iter:', 20
1200 write(file_id, *)
'control_variate:', .true.
1203 call self%init( maxwell_solver, &
1204 particle_mesh_coupling, &
1212 boundary_particles_set, &
1213 maxwell_tolerance, &
1215 force_sign=force_sign_set, &
1217 control_variate = control_variate,&
1219 else if (io_stat /= 0 .and. io_stat1 == 0)
then
1220 if (rank == 0 )
then
1221 open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position =
'append', status=
'old', action=
'write', iostat=io_stat)
1222 write(file_id, *)
'field solver tolerance:', 1d-12
1223 write(file_id, *)
'iter_tolerance:', iter_tolerance
1224 write(file_id, *)
'max_iter:', max_iter
1225 write(file_id, *)
'control_variate:', .true.
1228 call self%init( maxwell_solver, &
1229 particle_mesh_coupling, &
1237 boundary_particles = boundary_particles_set, &
1238 iter_tolerance=iter_tolerance, max_iter=max_iter, &
1240 force_sign=force_sign_set, &
1242 control_variate = control_variate,&
1245 if (rank == 0 )
then
1246 open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position =
'append', status=
'old', action=
'write', iostat=io_stat)
1247 write(file_id, *)
'field solver tolerance:', maxwell_tolerance
1248 write(file_id, *)
'iter_tolerance:', iter_tolerance
1249 write(file_id, *)
'max_iter:', max_iter
1250 write(file_id, *)
'control_variate:', .true.
1253 call self%init( maxwell_solver, &
1254 particle_mesh_coupling, &
1262 boundary_particles_set, &
1263 maxwell_tolerance, &
1264 iter_tolerance, max_iter, &
1266 force_sign=force_sign_set, &
1268 control_variate = control_variate,&
1276 open(newunit = input_file, file=filename, status=
'old',iostat=io_stat)
1277 if (io_stat /= 0)
then
1278 if (rank == 0 )
then
1279 print*,
'sll_m_time_propagator_pic_vm_3d3v_helper: Input file does not exist. Set default tolerance.'
1280 open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position =
'append', status=
'old', action=
'write', iostat=io_stat)
1281 write(file_id, *)
'field solver tolerance:', 1d-12
1282 write(file_id, *)
'iter_tolerance:', 1d-10
1283 write(file_id, *)
'max_iter:', 20
1286 call self%init( maxwell_solver, &
1287 particle_mesh_coupling, &
1295 boundary_particles = boundary_particles_set, &
1297 force_sign=force_sign_set,&
1301 read(input_file, output,iostat=io_stat0)
1302 read(input_file, time_solver,iostat=io_stat)
1303 read(input_file, time_iterate,iostat=io_stat1)
1304 if (io_stat /= 0.and. io_stat1 /= 0)
then
1305 if (rank == 0 )
then
1306 print*,
'sll_m_time_propagator_pic_vm_3d3v_helper: Input parameter does not exist. Set default tolerance.'
1307 open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position =
'append', status=
'old', action=
'write', iostat=io_stat)
1308 write(file_id, *)
'field solver tolerance:', 1d-12
1309 write(file_id, *)
'iter_tolerance:', 1d-10
1310 write(file_id, *)
'max_iter:', 20
1313 call self%init( maxwell_solver, &
1314 particle_mesh_coupling, &
1322 boundary_particles = boundary_particles_set, &
1324 force_sign=force_sign_set,&
1327 else if (io_stat == 0 .and. io_stat1 /= 0)
then
1328 if (rank == 0 )
then
1329 open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position =
'append', status=
'old', action=
'write', iostat=io_stat)
1330 write(file_id, *)
'field solver tolerance:', maxwell_tolerance
1331 write(file_id, *)
'iter_tolerance:', 1d-10
1332 write(file_id, *)
'max_iter:', 20
1335 call self%init( maxwell_solver, &
1336 particle_mesh_coupling, &
1344 boundary_particles_set, &
1345 maxwell_tolerance, &
1347 force_sign=force_sign_set, &
1349 else if (io_stat /= 0 .and. io_stat1 == 0)
then
1350 if (rank == 0 )
then
1351 open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position =
'append', status=
'old', action=
'write', iostat=io_stat)
1352 write(file_id, *)
'field solver tolerance:', 1d-12
1353 write(file_id, *)
'iter_tolerance:', iter_tolerance
1354 write(file_id, *)
'max_iter:', max_iter
1357 call self%init( maxwell_solver, &
1358 particle_mesh_coupling, &
1366 boundary_particles = boundary_particles_set, &
1367 iter_tolerance=iter_tolerance, max_iter=max_iter, &
1369 force_sign=force_sign_set,&
1373 if (rank == 0 )
then
1374 open(newunit=file_id, file=trim(file_prefix)//
'_parameters_used.dat', position =
'append', status=
'old', action=
'write', iostat=io_stat)
1375 write(file_id, *)
'solver tolerance:', maxwell_tolerance
1376 write(file_id, *)
'iter_tolerance:', iter_tolerance
1377 write(file_id, *)
'max_iter:', max_iter
1380 call self%init( maxwell_solver, &
1381 particle_mesh_coupling, &
1389 boundary_particles_set, &
1390 maxwell_tolerance, &
1391 iter_tolerance, max_iter, &
1393 force_sign=force_sign_set,&
1408 sll_int32 :: file_id, j
1410 if( self%boundary )
then
1411 print*,
'left boundary', self%counter_left
1412 print*,
'right boundary', self%counter_right
1415 if(self%adiabatic_electrons)
then
1416 call self%linear_solver_schur_phiv%free()
1417 call self%linear_op_schur_phiv%free()
1419 call self%linear_solver_schur_ev%free()
1420 call self%linear_op_schur_ev%free()
1423 call self%particle_mass_op%free()
1424 call self%particle_mass_1%free()
1425 call self%particle_mass_2%free()
1426 call self%particle_mass_3%free()
1427 deallocate( self%particle_mass_1 )
1428 deallocate( self%particle_mass_2 )
1429 deallocate( self%particle_mass_3 )
1431 deallocate(self%j_dofs)
1432 deallocate(self%j_dofs_local)
1433 deallocate( self%particle_mass_1_local )
1434 deallocate( self%particle_mass_2_local )
1435 deallocate( self%particle_mass_3_local )
1436 self%maxwell_solver => null()
1437 self%particle_mesh_coupling => null()
1438 self%particle_group => null()
1439 self%phi_dofs => null()
1440 self%efield_dofs => null()
1441 self%bfield_dofs => null()
1443 deallocate( self%vnew )
1444 deallocate( self%xnew )
1445 deallocate( self%efield_dofs_new )
1446 deallocate( self%efield_dofs_work )
1447 deallocate( self%phi_dofs_new )
1448 deallocate( self%phi_dofs_work )
1451 print*,
'No. of failed iterations:', self%n_failed
1453 open(newunit=file_id, file=
"outer-iters.dat", action=
'write')
1454 do j=1,self%iter_counter
1455 write(file_id,*) self%niter(j)
Combines values from all processes and distributes the result back to all processes.
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.
Parameters to define common initial distributions.
module for a block linear operator
module for conjugate gradient method in pure form
Module interface to solve Maxwell's equations in 3D.
Base class for kernel smoothers for accumulation and field evaluation in PIC.
Module interface to solve Maxwell's equations with coordinate transformation in 3D The linear systems...
Module interface to solve Maxwell's equations with coordinate transformation in 3D The linear systems...
functions for initial profile of the particle distribution function
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
Particle pusher based on antisymmetric splitting with AVF for 3d3v Vlasov-Maxwell.
subroutine advect_e_pic_vm_3d3v(self, dt)
advect_e: Equations to be solved Solution with Schur complement: $ S_{+}=M_1+\frac{\Delta t^2 q^2}{4 ...
subroutine compute_particle_boundary_current_evaluate(self, xi, xnew, vi, wi, sign)
Helper function for advect_ex.
subroutine advect_vb_pic_vm_3d3v(self, dt)
advect_vb: Equations to be solved $(\mathbb{I}-\Delta \frac{\Delta t q}{2 m} \mathbb{B}(X^n,...
subroutine initialize_pic_vm_3d3v(self, maxwell_solver, particle_mesh_coupling, particle_group, phi_dofs, efield_dofs, bfield_dofs, x_min, Lx, filter, boundary_particles, solver_tolerance, iter_tolerance, max_iter, betar, force_sign, rhob, control_variate, jmean)
Constructor.
subroutine delete_pic_vm_3d3v(self)
Destructor.
subroutine advect_ex_pic_vm_3d3v(self, dt)
advect_ex: Equations to be solved $\frac{X^{n+1}-X^n}{\Delta t}=\frac{V^{n+1}+V^n}{2}$ $\frac{V^{n+1}...
subroutine advect_e_pic_vm_3d3v_trunc(self, dt)
advect_e_trunc: This is a version of advect_e where the Particle Mass is approximated by the mass mat...
subroutine compute_particle_boundary(self, xold, xnew, vi)
Helper function for advect_x.
subroutine advect_eb_schur_pic_vm_3d3v(self, dt)
advect_eb: Equations to be solved Solution with Schur complement: $ S=M_1+\frac{\Delta t^2}{4} C^\top...
subroutine advect_x_pic_vm_3d3v(self, dt)
Finalization.
subroutine initialize_file_pic_vm_3d3v(self, maxwell_solver, particle_mesh_coupling, particle_group, phi_dofs, efield_dofs, bfield_dofs, x_min, Lx, filename, filter, boundary_particles, betar, force_sign, rhob, control_variate, jmean)
Constructor.
real(kind=f64) function, dimension(size(particle, 2)) control_variate(particle)
class for a linear operator_block
class for the cg linear solver
Basic type of a kernel smoother used for PIC simulations.
Helper for implicit time propagators for Vlasov-Maxwell 3d3v.