afivo-streamer 1.1
1D/2D/3D streamer simulations with AMR
Loading...
Searching...
No Matches
m_analysis.f90
Go to the documentation of this file.
1!> Module with routines to help analyze simulations
3#include "../afivo/src/cpp_macros.h"
4 use m_af_all
5 use m_types
6
7 implicit none
8 private
9
10 ! Public methods
11 public :: analysis_get_maxima
12#if NDIM == 2
13 public :: analysis_get_cross
14#endif
18
19contains
20
21 !> Find at most n_max maxima of a variable. Maxima are determined by looking
22 !> at the direct neighbors.
23 subroutine analysis_get_maxima(tree, iv, threshold, n_max, &
24 coord_val, n_found)
25 type(af_t), intent(in) :: tree
26 integer, intent(in) :: iv !< Index of variable
27 real(dp), intent(in) :: threshold !< Consider maxima above this value
28 integer, intent(in) :: n_max !< Maximum number of maxima
29 real(dp), intent(inout) :: coord_val(ndim+1, n_max) !< Up to n_max maxima and their coordinates
30 integer, intent(out) :: n_found !< Number of maxima found
31
32 integer :: ijk, nc, n, lvl, id
33 real(dp) :: val, neighbs(2*ndim)
34
35 n_found = 0
36 nc = tree%n_cell
37
38 !$omp parallel private(lvl, n, id, IJK, val, neighbs)
39 do lvl = 1, tree%highest_lvl
40 !$omp do
41 do n = 1, size(tree%lvls(lvl)%leaves)
42 id = tree%lvls(lvl)%leaves(n)
43
44 associate(cc => tree%boxes(id)%cc)
45 do kji_do(1,nc)
46 val = cc(ijk, iv)
47#if NDIM == 1
48 neighbs = [cc(i-1, iv), cc(i+1, iv)]
49#elif NDIM == 2
50 neighbs = [cc(i-1, j, iv), cc(i+1, j, iv), &
51 cc(i, j-1, iv), cc(i, j+1, iv)]
52#elif NDIM == 3
53 neighbs = [cc(i-1, j, k, iv), cc(i+1, j, k, iv), &
54 cc(i, j-1, k, iv), cc(i, j+1, k, iv), &
55 cc(i, j, k-1, iv), cc(i, j, k+1, iv)]
56#endif
57 ! The value has to be strictly larger than at least one of the
58 ! neigbors, and not smaller than the neighbors
59 if (val > threshold .and. all(val >= neighbs) &
60 .and. any(val > neighbs)) then
61 ! New maximum found
62 !$omp critical
63 n_found = n_found + 1
64 if (n_found <= n_max) then
65 coord_val(ndim+1, n_found) = val
66 coord_val(1:ndim, n_found) = af_r_cc(tree%boxes(id), [ijk])
67 end if
68 !$omp end critical
69 end if
70 end do; close_do
71 end associate
72
73 end do
74 !$omp end do
75 end do
76 !$omp end parallel
77
78 end subroutine analysis_get_maxima
79
80 !> Find minimum and maximum z coordinate where a variable exceeds a threshold
81 subroutine analysis_zmin_zmax_threshold(tree, iv, threshold, limits, z_minmax)
82 type(af_t), intent(in) :: tree
83 integer, intent(in) :: iv !< Index of variable
84 !> Threshold for variable
85 real(dp), intent(in) :: threshold
86 !> Limits for min/max
87 real(dp), intent(in) :: limits(2)
88 !> Minimum/maximum z coordinate above threshold
89 real(dp), intent(out) :: z_minmax(2)
90
91 call af_reduction_vec(tree, box_minmax_z, reduce_minmax, &
92 limits, z_minmax, 2)
93
94 contains
95
96 ! Find cell with min/max z coordinate that has a density exceeding a
97 ! threshold
98 function box_minmax_z(box, n_vals) result(vec)
99 type(box_t), intent(in) :: box
100 integer, intent(in) :: n_vals
101 real(dp) :: vec(n_vals)
102
103 integer :: i, j, n, nc, ix(ndim)
104 logical :: above
105 real(dp) :: r(ndim)
106
107 nc = box%n_cell
108 i = -1
109 j = -1
110
111 do n = 1, nc
112#if NDIM == 1
113 above = box%cc(n, iv) > threshold
114#elif NDIM == 2
115 above = maxval(box%cc(1:nc, n, iv)) > threshold
116#elif NDIM == 3
117 above = maxval(box%cc(1:nc, 1:nc, n, iv)) > threshold
118#endif
119 if (above) then
120 if (i == -1) i = n
121 j = n
122 end if
123 end do
124
125 vec = [1e100_dp, -1e100_dp]
126 ix = 1
127 if (i /= -1) then
128 ix(ndim) = i
129 r = af_r_cc(box, ix)
130 vec(1) = r(ndim)
131 end if
132
133 if (j /= -1) then
134 ix(ndim) = i
135 r = af_r_cc(box, ix)
136 vec(2) = r(ndim)
137 end if
138 end function box_minmax_z
139
140 !> Reduction method (e.g., min, max, sum)
141 function reduce_minmax(vec_1, vec_2, n_vals) result(vec)
142 integer, intent(in) :: n_vals
143 real(dp), intent(in) :: vec_1(n_vals), vec_2(n_vals)
144 real(dp) :: vec(n_vals)
145 vec(1) = min(vec_1(1), vec_2(1))
146 vec(2) = max(vec_1(2), vec_2(2))
147 end function reduce_minmax
148
149 end subroutine analysis_zmin_zmax_threshold
150
151 !> Find maximal value for boxes that are (at least partially) in the rectangle
152 !> from r0 to r1
153 subroutine analysis_max_var_region(tree, iv, r0, r1, max_value, loc)
154 type(af_t), intent(in) :: tree
155 integer, intent(in) :: iv !< Index of variable
156 real(dp), intent(in) :: r0(ndim) !< Minimum coordinates
157 real(dp), intent(in) :: r1(ndim) !< Maximum coordinates
158 real(dp), intent(out) :: max_value !< Found maximum
159 type(af_loc_t), intent(out) :: loc
160
161 call af_reduction_loc(tree, iv, box_max_region, reduce_max, &
162 -1e100_dp, max_value, loc)
163
164 contains
165
166 subroutine box_max_region(box, iv, val, ix)
167 type(box_t), intent(in) :: box
168 integer, intent(in) :: iv
169 real(dp), intent(out) :: val
170 integer, intent(out) :: ix(ndim)
171 integer :: nc
172 real(dp) :: r_max(ndim)
173
174 nc = box%n_cell
175 r_max = box%r_min + box%n_cell * box%dr
176
177 if (any(box%r_min > r1) .or. any(r_max < r0)) then
178 ix = -1
179 val = -1e100_dp
180 else
181 ix = maxloc(box%cc(dtimes(1:nc), iv))
182 val = box%cc(dindex(ix), iv)
183 end if
184 end subroutine box_max_region
185
186 end subroutine analysis_max_var_region
187
188 subroutine analysis_max_var_product(tree, ivs, max_value, loc)
189 type(af_t), intent(in) :: tree
190 integer, intent(in) :: ivs(:) !< Indices of variables
191 real(dp), intent(out) :: max_value !< Found maximum
192 type(af_loc_t), intent(out) :: loc
193
194 call af_reduction_loc(tree, -1, box_max_product, reduce_max, &
195 -1e100_dp, max_value, loc)
196
197 contains
198
199 subroutine box_max_product(box, iv, val, ix)
200 type(box_t), intent(in) :: box
201 integer, intent(in) :: iv
202 real(dp), intent(out) :: val
203 integer, intent(out) :: ix(ndim)
204 integer :: nc
205
206 nc = box%n_cell
207 ix = maxloc(product(box%cc(dtimes(1:nc), ivs), dim=ndim+1))
208 val = product(box%cc(dindex(ix), ivs))
209 end subroutine box_max_product
210
211 end subroutine analysis_max_var_product
212
213 real(dp) function reduce_max(a, b)
214 real(dp), intent(in) :: a, b
215 reduce_max = max(a, b)
216 end function reduce_max
217
218#if NDIM == 2
219 !> Get integrated quantities of an axisymmetric streamer at a z-coordinate
220 subroutine analysis_get_cross(tree, rmax, z, elec_dens, charge_dens, current_dens)
221 use m_lookup_table
223 use m_gas
224 use m_streamer
226 use m_chemistry
227 type(af_t), intent(in) :: tree
228 real(dp), intent(in) :: rmax !< Integrate up to this radius
229 real(dp), intent(in) :: z !< z-coordinate
230 real(dp), intent(out) :: elec_dens !< electron density
231 real(dp), intent(out) :: charge_dens !< charge density
232 real(dp), intent(out) :: current_dens !< current density
233
234 real(dp) :: ne_fld_rhs(3), mu, td, r, dr, n_inv
235 real(dp) :: ne, fld, ez, rhs, fld_vec(ndim)
236 real(dp) :: d_elec_dens, d_charge_dens, d_current_dens
237 logical :: success
238 integer :: id_guess, i, m
239
240 if (.not. st_cylindrical) &
241 error stop "analysis_get_cross error: need cylindrical coordinates"
242 if (.not. gas_constant_density) &
243 error stop "analysis_get_cross error: need constant gas density"
244
245 id_guess = -1
246 elec_dens = 0.0_dp
247 charge_dens = 0.0_dp
248 current_dens = 0.0_dp
249 n_inv = 1.0_dp/gas_number_density
250 dr = af_min_dr(tree)
251 m = int(rmax/dr) + 1
252
253 do i = 1, m
254 r = i * rmax / (m + 1)
255
256 ne_fld_rhs = af_interp1(tree, [r, z], &
257 [i_electron, i_electric_fld, i_rhs], success, id_guess)
258 if (.not. success) error stop "unsuccessful af_interp1"
259
260 ! Interpolate field components
261 fld_vec = af_interp1_fc(tree, [r, z], electric_fld, success, id_guess)
262 if (.not. success) error stop "unsuccessful af_interp1_fc"
263
264 ne = ne_fld_rhs(1)
265 fld = ne_fld_rhs(2)
266 rhs = ne_fld_rhs(3)
267 ez = fld_vec(2)
268
269 td = fld * si_to_townsend * n_inv
270 mu = lt_get_col(td_tbl, td_mobility, td) * n_inv
271 d_elec_dens = ne * 2.0_dp * uc_pi * r * dr
272 d_charge_dens = rhs * uc_eps0 * 2.0_dp * uc_pi * r * dr / uc_elec_charge
273 d_current_dens = ez * mu * ne * 2.0_dp * uc_pi * r * dr * uc_elem_charge
274
275 ! Update total
276 elec_dens = elec_dens + d_elec_dens
277 charge_dens = charge_dens + d_charge_dens
278 current_dens = current_dens + d_current_dens
279 end do
280
281 end subroutine analysis_get_cross
282#endif
283
284end module m_analysis
Module with routines to help analyze simulations.
Definition m_analysis.f90:2
subroutine, public analysis_max_var_region(tree, iv, r0, r1, max_value, loc)
Find maximal value for boxes that are (at least partially) in the rectangle from r0 to r1.
subroutine, public analysis_get_cross(tree, rmax, z, elec_dens, charge_dens, current_dens)
Get integrated quantities of an axisymmetric streamer at a z-coordinate.
subroutine, public analysis_max_var_product(tree, ivs, max_value, loc)
subroutine, public analysis_zmin_zmax_threshold(tree, iv, threshold, limits, z_minmax)
Find minimum and maximum z coordinate where a variable exceeds a threshold.
subroutine, public analysis_get_maxima(tree, iv, threshold, n_max, coord_val, n_found)
Find at most n_max maxima of a variable. Maxima are determined by looking at the direct neighbors.
Module for handling chemical reactions.
Module that stores parameters related to the gas.
Definition m_gas.f90:2
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
This module contains several pre-defined variables like:
Definition m_streamer.f90:6
logical, public, protected st_cylindrical
Whether cylindrical coordinates are used.
integer, public, protected i_electron
Index of electron density.
integer, public, protected electric_fld
Index of electric field vector.
integer, public, protected i_rhs
Index of source term Poisson.
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_mobility
Electron mobility.
Module with basic types.
Definition m_types.f90:2
Module that contains physical and numerical constants.
real(dp), parameter uc_elem_charge
real(dp), parameter uc_pi
real(dp), parameter uc_eps0
real(dp), parameter uc_elec_charge