PythonicDISORT 0.9.0__py3-none-any.whl → 0.9.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- PythonicDISORT/_assemble_intensity_and_fluxes.py +188 -166
- PythonicDISORT/_solve_for_coeffs.py +113 -192
- PythonicDISORT/_solve_for_gen_and_part_sols.py +64 -60
- PythonicDISORT/pydisort.py +132 -103
- PythonicDISORT/subroutines.py +139 -81
- {PythonicDISORT-0.9.0.dist-info → PythonicDISORT-0.9.2.dist-info}/METADATA +1 -1
- PythonicDISORT-0.9.2.dist-info/RECORD +11 -0
- {PythonicDISORT-0.9.0.dist-info → PythonicDISORT-0.9.2.dist-info}/WHEEL +1 -1
- PythonicDISORT-0.9.0.dist-info/RECORD +0 -11
- {PythonicDISORT-0.9.0.dist-info → PythonicDISORT-0.9.2.dist-info}/LICENSE.md +0 -0
- {PythonicDISORT-0.9.0.dist-info → PythonicDISORT-0.9.2.dist-info}/top_level.txt +0 -0
|
@@ -20,13 +20,13 @@ def _assemble_intensity_and_fluxes(
|
|
|
20
20
|
there_is_beam_source, # Is there a beam source?
|
|
21
21
|
b_pos, b_neg, # Dirichlet BCs
|
|
22
22
|
b_pos_is_scalar, b_neg_is_scalar, # Is each Dirichlet BCs scalar (isotropic)?
|
|
23
|
-
s_poly_coeffs, # Polynomial coefficients of isotropic source
|
|
24
23
|
Nscoeffs, # Number of isotropic source polynomial coefficients
|
|
24
|
+
s_poly_coeffs, # Polynomial coefficients of isotropic source
|
|
25
25
|
there_is_iso_source, # Is there an isotropic source?
|
|
26
26
|
scale_tau, # Delta-scale factor for tau
|
|
27
27
|
only_flux, # Only compute fluxes?
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
use_banded_solver_NLayers, # Number of layers above or equal which to use `scipy.linalg.solve_banded`
|
|
29
|
+
autograd_compatible, # Should the output functions be compatible with autograd?
|
|
30
30
|
):
|
|
31
31
|
"""Assembles the solution functions: intensity `u`, upward flux `flux_up`, downward flux `flux_down`
|
|
32
32
|
from the previously solved eigenpairs and coefficients from the boundary conditions.
|
|
@@ -66,14 +66,14 @@ def _assemble_intensity_and_fluxes(
|
|
|
66
66
|
| `b_pos` | `NQuad/2 x NFourier` or scalar |
|
|
67
67
|
| `b_neg` | `NQuad/2 x NFourier` or scalar |
|
|
68
68
|
| `b_pos_is_scalar` | boolean |
|
|
69
|
-
| `b_neg_is_scalar` | boolean |
|
|
69
|
+
| `b_neg_is_scalar` | boolean |
|
|
70
|
+
| `Nscoeffs` | scalar |
|
|
70
71
|
| `s_poly_coeffs` | `NLayers x Nscoeffs` or `Nscoeffs` |
|
|
71
|
-
| `Nscoeffs` | scalar |
|
|
72
72
|
| `there_is_iso_source` | boolean |
|
|
73
73
|
| `scale_tau` | `NLayers` |
|
|
74
74
|
| `only_flux` | boolean |
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
75
|
+
| `use_banded_solver_NLayers` | scalar |
|
|
76
|
+
| `autograd_compatible` | boolean |
|
|
77
77
|
|
|
78
78
|
Notable internal variables of _assemble_intensity_and_fluxes
|
|
79
79
|
| Variable | Type / Shape |
|
|
@@ -92,7 +92,7 @@ def _assemble_intensity_and_fluxes(
|
|
|
92
92
|
| `GC_pos` | `NLayers x NQuad/2 x NQuad` |
|
|
93
93
|
| `GC_neg` | `NLayers x NQuad/2 x NQuad` |
|
|
94
94
|
"""
|
|
95
|
-
if
|
|
95
|
+
if autograd_compatible:
|
|
96
96
|
import autograd.numpy as np
|
|
97
97
|
else:
|
|
98
98
|
import numpy as np
|
|
@@ -114,20 +114,21 @@ def _assemble_intensity_and_fluxes(
|
|
|
114
114
|
Nscoeffs,
|
|
115
115
|
there_is_iso_source,
|
|
116
116
|
)
|
|
117
|
-
if there_is_beam_source:
|
|
118
|
-
|
|
119
|
-
G_collect, K_collect, B_collect, G_inv_collect_0 = outputs
|
|
120
|
-
else:
|
|
121
|
-
G_collect, K_collect, B_collect = outputs
|
|
122
|
-
G_inv_collect_0 = None
|
|
117
|
+
if there_is_beam_source and there_is_iso_source:
|
|
118
|
+
G_collect, K_collect, B_collect, G_inv_collect_0 = outputs
|
|
123
119
|
B_collect_0 = B_collect[0, :, :]
|
|
120
|
+
elif there_is_beam_source and not there_is_iso_source:
|
|
121
|
+
G_collect, K_collect, B_collect = outputs
|
|
122
|
+
B_collect_0 = B_collect[0, :, :]
|
|
123
|
+
G_inv_collect_0 = None
|
|
124
|
+
elif not there_is_beam_source and there_is_iso_source:
|
|
125
|
+
G_collect, K_collect, G_inv_collect_0 = outputs
|
|
126
|
+
B_collect = None
|
|
124
127
|
else:
|
|
125
|
-
|
|
126
|
-
G_collect, K_collect, G_inv_collect_0 = outputs
|
|
127
|
-
else:
|
|
128
|
-
G_collect, K_collect = outputs
|
|
129
|
-
G_inv_collect_0 = None
|
|
128
|
+
G_collect, K_collect = outputs
|
|
130
129
|
B_collect = None
|
|
130
|
+
G_inv_collect_0 = None
|
|
131
|
+
|
|
131
132
|
|
|
132
133
|
GC_collect = _solve_for_coeffs(
|
|
133
134
|
NFourier,
|
|
@@ -146,10 +147,10 @@ def _assemble_intensity_and_fluxes(
|
|
|
146
147
|
there_is_beam_source,
|
|
147
148
|
b_pos, b_neg,
|
|
148
149
|
b_pos_is_scalar, b_neg_is_scalar,
|
|
149
|
-
s_poly_coeffs,
|
|
150
150
|
Nscoeffs,
|
|
151
|
+
s_poly_coeffs,
|
|
151
152
|
there_is_iso_source,
|
|
152
|
-
|
|
153
|
+
use_banded_solver_NLayers,
|
|
153
154
|
)
|
|
154
155
|
|
|
155
156
|
G_collect_0 = G_collect[0, :, :, :]
|
|
@@ -161,7 +162,7 @@ def _assemble_intensity_and_fluxes(
|
|
|
161
162
|
|
|
162
163
|
# Construct the intensity function (refer to Section 3.7 of the Comprehensive Documentation)
|
|
163
164
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
164
|
-
def u(tau, phi, return_Fourier_error=False,
|
|
165
|
+
def u(tau, phi, is_antiderivative_wrt_tau=False, return_Fourier_error=False, return_tau_arr=False):
|
|
165
166
|
"""
|
|
166
167
|
Intensity function with arguments `(tau, phi)` of types `(array or float, array or float)`.
|
|
167
168
|
Returns an ndarray with axes corresponding to variation with `mu, tau, phi` respectively.
|
|
@@ -172,8 +173,8 @@ def _assemble_intensity_and_fluxes(
|
|
|
172
173
|
"""
|
|
173
174
|
tau = np.atleast_1d(tau)
|
|
174
175
|
phi = np.atleast_1d(phi)
|
|
175
|
-
|
|
176
|
-
|
|
176
|
+
if np.all(tau < 0) or np.all(tau > tau_arr[-1]):
|
|
177
|
+
raise ValueError("tau input outside the tau range specified for the atmosphere (check `tau_arr`).")
|
|
177
178
|
|
|
178
179
|
# Atmospheric layer indices
|
|
179
180
|
l = np.argmax(tau[:, None] <= tau_arr[None, :], axis=1)
|
|
@@ -196,56 +197,55 @@ def _assemble_intensity_and_fluxes(
|
|
|
196
197
|
axis=-1,
|
|
197
198
|
)
|
|
198
199
|
|
|
199
|
-
if is_antiderivative_wrt_tau:
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
"mtij, mtj -> mti",
|
|
203
|
-
GC_collect[:, l, :, :],
|
|
204
|
-
np.exp(exponent) / (scale_tau[None, l, None] * K_collect[:, l, :]),
|
|
205
|
-
optimize=True,
|
|
206
|
-
) + B_collect[:, l, :] * np.exp(-scaled_tau[None, :, None] / mu0) / (
|
|
207
|
-
-scale_tau[None, l, None] / mu0
|
|
208
|
-
)
|
|
209
|
-
else:
|
|
210
|
-
um = np.einsum(
|
|
200
|
+
if is_antiderivative_wrt_tau and there_is_beam_source:
|
|
201
|
+
um = (
|
|
202
|
+
np.einsum(
|
|
211
203
|
"mtij, mtj -> mti",
|
|
212
204
|
GC_collect[:, l, :, :],
|
|
213
|
-
np.exp(exponent) / (scale_tau[None,
|
|
205
|
+
np.exp(exponent) / (scale_tau[None, :, None] * K_collect)[:, l, :],
|
|
214
206
|
optimize=True,
|
|
215
207
|
)
|
|
208
|
+
+ (B_collect / (-scale_tau / mu0)[None, :, None])[:, l, :]
|
|
209
|
+
* np.exp(-scaled_tau / mu0)[None, :, None]
|
|
210
|
+
)
|
|
211
|
+
elif is_antiderivative_wrt_tau and not there_is_beam_source:
|
|
212
|
+
um = np.einsum(
|
|
213
|
+
"mtij, mtj -> mti",
|
|
214
|
+
GC_collect[:, l, :, :],
|
|
215
|
+
np.exp(exponent) / (scale_tau[None, l, None] * K_collect)[:, l, :],
|
|
216
|
+
optimize=True,
|
|
217
|
+
)
|
|
218
|
+
elif not is_antiderivative_wrt_tau and there_is_beam_source:
|
|
219
|
+
um = np.einsum(
|
|
220
|
+
"mtij, mtj -> mti", GC_collect[:, l, :, :], np.exp(exponent), optimize=True
|
|
221
|
+
) + B_collect[:, l, :] * np.exp(-scaled_tau / mu0)[None, :, None]
|
|
216
222
|
else:
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
) + B_collect[:, l, :] * np.exp(-scaled_tau[None, :, None] / mu0)
|
|
221
|
-
else:
|
|
222
|
-
um = np.einsum(
|
|
223
|
-
"mtij, mtj -> mti", GC_collect[:, l, :, :], np.exp(exponent), optimize=True
|
|
224
|
-
)
|
|
223
|
+
um = np.einsum(
|
|
224
|
+
"mtij, mtj -> mti", GC_collect[:, l, :, :], np.exp(exponent), optimize=True
|
|
225
|
+
)
|
|
225
226
|
|
|
226
227
|
# Contribution from particular solution for isotropic internal sources
|
|
227
228
|
if there_is_iso_source:
|
|
229
|
+
l_uniq, l_inv = np.unique(l, return_inverse=True)
|
|
228
230
|
_mathscr_v_contribution = _mathscr_v(
|
|
229
|
-
tau,
|
|
230
|
-
s_poly_coeffs,
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
G_inv_collect_0,
|
|
231
|
+
tau, l_inv, Nscoeffs,
|
|
232
|
+
s_poly_coeffs[l_uniq],
|
|
233
|
+
G_collect_0[l_uniq],
|
|
234
|
+
K_collect_0[l_uniq],
|
|
235
|
+
G_inv_collect_0[l_uniq],
|
|
235
236
|
mu_arr,
|
|
236
237
|
is_antiderivative_wrt_tau,
|
|
237
|
-
|
|
238
|
+
autograd_compatible
|
|
238
239
|
)
|
|
239
240
|
|
|
240
|
-
if
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
um = um + np.concatenate((_mathscr_v_contribution.T, np.zeros((NFourier - 1, len(tau), NQuad))))
|
|
241
|
+
if NFourier == 1:
|
|
242
|
+
um = um + _mathscr_v_contribution.T
|
|
243
|
+
elif autograd_compatible:
|
|
244
|
+
um = um + np.concatenate((_mathscr_v_contribution.T, np.zeros((NFourier - 1, len(tau), NQuad))))
|
|
245
245
|
else:
|
|
246
246
|
um[0, :, :] += _mathscr_v_contribution.T
|
|
247
247
|
|
|
248
|
-
|
|
248
|
+
u = np.einsum(
|
|
249
249
|
"mti, mp -> itp",
|
|
250
250
|
um,
|
|
251
251
|
np.cos(np.arange(NFourier)[:, None] * (phi0 - phi)[None, :]),
|
|
@@ -260,52 +260,59 @@ def _assemble_intensity_and_fluxes(
|
|
|
260
260
|
],
|
|
261
261
|
axis=-1,
|
|
262
262
|
)
|
|
263
|
-
if is_antiderivative_wrt_tau:
|
|
264
|
-
|
|
265
|
-
|
|
263
|
+
if is_antiderivative_wrt_tau and there_is_beam_source:
|
|
264
|
+
ulast = (
|
|
265
|
+
np.einsum(
|
|
266
266
|
"tij, tj -> it",
|
|
267
267
|
GC_collect[-1, l, :, :],
|
|
268
|
-
np.exp(exponent) / (scale_tau[
|
|
268
|
+
np.exp(exponent) / (scale_tau[:, None] * K_collect[-1, :, :])[l, :],
|
|
269
269
|
optimize=True,
|
|
270
|
-
) + B_collect[-1, l, :].T * np.exp(-scaled_tau[None, :] / mu0) / (
|
|
271
|
-
-scale_tau[None, l] / mu0
|
|
272
270
|
)
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
271
|
+
+ (B_collect.T[-1, :, :] / (-scale_tau / mu0)[None, :])[:, l]
|
|
272
|
+
* np.exp(-scaled_tau / mu0)[None, :]
|
|
273
|
+
)
|
|
274
|
+
elif is_antiderivative_wrt_tau and not there_is_beam_source:
|
|
275
|
+
ulast = np.einsum(
|
|
276
|
+
"tij, tj -> it",
|
|
277
|
+
GC_collect[-1, l, :, :],
|
|
278
|
+
np.exp(exponent) / (scale_tau[:, None] * K_collect[-1, :, :])[l, :],
|
|
279
|
+
optimize=True,
|
|
279
280
|
)
|
|
281
|
+
elif not is_antiderivative_wrt_tau and not there_is_beam_source:
|
|
282
|
+
ulast = np.einsum(
|
|
283
|
+
"tij, tj -> it", GC_collect[-1, l, :, :], np.exp(exponent), optimize=True
|
|
284
|
+
) + B_collect.T[-1, :, l] * np.exp(-scaled_tau / mu0)[None, :]
|
|
280
285
|
else:
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
) + B_collect[-1, l, :].T * np.exp(-scaled_tau[None, :] / mu0)
|
|
285
|
-
else:
|
|
286
|
-
ulast = np.einsum(
|
|
287
|
-
"tij, tj -> it", GC_collect[-1, l, :, :], np.exp(exponent), optimize=True
|
|
288
|
-
)
|
|
286
|
+
ulast = np.einsum(
|
|
287
|
+
"tij, tj -> it", GC_collect[-1, l, :, :], np.exp(exponent), optimize=True
|
|
288
|
+
)
|
|
289
289
|
|
|
290
|
-
|
|
290
|
+
u_abs = np.abs(u)
|
|
291
291
|
Fourier_error = np.max(
|
|
292
292
|
np.divide(
|
|
293
293
|
np.abs(
|
|
294
294
|
ulast[:, :, None] * np.cos((NFourier - 1) * (phi0 - phi))[None, None, :]
|
|
295
295
|
),
|
|
296
|
-
|
|
297
|
-
out=np.zeros_like(
|
|
298
|
-
where=
|
|
296
|
+
u_abs,
|
|
297
|
+
out=np.zeros_like(u_abs),
|
|
298
|
+
where=u_abs > 1e-15,
|
|
299
299
|
)
|
|
300
300
|
)
|
|
301
|
-
|
|
301
|
+
|
|
302
|
+
if return_tau_arr:
|
|
303
|
+
return I0_orig * np.squeeze(u), Fourier_error, tau_arr
|
|
304
|
+
else:
|
|
305
|
+
return I0_orig * np.squeeze(u), Fourier_error
|
|
302
306
|
else:
|
|
303
|
-
|
|
307
|
+
if return_tau_arr:
|
|
308
|
+
return I0_orig * np.squeeze(u), tau_arr
|
|
309
|
+
else:
|
|
310
|
+
return I0_orig * np.squeeze(u)
|
|
304
311
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
305
312
|
|
|
306
313
|
# Construct u0
|
|
307
314
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
308
|
-
def u0(tau, is_antiderivative_wrt_tau=False, _return_act_dscale_for_reclass=False):
|
|
315
|
+
def u0(tau, is_antiderivative_wrt_tau=False, return_tau_arr=False, _return_act_dscale_for_reclass=False):
|
|
309
316
|
"""
|
|
310
317
|
Zeroth Fourier mode of the intensity with argument `tau` (type: array or float).
|
|
311
318
|
Returns an ndarray with axes corresponding to variation with `mu` and `tau` respectively.
|
|
@@ -316,8 +323,8 @@ def _assemble_intensity_and_fluxes(
|
|
|
316
323
|
to switch to an antiderivative of the function with respect to `tau`.
|
|
317
324
|
"""
|
|
318
325
|
tau = np.atleast_1d(tau)
|
|
319
|
-
|
|
320
|
-
|
|
326
|
+
if np.all(tau < 0) or np.all(tau > tau_arr[-1]):
|
|
327
|
+
raise ValueError("tau input outside the tau range given for the atmosphere (check `tau_arr`).")
|
|
321
328
|
|
|
322
329
|
# Atmospheric layer indices
|
|
323
330
|
l = np.argmax(tau[:, None] <= tau_arr[None, :], axis=1)
|
|
@@ -333,7 +340,10 @@ def _assemble_intensity_and_fluxes(
|
|
|
333
340
|
# in performing the reclassification of delta-scaled actinic flux
|
|
334
341
|
if _return_act_dscale_for_reclass:
|
|
335
342
|
if is_antiderivative_wrt_tau:
|
|
336
|
-
act_dscale_reclassification =
|
|
343
|
+
act_dscale_reclassification = (
|
|
344
|
+
I0 * np.exp(-scaled_tau / mu0) / (-scale_tau[l] / mu0)
|
|
345
|
+
- I0 * np.exp(-tau / mu0) * -mu0
|
|
346
|
+
)
|
|
337
347
|
else:
|
|
338
348
|
act_dscale_reclassification = I0 * np.exp(-scaled_tau / mu0) - I0 * np.exp(-tau / mu0)
|
|
339
349
|
else:
|
|
@@ -349,49 +359,53 @@ def _assemble_intensity_and_fluxes(
|
|
|
349
359
|
axis=-1,
|
|
350
360
|
)
|
|
351
361
|
|
|
352
|
-
if is_antiderivative_wrt_tau:
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
"tij, tj -> it",
|
|
356
|
-
GC_collect_0[l, :, :],
|
|
357
|
-
np.exp(exponent) / (scale_tau[l, None] * K_collect_0[l, :]),
|
|
358
|
-
optimize=True,
|
|
359
|
-
) + B_collect_0[l, :].T * np.exp(-scaled_tau[None, :] / mu0) / (
|
|
360
|
-
-scale_tau[None, l] / mu0
|
|
361
|
-
)
|
|
362
|
-
else:
|
|
363
|
-
u0 = np.einsum(
|
|
362
|
+
if is_antiderivative_wrt_tau and there_is_beam_source:
|
|
363
|
+
u0 = (
|
|
364
|
+
np.einsum(
|
|
364
365
|
"tij, tj -> it",
|
|
365
366
|
GC_collect_0[l, :, :],
|
|
366
|
-
np.exp(exponent) / (scale_tau[
|
|
367
|
+
np.exp(exponent) / (scale_tau[:, None] * K_collect_0)[l, :],
|
|
367
368
|
optimize=True,
|
|
368
369
|
)
|
|
370
|
+
+ (B_collect_0.T / (-scale_tau / mu0)[None, :])[:, l]
|
|
371
|
+
* np.exp(-scaled_tau / mu0)[None, :]
|
|
372
|
+
)
|
|
373
|
+
if is_antiderivative_wrt_tau and not there_is_beam_source:
|
|
374
|
+
u0 = np.einsum(
|
|
375
|
+
"tij, tj -> it",
|
|
376
|
+
GC_collect_0[l, :, :],
|
|
377
|
+
np.exp(exponent) / (scale_tau[:, None] * K_collect_0)[l, :],
|
|
378
|
+
optimize=True,
|
|
379
|
+
)
|
|
380
|
+
if not is_antiderivative_wrt_tau and there_is_beam_source:
|
|
381
|
+
u0 = np.einsum(
|
|
382
|
+
"tij, tj -> it", GC_collect_0[l, :, :], np.exp(exponent), optimize=True
|
|
383
|
+
) + B_collect_0.T[:, l] * np.exp(-scaled_tau / mu0)[None, :]
|
|
369
384
|
else:
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
) + B_collect_0[l, :].T * np.exp(-scaled_tau[None, :] / mu0)
|
|
374
|
-
else:
|
|
375
|
-
u0 = np.einsum(
|
|
376
|
-
"tij, tj -> it", GC_collect_0[l, :, :], np.exp(exponent), optimize=True
|
|
377
|
-
)
|
|
385
|
+
u0 = np.einsum(
|
|
386
|
+
"tij, tj -> it", GC_collect_0[l, :, :], np.exp(exponent), optimize=True
|
|
387
|
+
)
|
|
378
388
|
|
|
379
389
|
# Contribution from particular solution for isotropic internal sources
|
|
380
390
|
if there_is_iso_source:
|
|
391
|
+
l_uniq, l_inv = np.unique(l, return_inverse=True)
|
|
381
392
|
_mathscr_v_contribution = _mathscr_v(
|
|
382
|
-
tau,
|
|
383
|
-
s_poly_coeffs,
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
G_inv_collect_0,
|
|
393
|
+
tau, l_inv, Nscoeffs,
|
|
394
|
+
s_poly_coeffs[l_uniq],
|
|
395
|
+
G_collect_0[l_uniq],
|
|
396
|
+
K_collect_0[l_uniq],
|
|
397
|
+
G_inv_collect_0[l_uniq],
|
|
388
398
|
mu_arr,
|
|
389
399
|
is_antiderivative_wrt_tau,
|
|
390
|
-
|
|
400
|
+
autograd_compatible
|
|
391
401
|
)
|
|
392
402
|
u0 = u0 + _mathscr_v_contribution
|
|
393
|
-
|
|
394
|
-
if _return_act_dscale_for_reclass:
|
|
403
|
+
|
|
404
|
+
if return_tau_arr and _return_act_dscale_for_reclass:
|
|
405
|
+
return I0_orig * np.squeeze(u0), tau_arr, act_dscale_reclassification
|
|
406
|
+
elif return_tau_arr and not _return_act_dscale_for_reclass:
|
|
407
|
+
return I0_orig * np.squeeze(u0), tau_arr
|
|
408
|
+
elif not return_tau_arr and _return_act_dscale_for_reclass:
|
|
395
409
|
return I0_orig * np.squeeze(u0), act_dscale_reclassification
|
|
396
410
|
else:
|
|
397
411
|
return I0_orig * np.squeeze(u0)
|
|
@@ -406,7 +420,7 @@ def _assemble_intensity_and_fluxes(
|
|
|
406
420
|
B_neg = B_collect_0[:, N:].T
|
|
407
421
|
|
|
408
422
|
|
|
409
|
-
def flux_up(tau, is_antiderivative_wrt_tau=False):
|
|
423
|
+
def flux_up(tau, is_antiderivative_wrt_tau=False, return_tau_arr=False):
|
|
410
424
|
"""
|
|
411
425
|
(Energetic) Flux function with argument `tau` (type: array or float) for positive (upward) `mu` values.
|
|
412
426
|
Returns the diffuse flux magnitudes (same type and size as `tau`).
|
|
@@ -414,8 +428,8 @@ def _assemble_intensity_and_fluxes(
|
|
|
414
428
|
to switch to an antiderivative of the function with respect to `tau`.
|
|
415
429
|
"""
|
|
416
430
|
tau = np.atleast_1d(tau)
|
|
417
|
-
|
|
418
|
-
|
|
431
|
+
if np.all(tau < 0) or np.all(tau > tau_arr[-1]):
|
|
432
|
+
raise ValueError("tau input outside the tau range given for the atmosphere (check `tau_arr`).")
|
|
419
433
|
|
|
420
434
|
# Atmospheric layer indices
|
|
421
435
|
l = np.argmax(tau[:, None] <= tau_arr[None, :], axis=1)
|
|
@@ -431,27 +445,26 @@ def _assemble_intensity_and_fluxes(
|
|
|
431
445
|
scaled_tau = tau
|
|
432
446
|
|
|
433
447
|
if there_is_iso_source:
|
|
448
|
+
l_uniq, l_inv = np.unique(l, return_inverse=True)
|
|
434
449
|
_mathscr_v_contribution = _mathscr_v(
|
|
435
|
-
tau,
|
|
436
|
-
s_poly_coeffs,
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
G_inv_collect_0,
|
|
450
|
+
tau, l_inv, Nscoeffs,
|
|
451
|
+
s_poly_coeffs[l_uniq],
|
|
452
|
+
G_collect_0[l_uniq, :N, :],
|
|
453
|
+
K_collect_0[l_uniq],
|
|
454
|
+
G_inv_collect_0[l_uniq],
|
|
441
455
|
mu_arr,
|
|
442
456
|
is_antiderivative_wrt_tau,
|
|
443
|
-
|
|
444
|
-
)
|
|
457
|
+
autograd_compatible
|
|
458
|
+
)
|
|
445
459
|
else:
|
|
446
460
|
_mathscr_v_contribution = 0
|
|
447
461
|
|
|
448
|
-
if there_is_beam_source:
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
direct_beam_contribution = B_pos[:, l] * np.exp(-scaled_tau[None, :] / mu0)
|
|
462
|
+
if there_is_beam_source and is_antiderivative_wrt_tau:
|
|
463
|
+
direct_beam_contribution = (
|
|
464
|
+
(B_pos / (-scale_tau / mu0)[None, :])[:, l] * np.exp(-scaled_tau / mu0)[None, :]
|
|
465
|
+
)
|
|
466
|
+
elif there_is_beam_source and not is_antiderivative_wrt_tau:
|
|
467
|
+
direct_beam_contribution = B_pos[:, l] * np.exp(-scaled_tau / mu0)[None, :]
|
|
455
468
|
else:
|
|
456
469
|
direct_beam_contribution = 0
|
|
457
470
|
|
|
@@ -468,7 +481,7 @@ def _assemble_intensity_and_fluxes(
|
|
|
468
481
|
np.einsum(
|
|
469
482
|
"tij, tj -> it",
|
|
470
483
|
GC_pos[l, :, :],
|
|
471
|
-
np.exp(exponent) / (scale_tau[
|
|
484
|
+
np.exp(exponent) / (scale_tau[:, None] * K_collect_0)[l, :],
|
|
472
485
|
)
|
|
473
486
|
+ direct_beam_contribution
|
|
474
487
|
+ _mathscr_v_contribution
|
|
@@ -479,12 +492,15 @@ def _assemble_intensity_and_fluxes(
|
|
|
479
492
|
+ direct_beam_contribution
|
|
480
493
|
+ _mathscr_v_contribution
|
|
481
494
|
)
|
|
482
|
-
|
|
483
495
|
flux = 2 * pi * (mu_arr_pos * W) @ u0_pos
|
|
484
|
-
|
|
496
|
+
|
|
497
|
+
if return_tau_arr:
|
|
498
|
+
return I0_orig * np.squeeze(flux)[()], tau_arr
|
|
499
|
+
else:
|
|
500
|
+
return I0_orig * np.squeeze(flux)[()]
|
|
485
501
|
|
|
486
502
|
|
|
487
|
-
def flux_down(tau, is_antiderivative_wrt_tau=False):
|
|
503
|
+
def flux_down(tau, is_antiderivative_wrt_tau=False, return_tau_arr=False):
|
|
488
504
|
"""
|
|
489
505
|
(Energetic) Flux function with argument `tau` (type: array or float) for negative (downward) `mu` values.
|
|
490
506
|
Returns a tuple of the diffuse and direct flux magnitudes respectively where each entry is of the
|
|
@@ -493,8 +509,8 @@ def _assemble_intensity_and_fluxes(
|
|
|
493
509
|
to switch to an antiderivative of the function with respect to `tau`.
|
|
494
510
|
"""
|
|
495
511
|
tau = np.atleast_1d(tau)
|
|
496
|
-
|
|
497
|
-
|
|
512
|
+
if np.all(tau < 0) or np.all(tau > tau_arr[-1]):
|
|
513
|
+
raise ValueError("tau input outside the tau range given for the atmosphere (check `tau_arr`).")
|
|
498
514
|
|
|
499
515
|
# Atmospheric layer indices
|
|
500
516
|
l = np.argmax(tau[:, None] <= tau_arr[None, :], axis=1)
|
|
@@ -510,29 +526,28 @@ def _assemble_intensity_and_fluxes(
|
|
|
510
526
|
scaled_tau = tau
|
|
511
527
|
|
|
512
528
|
if there_is_iso_source:
|
|
529
|
+
l_uniq, l_inv = np.unique(l, return_inverse=True)
|
|
513
530
|
_mathscr_v_contribution = _mathscr_v(
|
|
514
|
-
tau,
|
|
515
|
-
s_poly_coeffs,
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
G_inv_collect_0,
|
|
531
|
+
tau, l_inv, Nscoeffs,
|
|
532
|
+
s_poly_coeffs[l_uniq],
|
|
533
|
+
G_collect_0[l_uniq, N:, :],
|
|
534
|
+
K_collect_0[l_uniq],
|
|
535
|
+
G_inv_collect_0[l_uniq],
|
|
520
536
|
mu_arr,
|
|
521
537
|
is_antiderivative_wrt_tau,
|
|
522
|
-
|
|
523
|
-
)
|
|
538
|
+
autograd_compatible
|
|
539
|
+
)
|
|
524
540
|
else:
|
|
525
541
|
_mathscr_v_contribution = 0
|
|
526
542
|
|
|
527
|
-
if there_is_beam_source:
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
direct_beam_scaled = I0 * mu0 * np.exp(-scaled_tau / mu0)
|
|
543
|
+
if there_is_beam_source and is_antiderivative_wrt_tau:
|
|
544
|
+
direct_beam_contribution = (B_neg / (-scale_tau / mu0)[None, l])[:, l] * np.exp(-scaled_tau / mu0)[None, :]
|
|
545
|
+
direct_beam = I0 * mu0 * np.exp(-tau / mu0) * -mu0
|
|
546
|
+
direct_beam_scaled = I0 * mu0 * np.exp(-scaled_tau / mu0) / (-scale_tau / mu0)[None, l]
|
|
547
|
+
elif there_is_beam_source and not is_antiderivative_wrt_tau:
|
|
548
|
+
direct_beam_contribution = B_neg[:, l] * np.exp(-scaled_tau / mu0)[None, :]
|
|
549
|
+
direct_beam = I0 * mu0 * np.exp(-tau / mu0)
|
|
550
|
+
direct_beam_scaled = I0 * mu0 * np.exp(-scaled_tau / mu0)
|
|
536
551
|
else:
|
|
537
552
|
direct_beam_contribution = 0
|
|
538
553
|
direct_beam = 0
|
|
@@ -548,7 +563,7 @@ def _assemble_intensity_and_fluxes(
|
|
|
548
563
|
|
|
549
564
|
if is_antiderivative_wrt_tau:
|
|
550
565
|
u0_neg = (
|
|
551
|
-
np.einsum("tij, tj -> it", GC_neg[l, :, :], np.exp(exponent) / (scale_tau[
|
|
566
|
+
np.einsum("tij, tj -> it", GC_neg[l, :, :], np.exp(exponent) / (scale_tau[:, None] * K_collect_0)[l, :])
|
|
552
567
|
+ direct_beam_contribution
|
|
553
568
|
+ _mathscr_v_contribution
|
|
554
569
|
)
|
|
@@ -558,15 +573,22 @@ def _assemble_intensity_and_fluxes(
|
|
|
558
573
|
+ direct_beam_contribution
|
|
559
574
|
+ _mathscr_v_contribution
|
|
560
575
|
)
|
|
561
|
-
|
|
562
576
|
diffuse_flux = 2 * pi * (mu_arr_pos * W) @ u0_neg + direct_beam_scaled - direct_beam
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
577
|
+
|
|
578
|
+
if return_tau_arr:
|
|
579
|
+
return (
|
|
580
|
+
I0_orig * np.squeeze(diffuse_flux)[()],
|
|
581
|
+
I0_orig * I0 * np.squeeze(direct_beam)[()],
|
|
582
|
+
tau_arr
|
|
583
|
+
)
|
|
584
|
+
else:
|
|
585
|
+
return (
|
|
586
|
+
I0_orig * np.squeeze(diffuse_flux)[()],
|
|
587
|
+
I0_orig * I0 * np.squeeze(direct_beam)[()],
|
|
588
|
+
)
|
|
567
589
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
568
590
|
|
|
569
591
|
if only_flux:
|
|
570
|
-
return flux_up, flux_down, u0
|
|
592
|
+
return flux_up, flux_down, u0, G_collect_0, K_collect_0 # TODO: Remove the temporary G_collect_0, K_collect_0
|
|
571
593
|
else:
|
|
572
594
|
return flux_up, flux_down, u0, u
|