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.
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()
288 procedure(mg_box_gsrb),
pointer,
nopass :: box_smoother => null()
291 procedure(mg_box_prolong),
pointer,
nopass :: box_prolong => null()
294 integer :: n_timers = 0
303 type(mg_box_t),
intent(in) :: box
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)
313 subroutine mg_subr_rb(box, nc, iv, nb, cgc)
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)
321 end subroutine mg_subr_rb
324 subroutine mg_box_op(mg, id, nc, i_out)
326 type(mg_t),
intent(inout) :: mg
327 integer,
intent(in) :: id
328 integer,
intent(in) :: nc
329 integer,
intent(in) :: i_out
330 end subroutine mg_box_op
333 subroutine mg_box_gsrb(mg, id, nc, redblack_cntr)
335 type(mg_t),
intent(inout) :: mg
336 integer,
intent(in) :: id
337 integer,
intent(in) :: nc
338 integer,
intent(in) :: redblack_cntr
339 end subroutine mg_box_gsrb
342 subroutine mg_box_prolong(mg, p_id, dix, nc, iv, fine)
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)
350 end subroutine mg_box_prolong
357 public :: mg_box_gsrb
358 public :: mg_box_prolong
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)
624 call mpi_reduce(mg%timers(1:mg%n_timers)%t, tmin, mg%n_timers, &
625 mpi_double, mpi_min, 0, mg%comm, ierr)
626 call mpi_reduce(mg%timers(1:mg%n_timers)%t, tmax, mg%n_timers, &
627 mpi_double, mpi_max, 0, mg%comm, ierr)
629 if (mg%my_rank == 0)
then
630 write(*,
"(A20,2A16)")
"name ",
"min(s)",
"max(s)"
631 do n = 1, mg%n_timers
632 write(*,
"(A20,2F16.6)") mg%timers(n)%name, &
642 type(
mg_t),
intent(inout) :: mg
645 if (.not. mg%is_allocated) &
646 error stop
"deallocate_storage: tree is not allocated"
651 deallocate(mg%comm_restrict%n_send)
652 deallocate(mg%comm_restrict%n_recv)
654 deallocate(mg%comm_prolong%n_send)
655 deallocate(mg%comm_prolong%n_recv)
657 deallocate(mg%comm_ghostcell%n_send)
658 deallocate(mg%comm_ghostcell%n_recv)
660 do lvl = mg%lowest_lvl, mg%highest_lvl
661 deallocate(mg%lvls(lvl)%ids)
662 deallocate(mg%lvls(lvl)%leaves)
663 deallocate(mg%lvls(lvl)%parents)
664 deallocate(mg%lvls(lvl)%ref_bnds)
665 deallocate(mg%lvls(lvl)%my_ids)
666 deallocate(mg%lvls(lvl)%my_leaves)
667 deallocate(mg%lvls(lvl)%my_parents)
668 deallocate(mg%lvls(lvl)%my_ref_bnds)
671 mg%is_allocated = .false.
673 mg%phi_bc_data_stored = .false.
680 type(
mg_t),
intent(inout) :: mg
681 integer :: i, id, lvl, nc
682 integer :: n_send(0:mg%n_cpu-1, 3)
683 integer :: n_recv(0:mg%n_cpu-1, 3)
685 integer :: n_in, n_out, n_id
687 if (.not. mg%tree_created) &
688 error stop
"allocate_storage: tree is not yet created"
690 if (mg%is_allocated) &
691 error stop
"allocate_storage: tree is already allocated"
693 do lvl = mg%lowest_lvl, mg%highest_lvl
694 nc = mg%box_size_lvl(lvl)
695 do i = 1,
size(mg%lvls(lvl)%my_ids)
696 id = mg%lvls(lvl)%my_ids(i)
697 allocate(mg%boxes(id)%cc(0:nc+1, 0:nc+1, 0:nc+1, &
701 mg%boxes(id)%cc(:, :, :, :) = 0.0_dp
705 allocate(mg%buf(0:mg%n_cpu-1))
708 n_recv(:, 1), dsize(1))
710 n_recv(:, 2), dsize(2))
712 n_recv(:, 3), dsize(3))
715 n_out = maxval(n_send(i, :) * dsize(:))
716 n_in = maxval(n_recv(i, :) * dsize(:))
717 n_id = maxval(n_send(i, :))
718 allocate(mg%buf(i)%send(n_out))
719 allocate(mg%buf(i)%recv(n_in))
720 allocate(mg%buf(i)%ix(n_id))
723 mg%is_allocated = .true.
733 type(
mg_t),
intent(inout) :: mg
734 real(
dp),
intent(in) :: dt
735 real(
dp),
intent(in) :: diffusion_coeff
736 integer,
intent(in) :: order
737 real(
dp),
intent(in) :: max_res
738 integer,
parameter :: max_its = 10
748 call set_rhs(mg, -1/(dt * diffusion_coeff), 0.0_dp)
753 call set_rhs(mg, -2/(dt * diffusion_coeff), -1.0_dp)
755 error stop
"diffusion_solve: order should be 1 or 2"
763 if (res <= max_res)
exit
767 if (n == max_its + 1)
then
768 if (mg%my_rank == 0) &
769 print *,
"Did you specify boundary conditions correctly?"
770 error stop
"diffusion_solve: no convergence"
780 type(
mg_t),
intent(inout) :: mg
781 real(
dp),
intent(in) :: dt
782 integer,
intent(in) :: order
783 real(
dp),
intent(in) :: max_res
784 integer,
parameter :: max_its = 10
794 call set_rhs(mg, -1/dt, 0.0_dp)
799 call set_rhs(mg, -2/dt, -1.0_dp)
801 error stop
"diffusion_solve: order should be 1 or 2"
809 if (res <= max_res)
exit
813 if (n == max_its + 1)
then
814 if (mg%my_rank == 0)
then
815 print *,
"Did you specify boundary conditions correctly?"
816 print *,
"Or is the variation in diffusion too large?"
818 error stop
"diffusion_solve: no convergence"
829 type(
mg_t),
intent(inout) :: mg
830 real(
dp),
intent(in) :: dt
831 integer,
intent(in) :: order
832 real(
dp),
intent(in) :: max_res
833 integer,
parameter :: max_its = 10
843 call set_rhs(mg, -1/dt, 0.0_dp)
848 call set_rhs(mg, -2/dt, -1.0_dp)
850 error stop
"diffusion_solve: order should be 1 or 2"
858 if (res <= max_res)
exit
862 if (n == max_its + 1)
then
863 if (mg%my_rank == 0)
then
864 print *,
"Did you specify boundary conditions correctly?"
865 print *,
"Or is the variation in diffusion too large?"
867 error stop
"diffusion_solve: no convergence"
871 subroutine set_rhs(mg, f1, f2)
872 type(
mg_t),
intent(inout) :: mg
873 real(
dp),
intent(in) :: f1, f2
874 integer :: lvl, i, id, nc
876 do lvl = 1, mg%highest_lvl
877 nc = mg%box_size_lvl(lvl)
878 do i = 1,
size(mg%lvls(lvl)%my_leaves)
879 id = mg%lvls(lvl)%my_leaves(i)
880 mg%boxes(id)%cc(1:nc, 1:nc, 1:nc,
mg_irhs) = &
881 f1 * mg%boxes(id)%cc(1:nc, 1:nc, 1:nc,
mg_iphi) + &
882 f2 * mg%boxes(id)%cc(1:nc, 1:nc, 1:nc,
mg_irhs)
885 end subroutine set_rhs
890 type(
mg_t),
intent(inout) :: mg
892 if (all(mg%periodic))
then
895 mg%subtract_mean = .true.
898 select case (mg%geometry_type)
902 select case (mg%smoother_type)
906 mg%box_smoother => box_gs_lpl
908 error stop
"laplacian_set_methods: unsupported smoother type"
911 error stop
"laplacian_set_methods: unsupported geometry"
917 subroutine box_gs_lpl(mg, id, nc, redblack_cntr)
918 type(
mg_t),
intent(inout) :: mg
919 integer,
intent(in) :: id
920 integer,
intent(in) :: nc
921 integer,
intent(in) :: redblack_cntr
922 integer :: i, j, k, i0, di
923 real(
dp) :: idr2(3), fac
925 real(
dp),
parameter :: sixth = 1/6.0_dp
927 idr2 = 1/mg%dr(:, mg%boxes(id)%lvl)**2
928 fac = 0.5_dp / sum(idr2)
940 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi)
944 i0 = 2 - iand(ieor(redblack_cntr, k+j), 1)
946 cc(i, j, k, n) = fac * ( &
947 idr2(1) * (cc(i+1, j, k, n) + cc(i-1, j, k, n)) + &
948 idr2(2) * (cc(i, j+1, k, n) + cc(i, j-1, k, n)) + &
949 idr2(3) * (cc(i, j, k+1, n) + cc(i, j, k-1, n)) - &
955 end subroutine box_gs_lpl
996 subroutine box_lpl(mg, id, nc, i_out)
997 type(
mg_t),
intent(inout) :: mg
998 integer,
intent(in) :: id
999 integer,
intent(in) :: nc
1000 integer,
intent(in) :: i_out
1004 idr2 = 1 / mg%dr(:, mg%boxes(id)%lvl)**2
1006 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi)
1010 cc(i, j, k, i_out) = &
1011 idr2(1) * (cc(i-1, j, k, n) + cc(i+1, j, k, n) &
1012 - 2 * cc(i, j, k, n)) &
1013 + idr2(2) * (cc(i, j-1, k, n) + cc(i, j+1, k, n) &
1014 - 2 * cc(i, j, k, n)) &
1015 + idr2(3) * (cc(i, j, k-1, n) + cc(i, j, k+1, n) &
1016 - 2 * cc(i, j, k, n))
1021 end subroutine box_lpl
1027 type(
mg_t),
intent(inout) :: mg
1029 if (mg%n_extra_vars == 0 .and. mg%is_allocated)
then
1030 error stop
"vhelmholtz_set_methods: mg%n_extra_vars == 0"
1032 mg%n_extra_vars = max(1, mg%n_extra_vars)
1035 mg%subtract_mean = .false.
1040 mg%bc(:,
mg_iveps)%bc_value = 0.0_dp
1042 select case (mg%geometry_type)
1044 mg%box_op => box_vhelmh
1046 select case (mg%smoother_type)
1048 mg%box_smoother => box_gs_vhelmh
1050 error stop
"vhelmholtz_set_methods: unsupported smoother type"
1053 error stop
"vhelmholtz_set_methods: unsupported geometry"
1059 real(
dp),
intent(in) :: lambda
1062 error stop
"vhelmholtz_set_lambda: lambda < 0 not allowed"
1068 subroutine box_gs_vhelmh(mg, id, nc, redblack_cntr)
1069 type(
mg_t),
intent(inout) :: mg
1070 integer,
intent(in) :: id
1071 integer,
intent(in) :: nc
1072 integer,
intent(in) :: redblack_cntr
1073 integer :: i, j, k, i0, di
1075 real(
dp) :: idr2(2*3), u(2*3)
1076 real(
dp) :: a0, a(2*3), c(2*3)
1079 idr2(1:2*3:2) = 1/mg%dr(:, mg%boxes(id)%lvl)**2
1080 idr2(2:2*3:2) = idr2(1:2*3:2)
1092 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi, &
1097 i0 = 2 - iand(ieor(redblack_cntr, k+j), 1)
1099 a0 = cc(i, j, k, i_eps)
1100 u(1:2) = cc(i-1:i+1:2, j, k, n)
1101 a(1:2) = cc(i-1:i+1:2, j, k, i_eps)
1102 u(3:4) = cc(i, j-1:j+1:2, k, n)
1103 a(3:4) = cc(i, j-1:j+1:2, k, i_eps)
1104 u(5:6) = cc(i, j, k-1:k+1:2, n)
1105 a(5:6) = cc(i, j, k-1:k+1:2, i_eps)
1106 c(:) = 2 * a0 * a(:) / (a0 + a(:)) * idr2
1108 cc(i, j, k, n) = (sum(c(:) * u(:)) - &
1115 end subroutine box_gs_vhelmh
1118 subroutine box_vhelmh(mg, id, nc, i_out)
1119 type(
mg_t),
intent(inout) :: mg
1120 integer,
intent(in) :: id
1121 integer,
intent(in) :: nc
1122 integer,
intent(in) :: i_out
1124 real(
dp) :: idr2(2*3), a0, u0, u(2*3), a(2*3)
1127 idr2(1:2*3:2) = 1/mg%dr(:, mg%boxes(id)%lvl)**2
1128 idr2(2:2*3:2) = idr2(1:2*3:2)
1130 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi, &
1136 a0 = cc(i, j, k, i_eps)
1137 u(1:2) = cc(i-1:i+1:2, j, k, n)
1138 u(3:4) = cc(i, j-1:j+1:2, k, n)
1139 u(5:6) = cc(i, j, k-1:k+1:2, n)
1140 a(1:2) = cc(i-1:i+1:2, j, k, i_eps)
1141 a(3:4) = cc(i, j-1:j+1:2, k, i_eps)
1142 a(5:6) = cc(i, j, k-1:k+1:2, i_eps)
1144 cc(i, j, k, i_out) = sum(2 * idr2 * &
1145 a0*a(:)/(a0 + a(:)) * (u(:) - u0)) - &
1151 end subroutine box_vhelmh
1157 type(
mg_t),
intent(inout) :: mg
1158 integer,
intent(in) :: domain_size(3)
1159 integer,
intent(in) :: box_size
1160 real(
dp),
intent(in) :: dx(3)
1161 real(
dp),
intent(in) :: r_min(3)
1162 logical,
intent(in) :: periodic(3)
1163 integer,
intent(in) :: n_finer
1164 integer :: i, j, k, lvl, n, id, nx(3), ib, nb(3)
1165 integer :: boxes_per_dim(3,
mg_lvl_lo:1)
1166 integer :: periodic_offset(3)
1168 if (modulo(box_size, 2) /= 0) &
1169 error stop
"box_size should be even"
1170 if (any(modulo(domain_size, box_size) /= 0)) &
1171 error stop
"box_size does not divide domain_size"
1173 if (all(periodic))
then
1174 mg%subtract_mean = .true.
1178 mg%box_size = box_size
1179 mg%box_size_lvl(1) = box_size
1180 mg%domain_size_lvl(:, 1) = domain_size
1181 mg%first_normal_lvl = 1
1184 mg%periodic = periodic
1185 boxes_per_dim(:, :) = 0
1186 boxes_per_dim(:, 1) = domain_size / box_size
1191 if (any(modulo(nx, 2) == 1 .or. nx == mg%coarsest_grid .or. &
1192 (mg%box_size_lvl(lvl) == mg%coarsest_grid .and. &
1195 if (all(modulo(nx/mg%box_size_lvl(lvl), 2) == 0))
then
1196 mg%box_size_lvl(lvl-1) = mg%box_size_lvl(lvl)
1197 boxes_per_dim(:, lvl-1) = boxes_per_dim(:, lvl)/2
1198 mg%first_normal_lvl = lvl-1
1200 mg%box_size_lvl(lvl-1) = mg%box_size_lvl(lvl)/2
1201 boxes_per_dim(:, lvl-1) = boxes_per_dim(:, lvl)
1204 mg%dr(:, lvl-1) = mg%dr(:, lvl) * 2
1206 mg%domain_size_lvl(:, lvl-1) = nx
1213 mg%dr(:, lvl) = mg%dr(:, lvl-1) * 0.5_dp
1214 mg%box_size_lvl(lvl) = box_size
1215 mg%domain_size_lvl(:, lvl) = 2 * mg%domain_size_lvl(:, lvl-1)
1218 n = sum(product(boxes_per_dim, dim=1)) + n_finer
1219 allocate(mg%boxes(n))
1222 nx = boxes_per_dim(:, mg%lowest_lvl)
1223 periodic_offset = [nx(1)-1, (nx(2)-1)*nx(1), &
1224 (nx(3)-1) * nx(2) * nx(1)]
1226 do k=1,nx(3);
do j=1,nx(2);
do i=1,nx(1)
1227 mg%n_boxes = mg%n_boxes + 1
1230 mg%boxes(n)%rank = 0
1232 mg%boxes(n)%lvl = mg%lowest_lvl
1233 mg%boxes(n)%ix(:) = [i, j, k]
1234 mg%boxes(n)%r_min(:) = r_min + (mg%boxes(n)%ix(:) - 1) * &
1235 mg%box_size_lvl(mg%lowest_lvl) * mg%dr(:, mg%lowest_lvl)
1236 mg%boxes(n)%dr(:) = mg%dr(:, mg%lowest_lvl)
1241 mg%boxes(n)%neighbors(:) = [n-1, n+1, n-nx(1), n+nx(1), &
1242 n-nx(1)*nx(2), n+nx(1)*nx(2)]
1247 if(nb(ib)==1 .and. .not.periodic(ib))
then
1250 if(nb(ib)==1 .and. periodic(ib))
then
1251 mg%boxes(n)%neighbors(ib*2-1) = n + periodic_offset(ib)
1253 if(nb(ib)==nx(ib) .and. .not.periodic(ib))
then
1256 if(nb(ib)==nx(ib) .and. periodic(ib))
then
1257 mg%boxes(n)%neighbors(ib*2) = n - periodic_offset(ib)
1277 end do;
end do;
end do
1279 mg%lvls(mg%lowest_lvl)%ids = [(n, n=1, mg%n_boxes)]
1282 do lvl = mg%lowest_lvl, 0
1283 if (mg%box_size_lvl(lvl+1) == mg%box_size_lvl(lvl))
then
1284 do i = 1,
size(mg%lvls(lvl)%ids)
1285 id = mg%lvls(lvl)%ids(i)
1293 do i = 1,
size(mg%lvls(lvl)%ids)
1294 id = mg%lvls(lvl)%ids(i)
1295 call add_single_child(mg, id,
size(mg%lvls(lvl)%ids))
1306 do lvl = mg%lowest_lvl, 1
1307 if (
allocated(mg%lvls(lvl)%ref_bnds)) &
1308 deallocate(mg%lvls(lvl)%ref_bnds)
1309 allocate(mg%lvls(lvl)%ref_bnds(0))
1312 mg%tree_created = .true.
1316 type(
mg_t),
intent(inout) :: mg
1317 integer,
intent(in) :: lvl
1320 do i = 1,
size(mg%lvls(lvl)%ids)
1321 id = mg%lvls(lvl)%ids(i)
1322 call set_neighbs(mg%boxes, id)
1327 type(
mg_t),
intent(inout) :: mg
1328 integer,
intent(in) :: lvl
1331 if (
allocated(mg%lvls(lvl+1)%ids)) &
1332 deallocate(mg%lvls(lvl+1)%ids)
1335 if (mg%box_size_lvl(lvl+1) == mg%box_size_lvl(lvl))
then
1337 allocate(mg%lvls(lvl+1)%ids(n))
1340 do i = 1,
size(mg%lvls(lvl)%parents)
1341 id = mg%lvls(lvl)%parents(i)
1342 mg%lvls(lvl+1)%ids(n*(i-1)+1:n*i) = mg%boxes(id)%children
1345 n =
size(mg%lvls(lvl)%parents)
1346 allocate(mg%lvls(lvl+1)%ids(n))
1349 do i = 1,
size(mg%lvls(lvl)%parents)
1350 id = mg%lvls(lvl)%parents(i)
1351 mg%lvls(lvl+1)%ids(i) = mg%boxes(id)%children(1)
1358 subroutine set_neighbs(boxes, id)
1359 type(
mg_box_t),
intent(inout) :: boxes(:)
1360 integer,
intent(in) :: id
1361 integer :: nb, nb_id
1364 if (boxes(id)%neighbors(nb) ==
mg_no_box)
then
1365 nb_id = find_neighb(boxes, id, nb)
1367 boxes(id)%neighbors(nb) = nb_id
1372 end subroutine set_neighbs
1375 function find_neighb(boxes, id, nb)
result(nb_id)
1376 type(
mg_box_t),
intent(in) :: boxes(:)
1377 integer,
intent(in) :: id
1378 integer,
intent(in) :: nb
1379 integer :: nb_id, p_id, c_ix, d, old_pid
1381 p_id = boxes(id)%parent
1389 p_id = boxes(p_id)%neighbors(nb)
1394 end function find_neighb
1398 type(
mg_box_t),
intent(in) :: boxes(:)
1399 type(
mg_lvl_t),
intent(inout) :: level
1400 integer :: i, id, i_leaf, i_parent
1401 integer :: n_parents, n_leaves
1404 n_leaves =
size(level%ids) - n_parents
1406 if (.not.
allocated(level%parents))
then
1407 allocate(level%parents(n_parents))
1408 else if (n_parents /=
size(level%parents))
then
1409 deallocate(level%parents)
1410 allocate(level%parents(n_parents))
1413 if (.not.
allocated(level%leaves))
then
1414 allocate(level%leaves(n_leaves))
1415 else if (n_leaves /=
size(level%leaves))
then
1416 deallocate(level%leaves)
1417 allocate(level%leaves(n_leaves))
1422 do i = 1,
size(level%ids)
1425 i_parent = i_parent + 1
1426 level%parents(i_parent) = id
1429 level%leaves(i_leaf) = id
1436 type(
mg_box_t),
intent(in) :: boxes(:)
1437 type(
mg_lvl_t),
intent(inout) :: level
1438 integer,
allocatable :: tmp(:)
1439 integer :: i, id, nb, nb_id, ix
1441 if (
allocated(level%ref_bnds))
deallocate(level%ref_bnds)
1443 if (
size(level%parents) == 0)
then
1445 allocate(level%ref_bnds(0))
1447 allocate(tmp(
size(level%leaves)))
1449 do i = 1,
size(level%leaves)
1450 id = level%leaves(i)
1453 nb_id = boxes(id)%neighbors(nb)
1464 allocate(level%ref_bnds(ix))
1465 level%ref_bnds(:) = tmp(1:ix)
1470 type(
mg_t),
intent(inout) :: mg
1471 integer,
intent(in) :: id
1472 integer :: lvl, i, nb, child_nb(2**(3-1))
1474 integer :: c_id, c_ix_base(3)
1477 error stop
"mg_add_children: not enough space"
1482 mg%boxes(id)%children = c_ids
1483 c_ix_base = 2 * mg%boxes(id)%ix - 1
1484 lvl = mg%boxes(id)%lvl+1
1488 mg%boxes(c_id)%rank = mg%boxes(id)%rank
1490 mg%boxes(c_id)%lvl = lvl
1491 mg%boxes(c_id)%parent = id
1494 mg%boxes(c_id)%r_min = mg%boxes(id)%r_min + &
1496 mg%boxes(c_id)%dr(:) = mg%dr(:, lvl)
1501 if (mg%boxes(id)%neighbors(nb) <
mg_no_box)
then
1503 mg%boxes(child_nb)%neighbors(nb) = mg%boxes(id)%neighbors(nb)
1508 subroutine add_single_child(mg, id, n_boxes_lvl)
1509 type(
mg_t),
intent(inout) :: mg
1510 integer,
intent(in) :: id
1511 integer,
intent(in) :: n_boxes_lvl
1512 integer :: lvl, c_id
1514 c_id = mg%n_boxes + 1
1515 mg%n_boxes = mg%n_boxes + 1
1516 mg%boxes(id)%children(1) = c_id
1517 lvl = mg%boxes(id)%lvl+1
1519 mg%boxes(c_id)%rank = mg%boxes(id)%rank
1520 mg%boxes(c_id)%ix = mg%boxes(id)%ix
1521 mg%boxes(c_id)%lvl = lvl
1522 mg%boxes(c_id)%parent = id
1525 mg%boxes(c_id)%neighbors = mg%boxes(id)%neighbors
1527 mg%boxes(c_id)%neighbors = mg%boxes(id)%neighbors + n_boxes_lvl
1529 mg%boxes(c_id)%r_min = mg%boxes(id)%r_min
1530 mg%boxes(c_id)%dr(:) = mg%dr(:, lvl)
1532 end subroutine add_single_child
1542 type(
mg_t),
intent(inout) :: mg
1543 integer :: i, id, lvl, single_cpu_lvl
1544 integer :: work_left, my_work, i_cpu
1548 single_cpu_lvl = max(mg%first_normal_lvl-1, mg%lowest_lvl)
1550 do lvl = mg%lowest_lvl, single_cpu_lvl
1551 do i = 1,
size(mg%lvls(lvl)%ids)
1552 id = mg%lvls(lvl)%ids(i)
1553 mg%boxes(id)%rank = 0
1559 do lvl = single_cpu_lvl+1, mg%highest_lvl
1560 work_left =
size(mg%lvls(lvl)%ids)
1564 do i = 1,
size(mg%lvls(lvl)%ids)
1565 if ((mg%n_cpu - i_cpu - 1) * my_work >= work_left)
then
1570 my_work = my_work + 1
1571 work_left = work_left - 1
1573 id = mg%lvls(lvl)%ids(i)
1574 mg%boxes(id)%rank = i_cpu
1578 do lvl = mg%lowest_lvl, mg%highest_lvl
1579 call update_lvl_info(mg, mg%lvls(lvl))
1591 type(
mg_t),
intent(inout) :: mg
1592 integer :: i, id, lvl, single_cpu_lvl
1593 integer :: work_left, my_work(0:mg%n_cpu), i_cpu
1596 integer :: coarse_rank
1600 single_cpu_lvl = max(mg%first_normal_lvl-1, mg%lowest_lvl)
1604 do lvl = mg%highest_lvl, single_cpu_lvl+1, -1
1608 do i = 1,
size(mg%lvls(lvl)%parents)
1609 id = mg%lvls(lvl)%parents(i)
1611 c_ids = mg%boxes(id)%children
1612 c_ranks = mg%boxes(c_ids)%rank
1613 i_cpu = most_popular(c_ranks, my_work, mg%n_cpu)
1614 mg%boxes(id)%rank = i_cpu
1615 my_work(i_cpu) = my_work(i_cpu) + 1
1618 work_left =
size(mg%lvls(lvl)%leaves)
1621 do i = 1,
size(mg%lvls(lvl)%leaves)
1623 if ((mg%n_cpu - i_cpu - 1) * my_work(i_cpu) >= &
1624 work_left + sum(my_work(i_cpu+1:)))
then
1628 my_work(i_cpu) = my_work(i_cpu) + 1
1629 work_left = work_left - 1
1631 id = mg%lvls(lvl)%leaves(i)
1632 mg%boxes(id)%rank = i_cpu
1637 if (single_cpu_lvl < mg%highest_lvl)
then
1638 coarse_rank = most_popular(mg%boxes(&
1639 mg%lvls(single_cpu_lvl+1)%ids)%rank, my_work, mg%n_cpu)
1644 do lvl = mg%lowest_lvl, single_cpu_lvl
1645 do i = 1,
size(mg%lvls(lvl)%ids)
1646 id = mg%lvls(lvl)%ids(i)
1647 mg%boxes(id)%rank = coarse_rank
1651 do lvl = mg%lowest_lvl, mg%highest_lvl
1652 call update_lvl_info(mg, mg%lvls(lvl))
1660 type(
mg_t),
intent(inout) :: mg
1661 integer :: i, id, lvl
1664 integer :: single_cpu_lvl, coarse_rank
1665 integer :: my_work(0:mg%n_cpu), i_cpu
1669 single_cpu_lvl = max(mg%first_normal_lvl-1, mg%lowest_lvl)
1671 do lvl = mg%highest_lvl-1, single_cpu_lvl+1, -1
1675 do i = 1,
size(mg%lvls(lvl)%leaves)
1676 id = mg%lvls(lvl)%leaves(i)
1677 i_cpu = mg%boxes(id)%rank
1678 my_work(i_cpu) = my_work(i_cpu) + 1
1681 do i = 1,
size(mg%lvls(lvl)%parents)
1682 id = mg%lvls(lvl)%parents(i)
1684 c_ids = mg%boxes(id)%children
1685 c_ranks = mg%boxes(c_ids)%rank
1686 i_cpu = most_popular(c_ranks, my_work, mg%n_cpu)
1687 mg%boxes(id)%rank = i_cpu
1688 my_work(i_cpu) = my_work(i_cpu) + 1
1694 if (single_cpu_lvl < mg%highest_lvl)
then
1695 coarse_rank = most_popular(mg%boxes(&
1696 mg%lvls(single_cpu_lvl+1)%ids)%rank, my_work, mg%n_cpu)
1701 do lvl = mg%lowest_lvl, single_cpu_lvl
1702 do i = 1,
size(mg%lvls(lvl)%ids)
1703 id = mg%lvls(lvl)%ids(i)
1704 mg%boxes(id)%rank = coarse_rank
1708 do lvl = mg%lowest_lvl, mg%highest_lvl
1709 call update_lvl_info(mg, mg%lvls(lvl))
1716 pure integer function most_popular(list, work, n_cpu)
1717 integer,
intent(in) :: list(:)
1718 integer,
intent(in) :: n_cpu
1719 integer,
intent(in) :: work(0:n_cpu-1)
1720 integer :: i, best_count, current_count
1721 integer :: my_work, best_work
1727 do i = 1,
size(list)
1728 current_count = count(list == list(i))
1729 my_work = work(list(i))
1732 if (current_count > best_count .or. &
1733 current_count == best_count .and. my_work < best_work)
then
1734 best_count = current_count
1736 most_popular = list(i)
1740 end function most_popular
1742 subroutine update_lvl_info(mg, lvl)
1743 type(
mg_t),
intent(inout) :: mg
1744 type(
mg_lvl_t),
intent(inout) :: lvl
1746 lvl%my_ids = pack(lvl%ids, &
1747 mg%boxes(lvl%ids)%rank == mg%my_rank)
1748 lvl%my_leaves = pack(lvl%leaves, &
1749 mg%boxes(lvl%leaves)%rank == mg%my_rank)
1750 lvl%my_parents = pack(lvl%parents, &
1751 mg%boxes(lvl%parents)%rank == mg%my_rank)
1752 lvl%my_ref_bnds = pack(lvl%ref_bnds, &
1753 mg%boxes(lvl%ref_bnds)%rank == mg%my_rank)
1754 end subroutine update_lvl_info
1759 type(
mg_t),
intent(inout) :: mg
1761 if (mg%n_extra_vars == 0 .and. mg%is_allocated)
then
1762 error stop
"vlaplacian_set_methods: mg%n_extra_vars == 0"
1764 mg%n_extra_vars = max(1, mg%n_extra_vars)
1767 mg%subtract_mean = .false.
1772 mg%bc(:,
mg_iveps)%bc_value = 0.0_dp
1774 select case (mg%geometry_type)
1776 mg%box_op => box_vlpl
1781 select case (mg%smoother_type)
1783 mg%box_smoother => box_gs_vlpl
1785 error stop
"vlaplacian_set_methods: unsupported smoother type"
1789 error stop
"vlaplacian_set_methods: unsupported geometry"
1795 subroutine box_gs_vlpl(mg, id, nc, redblack_cntr)
1796 type(
mg_t),
intent(inout) :: mg
1797 integer,
intent(in) :: id
1798 integer,
intent(in) :: nc
1799 integer,
intent(in) :: redblack_cntr
1800 integer :: i, j, k, i0, di
1802 real(
dp) :: idr2(2*3), u(2*3)
1803 real(
dp) :: a0, a(2*3), c(2*3)
1806 idr2(1:2*3:2) = 1/mg%dr(:, mg%boxes(id)%lvl)**2
1807 idr2(2:2*3:2) = idr2(1:2*3:2)
1819 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi, &
1824 i0 = 2 - iand(ieor(redblack_cntr, k+j), 1)
1826 a0 = cc(i, j, k, i_eps)
1827 u(1:2) = cc(i-1:i+1:2, j, k, n)
1828 a(1:2) = cc(i-1:i+1:2, j, k, i_eps)
1829 u(3:4) = cc(i, j-1:j+1:2, k, n)
1830 a(3:4) = cc(i, j-1:j+1:2, k, i_eps)
1831 u(5:6) = cc(i, j, k-1:k+1:2, n)
1832 a(5:6) = cc(i, j, k-1:k+1:2, i_eps)
1833 c(:) = 2 * a0 * a(:) / (a0 + a(:)) * idr2
1835 cc(i, j, k, n) = (sum(c(:) * u(:)) - &
1836 cc(i, j, k,
mg_irhs)) / sum(c(:))
1841 end subroutine box_gs_vlpl
1844 subroutine box_vlpl(mg, id, nc, i_out)
1845 type(
mg_t),
intent(inout) :: mg
1846 integer,
intent(in) :: id
1847 integer,
intent(in) :: nc
1848 integer,
intent(in) :: i_out
1850 real(
dp) :: idr2(2*3), a0, u0, u(2*3), a(2*3)
1853 idr2(1:2*3:2) = 1/mg%dr(:, mg%boxes(id)%lvl)**2
1854 idr2(2:2*3:2) = idr2(1:2*3:2)
1856 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi, &
1862 a0 = cc(i, j, k, i_eps)
1863 u(1:2) = cc(i-1:i+1:2, j, k, n)
1864 u(3:4) = cc(i, j-1:j+1:2, k, n)
1865 u(5:6) = cc(i, j, k-1:k+1:2, n)
1866 a(1:2) = cc(i-1:i+1:2, j, k, i_eps)
1867 a(3:4) = cc(i, j-1:j+1:2, k, i_eps)
1868 a(5:6) = cc(i, j, k-1:k+1:2, i_eps)
1870 cc(i, j, k, i_out) = sum(2 * idr2 * &
1871 a0*a(:)/(a0 + a(:)) * (u(:) - u0))
1876 end subroutine box_vlpl
1984 type(
mg_t),
intent(inout) :: mg
1986 integer,
intent(in),
optional :: comm
1988 logical :: initialized
1990 call mpi_initialized(initialized, ierr)
1991 if (.not. initialized)
then
1995 if (
present(comm))
then
1998 mg%comm = mpi_comm_world
2001 call mpi_comm_rank(mg%comm, mg%my_rank, ierr)
2002 call mpi_comm_size(mg%comm, mg%n_cpu, ierr)
2007 type(
mg_t),
intent(inout) :: mg
2008 integer,
intent(in) :: dsize
2009 integer :: i, n_send, n_recv
2010 integer :: send_req(mg%n_cpu)
2011 integer :: recv_req(mg%n_cpu)
2017 do i = 0, mg%n_cpu - 1
2018 if (mg%buf(i)%i_send > 0)
then
2021 call mpi_isend(mg%buf(i)%send, mg%buf(i)%i_send, mpi_double, &
2022 i, 0, mg%comm, send_req(n_send), ierr)
2024 if (mg%buf(i)%i_recv > 0)
then
2026 call mpi_irecv(mg%buf(i)%recv, mg%buf(i)%i_recv, mpi_double, &
2027 i, 0, mg%comm, recv_req(n_recv), ierr)
2031 call mpi_waitall(n_recv, recv_req(1:n_recv), mpi_statuses_ignore, ierr)
2032 call mpi_waitall(n_send, send_req(1:n_send), mpi_statuses_ignore, ierr)
2039 type(
mg_buf_t),
intent(inout) :: gc
2040 integer,
intent(in) :: dsize
2041 integer :: ix_sort(gc%i_ix)
2042 real(dp) :: buf_cpy(gc%i_send)
2045 call mrgrnk(gc%ix(1:gc%i_ix), ix_sort)
2047 buf_cpy = gc%send(1:gc%i_send)
2051 j = (ix_sort(n)-1) * dsize
2052 gc%send(i+1:i+dsize) = buf_cpy(j+1:j+dsize)
2054 gc%ix(1:gc%i_ix) = gc%ix(ix_sort)
2062 type(
mg_t),
intent(inout) :: mg
2063 integer,
intent(out) :: n_send(0:mg%n_cpu-1)
2064 integer,
intent(out) :: n_recv(0:mg%n_cpu-1)
2065 integer,
intent(out) :: dsize
2066 integer :: i, id, lvl, nc
2068 allocate(mg%comm_ghostcell%n_send(0:mg%n_cpu-1, &
2069 mg%first_normal_lvl:mg%highest_lvl))
2070 allocate(mg%comm_ghostcell%n_recv(0:mg%n_cpu-1, &
2071 mg%first_normal_lvl:mg%highest_lvl))
2073 dsize = mg%box_size**(3-1)
2075 do lvl = mg%first_normal_lvl, mg%highest_lvl
2076 nc = mg%box_size_lvl(lvl)
2077 mg%buf(:)%i_send = 0
2078 mg%buf(:)%i_recv = 0
2081 do i = 1,
size(mg%lvls(lvl)%my_ids)
2082 id = mg%lvls(lvl)%my_ids(i)
2083 call buffer_ghost_cells(mg, id, nc, 1, dry_run=.true.)
2087 do i = 1,
size(mg%lvls(lvl-1)%my_ref_bnds)
2088 id = mg%lvls(lvl-1)%my_ref_bnds(i)
2089 call buffer_refinement_boundaries(mg, id, nc, 1, dry_run=.true.)
2094 mg%buf(:)%i_recv = 0
2095 do i = 1,
size(mg%lvls(lvl)%my_ids)
2096 id = mg%lvls(lvl)%my_ids(i)
2097 call set_ghost_cells(mg, id, nc, 1, dry_run=.true.)
2100 mg%comm_ghostcell%n_send(:, lvl) = mg%buf(:)%i_send/dsize
2101 mg%comm_ghostcell%n_recv(:, lvl) = mg%buf(:)%i_recv/dsize
2104 n_send = maxval(mg%comm_ghostcell%n_send, dim=2)
2105 n_recv = maxval(mg%comm_ghostcell%n_recv, dim=2)
2111 type(
mg_t),
intent(inout) :: mg
2116 do lvl = mg%lowest_lvl, mg%highest_lvl
2117 nc = mg%box_size_lvl(lvl)
2118 call mg_phi_bc_store_lvl(mg, lvl, nc)
2121 mg%phi_bc_data_stored = .true.
2124 subroutine mg_phi_bc_store_lvl(mg, lvl, nc)
2125 type(
mg_t),
intent(inout) :: mg
2126 integer,
intent(in) :: lvl
2127 integer,
intent(in) :: nc
2128 real(
dp) :: bc(nc, nc)
2129 integer :: i, id, nb, nb_id, bc_type
2131 do i = 1,
size(mg%lvls(lvl)%my_ids)
2132 id = mg%lvls(lvl)%my_ids(i)
2134 nb_id = mg%boxes(id)%neighbors(nb)
2137 if (
associated(mg%bc(nb,
mg_iphi)%boundary_cond))
then
2138 call mg%bc(nb,
mg_iphi)%boundary_cond(mg%boxes(id), nc, &
2141 bc_type = mg%bc(nb,
mg_iphi)%bc_type
2142 bc = mg%bc(nb,
mg_iphi)%bc_value
2148 mg%boxes(id)%neighbors(nb) = bc_type
2151 call box_set_gc(mg%boxes(id), nb, nc,
mg_irhs, bc)
2155 end subroutine mg_phi_bc_store_lvl
2160 integer,
intent(in) :: iv
2163 do lvl = mg%lowest_lvl, mg%highest_lvl
2172 integer,
intent(in) :: lvl
2173 integer,
intent(in) :: iv
2174 integer :: i, id, dsize, nc
2176 if (lvl < mg%lowest_lvl) &
2177 error stop
"fill_ghost_cells_lvl: lvl < lowest_lvl"
2178 if (lvl > mg%highest_lvl) &
2179 error stop
"fill_ghost_cells_lvl: lvl > highest_lvl"
2181 nc = mg%box_size_lvl(lvl)
2183 if (lvl >= mg%first_normal_lvl)
then
2185 mg%buf(:)%i_send = 0
2186 mg%buf(:)%i_recv = 0
2189 do i = 1,
size(mg%lvls(lvl)%my_ids)
2190 id = mg%lvls(lvl)%my_ids(i)
2191 call buffer_ghost_cells(mg, id, nc, iv, .false.)
2195 do i = 1,
size(mg%lvls(lvl-1)%my_ref_bnds)
2196 id = mg%lvls(lvl-1)%my_ref_bnds(i)
2197 call buffer_refinement_boundaries(mg, id, nc, iv, .false.)
2202 mg%buf(:)%i_recv = mg%comm_ghostcell%n_recv(:, lvl) * dsize
2206 mg%buf(:)%i_recv = 0
2209 do i = 1,
size(mg%lvls(lvl)%my_ids)
2210 id = mg%lvls(lvl)%my_ids(i)
2211 call set_ghost_cells(mg, id, nc, iv, .false.)
2215 subroutine buffer_ghost_cells(mg, id, nc, iv, dry_run)
2216 type(
mg_t),
intent(inout) :: mg
2217 integer,
intent(in) :: id
2218 integer,
intent(in) :: nc
2219 integer,
intent(in) :: iv
2220 logical,
intent(in) :: dry_run
2221 integer :: nb, nb_id, nb_rank
2224 nb_id = mg%boxes(id)%neighbors(nb)
2228 nb_rank = mg%boxes(nb_id)%rank
2230 if (nb_rank /= mg%my_rank)
then
2231 call buffer_for_nb(mg, mg%boxes(id), nc, iv, nb_id, nb_rank, &
2236 end subroutine buffer_ghost_cells
2238 subroutine buffer_refinement_boundaries(mg, id, nc, iv, dry_run)
2239 type(
mg_t),
intent(inout) :: mg
2240 integer,
intent(in) :: id
2241 integer,
intent(in) :: nc
2242 integer,
intent(in) :: iv
2243 logical,
intent(in) :: dry_run
2244 integer :: nb, nb_id, c_ids(2**(3-1))
2245 integer :: n, c_id, c_rank
2248 nb_id = mg%boxes(id)%neighbors(nb)
2251 c_ids = mg%boxes(nb_id)%children(&
2256 c_rank = mg%boxes(c_id)%rank
2258 if (c_rank /= mg%my_rank)
then
2260 call buffer_for_fine_nb(mg, mg%boxes(id), nc, iv, c_id, &
2261 c_rank, nb, dry_run)
2267 end subroutine buffer_refinement_boundaries
2270 subroutine set_ghost_cells(mg, id, nc, iv, dry_run)
2271 type(
mg_t),
intent(inout) :: mg
2272 integer,
intent(in) :: id
2273 integer,
intent(in) :: nc
2274 integer,
intent(in) :: iv
2275 logical,
intent(in) :: dry_run
2276 real(
dp) :: bc(nc, nc)
2277 integer :: nb, nb_id, nb_rank, bc_type
2280 nb_id = mg%boxes(id)%neighbors(nb)
2284 nb_rank = mg%boxes(nb_id)%rank
2286 if (nb_rank /= mg%my_rank)
then
2287 call fill_buffered_nb(mg, mg%boxes(id), nb_rank, &
2288 nb, nc, iv, dry_run)
2289 else if (.not. dry_run)
then
2290 call copy_from_nb(mg%boxes(id), mg%boxes(nb_id), &
2295 call fill_refinement_bnd(mg, id, nb, nc, iv, dry_run)
2296 else if (.not. dry_run)
then
2298 if (mg%phi_bc_data_stored .and. iv ==
mg_iphi)
then
2301 call box_get_gc(mg%boxes(id), nb, nc,
mg_irhs, bc)
2304 if (
associated(mg%bc(nb, iv)%boundary_cond))
then
2305 call mg%bc(nb, iv)%boundary_cond(mg%boxes(id), nc, iv, &
2308 bc_type = mg%bc(nb, iv)%bc_type
2309 bc = mg%bc(nb, iv)%bc_value
2313 call box_set_gc(mg%boxes(id), nb, nc, iv, bc)
2314 call bc_to_gc(mg, id, nc, iv, nb, bc_type)
2317 end subroutine set_ghost_cells
2319 subroutine fill_refinement_bnd(mg, id, nb, nc, iv, dry_run)
2320 type(
mg_t),
intent(inout) :: mg
2321 integer,
intent(in) :: id
2322 integer,
intent(in) :: nc
2323 integer,
intent(in) :: iv
2324 integer,
intent(in) :: nb
2325 logical,
intent(in) :: dry_run
2326 real(
dp) :: gc(nc, nc)
2327 integer :: p_id, p_nb_id, ix_offset(3)
2328 integer :: i, dsize, p_nb_rank
2331 p_id = mg%boxes(id)%parent
2332 p_nb_id = mg%boxes(p_id)%neighbors(nb)
2333 p_nb_rank = mg%boxes(p_nb_id)%rank
2335 if (p_nb_rank /= mg%my_rank)
then
2336 i = mg%buf(p_nb_rank)%i_recv
2337 if (.not. dry_run)
then
2338 gc = reshape(mg%buf(p_nb_rank)%recv(i+1:i+dsize), shape(gc))
2340 mg%buf(p_nb_rank)%i_recv = mg%buf(p_nb_rank)%i_recv + dsize
2341 else if (.not. dry_run)
then
2343 call box_gc_for_fine_neighbor(mg%boxes(p_nb_id),
mg_neighb_rev(nb), &
2344 ix_offset, nc, iv, gc)
2347 if (.not. dry_run)
then
2348 if (
associated(mg%bc(nb, iv)%refinement_bnd))
then
2349 call mg%bc(nb, iv)%refinement_bnd(mg%boxes(id), nc, iv, nb, gc)
2351 call sides_rb(mg%boxes(id), nc, iv, nb, gc)
2354 end subroutine fill_refinement_bnd
2356 subroutine copy_from_nb(box, box_nb, nb, nc, iv)
2357 type(
mg_box_t),
intent(inout) :: box
2358 type(
mg_box_t),
intent(in) :: box_nb
2359 integer,
intent(in) :: nb
2360 integer,
intent(in) :: nc
2361 integer,
intent(in) :: iv
2362 real(
dp) :: gc(nc, nc)
2364 call box_gc_for_neighbor(box_nb,
mg_neighb_rev(nb), nc, iv, gc)
2365 call box_set_gc(box, nb, nc, iv, gc)
2366 end subroutine copy_from_nb
2368 subroutine buffer_for_nb(mg, box, nc, iv, nb_id, nb_rank, nb, dry_run)
2369 type(
mg_t),
intent(inout) :: mg
2370 type(
mg_box_t),
intent(inout) :: box
2371 integer,
intent(in) :: nc
2372 integer,
intent(in) :: iv
2373 integer,
intent(in) :: nb_id
2374 integer,
intent(in) :: nb_rank
2375 integer,
intent(in) :: nb
2376 logical,
intent(in) :: dry_run
2378 real(
dp) :: gc(nc, nc)
2380 i = mg%buf(nb_rank)%i_send
2383 if (.not. dry_run)
then
2384 call box_gc_for_neighbor(box, nb, nc, iv, gc)
2385 mg%buf(nb_rank)%send(i+1:i+dsize) = pack(gc, .true.)
2390 i = mg%buf(nb_rank)%i_ix
2391 if (.not. dry_run)
then
2395 mg%buf(nb_rank)%i_send = mg%buf(nb_rank)%i_send + dsize
2396 mg%buf(nb_rank)%i_ix = mg%buf(nb_rank)%i_ix + 1
2397 end subroutine buffer_for_nb
2399 subroutine buffer_for_fine_nb(mg, box, nc, iv, fine_id, fine_rank, nb, dry_run)
2400 type(
mg_t),
intent(inout) :: mg
2401 type(
mg_box_t),
intent(inout) :: box
2402 integer,
intent(in) :: nc
2403 integer,
intent(in) :: iv
2404 integer,
intent(in) :: fine_id
2405 integer,
intent(in) :: fine_rank
2406 integer,
intent(in) :: nb
2407 logical,
intent(in) :: dry_run
2408 integer :: i, dsize, ix_offset(3)
2409 real(
dp) :: gc(nc, nc)
2411 i = mg%buf(fine_rank)%i_send
2414 if (.not. dry_run)
then
2416 call box_gc_for_fine_neighbor(box, nb, ix_offset, nc, iv, gc)
2417 mg%buf(fine_rank)%send(i+1:i+dsize) = pack(gc, .true.)
2422 i = mg%buf(fine_rank)%i_ix
2423 if (.not. dry_run)
then
2428 mg%buf(fine_rank)%i_send = mg%buf(fine_rank)%i_send + dsize
2429 mg%buf(fine_rank)%i_ix = mg%buf(fine_rank)%i_ix + 1
2430 end subroutine buffer_for_fine_nb
2432 subroutine fill_buffered_nb(mg, box, nb_rank, nb, nc, iv, dry_run)
2433 type(
mg_t),
intent(inout) :: mg
2434 type(
mg_box_t),
intent(inout) :: box
2435 integer,
intent(in) :: nb_rank
2436 integer,
intent(in) :: nb
2437 integer,
intent(in) :: nc
2438 integer,
intent(in) :: iv
2439 logical,
intent(in) :: dry_run
2441 real(
dp) :: gc(nc, nc)
2443 i = mg%buf(nb_rank)%i_recv
2446 if (.not. dry_run)
then
2447 gc = reshape(mg%buf(nb_rank)%recv(i+1:i+dsize), shape(gc))
2448 call box_set_gc(box, nb, nc, iv, gc)
2450 mg%buf(nb_rank)%i_recv = mg%buf(nb_rank)%i_recv + dsize
2452 end subroutine fill_buffered_nb
2454 subroutine box_gc_for_neighbor(box, nb, nc, iv, gc)
2456 integer,
intent(in) :: nb, nc, iv
2457 real(
dp),
intent(out) :: gc(nc, nc)
2461 gc = box%cc(1, 1:nc, 1:nc, iv)
2463 gc = box%cc(nc, 1:nc, 1:nc, iv)
2465 gc = box%cc(1:nc, 1, 1:nc, iv)
2467 gc = box%cc(1:nc, nc, 1:nc, iv)
2469 gc = box%cc(1:nc, 1:nc, 1, iv)
2471 gc = box%cc(1:nc, 1:nc, nc, iv)
2473 end subroutine box_gc_for_neighbor
2476 subroutine box_gc_for_fine_neighbor(box, nb, di, nc, iv, gc)
2478 integer,
intent(in) :: nb
2479 integer,
intent(in) :: di(3)
2480 integer,
intent(in) :: nc, iv
2481 real(
dp),
intent(out) :: gc(nc, nc)
2482 real(
dp) :: tmp(0:nc/2+1, 0:nc/2+1), grad(3-1)
2483 integer :: i, j, hnc
2490 tmp = box%cc(1, di(2):di(2)+hnc+1, di(3):di(3)+hnc+1, iv)
2492 tmp = box%cc(nc, di(2):di(2)+hnc+1, di(3):di(3)+hnc+1, iv)
2494 tmp = box%cc(di(1):di(1)+hnc+1, 1, di(3):di(3)+hnc+1, iv)
2496 tmp = box%cc(di(1):di(1)+hnc+1, nc, di(3):di(3)+hnc+1, iv)
2498 tmp = box%cc(di(1):di(1)+hnc+1, di(2):di(2)+hnc+1, 1, iv)
2500 tmp = box%cc(di(1):di(1)+hnc+1, di(2):di(2)+hnc+1, nc, iv)
2509 grad(1) = 0.125_dp * (tmp(i+1, j) - tmp(i-1, j))
2510 grad(2) = 0.125_dp * (tmp(i, j+1) - tmp(i, j-1))
2511 gc(2*i-1, 2*j-1) = tmp(i, j) - grad(1) - grad(2)
2512 gc(2*i, 2*j-1) = tmp(i, j) + grad(1) - grad(2)
2513 gc(2*i-1, 2*j) = tmp(i, j) - grad(1) + grad(2)
2514 gc(2*i, 2*j) = tmp(i, j) + grad(1) + grad(2)
2517 end subroutine box_gc_for_fine_neighbor
2519 subroutine box_get_gc(box, nb, nc, iv, gc)
2521 integer,
intent(in) :: nb, nc, iv
2522 real(
dp),
intent(out) :: gc(nc, nc)
2526 gc = box%cc(0, 1:nc, 1:nc, iv)
2528 gc = box%cc(nc+1, 1:nc, 1:nc, iv)
2530 gc = box%cc(1:nc, 0, 1:nc, iv)
2532 gc = box%cc(1:nc, nc+1, 1:nc, iv)
2534 gc = box%cc(1:nc, 1:nc, 0, iv)
2536 gc = box%cc(1:nc, 1:nc, nc+1, iv)
2538 end subroutine box_get_gc
2540 subroutine box_set_gc(box, nb, nc, iv, gc)
2541 type(
mg_box_t),
intent(inout) :: box
2542 integer,
intent(in) :: nb, nc, iv
2543 real(
dp),
intent(in) :: gc(nc, nc)
2547 box%cc(0, 1:nc, 1:nc, iv) = gc
2549 box%cc(nc+1, 1:nc, 1:nc, iv) = gc
2551 box%cc(1:nc, 0, 1:nc, iv) = gc
2553 box%cc(1:nc, nc+1, 1:nc, iv) = gc
2555 box%cc(1:nc, 1:nc, 0, iv) = gc
2557 box%cc(1:nc, 1:nc, nc+1, iv) = gc
2559 end subroutine box_set_gc
2561 subroutine bc_to_gc(mg, id, nc, iv, nb, bc_type)
2562 type(
mg_t),
intent(inout) :: mg
2563 integer,
intent(in) :: id
2564 integer,
intent(in) :: nc
2565 integer,
intent(in) :: iv
2566 integer,
intent(in) :: nb
2567 integer,
intent(in) :: bc_type
2568 real(
dp) :: c0, c1, c2, dr
2578 select case (bc_type)
2593 error stop
"bc_to_gc: unknown boundary condition"
2598 mg%boxes(id)%cc(0, 1:nc, 1:nc, iv) = &
2599 c0 * mg%boxes(id)%cc(0, 1:nc, 1:nc, iv) + &
2600 c1 * mg%boxes(id)%cc(1, 1:nc, 1:nc, iv) + &
2601 c2 * mg%boxes(id)%cc(2, 1:nc, 1:nc, iv)
2603 mg%boxes(id)%cc(nc+1, 1:nc, 1:nc, iv) = &
2604 c0 * mg%boxes(id)%cc(nc+1, 1:nc, 1:nc, iv) + &
2605 c1 * mg%boxes(id)%cc(nc, 1:nc, 1:nc, iv) + &
2606 c2 * mg%boxes(id)%cc(nc-1, 1:nc, 1:nc, iv)
2608 mg%boxes(id)%cc(1:nc, 0, 1:nc, iv) = &
2609 c0 * mg%boxes(id)%cc(1:nc, 0, 1:nc, iv) + &
2610 c1 * mg%boxes(id)%cc(1:nc, 1, 1:nc, iv) + &
2611 c2 * mg%boxes(id)%cc(1:nc, 2, 1:nc, iv)
2613 mg%boxes(id)%cc(1:nc, nc+1, 1:nc, iv) = &
2614 c0 * mg%boxes(id)%cc(1:nc, nc+1, 1:nc, iv) + &
2615 c1 * mg%boxes(id)%cc(1:nc, nc, 1:nc, iv) + &
2616 c2 * mg%boxes(id)%cc(1:nc, nc-1, 1:nc, iv)
2618 mg%boxes(id)%cc(1:nc, 1:nc, 0, iv) = &
2619 c0 * mg%boxes(id)%cc(1:nc, 1:nc, 0, iv) + &
2620 c1 * mg%boxes(id)%cc(1:nc, 1:nc, 1, iv) + &
2621 c2 * mg%boxes(id)%cc(1:nc, 1:nc, 2, iv)
2623 mg%boxes(id)%cc(1:nc, 1:nc, nc+1, iv) = &
2624 c0 * mg%boxes(id)%cc(1:nc, 1:nc, nc+1, iv) + &
2625 c1 * mg%boxes(id)%cc(1:nc, 1:nc, nc, iv) + &
2626 c2 * mg%boxes(id)%cc(1:nc, 1:nc, nc-1, iv)
2628 end subroutine bc_to_gc
2631 subroutine sides_rb(box, nc, iv, nb, gc)
2632 type(
mg_box_t),
intent(inout) :: box
2633 integer,
intent(in) :: nc
2634 integer,
intent(in) :: iv
2635 integer,
intent(in) :: nb
2637 real(
dp),
intent(in) :: gc(nc, nc)
2638 integer :: di, dj, dk
2639 integer :: i, j, k, ix, dix
2654 dk = -1 + 2 * iand(k, 1)
2656 dj = -1 + 2 * iand(j, 1)
2657 box%cc(i-di, j, k, iv) = 0.5_dp * gc(j, k) &
2658 + 0.75_dp * box%cc(i, j, k, iv) &
2659 - 0.25_dp * box%cc(i+di, j, k, iv)
2666 dk = -1 + 2 * iand(k, 1)
2668 di = -1 + 2 * iand(i, 1)
2669 box%cc(i, j-dj, k, iv) = 0.5_dp * gc(i, k) &
2670 + 0.75_dp * box%cc(i, j, k, iv) &
2671 - 0.25_dp * box%cc(i, j+dj, k, iv)
2678 dj = -1 + 2 * iand(j, 1)
2680 di = -1 + 2 * iand(i, 1)
2681 box%cc(i, j, k-dk, iv) = 0.5_dp * gc(i, j) &
2682 + 0.75_dp * box%cc(i, j, k, iv) &
2683 - 0.25_dp * box%cc(i, j, k+dk, iv)
2688 end subroutine sides_rb
2694 type(
mg_t),
intent(inout) :: mg
2695 integer,
intent(out) :: n_send(0:mg%n_cpu-1)
2696 integer,
intent(out) :: n_recv(0:mg%n_cpu-1)
2697 integer,
intent(out) :: dsize
2698 integer :: lvl, min_lvl
2700 if (.not.
allocated(mg%comm_restrict%n_send))
then
2701 error stop
"Call restrict_buffer_size before prolong_buffer_size"
2704 min_lvl = max(mg%first_normal_lvl-1, mg%lowest_lvl)
2705 allocate(mg%comm_prolong%n_send(0:mg%n_cpu-1, &
2706 min_lvl:mg%highest_lvl))
2707 allocate(mg%comm_prolong%n_recv(0:mg%n_cpu-1, &
2708 min_lvl:mg%highest_lvl))
2710 mg%comm_prolong%n_recv(:, mg%highest_lvl) = 0
2711 mg%comm_prolong%n_send(:, mg%highest_lvl) = 0
2713 do lvl = min_lvl, mg%highest_lvl-1
2714 mg%comm_prolong%n_recv(:, lvl) = &
2715 mg%comm_restrict%n_send(:, lvl+1)
2716 mg%comm_prolong%n_send(:, lvl) = &
2717 mg%comm_restrict%n_recv(:, lvl+1)
2722 dsize = (mg%box_size)**3
2723 n_send = maxval(mg%comm_prolong%n_send, dim=2)
2724 n_recv = maxval(mg%comm_prolong%n_recv, dim=2)
2730 type(
mg_t),
intent(inout) :: mg
2731 integer,
intent(in) :: lvl
2732 integer,
intent(in) :: iv
2733 integer,
intent(in) :: iv_to
2734 procedure(mg_box_prolong) :: method
2735 logical,
intent(in) :: add
2736 integer :: i, id, dsize, nc
2738 if (lvl == mg%highest_lvl) error stop
"cannot prolong highest level"
2739 if (lvl < mg%lowest_lvl) error stop
"cannot prolong below lowest level"
2742 if (lvl >= mg%first_normal_lvl-1)
then
2743 dsize = mg%box_size**3
2744 mg%buf(:)%i_send = 0
2747 do i = 1,
size(mg%lvls(lvl)%my_ids)
2748 id = mg%lvls(lvl)%my_ids(i)
2749 call prolong_set_buffer(mg, id, mg%box_size, iv, method)
2752 mg%buf(:)%i_recv = mg%comm_prolong%n_recv(:, lvl) * dsize
2754 mg%buf(:)%i_recv = 0
2757 nc = mg%box_size_lvl(lvl+1)
2758 do i = 1,
size(mg%lvls(lvl+1)%my_ids)
2759 id = mg%lvls(lvl+1)%my_ids(i)
2760 call prolong_onto(mg, id, nc, iv, iv_to, add, method)
2767 subroutine prolong_set_buffer(mg, id, nc, iv, method)
2768 type(
mg_t),
intent(inout) :: mg
2769 integer,
intent(in) :: id
2770 integer,
intent(in) :: nc
2771 integer,
intent(in) :: iv
2772 procedure(mg_box_prolong) :: method
2773 integer :: i, dix(3)
2774 integer :: i_c, c_id, c_rank, dsize
2775 real(
dp) :: tmp(nc, nc, nc)
2780 c_id = mg%boxes(id)%children(i_c)
2782 c_rank = mg%boxes(c_id)%rank
2783 if (c_rank /= mg%my_rank)
then
2785 call method(mg, id, dix, nc, iv, tmp)
2787 i = mg%buf(c_rank)%i_send
2788 mg%buf(c_rank)%send(i+1:i+dsize) = pack(tmp, .true.)
2789 mg%buf(c_rank)%i_send = mg%buf(c_rank)%i_send + dsize
2791 i = mg%buf(c_rank)%i_ix
2792 mg%buf(c_rank)%ix(i+1) = c_id
2793 mg%buf(c_rank)%i_ix = mg%buf(c_rank)%i_ix + 1
2797 end subroutine prolong_set_buffer
2800 subroutine prolong_onto(mg, id, nc, iv, iv_to, add, method)
2801 type(
mg_t),
intent(inout) :: mg
2802 integer,
intent(in) :: id
2803 integer,
intent(in) :: nc
2804 integer,
intent(in) :: iv
2805 integer,
intent(in) :: iv_to
2806 logical,
intent(in) :: add
2807 procedure(mg_box_prolong) :: method
2808 integer :: hnc, p_id, p_rank, i, dix(3), dsize
2809 real(
dp) :: tmp(nc, nc, nc)
2812 p_id = mg%boxes(id)%parent
2813 p_rank = mg%boxes(p_id)%rank
2815 if (p_rank == mg%my_rank)
then
2817 call method(mg, p_id, dix, nc, iv, tmp)
2820 i = mg%buf(p_rank)%i_recv
2821 tmp = reshape(mg%buf(p_rank)%recv(i+1:i+dsize), [nc, nc, nc])
2822 mg%buf(p_rank)%i_recv = mg%buf(p_rank)%i_recv + dsize
2826 mg%boxes(id)%cc(1:nc, 1:nc, 1:nc, iv_to) = &
2827 mg%boxes(id)%cc(1:nc, 1:nc, 1:nc, iv_to) + tmp
2829 mg%boxes(id)%cc(1:nc, 1:nc, 1:nc, iv_to) = tmp
2832 end subroutine prolong_onto
2836 type(
mg_t),
intent(inout) :: mg
2837 integer,
intent(in) :: p_id
2838 integer,
intent(in) :: dix(3)
2839 integer,
intent(in) :: nc
2840 integer,
intent(in) :: iv
2841 real(
dp),
intent(out) :: fine(nc, nc, nc)
2843 integer :: i, j, k, hnc
2844 integer :: ic, jc, kc
2845 real(
dp) :: f0, flx, fhx, fly, fhy, flz, fhz
2849 associate(crs => mg%boxes(p_id)%cc)
2857 f0 = 0.25_dp * crs(ic, jc, kc, iv)
2858 flx = 0.25_dp * crs(ic-1, jc, kc, iv)
2859 fhx = 0.25_dp * crs(ic+1, jc, kc, iv)
2860 fly = 0.25_dp * crs(ic, jc-1, kc, iv)
2861 fhy = 0.25_dp * crs(ic, jc+1, kc, iv)
2862 flz = 0.25_dp * crs(ic, jc, kc-1, iv)
2863 fhz = 0.25_dp * crs(ic, jc, kc+1, iv)
2865 fine(2*i-1, 2*j-1, 2*k-1) = f0 + flx + fly + flz
2866 fine(2*i, 2*j-1, 2*k-1) = f0 + fhx + fly + flz
2867 fine(2*i-1, 2*j, 2*k-1) = f0 + flx + fhy + flz
2868 fine(2*i, 2*j, 2*k-1) = f0 + fhx + fhy + flz
2869 fine(2*i-1, 2*j-1, 2*k) = f0 + flx + fly + fhz
2870 fine(2*i, 2*j-1, 2*k) = f0 + fhx + fly + fhz
2871 fine(2*i-1, 2*j, 2*k) = f0 + flx + fhy + fhz
2872 fine(2*i, 2*j, 2*k) = f0 + fhx + fhy + fhz
2882 type(
mg_t),
intent(inout) :: mg
2884 mg%subtract_mean = .false.
2886 select case (mg%geometry_type)
2888 mg%box_op => box_helmh
2890 select case (mg%smoother_type)
2892 mg%box_smoother => box_gs_helmh
2894 error stop
"helmholtz_set_methods: unsupported smoother type"
2897 error stop
"helmholtz_set_methods: unsupported geometry"
2903 real(
dp),
intent(in) :: lambda
2906 error stop
"helmholtz_set_lambda: lambda < 0 not allowed"
2912 subroutine box_gs_helmh(mg, id, nc, redblack_cntr)
2913 type(
mg_t),
intent(inout) :: mg
2914 integer,
intent(in) :: id
2915 integer,
intent(in) :: nc
2916 integer,
intent(in) :: redblack_cntr
2917 integer :: i, j, k, i0, di
2918 real(
dp) :: idr2(3), fac
2920 real(
dp),
parameter :: sixth = 1/6.0_dp
2922 idr2 = 1/mg%dr(:, mg%boxes(id)%lvl)**2
2935 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi)
2939 i0 = 2 - iand(ieor(redblack_cntr, k+j), 1)
2941 cc(i, j, k, n) = fac * ( &
2942 idr2(1) * (cc(i+1, j, k, n) + cc(i-1, j, k, n)) + &
2943 idr2(2) * (cc(i, j+1, k, n) + cc(i, j-1, k, n)) + &
2944 idr2(3) * (cc(i, j, k+1, n) + cc(i, j, k-1, n)) - &
2950 end subroutine box_gs_helmh
2953 subroutine box_helmh(mg, id, nc, i_out)
2954 type(
mg_t),
intent(inout) :: mg
2955 integer,
intent(in) :: id
2956 integer,
intent(in) :: nc
2957 integer,
intent(in) :: i_out
2961 idr2 = 1 / mg%dr(:, mg%boxes(id)%lvl)**2
2963 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi)
2967 cc(i, j, k, i_out) = &
2968 idr2(1) * (cc(i-1, j, k, n) + cc(i+1, j, k, n) &
2969 - 2 * cc(i, j, k, n)) &
2970 + idr2(2) * (cc(i, j-1, k, n) + cc(i, j+1, k, n) &
2971 - 2 * cc(i, j, k, n)) &
2972 + idr2(3) * (cc(i, j, k-1, n) + cc(i, j, k+1, n) &
2973 - 2 * cc(i, j, k, n)) - &
2979 end subroutine box_helmh
2985 type(
mg_t),
intent(inout) :: mg
2990 select case (mg%operator_type)
3002 error stop
"mg_set_methods: unknown operator"
3008 mg%n_smoother_substeps = 2
3010 mg%n_smoother_substeps = 1
3014 subroutine check_methods(mg)
3015 type(
mg_t),
intent(inout) :: mg
3017 if (.not.
associated(mg%box_op) .or. &
3018 .not.
associated(mg%box_smoother))
then
3022 end subroutine check_methods
3024 subroutine mg_add_timers(mg)
3025 type(
mg_t),
intent(inout) :: mg
3026 timer_total_vcycle =
mg_add_timer(mg,
"mg total V-cycle")
3027 timer_total_fmg =
mg_add_timer(mg,
"mg total FMG cycle")
3029 timer_smoother_gc =
mg_add_timer(mg,
"mg smoother g.c.")
3032 timer_update_coarse =
mg_add_timer(mg,
"mg update coarse")
3033 end subroutine mg_add_timers
3037 type(
mg_t),
intent(inout) :: mg
3038 logical,
intent(in) :: have_guess
3039 real(
dp),
intent(out),
optional :: max_res
3040 integer :: lvl, i, id
3042 call check_methods(mg)
3043 if (timer_smoother == -1)
call mg_add_timers(mg)
3047 if (.not. have_guess)
then
3048 do lvl = mg%highest_lvl, mg%lowest_lvl, -1
3049 do i = 1,
size(mg%lvls(lvl)%my_ids)
3050 id = mg%lvls(lvl)%my_ids(i)
3051 mg%boxes(id)%cc(:, :, :,
mg_iphi) = 0.0_dp
3059 do lvl = mg%highest_lvl, mg%lowest_lvl+1, -1
3062 call update_coarse(mg, lvl)
3066 if (mg%subtract_mean)
then
3071 do lvl = mg%lowest_lvl, mg%highest_lvl
3073 do i = 1,
size(mg%lvls(lvl)%my_ids)
3074 id = mg%lvls(lvl)%my_ids(i)
3075 mg%boxes(id)%cc(:, :, :,
mg_iold) = &
3076 mg%boxes(id)%cc(:, :, :,
mg_iphi)
3079 if (lvl > mg%lowest_lvl)
then
3083 call correct_children(mg, lvl-1)
3091 if (lvl == mg%highest_lvl)
then
3104 type(
mg_t),
intent(inout) :: mg
3105 integer,
intent(in),
optional :: highest_lvl
3106 real(
dp),
intent(out),
optional :: max_res
3108 logical,
intent(in),
optional :: standalone
3109 integer :: lvl, min_lvl, i, max_lvl, ierr
3110 real(
dp) :: init_res, res
3111 logical :: is_standalone
3113 is_standalone = .true.
3114 if (
present(standalone)) is_standalone = standalone
3116 call check_methods(mg)
3117 if (timer_smoother == -1)
call mg_add_timers(mg)
3119 if (is_standalone) &
3122 if (mg%subtract_mean .and. .not.
present(highest_lvl))
then
3128 min_lvl = mg%lowest_lvl
3129 max_lvl = mg%highest_lvl
3130 if (
present(highest_lvl)) max_lvl = highest_lvl
3133 if (is_standalone)
then
3137 do lvl = max_lvl, min_lvl+1, -1
3139 call smooth_boxes(mg, lvl, mg%n_cycle_down)
3144 call update_coarse(mg, lvl)
3149 if (.not. all(mg%boxes(mg%lvls(min_lvl)%ids)%rank == &
3150 mg%boxes(mg%lvls(min_lvl)%ids(1))%rank))
then
3151 error stop
"Multiple CPUs for coarse grid (not implemented yet)"
3154 init_res = max_residual_lvl(mg, min_lvl)
3155 do i = 1, mg%max_coarse_cycles
3156 call smooth_boxes(mg, min_lvl, mg%n_cycle_up+mg%n_cycle_down)
3157 res = max_residual_lvl(mg, min_lvl)
3158 if (res < mg%residual_coarse_rel * init_res .or. &
3159 res < mg%residual_coarse_abs)
exit
3164 do lvl = min_lvl+1, max_lvl
3168 call correct_children(mg, lvl-1)
3175 call smooth_boxes(mg, lvl, mg%n_cycle_up)
3178 if (
present(max_res))
then
3180 do lvl = min_lvl, max_lvl
3181 res = max_residual_lvl(mg, lvl)
3182 init_res = max(res, init_res)
3184 call mpi_allreduce(init_res, max_res, 1, &
3185 mpi_double, mpi_max, mg%comm, ierr)
3189 if (mg%subtract_mean)
then
3193 if (is_standalone) &
3199 type(
mg_t),
intent(inout) :: mg
3200 integer,
intent(in) :: iv
3201 logical,
intent(in) :: include_ghostcells
3202 integer :: i, id, lvl, nc, ierr
3203 real(dp) :: sum_iv, mean_iv, volume
3207 call mpi_allreduce(sum_iv, mean_iv, 1, &
3208 mpi_double, mpi_sum, mg%comm, ierr)
3211 volume = nc**3 * product(mg%dr(:, 1)) *
size(mg%lvls(1)%ids)
3212 mean_iv = mean_iv / volume
3214 do lvl = mg%lowest_lvl, mg%highest_lvl
3215 nc = mg%box_size_lvl(lvl)
3217 do i = 1,
size(mg%lvls(lvl)%my_ids)
3218 id = mg%lvls(lvl)%my_ids(i)
3219 if (include_ghostcells)
then
3220 mg%boxes(id)%cc(:, :, :, iv) = &
3221 mg%boxes(id)%cc(:, :, :, iv) - mean_iv
3223 mg%boxes(id)%cc(1:nc, 1:nc, 1:nc, iv) = &
3224 mg%boxes(id)%cc(1:nc, 1:nc, 1:nc, iv) - mean_iv
3231 type(
mg_t),
intent(in) :: mg
3232 integer,
intent(in) :: iv
3233 integer :: lvl, i, id, nc
3237 do lvl = 1, mg%highest_lvl
3238 nc = mg%box_size_lvl(lvl)
3239 w = product(mg%dr(:, lvl))
3240 do i = 1,
size(mg%lvls(lvl)%my_leaves)
3241 id = mg%lvls(lvl)%my_leaves(i)
3243 sum(mg%boxes(id)%cc(1:nc, 1:nc, 1:nc, iv))
3248 real(
dp) function max_residual_lvl(mg, lvl)
3249 type(
mg_t),
intent(inout) :: mg
3250 integer,
intent(in) :: lvl
3251 integer :: i, id, nc
3254 nc = mg%box_size_lvl(lvl)
3255 max_residual_lvl = 0.0_dp
3257 do i = 1,
size(mg%lvls(lvl)%my_ids)
3258 id = mg%lvls(lvl)%my_ids(i)
3259 call residual_box(mg, id, nc)
3260 res = maxval(abs(mg%boxes(id)%cc(1:nc, 1:nc, 1:nc,
mg_ires)))
3261 max_residual_lvl = max(max_residual_lvl, res)
3263 end function max_residual_lvl
3299 subroutine update_coarse(mg, lvl)
3300 type(
mg_t),
intent(inout) :: mg
3301 integer,
intent(in) :: lvl
3302 integer :: i, id, nc, nc_c
3304 nc = mg%box_size_lvl(lvl)
3305 nc_c = mg%box_size_lvl(lvl-1)
3308 do i = 1,
size(mg%lvls(lvl)%my_ids)
3309 id = mg%lvls(lvl)%my_ids(i)
3310 call residual_box(mg, id, nc)
3321 do i = 1,
size(mg%lvls(lvl-1)%my_parents)
3322 id = mg%lvls(lvl-1)%my_parents(i)
3325 call mg%box_op(mg, id, nc_c,
mg_irhs)
3328 mg%boxes(id)%cc(1:nc_c, 1:nc_c, 1:nc_c,
mg_irhs) = &
3329 mg%boxes(id)%cc(1:nc_c, 1:nc_c, 1:nc_c,
mg_irhs) + &
3330 mg%boxes(id)%cc(1:nc_c, 1:nc_c, 1:nc_c,
mg_ires)
3333 mg%boxes(id)%cc(:, :, :,
mg_iold) = &
3334 mg%boxes(id)%cc(:, :, :,
mg_iphi)
3336 end subroutine update_coarse
3339 subroutine correct_children(mg, lvl)
3340 type(
mg_t),
intent(inout) :: mg
3341 integer,
intent(in) :: lvl
3344 do i = 1,
size(mg%lvls(lvl)%my_parents)
3345 id = mg%lvls(lvl)%my_parents(i)
3348 mg%boxes(id)%cc(:, :, :,
mg_ires) = &
3349 mg%boxes(id)%cc(:, :, :,
mg_iphi) - &
3350 mg%boxes(id)%cc(:, :, :,
mg_iold)
3354 end subroutine correct_children
3356 subroutine smooth_boxes(mg, lvl, n_cycle)
3357 type(
mg_t),
intent(inout) :: mg
3358 integer,
intent(in) :: lvl
3359 integer,
intent(in) :: n_cycle
3360 integer :: n, i, id, nc
3362 nc = mg%box_size_lvl(lvl)
3364 do n = 1, n_cycle * mg%n_smoother_substeps
3366 do i = 1,
size(mg%lvls(lvl)%my_ids)
3367 id = mg%lvls(lvl)%my_ids(i)
3368 call mg%box_smoother(mg, id, nc, n)
3376 end subroutine smooth_boxes
3378 subroutine residual_box(mg, id, nc)
3379 type(
mg_t),
intent(inout) :: mg
3380 integer,
intent(in) :: id
3381 integer,
intent(in) :: nc
3383 call mg%box_op(mg, id, nc,
mg_ires)
3385 mg%boxes(id)%cc(1:nc, 1:nc, 1:nc,
mg_ires) = &
3386 mg%boxes(id)%cc(1:nc, 1:nc, 1:nc,
mg_irhs) &
3387 - mg%boxes(id)%cc(1:nc, 1:nc, 1:nc,
mg_ires)
3388 end subroutine residual_box
3392 type(
mg_t),
intent(inout) :: mg
3393 integer,
intent(in) :: i_out
3394 procedure(mg_box_op),
optional :: op
3395 integer :: lvl, i, id, nc
3397 do lvl = mg%lowest_lvl, mg%highest_lvl
3398 nc = mg%box_size_lvl(lvl)
3399 do i = 1,
size(mg%lvls(lvl)%my_ids)
3400 id = mg%lvls(lvl)%my_ids(i)
3401 if (
present(op))
then
3402 call op(mg, id, nc, i_out)
3404 call mg%box_op(mg, id, nc, i_out)
3414 type(
mg_t),
intent(inout) :: mg
3415 integer,
intent(out) :: n_send(0:mg%n_cpu-1)
3416 integer,
intent(out) :: n_recv(0:mg%n_cpu-1)
3417 integer,
intent(out) :: dsize
3418 integer :: n_out(0:mg%n_cpu-1, mg%first_normal_lvl:mg%highest_lvl)
3419 integer :: n_in(0:mg%n_cpu-1, mg%first_normal_lvl:mg%highest_lvl)
3420 integer :: lvl, i, id, p_id, p_rank
3421 integer :: i_c, c_id, c_rank, min_lvl
3425 min_lvl = max(mg%lowest_lvl+1, mg%first_normal_lvl)
3427 do lvl = min_lvl, mg%highest_lvl
3429 do i = 1,
size(mg%lvls(lvl-1)%my_parents)
3430 id = mg%lvls(lvl-1)%my_parents(i)
3432 c_id = mg%boxes(id)%children(i_c)
3435 c_rank = mg%boxes(c_id)%rank
3436 if (c_rank /= mg%my_rank)
then
3437 n_in(c_rank, lvl) = n_in(c_rank, lvl) + 1
3444 do i = 1,
size(mg%lvls(lvl)%my_ids)
3445 id = mg%lvls(lvl)%my_ids(i)
3447 p_id = mg%boxes(id)%parent
3448 p_rank = mg%boxes(p_id)%rank
3449 if (p_rank /= mg%my_rank)
then
3450 n_out(p_rank, lvl) = n_out(p_rank, lvl) + 1
3456 allocate(mg%comm_restrict%n_send(0:mg%n_cpu-1, &
3457 mg%first_normal_lvl:mg%highest_lvl))
3458 allocate(mg%comm_restrict%n_recv(0:mg%n_cpu-1, &
3459 mg%first_normal_lvl:mg%highest_lvl))
3460 mg%comm_restrict%n_send = n_out
3461 mg%comm_restrict%n_recv = n_in
3463 dsize = (mg%box_size/2)**3
3464 n_send = maxval(n_out, dim=2)
3465 n_recv = maxval(n_in, dim=2)
3470 type(
mg_t),
intent(inout) :: mg
3471 integer,
intent(in) :: iv
3474 do lvl = mg%highest_lvl, mg%lowest_lvl+1, -1
3482 type(
mg_t),
intent(inout) :: mg
3483 integer,
intent(in) :: iv
3484 integer,
intent(in) :: lvl
3485 integer :: i, id, dsize, nc
3487 if (lvl <= mg%lowest_lvl) error stop
"cannot restrict lvl <= lowest_lvl"
3489 nc = mg%box_size_lvl(lvl)
3491 if (lvl >= mg%first_normal_lvl)
then
3494 mg%buf(:)%i_send = 0
3497 do i = 1,
size(mg%lvls(lvl)%my_ids)
3498 id = mg%lvls(lvl)%my_ids(i)
3499 call restrict_set_buffer(mg, id, iv)
3502 mg%buf(:)%i_recv = mg%comm_restrict%n_recv(:, lvl) * dsize
3504 mg%buf(:)%i_recv = 0
3507 do i = 1,
size(mg%lvls(lvl-1)%my_parents)
3508 id = mg%lvls(lvl-1)%my_parents(i)
3509 call restrict_onto(mg, id, nc, iv)
3513 subroutine restrict_set_buffer(mg, id, iv)
3514 type(
mg_t),
intent(inout) :: mg
3515 integer,
intent(in) :: id
3516 integer,
intent(in) :: iv
3517 integer :: i, j, k, n, hnc, p_id, p_rank
3518 real(
dp) :: tmp(mg%box_size/2, mg%box_size/2, mg%box_size/2)
3521 p_id = mg%boxes(id)%parent
3522 p_rank = mg%boxes(p_id)%rank
3524 if (p_rank /= mg%my_rank)
then
3528 tmp(i, j, k) = 0.125_dp * sum(mg%boxes(id)%cc(2*i-1:2*i, &
3529 2*j-1:2*j, 2*k-1:2*k, iv))
3536 i = mg%buf(p_rank)%i_send
3537 mg%buf(p_rank)%send(i+1:i+n) = pack(tmp, .true.)
3538 mg%buf(p_rank)%i_send = mg%buf(p_rank)%i_send + n
3541 i = mg%buf(p_rank)%i_ix
3544 mg%buf(p_rank)%i_ix = mg%buf(p_rank)%i_ix + 1
3546 end subroutine restrict_set_buffer
3548 subroutine restrict_onto(mg, id, nc, iv)
3549 type(
mg_t),
intent(inout) :: mg
3550 integer,
intent(in) :: id
3551 integer,
intent(in) :: nc
3552 integer,
intent(in) :: iv
3553 integer :: i, j, k, hnc, dsize, i_c, c_id
3554 integer :: c_rank, dix(3)
3560 c_id = mg%boxes(id)%children(i_c)
3562 c_rank = mg%boxes(c_id)%rank
3565 if (c_rank == mg%my_rank)
then
3566 do j=1, hnc;
do i=1, hnc;
do k=1, hnc
3567 mg%boxes(id)%cc(dix(1)+i, dix(2)+j, dix(3)+k, iv) = &
3568 0.125_dp * sum(mg%boxes(c_id)%cc(2*i-1:2*i, &
3569 2*j-1:2*j, 2*k-1:2*k, iv))
3570 end do;
end do;
end do
3572 i = mg%buf(c_rank)%i_recv
3573 mg%boxes(id)%cc(dix(1)+1:dix(1)+hnc, &
3574 dix(2)+1:dix(2)+hnc, dix(3)+1:dix(3)+hnc, iv) = &
3575 reshape(mg%buf(c_rank)%recv(i+1:i+dsize), [hnc, hnc, hnc])
3576 mg%buf(c_rank)%i_recv = mg%buf(c_rank)%i_recv + dsize
3580 end subroutine restrict_onto
3584 Subroutine i_mrgrnk (XDONT, IRNGT)
3591 Integer,
Dimension (:),
Intent (In) :: xdont
3592 Integer,
Dimension (:),
Intent (Out) :: irngt
3594 Integer :: xvala, xvalb
3596 Integer,
Dimension (SIZE(IRNGT)) :: jwrkt
3597 Integer :: lmtna, lmtnc, irng1, irng2
3598 Integer :: nval, iind, iwrkd, iwrk, iwrkf, jinda, iinda, iindb
3600 nval = min(
SIZE(xdont),
SIZE(irngt))
3613 Do iind = 2, nval, 2
3614 If (xdont(iind-1) <= xdont(iind))
Then
3615 irngt(iind-1) = iind - 1
3618 irngt(iind-1) = iind
3619 irngt(iind) = iind - 1
3622 If (modulo(nval, 2) /= 0)
Then
3639 Do iwrkd = 0, nval - 1, 4
3640 If ((iwrkd+4) > nval)
Then
3641 If ((iwrkd+2) >= nval)
Exit
3645 If (xdont(irngt(iwrkd+2)) <= xdont(irngt(iwrkd+3)))
Exit
3649 If (xdont(irngt(iwrkd+1)) <= xdont(irngt(iwrkd+3)))
Then
3650 irng2 = irngt(iwrkd+2)
3651 irngt(iwrkd+2) = irngt(iwrkd+3)
3652 irngt(iwrkd+3) = irng2
3657 irng1 = irngt(iwrkd+1)
3658 irngt(iwrkd+1) = irngt(iwrkd+3)
3659 irngt(iwrkd+3) = irngt(iwrkd+2)
3660 irngt(iwrkd+2) = irng1
3667 If (xdont(irngt(iwrkd+2)) <= xdont(irngt(iwrkd+3))) cycle
3671 If (xdont(irngt(iwrkd+1)) <= xdont(irngt(iwrkd+3)))
Then
3672 irng2 = irngt(iwrkd+2)
3673 irngt(iwrkd+2) = irngt(iwrkd+3)
3674 If (xdont(irng2) <= xdont(irngt(iwrkd+4)))
Then
3676 irngt(iwrkd+3) = irng2
3679 irngt(iwrkd+3) = irngt(iwrkd+4)
3680 irngt(iwrkd+4) = irng2
3686 irng1 = irngt(iwrkd+1)
3687 irng2 = irngt(iwrkd+2)
3688 irngt(iwrkd+1) = irngt(iwrkd+3)
3689 If (xdont(irng1) <= xdont(irngt(iwrkd+4)))
Then
3690 irngt(iwrkd+2) = irng1
3691 If (xdont(irng2) <= xdont(irngt(iwrkd+4)))
Then
3693 irngt(iwrkd+3) = irng2
3696 irngt(iwrkd+3) = irngt(iwrkd+4)
3697 irngt(iwrkd+4) = irng2
3701 irngt(iwrkd+2) = irngt(iwrkd+4)
3702 irngt(iwrkd+3) = irng1
3703 irngt(iwrkd+4) = irng2
3718 If (lmtna >= nval)
Exit
3727 jinda = iwrkf + lmtna
3728 iwrkf = iwrkf + lmtnc
3729 If (iwrkf >= nval)
Then
3730 If (jinda >= nval)
Exit
3746 jwrkt(1:lmtna) = irngt(iwrkd:jinda)
3748 xvala = xdont(jwrkt(iinda))
3749 xvalb = xdont(irngt(iindb))
3756 If (xvala > xvalb)
Then
3757 irngt(iwrk) = irngt(iindb)
3759 If (iindb > iwrkf)
Then
3761 irngt(iwrk+1:iwrkf) = jwrkt(iinda:lmtna)
3764 xvalb = xdont(irngt(iindb))
3766 irngt(iwrk) = jwrkt(iinda)
3768 If (iinda > lmtna) exit
3769 xvala = xdont(jwrkt(iinda))
3782 End Subroutine i_mrgrnk
3787 type(
mg_t),
intent(inout) :: mg
3789 if (mg%n_extra_vars == 0 .and. mg%is_allocated)
then
3790 error stop
"ahelmholtz_set_methods: mg%n_extra_vars == 0"
3792 mg%n_extra_vars = max(3, mg%n_extra_vars)
3806 select case (mg%geometry_type)
3808 mg%box_op => box_ahelmh
3810 select case (mg%smoother_type)
3812 mg%box_smoother => box_gs_ahelmh
3814 error stop
"ahelmholtz_set_methods: unsupported smoother type"
3817 error stop
"ahelmholtz_set_methods: unsupported geometry"
3823 real(
dp),
intent(in) :: lambda
3826 error stop
"ahelmholtz_set_lambda: lambda < 0 not allowed"
3832 subroutine box_gs_ahelmh(mg, id, nc, redblack_cntr)
3833 type(
mg_t),
intent(inout) :: mg
3834 integer,
intent(in) :: id
3835 integer,
intent(in) :: nc
3836 integer,
intent(in) :: redblack_cntr
3837 integer :: i, j, k, i0, di
3839 real(
dp) :: idr2(2*3), u(2*3)
3840 real(
dp) :: a0(2*3), a(2*3), c(2*3)
3843 idr2(1:2*3:2) = 1/mg%dr(:, mg%boxes(id)%lvl)**2
3844 idr2(2:2*3:2) = idr2(1:2*3:2)
3856 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi, &
3864 i0 = 2 - iand(ieor(redblack_cntr, k+j), 1)
3866 a0(1:2) = cc(i, j, k, i_eps1)
3867 a0(3:4) = cc(i, j, k, i_eps2)
3868 a0(4:5) = cc(i, j, k, i_eps3)
3869 u(1:2) = cc(i-1:i+1:2, j, k, n)
3870 a(1:2) = cc(i-1:i+1:2, j, k, i_eps1)
3871 u(3:4) = cc(i, j-1:j+1:2, k, n)
3872 a(3:4) = cc(i, j-1:j+1:2, k, i_eps2)
3873 u(5:6) = cc(i, j, k-1:k+1:2, n)
3874 a(5:6) = cc(i, j, k-1:k+1:2, i_eps3)
3875 c(:) = 2 * a0(:) * a(:) / (a0(:) + a(:)) * idr2
3877 cc(i, j, k, n) = (sum(c(:) * u(:)) - &
3884 end subroutine box_gs_ahelmh
3887 subroutine box_ahelmh(mg, id, nc, i_out)
3888 type(
mg_t),
intent(inout) :: mg
3889 integer,
intent(in) :: id
3890 integer,
intent(in) :: nc
3891 integer,
intent(in) :: i_out
3893 real(
dp) :: idr2(2*3), a0(2*3), u0, u(2*3), a(2*3)
3896 idr2(1:2*3:2) = 1/mg%dr(:, mg%boxes(id)%lvl)**2
3897 idr2(2:2*3:2) = idr2(1:2*3:2)
3899 associate(cc => mg%boxes(id)%cc, n =>
mg_iphi, &
3907 a0(1:2) = cc(i, j, k, i_eps1)
3908 a0(3:4) = cc(i, j, k, i_eps2)
3909 a0(5:6) = cc(i, j, k, i_eps3)
3910 u(1:2) = cc(i-1:i+1:2, j, k, n)
3911 u(3:4) = cc(i, j-1:j+1:2, k, n)
3912 u(5:6) = cc(i, j, k-1:k+1:2, n)
3913 a(1:2) = cc(i-1:i+1:2, j, k, i_eps1)
3914 a(3:4) = cc(i, j-1:j+1:2, k, i_eps2)
3915 a(5:6) = cc(i, j, k-1:k+1:2, i_eps3)
3917 cc(i, j, k, i_out) = sum(2 * idr2 * &
3918 a0(:)*a(:)/(a0(:) + a(:)) * (u(:) - u0)) - &
3924 end subroutine box_ahelmh
To fill ghost cells near physical 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 subtract_mean(mg, iv, include_ghostcells)
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.
real(dp) function get_sum(mg, iv)
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 sort_sendbuf(gc, dsize)
Sort send buffers according to the idbuf array.
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.