7 #include "sll_errors.h"
8 #include "sll_memory.h"
9 #include "sll_assert.h"
10 #include "sll_working_precision.h"
28 use sll_m_prob,
only: &
31 use sll_m_sobol,
only: &
60 sll_int32 :: symmetric
61 sll_int32 :: random_numbers
62 logical :: uniform = .false.
63 sll_int32,
allocatable :: random_seed(:)
64 sll_int32,
allocatable :: random_seed_start(:)
65 sll_int64 :: sobol_seed
66 sll_int64 :: sobol_seed_start
67 logical :: inverse = .false.
68 logical :: xiprofile = .false.
70 logical :: delta_perturb = .false.
71 sll_real64 :: eps(3) = [0.6, 0.6, 0.6]
72 sll_real64 :: a(3) = [0.0, 0.0, 0.0]
90 if (
allocated(self%random_seed))
deallocate( self%random_seed )
97 character(len=*),
intent( in ) :: sampling_type
98 sll_int32,
intent( in ) :: dims(:)
99 sll_int32,
intent( inout ) :: n_particles_local
100 sll_int32,
optional,
intent( in ) :: rank
101 logical,
optional,
intent( in ) :: delta_perturb
102 sll_real64,
optional,
intent( in ) :: delta_eps(6)
106 sll_int32 :: np, j, rnd_seed_size
108 if(
present(delta_perturb) )
then
109 self%delta_perturb = delta_perturb
110 if( delta_perturb )
then
111 self%eps = delta_eps(1:3)
112 self%a = delta_eps(4:6)
117 if(
present(rank)) prank = rank
119 select case( trim(sampling_type) )
120 case(
"particle_sampling_random" )
123 case(
"particle_sampling_random_xiprofile" )
126 self%xiprofile = .true.
127 case(
"particle_sampling_random_inverse" )
130 self%inverse = .true.
131 case(
"particle_sampling_random_inverse_xiprofile" )
134 self%inverse = .true.
135 self%xiprofile = .true.
136 case(
"particle_sampling_sobol" )
139 case(
"particle_sampling_sobol_xiprofile" )
142 self%xiprofile = .true.
143 case(
"particle_sampling_sobol_inverse" )
146 self%inverse = .true.
147 case(
"particle_sampling_sobol_inverse_xiprofile" )
150 self%inverse = .true.
151 self%xiprofile = .true.
152 case(
"particle_sampling_random_symmetric" )
155 case(
"particle_sampling_random_symmetric_xiprofile" )
158 self%xiprofile = .true.
159 case(
"particle_sampling_random_symmetric_inverse" )
162 self%inverse = .true.
163 case(
"particle_sampling_random_symmetric_inverse_xiprofile" )
166 self%inverse = .true.
167 self%xiprofile = .true.
168 case(
"particle_sampling_sobol_symmetric" )
171 case(
"particle_sampling_sobol_symmetric_xiprofile" )
174 self%xiprofile = .true.
175 case(
"particle_sampling_sobol_symmetric_inverse" )
178 self%inverse = .true.
179 case(
"particle_sampling_sobol_symmetric_inverse_xiprofile" )
182 self%inverse = .true.
183 self%xiprofile = .true.
184 case(
"particle_sampling_sobol_symmetric_uniform" )
186 self%uniform = .true.
188 case(
"particle_sampling_random_negative" )
191 case(
"particle_sampling_sobol_negative" )
194 case(
"particle_sampling_random_unix" )
197 case(
"particle_sampling_sobol_unix" )
201 sll_error(
"init_particle_sampling",
"Sampling type not implemented")
205 if (self%symmetric == 1 .or. self%symmetric == 3 )
then
206 ncopies = 2**(sum(dims))
207 np = modulo(n_particles_local,ncopies)
208 if ( np .ne. 0 )
then
209 n_particles_local = n_particles_local + ncopies - np
211 print*,
'Warning: Number of particles has been increased so that the particle number is compatable with symmetric sampling.'
213 elseif (self%symmetric == 2 )
then
215 np = modulo(n_particles_local,ncopies)
216 if ( np .ne. 0 )
then
217 n_particles_local = n_particles_local + ncopies - np
219 print*,
'Warning: Number of particles has been increased so that the particle number is compatable with symmetric sampling.'
225 select case ( self%random_numbers )
227 call random_seed(size=rnd_seed_size)
228 allocate(self%random_seed(1:rnd_seed_size))
229 allocate(self%random_seed_start(1:rnd_seed_size))
230 do j=1, rnd_seed_size
231 self%random_seed(j) = (-1)**j*(100 + 15*j)*(2*prank + 1)
233 self%random_seed_start = self%random_seed
235 self%sobol_seed = int(10 + prank*n_particles_local/ncopies, 8)
236 self%sobol_seed_start = self%sobol_seed
244 sll_int32,
intent( in ) :: jump
247 select case ( self%random_numbers )
249 self%random_seed = self%random_seed_start+jump
251 self%sobol_seed = self%sobol_seed_start+int(jump,8)
262 sll_real64,
intent(in) :: xmin(:)
263 sll_real64,
intent(in) :: lx(:)
265 sll_real64,
optional,
intent(in) :: time
267 logical,
optional :: lindf
269 sll_real64 :: vi(3), xi(3), x(3), wi(particle_group%n_weights)
270 sll_int32 :: i_part, counter
271 sll_real64 :: time0, rx(3), q, m, g0, df_weight
272 logical :: delta_perturb, lindf0
276 if(
present(time) ) time0 = time
277 if(
present(lindf) ) lindf0 = lindf
279 delta_perturb = self%delta_perturb
280 self%delta_perturb = .false.
282 if(
present(map))
then
284 call self%sample( particle_group, params, xmin, lx, map )
287 call self%sample( particle_group, params, xmin, lx )
293 do i_part = 1, particle_group%n_particles
294 q = particle_group%species%q
295 m = particle_group%species%m
296 xi = particle_group%get_x( i_part )
297 vi = particle_group%get_v( i_part )
298 wi = particle_group%get_weights( i_part )
300 if( self%xiprofile )
then
301 if(
present(map))
then
302 if( self%inverse )
then
303 g0 = params%eval_v_density( vi(1:params%dims(2)), xi(1:params%dims(1)), m=particle_group%species%m )/map%volume
305 g0 = params%eval_v_density( vi(1:params%dims(2)), xi(1:params%dims(1)), m=particle_group%species%m )/map%jacobian(xi)
308 rx(1) = map%get_x1(xi) + m*vi(2)/q
309 rx(1) = (rx(1) - xmin(1))/lx(1)
310 df_weight = control_variate%update_df_weight( rx, vi, time0, wi(1), g0 )
313 g0 = params%eval_v_density( vi(1:params%dims(2)), x(1:params%dims(1)), m=particle_group%species%m )/product(lx)
315 rx(1) = xi(1) + m*vi(2)/q
316 rx(1) = (rx(1) - xmin(1))/lx(1)
317 df_weight = control_variate%update_df_weight( rx, vi, time0, wi(1), g0 )
320 if(
present(map))
then
322 g0 = params%eval_v_density( vi(1:params%dims(2)), xi(1:params%dims(1)), m=particle_group%species%m )/map%jacobian(xi)
325 g0 = params%eval_v_density( vi(1:params%dims(2)), xi(1:params%dims(1)), m=particle_group%species%m )/product(lx)
327 df_weight = control_variate%update_df_weight( xi, vi, time0, wi(1), g0 )
328 if(delta_perturb)
then
329 if( particle_group%species%q < 0._f64)
then
330 if( x(1) > 0.5_f64-self%eps(1) .and. x(1) < 0.5_f64+self%eps(1) )
then
331 if( x(2) > 0.5_f64-self%eps(2) .and. x(2) < 0.5_f64+self%eps(2) )
then
332 if(xi(3) > 0.5_f64-self%eps(3) .and. x(3) < 0.5_f64+self%eps(3) )
then
334 counter = counter + 1
340 call particle_group%set_v(i_part, vi)
348 call particle_group%set_weights( i_part, wi )
350 if(delta_perturb)
then
351 print*,
'delta_perturb_cv: ', self%eps, self%a,
'shifted particles:', counter
447 sll_real64,
intent(in) :: xmin(:)
448 sll_real64,
intent(in) :: lx(:)
454 if(
present(map))
then
456 if( self%symmetric == 0 )
then
458 elseif ( self%symmetric == 1 )
then
459 if ( params%dims(1) == 1 .and. params%dims(2) == 2 )
then
461 elseif ( params%dims(1) == 3 .and. params%dims(2) == 3 )
then
464 sll_error(
"sample_particle_sampling",
"symmetric sampling not implemented for given dimension")
467 sll_error(
"sample_particle_sampling",
"this symmetric sampling is not implemented")
471 if( self%symmetric == 0 )
then
473 elseif ( self%symmetric == 1 )
then
474 if ( params%dims(1) == 1 .and. params%dims(2) == 2 )
then
476 elseif ( params%dims(1) == 3 .and. params%dims(2) == 3 )
then
477 if( self%uniform )
then
483 sll_error(
"sample_particle_sampling",
"symmetric sampling not implemented for given dimension")
485 elseif ( self%symmetric == 2)
then
486 if ( params%dims(1) == 1 .and. params%dims(2) == 2 )
then
489 sll_error(
"sample_particle_sampling",
"symmetric sampling not implemented for given dimension")
491 elseif( self%symmetric == 3)
then
492 if ( params%dims(1) == 1 .and. params%dims(2) == 2 )
then
507 sll_real64,
intent( in ) :: xmin(:)
508 sll_real64,
intent( in ) :: lx(:)
511 sll_real64 :: x(3), xi(3), v(3)
513 sll_int32 :: i_v, i_gauss
514 sll_real64,
allocatable :: rdn(:)
515 sll_real64 :: wi(particle_group%n_weights)
517 sll_real64 :: delta(params%n_gaussians)
518 sll_real64 :: common_weight
519 sll_real64 :: r, rx(3)
522 if ( params%n_gaussians > 1 )
then
526 do i_v=1,params%n_gaussians
527 delta(i_v) = sum(params%delta(1:i_v))
531 n_rnds = n_rnds+params%dims(1)+params%dims(2)
532 allocate( rdn(1:params%dims(1)+params%dims(2)+1) )
536 common_weight = particle_group%get_common_weight()
537 call particle_group%set_common_weight &
538 (common_weight/real(particle_group%n_total_particles, f64))
541 call random_seed(put=self%random_seed)
544 do i_part = 1, particle_group%n_particles
546 select case( self%random_numbers )
548 call sll_s_i8_sobol( int(n_rnds,8), self%sobol_seed, rdn(1:n_rnds))
550 call random_number( rdn(1:n_rnds) )
554 xi(1:params%dims(1)) = rdn(1:params%dims(1))
555 x(1:params%dims(1)) = xmin + lx * xi(1:params%dims(1))
558 do i_v = 1,params%dims(2)
559 call sll_s_normal_cdf_inv( rdn(i_v+params%dims(1)), 0.0_f64, 1.0_f64, &
563 rnd_no = rdn(params%dims(1)+params%dims(2)+1)
565 do while( rnd_no > delta(i_gauss) )
568 if( self%xiprofile )
then
569 select type(p=>params)
571 if( particle_group%species%q > 0._f64)
then
572 v(1:p%dims(2)) = v(1:p%dims(2)) * sqrt(p%profile%T_i(xi(1))/particle_group%species%m) + p%v_mean(:,i_gauss)
574 v(1:p%dims(2)) = v(1:p%dims(2)) * sqrt(p%profile%T_e(xi(1))/particle_group%species%m) + p%v_mean(:,i_gauss)
578 rx(1) = x(1) + particle_group%species%m*v(2)/particle_group%species%q
579 rx(1) = (rx(1) - xmin(1))/lx(1)
582 wi(1) = p%eval_x_density(xi(1:p%dims(1)), v(1:p%dims(2)))*&
583 p%eval_v_density(v(1:p%dims(2)), rx(1:p%dims(1)), particle_group%species%m)/p%eval_v_density(v(1:p%dims(2)), xi(1:p%dims(1)), particle_group%species%m) *product(lx)
585 if( particle_group%species%q > 0._f64)
then
586 v(1:p%dims(2)) = v(1:p%dims(2)) * sqrt(p%profile%T_i(xi(1))/particle_group%species%m) + p%v_mean(:,i_gauss)
588 v(1:p%dims(2)) = v(1:p%dims(2)) * sqrt(p%profile%T_e(xi(1))/particle_group%species%m) + p%v_mean(:,i_gauss)
590 wi(1) = p%eval_x_density(xi(1:p%dims(1))) *product(lx)
593 v(1:params%dims(2)) = v(1:params%dims(2)) * params%v_thermal(:,i_gauss) + params%v_mean(:,i_gauss)
595 wi(1) = params%eval_x_density(x(1:params%dims(1)),v(1:params%dims(2)))*product(lx)
598 call particle_group%set_x(i_part, x)
599 call particle_group%set_v(i_part, v)
601 call particle_group%set_weights(i_part, &
605 if( particle_group%species%q < 0._f64)
then
606 if( self%delta_perturb )
then
619 sll_real64,
intent(in) :: xmin(:)
620 sll_real64,
intent(in) :: lx(:)
623 sll_real64 :: x(3),v(3)
626 sll_real64,
allocatable :: rdn(:)
629 sll_int32 :: ip, i_gauss, counter
630 sll_real64 :: delta(params%n_gaussians)
633 if ( params%n_gaussians > 1 )
then
637 do i_v=1,params%n_gaussians
638 delta(i_v) = sum(params%delta(1:i_v))
641 n_rnds = n_rnds+params%dims(1)+params%dims(2)
642 allocate( rdn(1:params%dims(1)+params%dims(2)+1) )
646 call particle_group%set_common_weight &
647 (1.0_f64/real(particle_group%n_total_particles, f64))
650 call random_seed(put=self%random_seed)
653 do i_part = 1, particle_group%n_particles
654 ip = modulo(i_part, 8 )
657 select case( self%random_numbers )
659 call sll_s_i8_sobol( int(n_rnds,8), self%sobol_seed, rdn(1:n_rnds))
661 call random_number( rdn(1:n_rnds) )
665 x(1:params%dims(1)) = xmin + lx * rdn(1:params%dims(1))
668 wi(1) = params%eval_x_density(x(1:params%dims(1)))*product(lx)
671 do i_v = 1,params%dims(2)
672 call sll_s_normal_cdf_inv( rdn(i_v+params%dims(1)), 0.0_f64, 1.0_f64, &
676 rnd_no = rdn(params%dims(1)+params%dims(2)+1)
678 do while( rnd_no > delta(i_gauss) )
681 v(1:params%dims(2)) = v(1:params%dims(2)) * params%v_thermal(:,i_gauss) + params%v_mean(:,i_gauss)
682 elseif ( ip == 5 )
then
683 x(1) = lx(1) - x(1) + 2.0_f64*xmin(1)
685 wi(1) = params%eval_x_density(x(1:params%dims(1)))*product(lx)
687 elseif ( modulo(ip,2) == 0 )
then
688 v(1) = -v(1) + 2.0_f64*params%v_mean(1,i_gauss)
690 v(2) = -v(2) + 2.0_f64*params%v_mean(2,i_gauss)
694 call particle_group%set_x(i_part, x)
695 call particle_group%set_v(i_part, v)
697 call particle_group%set_weights(i_part, &
702 if( particle_group%species%q < 0._f64)
then
703 if( self%delta_perturb )
then
717 sll_real64,
intent(in) :: xmin(:)
718 sll_real64,
intent(in) :: lx(:)
721 sll_real64 :: x(3),v(3), xi(3)
724 sll_real64,
allocatable :: rdn(:)
727 sll_int32 :: ip, i_gauss
728 sll_real64 :: delta(params%n_gaussians)
729 sll_real64 :: common_weight
731 print*,
'new sampling'
734 if ( params%n_gaussians > 1 )
then
738 do i_v=1,params%n_gaussians
739 delta(i_v) = sum(params%delta(1:i_v))
742 n_rnds = n_rnds+params%dims(1)+params%dims(2)
743 allocate( rdn(1:params%dims(1)+params%dims(2)+1) )
747 common_weight = particle_group%get_common_weight()
748 call particle_group%set_common_weight &
749 (common_weight/real(particle_group%n_total_particles, f64))
752 call random_seed(put=self%random_seed)
755 do i_part = 1, particle_group%n_particles
756 ip = modulo(i_part, 2 )
759 select case( self%random_numbers )
761 call sll_s_i8_sobol( int(n_rnds,8), self%sobol_seed, rdn(1:n_rnds))
763 call random_number( rdn(1:n_rnds) )
767 xi(1:params%dims(1)) = rdn(1:params%dims(1))
768 x(1:params%dims(1)) = xmin + lx * xi(1:params%dims(1))
771 wi(1) = params%eval_x_density(x(1:params%dims(1)))*product(lx)
774 do i_v = 1,params%dims(2)
775 call sll_s_normal_cdf_inv( rdn(i_v+params%dims(1)), 0.0_f64, 1.0_f64, &
779 rnd_no = rdn(params%dims(1)+params%dims(2)+1)
781 do while( rnd_no > delta(i_gauss) )
784 v(1:params%dims(2)) = v(1:params%dims(2)) * params%v_thermal(:,i_gauss) + params%v_mean(:,i_gauss)
786 x(1) = lx(1) - x(1) + 2.0_f64*xmin(1)
787 v(1) = -v(1) + 2.0_f64*params%v_mean(1,i_gauss)
788 v(2) = -v(2) + 2.0_f64*params%v_mean(2,i_gauss)
792 call particle_group%set_x(i_part, x)
793 call particle_group%set_v(i_part, v)
795 call particle_group%set_weights(i_part, &
807 sll_real64,
intent(in) :: xmin(:)
808 sll_real64,
intent(in) :: lx(:)
811 sll_real64 :: x(3),v(3), xi(3)
814 sll_real64,
allocatable :: rdn(:)
818 sll_real64 :: delta(params%n_gaussians)
819 sll_real64 :: dx(params%dims(1))
820 sll_real64 :: common_weight
822 print*,
'new sampling 2'
825 if ( params%n_gaussians > 1 )
then
829 do i_v=1,params%n_gaussians
830 delta(i_v) = sum(params%delta(1:i_v))
833 n_rnds = n_rnds+params%dims(2)
834 allocate( rdn(1:params%dims(1)+params%dims(2)+1) )
838 common_weight = particle_group%get_common_weight()
839 call particle_group%set_common_weight &
840 (common_weight/real(particle_group%n_total_particles, f64))
843 call random_seed(put=self%random_seed)
846 dx = lx/real(particle_group%n_particles/2,f64)
848 do i_part = 1, particle_group%n_particles/4
851 x(1:params%dims(1)) = xmin + real(i_part-1, f64)*dx
853 wi(1) = params%eval_x_density(x(1:params%dims(1)))*product(lx)
857 select case( self%random_numbers )
859 call sll_s_i8_sobol( int(n_rnds,8), self%sobol_seed, rdn(1:n_rnds))
861 call random_number( rdn(1:n_rnds) )
864 do i_v = 1,params%dims(2)
865 call sll_s_normal_cdf_inv( rdn(i_v), 0.0_f64, 1.0_f64, &
869 rnd_no = rdn(params%dims(2)+1)
871 do while( rnd_no > delta(i_gauss) )
874 v(1:params%dims(2)) = v(1:params%dims(2)) * params%v_thermal(:,i_gauss) + params%v_mean(:,i_gauss)
877 call particle_group%set_x(2*i_part-1, x)
878 call particle_group%set_v(2*i_part-1, v)
880 call particle_group%set_weights(2*i_part-1, &
885 select case( self%random_numbers )
887 call sll_s_i8_sobol( int(n_rnds,8), self%sobol_seed, rdn(1:n_rnds))
889 call random_number( rdn(1:n_rnds) )
892 do i_v = 1,params%dims(2)
893 call sll_s_normal_cdf_inv( rdn(i_v), 0.0_f64, 1.0_f64, &
897 rnd_no = rdn(params%dims(2)+1)
899 do while( rnd_no > delta(i_gauss) )
902 v(1:params%dims(2)) = v(1:params%dims(2)) * params%v_thermal(:,i_gauss) + params%v_mean(:,i_gauss)
905 call particle_group%set_x(2*i_part, x)
906 call particle_group%set_v(2*i_part, v)
908 call particle_group%set_weights(2*i_part, &
912 x = xmin + lx*0.5_f64
913 call particle_group%set_x(1, x)
916 do i_part = 1,particle_group%n_particles/2
918 x = particle_group%get_x( i_part )
919 v = -particle_group%get_v( i_part )
921 x(1:params%dims(1)) = lx - x(1:params%dims(1)) + 2.0_f64*xmin
923 wi(1) = params%eval_x_density(x(1:params%dims(1)))*product(lx)
926 call particle_group%set_x(i_part+ particle_group%n_particles/2, x)
927 call particle_group%set_v(i_part+ particle_group%n_particles/2, v)
929 call particle_group%set_weights(i_part+ particle_group%n_particles/2, &
942 sll_real64,
intent(in) :: xmin(:)
943 sll_real64,
intent(in) :: lx(:)
946 sll_real64 :: x(3),v(3), xi(3)
950 sll_real64,
allocatable :: rdn(:)
954 sll_real64 :: delta(params%n_gaussians)
955 sll_real64 :: dx(params%dims(1))
956 sll_real64 :: common_weight
958 print*,
'new sampling 2'
961 if ( params%n_gaussians > 1 )
then
965 do i_v=1,params%n_gaussians
966 delta(i_v) = sum(params%delta(1:i_v))
969 n_rnds = n_rnds+params%dims(2)
970 allocate( rdn(1:params%dims(1)+params%dims(2)+1) )
974 common_weight = particle_group%get_common_weight()
975 call particle_group%set_common_weight &
976 (common_weight/real(particle_group%n_total_particles, f64))
979 call random_seed(put=self%random_seed)
982 dx = lx/real(particle_group%n_particles/4,f64)
984 do i_part = 1, particle_group%n_particles/8+1
987 x(1:params%dims(1)) = xmin + real(i_part-1,f64)*dx
989 wi(1) = params%eval_x_density(x(1:params%dims(1)))*product(lx)
993 select case( self%random_numbers )
995 call sll_s_i8_sobol( int(n_rnds,8), self%sobol_seed, rdn(1:n_rnds))
997 call random_number( rdn(1:n_rnds) )
1000 do i_v = 1,params%dims(2)
1001 call sll_s_normal_cdf_inv( rdn(i_v), 0.0_f64, 1.0_f64, &
1005 rnd_no = rdn(params%dims(2)+1)
1007 do while( rnd_no > delta(i_gauss) )
1010 v(1:params%dims(2)) = v(1:params%dims(2)) * params%v_thermal(:,i_gauss) + params%v_mean(:,i_gauss)
1014 call particle_group%set_x(4*i_part-j, x)
1016 call particle_group%set_weights(4*i_part-j, &
1020 call particle_group%set_v(4*i_part-3, v)
1021 call particle_group%set_v(4*i_part-2, [-v(1),v(2),v(3)])
1022 call particle_group%set_v(4*i_part-1, [v(1),-v(2),v(3)])
1023 call particle_group%set_v(4*i_part, [-v(1),-v(2),v(3)])
1029 do i_part = 5,particle_group%n_particles/2
1031 x = particle_group%get_x( i_part )
1032 v = -particle_group%get_v( i_part )
1034 x(1:params%dims(1)) = lx - x(1:params%dims(1)) + 2.0_f64*xmin
1036 wi(1) = params%eval_x_density(x(1:params%dims(1)))*product(lx)
1039 call particle_group%set_x(i_part+ particle_group%n_particles/2, x)
1040 call particle_group%set_v(i_part+ particle_group%n_particles/2, v)
1042 call particle_group%set_weights(i_part+ particle_group%n_particles/2, &
1056 sll_real64,
intent(in) :: xmin(:)
1057 sll_real64,
intent(in) :: lx(:)
1060 sll_real64 :: x(3),v(3)
1063 sll_real64,
allocatable :: rdn(:)
1065 sll_real64 :: rnd_no
1066 sll_int32 :: ip, i_gauss
1067 sll_real64 :: delta(params%n_gaussians)
1070 if ( params%n_gaussians > 1 )
then
1074 do i_v=1,params%n_gaussians
1075 delta(i_v) = sum(params%delta(1:i_v))
1078 n_rnds = n_rnds+params%dims(1)+params%dims(2)
1079 allocate( rdn(1:params%dims(1)+params%dims(2)+1) )
1083 call particle_group%set_common_weight &
1084 (1.0_f64/real(particle_group%n_total_particles, f64))
1087 call random_seed(put=self%random_seed)
1090 do i_part = 1, particle_group%n_particles
1091 ip = modulo(i_part, 64 )
1094 select case( self%random_numbers )
1096 call sll_s_i8_sobol( int(n_rnds,8), self%sobol_seed, rdn(1:n_rnds))
1098 call random_number( rdn(1:n_rnds) )
1102 x(1:params%dims(1)) = xmin + lx * rdn(1:params%dims(1))
1105 wi(1) = params%eval_x_density(x(1:params%dims(1)))*product(lx)
1108 do i_v = 1,params%dims(2)
1109 call sll_s_normal_cdf_inv( rdn(i_v+params%dims(1)), 0.0_f64, 1.0_f64, &
1113 rnd_no = rdn(params%dims(1)+params%dims(2)+1)
1115 do while( rnd_no > delta(i_gauss) )
1118 v(1:params%dims(2)) = v(1:params%dims(2)) * params%v_thermal(:,i_gauss) + params%v_mean(:,i_gauss)
1119 elseif ( modulo(i_part, 2) == 0 )
then
1120 v(3) = - v(3) + 2.0_f64*params%v_mean(3,i_gauss)
1121 elseif ( modulo(i_part, 4) == 3 )
then
1122 v(2) = - v(2) + 2.0_f64*params%v_mean(2,i_gauss)
1123 elseif ( modulo(i_part, 8) == 5 )
then
1124 v(1) = - v(1) + 2.0_f64*params%v_mean(1,i_gauss)
1125 elseif ( modulo(i_part, 16) == 9 )
then
1126 x(3) = lx(3) - x(3) + 2.0_f64*xmin(3)
1128 wi(1) = params%eval_x_density(x(1:params%dims(1)))*product(lx)
1129 elseif ( modulo(i_part, 32) == 17 )
then
1130 x(2) = lx(2) - x(2) + 2.0_f64*xmin(2)
1132 wi(1) = params%eval_x_density(x(1:params%dims(1)))*product(lx)
1133 elseif ( modulo(i_part, 64) == 33 )
then
1134 x(1) = lx(1) - x(1) + 2.0_f64*xmin(1)
1136 wi(1) = params%eval_x_density(x(1:params%dims(1)))*product(lx)
1140 call particle_group%set_x(i_part, x)
1141 call particle_group%set_v(i_part, v)
1143 call particle_group%set_weights(i_part, &
1148 if( particle_group%species%q < 0._f64)
then
1149 if( self%delta_perturb )
then
1162 sll_real64,
intent(in) :: xmin(:)
1163 sll_real64,
intent(in) :: lx(:)
1166 sll_real64 :: x(3), v(3), xi(3)
1167 sll_int32 :: i_part, i_v
1168 sll_real64,
allocatable :: rdn(:)
1170 sll_real64 :: rnd_no
1171 sll_int32 :: ip, i_gauss
1172 sll_real64 :: v_min(3), lv(3)
1175 if ( params%n_gaussians > 1 )
then
1180 n_rnds = n_rnds+params%dims(1)+params%dims(2)
1181 allocate( rdn(1:params%dims(1)+params%dims(2)+1) )
1185 v_min(i_v) = minval(params%v_mean(i_v,:)) -3._f64 * maxval(params%v_thermal(i_v,:))
1186 lv(i_v) = v_min(i_v) - maxval(params%v_mean(i_v,:)) +3._f64 * maxval(params%v_thermal(i_v,:))
1190 call particle_group%set_common_weight &
1191 (1.0_f64/real(particle_group%n_total_particles, f64))
1194 call random_seed(put=self%random_seed)
1197 do i_part = 1, particle_group%n_particles
1198 ip = modulo(i_part, 64 )
1201 select case( self%random_numbers )
1203 call sll_s_i8_sobol( int(n_rnds,8), self%sobol_seed, rdn(1:n_rnds))
1205 call random_number( rdn(1:n_rnds) )
1209 xi(1:params%dims(1)) = rdn(1:params%dims(1))
1210 x(1:params%dims(1)) = xmin + lx * xi(1:params%dims(1))
1213 v(1:params%dims(2)) = v_min + lv * rdn(params%dims(1)+1:params%dims(1)+params%dims(2))
1216 wi(1) = params%eval_xv_density(x(1:params%dims(1)), v(1:params%dims(2)))*product(lx)*product(lv)
1217 elseif ( modulo(i_part, 2) == 0 )
then
1218 v(3) = - v(3) + 2.0_f64*params%v_mean(3,i_gauss)
1219 elseif ( modulo(i_part, 4) == 3 )
then
1220 v(2) = - v(2) + 2.0_f64*params%v_mean(2,i_gauss)
1221 elseif ( modulo(i_part, 8) == 5 )
then
1222 v(1) = - v(1) + 2.0_f64*params%v_mean(1,i_gauss)
1223 elseif ( modulo(i_part, 16) == 9 )
then
1224 x(3) = lx(3) - x(3) + 2.0_f64*xmin(3)
1227 wi(1) = params%eval_x_density(x(1:params%dims(1)))*product(lx)
1228 elseif ( modulo(i_part, 32) == 17 )
then
1229 x(2) = lx(2) - x(2) + 2.0_f64*xmin(2)
1232 wi(1) = params%eval_x_density(x(1:params%dims(1)))*product(lx)
1233 elseif ( modulo(i_part, 64) == 33 )
then
1234 x(1) = lx(1) - x(1) + 2.0_f64*xmin(1)
1237 wi(1) = params%eval_x_density(x(1:params%dims(1)))*product(lx)
1241 call particle_group%set_x(i_part, x)
1242 call particle_group%set_v(i_part, v)
1244 call particle_group%set_weights(i_part, &
1257 sll_real64,
intent( in ) :: xmin(:)
1258 sll_real64,
intent( in ) :: lx(:)
1262 sll_real64 :: x(3), xi(3), v(3)
1264 sll_int32 :: i_v, i_gauss
1265 sll_real64,
allocatable :: rdn(:)
1266 sll_real64 :: wi(particle_group%n_weights)
1267 sll_real64 :: rnd_no
1268 sll_real64 :: delta(params%n_gaussians)
1269 sll_real64 :: w_total(1), w_local(1)
1270 sll_real64 :: common_weight
1271 sll_real64 :: r, rx(3)
1276 if ( params%n_gaussians > 1 )
then
1280 do i_v=1,params%n_gaussians
1281 delta(i_v) = sum(params%delta(1:i_v))
1284 n_rnds = n_rnds+params%dims(1)+params%dims(2)
1285 allocate( rdn(1:params%dims(1)+params%dims(2)+1) )
1289 common_weight = particle_group%get_common_weight()
1290 call particle_group%set_common_weight &
1291 (common_weight/real(particle_group%n_total_particles, f64))
1294 call random_seed(put=self%random_seed)
1297 do i_part = 1, particle_group%n_particles
1299 select case( self%random_numbers )
1301 call sll_s_i8_sobol( int(n_rnds,8), self%sobol_seed, rdn(1:n_rnds))
1303 call random_number( rdn(1:n_rnds) )
1310 if( self%inverse )
then
1312 x(1:2) = 2._f64*map%params(2) * rdn(1:2) - map%params(2)
1313 x(3) = map%params(3) * rdn(3)
1314 r = sqrt(x(1)**2 +x(2)**2)
1315 do while( r > map%params(2) .or. r < map%params(1) )
1316 select case( self%random_numbers )
1318 call sll_s_i8_sobol( int(n_rnds,8), self%sobol_seed, rdn(1:n_rnds))
1320 call random_number( rdn(1:n_rnds) )
1323 x(1:2) = 2._f64*map%params(2) * rdn(1:2) - map%params(2)
1324 x(3) = map%params(3) * rdn(3)
1326 r = sqrt(x(1)**2 +x(2)**2)
1331 wi(1) = params%eval_x_density(x) * map%volume
1333 xi(1:params%dims(1)) = rdn(1:params%dims(1))
1337 do i_v = 1,params%dims(2)
1338 call sll_s_normal_cdf_inv( rdn(i_v+params%dims(1)), 0.0_f64, 1.0_f64, &
1342 rnd_no = rdn(params%dims(1)+params%dims(2)+1)
1344 do while( rnd_no > delta(i_gauss) )
1347 if( self%xiprofile )
then
1348 select type(p=>params)
1350 if( particle_group%species%q > 0._f64)
then
1351 v(1:p%dims(2)) = v(1:p%dims(2)) * sqrt(p%profile%T_i(xi(1))/particle_group%species%m) + p%v_mean(:,i_gauss)
1353 v(1:p%dims(2)) = v(1:p%dims(2)) * sqrt(p%profile%T_e(xi(1))/particle_group%species%m) + p%v_mean(:,i_gauss)
1356 rx(1) = x(1) + particle_group%species%m*v(2)/particle_group%species%q
1357 rx(1) = (rx(1) - xmin(1))/lx(1)
1360 wi(1) = p%eval_x_density(xi(1:p%dims(1)), v(1:p%dims(2)))*&
1361 p%eval_v_density(v(1:p%dims(2)), rx(1:p%dims(1)), particle_group%species%m)/p%eval_v_density(v(1:p%dims(2)), xi(1:p%dims(1)), particle_group%species%m) *map%jacobian(xi)
1363 wi(1) = params%eval_x_density( xi(1:params%dims(1)) )*map%jacobian(xi)
1366 v(1:params%dims(2)) = v(1:params%dims(2)) * params%v_thermal(:,i_gauss) + params%v_mean(:,i_gauss)
1368 wi(1) = params%eval_x_density( x(1:params%dims(1)) )*map%jacobian(xi)
1371 call particle_group%set_x(i_part, xi)
1372 call particle_group%set_v(i_part, v)
1374 call particle_group%set_weights(i_part, &
1379 if( particle_group%species%q < 0._f64)
then
1380 if( self%delta_perturb )
then
1390 sll_real64,
intent(in) :: xmin(:)
1391 sll_real64,
intent(in) :: lx(:)
1394 sll_real64 :: xi(3), vi(3)
1395 sll_int32 :: i_part, counter
1398 do i_part = 1, particle_group%n_particles
1399 xi = particle_group%get_x(i_part)
1400 vi = particle_group%get_v(i_part)
1403 if( xi(1) > 0.5_f64-self%eps(1) .and. xi(1) < 0.5_f64+self%eps(1) )
then
1404 if( xi(2) > 0.5_f64-self%eps(2) .and. xi(2) < 0.5_f64+self%eps(2) )
then
1405 if(xi(3) > 0.5_f64-self%eps(3) .and. xi(3) < 0.5_f64+self%eps(3) )
then
1407 counter = counter + 1
1411 call particle_group%set_v(i_part, vi)
1413 print*,
'delta_perturb, ', self%eps, self%a,
'shifted particles:', counter
1422 sll_real64,
intent( in ) :: lx(:)
1426 sll_real64 :: x(3),v(3), xi(3)
1429 sll_real64,
allocatable :: rdn(:)
1431 sll_real64 :: rnd_no
1432 sll_int32 :: ip, i_gauss
1433 sll_real64 :: delta(params%n_gaussians)
1434 sll_real64 :: common_weight
1437 if ( params%n_gaussians > 1 )
then
1441 do i_v=1,params%n_gaussians
1442 delta(i_v) = sum(params%delta(1:i_v))
1445 n_rnds = n_rnds+params%dims(1)+params%dims(2)
1446 allocate( rdn(1:params%dims(1)+params%dims(2)+1) )
1450 common_weight = particle_group%get_common_weight()
1451 call particle_group%set_common_weight &
1452 (common_weight/real(particle_group%n_total_particles, f64))
1455 call random_seed(put=self%random_seed)
1458 do i_part = 1, particle_group%n_particles
1459 ip = modulo(i_part, 8 )
1462 select case( self%random_numbers )
1464 call sll_s_i8_sobol( int(n_rnds,8), self%sobol_seed, rdn(1:n_rnds))
1466 call random_number( rdn(1:n_rnds) )
1474 xi(1:params%dims(1)) = rdn(1:params%dims(1))
1475 x(1) = map%get_x1(xi)
1477 wi(1) = params%eval_x_density(x(1:params%dims(1)))*abs(map%jacobian(xi))
1480 do i_v = 1,params%dims(2)
1481 call sll_s_normal_cdf_inv( rdn(i_v+params%dims(1)), 0.0_f64, 1.0_f64, &
1485 rnd_no = rdn(params%dims(1)+params%dims(2)+1)
1487 do while( rnd_no > delta(i_gauss) )
1490 v(1:params%dims(2)) = v(1:params%dims(2)) * params%v_thermal(:,i_gauss) + params%v_mean(:,i_gauss)
1491 elseif ( ip == 5 )
then
1492 xi(1) = 1._f64 - xi(1)
1494 x(1) = map%get_x1(xi)
1496 wi(1) = params%eval_x_density(x(1:params%dims(1)))*abs(map%jacobian(xi))
1497 elseif ( modulo(ip,2) == 0 )
then
1498 v(1) = -v(1) + 2.0_f64*params%v_mean(1,i_gauss)
1500 v(2) = -v(2) + 2.0_f64*params%v_mean(2,i_gauss)
1504 call particle_group%set_x(i_part, xi)
1505 call particle_group%set_v(i_part, v)
1507 call particle_group%set_weights(i_part, &
1519 sll_real64,
intent( in ) :: xmin(:)
1520 sll_real64,
intent( in ) :: lx(:)
1524 sll_real64 :: x(3), xi(3), v(3)
1527 sll_real64,
allocatable :: rdn(:)
1528 sll_real64 :: wi(particle_group%n_weights)
1529 sll_real64 :: rnd_no
1530 sll_int32 :: ip, i_gauss
1531 sll_real64 :: delta(params%n_gaussians)
1532 sll_real64 :: w_total(1), w_local(1)
1533 sll_real64 :: common_weight, weight
1539 if ( params%n_gaussians > 1 )
then
1543 do i_v=1,params%n_gaussians
1544 delta(i_v) = sum(params%delta(1:i_v))
1547 n_rnds = n_rnds+params%dims(1)+params%dims(2)
1548 allocate( rdn(1:params%dims(1)+params%dims(2)+1) )
1552 common_weight = particle_group%get_common_weight()
1553 call particle_group%set_common_weight &
1554 (common_weight/real(particle_group%n_total_particles, f64))
1557 call random_seed(put=self%random_seed)
1560 do i_part = 1, particle_group%n_particles
1561 ip = modulo(i_part, 4 )
1564 select case( self%random_numbers )
1566 call sll_s_i8_sobol( int(n_rnds,8), self%sobol_seed, rdn(1:n_rnds))
1568 call random_number( rdn(1:n_rnds) )
1571 if( self%inverse )
then
1573 x(1:params%dims(1)-1) = 2._f64*map%params(2) * rdn(1:params%dims(1)-1) - map%params(2)
1574 x(params%dims(1)) = map%params(3) * rdn(params%dims(1))
1576 r = sqrt(x(1)**2 +x(2)**2)
1577 do while( r > map%params(2) .or. r < map%params(1) )
1578 select case( self%random_numbers )
1580 call sll_s_i8_sobol( int(n_rnds,8), self%sobol_seed, rdn(1:n_rnds))
1582 call random_number( rdn(1:n_rnds) )
1585 x(1:params%dims(1)-1) = 2._f64*map%params(2) * rdn(1:params%dims(1)-1) - map%params(2)
1586 x(params%dims(1)) = map%params(3) * rdn(params%dims(1))
1588 r = sqrt(x(1)**2 +x(2)**2)
1592 wi(1) = params%eval_x_density(x) * map%volume
1594 xi(1:params%dims(1)) = rdn(1:params%dims(1))
1598 do i_v = 1,params%dims(2)
1599 call sll_s_normal_cdf_inv( rdn(i_v+params%dims(1)), 0.0_f64, 1.0_f64, &
1603 rnd_no = rdn(params%dims(1)+params%dims(2)+1)
1605 do while( rnd_no > delta(i_gauss) )
1608 if( self%xiprofile )
then
1609 select type(p=>params)
1611 if( particle_group%species%q > 0._f64)
then
1612 v(1:p%dims(2)) = v(1:p%dims(2)) * sqrt(p%profile%T_i(xi(1))/particle_group%species%m) + p%v_mean(:,i_gauss)
1614 v(1:p%dims(2)) = v(1:p%dims(2)) * sqrt(p%profile%T_e(xi(1))/particle_group%species%m) + p%v_mean(:,i_gauss)
1618 wi(1) = params%eval_x_density(xi)*map%jacobian(xi)
1622 wi(1) = params%eval_x_density(x)*map%jacobian(xi)
1623 v(1:params%dims(2)) = v(1:params%dims(2)) * params%v_thermal(:,i_gauss) + params%v_mean(:,i_gauss)
1625 elseif ( modulo(i_part, 2) == 0 )
then
1626 v(3) = - v(3) + 2.0_f64*params%v_mean(3,i_gauss)
1627 elseif ( modulo(i_part, 4) == 3 )
then
1628 v(2) = - v(2) + 2.0_f64*params%v_mean(2,i_gauss)
1629 v(1) = - v(1) + 2.0_f64*params%v_mean(1,i_gauss)
1632 call particle_group%set_x(i_part, xi)
1633 call particle_group%set_v(i_part, v)
1635 call particle_group%set_weights(i_part, &
1640 if( particle_group%species%q < 0._f64)
then
1641 if( self%delta_perturb )
then
1650 sll_real64,
intent(in) :: alpha
1651 sll_int32,
intent(in),
optional :: seed(:)
1654 sll_real64 :: wi(particle_group%N_weights)
1655 sll_real64 :: pert, rnd(1)
1657 if (
present(seed))
call random_seed(put=seed)
1660 do i_part = 1, particle_group%n_particles
1661 call random_number( rnd )
1662 wi = particle_group%get_weights(i_part)
1663 call sll_s_normal_cdf_inv( rnd(1), 0.0_f64, 1.0_f64, &
1665 if (particle_group%n_weights > 2)
then
1668 wi(1) = wi(1) + alpha * pert
1669 if (particle_group%n_weights > 2)
then
1672 call particle_group%set_weights(i_part, wi)
Combines values from all processes and distributes the result back to all processes.
type(sll_t_collective_t), pointer, public sll_v_world_collective
Control of subset assignment. Processes with the same color are in the same new communicator.
Parameters to define common initial distributions.
Module interfaces for coordinate transformation.
Particle initializer class with various functions to initialize a particle.
subroutine delta_function_perturbation(self, particle_group, xmin, Lx)
subroutine sample_particle_sampling_sym_1d2v(self, particle_group, params, xmin, Lx)
Helper function for antithetic sampling in 1d2v.
subroutine sample_particle_sampling_sym_uni_3d3v(self, particle_group, params, xmin, Lx)
Helper function for antithetic sampling in 1d2v.
integer(kind=i32), parameter sll_p_symmetric_all
2^(dim_x+dim_v) points constructed from each drawn particle, all possible combinations of reflections...
subroutine sample_particle_sampling_unix(self, particle_group, params, xmin, Lx)
Helper function for antithetic sampling in 1d2v.
subroutine sample_particle_sampling_sym_1d2v_trafo(self, particle_group, params, Lx, map)
Helper function for antithetic sampling in 1d2v.
subroutine sample_cv_particle_sampling(self, particle_group, params, xmin, Lx, control_variate, time, map, lindf)
Sample with control variate (we assume that the particle weights are given in the following order: (f...
subroutine init_particle_sampling(self, sampling_type, dims, n_particles_local, rank, delta_perturb, delta_eps)
Initializer.
integer(kind=i32), parameter sll_p_random_numbers
draw random numbers
integer(kind=i32), parameter sll_p_uniformx_negative
subroutine sample_particle_sampling_all(self, particle_group, params, xmin, Lx)
Helper function for pure sampling.
integer(kind=i32), parameter sll_p_symmetric_negative
one additional point for each drawd point, the one reflected along all directions
integer(kind=i32), parameter sll_p_standard
each particle is drawn separately
subroutine sample_particle_sampling_all_trafo(self, particle_group, params, xmin, Lx, map)
Helper function for pure sampling.
subroutine sample_particle_sampling_unix_1d2v(self, particle_group, params, xmin, Lx)
Helper function for antithetic sampling in 1d2v.
subroutine sample_particle_sampling(self, particle_group, params, xmin, Lx, map)
Sample from distribution defined by params.
subroutine sample_particle_sampling_sym_3d3v_trafo(self, particle_group, params, xmin, Lx, map)
Helper function for antithetic sampling in 1d2v.
subroutine sample_particle_sampling_sym_3d3v(self, particle_group, params, xmin, Lx)
Helper function for antithetic sampling in 3d3v.
subroutine sample_particle_sampling_sym2_1d2v(self, particle_group, params, xmin, Lx)
Helper function for antithetic sampling in 1d2v.
subroutine reset_seed_jump(self, jump)
subroutine, public sll_s_particle_sampling_randomized_weights(particle_group, alpha, seed)
integer(kind=i32), parameter sll_p_sobol_numbers
draw sobol numbers
subroutine free_particle_sampling(self)
Descructor.
Abstract data type for parameters of initial distribution.
Data type for distribution function with (multiple) Gaussians in v and one plus cosine perturbations ...
type collecting functions for analytical coordinate mapping
Data type for particle sampling.