6 program multigrid_matrix_2d
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(2, 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_2d" 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]
51 call a2_set_base(tree, 1, ix_list)
54 call a2_loop_box(tree, set_initial_condition)
55 call a2_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 mg2_fas_fmg(tree, mg, set_residual=.true., have_guess=(mg_iter>1))
83 call a2_tree_min_cc(tree, i_tmp, residu(1))
84 call a2_tree_max_cc(tree, i_tmp, residu(2))
85 call a2_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_2d_", mg_iter
89 call a2_write_silo(tree, trim(fname), dir=
"output")
95 subroutine refine_routine(box, cell_flags)
96 type(box2_t),
intent(in) :: box
97 integer,
intent(out) :: cell_flags(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(box2_t),
intent(inout) :: box
110 real(dp) :: rr(2), inv_dr2, dr2
114 inv_dr2 = 1/box%dr**2
116 do j = 0, nc+1;
do i = 0, nc+1
118 rr = a2_r_cc(box, [i, j])
121 box%cc(i, j, i_rhs) = 0.0_dp
122 box%cc(i, j, i_phi) = 0.0_dp
127 box%cc(i, j, i_ins) = sum(abs(rr)) - 0.5_dp
135 box%cc(i, j, i_mat_diag) = -4 * inv_dr2
141 if (box%cc(i-1, j, i_ins) < 0 .or. box%cc(i, j, i_ins) < 0)
then 143 box%fc(i, j, 1, if_mat_nb) = 0
144 box%cc(i-1, j, i_rhs) = box%cc(i-1, j, i_rhs) - 2*inv_dr2
145 box%cc(i-1, j, i_mat_diag) = box%cc(i-1, j, i_mat_diag) - inv_dr2
146 box%cc(i, j, i_rhs) = box%cc(i, j, i_rhs) - 2*inv_dr2
147 box%cc(i, j, i_mat_diag) = box%cc(i, j, i_mat_diag) - inv_dr2
149 box%fc(i, j, 1, if_mat_nb) = inv_dr2
156 if (box%cc(i, j-1, i_ins) < 0 .or. box%cc(i, j, i_ins) < 0)
then 158 box%fc(i, j, 2, if_mat_nb) = 0
159 box%cc(i, j-1, i_rhs) = box%cc(i, j-1, i_rhs) - 2*inv_dr2
160 box%cc(i, j-1, i_mat_diag) = box%cc(i, j-1, i_mat_diag) - inv_dr2
161 box%cc(i, j, i_rhs) = box%cc(i, j, i_rhs) - 2*inv_dr2
162 box%cc(i, j, i_mat_diag) = box%cc(i, j, i_mat_diag) - inv_dr2
164 box%fc(i, j, 2, if_mat_nb) = inv_dr2
169 end subroutine set_initial_condition
171 subroutine box_matrix(box, i_out, mg)
172 type(box2_t),
intent(inout) :: box
173 integer,
intent(in) :: i_out
174 type(mg2_t),
intent(in) :: mg
175 integer :: i, j, nc, i_phi
176 real(dp) :: inv_dr_sq, coeffs(2*2+1), vals(2*2+1)
179 inv_dr_sq = 1 / box%dr**2
184 coeffs(1:2) = box%fc(i:i+1, j, 1, if_mat_nb)
185 coeffs(3:4) = box%fc(i, j:j+1, 2, if_mat_nb)
186 coeffs(5) = box%cc(i, j, i_mat_diag)
188 vals(1) = box%cc(i-1, j, i_phi)
189 vals(2) = box%cc(i+1, j, i_phi)
190 vals(3) = box%cc(i, j-1, i_phi)
191 vals(4) = box%cc(i, j+1, i_phi)
192 vals(5) = box%cc(i, j, i_phi)
194 box%cc(i, j, i_out) = sum(coeffs * vals)
197 end subroutine box_matrix
199 subroutine box_gsrb(box, redblack_cntr, mg)
200 type(box2_t),
intent(inout) :: box
201 integer,
intent(in) :: redblack_cntr
202 type(mg2_t),
intent(in) :: mg
203 integer :: i, i0, j, nc, i_phi, i_rhs
204 real(dp) :: inv_dr_sq, coeffs(2*2+1), vals(2*2)
207 inv_dr_sq = 1 / box%dr**2
212 i0 = 2 - iand(ieor(redblack_cntr, j), 1)
214 coeffs(1:2) = box%fc(i:i+1, j, 1, if_mat_nb)
215 coeffs(3:4) = box%fc(i, j:j+1, 2, if_mat_nb)
216 coeffs(5) = box%cc(i, j, i_mat_diag)
218 vals(1) = box%cc(i-1, j, i_phi)
219 vals(2) = box%cc(i+1, j, i_phi)
220 vals(3) = box%cc(i, j-1, i_phi)
221 vals(4) = box%cc(i, j+1, i_phi)
223 box%cc(i, j, i_phi) = (box%cc(i, j, i_rhs) - &
224 sum(coeffs(1:4) * vals)) / coeffs(5)
227 end subroutine box_gsrb
229 subroutine restrict_matrix(boxes, p_id, iv_diag, ivf_nb)
230 type(box2_t),
intent(inout) :: boxes(:)
231 integer,
intent(in) :: p_id
232 integer,
intent(in) :: iv_diag
233 integer,
intent(in) :: ivf_nb
234 integer :: c_id, nc, n
236 nc = boxes(p_id)%n_cell
238 do n = 1, a2_num_children
239 c_id = boxes(p_id)%children(n)
240 if (c_id <= af_no_box) cycle
241 call a2_restrict_box(boxes(c_id), boxes(p_id), iv_diag)
242 call a2_restrict_box_face(boxes(c_id), boxes(p_id), ivf_nb)
245 boxes(p_id)%cc(1:nc, 1:nc, iv_diag) = &
246 boxes(p_id)%cc(1:nc, 1:nc, iv_diag) * 0.25_dp
247 boxes(p_id)%fc(1:nc+1, 1:nc+1, 1:2, ivf_nb) = &
248 boxes(p_id)%fc(1:nc+1, 1:nc+1, 1:2, ivf_nb) * 0.25_dp
250 end subroutine restrict_matrix
253 subroutine bc_dirichlet_one(box, nb, iv, bc_type)
254 type(box2_t),
intent(inout) :: box
255 integer,
intent(in) :: nb, iv
256 integer,
intent(out) :: bc_type
258 bc_type = af_bc_dirichlet
259 call a2_set_box_gc(box, nb, iv, 1.0_dp)
260 end subroutine bc_dirichlet_one
262 end program multigrid_matrix_2d
Module which contains all Afivo modules, so that a user does not have to include them separately...