Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_initial_distribution.F90
Go to the documentation of this file.
1 
6  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
7 #include "sll_working_precision.h"
8 #include "sll_errors.h"
9 
10  use sll_m_constants, only : &
12 
13  use sll_m_prob, only: &
14  sll_s_normal_cdf_inv
15 
16  use sll_m_profile_functions, only: &
18 
19  implicit none
20 
21  public :: sll_p_sumcos_onegaussian, &
33 
34  private
35  !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
36  ! Descriptors for various distributions
37  sll_int32, parameter :: sll_p_sumcos_onegaussian = 0
38  sll_int32, parameter :: sll_p_cossum_onegaussian = 1
39  sll_int32, parameter :: sll_p_sumcos_twogaussian = 2
40  sll_int32, parameter :: sll_p_cossum_twogaussian = 3
41  sll_int32, parameter :: sll_p_cossum_multigaussian1 = 4
42  sll_int32, parameter :: sll_p_cossum_multigaussian2 = 5
43  sll_int32, parameter :: sll_p_cossum_multigaussian11 = 14
44  sll_int32, parameter :: sll_p_noise_multigaussian1 = 15
45  sll_int32, parameter :: sll_p_noise_multigaussian11 = 16
46 
48  type, abstract :: sll_c_distribution_params
49  sll_int32 :: dims(2)
50  sll_int32 :: n_gaussians
51  sll_real64, allocatable :: v_thermal(:,:)
52  sll_real64, allocatable :: v_mean(:,:)
53  sll_real64, allocatable :: delta(:)
54  sll_real64, allocatable :: normal(:)
55 
56  contains
57  procedure( signature_eval ), deferred :: eval_xv_density
58  procedure( signature_evalx), deferred :: eval_x_density
59  procedure( signature_evalv), deferred :: eval_v_density
60  procedure( signature_empty), deferred :: free
61 
63 
66  sll_real64, allocatable :: kx(:,:)
67  sll_real64, allocatable :: modnum(:,:)
68  sll_real64, allocatable :: alpha(:)
69  sll_real64, allocatable :: phase_shift(:)
70  sll_int32 :: n_cos
71 
72 contains
73  procedure :: eval_xv_density => sll_f_cos_gaussian
74  procedure :: free => free_cos_gaussian
75  procedure :: eval_x_density => sll_f_cos
76  procedure :: eval_v_density => sll_f_gaussian
77  procedure :: init => cos_gaussian_init
78 
80 
82  ! For the Gaussians in velocity
83 
84  ! For the white noise in space
85  sll_real64 :: alpha
86  sll_int32 :: n_boxes(3)
87  sll_real64 :: rdx(3)
88  sll_real64, allocatable :: noise_vector(:,:,:)
89  type(sll_t_profile_functions) :: profile
90 
91  contains
92  procedure :: eval_xv_density => sll_f_noise_gaussian
93  procedure :: free => free_noise_gaussian
94  procedure :: eval_x_density => sll_f_noise
95  procedure :: eval_v_density => sll_f_gaussian_pnoise
96  procedure :: init => noise_gaussian_init
97 
99 
101  type(sll_t_profile_functions) :: profile
102  contains
103  procedure :: eval_xv_density => sll_f_cos_gaussian_screwpinch
104  procedure :: eval_x_density => sll_f_cos_screwpinch
105  procedure :: eval_v_density => sll_f_gaussian_screwpinch
106  !procedure :: free => free_cos_gaussian_screwpinch !< Descructor
107  !procedure :: init => cos_gaussian_screwpinch_init !< Initialization
108 
110 
111 abstract interface
112  subroutine signature_empty( self )
114  class( sll_c_distribution_params ), intent(inout) :: self
115 
116  end subroutine signature_empty
117 end interface
118 
119 abstract interface
120  function signature_eval( self, x, v, m ) result( fval )
123  class( sll_c_distribution_params ) :: self
124  sll_real64 :: x(:)
125  sll_real64 :: v(:)
126  sll_real64, optional :: m
127  sll_real64 :: fval
128 
129  end function signature_eval
130 end interface
131 
132 abstract interface
133  function signature_evalx( self, x, v ) result( fval )
136  class( sll_c_distribution_params ) :: self
137  sll_real64 :: x(:)
138  sll_real64, optional :: v(:)
139  sll_real64 :: fval
140 
141  end function signature_evalx
142 end interface
143 
144 abstract interface
145  function signature_evalv( self, v, x, m ) result( fval )
148  class( sll_c_distribution_params ) :: self
149  sll_real64 :: v(:)
150  sll_real64, optional :: x(:)
151  sll_real64, optional :: m
152  sll_real64 :: fval
153 
154  end function signature_evalv
155 end interface
156 contains
157 
158  !-------------------------------------------------------------------------------
159  ! Define the procedures of the type sll_t_params_cos_gaussian
160  !-------------------------------------------------------------------------------
161 
162 function sll_f_cos_gaussian( self, x, v, m ) result( fval )
163  class( sll_t_params_cos_gaussian ) :: self
164  sll_real64 :: x(:)
165  sll_real64 :: v(:)
166  sll_real64, optional :: m
167  sll_real64 :: fval
168  !local variables
169  sll_real64 :: fexp
170 
171  fval = sll_f_cos( self, x )
172  fexp = sll_f_gaussian( self, v, x, m )
173 
174  fval = fval*fexp
175 
176 end function sll_f_cos_gaussian
177 
178 
179 function sll_f_cos( self, x, v ) result( fval )
180  class( sll_t_params_cos_gaussian ) :: self
181  sll_real64 :: x(:)
182  sll_real64, optional :: v(:)
183  sll_real64 :: fval
184  !local variables
185  sll_int32 :: j
186 
187  fval = 1.0_f64
188 !!$ do j = 1, self%n_cos
189 !!$ fval = fval + self%alpha(j) * (cos( self%kx(1,j) * (x(1) + self%modnum(1,j)*v(2))+ self%kx(2,j)*(x(2) - self%modnum(2,j)*v(1)) - self%phase_shift(j)*sll_p_pi ) - &
190 !!$ 0.5_f64*cos( sum(self%kx(:,j) * x) )*exp(-0.5_f64*sum(self%kx(1:2,j)**2) )*sum(self%modnum(:,j)*0.5_f64) )
191 !!$ end do
192 !!$
193 !!$
194  do j = 1, self%n_cos
195  fval = fval + self%alpha(j) * cos( sum(self%kx(:,j) * x) - self%phase_shift(j)*sll_p_pi )
196  end do
197 
198 !!$ do j=1,self%n_cos
199 !!$ fval = fval + self%alpha(j) * product( cos( (self%kx(:,j) * x(:)) - self%phase_shift(j)*sll_p_pi ) )
200 !!$ end do
201 
202 end function sll_f_cos
203 
204 
205 function sll_f_gaussian( self, v, x, m ) result( fval )
206  class( sll_t_params_cos_gaussian ) :: self
207  sll_real64 :: v(:)
208  sll_real64, optional :: x(:)
209  sll_real64, optional :: m
210  sll_real64 :: fval
211  !local variables
212  sll_int32 :: j
213 
214  fval = 0.0_f64
215  do j = 1, self%n_gaussians
216  fval = fval + self%normal(j)*self%delta(j)* &
217  exp( -0.5_f64 * sum( ((v-self%v_mean(:,j))/self%v_thermal(:,j))**2 ) )
218  end do
219 
220 end function sll_f_gaussian
221 
222 function sll_f_gaussian_pnoise( self, v, x, m ) result( fval )
223  class( sll_t_params_noise_gaussian ) :: self
224  sll_real64 :: v(:)
225  sll_real64, optional :: x(:)
226  sll_real64, optional :: m
227  sll_real64 :: fval
228  !local variables
229  sll_int32 :: j
230 
231  fval = 0.0_f64
232  do j=1,self%n_gaussians
233  fval = fval + self%normal(j)*self%delta(j)* &
234  exp( -0.5_f64 * sum( ((v-self%v_mean(:,j))/self%v_thermal(:,j))**2 ) )
235  end do
236 
237 end function sll_f_gaussian_pnoise
238 
239 
240 function sll_f_noise( self, x, v ) result(fval)
241  class( sll_t_params_noise_gaussian ) :: self
242  sll_real64 :: x(:)
243  sll_real64, optional :: v(:)
244  sll_real64 :: fval
245  !local variables
246  sll_int32 :: box(3)
247  sll_real64 :: xbox(3)
248 
249  xbox = x* self%rdx
250  box = floor(xbox)+1
251 
252  if(self%dims(1) == 1 ) then
253  xbox = xbox - real(box-1,f64)
254  fval = (1.0_f64-xbox(1)) * self%noise_vector(box(1)+1,1,1) + xbox(1)* self%noise_vector(box(1),1,1)
255  else if (self%dims(1) == 3 ) then
256  fval = self%noise_vector(box(1), box(2), box(3) )
257  else
258  print*, 'wrong dimension in eval_x_noise'
259  end if
260 
261 end function sll_f_noise
262 
263 function sll_f_noise_gaussian( self, x, v, m ) result( fval )
264  class( sll_t_params_noise_gaussian ) :: self
265  sll_real64 :: x(:)
266  sll_real64 :: v(:)
267  sll_real64, optional :: m
268  sll_real64 :: fval
269 
270  fval = self%eval_x_density( x ) * self%eval_v_density( v )
271 
272 end function sll_f_noise_gaussian
273 
274 function sll_f_cos_gaussian_screwpinch( self, x, v, m ) result( fval )
275  class( sll_t_params_cos_gaussian_screwpinch ) :: self
276  sll_real64 :: x(:)
277  sll_real64 :: v(:)
278  sll_real64, optional :: m
279  sll_real64 :: fval
280  !local variables
281  sll_real64 :: fexp
282 
283  fval = sll_f_cos_screwpinch( self, x, v )
284  fexp = sll_f_gaussian_screwpinch( self, v, x, m )
285 
286  fval = fval*fexp!/self%profile%rho_0(x(1))
287 
289 
290 
291 function sll_f_cos_screwpinch( self, x, v ) result( fval )
292  class( sll_t_params_cos_gaussian_screwpinch ) :: self
293  sll_real64 :: x(:)
294  sll_real64, optional :: v(:)
295  sll_real64 :: fval
296  !local variables
297  sll_int32 :: j
298 
299  fval = 1.0_f64
300  do j=1,self%n_cos
301  fval = fval + self%alpha(j) * ( cos( sll_p_twopi*sum(self%modnum(:,j) * x) - self%kx(2,j)*v(1) - self%phase_shift(j)*sll_p_pi ) - 0.5_f64*cos( sll_p_twopi*sum(self%modnum(:,j) * x) - self%phase_shift(j)*sll_p_pi )*exp(-0.5_f64*self%profile%T_i(x(1) + self%kx(1,j)*v(2))*self%kx(2,j)**2 ) ) * self%profile%radial_distrib(x(1))
302  end do
303 
304  fval = fval! * self%profile%rho_0(x(1))
305 
306 end function sll_f_cos_screwpinch
307 
308 function sll_f_gaussian_screwpinch( self, v, x, m ) result( fexp )
309  class( sll_t_params_cos_gaussian_screwpinch ) :: self
310  sll_real64 :: v(:)
311  sll_real64, optional :: x(:)
312  sll_real64, optional :: m
313  sll_real64 :: fexp
314  !local variables
315  sll_int32 :: j
316 
317  fexp = 0.0_f64
318  do j=1,self%n_gaussians
319  fexp = fexp + self%profile%rho_0(x(1))/sqrt(sll_p_twopi*self%profile%T_i(x(1))/m)**3 * &
320  exp( -0.5_f64 * sum( (v-self%v_mean(:,j))**2/(self%profile%T_i(x(1))/m) ) )
321  end do
322 
323 end function sll_f_gaussian_screwpinch
324 
325 
326 subroutine free_cos_gaussian( self )
327  class( sll_t_params_cos_gaussian ), intent( inout ) :: self
328 
329  if (allocated(self%kx)) deallocate(self%kx)
330  if (allocated(self%modnum)) deallocate(self%modnum)
331  if (allocated(self%alpha)) deallocate(self%alpha)
332  if (allocated(self%phase_shift)) deallocate(self%phase_shift)
333  if (allocated(self%v_thermal)) deallocate(self%v_thermal)
334  if (allocated(self%v_mean)) deallocate(self%v_mean)
335  if (allocated(self%normal)) deallocate(self%normal)
336  if (allocated(self%delta)) deallocate(self%delta)
337 
338 end subroutine free_cos_gaussian
339 
340 subroutine free_noise_gaussian( self )
341  class( sll_t_params_noise_gaussian ), intent( inout ) :: self
342 
343  if (allocated(self%v_thermal)) deallocate(self%v_thermal)
344  if (allocated(self%v_mean)) deallocate(self%v_mean)
345  if (allocated(self%normal)) deallocate(self%normal)
346  if (allocated(self%delta)) deallocate(self%delta)
347  if (allocated(self%noise_vector)) deallocate(self%noise_vector)
348 
349 end subroutine free_noise_gaussian
350 
351 subroutine noise_gaussian_init( self, n_gaussians, dims, file_id, profile )
352  class( sll_t_params_noise_gaussian ), intent( out ) :: self
353  sll_int32, intent( in ) :: n_gaussians
354  sll_int32, intent( in ) :: dims(2)
355  sll_int32, intent( in ) :: file_id
356  type(sll_t_profile_functions), optional :: profile
357 
358  if( present(profile) ) then
359  self%profile = profile
360  end if
361  self%dims = dims
362  self%n_gaussians = n_gaussians
363  select case( self%dims(1) )
364  case (1)
365  call noise_gaussian_init_1d2v( self, file_id )
366  case(3)
367  call noise_gaussian_init_3d3v( self, file_id )
368  end select
369 end subroutine noise_gaussian_init
370 
371 subroutine noise_gaussian_init_1d2v( self, file_id )
372  class( sll_t_params_noise_gaussian ), intent( inout ) :: self
373  sll_int32, intent( in ) :: file_id
374  sll_real64 :: alpha
375  sll_real64 :: v_thermal_1(self%n_gaussians)
376  sll_real64 :: v_mean_1(self%n_gaussians)
377  sll_real64 :: v_thermal_2(self%n_gaussians)
378  sll_real64 :: v_mean_2(self%n_gaussians)
379  sll_real64 :: delta(self%n_gaussians)
380  sll_int32 :: n_boxes
381  sll_real64 :: domain
382  sll_int32 :: i, j
383  sll_int32 :: rnd_seed_size
384  sll_int32, allocatable :: rnd_seed(:)
385  sll_real64 :: rnd
386 
387  namelist /noise_multigaussian/ alpha, n_boxes, v_thermal_1, v_mean_1, v_thermal_2, v_mean_2, delta, domain
388 
389 
390 
391  read(file_id, noise_multigaussian)
392 
393  allocate( self%noise_vector(1:n_boxes+1,1,1) )
394  allocate( self%v_thermal(1:self%dims(2), 1:self%n_gaussians) )
395  allocate( self%v_mean(1:self%dims(2), 1:self%n_gaussians) )
396  allocate( self%normal(1:self%n_gaussians) )
397  allocate( self%delta(1:self%n_gaussians) )
398 
399 
400 
401  self%alpha = alpha
402  self%v_thermal(1,:) = v_thermal_1
403  self%v_mean(1,:) = v_mean_1
404  self%v_thermal(2,:) = v_thermal_2
405  self%v_mean(2,:) = v_mean_2
406  self%delta = delta
407  self%n_boxes = n_boxes
408 
409  do j=1,self%n_gaussians
410  self%normal(j) = 1.0_f64/(sll_p_twopi**(0.5_f64*real(self%dims(2),f64))*&
411  product(self%v_thermal(:,j)))
412  end do
413 
414  ! Set random seed: Same on all processes
415  call random_seed(size=rnd_seed_size)
416  allocate( rnd_seed(rnd_seed_size) )
417  do i=1, rnd_seed_size
418  rnd_seed(i) = 15*i
419  end do
420  call random_seed(put=rnd_seed)
421  do i=1,n_boxes
422  call random_number( rnd )
423  call sll_s_normal_cdf_inv( rnd, 1.0_f64, alpha, self%noise_vector(i,1,1) )
424  end do
425 
426  ! Make sure the function integrates up to one
427  rnd = sum(self%noise_vector(1:n_boxes,1,1))/real(n_boxes, f64)
428  rnd = rnd - 1.0_f64
429  self%noise_vector(1:n_boxes,1,1) = self%noise_vector(1:n_boxes,1,1) - rnd
430 
431  ! Periodic boundary conditions
432  self%noise_vector(n_boxes+1,1,1) = self%noise_vector(1,1,1)
433 
434  self%rdx = real( self%n_boxes, f64 ) / domain
435 
436 end subroutine noise_gaussian_init_1d2v
437 
438 subroutine noise_gaussian_init_3d3v( self, file_id )
439  class( sll_t_params_noise_gaussian ), intent( inout ) :: self
440  sll_int32, intent( in ) :: file_id
441  sll_real64 :: alpha
442  sll_real64 :: v_thermal(3,self%n_gaussians)
443  sll_real64 :: v_mean(3,self%n_gaussians)
444  sll_real64 :: delta(self%n_gaussians)
445  sll_int32 :: n_boxes(3)
446  sll_real64 :: domain(3)
447  sll_int32 :: i, j, k
448  sll_int32 :: rnd_seed_size
449  sll_int32, allocatable :: rnd_seed(:)
450  sll_real64 :: rnd
451 
452  namelist /noise_multigaussian/ alpha, n_boxes, v_thermal, v_mean, delta, domain
453 
454  read(file_id, noise_multigaussian)
455 
456  allocate( self%noise_vector(1:n_boxes(1)+1, 1:n_boxes(2)+1, 1:n_boxes(3)+1) )
457  allocate( self%v_thermal(1:self%dims(2), 1:self%n_gaussians) )
458  allocate( self%v_mean(1:self%dims(2), 1:self%n_gaussians) )
459  allocate( self%normal(1:self%n_gaussians) )
460  allocate( self%delta(1:self%n_gaussians) )
461 
462 
463 
464  self%alpha = alpha
465  self%v_thermal = v_thermal
466  self%v_mean = v_mean
467  self%delta = delta
468  self%n_boxes = n_boxes
469 
470  do j=1,self%n_gaussians
471  self%normal(j) = 1.0_f64/(sll_p_twopi**(0.5_f64*real(self%dims(2),f64))*&
472  product(self%v_thermal(:,j)))
473  end do
474 
475  ! Set random seed: Same on all processes
476  call random_seed(size=rnd_seed_size)
477  allocate( rnd_seed(rnd_seed_size) )
478  do i=1, rnd_seed_size
479  rnd_seed(i) = 15*i
480  end do
481  call random_seed(put=rnd_seed)
482  do i=1,n_boxes(1)
483  do j = 1, n_boxes(2)
484  do k = 1, n_boxes(3)
485  call random_number( rnd )
486  call sll_s_normal_cdf_inv( rnd, 1.0_f64, alpha, self%noise_vector(i,j,k) )
487  end do
488  end do
489  end do
490 
491  ! Make sure the function integrates up to one
492  do j = 1, n_boxes(2)
493  do k = 1, n_boxes(3)
494  rnd = sum(self%noise_vector(1:n_boxes(1),j,k))/real(n_boxes(1), f64)
495  rnd = rnd - 1.0_f64
496  self%noise_vector(1:n_boxes(1),j,k) = self%noise_vector(1:n_boxes(1),j,k) - rnd
497  end do
498  end do
499  ! Periodic boundary conditions
500  !self%noise_vector(n_boxes+1) = self%noise_vector(1)
501 
502  self%rdx = real( self%n_boxes, f64 ) / domain
503 
504 end subroutine noise_gaussian_init_3d3v
505 
506 
507 subroutine cos_gaussian_init( self, descriptor, dims, file_id, profile )
508  class( sll_t_params_cos_gaussian ), intent( out ) :: self
509  sll_int32, intent( in ) :: descriptor
510  sll_int32, intent( in ) :: dims(2)
511  sll_int32, intent( in ) :: file_id
512  type(sll_t_profile_functions), optional :: profile
513 
514  select type( self)
516  if( present(profile) ) then
517  self%profile = profile
518  else
519  print*, 'Error: no profile given'
520  stop
521  end if
522  end select
523  self%dims = dims
524  select case( descriptor )
526  select case( self%dims(1) )
527  case (1)
528  select case (self%dims(2) )
529  case(1)
530  call sumcos_onegaussian_init_1d1v( file_id, self )
531  case(2)
532  call sumcos_onegaussian_init_1d2v( file_id, self )
533  end select
534  case(2)
535  select case ( self%dims(2) )
536  case ( 2)
537  call sumcos_onegaussian_init_2d2v( file_id, self )
538  case(3)
539  call sumcos_onegaussian_init_2d3v( file_id, self )
540  end select
541  case(3)
542  call sumcos_onegaussian_init_3d3v( file_id, self )
543  end select
545  select case( self%dims(1) )
546  case (1)
547  select case (self%dims(2) )
548  case(1)
549  call cossum_onegaussian_init_1d1v( file_id, self )
550  case(2)
551  call cossum_onegaussian_init_1d2v( file_id, self )
552  end select
553  case(2)
554  select case ( self%dims(2) )
555  case ( 2)
556  call cossum_onegaussian_init_2d2v( file_id, self )
557  case (3)
558  call cossum_onegaussian_init_2d3v( file_id, self )
559  end select
560  case(3)
561  call cossum_onegaussian_init_3d3v( file_id, self )
562  end select
563 
565  select case( self%dims(1) )
566  case (1)
567  select case (self%dims(2) )
568  case(1)
569  call cossum_twogaussian_init_1d1v( file_id, self )
570  case(2)
571  call cossum_twogaussian_init_1d2v( file_id, self )
572  end select
573  case(2)
574  call cossum_twogaussian_init_2d2v( file_id, self )
575  case(3)
576  call cossum_twogaussian_init_3d3v( file_id, self )
577  end select
579  select case( self%dims(1) )
580  case (1)
581  select case (self%dims(2) )
582  case(1)
583  call sumcos_twogaussian_init_1d1v( file_id, self )
584  case(2)
585  call sumcos_twogaussian_init_1d2v( file_id, self )
586  end select
587  case(2)
588  call sumcos_twogaussian_init_2d2v( file_id, self )
589  case(3)
590  call sumcos_twogaussian_init_3d3v( file_id, self )
591  end select
593  select case (self%dims(1) )
594  case(1)
595  select case( self%dims(2) )
596  case(2)
597  call cossum_multigaussian_init_1d2v( file_id, self, 1 )
598  end select
599  end select
601  select case (self%dims(1) )
602  case(1)
603  select case( self%dims(2) )
604  case(2)
605  call cossum_multigaussian_init_1d2v( file_id, self, 2 )
606  end select
607  end select
609  select case (self%dims(1) )
610  case(1)
611  select case( self%dims(2) )
612  case(2)
613  call cossum_multigaussian_init_1d2v( file_id, self, 11 )
614  end select
615  end select
616  case default
617  sll_error('Initial distribution not implemented.','cos_gaussian_init')
618  end select
619 
620 
621 end subroutine cos_gaussian_init
622 
623 
624 !-------------------------------------------------------------------------------
625 ! Factory function with specific functions called depending on chosen distribution type
626 !-------------------------------------------------------------------------------
628 subroutine sll_s_initial_distribution_new( distribution, dims, file_id, params, profile )
629  character(len=*), intent( in ) :: distribution
630  sll_int32, intent( in ) :: dims(2)
631  sll_int32, intent( in ) :: file_id
632  class(sll_c_distribution_params), allocatable, intent( out ) :: params
633  type(sll_t_profile_functions), optional :: profile
634 
635  sll_int32 :: descriptor
636 
637  select case( distribution )
638  case( "sumcos_onegaussian" )
639  allocate( sll_t_params_cos_gaussian :: params )
640  descriptor = sll_p_sumcos_onegaussian
641  case( "cossum_onegaussian" )
642  allocate( sll_t_params_cos_gaussian :: params )
643  descriptor = sll_p_cossum_onegaussian
644  case( "cossum_twogaussian" )
645  allocate( sll_t_params_cos_gaussian :: params )
646  descriptor = sll_p_cossum_twogaussian
647  case( "sumcos_twogaussian" )
648  allocate( sll_t_params_cos_gaussian :: params )
649  descriptor = sll_p_sumcos_twogaussian
650  case( "cossum_multigaussian1" )
651  allocate( sll_t_params_cos_gaussian :: params )
652  descriptor = sll_p_cossum_multigaussian1
653  case( "cossum_multigaussian2" )
654  allocate( sll_t_params_cos_gaussian :: params )
655  descriptor = sll_p_cossum_multigaussian2
656  case( "cossum_multigaussian11" )
657  allocate( sll_t_params_cos_gaussian :: params )
658  descriptor = sll_p_cossum_multigaussian11
659  case ( "noise_multigaussian1" )
660  allocate( sll_t_params_noise_gaussian :: params )
661  descriptor = sll_p_noise_multigaussian1
662  case ( "noise_multigaussian11" )
663  allocate( sll_t_params_noise_gaussian :: params )
664  descriptor = sll_p_noise_multigaussian11
665  case( "cossum_onegaussian_screwpinch" )
666  allocate( sll_t_params_cos_gaussian_screwpinch :: params )
667  descriptor = sll_p_cossum_onegaussian
668  case( "sumcos_onegaussian_screwpinch" )
669  allocate( sll_t_params_cos_gaussian_screwpinch :: params )
670  descriptor = sll_p_sumcos_onegaussian
671  case( "cossum_twogaussian_screwpinch" )
672  allocate( sll_t_params_cos_gaussian_screwpinch :: params )
673  descriptor = sll_p_cossum_twogaussian
674  case( "sumcos_twogaussian_screwpinch" )
675  allocate( sll_t_params_cos_gaussian_screwpinch :: params )
676  descriptor = sll_p_sumcos_twogaussian
677  case default
678  sll_error('Initial distribution not implemented.','sll_s_initial_distribution_new')
679  end select
680 
681  select type( params )
682  type is( sll_t_params_cos_gaussian )
683  call params%init( descriptor, dims, file_id )
684  type is( sll_t_params_noise_gaussian )
685  select case ( descriptor )
687  call params%init( 1, dims, file_id, profile )
689  call params%init( 11, dims, file_id, profile )
690  case default
691  !call params%init( descriptor, dims, file_id, profile )
692  end select
694  call params%init( descriptor, dims, file_id, profile )
695  end select
696 
697 
698 end subroutine sll_s_initial_distribution_new
699 
700 
701 !-------------------------------------------------------------------------------
702 ! Factory function with specific functions called depending on chosen distribution type
703 !-------------------------------------------------------------------------------
705 subroutine sll_s_initial_distribution_file_new( dims, nml_file, params, profile )
706  sll_int32, intent( in ) :: dims(2)
707  character(*), intent( in ) :: nml_file
708  class(sll_c_distribution_params), allocatable, intent( out ) :: params
709  type(sll_t_profile_functions), optional :: profile
710 
711  character(len=256) :: type
712  sll_int32 :: descriptor
713  sll_int32 :: file_id, ierr
714 
715  namelist /initial_distribution/ type
716 
717  ! Read what type
718  open(newunit=file_id, file=trim(nml_file), iostat=ierr)
719  if ( ierr /= 0 ) then
720  sll_error('NML file could not be opened.','sll_s_initial_distribution_file_new')
721  end if
722  read( file_id, initial_distribution )
723 
724  select case( type )
725  case( "sumcos_onegaussian" )
726  allocate( sll_t_params_cos_gaussian :: params )
727  descriptor = sll_p_sumcos_onegaussian
728  case( "cossum_onegaussian" )
729  allocate( sll_t_params_cos_gaussian :: params )
730  descriptor = sll_p_cossum_onegaussian
731  case( "cossum_twogaussian" )
732  allocate( sll_t_params_cos_gaussian :: params )
733  descriptor = sll_p_cossum_twogaussian
734  case( "sumcos_twogaussian" )
735  allocate( sll_t_params_cos_gaussian :: params )
736  descriptor = sll_p_sumcos_twogaussian
737  case( "cossum_multigaussian1" )
738  allocate( sll_t_params_cos_gaussian :: params )
739  descriptor = sll_p_cossum_multigaussian1
740  case( "cossum_multigaussian2" )
741  allocate( sll_t_params_cos_gaussian :: params )
742  descriptor = sll_p_cossum_multigaussian2
743  case( "cossum_multigaussian11" )
744  allocate( sll_t_params_cos_gaussian :: params )
745  descriptor = sll_p_cossum_multigaussian11
746  case ( "noise_multigaussian1" )
747  allocate( sll_t_params_noise_gaussian :: params )
748  descriptor = sll_p_noise_multigaussian1
749  case ( "noise_multigaussian11" )
750  allocate( sll_t_params_noise_gaussian :: params )
751  descriptor = sll_p_noise_multigaussian11
752  case( "cossum_onegaussian_screwpinch" )
753  allocate( sll_t_params_cos_gaussian_screwpinch :: params )
754  descriptor = sll_p_cossum_onegaussian
755  case( "sumcos_onegaussian_screwpinch" )
756  allocate( sll_t_params_cos_gaussian_screwpinch :: params )
757  descriptor = sll_p_sumcos_onegaussian
758  case( "cossum_twogaussian_screwpinch" )
759  allocate( sll_t_params_cos_gaussian_screwpinch :: params )
760  descriptor = sll_p_cossum_twogaussian
761  case( "sumcos_twogaussian_screwpinch" )
762  allocate( sll_t_params_cos_gaussian_screwpinch :: params )
763  descriptor = sll_p_sumcos_twogaussian
764  case default
765  sll_error('Initial distribution not implemented.','sll_s_initial_distribution_file_new')
766  end select
767 
768  select type( params )
769  type is( sll_t_params_cos_gaussian )
770  call params%init( descriptor, dims, file_id )
771  type is( sll_t_params_noise_gaussian )
772  select case ( descriptor )
774  call params%init( 1, dims, file_id, profile )
776  call params%init( 11, dims, file_id, profile )
777  case default
778  !call params%init( descriptor, dims, file_id, profile )
779  end select
781  call params%init( descriptor, dims, file_id, profile )
782  end select
783 
784  close(file_id)
785 
787 
788 
790 subroutine sll_s_initial_distribution_new_descriptor( distribution, dims, file_id, params, profile )
791  sll_int32, intent( in ) :: distribution
792  sll_int32, intent( in ) :: dims(2)
793  sll_int32, intent( in ) :: file_id
794  class(sll_c_distribution_params), allocatable, intent( out ) :: params
795  type(sll_t_profile_functions), optional :: profile
796 
797 
798  select case( distribution )
800  allocate( sll_t_params_cos_gaussian :: params )
802  allocate( sll_t_params_cos_gaussian :: params )
804  allocate( sll_t_params_cos_gaussian :: params )
806  allocate( sll_t_params_cos_gaussian :: params )
808  allocate( sll_t_params_cos_gaussian :: params )
810  allocate( sll_t_params_cos_gaussian :: params )
812  allocate( sll_t_params_cos_gaussian :: params )
814  allocate( sll_t_params_noise_gaussian :: params )
816  allocate( sll_t_params_noise_gaussian :: params )
817  case default
818  sll_error('Initial distribution not implemented.','sll_s_initial_distribution_new')
819  end select
820 
821  select type( params )
822  type is( sll_t_params_cos_gaussian )
823  call params%init( distribution, dims, file_id )
824  type is( sll_t_params_noise_gaussian )
825  select case ( distribution)
827  call params%init( 1, dims, file_id, profile )
829  call params%init( 11, dims, file_id, profile )
830  end select
832  call params%init( distribution, dims, file_id )
833  end select
834 
836 
837 
838 ! Since assumed shape arrays are not allowed in namelists, we need to define a separate function for each combination of dimensions in x and v. We use a macro to avoid code dublication.
839 
840 #define MAKE_COS_ONEGAUSSIAN_INIT( fname, dimx, dimv, dimalpha )\
841 subroutine fname( file_id, params );\
842  sll_int32, intent( in ) :: file_id;\
843  type( sll_t_params_cos_gaussian ), intent( inout ) :: params; \
844  sll_real64 :: kx(dimx)= 0.0_f64; \
845  sll_real64 :: modnum(dimx)= 0.0_f64; \
846  sll_real64 :: alpha(dimalpha); \
847  sll_real64 :: phase_shift(dimalpha) = 0.0_f64; \
848  sll_real64 :: v_thermal(dimv); \
849  sll_real64 :: v_mean(dimv)= 0.0_f64; \
850  sll_int32 :: j; \
851  namelist /cos_onegaussian/ kx, modnum, alpha, phase_shift, v_thermal, v_mean; \
852  params%n_cos = dimalpha;
853  !-----------------------------------------------------------------
854 
855  make_cos_onegaussian_init( cossum_onegaussian_init_1d1v, 1, 1, 1 )
856 #include "sll_k_make_cos_onegaussian_init.F90"
857 
858  make_cos_onegaussian_init( cossum_onegaussian_init_1d2v, 1, 2, 1 )
859 #include "sll_k_make_cos_onegaussian_init.F90"
860 
861  make_cos_onegaussian_init( cossum_onegaussian_init_2d2v, 2, 2, 1 )
862 #include "sll_k_make_cos_onegaussian_init.F90"
863 
864  make_cos_onegaussian_init( cossum_onegaussian_init_2d3v, 2, 3, 1 )
865 #include "sll_k_make_cos_onegaussian_init.F90"
866 
867  make_cos_onegaussian_init( cossum_onegaussian_init_3d3v, 3, 3, 1 )
868 #include "sll_k_make_cos_onegaussian_init.F90"
869 
870  make_cos_onegaussian_init( sumcos_onegaussian_init_1d1v, 1, 1, 1 )
871 #include "sll_k_make_cos_onegaussian_init.F90"
872 
873  make_cos_onegaussian_init( sumcos_onegaussian_init_1d2v, 1, 2, 1 )
874 #include "sll_k_make_cos_onegaussian_init.F90"
875 
876  make_cos_onegaussian_init( sumcos_onegaussian_init_2d2v, 2, 2, 2 )
877 #include "sll_k_make_cos_onegaussian_init.F90"
878 
879  make_cos_onegaussian_init( sumcos_onegaussian_init_2d3v, 2, 3, 2 )
880 #include "sll_k_make_cos_onegaussian_init.F90"
881 
882  make_cos_onegaussian_init( sumcos_onegaussian_init_3d3v, 3, 3, 3 )
883 #include "sll_k_make_cos_onegaussian_init.F90"
884 
885 
886 #define MAKE_COS_TWOGAUSSIAN_INIT( fname, dimx, dimv, dimalpha ) \
887  subroutine fname( file_id, params ); \
888  sll_int32, intent( in ) :: file_id; \
889  type( sll_t_params_cos_gaussian ), intent( inout ) :: params; \
890  sll_real64 :: kx(dimx)= 0.0_f64; \
891  sll_real64 :: modnum(dimx)= 0.0_f64; \
892  sll_real64 :: alpha(dimalpha); \
893  sll_real64 :: phase_shift(dimalpha) = 0.0_f64; \
894  sll_real64 :: v_thermal_1(dimv); \
895  sll_real64 :: v_mean_1(dimv); \
896  sll_real64 :: v_thermal_2(dimv); \
897  sll_real64 :: v_mean_2(dimv); \
898  sll_real64 :: delta; \
899  sll_int32 :: j; \
900  namelist /cos_twogaussian/ kx, modnum, alpha, phase_shift, v_thermal_1, v_mean_1, v_thermal_2, v_mean_2, delta; \
901  params%n_cos = dimalpha;
902  !-------------------------------
903 
904  make_cos_twogaussian_init( cossum_twogaussian_init_1d1v, 1, 1, 1 )
905 #include "sll_k_make_cos_twogaussian_init.F90"
906 
907  make_cos_twogaussian_init( cossum_twogaussian_init_1d2v, 1, 2, 1 )
908 #include "sll_k_make_cos_twogaussian_init.F90"
909 
910  make_cos_twogaussian_init( cossum_twogaussian_init_2d2v, 2, 2, 1 )
911 #include "sll_k_make_cos_twogaussian_init.F90"
912 
913  make_cos_twogaussian_init( cossum_twogaussian_init_3d3v, 3, 3, 1 )
914 #include "sll_k_make_cos_twogaussian_init.F90"
915 
916  make_cos_twogaussian_init( sumcos_twogaussian_init_1d1v, 1, 1, 1 )
917 #include "sll_k_make_cos_twogaussian_init.F90"
918 
919  make_cos_twogaussian_init( sumcos_twogaussian_init_1d2v, 1, 2, 1 )
920 #include "sll_k_make_cos_twogaussian_init.F90"
921 
922  make_cos_twogaussian_init( sumcos_twogaussian_init_2d2v, 2, 2, 2 )
923 #include "sll_k_make_cos_twogaussian_init.F90"
924 
925  make_cos_twogaussian_init( sumcos_twogaussian_init_3d3v, 3, 3, 3 )
926 #include "sll_k_make_cos_twogaussian_init.F90"
927 
928 
931  subroutine cossum_multigaussian_init_1d2v( file_id, params, n_gaussians )
932  sll_int32, intent( in ) :: file_id
933  type( sll_t_params_cos_gaussian ), intent( inout ) :: params
934  sll_int32, intent( in ) :: n_gaussians
935  sll_real64 :: kx(1)
936  sll_real64 :: modnum(1)
937  sll_real64 :: alpha(1)
938  sll_real64 :: phase_shift(1) = 0.0_f64
939  sll_real64 :: v_thermal_1(n_gaussians)
940  sll_real64 :: v_mean_1(n_gaussians)
941  sll_real64 :: v_thermal_2(n_gaussians)
942  sll_real64 :: v_mean_2(n_gaussians)
943  sll_real64 :: delta(n_gaussians)
944  sll_int32 :: j
945  namelist /cos_multigaussian/ kx, modnum, alpha, phase_shift, v_thermal_1, v_mean_1, v_thermal_2, v_mean_2, delta
946  params%n_cos = 1
947  params%n_gaussians = n_gaussians
948 
949  read(file_id, cos_multigaussian)
950 
951  allocate( params%alpha(1:params%n_cos) );
952  allocate( params%phase_shift(1:params%n_cos) );
953  allocate( params%kx(1:params%dims(1), 1:params%n_cos) )
954  allocate( params%modnum(1:params%dims(1), 1:params%n_cos) )
955  allocate( params%v_thermal(1:params%dims(2), 1:params%n_gaussians) )
956  allocate( params%v_mean(1:params%dims(2), 1:params%n_gaussians) )
957  allocate( params%normal(1:params%n_gaussians) )
958  allocate( params%delta(1:params%n_gaussians) )
959 
960  if ( params%n_cos == 1 ) then
961  params%kx(:,1) = kx
962  params%modnum(:,1) = modnum
963  else
964  params%modnum = 0.0_f64
965  do j=1, params%n_cos
966  params%modnum(j,j) = modnum(j)
967  end do
968  end if
969  params%alpha = alpha
970  params%phase_shift=phase_shift
971  params%v_thermal(1,:) = v_thermal_1
972  params%v_mean(1,:) = v_mean_1
973  params%v_thermal(2,:) = v_thermal_2
974  params%v_mean(2,:) = v_mean_2
975  params%delta = delta
976 
977  do j=1,params%n_gaussians
978  params%normal(j) = 1.0_f64/(sll_p_twopi**(0.5_f64*real(params%dims(2),f64))*&
979  product(params%v_thermal(:,j)))
980 
981  end do
982 
983  end subroutine cossum_multigaussian_init_1d2v
984 
985 
986  end module sll_m_initial_distribution
Fortran module where set some physical and mathematical constants.
real(kind=f64), parameter, public sll_p_pi
real(kind=f64), parameter, public sll_p_twopi
Parameters to define common initial distributions.
subroutine cossum_multigaussian_init_1d2v(file_id, params, n_gaussians)
1d2v subroutine for initialization of sum of arbitrary number of Gaussians. Note that v_thermal_1/2 r...
real(kind=f64) function sll_f_noise_gaussian(self, x, v, m)
integer(kind=i32), parameter, public sll_p_cossum_onegaussian
Descriptor for (1+cos( \sum kx_i * x_i))*exp(-0.5(v-v_mean)**2/v_thermal**2)
integer(kind=i32), parameter, public sll_p_sumcos_twogaussian
as sll_p_sumcos_onegaussian but with sum of two Gaussians
integer(kind=i32), parameter sll_p_noise_multigaussian1
integer(kind=i32), parameter, public sll_p_sumcos_onegaussian
Descriptor for (1+\sum cos( kx * x_i))*exp(-0.5(v-v_mean)**2/v_thermal**2)
real(kind=f64) function sll_f_cos(self, x, v)
subroutine cos_gaussian_init(self, descriptor, dims, file_id, profile)
subroutine, public sll_s_initial_distribution_new_descriptor(distribution, dims, file_id, params, profile)
Factory function for sll_c_distribution_params, parameters read form input file. Version build upon d...
real(kind=f64) function sll_f_gaussian_screwpinch(self, v, x, m)
integer(kind=i32), parameter sll_p_noise_multigaussian11
real(kind=f64) function sll_f_cos_gaussian_screwpinch(self, x, v, m)
real(kind=f64) function sll_f_gaussian(self, v, x, m)
integer(kind=i32), parameter sll_p_cossum_multigaussian2
integer(kind=i32), parameter, public sll_p_cossum_multigaussian1
subroutine noise_gaussian_init_1d2v(self, file_id)
subroutine, public sll_s_initial_distribution_new(distribution, dims, file_id, params, profile)
Factory function for sll_c_distribution_params, parameters read form input file.
real(kind=f64) function sll_f_gaussian_pnoise(self, v, x, m)
integer(kind=i32), parameter, public sll_p_cossum_twogaussian
as sll_p_sumcos_onegaussian but with sum of two Gaussians
real(kind=f64) function sll_f_cos_screwpinch(self, x, v)
real(kind=f64) function sll_f_noise(self, x, v)
subroutine, public sll_s_initial_distribution_file_new(dims, nml_file, params, profile)
Factory function for sll_c_distribution_params, parameters read form input file.
integer(kind=i32), parameter sll_p_cossum_multigaussian11
subroutine noise_gaussian_init(self, n_gaussians, dims, file_id, profile)
subroutine noise_gaussian_init_3d3v(self, file_id)
real(kind=f64) function sll_f_cos_gaussian(self, x, v, m)
functions for initial profile of the particle distribution function
Module to select the kind parameter.
Abstract data type for parameters of initial distribution.
Data type for distribution function with (multiple) Gaussians in v and one plus cosine perturbations ...
    Report Typos and Errors