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(
a2_subr_bc),
pointer,
nopass :: sides_bc => null()
43 procedure(
a2_subr_rb),
pointer,
nopass :: sides_rb => null()
46 procedure(
mg2_box_op),
pointer,
nopass :: box_op => null()
49 procedure(mg2_box_gsrb),
pointer,
nopass :: box_gsrb => null()
52 procedure(mg2_box_corr),
pointer,
nopass :: box_corr => null()
55 procedure(mg2_box_rstr),
pointer,
nopass :: box_rstr => null()
62 type(
box2_t),
intent(inout) :: box
63 type(
mg2_t),
intent(in) :: mg
64 integer,
intent(in) :: i_out
68 subroutine mg2_box_gsrb(box, redblack_cntr, mg)
70 type(
box2_t),
intent(inout) :: box
71 type(
mg2_t),
intent(in) :: mg
72 integer,
intent(in) :: redblack_cntr
73 end subroutine mg2_box_gsrb
75 subroutine mg2_box_corr(box_p, box_c, mg)
77 type(
box2_t),
intent(inout) :: box_c
78 type(
box2_t),
intent(in) :: box_p
79 type(
mg2_t),
intent(in) :: mg
80 end subroutine mg2_box_corr
82 subroutine mg2_box_rstr(box_c, box_p, iv, mg)
84 type(
box2_t),
intent(in) :: box_c
85 type(
box2_t),
intent(inout) :: box_p
86 integer,
intent(in) :: iv
87 type(
mg2_t),
intent(in) :: mg
88 end subroutine mg2_box_rstr
93 public :: mg2_fas_vcycle
95 public :: mg2_box_gsrb
96 public :: mg2_box_corr
97 public :: mg2_box_rstr
100 public :: mg2_set_box_tag
101 public :: mg2_auto_op
102 public :: mg2_auto_gsrb
103 public :: mg2_auto_corr
104 public :: mg2_auto_rstr
107 public :: mg2_box_lpl
108 public :: mg2_box_gsrb_lpl
109 public :: mg2_box_corr_lpl
110 public :: mg2_box_rstr_lpl
111 public :: mg2_sides_rb
114 public :: mg2_box_lpld
115 public :: mg2_box_gsrb_lpld
116 public :: mg2_box_corr_lpld
119 public :: mg2_box_lpllsf
120 public :: mg2_box_gsrb_lpllsf
121 public :: mg2_box_corr_lpllsf
122 public :: mg2_box_rstr_lpllsf
124 public :: mg2_box_clpl
125 public :: mg2_box_gsrb_clpl
126 public :: mg2_box_clpld
127 public :: mg2_box_gsrb_clpld
132 subroutine mg2_init_mg(mg)
135 if (mg%i_phi < 0) stop
"mg2_init_mg: i_phi not set" 136 if (mg%i_tmp < 0) stop
"mg2_init_mg: i_tmp not set" 137 if (mg%i_rhs < 0) stop
"mg2_init_mg: i_rhs not set" 138 if (mg%i_lsf * mg%i_bval < 0) &
139 stop
"mg2_init_mg: you have to set both i_lsf and i_bval" 141 if (.not.
associated(mg%sides_bc)) stop
"mg2_init_mg: sides_bc not set" 144 if (mg%n_cycle_down < 0) mg%n_cycle_down = 2
145 if (mg%n_cycle_up < 0) mg%n_cycle_up = 2
146 if (mg%n_cycle_base < 0) mg%n_cycle_base = 4
149 if (.not.
associated(mg%sides_rb)) mg%sides_rb => mg2_sides_rb
150 if (.not.
associated(mg%box_op)) mg%box_op => mg2_box_lpl
151 if (.not.
associated(mg%box_gsrb)) mg%box_gsrb => mg2_box_gsrb_lpl
152 if (.not.
associated(mg%box_corr)) mg%box_corr => mg2_box_corr_lpl
153 if (.not.
associated(mg%box_rstr)) mg%box_rstr => mg2_box_rstr_lpl
155 mg%initialized = .true.
156 end subroutine mg2_init_mg
158 subroutine check_mg(mg)
159 type(
mg2_t),
intent(in) :: mg
160 if (.not. mg%initialized) stop
"check_mg: you haven't called mg2_init_mg" 161 end subroutine check_mg
166 subroutine mg2_fas_fmg(tree, mg, set_residual, have_guess)
169 type(
a2_t),
intent(inout) :: tree
170 type(
mg2_t),
intent(in) :: mg
171 logical,
intent(in) :: set_residual
172 logical,
intent(in) :: have_guess
173 integer :: lvl, min_lvl
177 min_lvl = lbound(tree%lvls, 1)
180 do lvl = tree%highest_lvl, min_lvl+1, -1
182 call set_coarse_phi_rhs(tree, lvl, mg)
185 call init_phi_rhs(tree, mg)
188 do lvl = min_lvl, tree%highest_lvl
190 call a2_boxes_copy_cc(tree%boxes, tree%lvls(lvl)%ids, &
193 if (lvl > min_lvl)
then 196 call correct_children(tree%boxes, tree%lvls(lvl-1)%parents, mg)
199 call a2_gc_ids(tree, tree%lvls(lvl)%ids, mg%i_phi, &
200 mg%sides_rb, mg%sides_bc)
204 call mg2_fas_vcycle(tree, mg, &
205 set_residual .and. lvl == tree%highest_lvl, lvl)
207 end subroutine mg2_fas_fmg
212 subroutine mg2_fas_vcycle(tree, mg, set_residual, highest_lvl)
215 type(
a2_t),
intent(inout) :: tree
216 type(
mg2_t),
intent(in) :: mg
217 logical,
intent(in) :: set_residual
218 integer,
intent(in),
optional :: highest_lvl
219 integer :: lvl, min_lvl, i, id, max_lvl
220 real(dp) :: sum_phi, mean_phi
223 min_lvl = lbound(tree%lvls, 1)
224 max_lvl = tree%highest_lvl
225 if (
present(highest_lvl)) max_lvl = highest_lvl
227 do lvl = max_lvl, min_lvl+1, -1
229 call gsrb_boxes(tree, tree%lvls(lvl)%ids, mg, mg_cycle_down)
233 call update_coarse(tree, lvl, mg)
237 call gsrb_boxes(tree, tree%lvls(lvl)%ids, mg, mg_cycle_base)
240 do lvl = min_lvl+1, max_lvl
243 call correct_children(tree%boxes, tree%lvls(lvl-1)%parents, mg)
246 call a2_gc_ids(tree, tree%lvls(lvl)%ids, mg%i_phi, &
247 mg%sides_rb, mg%sides_bc)
250 call gsrb_boxes(tree, tree%lvls(lvl)%ids, mg, mg_cycle_up)
253 if (set_residual)
then 255 do lvl = min_lvl, max_lvl
257 do i = 1,
size(tree%lvls(lvl)%ids)
258 id = tree%lvls(lvl)%ids(i)
259 call residual_box(tree%boxes(id), mg)
268 if (mg%subtract_mean)
then 269 call a2_tree_sum_cc(tree, mg%i_phi, sum_phi)
270 mean_phi = sum_phi / a2_total_volume(tree)
272 do lvl = min_lvl, max_lvl
274 do i = 1,
size(tree%lvls(lvl)%ids)
275 id = tree%lvls(lvl)%ids(i)
276 tree%boxes(id)%cc(:, :, mg%i_phi) = &
277 tree%boxes(id)%cc(:, :, mg%i_phi) - mean_phi
284 end subroutine mg2_fas_vcycle
287 subroutine mg2_sides_rb(boxes, id, nb, iv)
289 type(
box2_t),
intent(inout) :: boxes(:)
290 integer,
intent(in) :: id
291 integer,
intent(in) :: nb
292 integer,
intent(in) :: iv
293 integer :: nc, ix, dix, i, di, j, dj, co(2)
294 integer :: hnc, p_id, p_nb_id
295 real(dp) :: grad(2-1)
296 real(dp) :: tmp(0:boxes(id)%n_cell/2+1)
297 real(dp) :: gc(boxes(id)%n_cell)
299 nc = boxes(id)%n_cell
302 p_id = boxes(id)%parent
303 p_nb_id = boxes(p_id)%neighbors(nb)
304 co = a2_get_child_offset(boxes(id))
306 associate(box => boxes(p_nb_id))
309 case (a2_neighb_lowx)
310 tmp = box%cc(nc, co(2):co(2)+hnc+1, iv)
311 case (a2_neighb_highx)
312 tmp = box%cc(1, co(2):co(2)+hnc+1, iv)
313 case (a2_neighb_lowy)
314 tmp = box%cc(co(1):co(1)+hnc+1, nc, iv)
315 case (a2_neighb_highy)
316 tmp = box%cc(co(1):co(1)+hnc+1, 1, iv)
323 grad(1) = 0.125_dp * (tmp(i+1) - tmp(i-1))
324 gc(2*i-1) = tmp(i) - grad(1)
325 gc(2*i) = tmp(i) + grad(1)
328 if (a2_neighb_low(nb))
then 336 select case (a2_neighb_dim(nb))
341 dj = -1 + 2 * iand(j, 1)
342 boxes(id)%cc(i-di, j, iv) = 0.5_dp * gc(j) &
343 + 0.75_dp * boxes(id)%cc(i, j, iv) &
344 - 0.25_dp * boxes(id)%cc(i+di, j, iv)
350 di = -1 + 2 * iand(i, 1)
351 boxes(id)%cc(i, j-dj, iv) = 0.5_dp * gc(i) &
352 + 0.75_dp * boxes(id)%cc(i, j, iv) &
353 - 0.25_dp * boxes(id)%cc(i, j+dj, iv)
357 end subroutine mg2_sides_rb
364 subroutine mg2_sides_rb_old(boxes, id, nb, iv)
366 type(box2_t),
intent(inout) :: boxes(:)
367 integer,
intent(in) :: id
368 integer,
intent(in) :: nb
369 integer,
intent(in) :: iv
370 integer :: nc, ix, dix, i, di, j, dj
372 nc = boxes(id)%n_cell
374 if (a2_neighb_low(nb))
then 382 call a2_gc_prolong_copy(boxes, id, nb, iv)
384 select case (a2_neighb_dim(nb))
389 dj = -1 + 2 * iand(j, 1)
392 boxes(id)%cc(i-di, j, iv) = 0.5_dp * boxes(id)%cc(i-di, j, iv) + &
393 1.125_dp * boxes(id)%cc(i, j, iv) - 0.375_dp * &
394 (boxes(id)%cc(i+di, j, iv) + boxes(id)%cc(i, j+dj, iv)) &
395 + 0.125_dp * boxes(id)%cc(i+di, j+dj, iv)
411 di = -1 + 2 * iand(i, 1)
414 boxes(id)%cc(i, j-dj, iv) = 0.5_dp * boxes(id)%cc(i, j-dj, iv) + &
415 1.125_dp * boxes(id)%cc(i, j, iv) - 0.375_dp * &
416 (boxes(id)%cc(i+di, j, iv) + boxes(id)%cc(i, j+dj, iv)) &
417 + 0.125_dp * boxes(id)%cc(i+di, j+dj, iv)
426 end subroutine mg2_sides_rb_old
429 subroutine correct_children(boxes, ids, mg)
430 type(box2_t),
intent(inout) :: boxes(:)
431 integer,
intent(in) :: ids(:)
432 type(
mg2_t),
intent(in) :: mg
433 integer :: i, id, nc, i_c, c_id
438 nc = boxes(id)%n_cell
441 boxes(id)%cc(:, :, mg%i_tmp) = boxes(id)%cc(:, :, mg%i_phi) - &
442 boxes(id)%cc(:, :, mg%i_tmp)
444 do i_c = 1, a2_num_children
445 c_id = boxes(id)%children(i_c)
446 if (c_id == af_no_box) cycle
447 call mg%box_corr(boxes(id), boxes(c_id), mg)
451 end subroutine correct_children
453 subroutine gsrb_boxes(tree, ids, mg, type_cycle)
455 type(a2_t),
intent(inout) :: tree
456 type(
mg2_t),
intent(in) :: mg
457 integer,
intent(in) :: ids(:)
458 integer,
intent(in) :: type_cycle
459 integer :: n, i, n_cycle
460 logical :: use_corners
462 select case (type_cycle)
464 n_cycle = mg%n_cycle_down
466 n_cycle = mg%n_cycle_up
468 n_cycle = mg%n_cycle_base
470 error stop
"gsrb_boxes: invalid cycle type" 474 do n = 1, 2 * n_cycle
477 call mg%box_gsrb(tree%boxes(ids(i)), n, mg)
481 use_corners = mg%use_corners .or. &
482 (type_cycle /= mg_cycle_down .and. n == 2 * n_cycle)
486 call a2_gc_box(tree, ids(i), mg%i_phi, mg%sides_rb, &
487 mg%sides_bc, use_corners)
492 end subroutine gsrb_boxes
496 subroutine update_coarse(tree, lvl, mg)
497 use m_a2_utils, only: a2_n_cell, a2_box_add_cc, a2_box_copy_cc
499 type(a2_t),
intent(inout) :: tree
500 integer,
intent(in) :: lvl
501 type(
mg2_t),
intent(in) :: mg
502 integer :: i, id, p_id, nc
503 real(dp),
allocatable :: tmp(:,:)
505 id = tree%lvls(lvl)%ids(1)
506 nc = a2_n_cell(tree, lvl)
507 allocate(tmp(1:nc, 1:nc))
511 do i = 1,
size(tree%lvls(lvl)%ids)
512 id = tree%lvls(lvl)%ids(i)
513 p_id = tree%boxes(id)%parent
517 tmp = tree%boxes(id)%cc(1:nc, 1:nc, mg%i_tmp)
518 call residual_box(tree%boxes(id), mg)
519 call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_tmp, mg)
520 call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_phi, mg)
521 tree%boxes(id)%cc(1:nc, 1:nc, mg%i_tmp) = tmp
525 call a2_gc_ids(tree, tree%lvls(lvl-1)%ids, mg%i_phi, &
526 mg%sides_rb, mg%sides_bc)
532 do i = 1,
size(tree%lvls(lvl-1)%parents)
533 id = tree%lvls(lvl-1)%parents(i)
536 call mg%box_op(tree%boxes(id), mg%i_rhs, mg)
539 call a2_box_add_cc(tree%boxes(id), mg%i_tmp, mg%i_rhs)
542 call a2_box_copy_cc(tree%boxes(id), mg%i_phi, mg%i_tmp)
545 end subroutine update_coarse
549 subroutine set_coarse_phi_rhs(tree, lvl, mg)
552 type(a2_t),
intent(inout) :: tree
553 integer,
intent(in) :: lvl
554 type(
mg2_t),
intent(in) :: mg
555 integer :: i, id, p_id
558 if (lvl == tree%highest_lvl)
then 559 call a2_gc_ids(tree, tree%lvls(lvl)%ids, mg%i_phi, &
560 mg%sides_rb, mg%sides_bc)
564 do i = 1,
size(tree%lvls(lvl)%ids)
565 id = tree%lvls(lvl)%ids(i)
566 p_id = tree%boxes(id)%parent
568 call residual_box(tree%boxes(id), mg)
569 call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_tmp, mg)
570 call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_phi, mg)
574 call a2_gc_ids(tree, tree%lvls(lvl-1)%ids, mg%i_phi, &
575 mg%sides_rb, mg%sides_bc)
580 do i = 1,
size(tree%lvls(lvl-1)%parents)
581 id = tree%lvls(lvl-1)%parents(i)
582 call mg%box_op(tree%boxes(id), mg%i_rhs, mg)
583 call a2_box_add_cc(tree%boxes(id), mg%i_tmp, mg%i_rhs)
586 end subroutine set_coarse_phi_rhs
589 subroutine init_phi_rhs(tree, mg)
591 type(a2_t),
intent(inout) :: tree
592 type(
mg2_t),
intent(in) :: mg
593 integer :: i, id, p_id, lvl, min_lvl
596 min_lvl = lbound(tree%lvls, 1)
599 do lvl = tree%highest_lvl, min_lvl+1, -1
601 do i = 1,
size(tree%lvls(lvl)%ids)
602 id = tree%lvls(lvl)%ids(i)
603 call a2_box_clear_cc(tree%boxes(id), mg%i_phi)
604 if (lvl > min_lvl)
then 605 p_id = tree%boxes(id)%parent
606 call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_rhs, mg)
612 end subroutine init_phi_rhs
614 subroutine residual_box(box, mg)
615 type(box2_t),
intent(inout) :: box
616 type(
mg2_t),
intent(in) :: mg
619 call mg%box_op(box, mg%i_tmp, mg)
621 box%cc(1:nc, 1:nc, mg%i_tmp) = box%cc(1:nc, 1:nc, mg%i_rhs) &
622 - box%cc(1:nc, 1:nc, mg%i_tmp)
623 end subroutine residual_box
626 subroutine mg2_auto_gsrb(box, redblack_cntr, mg)
627 type(box2_t),
intent(inout) :: box
628 integer,
intent(in) :: redblack_cntr
629 type(
mg2_t),
intent(in) :: mg
631 if (box%tag == af_init_tag)
call mg2_set_box_tag(box, mg)
635 if (box%coord_t == af_cyl)
then 636 call mg2_box_gsrb_clpl(box, redblack_cntr, mg)
638 call mg2_box_gsrb_lpl(box, redblack_cntr, mg)
641 call mg2_box_gsrb_lpllsf(box, redblack_cntr, mg)
642 case (mg_veps_box, mg_ceps_box)
643 if (box%coord_t == af_cyl)
then 644 call mg2_box_gsrb_clpld(box, redblack_cntr, mg)
646 call mg2_box_gsrb_lpld(box, redblack_cntr, mg)
649 end subroutine mg2_auto_gsrb
652 subroutine mg2_auto_op(box, i_out, mg)
653 type(box2_t),
intent(inout) :: box
654 integer,
intent(in) :: i_out
655 type(
mg2_t),
intent(in) :: mg
657 if (box%tag == af_init_tag)
call mg2_set_box_tag(box, mg)
661 if (box%coord_t == af_cyl)
then 662 call mg2_box_clpl(box, i_out, mg)
664 call mg2_box_lpl(box, i_out, mg)
667 call mg2_box_lpllsf(box, i_out, mg)
668 case (mg_veps_box, mg_ceps_box)
669 if (box%coord_t == af_cyl)
then 670 call mg2_box_clpld(box, i_out, mg)
672 call mg2_box_lpld(box, i_out, mg)
675 end subroutine mg2_auto_op
678 subroutine mg2_auto_rstr(box_c, box_p, iv, mg)
679 type(box2_t),
intent(in) :: box_c
680 type(box2_t),
intent(inout) :: box_p
681 integer,
intent(in) :: iv
682 type(
mg2_t),
intent(in) :: mg
685 if (box_c%tag == af_init_tag) stop
"mg2_auto_rstr: box_c tag not set" 687 select case(box_c%tag)
688 case (mg_normal_box, mg_veps_box, mg_ceps_box)
689 call mg2_box_rstr_lpl(box_c, box_p, iv, mg)
691 call mg2_box_rstr_lpllsf(box_c, box_p, iv, mg)
693 end subroutine mg2_auto_rstr
696 subroutine mg2_auto_corr(box_p, box_c, mg)
697 type(box2_t),
intent(inout) :: box_c
698 type(box2_t),
intent(in) :: box_p
699 type(
mg2_t),
intent(in) :: mg
701 if (box_c%tag == af_init_tag)
call mg2_set_box_tag(box_c, mg)
703 select case(box_c%tag)
705 call mg2_box_corr_lpl(box_p, box_c, mg)
707 call mg2_box_corr_lpllsf(box_p, box_c, mg)
708 case (mg_veps_box, mg_ceps_box)
709 call mg2_box_corr_lpld(box_p, box_c, mg)
711 end subroutine mg2_auto_corr
713 subroutine mg2_set_box_tag(box, mg)
714 type(box2_t),
intent(inout) :: box
715 type(
mg2_t),
intent(in) :: mg
717 logical :: is_lsf, is_deps, is_eps
723 if (mg%i_lsf /= -1)
then 724 is_lsf = minval(box%cc(:, :, mg%i_lsf)) * &
725 maxval(box%cc(:, :, mg%i_lsf)) < 0
728 if (mg%i_eps /= -1)
then 729 a = minval(box%cc(:, :, mg%i_eps))
730 b = maxval(box%cc(:, :, mg%i_eps))
732 if (.not. is_deps) is_eps = (a < 1 .or. a > 1)
735 if (count([is_lsf, is_eps, is_deps]) > 1) &
736 stop
"mg2_set_box_tag: Cannot set lsf and eps tag for same box" 738 box%tag = mg_normal_box
739 if (is_lsf) box%tag = mg_lsf_box
740 if (is_eps) box%tag = mg_ceps_box
741 if (is_deps) box%tag = mg_veps_box
742 end subroutine mg2_set_box_tag
744 subroutine mg2_box_corr_lpl(box_p, box_c, mg)
746 type(box2_t),
intent(inout) :: box_c
747 type(box2_t),
intent(in) :: box_p
748 type(
mg2_t),
intent(in) :: mg
750 call a2_prolong_linear(box_p, box_c, mg%i_tmp, mg%i_phi, add=.true.)
751 end subroutine mg2_box_corr_lpl
754 subroutine mg2_box_gsrb_lpl(box, redblack_cntr, mg)
755 type(box2_t),
intent(inout) :: box
756 integer,
intent(in) :: redblack_cntr
757 type(
mg2_t),
intent(in) :: mg
758 integer :: i, i0, j, nc, i_phi, i_rhs
769 i0 = 2 - iand(ieor(redblack_cntr, j), 1)
771 box%cc(i, j, i_phi) = 0.25_dp * ( &
772 box%cc(i+1, j, i_phi) + box%cc(i-1, j, i_phi) + &
773 box%cc(i, j+1, i_phi) + box%cc(i, j-1, i_phi) - &
774 dx2 * box%cc(i, j, i_rhs))
777 end subroutine mg2_box_gsrb_lpl
780 subroutine mg2_box_lpl(box, i_out, mg)
781 type(box2_t),
intent(inout) :: box
782 integer,
intent(in) :: i_out
783 type(
mg2_t),
intent(in) :: mg
784 integer :: i, j, nc, i_phi
785 real(dp) :: inv_dr_sq
788 inv_dr_sq = 1 / box%dr**2
793 box%cc(i, j, i_out) = inv_dr_sq * (box%cc(i-1, j, i_phi) + &
794 box%cc(i+1, j, i_phi) + box%cc(i, j-1, i_phi) + &
795 box%cc(i, j+1, i_phi) - 4 * box%cc(i, j, i_phi))
798 end subroutine mg2_box_lpl
801 subroutine mg2_box_rstr_lpl(box_c, box_p, iv, mg)
803 type(box2_t),
intent(in) :: box_c
804 type(box2_t),
intent(inout) :: box_p
805 integer,
intent(in) :: iv
806 type(
mg2_t),
intent(in) :: mg
810 call a2_restrict_box(box_c, box_p, iv, use_geometry=.false.)
811 end subroutine mg2_box_rstr_lpl
815 subroutine mg2_box_gsrb_lpld(box, redblack_cntr, mg)
816 type(box2_t),
intent(inout) :: box
817 integer,
intent(in) :: redblack_cntr
818 type(
mg2_t),
intent(in) :: mg
819 integer :: i, i0, j, nc, i_phi, i_eps, i_rhs
820 real(dp) :: dx2, u(2*2), a0, a(2*2), c(2*2)
831 i0 = 2 - iand(ieor(redblack_cntr, j), 1)
833 a0 = box%cc(i, j, i_eps)
834 u(1:2) = box%cc(i-1:i+1:2, j, i_phi)
835 a(1:2) = box%cc(i-1:i+1:2, j, i_eps)
836 u(3:4) = box%cc(i, j-1:j+1:2, i_phi)
837 a(3:4) = box%cc(i, j-1:j+1:2, i_eps)
838 c(:) = 2 * a0 * a(:) / (a0 + a(:))
840 box%cc(i, j, i_phi) = &
841 (sum(c(:) * u(:)) - dx2 * box%cc(i, j, i_rhs)) / sum(c(:))
844 end subroutine mg2_box_gsrb_lpld
847 subroutine mg2_box_lpld(box, i_out, mg)
848 type(box2_t),
intent(inout) :: box
849 integer,
intent(in) :: i_out
850 type(
mg2_t),
intent(in) :: mg
851 integer :: i, j, nc, i_phi, i_eps
852 real(dp) :: inv_dr_sq, a0, u0, u(2*2), a(2*2)
855 inv_dr_sq = 1 / box%dr**2
861 u0 = box%cc(i, j, i_phi)
862 a0 = box%cc(i, j, i_eps)
863 u(1:2) = box%cc(i-1:i+1:2, j, i_phi)
864 u(3:4) = box%cc(i, j-1:j+1:2, i_phi)
865 a(1:2) = box%cc(i-1:i+1:2, j, i_eps)
866 a(3:4) = box%cc(i, j-1:j+1:2, i_eps)
868 box%cc(i, j, i_out) = inv_dr_sq * 2 * &
869 sum(a0*a(:)/(a0 + a(:)) * (u(:) - u0))
873 end subroutine mg2_box_lpld
877 subroutine mg2_box_corr_lpld(box_p, box_c, mg)
878 type(box2_t),
intent(inout) :: box_c
879 type(box2_t),
intent(in) :: box_p
880 type(
mg2_t),
intent(in) :: mg
881 integer :: ix_offset(2), i_phi, i_corr, i_eps
882 integer :: nc, i, j, i_c1, i_c2, j_c1, j_c2
883 real(dp) :: u0, u(2), a0, a(2)
886 ix_offset = a2_get_child_offset(box_c)
894 j_c1 = ix_offset(2) + ishft(j+1, -1)
895 j_c2 = j_c1 + 1 - 2 * iand(j, 1)
897 i_c1 = ix_offset(1) + ishft(i+1, -1)
898 i_c2 = i_c1 + 1 - 2 * iand(i, 1)
900 u0 = box_p%cc(i_c1, j_c1, i_corr)
901 a0 = box_p%cc(i_c1, j_c1, i_eps)
902 u(1) = box_p%cc(i_c2, j_c1, i_corr)
903 u(2) = box_p%cc(i_c1, j_c2, i_corr)
904 a(1) = box_p%cc(i_c2, j_c1, i_eps)
905 a(2) = box_p%cc(i_c1, j_c2, i_eps)
908 box_c%cc(i, j, i_phi) = box_c%cc(i, j, i_phi) + 0.5_dp * &
909 sum( (a0*u0 + a(:)*u(:)) / (a0 + a(:)) )
912 end subroutine mg2_box_corr_lpld
918 subroutine lsf_dist_val(lsf_val_bval_a, lsf_val_bval_b, dist, val)
920 real(dp),
intent(in) :: lsf_val_bval_a(3)
922 real(dp),
intent(in) :: lsf_val_bval_b(3)
924 real(dp),
intent(out) :: dist
926 real(dp),
intent(out) :: val
927 real(dp) :: lsf_a, lsf_b, bval_a, bval_b
929 lsf_a = lsf_val_bval_a(1)
930 lsf_b = lsf_val_bval_b(1)
932 if (lsf_a * lsf_b < 0)
then 934 dist = lsf_a / (lsf_a - lsf_b)
935 bval_a = lsf_val_bval_a(3)
936 bval_b = lsf_val_bval_b(3)
939 val = bval_a * (1-dist) + bval_b * dist
943 val = lsf_val_bval_b(2)
945 end subroutine lsf_dist_val
947 subroutine mg2_box_corr_lpllsf(box_p, box_c, mg)
948 type(box2_t),
intent(inout) :: box_c
949 type(box2_t),
intent(in) :: box_p
950 type(
mg2_t),
intent(in) :: mg
951 integer :: i_phi, i_corr, i_lsf, ix_offset(2)
952 integer :: nc, i, j, i_c1, i_c2, j_c1, j_c2
953 real(dp) :: v_a(3), v_b(3), val(2+1), dist(2+1), c(2+1)
956 ix_offset = a2_get_child_offset(box_c)
964 j_c1 = ix_offset(2) + ishft(j+1, -1)
965 j_c2 = j_c1 + 1 - 2 * iand(j, 1)
967 i_c1 = ix_offset(1) + ishft(i+1, -1)
968 i_c2 = i_c1 + 1 - 2 * iand(i, 1)
970 v_a(1:2) = box_c%cc(i, j, [i_lsf, i_corr])
973 v_b(1:2) = box_p%cc(i_c1, j_c1, [i_lsf, i_corr])
974 call lsf_dist_val(v_a, v_b, dist(1), val(1))
975 v_b(1:2) = box_p%cc(i_c2, j_c1, [i_lsf, i_corr])
976 call lsf_dist_val(v_a, v_b, dist(2), val(2))
977 v_b(1:2) = box_p%cc(i_c1, j_c2, [i_lsf, i_corr])
978 call lsf_dist_val(v_a, v_b, dist(3), val(3))
982 c(1) = 2 * dist(2) * dist(3)
983 c(2) = dist(1) * dist(3)
984 c(3) = dist(1) * dist(2)
985 box_c%cc(i, j, i_phi) = box_c%cc(i, j, i_phi) + sum(c * val)/sum(c)
988 end subroutine mg2_box_corr_lpllsf
991 subroutine mg2_box_gsrb_lpllsf(box, redblack_cntr, mg)
992 type(box2_t),
intent(inout) :: box
993 integer,
intent(in) :: redblack_cntr
994 type(
mg2_t),
intent(in) :: mg
995 integer :: i, i0, j, nc, i_phi, i_rhs, i_lsf, i_bval
996 real(dp) :: dx2, dd(2*2), val(2*2), v_a(3), v_b(3)
1008 i0 = 2 - iand(ieor(redblack_cntr, j), 1)
1010 v_a = box%cc(i, j, [i_lsf, i_phi, i_bval])
1011 v_b = box%cc(i-1, j, [i_lsf, i_phi, i_bval])
1012 call lsf_dist_val(v_a, v_b, dd(1), val(1))
1013 v_b = box%cc(i+1, j, [i_lsf, i_phi, i_bval])
1014 call lsf_dist_val(v_a, v_b, dd(2), val(2))
1015 v_b = box%cc(i, j-1, [i_lsf, i_phi, i_bval])
1016 call lsf_dist_val(v_a, v_b, dd(3), val(3))
1017 v_b = box%cc(i, j+1, [i_lsf, i_phi, i_bval])
1018 call lsf_dist_val(v_a, v_b, dd(4), val(4))
1021 box%cc(i, j, i_phi) = 1 / &
1022 (dd(1) * dd(2) + dd(3) * dd(4)) * ( &
1023 (dd(2) * val(1) + dd(1) * val(2)) * &
1024 dd(3) * dd(4) / (dd(1) + dd(2)) + &
1025 (dd(4) * val(3) + dd(3) * val(4)) * &
1026 dd(1) * dd(2) / (dd(3) + dd(4)) - &
1027 0.5_dp * product(dd) * dx2 * box%cc(i, j, i_rhs))
1030 end subroutine mg2_box_gsrb_lpllsf
1033 subroutine mg2_box_lpllsf(box, i_out, mg)
1034 type(box2_t),
intent(inout) :: box
1035 integer,
intent(in) :: i_out
1036 type(
mg2_t),
intent(in) :: mg
1037 integer :: i, j, nc, i_phi, i_lsf, i_bval
1038 real(dp) :: inv_dr_sq, dd(2*2), val(2*2)
1039 real(dp) :: f0, v_a(3), v_b(3)
1042 inv_dr_sq = 1 / box%dr**2
1049 v_a = box%cc(i, j, [i_lsf, i_phi, i_bval])
1050 v_b = box%cc(i-1, j, [i_lsf, i_phi, i_bval])
1051 call lsf_dist_val(v_a, v_b, dd(1), val(1))
1052 v_b = box%cc(i+1, j, [i_lsf, i_phi, i_bval])
1053 call lsf_dist_val(v_a, v_b, dd(2), val(2))
1054 v_b = box%cc(i, j-1, [i_lsf, i_phi, i_bval])
1055 call lsf_dist_val(v_a, v_b, dd(3), val(3))
1056 v_b = box%cc(i, j+1, [i_lsf, i_phi, i_bval])
1057 call lsf_dist_val(v_a, v_b, dd(4), val(4))
1060 f0 = box%cc(i, j, i_phi)
1061 box%cc(i, j, i_out) = 2 * inv_dr_sq * ( &
1062 (dd(2) * val(1) + dd(1) * val(2) - (dd(1)+dd(2)) * f0) / &
1063 ((dd(1) + dd(2)) * dd(1) * dd(2)) + &
1064 (dd(4) * val(3) + dd(3) * val(4) - (dd(3)+dd(4)) * f0) / &
1065 ((dd(3) + dd(4)) * dd(3) * dd(4)))
1068 end subroutine mg2_box_lpllsf
1071 subroutine mg2_box_rstr_lpllsf(box_c, box_p, iv, mg)
1072 type(box2_t),
intent(in) :: box_c
1073 type(box2_t),
intent(inout) :: box_p
1074 integer,
intent(in) :: iv
1075 type(
mg2_t),
intent(in) :: mg
1076 integer :: i, j, i_f, j_f, i_c, j_c
1077 integer :: hnc, ix_offset(2), n_ch
1078 logical :: child_mask(2, 2)
1080 hnc = ishft(box_c%n_cell, -1)
1081 ix_offset = a2_get_child_offset(box_c)
1084 j_c = ix_offset(2) + j
1087 i_c = ix_offset(1) + i
1090 child_mask = (box_p%cc(i_c, j_c, mg%i_lsf) * &
1091 box_c%cc(i_f:i_f+1, j_f:j_f+1, mg%i_lsf) > 0)
1092 n_ch = count(child_mask)
1094 if (n_ch < a2_num_children .and. n_ch > 0)
then 1095 box_p%cc(i_c, j_c, iv) = 1 / n_ch * &
1096 sum(box_c%cc(i_f:i_f+1, j_f:j_f+1, iv), mask=child_mask)
1098 box_p%cc(i_c, j_c, iv) = 0.25_dp * &
1099 sum(box_c%cc(i_f:i_f+1, j_f:j_f+1, iv))
1103 end subroutine mg2_box_rstr_lpllsf
1106 subroutine mg2_box_gsrb_clpl(box, redblack_cntr, mg)
1107 type(box2_t),
intent(inout) :: box
1108 integer,
intent(in) :: redblack_cntr
1109 type(
mg2_t),
intent(in) :: mg
1110 integer :: i, i0, j, nc, i_phi, i_rhs, ioff
1111 real(dp) :: dx2, rfac(2)
1117 ioff = (box%ix(1)-1) * nc
1122 i0 = 2 - iand(ieor(redblack_cntr, j), 1)
1124 rfac = [i+ioff-1, i+ioff] / (i+ioff-0.5_dp)
1125 box%cc(i, j, i_phi) = 0.25_dp * ( &
1126 rfac(1) * box%cc(i-1, j, i_phi) + &
1127 rfac(2) * box%cc(i+1, j, i_phi) + &
1128 box%cc(i, j+1, i_phi) + box%cc(i, j-1, i_phi) - &
1129 dx2 * box%cc(i, j, i_rhs))
1132 end subroutine mg2_box_gsrb_clpl
1135 subroutine mg2_box_clpl(box, i_out, mg)
1136 type(box2_t),
intent(inout) :: box
1137 integer,
intent(in) :: i_out
1138 type(
mg2_t),
intent(in) :: mg
1139 integer :: i, j, nc, i_phi, ioff
1140 real(dp) :: inv_dr_sq, rfac(2)
1143 inv_dr_sq = 1 / box%dr**2
1145 ioff = (box%ix(1)-1) * nc
1149 rfac = [i+ioff-1, i+ioff] / (i+ioff-0.5_dp)
1150 box%cc(i, j, i_out) = ( &
1151 rfac(1) * box%cc(i-1, j, i_phi) + &
1152 rfac(2) * box%cc(i+1, j, i_phi) + &
1153 box%cc(i, j-1, i_phi) + box%cc(i, j+1, i_phi) - &
1154 4 * box%cc(i, j, i_phi)) * inv_dr_sq
1157 end subroutine mg2_box_clpl
1160 subroutine mg2_box_clpld(box, i_out, mg)
1161 type(box2_t),
intent(inout) :: box
1162 integer,
intent(in) :: i_out
1163 type(
mg2_t),
intent(in) :: mg
1164 integer :: i, j, nc, i_phi, i_eps, ioff
1165 real(dp) :: inv_dr_sq, a0, u0, u(4), a(4), rfac(4)
1168 inv_dr_sq = 1 / box%dr**2
1171 ioff = (box%ix(1)-1) * nc
1175 rfac(1:2) = [i+ioff-1, i+ioff] / (i+ioff-0.5_dp)
1177 u0 = box%cc(i, j, i_phi)
1178 a0 = box%cc(i, j, i_eps)
1179 u(1:2) = box%cc(i-1:i+1:2, j, i_phi)
1180 u(3:4) = box%cc(i, j-1:j+1:2, i_phi)
1181 a(1:2) = box%cc(i-1:i+1:2, j, i_eps)
1182 a(3:4) = box%cc(i, j-1:j+1:2, i_eps)
1184 box%cc(i, j, i_out) = inv_dr_sq * 2 * &
1185 sum(rfac*a0*a(:)/(a0 + a(:)) * (u(:) - u0))
1188 end subroutine mg2_box_clpld
1192 subroutine mg2_box_gsrb_clpld(box, redblack_cntr, mg)
1193 type(box2_t),
intent(inout) :: box
1194 integer,
intent(in) :: redblack_cntr
1195 type(
mg2_t),
intent(in) :: mg
1196 integer :: i, i0, j, nc, i_phi, i_eps, i_rhs, ioff
1197 real(dp) :: dx2, u(4), a0, a(4), c(4), rfac(4)
1204 ioff = (box%ix(1)-1) * nc
1209 i0 = 2 - iand(ieor(redblack_cntr, j), 1)
1211 rfac(1:2) = [i+ioff-1, i+ioff] / (i+ioff-0.5_dp)
1213 a0 = box%cc(i, j, i_eps)
1214 u(1:2) = box%cc(i-1:i+1:2, j, i_phi)
1215 a(1:2) = box%cc(i-1:i+1:2, j, i_eps)
1216 u(3:4) = box%cc(i, j-1:j+1:2, i_phi)
1217 a(3:4) = box%cc(i, j-1:j+1:2, i_eps)
1218 c(:) = 2 * a0 * a(:) / (a0 + a(:))
1220 box%cc(i, j, i_phi) = (sum(c(:) * rfac * u(:)) &
1221 - dx2 * box%cc(i, j, i_rhs)) / sum(c(:) * rfac)
1224 end subroutine mg2_box_gsrb_clpld
Subroutine that performs A * cc(..., i_in) = cc(..., i_out)
Type to store multigrid options in.
This module contains all kinds of different 'helper' routines for Afivo. If the number of routines fo...
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 routines for restriction: going from fine to coarse variables.
This module contains the routines related to prolongation: going from coarse to fine variables...
This module contains the geometric multigrid routines that come with Afivo.
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.