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
20 public :: a2_gc2_prolong_linear
21 public :: a2_bc2_neumann_zero
22 public :: a2_bc2_dirichlet_zero
27 module procedure a2_gc_tree_iv, a2_gc_tree_ivs
28 end interface a2_gc_tree
31 module procedure a2_gc_ids_iv, a2_gc_ids_ivs, a2_gc_ids_v1
32 end interface a2_gc_ids
35 module procedure a2_gc_box_iv, a2_gc_box_ivs, a2_gc_box_v1
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(:)
47 logical,
intent(in),
optional :: corners
48 logical,
intent(in),
optional :: leaves_only
52 if (.not. tree%ready) error stop
"a2_gc_tree: tree not ready" 54 if (
present(leaves_only)) all_ids = .not. leaves_only
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)
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)
67 end subroutine a2_gc_tree_ivs
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
76 logical,
intent(in),
optional :: corners
77 logical,
intent(in),
optional :: leaves_only
81 if (.not. tree%ready) error stop
"a2_gc_tree: tree not ready" 83 if (
present(leaves_only)) all_ids = .not. leaves_only
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)
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)
96 end subroutine a2_gc_tree_iv
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(:)
107 logical,
intent(in),
optional :: corners
112 call a2_gc_box(tree, ids(i), ivs, subr_rb, subr_bc, corners)
115 end subroutine a2_gc_ids_ivs
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
126 logical,
intent(in),
optional :: corners
131 call a2_gc_box(tree, ids(i), iv, subr_rb, subr_bc, corners)
134 end subroutine a2_gc_ids_iv
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
145 logical,
intent(in),
optional :: corners
150 call a2_gc_box(boxes, ids(i), iv, subr_rb, subr_bc, corners)
153 end subroutine a2_gc_ids_v1
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(:)
162 logical,
intent(in),
optional :: corners
163 logical :: do_corners
169 if (
present(corners)) do_corners = corners
174 if (
present(subr_rb))
then 176 else if (tree%has_cc_method(iv))
then 177 use_rb => tree%cc_methods(iv)%rb
179 error stop
"a2_gc_box: no refinement boundary method stored" 182 if (
present(subr_bc))
then 184 else if (tree%has_cc_method(iv))
then 185 use_bc => tree%cc_methods(iv)%bc
187 error stop
"a2_gc_box: no boundary condition stored" 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)
193 end subroutine a2_gc_box_ivs
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
202 logical,
intent(in),
optional :: corners
203 logical :: do_corners
207 if (
present(subr_rb))
then 209 else if (tree%has_cc_method(iv))
then 210 use_rb => tree%cc_methods(iv)%rb
212 error stop
"a2_gc_box: no refinement boundary method stored" 215 if (
present(subr_bc))
then 217 else if (tree%has_cc_method(iv))
then 218 use_bc => tree%cc_methods(iv)%bc
220 error stop
"a2_gc_box: no boundary condition stored" 224 if (
present(corners)) do_corners = corners
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
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
237 logical,
intent(in),
optional :: corners
238 logical :: do_corners
241 if (
present(corners)) do_corners = corners
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
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
255 integer :: nb, nb_id, bc_type
256 integer :: nb_dim, lo(2), hi(2), dnb(2)
258 do nb = 1, a2_num_neighbors
259 nb_id = boxes(id)%neighbors(nb)
261 if (nb_id > af_no_box)
then 263 nb_dim = a2_neighb_dim(nb)
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 272 call subr_rb(boxes, id, nb, iv)
275 call subr_bc(boxes(id), nb, iv, bc_type)
276 call bc_to_gc(boxes(id), nb, iv, bc_type)
280 end subroutine a2_gc_box_sides
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)
291 do n = 1, a2_num_children
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)
297 if (nb_id > af_no_box)
then 298 call copy_from_nb(boxes(id), boxes(nb_id), dnb, lo, lo, iv)
300 call a2_corner_gc_extrap(boxes(id), lo, iv)
303 end subroutine a2_gc_box_corner
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
323 select case (bc_type)
324 case (af_bc_dirichlet)
329 c0 = box%dr * a2_neighb_high_pm(nb)
332 case (af_bc_continuous)
337 stop
"fill_bc: unknown boundary condition" 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)
362 end subroutine bc_to_gc
365 subroutine a2_gc_prolong_copy(boxes, id, nb, iv)
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)
373 p_id = boxes(id)%parent
374 nb_dim = a2_neighb_dim(nb)
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)
380 call a2_prolong_copy(boxes(p_id), boxes(id), iv, low=lo, high=hi)
381 end subroutine a2_gc_prolong_copy
385 subroutine a2_gc_interp(boxes, id, nb, iv)
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
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)
400 if (a2_neighb_low(nb))
then 410 select case (a2_neighb_dim(nb))
413 j_c1 = ix_offset(2) + ishft(j+1, -1)
414 j_c2 = j_c1 + 1 - 2 * iand(j, 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)
422 i_c1 = ix_offset(1) + ishft(i+1, -1)
423 i_c2 = i_c1 + 1 - 2 * iand(i, 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)
431 end subroutine a2_gc_interp
436 subroutine a2_gc_interp_lim(boxes, id, nb, iv)
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)
445 real(dp),
parameter :: sixth=1/6.0_dp, third=1/3.0_dp
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)
452 if (a2_neighb_low(nb))
then 462 select case (a2_neighb_dim(nb))
465 j_c1 = ix_offset(2) + ishft(j+1, -1)
466 j_c2 = j_c1 + 1 - 2 * iand(j, 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
475 i_c1 = ix_offset(1) + ishft(i+1, -1)
476 i_c2 = i_c1 + 1 - 2 * iand(i, 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
485 end subroutine a2_gc_interp_lim
488 subroutine a2_bc_neumann_zero(box, nb, iv, bc_type)
490 integer,
intent(in) :: nb, iv
491 integer,
intent(out) :: bc_type
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
498 subroutine a2_bc_dirichlet_zero(box, nb, iv, bc_type)
500 integer,
intent(in) :: nb, iv
501 integer,
intent(out) :: bc_type
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
508 subroutine a2_bc_continuous(box, nb, iv, bc_type)
510 integer,
intent(in) :: nb, iv
511 integer,
intent(out) :: bc_type
513 bc_type = af_bc_continuous
515 call a2_set_box_gc(box, nb, iv, 0.0_dp)
516 end subroutine a2_bc_continuous
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)
528 nlo = lo - dnb * box%n_cell
529 nhi = hi - dnb * box%n_cell
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
538 subroutine a2_gc2_box(boxes, id, iv, subr_rb, subr_bc, cc, nc)
540 integer,
intent(in) :: id
541 integer,
intent(in) :: iv
544 integer,
intent(in) :: nc
546 real(dp),
intent(out) :: cc(-1:nc+2, -1:nc+2)
548 integer :: nb, nb_id, nb_dim, lo(2), hi(2)
550 cc(0:nc+1, 0:nc+1) = boxes(id)%cc(0:nc+1, 0:nc+1, iv)
552 do nb = 1, a2_num_neighbors
553 nb_id = boxes(id)%neighbors(nb)
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)
560 call subr_bc(boxes, id, nb, iv, gc, nc)
564 nb_dim = a2_neighb_dim(nb)
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)
570 cc(lo(1):hi(1), lo(2):hi(2)) = reshape(gc, 1 + hi - lo)
572 end subroutine a2_gc2_box
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)
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)
592 end subroutine sides2_from_nb
595 subroutine a2_gc2_prolong_linear(boxes, id, nb, iv, gc_side, nc)
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)
603 integer :: i_c1, i_c2, j_c1, j_c2, p_nb_id
604 integer :: p_id, ix_offset(2)
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
611 select case (a2_neighb_dim(nb))
613 i_c1 = ix_offset(1) + ishft(ix+1, -1)
614 i_c2 = i_c1 + 1 - 2 * iand(ix, 1)
616 j_c1 = ix_offset(2) + ishft(j+1, -1)
617 j_c2 = j_c1 + 1 - 2 * iand(j, 1)
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)
624 j_c1 = ix_offset(2) + ishft(ix+1, -1)
625 j_c2 = j_c1 + 1 - 2 * iand(ix, 1)
627 i_c1 = ix_offset(1) + ishft(i+1, -1)
628 i_c2 = i_c1 + 1 - 2 * iand(i, 1)
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)
636 end subroutine a2_gc2_prolong_linear
639 subroutine a2_bc2_neumann_zero(boxes, id, nb, iv, gc_side, nc)
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)
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)
657 end subroutine a2_bc2_neumann_zero
660 subroutine a2_bc2_dirichlet_zero(boxes, id, nb, iv, gc_side, nc)
662 integer,
intent(in) :: id, nb, iv, nc
663 real(dp),
intent(out) :: gc_side(nc)
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)
675 end subroutine a2_bc2_dirichlet_zero
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
685 di = 1 - 2 * iand(ix, 1)
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
Subroutine for getting extra ghost cell data (> 1) near physical boundaries.
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...
This module contains the basic types and constants that are used in the 2-dimensional version of Afiv...
To fill ghost cells near physical boundaries.
This module contains the routines related to prolongation: going from coarse to fine variables...
To fill ghost cells near refinement boundaries.
The basic building block of afivo: a box with cell-centered and face centered data, and information about its position, neighbors, children etc.