Afivo  0.3
m_a3_ghostcell.f90
1 
5  use m_a3_types
6 
7  implicit none
8  private
9 
10  public :: a3_gc_tree
11  public :: a3_gc_ids
12  public :: a3_gc_box
13  public :: a3_bc_dirichlet_zero
14  public :: a3_bc_neumann_zero
15  public :: a3_bc_continuous
16  public :: a3_gc_interp
17  public :: a3_gc_prolong_copy
18  public :: a3_gc_interp_lim
19  public :: a3_gc2_box
20  public :: a3_gc2_prolong_linear
21  public :: a3_bc2_neumann_zero
22  public :: a3_bc2_dirichlet_zero
23 
24  ! Define interfaces so ghost cell routines can be called for a single variable
25  ! or for multiple variables
26  interface a3_gc_tree
27  module procedure a3_gc_tree_iv, a3_gc_tree_ivs
28  end interface a3_gc_tree
29 
30  interface a3_gc_ids
31  module procedure a3_gc_ids_iv, a3_gc_ids_ivs, a3_gc_ids_v1
32  end interface a3_gc_ids
33 
34  interface a3_gc_box
35  module procedure a3_gc_box_iv, a3_gc_box_ivs, a3_gc_box_v1
36  end interface
37 
38 contains
39 
42  subroutine a3_gc_tree_ivs(tree, ivs, subr_rb, subr_bc, corners, leaves_only)
43  type(a3_t), intent(inout) :: tree
44  integer, intent(in) :: ivs(:)
45  procedure(a3_subr_rb), optional :: subr_rb
46  procedure(a3_subr_bc), optional :: subr_bc
47  logical, intent(in), optional :: corners
48  logical, intent(in), optional :: leaves_only
49  integer :: lvl
50  logical :: all_ids
51 
52  if (.not. tree%ready) error stop "a3_gc_tree: tree not ready"
53  all_ids = .true.
54  if (present(leaves_only)) all_ids = .not. leaves_only
55 
56  if (all_ids) then
57  do lvl = lbound(tree%lvls, 1), tree%highest_lvl
58  call a3_gc_ids(tree, tree%lvls(lvl)%ids, ivs, &
59  subr_rb, subr_bc, corners)
60  end do
61  else
62  do lvl = lbound(tree%lvls, 1), tree%highest_lvl
63  call a3_gc_ids(tree, tree%lvls(lvl)%leaves, ivs, &
64  subr_rb, subr_bc, corners)
65  end do
66  end if
67  end subroutine a3_gc_tree_ivs
68 
71  subroutine a3_gc_tree_iv(tree, iv, subr_rb, subr_bc, corners, leaves_only)
72  type(a3_t), intent(inout) :: tree
73  integer, intent(in) :: iv
74  procedure(a3_subr_rb), optional :: subr_rb
75  procedure(a3_subr_bc), optional :: subr_bc
76  logical, intent(in), optional :: corners
77  logical, intent(in), optional :: leaves_only
78  integer :: lvl
79  logical :: all_ids
80 
81  if (.not. tree%ready) error stop "a3_gc_tree: tree not ready"
82  all_ids = .true.
83  if (present(leaves_only)) all_ids = .not. leaves_only
84 
85  if (all_ids) then
86  do lvl = lbound(tree%lvls, 1), tree%highest_lvl
87  call a3_gc_ids(tree, tree%lvls(lvl)%ids, iv, &
88  subr_rb, subr_bc, corners)
89  end do
90  else
91  do lvl = lbound(tree%lvls, 1), tree%highest_lvl
92  call a3_gc_ids(tree, tree%lvls(lvl)%leaves, iv, &
93  subr_rb, subr_bc, corners)
94  end do
95  end if
96  end subroutine a3_gc_tree_iv
97 
101  subroutine a3_gc_ids_ivs(tree, ids, ivs, subr_rb, subr_bc, corners)
102  type(a3_t), intent(inout) :: tree
103  integer, intent(in) :: ids(:)
104  integer, intent(in) :: ivs(:)
105  procedure(a3_subr_rb), optional :: subr_rb
106  procedure(a3_subr_bc), optional :: subr_bc
107  logical, intent(in), optional :: corners
108  integer :: i
109 
110  !$omp parallel do
111  do i = 1, size(ids)
112  call a3_gc_box(tree, ids(i), ivs, subr_rb, subr_bc, corners)
113  end do
114  !$omp end parallel do
115  end subroutine a3_gc_ids_ivs
116 
120  subroutine a3_gc_ids_iv(tree, ids, iv, subr_rb, subr_bc, corners)
121  type(a3_t), intent(inout) :: tree
122  integer, intent(in) :: ids(:)
123  integer, intent(in) :: iv
124  procedure(a3_subr_rb), optional :: subr_rb
125  procedure(a3_subr_bc), optional :: subr_bc
126  logical, intent(in), optional :: corners
127  integer :: i
128 
129  !$omp parallel do
130  do i = 1, size(ids)
131  call a3_gc_box(tree, ids(i), iv, subr_rb, subr_bc, corners)
132  end do
133  !$omp end parallel do
134  end subroutine a3_gc_ids_iv
135 
139  subroutine a3_gc_ids_v1(boxes, ids, iv, subr_rb, subr_bc, corners)
140  type(box3_t), intent(inout) :: boxes(:)
141  integer, intent(in) :: ids(:)
142  integer, intent(in) :: iv
143  procedure(a3_subr_rb), optional :: subr_rb
144  procedure(a3_subr_bc), optional :: subr_bc
145  logical, intent(in), optional :: corners
146  integer :: i
147 
148  !$omp parallel do
149  do i = 1, size(ids)
150  call a3_gc_box(boxes, ids(i), iv, subr_rb, subr_bc, corners)
151  end do
152  !$omp end parallel do
153  end subroutine a3_gc_ids_v1
154 
156  subroutine a3_gc_box_ivs(tree, id, ivs, subr_rb, subr_bc, corners)
157  type(a3_t), intent(inout) :: tree
158  integer, intent(in) :: id
159  integer, intent(in) :: ivs(:)
160  procedure(a3_subr_rb), optional :: subr_rb
161  procedure(a3_subr_bc), optional :: subr_bc
162  logical, intent(in), optional :: corners
163  logical :: do_corners
164  integer :: i, iv
165  procedure(a3_subr_rb), pointer :: use_rb
166  procedure(a3_subr_bc), pointer :: use_bc
167 
168  do_corners = .true.
169  if (present(corners)) do_corners = corners
170 
171  do i = 1, size(ivs)
172  iv = ivs(i)
173 
174  if (present(subr_rb)) then
175  use_rb => subr_rb
176  else if (tree%has_cc_method(iv)) then
177  use_rb => tree%cc_methods(iv)%rb
178  else
179  error stop "a3_gc_box: no refinement boundary method stored"
180  end if
181 
182  if (present(subr_bc)) then
183  use_bc => subr_bc
184  else if (tree%has_cc_method(iv)) then
185  use_bc => tree%cc_methods(iv)%bc
186  else
187  error stop "a3_gc_box: no boundary condition stored"
188  end if
189 
190  call a3_gc_box_sides(tree%boxes, id, iv, use_rb, use_bc)
191  if (do_corners) call a3_gc_box_corner(tree%boxes, id, iv)
192  end do
193  end subroutine a3_gc_box_ivs
194 
196  subroutine a3_gc_box_iv(tree, id, iv, subr_rb, subr_bc, corners)
197  type(a3_t), intent(inout) :: tree
198  integer, intent(in) :: id
199  integer, intent(in) :: iv
200  procedure(a3_subr_rb), optional :: subr_rb
201  procedure(a3_subr_bc), optional :: subr_bc
202  logical, intent(in), optional :: corners
203  logical :: do_corners
204  procedure(a3_subr_rb), pointer :: use_rb
205  procedure(a3_subr_bc), pointer :: use_bc
206 
207  if (present(subr_rb)) then
208  use_rb => subr_rb
209  else if (tree%has_cc_method(iv)) then
210  use_rb => tree%cc_methods(iv)%rb
211  else
212  error stop "a3_gc_box: no refinement boundary method stored"
213  end if
214 
215  if (present(subr_bc)) then
216  use_bc => subr_bc
217  else if (tree%has_cc_method(iv)) then
218  use_bc => tree%cc_methods(iv)%bc
219  else
220  error stop "a3_gc_box: no boundary condition stored"
221  end if
222 
223  do_corners = .true.
224  if (present(corners)) do_corners = corners
225 
226  call a3_gc_box_sides(tree%boxes, id, iv, use_rb, use_bc)
227  if (do_corners) call a3_gc_box_corner(tree%boxes, id, iv)
228  end subroutine a3_gc_box_iv
229 
231  subroutine a3_gc_box_v1(boxes, id, iv, subr_rb, subr_bc, corners)
232  type(box3_t), intent(inout) :: boxes(:)
233  integer, intent(in) :: id
234  integer, intent(in) :: iv
235  procedure(a3_subr_rb) :: subr_rb
236  procedure(a3_subr_bc) :: subr_bc
237  logical, intent(in), optional :: corners
238  logical :: do_corners
239 
240  do_corners = .true.
241  if (present(corners)) do_corners = corners
242 
243  call a3_gc_box_sides(boxes, id, iv, subr_rb, subr_bc)
244  if (do_corners) call a3_gc_box_corner(boxes, id, iv)
245  end subroutine a3_gc_box_v1
246 
249  subroutine a3_gc_box_sides(boxes, id, iv, subr_rb, subr_bc)
250  type(box3_t), intent(inout) :: boxes(:)
251  integer, intent(in) :: id
252  integer, intent(in) :: iv
253  procedure(a3_subr_rb) :: subr_rb
254  procedure(a3_subr_bc) :: subr_bc
255  integer :: nb, nb_id, bc_type
256  integer :: nb_dim, lo(3), hi(3), dnb(3)
257 
258  do nb = 1, a3_num_neighbors
259  nb_id = boxes(id)%neighbors(nb)
260 
261  if (nb_id > af_no_box) then
262  ! There is a neighbor
263  nb_dim = a3_neighb_dim(nb)
264  lo(:) = 1
265  hi(:) = boxes(id)%n_cell
266  lo(nb_dim) = a3_neighb_high_01(nb) * (boxes(id)%n_cell + 1)
267  hi(nb_dim) = lo(nb_dim)
268  dnb = a3_neighb_offset([nb])
269  call copy_from_nb(boxes(id), boxes(nb_id), dnb, lo, hi, iv)
270  else if (nb_id == af_no_box) then
271  ! Refinement boundary
272  call subr_rb(boxes, id, nb, iv)
273  else
274  ! Physical boundary
275  call subr_bc(boxes(id), nb, iv, bc_type)
276  call bc_to_gc(boxes(id), nb, iv, bc_type)
277  end if
278  end do
279 
280  end subroutine a3_gc_box_sides
281 
285  subroutine a3_gc_box_corner(boxes, id, iv)
286  type(box3_t), intent(inout) :: boxes(:)
287  integer, intent(in) :: id
288  integer, intent(in) :: iv
289  integer :: n, nb_id, dnb(3), lo(3)
290  integer :: hi(3), dim
291 
292  ! Have to do edges before corners (since extrapolation can depend on edge values)
293  do n = 1, a3_num_edges
294  dim = a3_edge_dim(n)
295 
296  ! Check whether there is a neighbor, and find its index
297  nb_id = boxes(id)%neighbor_mat(a3_edge_dir(1, n), &
298  a3_edge_dir(2, n), a3_edge_dir(3, n))
299 
300  lo = a3_edge_min_ix(:, n) * (boxes(id)%n_cell + 1)
301  lo(dim) = 1
302 
303  if (nb_id > af_no_box) then
304  hi = lo
305  hi(dim) = boxes(id)%n_cell
306  dnb = a3_neighb_offset(a3_nb_adj_edge(:, n))
307  call copy_from_nb(boxes(id), boxes(nb_id), dnb, lo, hi, iv)
308  else
309  call a3_edge_gc_extrap(boxes(id), lo, dim, iv)
310  end if
311  end do
312 
313  do n = 1, a3_num_children
314  ! Check whether there is a neighbor, and find its index
315  dnb = 2 * a3_child_dix(:, n) - 1
316  nb_id = boxes(id)%neighbor_mat(dnb(1), dnb(2), dnb(3))
317  lo = a3_child_dix(:, n) * (boxes(id)%n_cell + 1)
318 
319  if (nb_id > af_no_box) then
320  call copy_from_nb(boxes(id), boxes(nb_id), dnb, lo, lo, iv)
321  else
322  call a3_corner_gc_extrap(boxes(id), lo, iv)
323  end if
324  end do
325  end subroutine a3_gc_box_corner
326 
327  subroutine bc_to_gc(box, nb, iv, bc_type)
328  type(box3_t), intent(inout) :: box
329  integer, intent(in) :: iv
330  integer, intent(in) :: nb
331  integer, intent(in) :: bc_type
332  real(dp) :: c0, c1, c2
333  integer :: nc
334 
335  nc = box%n_cell
336 
337  ! If we call the interior point x1, x2 and the ghost point x0, then a
338  ! Dirichlet boundary value b can be imposed as:
339  ! x0 = -x1 + 2*b
340  ! A Neumann b.c. can be imposed as:
341  ! x0 = x1 +/- dx * b
342  ! A continuous boundary (same slope) as:
343  ! x0 = 2 * x1 - x2
344  ! Below, we set coefficients to handle these cases
345  select case (bc_type)
346  case (af_bc_dirichlet)
347  c0 = 2
348  c1 = -1
349  c2 = 0
350  case (af_bc_neumann)
351  c0 = box%dr * a3_neighb_high_pm(nb) ! This gives a + or - sign
352  c1 = 1
353  c2 = 0
354  case (af_bc_continuous)
355  c0 = 0
356  c1 = 2
357  c2 = -1
358  case default
359  stop "fill_bc: unknown boundary condition"
360  end select
361 
362  select case (nb)
363  case (a3_neighb_lowx)
364  box%cc(0, 1:nc, 1:nc, iv) = &
365  c0 * box%cc(0, 1:nc, 1:nc, iv) + &
366  c1 * box%cc(1, 1:nc, 1:nc, iv) + &
367  c2 * box%cc(2, 1:nc, 1:nc, iv)
368  case (a3_neighb_highx)
369  box%cc(nc+1, 1:nc, 1:nc, iv) = &
370  c0 * box%cc(nc+1, 1:nc, 1:nc, iv) + &
371  c1 * box%cc(nc, 1:nc, 1:nc, iv) + &
372  c2 * box%cc(nc-1, 1:nc, 1:nc, iv)
373  case (a3_neighb_lowy)
374  box%cc(1:nc, 0, 1:nc, iv) = &
375  c0 * box%cc(1:nc, 0, 1:nc, iv) + &
376  c1 * box%cc(1:nc, 1, 1:nc, iv) + &
377  c2 * box%cc(1:nc, 2, 1:nc, iv)
378  case (a3_neighb_highy)
379  box%cc(1:nc, nc+1, 1:nc, iv) = &
380  c0 * box%cc(1:nc, nc+1, 1:nc, iv) + &
381  c1 * box%cc(1:nc, nc, 1:nc, iv) + &
382  c2 * box%cc(1:nc, nc-1, 1:nc, iv)
383  case (a3_neighb_lowz)
384  box%cc(1:nc, 1:nc, 0, iv) = &
385  c0 * box%cc(1:nc, 1:nc, 0, iv) + &
386  c1 * box%cc(1:nc, 1:nc, 1, iv) + &
387  c2 * box%cc(1:nc, 1:nc, 2, iv)
388  case (a3_neighb_highz)
389  box%cc(1:nc, 1:nc, nc+1, iv) = &
390  c0 * box%cc(1:nc, 1:nc, nc+1, iv) + &
391  c1 * box%cc(1:nc, 1:nc, nc, iv) + &
392  c2 * box%cc(1:nc, 1:nc, nc-1, iv)
393  end select
394  end subroutine bc_to_gc
395 
397  subroutine a3_gc_prolong_copy(boxes, id, nb, iv)
398  use m_a3_prolong, only: a3_prolong_copy
399  type(box3_t), intent(inout) :: boxes(:)
400  integer, intent(in) :: id
401  integer, intent(in) :: iv
402  integer, intent(in) :: nb
403  integer :: p_id, nb_dim, lo(3), hi(3)
404 
405  p_id = boxes(id)%parent
406  nb_dim = a3_neighb_dim(nb)
407  lo(:) = 1
408  hi(:) = boxes(id)%n_cell
409  lo(nb_dim) = a3_neighb_high_01(nb) * (boxes(id)%n_cell+1)
410  hi(nb_dim) = a3_neighb_high_01(nb) * (boxes(id)%n_cell+1)
411 
412  call a3_prolong_copy(boxes(p_id), boxes(id), iv, low=lo, high=hi)
413  end subroutine a3_gc_prolong_copy
414 
417  subroutine a3_gc_interp(boxes, id, nb, iv)
418  type(box3_t), intent(inout) :: boxes(:)
419  integer, intent(in) :: id
420  integer, intent(in) :: nb
421  integer, intent(in) :: iv
422  integer :: nc, ix, ix_c, ix_f, i, j
423  integer :: i_c1, i_c2, j_c1, j_c2, p_nb_id
424  integer :: p_id, ix_offset(3)
425  real(dp), parameter :: sixth=1/6.0_dp, third=1/3.0_dp
426  integer :: k_c1, k_c2, k
427 
428  nc = boxes(id)%n_cell
429  p_id = boxes(id)%parent
430  p_nb_id = boxes(p_id)%neighbors(nb)
431  ix_offset = a3_get_child_offset(boxes(id), nb)
432 
433  if (a3_neighb_low(nb)) then
434  ix = 0
435  ix_f = 1
436  ix_c = nc
437  else
438  ix = nc+1
439  ix_f = nc
440  ix_c = 1
441  end if
442 
443  select case (a3_neighb_dim(nb))
444  case (1)
445  do k = 1, nc
446  k_c1 = ix_offset(3) + ishft(k+1, -1) ! (k+1)/2
447  k_c2 = k_c1 + 1 - 2 * iand(k, 1) ! even: +1, odd: -1
448  do j = 1, nc
449  j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
450  j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
451  boxes(id)%cc(ix, j, k, iv) = &
452  third * boxes(p_nb_id)%cc(ix_c, j_c1, k_c1, iv) + &
453  sixth * boxes(p_nb_id)%cc(ix_c, j_c2, k_c1, iv) + &
454  sixth * boxes(p_nb_id)%cc(ix_c, j_c1, k_c2, iv) + &
455  third * boxes(id)%cc(ix_f, j, k, iv)
456  end do
457  end do
458  case (2)
459  do k = 1, nc
460  k_c1 = ix_offset(3) + ishft(k+1, -1) ! (k+1)/2
461  k_c2 = k_c1 + 1 - 2 * iand(k, 1) ! even: +1, odd: -1
462  do i = 1, nc
463  i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
464  i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
465  boxes(id)%cc(i, ix, k, iv) = &
466  third * boxes(p_nb_id)%cc(i_c1, ix_c, k_c1, iv) + &
467  sixth * boxes(p_nb_id)%cc(i_c2, ix_c, k_c1, iv) + &
468  sixth * boxes(p_nb_id)%cc(i_c1, ix_c, k_c2, iv) + &
469  third * boxes(id)%cc(i, ix_f, k, iv)
470  end do
471  end do
472  case (3)
473  do j = 1, nc
474  j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
475  j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
476  do i = 1, nc
477  i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
478  i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
479  boxes(id)%cc(i, j, ix, iv) = &
480  third * boxes(p_nb_id)%cc(i_c1, j_c1, ix_c, iv) + &
481  sixth * boxes(p_nb_id)%cc(i_c1, j_c2, ix_c, iv) + &
482  sixth * boxes(p_nb_id)%cc(i_c2, j_c1, ix_c, iv) + &
483  third * boxes(id)%cc(i, j, ix_f, iv)
484  end do
485  end do
486  end select
487 
488  end subroutine a3_gc_interp
489 
493  subroutine a3_gc_interp_lim(boxes, id, nb, iv)
494  type(box3_t), intent(inout) :: boxes(:)
495  integer, intent(in) :: id
496  integer, intent(in) :: nb
497  integer, intent(in) :: iv
498  integer :: nc, ix, ix_c, ix_f, i, j
499  integer :: i_c1, i_c2, j_c1, j_c2, p_nb_id
500  integer :: p_id, ix_offset(3)
501  real(dp) :: c1, c2
502  real(dp), parameter :: sixth=1/6.0_dp, third=1/3.0_dp
503  integer :: k_c1, k_c2, k
504  real(dp) :: c3
505 
506  nc = boxes(id)%n_cell
507  p_id = boxes(id)%parent
508  p_nb_id = boxes(p_id)%neighbors(nb)
509  ix_offset = a3_get_child_offset(boxes(id), nb)
510 
511  if (a3_neighb_low(nb)) then
512  ix = 0
513  ix_f = 1
514  ix_c = nc
515  else
516  ix = nc+1
517  ix_f = nc
518  ix_c = 1
519  end if
520 
521  select case (a3_neighb_dim(nb))
522  case (1)
523  do k = 1, nc
524  k_c1 = ix_offset(3) + ishft(k+1, -1) ! (k+1)/2
525  k_c2 = k_c1 + 1 - 2 * iand(k, 1) ! even: +1, odd: -1
526  do j = 1, nc
527  j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
528  j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
529  c1 = boxes(p_nb_id)%cc(ix_c, j_c1, k_c1, iv)
530  c2 = boxes(p_nb_id)%cc(ix_c, j_c2, k_c1, iv)
531  c3 = boxes(p_nb_id)%cc(ix_c, j_c1, k_c2, iv)
532  boxes(id)%cc(ix, j, k, iv) = third * c1 + sixth * c2 + &
533  sixth * c3 + third * boxes(id)%cc(ix_f, j, k, iv)
534  if (boxes(id)%cc(ix, j, k, iv) > 2 * c1) &
535  boxes(id)%cc(ix, j, k, iv) = 2 * c1
536  end do
537  end do
538  case (2)
539  do k = 1, nc
540  k_c1 = ix_offset(3) + ishft(k+1, -1) ! (k+1)/2
541  k_c2 = k_c1 + 1 - 2 * iand(k, 1) ! even: +1, odd: -1
542  do i = 1, nc
543  i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
544  i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
545  c1 = boxes(p_nb_id)%cc(i_c1, ix_c, k_c1, iv)
546  c2 = boxes(p_nb_id)%cc(i_c2, ix_c, k_c1, iv)
547  c3 = boxes(p_nb_id)%cc(i_c1, ix_c, k_c2, iv)
548  boxes(id)%cc(i, ix, k, iv) = third * c1 + sixth * c2 + &
549  sixth * c3 + third * boxes(id)%cc(i, ix_f, k, iv)
550  if (boxes(id)%cc(i, ix, k, iv) > 2 * c1) &
551  boxes(id)%cc(i, ix, k, iv) = 2 * c1
552  end do
553  end do
554  case (3)
555  do j = 1, nc
556  j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
557  j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
558  do i = 1, nc
559  i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
560  i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
561  c1 = boxes(p_nb_id)%cc(i_c1, j_c1, ix_c, iv)
562  c2 = boxes(p_nb_id)%cc(i_c1, j_c2, ix_c, iv)
563  c3 = boxes(p_nb_id)%cc(i_c2, j_c1, ix_c, iv)
564  boxes(id)%cc(i, j, ix, iv) = third * c1 + sixth * c2 + &
565  sixth * c3 + third * boxes(id)%cc(i, j, ix_f, iv)
566  if (boxes(id)%cc(i, j, ix, iv) > 2 * c1) &
567  boxes(id)%cc(i, j, ix, iv) = 2 * c1
568  end do
569  end do
570  end select
571 
572  end subroutine a3_gc_interp_lim
573 
574  ! This fills ghost cells near physical boundaries using Neumann zero
575  subroutine a3_bc_neumann_zero(box, nb, iv, bc_type)
576  type(box3_t), intent(inout) :: box
577  integer, intent(in) :: nb, iv
578  integer, intent(out) :: bc_type
579 
580  bc_type = af_bc_neumann
581  call a3_set_box_gc(box, nb, iv, 0.0_dp)
582  end subroutine a3_bc_neumann_zero
583 
584  ! This fills ghost cells near physical boundaries using Neumann zero
585  subroutine a3_bc_dirichlet_zero(box, nb, iv, bc_type)
586  type(box3_t), intent(inout) :: box
587  integer, intent(in) :: nb, iv
588  integer, intent(out) :: bc_type
589 
590  bc_type = af_bc_dirichlet
591  call a3_set_box_gc(box, nb, iv, 0.0_dp)
592  end subroutine a3_bc_dirichlet_zero
593 
594  ! This fills ghost cells near physical boundaries using the same slope
595  subroutine a3_bc_continuous(box, nb, iv, bc_type)
596  type(box3_t), intent(inout) :: box
597  integer, intent(in) :: nb, iv
598  integer, intent(out) :: bc_type
599 
600  bc_type = af_bc_continuous
601  ! Set values to zero (to prevent problems with NaN)
602  call a3_set_box_gc(box, nb, iv, 0.0_dp)
603  end subroutine a3_bc_continuous
604 
605  subroutine copy_from_nb(box, box_nb, dnb, lo, hi, iv)
606  type(box3_t), intent(inout) :: box
607  type(box3_t), intent(in) :: box_nb
608  integer, intent(in) :: dnb(3)
609  integer, intent(in) :: lo(3)
610  integer, intent(in) :: hi(3)
611  integer, intent(in) :: iv
612  integer :: nlo(3), nhi(3)
613 
614  ! Get indices on neighbor
615  nlo = lo - dnb * box%n_cell
616  nhi = hi - dnb * box%n_cell
617 
618  box%cc(lo(1):hi(1), lo(2):hi(2), lo(3):hi(3), iv) = &
619  box_nb%cc(nlo(1):nhi(1), nlo(2):nhi(2), nlo(3):nhi(3), iv)
620  end subroutine copy_from_nb
621 
625  subroutine a3_gc2_box(boxes, id, iv, subr_rb, subr_bc, cc, nc)
626  type(box3_t), intent(inout) :: boxes(:)
627  integer, intent(in) :: id
628  integer, intent(in) :: iv
629  procedure(a3_subr_egc) :: subr_rb
630  procedure(a3_subr_egc) :: subr_bc
631  integer, intent(in) :: nc
633  real(dp), intent(out) :: cc(-1:nc+2, -1:nc+2, -1:nc+2)
634  real(dp) :: gc(1:nc, 1:nc)
635  integer :: nb, nb_id, nb_dim, lo(3), hi(3)
636 
637  cc(0:nc+1, 0:nc+1, 0:nc+1) = boxes(id)%cc(0:nc+1, 0:nc+1, 0:nc+1, iv)
638 
639  do nb = 1, a3_num_neighbors
640  nb_id = boxes(id)%neighbors(nb)
641 
642  if (nb_id > af_no_box) then
643  call sides2_from_nb(boxes(nb_id), nb, iv, gc, nc)
644  else if (nb_id == af_no_box) then
645  call subr_rb(boxes, id, nb, iv, gc, nc)
646  else
647  call subr_bc(boxes, id, nb, iv, gc, nc)
648  end if
649 
650  ! Determine ghost cell indices
651  nb_dim = a3_neighb_dim(nb)
652  lo(:) = 1
653  hi(:) = boxes(id)%n_cell
654  lo(nb_dim) = -1 + a3_neighb_high_01(nb) * (boxes(id)%n_cell + 3)
655  hi(nb_dim) = lo(nb_dim)
656 
657  cc(lo(1):hi(1), lo(2):hi(2), lo(3):hi(3)) = reshape(gc, 1 + hi - lo)
658  end do
659  end subroutine a3_gc2_box
660 
662  subroutine sides2_from_nb(box_nb, nb, iv, gc_side, nc)
663  type(box3_t), intent(in) :: box_nb
664  integer, intent(in) :: nb
665  integer, intent(in) :: iv
666  integer, intent(in) :: nc
667  real(dp), intent(out) :: gc_side(nc, nc)
668 
669  select case (nb)
670  case (a3_neighb_lowx)
671  gc_side = box_nb%cc(nc-1, 1:nc, 1:nc, iv)
672  case (a3_neighb_highx)
673  gc_side = box_nb%cc(2, 1:nc, 1:nc, iv)
674  case (a3_neighb_lowy)
675  gc_side = box_nb%cc(1:nc, nc-1, 1:nc, iv)
676  case (a3_neighb_highy)
677  gc_side = box_nb%cc(1:nc, 2, 1:nc, iv)
678  case (a3_neighb_lowz)
679  gc_side = box_nb%cc(1:nc, 1:nc, nc-1, iv)
680  case (a3_neighb_highz)
681  gc_side = box_nb%cc(1:nc, 1:nc, 2, iv)
682  end select
683  end subroutine sides2_from_nb
684 
686  subroutine a3_gc2_prolong_linear(boxes, id, nb, iv, gc_side, nc)
687  type(box3_t), intent(inout) :: boxes(:)
688  integer, intent(in) :: id
689  integer, intent(in) :: nb
690  integer, intent(in) :: iv
691  integer, intent(in) :: nc
692  real(dp), intent(out) :: gc_side(nc, nc)
693  integer :: ix, i, j
694  integer :: i_c1, i_c2, j_c1, j_c2, p_nb_id
695  integer :: p_id, ix_offset(3)
696  integer :: k, k_c1, k_c2
697 
698  p_id = boxes(id)%parent
699  p_nb_id = boxes(p_id)%neighbors(nb)
700  ix_offset = a3_get_child_offset(boxes(id), nb)
701  ix = a3_neighb_high_01(nb) * (nc+3) - 1 ! -1 or nc+2
702 
703  select case (a3_neighb_dim(nb))
704  case (1)
705  i_c1 = ix_offset(1) + ishft(ix+1, -1) ! (ix+1)/2
706  i_c2 = i_c1 + 1 - 2 * iand(ix, 1) ! even: +1, odd: -1
707  do k = 1, nc
708  k_c1 = ix_offset(3) + ishft(k+1, -1) ! (k+1)/2
709  k_c2 = k_c1 + 1 - 2 * iand(k, 1) ! even: +1, odd: -1
710  do j = 1, nc
711  j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
712  j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
713  gc_side(j, k) = &
714  0.25_dp * boxes(p_nb_id)%cc(i_c1, j_c1, k_c1, iv) + &
715  0.25_dp * boxes(p_nb_id)%cc(i_c2, j_c1, k_c1, iv) + &
716  0.25_dp * boxes(p_nb_id)%cc(i_c1, j_c2, k_c1, iv) + &
717  0.25_dp * boxes(p_nb_id)%cc(i_c1, j_c1, k_c2, iv)
718  end do
719  end do
720  case (2)
721  j_c1 = ix_offset(2) + ishft(ix+1, -1) ! (j+1)/2
722  j_c2 = j_c1 + 1 - 2 * iand(ix, 1) ! even: +1, odd: -1
723  do k = 1, nc
724  k_c1 = ix_offset(3) + ishft(k+1, -1) ! (k+1)/2
725  k_c2 = k_c1 + 1 - 2 * iand(k, 1) ! even: +1, odd: -1
726  do i = 1, nc
727  i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
728  i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
729  gc_side(i, k) = &
730  0.25_dp * boxes(p_nb_id)%cc(i_c1, j_c1, k_c1, iv) + &
731  0.25_dp * boxes(p_nb_id)%cc(i_c2, j_c1, k_c1, iv) + &
732  0.25_dp * boxes(p_nb_id)%cc(i_c1, j_c2, k_c1, iv) + &
733  0.25_dp * boxes(p_nb_id)%cc(i_c1, j_c1, k_c2, iv)
734  end do
735  end do
736  case (3)
737  k_c1 = ix_offset(3) + ishft(ix+1, -1) ! (k+1)/2
738  k_c2 = k_c1 + 1 - 2 * iand(ix, 1) ! even: +1, odd: -1
739  do j = 1, nc
740  j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
741  j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
742  do i = 1, nc
743  i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
744  i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
745  gc_side(i, j) = &
746  0.25_dp * boxes(p_nb_id)%cc(i_c1, j_c1, k_c1, iv) + &
747  0.25_dp * boxes(p_nb_id)%cc(i_c2, j_c1, k_c1, iv) + &
748  0.25_dp * boxes(p_nb_id)%cc(i_c1, j_c2, k_c1, iv) + &
749  0.25_dp * boxes(p_nb_id)%cc(i_c1, j_c1, k_c2, iv)
750  end do
751  end do
752  end select
753 
754  end subroutine a3_gc2_prolong_linear
755 
756  ! This fills second ghost cells near physical boundaries using Neumann zero
757  subroutine a3_bc2_neumann_zero(boxes, id, nb, iv, gc_side, nc)
758  type(box3_t), intent(inout) :: boxes(:)
759  integer, intent(in) :: id
760  integer, intent(in) :: nb
761  integer, intent(in) :: iv
762  integer, intent(in) :: nc
763  real(dp), intent(out) :: gc_side(nc, nc)
764 
765  select case (nb)
766  case (a3_neighb_lowx)
767  gc_side = boxes(id)%cc(2, 1:nc, 1:nc, iv)
768  case (a3_neighb_highx)
769  gc_side = boxes(id)%cc(nc-1, 1:nc, 1:nc, iv)
770  case (a3_neighb_lowy)
771  gc_side = boxes(id)%cc(1:nc, 2, 1:nc, iv)
772  case (a3_neighb_highy)
773  gc_side = boxes(id)%cc(1:nc, nc-1, 1:nc, iv)
774  case (a3_neighb_lowz)
775  gc_side = boxes(id)%cc(1:nc, 1:nc, 2, iv)
776  case (a3_neighb_highz)
777  gc_side = boxes(id)%cc(1:nc, 1:nc, nc-1, iv)
778  end select
779  end subroutine a3_bc2_neumann_zero
780 
781  ! This fills second ghost cells near physical boundaries using Neumann zero
782  subroutine a3_bc2_dirichlet_zero(boxes, id, nb, iv, gc_side, nc)
783  type(box3_t), intent(inout) :: boxes(:)
784  integer, intent(in) :: id, nb, iv, nc
785  real(dp), intent(out) :: gc_side(nc, nc)
786 
787  select case (nb)
788  case (a3_neighb_lowx)
789  gc_side = -boxes(id)%cc(2, 1:nc, 1:nc, iv)
790  case (a3_neighb_highx)
791  gc_side = -boxes(id)%cc(nc-1, 1:nc, 1:nc, iv)
792  case (a3_neighb_lowy)
793  gc_side = -boxes(id)%cc(1:nc, 2, 1:nc, iv)
794  case (a3_neighb_highy)
795  gc_side = -boxes(id)%cc(1:nc, nc-1, 1:nc, iv)
796  case (a3_neighb_lowz)
797  gc_side = -boxes(id)%cc(1:nc, 1:nc, 2, iv)
798  case (a3_neighb_highz)
799  gc_side = -boxes(id)%cc(1:nc, 1:nc, nc-1, iv)
800  end select
801  end subroutine a3_bc2_dirichlet_zero
802 
805  subroutine a3_corner_gc_extrap(box, ix, iv)
806  type(box3_t), intent(inout) :: box
807  integer, intent(in) :: ix(3)
808  integer, intent(in) :: iv
809  integer :: di(3)
810 
811  di = 1 - 2 * iand(ix, 1) ! 0 -> di = 1, nc+1 -> di = -1
812 
813  box%cc(ix(1), ix(2), ix(3), iv) = &
814  box%cc(ix(1), ix(2)+di(2), ix(3)+di(3), iv) + &
815  box%cc(ix(1)+di(1), ix(2), ix(3)+di(3), iv) + &
816  box%cc(ix(1)+di(1), ix(2)+di(2), ix(3), iv) - 2 * &
817  box%cc(ix(1)+di(1), ix(2)+di(2), ix(3)+di(3), iv)
818  end subroutine a3_corner_gc_extrap
819 
823  subroutine a3_edge_gc_extrap(box, lo, dim, iv)
824  type(box3_t), intent(inout) :: box
825  integer, intent(in) :: lo(3)
826  integer, intent(in) :: dim
827  integer, intent(in) :: iv
828  integer :: di(3), ix(3), ia(3), ib(3), ic(3)
829  integer :: n, o_dims(3-1)
830 
831  ! Dimensions other than/perpendicular to dim
832  o_dims = [1 + mod(dim, 3), 1 + mod(dim + 1, 3)]
833 
834  ! Index offsets
835  di = 1 - 2 * iand(lo, 1) ! 0 -> di = 1, nc+1 -> di = -1
836  di(dim) = 0
837 
838  ! Neighbor index in direction one
839  ia = lo
840  ia(o_dims(1)) = ia(o_dims(1)) + di(o_dims(1))
841 
842  ! Neighbor index in direction two
843  ib = lo
844  ib(o_dims(2)) = ib(o_dims(2)) + di(o_dims(2))
845 
846  ! Diagional neighbor index
847  ic = lo + di
848  ix = lo
849 
850  do n = 1, box%n_cell
851  ia(dim) = n
852  ib(dim) = n
853  ic(dim) = n
854  ix(dim) = n
855 
856  box%cc(ix(1), ix(2), ix(3), iv) = &
857  box%cc(ia(1), ia(2), ia(3), iv) + &
858  box%cc(ib(1), ib(2), ib(3), iv) - &
859  box%cc(ic(1), ic(2), ic(3), iv)
860  end do
861 
862  end subroutine a3_edge_gc_extrap
863 
864 end module m_a3_ghostcell
To fill ghost cells near physical boundaries.
Definition: m_a3_types.f90:216
Subroutine for getting extra ghost cell data (> 1) near physical boundaries.
Definition: m_a3_types.f90:225
The basic building block of afivo: a box with cell-centered and face centered data, and information about its position, neighbors, children etc.
Definition: m_a3_types.f90:109
Type which stores all the boxes and levels, as well as some information about the number of boxes...
Definition: m_a3_types.f90:131
To fill ghost cells near refinement boundaries.
Definition: m_a3_types.f90:207
This module contains the routines related to prolongation: going from coarse to fine variables...
Definition: m_a3_prolong.f90:4
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...
Definition: m_a3_types.f90:5