3 program anisotropic_diffusion_2d
8 integer,
parameter :: box_size = 8
9 integer,
parameter :: i_phi = 1
10 integer,
parameter :: i_phi_old = 2
11 integer,
parameter :: i_bx = 3
12 integer,
parameter :: i_by = 4
13 real(dp),
parameter :: domain_len = 2 * acos(-1.0_dp)
14 real(dp),
parameter :: dr = domain_len / box_size
17 type(ref_info_t) :: refine_info
18 integer :: ix_list(2, 1)
19 integer :: nb_list(a2_num_neighbors, 1)
20 integer :: time_steps, output_cnt
21 integer :: i, id, n, n_steps
22 real(dp) :: dt, time, end_time
23 real(dp) :: dt_adapt, dt_output
24 real(dp) :: velocity(2), dr_min(2)
25 character(len=100) :: fname
26 integer :: count_rate, t_start, t_end
28 print *,
"Running anisotropic_diffusion_2d" 29 print *,
"Number of threads", af_get_max_threads()
37 r_min=[-0.5_dp, -0.5_dp] * domain_len, &
38 cc_names=[
"phi",
"old",
"Bx ",
"By "])
40 call a2_set_cc_methods(tree, i_phi, a2_bc_neumann_zero, a2_gc_interp_lim)
48 call a2_set_base(tree, 1, ix_list, nb_list)
60 call system_clock(t_start,count_rate)
63 call a2_loop_box(tree, set_initial_condition)
64 call a2_gc_tree(tree, i_phi, a2_gc_interp_lim, a2_bc_neumann_zero)
65 call a2_adjust_refinement(tree, &
69 if (refine_info%n_add == 0)
exit 72 call a2_gc_tree(tree, i_phi, a2_gc_interp_lim, a2_bc_neumann_zero)
73 call a2_print_info(tree)
79 time_steps = time_steps + 1
80 dr_min = a2_min_dr(tree)
81 dt = 0.25_dp * minval(dr_min)**2
83 n_steps = ceiling(dt_adapt/dt)
84 dt = dt_adapt / n_steps
86 if (output_cnt * dt_output <= time)
then 87 output_cnt = output_cnt + 1
88 write(fname,
"(A,I0)")
"anisotropic_diffusion_2d_", output_cnt
89 call a2_write_silo(tree, trim(fname), output_cnt, time, dir=
"output")
92 if (time > end_time)
exit 96 call a2_tree_copy_cc(tree, i_phi, i_phi_old)
101 call a2_loop_boxes(tree, get_fluxes)
104 call a2_consistent_fluxes(tree, [i_phi])
107 call a2_loop_box_arg(tree, update_solution, [dt])
110 call a2_restrict_tree(tree, i_phi)
114 call a2_loop_box(tree, average_phi)
119 call a2_gc_tree(tree, i_phi, a2_gc_interp_lim, a2_bc_neumann_zero)
133 call system_clock(t_end,count_rate)
134 write(*,
"(A,I0,A,Es10.3,A)") &
135 " Wall-clock time after ",time_steps, &
136 " time steps: ", (t_end-t_start) /
real(count_rate, dp), &
141 call a2_destroy(tree)
146 subroutine refine_routine(box, cell_flags)
147 type(box2_t),
intent(in) :: box
148 integer,
intent(out) :: cell_flags(box%n_cell, box%n_cell)
170 if (box%lvl < 5)
then 171 cell_flags(:, :) = af_do_ref
173 cell_flags(:, :) = af_keep_ref
175 end subroutine refine_routine
178 subroutine set_initial_condition(box)
179 type(box2_t),
intent(inout) :: box
184 do j = 0, nc+1;
do i = 0, nc+1
185 rr = a2_r_cc(box, [i, j])
186 box%cc(i, j, i_phi) = solution(rr)
187 box%cc(i, j, i_bx:i_by) = get_bvec(rr)
189 end subroutine set_initial_condition
192 function solution(rr)
result(sol)
193 real(dp),
intent(in) :: rr(2)
196 if (all(abs(rr - domain_len * [0.25_dp, 0.0_dp]) < 0.2_dp))
then 202 end function solution
204 function get_bvec(rr)
result(bvec)
205 real(dp),
intent(in) :: rr(2)
206 real(dp) :: bvec(2), phi
210 bvec = [1.0_dp, 1.0_dp] * sqrt(0.5_dp)
211 end function get_bvec
215 subroutine get_fluxes(boxes, id)
217 type(box2_t),
intent(inout) :: boxes(:)
218 integer,
intent(in) :: id
220 real(dp) :: rr(2), bvec(2), grad(2), tmp(2), inv_dx
222 nc = boxes(id)%n_cell
223 inv_dx = 1/boxes(id)%dr
225 call a2_gc_box(boxes, id, i_phi, a2_gc_interp_lim, a2_bc_neumann_zero)
229 rr = a2_rr_cc(boxes(id), [n-0.5_dp, m+0.0_dp])
232 grad(1) = boxes(id)%cc(n-1, m, i_phi) - boxes(id)%cc(n, m, i_phi)
233 grad(2) = 0.25_dp * (&
234 boxes(id)%cc(n-1, m-1, i_phi) - boxes(id)%cc(n-1, m+1, i_phi) + &
235 boxes(id)%cc(n, m-1, i_phi) - boxes(id)%cc(n, m+1, i_phi))
237 tmp = bvec(1) * inv_dx * bvec * grad
238 boxes(id)%fc(n, m, 1, i_phi) = sum(tmp)
240 if (boxes(id)%fc(n, m, 1, i_phi) > inv_dx * boxes(id)%cc(n-1, m, i_phi))
then 241 boxes(id)%fc(n, m, 1, i_phi) = inv_dx * boxes(id)%cc(n-1, m, i_phi)
242 else if (boxes(id)%fc(n, m, 1, i_phi) < -inv_dx * boxes(id)%cc(n, m, i_phi))
then 243 boxes(id)%fc(n, m, 1, i_phi) = -inv_dx * boxes(id)%cc(n, m, i_phi)
246 rr = a2_rr_cc(boxes(id), [m+0.0_dp, n-0.5_dp])
249 grad(2) = boxes(id)%cc(m, n-1, i_phi) - boxes(id)%cc(m, n, i_phi)
250 grad(1) = 0.25_dp * (&
251 boxes(id)%cc(m-1, n-1, i_phi) - boxes(id)%cc(m+1, n-1, i_phi) + &
252 boxes(id)%cc(m-1, n, i_phi) - boxes(id)%cc(m+1, n, i_phi))
254 tmp = bvec(2) * inv_dx * bvec * grad
255 boxes(id)%fc(m, n, 2, i_phi) = sum(tmp)
257 if (boxes(id)%fc(m, n, 2, i_phi) > inv_dx * boxes(id)%cc(m, n-1, i_phi))
then 258 boxes(id)%fc(m, n, 2, i_phi) = inv_dx * boxes(id)%cc(m, n-1, i_phi)
259 else if (boxes(id)%fc(m, n, 2, i_phi) < -inv_dx * boxes(id)%cc(m, n, i_phi))
then 260 boxes(id)%fc(m, n, 2, i_phi) = -inv_dx * boxes(id)%cc(m, n, i_phi)
265 end subroutine get_fluxes
268 subroutine update_solution(box, dt)
269 type(box2_t),
intent(inout) :: box
270 real(dp),
intent(in) :: dt(:)
271 real(dp) :: inv_dr, fx(2), fy(2), tmp
279 fx = box%fc(i:i+1, j, 1, i_phi)
280 fy = box%fc(i, j:j+1, 2, i_phi)
282 tmp = dt(1) * inv_dr * (fx(1) - fx(2) + fy(1) - fy(2))
284 box%cc(i, j, i_phi) = box%cc(i, j, i_phi) + tmp
287 end subroutine update_solution
290 subroutine average_phi(box)
291 type(box2_t),
intent(inout) :: box
293 box%cc(:, :, i_phi) = 0.5_dp * (box%cc(:, :, i_phi) + &
294 box%cc(:, :, i_phi_old))
295 end subroutine average_phi
297 end program anisotropic_diffusion_2d
Module containing a couple simple flux schemes for scalar advection/diffusion problems.
Module which contains all Afivo modules, so that a user does not have to include them separately...