11 integer,
parameter,
public :: mg_normal_box = 1
12 integer,
parameter,
public :: mg_lsf_box = 2
13 integer,
parameter,
public :: mg_ceps_box = 3
14 integer,
parameter,
public :: mg_veps_box = 4
17 integer,
parameter :: mg_cycle_down = 1
18 integer,
parameter :: mg_cycle_base = 2
19 integer,
parameter :: mg_cycle_up = 3
29 integer :: i_bval = -1
31 integer :: n_cycle_down = -1
32 integer :: n_cycle_up = -1
33 integer :: n_cycle_base = -1
35 logical :: initialized = .false.
36 logical :: use_corners = .false.
37 logical :: subtract_mean = .false.
40 procedure(
a3_subr_bc),
pointer,
nopass :: sides_bc => null()
43 procedure(
a3_subr_rb),
pointer,
nopass :: sides_rb => null()
46 procedure(
mg3_box_op),
pointer,
nopass :: box_op => null()
49 procedure(mg3_box_gsrb),
pointer,
nopass :: box_gsrb => null()
52 procedure(mg3_box_corr),
pointer,
nopass :: box_corr => null()
55 procedure(mg3_box_rstr),
pointer,
nopass :: box_rstr => null()
62 type(
box3_t),
intent(inout) :: box
63 type(
mg3_t),
intent(in) :: mg
64 integer,
intent(in) :: i_out
68 subroutine mg3_box_gsrb(box, redblack_cntr, mg)
70 type(
box3_t),
intent(inout) :: box
71 type(
mg3_t),
intent(in) :: mg
72 integer,
intent(in) :: redblack_cntr
73 end subroutine mg3_box_gsrb
75 subroutine mg3_box_corr(box_p, box_c, mg)
77 type(
box3_t),
intent(inout) :: box_c
78 type(
box3_t),
intent(in) :: box_p
79 type(
mg3_t),
intent(in) :: mg
80 end subroutine mg3_box_corr
82 subroutine mg3_box_rstr(box_c, box_p, iv, mg)
84 type(
box3_t),
intent(in) :: box_c
85 type(
box3_t),
intent(inout) :: box_p
86 integer,
intent(in) :: iv
87 type(
mg3_t),
intent(in) :: mg
88 end subroutine mg3_box_rstr
93 public :: mg3_fas_vcycle
95 public :: mg3_box_gsrb
96 public :: mg3_box_corr
97 public :: mg3_box_rstr
100 public :: mg3_set_box_tag
101 public :: mg3_auto_op
102 public :: mg3_auto_gsrb
103 public :: mg3_auto_corr
104 public :: mg3_auto_rstr
107 public :: mg3_box_lpl
108 public :: mg3_box_gsrb_lpl
109 public :: mg3_box_corr_lpl
110 public :: mg3_box_rstr_lpl
111 public :: mg3_sides_rb
114 public :: mg3_box_lpld
115 public :: mg3_box_gsrb_lpld
116 public :: mg3_box_corr_lpld
119 public :: mg3_box_lpllsf
120 public :: mg3_box_gsrb_lpllsf
121 public :: mg3_box_corr_lpllsf
122 public :: mg3_box_rstr_lpllsf
127 subroutine mg3_init_mg(mg)
130 if (mg%i_phi < 0) stop
"mg3_init_mg: i_phi not set" 131 if (mg%i_tmp < 0) stop
"mg3_init_mg: i_tmp not set" 132 if (mg%i_rhs < 0) stop
"mg3_init_mg: i_rhs not set" 133 if (mg%i_lsf * mg%i_bval < 0) &
134 stop
"mg3_init_mg: you have to set both i_lsf and i_bval" 136 if (.not.
associated(mg%sides_bc)) stop
"mg3_init_mg: sides_bc not set" 139 if (mg%n_cycle_down < 0) mg%n_cycle_down = 2
140 if (mg%n_cycle_up < 0) mg%n_cycle_up = 2
141 if (mg%n_cycle_base < 0) mg%n_cycle_base = 4
144 if (.not.
associated(mg%sides_rb)) mg%sides_rb => mg3_sides_rb
145 if (.not.
associated(mg%box_op)) mg%box_op => mg3_box_lpl
146 if (.not.
associated(mg%box_gsrb)) mg%box_gsrb => mg3_box_gsrb_lpl
147 if (.not.
associated(mg%box_corr)) mg%box_corr => mg3_box_corr_lpl
148 if (.not.
associated(mg%box_rstr)) mg%box_rstr => mg3_box_rstr_lpl
150 mg%initialized = .true.
151 end subroutine mg3_init_mg
153 subroutine check_mg(mg)
154 type(
mg3_t),
intent(in) :: mg
155 if (.not. mg%initialized) stop
"check_mg: you haven't called mg3_init_mg" 156 end subroutine check_mg
161 subroutine mg3_fas_fmg(tree, mg, set_residual, have_guess)
164 type(
a3_t),
intent(inout) :: tree
165 type(
mg3_t),
intent(in) :: mg
166 logical,
intent(in) :: set_residual
167 logical,
intent(in) :: have_guess
168 integer :: lvl, min_lvl
172 min_lvl = lbound(tree%lvls, 1)
175 do lvl = tree%highest_lvl, min_lvl+1, -1
177 call set_coarse_phi_rhs(tree, lvl, mg)
180 call init_phi_rhs(tree, mg)
183 do lvl = min_lvl, tree%highest_lvl
185 call a3_boxes_copy_cc(tree%boxes, tree%lvls(lvl)%ids, &
188 if (lvl > min_lvl)
then 191 call correct_children(tree%boxes, tree%lvls(lvl-1)%parents, mg)
194 call a3_gc_ids(tree, tree%lvls(lvl)%ids, mg%i_phi, &
195 mg%sides_rb, mg%sides_bc)
199 call mg3_fas_vcycle(tree, mg, &
200 set_residual .and. lvl == tree%highest_lvl, lvl)
202 end subroutine mg3_fas_fmg
207 subroutine mg3_fas_vcycle(tree, mg, set_residual, highest_lvl)
210 type(
a3_t),
intent(inout) :: tree
211 type(
mg3_t),
intent(in) :: mg
212 logical,
intent(in) :: set_residual
213 integer,
intent(in),
optional :: highest_lvl
214 integer :: lvl, min_lvl, i, id, max_lvl
215 real(dp) :: sum_phi, mean_phi
218 min_lvl = lbound(tree%lvls, 1)
219 max_lvl = tree%highest_lvl
220 if (
present(highest_lvl)) max_lvl = highest_lvl
222 do lvl = max_lvl, min_lvl+1, -1
224 call gsrb_boxes(tree, tree%lvls(lvl)%ids, mg, mg_cycle_down)
228 call update_coarse(tree, lvl, mg)
232 call gsrb_boxes(tree, tree%lvls(lvl)%ids, mg, mg_cycle_base)
235 do lvl = min_lvl+1, max_lvl
238 call correct_children(tree%boxes, tree%lvls(lvl-1)%parents, mg)
241 call a3_gc_ids(tree, tree%lvls(lvl)%ids, mg%i_phi, &
242 mg%sides_rb, mg%sides_bc)
245 call gsrb_boxes(tree, tree%lvls(lvl)%ids, mg, mg_cycle_up)
248 if (set_residual)
then 250 do lvl = min_lvl, max_lvl
252 do i = 1,
size(tree%lvls(lvl)%ids)
253 id = tree%lvls(lvl)%ids(i)
254 call residual_box(tree%boxes(id), mg)
263 if (mg%subtract_mean)
then 264 call a3_tree_sum_cc(tree, mg%i_phi, sum_phi)
265 mean_phi = sum_phi / a3_total_volume(tree)
267 do lvl = min_lvl, max_lvl
269 do i = 1,
size(tree%lvls(lvl)%ids)
270 id = tree%lvls(lvl)%ids(i)
271 tree%boxes(id)%cc(:, :, :, mg%i_phi) = &
272 tree%boxes(id)%cc(:, :, :, mg%i_phi) - mean_phi
279 end subroutine mg3_fas_vcycle
282 subroutine mg3_sides_rb(boxes, id, nb, iv)
284 type(
box3_t),
intent(inout) :: boxes(:)
285 integer,
intent(in) :: id
286 integer,
intent(in) :: nb
287 integer,
intent(in) :: iv
288 integer :: nc, ix, dix, i, di, j, dj, co(3)
289 integer :: hnc, p_id, p_nb_id
290 real(dp) :: grad(3-1)
292 real(dp) :: tmp(0:boxes(id)%n_cell/2+1, 0:boxes(id)%n_cell/2+1)
293 real(dp) :: gc(boxes(id)%n_cell, boxes(id)%n_cell)
295 nc = boxes(id)%n_cell
298 p_id = boxes(id)%parent
299 p_nb_id = boxes(p_id)%neighbors(nb)
300 co = a3_get_child_offset(boxes(id))
302 associate(box => boxes(p_nb_id))
305 case (a3_neighb_lowx)
306 tmp = box%cc(nc, co(2):co(2)+hnc+1, co(3):co(3)+hnc+1, iv)
307 case (a3_neighb_highx)
308 tmp = box%cc(1, co(2):co(2)+hnc+1, co(3):co(3)+hnc+1, iv)
309 case (a3_neighb_lowy)
310 tmp = box%cc(co(1):co(1)+hnc+1, nc, co(3):co(3)+hnc+1, iv)
311 case (a3_neighb_highy)
312 tmp = box%cc(co(1):co(1)+hnc+1, 1, co(3):co(3)+hnc+1, iv)
313 case (a3_neighb_lowz)
314 tmp = box%cc(co(1):co(1)+hnc+1, co(2):co(2)+hnc+1, nc, iv)
315 case (a3_neighb_highz)
316 tmp = box%cc(co(1):co(1)+hnc+1, co(2):co(2)+hnc+1, 1, iv)
324 grad(1) = 0.125_dp * (tmp(i+1, j) - tmp(i-1, j))
325 grad(2) = 0.125_dp * (tmp(i, j+1) - tmp(i, j-1))
326 gc(2*i-1, 2*j-1) = tmp(i, j) - grad(1) - grad(2)
327 gc(2*i, 2*j-1) = tmp(i, j) + grad(1) - grad(2)
328 gc(2*i-1, 2*j) = tmp(i, j) - grad(1) + grad(2)
329 gc(2*i, 2*j) = tmp(i, j) + grad(1) + grad(2)
333 if (a3_neighb_low(nb))
then 341 select case (a3_neighb_dim(nb))
346 dk = -1 + 2 * iand(k, 1)
348 dj = -1 + 2 * iand(j, 1)
349 boxes(id)%cc(i-di, j, k, iv) = &
350 0.5_dp * gc(j, k) + &
351 0.75_dp * boxes(id)%cc(i, j, k, iv) - &
352 0.25_dp * boxes(id)%cc(i+di, j, k, iv)
359 dk = -1 + 2 * iand(k, 1)
361 di = -1 + 2 * iand(i, 1)
362 boxes(id)%cc(i, j-dj, k, iv) = &
363 0.5_dp * gc(i, k) + &
364 0.75_dp * boxes(id)%cc(i, j, k, iv) - &
365 0.25_dp * boxes(id)%cc(i, j+dj, k, iv)
372 dj = -1 + 2 * iand(j, 1)
374 di = -1 + 2 * iand(i, 1)
375 boxes(id)%cc(i, j, k-dk, iv) = &
376 0.5_dp * gc(i, j) + &
377 0.75_dp * boxes(id)%cc(i, j, k, iv) - &
378 0.25_dp * boxes(id)%cc(i, j, k+dk, iv)
383 end subroutine mg3_sides_rb
390 subroutine mg3_sides_rb_old(boxes, id, nb, iv)
392 type(box3_t),
intent(inout) :: boxes(:)
393 integer,
intent(in) :: id
394 integer,
intent(in) :: nb
395 integer,
intent(in) :: iv
396 integer :: nc, ix, dix, i, di, j, dj
399 nc = boxes(id)%n_cell
401 if (a3_neighb_low(nb))
then 409 call a3_gc_prolong_copy(boxes, id, nb, iv)
411 select case (a3_neighb_dim(nb))
416 dk = -1 + 2 * iand(k, 1)
418 dj = -1 + 2 * iand(j, 1)
432 boxes(id)%cc(i-di, j, k, iv) = &
433 0.5_dp * boxes(id)%cc(i-di, j, k, iv) + &
434 0.75_dp * boxes(id)%cc(i, j, k, iv) - &
435 0.25_dp * boxes(id)%cc(i+di, j+dj, k+dk, iv)
442 dk = -1 + 2 * iand(k, 1)
444 di = -1 + 2 * iand(i, 1)
457 boxes(id)%cc(i, j-dj, k, iv) = &
458 0.5_dp * boxes(id)%cc(i, j-dj, k, iv) + &
459 0.75_dp * boxes(id)%cc(i, j, k, iv) - &
460 0.25_dp * boxes(id)%cc(i+di, j+dj, k+dk, iv)
467 dj = -1 + 2 * iand(j, 1)
469 di = -1 + 2 * iand(i, 1)
482 boxes(id)%cc(i, j, k-dk, iv) = &
483 0.5_dp * boxes(id)%cc(i, j, k-dk, iv) + &
484 0.75_dp * boxes(id)%cc(i, j, k, iv) - &
485 0.25_dp * boxes(id)%cc(i+di, j+dj, k+dk, iv)
490 end subroutine mg3_sides_rb_old
493 subroutine correct_children(boxes, ids, mg)
494 type(box3_t),
intent(inout) :: boxes(:)
495 integer,
intent(in) :: ids(:)
496 type(
mg3_t),
intent(in) :: mg
497 integer :: i, id, nc, i_c, c_id
502 nc = boxes(id)%n_cell
505 boxes(id)%cc(:, :, :, mg%i_tmp) = boxes(id)%cc(:, :, :, mg%i_phi) - &
506 boxes(id)%cc(:, :, :, mg%i_tmp)
508 do i_c = 1, a3_num_children
509 c_id = boxes(id)%children(i_c)
510 if (c_id == af_no_box) cycle
511 call mg%box_corr(boxes(id), boxes(c_id), mg)
515 end subroutine correct_children
517 subroutine gsrb_boxes(tree, ids, mg, type_cycle)
519 type(a3_t),
intent(inout) :: tree
520 type(
mg3_t),
intent(in) :: mg
521 integer,
intent(in) :: ids(:)
522 integer,
intent(in) :: type_cycle
523 integer :: n, i, n_cycle
524 logical :: use_corners
526 select case (type_cycle)
528 n_cycle = mg%n_cycle_down
530 n_cycle = mg%n_cycle_up
532 n_cycle = mg%n_cycle_base
534 error stop
"gsrb_boxes: invalid cycle type" 538 do n = 1, 2 * n_cycle
541 call mg%box_gsrb(tree%boxes(ids(i)), n, mg)
545 use_corners = mg%use_corners .or. &
546 (type_cycle /= mg_cycle_down .and. n == 2 * n_cycle)
550 call a3_gc_box(tree, ids(i), mg%i_phi, mg%sides_rb, &
551 mg%sides_bc, use_corners)
556 end subroutine gsrb_boxes
560 subroutine update_coarse(tree, lvl, mg)
561 use m_a3_utils, only: a3_n_cell, a3_box_add_cc, a3_box_copy_cc
563 type(a3_t),
intent(inout) :: tree
564 integer,
intent(in) :: lvl
565 type(
mg3_t),
intent(in) :: mg
566 integer :: i, id, p_id, nc
567 real(dp),
allocatable :: tmp(:,:,:)
569 id = tree%lvls(lvl)%ids(1)
570 nc = a3_n_cell(tree, lvl)
571 allocate(tmp(1:nc, 1:nc, 1:nc))
575 do i = 1,
size(tree%lvls(lvl)%ids)
576 id = tree%lvls(lvl)%ids(i)
577 p_id = tree%boxes(id)%parent
581 tmp = tree%boxes(id)%cc(1:nc, 1:nc, 1:nc, mg%i_tmp)
582 call residual_box(tree%boxes(id), mg)
583 call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_tmp, mg)
584 call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_phi, mg)
585 tree%boxes(id)%cc(1:nc, 1:nc, 1:nc, mg%i_tmp) = tmp
589 call a3_gc_ids(tree, tree%lvls(lvl-1)%ids, mg%i_phi, &
590 mg%sides_rb, mg%sides_bc)
596 do i = 1,
size(tree%lvls(lvl-1)%parents)
597 id = tree%lvls(lvl-1)%parents(i)
600 call mg%box_op(tree%boxes(id), mg%i_rhs, mg)
603 call a3_box_add_cc(tree%boxes(id), mg%i_tmp, mg%i_rhs)
606 call a3_box_copy_cc(tree%boxes(id), mg%i_phi, mg%i_tmp)
609 end subroutine update_coarse
613 subroutine set_coarse_phi_rhs(tree, lvl, mg)
616 type(a3_t),
intent(inout) :: tree
617 integer,
intent(in) :: lvl
618 type(
mg3_t),
intent(in) :: mg
619 integer :: i, id, p_id
622 if (lvl == tree%highest_lvl)
then 623 call a3_gc_ids(tree, tree%lvls(lvl)%ids, mg%i_phi, &
624 mg%sides_rb, mg%sides_bc)
628 do i = 1,
size(tree%lvls(lvl)%ids)
629 id = tree%lvls(lvl)%ids(i)
630 p_id = tree%boxes(id)%parent
632 call residual_box(tree%boxes(id), mg)
633 call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_tmp, mg)
634 call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_phi, mg)
638 call a3_gc_ids(tree, tree%lvls(lvl-1)%ids, mg%i_phi, &
639 mg%sides_rb, mg%sides_bc)
644 do i = 1,
size(tree%lvls(lvl-1)%parents)
645 id = tree%lvls(lvl-1)%parents(i)
646 call mg%box_op(tree%boxes(id), mg%i_rhs, mg)
647 call a3_box_add_cc(tree%boxes(id), mg%i_tmp, mg%i_rhs)
650 end subroutine set_coarse_phi_rhs
653 subroutine init_phi_rhs(tree, mg)
655 type(a3_t),
intent(inout) :: tree
656 type(
mg3_t),
intent(in) :: mg
657 integer :: i, id, p_id, lvl, min_lvl
660 min_lvl = lbound(tree%lvls, 1)
663 do lvl = tree%highest_lvl, min_lvl+1, -1
665 do i = 1,
size(tree%lvls(lvl)%ids)
666 id = tree%lvls(lvl)%ids(i)
667 call a3_box_clear_cc(tree%boxes(id), mg%i_phi)
668 if (lvl > min_lvl)
then 669 p_id = tree%boxes(id)%parent
670 call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_rhs, mg)
676 end subroutine init_phi_rhs
678 subroutine residual_box(box, mg)
679 type(box3_t),
intent(inout) :: box
680 type(
mg3_t),
intent(in) :: mg
683 call mg%box_op(box, mg%i_tmp, mg)
685 box%cc(1:nc, 1:nc, 1:nc, mg%i_tmp) = box%cc(1:nc, 1:nc, 1:nc, mg%i_rhs) &
686 - box%cc(1:nc, 1:nc, 1:nc, mg%i_tmp)
687 end subroutine residual_box
690 subroutine mg3_auto_gsrb(box, redblack_cntr, mg)
691 type(box3_t),
intent(inout) :: box
692 integer,
intent(in) :: redblack_cntr
693 type(
mg3_t),
intent(in) :: mg
695 if (box%tag == af_init_tag)
call mg3_set_box_tag(box, mg)
699 call mg3_box_gsrb_lpl(box, redblack_cntr, mg)
701 call mg3_box_gsrb_lpllsf(box, redblack_cntr, mg)
702 case (mg_veps_box, mg_ceps_box)
703 call mg3_box_gsrb_lpld(box, redblack_cntr, mg)
705 end subroutine mg3_auto_gsrb
708 subroutine mg3_auto_op(box, i_out, mg)
709 type(box3_t),
intent(inout) :: box
710 integer,
intent(in) :: i_out
711 type(
mg3_t),
intent(in) :: mg
713 if (box%tag == af_init_tag)
call mg3_set_box_tag(box, mg)
717 call mg3_box_lpl(box, i_out, mg)
719 call mg3_box_lpllsf(box, i_out, mg)
720 case (mg_veps_box, mg_ceps_box)
721 call mg3_box_lpld(box, i_out, mg)
723 end subroutine mg3_auto_op
726 subroutine mg3_auto_rstr(box_c, box_p, iv, mg)
727 type(box3_t),
intent(in) :: box_c
728 type(box3_t),
intent(inout) :: box_p
729 integer,
intent(in) :: iv
730 type(
mg3_t),
intent(in) :: mg
733 if (box_c%tag == af_init_tag) stop
"mg3_auto_rstr: box_c tag not set" 735 select case(box_c%tag)
736 case (mg_normal_box, mg_veps_box, mg_ceps_box)
737 call mg3_box_rstr_lpl(box_c, box_p, iv, mg)
739 call mg3_box_rstr_lpllsf(box_c, box_p, iv, mg)
741 end subroutine mg3_auto_rstr
744 subroutine mg3_auto_corr(box_p, box_c, mg)
745 type(box3_t),
intent(inout) :: box_c
746 type(box3_t),
intent(in) :: box_p
747 type(
mg3_t),
intent(in) :: mg
749 if (box_c%tag == af_init_tag)
call mg3_set_box_tag(box_c, mg)
751 select case(box_c%tag)
753 call mg3_box_corr_lpl(box_p, box_c, mg)
755 call mg3_box_corr_lpllsf(box_p, box_c, mg)
756 case (mg_veps_box, mg_ceps_box)
757 call mg3_box_corr_lpld(box_p, box_c, mg)
759 end subroutine mg3_auto_corr
761 subroutine mg3_set_box_tag(box, mg)
762 type(box3_t),
intent(inout) :: box
763 type(
mg3_t),
intent(in) :: mg
765 logical :: is_lsf, is_deps, is_eps
771 if (mg%i_lsf /= -1)
then 772 is_lsf = minval(box%cc(:, :, :, mg%i_lsf)) * &
773 maxval(box%cc(:, :, :, mg%i_lsf)) < 0
776 if (mg%i_eps /= -1)
then 777 a = minval(box%cc(:, :, :, mg%i_eps))
778 b = maxval(box%cc(:, :, :, mg%i_eps))
780 if (.not. is_deps) is_eps = (a < 1 .or. a > 1)
783 if (count([is_lsf, is_eps, is_deps]) > 1) &
784 stop
"mg3_set_box_tag: Cannot set lsf and eps tag for same box" 786 box%tag = mg_normal_box
787 if (is_lsf) box%tag = mg_lsf_box
788 if (is_eps) box%tag = mg_ceps_box
789 if (is_deps) box%tag = mg_veps_box
790 end subroutine mg3_set_box_tag
792 subroutine mg3_box_corr_lpl(box_p, box_c, mg)
794 type(box3_t),
intent(inout) :: box_c
795 type(box3_t),
intent(in) :: box_p
796 type(
mg3_t),
intent(in) :: mg
798 call a3_prolong_linear(box_p, box_c, mg%i_tmp, mg%i_phi, add=.true.)
799 end subroutine mg3_box_corr_lpl
802 subroutine mg3_box_gsrb_lpl(box, redblack_cntr, mg)
803 type(box3_t),
intent(inout) :: box
804 integer,
intent(in) :: redblack_cntr
805 type(
mg3_t),
intent(in) :: mg
806 integer :: i, i0, j, nc, i_phi, i_rhs
809 real(dp),
parameter :: sixth = 1/6.0_dp
820 i0 = 2 - iand(ieor(redblack_cntr, k+j), 1)
822 box%cc(i, j, k, i_phi) = sixth * ( &
823 box%cc(i+1, j, k, i_phi) + box%cc(i-1, j, k, i_phi) + &
824 box%cc(i, j+1, k, i_phi) + box%cc(i, j-1, k, i_phi) + &
825 box%cc(i, j, k+1, i_phi) + box%cc(i, j, k-1, i_phi) - &
826 dx2 * box%cc(i, j, k, i_rhs))
830 end subroutine mg3_box_gsrb_lpl
833 subroutine mg3_box_lpl(box, i_out, mg)
834 type(box3_t),
intent(inout) :: box
835 integer,
intent(in) :: i_out
836 type(
mg3_t),
intent(in) :: mg
837 integer :: i, j, nc, i_phi
838 real(dp) :: inv_dr_sq
842 inv_dr_sq = 1 / box%dr**2
848 box%cc(i, j, k, i_out) = inv_dr_sq * (box%cc(i-1, j, k, i_phi) + &
849 box%cc(i+1, j, k, i_phi) + box%cc(i, j-1, k, i_phi) + &
850 box%cc(i, j+1, k, i_phi) + box%cc(i, j, k-1, i_phi) + &
851 box%cc(i, j, k+1, i_phi) - 6 * box%cc(i, j, k, i_phi))
855 end subroutine mg3_box_lpl
858 subroutine mg3_box_rstr_lpl(box_c, box_p, iv, mg)
860 type(box3_t),
intent(in) :: box_c
861 type(box3_t),
intent(inout) :: box_p
862 integer,
intent(in) :: iv
863 type(
mg3_t),
intent(in) :: mg
867 call a3_restrict_box(box_c, box_p, iv, use_geometry=.false.)
868 end subroutine mg3_box_rstr_lpl
872 subroutine mg3_box_gsrb_lpld(box, redblack_cntr, mg)
873 type(box3_t),
intent(inout) :: box
874 integer,
intent(in) :: redblack_cntr
875 type(
mg3_t),
intent(in) :: mg
876 integer :: i, i0, j, nc, i_phi, i_eps, i_rhs
877 real(dp) :: dx2, u(2*3), a0, a(2*3), c(2*3)
890 i0 = 2 - iand(ieor(redblack_cntr, k+j), 1)
892 a0 = box%cc(i, j, k, i_eps)
893 u(1:2) = box%cc(i-1:i+1:2, j, k, i_phi)
894 a(1:2) = box%cc(i-1:i+1:2, j, k, i_eps)
895 u(3:4) = box%cc(i, j-1:j+1:2, k, i_phi)
896 a(3:4) = box%cc(i, j-1:j+1:2, k, i_eps)
897 u(5:6) = box%cc(i, j, k-1:k+1:2, i_phi)
898 a(5:6) = box%cc(i, j, k-1:k+1:2, i_eps)
899 c(:) = 2 * a0 * a(:) / (a0 + a(:))
901 box%cc(i, j, k, i_phi) = &
902 (sum(c(:) * u(:)) - dx2 * box%cc(i, j, k, i_rhs)) / sum(c(:))
906 end subroutine mg3_box_gsrb_lpld
909 subroutine mg3_box_lpld(box, i_out, mg)
910 type(box3_t),
intent(inout) :: box
911 integer,
intent(in) :: i_out
912 type(
mg3_t),
intent(in) :: mg
913 integer :: i, j, nc, i_phi, i_eps
914 real(dp) :: inv_dr_sq, a0, u0, u(2*3), a(2*3)
918 inv_dr_sq = 1 / box%dr**2
925 u0 = box%cc(i, j, k, i_phi)
926 a0 = box%cc(i, j, k, i_eps)
927 u(1:2) = box%cc(i-1:i+1:2, j, k, i_phi)
928 u(3:4) = box%cc(i, j-1:j+1:2, k, i_phi)
929 u(5:6) = box%cc(i, j, k-1:k+1:2, i_phi)
930 a(1:2) = box%cc(i-1:i+1:2, j, k, i_eps)
931 a(3:4) = box%cc(i, j-1:j+1:2, k, i_eps)
932 a(5:6) = box%cc(i, j, k-1:k+1:2, i_eps)
934 box%cc(i, j, k, i_out) = inv_dr_sq * 2 * &
935 sum(a0*a(:)/(a0 + a(:)) * (u(:) - u0))
940 end subroutine mg3_box_lpld
944 subroutine mg3_box_corr_lpld(box_p, box_c, mg)
945 type(box3_t),
intent(inout) :: box_c
946 type(box3_t),
intent(in) :: box_p
947 type(
mg3_t),
intent(in) :: mg
948 integer :: ix_offset(3), i_phi, i_corr, i_eps
949 integer :: nc, i, j, i_c1, i_c2, j_c1, j_c2
950 real(dp) :: u0, u(3), a0, a(3)
951 integer :: k, k_c1, k_c2
952 real(dp),
parameter :: third = 1/3.0_dp
955 ix_offset = a3_get_child_offset(box_c)
963 k_c1 = ix_offset(3) + ishft(k+1, -1)
964 k_c2 = k_c1 + 1 - 2 * iand(k, 1)
966 j_c1 = ix_offset(2) + ishft(j+1, -1)
967 j_c2 = j_c1 + 1 - 2 * iand(j, 1)
969 i_c1 = ix_offset(1) + ishft(i+1, -1)
970 i_c2 = i_c1 + 1 - 2 * iand(i, 1)
972 u0 = box_p%cc(i_c1, j_c1, k_c1, i_corr)
973 u(1) = box_p%cc(i_c2, j_c1, k_c1, i_corr)
974 u(2) = box_p%cc(i_c1, j_c2, k_c1, i_corr)
975 u(3) = box_p%cc(i_c1, j_c1, k_c2, i_corr)
976 a0 = box_p%cc(i_c1, j_c1, k_c1, i_eps)
977 a(1) = box_p%cc(i_c2, j_c1, k_c1, i_eps)
978 a(2) = box_p%cc(i_c1, j_c2, k_c1, i_eps)
979 a(3) = box_p%cc(i_c1, j_c1, k_c2, i_eps)
982 box_c%cc(i, j, k, i_phi) = box_c%cc(i, j, k, i_phi) + third * &
983 sum((a0*u0 + a(:) * (1.5_dp * u(:) - 0.5_dp * u0)) / &
988 end subroutine mg3_box_corr_lpld
994 subroutine lsf_dist_val(lsf_val_bval_a, lsf_val_bval_b, dist, val)
996 real(dp),
intent(in) :: lsf_val_bval_a(3)
998 real(dp),
intent(in) :: lsf_val_bval_b(3)
1000 real(dp),
intent(out) :: dist
1002 real(dp),
intent(out) :: val
1003 real(dp) :: lsf_a, lsf_b, bval_a, bval_b
1005 lsf_a = lsf_val_bval_a(1)
1006 lsf_b = lsf_val_bval_b(1)
1008 if (lsf_a * lsf_b < 0)
then 1010 dist = lsf_a / (lsf_a - lsf_b)
1011 bval_a = lsf_val_bval_a(3)
1012 bval_b = lsf_val_bval_b(3)
1015 val = bval_a * (1-dist) + bval_b * dist
1019 val = lsf_val_bval_b(2)
1021 end subroutine lsf_dist_val
1023 subroutine mg3_box_corr_lpllsf(box_p, box_c, mg)
1024 type(box3_t),
intent(inout) :: box_c
1025 type(box3_t),
intent(in) :: box_p
1026 type(
mg3_t),
intent(in) :: mg
1027 integer :: i_phi, i_corr, i_lsf, ix_offset(3)
1028 integer :: nc, i, j, i_c1, i_c2, j_c1, j_c2
1029 real(dp) :: v_a(3), v_b(3), val(3+1), dist(3+1), c(3+1)
1030 integer :: k, k_c1, k_c2
1033 ix_offset = a3_get_child_offset(box_c)
1041 k_c1 = ix_offset(3) + ishft(k+1, -1)
1042 k_c2 = k_c1 + 1 - 2 * iand(k, 1)
1044 j_c1 = ix_offset(2) + ishft(j+1, -1)
1045 j_c2 = j_c1 + 1 - 2 * iand(j, 1)
1047 i_c1 = ix_offset(1) + ishft(i+1, -1)
1048 i_c2 = i_c1 + 1 - 2 * iand(i, 1)
1050 v_a(1:2) = box_c%cc(i, j, k, [i_lsf, i_corr])
1053 v_b(1:2) = box_p%cc(i_c1, j_c1, k_c1, [i_lsf, i_corr])
1054 call lsf_dist_val(v_a, v_b, dist(1), val(1))
1055 v_b(1:2) = box_p%cc(i_c2, j_c1, k_c1, [i_lsf, i_corr])
1056 call lsf_dist_val(v_a, v_b, dist(2), val(2))
1057 v_b(1:2) = box_p%cc(i_c1, j_c2, k_c1, [i_lsf, i_corr])
1058 call lsf_dist_val(v_a, v_b, dist(3), val(3))
1059 v_b(1:2) = box_p%cc(i_c1, j_c1, k_c2, [i_lsf, i_corr])
1060 call lsf_dist_val(v_a, v_b, dist(4), val(4))
1064 c(1) = dist(2) * dist(3) * dist(4)
1065 c(2) = dist(1) * dist(3) * dist(4)
1066 c(3) = dist(1) * dist(2) * dist(4)
1067 c(4) = dist(1) * dist(2) * dist(3)
1068 box_c%cc(i, j, k, i_phi) = box_c%cc(i, j, k, i_phi) + &
1073 end subroutine mg3_box_corr_lpllsf
1076 subroutine mg3_box_gsrb_lpllsf(box, redblack_cntr, mg)
1077 type(box3_t),
intent(inout) :: box
1078 integer,
intent(in) :: redblack_cntr
1079 type(
mg3_t),
intent(in) :: mg
1080 integer :: i, i0, j, nc, i_phi, i_rhs, i_lsf, i_bval
1081 real(dp) :: dx2, dd(2*3), val(2*3), v_a(3), v_b(3)
1095 i0 = 2 - iand(ieor(redblack_cntr, k+j), 1)
1097 v_a = box%cc(i, j, k, [i_lsf, i_phi, i_bval])
1098 v_b = box%cc(i-1, j, k, [i_lsf, i_phi, i_bval])
1099 call lsf_dist_val(v_a, v_b, dd(1), val(1))
1100 v_b = box%cc(i+1, j, k, [i_lsf, i_phi, i_bval])
1101 call lsf_dist_val(v_a, v_b, dd(2), val(2))
1102 v_b = box%cc(i, j-1, k, [i_lsf, i_phi, i_bval])
1103 call lsf_dist_val(v_a, v_b, dd(3), val(3))
1104 v_b = box%cc(i, j+1, k, [i_lsf, i_phi, i_bval])
1105 call lsf_dist_val(v_a, v_b, dd(4), val(4))
1106 v_b = box%cc(i, j, k-1, [i_lsf, i_phi, i_bval])
1107 call lsf_dist_val(v_a, v_b, dd(5), val(5))
1108 v_b = box%cc(i, j, k+1, [i_lsf, i_phi, i_bval])
1109 call lsf_dist_val(v_a, v_b, dd(6), val(6))
1112 box%cc(i, j, k, i_phi) = 1 / (1/(dd(1)*dd(2)) + &
1113 1/(dd(3)*dd(4)) + 1/(dd(5)*dd(6))) * ( &
1114 (dd(2) * val(1) + dd(1) * val(2)) / &
1115 ((dd(1) + dd(2)) * dd(1) * dd(2)) + &
1116 (dd(4) * val(3) + dd(3) * val(4)) / &
1117 ((dd(3) + dd(4)) * dd(3) * dd(4)) + &
1118 (dd(6) * val(5) + dd(5) * val(6)) / &
1119 ((dd(5) + dd(6)) * dd(5) * dd(6)) - &
1120 0.5_dp * dx2 * box%cc(i, j, k, i_rhs))
1125 end subroutine mg3_box_gsrb_lpllsf
1128 subroutine mg3_box_lpllsf(box, i_out, mg)
1129 type(box3_t),
intent(inout) :: box
1130 integer,
intent(in) :: i_out
1131 type(
mg3_t),
intent(in) :: mg
1132 integer :: i, j, nc, i_phi, i_lsf, i_bval
1133 real(dp) :: inv_dr_sq, dd(2*3), val(2*3)
1134 real(dp) :: f0, v_a(3), v_b(3)
1138 inv_dr_sq = 1 / box%dr**2
1146 v_a = box%cc(i, j, k, [i_lsf, i_phi, i_bval])
1147 v_b = box%cc(i-1, j, k, [i_lsf, i_phi, i_bval])
1148 call lsf_dist_val(v_a, v_b, dd(1), val(1))
1149 v_b = box%cc(i+1, j, k, [i_lsf, i_phi, i_bval])
1150 call lsf_dist_val(v_a, v_b, dd(2), val(2))
1151 v_b = box%cc(i, j-1, k, [i_lsf, i_phi, i_bval])
1152 call lsf_dist_val(v_a, v_b, dd(3), val(3))
1153 v_b = box%cc(i, j+1, k, [i_lsf, i_phi, i_bval])
1154 call lsf_dist_val(v_a, v_b, dd(4), val(4))
1155 v_b = box%cc(i, j, k-1, [i_lsf, i_phi, i_bval])
1156 call lsf_dist_val(v_a, v_b, dd(5), val(5))
1157 v_b = box%cc(i, j, k+1, [i_lsf, i_phi, i_bval])
1158 call lsf_dist_val(v_a, v_b, dd(6), val(6))
1161 f0 = box%cc(i, j, k, i_phi)
1162 box%cc(i, j, k, i_out) = 2 * inv_dr_sq * ( &
1163 (dd(2) * val(1) + dd(1) * val(2) - (dd(1)+dd(2)) * f0) / &
1164 ((dd(1) + dd(2)) * dd(1) * dd(2)) + &
1165 (dd(4) * val(3) + dd(3) * val(4) - (dd(3)+dd(4)) * f0) / &
1166 ((dd(3) + dd(4)) * dd(3) * dd(4)) + &
1167 (dd(6) * val(5) + dd(5) * val(6) - (dd(5)+dd(6)) * f0) / &
1168 ((dd(5) + dd(6)) * dd(5) * dd(6)))
1172 end subroutine mg3_box_lpllsf
1175 subroutine mg3_box_rstr_lpllsf(box_c, box_p, iv, mg)
1176 type(box3_t),
intent(in) :: box_c
1177 type(box3_t),
intent(inout) :: box_p
1178 integer,
intent(in) :: iv
1179 type(
mg3_t),
intent(in) :: mg
1180 integer :: i, j, i_f, j_f, i_c, j_c
1181 integer :: hnc, ix_offset(3), n_ch
1182 logical :: child_mask(2, 2, 2)
1183 integer :: k, k_f, k_c
1185 hnc = ishft(box_c%n_cell, -1)
1186 ix_offset = a3_get_child_offset(box_c)
1189 k_c = ix_offset(3) + k
1192 j_c = ix_offset(2) + j
1195 i_c = ix_offset(1) + i
1198 child_mask = (box_p%cc(i_c, j_c, k_c, mg%i_lsf) * &
1199 box_c%cc(i_f:i_f+1, j_f:j_f+1, k_f:k_f+1, mg%i_lsf) > 0)
1200 n_ch = count(child_mask)
1202 if (n_ch < a3_num_children .and. n_ch > 0)
then 1203 box_p%cc(i_c, j_c, k_c, iv) = 1 / n_ch * &
1204 sum(box_c%cc(i_f:i_f+1, j_f:j_f+1, k_f:k_f+1, iv), &
1207 box_p%cc(i_c, j_c, k_c, iv) = 0.125_dp * &
1208 sum(box_c%cc(i_f:i_f+1, j_f:j_f+1, k_f:k_f+1, iv))
1213 end subroutine mg3_box_rstr_lpllsf
This module contains all kinds of different 'helper' routines for Afivo. If the number of routines fo...
Subroutine that performs A * cc(..., i_in) = cc(..., i_out)
This module contains the geometric multigrid routines that come with Afivo.
This module contains routines for restriction: going from fine to coarse variables.
To fill ghost cells near physical boundaries.
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...
Type to store multigrid options in.
To fill ghost cells near refinement boundaries.
This module contains the routines related to prolongation: going from coarse to fine variables...
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...