6 #include "sll_working_precision.h"
7 #include "sll_memory.h"
8 #include "sll_assert.h"
22 sll_int32,
parameter :: sobol_offset = 10
25 sll_real64,
dimension(:, :),
allocatable :: particle
26 sll_real64,
dimension(:),
allocatable :: weight_const, prior_weight
27 sll_real64,
dimension(:),
allocatable :: rk_d, rk_c
28 type(pif_fieldsolver) :: solver
31 sll_int32,
dimension(:),
allocatable :: maskx, maskv, maskxw, maskxv
43 sll_int32 :: npart, npart_loc
44 sll_int32 :: collisions = sll_collisions_none
45 sll_int32 :: controlvariate = sll_controlvariate_none
48 sll_real64,
dimension(:),
allocatable :: kineticenergy, fieldenergy, energy, energy_error, weight_sum, weight_var, moment_error
49 sll_real64,
dimension(:, :),
allocatable ::moment, moment_var
50 sll_comp64,
dimension(:),
allocatable :: rhs, solution
54 sll_int32 :: coll_rank, coll_size
58 sll_int32 ::ierr, idx, jdx
76 if (coll_rank == 0)
then
77 print *,
"Size of MPI-Collective: ", coll_size
82 npart_loc = npart/coll_size
86 if (coll_rank == 0) print *,
"#Total Number of particles: ", npart_loc*coll_size
94 call solver%set_box_len(boxlen)
104 particle(maskw, :) = (1 - 0.4*sum(cos(0.5*particle(maskx, :) + sll_p_pi/3.0), 1))
105 particle(maskw, :) = particle(maskw, :)/prior_weight
107 sll_allocate(weight_const(npart_loc), ierr)
108 weight_const = particle(maskw, :)
111 do idx = 1,
size(maskv)
112 call match_moment_1d_weight_linear_real64(particle(maskv(idx), :), particle(maskw, :), 0.0_f64, 1.0_f64, npart)
116 sll_allocate(rhs(solver%problemsize()), ierr)
117 sll_allocate(solution(solver%problemsize()), ierr)
119 if (coll_rank == 0) print *,
"# TIME IMPULSE ERR.(abs.) ENERGY ERROR(rel.)"
122 if (coll_rank == 0) print *,
"#", dt*(tstep - 1), abs(moment(1, tstep))/npart, energy_error(tstep)
143 sll_allocate(particle(2*dimx + 1, npart_loc), ierr)
146 seed = sobol_offset + coll_rank*npart_loc
147 do idx = 1, npart_loc
149 call i8_sobol(int(2*dimx, 8), seed, particle(1:2*dimx, idx))
155 sll_clear_allocate(kineticenergy(tsteps), ierr)
156 sll_clear_allocate(fieldenergy(tsteps), ierr)
157 sll_clear_allocate(energy(tsteps), ierr)
158 sll_clear_allocate(energy_error(tsteps), ierr)
159 sll_clear_allocate(moment(dimx, tsteps), ierr)
160 sll_clear_allocate(moment_error(tsteps), ierr)
161 sll_clear_allocate(moment_var(dimx, tsteps), ierr)
162 sll_clear_allocate(weight_sum(tsteps), ierr)
163 sll_clear_allocate(weight_var(tsteps), ierr)
170 kineticenergy(tstep) = sum(sum(particle(maskv, :)**2, 1)*particle(maskw, :))/npart
173 fieldenergy(tstep) = abs(dot_product(solution, rhs))
175 energy(tstep) = kineticenergy(tstep) + fieldenergy(tstep)
176 energy_error(tstep) = abs(energy(2) - energy(tstep))/abs(energy(1))
178 do idx = 1,
size(particle, 2)
179 moment(:, tstep) = moment(:, tstep) + (particle(maskv, idx)*particle(maskw, idx))
183 moment_error(tstep) = sqrt(sum((moment(:, 1) - moment(:, tstep))**2))
185 weight_sum(tstep) = sum(particle(maskw, :))/npart
191 sll_int32 :: idx, jdx
194 particle(maskx, :) = particle(maskx, :)*boxlen
196 do idx = 1,
size(particle, 2)
197 do jdx = 1,
size(maskv)
198 call normal_cdf_inv(particle(maskv(jdx), idx), 0.0_f64, 1.0_f64, particle(maskv(jdx), idx))
203 do idx = 1,
size(maskv)
209 sll_allocate(prior_weight(1:npart_loc), ierr)
210 prior_weight = 1.0/boxlen**dimx
218 sll_assert(
size(rk_d) ==
size(rk_c))
221 do rkidx = 1,
size(rk_d);
226 rhs = solver%get_rhs_particle(particle(maskxw, :))/npart
230 solution = solver%solve_poisson(rhs)
236 particle(maskv, :) = particle(maskv, :) - &
237 rk_c(rkidx)*dt*qm*(-solver%eval_gradient(particle(maskx, :), solution));
238 particle(maskx, :) = particle(maskx, :) + rk_d(rkidx)*dt*particle(maskv, :);
244 t = (tstep - 1)*dt + sum(rk_d(1:rkidx))*dt;
250 sll_int32,
intent(in) :: rk_order
251 sll_real64 :: rk4sx = ((2**(1/3) + 2**(-1/3) - 1)/6)
253 sll_allocate(rk_c(rk_order), ierr)
254 sll_allocate(rk_d(rk_order), ierr)
256 SELECT CASE (rk_order)
265 rk_d(:) = (/2.0/3.0, -2.0/3.0, 1.0/)
266 rk_c(:) = (/7.0/24.0, 3/4.0, -1.0/24.0/)
268 rk_d = (/2.0*rk4sx + 1.0, -4.0*rk4sx - 1.0, 2.0*rk4sx + 1.0, 0.0_f64/)
269 rk_c = (/rk4sx + 0.5, -rk4sx, -rk4sx, rk4sx + 0.5/)
272 print *,
"Symplectic Runge Kutta of order:", rk_order
273 print *,
"D_COEFFS:", rk_d
274 print *,
"C_COEFFS:", rk_c
282 sll_allocate(maskx(dimx), ierr)
283 sll_allocate(maskxw(dimx + 1), ierr)
284 sll_allocate(maskv(dimx), ierr)
285 sll_allocate(maskxv(dimx*2), ierr)
287 maskx = (/(idx, idx=1, dimx)/)
288 maskv = (/(idx, idx=dimx + 1, 2*dimx)/)
290 maskxw(1:dimx) = maskx
291 maskxw(dimx + 1) = maskw
292 maskxv(1:dimx) = maskx
293 maskxv(dimx + 1:2*dimx) = maskv
300 if (controlvariate /= 0)
then
302 if (collisions /= 0)
then
304 print *,
"not implemented"
307 particle(maskw, :) = weight_const(:) -
control_variate(particle(maskxv, :))/prior_weight(:)
314 sll_real64,
dimension(:, :),
intent(in) :: particle
315 sll_real64,
dimension(size(particle, 2)) :: cv
318 SELECT CASE (controlvariate)
319 CASE (sll_controlvariate_none)
322 CASE (sll_controlvariate_standard)
323 cv = sqrt(2*sll_p_pi)**(-
size(maskv))*exp(-0.5*sum(particle(maskv, :), 1)**2)
324 CASE (sll_controlvariate_maxwellian)
325 cv = sqrt(2*sll_p_pi)**(-
size(maskv))*exp(-0.5*sum(particle(maskv, :), 1)**2)
332 character(len=*),
parameter :: filename =
"pif"
336 integer :: idx, file_id, file_id_err
339 if (coll_rank == 0)
then
341 call sll_new_file_id(file_id, ierr)
345 open (file_id, file=
'./'//filename//
'.csv')
355 write (file_id, *)
' \"time\", \"kineticenergy\", \"fieldenergy\", \"energy_error\", \"moment_error\"'
360 write (file_id, *) (idx - 1)*dt,
",", kineticenergy(idx),
",", fieldenergy(idx),
",", &
361 fieldenergy(idx),
",", energy_error(idx),
",", moment_error(idx)
integer(kind=i32) function, public sll_f_get_collective_rank(col)
Determines the rank of the calling process in the communicator.
subroutine, public sll_s_halt_collective()
Ends the paralell environment.
subroutine, public sll_s_boot_collective(required)
Starts the paralell environment.
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.
integer(kind=i32) function, public sll_f_get_collective_size(col)
Determines the size of the group associated with a communicator.
subroutine match_moment_1d_linear_real64(x, mean, mom2)
Descriptors for particle methods.
This module provides some routines for plotting during PIC simulations.
We can now use the functions.
subroutine update_weight()
subroutine write_result()
subroutine init_diagnostics
subroutine init_particle_prior_maxwellian()
subroutine calculate_diagnostics
real(kind=f64) function, dimension(size(particle, 2)) control_variate(particle)
subroutine symplectic_rungekutta()
subroutine init_particle_masks()
subroutine set_symplectic_rungekutta_coeffs(rk_order)