Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_distribution_function_initializer_4d.F90
Go to the documentation of this file.
2 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 #include "sll_assert.h"
4 #include "sll_memory.h"
5 #include "sll_working_precision.h"
6 
7  use sll_m_collective, only: &
10 
11  use sll_m_constants, only: &
12  sll_p_pi
13 
14  use sll_m_remapper, only: &
15  sll_o_get_layout_collective, &
16  sll_o_get_layout_i_max, &
17  sll_o_get_layout_i_min, &
18  sll_o_get_layout_j_max, &
19  sll_o_get_layout_j_min, &
20  sll_o_get_layout_k_max, &
21  sll_o_get_layout_k_min, &
22  sll_o_get_layout_l_max, &
23  sll_o_get_layout_l_min, &
24  sll_t_layout_4d, &
25  sll_o_local_to_global
26 
29 
30  implicit none
31 
32  public :: &
37 
38  private
39 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
40 
41  ! This is a simplistic initializer aimed at a 4d cartesian distribution
42  ! function, periodic in x and y, and compact-ish in vx and vy.
43  !
44  ! Basically:
45  !
46  ! f(x,y,vx,vy) = pi/(8*vt^2)*sin(pi*x)*sin(pi*y)*exp(-(vx^2+vy^2)/(2*vt^2))
47  !
48  ! It is meant to be used in the intervals:
49  ! x: [ 0,1]
50  ! y: [ 0,1]
51  ! vx: [-1,1]
52  ! vy: [-1,1]
53  ! thus vthermal has to be small relative to 1 to make the support as
54  ! 'compact' as possible.
55  !
56  ! Issue to resolve: to initialize the data we need the 'mesh'/'mapping'
57  ! information. How to deal with this in 4D? Do we pass multiple 2D
58  ! meshes? As something tentative, here we just write an ad hoc 4D
59  ! cartesian mesh.
60 
62  sll_real64 :: v_thermal
63  type(sll_t_layout_4d), pointer :: data_layout
64  type(sll_t_simple_cartesian_4d_mesh), pointer :: mesh_4d
65  contains
66  procedure, pass(init_obj) :: initialize => sll_s_load_test_4d_initializer
67  procedure, pass(init_obj) :: f_of_4args => compact_4d_field
68  end type sll_t_init_test_4d_par
69 
70  ! This has to end up somewhere else, if it is to stay in the library
72  sll_int32 :: num_cells1
73  sll_int32 :: num_cells2
74  sll_int32 :: num_cells3
75  sll_int32 :: num_cells4
76  sll_real64 :: x1_min
77  sll_real64 :: x1_max
78  sll_real64 :: x2_min
79  sll_real64 :: x2_max
80  sll_real64 :: x3_min
81  sll_real64 :: x3_max
82  sll_real64 :: x4_min
83  sll_real64 :: x4_max
84  sll_real64 :: delta_x1
85  sll_real64 :: delta_x2
86  sll_real64 :: delta_x3
87  sll_real64 :: delta_x4
89 
90 contains
91 
93  num_cells1, &
94  num_cells2, &
95  num_cells3, &
96  num_cells4, &
97  x1_min, &
98  x1_max, &
99  x2_min, &
100  x2_max, &
101  x3_min, &
102  x3_max, &
103  x4_min, &
104  x4_max)
105 
107  sll_int32, intent(in) :: num_cells1
108  sll_int32, intent(in) :: num_cells2
109  sll_int32, intent(in) :: num_cells3
110  sll_int32, intent(in) :: num_cells4
111  sll_real64, intent(in) :: x1_min
112  sll_real64, intent(in) :: x1_max
113  sll_real64, intent(in) :: x2_min
114  sll_real64, intent(in) :: x2_max
115  sll_real64, intent(in) :: x3_min
116  sll_real64, intent(in) :: x3_max
117  sll_real64, intent(in) :: x4_min
118  sll_real64, intent(in) :: x4_max
119  sll_int32 :: ierr
120 
121  sll_allocate(sll_f_new_cartesian_4d_mesh, ierr)
122  sll_f_new_cartesian_4d_mesh%num_cells1 = num_cells1
123  sll_f_new_cartesian_4d_mesh%num_cells2 = num_cells2
124  sll_f_new_cartesian_4d_mesh%num_cells3 = num_cells3
125  sll_f_new_cartesian_4d_mesh%num_cells4 = num_cells4
126  sll_f_new_cartesian_4d_mesh%x1_min = x1_min
127  sll_f_new_cartesian_4d_mesh%x1_max = x1_max
128  sll_f_new_cartesian_4d_mesh%x2_min = x2_min
129  sll_f_new_cartesian_4d_mesh%x2_max = x2_max
130  sll_f_new_cartesian_4d_mesh%x3_min = x3_min
131  sll_f_new_cartesian_4d_mesh%x3_max = x3_max
132  sll_f_new_cartesian_4d_mesh%x4_min = x4_min
133  sll_f_new_cartesian_4d_mesh%x4_max = x4_max
134  sll_f_new_cartesian_4d_mesh%delta_x1 = (x1_max - x1_min)/real(num_cells1, f64)
135  sll_f_new_cartesian_4d_mesh%delta_x2 = (x2_max - x2_min)/real(num_cells2, f64)
136  sll_f_new_cartesian_4d_mesh%delta_x3 = (x3_max - x3_min)/real(num_cells3, f64)
137  sll_f_new_cartesian_4d_mesh%delta_x4 = (x4_max - x4_min)/real(num_cells4, f64)
138  end function sll_f_new_cartesian_4d_mesh
139 
140  subroutine delete_cartesian_4d_mesh(mesh)
141  type(sll_t_simple_cartesian_4d_mesh), pointer :: mesh
142  sll_int32 :: ierr
143  sll_deallocate(mesh, ierr)
144  end subroutine delete_cartesian_4d_mesh
145 
147  init_obj, &
148  data_position, &
149  mesh_4d, &
150  v_thermal, &
151  layout)
152 
153  class(sll_t_init_test_4d_par), intent(inout) :: init_obj
154  sll_int32 :: data_position
155  sll_real64, intent(in) :: v_thermal
156  type(sll_t_layout_4d), pointer :: layout
157  type(sll_t_simple_cartesian_4d_mesh), pointer :: mesh_4d
158 
159  if (.not. associated(layout)) then
160  print *, 'initialize_test_4d(): ERROR, passed layout is not initialized'
161  stop
162  end if
163 
164  if (.not. associated(mesh_4d)) then
165  print *, 'initialize_test_4d(): ERROR, passed 4d mesh is not initialized'
166  stop
167  end if
168 
169  init_obj%data_position = data_position
170  init_obj%mesh_4d => mesh_4d
171  init_obj%v_thermal = v_thermal
172  init_obj%data_layout => layout
173  end subroutine
174 
175  subroutine compact_4d_field(init_obj, data_out)
176  class(sll_t_init_test_4d_par), intent(inout) :: init_obj
177  sll_real64, dimension(:, :, :, :), intent(out) :: data_out
178  type(sll_t_layout_4d), pointer :: layout
179  sll_int32 :: i
180  sll_int32 :: j
181  sll_int32 :: k
182  sll_int32 :: l
183  sll_int32 :: i_min
184  sll_int32 :: i_max
185  sll_int32 :: j_min
186  sll_int32 :: j_max
187  sll_int32 :: k_min
188  sll_int32 :: k_max
189  sll_int32 :: l_min
190  sll_int32 :: l_max
191  sll_int32 :: myrank
192  sll_int32 :: num_pts1
193  sll_int32 :: num_pts2
194  sll_int32 :: num_pts3
195  sll_int32 :: num_pts4
196  sll_int32, dimension(1:4) :: gi
197  sll_real64 :: x
198  sll_real64 :: y
199  sll_real64 :: vx
200  sll_real64 :: vy
201  sll_real64 :: vx_min
202  sll_real64 :: vx_max
203  sll_real64 :: vy_min
204  sll_real64 :: vy_max
205  sll_real64 :: v_thermal
206  type(sll_t_collective_t), pointer :: col
207  sll_real64 :: delta1
208  sll_real64 :: delta2
209  sll_real64 :: delta3
210  sll_real64 :: delta4
211  sll_real64 :: factor, factor2
212 
213  ! Find the local limits of the array to initialize. This could have been
214  ! done as an initialization step, but it really does not matter, since
215  ! the whole process is supposed to be done only once anyway.
216  layout => init_obj%data_layout
217  col => sll_o_get_layout_collective(layout)
218  myrank = sll_f_get_collective_rank(col)
219  i_min = sll_o_get_layout_i_min(layout, myrank)
220  i_max = sll_o_get_layout_i_max(layout, myrank)
221  j_min = sll_o_get_layout_j_min(layout, myrank)
222  j_max = sll_o_get_layout_j_max(layout, myrank)
223  k_min = sll_o_get_layout_k_min(layout, myrank)
224  k_max = sll_o_get_layout_k_max(layout, myrank)
225  l_min = sll_o_get_layout_l_min(layout, myrank)
226  l_max = sll_o_get_layout_l_max(layout, myrank)
227  num_pts1 = i_max - i_min + 1
228  num_pts2 = j_max - j_min + 1
229  num_pts3 = k_max - k_min + 1
230  num_pts4 = l_max - l_min + 1
231  delta1 = init_obj%mesh_4d%delta_x1
232  delta2 = init_obj%mesh_4d%delta_x2
233  delta3 = init_obj%mesh_4d%delta_x3
234  delta4 = init_obj%mesh_4d%delta_x4
235 
236  vx_min = init_obj%mesh_4d%x3_min
237  vx_max = init_obj%mesh_4d%x3_max
238  vy_min = init_obj%mesh_4d%x4_min
239  vy_max = init_obj%mesh_4d%x4_max
240  v_thermal = init_obj%v_thermal
241  factor = sll_p_pi/(8.0_f64*v_thermal**2)
242  factor2 = 0.5_f64/v_thermal**2
243 
244  sll_assert(size(data_out, 1) .ge. num_pts1)
245  sll_assert(size(data_out, 2) .ge. num_pts2)
246  sll_assert(size(data_out, 3) .ge. num_pts3)
247  sll_assert(size(data_out, 4) .ge. num_pts4)
248 
249  ! At this point nothing has been done regarding the data being
250  ! cell centered... add this later.
251 
252  do l = 1, num_pts4
253  do k = 1, num_pts3
254  do j = 1, num_pts2
255  do i = 1, num_pts1
256  ! convert to global indices
257  gi(:) = sll_o_local_to_global(layout, (/i, j, k, l/))
258  x = gi(1)*delta1 ! danger: implicit xmin = 0
259  y = gi(2)*delta2 ! danger: implicit ymin = 0
260  vx = vx_min + gi(3)*delta3
261  vy = vy_min + gi(4)*delta4
262  ! The following function could be defined outside and
263  ! maybe stored in the object as a function pointer.
264  data_out(i, j, k, l) = factor*sin(sll_p_pi*x)*sin(sll_p_pi*y)* &
265  exp(-(vx**2 + vy**2)*factor2)
266  end do
267  end do
268  end do
269  end do
270 
271  end subroutine
272 
273 !!$ subroutine compact_4d_field( init_obj, data_out )
274 !!$ class(sll_t_init_test_4d_par), intent(inout) :: init_obj
275 !!$ sll_real64, dimension(:,:,:,:), intent(out) :: data_out
276 !!$ type(sll_t_layout_4d), pointer :: layout
277 !!$ sll_int32 :: i
278 !!$ sll_int32 :: j
279 !!$ sll_int32 :: k
280 !!$ sll_int32 :: l
281 !!$ sll_int32 :: i_min
282 !!$ sll_int32 :: i_max
283 !!$ sll_int32 :: j_min
284 !!$ sll_int32 :: j_max
285 !!$ sll_int32 :: k_min
286 !!$ sll_int32 :: k_max
287 !!$ sll_int32 :: l_min
288 !!$ sll_int32 :: l_max
289 !!$ sll_int32 :: myrank
290 !!$ sll_int32 :: num_pts1
291 !!$ sll_int32 :: num_pts2
292 !!$ sll_int32 :: num_pts3
293 !!$ sll_int32 :: num_pts4
294 !!$ sll_int32, dimension(1:4) :: gi
295 !!$ sll_real64 :: x
296 !!$ sll_real64 :: y
297 !!$ sll_real64 :: vx
298 !!$ sll_real64 :: vy
299 !!$ sll_real64 :: vx_min
300 !!$ sll_real64 :: vx_max
301 !!$ sll_real64 :: vy_min
302 !!$ sll_real64 :: vy_max
303 !!$ sll_real64 :: v_thermal
304 !!$ type(sll_t_collective_t), pointer :: col
305 !!$ sll_real64 :: delta1
306 !!$ sll_real64 :: delta2
307 !!$ sll_real64 :: delta3
308 !!$ sll_real64 :: delta4
309 !!$ sll_real64 :: factor, factor2
310 !!$
311 !!$ ! Find the local limits of the array to initialize. This could have been
312 !!$ ! done as an initialization step, but it really does not matter, since
313 !!$ ! the whole process is supposed to be done only once anyway.
314 !!$ layout => init_obj%data_layout
315 !!$ col => sll_o_get_layout_collective(layout)
316 !!$ myrank = sll_f_get_collective_rank( col )
317 !!$ i_min = sll_o_get_layout_i_min( layout, myrank )
318 !!$ i_max = sll_o_get_layout_i_max( layout, myrank )
319 !!$ j_min = sll_o_get_layout_j_min( layout, myrank )
320 !!$ j_max = sll_o_get_layout_j_max( layout, myrank )
321 !!$ k_min = sll_o_get_layout_k_min( layout, myrank )
322 !!$ k_max = sll_o_get_layout_k_max( layout, myrank )
323 !!$ l_min = sll_o_get_layout_l_min( layout, myrank )
324 !!$ l_max = sll_o_get_layout_l_max( layout, myrank )
325 !!$ num_pts1 = i_max - i_min + 1
326 !!$ num_pts2 = j_max - j_min + 1
327 !!$ num_pts3 = k_max - k_min + 1
328 !!$ num_pts4 = l_max - l_min + 1
329 !!$ delta1 = init_obj%mesh_4d%delta_x1
330 !!$ delta2 = init_obj%mesh_4d%delta_x2
331 !!$ delta3 = init_obj%mesh_4d%delta_x3
332 !!$ delta4 = init_obj%mesh_4d%delta_x4
333 !!$
334 !!$ vx_min = init_obj%mesh_4d%x3_min
335 !!$ vx_max = init_obj%mesh_4d%x3_max
336 !!$ vy_min = init_obj%mesh_4d%x4_min
337 !!$ vy_max = init_obj%mesh_4d%x4_max
338 !!$ v_thermal = init_obj%v_thermal
339 !!$ factor = sll_p_pi/(8.0_f64*v_thermal**2)
340 !!$ factor2 = 0.5_f64/v_thermal**2
341 !!$
342 !!$ SLL_ASSERT( size(data_out,1) .ge. num_pts1 )
343 !!$ SLL_ASSERT( size(data_out,2) .ge. num_pts2 )
344 !!$ SLL_ASSERT( size(data_out,3) .ge. num_pts3 )
345 !!$ SLL_ASSERT( size(data_out,4) .ge. num_pts4 )
346 !!$
347 !!$ ! At this point nothing has been done regarding the data being
348 !!$ ! cell centered... add this later.
349 !!$
350 !!$ do l=1, num_pts4
351 !!$ do k=1, num_pts3
352 !!$ do j=1, num_pts2
353 !!$ do i=1, num_pts1
354 !!$ ! convert to global indices
355 !!$ gi(:) = sll_o_local_to_global( layout, (/i,j,k,l/) )
356 !!$ x = gi(1)*delta1 ! danger: implicit xmin = 0
357 !!$ y = gi(2)*delta2 ! danger: implicit ymin = 0
358 !!$ vx = vx_min + gi(3)*delta3
359 !!$ vy = vy_min + gi(4)*delta4
360 !!$ ! The following function could be defined outside and
361 !!$ ! maybe stored in the object as a function pointer.
362 !!$ data_out(i,j,k,l) = factor*sin(sll_p_pi*x)*sin(sll_p_pi*y)*&
363 !!$ exp(-(vx**2+vy**2)*factor2)
364 !!$ end do
365 !!$ end do
366 !!$ end do
367 !!$ end do
368 !!$
369 !!$ end subroutine
370 
Parallelizing facility.
integer(kind=i32) function, public sll_f_get_collective_rank(col)
Determines the rank of the calling process in the communicator.
Fortran module where set some physical and mathematical constants.
real(kind=f64), parameter, public sll_p_pi
type(sll_t_simple_cartesian_4d_mesh) function, pointer, public sll_f_new_cartesian_4d_mesh(num_cells1, num_cells2, num_cells3, num_cells4, x1_min, x1_max, x2_min, x2_max, x3_min, x3_max, x4_min, x4_max)
subroutine, public sll_s_load_test_4d_initializer(init_obj, data_position, mesh_4d, v_thermal, layout)
Wrapper around the communicator.
    Report Typos and Errors