11 integer,
parameter :: box_size = 8
12 integer,
parameter :: i_phi = 1
13 integer,
parameter :: i_phi_old = 2
14 integer,
parameter :: i_err = 3
15 integer,
parameter :: sol_type = 1
16 real(dp),
parameter :: domain_len = 2 * acos(-1.0_dp)
17 real(dp),
parameter :: dr = domain_len / box_size
20 type(ref_info_t) :: refine_info
21 integer :: ix_list(3, 1)
22 integer :: nb_list(a3_num_neighbors, 1)
23 integer :: refine_steps, time_steps, output_cnt
24 integer :: i, id, n, n_steps
25 real(dp) :: dt, time, end_time, p_err, n_err
26 real(dp) :: sum_phi, sum_phi_t0
27 real(dp) :: dt_adapt, dt_output
28 real(dp) :: velocity(3), dr_min(3)
29 character(len=100) :: fname
30 integer :: count_rate, t_start, t_end
32 print *,
"Running advection_3d" 33 print *,
"Number of threads", af_get_max_threads()
41 cc_names=[
"phi",
"old",
"err"])
43 call a3_set_cc_methods(tree, i_phi, a3_bc_neumann_zero, a3_gc_interp_lim, &
44 prolong=a3_prolong_limit)
52 call a3_set_base(tree, 1, ix_list, nb_list)
64 call system_clock(t_start,count_rate)
68 refine_steps=refine_steps+1
70 call a3_loop_box(tree, set_initial_condition)
78 call a3_gc_tree(tree, i_phi, a3_gc_interp_lim, a3_bc_neumann_zero)
86 call a3_adjust_refinement(tree, &
92 if (refine_info%n_add == 0)
exit 94 call system_clock(t_end, count_rate)
96 write(*,
"(A,i0,A,Es10.3,A)")
" Wall-clock time for ", &
97 refine_steps,
" refinement steps: ", &
98 (t_end-t_start) /
real(count_rate, dp),
" seconds" 100 call a3_print_info(tree)
105 call a3_restrict_tree(tree, i_phi)
110 call a3_gc_tree(tree, i_phi, a3_gc_interp_lim, a3_bc_neumann_zero)
112 call system_clock(t_start, count_rate)
115 call a3_tree_sum_cc(tree, i_phi, sum_phi_t0)
119 time_steps = time_steps + 1
120 dr_min = a3_min_dr(tree)
121 dt = 0.5_dp / (sum(abs(velocity/dr_min)) + epsilon(1.0_dp))
123 n_steps = ceiling(dt_adapt/dt)
124 dt = dt_adapt / n_steps
126 if (output_cnt * dt_output <= time)
then 127 output_cnt = output_cnt + 1
128 write(fname,
"(A,I0)")
"advection_3d_", output_cnt
131 call a3_loop_box_arg(tree, set_error, [time])
135 call a3_write_silo(tree, trim(fname), output_cnt, time, dir=
"output")
139 call a3_tree_max_cc(tree, i_err, p_err)
140 call a3_tree_min_cc(tree, i_err, n_err)
141 call a3_tree_sum_cc(tree, i_phi, sum_phi)
142 write(*,
"(2(A,1x,Es12.4,2x))") &
143 " max error:", max(p_err, abs(n_err)), &
144 "conservation error: ", (sum_phi - sum_phi_t0) / sum_phi_t0
147 if (time > end_time)
exit 151 call a3_tree_copy_cc(tree, i_phi, i_phi_old)
156 call a3_loop_boxes(tree, fluxes_koren)
159 call a3_consistent_fluxes(tree, [i_phi])
162 call a3_loop_box_arg(tree, update_solution, [dt])
165 call a3_restrict_tree(tree, i_phi)
169 call a3_loop_box(tree, average_phi)
174 call a3_gc_tree(tree, i_phi, a3_gc_interp_lim, a3_bc_neumann_zero)
181 call a3_adjust_refinement(tree, refine_routine, refine_info, 1)
185 call system_clock(t_end,count_rate)
186 write(*,
"(A,I0,A,Es10.3,A)") &
187 " Wall-clock time after ",time_steps, &
188 " time steps: ", (t_end-t_start) /
real(count_rate, dp), &
193 call a3_destroy(tree)
199 subroutine refine_routine(box, cell_flags)
200 type(box3_t),
intent(in) :: box
201 integer,
intent(out) :: cell_flags(box%n_cell, box%n_cell, box%n_cell)
203 integer :: i, j, k, nc
207 do k = 1, nc;
do j = 1, nc;
do i = 1, nc
208 diff = abs(box%cc(i+1, j, k, i_phi) + &
209 box%cc(i-1, j, k, i_phi) + &
210 box%cc(i, j+1, k, i_phi) + &
211 box%cc(i, j-1, k, i_phi) + &
212 box%cc(i, j, k+1, i_phi) + &
213 box%cc(i, j, k-1, i_phi) - &
214 6 * box%cc(i, j, k, i_phi)) * box%dr
216 if (box%lvl < 2 .or. diff > 0.5e-3_dp .and. box%lvl < 5)
then 217 cell_flags(i, j, k) = af_do_ref
218 else if (diff < 0.1_dp * 0.1e-3_dp)
then 219 cell_flags(i, j, k) = af_rm_ref
221 cell_flags(i, j, k) = af_keep_ref
223 end do; end do; end do
224 end subroutine refine_routine
228 subroutine set_initial_condition(box)
229 type(box3_t),
intent(inout) :: box
230 integer :: i, j, k, nc
234 do k = 0, nc+1;
do j = 0, nc+1;
do i = 0, nc+1
235 rr = a3_r_cc(box, [i, j, k])
236 box%cc(i, j, k, i_phi) = solution(rr, 0.0_dp)
237 end do; end do; end do
238 end subroutine set_initial_condition
241 subroutine set_error(box, time)
242 type(box3_t),
intent(inout) :: box
243 real(dp),
intent(in) :: time(:)
244 integer :: i, j, k, nc
248 do k = 1, nc;
do j = 1, nc;
do i = 1, nc
249 rr = a3_r_cc(box, [i, j, k])
250 box%cc(i, j, k, i_err) = &
251 box%cc(i, j, k, i_phi) - solution(rr, time(1))
252 end do; end do; end do
253 end subroutine set_error
256 function solution(rr, t)
result(sol)
257 real(dp),
intent(in) :: rr(3), t
258 real(dp) :: sol, rr_t(3)
260 rr_t = rr - velocity * t
262 select case (sol_type)
264 sol = sin(rr_t(1))**4 * cos(rr_t(2))**4
266 rr_t = modulo(rr_t, domain_len) / domain_len
267 if (norm2(rr_t - 0.5_dp) < 0.1_dp)
then 273 end function solution
277 subroutine fluxes_koren(boxes, id)
279 type(box3_t),
intent(inout) :: boxes(:)
280 integer,
intent(in) :: id
282 real(dp),
allocatable :: cc(:, :, :)
283 real(dp),
allocatable :: v(:, :, :, :)
285 nc = boxes(id)%n_cell
286 allocate(cc(-1:nc+2, -1:nc+2, -1:nc+2))
287 allocate(v(1:nc+1, 1:nc+1, 1:nc+1, 3))
289 call a3_gc_box(boxes, id, i_phi, a3_gc_interp_lim, a3_bc_neumann_zero)
294 call a3_gc2_box(boxes, &
297 a3_gc2_prolong_linear, &
298 a3_bc2_neumann_zero, &
302 v(:, :, :, 1) = velocity(1)
303 v(:, :, :, 2) = velocity(2)
304 v(:, :, :, 3) = velocity(3)
306 call flux_koren_3d(cc, v, nc, 2)
307 boxes(id)%fc(:, :, :, :, i_phi) = v
309 end subroutine fluxes_koren
312 subroutine update_solution(box, dt)
313 type(box3_t),
intent(inout) :: box
314 real(dp),
intent(in) :: dt(:)
316 integer :: i, j, k, nc
321 forall (i = 1:nc, j = 1:nc, k = 1:nc)
322 box%cc(i, j, k, i_phi) = box%cc(i, j, k, i_phi) + dt(1) * inv_dr * ( &
323 box%fc(i, j, k, 1, i_phi) - box%fc(i+1, j, k, 1, i_phi) + &
324 box%fc(i, j, k, 2, i_phi) - box%fc(i, j+1, k, 2, i_phi) + &
325 box%fc(i, j, k, 3, i_phi) - box%fc(i, j, k+1, 3, i_phi))
327 end subroutine update_solution
330 subroutine average_phi(box)
331 type(box3_t),
intent(inout) :: box
333 box%cc(:, :, :, i_phi) = 0.5_dp * (box%cc(:, :, :, i_phi) + &
334 box%cc(:, :, :, i_phi_old))
335 end subroutine average_phi
337 end program advection_3d
Module which contains all Afivo modules, so that a user does not have to include them separately...
Module containing a couple simple flux schemes for scalar advection/diffusion problems.