30 integer,
parameter,
public ::
dp = kind(0.0d0)
33 integer,
parameter,
public ::
i8 = selected_int_kind(18)
112 [0,0,0, 1,0,0, 0,1,0, 1,1,0, &
113 0,0,1, 1,0,1, 0,1,1, 1,1,1], [3,8])
116 [2,1,4,3,6,5,8,7, 3,4,1,2,7,8,5,6, 5,6,7,8,1,2,3,4], [8,3])
119 [1,3,5,7, 2,4,6,8, 1,2,5,6, 3,4,7,8, 1,2,3,4, 5,6,7,8], [4,6])
122 .true., .true., .true., .false., .true., .true., &
123 .true., .false., .true., .false., .false., .true., &
124 .true., .true., .false., .false., .true., .false., &
125 .true., .false., .false., .false., .false., .false.], [3, 8])
137 [-1,0,0, 1,0,0, 0,-1,0, 0,1,0, 0,0,-1, 0,0,1], [3,6])
140 [.true., .false., .true., .false., .true., .false.]
150 integer,
allocatable :: leaves(:)
151 integer,
allocatable :: parents(:)
152 integer,
allocatable :: ref_bnds(:)
153 integer,
allocatable :: ids(:)
154 integer,
allocatable :: my_leaves(:)
155 integer,
allocatable :: my_parents(:)
156 integer,
allocatable :: my_ref_bnds(:)
157 integer,
allocatable :: my_ids(:)
167 integer :: children(2**3)
168 integer :: neighbors(2*3)
172 real(
dp),
allocatable :: cc(:, :, :, :)
180 integer,
allocatable :: ix(:)
181 real(
dp),
allocatable :: send(:)
182 real(
dp),
allocatable :: recv(:)
186 integer,
allocatable :: n_send(:, :)
187 integer,
allocatable :: n_recv(:, :)
192 real(
dp) :: bc_value = 0.0_dp
194 procedure(
mg_subr_bc),
pointer,
nopass :: boundary_cond => null()
196 procedure(
mg_subr_rb),
pointer,
nopass :: refinement_bnd => null()
200 character(len=20) :: name
201 real(
dp) :: t = 0.0_dp
207 logical :: tree_created = .false.
209 logical :: is_allocated = .false.
211 integer :: n_extra_vars = 0
215 integer :: n_cpu = -1
217 integer :: my_rank = -1
219 integer :: box_size = -1
221 integer :: highest_lvl = -1
223 integer :: lowest_lvl = -1
226 integer :: first_normal_lvl = -1
228 integer :: n_boxes = 0
253 logical :: phi_bc_data_stored = .false.
256 logical :: periodic(3) = .false.
267 logical :: subtract_mean = .false.
271 integer :: n_smoother_substeps = 1
273 integer :: n_cycle_down = 2
275 integer :: n_cycle_up = 2
277 integer :: max_coarse_cycles = 1000
278 integer :: coarsest_grid(3) = 2
280 real(
dp) :: residual_coarse_abs = 1e-8_dp
282 real(
dp) :: residual_coarse_rel = 1e-8_dp
285 procedure(
mg_box_op),
pointer,
nopass :: box_op => null()
294 integer :: n_timers = 0
304 integer,
intent(in) :: nc
305 integer,
intent(in) :: iv
306 integer,
intent(in) :: nb
307 integer,
intent(out) :: bc_type
309 real(dp),
intent(out) :: bc(nc, nc)
315 type(
mg_box_t),
intent(inout) :: box
316 integer,
intent(in) :: nc
317 integer,
intent(in) :: iv
318 integer,
intent(in) :: nb
320 real(dp),
intent(in) :: cgc(nc, nc)
326 type(
mg_t),
intent(inout) :: mg
327 integer,
intent(in) :: id
328 integer,
intent(in) :: nc
329 integer,
intent(in) :: i_out
335 type(
mg_t),
intent(inout) :: mg
336 integer,
intent(in) :: id
337 integer,
intent(in) :: nc
338 integer,
intent(in) :: redblack_cntr
344 type(
mg_t),
intent(inout) :: mg
345 integer,
intent(in) :: p_id
346 integer,
intent(in) :: dix(3)
347 integer,
intent(in) :: nc
348 integer,
intent(in) :: iv
349 real(dp),
intent(out) :: fine(nc, nc, nc)
462 integer :: timer_total_vcycle = -1
463 integer :: timer_total_fmg = -1
464 integer :: timer_smoother = -1
465 integer :: timer_smoother_gc = -1
466 integer :: timer_coarse = -1
467 integer :: timer_correct = -1
468 integer :: timer_update_coarse = -1
485 Integer,
Parameter :: kdp = selected_real_kind(15)
490 module procedure i_mrgrnk
520 integer,
intent(in) :: ix(3)
523 2 * iand(ix(2), 1) - iand(ix(1), 1)
530 type(
mg_t),
intent(in) :: mg
531 integer,
intent(in) :: id
532 integer :: ix_offset(3)
534 if (mg%boxes(id)%lvl <= mg%first_normal_lvl)
then
537 ix_offset = iand(mg%boxes(id)%ix-1, 1) * &
538 ishft(mg%box_size, -1)
543 type(
mg_t),
intent(in) :: mg
546 do lvl = mg%first_normal_lvl, mg%highest_lvl-1
548 if (
size(mg%lvls(lvl)%leaves) /= 0 .and. &
549 size(mg%lvls(lvl)%parents) /= 0)
exit
556 type(
mg_t),
intent(in) :: mg
558 integer(i8) :: n_unknowns
561 do lvl = mg%first_normal_lvl, mg%highest_lvl
562 n_unknowns = n_unknowns +
size(mg%lvls(lvl)%leaves)
564 n_unknowns = n_unknowns * int(mg%box_size**3,
i8)
570 integer,
intent(in) :: nb
571 integer,
intent(in) :: nc
572 real(
dp),
intent(out) :: x(nc, nc, 3)
573 integer :: i, j, ixs(3-1)
580 ixs = [(i, i = 1, 3-1)]
581 ixs(nb_dim:) = ixs(nb_dim:) + 1
585 rmin(nb_dim) = rmin(nb_dim) + box%dr(nb_dim) * nc
591 x(i, j, ixs) = x(i, j, ixs) + ([i, j] - 0.5d0) * box%dr(ixs)
597 type(
mg_t),
intent(inout) :: mg
598 character(len=*),
intent(in) :: name
600 mg%n_timers = mg%n_timers + 1
608 timer%t0 = mpi_wtime()
614 timer%t = timer%t + mpi_wtime() - timer%t0
619 type(
mg_t),
intent(in) :: mg
621 real(
dp) :: tmin(mg%n_timers)
622 real(
dp) :: tmax(mg%n_timers)
623 real(
dp),
allocatable :: tmp_array(:)
625 allocate(tmp_array(mg%n_timers))
626 tmp_array(:) = mg%timers(1:mg%n_timers)%t
628 call mpi_reduce(tmp_array, tmin, mg%n_timers, &
629 mpi_double, mpi_min, 0, mg%comm, ierr)
630 call mpi_reduce(tmp_array, tmax, mg%n_timers, &
631 mpi_double, mpi_max, 0, mg%comm, ierr)
633 if (mg%my_rank == 0)
then
634 write(*,
"(A20,2A16)")
"name ",
"min(s)",
"max(s)"
635 do n = 1, mg%n_timers
636 write(*,
"(A20,2F16.6)") mg%timers(n)%name, &
646 type(
mg_t),
intent(inout) :: mg
649 if (.not. mg%is_allocated) &
650 error stop
"deallocate_storage: tree is not allocated"
655 deallocate(mg%comm_restrict%n_send)
656 deallocate(mg%comm_restrict%n_recv)
658 deallocate(mg%comm_prolong%n_send)
659 deallocate(mg%comm_prolong%n_recv)
661 deallocate(mg%comm_ghostcell%n_send)
662 deallocate(mg%comm_ghostcell%n_recv)
664 do lvl = mg%lowest_lvl, mg%highest_lvl
665 deallocate(mg%lvls(lvl)%ids)
666 deallocate(mg%lvls(lvl)%leaves)
667 deallocate(mg%lvls(lvl)%parents)
668 deallocate(mg%lvls(lvl)%ref_bnds)
669 deallocate(mg%lvls(lvl)%my_ids)
670 deallocate(mg%lvls(lvl)%my_leaves)
671 deallocate(mg%lvls(lvl)%my_parents)
672 deallocate(mg%lvls(lvl)%my_ref_bnds)
675 mg%is_allocated = .false.
677 mg%phi_bc_data_stored = .false.
684 type(
mg_t),
intent(inout) :: mg
685 integer :: i, id, lvl, nc
686 integer :: n_send(0:mg%n_cpu-1, 3)
687 integer :: n_recv(0:mg%n_cpu-1, 3)
689 integer :: n_in, n_out, n_id
691 if (.not. mg%tree_created) &
692 error stop
"allocate_storage: tree is not yet created"
694 if (mg%is_allocated) &
695 error stop
"allocate_storage: tree is already allocated"
697 do lvl = mg%lowest_lvl, mg%highest_lvl
698 nc = mg%box_size_lvl(lvl)
699 do i = 1,
size(mg%lvls(lvl)%my_ids)
700 id = mg%lvls(lvl)%my_ids(i)
701 allocate(mg%boxes(id)%cc(0:nc+1, 0:nc+1, 0:nc+1, &
705 mg%boxes(id)%cc(:, :, :, :) = 0.0_dp
709 allocate(mg%buf(0:mg%n_cpu-1))
712 n_recv(:, 1), dsize(1))
714 n_recv(:, 2), dsize(2))
716 n_recv(:, 3), dsize(3))
719 n_out = maxval(n_send(i, :) * dsize(:))
720 n_in = maxval(n_recv(i, :) * dsize(:))
721 n_id = maxval(n_send(i, :))
722 allocate(mg%buf(i)%send(n_out))
723 allocate(mg%buf(i)%recv(n_in))
724 allocate(mg%buf(i)%ix(n_id))
727 mg%is_allocated = .true.
737 type(
mg_t),
intent(inout) :: mg
738 real(
dp),
intent(in) :: dt
739 real(
dp),
intent(in) :: diffusion_coeff
740 integer,
intent(in) :: order
741 real(
dp),
intent(in) :: max_res
742 integer,
parameter :: max_its = 10
752 call set_rhs(mg, -1/(dt * diffusion_coeff), 0.0_dp)
757 call set_rhs(mg, -2/(dt * diffusion_coeff), -1.0_dp)
759 error stop
"diffusion_solve: order should be 1 or 2"
767 if (res <= max_res)
exit
771 if (n == max_its + 1)
then
772 if (mg%my_rank == 0) &
773 print *,
"Did you specify boundary conditions correctly?"
774 error stop
"diffusion_solve: no convergence"
784 type(
mg_t),
intent(inout) :: mg
785 real(
dp),
intent(in) :: dt
786 integer,
intent(in) :: order
787 real(
dp),
intent(in) :: max_res
788 integer,
parameter :: max_its = 10
798 call set_rhs(mg, -1/dt, 0.0_dp)
803 call set_rhs(mg, -2/dt, -1.0_dp)
805 error stop
"diffusion_solve: order should be 1 or 2"
813 if (res <= max_res)
exit
817 if (n == max_its + 1)
then
818 if (mg%my_rank == 0)
then
819 print *,
"Did you specify boundary conditions correctly?"
820 print *,
"Or is the variation in diffusion too large?"
822 error stop
"diffusion_solve: no convergence"
833 type(
mg_t),
intent(inout) :: mg
834 real(
dp),
intent(in) :: dt
835 integer,
intent(in) :: order
836 real(
dp),
intent(in) :: max_res
837 integer,
parameter :: max_its = 10
847 call set_rhs(mg, -1/dt, 0.0_dp)
852 call set_rhs(mg, -2/dt, -1.0_dp)
854 error stop
"diffusion_solve: order should be 1 or 2"
862 if (res <= max_res)
exit
866 if (n == max_its + 1)
then
867 if (mg%my_rank == 0)
then
868 print *,
"Did you specify boundary conditions correctly?"
869 print *,
"Or is the variation in diffusion too large?"
871 error stop
"diffusion_solve: no convergence"
875 subroutine set_rhs(mg, f1, f2)
876 type(
mg_t),
intent(inout) :: mg
877 real(
dp),
intent(in) :: f1, f2
878 integer :: lvl, i, id, nc
880 do lvl = 1, mg%highest_lvl
881 nc = mg%box_size_lvl(lvl)
882 do i = 1,
size(mg%lvls(lvl)%my_leaves)
883 id = mg%lvls(lvl)%my_leaves(i)
884 mg%boxes(id)%cc(1:nc, 1:nc, 1:nc,
mg_irhs) = &
885 f1 * mg%boxes(id)%cc(1:nc, 1:nc, 1:nc,
mg_iphi) + &
886 f2 * mg%boxes(id)%cc(1:nc, 1:nc, 1:nc,
mg_irhs)
889 end subroutine set_rhs
894 type(
mg_t),
intent(inout) :: mg
896 if (all(mg%periodic))
then
899 mg%subtract_mean = .true.
902 select case (mg%geometry_type)
906 select case (mg%smoother_type)
910 mg%box_smoother => box_gs_lpl
912 error stop
"laplacian_set_methods: unsupported smoother type"
915 error stop
"laplacian_set_methods: unsupported geometry"
921 subroutine box_gs_lpl(mg, id, nc, redblack_cntr)
922 type(
mg_t),
intent(inout) :: mg
923 integer,
intent(in) :: id
924 integer,
intent(in) :: nc
925 integer,
intent(in) :: redblack_cntr
926 integer :: i, j, k, i0, di
927 real(
dp) :: idr2(3), fac
929 real(
dp),
parameter :: sixth = 1/6.0_dp
931 idr2 = 1/mg%dr(:, mg%boxes(id)%lvl)**2
932 fac = 0.5_dp / sum(idr2)
944 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi)
948 i0 = 2 - iand(ieor(redblack_cntr, k+j), 1)
950 cc(i, j, k, n) = fac * ( &
951 idr2(1) * (cc(i+1, j, k, n) + cc(i-1, j, k, n)) + &
952 idr2(2) * (cc(i, j+1, k, n) + cc(i, j-1, k, n)) + &
953 idr2(3) * (cc(i, j, k+1, n) + cc(i, j, k-1, n)) - &
959 end subroutine box_gs_lpl
1000 subroutine box_lpl(mg, id, nc, i_out)
1001 type(
mg_t),
intent(inout) :: mg
1002 integer,
intent(in) :: id
1003 integer,
intent(in) :: nc
1004 integer,
intent(in) :: i_out
1008 idr2 = 1 / mg%dr(:, mg%boxes(id)%lvl)**2
1010 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi)
1014 cc(i, j, k, i_out) = &
1015 idr2(1) * (cc(i-1, j, k, n) + cc(i+1, j, k, n) &
1016 - 2 * cc(i, j, k, n)) &
1017 + idr2(2) * (cc(i, j-1, k, n) + cc(i, j+1, k, n) &
1018 - 2 * cc(i, j, k, n)) &
1019 + idr2(3) * (cc(i, j, k-1, n) + cc(i, j, k+1, n) &
1020 - 2 * cc(i, j, k, n))
1025 end subroutine box_lpl
1031 type(
mg_t),
intent(inout) :: mg
1033 if (mg%n_extra_vars == 0 .and. mg%is_allocated)
then
1034 error stop
"vhelmholtz_set_methods: mg%n_extra_vars == 0"
1036 mg%n_extra_vars = max(1, mg%n_extra_vars)
1039 mg%subtract_mean = .false.
1044 mg%bc(:,
mg_iveps)%bc_value = 0.0_dp
1046 select case (mg%geometry_type)
1048 mg%box_op => box_vhelmh
1050 select case (mg%smoother_type)
1052 mg%box_smoother => box_gs_vhelmh
1054 error stop
"vhelmholtz_set_methods: unsupported smoother type"
1057 error stop
"vhelmholtz_set_methods: unsupported geometry"
1063 real(
dp),
intent(in) :: lambda
1066 error stop
"vhelmholtz_set_lambda: lambda < 0 not allowed"
1072 subroutine box_gs_vhelmh(mg, id, nc, redblack_cntr)
1073 type(
mg_t),
intent(inout) :: mg
1074 integer,
intent(in) :: id
1075 integer,
intent(in) :: nc
1076 integer,
intent(in) :: redblack_cntr
1077 integer :: i, j, k, i0, di
1079 real(
dp) :: idr2(2*3), u(2*3)
1080 real(
dp) :: a0, a(2*3), c(2*3)
1083 idr2(1:2*3:2) = 1/mg%dr(:, mg%boxes(id)%lvl)**2
1084 idr2(2:2*3:2) = idr2(1:2*3:2)
1096 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi, &
1101 i0 = 2 - iand(ieor(redblack_cntr, k+j), 1)
1103 a0 = cc(i, j, k, i_eps)
1104 u(1:2) = cc(i-1:i+1:2, j, k, n)
1105 a(1:2) = cc(i-1:i+1:2, j, k, i_eps)
1106 u(3:4) = cc(i, j-1:j+1:2, k, n)
1107 a(3:4) = cc(i, j-1:j+1:2, k, i_eps)
1108 u(5:6) = cc(i, j, k-1:k+1:2, n)
1109 a(5:6) = cc(i, j, k-1:k+1:2, i_eps)
1110 c(:) = 2 * a0 * a(:) / (a0 + a(:)) * idr2
1112 cc(i, j, k, n) = (sum(c(:) * u(:)) - &
1119 end subroutine box_gs_vhelmh
1122 subroutine box_vhelmh(mg, id, nc, i_out)
1123 type(
mg_t),
intent(inout) :: mg
1124 integer,
intent(in) :: id
1125 integer,
intent(in) :: nc
1126 integer,
intent(in) :: i_out
1128 real(
dp) :: idr2(2*3), a0, u0, u(2*3), a(2*3)
1131 idr2(1:2*3:2) = 1/mg%dr(:, mg%boxes(id)%lvl)**2
1132 idr2(2:2*3:2) = idr2(1:2*3:2)
1134 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi, &
1140 a0 = cc(i, j, k, i_eps)
1141 u(1:2) = cc(i-1:i+1:2, j, k, n)
1142 u(3:4) = cc(i, j-1:j+1:2, k, n)
1143 u(5:6) = cc(i, j, k-1:k+1:2, n)
1144 a(1:2) = cc(i-1:i+1:2, j, k, i_eps)
1145 a(3:4) = cc(i, j-1:j+1:2, k, i_eps)
1146 a(5:6) = cc(i, j, k-1:k+1:2, i_eps)
1148 cc(i, j, k, i_out) = sum(2 * idr2 * &
1149 a0*a(:)/(a0 + a(:)) * (u(:) - u0)) - &
1155 end subroutine box_vhelmh
1161 type(
mg_t),
intent(inout) :: mg
1162 integer,
intent(in) :: domain_size(3)
1163 integer,
intent(in) :: box_size
1164 real(
dp),
intent(in) :: dx(3)
1165 real(
dp),
intent(in) :: r_min(3)
1166 logical,
intent(in) :: periodic(3)
1167 integer,
intent(in) :: n_finer
1168 integer :: i, j, k, lvl, n, id, nx(3), ijk_vec(3), idim
1169 integer :: boxes_per_dim(3,
mg_lvl_lo:1)
1170 integer :: periodic_offset(3)
1172 if (modulo(box_size, 2) /= 0) &
1173 error stop
"box_size should be even"
1174 if (any(modulo(domain_size, box_size) /= 0)) &
1175 error stop
"box_size does not divide domain_size"
1177 if (all(periodic))
then
1178 mg%subtract_mean = .true.
1182 mg%box_size = box_size
1183 mg%box_size_lvl(1) = box_size
1184 mg%domain_size_lvl(:, 1) = domain_size
1185 mg%first_normal_lvl = 1
1188 mg%periodic = periodic
1189 boxes_per_dim(:, :) = 0
1190 boxes_per_dim(:, 1) = domain_size / box_size
1195 if (any(modulo(nx, 2) == 1 .or. nx == mg%coarsest_grid .or. &
1196 (mg%box_size_lvl(lvl) == mg%coarsest_grid .and. &
1199 if (all(modulo(nx/mg%box_size_lvl(lvl), 2) == 0))
then
1200 mg%box_size_lvl(lvl-1) = mg%box_size_lvl(lvl)
1201 boxes_per_dim(:, lvl-1) = boxes_per_dim(:, lvl)/2
1202 mg%first_normal_lvl = lvl-1
1204 mg%box_size_lvl(lvl-1) = mg%box_size_lvl(lvl)/2
1205 boxes_per_dim(:, lvl-1) = boxes_per_dim(:, lvl)
1208 mg%dr(:, lvl-1) = mg%dr(:, lvl) * 2
1210 mg%domain_size_lvl(:, lvl-1) = nx
1217 mg%dr(:, lvl) = mg%dr(:, lvl-1) * 0.5_dp
1218 mg%box_size_lvl(lvl) = box_size
1219 mg%domain_size_lvl(:, lvl) = 2 * mg%domain_size_lvl(:, lvl-1)
1222 n = sum(product(boxes_per_dim, dim=1)) + n_finer
1223 allocate(mg%boxes(n))
1226 nx = boxes_per_dim(:, mg%lowest_lvl)
1227 periodic_offset = [nx(1)-1, (nx(2)-1)*nx(1), &
1228 (nx(3)-1) * nx(2) * nx(1)]
1230 do k=1,nx(3);
do j=1,nx(2);
do i=1,nx(1)
1231 mg%n_boxes = mg%n_boxes + 1
1234 mg%boxes(n)%rank = 0
1236 mg%boxes(n)%lvl = mg%lowest_lvl
1237 mg%boxes(n)%ix(:) = [i, j, k]
1238 mg%boxes(n)%r_min(:) = r_min + (mg%boxes(n)%ix(:) - 1) * &
1239 mg%box_size_lvl(mg%lowest_lvl) * mg%dr(:, mg%lowest_lvl)
1240 mg%boxes(n)%dr(:) = mg%dr(:, mg%lowest_lvl)
1245 mg%boxes(n)%neighbors(:) = [n-1, n+1, n-nx(1), n+nx(1), &
1246 n-nx(1)*nx(2), n+nx(1)*nx(2)]
1251 if (ijk_vec(idim) == 1)
then
1252 if (periodic(idim))
then
1253 mg%boxes(n)%neighbors(2*idim-1) = n + periodic_offset(idim)
1259 if (ijk_vec(idim) == nx(idim))
then
1260 if (periodic(idim))
then
1261 mg%boxes(n)%neighbors(2*idim) = n - periodic_offset(idim)
1267 end do;
end do;
end do
1269 mg%lvls(mg%lowest_lvl)%ids = [(n, n=1, mg%n_boxes)]
1272 do lvl = mg%lowest_lvl, 0
1273 if (mg%box_size_lvl(lvl+1) == mg%box_size_lvl(lvl))
then
1274 do i = 1,
size(mg%lvls(lvl)%ids)
1275 id = mg%lvls(lvl)%ids(i)
1283 do i = 1,
size(mg%lvls(lvl)%ids)
1284 id = mg%lvls(lvl)%ids(i)
1285 call add_single_child(mg, id,
size(mg%lvls(lvl)%ids))
1296 do lvl = mg%lowest_lvl, 1
1297 if (
allocated(mg%lvls(lvl)%ref_bnds)) &
1298 deallocate(mg%lvls(lvl)%ref_bnds)
1299 allocate(mg%lvls(lvl)%ref_bnds(0))
1302 mg%tree_created = .true.
1306 type(
mg_t),
intent(inout) :: mg
1307 integer,
intent(in) :: lvl
1310 do i = 1,
size(mg%lvls(lvl)%ids)
1311 id = mg%lvls(lvl)%ids(i)
1312 call set_neighbs(mg%boxes, id)
1317 type(
mg_t),
intent(inout) :: mg
1318 integer,
intent(in) :: lvl
1321 if (
allocated(mg%lvls(lvl+1)%ids)) &
1322 deallocate(mg%lvls(lvl+1)%ids)
1325 if (mg%box_size_lvl(lvl+1) == mg%box_size_lvl(lvl))
then
1327 allocate(mg%lvls(lvl+1)%ids(n))
1330 do i = 1,
size(mg%lvls(lvl)%parents)
1331 id = mg%lvls(lvl)%parents(i)
1332 mg%lvls(lvl+1)%ids(n*(i-1)+1:n*i) = mg%boxes(id)%children
1335 n =
size(mg%lvls(lvl)%parents)
1336 allocate(mg%lvls(lvl+1)%ids(n))
1339 do i = 1,
size(mg%lvls(lvl)%parents)
1340 id = mg%lvls(lvl)%parents(i)
1341 mg%lvls(lvl+1)%ids(i) = mg%boxes(id)%children(1)
1348 subroutine set_neighbs(boxes, id)
1349 type(
mg_box_t),
intent(inout) :: boxes(:)
1350 integer,
intent(in) :: id
1351 integer :: nb, nb_id
1354 if (boxes(id)%neighbors(nb) ==
mg_no_box)
then
1355 nb_id = find_neighb(boxes, id, nb)
1357 boxes(id)%neighbors(nb) = nb_id
1362 end subroutine set_neighbs
1365 function find_neighb(boxes, id, nb)
result(nb_id)
1366 type(
mg_box_t),
intent(in) :: boxes(:)
1367 integer,
intent(in) :: id
1368 integer,
intent(in) :: nb
1369 integer :: nb_id, p_id, c_ix, d, old_pid
1371 p_id = boxes(id)%parent
1379 p_id = boxes(p_id)%neighbors(nb)
1384 end function find_neighb
1388 type(
mg_box_t),
intent(in) :: boxes(:)
1389 type(
mg_lvl_t),
intent(inout) :: level
1390 integer :: i, id, i_leaf, i_parent
1391 integer :: n_parents, n_leaves
1394 n_leaves =
size(level%ids) - n_parents
1396 if (.not.
allocated(level%parents))
then
1397 allocate(level%parents(n_parents))
1398 else if (n_parents /=
size(level%parents))
then
1399 deallocate(level%parents)
1400 allocate(level%parents(n_parents))
1403 if (.not.
allocated(level%leaves))
then
1404 allocate(level%leaves(n_leaves))
1405 else if (n_leaves /=
size(level%leaves))
then
1406 deallocate(level%leaves)
1407 allocate(level%leaves(n_leaves))
1412 do i = 1,
size(level%ids)
1415 i_parent = i_parent + 1
1416 level%parents(i_parent) = id
1419 level%leaves(i_leaf) = id
1426 type(
mg_box_t),
intent(in) :: boxes(:)
1427 type(
mg_lvl_t),
intent(inout) :: level
1428 integer,
allocatable :: tmp(:)
1429 integer :: i, id, nb, nb_id, ix
1431 if (
allocated(level%ref_bnds))
deallocate(level%ref_bnds)
1433 if (
size(level%parents) == 0)
then
1435 allocate(level%ref_bnds(0))
1437 allocate(tmp(
size(level%leaves)))
1439 do i = 1,
size(level%leaves)
1440 id = level%leaves(i)
1443 nb_id = boxes(id)%neighbors(nb)
1454 allocate(level%ref_bnds(ix))
1455 level%ref_bnds(:) = tmp(1:ix)
1460 type(
mg_t),
intent(inout) :: mg
1461 integer,
intent(in) :: id
1462 integer :: lvl, i, nb, child_nb(2**(3-1))
1464 integer :: c_id, c_ix_base(3)
1467 error stop
"mg_add_children: not enough space"
1472 mg%boxes(id)%children = c_ids
1473 c_ix_base = 2 * mg%boxes(id)%ix - 1
1474 lvl = mg%boxes(id)%lvl+1
1478 mg%boxes(c_id)%rank = mg%boxes(id)%rank
1480 mg%boxes(c_id)%lvl = lvl
1481 mg%boxes(c_id)%parent = id
1484 mg%boxes(c_id)%r_min = mg%boxes(id)%r_min + &
1486 mg%boxes(c_id)%dr(:) = mg%dr(:, lvl)
1491 if (mg%boxes(id)%neighbors(nb) <
mg_no_box)
then
1493 mg%boxes(child_nb)%neighbors(nb) = mg%boxes(id)%neighbors(nb)
1498 subroutine add_single_child(mg, id, n_boxes_lvl)
1499 type(
mg_t),
intent(inout) :: mg
1500 integer,
intent(in) :: id
1501 integer,
intent(in) :: n_boxes_lvl
1502 integer :: lvl, c_id
1504 c_id = mg%n_boxes + 1
1505 mg%n_boxes = mg%n_boxes + 1
1506 mg%boxes(id)%children(1) = c_id
1507 lvl = mg%boxes(id)%lvl+1
1509 mg%boxes(c_id)%rank = mg%boxes(id)%rank
1510 mg%boxes(c_id)%ix = mg%boxes(id)%ix
1511 mg%boxes(c_id)%lvl = lvl
1512 mg%boxes(c_id)%parent = id
1515 mg%boxes(c_id)%neighbors = mg%boxes(id)%neighbors
1517 mg%boxes(c_id)%neighbors = mg%boxes(id)%neighbors + n_boxes_lvl
1519 mg%boxes(c_id)%r_min = mg%boxes(id)%r_min
1520 mg%boxes(c_id)%dr(:) = mg%dr(:, lvl)
1522 end subroutine add_single_child
1532 type(
mg_t),
intent(inout) :: mg
1533 integer :: i, id, lvl, single_cpu_lvl
1534 integer :: work_left, my_work, i_cpu
1538 single_cpu_lvl = max(mg%first_normal_lvl-1, mg%lowest_lvl)
1540 do lvl = mg%lowest_lvl, single_cpu_lvl
1541 do i = 1,
size(mg%lvls(lvl)%ids)
1542 id = mg%lvls(lvl)%ids(i)
1543 mg%boxes(id)%rank = 0
1549 do lvl = single_cpu_lvl+1, mg%highest_lvl
1550 work_left =
size(mg%lvls(lvl)%ids)
1554 do i = 1,
size(mg%lvls(lvl)%ids)
1555 if ((mg%n_cpu - i_cpu - 1) * my_work >= work_left)
then
1560 my_work = my_work + 1
1561 work_left = work_left - 1
1563 id = mg%lvls(lvl)%ids(i)
1564 mg%boxes(id)%rank = i_cpu
1568 do lvl = mg%lowest_lvl, mg%highest_lvl
1569 call update_lvl_info(mg, mg%lvls(lvl))
1581 type(
mg_t),
intent(inout) :: mg
1582 integer :: i, id, lvl, single_cpu_lvl
1583 integer :: work_left, my_work(0:mg%n_cpu), i_cpu
1586 integer :: coarse_rank
1590 single_cpu_lvl = max(mg%first_normal_lvl-1, mg%lowest_lvl)
1594 do lvl = mg%highest_lvl, single_cpu_lvl+1, -1
1598 do i = 1,
size(mg%lvls(lvl)%parents)
1599 id = mg%lvls(lvl)%parents(i)
1601 c_ids = mg%boxes(id)%children
1602 c_ranks = mg%boxes(c_ids)%rank
1603 i_cpu = most_popular(c_ranks, my_work, mg%n_cpu)
1604 mg%boxes(id)%rank = i_cpu
1605 my_work(i_cpu) = my_work(i_cpu) + 1
1608 work_left =
size(mg%lvls(lvl)%leaves)
1611 do i = 1,
size(mg%lvls(lvl)%leaves)
1613 if ((mg%n_cpu - i_cpu - 1) * my_work(i_cpu) >= &
1614 work_left + sum(my_work(i_cpu+1:)))
then
1618 my_work(i_cpu) = my_work(i_cpu) + 1
1619 work_left = work_left - 1
1621 id = mg%lvls(lvl)%leaves(i)
1622 mg%boxes(id)%rank = i_cpu
1627 if (single_cpu_lvl < mg%highest_lvl)
then
1628 coarse_rank = most_popular(mg%boxes(&
1629 mg%lvls(single_cpu_lvl+1)%ids)%rank, my_work, mg%n_cpu)
1634 do lvl = mg%lowest_lvl, single_cpu_lvl
1635 do i = 1,
size(mg%lvls(lvl)%ids)
1636 id = mg%lvls(lvl)%ids(i)
1637 mg%boxes(id)%rank = coarse_rank
1641 do lvl = mg%lowest_lvl, mg%highest_lvl
1642 call update_lvl_info(mg, mg%lvls(lvl))
1650 type(
mg_t),
intent(inout) :: mg
1651 integer :: i, id, lvl, n_boxes
1654 integer :: single_cpu_lvl, coarse_rank
1655 integer :: my_work(0:mg%n_cpu), i_cpu
1656 integer,
allocatable :: ranks(:)
1660 single_cpu_lvl = max(mg%first_normal_lvl-1, mg%lowest_lvl)
1662 do lvl = mg%highest_lvl-1, single_cpu_lvl+1, -1
1666 do i = 1,
size(mg%lvls(lvl)%leaves)
1667 id = mg%lvls(lvl)%leaves(i)
1668 i_cpu = mg%boxes(id)%rank
1669 my_work(i_cpu) = my_work(i_cpu) + 1
1672 do i = 1,
size(mg%lvls(lvl)%parents)
1673 id = mg%lvls(lvl)%parents(i)
1675 c_ids = mg%boxes(id)%children
1676 c_ranks = mg%boxes(c_ids)%rank
1677 i_cpu = most_popular(c_ranks, my_work, mg%n_cpu)
1678 mg%boxes(id)%rank = i_cpu
1679 my_work(i_cpu) = my_work(i_cpu) + 1
1685 if (single_cpu_lvl < mg%highest_lvl)
then
1687 n_boxes =
size(mg%lvls(single_cpu_lvl+1)%ids)
1688 allocate(ranks(n_boxes))
1689 ranks(:) = mg%boxes(mg%lvls(single_cpu_lvl+1)%ids)%rank
1691 coarse_rank = most_popular(ranks, my_work, mg%n_cpu)
1697 do lvl = mg%lowest_lvl, single_cpu_lvl
1698 do i = 1,
size(mg%lvls(lvl)%ids)
1699 id = mg%lvls(lvl)%ids(i)
1700 mg%boxes(id)%rank = coarse_rank
1704 do lvl = mg%lowest_lvl, mg%highest_lvl
1705 call update_lvl_info(mg, mg%lvls(lvl))
1712 pure integer function most_popular(list, work, n_cpu)
1713 integer,
intent(in) :: list(:)
1714 integer,
intent(in) :: n_cpu
1715 integer,
intent(in) :: work(0:n_cpu-1)
1716 integer :: i, best_count, current_count
1717 integer :: my_work, best_work
1723 do i = 1,
size(list)
1724 current_count = count(list == list(i))
1725 my_work = work(list(i))
1728 if (current_count > best_count .or. &
1729 current_count == best_count .and. my_work < best_work)
then
1730 best_count = current_count
1732 most_popular = list(i)
1736 end function most_popular
1738 subroutine update_lvl_info(mg, lvl)
1739 type(
mg_t),
intent(inout) :: mg
1740 type(
mg_lvl_t),
intent(inout) :: lvl
1742 lvl%my_ids = pack(lvl%ids, &
1743 mg%boxes(lvl%ids)%rank == mg%my_rank)
1744 lvl%my_leaves = pack(lvl%leaves, &
1745 mg%boxes(lvl%leaves)%rank == mg%my_rank)
1746 lvl%my_parents = pack(lvl%parents, &
1747 mg%boxes(lvl%parents)%rank == mg%my_rank)
1748 lvl%my_ref_bnds = pack(lvl%ref_bnds, &
1749 mg%boxes(lvl%ref_bnds)%rank == mg%my_rank)
1750 end subroutine update_lvl_info
1755 type(
mg_t),
intent(inout) :: mg
1757 if (mg%n_extra_vars == 0 .and. mg%is_allocated)
then
1758 error stop
"vlaplacian_set_methods: mg%n_extra_vars == 0"
1760 mg%n_extra_vars = max(1, mg%n_extra_vars)
1763 mg%subtract_mean = .false.
1768 mg%bc(:,
mg_iveps)%bc_value = 0.0_dp
1770 select case (mg%geometry_type)
1772 mg%box_op => box_vlpl
1777 select case (mg%smoother_type)
1779 mg%box_smoother => box_gs_vlpl
1781 error stop
"vlaplacian_set_methods: unsupported smoother type"
1785 error stop
"vlaplacian_set_methods: unsupported geometry"
1791 subroutine box_gs_vlpl(mg, id, nc, redblack_cntr)
1792 type(
mg_t),
intent(inout) :: mg
1793 integer,
intent(in) :: id
1794 integer,
intent(in) :: nc
1795 integer,
intent(in) :: redblack_cntr
1796 integer :: i, j, k, i0, di
1798 real(
dp) :: idr2(2*3), u(2*3)
1799 real(
dp) :: a0, a(2*3), c(2*3)
1802 idr2(1:2*3:2) = 1/mg%dr(:, mg%boxes(id)%lvl)**2
1803 idr2(2:2*3:2) = idr2(1:2*3:2)
1815 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi, &
1820 i0 = 2 - iand(ieor(redblack_cntr, k+j), 1)
1822 a0 = cc(i, j, k, i_eps)
1823 u(1:2) = cc(i-1:i+1:2, j, k, n)
1824 a(1:2) = cc(i-1:i+1:2, j, k, i_eps)
1825 u(3:4) = cc(i, j-1:j+1:2, k, n)
1826 a(3:4) = cc(i, j-1:j+1:2, k, i_eps)
1827 u(5:6) = cc(i, j, k-1:k+1:2, n)
1828 a(5:6) = cc(i, j, k-1:k+1:2, i_eps)
1829 c(:) = 2 * a0 * a(:) / (a0 + a(:)) * idr2
1831 cc(i, j, k, n) = (sum(c(:) * u(:)) - &
1832 cc(i, j, k,
mg_irhs)) / sum(c(:))
1837 end subroutine box_gs_vlpl
1840 subroutine box_vlpl(mg, id, nc, i_out)
1841 type(
mg_t),
intent(inout) :: mg
1842 integer,
intent(in) :: id
1843 integer,
intent(in) :: nc
1844 integer,
intent(in) :: i_out
1846 real(
dp) :: idr2(2*3), a0, u0, u(2*3), a(2*3)
1849 idr2(1:2*3:2) = 1/mg%dr(:, mg%boxes(id)%lvl)**2
1850 idr2(2:2*3:2) = idr2(1:2*3:2)
1852 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi, &
1858 a0 = cc(i, j, k, i_eps)
1859 u(1:2) = cc(i-1:i+1:2, j, k, n)
1860 u(3:4) = cc(i, j-1:j+1:2, k, n)
1861 u(5:6) = cc(i, j, k-1:k+1:2, n)
1862 a(1:2) = cc(i-1:i+1:2, j, k, i_eps)
1863 a(3:4) = cc(i, j-1:j+1:2, k, i_eps)
1864 a(5:6) = cc(i, j, k-1:k+1:2, i_eps)
1866 cc(i, j, k, i_out) = sum(2 * idr2 * &
1867 a0*a(:)/(a0 + a(:)) * (u(:) - u0))
1872 end subroutine box_vlpl
1980 type(
mg_t),
intent(inout) :: mg
1982 integer,
intent(in),
optional :: comm
1984 logical :: initialized
1986 call mpi_initialized(initialized, ierr)
1987 if (.not. initialized)
then
1991 if (
present(comm))
then
1994 mg%comm = mpi_comm_world
1997 call mpi_comm_rank(mg%comm, mg%my_rank, ierr)
1998 call mpi_comm_size(mg%comm, mg%n_cpu, ierr)
2003 type(
mg_t),
intent(inout) :: mg
2004 integer,
intent(in) :: dsize
2005 integer :: i, n_send, n_recv
2006 integer :: send_req(mg%n_cpu)
2007 integer :: recv_req(mg%n_cpu)
2013 do i = 0, mg%n_cpu - 1
2014 if (mg%buf(i)%i_send > 0)
then
2016 call sort_sendbuf(mg%buf(i), dsize)
2017 call mpi_isend(mg%buf(i)%send, mg%buf(i)%i_send, mpi_double, &
2018 i, 0, mg%comm, send_req(n_send), ierr)
2020 if (mg%buf(i)%i_recv > 0)
then
2022 call mpi_irecv(mg%buf(i)%recv, mg%buf(i)%i_recv, mpi_double, &
2023 i, 0, mg%comm, recv_req(n_recv), ierr)
2027 call mpi_waitall(n_recv, recv_req(1:n_recv), mpi_statuses_ignore, ierr)
2028 call mpi_waitall(n_send, send_req(1:n_send), mpi_statuses_ignore, ierr)
2033 subroutine sort_sendbuf(gc, dsize)
2035 type(
mg_buf_t),
intent(inout) :: gc
2036 integer,
intent(in) :: dsize
2037 integer :: ix_sort(gc%i_ix)
2038 real(
dp) :: buf_cpy(gc%i_send)
2041 call mrgrnk(gc%ix(1:gc%i_ix), ix_sort)
2043 buf_cpy = gc%send(1:gc%i_send)
2047 j = (ix_sort(n)-1) * dsize
2048 gc%send(i+1:i+dsize) = buf_cpy(j+1:j+dsize)
2050 gc%ix(1:gc%i_ix) = gc%ix(ix_sort)
2052 end subroutine sort_sendbuf
2058 type(
mg_t),
intent(inout) :: mg
2059 integer,
intent(out) :: n_send(0:mg%n_cpu-1)
2060 integer,
intent(out) :: n_recv(0:mg%n_cpu-1)
2061 integer,
intent(out) :: dsize
2062 integer :: i, id, lvl, nc
2064 allocate(mg%comm_ghostcell%n_send(0:mg%n_cpu-1, &
2065 mg%first_normal_lvl:mg%highest_lvl))
2066 allocate(mg%comm_ghostcell%n_recv(0:mg%n_cpu-1, &
2067 mg%first_normal_lvl:mg%highest_lvl))
2069 dsize = mg%box_size**(3-1)
2071 do lvl = mg%first_normal_lvl, mg%highest_lvl
2072 nc = mg%box_size_lvl(lvl)
2073 mg%buf(:)%i_send = 0
2074 mg%buf(:)%i_recv = 0
2077 do i = 1,
size(mg%lvls(lvl)%my_ids)
2078 id = mg%lvls(lvl)%my_ids(i)
2079 call buffer_ghost_cells(mg, id, nc, 1, dry_run=.true.)
2083 do i = 1,
size(mg%lvls(lvl-1)%my_ref_bnds)
2084 id = mg%lvls(lvl-1)%my_ref_bnds(i)
2085 call buffer_refinement_boundaries(mg, id, nc, 1, dry_run=.true.)
2090 mg%buf(:)%i_recv = 0
2091 do i = 1,
size(mg%lvls(lvl)%my_ids)
2092 id = mg%lvls(lvl)%my_ids(i)
2093 call set_ghost_cells(mg, id, nc, 1, dry_run=.true.)
2096 mg%comm_ghostcell%n_send(:, lvl) = mg%buf(:)%i_send/dsize
2097 mg%comm_ghostcell%n_recv(:, lvl) = mg%buf(:)%i_recv/dsize
2100 n_send = maxval(mg%comm_ghostcell%n_send, dim=2)
2101 n_recv = maxval(mg%comm_ghostcell%n_recv, dim=2)
2107 type(
mg_t),
intent(inout) :: mg
2112 do lvl = mg%lowest_lvl, mg%highest_lvl
2113 nc = mg%box_size_lvl(lvl)
2114 call mg_phi_bc_store_lvl(mg, lvl, nc)
2117 mg%phi_bc_data_stored = .true.
2120 subroutine mg_phi_bc_store_lvl(mg, lvl, nc)
2121 type(
mg_t),
intent(inout) :: mg
2122 integer,
intent(in) :: lvl
2123 integer,
intent(in) :: nc
2124 real(
dp) :: bc(nc, nc)
2125 integer :: i, id, nb, nb_id, bc_type
2127 do i = 1,
size(mg%lvls(lvl)%my_ids)
2128 id = mg%lvls(lvl)%my_ids(i)
2130 nb_id = mg%boxes(id)%neighbors(nb)
2133 if (
associated(mg%bc(nb,
mg_iphi)%boundary_cond))
then
2134 call mg%bc(nb,
mg_iphi)%boundary_cond(mg%boxes(id), nc, &
2137 bc_type = mg%bc(nb,
mg_iphi)%bc_type
2138 bc = mg%bc(nb,
mg_iphi)%bc_value
2144 mg%boxes(id)%neighbors(nb) = bc_type
2147 call box_set_gc(mg%boxes(id), nb, nc,
mg_irhs, bc)
2151 end subroutine mg_phi_bc_store_lvl
2156 integer,
intent(in) :: iv
2159 do lvl = mg%lowest_lvl, mg%highest_lvl
2168 integer,
intent(in) :: lvl
2169 integer,
intent(in) :: iv
2170 integer :: i, id, dsize, nc
2172 if (lvl < mg%lowest_lvl) &
2173 error stop
"fill_ghost_cells_lvl: lvl < lowest_lvl"
2174 if (lvl > mg%highest_lvl) &
2175 error stop
"fill_ghost_cells_lvl: lvl > highest_lvl"
2177 nc = mg%box_size_lvl(lvl)
2179 if (lvl >= mg%first_normal_lvl)
then
2181 mg%buf(:)%i_send = 0
2182 mg%buf(:)%i_recv = 0
2185 do i = 1,
size(mg%lvls(lvl)%my_ids)
2186 id = mg%lvls(lvl)%my_ids(i)
2187 call buffer_ghost_cells(mg, id, nc, iv, .false.)
2191 do i = 1,
size(mg%lvls(lvl-1)%my_ref_bnds)
2192 id = mg%lvls(lvl-1)%my_ref_bnds(i)
2193 call buffer_refinement_boundaries(mg, id, nc, iv, .false.)
2198 mg%buf(:)%i_recv = mg%comm_ghostcell%n_recv(:, lvl) * dsize
2202 mg%buf(:)%i_recv = 0
2205 do i = 1,
size(mg%lvls(lvl)%my_ids)
2206 id = mg%lvls(lvl)%my_ids(i)
2207 call set_ghost_cells(mg, id, nc, iv, .false.)
2211 subroutine buffer_ghost_cells(mg, id, nc, iv, dry_run)
2212 type(
mg_t),
intent(inout) :: mg
2213 integer,
intent(in) :: id
2214 integer,
intent(in) :: nc
2215 integer,
intent(in) :: iv
2216 logical,
intent(in) :: dry_run
2217 integer :: nb, nb_id, nb_rank
2220 nb_id = mg%boxes(id)%neighbors(nb)
2224 nb_rank = mg%boxes(nb_id)%rank
2226 if (nb_rank /= mg%my_rank)
then
2227 call buffer_for_nb(mg, mg%boxes(id), nc, iv, nb_id, nb_rank, &
2232 end subroutine buffer_ghost_cells
2234 subroutine buffer_refinement_boundaries(mg, id, nc, iv, dry_run)
2235 type(
mg_t),
intent(inout) :: mg
2236 integer,
intent(in) :: id
2237 integer,
intent(in) :: nc
2238 integer,
intent(in) :: iv
2239 logical,
intent(in) :: dry_run
2240 integer :: nb, nb_id, c_ids(2**(3-1))
2241 integer :: n, c_id, c_rank
2244 nb_id = mg%boxes(id)%neighbors(nb)
2247 c_ids = mg%boxes(nb_id)%children(&
2252 c_rank = mg%boxes(c_id)%rank
2254 if (c_rank /= mg%my_rank)
then
2256 call buffer_for_fine_nb(mg, mg%boxes(id), nc, iv, c_id, &
2257 c_rank, nb, dry_run)
2263 end subroutine buffer_refinement_boundaries
2266 subroutine set_ghost_cells(mg, id, nc, iv, dry_run)
2267 type(
mg_t),
intent(inout) :: mg
2268 integer,
intent(in) :: id
2269 integer,
intent(in) :: nc
2270 integer,
intent(in) :: iv
2271 logical,
intent(in) :: dry_run
2272 real(
dp) :: bc(nc, nc)
2273 integer :: nb, nb_id, nb_rank, bc_type
2276 nb_id = mg%boxes(id)%neighbors(nb)
2280 nb_rank = mg%boxes(nb_id)%rank
2282 if (nb_rank /= mg%my_rank)
then
2283 call fill_buffered_nb(mg, mg%boxes(id), nb_rank, &
2284 nb, nc, iv, dry_run)
2285 else if (.not. dry_run)
then
2286 call copy_from_nb(mg%boxes(id), mg%boxes(nb_id), &
2291 call fill_refinement_bnd(mg, id, nb, nc, iv, dry_run)
2292 else if (.not. dry_run)
then
2294 if (mg%phi_bc_data_stored .and. iv ==
mg_iphi)
then
2297 call box_get_gc(mg%boxes(id), nb, nc,
mg_irhs, bc)
2300 if (
associated(mg%bc(nb, iv)%boundary_cond))
then
2301 call mg%bc(nb, iv)%boundary_cond(mg%boxes(id), nc, iv, &
2304 bc_type = mg%bc(nb, iv)%bc_type
2305 bc = mg%bc(nb, iv)%bc_value
2309 call box_set_gc(mg%boxes(id), nb, nc, iv, bc)
2310 call bc_to_gc(mg, id, nc, iv, nb, bc_type)
2313 end subroutine set_ghost_cells
2315 subroutine fill_refinement_bnd(mg, id, nb, nc, iv, dry_run)
2316 type(
mg_t),
intent(inout) :: mg
2317 integer,
intent(in) :: id
2318 integer,
intent(in) :: nc
2319 integer,
intent(in) :: iv
2320 integer,
intent(in) :: nb
2321 logical,
intent(in) :: dry_run
2322 real(
dp) :: gc(nc, nc)
2323 integer :: p_id, p_nb_id, ix_offset(3)
2324 integer :: i, dsize, p_nb_rank
2327 p_id = mg%boxes(id)%parent
2328 p_nb_id = mg%boxes(p_id)%neighbors(nb)
2329 p_nb_rank = mg%boxes(p_nb_id)%rank
2331 if (p_nb_rank /= mg%my_rank)
then
2332 i = mg%buf(p_nb_rank)%i_recv
2333 if (.not. dry_run)
then
2334 gc = reshape(mg%buf(p_nb_rank)%recv(i+1:i+dsize), shape(gc))
2336 mg%buf(p_nb_rank)%i_recv = mg%buf(p_nb_rank)%i_recv + dsize
2337 else if (.not. dry_run)
then
2339 call box_gc_for_fine_neighbor(mg%boxes(p_nb_id),
mg_neighb_rev(nb), &
2340 ix_offset, nc, iv, gc)
2343 if (.not. dry_run)
then
2344 if (
associated(mg%bc(nb, iv)%refinement_bnd))
then
2345 call mg%bc(nb, iv)%refinement_bnd(mg%boxes(id), nc, iv, nb, gc)
2347 call sides_rb(mg%boxes(id), nc, iv, nb, gc)
2350 end subroutine fill_refinement_bnd
2352 subroutine copy_from_nb(box, box_nb, nb, nc, iv)
2353 type(
mg_box_t),
intent(inout) :: box
2354 type(
mg_box_t),
intent(in) :: box_nb
2355 integer,
intent(in) :: nb
2356 integer,
intent(in) :: nc
2357 integer,
intent(in) :: iv
2358 real(
dp) :: gc(nc, nc)
2360 call box_gc_for_neighbor(box_nb,
mg_neighb_rev(nb), nc, iv, gc)
2361 call box_set_gc(box, nb, nc, iv, gc)
2362 end subroutine copy_from_nb
2364 subroutine buffer_for_nb(mg, box, nc, iv, nb_id, nb_rank, nb, dry_run)
2365 type(
mg_t),
intent(inout) :: mg
2366 type(
mg_box_t),
intent(inout) :: box
2367 integer,
intent(in) :: nc
2368 integer,
intent(in) :: iv
2369 integer,
intent(in) :: nb_id
2370 integer,
intent(in) :: nb_rank
2371 integer,
intent(in) :: nb
2372 logical,
intent(in) :: dry_run
2374 real(
dp) :: gc(nc, nc)
2376 i = mg%buf(nb_rank)%i_send
2379 if (.not. dry_run)
then
2380 call box_gc_for_neighbor(box, nb, nc, iv, gc)
2381 mg%buf(nb_rank)%send(i+1:i+dsize) = pack(gc, .true.)
2386 i = mg%buf(nb_rank)%i_ix
2387 if (.not. dry_run)
then
2391 mg%buf(nb_rank)%i_send = mg%buf(nb_rank)%i_send + dsize
2392 mg%buf(nb_rank)%i_ix = mg%buf(nb_rank)%i_ix + 1
2393 end subroutine buffer_for_nb
2395 subroutine buffer_for_fine_nb(mg, box, nc, iv, fine_id, fine_rank, nb, dry_run)
2396 type(
mg_t),
intent(inout) :: mg
2397 type(
mg_box_t),
intent(inout) :: box
2398 integer,
intent(in) :: nc
2399 integer,
intent(in) :: iv
2400 integer,
intent(in) :: fine_id
2401 integer,
intent(in) :: fine_rank
2402 integer,
intent(in) :: nb
2403 logical,
intent(in) :: dry_run
2404 integer :: i, dsize, ix_offset(3)
2405 real(
dp) :: gc(nc, nc)
2407 i = mg%buf(fine_rank)%i_send
2410 if (.not. dry_run)
then
2412 call box_gc_for_fine_neighbor(box, nb, ix_offset, nc, iv, gc)
2413 mg%buf(fine_rank)%send(i+1:i+dsize) = pack(gc, .true.)
2418 i = mg%buf(fine_rank)%i_ix
2419 if (.not. dry_run)
then
2424 mg%buf(fine_rank)%i_send = mg%buf(fine_rank)%i_send + dsize
2425 mg%buf(fine_rank)%i_ix = mg%buf(fine_rank)%i_ix + 1
2426 end subroutine buffer_for_fine_nb
2428 subroutine fill_buffered_nb(mg, box, nb_rank, nb, nc, iv, dry_run)
2429 type(
mg_t),
intent(inout) :: mg
2430 type(
mg_box_t),
intent(inout) :: box
2431 integer,
intent(in) :: nb_rank
2432 integer,
intent(in) :: nb
2433 integer,
intent(in) :: nc
2434 integer,
intent(in) :: iv
2435 logical,
intent(in) :: dry_run
2437 real(
dp) :: gc(nc, nc)
2439 i = mg%buf(nb_rank)%i_recv
2442 if (.not. dry_run)
then
2443 gc = reshape(mg%buf(nb_rank)%recv(i+1:i+dsize), shape(gc))
2444 call box_set_gc(box, nb, nc, iv, gc)
2446 mg%buf(nb_rank)%i_recv = mg%buf(nb_rank)%i_recv + dsize
2448 end subroutine fill_buffered_nb
2450 subroutine box_gc_for_neighbor(box, nb, nc, iv, gc)
2452 integer,
intent(in) :: nb, nc, iv
2453 real(
dp),
intent(out) :: gc(nc, nc)
2457 gc = box%cc(1, 1:nc, 1:nc, iv)
2459 gc = box%cc(nc, 1:nc, 1:nc, iv)
2461 gc = box%cc(1:nc, 1, 1:nc, iv)
2463 gc = box%cc(1:nc, nc, 1:nc, iv)
2465 gc = box%cc(1:nc, 1:nc, 1, iv)
2467 gc = box%cc(1:nc, 1:nc, nc, iv)
2469 end subroutine box_gc_for_neighbor
2472 subroutine box_gc_for_fine_neighbor(box, nb, di, nc, iv, gc)
2474 integer,
intent(in) :: nb
2475 integer,
intent(in) :: di(3)
2476 integer,
intent(in) :: nc, iv
2477 real(
dp),
intent(out) :: gc(nc, nc)
2478 real(
dp) :: tmp(0:nc/2+1, 0:nc/2+1), grad(3-1)
2479 integer :: i, j, hnc
2486 tmp = box%cc(1, di(2):di(2)+hnc+1, di(3):di(3)+hnc+1, iv)
2488 tmp = box%cc(nc, di(2):di(2)+hnc+1, di(3):di(3)+hnc+1, iv)
2490 tmp = box%cc(di(1):di(1)+hnc+1, 1, di(3):di(3)+hnc+1, iv)
2492 tmp = box%cc(di(1):di(1)+hnc+1, nc, di(3):di(3)+hnc+1, iv)
2494 tmp = box%cc(di(1):di(1)+hnc+1, di(2):di(2)+hnc+1, 1, iv)
2496 tmp = box%cc(di(1):di(1)+hnc+1, di(2):di(2)+hnc+1, nc, iv)
2505 grad(1) = 0.125_dp * (tmp(i+1, j) - tmp(i-1, j))
2506 grad(2) = 0.125_dp * (tmp(i, j+1) - tmp(i, j-1))
2507 gc(2*i-1, 2*j-1) = tmp(i, j) - grad(1) - grad(2)
2508 gc(2*i, 2*j-1) = tmp(i, j) + grad(1) - grad(2)
2509 gc(2*i-1, 2*j) = tmp(i, j) - grad(1) + grad(2)
2510 gc(2*i, 2*j) = tmp(i, j) + grad(1) + grad(2)
2513 end subroutine box_gc_for_fine_neighbor
2515 subroutine box_get_gc(box, nb, nc, iv, gc)
2517 integer,
intent(in) :: nb, nc, iv
2518 real(
dp),
intent(out) :: gc(nc, nc)
2522 gc = box%cc(0, 1:nc, 1:nc, iv)
2524 gc = box%cc(nc+1, 1:nc, 1:nc, iv)
2526 gc = box%cc(1:nc, 0, 1:nc, iv)
2528 gc = box%cc(1:nc, nc+1, 1:nc, iv)
2530 gc = box%cc(1:nc, 1:nc, 0, iv)
2532 gc = box%cc(1:nc, 1:nc, nc+1, iv)
2534 end subroutine box_get_gc
2536 subroutine box_set_gc(box, nb, nc, iv, gc)
2537 type(
mg_box_t),
intent(inout) :: box
2538 integer,
intent(in) :: nb, nc, iv
2539 real(
dp),
intent(in) :: gc(nc, nc)
2543 box%cc(0, 1:nc, 1:nc, iv) = gc
2545 box%cc(nc+1, 1:nc, 1:nc, iv) = gc
2547 box%cc(1:nc, 0, 1:nc, iv) = gc
2549 box%cc(1:nc, nc+1, 1:nc, iv) = gc
2551 box%cc(1:nc, 1:nc, 0, iv) = gc
2553 box%cc(1:nc, 1:nc, nc+1, iv) = gc
2555 end subroutine box_set_gc
2557 subroutine bc_to_gc(mg, id, nc, iv, nb, bc_type)
2558 type(
mg_t),
intent(inout) :: mg
2559 integer,
intent(in) :: id
2560 integer,
intent(in) :: nc
2561 integer,
intent(in) :: iv
2562 integer,
intent(in) :: nb
2563 integer,
intent(in) :: bc_type
2564 real(
dp) :: c0, c1, c2, dr
2574 select case (bc_type)
2589 error stop
"bc_to_gc: unknown boundary condition"
2594 mg%boxes(id)%cc(0, 1:nc, 1:nc, iv) = &
2595 c0 * mg%boxes(id)%cc(0, 1:nc, 1:nc, iv) + &
2596 c1 * mg%boxes(id)%cc(1, 1:nc, 1:nc, iv) + &
2597 c2 * mg%boxes(id)%cc(2, 1:nc, 1:nc, iv)
2599 mg%boxes(id)%cc(nc+1, 1:nc, 1:nc, iv) = &
2600 c0 * mg%boxes(id)%cc(nc+1, 1:nc, 1:nc, iv) + &
2601 c1 * mg%boxes(id)%cc(nc, 1:nc, 1:nc, iv) + &
2602 c2 * mg%boxes(id)%cc(nc-1, 1:nc, 1:nc, iv)
2604 mg%boxes(id)%cc(1:nc, 0, 1:nc, iv) = &
2605 c0 * mg%boxes(id)%cc(1:nc, 0, 1:nc, iv) + &
2606 c1 * mg%boxes(id)%cc(1:nc, 1, 1:nc, iv) + &
2607 c2 * mg%boxes(id)%cc(1:nc, 2, 1:nc, iv)
2609 mg%boxes(id)%cc(1:nc, nc+1, 1:nc, iv) = &
2610 c0 * mg%boxes(id)%cc(1:nc, nc+1, 1:nc, iv) + &
2611 c1 * mg%boxes(id)%cc(1:nc, nc, 1:nc, iv) + &
2612 c2 * mg%boxes(id)%cc(1:nc, nc-1, 1:nc, iv)
2614 mg%boxes(id)%cc(1:nc, 1:nc, 0, iv) = &
2615 c0 * mg%boxes(id)%cc(1:nc, 1:nc, 0, iv) + &
2616 c1 * mg%boxes(id)%cc(1:nc, 1:nc, 1, iv) + &
2617 c2 * mg%boxes(id)%cc(1:nc, 1:nc, 2, iv)
2619 mg%boxes(id)%cc(1:nc, 1:nc, nc+1, iv) = &
2620 c0 * mg%boxes(id)%cc(1:nc, 1:nc, nc+1, iv) + &
2621 c1 * mg%boxes(id)%cc(1:nc, 1:nc, nc, iv) + &
2622 c2 * mg%boxes(id)%cc(1:nc, 1:nc, nc-1, iv)
2624 end subroutine bc_to_gc
2627 subroutine sides_rb(box, nc, iv, nb, gc)
2628 type(
mg_box_t),
intent(inout) :: box
2629 integer,
intent(in) :: nc
2630 integer,
intent(in) :: iv
2631 integer,
intent(in) :: nb
2633 real(
dp),
intent(in) :: gc(nc, nc)
2634 integer :: di, dj, dk
2635 integer :: i, j, k, ix, dix
2650 dk = -1 + 2 * iand(k, 1)
2652 dj = -1 + 2 * iand(j, 1)
2653 box%cc(i-di, j, k, iv) = 0.5_dp * gc(j, k) &
2654 + 0.75_dp * box%cc(i, j, k, iv) &
2655 - 0.25_dp * box%cc(i+di, j, k, iv)
2662 dk = -1 + 2 * iand(k, 1)
2664 di = -1 + 2 * iand(i, 1)
2665 box%cc(i, j-dj, k, iv) = 0.5_dp * gc(i, k) &
2666 + 0.75_dp * box%cc(i, j, k, iv) &
2667 - 0.25_dp * box%cc(i, j+dj, k, iv)
2674 dj = -1 + 2 * iand(j, 1)
2676 di = -1 + 2 * iand(i, 1)
2677 box%cc(i, j, k-dk, iv) = 0.5_dp * gc(i, j) &
2678 + 0.75_dp * box%cc(i, j, k, iv) &
2679 - 0.25_dp * box%cc(i, j, k+dk, iv)
2684 end subroutine sides_rb
2690 type(
mg_t),
intent(inout) :: mg
2691 integer,
intent(out) :: n_send(0:mg%n_cpu-1)
2692 integer,
intent(out) :: n_recv(0:mg%n_cpu-1)
2693 integer,
intent(out) :: dsize
2694 integer :: lvl, min_lvl
2696 if (.not.
allocated(mg%comm_restrict%n_send))
then
2697 error stop
"Call restrict_buffer_size before prolong_buffer_size"
2700 min_lvl = max(mg%first_normal_lvl-1, mg%lowest_lvl)
2701 allocate(mg%comm_prolong%n_send(0:mg%n_cpu-1, &
2702 min_lvl:mg%highest_lvl))
2703 allocate(mg%comm_prolong%n_recv(0:mg%n_cpu-1, &
2704 min_lvl:mg%highest_lvl))
2706 mg%comm_prolong%n_recv(:, mg%highest_lvl) = 0
2707 mg%comm_prolong%n_send(:, mg%highest_lvl) = 0
2709 do lvl = min_lvl, mg%highest_lvl-1
2710 mg%comm_prolong%n_recv(:, lvl) = &
2711 mg%comm_restrict%n_send(:, lvl+1)
2712 mg%comm_prolong%n_send(:, lvl) = &
2713 mg%comm_restrict%n_recv(:, lvl+1)
2718 dsize = (mg%box_size)**3
2719 n_send = maxval(mg%comm_prolong%n_send, dim=2)
2720 n_recv = maxval(mg%comm_prolong%n_recv, dim=2)
2726 type(
mg_t),
intent(inout) :: mg
2727 integer,
intent(in) :: lvl
2728 integer,
intent(in) :: iv
2729 integer,
intent(in) :: iv_to
2731 logical,
intent(in) :: add
2732 integer :: i, id, dsize, nc
2734 if (lvl == mg%highest_lvl) error stop
"cannot prolong highest level"
2735 if (lvl < mg%lowest_lvl) error stop
"cannot prolong below lowest level"
2738 if (lvl >= mg%first_normal_lvl-1)
then
2739 dsize = mg%box_size**3
2740 mg%buf(:)%i_send = 0
2743 do i = 1,
size(mg%lvls(lvl)%my_ids)
2744 id = mg%lvls(lvl)%my_ids(i)
2745 call prolong_set_buffer(mg, id, mg%box_size, iv, method)
2748 mg%buf(:)%i_recv = mg%comm_prolong%n_recv(:, lvl) * dsize
2750 mg%buf(:)%i_recv = 0
2753 nc = mg%box_size_lvl(lvl+1)
2754 do i = 1,
size(mg%lvls(lvl+1)%my_ids)
2755 id = mg%lvls(lvl+1)%my_ids(i)
2756 call prolong_onto(mg, id, nc, iv, iv_to, add, method)
2763 subroutine prolong_set_buffer(mg, id, nc, iv, method)
2764 type(
mg_t),
intent(inout) :: mg
2765 integer,
intent(in) :: id
2766 integer,
intent(in) :: nc
2767 integer,
intent(in) :: iv
2769 integer :: i, dix(3)
2770 integer :: i_c, c_id, c_rank, dsize
2771 real(
dp) :: tmp(nc, nc, nc)
2776 c_id = mg%boxes(id)%children(i_c)
2778 c_rank = mg%boxes(c_id)%rank
2779 if (c_rank /= mg%my_rank)
then
2781 call method(mg, id, dix, nc, iv, tmp)
2783 i = mg%buf(c_rank)%i_send
2784 mg%buf(c_rank)%send(i+1:i+dsize) = pack(tmp, .true.)
2785 mg%buf(c_rank)%i_send = mg%buf(c_rank)%i_send + dsize
2787 i = mg%buf(c_rank)%i_ix
2788 mg%buf(c_rank)%ix(i+1) = c_id
2789 mg%buf(c_rank)%i_ix = mg%buf(c_rank)%i_ix + 1
2793 end subroutine prolong_set_buffer
2796 subroutine prolong_onto(mg, id, nc, iv, iv_to, add, method)
2797 type(
mg_t),
intent(inout) :: mg
2798 integer,
intent(in) :: id
2799 integer,
intent(in) :: nc
2800 integer,
intent(in) :: iv
2801 integer,
intent(in) :: iv_to
2802 logical,
intent(in) :: add
2804 integer :: hnc, p_id, p_rank, i, dix(3), dsize
2805 real(
dp) :: tmp(nc, nc, nc)
2808 p_id = mg%boxes(id)%parent
2809 p_rank = mg%boxes(p_id)%rank
2811 if (p_rank == mg%my_rank)
then
2813 call method(mg, p_id, dix, nc, iv, tmp)
2816 i = mg%buf(p_rank)%i_recv
2817 tmp = reshape(mg%buf(p_rank)%recv(i+1:i+dsize), [nc, nc, nc])
2818 mg%buf(p_rank)%i_recv = mg%buf(p_rank)%i_recv + dsize
2822 mg%boxes(id)%cc(1:nc, 1:nc, 1:nc, iv_to) = &
2823 mg%boxes(id)%cc(1:nc, 1:nc, 1:nc, iv_to) + tmp
2825 mg%boxes(id)%cc(1:nc, 1:nc, 1:nc, iv_to) = tmp
2828 end subroutine prolong_onto
2832 type(
mg_t),
intent(inout) :: mg
2833 integer,
intent(in) :: p_id
2834 integer,
intent(in) :: dix(3)
2835 integer,
intent(in) :: nc
2836 integer,
intent(in) :: iv
2837 real(
dp),
intent(out) :: fine(nc, nc, nc)
2839 integer :: i, j, k, hnc
2840 integer :: ic, jc, kc
2841 real(
dp) :: f0, flx, fhx, fly, fhy, flz, fhz
2845 associate(crs => mg%boxes(p_id)%cc)
2853 f0 = 0.25_dp * crs(ic, jc, kc, iv)
2854 flx = 0.25_dp * crs(ic-1, jc, kc, iv)
2855 fhx = 0.25_dp * crs(ic+1, jc, kc, iv)
2856 fly = 0.25_dp * crs(ic, jc-1, kc, iv)
2857 fhy = 0.25_dp * crs(ic, jc+1, kc, iv)
2858 flz = 0.25_dp * crs(ic, jc, kc-1, iv)
2859 fhz = 0.25_dp * crs(ic, jc, kc+1, iv)
2861 fine(2*i-1, 2*j-1, 2*k-1) = f0 + flx + fly + flz
2862 fine(2*i, 2*j-1, 2*k-1) = f0 + fhx + fly + flz
2863 fine(2*i-1, 2*j, 2*k-1) = f0 + flx + fhy + flz
2864 fine(2*i, 2*j, 2*k-1) = f0 + fhx + fhy + flz
2865 fine(2*i-1, 2*j-1, 2*k) = f0 + flx + fly + fhz
2866 fine(2*i, 2*j-1, 2*k) = f0 + fhx + fly + fhz
2867 fine(2*i-1, 2*j, 2*k) = f0 + flx + fhy + fhz
2868 fine(2*i, 2*j, 2*k) = f0 + fhx + fhy + fhz
2878 type(
mg_t),
intent(inout) :: mg
2880 mg%subtract_mean = .false.
2882 select case (mg%geometry_type)
2884 mg%box_op => box_helmh
2886 select case (mg%smoother_type)
2888 mg%box_smoother => box_gs_helmh
2890 error stop
"helmholtz_set_methods: unsupported smoother type"
2893 error stop
"helmholtz_set_methods: unsupported geometry"
2899 real(
dp),
intent(in) :: lambda
2902 error stop
"helmholtz_set_lambda: lambda < 0 not allowed"
2908 subroutine box_gs_helmh(mg, id, nc, redblack_cntr)
2909 type(
mg_t),
intent(inout) :: mg
2910 integer,
intent(in) :: id
2911 integer,
intent(in) :: nc
2912 integer,
intent(in) :: redblack_cntr
2913 integer :: i, j, k, i0, di
2914 real(
dp) :: idr2(3), fac
2917 idr2 = 1/mg%dr(:, mg%boxes(id)%lvl)**2
2930 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi)
2934 i0 = 2 - iand(ieor(redblack_cntr, k+j), 1)
2936 cc(i, j, k, n) = fac * ( &
2937 idr2(1) * (cc(i+1, j, k, n) + cc(i-1, j, k, n)) + &
2938 idr2(2) * (cc(i, j+1, k, n) + cc(i, j-1, k, n)) + &
2939 idr2(3) * (cc(i, j, k+1, n) + cc(i, j, k-1, n)) - &
2945 end subroutine box_gs_helmh
2948 subroutine box_helmh(mg, id, nc, i_out)
2949 type(
mg_t),
intent(inout) :: mg
2950 integer,
intent(in) :: id
2951 integer,
intent(in) :: nc
2952 integer,
intent(in) :: i_out
2956 idr2 = 1 / mg%dr(:, mg%boxes(id)%lvl)**2
2958 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi)
2962 cc(i, j, k, i_out) = &
2963 idr2(1) * (cc(i-1, j, k, n) + cc(i+1, j, k, n) &
2964 - 2 * cc(i, j, k, n)) &
2965 + idr2(2) * (cc(i, j-1, k, n) + cc(i, j+1, k, n) &
2966 - 2 * cc(i, j, k, n)) &
2967 + idr2(3) * (cc(i, j, k-1, n) + cc(i, j, k+1, n) &
2968 - 2 * cc(i, j, k, n)) - &
2974 end subroutine box_helmh
2980 type(
mg_t),
intent(inout) :: mg
2985 select case (mg%operator_type)
2997 error stop
"mg_set_methods: unknown operator"
3003 mg%n_smoother_substeps = 2
3005 mg%n_smoother_substeps = 1
3009 subroutine check_methods(mg)
3010 type(
mg_t),
intent(inout) :: mg
3012 if (.not.
associated(mg%box_op) .or. &
3013 .not.
associated(mg%box_smoother))
then
3017 end subroutine check_methods
3019 subroutine mg_add_timers(mg)
3020 type(
mg_t),
intent(inout) :: mg
3021 timer_total_vcycle =
mg_add_timer(mg,
"mg total V-cycle")
3022 timer_total_fmg =
mg_add_timer(mg,
"mg total FMG cycle")
3024 timer_smoother_gc =
mg_add_timer(mg,
"mg smoother g.c.")
3027 timer_update_coarse =
mg_add_timer(mg,
"mg update coarse")
3028 end subroutine mg_add_timers
3032 type(
mg_t),
intent(inout) :: mg
3033 logical,
intent(in) :: have_guess
3034 real(
dp),
intent(out),
optional :: max_res
3035 integer :: lvl, i, id
3037 call check_methods(mg)
3038 if (timer_smoother == -1)
call mg_add_timers(mg)
3042 if (.not. have_guess)
then
3043 do lvl = mg%highest_lvl, mg%lowest_lvl, -1
3044 do i = 1,
size(mg%lvls(lvl)%my_ids)
3045 id = mg%lvls(lvl)%my_ids(i)
3046 mg%boxes(id)%cc(:, :, :,
mg_iphi) = 0.0_dp
3054 do lvl = mg%highest_lvl, mg%lowest_lvl+1, -1
3057 call update_coarse(mg, lvl)
3061 if (mg%subtract_mean)
then
3063 call subtract_mean(mg,
mg_irhs, .false.)
3066 do lvl = mg%lowest_lvl, mg%highest_lvl
3068 do i = 1,
size(mg%lvls(lvl)%my_ids)
3069 id = mg%lvls(lvl)%my_ids(i)
3070 mg%boxes(id)%cc(:, :, :,
mg_iold) = &
3071 mg%boxes(id)%cc(:, :, :,
mg_iphi)
3074 if (lvl > mg%lowest_lvl)
then
3078 call correct_children(mg, lvl-1)
3086 if (lvl == mg%highest_lvl)
then
3099 type(
mg_t),
intent(inout) :: mg
3100 integer,
intent(in),
optional :: highest_lvl
3101 real(
dp),
intent(out),
optional :: max_res
3103 logical,
intent(in),
optional :: standalone
3104 integer :: lvl, min_lvl, i, max_lvl, ierr
3105 real(
dp) :: init_res, res
3106 logical :: is_standalone
3108 is_standalone = .true.
3109 if (
present(standalone)) is_standalone = standalone
3111 call check_methods(mg)
3112 if (timer_smoother == -1)
call mg_add_timers(mg)
3114 if (is_standalone) &
3117 if (mg%subtract_mean .and. .not.
present(highest_lvl))
then
3120 call subtract_mean(mg,
mg_irhs, .false.)
3123 min_lvl = mg%lowest_lvl
3124 max_lvl = mg%highest_lvl
3125 if (
present(highest_lvl)) max_lvl = highest_lvl
3128 if (is_standalone)
then
3132 do lvl = max_lvl, min_lvl+1, -1
3134 call smooth_boxes(mg, lvl, mg%n_cycle_down)
3139 call update_coarse(mg, lvl)
3144 if (.not. all(mg%boxes(mg%lvls(min_lvl)%ids)%rank == &
3145 mg%boxes(mg%lvls(min_lvl)%ids(1))%rank))
then
3146 error stop
"Multiple CPUs for coarse grid (not implemented yet)"
3149 init_res = max_residual_lvl(mg, min_lvl)
3150 do i = 1, mg%max_coarse_cycles
3151 call smooth_boxes(mg, min_lvl, mg%n_cycle_up+mg%n_cycle_down)
3152 res = max_residual_lvl(mg, min_lvl)
3153 if (res < mg%residual_coarse_rel * init_res .or. &
3154 res < mg%residual_coarse_abs)
exit
3159 do lvl = min_lvl+1, max_lvl
3163 call correct_children(mg, lvl-1)
3170 call smooth_boxes(mg, lvl, mg%n_cycle_up)
3173 if (
present(max_res))
then
3175 do lvl = min_lvl, max_lvl
3176 res = max_residual_lvl(mg, lvl)
3177 init_res = max(res, init_res)
3179 call mpi_allreduce(init_res, max_res, 1, &
3180 mpi_double, mpi_max, mg%comm, ierr)
3184 if (mg%subtract_mean)
then
3185 call subtract_mean(mg,
mg_iphi, .true.)
3188 if (is_standalone) &
3192 subroutine subtract_mean(mg, iv, include_ghostcells)
3194 type(
mg_t),
intent(inout) :: mg
3195 integer,
intent(in) :: iv
3196 logical,
intent(in) :: include_ghostcells
3197 integer :: i, id, lvl, nc, ierr
3198 real(
dp) :: sum_iv, mean_iv, volume
3201 sum_iv = get_sum(mg, iv)
3202 call mpi_allreduce(sum_iv, mean_iv, 1, &
3203 mpi_double, mpi_sum, mg%comm, ierr)
3206 volume = nc**3 * product(mg%dr(:, 1)) *
size(mg%lvls(1)%ids)
3207 mean_iv = mean_iv / volume
3209 do lvl = mg%lowest_lvl, mg%highest_lvl
3210 nc = mg%box_size_lvl(lvl)
3212 do i = 1,
size(mg%lvls(lvl)%my_ids)
3213 id = mg%lvls(lvl)%my_ids(i)
3214 if (include_ghostcells)
then
3215 mg%boxes(id)%cc(:, :, :, iv) = &
3216 mg%boxes(id)%cc(:, :, :, iv) - mean_iv
3218 mg%boxes(id)%cc(1:nc, 1:nc, 1:nc, iv) = &
3219 mg%boxes(id)%cc(1:nc, 1:nc, 1:nc, iv) - mean_iv
3223 end subroutine subtract_mean
3225 real(
dp) function get_sum(mg, iv)
3226 type(
mg_t),
intent(in) :: mg
3227 integer,
intent(in) :: iv
3228 integer :: lvl, i, id, nc
3232 do lvl = 1, mg%highest_lvl
3233 nc = mg%box_size_lvl(lvl)
3234 w = product(mg%dr(:, lvl))
3235 do i = 1,
size(mg%lvls(lvl)%my_leaves)
3236 id = mg%lvls(lvl)%my_leaves(i)
3237 get_sum = get_sum + w * &
3238 sum(mg%boxes(id)%cc(1:nc, 1:nc, 1:nc, iv))
3241 end function get_sum
3243 real(
dp) function max_residual_lvl(mg, lvl)
3244 type(
mg_t),
intent(inout) :: mg
3245 integer,
intent(in) :: lvl
3246 integer :: i, id, nc
3249 nc = mg%box_size_lvl(lvl)
3250 max_residual_lvl = 0.0_dp
3252 do i = 1,
size(mg%lvls(lvl)%my_ids)
3253 id = mg%lvls(lvl)%my_ids(i)
3254 call residual_box(mg, id, nc)
3255 res = maxval(abs(mg%boxes(id)%cc(1:nc, 1:nc, 1:nc,
mg_ires)))
3256 max_residual_lvl = max(max_residual_lvl, res)
3258 end function max_residual_lvl
3294 subroutine update_coarse(mg, lvl)
3295 type(
mg_t),
intent(inout) :: mg
3296 integer,
intent(in) :: lvl
3297 integer :: i, id, nc, nc_c
3299 nc = mg%box_size_lvl(lvl)
3300 nc_c = mg%box_size_lvl(lvl-1)
3303 do i = 1,
size(mg%lvls(lvl)%my_ids)
3304 id = mg%lvls(lvl)%my_ids(i)
3305 call residual_box(mg, id, nc)
3316 do i = 1,
size(mg%lvls(lvl-1)%my_parents)
3317 id = mg%lvls(lvl-1)%my_parents(i)
3320 call mg%box_op(mg, id, nc_c,
mg_irhs)
3323 mg%boxes(id)%cc(1:nc_c, 1:nc_c, 1:nc_c,
mg_irhs) = &
3324 mg%boxes(id)%cc(1:nc_c, 1:nc_c, 1:nc_c,
mg_irhs) + &
3325 mg%boxes(id)%cc(1:nc_c, 1:nc_c, 1:nc_c,
mg_ires)
3328 mg%boxes(id)%cc(:, :, :,
mg_iold) = &
3329 mg%boxes(id)%cc(:, :, :,
mg_iphi)
3331 end subroutine update_coarse
3334 subroutine correct_children(mg, lvl)
3335 type(
mg_t),
intent(inout) :: mg
3336 integer,
intent(in) :: lvl
3339 do i = 1,
size(mg%lvls(lvl)%my_parents)
3340 id = mg%lvls(lvl)%my_parents(i)
3343 mg%boxes(id)%cc(:, :, :,
mg_ires) = &
3344 mg%boxes(id)%cc(:, :, :,
mg_iphi) - &
3345 mg%boxes(id)%cc(:, :, :,
mg_iold)
3349 end subroutine correct_children
3351 subroutine smooth_boxes(mg, lvl, n_cycle)
3352 type(
mg_t),
intent(inout) :: mg
3353 integer,
intent(in) :: lvl
3354 integer,
intent(in) :: n_cycle
3355 integer :: n, i, id, nc
3357 nc = mg%box_size_lvl(lvl)
3359 do n = 1, n_cycle * mg%n_smoother_substeps
3361 do i = 1,
size(mg%lvls(lvl)%my_ids)
3362 id = mg%lvls(lvl)%my_ids(i)
3363 call mg%box_smoother(mg, id, nc, n)
3371 end subroutine smooth_boxes
3373 subroutine residual_box(mg, id, nc)
3374 type(
mg_t),
intent(inout) :: mg
3375 integer,
intent(in) :: id
3376 integer,
intent(in) :: nc
3378 call mg%box_op(mg, id, nc,
mg_ires)
3380 mg%boxes(id)%cc(1:nc, 1:nc, 1:nc,
mg_ires) = &
3381 mg%boxes(id)%cc(1:nc, 1:nc, 1:nc,
mg_irhs) &
3382 - mg%boxes(id)%cc(1:nc, 1:nc, 1:nc,
mg_ires)
3383 end subroutine residual_box
3387 type(
mg_t),
intent(inout) :: mg
3388 integer,
intent(in) :: i_out
3390 integer :: lvl, i, id, nc
3392 do lvl = mg%lowest_lvl, mg%highest_lvl
3393 nc = mg%box_size_lvl(lvl)
3394 do i = 1,
size(mg%lvls(lvl)%my_ids)
3395 id = mg%lvls(lvl)%my_ids(i)
3396 if (
present(op))
then
3397 call op(mg, id, nc, i_out)
3399 call mg%box_op(mg, id, nc, i_out)
3409 type(
mg_t),
intent(inout) :: mg
3410 integer,
intent(out) :: n_send(0:mg%n_cpu-1)
3411 integer,
intent(out) :: n_recv(0:mg%n_cpu-1)
3412 integer,
intent(out) :: dsize
3413 integer :: n_out(0:mg%n_cpu-1, mg%first_normal_lvl:mg%highest_lvl)
3414 integer :: n_in(0:mg%n_cpu-1, mg%first_normal_lvl:mg%highest_lvl)
3415 integer :: lvl, i, id, p_id, p_rank
3416 integer :: i_c, c_id, c_rank, min_lvl
3420 min_lvl = max(mg%lowest_lvl+1, mg%first_normal_lvl)
3422 do lvl = min_lvl, mg%highest_lvl
3424 do i = 1,
size(mg%lvls(lvl-1)%my_parents)
3425 id = mg%lvls(lvl-1)%my_parents(i)
3427 c_id = mg%boxes(id)%children(i_c)
3430 c_rank = mg%boxes(c_id)%rank
3431 if (c_rank /= mg%my_rank)
then
3432 n_in(c_rank, lvl) = n_in(c_rank, lvl) + 1
3439 do i = 1,
size(mg%lvls(lvl)%my_ids)
3440 id = mg%lvls(lvl)%my_ids(i)
3442 p_id = mg%boxes(id)%parent
3443 p_rank = mg%boxes(p_id)%rank
3444 if (p_rank /= mg%my_rank)
then
3445 n_out(p_rank, lvl) = n_out(p_rank, lvl) + 1
3451 allocate(mg%comm_restrict%n_send(0:mg%n_cpu-1, &
3452 mg%first_normal_lvl:mg%highest_lvl))
3453 allocate(mg%comm_restrict%n_recv(0:mg%n_cpu-1, &
3454 mg%first_normal_lvl:mg%highest_lvl))
3455 mg%comm_restrict%n_send = n_out
3456 mg%comm_restrict%n_recv = n_in
3458 dsize = (mg%box_size/2)**3
3459 n_send = maxval(n_out, dim=2)
3460 n_recv = maxval(n_in, dim=2)
3465 type(
mg_t),
intent(inout) :: mg
3466 integer,
intent(in) :: iv
3469 do lvl = mg%highest_lvl, mg%lowest_lvl+1, -1
3477 type(
mg_t),
intent(inout) :: mg
3478 integer,
intent(in) :: iv
3479 integer,
intent(in) :: lvl
3480 integer :: i, id, dsize, nc
3482 if (lvl <= mg%lowest_lvl) error stop
"cannot restrict lvl <= lowest_lvl"
3484 nc = mg%box_size_lvl(lvl)
3486 if (lvl >= mg%first_normal_lvl)
then
3489 mg%buf(:)%i_send = 0
3492 do i = 1,
size(mg%lvls(lvl)%my_ids)
3493 id = mg%lvls(lvl)%my_ids(i)
3494 call restrict_set_buffer(mg, id, iv)
3497 mg%buf(:)%i_recv = mg%comm_restrict%n_recv(:, lvl) * dsize
3499 mg%buf(:)%i_recv = 0
3502 do i = 1,
size(mg%lvls(lvl-1)%my_parents)
3503 id = mg%lvls(lvl-1)%my_parents(i)
3504 call restrict_onto(mg, id, nc, iv)
3508 subroutine restrict_set_buffer(mg, id, iv)
3509 type(
mg_t),
intent(inout) :: mg
3510 integer,
intent(in) :: id
3511 integer,
intent(in) :: iv
3512 integer :: i, j, k, n, hnc, p_id, p_rank
3513 real(
dp) :: tmp(mg%box_size/2, mg%box_size/2, mg%box_size/2)
3516 p_id = mg%boxes(id)%parent
3517 p_rank = mg%boxes(p_id)%rank
3519 if (p_rank /= mg%my_rank)
then
3523 tmp(i, j, k) = 0.125_dp * sum(mg%boxes(id)%cc(2*i-1:2*i, &
3524 2*j-1:2*j, 2*k-1:2*k, iv))
3531 i = mg%buf(p_rank)%i_send
3532 mg%buf(p_rank)%send(i+1:i+n) = pack(tmp, .true.)
3533 mg%buf(p_rank)%i_send = mg%buf(p_rank)%i_send + n
3536 i = mg%buf(p_rank)%i_ix
3539 mg%buf(p_rank)%i_ix = mg%buf(p_rank)%i_ix + 1
3541 end subroutine restrict_set_buffer
3543 subroutine restrict_onto(mg, id, nc, iv)
3544 type(
mg_t),
intent(inout) :: mg
3545 integer,
intent(in) :: id
3546 integer,
intent(in) :: nc
3547 integer,
intent(in) :: iv
3548 integer :: i, j, k, hnc, dsize, i_c, c_id
3549 integer :: c_rank, dix(3)
3555 c_id = mg%boxes(id)%children(i_c)
3557 c_rank = mg%boxes(c_id)%rank
3560 if (c_rank == mg%my_rank)
then
3561 do j=1, hnc;
do i=1, hnc;
do k=1, hnc
3562 mg%boxes(id)%cc(dix(1)+i, dix(2)+j, dix(3)+k, iv) = &
3563 0.125_dp * sum(mg%boxes(c_id)%cc(2*i-1:2*i, &
3564 2*j-1:2*j, 2*k-1:2*k, iv))
3565 end do;
end do;
end do
3567 i = mg%buf(c_rank)%i_recv
3568 mg%boxes(id)%cc(dix(1)+1:dix(1)+hnc, &
3569 dix(2)+1:dix(2)+hnc, dix(3)+1:dix(3)+hnc, iv) = &
3570 reshape(mg%buf(c_rank)%recv(i+1:i+dsize), [hnc, hnc, hnc])
3571 mg%buf(c_rank)%i_recv = mg%buf(c_rank)%i_recv + dsize
3575 end subroutine restrict_onto
3579 Subroutine i_mrgrnk (XDONT, IRNGT)
3586 Integer,
Dimension (:),
Intent (In) :: XDONT
3587 Integer,
Dimension (:),
Intent (Out) :: IRNGT
3589 Integer :: XVALA, XVALB
3591 Integer,
Dimension (SIZE(IRNGT)) :: JWRKT
3592 Integer :: LMTNA, LMTNC, IRNG1, IRNG2
3593 Integer :: NVAL, IIND, IWRKD, IWRK, IWRKF, JINDA, IINDA, IINDB
3595 nval = min(
SIZE(xdont),
SIZE(irngt))
3608 Do iind = 2, nval, 2
3609 If (xdont(iind-1) <= xdont(iind))
Then
3610 irngt(iind-1) = iind - 1
3613 irngt(iind-1) = iind
3614 irngt(iind) = iind - 1
3617 If (modulo(nval, 2) /= 0)
Then
3634 Do iwrkd = 0, nval - 1, 4
3635 If ((iwrkd+4) > nval)
Then
3636 If ((iwrkd+2) >= nval)
Exit
3640 If (xdont(irngt(iwrkd+2)) <= xdont(irngt(iwrkd+3)))
Exit
3644 If (xdont(irngt(iwrkd+1)) <= xdont(irngt(iwrkd+3)))
Then
3645 irng2 = irngt(iwrkd+2)
3646 irngt(iwrkd+2) = irngt(iwrkd+3)
3647 irngt(iwrkd+3) = irng2
3652 irng1 = irngt(iwrkd+1)
3653 irngt(iwrkd+1) = irngt(iwrkd+3)
3654 irngt(iwrkd+3) = irngt(iwrkd+2)
3655 irngt(iwrkd+2) = irng1
3662 If (xdont(irngt(iwrkd+2)) <= xdont(irngt(iwrkd+3))) cycle
3666 If (xdont(irngt(iwrkd+1)) <= xdont(irngt(iwrkd+3)))
Then
3667 irng2 = irngt(iwrkd+2)
3668 irngt(iwrkd+2) = irngt(iwrkd+3)
3669 If (xdont(irng2) <= xdont(irngt(iwrkd+4)))
Then
3671 irngt(iwrkd+3) = irng2
3674 irngt(iwrkd+3) = irngt(iwrkd+4)
3675 irngt(iwrkd+4) = irng2
3681 irng1 = irngt(iwrkd+1)
3682 irng2 = irngt(iwrkd+2)
3683 irngt(iwrkd+1) = irngt(iwrkd+3)
3684 If (xdont(irng1) <= xdont(irngt(iwrkd+4)))
Then
3685 irngt(iwrkd+2) = irng1
3686 If (xdont(irng2) <= xdont(irngt(iwrkd+4)))
Then
3688 irngt(iwrkd+3) = irng2
3691 irngt(iwrkd+3) = irngt(iwrkd+4)
3692 irngt(iwrkd+4) = irng2
3696 irngt(iwrkd+2) = irngt(iwrkd+4)
3697 irngt(iwrkd+3) = irng1
3698 irngt(iwrkd+4) = irng2
3713 If (lmtna >= nval)
Exit
3722 jinda = iwrkf + lmtna
3723 iwrkf = iwrkf + lmtnc
3724 If (iwrkf >= nval)
Then
3725 If (jinda >= nval)
Exit
3741 jwrkt(1:lmtna) = irngt(iwrkd:jinda)
3743 xvala = xdont(jwrkt(iinda))
3744 xvalb = xdont(irngt(iindb))
3751 If (xvala > xvalb)
Then
3752 irngt(iwrk) = irngt(iindb)
3754 If (iindb > iwrkf)
Then
3756 irngt(iwrk+1:iwrkf) = jwrkt(iinda:lmtna)
3759 xvalb = xdont(irngt(iindb))
3761 irngt(iwrk) = jwrkt(iinda)
3763 If (iinda > lmtna) exit
3764 xvala = xdont(jwrkt(iinda))
3777 End Subroutine i_mrgrnk
3782 type(
mg_t),
intent(inout) :: mg
3784 if (mg%n_extra_vars == 0 .and. mg%is_allocated)
then
3785 error stop
"ahelmholtz_set_methods: mg%n_extra_vars == 0"
3787 mg%n_extra_vars = max(3, mg%n_extra_vars)
3801 select case (mg%geometry_type)
3803 mg%box_op => box_ahelmh
3805 select case (mg%smoother_type)
3807 mg%box_smoother => box_gs_ahelmh
3809 error stop
"ahelmholtz_set_methods: unsupported smoother type"
3812 error stop
"ahelmholtz_set_methods: unsupported geometry"
3818 real(
dp),
intent(in) :: lambda
3821 error stop
"ahelmholtz_set_lambda: lambda < 0 not allowed"
3827 subroutine box_gs_ahelmh(mg, id, nc, redblack_cntr)
3828 type(
mg_t),
intent(inout) :: mg
3829 integer,
intent(in) :: id
3830 integer,
intent(in) :: nc
3831 integer,
intent(in) :: redblack_cntr
3832 integer :: i, j, k, i0, di
3834 real(
dp) :: idr2(2*3), u(2*3)
3835 real(
dp) :: a0(2*3), a(2*3), c(2*3)
3838 idr2(1:2*3:2) = 1/mg%dr(:, mg%boxes(id)%lvl)**2
3839 idr2(2:2*3:2) = idr2(1:2*3:2)
3851 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi, &
3859 i0 = 2 - iand(ieor(redblack_cntr, k+j), 1)
3861 a0(1:2) = cc(i, j, k, i_eps1)
3862 a0(3:4) = cc(i, j, k, i_eps2)
3863 a0(4:5) = cc(i, j, k, i_eps3)
3864 u(1:2) = cc(i-1:i+1:2, j, k, n)
3865 a(1:2) = cc(i-1:i+1:2, j, k, i_eps1)
3866 u(3:4) = cc(i, j-1:j+1:2, k, n)
3867 a(3:4) = cc(i, j-1:j+1:2, k, i_eps2)
3868 u(5:6) = cc(i, j, k-1:k+1:2, n)
3869 a(5:6) = cc(i, j, k-1:k+1:2, i_eps3)
3870 c(:) = 2 * a0(:) * a(:) / (a0(:) + a(:)) * idr2
3872 cc(i, j, k, n) = (sum(c(:) * u(:)) - &
3879 end subroutine box_gs_ahelmh
3882 subroutine box_ahelmh(mg, id, nc, i_out)
3883 type(
mg_t),
intent(inout) :: mg
3884 integer,
intent(in) :: id
3885 integer,
intent(in) :: nc
3886 integer,
intent(in) :: i_out
3888 real(
dp) :: idr2(2*3), a0(2*3), u0, u(2*3), a(2*3)
3891 idr2(1:2*3:2) = 1/mg%dr(:, mg%boxes(id)%lvl)**2
3892 idr2(2:2*3:2) = idr2(1:2*3:2)
3894 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi, &
3902 a0(1:2) = cc(i, j, k, i_eps1)
3903 a0(3:4) = cc(i, j, k, i_eps2)
3904 a0(5:6) = cc(i, j, k, i_eps3)
3905 u(1:2) = cc(i-1:i+1:2, j, k, n)
3906 u(3:4) = cc(i, j-1:j+1:2, k, n)
3907 u(5:6) = cc(i, j, k-1:k+1:2, n)
3908 a(1:2) = cc(i-1:i+1:2, j, k, i_eps1)
3909 a(3:4) = cc(i, j-1:j+1:2, k, i_eps2)
3910 a(5:6) = cc(i, j, k-1:k+1:2, i_eps3)
3912 cc(i, j, k, i_out) = sum(2 * idr2 * &
3913 a0(:)*a(:)/(a0(:) + a(:)) * (u(:) - u0)) - &
3919 end subroutine box_ahelmh
Subroutine that performs Gauss-Seidel relaxation.
Subroutine that performs A * cc(..., i_in) = cc(..., i_out)
Subroutine that performs prolongation to a single child.
To fill ghost cells near physical boundaries.
To fill ghost cells near refinement boundaries.
subroutine, public helmholtz_set_lambda(lambda)
subroutine, public mg_set_methods(mg)
subroutine, public mg_restrict_buffer_size(mg, n_send, n_recv, dsize)
Specify minimum buffer size (per process) for communication.
integer, parameter, public mg_irhs
Index of right-hand side.
integer, parameter, public mg_vhelmholtz
Indicates a variable-coefficient Helmholtz equation.
integer, dimension(4, 6), parameter, public mg_child_adj_nb
integer, parameter, public mg_ahelmholtz
Indicates a anisotropic-coefficient Helmholtz equation.
integer, dimension(3, 6), parameter, public mg_neighb_dix
integer function, public mg_ix_to_ichild(ix)
Compute the child index for a box with spatial index ix. With child index we mean the index in the ch...
subroutine, public mg_fas_fmg(mg, have_guess, max_res)
Perform FAS-FMG cycle (full approximation scheme, full multigrid).
integer, parameter, public mg_smoother_gsrb
subroutine, public mg_load_balance(mg)
Load balance all boxes in the multigrid tree. Compared to mg_load_balance_simple, this method does a ...
integer, parameter, public mg_num_children
subroutine, public mg_timers_show(mg)
integer, parameter, public mg_max_timers
Maximum number of timers to use.
subroutine, public mg_fas_vcycle(mg, highest_lvl, max_res, standalone)
Perform FAS V-cycle (full approximation scheme).
subroutine, public vhelmholtz_set_methods(mg)
integer, parameter, public mg_bc_dirichlet
Value to indicate a Dirichlet boundary condition.
integer, parameter, public mg_iveps
Index of the variable coefficient (at cell centers)
subroutine, public mg_load_balance_parents(mg)
Load balance the parents (non-leafs). Assign them to the rank that has most children.
integer, dimension(3, 8), parameter, public mg_child_dix
subroutine, public mg_phi_bc_store(mg)
Store boundary conditions for the solution variable, this can speed up calculations if the same bound...
integer(i8) function, public mg_number_of_unknowns(mg)
Determine total number of unknowns (on leaves)
integer, parameter, public mg_vlaplacian
Indicates a variable-coefficient Laplacian.
integer, parameter, public mg_cylindrical
Cylindrical coordinate system.
subroutine, public mg_prolong_sparse(mg, p_id, dix, nc, iv, fine)
Prolong from a parent to a child with index offset dix.
subroutine, public mg_build_rectangle(mg, domain_size, box_size, dx, r_min, periodic, n_finer)
subroutine, public vhelmholtz_set_lambda(lambda)
integer, parameter, public mg_ires
Index of residual.
integer, parameter, public mg_smoother_gs
subroutine, public laplacian_set_methods(mg)
subroutine, public mg_load_balance_simple(mg)
Load balance all boxes in the multigrid tree, by simply distributing the load per grid level....
subroutine, public mg_ghost_cell_buffer_size(mg, n_send, n_recv, dsize)
Specify minimum buffer size (per process) for communication.
subroutine, public mg_set_neighbors_lvl(mg, lvl)
integer, parameter, public mg_smoother_jacobi
integer, parameter, public mg_neighb_lowy
integer, parameter, public mg_bc_continuous
Value to indicate a continuous boundary condition.
subroutine, public mg_set_leaves_parents(boxes, level)
Create a list of leaves and a list of parents for a level.
subroutine, public helmholtz_set_methods(mg)
subroutine, public mg_add_children(mg, id)
integer, parameter, public mg_lvl_lo
Minimum allowed grid level.
integer, parameter, public mg_num_neighbors
integer, parameter, public mg_neighb_highy
real(dp), public, protected ahelmholtz_lambda
Module which contains multigrid procedures for a Helmholtz operator of the form: div(D grad(phi)) - l...
integer, parameter, public mg_iold
Index of previous solution (used for correction)
integer, parameter, public mg_bc_neumann
Value to indicate a Neumann boundary condition.
integer, dimension(6), parameter, public mg_neighb_high_pm
integer, parameter, public mg_ndim
Problem dimension.
integer, parameter, public mg_iphi
Index of solution.
integer, parameter, public mg_helmholtz
Indicates a constant-coefficient Helmholtz equation.
subroutine, public mg_allocate_storage(mg)
Allocate communication buffers and local boxes for a tree that has already been created.
subroutine, public mg_timer_end(timer)
integer, parameter, public mg_num_vars
Number of predefined multigrid variables.
subroutine, public ahelmholtz_set_methods(mg)
real(dp), public, protected vhelmholtz_lambda
Module for implicitly solving diffusion equations.
subroutine, public mg_restrict(mg, iv)
Restrict all levels.
integer, parameter, public mg_neighb_lowx
subroutine, public mg_set_next_level_ids(mg, lvl)
integer, parameter, public mg_physical_boundary
Special value that indicates there is a physical boundary.
integer, dimension(6), parameter, public mg_neighb_rev
integer, parameter, public mg_spherical
Spherical coordinate system.
integer, parameter, public mg_laplacian
Indicates a standard Laplacian.
subroutine, public mg_get_face_coords(box, nb, nc, x)
Get coordinates at the face of a box.
subroutine, public mg_timer_start(timer)
subroutine, public mg_prolong_buffer_size(mg, n_send, n_recv, dsize)
Specify minimum buffer size (per process) for communication.
subroutine, public diffusion_solve(mg, dt, diffusion_coeff, order, max_res)
Solve a diffusion equation implicitly, assuming a constant diffusion coefficient. The solution at tim...
integer, parameter, public mg_neighb_highx
integer, parameter, public mg_cartesian
Cartesian coordinate system.
integer, parameter, public mg_iveps2
integer, parameter, public i8
Type for 64-bit integers.
integer, parameter, public mg_iveps1
Indexes of anisotropic variable coefficients.
subroutine, public mg_fill_ghost_cells_lvl(mg, lvl, iv)
Fill ghost cells at a grid level.
integer, parameter, public mg_neighb_lowz
subroutine, public diffusion_solve_vcoeff(mg, dt, order, max_res)
Solve a diffusion equation implicitly, assuming a variable diffusion coefficient which has been store...
subroutine, public mg_comm_init(mg, comm)
Prolong from a parent to a child with index offset dix. This method could sometimes work better than ...
integer, parameter, public mg_lvl_hi
Maximum allowed grid level.
subroutine, public vlaplacian_set_methods(mg)
logical, dimension(6), parameter, public mg_neighb_low
integer, parameter, public mg_iveps3
elemental logical function, public mg_has_children(box)
Return .true. if a box has children.
subroutine, public mg_deallocate_storage(mg)
Deallocate all allocatable arrays.
real(dp), public, protected helmholtz_lambda
Module for load balancing a tree (that already has been constructed). The load balancing determines w...
subroutine, public mg_set_refinement_boundaries(boxes, level)
Create a list of refinement boundaries (from the coarse side)
pure integer function, dimension(3), public mg_get_child_offset(mg, id)
Get the offset of a box with respect to its parent (e.g. in 2d, there can be a child at offset 0,...
integer, parameter, public mg_no_box
Special value that indicates there is no box.
subroutine, public mg_restrict_lvl(mg, iv, lvl)
Restrict from lvl to lvl-1.
subroutine, public diffusion_solve_acoeff(mg, dt, order, max_res)
Solve a diffusion equation implicitly, assuming anisotropic diffusion coefficient which has been stor...
pure integer function, public mg_highest_uniform_lvl(mg)
integer, dimension(6), parameter, public mg_neighb_dim
subroutine, public mg_prolong(mg, lvl, iv, iv_to, method, add)
Prolong variable iv from lvl to variable iv_to at lvl+1.
subroutine, public ahelmholtz_set_lambda(lambda)
subroutine, public mg_fill_ghost_cells(mg, iv)
Fill ghost cells at all grid levels.
integer function, public mg_add_timer(mg, name)
subroutine, public mg_apply_op(mg, i_out, op)
Apply operator to the tree and store in variable i_out.
integer, dimension(8, 3), parameter, public mg_child_rev
logical, dimension(3, 8), parameter, public mg_child_low
integer, parameter, public mg_max_num_vars
Maximum number of variables.
integer, parameter, public dp
Type of reals.
subroutine, public sort_and_transfer_buffers(mg, dsize)
integer, parameter, public mg_neighb_highz
Buffer type (one is used for each pair of communicating processes)
Lists of blocks per refinement level.