5 #include "../src/cpp_macros.h"
19 public :: mg_fas_vcycle
22 public :: mg_lsf_dist_linear
23 public :: mg_lsf_dist_gss
26 public :: mg_set_box_tag
27 public :: mg_set_operators_lvl
28 public :: mg_set_operators_tree
29 public :: mg_update_operator_stencil
32 public :: mg_box_lpl_gradient
36 public :: mg_compute_phi_gradient
37 public :: mg_compute_field_norm
38 public :: mg_box_field_norm
43 subroutine mg_init(tree, mg)
45 type(
af_t),
intent(inout) :: tree
46 type(
mg_t),
intent(inout) :: mg
48 if (mg%i_phi < 0) stop
"mg_init: i_phi not set"
49 if (mg%i_tmp < 0) stop
"mg_init: i_tmp not set"
50 if (mg%i_rhs < 0) stop
"mg_init: i_rhs not set"
52 if (.not.
associated(mg%sides_bc)) stop
"mg_init: sides_bc not set"
53 if (.not. tree%ready) error stop
"mg_init: tree not initialized"
56 if (.not.
associated(mg%box_op)) mg%box_op => mg_auto_op
58 if (.not.
associated(mg%box_gsrb)) mg%box_gsrb => mg_auto_gsrb
59 if (.not.
associated(mg%box_corr)) mg%box_corr => mg_auto_corr
60 if (.not.
associated(mg%box_rstr)) mg%box_rstr => mg_auto_rstr
61 if (.not.
associated(mg%sides_rb)) mg%sides_rb => mg_auto_rb
64 if (mg%operator_key == af_stencil_none)
then
65 tree%n_stencil_keys_stored = tree%n_stencil_keys_stored + 1
66 mg%operator_key = tree%n_stencil_keys_stored
69 if (mg%prolongation_key == af_stencil_none)
then
70 tree%n_stencil_keys_stored = tree%n_stencil_keys_stored + 1
71 mg%prolongation_key = tree%n_stencil_keys_stored
74 if (mg%i_lsf /= -1)
then
75 error stop
"Set tree%mg_i_lsf instead of mg%i_lsf"
76 else if (iand(mg%operator_mask, mg_lsf_box) > 0)
then
77 mg%i_lsf = tree%mg_i_lsf
80 if (mg%i_eps /= -1)
then
81 error stop
"Set tree%mg_i_eps instead of mg%i_eps"
82 else if (iand(mg%operator_mask, mg_veps_box+mg_ceps_box) > 0)
then
83 mg%i_eps = tree%mg_i_eps
86 if (mg%i_lsf /= -1)
then
87 if (.not.
associated(mg%lsf_dist)) &
88 mg%lsf_dist => mg_lsf_dist_linear
89 if (
associated(mg%lsf_dist, mg_lsf_dist_gss) .and. .not. &
90 associated(mg%lsf))
then
91 error stop
"mg_lsf_dist_gss requires mg%lsf to be set"
95 call mg_set_operators_lvl(tree, mg, 1)
96 call coarse_solver_initialize(tree, mg)
98 if (mg%i_lsf /= -1)
then
99 call check_coarse_representation_lsf(tree, mg)
102 if (.not. tree%has_cc_method(mg%i_phi))
then
104 call af_set_cc_methods(tree, mg%i_phi, mg%sides_bc, mg%sides_rb)
107 mg%initialized = .true.
109 end subroutine mg_init
111 subroutine mg_destroy(mg)
112 type(
mg_t),
intent(inout) :: mg
113 if (.not. mg%initialized) error stop
"mg%initialized is false"
114 call coarse_solver_destroy(mg%csolver)
115 end subroutine mg_destroy
118 subroutine mg_use(tree, mg)
119 type(
af_t),
intent(inout) :: tree
120 type(
mg_t),
intent(in),
target :: mg
122 if (.not. mg%initialized) error stop
"mg%initialized is false"
123 tree%mg_current_operator_mask = mg%operator_mask
125 call mg_set_operators_tree(tree, mg)
126 end subroutine mg_use
129 subroutine done_with_mg(tree)
130 type(
af_t),
intent(inout) :: tree
131 tree%mg_current_operator_mask = -1
132 end subroutine done_with_mg
137 subroutine mg_fas_fmg(tree, mg, set_residual, have_guess)
139 type(
af_t),
intent(inout) :: tree
140 type(
mg_t),
intent(inout) :: mg
141 logical,
intent(in) :: set_residual
142 logical,
intent(in) :: have_guess
145 call mg_use(tree, mg)
148 do lvl = tree%highest_lvl, 2, -1
150 call set_coarse_phi_rhs(tree, lvl, mg)
153 call init_phi_rhs(tree, mg)
158 call af_boxes_copy_cc(tree%boxes, tree%lvls(lvl)%ids, &
160 call mg_fas_vcycle(tree, mg, set_residual .and. &
161 lvl == tree%highest_lvl, lvl, standalone=.false.)
163 do lvl = 2, tree%highest_lvl
165 call af_boxes_copy_cc(tree%boxes, tree%lvls(lvl)%ids, &
170 call correct_children(tree%boxes, tree%lvls(lvl-1)%parents, mg)
173 call af_gc_lvl(tree, lvl, [mg%i_phi])
175 call mg_fas_vcycle(tree, mg, set_residual .and. &
176 lvl == tree%highest_lvl, lvl, standalone=.false.)
179 call done_with_mg(tree)
180 end subroutine mg_fas_fmg
185 subroutine mg_fas_vcycle(tree, mg, set_residual, highest_lvl, standalone)
187 type(
af_t),
intent(inout) :: tree
188 type(
mg_t),
intent(in) :: mg
189 logical,
intent(in) :: set_residual
190 integer,
intent(in),
optional :: highest_lvl
191 logical,
intent(in),
optional :: standalone
192 integer :: lvl, i, id, max_lvl
194 real(dp) :: sum_phi, mean_phi
196 by_itself = .true.;
if (
present(standalone)) by_itself = standalone
199 call mg_use(tree, mg)
202 max_lvl = tree%highest_lvl
203 if (
present(highest_lvl)) max_lvl = highest_lvl
205 do lvl = max_lvl, 2, -1
207 call gsrb_boxes(tree, lvl, mg, mg_cycle_down)
211 call update_coarse(tree, lvl, mg)
214 call solve_coarse_grid(tree, mg)
220 call correct_children(tree%boxes, tree%lvls(lvl-1)%parents, mg)
223 call af_gc_lvl(tree, lvl, [mg%i_phi])
226 call gsrb_boxes(tree, lvl, mg, mg_cycle_up)
229 if (set_residual)
then
233 do i = 1,
size(tree%lvls(lvl)%ids)
234 id = tree%lvls(lvl)%ids(i)
235 call residual_box(tree%boxes(id), mg)
244 if (mg%subtract_mean)
then
245 call af_tree_sum_cc(tree, mg%i_phi, sum_phi)
246 mean_phi = sum_phi / af_total_volume(tree)
250 do i = 1,
size(tree%lvls(lvl)%ids)
251 id = tree%lvls(lvl)%ids(i)
252 tree%boxes(id)%cc(dtimes(:), mg%i_phi) = &
253 tree%boxes(id)%cc(dtimes(:), mg%i_phi) - mean_phi
261 call done_with_mg(tree)
264 end subroutine mg_fas_vcycle
266 subroutine solve_coarse_grid(tree, mg)
268 type(
af_t),
intent(inout) :: tree
269 type(
mg_t),
intent(in) :: mg
270 integer :: num_iterations, max_threads
271 integer :: n_unknowns
273 call coarse_solver_set_rhs_phi(tree, mg)
274 n_unknowns = product(tree%coarse_grid_size)
276 if (n_unknowns < mg%csolver%min_unknowns_for_openmp)
then
278 max_threads = omp_get_max_threads()
279 call omp_set_num_threads(1)
282 call coarse_solver(mg%csolver, num_iterations)
283 call coarse_solver_get_phi(tree, mg)
286 call af_gc_lvl(tree, 1, [mg%i_phi])
288 if (n_unknowns < mg%csolver%min_unknowns_for_openmp)
then
289 call omp_set_num_threads(max_threads)
291 end subroutine solve_coarse_grid
294 subroutine mg_sides_rb(boxes, id, nb, iv)
295 type(
box_t),
intent(inout) :: boxes(:)
296 integer,
intent(in) :: id
297 integer,
intent(in) :: nb
298 integer,
intent(in) :: iv
299 integer :: nc, ix, dix, ijk, di, co(ndim)
300 integer :: hnc, p_id, p_nb_id
306 real(dp) :: tmp(0:boxes(id)%n_cell/2+1)
307 real(dp) :: gc(boxes(id)%n_cell)
310 real(dp) :: tmp(0:boxes(id)%n_cell/2+1, 0:boxes(id)%n_cell/2+1)
311 real(dp) :: gc(boxes(id)%n_cell, boxes(id)%n_cell)
314 real(dp) :: grad(ndim-1)
317 nc = boxes(id)%n_cell
320 p_id = boxes(id)%parent
321 p_nb_id = boxes(p_id)%neighbors(nb)
322 co = af_get_child_offset(boxes(id))
324 associate(box => boxes(p_nb_id))
328 case (af_neighb_lowx)
330 case (af_neighb_highx)
333 case (af_neighb_lowx)
334 tmp = box%cc(nc, co(2):co(2)+hnc+1, iv)
335 case (af_neighb_highx)
336 tmp = box%cc(1, co(2):co(2)+hnc+1, iv)
337 case (af_neighb_lowy)
338 tmp = box%cc(co(1):co(1)+hnc+1, nc, iv)
339 case (af_neighb_highy)
340 tmp = box%cc(co(1):co(1)+hnc+1, 1, iv)
342 case (af_neighb_lowx)
343 tmp = box%cc(nc, co(2):co(2)+hnc+1, co(3):co(3)+hnc+1, iv)
344 case (af_neighb_highx)
345 tmp = box%cc(1, co(2):co(2)+hnc+1, co(3):co(3)+hnc+1, iv)
346 case (af_neighb_lowy)
347 tmp = box%cc(co(1):co(1)+hnc+1, nc, co(3):co(3)+hnc+1, iv)
348 case (af_neighb_highy)
349 tmp = box%cc(co(1):co(1)+hnc+1, 1, co(3):co(3)+hnc+1, iv)
350 case (af_neighb_lowz)
351 tmp = box%cc(co(1):co(1)+hnc+1, co(2):co(2)+hnc+1, nc, iv)
352 case (af_neighb_highz)
353 tmp = box%cc(co(1):co(1)+hnc+1, co(2):co(2)+hnc+1, 1, iv)
356 error stop
"mg_sides_rb: wrong argument for nb"
366 grad(1) = 0.125_dp * (tmp(i+1) - tmp(i-1))
367 gc(2*i-1) = tmp(i) - grad(1)
368 gc(2*i) = tmp(i) + grad(1)
373 grad(1) = 0.125_dp * (tmp(i+1, j) - tmp(i-1, j))
374 grad(2) = 0.125_dp * (tmp(i, j+1) - tmp(i, j-1))
375 gc(2*i-1, 2*j-1) = tmp(i, j) - grad(1) - grad(2)
376 gc(2*i, 2*j-1) = tmp(i, j) + grad(1) - grad(2)
377 gc(2*i-1, 2*j) = tmp(i, j) - grad(1) + grad(2)
378 gc(2*i, 2*j) = tmp(i, j) + grad(1) + grad(2)
383 if (af_neighb_low(nb))
then
391 select case (af_neighb_dim(nb))
396 boxes(id)%cc(i-di, iv) = 0.5_dp * gc &
397 + 0.75_dp * boxes(id)%cc(i, iv) &
398 - 0.25_dp * boxes(id)%cc(i+di, iv)
404 dj = -1 + 2 * iand(j, 1)
405 boxes(id)%cc(i-di, j, iv) = 0.5_dp * gc(j) &
406 + 0.75_dp * boxes(id)%cc(i, j, iv) &
407 - 0.25_dp * boxes(id)%cc(i+di, j, iv)
413 di = -1 + 2 * iand(i, 1)
414 boxes(id)%cc(i, j-dj, iv) = 0.5_dp * gc(i) &
415 + 0.75_dp * boxes(id)%cc(i, j, iv) &
416 - 0.25_dp * boxes(id)%cc(i, j+dj, iv)
423 dk = -1 + 2 * iand(k, 1)
425 dj = -1 + 2 * iand(j, 1)
426 boxes(id)%cc(i-di, j, k, iv) = &
427 0.5_dp * gc(j, k) + &
428 0.75_dp * boxes(id)%cc(i, j, k, iv) - &
429 0.25_dp * boxes(id)%cc(i+di, j, k, iv)
436 dk = -1 + 2 * iand(k, 1)
438 di = -1 + 2 * iand(i, 1)
439 boxes(id)%cc(i, j-dj, k, iv) = &
440 0.5_dp * gc(i, k) + &
441 0.75_dp * boxes(id)%cc(i, j, k, iv) - &
442 0.25_dp * boxes(id)%cc(i, j+dj, k, iv)
449 dj = -1 + 2 * iand(j, 1)
451 di = -1 + 2 * iand(i, 1)
452 boxes(id)%cc(i, j, k-dk, iv) = &
453 0.5_dp * gc(i, j) + &
454 0.75_dp * boxes(id)%cc(i, j, k, iv) - &
455 0.25_dp * boxes(id)%cc(i, j, k+dk, iv)
461 end subroutine mg_sides_rb
468 subroutine mg_sides_rb_extrap(boxes, id, nb, iv)
469 type(box_t),
intent(inout) :: boxes(:)
470 integer,
intent(in) :: id
471 integer,
intent(in) :: nb
472 integer,
intent(in) :: iv
473 integer :: nc, ix, dix, IJK, di
481 nc = boxes(id)%n_cell
483 if (af_neighb_low(nb))
then
491 call af_gc_prolong_copy(boxes, id, nb, iv, 0)
493 select case (af_neighb_dim(nb))
498 boxes(id)%cc(i-di, iv) = 0.5_dp * boxes(id)%cc(i-di, iv) &
499 + 0.75_dp * boxes(id)%cc(i, iv) &
500 - 0.25_dp * boxes(id)%cc(i+di, iv)
506 dj = -1 + 2 * iand(j, 1)
509 boxes(id)%cc(i-di, j, iv) = 0.5_dp * boxes(id)%cc(i-di, j, iv) + &
510 1.125_dp * boxes(id)%cc(i, j, iv) - 0.375_dp * &
511 (boxes(id)%cc(i+di, j, iv) + boxes(id)%cc(i, j+dj, iv)) &
512 + 0.125_dp * boxes(id)%cc(i+di, j+dj, iv)
528 di = -1 + 2 * iand(i, 1)
531 boxes(id)%cc(i, j-dj, iv) = 0.5_dp * boxes(id)%cc(i, j-dj, iv) + &
532 1.125_dp * boxes(id)%cc(i, j, iv) - 0.375_dp * &
533 (boxes(id)%cc(i+di, j, iv) + boxes(id)%cc(i, j+dj, iv)) &
534 + 0.125_dp * boxes(id)%cc(i+di, j+dj, iv)
546 dk = -1 + 2 * iand(k, 1)
548 dj = -1 + 2 * iand(j, 1)
562 boxes(id)%cc(i-di, j, k, iv) = &
563 0.5_dp * boxes(id)%cc(i-di, j, k, iv) + &
564 0.75_dp * boxes(id)%cc(i, j, k, iv) - &
565 0.25_dp * boxes(id)%cc(i+di, j+dj, k+dk, iv)
572 dk = -1 + 2 * iand(k, 1)
574 di = -1 + 2 * iand(i, 1)
587 boxes(id)%cc(i, j-dj, k, iv) = &
588 0.5_dp * boxes(id)%cc(i, j-dj, k, iv) + &
589 0.75_dp * boxes(id)%cc(i, j, k, iv) - &
590 0.25_dp * boxes(id)%cc(i+di, j+dj, k+dk, iv)
597 dj = -1 + 2 * iand(j, 1)
599 di = -1 + 2 * iand(i, 1)
612 boxes(id)%cc(i, j, k-dk, iv) = &
613 0.5_dp * boxes(id)%cc(i, j, k-dk, iv) + &
614 0.75_dp * boxes(id)%cc(i, j, k, iv) - &
615 0.25_dp * boxes(id)%cc(i+di, j+dj, k+dk, iv)
621 end subroutine mg_sides_rb_extrap
624 subroutine correct_children(boxes, ids, mg)
625 type(box_t),
intent(inout) :: boxes(:)
626 integer,
intent(in) :: ids(:)
627 type(mg_t),
intent(in) :: mg
628 integer :: i, id, nc, i_c, c_id
633 nc = boxes(id)%n_cell
636 boxes(id)%cc(dtimes(:), mg%i_tmp) = boxes(id)%cc(dtimes(:), mg%i_phi) - &
637 boxes(id)%cc(dtimes(:), mg%i_tmp)
639 do i_c = 1, af_num_children
640 c_id = boxes(id)%children(i_c)
641 if (c_id == af_no_box) cycle
642 call mg%box_corr(boxes(id), boxes(c_id), mg)
646 end subroutine correct_children
648 subroutine gsrb_boxes(tree, lvl, mg, type_cycle)
649 type(af_t),
intent(inout) :: tree
650 type(mg_t),
intent(in) :: mg
651 integer,
intent(in) :: lvl
652 integer,
intent(in) :: type_cycle
653 integer :: n, i, n_cycle
654 logical :: use_corners
656 select case (type_cycle)
658 n_cycle = mg%n_cycle_down
660 n_cycle = mg%n_cycle_up
662 error stop
"gsrb_boxes: invalid cycle type"
665 associate(ids => tree%lvls(lvl)%ids)
667 do n = 1, 2 * n_cycle
670 call mg%box_gsrb(tree%boxes(ids(i)), n, mg)
676 use_corners = mg%use_corners .or. &
677 (type_cycle /= mg_cycle_down .and. n == 2 * n_cycle)
681 call af_gc_box(tree, ids(i), [mg%i_phi], use_corners)
687 end subroutine gsrb_boxes
691 subroutine update_coarse(tree, lvl, mg)
692 use m_af_utils,
only: af_box_add_cc, af_box_copy_cc
693 type(af_t),
intent(inout) :: tree
694 integer,
intent(in) :: lvl
695 type(mg_t),
intent(in) :: mg
696 integer :: i, id, p_id, nc
697 real(dp),
allocatable :: tmp(DTIMES(:))
699 id = tree%lvls(lvl)%ids(1)
701 allocate(tmp(dtimes(1:nc)))
705 do i = 1,
size(tree%lvls(lvl)%ids)
706 id = tree%lvls(lvl)%ids(i)
707 p_id = tree%boxes(id)%parent
711 tmp = tree%boxes(id)%cc(dtimes(1:nc), mg%i_tmp)
712 call residual_box(tree%boxes(id), mg)
713 call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_tmp, mg)
714 call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_phi, mg)
715 tree%boxes(id)%cc(dtimes(1:nc), mg%i_tmp) = tmp
719 call af_gc_lvl(tree, lvl-1, [mg%i_phi])
725 do i = 1,
size(tree%lvls(lvl-1)%parents)
726 id = tree%lvls(lvl-1)%parents(i)
729 call mg%box_op(tree%boxes(id), mg%i_rhs, mg)
732 call af_box_add_cc(tree%boxes(id), mg%i_tmp, mg%i_rhs)
735 call af_box_copy_cc(tree%boxes(id), mg%i_phi, mg%i_tmp)
738 end subroutine update_coarse
742 subroutine set_coarse_phi_rhs(tree, lvl, mg)
744 type(af_t),
intent(inout) :: tree
745 integer,
intent(in) :: lvl
746 type(mg_t),
intent(in) :: mg
747 integer :: i, id, p_id
750 if (lvl == tree%highest_lvl)
then
751 call af_gc_lvl(tree, lvl, [mg%i_phi])
755 do i = 1,
size(tree%lvls(lvl)%ids)
756 id = tree%lvls(lvl)%ids(i)
757 p_id = tree%boxes(id)%parent
759 call residual_box(tree%boxes(id), mg)
760 call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_tmp, mg)
761 call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_phi, mg)
765 call af_gc_lvl(tree, lvl-1, [mg%i_phi])
770 do i = 1,
size(tree%lvls(lvl-1)%parents)
771 id = tree%lvls(lvl-1)%parents(i)
772 call mg%box_op(tree%boxes(id), mg%i_rhs, mg)
773 call af_box_add_cc(tree%boxes(id), mg%i_tmp, mg%i_rhs)
776 end subroutine set_coarse_phi_rhs
779 subroutine init_phi_rhs(tree, mg)
781 type(af_t),
intent(inout) :: tree
782 type(mg_t),
intent(in) :: mg
783 integer :: i, id, p_id, lvl
786 do lvl = tree%highest_lvl, 1+1, -1
788 do i = 1,
size(tree%lvls(lvl)%ids)
789 id = tree%lvls(lvl)%ids(i)
790 call af_box_clear_cc(tree%boxes(id), mg%i_phi)
792 p_id = tree%boxes(id)%parent
793 call mg%box_rstr(tree%boxes(id), tree%boxes(p_id), mg%i_rhs, mg)
799 end subroutine init_phi_rhs
801 subroutine residual_box(box, mg)
802 type(box_t),
intent(inout) :: box
803 type(mg_t),
intent(in) :: mg
806 call mg%box_op(box, mg%i_tmp, mg)
808 box%cc(dtimes(1:nc), mg%i_tmp) = box%cc(dtimes(1:nc), mg%i_rhs) &
809 - box%cc(dtimes(1:nc), mg%i_tmp)
810 end subroutine residual_box
813 subroutine mg_auto_gsrb(box, redblack_cntr, mg)
814 type(box_t),
intent(inout) :: box
815 integer,
intent(in) :: redblack_cntr
816 type(mg_t),
intent(in) :: mg
818 call af_stencil_gsrb_box(box, mg%operator_key, redblack_cntr, &
820 end subroutine mg_auto_gsrb
823 subroutine mg_store_operator_stencil(box, mg, ix)
824 type(box_t),
intent(inout) :: box
825 type(mg_t),
intent(in) :: mg
827 integer,
intent(inout) :: ix
829 if (ix == af_stencil_none)
then
830 call af_stencil_prepare_store(box, mg%operator_key, ix)
833 select case (mg%operator_type)
834 case (mg_normal_operator)
835 call mg_box_lpl_stencil(box, mg, ix)
836 case (mg_lsf_operator)
837 call mg_box_lsf_stencil(box, mg, ix)
838 case (mg_eps_operator)
839 call mg_box_lpld_stencil(box, mg, ix)
840 case (mg_auto_operator)
842 select case (iand(box%tag, mg%operator_mask))
844 call mg_box_lpl_stencil(box, mg, ix)
846 call mg_box_lsf_stencil(box, mg, ix)
847 case (mg_veps_box, mg_ceps_box)
848 call mg_box_lpld_stencil(box, mg, ix)
849 case (mg_veps_box+mg_lsf_box, mg_ceps_box+mg_lsf_box)
850 call mg_box_lpld_lsf_stencil(box, mg, ix)
852 error stop
"mg_store_operator_stencil: unknown box tag"
855 error stop
"mg_store_operator_stencil: unknown mg%operator_type"
858 call af_stencil_check_box(box, mg%operator_key, ix)
859 end subroutine mg_store_operator_stencil
862 subroutine mg_store_prolongation_stencil(tree, id, mg)
863 type(af_t),
intent(inout) :: tree
864 integer,
intent(in) :: id
865 type(mg_t),
intent(in) :: mg
868 call af_stencil_prepare_store(tree%boxes(id), mg%prolongation_key, ix)
870 p_id = tree%boxes(id)%parent
871 if (p_id <= af_no_box) error stop
"Box does not have parent"
873 select case (mg%prolongation_type)
874 case (mg_prolong_linear)
875 call mg_box_prolong_linear_stencil(tree%boxes(id), &
876 tree%boxes(p_id), mg, ix)
877 case (mg_prolong_sparse)
878 call mg_box_prolong_sparse_stencil(tree%boxes(id), &
879 tree%boxes(p_id), mg, ix)
880 case (mg_prolong_auto)
882 associate(box=>tree%boxes(id), box_p=>tree%boxes(p_id))
883 select case (iand(box%tag, mg%operator_mask))
884 case (mg_normal_box, mg_ceps_box)
885 call mg_box_prolong_linear_stencil(box, box_p, mg, ix)
886 case (mg_lsf_box, mg_ceps_box+mg_lsf_box)
887 if (mg%lsf_use_custom_prolongation)
then
888 call mg_box_prolong_lsf_stencil(box, box_p, mg, ix)
890 call mg_box_prolong_linear_stencil(box, box_p, mg, ix)
892 case (mg_veps_box, mg_veps_box + mg_lsf_box)
893 call mg_box_prolong_eps_stencil(box, box_p, mg, ix)
895 error stop
"mg_store_prolongation_stencil: unknown box tag"
899 error stop
"mg_store_prolongation_stencil: unknown mg%prolongation_type"
902 call af_stencil_check_box(tree%boxes(id), mg%prolongation_key, ix)
903 end subroutine mg_store_prolongation_stencil
906 subroutine mg_auto_op(box, i_out, mg)
907 type(box_t),
intent(inout) :: box
908 integer,
intent(in) :: i_out
909 type(mg_t),
intent(in) :: mg
911 call af_stencil_apply_box(box, mg%operator_key, mg%i_phi, i_out)
912 end subroutine mg_auto_op
915 subroutine mg_auto_rstr(box_c, box_p, iv, mg)
916 type(box_t),
intent(in) :: box_c
917 type(box_t),
intent(inout) :: box_p
918 integer,
intent(in) :: iv
919 type(mg_t),
intent(in) :: mg
922 call mg_box_rstr_lpl(box_c, box_p, iv, mg)
923 end subroutine mg_auto_rstr
926 subroutine mg_auto_rb(boxes, id, nb, iv, op_mask)
927 type(box_t),
intent(inout) :: boxes(:)
928 integer,
intent(in) :: id
929 integer,
intent(in) :: nb
930 integer,
intent(in) :: iv
931 integer,
intent(in) :: op_mask
933 select case (iand(boxes(id)%tag, op_mask))
936 call mg_sides_rb_extrap(boxes, id, nb, iv)
938 call mg_sides_rb(boxes, id, nb, iv)
940 end subroutine mg_auto_rb
943 subroutine mg_auto_corr(box_p, box_c, mg)
944 type(box_t),
intent(inout) :: box_c
945 type(box_t),
intent(in) :: box_p
946 type(mg_t),
intent(in) :: mg
948 call af_stencil_prolong_box(box_p, box_c, mg%prolongation_key, &
949 mg%i_tmp, mg%i_phi, .true.)
950 end subroutine mg_auto_corr
954 subroutine get_possible_lsf_root_mask(box, nc, dmax, mg, root_mask)
955 type(box_t),
intent(in) :: box
956 real(dp),
intent(in) :: dmax
957 integer,
intent(in) :: nc
958 type(mg_t),
intent(in) :: mg
960 logical,
intent(out) :: root_mask(DTIMES(nc))
962 real(dp) :: gradnorm, rr(NDIM)
964 if (.not.
associated(mg%lsf)) error stop
"mg%lsf not set"
968 rr = af_r_cc(box, [ijk])
969 gradnorm = norm2(numerical_gradient(mg%lsf, rr))
970 root_mask(ijk) = (abs(box%cc(ijk, mg%i_lsf)) < dmax * gradnorm * &
971 mg%lsf_gradient_safety_factor)
973 end subroutine get_possible_lsf_root_mask
977 subroutine store_lsf_distance_matrix(box, nc, mg, boundary)
978 type(box_t),
intent(inout) :: box
979 integer,
intent(in) :: nc
980 type(mg_t),
intent(in) :: mg
981 logical,
intent(out) :: boundary
982 logical :: root_mask(DTIMES(nc))
983 real(dp) :: dd(2*NDIM), a(NDIM)
984 integer :: ixs(NDIM, nc**NDIM), IJK, ix, n
986 real(dp) :: v(2*NDIM, nc**NDIM)
988 integer :: nb, dim, i_step, n_steps
989 real(dp) :: dist, gradient(NDIM), dvec(NDIM)
990 real(dp) :: x(NDIM), step_size(NDIM), min_dr
992 min_dr = minval(box%dr)
998 call get_possible_lsf_root_mask(box, nc, norm2(box%dr), mg, root_mask)
999 n_mask = count(root_mask)
1001 if (n_mask > 0)
then
1003 call af_stencil_prepare_store(box, mg_lsf_mask_key, ix)
1004 box%stencils(ix)%stype = stencil_sparse
1005 box%stencils(ix)%shape = af_stencil_mask
1006 call af_stencil_allocate_coeff(box%stencils(ix), box%n_cell, &
1011 if (root_mask(ijk))
then
1013 box%stencils(ix)%sparse_ix(:, m) = [ijk]
1022 if (root_mask(ijk))
then
1023 a = af_r_cc(box, [ijk])
1025 dd(1) = mg%lsf_dist(a, af_r_cc(box, [i-1]), mg)
1026 dd(2) = mg%lsf_dist(a, af_r_cc(box, [i+1]), mg)
1028 dd(1) = mg%lsf_dist(a, af_r_cc(box, [i-1, j]), mg)
1029 dd(2) = mg%lsf_dist(a, af_r_cc(box, [i+1, j]), mg)
1030 dd(3) = mg%lsf_dist(a, af_r_cc(box, [i, j-1]), mg)
1031 dd(4) = mg%lsf_dist(a, af_r_cc(box, [i, j+1]), mg)
1033 dd(1) = mg%lsf_dist(a, af_r_cc(box, [i-1, j, k]), mg)
1034 dd(2) = mg%lsf_dist(a, af_r_cc(box, [i+1, j, k]), mg)
1035 dd(3) = mg%lsf_dist(a, af_r_cc(box, [i, j-1, k]), mg)
1036 dd(4) = mg%lsf_dist(a, af_r_cc(box, [i, j+1, k]), mg)
1037 dd(5) = mg%lsf_dist(a, af_r_cc(box, [i, j, k-1]), mg)
1038 dd(6) = mg%lsf_dist(a, af_r_cc(box, [i, j, k+1]), mg)
1044 if (min_dr > mg%lsf_length_scale .and. all(dd >= 1))
then
1045 n_steps = ceiling(min_dr/mg%lsf_length_scale)
1046 step_size = sign(mg%lsf_length_scale, box%cc(ijk, mg%i_lsf))
1049 do i_step = 1, n_steps
1050 gradient = numerical_gradient(mg%lsf, x)
1051 gradient = gradient/max(norm2(gradient), 1e-50_dp)
1054 x = x - gradient * step_size
1055 if (mg%lsf(x) * box%cc(ijk, mg%i_lsf) <= 0)
exit
1058 dist = mg%lsf_dist(a, x, mg)
1062 dist = dist * norm2(x - a)/min_dr
1066 dim = maxloc(abs(dvec), dim=1)
1068 if (dvec(dim) > 0) nb = nb + 1
1079 if (any(dd < 1.0_dp))
then
1088 call af_stencil_prepare_store(box, mg_lsf_distance_key, ix)
1089 box%stencils(ix)%stype = stencil_sparse
1090 box%stencils(ix)%shape = af_stencil_246
1091 call af_stencil_allocate_coeff(box%stencils(ix), box%n_cell, &
1093 box%stencils(ix)%sparse_ix(:, :) = ixs(:, 1:n)
1094 box%stencils(ix)%sparse_v(:, :) = v(:, 1:n)
1097 end subroutine store_lsf_distance_matrix
1100 subroutine mg_set_box_tag(tree, id, mg, new_lsf, new_eps)
1101 type(af_t),
intent(inout) :: tree
1102 integer,
intent(in) :: id
1103 type(mg_t),
intent(in) :: mg
1104 logical,
intent(in) :: new_lsf
1105 logical,
intent(in) :: new_eps
1106 logical :: has_lsf, update_lsf, update_eps
1109 associate(box => tree%boxes(id))
1110 if (box%tag == af_init_tag)
then
1111 box%tag = mg_normal_box
1115 update_lsf = new_lsf
1116 update_eps = new_eps
1119 if (new_lsf) box%tag = iand(box%tag, not(mg_lsf_box))
1120 if (new_eps) box%tag = iand(box%tag, not(ior(mg_veps_box, mg_ceps_box)))
1123 if (tree%mg_i_lsf /= -1 .and. update_lsf)
then
1124 call store_lsf_distance_matrix(box, box%n_cell, mg, has_lsf)
1127 box%tag = box%tag + mg_lsf_box
1131 if (tree%mg_i_eps /= -1 .and. update_eps)
then
1132 a = minval(box%cc(dtimes(:), tree%mg_i_eps))
1133 b = maxval(box%cc(dtimes(:), tree%mg_i_eps))
1137 box%tag = box%tag + mg_veps_box
1138 else if (maxval(abs([a, b] - 1)) > 1e-8_dp)
then
1140 box%tag = box%tag + mg_ceps_box
1145 end subroutine mg_set_box_tag
1147 subroutine mg_set_operators_lvl(tree, mg, lvl)
1148 type(af_t),
intent(inout) :: tree
1149 type(mg_t),
intent(in) :: mg
1150 integer,
intent(in) :: lvl
1154 do i = 1,
size(tree%lvls(lvl)%ids)
1155 id = tree%lvls(lvl)%ids(i)
1156 associate(box => tree%boxes(id))
1158 if (box%tag == af_init_tag)
then
1161 call mg_set_box_tag(tree, id, mg, .true., .true.)
1165 n = af_stencil_index(box, mg%operator_key)
1166 if (n == af_stencil_none)
then
1167 call mg_store_operator_stencil(box, mg, n)
1171 if (
allocated(box%stencils(n)%f))
then
1172 box%stencils(n)%bc_correction = box%stencils(n)%f * &
1173 mg_lsf_boundary_value(box, mg)
1177 n = af_stencil_index(box, mg%prolongation_key)
1178 if (n == af_stencil_none)
then
1179 call mg_store_prolongation_stencil(tree, id, mg)
1185 end subroutine mg_set_operators_lvl
1188 subroutine mg_update_operator_stencil(tree, mg, new_lsf, new_eps)
1189 type(af_t),
intent(inout) :: tree
1190 type(mg_t),
intent(inout) :: mg
1191 logical,
intent(in) :: new_lsf
1192 logical,
intent(in) :: new_eps
1193 integer :: lvl, i, id, n
1196 do lvl = 1, tree%highest_lvl
1198 do i = 1,
size(tree%lvls(lvl)%ids)
1199 id = tree%lvls(lvl)%ids(i)
1200 associate(box => tree%boxes(id))
1201 n = af_stencil_index(box, mg%operator_key)
1204 call mg_set_box_tag(tree, id, mg, new_lsf, new_eps)
1206 call mg_store_operator_stencil(box, mg, n)
1213 call coarse_solver_update_matrix(tree, mg)
1214 end subroutine mg_update_operator_stencil
1216 subroutine mg_set_operators_tree(tree, mg)
1217 type(af_t),
intent(inout) :: tree
1218 type(mg_t),
intent(in) :: mg
1221 do lvl = 1, tree%highest_lvl
1222 call mg_set_operators_lvl(tree, mg, lvl)
1224 end subroutine mg_set_operators_tree
1227 subroutine mg_box_rstr_lpl(box_c, box_p, iv, mg)
1229 type(box_t),
intent(in) :: box_c
1230 type(box_t),
intent(inout) :: box_p
1231 integer,
intent(in) :: iv
1232 type(mg_t),
intent(in) :: mg
1234 if (iv == mg%i_phi)
then
1237 call af_restrict_box(box_c, box_p, [iv], use_geometry=.false.)
1240 call af_restrict_box(box_c, box_p, [iv], use_geometry=.true.)
1242 end subroutine mg_box_rstr_lpl
1246 subroutine mg_box_lpl_stencil(box, mg, ix)
1247 type(box_t),
intent(inout) :: box
1248 type(mg_t),
intent(in) :: mg
1249 integer,
intent(in) :: ix
1250 real(dp) :: inv_dr2(NDIM)
1253 box%stencils(ix)%shape = af_stencil_357
1254 box%stencils(ix)%stype = stencil_constant
1255 box%stencils(ix)%cylindrical_gradient = (box%coord_t == af_cyl)
1256 inv_dr2 = 1 / box%dr**2
1257 call af_stencil_allocate_coeff(box%stencils(ix), box%n_cell)
1260 box%stencils(ix)%c(2*idim:2*idim+1) = inv_dr2(idim)
1262 box%stencils(ix)%c(1) = -sum(box%stencils(ix)%c(2:)) - mg%helmholtz_lambda
1264 end subroutine mg_box_lpl_stencil
1267 subroutine mg_box_prolong_linear_stencil(box, box_p, mg, ix)
1268 type(box_t),
intent(inout) :: box
1269 type(box_t),
intent(in) :: box_p
1270 type(mg_t),
intent(in) :: mg
1271 integer,
intent(in) :: ix
1273 box%stencils(ix)%shape = af_stencil_p248
1274 box%stencils(ix)%stype = stencil_constant
1275 call af_stencil_allocate_coeff(box%stencils(ix), box%n_cell)
1278 box%stencils(ix)%c(:) = [0.75_dp, 0.25_dp]
1280 box%stencils(ix)%c(:) = [9, 3, 3, 1] / 16.0_dp
1282 box%stencils(ix)%c(:) = [27, 9, 9, 3, 9, 3, 3, 1] / 64.0_dp
1284 end subroutine mg_box_prolong_linear_stencil
1287 subroutine mg_box_prolong_sparse_stencil(box, box_p, mg, ix)
1288 type(box_t),
intent(inout) :: box
1289 type(box_t),
intent(in) :: box_p
1290 type(mg_t),
intent(in) :: mg
1291 integer,
intent(in) :: ix
1293 box%stencils(ix)%shape = af_stencil_p234
1294 box%stencils(ix)%stype = stencil_constant
1295 call af_stencil_allocate_coeff(box%stencils(ix), box%n_cell)
1298 box%stencils(ix)%c(:) = [0.75_dp, 0.25_dp]
1300 box%stencils(ix)%c(:) = [0.5_dp, 0.25_dp, 0.25_dp]
1302 box%stencils(ix)%c(:) = [0.25_dp, 0.25_dp, 0.25_dp, 0.25_dp]
1304 end subroutine mg_box_prolong_sparse_stencil
1308 subroutine mg_box_prolong_eps_stencil(box, box_p, mg, ix)
1309 type(box_t),
intent(inout) :: box
1310 type(box_t),
intent(in) :: box_p
1311 type(mg_t),
intent(in) :: mg
1312 integer,
intent(in) :: ix
1313 real(dp) :: a0, a(NDIM)
1314 integer :: i_eps, nc
1316 integer :: IJK, IJK_(c1)
1317 integer :: IJK_(c2), ix_offset(NDIM)
1319 real(dp),
parameter :: third = 1/3.0_dp
1323 box%stencils(ix)%shape = af_stencil_p234
1324 box%stencils(ix)%stype = stencil_variable
1325 ix_offset = af_get_child_offset(box)
1326 call af_stencil_allocate_coeff(box%stencils(ix), box%n_cell)
1330 associate(v => box%stencils(ix)%v)
1335 i_c1 = ix_offset(1) + ishft(i+1, -1)
1336 i_c2 = i_c1 + 1 - 2 * iand(i, 1)
1338 a0 = box_p%cc(i_c1, i_eps)
1339 a(1) = box_p%cc(i_c2, i_eps)
1342 v(:, ijk) = [a0, a(1)] / (a0 + a(1))
1346 j_c1 = ix_offset(2) + ishft(j+1, -1)
1347 j_c2 = j_c1 + 1 - 2 * iand(j, 1)
1349 i_c1 = ix_offset(1) + ishft(i+1, -1)
1350 i_c2 = i_c1 + 1 - 2 * iand(i, 1)
1352 a0 = box_p%cc(i_c1, j_c1, i_eps)
1353 a(1) = box_p%cc(i_c2, j_c1, i_eps)
1354 a(2) = box_p%cc(i_c1, j_c2, i_eps)
1357 v(1, ijk) = 0.5_dp * sum(a0 / (a0 + a(:)))
1358 v(2:, ijk) = 0.5_dp * a(:) / (a0 + a(:))
1363 k_c1 = ix_offset(3) + ishft(k+1, -1)
1364 k_c2 = k_c1 + 1 - 2 * iand(k, 1)
1366 j_c1 = ix_offset(2) + ishft(j+1, -1)
1367 j_c2 = j_c1 + 1 - 2 * iand(j, 1)
1369 i_c1 = ix_offset(1) + ishft(i+1, -1)
1370 i_c2 = i_c1 + 1 - 2 * iand(i, 1)
1372 a0 = box_p%cc(i_c1, j_c1, k_c1, i_eps)
1373 a(1) = box_p%cc(i_c2, j_c1, k_c1, i_eps)
1374 a(2) = box_p%cc(i_c1, j_c2, k_c1, i_eps)
1375 a(3) = box_p%cc(i_c1, j_c1, k_c2, i_eps)
1378 v(1, ijk) = third * sum((a0 - 0.5_dp * a(:))/(a0 + a(:)))
1379 v(2:, ijk) = 0.5_dp * a(:) / (a0 + a(:))
1386 call af_stencil_try_constant(box, ix, epsilon(1.0_dp), success)
1388 end subroutine mg_box_prolong_eps_stencil
1392 subroutine mg_box_prolong_lsf_stencil(box, box_p, mg, ix)
1393 type(box_t),
intent(inout) :: box
1394 type(box_t),
intent(in) :: box_p
1395 type(mg_t),
intent(in) :: mg
1396 integer,
intent(in) :: ix
1397 real(dp) :: dd(NDIM+1), a(NDIM)
1398 integer :: i_lsf, nc, ix_mask
1400 integer :: IJK, IJK_(c1), n, n_mask
1401 integer :: IJK_(c2), ix_offset(NDIM)
1404 box%stencils(ix)%shape = af_stencil_p234
1405 box%stencils(ix)%stype = stencil_variable
1406 ix_offset = af_get_child_offset(box)
1408 call af_stencil_allocate_coeff(box%stencils(ix), box%n_cell)
1410 ix_mask = af_stencil_index(box, mg_lsf_mask_key)
1411 if (ix_mask == af_stencil_none) error stop
"No LSF root mask stored"
1412 n_mask =
size(box%stencils(ix_mask)%sparse_ix, 2)
1414 associate(v => box%stencils(ix)%v)
1422 i = box%stencils(ix_mask)%sparse_ix(1, n)
1423 i_c1 = ix_offset(1) + ishft(i+1, -1)
1424 i_c2 = i_c1 + 1 - 2 * iand(i, 1)
1426 a = af_r_cc(box, [ijk])
1427 dd(1) = mg%lsf_dist(a, af_r_cc(box_p, [i_c1]), mg)
1428 dd(2) = mg%lsf_dist(a, af_r_cc(box_p, [i_c2]), mg)
1430 v(:, ijk) = [3 * dd(2), dd(1)]
1431 v(:, ijk) = v(:, ijk) / sum(v(:, ijk))
1432 where (dd < 1) v(:, ijk) = 0
1436 v(2, :, :) = 0.25_dp
1437 v(3, :, :) = 0.25_dp
1440 i = box%stencils(ix_mask)%sparse_ix(1, n)
1441 j = box%stencils(ix_mask)%sparse_ix(2, n)
1443 j_c1 = ix_offset(2) + ishft(j+1, -1)
1444 j_c2 = j_c1 + 1 - 2 * iand(j, 1)
1445 i_c1 = ix_offset(1) + ishft(i+1, -1)
1446 i_c2 = i_c1 + 1 - 2 * iand(i, 1)
1448 a = af_r_cc(box, [ijk])
1449 dd(1) = mg%lsf_dist(a, af_r_cc(box_p, [i_c1, j_c1]), mg)
1450 dd(2) = mg%lsf_dist(a, af_r_cc(box_p, [i_c2, j_c1]), mg)
1451 dd(3) = mg%lsf_dist(a, af_r_cc(box_p, [i_c1, j_c2]), mg)
1453 v(:, ijk) = [2 * dd(2) * dd(3), dd(1) * dd(3), dd(1) * dd(2)]
1454 v(:, ijk) = v(:, ijk) / sum(v(:, ijk))
1455 where (dd < 1) v(:, ijk) = 0
1458 v(:, :, :, :) = 0.25_dp
1461 i = box%stencils(ix_mask)%sparse_ix(1, n)
1462 j = box%stencils(ix_mask)%sparse_ix(2, n)
1463 k = box%stencils(ix_mask)%sparse_ix(3, n)
1465 k_c1 = ix_offset(3) + ishft(k+1, -1)
1466 k_c2 = k_c1 + 1 - 2 * iand(k, 1)
1467 j_c1 = ix_offset(2) + ishft(j+1, -1)
1468 j_c2 = j_c1 + 1 - 2 * iand(j, 1)
1469 i_c1 = ix_offset(1) + ishft(i+1, -1)
1470 i_c2 = i_c1 + 1 - 2 * iand(i, 1)
1472 a = af_r_cc(box, [ijk])
1473 dd(1) = mg%lsf_dist(a, af_r_cc(box_p, [i_c1, j_c1, k_c1]), mg)
1474 dd(2) = mg%lsf_dist(a, af_r_cc(box_p, [i_c2, j_c1, k_c1]), mg)
1475 dd(3) = mg%lsf_dist(a, af_r_cc(box_p, [i_c1, j_c2, k_c1]), mg)
1476 dd(4) = mg%lsf_dist(a, af_r_cc(box_p, [i_c1, j_c1, k_c2]), mg)
1478 v(:, ijk) = [dd(2) * dd(3) * dd(4), &
1479 dd(1) * dd(3) * dd(4), dd(1) * dd(2) * dd(4), &
1480 dd(1) * dd(2) * dd(3)]
1481 v(:, ijk) = v(:, ijk) / sum(v(:, ijk))
1482 where (dd < 1) v(:, ijk) = 0
1487 call af_stencil_try_constant(box, ix, epsilon(1.0_dp), success)
1489 end subroutine mg_box_prolong_lsf_stencil
1493 subroutine mg_box_lpld_stencil(box, mg, ix)
1494 type(box_t),
intent(inout) :: box
1495 type(mg_t),
intent(in) :: mg
1496 integer,
intent(in) :: ix
1498 real(dp) :: idr2(2*NDIM), a0, a(2*NDIM)
1502 idr2(1:2*ndim:2) = 1/box%dr**2
1503 idr2(2:2*ndim:2) = idr2(1:2*ndim:2)
1505 box%stencils(ix)%shape = af_stencil_357
1506 box%stencils(ix)%stype = stencil_variable
1507 box%stencils(ix)%cylindrical_gradient = (box%coord_t == af_cyl)
1508 call af_stencil_allocate_coeff(box%stencils(ix), box%n_cell)
1510 associate(cc => box%cc, n => mg%i_phi, i_eps => mg%i_eps)
1513 a0 = box%cc(i, i_eps)
1514 a(1:2) = box%cc(i-1:i+1:2, i_eps)
1516 a0 = box%cc(i, j, i_eps)
1517 a(1:2) = box%cc(i-1:i+1:2, j, i_eps)
1518 a(3:4) = box%cc(i, j-1:j+1:2, i_eps)
1520 a0 = box%cc(i, j, k, i_eps)
1521 a(1:2) = box%cc(i-1:i+1:2, j, k, i_eps)
1522 a(3:4) = box%cc(i, j-1:j+1:2, k, i_eps)
1523 a(5:6) = box%cc(i, j, k-1:k+1:2, i_eps)
1525 box%stencils(ix)%v(2:, ijk) = idr2 * 2 * a0*a(:)/(a0 + a(:))
1526 box%stencils(ix)%v(1, ijk) = -sum(box%stencils(ix)%v(2:, ijk))
1530 call af_stencil_try_constant(box, ix, epsilon(1.0_dp), success)
1532 end subroutine mg_box_lpld_stencil
1535 subroutine mg_box_lpld_lsf_stencil(box, mg, ix)
1536 type(box_t),
intent(inout) :: box
1537 type(mg_t),
intent(in) :: mg
1538 integer,
intent(in) :: ix
1540 real(dp) :: idr2(2*NDIM), a0, a(2*NDIM), dr2(NDIM)
1541 integer :: n, m, idim, s_ix(NDIM), ix_dist
1542 real(dp) :: dd(2*NDIM)
1543 real(dp),
allocatable :: all_distances(:, DTIMES(:))
1547 idr2(1:2*ndim:2) = 1/box%dr**2
1548 idr2(2:2*ndim:2) = idr2(1:2*ndim:2)
1551 box%stencils(ix)%shape = af_stencil_357
1552 box%stencils(ix)%stype = stencil_variable
1556 box%stencils(ix)%cylindrical_gradient = (box%coord_t == af_cyl)
1557 call af_stencil_allocate_coeff(box%stencils(ix), box%n_cell, use_f=.true.)
1558 allocate(all_distances(2*ndim, dtimes(nc)))
1560 box%stencils(ix)%f = 0.0_dp
1562 all_distances = 1.0_dp
1564 ix_dist = af_stencil_index(box, mg_lsf_distance_key)
1565 if (ix_dist == af_stencil_none) error stop
"No distances stored"
1568 do n = 1,
size(box%stencils(ix_dist)%sparse_ix, 2)
1569 s_ix = box%stencils(ix_dist)%sparse_ix(:, n)
1570 all_distances(:, dindex(s_ix)) = &
1571 box%stencils(ix_dist)%sparse_v(:, n)
1574 associate(cc => box%cc, n => mg%i_phi, i_eps => mg%i_eps)
1576 dd = all_distances(:, ijk)
1579 a0 = box%cc(i, i_eps)
1580 a(1:2) = box%cc(i-1:i+1:2, i_eps)
1582 a0 = box%cc(i, j, i_eps)
1583 a(1:2) = box%cc(i-1:i+1:2, j, i_eps)
1584 a(3:4) = box%cc(i, j-1:j+1:2, i_eps)
1586 a0 = box%cc(i, j, k, i_eps)
1587 a(1:2) = box%cc(i-1:i+1:2, j, k, i_eps)
1588 a(3:4) = box%cc(i, j-1:j+1:2, k, i_eps)
1589 a(5:6) = box%cc(i, j, k-1:k+1:2, i_eps)
1593 box%stencils(ix)%v(1+2*idim-1, ijk) = 1 / &
1594 (0.5_dp * dr2(idim) * (dd(2*idim-1) + dd(2*idim)) * &
1596 box%stencils(ix)%v(1+2*idim, ijk) = 1 / &
1597 (0.5_dp * dr2(idim) * (dd(2*idim-1) + dd(2*idim)) * &
1603 where (dd(:) < 1.0_dp) a(:) = a0
1605 box%stencils(ix)%v(2:, ijk) = box%stencils(ix)%v(2:, ijk) * &
1606 2 * a0*a(:)/(a0 + a(:))
1608 box%stencils(ix)%v(1, ijk) = -sum(box%stencils(ix)%v(2:, ijk))
1612 if (dd(m) < 1.0_dp)
then
1613 box%stencils(ix)%f(ijk) = box%stencils(ix)%f(ijk) - &
1614 box%stencils(ix)%v(m+1, ijk)
1615 box%stencils(ix)%v(m+1, ijk) = 0.0_dp
1621 call af_stencil_try_constant(box, ix, epsilon(1.0_dp), success)
1623 end subroutine mg_box_lpld_lsf_stencil
1627 function mg_lsf_dist_linear(a, b, mg)
result(dist)
1628 real(dp),
intent(in) :: a(ndim)
1629 real(dp),
intent(in) :: b(ndim)
1630 type(mg_t),
intent(in) :: mg
1631 real(dp) :: dist, lsf_a, lsf_b
1636 if (lsf_a * lsf_b < 0)
then
1638 dist = lsf_a / (lsf_a - lsf_b)
1639 dist = max(dist, mg%lsf_min_rel_distance)
1643 end function mg_lsf_dist_linear
1649 function mg_lsf_dist_gss(a, b, mg)
result(dist)
1650 real(dp),
intent(in) :: a(ndim)
1651 real(dp),
intent(in) :: b(ndim)
1652 type(mg_t),
intent(in) :: mg
1653 real(dp) :: bracket(ndim, 2), b_new(ndim)
1654 real(dp) :: dist, r_root(ndim), lsf_a, lsf_b
1655 integer,
parameter :: max_iter = 100
1661 if (lsf_a * lsf_b <= 0)
then
1662 r_root = bisection(mg%lsf, a, b, mg%lsf_tol, max_iter)
1665 bracket = gss(mg%lsf, a, b, minimization=(lsf_a >= 0), &
1666 tol=mg%lsf_tol, find_bracket=.true.)
1669 if (mg%lsf(bracket(:, 1)) * lsf_a <= 0)
then
1670 b_new = bracket(:, 1)
1672 b_new = bracket(:, 2)
1675 if (mg%lsf(b_new) * lsf_a > 0)
then
1678 r_root = bisection(mg%lsf, a, b_new, mg%lsf_tol, max_iter)
1682 dist = norm2(r_root - a)/norm2(b-a)
1683 dist = max(dist, mg%lsf_min_rel_distance)
1684 end function mg_lsf_dist_gss
1687 function bisection(f, in_a, in_b, tol, max_iter)
result(c)
1688 procedure(mg_func_lsf) :: f
1689 real(dp),
intent(in) :: in_a(ndim), in_b(ndim), tol
1690 integer,
intent(in) :: max_iter
1691 real(dp) :: a(ndim), b(ndim), c(ndim), fc
1700 if (0.5 * norm2(b-a) < tol .or. abs(fc) <= 0)
exit
1702 if (fc * f(a) >= 0)
then
1708 end function bisection
1714 function gss(f, in_a, in_b, minimization, tol, find_bracket)
result(bracket)
1715 procedure(mg_func_lsf) :: f
1716 real(dp),
intent(in) :: in_a(ndim)
1717 real(dp),
intent(in) :: in_b(ndim)
1719 logical,
intent(in) :: minimization
1720 real(dp),
intent(in) :: tol
1721 logical,
intent(in) :: find_bracket
1722 real(dp) :: bracket(ndim, 2)
1723 real(dp) :: a(ndim), b(ndim), c(ndim), d(ndim)
1724 real(dp) :: h(ndim), yc, yd, ya
1725 real(dp) :: invphi, invphi2
1728 invphi = (sqrt(5.0_dp) - 1) / 2
1729 invphi2 = (3 - sqrt(5.0_dp)) / 2
1735 if (norm2(h) <= tol)
then
1742 n = int(ceiling(log(tol / norm2(h)) / log(invphi)))
1751 if ((yc < yd) .eqv. minimization)
then
1768 if (find_bracket .and. ya * yc <= 0 .and. ya * yd <= 0)
exit
1771 if ((yc < yd) .eqv. minimization)
then
1782 subroutine mg_box_lsf_stencil(box, mg, ix)
1783 type(box_t),
intent(inout) :: box
1784 type(mg_t),
intent(in) :: mg
1785 integer,
intent(in) :: ix
1786 integer :: IJK, n, nc, idim
1787 integer :: s_ix(NDIM), ix_dist
1788 real(dp) :: dd(2*NDIM), dr2(NDIM)
1789 real(dp),
allocatable :: all_distances(:, DTIMES(:))
1797 ix_dist = af_stencil_index(box, mg_lsf_distance_key)
1798 if (ix_dist == af_stencil_none) error stop
"No distances stored"
1801 box%stencils(ix)%shape = af_stencil_357
1802 box%stencils(ix)%stype = stencil_variable
1804 box%stencils(ix)%cylindrical_gradient = .false.
1805 call af_stencil_allocate_coeff(box%stencils(ix), box%n_cell, use_f=.true.)
1806 box%stencils(ix)%f = 0.0_dp
1808 allocate(all_distances(2*ndim, dtimes(nc)))
1811 all_distances = 1.0_dp
1814 do n = 1,
size(box%stencils(ix_dist)%sparse_ix, 2)
1815 s_ix = box%stencils(ix_dist)%sparse_ix(:, n)
1816 all_distances(:, dindex(s_ix)) = &
1817 box%stencils(ix_dist)%sparse_v(:, n)
1821 dd = all_distances(:, ijk)
1825 box%stencils(ix)%v(1+2*idim-1, ijk) = 1 / &
1826 (0.5_dp * dr2(idim) * (dd(2*idim-1) + dd(2*idim)) * &
1828 box%stencils(ix)%v(1+2*idim, ijk) = 1 / &
1829 (0.5_dp * dr2(idim) * (dd(2*idim-1) + dd(2*idim)) * &
1834 if (box%coord_t == af_cyl)
then
1837 tmp = 1/(box%dr(1) * (dd(1) + dd(2)) * af_cyl_radius_cc(box, i))
1838 box%stencils(ix)%v(2, ijk) = box%stencils(ix)%v(2, ijk) - tmp
1839 box%stencils(ix)%v(3, ijk) = box%stencils(ix)%v(3, ijk) + tmp
1842 box%stencils(ix)%v(1, ijk) = -sum(box%stencils(ix)%v(2:, ijk))
1846 if (dd(n) < 1.0_dp)
then
1847 box%stencils(ix)%f(ijk) = box%stencils(ix)%f(ijk) - &
1848 box%stencils(ix)%v(n+1, ijk)
1849 box%stencils(ix)%v(n+1, ijk) = 0.0_dp
1854 end subroutine mg_box_lsf_stencil
1857 subroutine mg_compute_phi_gradient(tree, mg, i_fc, fac, i_norm)
1858 type(af_t),
intent(inout) :: tree
1859 type(mg_t),
intent(in) :: mg
1860 integer,
intent(in) :: i_fc
1861 real(dp),
intent(in) :: fac
1863 integer,
intent(in),
optional :: i_norm
1864 integer :: lvl, i, id
1867 do lvl = 1, tree%highest_lvl
1869 do i = 1,
size(tree%lvls(lvl)%ids)
1870 id = tree%lvls(lvl)%ids(i)
1871 select case (iand(tree%boxes(id)%tag, mg%operator_mask))
1872 case (mg_normal_box, mg_ceps_box)
1873 call mg_box_lpl_gradient(tree, id, mg, i_fc, fac)
1874 case (mg_lsf_box, mg_ceps_box+mg_lsf_box, mg_veps_box+mg_lsf_box)
1876 if (af_has_children(tree%boxes(id)))
then
1879 call mg_box_lpl_gradient(tree, id, mg, i_fc, fac)
1881 call mg_box_lpllsf_gradient(tree, id, mg, i_fc, fac)
1885 call mg_box_lpl_gradient(tree, id, mg, i_fc, fac)
1887 error stop
"box tag not set"
1889 error stop
"unknown box tag"
1892 if (
present(i_norm))
then
1893 call mg_box_field_norm(tree, id, i_fc, i_norm)
1899 end subroutine mg_compute_phi_gradient
1902 subroutine mg_box_lpl_gradient(tree, id, mg, i_fc, fac)
1903 type(af_t),
intent(inout) :: tree
1904 integer,
intent(in) :: id
1905 type(mg_t),
intent(in) :: mg
1906 integer,
intent(in) :: i_fc
1907 real(dp),
intent(in) :: fac
1908 integer :: nc, i_phi, i_eps
1909 real(dp) :: inv_dr(ndim)
1911 associate(box => tree%boxes(id), cc => tree%boxes(id)%cc)
1914 inv_dr = fac / box%dr
1917 box%fc(1:nc+1, 1, i_fc) = inv_dr(1) * &
1918 (cc(1:nc+1, i_phi) - cc(0:nc, i_phi))
1920 box%fc(1:nc+1, 1:nc, 1, i_fc) = inv_dr(1) * &
1921 (cc(1:nc+1, 1:nc, i_phi) - cc(0:nc, 1:nc, i_phi))
1922 box%fc(1:nc, 1:nc+1, 2, i_fc) = inv_dr(2) * &
1923 (cc(1:nc, 1:nc+1, i_phi) - cc(1:nc, 0:nc, i_phi))
1925 box%fc(1:nc+1, 1:nc, 1:nc, 1, i_fc) = inv_dr(1) * &
1926 (cc(1:nc+1, 1:nc, 1:nc, i_phi) - &
1927 cc(0:nc, 1:nc, 1:nc, i_phi))
1928 box%fc(1:nc, 1:nc+1, 1:nc, 2, i_fc) = inv_dr(2) * &
1929 (cc(1:nc, 1:nc+1, 1:nc, i_phi) - &
1930 cc(1:nc, 0:nc, 1:nc, i_phi))
1931 box%fc(1:nc, 1:nc, 1:nc+1, 3, i_fc) = inv_dr(3) * &
1932 (cc(1:nc, 1:nc, 1:nc+1, i_phi) - &
1933 cc(1:nc, 1:nc, 0:nc, i_phi))
1936 if (iand(box%tag, mg%operator_mask) == mg_veps_box)
then
1941 box%fc(1, 1, i_fc) = 2 * inv_dr(1) * &
1942 (cc(1, i_phi) - cc(0, i_phi)) * &
1944 (cc(1, i_eps) + cc(0, i_eps))
1945 box%fc(nc+1, 1, i_fc) = 2 * inv_dr(1) * &
1946 (cc(nc+1, i_phi) - cc(nc, i_phi)) * &
1948 (cc(nc+1, i_eps) + cc(nc, i_eps))
1950 box%fc(1, 1:nc, 1, i_fc) = 2 * inv_dr(1) * &
1951 (cc(1, 1:nc, i_phi) - cc(0, 1:nc, i_phi)) * &
1952 cc(0, 1:nc, i_eps) / &
1953 (cc(1, 1:nc, i_eps) + cc(0, 1:nc, i_eps))
1954 box%fc(nc+1, 1:nc, 1, i_fc) = 2 * inv_dr(1) * &
1955 (cc(nc+1, 1:nc, i_phi) - cc(nc, 1:nc, i_phi)) * &
1956 cc(nc+1, 1:nc, i_eps) / &
1957 (cc(nc+1, 1:nc, i_eps) + cc(nc, 1:nc, i_eps))
1958 box%fc(1:nc, 1, 2, i_fc) = 2 * inv_dr(2) * &
1959 (cc(1:nc, 1, i_phi) - cc(1:nc, 0, i_phi)) * &
1960 cc(1:nc, 0, i_eps) / &
1961 (cc(1:nc, 1, i_eps) + cc(1:nc, 0, i_eps))
1962 box%fc(1:nc, nc+1, 2, i_fc) = 2 * inv_dr(2) * &
1963 (cc(1:nc, nc+1, i_phi) - cc(1:nc, nc, i_phi)) * &
1964 cc(1:nc, nc+1, i_eps) / &
1965 (cc(1:nc, nc+1, i_eps) + cc(1:nc, nc, i_eps))
1967 box%fc(1, 1:nc, 1:nc, 1, i_fc) = 2 * inv_dr(1) * &
1968 (cc(1, 1:nc, 1:nc, i_phi) - cc(0, 1:nc, 1:nc, i_phi)) * &
1969 cc(0, 1:nc, 1:nc, i_eps) / &
1970 (cc(1, 1:nc, 1:nc, i_eps) + cc(0, 1:nc, 1:nc, i_eps))
1971 box%fc(nc+1, 1:nc, 1:nc, 1, i_fc) = 2 * inv_dr(1) * &
1972 (cc(nc+1, 1:nc, 1:nc, i_phi) - cc(nc, 1:nc, 1:nc, i_phi)) * &
1973 cc(nc+1, 1:nc, 1:nc, i_eps) / &
1974 (cc(nc+1, 1:nc, 1:nc, i_eps) + cc(nc, 1:nc, 1:nc, i_eps))
1975 box%fc(1:nc, 1, 1:nc, 2, i_fc) = 2 * inv_dr(2) * &
1976 (cc(1:nc, 1, 1:nc, i_phi) - cc(1:nc, 0, 1:nc, i_phi)) * &
1977 cc(1:nc, 0, 1:nc, i_eps) / &
1978 (cc(1:nc, 1, 1:nc, i_eps) + cc(1:nc, 0, 1:nc, i_eps))
1979 box%fc(1:nc, nc+1, 1:nc, 2, i_fc) = 2 * inv_dr(2) * &
1980 (cc(1:nc, nc+1, 1:nc, i_phi) - cc(1:nc, nc, 1:nc, i_phi)) * &
1981 cc(1:nc, nc+1, 1:nc, i_eps) / &
1982 (cc(1:nc, nc+1, 1:nc, i_eps) + cc(1:nc, nc, 1:nc, i_eps))
1983 box%fc(1:nc, 1:nc, 1, 3, i_fc) = 2 * inv_dr(3) * &
1984 (cc(1:nc, 1:nc, 1, i_phi) - cc(1:nc, 1:nc, 0, i_phi)) * &
1985 cc(1:nc, 1:nc, 0, i_eps) / &
1986 (cc(1:nc, 1:nc, 1, i_eps) + cc(1:nc, 1:nc, 0, i_eps))
1987 box%fc(1:nc, 1:nc, nc+1, 3, i_fc) = 2 * inv_dr(3) * &
1988 (cc(1:nc, 1:nc, nc+1, i_phi) - cc(1:nc, 1:nc, nc, i_phi)) * &
1989 cc(1:nc, 1:nc, nc+1, i_eps) / &
1990 (cc(1:nc, 1:nc, nc+1, i_eps) + cc(1:nc, 1:nc, nc, i_eps))
1994 end subroutine mg_box_lpl_gradient
1997 subroutine mg_compute_field_norm(tree, i_fc, i_norm)
1998 type(af_t),
intent(inout) :: tree
1999 integer,
intent(in) :: i_fc
2000 integer,
intent(in) :: i_norm
2001 integer :: lvl, i, id
2004 do lvl = 1, tree%highest_lvl
2006 do i = 1,
size(tree%lvls(lvl)%ids)
2007 id = tree%lvls(lvl)%ids(i)
2008 call mg_box_field_norm(tree, id, i_fc, i_norm)
2013 end subroutine mg_compute_field_norm
2015 subroutine mg_box_field_norm(tree, id, i_fc, i_norm)
2016 type(af_t),
intent(inout) :: tree
2017 integer,
intent(in) :: id
2018 integer,
intent(in) :: i_fc
2020 integer,
intent(in) :: i_norm
2023 associate(box => tree%boxes(id))
2026 box%cc(1:nc, i_norm) = 0.5_dp * sqrt(&
2027 (box%fc(1:nc, 1, i_fc) + &
2028 box%fc(2:nc+1, 1, i_fc))**2)
2030 box%cc(1:nc, 1:nc, i_norm) = 0.5_dp * sqrt(&
2031 (box%fc(1:nc, 1:nc, 1, i_fc) + &
2032 box%fc(2:nc+1, 1:nc, 1, i_fc))**2 + &
2033 (box%fc(1:nc, 1:nc, 2, i_fc) + &
2034 box%fc(1:nc, 2:nc+1, 2, i_fc))**2)
2036 box%cc(1:nc, 1:nc, 1:nc, i_norm) = 0.5_dp * sqrt(&
2037 (box%fc(1:nc, 1:nc, 1:nc, 1, i_fc) + &
2038 box%fc(2:nc+1, 1:nc, 1:nc, 1, i_fc))**2 + &
2039 (box%fc(1:nc, 1:nc, 1:nc, 2, i_fc) + &
2040 box%fc(1:nc, 2:nc+1, 1:nc, 2, i_fc))**2 + &
2041 (box%fc(1:nc, 1:nc, 1:nc, 3, i_fc) + &
2042 box%fc(1:nc, 1:nc, 2:nc+1, 3, i_fc))**2)
2045 end subroutine mg_box_field_norm
2050 subroutine mg_box_lpllsf_gradient(tree, id, mg, i_fc, fac)
2051 type(af_t),
intent(inout) :: tree
2052 integer,
intent(in) :: id
2053 type(mg_t),
intent(in) :: mg
2054 integer,
intent(in) :: i_fc
2055 real(dp),
intent(in) :: fac
2057 integer :: n, nc, i_phi, ix_dist
2058 real(dp) :: inv_dr(NDIM), dd(2*NDIM)
2059 real(dp) :: bc(DTIMES(tree%n_cell))
2062 call mg_box_lpl_gradient(tree, id, mg, i_fc, fac)
2064 ix_dist = af_stencil_index(tree%boxes(id), mg_lsf_distance_key)
2065 if (ix_dist == af_stencil_none) error stop
"No distances stored"
2067 associate(box => tree%boxes(id), cc => tree%boxes(id)%cc)
2070 inv_dr = fac / box%dr
2071 bc = mg_lsf_boundary_value(box, mg)
2074 do n = 1,
size(box%stencils(ix_dist)%sparse_ix, 2)
2075 dd = box%stencils(ix_dist)%sparse_v(:, n)
2078 i = box%stencils(ix_dist)%sparse_ix(1, n)
2080 if (dd(1) < 1 .and. cc(ijk, mg%i_lsf) >= 0)
then
2081 box%fc(i, 1, i_fc) = inv_dr(1) * &
2082 (cc(i, i_phi) - bc(ijk)) / dd(1)
2084 if (dd(2) < 1 .and. cc(ijk, mg%i_lsf) >= 0)
then
2085 box%fc(i+1, 1, i_fc) = inv_dr(1) * &
2086 (bc(ijk) - cc(i, i_phi)) / dd(2)
2089 i = box%stencils(ix_dist)%sparse_ix(1, n)
2090 j = box%stencils(ix_dist)%sparse_ix(2, n)
2092 if (dd(1) < 1 .and. cc(ijk, mg%i_lsf) >= 0)
then
2093 box%fc(i, j, 1, i_fc) = inv_dr(1) * &
2094 (cc(i, j, i_phi) - bc(ijk)) / dd(1)
2096 if (dd(2) < 1 .and. cc(ijk, mg%i_lsf) >= 0)
then
2097 box%fc(i+1, j, 1, i_fc) = inv_dr(1) * &
2098 (bc(ijk) - cc(i, j, i_phi)) / dd(2)
2100 if (dd(3) < 1 .and. cc(ijk, mg%i_lsf) >= 0)
then
2101 box%fc(i, j, 2, i_fc) = inv_dr(2) * &
2102 (cc(i, j, i_phi) - bc(ijk)) / dd(3)
2104 if (dd(4) < 1 .and. cc(ijk, mg%i_lsf) >= 0)
then
2105 box%fc(i, j+1, 2, i_fc) = inv_dr(2) * &
2106 (bc(ijk) - cc(i, j, i_phi)) / dd(4)
2109 i = box%stencils(ix_dist)%sparse_ix(1, n)
2110 j = box%stencils(ix_dist)%sparse_ix(2, n)
2111 k = box%stencils(ix_dist)%sparse_ix(3, n)
2113 if (dd(1) < 1 .and. cc(ijk, mg%i_lsf) >= 0)
then
2114 box%fc(i, j, k, 1, i_fc) = inv_dr(1) * &
2115 (cc(ijk, i_phi) - bc(ijk)) / dd(1)
2117 if (dd(2) < 1 .and. cc(ijk, mg%i_lsf) >= 0)
then
2118 box%fc(i+1, j, k, 1, i_fc) = inv_dr(1) * &
2119 (bc(ijk) - cc(ijk, i_phi)) / dd(2)
2121 if (dd(3) < 1 .and. cc(ijk, mg%i_lsf) >= 0)
then
2122 box%fc(i, j, k, 2, i_fc) = inv_dr(2) * &
2123 (cc(ijk, i_phi) - bc(ijk)) / dd(3)
2125 if (dd(4) < 1 .and. cc(ijk, mg%i_lsf) >= 0)
then
2126 box%fc(i, j+1, k, 2, i_fc) = inv_dr(2) * &
2127 (bc(ijk) - cc(ijk, i_phi)) / dd(4)
2129 if (dd(5) < 1 .and. cc(ijk, mg%i_lsf) >= 0)
then
2130 box%fc(i, j, k, 3, i_fc) = inv_dr(3) * &
2131 (cc(ijk, i_phi) - bc(ijk)) / dd(5)
2133 if (dd(6) < 1 .and. cc(ijk, mg%i_lsf) >= 0)
then
2134 box%fc(i, j, k+1, 3, i_fc) = inv_dr(3) * &
2135 (bc(ijk) - cc(ijk, i_phi)) / dd(6)
2140 end subroutine mg_box_lpllsf_gradient
2144 subroutine check_coarse_representation_lsf(tree, mg)
2145 type(af_t),
intent(in) :: tree
2146 type(mg_t),
intent(in) :: mg
2147 integer :: i, id, ix
2149 do i = 1,
size(tree%lvls(1)%ids)
2150 id = tree%lvls(1)%ids(i)
2151 ix = af_stencil_index(tree%boxes(id), mg_lsf_distance_key)
2152 if (ix > af_stencil_none)
exit
2155 if (i ==
size(tree%lvls(1)%ids)+1)
then
2156 print *,
"No roots found for level set function on coarse grid"
2157 print *,
"you should probably use a finer coarse grid"
2158 error stop
"level set function not resolved on coarse grid"
2161 end subroutine check_coarse_representation_lsf
2164 function numerical_gradient(f, r)
result(gradient)
2165 procedure(mg_func_lsf) :: f
2166 real(dp),
intent(in) :: r(ndim)
2167 real(dp),
parameter :: sqrteps = sqrt(epsilon(1.0_dp))
2168 real(dp),
parameter :: min_stepsize = epsilon(1.0_dp)
2169 real(dp) :: r_eval(ndim), gradient(ndim)
2170 real(dp) :: stepsize(ndim), flo, fhi
2173 stepsize = max(min_stepsize, sqrteps * abs(r))
2178 r_eval(idim) = r(idim) - stepsize(idim)
2181 r_eval(idim) = r(idim) + stepsize(idim)
2185 gradient(idim) = (fhi - flo)/(2 * stepsize(idim))
2188 r_eval(idim) = r(idim)
2190 end function numerical_gradient
This module contains the core routines of Afivo, namely those that deal with initializing and changin...
This module contains routines related to the filling of ghost cells. Note that corner ghost cells are...
This module contains the geometric multigrid routines that come with Afivo.
This module contains routines for restriction: going from fine to coarse variables.
This module contains functionality for dealing with numerical stencils.
This module contains the basic types and constants that are used in the NDIM-dimensional version of A...
This module contains all kinds of different 'helper' routines for Afivo. If the number of routines fo...
Module to solve elliptic PDEs on the coarse grid. This module contains an interface to Hypre,...
Type which stores all the boxes and levels, as well as some information about the number of boxes,...
The basic building block of afivo: a box with cell-centered and face centered data,...
Type to store multigrid options in.