Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_particle_initializers_4d.F90
Go to the documentation of this file.
1 !**************************************************************
2 ! Copyright INRIA
3 ! Authors :
4 ! CALVI project team
5 !
6 ! This code SeLaLib (for Semi-Lagrangian-Library)
7 ! is a parallel library for simulating the plasma turbulence
8 ! in a tokamak.
9 !
10 ! This software is governed by the CeCILL-B license
11 ! under French law and abiding by the rules of distribution
12 ! of free software. You can use, modify and redistribute
13 ! the software under the terms of the CeCILL-B license as
14 ! circulated by CEA, CNRS and INRIA at the following URL
15 ! "http://www.cecill.info".
16 !**************************************************************
19 
21 
23 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
24 #include "sll_assert.h"
25 #include "sll_memory.h"
26 #include "sll_working_precision.h"
27 #include "sll_particle_representation.h"
28 
29  use sll_m_cartesian_meshes, only: &
31 
32  use sll_m_constants, only: &
33  sll_p_pi
34 
35  use sll_m_gaussian, only: &
37 
38  use sll_m_hammersley, only: &
40 
41  use sll_m_particle_group_4d, only: &
43 
44  implicit none
45 
46  public :: &
49 
50  private
51 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
52 
53 ! private sll_init_spatial_particle2D, suite_hamm
54 ! ! In the future, we have to build a directory called
55 ! ! random_number_generators
56 
57 contains
58 
63  thermal_speed, &
64  alpha, k, &
65  m2d, &
66  num_particles, &
67  p_group, &
68  rand_seed, &
69  rank, worldsize)
70  sll_real64, intent(in) :: thermal_speed! < sigma of Gaussian distribution
71  sll_real64, intent(in) :: alpha, k
72  type(sll_t_cartesian_mesh_2d), intent(in) :: m2d
73  sll_int32, intent(in) :: num_particles
74  sll_int32, dimension(:), intent(in), optional :: rand_seed
75  sll_int32, optional :: rank, worldsize
76  type(sll_t_particle_group_4d), pointer, intent(inout) :: p_group
77  sll_int32 :: j
78  sll_int32 :: ncx, ic_x, ic_y
79  sll_real64 :: x, y, vx, vy, z
80  sll_real64 :: xmin, ymin, rdx, rdy
81  sll_real32 :: weight
82  sll_real32 :: off_x, off_y
83  sll_real64 :: tmp1, tmp2
84  sll_real64 :: yo, nu, fdx
85 
86  if (present(rand_seed)) then
87  call random_seed(put=rand_seed)
88  end if
89 
90  if (present(worldsize)) then
91  weight = real((m2d%eta1_max - m2d%eta1_min)* &
92  (m2d%eta2_max - m2d%eta2_min), f32)/(real(worldsize, f32)*real(num_particles, f32))
93  else
94  weight = real((m2d%eta1_max - m2d%eta1_min)* &
95  (m2d%eta2_max - m2d%eta2_min), f32)/real(num_particles, f32)
96  end if
97 ! Each MPI node initialize 'num_particles' particles in the phase space
98 
99  rdx = 1._f64/m2d%delta_eta1
100  rdy = 1._f64/m2d%delta_eta2
101  xmin = m2d%eta1_min
102  ymin = m2d%eta2_min
103  ncx = m2d%num_cells1
104 
105  j = 1
106  do while (j <= num_particles)
107  call random_number(x)
108  x = (m2d%eta1_max - xmin)*x + xmin
109  call random_number(fdx)
110  fdx = (1._f64 + alpha)*fdx
111  if (sll_f_eval_landau1d(alpha, k, x) >= fdx) then
112  call random_number(y)
113  y = (m2d%eta2_max - ymin)*y + ymin
114  call random_number(z)
115  nu = thermal_speed*sqrt(-2._f64*log(1.0_f64 - z))
116  call random_number(yo)
117  vx = nu*cos(yo*2.0_f64*sll_p_pi)
118  vy = nu*sin(yo*2.0_f64*sll_p_pi)
119  set_particle_values(p_group%p_list(j), x, y, vx, vy, weight, xmin, ymin, ncx, ic_x, ic_y, off_x, off_y, rdx, rdy, tmp1, tmp2)
120  j = j + 1
121  end if
122  end do
123 
124  return
125  sll_assert(present(rank))
126  end subroutine sll_s_initial_random_particles_4d
127 
132  thermal_speed, alpha, k, &
133  m2d, &
134  num_particles, &
135  p_group, &
136  rand_seed, rank, worldsize)
137  sll_real64, intent(in) :: thermal_speed
138  sll_real64, intent(in) :: alpha, k
139  type(sll_t_cartesian_mesh_2d), intent(in) :: m2d
140  sll_int32, intent(in) :: num_particles
141  type(sll_t_particle_group_4d), pointer, intent(inout) :: p_group
142  sll_int32 :: j, ll
143  sll_int32 :: ncx, ic_x, ic_y
144  sll_real64 :: x, y, vx, vy
145  sll_real64 :: xmin, ymin, rdx, rdy
146  sll_real32 :: weight
147  sll_real32 :: off_x, off_y
148  sll_real64 :: tmp1, tmp2
149  sll_int32, dimension(:), intent(in), optional :: rand_seed
150  sll_int32, optional :: rank, worldsize
151  sll_real64, dimension(:), allocatable :: pos_x, pos_y
152  sll_int32 :: ierr
153  sll_real64 :: nu, rtheta
154 
155  if (present(rand_seed)) then
156  call random_seed(put=rand_seed)
157  end if
158 
159  if (present(worldsize)) then
160  weight = real((m2d%eta1_max - m2d%eta1_min)* &
161  (m2d%eta2_max - m2d%eta2_min), f32)/(real(worldsize, f32)*real(num_particles, f32))
162  else
163  weight = real((m2d%eta1_max - m2d%eta1_min)* &
164  (m2d%eta2_max - m2d%eta2_min), f32)/real(num_particles, f32)
165  end if
166 ! Each MPI node initialize 'num_particles' particles in the phase space
167 
168  sll_allocate(pos_x(1:num_particles), ierr)
169  sll_allocate(pos_y(1:num_particles), ierr)
170 
171  rdx = 1._f64/m2d%delta_eta1
172  rdy = 1._f64/m2d%delta_eta2
173  xmin = m2d%eta1_min
174  ymin = m2d%eta2_min
175  ncx = m2d%num_cells1
176 
177  ll = 0
178  j = 1
179  do while (j <= num_particles + ll)
180  x = sll_f_suite_hamm(j, 3)
181  x = (m2d%eta1_max - xmin)*x + xmin
182  y = sll_f_suite_hamm(j, 5)
183  y = (1._f64 + alpha)*y
184  if (sll_f_eval_landau1d(alpha, k, x) >= y) then
185  pos_x(j - ll) = x
186  pos_y(j - ll) = sll_f_suite_hamm(j - ll, 7)*(m2d%eta2_max - ymin) + ymin
187  j = j + 1
188  else
189  ll = ll + 1
190  j = j + 1
191  end if
192  end do
193  do j = 1, num_particles
194  nu = sqrt(-2._f64*log(1._f64 - (real(j, f64) - 0.5_f64)/real(num_particles, f64)))
195  rtheta = sll_f_suite_hamm(j, 2)
196  vx = nu*cos(rtheta*2._f64*sll_p_pi)
197  vy = nu*sin(rtheta*2._f64*sll_p_pi)
198  vx = vx*thermal_speed
199  vy = vy*thermal_speed
200  set_particle_values(p_group%p_list(j),pos_x(j),pos_y(j),vx,vy,weight,xmin,ymin,ncx,ic_x,ic_y,off_x,off_y,rdx,rdy,tmp1,tmp2)
201  end do
202  sll_deallocate_array(pos_x, ierr)
203  sll_deallocate_array(pos_y, ierr)
204 
205  return
206  sll_assert(present(rank))
208 
212  thermal_speed, &
213  alpha, kx, ky, &
214  m2d, &
215  num_particles, &
216  p_group, &
217  rand_seed, &
218  rank, worldsize)
219  sll_real64, intent(in) :: thermal_speed
220  sll_real64, intent(in) :: alpha, kx, ky
221  type(sll_t_cartesian_mesh_2d), intent(in) :: m2d
222  sll_int32, intent(in) :: num_particles
223  sll_int32, dimension(:), intent(in), optional :: rand_seed
224  sll_int32, optional :: rank, worldsize
225  type(sll_t_particle_group_4d), pointer, intent(inout) :: p_group
226  sll_int32 :: j, ncx, ic_x, ic_y
227  sll_real64 :: x, y, vx, vy, z
228  sll_real64 :: xmin, ymin, rdx, rdy
229  sll_real32 :: weight
230  sll_real32 :: off_x, off_y
231  sll_real64 :: tmp1, tmp2
232  sll_real64 :: val(1:2)
233 
234  if (present(rand_seed)) then
235  call random_seed(put=rand_seed)
236  end if
237 
238  if (present(worldsize)) then
239  weight = real((m2d%eta1_max - m2d%eta1_min)* &
240  (m2d%eta2_max - m2d%eta2_min), f32)/(real(worldsize, f32)*real(num_particles, f32))
241  else
242  weight = real((m2d%eta1_max - m2d%eta1_min)* &
243  (m2d%eta2_max - m2d%eta2_min), f32)/real(num_particles, f32)
244  end if
245 
246  rdx = 1._f64/m2d%delta_eta1
247  rdy = 1._f64/m2d%delta_eta2
248  xmin = m2d%eta1_min
249  ymin = m2d%eta2_min
250  ncx = m2d%num_cells1
251 
252  j = 1
253  do while (j <= num_particles)
254  call random_number(x)
255  x = (m2d%eta1_max - xmin)*x + xmin
256  call random_number(y)
257  y = (m2d%eta2_max - ymin)*y + ymin
258  call random_number(z)
259  z = (1._f64 + alpha)*z
260  if (sll_f_eval_landau2d(alpha, kx, x, ky, y) >= z) then
261  call sll_s_gaussian_deviate_2d(val)
262  vx = val(1)*thermal_speed
263  vy = val(2)*thermal_speed
264  set_particle_values(p_group%p_list(j), x, y, vx, vy, weight, xmin, ymin, ncx, ic_x, ic_y, off_x, off_y, rdx, rdy, tmp1, tmp2)
265  j = j + 1
266  end if
267  end do
268 
269  return
270  sll_assert(present(rank))
271 
273 
274  function sll_f_eval_landau1d(alp, kx, x)
275  sll_real64 :: alp, kx, x
276  sll_real64 :: sll_f_eval_landau1d
277  sll_f_eval_landau1d = 1._f64 + alp*cos(kx*x)
278  end function sll_f_eval_landau1d
279 
280  function sll_f_eval_landau2d(alp, kx, x, ky, y)
281  sll_real64 :: alp, kx, x, ky, y
282  sll_real64 :: sll_f_eval_landau2d
283  sll_f_eval_landau2d = 1._f64 + alp*cos(kx*x)*cos(ky*y)
284  end function sll_f_eval_landau2d
285 
Cartesian mesh basic types.
Fortran module where set some physical and mathematical constants.
real(kind=f64), parameter, public sll_p_pi
sll_m_gaussian random generator
subroutine, public sll_s_gaussian_deviate_2d(res)
Returns a value of a random variable in TWO dimensions following the Gaussian probability density wit...
hamm pseudo-random generator
real(kind=f64) function, public sll_f_suite_hamm(n, b)
Initialization of particles in 2d+2v: the Landau damping case.
subroutine, public sll_s_initial_hammersley_particles_4d(thermal_speed, alpha, k, m2d, num_particles, p_group, rand_seed, rank, worldsize)
Initialize particles in a 2d+2v phase space using pseudo-random generators. The Landau damping case w...
subroutine, public sll_s_initial_random_particles_4d(thermal_speed, alpha, k, m2d, num_particles, p_group, rand_seed, rank, worldsize)
Initialize particles in a 2d+2v phase space using random generators. The Landau damping case with a p...
subroutine sll_s_initial_random_particles_4d_landau2d(thermal_speed, alpha, kx, ky, m2d, num_particles, p_group, rand_seed, rank, worldsize)
The Landau damping case with a perturbation in BOTH directions of the physical space: (x,...
real(kind=f64) function sll_f_eval_landau1d(alp, kx, x)
real(kind=f64) function sll_f_eval_landau2d(alp, kx, x, ky, y)
    Report Typos and Errors