1 #include "../src/cpp_macros.h"
6 program check_ghostcells
10 integer,
parameter :: box_size = 8
11 integer,
parameter :: n_runs = 50
13 real(dp) :: gradient(NDIM)
14 logical,
parameter :: write_silo = .false.
16 write(*,
'(A,I0,A)')
'program check_ghostcells_', ndim,
"d"
17 print *,
"Number of threads", af_get_max_threads()
20 call test_valid_range(n_runs)
23 call test_gradient(n_runs)
25 print *,
"Tests passed"
29 subroutine test_valid_range(max_iter)
30 integer,
intent(in) :: max_iter
33 type(ref_info_t) :: ref_info
34 character(len=100) :: fname
36 print *,
"Testing range of ghost cells"
38 call af_add_cc_variable(tree,
"phi", ix=i_phi)
39 call af_set_cc_methods(tree, i_phi, af_bc_dirichlet_zero)
41 call af_init(tree, box_size, [dtimes(1.0_dp)], &
42 [dtimes(box_size)], periodic=[dtimes(.true.)], &
46 call af_adjust_refinement(tree, ref_routine, ref_info, ref_buffer=0)
47 call af_loop_box(tree, set_random_state)
49 call af_restrict_ref_boundary(tree, [i_phi])
50 call af_loop_tree(tree, check_range_box, leaves_only=.true.)
53 write(fname,
"(A,I0)")
"output/check_ghostcells_range_" &
54 // dimname //
"_", iter
55 call af_write_silo(tree, trim(fname), n_cycle=iter)
58 end subroutine test_valid_range
60 subroutine test_gradient(max_iter)
61 integer,
intent(in) :: max_iter
64 type(ref_info_t) :: ref_info
65 character(len=100) :: fname
67 print *,
"Testing linear gradient"
69 call af_add_cc_variable(tree,
"phi", ix=i_phi)
70 call af_set_cc_methods(tree, i_phi, bc_gradient)
72 call af_init(tree, box_size, [dtimes(1.0_dp)], &
73 [dtimes(box_size)], periodic=[dtimes(.false.)], &
77 call random_number(gradient)
78 call af_adjust_refinement(tree, ref_routine, ref_info, ref_buffer=0)
79 call af_loop_box(tree, set_solution_gradient)
81 call af_restrict_ref_boundary(tree, [i_phi])
82 call af_loop_tree(tree, check_gradient_box, leaves_only=.true.)
85 write(fname,
"(A,I0)")
"output/check_ghostcells_gradient_" &
86 // dimname //
"_", iter
87 call af_write_silo(tree, trim(fname), n_cycle=iter)
90 end subroutine test_gradient
92 subroutine ref_routine(box, cell_flags)
93 type(box_t),
intent(in) :: box
94 integer,
intent(out) :: cell_flags(DTIMES(box%n_cell))
97 call random_number(rr)
99 if (rr < 0.5_dp**ndim .and. box%lvl < 5)
then
100 cell_flags = af_do_ref
102 cell_flags = af_rm_ref
104 end subroutine ref_routine
106 subroutine set_random_state(box)
107 type(box_t),
intent(inout) :: box
110 call random_number(box%cc(dtimes(1:nc), i_phi))
111 end subroutine set_random_state
113 subroutine set_solution_gradient(box)
114 type(box_t),
intent(inout) :: box
121 r = af_r_cc(box, [ijk])
122 box%cc(ijk, i_phi) = sum(gradient * r)
124 end subroutine set_solution_gradient
126 subroutine check_range_box(tree, id)
127 type(af_t),
intent(inout) :: tree
128 integer,
intent(in) :: id
130 real(dp) :: cc(DTIMES(-1:tree%n_cell+2), 1)
131 logical :: mask(DTIMES(-1:tree%n_cell+2))
132 real(dp) :: min_sides, max_sides
133 integer :: minloc_sides(NDIM), maxloc_sides(NDIM)
137 call af_gc2_box(tree, id, [i_phi], cc)
145 mask(:0, 1:nc) = .true.
146 mask(nc+1:, 1:nc) = .true.
147 mask(1:nc, :0) = .true.
148 mask(1:nc, nc+1:) = .true.
150 mask(:0, 1:nc, 1:nc) = .true.
151 mask(nc+1:, 1:nc, 1:nc) = .true.
152 mask(1:nc, :0, 1:nc) = .true.
153 mask(1:nc, nc+1:, 1:nc) = .true.
154 mask(1:nc, 1:nc, :0) = .true.
155 mask(1:nc, 1:nc, nc+1:) = .true.
158 min_sides = minval(cc(dtimes(:), 1), mask=mask)
159 minloc_sides = minloc(cc(dtimes(:), 1), mask=mask)
160 max_sides = maxval(cc(dtimes(:), 1), mask=mask)
161 maxloc_sides = maxloc(cc(dtimes(:), 1), mask=mask)
163 if (min_sides < 0 .or. max_sides > 1)
then
164 print *,
"minimum on sides: ", min_sides, minloc_sides - 2
165 print *,
"maximum on sides: ", max_sides, maxloc_sides - 2
166 error stop
"min/max not in range [0, 1]"
168 end subroutine check_range_box
170 subroutine check_gradient_box(tree, id)
171 type(af_t),
intent(inout) :: tree
172 integer,
intent(in) :: id
174 real(dp) :: cc(DTIMES(-1:tree%n_cell+2), 1)
175 logical :: mask(DTIMES(-1:tree%n_cell+2))
176 real(dp) :: diff(DTIMES(-1:tree%n_cell+2))
177 real(dp) :: max_deviation, r(NDIM)
178 real(dp),
parameter :: threshold = 1e-13_dp
182 call af_gc2_box(tree, id, [i_phi], cc)
190 mask(:0, 1:nc) = .true.
191 mask(nc+1:, 1:nc) = .true.
192 mask(1:nc, :0) = .true.
193 mask(1:nc, nc+1:) = .true.
195 mask(:0, 1:nc, 1:nc) = .true.
196 mask(nc+1:, 1:nc, 1:nc) = .true.
197 mask(1:nc, :0, 1:nc) = .true.
198 mask(1:nc, nc+1:, 1:nc) = .true.
199 mask(1:nc, 1:nc, :0) = .true.
200 mask(1:nc, 1:nc, nc+1:) = .true.
207 r = af_r_cc(tree%boxes(id), [ijk])
208 diff(ijk) = abs(sum(gradient * r) - cc(ijk, 1))
212 max_deviation = maxval(diff)
214 if (max_deviation > threshold)
then
215 print *,
"max deviation from linear solution: ", max_deviation
216 print *,
"location: ", maxloc(diff) - 2
217 error stop
"max deviation larger than threshold"
219 end subroutine check_gradient_box
222 subroutine bc_gradient(box, nb, iv, coords, bc_val, bc_type)
223 type(box_t),
intent(in) :: box
224 integer,
intent(in) :: nb
225 integer,
intent(in) :: iv
226 real(dp),
intent(in) :: coords(NDIM, box%n_cell**(NDIM-1))
227 real(dp),
intent(out) :: bc_val(box%n_cell**(NDIM-1))
228 integer,
intent(out) :: bc_type
232 bc_type = af_bc_dirichlet
233 bc_val = matmul(gradient, coords)
234 end subroutine bc_gradient
Module which contains all Afivo modules, so that a user does not have to include them separately.