6 program multigrid_matrix_3d
11 integer,
parameter :: box_size = 16
12 integer,
parameter :: n_boxes_base = 1
13 integer,
parameter :: n_iterations = 10
14 integer,
parameter :: n_var_cell = 5
15 integer,
parameter :: i_phi = 1
16 integer,
parameter :: i_rhs = 2
17 integer,
parameter :: i_tmp = 3
18 integer,
parameter :: i_mat_diag = 4
19 integer,
parameter :: i_ins = 5
20 integer,
parameter :: if_mat_nb = 1
23 type(ref_info_t) :: refine_info
25 integer :: ix_list(3, n_boxes_base)
26 real(dp) :: dr, residu(2), my_sum
27 character(len=100) :: fname
29 integer :: lvl, i, id, p_id
31 print *,
"Running multigrid_matrix_3d" 32 print *,
"Number of threads", af_get_max_threads()
35 dr = 4.0_dp / box_size
44 cc_names=[
"phi",
"rhs",
"tmp",
"a00",
"ins"])
48 ix_list(:, 1) = [1, 1, 1]
51 call a3_set_base(tree, 1, ix_list)
54 call a3_loop_box(tree, set_initial_condition)
55 call a3_adjust_refinement(tree, refine_routine, refine_info)
56 if (refine_info%n_add == 0)
exit 60 do lvl = tree%highest_lvl-1, lbound(tree%lvls, 1), -1
61 do i = 1,
size(tree%lvls(lvl)%parents)
62 p_id = tree%lvls(lvl)%parents(i)
63 call restrict_matrix(tree%boxes, p_id, i_mat_diag, if_mat_nb)
72 mg%sides_bc => bc_dirichlet_one
74 mg%box_op => box_matrix
75 mg%box_gsrb => box_gsrb
79 do mg_iter = 1, n_iterations
80 call mg3_fas_fmg(tree, mg, set_residual=.true., have_guess=(mg_iter>1))
83 call a3_tree_min_cc(tree, i_tmp, residu(1))
84 call a3_tree_max_cc(tree, i_tmp, residu(2))
85 call a3_tree_sum_cc(tree, i_phi, my_sum)
86 write(*,
"(I8,13x,2Es14.5)") mg_iter, maxval(abs(residu)), my_sum
88 write(fname,
"(A,I0)")
"multigrid_matrix_3d_", mg_iter
89 call a3_write_silo(tree, trim(fname), dir=
"output")
95 subroutine refine_routine(box, cell_flags)
96 type(box3_t),
intent(in) :: box
97 integer,
intent(out) :: cell_flags(box%n_cell, box%n_cell, box%n_cell)
100 cell_flags(:, :, :) = af_do_ref
102 cell_flags(:, :, :) = af_keep_ref
104 end subroutine refine_routine
107 subroutine set_initial_condition(box)
108 type(box3_t),
intent(inout) :: box
109 integer :: i, j, k, nc
110 real(dp) :: rr(3), inv_dr2, dr2
114 inv_dr2 = 1/box%dr**2
116 do k = 0, nc+1;
do j = 0, nc+1;
do i = 0, nc+1
118 rr = a3_r_cc(box, [i, j, k])
121 box%cc(i, j, k, i_rhs) = 0.0_dp
122 box%cc(i, j, k, i_phi) = 0.0_dp
127 box%cc(i, j, k, i_ins) = sum(abs(rr)) - 0.5_dp
130 end do; end do; end do
132 end subroutine set_initial_condition
134 subroutine box_matrix(box, i_out, mg)
135 type(box3_t),
intent(inout) :: box
136 integer,
intent(in) :: i_out
137 type(mg3_t),
intent(in) :: mg
138 integer :: i, j, nc, i_phi
139 real(dp) :: inv_dr_sq, coeffs(2*3+1), vals(2*3+1)
143 inv_dr_sq = 1 / box%dr**2
149 coeffs(1:2) = box%fc(i:i+1, j, k, 1, if_mat_nb)
150 coeffs(3:4) = box%fc(i, j:j+1, k, 2, if_mat_nb)
151 coeffs(5:6) = box%fc(i, j, k:k+1, 3, if_mat_nb)
152 coeffs(7) = box%cc(i, j, k, i_mat_diag)
154 vals(1) = box%cc(i-1, j, k, i_phi)
155 vals(2) = box%cc(i+1, j, k, i_phi)
156 vals(3) = box%cc(i, j-1, k, i_phi)
157 vals(4) = box%cc(i, j+1, k, i_phi)
158 vals(5) = box%cc(i, j, k-1, i_phi)
159 vals(6) = box%cc(i, j, k+1, i_phi)
160 vals(7) = box%cc(i, j, k, i_phi)
162 box%cc(i, j, k, i_out) = sum(coeffs * vals)
166 end subroutine box_matrix
168 subroutine box_gsrb(box, redblack_cntr, mg)
169 type(box3_t),
intent(inout) :: box
170 integer,
intent(in) :: redblack_cntr
171 type(mg3_t),
intent(in) :: mg
172 integer :: i, i0, j, nc, i_phi, i_rhs
173 real(dp) :: inv_dr_sq, coeffs(2*3+1), vals(2*3)
177 inv_dr_sq = 1 / box%dr**2
183 i0 = 2 - iand(ieor(redblack_cntr, k+j), 1)
185 coeffs(1:2) = box%fc(i:i+1, j, k, 1, if_mat_nb)
186 coeffs(3:4) = box%fc(i, j:j+1, k, 2, if_mat_nb)
187 coeffs(5:6) = box%fc(i, j, k:k+1, 3, if_mat_nb)
188 coeffs(7) = box%cc(i, j, k, i_mat_diag)
190 vals(1) = box%cc(i-1, j, k, i_phi)
191 vals(2) = box%cc(i+1, j, k, i_phi)
192 vals(3) = box%cc(i, j-1, k, i_phi)
193 vals(4) = box%cc(i, j+1, k, i_phi)
194 vals(5) = box%cc(i, j, k-1, i_phi)
195 vals(6) = box%cc(i, j, k+1, i_phi)
197 box%cc(i, j, k, i_phi) = (box%cc(i, j, k, i_rhs) - &
198 sum(coeffs(1:6) * vals)) / coeffs(7)
202 end subroutine box_gsrb
204 subroutine restrict_matrix(boxes, p_id, iv_diag, ivf_nb)
205 type(box3_t),
intent(inout) :: boxes(:)
206 integer,
intent(in) :: p_id
207 integer,
intent(in) :: iv_diag
208 integer,
intent(in) :: ivf_nb
209 integer :: c_id, nc, n
211 nc = boxes(p_id)%n_cell
213 do n = 1, a3_num_children
214 c_id = boxes(p_id)%children(n)
215 if (c_id <= af_no_box) cycle
216 call a3_restrict_box(boxes(c_id), boxes(p_id), iv_diag)
217 call a3_restrict_box_face(boxes(c_id), boxes(p_id), ivf_nb)
220 boxes(p_id)%cc(1:nc, 1:nc, 1:nc, iv_diag) = &
221 boxes(p_id)%cc(1:nc, 1:nc, 1:nc, iv_diag) * 0.25_dp
222 boxes(p_id)%fc(1:nc+1, 1:nc+1, 1:nc+1, 1:3, ivf_nb) = &
223 boxes(p_id)%fc(1:nc+1, 1:nc+1, 1:nc+1, 1:3, ivf_nb) * 0.25_dp
225 end subroutine restrict_matrix
228 subroutine bc_dirichlet_one(box, nb, iv, bc_type)
229 type(box3_t),
intent(inout) :: box
230 integer,
intent(in) :: nb, iv
231 integer,
intent(out) :: bc_type
233 bc_type = af_bc_dirichlet
234 call a3_set_box_gc(box, nb, iv, 1.0_dp)
235 end subroutine bc_dirichlet_one
237 end program multigrid_matrix_3d
Module which contains all Afivo modules, so that a user does not have to include them separately...