Report Typos and Errors    
Semi-Lagrangian Library
Modular library for kinetic and gyrokinetic simulations of plasmas in fusion energy devices.
sll_m_particle_sort.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 !**************************************************************
17 
19 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
20 #include "sll_assert.h"
21 #include "sll_memory.h"
22 #include "sll_working_precision.h"
23 
24  use sll_m_cartesian_meshes, only: &
26 
27  use sll_m_particle_group_2d, only: &
29 
30  use sll_m_particle_group_4d, only: &
32 
36 
37  implicit none
38 
39  public :: &
40  sll_o_delete, &
45 
46  private
47 !+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
48 
50  sll_int32, dimension(:), pointer :: pa
51  sll_int32, dimension(:), pointer :: pa_save
52  type(sll_t_cartesian_mesh_2d), pointer :: mesh
53  sll_int32 :: num_cells
55 
56  interface sll_o_delete
57  module procedure delete_particle_sorter_2d
58  end interface sll_o_delete
59 
60 contains
61 
62  function sll_f_new_particle_sorter_2d(mesh) result(res)
63  type(sll_t_particle_sorter_2d), pointer :: res
64  type(sll_t_cartesian_mesh_2d), pointer :: mesh
65  sll_int32 :: ierr
66  sll_int32 :: ncx
67  sll_int32 :: ncy
68 
69  if (.not. associated(mesh)) then
70  print *, 'ERROR, sll_f_new_particle_sorter_2d(): passed mesh is not ', &
71  'associated.'
72  stop
73  end if
74 
75  ncx = mesh%num_cells1
76  ncy = mesh%num_cells2
77 
78  sll_allocate(res, ierr)
79  sll_allocate(res%pa(ncx*ncy + 1), ierr)
80  sll_allocate(res%pa_save(ncx*ncy + 1), ierr)
81 
82  res%mesh => mesh
83  res%num_cells = ncx*ncy
84  end function sll_f_new_particle_sorter_2d
85 
86  subroutine sll_s_sort_particles_2d(sorter, group)
87  type(sll_t_particle_sorter_2d), pointer :: sorter
88  type(sll_t_particle_group_4d), pointer :: group
89  sll_int32 :: i
90  sll_int32 :: j
91  sll_int32 :: k
92  sll_int32 :: n ! number of particles
93  sll_int32 :: num_cells
94  sll_int32 :: current_cell
95  sll_int32 :: index_in
96  sll_int32 :: index_out
97  sll_int32 :: index_stop
98  type(sll_t_particle_4d), dimension(:), pointer :: p
99  type(sll_t_particle_4d) :: p_tmp
100  sll_int32, dimension(:), pointer :: pa
101  sll_int32, dimension(:), pointer :: pa_save
102  ! make sure that the meshes are the same
103  if (.not. associated(sorter%mesh, target=group%mesh)) then
104  print *, 'ERROR, sll_s_sort_particles_2d(): mesh passed to sorter ', &
105  'and particle group mesh are not the same. Code will not stop ', &
106  'but bad things may happen...'
107  end if
108 
109  n = group%number_particles
110  num_cells = sorter%num_cells
111  p => group%p_list
112  pa => sorter%pa(:)
113  pa_save => sorter%pa_save(:)
114  pa(:) = 0
115  pa_save(:) = 0
116  ! Count how many particles are there in each cell, name this 'cell count'.
117  do i = 1, n
118  pa(p(i)%ic) = pa(p(i)%ic) + 1
119  end do
120 
121  ! Convert the 'cell count' into an allocation within pa and save a copy
122  ! of this allocation in pa_save. The allocation is just the sum of
123  ! particles up to, and including the previous cell. Thus pa(i) stores
124  ! the number of particles up to cell i-1.
125  k = 0
126  do i = 1, num_cells + 1
127  j = pa(i)
128  pa_save(i) = k
129  pa(i) = k
130  k = k + j
131  end do
132 
133  i = 1
134  do while (i < num_cells + 1)
135  if (pa(i) >= pa_save(i + 1)) then
136  i = i + 1 ! current cell is done, process next cell.
137  else
138  ! The current cell still contain sunsorted particles, get the next
139  ! unsorted particle in the current cell for the next sorting cycle.
140  ! pa(i) contains the index in which the next particle in cell 'i'
141  ! should be put.
142  index_in = pa(i) + 1 ! which particle to process
143  index_stop = pa(i) + 1 ! when to stop the swaps
144  do
145  ! Figure out where to store the input particle. Update the
146  ! allocation accordingly.
147  current_cell = p(index_in)%ic
148  pa(current_cell) = pa(current_cell) + 1
149  index_out = pa(current_cell)
150  if (index_out .ne. index_stop) then
151  p_tmp = p(index_out)
152  p(index_out) = p(index_in)
153  p(index_in) = p_tmp
154  else
155  exit
156  end if
157  end do
158  end if
159  end do
160  end subroutine sll_s_sort_particles_2d
161 
162  subroutine sll_s_sort_gc_particles_2d(sorter, group)
163  type(sll_t_particle_sorter_2d), pointer :: sorter
164  type(sll_t_particle_group_2d), pointer :: group
165  sll_int32 :: i
166  sll_int32 :: j
167  sll_int32 :: k
168  sll_int32 :: n ! number of particles
169  sll_int32 :: num_cells
170  sll_int32 :: current_cell
171  sll_int32 :: index_in
172  sll_int32 :: index_out
173  sll_int32 :: index_stop
174  type(sll_t_particle_2d), dimension(:), pointer :: p
175  type(sll_t_particle_2d) :: p_tmp
176  sll_int32, dimension(:), pointer :: pa
177  sll_int32, dimension(:), pointer :: pa_save
178  ! make sure that the meshes are the same
179  if (.not. associated(sorter%mesh, target=group%mesh)) then
180  print *, 'ERROR, sll_s_sort_particles_2d(): mesh passed to sorter ', &
181  'and particle group mesh are not the same. Code will not stop ', &
182  'but bad things may happen...'
183  end if
184 
185  n = group%number_particles
186  num_cells = sorter%num_cells
187  p => group%p_list
188  pa => sorter%pa(:)
189  pa_save => sorter%pa_save(:)
190  pa(:) = 0
191  pa_save(:) = 0
192  ! Count how many particles are there in each cell, name this 'cell count'.
193  do i = 1, n
194  pa(p(i)%ic) = pa(p(i)%ic) + 1
195  end do
196 
197  ! Convert the 'cell count' into an allocation within pa and save a copy
198  ! of this allocation in pa_save. The allocation is just the sum of
199  ! particles up to, and including the previous cell. Thus pa(i) stores
200  ! the number of particles up to cell i-1.
201  k = 0
202  do i = 1, num_cells + 1
203  j = pa(i)
204  pa_save(i) = k
205  pa(i) = k
206  k = k + j
207  end do
208 
209  i = 1
210  do while (i < num_cells + 1)
211  if (pa(i) >= pa_save(i + 1)) then
212  i = i + 1 ! current cell is done, process next cell.
213  else
214  ! The current cell still contain sunsorted particles, get the next
215  ! unsorted particle in the current cell for the next sorting cycle.
216  ! pa(i) contains the index in which the next particle in cell 'i'
217  ! should be put.
218  index_in = pa(i) + 1 ! which particle to process
219  index_stop = pa(i) + 1 ! when to stop the swaps
220  do
221  ! Figure out where to store the input particle. Update the
222  ! allocation accordingly.
223  current_cell = p(index_in)%ic
224  pa(current_cell) = pa(current_cell) + 1
225  index_out = pa(current_cell)
226  if (index_out .ne. index_stop) then
227  p_tmp = p(index_out)
228  p(index_out) = p(index_in)
229  p(index_in) = p_tmp
230  else
231  exit
232  end if
233  end do
234  end if
235  end do
236  end subroutine sll_s_sort_gc_particles_2d
237 
238  subroutine delete_particle_sorter_2d(sorter)
239  type(sll_t_particle_sorter_2d), pointer :: sorter
240  sll_assert(associated(sorter))
241  end subroutine delete_particle_sorter_2d
242 
243 end module sll_m_particle_sort
Cartesian mesh basic types.
type(sll_t_particle_sorter_2d) function, pointer, public sll_f_new_particle_sorter_2d(mesh)
subroutine, public sll_s_sort_particles_2d(sorter, group)
subroutine, public sll_s_sort_gc_particles_2d(sorter, group)
subroutine delete_particle_sorter_2d(sorter)
    Report Typos and Errors