1 #include "../src/cpp_macros.h"
12 integer :: box_size = 8
13 integer :: n_iterations = 10
14 integer :: max_refine_level = 7
15 integer :: min_refine_level = 5
21 integer :: i_field_norm
24 type(ref_info_t) :: ref_info
27 character(len=150) :: fname
29 real(dp) :: mem_limit_gb = 8.0_dp
32 real(dp) :: rod_r0(NDIM), rod_r1(NDIM), rod_radius
33 real(dp) :: sphere_r0(NDIM), sphere_radius
42 sphere_r0(ndim) = 0.0_dp
43 sphere_radius = 0.25_dp
45 call af_add_cc_variable(tree,
"phi", ix=i_phi)
46 call af_add_cc_variable(tree,
"rhs", ix=i_rhs)
47 call af_add_cc_variable(tree,
"tmp", ix=i_tmp)
48 call af_add_cc_variable(tree,
"lsf", ix=i_lsf)
49 call af_add_cc_variable(tree,
"field_norm", ix=i_field_norm)
50 call af_add_fc_variable(tree,
"field", ix=i_field)
52 call af_set_cc_methods(tree, i_lsf, funcval=set_lsf)
58 mg%sides_bc => af_bc_dirichlet_zero
59 mg%lsf_boundary_value = 1.0_dp
61 mg%lsf_length_scale = 1e-2_dp
62 mg%lsf_boundary_function => get_boundary_value
63 mg%sides_bc => bc_sides
70 mem_limit_gb=mem_limit_gb)
72 call af_refine_up_to_lvl(tree, min_refine_level)
73 call mg_init(tree, mg)
76 call af_adjust_refinement(tree, ref_routine, ref_info)
77 if (ref_info%n_add == 0)
exit
80 call af_print_info(tree)
83 write(*,
"(A,A4,4A14)")
"# ",
"iter",
"residu"
85 do mg_iter = 1, n_iterations
87 call mg_fas_fmg(tree, mg, .true., mg_iter>1)
88 t_sum = t_sum + omp_get_wtime() - t0
90 call mg_compute_phi_gradient(tree, mg, i_field, 1.0_dp, i_field_norm)
91 call af_loop_box(tree, set_field_to_zero_inside)
94 call af_tree_maxabs_cc(tree, i_tmp, residu)
95 write(*,
"(A,i4,4E14.5)")
"# ", mg_iter, residu
97 write(fname,
"(A,I0)")
"output/two_electrodes_" // dimname //
"_", mg_iter
98 call af_write_silo(tree, trim(fname))
101 write(*,
"(A,E14.5)")
" seconds_per_FMG_cycle", t_sum/n_iterations
103 call af_stencil_print_info(tree)
108 subroutine ref_routine(box, cell_flags)
109 type(box_t),
intent(in) :: box
110 integer,
intent(out) :: cell_flags(DTIMES(box%n_cell))
112 real(dp) :: r(NDIM), r_ref(NDIM)
115 cell_flags(dtimes(:)) = af_keep_ref
119 r_ref(ndim) = r_ref(ndim) - rod_radius
121 if (box%lvl < max_refine_level)
then
123 r = af_r_cc(box, [ijk])
124 if (norm2(r - r_ref) < 2 * rod_radius)
then
125 cell_flags(dtimes(:)) = af_do_ref
129 end subroutine ref_routine
132 subroutine set_lsf(box, iv)
133 type(box_t),
intent(inout) :: box
134 integer,
intent(in) :: iv
141 rr = af_r_cc(box, [ijk])
142 box%cc(ijk, iv) = get_lsf(rr)
144 end subroutine set_lsf
147 real(dp) function get_boundary_value(r)
148 real(dp),
intent(in) :: r(NDIM)
150 if (r(ndim) > 0.5_dp)
then
151 get_boundary_value = 1.0_dp
153 get_boundary_value = 0.0_dp
155 end function get_boundary_value
157 real(dp) function get_lsf(r)
158 real(dp),
intent(in) :: r(NDIM)
160 if (r(ndim) > 0.5_dp)
then
161 get_lsf = gm_dist_line(r, rod_r0, rod_r1, ndim) - rod_radius
163 get_lsf = norm2(r - sphere_r0) - sphere_radius
168 subroutine bc_sides(box, nb, iv, coords, bc_val, bc_type)
169 type(box_t),
intent(in) :: box
170 integer,
intent(in) :: nb
171 integer,
intent(in) :: iv
172 real(dp),
intent(in) :: coords(NDIM, box%n_cell**(NDIM-1))
173 real(dp),
intent(out) :: bc_val(box%n_cell**(NDIM-1))
174 integer,
intent(out) :: bc_type
176 bc_type = af_bc_dirichlet
178 if (af_neighb_dim(nb) == ndim)
then
179 if (af_neighb_low(nb))
then
180 bc_type = af_bc_dirichlet
183 bc_type = af_bc_dirichlet
187 bc_type = af_bc_neumann
190 end subroutine bc_sides
193 subroutine set_field_to_zero_inside(box)
194 type(box_t),
intent(inout) :: box
196 where (box%cc(dtimes(:), i_lsf) < 0)
197 box%cc(dtimes(:), i_field_norm) = 0
199 end subroutine set_field_to_zero_inside
203 subroutine gm_dist_vec_line(r, r0, r1, n_dim, dist_vec, frac)
204 integer,
intent(in) :: n_dim
205 real(dp),
intent(in) :: r(n_dim), r0(n_dim), r1(n_dim)
206 real(dp),
intent(out) :: dist_vec(n_dim)
207 real(dp),
intent(out) :: frac
208 real(dp) :: line_len2
210 line_len2 = sum((r1 - r0)**2)
211 frac = sum((r - r0) * (r1 - r0))
213 if (frac <= 0.0_dp)
then
216 else if (frac >= line_len2)
then
220 dist_vec = r - (r0 + frac/line_len2 * (r1 - r0))
221 frac = sqrt(frac / line_len2)
223 end subroutine gm_dist_vec_line
225 function gm_dist_line(r, r0, r1, n_dim)
result(dist)
226 integer,
intent(in) :: n_dim
227 real(dp),
intent(in) :: r(n_dim), r0(n_dim), r1(n_dim)
228 real(dp) :: dist, dist_vec(n_dim), frac
229 call gm_dist_vec_line(r, r0, r1, n_dim, dist_vec, frac)
230 dist = norm2(dist_vec)
231 end function gm_dist_line
Module which contains all Afivo modules, so that a user does not have to include them separately.
Module that allows working with a configuration file.