11 public :: a3_particles_to_grid
18 subroutine a3_particles_to_grid(tree, iv, coords, weights, n_particles, &
19 order, id_guess, density, fill_gc)
22 use m_a3_utils, only: a3_get_id_at, a3_tree_clear_ghostcells
23 type(
a3_t),
intent(inout) :: tree
24 integer,
intent(in) :: iv
25 integer,
intent(in) :: n_particles
26 real(dp),
intent(in) :: coords(3, n_particles)
27 real(dp),
intent(in) :: weights(n_particles)
28 integer,
intent(in) :: order
30 integer,
intent(inout),
optional :: id_guess(n_particles)
32 logical,
intent(in),
optional :: density
34 logical,
intent(in),
optional :: fill_gc
37 integer :: current_thread, current_work
38 integer :: threads_left, work_left
39 integer,
allocatable :: ids(:)
40 integer,
allocatable :: npart_per_box(:)
41 integer,
allocatable :: box_threads(:)
42 integer,
allocatable :: threads(:)
44 logical :: fill_gc_at_end
46 allocate(ids(n_particles))
47 allocate(npart_per_box(-1:tree%highest_id))
48 allocate(box_threads(tree%highest_id))
49 allocate(threads(n_particles))
53 if (
present(density)) as_density = density
54 fill_gc_at_end = .true.
55 if (
present(fill_gc)) fill_gc_at_end = fill_gc
57 if (
present(id_guess))
then 60 ids(n) = a3_get_id_at(tree, coords(:, n), &
63 npart_per_box(ids(n)) = npart_per_box(ids(n)) + 1
69 ids(n) = a3_get_id_at(tree, coords(:, n))
70 npart_per_box(ids(n)) = npart_per_box(ids(n)) + 1
75 if (sum(npart_per_box(-1:0)) > 0)
then 76 print *,
"a3_particles_to_grid: some are outside domain" 79 if (ids(n) <= af_no_box)
then 80 print *, n, coords(:, n)
88 error stop
"a3_particles_to_grid: some are outside domain" 91 threads_left = af_get_max_threads()
94 work_left = n_particles
96 do m = 1, tree%highest_id
97 box_threads(m) = current_thread
98 current_work = current_work + npart_per_box(m)
100 if (current_work > work_left/threads_left)
then 101 current_thread = current_thread + 1
102 threads_left = threads_left - 1
103 work_left = work_left - current_work
109 do n = 1, n_particles
110 threads(n) = box_threads(ids(n))
115 call a3_tree_clear_ghostcells(tree, iv)
119 call particles_to_grid_0(tree, iv, coords, weights, ids, &
120 threads, n_particles, as_density)
122 call particles_to_grid_1(tree, iv, coords, weights, ids, &
123 threads, n_particles, as_density)
124 call tree_add_from_ghostcells(tree, iv)
126 error stop
"a3_particles_to_grid: Invalid interpolation order" 129 call a3_restrict_tree(tree, iv)
131 if (fill_gc_at_end)
then 132 if (.not. tree%has_cc_method(iv))
then 133 print *,
"Variable with index ", iv,
"has no cc_method" 134 print *,
"do this with call a3_set_cc_methods(tree, iv, ...)" 135 error stop
"a3_particles_to_grid: no ghost cell method defined" 137 call a3_gc_tree(tree, iv)
140 end subroutine a3_particles_to_grid
142 subroutine particles_to_grid_0(tree, iv, coords, weights, ids, &
143 threads, n_particles, density)
145 type(
a3_t),
intent(inout) :: tree
146 integer,
intent(in) :: iv
147 integer,
intent(in) :: n_particles
148 real(dp),
intent(in) :: coords(3, n_particles)
149 real(dp),
intent(in) :: weights(n_particles)
150 integer,
intent(in) :: ids(n_particles)
151 integer,
intent(in) :: threads(n_particles)
152 logical,
intent(in) :: density
153 integer :: n, thread_id, ix(3)
156 thread_id = omp_get_thread_num()
158 do n = 1, n_particles
159 if (threads(n) /= thread_id) cycle
161 ix = a3_cc_ix(tree%boxes(ids(n)), coords(:, n))
165 where (ix < 1) ix = 1
166 where (ix > tree%n_cell) ix = tree%n_cell
169 tree%boxes(ids(n))%cc(ix(1), ix(2), ix(3), iv) = &
170 tree%boxes(ids(n))%cc(ix(1), ix(2), ix(3), iv) + &
171 weights(n) / tree%boxes(ids(n))%dr**3
173 tree%boxes(ids(n))%cc(ix(1), ix(2), ix(3), iv) = &
174 tree%boxes(ids(n))%cc(ix(1), ix(2), ix(3), iv) + &
179 end subroutine particles_to_grid_0
183 subroutine particles_to_grid_1(tree, iv, coords, weights, ids, &
184 threads, n_particles, density)
186 type(
a3_t),
intent(inout) :: tree
187 integer,
intent(in) :: iv
188 integer,
intent(in) :: n_particles
189 real(dp),
intent(in) :: coords(3, n_particles)
190 real(dp),
intent(in) :: weights(n_particles)
191 integer,
intent(in) :: ids(n_particles)
192 integer,
intent(in) :: threads(n_particles)
193 logical,
intent(in) :: density
194 real(dp) :: tmp(3), inv_dr
195 real(dp) :: wu(3), wl(3), w(2, 2, 2)
196 integer :: id, ix(3), n, thread_id
199 thread_id = omp_get_thread_num()
201 do n = 1, n_particles
202 if (threads(n) /= thread_id) cycle
205 inv_dr = 1.0_dp/tree%boxes(id)%dr
206 tmp = (coords(:, n) - tree%boxes(id)%r_min) * inv_dr + 0.5_dp
211 w(:, 1, 1) = [wl(1), wu(1)] * wl(2) * wl(3)
212 w(:, 2, 1) = [wl(1), wu(1)] * wu(2) * wl(3)
213 w(:, 1, 2) = [wl(1), wu(1)] * wl(2) * wu(3)
214 w(:, 2, 2) = [wl(1), wu(1)] * wu(2) * wu(3)
218 tree%boxes(id)%cc(ix(1):ix(1)+1, ix(2):ix(2)+1, ix(3):ix(3)+1, iv) = &
219 tree%boxes(id)%cc(ix(1):ix(1)+1, ix(2):ix(2)+1, ix(3):ix(3)+1, iv) + &
220 w * weights(n) / tree%boxes(id)%dr**3
222 tree%boxes(id)%cc(ix(1):ix(1)+1, ix(2):ix(2)+1, ix(3):ix(3)+1, iv) = &
223 tree%boxes(id)%cc(ix(1):ix(1)+1, ix(2):ix(2)+1, ix(3):ix(3)+1, iv) + &
229 end subroutine particles_to_grid_1
231 subroutine tree_add_from_ghostcells(tree, iv)
232 type(
a3_t),
intent(inout) :: tree
233 integer,
intent(in) :: iv
234 integer :: lvl, i, id
237 do lvl = 1, tree%highest_lvl
239 do i = 1,
size(tree%lvls(lvl)%leaves)
240 id = tree%lvls(lvl)%leaves(i)
241 call add_from_ghostcells(tree%boxes, id, iv)
246 end subroutine tree_add_from_ghostcells
248 subroutine add_from_ghostcells(boxes, id, iv)
249 type(
box3_t),
intent(inout) :: boxes(:)
250 integer,
intent(in) :: id
251 integer,
intent(in) :: iv
252 integer :: i, j, k, i0(3), i1(3)
253 integer :: n0(3), n1(3), nb_id, nc
256 nc = boxes(id)%n_cell
258 do k = -1, 1;
do j = -1, 1;
do i = -1, 1
259 if (all([i, j, k] == 0)) cycle
261 nb_id = boxes(id)%neighbor_mat(i, j, k)
265 if (nb_id <= af_no_box)
then 267 else if (nb_id > af_no_box)
then 268 if (a3_has_children(boxes(nb_id))) copy_own = .true.
278 where ([i, j, k] == 1)
282 elsewhere ([i, j, k] == -1)
288 boxes(id)%cc(i0(1):i1(1), i0(2):i1(2), i0(3):i1(3), iv) = &
289 boxes(id)%cc(i0(1):i1(1), i0(2):i1(2), i0(3):i1(3), iv) + &
290 boxes(id)%cc(n0(1):n1(1), n0(2):n1(2), n0(3):n1(3), iv)
296 where ([i, j, k] == 1)
300 elsewhere ([i, j, k] == -1)
306 boxes(id)%cc(i0(1):i1(1), i0(2):i1(2), i0(3):i1(3), iv) = &
307 boxes(id)%cc(i0(1):i1(1), i0(2):i1(2), i0(3):i1(3), iv) + &
308 boxes(nb_id)%cc(n0(1):n1(1), n0(2):n1(2), n0(3):n1(3), iv)
310 end do; end do; end do
311 end subroutine add_from_ghostcells
This module contains all kinds of different 'helper' routines for Afivo. If the number of routines fo...
This module contains routines for restriction: going from fine to coarse variables.
This module contains routines related to , which can interpolate 'to' the grid and 'from' the grid (u...
The basic building block of afivo: a box with cell-centered and face centered data, and information about its position, neighbors, children etc.
Type which stores all the boxes and levels, as well as some information about the number of boxes...
This module contains routines related to the filling of ghost cells. Note that corner ghost cells are...
This module contains the basic types and constants that are used in the 3-dimensional version of Afiv...