afivo-streamer 1.1
1D/2D/3D streamer simulations with AMR
Loading...
Searching...
No Matches
m_refine.f90
Go to the documentation of this file.
1!> Module with grid refinement settings and routines
2module m_refine
3#include "../afivo/src/cpp_macros.h"
4 use m_af_all
5
6 implicit none
7 private
8
9 ! The refinement buffer width in cells (around flagged cells)
10 integer, public, protected :: refine_buffer_width = 4
11
12 ! The number of steps after which the mesh is updated
13 integer, public, protected :: refine_per_steps = 2
14
15 ! The grid spacing will always be larger than this value
16 real(dp), public, protected :: refine_min_dx = 1.0e-7_dp
17
18 ! The grid spacing will always be smaller than this value
19 real(dp), public, protected :: refine_max_dx = 1.0e-3_dp
20
21 ! Refine if alpha*dx is larger than this value
22 real(dp), protected :: refine_adx = 1.0_dp
23
24 ! For refinement, use alpha(f * E)/f, where f is this factor
25 real(dp), protected :: refine_adx_fac = 1.0_dp
26
27 ! Refine if the curvature in phi is larger than this value
28 real(dp), protected :: refine_cphi = 1e99_dp
29
30 ! Allow derefinement if the curvature in phi is smaller than this value
31 real(dp), protected :: derefine_cphi = 1e99_dp
32
33 ! Only derefine if grid spacing if smaller than this value
34 real(dp), protected :: derefine_dx = 1e-4_dp
35
36 ! Refine around initial conditions up to this time
37 real(dp), protected :: refine_init_time = 10e-9_dp
38
39 ! Refine until dx is smaller than this factor times the seed width
40 real(dp), protected :: refine_init_fac = 0.25_dp
41
42 ! Ensure grid spacing around electrode is less than this value
43 real(dp), public :: refine_electrode_dx = 1e99_dp
44
45 ! Auxiliary variable used for electrode derefinement
46 ! it will be the same value as above
47 real(dp), public :: current_electrode_dx = 1e99_dp
48
49 ! Multiply the above value by this factor to derefine
50 ! during interpulse
51 real(dp), public, protected :: electrode_derefine_factor = 1.0
52
53 ! Start refining electrode some time before the start of a new pulse
54 real(dp), public, protected :: refine_prepulse_time = 1.0e-9_dp
55
56 ! Minimum electron density for adding grid refinement
57 real(dp), protected :: refine_min_dens = -1.0e99_dp
58
59 ! Refine a region up to this grid spacing
60 real(dp), protected, allocatable :: refine_regions_dr(:)
61
62 ! Refine regions up to this simulation time
63 real(dp), protected, allocatable :: refine_regions_tstop(:)
64
65 ! Minimum coordinate of the refinement regions
66 real(dp), protected, allocatable :: refine_regions_rmin(:,:)
67
68 ! Maximum coordinate of the refinement regions
69 real(dp), protected, allocatable :: refine_regions_rmax(:,:)
70
71 ! Limit refinement in a region to this grid spacing
72 real(dp), protected, allocatable :: refine_limits_dr(:)
73
74 ! Minimum coordinate of the refinement limits
75 real(dp), protected, allocatable :: refine_limits_rmin(:,:)
76
77 ! Maximum coordinate of the refinement limits
78 real(dp), protected, allocatable :: refine_limits_rmax(:,:)
79
80 ! Use effective alpha (minus attachment) for refinement
81 logical, protected :: refine_use_alpha_effective
82
83 procedure(af_subr_ref), pointer :: refine_routine => null()
84
85 ! Public methods
86 public :: refine_initialize
87 public :: refine_routine
88
89contains
90
91 !> Initialize the grid refinement options
92 subroutine refine_initialize(cfg)
93 use m_config
94 use m_gas
96 type(cfg_t), intent(inout) :: cfg
97 integer :: n
98 real(dp) :: vec(ndim)
99 real(dp), allocatable :: dbuffer(:)
100
101 !< [basic_refinement_settings]
102 call cfg_add_get(cfg, "refine_buffer_width", refine_buffer_width, &
103 "The refinement buffer width in cells (around flagged cells)")
104 call cfg_add_get(cfg, "refine_per_steps", refine_per_steps, &
105 "The number of steps after which the mesh is updated")
106 call cfg_add_get(cfg, "refine_min_dx", refine_min_dx, &
107 "The grid spacing will always be larger than this value (m)")
108 call cfg_add_get(cfg, "refine_max_dx", refine_max_dx, &
109 "The grid spacing will always be smaller than this value (m)")
110 call cfg_add_get(cfg, "refine_adx", refine_adx, &
111 "Refine if alpha*dx is larger than this value")
112 call cfg_add_get(cfg, "derefine_dx", derefine_dx, &
113 "Only derefine if grid spacing if smaller than this value")
114 call cfg_add_get(cfg, "refine_init_time", refine_init_time, &
115 "Refine around initial conditions up to this time")
116 call cfg_add_get(cfg, "refine_init_fac", refine_init_fac, &
117 "Refine until dx is smaller than this factor times the seed width")
118 call cfg_add_get(cfg, "refine_electrode_dx", refine_electrode_dx, &
119 "Ensure grid spacing around electrode is less than this value (m)")
120 !< [basic_refinement_settings]
121
123 error stop "Cannot have refine_min_dx < refine_max_dx"
125
126
127 call cfg_add_get(cfg, "refine_adx_fac", refine_adx_fac, &
128 "For refinement, use alpha(f * E)/f, where f is this factor")
129 call cfg_add_get(cfg, "refine_cphi", refine_cphi, &
130 "Refine if the curvature in phi is larger than this value")
131 call cfg_add_get(cfg, "derefine_cphi", derefine_cphi, &
132 "Allow derefinement if the curvature in phi is smaller than this value")
133
134 call cfg_add_get(cfg, "electrode_derefine_factor", &
136 "Multiplication factor to derefine electrode during interpulse")
137 call cfg_add_get(cfg, "refine_prepulse_time", refine_prepulse_time, &
138 "Start refining electrode some time before the start of a new pulse")
139 call cfg_add_get(cfg, "refine_min_dens", refine_min_dens, &
140 "Minimum electron density for adding grid refinement")
141 call cfg_add_get(cfg, "refine_use_alpha_effective", refine_use_alpha_effective, &
142 "Use effective alpha (minus attachment) for refinement")
143
144 call cfg_add(cfg, "refine_regions_dr", [1.0e99_dp], &
145 "Refine regions up to this grid spacing (m)", .true.)
146 call cfg_add(cfg, "refine_regions_tstop", [1.0e99_dp], &
147 "Refine regions up to this simulation time", .true.)
148 vec = 0.0_dp
149 call cfg_add(cfg, "refine_regions_rmin", vec, &
150 "Minimum coordinate of the refinement regions", .true.)
151 call cfg_add(cfg, "refine_regions_rmax", vec, &
152 "Maximum coordinate of the refinement regions", .true.)
153
154 call cfg_get_size(cfg, "refine_regions_dr", n)
155 allocate(refine_regions_dr(n))
156 allocate(refine_regions_tstop(n))
157 allocate(refine_regions_rmin(ndim, n))
158 allocate(refine_regions_rmax(ndim, n))
159 allocate(dbuffer(ndim * n))
160
161 call cfg_get(cfg, "refine_regions_dr", refine_regions_dr)
162 call cfg_get(cfg, "refine_regions_tstop", refine_regions_tstop)
163 call cfg_get(cfg, "refine_regions_rmin", dbuffer)
164 refine_regions_rmin = reshape(dbuffer, [ndim, n])
165 call cfg_get(cfg, "refine_regions_rmax", dbuffer)
166 refine_regions_rmax = reshape(dbuffer, [ndim, n])
167
168 call cfg_add(cfg, "refine_limits_dr", [1.0e99_dp], &
169 "Refine regions at most up to this grid spacing", .true.)
170 vec = 0.0_dp
171 call cfg_add(cfg, "refine_limits_rmin", vec, &
172 "Minimum coordinate of the refinement limits", .true.)
173 call cfg_add(cfg, "refine_limits_rmax", vec, &
174 "Maximum coordinate of the refinement limits", .true.)
175
176 call cfg_get_size(cfg, "refine_limits_dr", n)
177 allocate(refine_limits_dr(n))
178 allocate(refine_limits_rmin(ndim, n))
179 allocate(refine_limits_rmax(ndim, n))
180 deallocate(dbuffer)
181 allocate(dbuffer(ndim * n))
182
183 call cfg_get(cfg, "refine_limits_dr", refine_limits_dr)
184 call cfg_get(cfg, "refine_limits_rmin", dbuffer)
185 refine_limits_rmin = reshape(dbuffer, [ndim, n])
186 call cfg_get(cfg, "refine_limits_rmax", dbuffer)
187 refine_limits_rmax = reshape(dbuffer, [ndim, n])
188
189 if (associated(user_refine)) then
191 else
192 refine_routine => default_refinement
193 end if
194
195 end subroutine refine_initialize
196
197 !> Set the cell refinement flags for box
198 subroutine default_refinement(box, cell_flags)
199 use m_streamer
200 use m_geometry
201 use m_init_cond
202 use m_gas
203 use m_lookup_table
205 type(box_t), intent(in) :: box
206 !> Refinement flags for the cells of the box
207 integer, intent(out) :: &
208 cell_flags(dtimes(box%n_cell))
209 integer :: ijk, n, nc
210 real(dp) :: min_dx, max_dx, gas_dens
211 real(dp) :: alpha, adx, fld, elec_dens
212 real(dp) :: dist, rmin(ndim), rmax(ndim)
213
214 nc = box%n_cell
215 min_dx = minval(box%dr)
216 max_dx = maxval(box%dr)
217
218 do kji_do(1,nc)
219 if (gas_constant_density) then
220 gas_dens = gas_number_density
221 else
222 gas_dens = box%cc(ijk, i_gas_dens)
223 end if
224 fld = box%cc(ijk, i_electric_fld) * si_to_townsend / gas_dens
225
226 if (refine_use_alpha_effective) then
227 alpha = (lt_get_col(td_tbl, td_alpha, refine_adx_fac * fld) - &
228 lt_get_col(td_tbl, td_eta, refine_adx_fac * fld)) * &
229 gas_dens / refine_adx_fac
230 alpha = max(0.0_dp, alpha)
231 else
232 alpha = lt_get_col(td_tbl, td_alpha, refine_adx_fac * fld) * &
233 gas_dens / refine_adx_fac
234 end if
235
236 adx = max_dx * alpha
237 elec_dens = box%cc(ijk, i_electron)
238
239 if (adx > refine_adx .and. elec_dens > refine_min_dens) then
240 cell_flags(ijk) = af_do_ref
241 else if (adx < 0.125_dp * refine_adx .and. max_dx < derefine_dx) then
242 cell_flags(ijk) = af_rm_ref
243 else
244 cell_flags(ijk) = af_keep_ref
245 end if
246
247 ! Refine around the initial conditions
248 if (global_time < refine_init_time) then
249 do n = 1, init_conds%n_cond
250 dist = gm_dist_line(af_r_cc(box, [ijk]), &
251 init_conds%seed_r0(:, n), &
252 init_conds%seed_r1(:, n), ndim)
253 if (dist - init_conds%seed_width(n) < 2 * max_dx &
254 .and. max_dx > refine_init_fac * &
255 init_conds%seed_width(n)) then
256 cell_flags(ijk) = af_do_ref
257 end if
258 end do
259 end if
260
261 ! Refine around electrode
262 if (iand(box%tag, mg_lsf_box) > 0 .and. &
263 max_dx > current_electrode_dx) then
264 cell_flags(ijk) = af_do_ref
265 end if
266 end do; close_do
267
268 ! Check fixed refinements
269 rmin = box%r_min
270 rmax = box%r_min + box%dr * box%n_cell
271
272 do n = 1, size(refine_regions_dr)
273 if (global_time <= refine_regions_tstop(n) .and. &
274 max_dx > refine_regions_dr(n) .and. all(&
275 rmax >= refine_regions_rmin(:, n) .and. &
276 rmin <= refine_regions_rmax(:, n))) then
277 ! Mark just the center cell to prevent refining neighbors
278 cell_flags(dtimes(nc/2)) = af_do_ref
279 end if
280 end do
281
282 do n = 1, size(refine_limits_dr)
283 if (max_dx < 2 * refine_limits_dr(n) .and. all(&
284 rmin >= refine_limits_rmin(:, n) .and. &
285 rmax <= refine_limits_rmax(:, n))) then
286 ! Mark just the center cell to prevent refining neighbors
287 where (cell_flags == af_do_ref) cell_flags = af_keep_ref
288 end if
289 end do
290
291 ! Make sure we don't have or get a too fine or too coarse grid
292 if (max_dx > refine_max_dx) then
293 cell_flags = af_do_ref
294 else if (min_dx < 2 * refine_min_dx) then
295 where(cell_flags == af_do_ref) cell_flags = af_keep_ref
296 end if
297
298 end subroutine default_refinement
299
300end module m_refine
Module that stores parameters related to the gas.
Definition m_gas.f90:2
integer, public, protected i_gas_dens
Definition m_gas.f90:45
real(dp), parameter, public si_to_townsend
Definition m_gas.f90:39
logical, public, protected gas_constant_density
Whether the gas has a constant density.
Definition m_gas.f90:12
real(dp), public, protected gas_number_density
Definition m_gas.f90:33
Module that provides routines for geometric operations and calculations. Methods and types have a pre...
Definition m_geometry.f90:3
real(dp) function, public gm_dist_line(r, r0, r1, n_dim)
Module to help setting up initial conditions.
type(initcnd_t), public, protected init_conds
Module with grid refinement settings and routines.
Definition m_refine.f90:2
integer, public, protected refine_buffer_width
Definition m_refine.f90:10
subroutine, public refine_initialize(cfg)
Initialize the grid refinement options.
Definition m_refine.f90:93
real(dp), public current_electrode_dx
Definition m_refine.f90:47
real(dp), public refine_electrode_dx
Definition m_refine.f90:43
real(dp), public, protected refine_prepulse_time
Definition m_refine.f90:54
integer, public, protected refine_per_steps
Definition m_refine.f90:13
real(dp), public, protected refine_min_dx
Definition m_refine.f90:16
procedure(af_subr_ref), pointer, public refine_routine
Definition m_refine.f90:83
real(dp), public, protected electrode_derefine_factor
Definition m_refine.f90:51
real(dp), public, protected refine_max_dx
Definition m_refine.f90:19
This module contains several pre-defined variables like:
Definition m_streamer.f90:6
real(dp), public global_time
Global time.
integer, public, protected i_electron
Index of electron density.
integer, public, protected i_electric_fld
Index of electric field norm.
Module that provides routines for reading in arbritrary transport data.
type(lt_t), public, protected td_tbl
integer, parameter, public td_eta
Attachment coefficient.
integer, parameter, public td_alpha
Ionization coefficient.
This module contains all the methods that users can customize.
procedure(af_subr_ref), pointer user_refine
User-defined refinement routine.