Passed
Push — master ( 861427...2a29b5 )
by Stefan
01:38
created

eppaurora.ionization   A

Complexity

Total Complexity 9

Size/Duplication

Total Lines 358
Duplicated Lines 55.87 %

Importance

Changes 0
Metric Value
wmc 9
eloc 112
dl 200
loc 358
rs 10
c 0
b 0
f 0

9 Functions

Rating   Name   Duplication   Size   Complexity  
A fang2008() 0 39 1
A maxwell_pflux() 0 22 1
A fang2010_maxw_int() 17 17 1
A rr1987_mod() 45 45 1
A rr1987() 42 42 1
A fang2013_protons() 24 24 1
A maxwell_general() 0 20 1
A fang2010_mono() 39 39 1
A fang2010_spec_int() 33 33 1

How to fix   Duplicated Code   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

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 ionization rate parametrizations
10
11
Includes the atmospheric ionization rate parametrizations for auroral
12
and medium-energy electron precipitation, 100 eV--1 MeV.
13
14
.. [#] Roble and Ridley, Ann. Geophys., 5A(6), 369--382, 1987
15
.. [#] Fang et al., J. Geophys. Res., 113, A09311, 2008
16
.. [#] Fang et al., Geophys. Res. Lett., 37, L22106, 2010
17
"""
18
19
import numpy as np
20
21
POLY_F2008 = np.array([
22
	[ 3.49979e-1, -6.18200e-2, -4.08124e-2,  1.65414e-2],
23
	[ 5.85425e-1, -5.00793e-2,  5.69309e-2, -4.02491e-3],
24
	[ 1.69692e-1, -2.58981e-2,  1.96822e-2,  1.20505e-3],
25
	[-1.22271e-1, -1.15532e-2,  5.37951e-6,  1.20189e-3],
26
	[ 1.57018,     2.87896e-1, -4.14857e-1,  5.18158e-2],
27
	[ 8.83195e-1,  4.31402e-2, -8.33599e-2,  1.02515e-2],
28
	[ 1.90953,    -4.74704e-2, -1.80200e-1,  2.46652e-2],
29
	[-1.29566,    -2.10952e-1,  2.73106e-1, -2.92752e-2]
30
])
31
32
POLY_F2010 = np.array([
33
	[ 1.24616E+0,  1.45903E+0, -2.42269E-1,  5.95459E-2],
34
	[ 2.23976E+0, -4.22918E-7,  1.36458E-2,  2.53332E-3],
35
	[ 1.41754E+0,  1.44597E-1,  1.70433E-2,  6.39717E-4],
36
	[ 2.48775E-1, -1.50890E-1,  6.30894E-9,  1.23707E-3],
37
	[-4.65119E-1, -1.05081E-1, -8.95701E-2,  1.22450E-2],
38
	[ 3.86019E-1,  1.75430E-3, -7.42960E-4,  4.60881E-4],
39
	[-6.45454E-1,  8.49555E-4, -4.28581E-2, -2.99302E-3],
40
	[ 9.48930E-1,  1.97385E-1, -2.50660E-3, -2.06938E-3]
41
])
42
43
POLY_F2013 = np.array([
44
	[ 2.55050e+0,  2.69476e-1, -2.58425e-1,  4.43190e-2],
45
	[ 6.39287e-1, -1.85817e-1, -3.15636e-2,  1.01370e-2],
46
	[ 1.63996e+0,  2.43580e-1,  4.29873e-2,  3.77803e-2],
47
	[-2.13479e-1,  1.42464e-1,  1.55840e-2,  1.97407e-3],
48
	[-1.65764e-1,  3.39654e-1, -9.87971e-3,  4.02411e-3],
49
	[-3.59358e-2,  2.50330e-2, -3.29365e-2,  5.08057e-3],
50
	[-6.26528e-1,  1.46865e+0,  2.51853e-1, -4.57132e-2],
51
	[ 1.01384e+0,  5.94301e-2, -3.27839e-2,  3.42688e-3],
52
	[-1.29454e-6, -1.43623e-1,  2.82583e-1,  8.29809e-2],
53
	[-1.18622e-1,  1.79191e-1,  6.49171e-2, -3.99715e-3],
54
	[ 2.94890e+0, -5.75821e-1,  2.48563e-2,  8.31078e-2],
55
	[-1.89515e-1,  3.53452e-2,  7.77964e-2, -4.06034e-3]
56
])
57
58
vpolyval = np.vectorize(np.polyval, signature='(m,n),()->(n)')
59
60
61 View Code Duplication
def rr1987(energy, flux, scale_height, rho):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
62
	"""Atmospheric electron energy dissipation Roble and Ridley, 1987
63
64
	Equations (typo corrected) taken from Fang et al., 2008.
65
66
	Parameters
67
	----------
68
	energy: array_like (M,...)
69
		Characteristic energy E_0 [keV] of the Maxwellian distribution.
70
	flux: array_like (M,...)
71
		Integrated energy flux Q_0 [keV / cm² / s¹]
72
	scale_height: array_like (N,...)
73
		The atmospheric scale heights [cm].
74
	rho: array_like (N,...)
75
		The atmospheric mass density [g / cm³]
76
77
	Returns
78
	-------
79
	en_diss: array_like (M,N)
80
		The dissipated energy profiles.
81
82
	References
83
	----------
84
85
	.. [#] Roble and Ridley, Ann. Geophys., 5A(6), 369--382, 1987
86
	"""
87
	_c1 = 2.11685
88
	_c2 = 2.97035
89
	_c3 = 2.09710
90
	_c4 = 0.74054
91
	_c5 = 0.58795
92
	_c6 = 1.72746
93
	_c7 = 1.37459
94
	_c8 = 0.93296
95
96
	beta = (rho * scale_height / (4 * 1e-6))**(1 / 1.65)  # RR 1987, p. 371
97
	y = beta / energy  # Corrected in Fang et al. 2008 (4)
98
	f_y = (_c1 * (y**_c2) * np.exp(-_c3 * (y**_c4)) +
99
		_c5 * (y**_c6) * np.exp(-_c7 * (y**_c8)))
100
	# Corrected in Fang et al. 2008 (2)
101
	en_diss = 0.5 * flux / scale_height * f_y
102
	return en_diss
103
104
105 View Code Duplication
def rr1987_mod(energy, flux, scale_height, rho):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
106
	"""Atmospheric electron energy dissipation Roble and Ridley, 1987
107
108
	Equations (typo corrected) taken from Fang et al., 2008.
109
	Modified polynomial values to get closer to Fang et al., 2008,
110
	origin unknown.
111
112
	Parameters
113
	----------
114
	energy: array_like (M,...)
115
		Characteristic energy E_0 [keV] of the Maxwellian distribution.
116
	flux: array_like (M,...)
117
		Integrated energy flux Q_0 [keV / cm² / s¹]
118
	scale_height: array_like (N,...)
119
		The atmospheric scale heights [cm].
120
	rho: array_like (N,...)
121
		The atmospheric mass density [g / cm³]
122
123
	Returns
124
	-------
125
	en_diss: array_like (M,N)
126
		The dissipated energy profiles.
127
128
	References
129
	----------
130
131
	.. [#] Roble and Ridley, Ann. Geophys., 5A(6), 369--382, 1987
132
	"""
133
	# Modified polynomial, origin unknown
134
	_c1 = 3.233
135
	_c2 = 2.56588
136
	_c3 = 2.2541
137
	_c4 = 0.7297198
138
	_c5 = 1.106907
139
	_c6 = 1.71349
140
	_c7 = 1.8835444
141
	_c8 = 0.86472135
142
143
	# Fang et al., 2008, Eq. (4)
144
	y = (rho * scale_height / (4.6 * 1e-6))**(1 / 1.65) / energy
145
	f_y = (_c1 * (y**_c2) * np.exp(-_c3 * (y**_c4)) +
146
		_c5 * (y**_c6) * np.exp(-_c7 * (y**_c8)))
147
	# energy dissipated [keV]
148
	en_diss = 0.5 * flux / scale_height * f_y
149
	return en_diss
150
151
152
def fang2008(energy, flux, scale_height, rho, pij=POLY_F2008):
153
	"""Atmospheric electron energy dissipation from Fang et al., 2008
154
155
	Ionization profile parametrization as derived in Fang et al., 2008 [#]_.
156
157
	Parameters
158
	----------
159
	energy: array_like (M,...)
160
		Characteristic energy E_0 [keV] of the Maxwellian distribution.
161
	flux: array_like (M,...)
162
		Integrated energy flux Q_0 [keV / cm² / s¹]
163
	scale_height: array_like (N,...)
164
		The atmospheric scale height(s) [cm].
165
	rho: array_like (N,...)
166
		The atmospheric densities [g / cm³], corresponding to the scale heights.
167
168
	Returns
169
	-------
170
	en_diss: array_like (M,N)
171
		The dissipated energy profile(s).
172
173
	References
174
	----------
175
176
	.. [#] Fang et al., J. Geophys. Res., 113, A09311, 2008, doi: 10.1029/2008JA013384
177
	"""
178
	def _f_y(_cc, _y):
179
		# Fang et al., 2008, Eq. (6)
180
		_c = _cc.reshape((8, -1))
181
		return (_c[0] * (_y**_c[1]) * np.exp(-_c[2] * (_y**_c[3])) +
182
			_c[4] * (_y**_c[5]) * np.exp(-_c[6] * (_y**_c[7])))
183
	# Fang et al., 2008, Eq. (7)
184
	_cs = np.exp(vpolyval(pij[:, ::-1].T, np.log(energy))).T
185
	# Fang et al., 2008, Eq. (4)
186
	y = (rho * scale_height / (4e-6))**(1 / 1.65) / energy
187
	f_y = _f_y(_cs, y)
188
	# Fang et al., 2008, Eq. (2)
189
	en_diss = 0.5 * f_y * flux / scale_height
190
	return en_diss
191
192
193 View Code Duplication
def fang2010_mono(energy, flux, scale_height, rho, pij=POLY_F2010):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
194
	r"""Atmospheric electron energy dissipation from Fang et al., 2010
195
196
	Parametrization for mono-energetic electrons [#]_.
197
198
	Parameters
199
	----------
200
	energy: array_like (M,...)
201
		Characteristic energy E_0 [keV] of the Maxwellian distribution.
202
	flux: array_like (M,...)
203
		Integrated energy flux Q_0 [keV / cm² / s¹]
204
	scale_height: array_like (N,...)
205
		The atmospheric scale heights.
206
	rho: array_like (N,...)
207
		The atmospheric densities, corresponding to the scale heights.
208
209
	Returns
210
	-------
211
	en_diss: array_like (M,N)
212
		The dissipated energy profile(s).
213
214
	References
215
	----------
216
217
	.. [#] Fang et al., Geophys. Res. Lett., 37, L22106, 2010, doi: 10.1029/2010GL045406
218
	"""
219
	def _f_y(_cc, _y):
220
		# Fang et al., 2008, Eq. (6), Fang et al., 2010 Eq. (4)
221
		_c = _cc.reshape((8, -1))
222
		return (_c[0] * (_y**_c[1]) * np.exp(-_c[2] * (_y**_c[3])) +
223
			_c[4] * (_y**_c[5]) * np.exp(-_c[6] * (_y**_c[7])))
224
	# Fang et al., 2010, Eq. (5)
225
	_cs = np.exp(vpolyval(pij[:, ::-1].T, np.log(energy))).T
226
	# Fang et al., 2010, Eq. (1)
227
	y = 2. / energy * (rho * scale_height / (6e-6))**(0.7)
228
	f_y = _f_y(_cs, y)
229
	# Fang et al., 2008, Eq. (2)
230
	en_diss = f_y * flux / scale_height
231
	return en_diss
232
233
234 View Code Duplication
def fang2010_spec_int(ens, dfluxes, scale_height, rho, pij=POLY_F2010, axis=-1):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
235
	r"""Integrate over a given energy spectrum
236
237
	Integrates over the mono-energetic parametrization `q` from Fang et al., 2010
238
	using the given differential particle spectrum `phi`:
239
240
	:math:`\int_\text{spec} \phi(E) q(E, Q) E \text{d}E`
241
242
	Parameters
243
	----------
244
	ens: array_like (M,...)
245
		Central (bin) energies of the spectrum
246
	dfluxes: array_like (M,...)
247
		Differential particle fluxes in the given bins
248
	scale_height: array_like (N,...)
249
		The atmospheric scale heights
250
	rho: array_like (N,...)
251
		The atmospheric densities, corresponding to the
252
		scale heights.
253
254
	Returns
255
	-------
256
	en_diss: array_like (N)
257
		The dissipated energy profile(s).
258
	"""
259
	ediss_f10 = fang2010_mono(
260
		ens[None, None, :],
261
		dfluxes,
262
		scale_height[..., None],
263
		rho[..., None],
264
		pij=pij,
265
	)
266
	return np.trapz(ediss_f10 * ens, ens, axis=axis)
267
268
269
def maxwell_general(en, en_0=10.):
270
	"""Maxwell number flux spectrum as in Fang2008 [1]
271
272
	Defined in Fang et al., JGR 2008, Eq. (1).
273
274
	Parameters
275
	----------
276
	en: float
277
		Energy in [keV]
278
	en_0: float, optional
279
		Characteristic energy in [keV], i.e. mode of the distribution.
280
		Default: 10 keV
281
282
	Returns
283
	-------
284
	phi: float
285
		Differential hemispherical number flux in [keV-1 cm-2 s-1]
286
		([keV] or scaled by 1 keV-2 cm-2 s-1, e.g. ).
287
	"""
288
	return en * np.exp(-en / en_0)
289
290
291
def maxwell_pflux(en, en_0=10.):
292
	"""Maxwell particle flux spectrum as in Fang2008 [1]
293
294
	Defined in Fang et al., JGR 2008, Eq. (1).
295
	The total precipitating energy flux is fixed to 1 keV cm-2 s-1,
296
	multiply by Q_0 [keV cm-2 s-1] to scale the particle flux.
297
298
	Parameters
299
	----------
300
	en: float
301
		Energy in [keV]
302
	en_0: float, optional
303
		Characteristic energy in [keV], i.e. mode of the distribution.
304
		Default: 10 keV.
305
306
	Returns
307
	-------
308
	phi: float
309
		Hemispherical differential particle flux in [keV-1 cm-2 s-1]
310
		([kev-2] scaled by unit energy flux).
311
	"""
312
	return 0.5 / en_0**3 * maxwell_general(en, en_0)
313
314
315 View Code Duplication
def fang2010_maxw_int(energy, flux, scale_height, rho, bounds=(0.1, 300.), nstep=128, pij=POLY_F2010):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
316
	"""
317
	Integrate the mono-energetic parametrization over a Maxwellian
318
319
	Parameters
320
	----------
321
	bounds: tuple, optional
322
		(min, max) [keV] of the integration range to integrate the Maxwellian.
323
		Make sure that this is appropriate to encompass the spectrum.
324
		Default: (0.1, 300.)
325
	nsteps: int, optional
326
		Number of integration steps, default: 128.
327
	"""
328
	bounds_l10 = np.log10(bounds)
329
	ens = np.logspace(*bounds_l10, num=nstep)
330
	dflux = flux * maxwell_pflux(ens[:, None], energy)
331
	return fang2010_spec_int(ens, dflux.T, scale_height, rho, pij=pij, axis=-1)
332
333
334 View Code Duplication
def fang2013_protons(energy, flux, scale_height, rho, pij=POLY_F2013):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
335
	"""Proton ionization parametrization by Fang et al., 2013 [1]_
336
337
	.. [1] Fang, X., Lummerzheim, D., and Jackman, C. H. (2013),
338
		Proton impact ionization and a fast calculation method,
339
		J. Geophys. Res. Space Physics, 118, 5369--5378, doi:10.1002/jgra.50484.
340
	"""
341
	def _f_y(_cc, _y):
342
		# Fang et al., 2008, Eq. (6), Fang et al., 2010 Eq. (4)
343
		# Fang et al., 2013, Eqs. (6), (7)
344
		_c = _cc.reshape((12, -1))
345
		return (
346
			_c[0] * (_y**_c[1]) * np.exp(-_c[2] * (_y**_c[3])) +
347
			_c[4] * (_y**_c[5]) * np.exp(-_c[6] * (_y**_c[7])) +
348
			_c[8] * (_y**_c[9]) * np.exp(-_c[10] * (_y**_c[11]))
349
		)
350
	# Fang et al., 2013, Eqs. (6), (7)
351
	_cs = np.exp(vpolyval(pij[:, ::-1].T, np.log(energy))).T
352
	# Fang et al., 2013, Eq. (5)
353
	y = 7.5 / energy * (1e4 * rho * scale_height)**(0.9)
354
	f_y = _f_y(_cs, y)
355
	# Fang et al., 2013, Eq. (3)
356
	en_diss = f_y * flux / scale_height
357
	return en_diss
358