Afivo  0.3
m_a2_ghostcell.f90
1 
5  use m_a2_types
6 
7  implicit none
8  private
9 
10  public :: a2_gc_tree
11  public :: a2_gc_ids
12  public :: a2_gc_box
13  public :: a2_bc_dirichlet_zero
14  public :: a2_bc_neumann_zero
15  public :: a2_bc_continuous
16  public :: a2_gc_interp
17  public :: a2_gc_prolong_copy
18  public :: a2_gc_interp_lim
19  public :: a2_gc2_box
20  public :: a2_gc2_prolong_linear
21  public :: a2_bc2_neumann_zero
22  public :: a2_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 a2_gc_tree
27  module procedure a2_gc_tree_iv, a2_gc_tree_ivs
28  end interface a2_gc_tree
29 
30  interface a2_gc_ids
31  module procedure a2_gc_ids_iv, a2_gc_ids_ivs, a2_gc_ids_v1
32  end interface a2_gc_ids
33 
34  interface a2_gc_box
35  module procedure a2_gc_box_iv, a2_gc_box_ivs, a2_gc_box_v1
36  end interface
37 
38 contains
39 
42  subroutine a2_gc_tree_ivs(tree, ivs, subr_rb, subr_bc, corners, leaves_only)
43  type(a2_t), intent(inout) :: tree
44  integer, intent(in) :: ivs(:)
45  procedure(a2_subr_rb), optional :: subr_rb
46  procedure(a2_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 "a2_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 a2_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 a2_gc_ids(tree, tree%lvls(lvl)%leaves, ivs, &
64  subr_rb, subr_bc, corners)
65  end do
66  end if
67  end subroutine a2_gc_tree_ivs
68 
71  subroutine a2_gc_tree_iv(tree, iv, subr_rb, subr_bc, corners, leaves_only)
72  type(a2_t), intent(inout) :: tree
73  integer, intent(in) :: iv
74  procedure(a2_subr_rb), optional :: subr_rb
75  procedure(a2_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 "a2_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 a2_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 a2_gc_ids(tree, tree%lvls(lvl)%leaves, iv, &
93  subr_rb, subr_bc, corners)
94  end do
95  end if
96  end subroutine a2_gc_tree_iv
97 
101  subroutine a2_gc_ids_ivs(tree, ids, ivs, subr_rb, subr_bc, corners)
102  type(a2_t), intent(inout) :: tree
103  integer, intent(in) :: ids(:)
104  integer, intent(in) :: ivs(:)
105  procedure(a2_subr_rb), optional :: subr_rb
106  procedure(a2_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 a2_gc_box(tree, ids(i), ivs, subr_rb, subr_bc, corners)
113  end do
114  !$omp end parallel do
115  end subroutine a2_gc_ids_ivs
116 
120  subroutine a2_gc_ids_iv(tree, ids, iv, subr_rb, subr_bc, corners)
121  type(a2_t), intent(inout) :: tree
122  integer, intent(in) :: ids(:)
123  integer, intent(in) :: iv
124  procedure(a2_subr_rb), optional :: subr_rb
125  procedure(a2_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 a2_gc_box(tree, ids(i), iv, subr_rb, subr_bc, corners)
132  end do
133  !$omp end parallel do
134  end subroutine a2_gc_ids_iv
135 
139  subroutine a2_gc_ids_v1(boxes, ids, iv, subr_rb, subr_bc, corners)
140  type(box2_t), intent(inout) :: boxes(:)
141  integer, intent(in) :: ids(:)
142  integer, intent(in) :: iv
143  procedure(a2_subr_rb), optional :: subr_rb
144  procedure(a2_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 a2_gc_box(boxes, ids(i), iv, subr_rb, subr_bc, corners)
151  end do
152  !$omp end parallel do
153  end subroutine a2_gc_ids_v1
154 
156  subroutine a2_gc_box_ivs(tree, id, ivs, subr_rb, subr_bc, corners)
157  type(a2_t), intent(inout) :: tree
158  integer, intent(in) :: id
159  integer, intent(in) :: ivs(:)
160  procedure(a2_subr_rb), optional :: subr_rb
161  procedure(a2_subr_bc), optional :: subr_bc
162  logical, intent(in), optional :: corners
163  logical :: do_corners
164  integer :: i, iv
165  procedure(a2_subr_rb), pointer :: use_rb
166  procedure(a2_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 "a2_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 "a2_gc_box: no boundary condition stored"
188  end if
189 
190  call a2_gc_box_sides(tree%boxes, id, iv, use_rb, use_bc)
191  if (do_corners) call a2_gc_box_corner(tree%boxes, id, iv)
192  end do
193  end subroutine a2_gc_box_ivs
194 
196  subroutine a2_gc_box_iv(tree, id, iv, subr_rb, subr_bc, corners)
197  type(a2_t), intent(inout) :: tree
198  integer, intent(in) :: id
199  integer, intent(in) :: iv
200  procedure(a2_subr_rb), optional :: subr_rb
201  procedure(a2_subr_bc), optional :: subr_bc
202  logical, intent(in), optional :: corners
203  logical :: do_corners
204  procedure(a2_subr_rb), pointer :: use_rb
205  procedure(a2_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 "a2_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 "a2_gc_box: no boundary condition stored"
221  end if
222 
223  do_corners = .true.
224  if (present(corners)) do_corners = corners
225 
226  call a2_gc_box_sides(tree%boxes, id, iv, use_rb, use_bc)
227  if (do_corners) call a2_gc_box_corner(tree%boxes, id, iv)
228  end subroutine a2_gc_box_iv
229 
231  subroutine a2_gc_box_v1(boxes, id, iv, subr_rb, subr_bc, corners)
232  type(box2_t), intent(inout) :: boxes(:)
233  integer, intent(in) :: id
234  integer, intent(in) :: iv
235  procedure(a2_subr_rb) :: subr_rb
236  procedure(a2_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 a2_gc_box_sides(boxes, id, iv, subr_rb, subr_bc)
244  if (do_corners) call a2_gc_box_corner(boxes, id, iv)
245  end subroutine a2_gc_box_v1
246 
249  subroutine a2_gc_box_sides(boxes, id, iv, subr_rb, subr_bc)
250  type(box2_t), intent(inout) :: boxes(:)
251  integer, intent(in) :: id
252  integer, intent(in) :: iv
253  procedure(a2_subr_rb) :: subr_rb
254  procedure(a2_subr_bc) :: subr_bc
255  integer :: nb, nb_id, bc_type
256  integer :: nb_dim, lo(2), hi(2), dnb(2)
257 
258  do nb = 1, a2_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 = a2_neighb_dim(nb)
264  lo(:) = 1
265  hi(:) = boxes(id)%n_cell
266  lo(nb_dim) = a2_neighb_high_01(nb) * (boxes(id)%n_cell + 1)
267  hi(nb_dim) = lo(nb_dim)
268  dnb = a2_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 a2_gc_box_sides
281 
285  subroutine a2_gc_box_corner(boxes, id, iv)
286  type(box2_t), intent(inout) :: boxes(:)
287  integer, intent(in) :: id
288  integer, intent(in) :: iv
289  integer :: n, nb_id, dnb(2), lo(2)
290 
291  do n = 1, a2_num_children
292  ! Check whether there is a neighbor, and find its index
293  dnb = 2 * a2_child_dix(:, n) - 1
294  nb_id = boxes(id)%neighbor_mat(dnb(1), dnb(2))
295  lo = a2_child_dix(:, n) * (boxes(id)%n_cell + 1)
296 
297  if (nb_id > af_no_box) then
298  call copy_from_nb(boxes(id), boxes(nb_id), dnb, lo, lo, iv)
299  else
300  call a2_corner_gc_extrap(boxes(id), lo, iv)
301  end if
302  end do
303  end subroutine a2_gc_box_corner
304 
305  subroutine bc_to_gc(box, nb, iv, bc_type)
306  type(box2_t), intent(inout) :: box
307  integer, intent(in) :: iv
308  integer, intent(in) :: nb
309  integer, intent(in) :: bc_type
310  real(dp) :: c0, c1, c2
311  integer :: nc
312 
313  nc = box%n_cell
314 
315  ! If we call the interior point x1, x2 and the ghost point x0, then a
316  ! Dirichlet boundary value b can be imposed as:
317  ! x0 = -x1 + 2*b
318  ! A Neumann b.c. can be imposed as:
319  ! x0 = x1 +/- dx * b
320  ! A continuous boundary (same slope) as:
321  ! x0 = 2 * x1 - x2
322  ! Below, we set coefficients to handle these cases
323  select case (bc_type)
324  case (af_bc_dirichlet)
325  c0 = 2
326  c1 = -1
327  c2 = 0
328  case (af_bc_neumann)
329  c0 = box%dr * a2_neighb_high_pm(nb) ! This gives a + or - sign
330  c1 = 1
331  c2 = 0
332  case (af_bc_continuous)
333  c0 = 0
334  c1 = 2
335  c2 = -1
336  case default
337  stop "fill_bc: unknown boundary condition"
338  end select
339 
340  select case (nb)
341  case (a2_neighb_lowx)
342  box%cc(0, 1:nc, iv) = &
343  c0 * box%cc(0, 1:nc, iv) + &
344  c1 * box%cc(1, 1:nc, iv) + &
345  c2 * box%cc(2, 1:nc, iv)
346  case (a2_neighb_highx)
347  box%cc(nc+1, 1:nc, iv) = &
348  c0 * box%cc(nc+1, 1:nc, iv) + &
349  c1 * box%cc(nc, 1:nc, iv) + &
350  c2 * box%cc(nc-1, 1:nc, iv)
351  case (a2_neighb_lowy)
352  box%cc(1:nc, 0, iv) = &
353  c0 * box%cc(1:nc, 0, iv) + &
354  c1 * box%cc(1:nc, 1, iv) + &
355  c2 * box%cc(1:nc, 2, iv)
356  case (a2_neighb_highy)
357  box%cc(1:nc, nc+1, iv) = &
358  c0 * box%cc(1:nc, nc+1, iv) + &
359  c1 * box%cc(1:nc, nc, iv) + &
360  c2 * box%cc(1:nc, nc-1, iv)
361  end select
362  end subroutine bc_to_gc
363 
365  subroutine a2_gc_prolong_copy(boxes, id, nb, iv)
366  use m_a2_prolong, only: a2_prolong_copy
367  type(box2_t), intent(inout) :: boxes(:)
368  integer, intent(in) :: id
369  integer, intent(in) :: iv
370  integer, intent(in) :: nb
371  integer :: p_id, nb_dim, lo(2), hi(2)
372 
373  p_id = boxes(id)%parent
374  nb_dim = a2_neighb_dim(nb)
375  lo(:) = 1
376  hi(:) = boxes(id)%n_cell
377  lo(nb_dim) = a2_neighb_high_01(nb) * (boxes(id)%n_cell+1)
378  hi(nb_dim) = a2_neighb_high_01(nb) * (boxes(id)%n_cell+1)
379 
380  call a2_prolong_copy(boxes(p_id), boxes(id), iv, low=lo, high=hi)
381  end subroutine a2_gc_prolong_copy
382 
385  subroutine a2_gc_interp(boxes, id, nb, iv)
386  type(box2_t), intent(inout) :: boxes(:)
387  integer, intent(in) :: id
388  integer, intent(in) :: nb
389  integer, intent(in) :: iv
390  integer :: nc, ix, ix_c, ix_f, i, j
391  integer :: i_c1, i_c2, j_c1, j_c2, p_nb_id
392  integer :: p_id, ix_offset(2)
393  real(dp), parameter :: sixth=1/6.0_dp, third=1/3.0_dp
394 
395  nc = boxes(id)%n_cell
396  p_id = boxes(id)%parent
397  p_nb_id = boxes(p_id)%neighbors(nb)
398  ix_offset = a2_get_child_offset(boxes(id), nb)
399 
400  if (a2_neighb_low(nb)) then
401  ix = 0
402  ix_f = 1
403  ix_c = nc
404  else
405  ix = nc+1
406  ix_f = nc
407  ix_c = 1
408  end if
409 
410  select case (a2_neighb_dim(nb))
411  case (1)
412  do j = 1, nc
413  j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
414  j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
415  boxes(id)%cc(ix, j, iv) = &
416  0.5_dp * boxes(p_nb_id)%cc(ix_c, j_c1, iv) + &
417  sixth * boxes(p_nb_id)%cc(ix_c, j_c2, iv) + &
418  third * boxes(id)%cc(ix_f, j, iv)
419  end do
420  case (2)
421  do i = 1, nc
422  i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
423  i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
424  boxes(id)%cc(i, ix, iv) = &
425  0.5_dp * boxes(p_nb_id)%cc(i_c1, ix_c, iv) + &
426  sixth * boxes(p_nb_id)%cc(i_c2, ix_c, iv) + &
427  third * boxes(id)%cc(i, ix_f, iv)
428  end do
429  end select
430 
431  end subroutine a2_gc_interp
432 
436  subroutine a2_gc_interp_lim(boxes, id, nb, iv)
437  type(box2_t), intent(inout) :: boxes(:)
438  integer, intent(in) :: id
439  integer, intent(in) :: nb
440  integer, intent(in) :: iv
441  integer :: nc, ix, ix_c, ix_f, i, j
442  integer :: i_c1, i_c2, j_c1, j_c2, p_nb_id
443  integer :: p_id, ix_offset(2)
444  real(dp) :: c1, c2
445  real(dp), parameter :: sixth=1/6.0_dp, third=1/3.0_dp
446 
447  nc = boxes(id)%n_cell
448  p_id = boxes(id)%parent
449  p_nb_id = boxes(p_id)%neighbors(nb)
450  ix_offset = a2_get_child_offset(boxes(id), nb)
451 
452  if (a2_neighb_low(nb)) then
453  ix = 0
454  ix_f = 1
455  ix_c = nc
456  else
457  ix = nc+1
458  ix_f = nc
459  ix_c = 1
460  end if
461 
462  select case (a2_neighb_dim(nb))
463  case (1)
464  do j = 1, nc
465  j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
466  j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
467  c1 = boxes(p_nb_id)%cc(ix_c, j_c1, iv)
468  c2 = boxes(p_nb_id)%cc(ix_c, j_c2, iv)
469  boxes(id)%cc(ix, j, iv) = 0.5_dp * c1 + sixth * c2 + &
470  third * boxes(id)%cc(ix_f, j, iv)
471  if (boxes(id)%cc(ix, j, iv) > 2 * c1) boxes(id)%cc(ix, j, iv) = 2 * c1
472  end do
473  case (2)
474  do i = 1, nc
475  i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
476  i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
477  c1 = boxes(p_nb_id)%cc(i_c1, ix_c, iv)
478  c2 = boxes(p_nb_id)%cc(i_c2, ix_c, iv)
479  boxes(id)%cc(i, ix, iv) = 0.5_dp * c1 + sixth * c2 + &
480  third * boxes(id)%cc(i, ix_f, iv)
481  if (boxes(id)%cc(i, ix, iv) > 2 * c1) boxes(id)%cc(i, ix, iv) = 2 * c1
482  end do
483  end select
484 
485  end subroutine a2_gc_interp_lim
486 
487  ! This fills ghost cells near physical boundaries using Neumann zero
488  subroutine a2_bc_neumann_zero(box, nb, iv, bc_type)
489  type(box2_t), intent(inout) :: box
490  integer, intent(in) :: nb, iv
491  integer, intent(out) :: bc_type
492 
493  bc_type = af_bc_neumann
494  call a2_set_box_gc(box, nb, iv, 0.0_dp)
495  end subroutine a2_bc_neumann_zero
496 
497  ! This fills ghost cells near physical boundaries using Neumann zero
498  subroutine a2_bc_dirichlet_zero(box, nb, iv, bc_type)
499  type(box2_t), intent(inout) :: box
500  integer, intent(in) :: nb, iv
501  integer, intent(out) :: bc_type
502 
503  bc_type = af_bc_dirichlet
504  call a2_set_box_gc(box, nb, iv, 0.0_dp)
505  end subroutine a2_bc_dirichlet_zero
506 
507  ! This fills ghost cells near physical boundaries using the same slope
508  subroutine a2_bc_continuous(box, nb, iv, bc_type)
509  type(box2_t), intent(inout) :: box
510  integer, intent(in) :: nb, iv
511  integer, intent(out) :: bc_type
512 
513  bc_type = af_bc_continuous
514  ! Set values to zero (to prevent problems with NaN)
515  call a2_set_box_gc(box, nb, iv, 0.0_dp)
516  end subroutine a2_bc_continuous
517 
518  subroutine copy_from_nb(box, box_nb, dnb, lo, hi, iv)
519  type(box2_t), intent(inout) :: box
520  type(box2_t), intent(in) :: box_nb
521  integer, intent(in) :: dnb(2)
522  integer, intent(in) :: lo(2)
523  integer, intent(in) :: hi(2)
524  integer, intent(in) :: iv
525  integer :: nlo(2), nhi(2)
526 
527  ! Get indices on neighbor
528  nlo = lo - dnb * box%n_cell
529  nhi = hi - dnb * box%n_cell
530 
531  box%cc(lo(1):hi(1), lo(2):hi(2), iv) = &
532  box_nb%cc(nlo(1):nhi(1), nlo(2):nhi(2), iv)
533  end subroutine copy_from_nb
534 
538  subroutine a2_gc2_box(boxes, id, iv, subr_rb, subr_bc, cc, nc)
539  type(box2_t), intent(inout) :: boxes(:)
540  integer, intent(in) :: id
541  integer, intent(in) :: iv
542  procedure(a2_subr_egc) :: subr_rb
543  procedure(a2_subr_egc) :: subr_bc
544  integer, intent(in) :: nc
546  real(dp), intent(out) :: cc(-1:nc+2, -1:nc+2)
547  real(dp) :: gc(1:nc)
548  integer :: nb, nb_id, nb_dim, lo(2), hi(2)
549 
550  cc(0:nc+1, 0:nc+1) = boxes(id)%cc(0:nc+1, 0:nc+1, iv)
551 
552  do nb = 1, a2_num_neighbors
553  nb_id = boxes(id)%neighbors(nb)
554 
555  if (nb_id > af_no_box) then
556  call sides2_from_nb(boxes(nb_id), nb, iv, gc, nc)
557  else if (nb_id == af_no_box) then
558  call subr_rb(boxes, id, nb, iv, gc, nc)
559  else
560  call subr_bc(boxes, id, nb, iv, gc, nc)
561  end if
562 
563  ! Determine ghost cell indices
564  nb_dim = a2_neighb_dim(nb)
565  lo(:) = 1
566  hi(:) = boxes(id)%n_cell
567  lo(nb_dim) = -1 + a2_neighb_high_01(nb) * (boxes(id)%n_cell + 3)
568  hi(nb_dim) = lo(nb_dim)
569 
570  cc(lo(1):hi(1), lo(2):hi(2)) = reshape(gc, 1 + hi - lo)
571  end do
572  end subroutine a2_gc2_box
573 
575  subroutine sides2_from_nb(box_nb, nb, iv, gc_side, nc)
576  type(box2_t), intent(in) :: box_nb
577  integer, intent(in) :: nb
578  integer, intent(in) :: iv
579  integer, intent(in) :: nc
580  real(dp), intent(out) :: gc_side(nc)
581 
582  select case (nb)
583  case (a2_neighb_lowx)
584  gc_side = box_nb%cc(nc-1, 1:nc, iv)
585  case (a2_neighb_highx)
586  gc_side = box_nb%cc(2, 1:nc, iv)
587  case (a2_neighb_lowy)
588  gc_side = box_nb%cc(1:nc, nc-1, iv)
589  case (a2_neighb_highy)
590  gc_side = box_nb%cc(1:nc, 2, iv)
591  end select
592  end subroutine sides2_from_nb
593 
595  subroutine a2_gc2_prolong_linear(boxes, id, nb, iv, gc_side, nc)
596  type(box2_t), intent(inout) :: boxes(:)
597  integer, intent(in) :: id
598  integer, intent(in) :: nb
599  integer, intent(in) :: iv
600  integer, intent(in) :: nc
601  real(dp), intent(out) :: gc_side(nc)
602  integer :: ix, i, j
603  integer :: i_c1, i_c2, j_c1, j_c2, p_nb_id
604  integer :: p_id, ix_offset(2)
605 
606  p_id = boxes(id)%parent
607  p_nb_id = boxes(p_id)%neighbors(nb)
608  ix_offset = a2_get_child_offset(boxes(id), nb)
609  ix = a2_neighb_high_01(nb) * (nc+3) - 1 ! -1 or nc+2
610 
611  select case (a2_neighb_dim(nb))
612  case (1)
613  i_c1 = ix_offset(1) + ishft(ix+1, -1) ! (ix+1)/2
614  i_c2 = i_c1 + 1 - 2 * iand(ix, 1) ! even: +1, odd: -1
615  do j = 1, nc
616  j_c1 = ix_offset(2) + ishft(j+1, -1) ! (j+1)/2
617  j_c2 = j_c1 + 1 - 2 * iand(j, 1) ! even: +1, odd: -1
618  gc_side(j) = &
619  0.5_dp * boxes(p_nb_id)%cc(i_c1, j_c1, iv) + &
620  0.25_dp * boxes(p_nb_id)%cc(i_c2, j_c1, iv) + &
621  0.25_dp * boxes(p_nb_id)%cc(i_c1, j_c2, iv)
622  end do
623  case (2)
624  j_c1 = ix_offset(2) + ishft(ix+1, -1) ! (j+1)/2
625  j_c2 = j_c1 + 1 - 2 * iand(ix, 1) ! even: +1, odd: -1
626  do i = 1, nc
627  i_c1 = ix_offset(1) + ishft(i+1, -1) ! (i+1)/2
628  i_c2 = i_c1 + 1 - 2 * iand(i, 1) ! even: +1, odd: -1
629  gc_side(i) = &
630  0.5_dp * boxes(p_nb_id)%cc(i_c1, j_c1, iv) + &
631  0.25_dp * boxes(p_nb_id)%cc(i_c2, j_c1, iv) + &
632  0.25_dp * boxes(p_nb_id)%cc(i_c1, j_c2, iv)
633  end do
634  end select
635 
636  end subroutine a2_gc2_prolong_linear
637 
638  ! This fills second ghost cells near physical boundaries using Neumann zero
639  subroutine a2_bc2_neumann_zero(boxes, id, nb, iv, gc_side, nc)
640  type(box2_t), intent(inout) :: boxes(:)
641  integer, intent(in) :: id
642  integer, intent(in) :: nb
643  integer, intent(in) :: iv
644  integer, intent(in) :: nc
645  real(dp), intent(out) :: gc_side(nc)
646 
647  select case (nb)
648  case (a2_neighb_lowx)
649  gc_side = boxes(id)%cc(2, 1:nc, iv)
650  case (a2_neighb_highx)
651  gc_side = boxes(id)%cc(nc-1, 1:nc, iv)
652  case (a2_neighb_lowy)
653  gc_side = boxes(id)%cc(1:nc, 2, iv)
654  case (a2_neighb_highy)
655  gc_side = boxes(id)%cc(1:nc, nc-1, iv)
656  end select
657  end subroutine a2_bc2_neumann_zero
658 
659  ! This fills second ghost cells near physical boundaries using Neumann zero
660  subroutine a2_bc2_dirichlet_zero(boxes, id, nb, iv, gc_side, nc)
661  type(box2_t), intent(inout) :: boxes(:)
662  integer, intent(in) :: id, nb, iv, nc
663  real(dp), intent(out) :: gc_side(nc)
664 
665  select case (nb)
666  case (a2_neighb_lowx)
667  gc_side = -boxes(id)%cc(2, 1:nc, iv)
668  case (a2_neighb_highx)
669  gc_side = -boxes(id)%cc(nc-1, 1:nc, iv)
670  case (a2_neighb_lowy)
671  gc_side = -boxes(id)%cc(1:nc, 2, iv)
672  case (a2_neighb_highy)
673  gc_side = -boxes(id)%cc(1:nc, nc-1, iv)
674  end select
675  end subroutine a2_bc2_dirichlet_zero
676 
679  subroutine a2_corner_gc_extrap(box, ix, iv)
680  type(box2_t), intent(inout) :: box
681  integer, intent(in) :: ix(2)
682  integer, intent(in) :: iv
683  integer :: di(2)
684 
685  di = 1 - 2 * iand(ix, 1) ! 0 -> di = 1, nc+1 -> di = -1
686 
687  box%cc(ix(1), ix(2), iv) = box%cc(ix(1)+di(1), ix(2), iv) &
688  + box%cc(ix(1), ix(2)+di(2), iv) &
689  - box%cc(ix(1)+di(1), ix(2)+di(2), iv)
690  end subroutine a2_corner_gc_extrap
691 
692 end module m_a2_ghostcell
Subroutine for getting extra ghost cell data (> 1) near physical boundaries.
Definition: m_a2_types.f90:186
This module contains routines related to the filling of ghost cells. Note that corner ghost cells are...
Type which stores all the boxes and levels, as well as some information about the number of boxes...
Definition: m_a2_types.f90:93
This module contains the basic types and constants that are used in the 2-dimensional version of Afiv...
Definition: m_a2_types.f90:5
To fill ghost cells near physical boundaries.
Definition: m_a2_types.f90:177
This module contains the routines related to prolongation: going from coarse to fine variables...
Definition: m_a2_prolong.f90:4
To fill ghost cells near refinement boundaries.
Definition: m_a2_types.f90:168
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_a2_types.f90:71