Dispersion Modules
These modules handle the Gaussian plume and wind profile logic.
PKI Three-Dimensional Dispersion
The advanced photon point-kernel comparison evaluates physical plume values at
paired three-dimensional points through
WeatherAverager.average_dispersion_at_points. Coordinates are global
east, north, and up distances relative to the chimney base. The returned
dispersion has units s/m^3.
The observer height used by the runners defaults to the local terrain height. The weather-averaged callback masks points below terrain and points upwind of a weather bin. Photon rays that cross terrain are not blocked. PKI is opt-in and non-regulatory; the ENSI-G14 dispersion remains the reference calculation.
ensi_g14_calculator.dispersion
Modules
dispersion_factors_vogt
Classes
VogtModel
Dispersion parameters calculator (sigma_x and sigma_y), according to section A2.5.4 of the ENSI-G14
Usage:
# instanciate:
model = VogtModel()
# pass quantities (with units!)
from astropy.units import km, m
x = 0.1 * km
H = 75.0 * m
# except the weather category, a character (A to F)
w = "A"
# recover whatever you need, see below:
print("Params:", model.vogt_params(w, H))
print("sigma_y:", model.sigma_y(x, w, H))
print("sigma_z:", model.sigma_z(x, w, H))
vogt_params(weather, H_eff)
calculates p_y, q_y, p_z, q_z according to section A2.5.4 of the ENSI G14 (interpolates between tabulated values).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
weather
|
string, weather category ('A', 'B', ..., 'F') |
required | |
H_eff
|
effective release height, with astropy units (length) |
required |
Returns:
| Type | Description |
|---|---|
|
VogtParams instance, where the p_y, q_y, p_z and q_z can be acessed by doing i.e. |
sigma_y(x_m, weather, H_eff)
Horizontal dispersion (perpendicular to wind axis) parameter, standard deviation of the gaussian plume.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x_m
|
distance along the plume axis, with astropy units (length) |
required | |
weather
|
string, weather category ('A', 'B', ..., 'F') |
required | |
H_eff
|
effective release height, with astropy units (length) |
required |
Returns:
| Type | Description |
|---|---|
|
sigma_y, quantity with astropy units, m |
sigma_z(x_m, weather, H_eff)
Vertical dispersion (perpendicular to wind axis) parameter, standard deviation of the gaussian plume.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
x_m
|
distance along the plume axis, with astropy units (length) |
required | |
weather
|
string, weather category ('A', 'B', ..., 'F') |
required | |
H_eff
|
effective release height, with astropy units (length) |
required |
Returns:
| Type | Description |
|---|---|
|
sigma_z, quantity with astropy units, m |
gaussian_plume
Classes
SubmersionCorrectionModel
Calculates the correction coefficients \(KF_{sub,shape}\) and \(KF_{sub,axis}\), used in A2.1.1.2.
Usage:
corr = SubmersionCorrectionModel()
print(corr.kf_sub_shape(10*m, 5*m))
print(corr.kf_sub_axis(10*m, 5*m, H_eff_oro=20*m, y=0*m))
So instanciate class, then override it. (default True: applies rule 4 page 13 Beilage)
p_shape(sigma_y, sigma_z)
P_shape polynomial of section A2.1.1.2, ENSI G14.
sigma_y and sigma_z are to be provided with units, but they will be cast to m in the formula.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sigma_y
|
float or array, horizontal dispersion parameter, with astropy units (length) |
required | |
sigma_z
|
float or array, vertical dispersion parameter, with astropy units (length) |
required |
Returns:
| Type | Description |
|---|---|
|
unitless, float or array. |
kf_sub_shape(sigma_y, sigma_z)
\(KF_{sub,shape}\) term of section A2.1.1.2, ENSI G14.
sigma_y and sigma_z are to be provided with units, but they will be cast to m in the formula.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sigma_y
|
float or array, horizontal dispersion parameter, with astropy units (length) |
required | |
sigma_z
|
float or array, vertical dispersion parameter, with astropy units (length) |
required |
Returns:
| Type | Description |
|---|---|
|
unitless, float or array. |
p_axis_from_vars(mu_r_asym, r_over_sy_p, r_over_sz_p)
\(P_{axis}\) polynomial of page 24 of the ENSI G14 2025 (section A2.1.1.2). Since the arguments are "pre-processed", you should not be using this function unless you are working on the internals of this package.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
mu_r_asym
|
first argument, mu * r * asym (see _asym method of this class; r defined on page 24) |
required | |
r_over_sy_p
|
second argument of the formula |
required | |
r_over_sz_p
|
third argument of the formula |
required |
Returns:
| Type | Description |
|---|---|
|
|
kf_sub_axis(sigma_y, sigma_z, H_eff_oro, y, mu=None)
\(KF_{sub, axis}\) term of bottom of page 23, ENSI G14 2025.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sigma_y
|
float or array, horizontal dispersion parameter, with astropy units (length) |
required | |
sigma_z
|
float or array, vertical dispersion parameter, with astropy units (length) |
required | |
H_eff_oro
|
float or array, effective height, orography corrected (see A2.5.2 and release_height file), units length. |
required | |
y
|
float or array, distance to plume axis (perpendicular to wind direction) |
required | |
mu
|
air attenuation coefficient, given in ENSI G14 params but see discussion on page 24. |
None
|
Returns:
| Type | Description |
|---|---|
|
KF_{sub,axis} coefficient, unitless. |
GaussianPlumeModel
Class calculating the dispersion factors \(chi_K\) and \(chi_{K,S}\), the fundamental quantites upon which everything else is computed.
chi_k(sigma_y, sigma_z, U_Ha, H_eff_oro, y, G_t, sigma_y0, sigma_z0, U0, height=None, weight_elevated=1.0, weight_ground=1.0, height_ground=None)
Computes the dispersion factor \(chi_K\), base quantity upon which deposition and dose calculation rely.
When height is provided, it is the observer height above local terrain
(not global chimney-relative z) and direct plus reflected-image vertical
Gaussian terms are used. A one-dimensional height array is interpreted as
trailing vertical levels when another non-scalar plume input has a
different shape; otherwise it is broadcast elementwise. N-dimensional
height arrays are evaluated as paired points and broadcast using normal
numpy rules.
By the way, when I added height, I realised we need to make an assumption
on the type of plume ENSI was envisioning. Since the ENSI plume is evaluated at 0,
we do not see whether they meant to add a second plume reflecting on the ground, as
is usual. From the normalisation of the plume (1/pi and not 1/2pi), I think they
meant to add a reflected plume. Thus this is what I implemented here.
For the normal G-14 use, the plume is still evaluated on the ground, and adding
the reflected term makes no difference. It only impacts PKI, where we need to
evaluate the plume in its bulk and not only on th eground.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sigma_y
|
float or array, horizontal dispersion parameter, with astropy units (length) |
required | |
sigma_z
|
float or array, vertical dispersion parameter, with astropy units (length) |
required | |
U_Ha
|
velocity of wind at height of release, with astropy units (length/time) |
required | |
H_eff_oro
|
float or array, effective height, orography corrected (see A2.5.2 and release_height file), units length. |
required | |
y
|
float or array, distance to plume axis (perpendicular to wind direction) |
required | |
G_t
|
ground fraction |
required | |
sigma_y0
|
same as sigma_y but evaluated at ground level rather than at plume height level. |
required | |
sigma_z0
|
same as sigma_z but evaluated at ground level rather than at plume height level. |
required | |
U0
|
same as U_Ha, but wind speed at ground level. |
required | |
height
|
optional observer height above local terrain, with astropy length units. |
None
|
|
weight_elevated
|
optional dimensionless factor (scalar or array) multiplying the elevated component, e.g. radioactive decay during transport (see plume_decay.py). |
1.0
|
|
weight_ground
|
same for the ground-level component. |
1.0
|
|
height_ground
|
optional observer height used for the ground-level component only, same shape
as |
None
|
Returns:
| Type | Description |
|---|---|
|
float or array, with astropy units (s/m^3), dispersion factor. |
chi_k_s(sigma_y, sigma_z, U_Ha, H_eff_oro, y, G_t, sigma_y0, sigma_z0, U0, mu=None, weight_elevated=1.0, weight_ground=1.0, height=None)
Computes the pseudo-dispersion factor \(chi_{K,S}\), to be used for submersion dose calculation. (not a real dispersion) HERE MAKE SURE TO COMPUTE THE SIGMAs FOR x=5km if your x>5km (page 15 of annex document to G14) I cannot verify you did it correctly internally to this function. However, you should not be calling this function yourself, there are higher level routines in the package that should do it for you.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sigma_y
|
dispersion coefficient, as computed by the VogtModel class in dispersion_factors_vogt.py |
required | |
sigma_z
|
ditto but vertical |
required | |
U_Ha
|
Wind speed in m/s at the uncorrected release height (e.g. stack height) |
required | |
H_eff_oro
|
Orography-corrected, effective plume height in m above the point in the surroundings with absolute coordinates X (eastward) and Y (northward) relative to the release location (cf. Sec. A2.5.2). Without orography correction, set Heff,oro = Heff . |
required | |
y
|
lateral deviation from the plume axis, orthogonal to the direction of dispersion |
required | |
G_t
|
Fraction of the release that, due to building influences, is to be treated as a ground-level release (cf. Sec. A2.5.1). computed by EffectiveReleaseModel.ground_fraction |
required | |
sigma_y0
|
Gaussian dispersion parameter for ground-level release. |
required | |
sigma_z0
|
Gaussian dispersion parameter for ground-level release. |
required | |
U0
|
Wind speed in m/s near the ground (10 m above ground). |
required | |
mu
|
attenuation coefficient in air, should be read from the package data. |
None
|
|
height
|
optional observer height above local terrain, with astropy length units. Outside G-14: the vertical offset between observer and plume axis, |H_eff_oro - height| (and height for the ground-level component), replaces H_eff_oro in KF_sub,axis. |
None
|
|
weight_elevated
|
optional dimensionless factor (scalar or array) multiplying the elevated component, e.g. radioactive decay during transport (see plume_decay.py). |
1.0
|
|
weight_ground
|
same for the ground-level component. |
1.0
|
Returns:
| Type | Description |
|---|---|
|
chi_ks, float or array, in s/m^3. |
plume_decay
Classes
DecayedDispersion
dataclass
Dispersion of one emitted nuclide with decay during transport already applied.
parent: chi weighted by the parent survival g_m(t), with units (s/m^3) daughters: {daughter nuclide: chi weighted by the in-growth g_d(t)}, activity of the daughter per emitted parent Bq (branching ratios are applied in the dose functions, as in G-14)
__getitem__(index)
Select points, e.g. one receptor of an array: decayed[i].
Functions
parent_survival(lambda_m)
Time weight g_m(t) = exp(-lambda_m t).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lambda_m
|
decay constant of the parent, with units (1/time) |
required |
Returns:
| Type | Description |
|---|---|
|
callable t (Quantity, time) -> dimensionless array |
daughter_ingrowth(lambda_m, lambda_d)
Time weight g_d(t) = lambda_d / (lambda_d - lambda_m) (exp(-lambda_m t) - exp(-lambda_d t)): activity of the daughter at time t per unit initial activity of the parent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lambda_m
|
decay constant of the parent, with units (1/time) |
required | |
lambda_d
|
decay constant of the daughter, with units (1/time) |
required |
Returns:
| Type | Description |
|---|---|
|
callable t (Quantity, time) -> dimensionless array |
decayed_dispersion(evaluate, nuclide, dose_calculator)
Evaluate the decayed dispersion of nuclide and of all its daughters (G-14 Table 4.3.1).
decayed = decayed_dispersion(
lambda w: averager.average_dispersion_at_points(x, y, z, weather, time_weight=w),
"F-18", LongTermDoseCalculator(),
)
dose = LongTermDoseCalculator().inhalation("F-18", Q, decayed) # no T_fz
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
evaluate
|
Callable
|
callable time_weight -> chi (Quantity), e.g. a WeatherAverager method with time_weight. It may also return a tuple of Quantities, e.g. (chi_K, chi_K,S) of average_dispersion. |
required |
nuclide
|
str
|
string, e.g. 'F-18' |
required |
dose_calculator
|
a dose calculator (short or long term), used for the decay constants and daughters |
required |
Returns:
| Type | Description |
|---|---|
DecayedDispersion
|
DecayedDispersion, or a tuple of them if |
parent_dispersion(chi)
The parent's dispersion: chi.parent for a DecayedDispersion, chi itself otherwise (G-14 path).
release_height
Classes
EffectiveReleaseModel
usage:
model = EffectiveReleaseModel()
from astropy.units import m, s
H_a = 60.0 * m
D_i = 2.0 * m
D_e = 2.2 * m
W_0 = 15.0 * m / s
U_Ha = 6.0 * m / s
S = 0.02 / (s**2) # only needed for E/F
w = "D"
dH = model.plume_rise(w, D_i, D_e, W_0, U_Ha, S=S)
print("delta H:", dH)
print("H_eff:", model.effective_release_height(H_a, w, D_i, D_e, W_0, U_Ha, S=S))
H_G = 20.0 * m
print("G_t:", model.ground_fraction(w, H_a, H_G, W_0, U_Ha, scenario="normal"))
downwash_correction(D_e, W_0, U_Ha)
C symbol on page 33, section A2.5.1
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
D_e
|
astropy quantity (units length), external diameter of chimney |
required | |
W_0
|
astropy quantity (units length/time), exhaust velocity of the chimney |
required | |
U_Ha
|
astropy quantity (units length/time), wind speed at the height of the chimney |
required |
Returns:
| Type | Description |
|---|---|
|
downwash correction |
plume_rise(weather, D_i, D_e, W_0, U_Ha, S=None, x=None)
Delta H according to section 2.5.1
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
weather
|
string, weather category (from 'A' to 'F') |
required | |
D_i
|
internal diameter of chimney, with units (length) |
required | |
D_e
|
external diameter of chimney, with units (length) |
required | |
W_0
|
exhaust speed of chimney, with units (length/time) |
required | |
U_Ha
|
astropy quantity (units length/time), wind speed at the height of the chimney |
required | |
S
|
stability parameter, should be read from the package data, keep it to the default (None). |
None
|
|
x
|
optional downwind distance(s) at which the momentum rise dH1 is evaluated, with units (length). Defaults to the G-14 value of 200 m (final rise). Only the near-field module passes it. |
None
|
Returns:
| Type | Description |
|---|---|
|
plume rise with units (length) |
effective_release_height(H_a, weather, D_i, D_e, W_0, U_Ha, scenario='normal', x=None)
H_eff according to section 2.5.1
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
weather
|
string, weather category (from 'A' to 'F') |
required | |
D_i
|
internal diameter of chimney, with units (length) |
required | |
D_e
|
external diameter of chimney, with units (length) |
required | |
W_0
|
exhaust speed of chimney, with units (length/time) |
required | |
U_Ha
|
astropy quantity (units length/time), wind speed at the height of the chimney |
required | |
scenario
|
string, 'normal' or accident'. If accident, the release height is that of the chimney, no rise. |
'normal'
|
|
x
|
optional downwind distance(s) for the momentum rise, see plume_rise. Defaults to 200 m. |
None
|
Returns:
| Type | Description |
|---|---|
|
effective release height with units (length) |
ground_fraction(weather, H_a, H_G, W_0, U_Ha, scenario='normal')
Ground fraction G_t according to section 2.5.1, bottom of page 23 and top of page 24.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
weather
|
string, weather category (from 'A' to 'F') |
required | |
H_a
|
height of chimney (total stack height), with units (length) |
required | |
H_G
|
height of nearby buildings, with units (length) |
required | |
W_0
|
exhaust speed of chimney, with units (length/time) |
required | |
U_Ha
|
astropy quantity (units length/time), wind speed at the height of the chimney. |
required | |
scenario
|
string, 'normal' or 'accident'. If accident, the release height is that of the chimney, no rise. |
'normal'
|
Returns:
| Type | Description |
|---|---|
|
effective release height with units (length) |
heff_oro_axis(H_eff, weather, h_oro_x0)
orography correction for receptor points directly beneath plume axis, first step to computing the actual H_eff_oro.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
H_eff
|
effective release height, with units (length) |
required | |
weather
|
string, weather category (from 'A' to 'F') |
required | |
h_oro_x0
|
terrain elevation (relative to the base of the stack, which is at 0) at distance x from the stack, on the plume axis. |
required |
Returns:
| Type | Description |
|---|---|
|
heff_oro_axis, with units (height) |
heff_oro(H_eff, weather, h_oro_x0, h_oro_xy)
Computes the effective height of the release, plus the terrain height differential.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
H_eff
|
effective release height, with astropy units (length) |
required | |
weather
|
string, weather category (from 'A' to 'F') |
required | |
h_oro_x0
|
terrain elevation (relative to the base of the stack, which is at 0) at distance x from the stack, on the plume axis. |
required | |
h_oro_xy
|
terrain elevation (relative to the base of the stack, which is at 0) at distance x from the stack down the plume axis, and distance y from the plume axis (perpendicular) |
required |
Returns:
| Type | Description |
|---|---|
|
effective release height, orography corrected (with units, height) |
wind_profile
Classes
WindProfileModel
Class computing wind speed correction depending on height. Usage:
model = WindProfileModel()
from astropy.units import m, s
U_M = 5.0 * m / s
z_m = 10.0 * m
H_a = 60.0 * m
w = "D"
print("U(H_a):", model.wind_at_release(U_M, H_a, z_m, w))
wind_at_release(U_M, H_a, z_m, weather)
Estimates U_Ha (wind speed at height H_a) starting from the wind speed U_M measured at height z_m
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
U_M
|
measured wind speed, with units (length/time) |
required | |
H_a
|
desired height, with units (height) |
required | |
z_m
|
measurement height, normally 10m, with units (height) |
required | |
weather
|
string, weather category (from 'A' to 'F'). |
required |
Returns:
| Type | Description |
|---|---|
|
wind speed estimate at height H_a, with units (length/time). |