1 #include "../src/cpp_macros.h"
10 integer,
parameter :: box_size = 8
14 integer,
parameter :: sol_type = 2
15 real(dp),
parameter :: domain_len = 2 * acos(-1.0_dp)
18 type(ref_info_t) :: refine_info
19 integer :: refine_steps, output_cnt
20 real(dp) :: dt, dt_lim, time, time_prev_refine
21 real(dp) :: end_time, err, sum_err2
22 real(dp) :: sum_phi, sum_phi_t0
23 real(dp) :: dt_amr, dt_output
24 real(dp) :: velocity(NDIM)
25 real(dp) :: cfl_number
27 character(len=100) :: fname
28 character(len=20) :: flux_method
30 print *,
"Running advection_" // dimname //
""
31 print *,
"Number of threads", af_get_max_threads()
33 flux_method =
"generic"
35 if (command_argument_count() > 0)
then
36 call get_command_argument(1, flux_method)
39 integrator = af_heuns_method
41 call af_add_cc_variable(tree,
"phi", ix=i_phi, &
42 n_copies=af_advance_num_steps(integrator))
43 call af_add_cc_variable(tree,
"err", ix=i_err)
44 call af_add_fc_variable(tree,
"flux", ix=i_flux)
46 call af_set_cc_methods(tree, i_phi, af_bc_neumann_zero, &
47 prolong=af_prolong_limit)
52 [dtimes(domain_len)], &
54 periodic=[dtimes(.true.)])
69 refine_steps=refine_steps+1
71 call af_loop_box(tree, set_initial_condition)
74 call af_gc_tree(tree, [i_phi])
77 call af_adjust_refinement(tree, refine_routine, refine_info, 1)
80 if (refine_info%n_add == 0)
exit
83 call af_print_info(tree)
86 call af_restrict_tree(tree, [i_phi])
89 call af_gc_tree(tree, [i_phi])
91 call af_tree_sum_cc(tree, i_phi, sum_phi_t0)
93 dt = cfl_number / (sum(abs(velocity/af_min_dr(tree))) + epsilon(1.0_dp))
94 time_prev_refine = time
98 if (output_cnt * dt_output <= time)
then
99 output_cnt = output_cnt + 1
100 write(fname,
"(A,I0)")
"output/advection_v2_" // dimname //
"_", output_cnt
103 call af_loop_box_arg(tree, set_error, [time])
107 call af_write_silo(tree, trim(fname), output_cnt, time)
111 call af_tree_maxabs_cc(tree, i_err, err)
112 call af_tree_sum_cc(tree, i_phi, sum_phi)
113 call af_tree_sum_cc(tree, i_err, sum_err2, power=2)
114 write(*,
"(3(A,Es16.8))") &
115 " max error:", err, &
116 " mean error:", sqrt(sum_err2/af_total_volume(tree)), &
117 " conservation error: ", (sum_phi - sum_phi_t0) / sum_phi_t0
120 if (time > end_time)
exit
122 call af_advance(tree, dt, dt_lim, time, [i_phi], integrator, forward_euler)
123 dt = cfl_number * dt_lim
125 if (time > time_prev_refine + dt_amr)
then
126 call af_restrict_tree(tree, [i_phi])
127 call af_gc_tree(tree, [i_phi])
128 call af_adjust_refinement(tree, refine_routine, refine_info, 1)
129 time_prev_refine = time
137 subroutine refine_routine(box, cell_flags)
138 type(box_t),
intent(in) :: box
139 integer,
intent(out) :: cell_flags(DTIMES(box%n_cell))
147 diff = abs(box%dr(1) * (box%cc(i+1, i_phi) + &
148 box%cc(i-1, i_phi) - 2 * box%cc(i, i_phi)))
150 diff = abs(box%dr(1) * (box%cc(i+1, j, i_phi) + &
151 box%cc(i-1, j, i_phi) - 2 * box%cc(i, j, i_phi)) + &
152 box%dr(2) * (box%cc(i, j+1, i_phi) + &
153 box%cc(i, j-1, i_phi) - 2 * box%cc(i, j, i_phi)))
155 diff = abs(box%dr(1) * (box%cc(i+1, j, k, i_phi) + &
156 box%cc(i-1, j, k, i_phi) - 2 * box%cc(i, j, k, i_phi)) + &
157 box%dr(2) * (box%cc(i, j+1, k, i_phi) + &
158 box%cc(i, j-1, k, i_phi) - 2 * box%cc(i, j, k, i_phi)) + &
159 box%dr(3) * (box%cc(i, j, k+1, i_phi) + &
160 box%cc(i, j, k-1, i_phi) - 2 * box%cc(i, j, k, i_phi)))
163 if (box%lvl < 2 .or. diff > 2.0e-3_dp .and. box%lvl < 5)
then
164 cell_flags(ijk) = af_do_ref
165 else if (diff < 0.1_dp * 2.0e-3_dp)
then
166 cell_flags(ijk) = af_rm_ref
168 cell_flags(ijk) = af_keep_ref
171 end subroutine refine_routine
175 subroutine set_initial_condition(box)
176 type(box_t),
intent(inout) :: box
182 rr = af_r_cc(box, [ijk])
183 box%cc(ijk, i_phi) = solution(rr, 0.0_dp)
185 end subroutine set_initial_condition
188 subroutine set_error(box, time)
189 type(box_t),
intent(inout) :: box
190 real(dp),
intent(in) :: time(:)
196 rr = af_r_cc(box, [ijk])
197 box%cc(ijk, i_err) = &
198 box%cc(ijk, i_phi) - solution(rr, time(1))
200 end subroutine set_error
203 function solution(rr, t)
result(sol)
204 real(dp),
intent(in) :: rr(NDIM), t
205 real(dp) :: sol, rr_t(NDIM)
207 rr_t = rr - velocity * t
209 select case (sol_type)
212 sol = sin(0.5_dp * rr_t(1))**8 * cos(0.5_dp * rr_t(2))**8
214 sol = sin(0.5_dp * rr_t(1))**8
217 rr_t = modulo(rr_t, domain_len) / domain_len
218 if (norm2(rr_t - 0.5_dp) < 0.1_dp)
then
224 end function solution
226 subroutine forward_euler(tree, dt, dt_stiff, dt_lim, time, s_deriv, n_prev, &
227 s_prev, w_prev, s_out, i_step, n_steps)
228 type(af_t),
intent(inout) :: tree
229 real(dp),
intent(in) :: dt
230 real(dp),
intent(in) :: dt_stiff
231 real(dp),
intent(in) :: time
232 real(dp),
intent(inout) :: dt_lim
233 integer,
intent(in) :: s_deriv
234 integer,
intent(in) :: n_prev
235 integer,
intent(in) :: s_prev(n_prev)
236 real(dp),
intent(in) :: w_prev(n_prev)
237 integer,
intent(in) :: s_out
238 integer,
intent(in) :: i_step, n_steps
239 integer :: lvl, i, id
240 real(dp) :: all_dt(1)
242 select case (flux_method)
244 call flux_generic_tree(tree, 1, [i_phi], s_deriv, [i_flux], dt_lim, &
245 max_wavespeed, get_flux, flux_dummy_modify, flux_dummy_line_modify, &
246 flux_dummy_conversion, flux_dummy_conversion, af_limiter_koren_t)
248 call flux_upwind_tree(tree, 1, [i_phi], s_deriv, [i_flux], &
249 1, all_dt, flux_upwind, flux_direction, &
250 flux_dummy_line_modify, af_limiter_koren_t)
254 call af_restrict_ref_boundary(tree, [i_phi+s_deriv])
258 do lvl = 1, tree%highest_lvl
260 do i = 1,
size(tree%lvls(lvl)%leaves)
261 id = tree%lvls(lvl)%leaves(i)
262 call fluxes_koren(tree, id, s_deriv)
269 call af_consistent_fluxes(tree, [i_flux])
271 dt_lim = 1/(sum(abs(velocity/af_min_dr(tree))) + epsilon(1.0_dp))
273 error stop
"Unknown flux_method, choices: generic, upwind, custom"
276 call flux_update_densities(tree, dt, 1, [i_phi], 1, [i_phi], [i_flux], &
277 s_deriv, n_prev, s_prev, w_prev, s_out, flux_dummy_source, 0, all_dt)
279 end subroutine forward_euler
283 subroutine fluxes_koren(tree, id, s_deriv)
285 type(af_t),
intent(inout) :: tree
286 integer,
intent(in) :: id
287 integer,
intent(in) :: s_deriv
289 real(dp),
allocatable :: cc(DTIMES(:), :)
290 real(dp),
allocatable :: v(DTIMES(:), :)
292 nc = tree%boxes(id)%n_cell
293 allocate(cc(dtimes(-1:nc+2), 1))
294 allocate(v(dtimes(1:nc+1), ndim))
296 call af_gc2_box(tree, id, [i_phi+s_deriv], cc)
299 v(dtimes(:), idim) = velocity(idim)
303 call flux_koren_1d(cc(dtimes(:), 1), v, nc, 2)
305 call flux_koren_2d(cc(dtimes(:), 1), v, nc, 2)
307 call flux_koren_3d(cc(dtimes(:), 1), v, nc, 2)
310 tree%boxes(id)%fc(dtimes(:), :, i_flux) = v
312 end subroutine fluxes_koren
314 subroutine max_wavespeed(n_values, n_var, flux_dim, u, w)
315 integer,
intent(in) :: n_values
316 integer,
intent(in) :: n_var
317 integer,
intent(in) :: flux_dim
318 real(dp),
intent(in) :: u(n_values, n_var)
319 real(dp),
intent(out) :: w(n_values)
321 w = abs(velocity(flux_dim))
322 end subroutine max_wavespeed
324 subroutine get_flux(n_values, n_var, flux_dim, u, flux, box, line_ix, s_deriv)
325 integer,
intent(in) :: n_values
326 integer,
intent(in) :: n_var
327 integer,
intent(in) :: flux_dim
328 real(dp),
intent(in) :: u(n_values, n_var)
329 real(dp),
intent(out) :: flux(n_values, n_var)
330 type(box_t),
intent(in) :: box
331 integer,
intent(in) :: line_ix(NDIM-1)
332 integer,
intent(in) :: s_deriv
334 flux = u * velocity(flux_dim)
335 end subroutine get_flux
337 subroutine flux_upwind(nf, n_var, flux_dim, u, flux, cfl_sum, &
338 n_other_dt, other_dt, box, line_ix, s_deriv)
339 integer,
intent(in) :: nf
340 integer,
intent(in) :: n_var
341 integer,
intent(in) :: flux_dim
342 real(dp),
intent(in) :: u(nf, n_var)
343 real(dp),
intent(out) :: flux(nf, n_var)
345 real(dp),
intent(out) :: cfl_sum(nf-1)
346 integer,
intent(in) :: n_other_dt
347 real(dp),
intent(inout) :: other_dt(n_other_dt)
348 type(box_t),
intent(in) :: box
349 integer,
intent(in) :: line_ix(NDIM-1)
350 integer,
intent(in) :: s_deriv
353 flux = u * velocity(flux_dim)
355 tmp = abs(velocity(flux_dim)) / box%dr(flux_dim)
357 end subroutine flux_upwind
359 subroutine flux_direction(box, line_ix, s_deriv, n_var, flux_dim, direction_positive)
360 type(box_t),
intent(in) :: box
361 integer,
intent(in) :: line_ix(NDIM-1)
362 integer,
intent(in) :: s_deriv
363 integer,
intent(in) :: n_var
364 integer,
intent(in) :: flux_dim
366 logical,
intent(out) :: direction_positive(box%n_cell+1, n_var)
368 direction_positive(:, 1) = (velocity(flux_dim) > 0)
369 end subroutine flux_direction
Module which contains all Afivo modules, so that a user does not have to include them separately.
Module containing a couple flux schemes for solving hyperbolic problems explicitly,...