6 program poisson_helmholtz_2d
12 integer,
parameter :: box_size = 8
13 integer,
parameter :: n_boxes_base = 1
14 integer,
parameter :: n_iterations = 10
15 integer,
parameter :: n_var_cell = 4
16 integer,
parameter :: i_phi = 1
17 integer,
parameter :: i_rhs = 2
18 integer,
parameter :: i_err = 3
19 integer,
parameter :: i_tmp = 4
20 real(dp),
parameter :: lambda = 1.0e3_dp
23 type(ref_info_t) :: refine_info
25 integer :: ix_list(2, n_boxes_base)
26 real(dp) :: dr, residu(2), anal_err(2)
27 character(len=100) :: fname
30 integer :: count_rate,t_start,t_end
32 print *,
"Running poisson_helmholtz_2d" 33 print *,
"Number of threads", af_get_max_threads()
35 call gauss_init(gs, [1.0_dp, 1.0_dp], [0.04_dp, 0.04_dp], &
36 reshape([0.25_dp, 0.25_dp, &
37 0.75_dp, 0.75_dp], [2,2]))
40 dr = 1.0_dp / box_size
49 cc_names=[
"phi",
"rhs",
"err",
"tmp"])
51 ix_list(:, 1) = [1, 1]
52 call a2_set_base(tree, 1, ix_list)
55 call a2_loop_box(tree, set_initial_condition)
56 call a2_adjust_refinement(tree, refine_routine, refine_info)
57 if (refine_info%n_add == 0)
exit 60 call a2_print_info(tree)
65 mg%sides_bc => sides_bc
66 mg%box_op => helmholtz_operator
67 mg%box_gsrb => helmholtz_gsrb
71 print *,
"Multigrid iteration | max residual | max error" 72 call system_clock(t_start, count_rate)
74 do mg_iter = 1, n_iterations
75 call mg2_fas_fmg(tree, mg, set_residual=.true., have_guess=(mg_iter>1))
76 call a2_loop_box(tree, set_error)
77 call a2_tree_min_cc(tree, i_tmp, residu(1))
78 call a2_tree_max_cc(tree, i_tmp, residu(2))
79 call a2_tree_min_cc(tree, i_err, anal_err(1))
80 call a2_tree_max_cc(tree, i_err, anal_err(2))
81 write(*,
"(I8,13x,2(Es14.5))") mg_iter, maxval(abs(residu)), &
84 write(fname,
"(A,I0)")
"poisson_helmholtz_2d_", mg_iter
85 call a2_write_vtk(tree, trim(fname), dir=
"output")
87 call system_clock(t_end, count_rate)
89 write(*,
"(A,I0,A,E10.3,A)") &
90 " Wall-clock time after ", n_iterations, &
91 " iterations: ", (t_end-t_start) /
real(count_rate, dp), &
97 subroutine refine_routine(box, cell_flags)
98 type(box2_t),
intent(in) :: box
99 integer,
intent(out) :: cell_flags(box%n_cell, box%n_cell)
101 real(dp) :: rr(2), dr2, drhs
106 do j = 1, nc;
do i = 1, nc
107 rr = a2_r_cc(box, [i, j])
111 drhs = dr2 * box%cc(i, j, i_rhs)
113 if (abs(drhs) > 1e-3_dp .and. box%lvl < 5)
then 114 cell_flags(i, j) = af_do_ref
116 cell_flags(i, j) = af_keep_ref
119 end subroutine refine_routine
122 subroutine set_initial_condition(box)
123 type(box2_t),
intent(inout) :: box
129 do j = 1, nc;
do i = 1, nc
131 rr = a2_r_cc(box, [i, j])
134 box%cc(i, j, i_rhs) = gauss_laplacian(gs, rr) - &
135 lambda * gauss_value(gs, rr)
137 end subroutine set_initial_condition
140 subroutine set_error(box)
141 type(box2_t),
intent(inout) :: box
146 do j = 1, nc;
do i = 1, nc
147 rr = a2_r_cc(box, [i, j])
148 box%cc(i, j, i_err) = box%cc(i, j, i_phi) - gauss_value(gs, rr)
150 end subroutine set_error
154 subroutine sides_bc(box, nb, iv, bc_type)
155 type(box2_t),
intent(inout) :: box
156 integer,
intent(in) :: nb
157 integer,
intent(in) :: iv
158 integer,
intent(out) :: bc_type
165 bc_type = af_bc_dirichlet
169 case (a2_neighb_lowx)
171 rr = a2_rr_cc(box, [0.5_dp,
real(n, dp)])
172 box%cc(0, n, iv) = gauss_value(gs, rr)
174 case (a2_neighb_highx)
176 rr = a2_rr_cc(box, [nc+0.5_dp,
real(n, dp)])
177 box%cc(nc+1, n, iv) = gauss_value(gs, rr)
179 case (a2_neighb_lowy)
181 rr = a2_rr_cc(box, [
real(n, dp), 0.5_dp])
182 box%cc(n, 0, iv) = gauss_value(gs, rr)
184 case (a2_neighb_highy)
186 rr = a2_rr_cc(box, [
real(n, dp), nc+0.5_dp])
187 box%cc(n, nc+1, iv) = gauss_value(gs, rr)
190 end subroutine sides_bc
193 subroutine helmholtz_operator(box, i_out, mg)
194 type(box2_t),
intent(inout) :: box
195 integer,
intent(in) :: i_out
196 type(mg2_t),
intent(in) :: mg
197 integer :: i, j, nc, i_phi
198 real(dp) :: inv_dr_sq
201 inv_dr_sq = 1 / box%dr**2
206 box%cc(i, j, i_out) = inv_dr_sq * (box%cc(i-1, j, i_phi) + &
207 box%cc(i+1, j, i_phi) + box%cc(i, j-1, i_phi) + &
208 box%cc(i, j+1, i_phi) - 4 * box%cc(i, j, i_phi)) - &
209 lambda * box%cc(i, j, i_phi)
212 end subroutine helmholtz_operator
215 subroutine helmholtz_gsrb(box, redblack_cntr, mg)
216 type(box2_t),
intent(inout) :: box
217 integer,
intent(in) :: redblack_cntr
218 type(mg2_t),
intent(in) :: mg
219 integer :: i, i0, j, nc, i_phi, i_rhs
230 i0 = 2 - iand(ieor(redblack_cntr, j), 1)
232 box%cc(i, j, i_phi) = 1/(4 + lambda * dx2) * ( &
233 box%cc(i+1, j, i_phi) + box%cc(i-1, j, i_phi) + &
234 box%cc(i, j+1, i_phi) + box%cc(i, j-1, i_phi) - &
235 dx2 * box%cc(i, j, i_rhs))
238 end subroutine helmholtz_gsrb
240 end program poisson_helmholtz_2d
This module can be used to construct solutions consisting of one or more Gaussians.
Module which contains all Afivo modules, so that a user does not have to include them separately...