1
|
|
|
# coding: utf-8 |
2
|
|
|
# Copyright (c) 2020 Stefan Bender |
3
|
|
|
# |
4
|
|
|
# This file is part of pyeppaurora. |
5
|
|
|
# pyeppaurora is free software: you can redistribute it or modify |
6
|
|
|
# it under the terms of the GNU General Public License as published |
7
|
|
|
# by the Free Software Foundation, version 2. |
8
|
|
|
# See accompanying LICENSE file or http://www.gnu.org/licenses/gpl-2.0.html. |
9
|
|
|
"""Atmospheric bremsstrahlung ionization parametrization [1]_ |
10
|
|
|
|
11
|
|
|
.. [1] Berger, M.J., Seltzer, S.M., Maeda, K., |
12
|
|
|
Some new results on electron transport in the atmosphere, |
13
|
|
|
Journal of Atmospheric and Terrestrial Physics, v36, i4, pp. 591--617, |
14
|
|
|
April 1974, |
15
|
|
|
doi: 10.1016/0021-9169(74)90085-3 |
16
|
|
|
""" |
17
|
|
|
|
18
|
|
|
import numpy as np |
19
|
|
|
from scipy import interpolate |
20
|
|
|
|
21
|
|
|
__all__ = ["berger1974"] |
22
|
|
|
|
23
|
|
|
E_BR = [2., 5., 10., 20., 50., 100., 200., 500., 1000., 2000.] |
24
|
|
|
|
25
|
|
|
Z_BR = [ |
26
|
|
|
2e-6, 4e-6, 8e-6, |
27
|
|
|
2e-5, 4e-5, 8e-5, |
28
|
|
|
2e-4, 4e-4, 8e-4, |
29
|
|
|
2e-3, 4e-3, 8e-3, |
30
|
|
|
2e-2, 4e-2, 8e-2, |
31
|
|
|
2e-1, 4e-1, |
32
|
|
|
] |
33
|
|
|
|
34
|
|
|
A_BR = [ |
35
|
|
|
[np.nan] * 9 + [8.6e-6, 5.1e-7] + [np.nan] * 6, |
36
|
|
|
[np.nan] * 8 + [7.2e-4, 1.4e-4, 3.3e-5, 5.2e-6, 1.1e-7] + [np.nan] * 4, |
37
|
|
|
[np.nan] * 7 + [2.0e-3, 8.8e-4, 2.7e-4, 9.4e-5, 2.8e-5, 3.0e-6, 3.8e-7, 3.9e-8] + [np.nan] * 2, |
38
|
|
|
[np.nan] * 6 + [3.4e-3, 1.7e-3, 8.0e-4, 3.0e-4, 1.3e-4, 5.7e-5, 1.5e-5, 3.3e-6, 5.7e-7, 2.9e-8] + [np.nan], |
39
|
|
|
[np.nan] * 5 + [7.3e-3, 2.2e-3, 1.1e-3, 5.7e-4, 2.3e-4, 1.1e-4, 5.4e-5, 2.0e-5, 8.3e-6, 2.6e-6, 3.1e-7, 2.8e-8], |
40
|
|
|
[np.nan] * 4 + [1.1e-2, 7.9e-3, 1.7e-3, 8.4e-4, 4.4e-4, 1.9e-4, 1.0e-4, 5.4e-5, 2.3e-5, 1.1e-5, 3.9e-6, 5.4e-7, 2.4e-8], |
41
|
|
|
[np.nan] * 3 + [5.0e-3, 5.3e-3, 5.0e-3, 1.8e-3, 6.5e-4, 3.3e-4, 1.5e-4, 8.8e-5, 5.2e-5, 2.4e-5, 1.1e-5, 3.8e-6, 1.7e-7, 5.9e-9], |
42
|
|
|
[np.nan] * 2 + [2.2e-3, 2.4e-3, 2.5e-3, 2.5e-3, 1.6e-3, 5.2e-4, 2.8e-4, 1.5e-4, 9.9e-5, 6.5e-5, 2.8e-5, 9.5e-6, 1.5e-6, 6.0e-9] + [np.nan], |
43
|
|
|
[np.nan] + [1.0e-3, 1.1e-3, 1.2e-3, 1.3e-3, 1.4e-3, 1.2e-3, 5.5e-4, 3.2e-4, 1.9e-4, 1.3e-4, 8.3e-5, 2.8e-5, 5.5e-6, 2.4e-7] + [np.nan] * 2, |
44
|
|
|
[6.8e-4, 7.6e-4, 8.4e-4, 9.3e-4, 9.9e-4, 1.1e-3, 1.1e-3, 6.8e-4, 4.5e-4, 2.9e-4, 1.9e-4, 9.2e-5, 1.7e-5, 1.2e-6] + [np.nan] * 3, |
45
|
|
|
] |
46
|
|
|
|
47
|
|
|
|
48
|
|
|
def berger1974( |
49
|
|
|
energy, flux, |
50
|
|
|
scale_height, rho, |
51
|
|
|
ens=None, zm_p_en=None, coeffs=None, |
52
|
|
|
fillna=None, log3=True, |
53
|
|
|
rbf="multiquadric", |
54
|
|
|
): |
55
|
|
|
"""Bremsstrahlung ionization by secondary electrons |
56
|
|
|
|
57
|
|
|
Formulae and parameters as described in [#]_. |
58
|
|
|
|
59
|
|
|
By default, the `log(coefficients)` are interpolated wrt. `log(energy)` |
60
|
|
|
and `log(zm)` using :class:`scipy.interpolated.Rbf`. |
61
|
|
|
The default "multiquadric" should work fine, if not consider |
62
|
|
|
using "thin-plate" splines. |
63
|
|
|
|
64
|
|
|
Parameters |
65
|
|
|
---------- |
66
|
|
|
energy: array_like (M, ...) |
67
|
|
|
Energy E_0 of the mono-energetic electron beam [keV]. |
68
|
|
|
A scalar (0-D) value is promoted to 1-D with one element. |
69
|
|
|
flux: array_like (M,...) |
70
|
|
|
Energy flux Q_0 of the mono-energetic electron beam [keV / cm² / s¹]. |
71
|
|
|
scale_height: array_like (N, ...) |
72
|
|
|
The atmospheric scale heights [cm]. |
73
|
|
|
rho: array_like (N, ...) |
74
|
|
|
The atmospheric mass density [g / cm³]. |
75
|
|
|
ens: array_like (I,), optional |
76
|
|
|
The energies (one axis) of the coefficient array, |
77
|
|
|
used to interpolate the coefficients to `energy`. |
78
|
|
|
Defaults to the Berger et al., 1974 coefficients. |
79
|
|
|
zm_p_en: array_like (J,), optional |
80
|
|
|
The atmospheric depth (the other axis) of the coefficient array, |
81
|
|
|
used to interpolate the coefficients to `z` = `scale_height` * `rhos`. |
82
|
|
|
Defaults to the Berger et al., 1974 coefficients. |
83
|
|
|
coeffs: array_like, (J, I), optional |
84
|
|
|
The bremsstrahlung energy dissipation coefficients. |
85
|
|
|
Defaults to the Berger et al., 1974 coefficients. |
86
|
|
|
fillna: float or None, optional (default `None`) |
87
|
|
|
Value to use for `nan` values in `coeffs`, `None` skips them. |
88
|
|
|
log3: bool, optional (default `True`) |
89
|
|
|
Interpolate the coefficients as log(ens)-log(zm)-log(coeff) |
90
|
|
|
instead of a linear variant. |
91
|
|
|
rbf: str or callable, optional (default "multiquadric") |
92
|
|
|
Radial basis functions to use for :class:`scipy.interpolate.Rbf`. |
93
|
|
|
|
94
|
|
|
Returns |
95
|
|
|
------- |
96
|
|
|
a_br: array_like (M, N) |
97
|
|
|
A scalar (0-D) `energy` is promoted to 1-D, and the result will |
98
|
|
|
have shape (1, N), *not* (N,). |
99
|
|
|
Energy dissipation rate, units: [keV cm⁻³ s⁻¹] |
100
|
|
|
|
101
|
|
|
References |
102
|
|
|
---------- |
103
|
|
|
.. [#] Berger, M.J., Seltzer, S.M., Maeda, K., |
104
|
|
|
Some new results on electron transport in the atmosphere, |
105
|
|
|
Journal of Atmospheric and Terrestrial Physics, v36, i4, pp. 591--617, |
106
|
|
|
April 1974, |
107
|
|
|
doi: 10.1016/0021-9169(74)90085-3 |
108
|
|
|
|
109
|
|
|
See also |
110
|
|
|
-------- |
111
|
|
|
scipy.interpolate.Rbf |
112
|
|
|
""" |
113
|
|
|
energy = np.atleast_1d(np.asarray(energy, dtype=float)) |
114
|
|
|
ens = np.asarray(ens) or np.asarray(E_BR) |
115
|
|
|
zm_p_en = np.asarray(zm_p_en) or np.asarray(Z_BR) |
116
|
|
|
|
117
|
|
|
coeffs = ( |
118
|
|
|
np.array(coeffs, copy=fillna is not None) |
119
|
|
|
or np.array(A_BR, copy=fillna is not None) |
120
|
|
|
) |
121
|
|
|
nans = np.isnan(coeffs) |
122
|
|
|
if fillna is not None: |
123
|
|
|
coeffs[nans] = fillna |
124
|
|
|
# update nan positions (should be all False) |
125
|
|
|
nans = np.isnan(coeffs) |
126
|
|
|
|
127
|
|
|
z = scale_height * rho / energy |
128
|
|
|
# reshape by `numpy`'s automatic broacdasting to the same shape as z |
129
|
|
|
enp = np.ones_like(z) * energy |
130
|
|
|
|
131
|
|
|
pts = [ |
132
|
|
|
(_e, _z, coeffs[_i, _j]) |
133
|
|
|
for _i, _e in enumerate(ens) |
134
|
|
|
for _j, _z in enumerate(zm_p_en) |
135
|
|
|
if not nans[_i, _j] |
136
|
|
|
] |
137
|
|
|
pts = np.array(pts, copy=False) |
138
|
|
|
|
139
|
|
|
if log3: |
140
|
|
|
enp = np.log(enp) |
141
|
|
|
z = np.log(z) |
142
|
|
|
pts = np.log(pts) |
143
|
|
|
intp = interpolate.Rbf(*(pts.T), function=rbf) |
144
|
|
|
abr_zm = intp(enp, z) |
145
|
|
|
|
146
|
|
|
if log3: |
147
|
|
|
abr_zm = np.exp(abr_zm) |
148
|
|
|
return abr_zm * rho * flux |
149
|
|
|
|