PythonicDISORT 0.9.0__py3-none-any.whl → 0.9.1__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 +77 -68
- PythonicDISORT/_solve_for_coeffs.py +104 -182
- PythonicDISORT/_solve_for_gen_and_part_sols.py +42 -34
- PythonicDISORT/pydisort.py +34 -36
- PythonicDISORT/subroutines.py +43 -17
- {PythonicDISORT-0.9.0.dist-info → PythonicDISORT-0.9.1.dist-info}/METADATA +1 -1
- PythonicDISORT-0.9.1.dist-info/RECORD +11 -0
- {PythonicDISORT-0.9.0.dist-info → PythonicDISORT-0.9.1.dist-info}/WHEEL +1 -1
- PythonicDISORT-0.9.0.dist-info/RECORD +0 -11
- {PythonicDISORT-0.9.0.dist-info → PythonicDISORT-0.9.1.dist-info}/LICENSE.md +0 -0
- {PythonicDISORT-0.9.0.dist-info → PythonicDISORT-0.9.1.dist-info}/top_level.txt +0 -0
|
@@ -20,12 +20,12 @@ 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
|
-
|
|
28
|
+
use_banded_solver_NLayers, # Number of layers above or equal which to use `scipy.linalg.solve_banded`
|
|
29
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`
|
|
@@ -66,13 +66,13 @@ 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
|
-
| `
|
|
75
|
+
| `use_banded_solver_NLayers` | scalar |
|
|
76
76
|
| `_autograd_compatible` | boolean |
|
|
77
77
|
|
|
78
78
|
Notable internal variables of _assemble_intensity_and_fluxes
|
|
@@ -146,10 +146,10 @@ def _assemble_intensity_and_fluxes(
|
|
|
146
146
|
there_is_beam_source,
|
|
147
147
|
b_pos, b_neg,
|
|
148
148
|
b_pos_is_scalar, b_neg_is_scalar,
|
|
149
|
-
s_poly_coeffs,
|
|
150
149
|
Nscoeffs,
|
|
150
|
+
s_poly_coeffs,
|
|
151
151
|
there_is_iso_source,
|
|
152
|
-
|
|
152
|
+
use_banded_solver_NLayers,
|
|
153
153
|
)
|
|
154
154
|
|
|
155
155
|
G_collect_0 = G_collect[0, :, :, :]
|
|
@@ -198,26 +198,28 @@ def _assemble_intensity_and_fluxes(
|
|
|
198
198
|
|
|
199
199
|
if is_antiderivative_wrt_tau:
|
|
200
200
|
if there_is_beam_source:
|
|
201
|
-
um =
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
201
|
+
um = (
|
|
202
|
+
np.einsum(
|
|
203
|
+
"mtij, mtj -> mti",
|
|
204
|
+
GC_collect[:, l, :, :],
|
|
205
|
+
np.exp(exponent) / (scale_tau[None, :, None] * K_collect)[:, l, :],
|
|
206
|
+
optimize=True,
|
|
207
|
+
)
|
|
208
|
+
+ (B_collect / (-scale_tau / mu0)[None, :, None])[:, l, :]
|
|
209
|
+
* np.exp(-scaled_tau / mu0)[None, :, None]
|
|
208
210
|
)
|
|
209
211
|
else:
|
|
210
212
|
um = np.einsum(
|
|
211
213
|
"mtij, mtj -> mti",
|
|
212
214
|
GC_collect[:, l, :, :],
|
|
213
|
-
np.exp(exponent) / (scale_tau[None, l, None] * K_collect[:, l, :]
|
|
215
|
+
np.exp(exponent) / (scale_tau[None, l, None] * K_collect)[:, l, :],
|
|
214
216
|
optimize=True,
|
|
215
217
|
)
|
|
216
218
|
else:
|
|
217
219
|
if there_is_beam_source:
|
|
218
220
|
um = np.einsum(
|
|
219
221
|
"mtij, mtj -> mti", GC_collect[:, l, :, :], np.exp(exponent), optimize=True
|
|
220
|
-
) + B_collect[:, l, :] * np.exp(-scaled_tau[None, :, None]
|
|
222
|
+
) + B_collect[:, l, :] * np.exp(-scaled_tau / mu0)[None, :, None]
|
|
221
223
|
else:
|
|
222
224
|
um = np.einsum(
|
|
223
225
|
"mtij, mtj -> mti", GC_collect[:, l, :, :], np.exp(exponent), optimize=True
|
|
@@ -225,13 +227,13 @@ def _assemble_intensity_and_fluxes(
|
|
|
225
227
|
|
|
226
228
|
# Contribution from particular solution for isotropic internal sources
|
|
227
229
|
if there_is_iso_source:
|
|
230
|
+
l_uniq, l_inv = np.unique(l, return_inverse=True)
|
|
228
231
|
_mathscr_v_contribution = _mathscr_v(
|
|
229
|
-
tau,
|
|
230
|
-
s_poly_coeffs,
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
G_inv_collect_0,
|
|
232
|
+
tau, l_inv, Nscoeffs,
|
|
233
|
+
s_poly_coeffs[l_uniq],
|
|
234
|
+
G_collect_0[l_uniq],
|
|
235
|
+
K_collect_0[l_uniq],
|
|
236
|
+
G_inv_collect_0[l_uniq],
|
|
235
237
|
mu_arr,
|
|
236
238
|
is_antiderivative_wrt_tau,
|
|
237
239
|
_autograd_compatible
|
|
@@ -262,26 +264,28 @@ def _assemble_intensity_and_fluxes(
|
|
|
262
264
|
)
|
|
263
265
|
if is_antiderivative_wrt_tau:
|
|
264
266
|
if there_is_beam_source:
|
|
265
|
-
ulast =
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
267
|
+
ulast = (
|
|
268
|
+
np.einsum(
|
|
269
|
+
"tij, tj -> it",
|
|
270
|
+
GC_collect[-1, l, :, :],
|
|
271
|
+
np.exp(exponent) / (scale_tau[:, None] * K_collect[-1, :, :])[l, :],
|
|
272
|
+
optimize=True,
|
|
273
|
+
)
|
|
274
|
+
+ (B_collect.T[-1, :, :] / (-scale_tau / mu0)[None, :])[:, l]
|
|
275
|
+
* np.exp(-scaled_tau / mu0)[None, :]
|
|
272
276
|
)
|
|
273
277
|
else:
|
|
274
278
|
ulast = np.einsum(
|
|
275
279
|
"tij, tj -> it",
|
|
276
280
|
GC_collect[-1, l, :, :],
|
|
277
|
-
np.exp(exponent) / (scale_tau[
|
|
281
|
+
np.exp(exponent) / (scale_tau[:, None] * K_collect[-1, :, :])[l, :],
|
|
278
282
|
optimize=True,
|
|
279
283
|
)
|
|
280
284
|
else:
|
|
281
285
|
if there_is_beam_source:
|
|
282
286
|
ulast = np.einsum(
|
|
283
287
|
"tij, tj -> it", GC_collect[-1, l, :, :], np.exp(exponent), optimize=True
|
|
284
|
-
) + B_collect[-1, l
|
|
288
|
+
) + B_collect.T[-1, :, l] * np.exp(-scaled_tau / mu0)[None, :]
|
|
285
289
|
else:
|
|
286
290
|
ulast = np.einsum(
|
|
287
291
|
"tij, tj -> it", GC_collect[-1, l, :, :], np.exp(exponent), optimize=True
|
|
@@ -333,7 +337,10 @@ def _assemble_intensity_and_fluxes(
|
|
|
333
337
|
# in performing the reclassification of delta-scaled actinic flux
|
|
334
338
|
if _return_act_dscale_for_reclass:
|
|
335
339
|
if is_antiderivative_wrt_tau:
|
|
336
|
-
act_dscale_reclassification =
|
|
340
|
+
act_dscale_reclassification = (
|
|
341
|
+
I0 * np.exp(-scaled_tau / mu0) / (-scale_tau[l] / mu0)
|
|
342
|
+
- I0 * np.exp(-tau / mu0) * -mu0
|
|
343
|
+
)
|
|
337
344
|
else:
|
|
338
345
|
act_dscale_reclassification = I0 * np.exp(-scaled_tau / mu0) - I0 * np.exp(-tau / mu0)
|
|
339
346
|
else:
|
|
@@ -351,26 +358,28 @@ def _assemble_intensity_and_fluxes(
|
|
|
351
358
|
|
|
352
359
|
if is_antiderivative_wrt_tau:
|
|
353
360
|
if there_is_beam_source:
|
|
354
|
-
u0 =
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
+
u0 = (
|
|
362
|
+
np.einsum(
|
|
363
|
+
"tij, tj -> it",
|
|
364
|
+
GC_collect_0[l, :, :],
|
|
365
|
+
np.exp(exponent) / (scale_tau[:, None] * K_collect_0)[l, :],
|
|
366
|
+
optimize=True,
|
|
367
|
+
)
|
|
368
|
+
+ (B_collect_0.T / (-scale_tau / mu0)[None, :])[:, l]
|
|
369
|
+
* np.exp(-scaled_tau / mu0)[None, :]
|
|
361
370
|
)
|
|
362
371
|
else:
|
|
363
372
|
u0 = np.einsum(
|
|
364
373
|
"tij, tj -> it",
|
|
365
374
|
GC_collect_0[l, :, :],
|
|
366
|
-
np.exp(exponent) / (scale_tau[
|
|
375
|
+
np.exp(exponent) / (scale_tau[:, None] * K_collect_0)[l, :],
|
|
367
376
|
optimize=True,
|
|
368
377
|
)
|
|
369
378
|
else:
|
|
370
379
|
if there_is_beam_source:
|
|
371
380
|
u0 = np.einsum(
|
|
372
381
|
"tij, tj -> it", GC_collect_0[l, :, :], np.exp(exponent), optimize=True
|
|
373
|
-
) + B_collect_0[l
|
|
382
|
+
) + B_collect_0.T[:, l] * np.exp(-scaled_tau / mu0)[None, :]
|
|
374
383
|
else:
|
|
375
384
|
u0 = np.einsum(
|
|
376
385
|
"tij, tj -> it", GC_collect_0[l, :, :], np.exp(exponent), optimize=True
|
|
@@ -378,13 +387,13 @@ def _assemble_intensity_and_fluxes(
|
|
|
378
387
|
|
|
379
388
|
# Contribution from particular solution for isotropic internal sources
|
|
380
389
|
if there_is_iso_source:
|
|
390
|
+
l_uniq, l_inv = np.unique(l, return_inverse=True)
|
|
381
391
|
_mathscr_v_contribution = _mathscr_v(
|
|
382
|
-
tau,
|
|
383
|
-
s_poly_coeffs,
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
G_inv_collect_0,
|
|
392
|
+
tau, l_inv, Nscoeffs,
|
|
393
|
+
s_poly_coeffs[l_uniq],
|
|
394
|
+
G_collect_0[l_uniq],
|
|
395
|
+
K_collect_0[l_uniq],
|
|
396
|
+
G_inv_collect_0[l_uniq],
|
|
388
397
|
mu_arr,
|
|
389
398
|
is_antiderivative_wrt_tau,
|
|
390
399
|
_autograd_compatible
|
|
@@ -431,27 +440,27 @@ def _assemble_intensity_and_fluxes(
|
|
|
431
440
|
scaled_tau = tau
|
|
432
441
|
|
|
433
442
|
if there_is_iso_source:
|
|
443
|
+
l_uniq, l_inv = np.unique(l, return_inverse=True)
|
|
434
444
|
_mathscr_v_contribution = _mathscr_v(
|
|
435
|
-
tau,
|
|
436
|
-
s_poly_coeffs,
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
G_inv_collect_0,
|
|
445
|
+
tau, l_inv, Nscoeffs,
|
|
446
|
+
s_poly_coeffs[l_uniq],
|
|
447
|
+
G_collect_0[l_uniq, :N, :],
|
|
448
|
+
K_collect_0[l_uniq],
|
|
449
|
+
G_inv_collect_0[l_uniq],
|
|
441
450
|
mu_arr,
|
|
442
451
|
is_antiderivative_wrt_tau,
|
|
443
452
|
_autograd_compatible
|
|
444
|
-
)
|
|
453
|
+
)
|
|
445
454
|
else:
|
|
446
455
|
_mathscr_v_contribution = 0
|
|
447
456
|
|
|
448
457
|
if there_is_beam_source:
|
|
449
458
|
if is_antiderivative_wrt_tau:
|
|
450
459
|
direct_beam_contribution = (
|
|
451
|
-
B_pos[:, l] * np.exp(-scaled_tau
|
|
460
|
+
(B_pos / (-scale_tau / mu0)[None, :])[:, l] * np.exp(-scaled_tau / mu0)[None, :]
|
|
452
461
|
)
|
|
453
462
|
else:
|
|
454
|
-
direct_beam_contribution = B_pos[:, l] * np.exp(-scaled_tau[None, :]
|
|
463
|
+
direct_beam_contribution = B_pos[:, l] * np.exp(-scaled_tau / mu0)[None, :]
|
|
455
464
|
else:
|
|
456
465
|
direct_beam_contribution = 0
|
|
457
466
|
|
|
@@ -468,7 +477,7 @@ def _assemble_intensity_and_fluxes(
|
|
|
468
477
|
np.einsum(
|
|
469
478
|
"tij, tj -> it",
|
|
470
479
|
GC_pos[l, :, :],
|
|
471
|
-
np.exp(exponent) / (scale_tau[
|
|
480
|
+
np.exp(exponent) / (scale_tau[:, None] * K_collect_0)[l, :],
|
|
472
481
|
)
|
|
473
482
|
+ direct_beam_contribution
|
|
474
483
|
+ _mathscr_v_contribution
|
|
@@ -510,27 +519,27 @@ def _assemble_intensity_and_fluxes(
|
|
|
510
519
|
scaled_tau = tau
|
|
511
520
|
|
|
512
521
|
if there_is_iso_source:
|
|
522
|
+
l_uniq, l_inv = np.unique(l, return_inverse=True)
|
|
513
523
|
_mathscr_v_contribution = _mathscr_v(
|
|
514
|
-
tau,
|
|
515
|
-
s_poly_coeffs,
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
G_inv_collect_0,
|
|
524
|
+
tau, l_inv, Nscoeffs,
|
|
525
|
+
s_poly_coeffs[l_uniq],
|
|
526
|
+
G_collect_0[l_uniq, N:, :],
|
|
527
|
+
K_collect_0[l_uniq],
|
|
528
|
+
G_inv_collect_0[l_uniq],
|
|
520
529
|
mu_arr,
|
|
521
530
|
is_antiderivative_wrt_tau,
|
|
522
531
|
_autograd_compatible
|
|
523
|
-
)
|
|
532
|
+
)
|
|
524
533
|
else:
|
|
525
534
|
_mathscr_v_contribution = 0
|
|
526
535
|
|
|
527
536
|
if there_is_beam_source:
|
|
528
537
|
if is_antiderivative_wrt_tau:
|
|
529
|
-
direct_beam_contribution = B_neg[:, l] * np.exp(-scaled_tau
|
|
538
|
+
direct_beam_contribution = (B_neg / (-scale_tau / mu0)[None, l])[:, l] * np.exp(-scaled_tau / mu0)[None, :]
|
|
530
539
|
direct_beam = I0 * mu0 * np.exp(-tau / mu0) * -mu0
|
|
531
|
-
direct_beam_scaled = I0 * mu0 * np.exp(-scaled_tau / mu0) / (-scale_tau[None, l]
|
|
540
|
+
direct_beam_scaled = I0 * mu0 * np.exp(-scaled_tau / mu0) / (-scale_tau / mu0)[None, l]
|
|
532
541
|
else:
|
|
533
|
-
direct_beam_contribution = B_neg[:, l] * np.exp(-scaled_tau[None, :]
|
|
542
|
+
direct_beam_contribution = B_neg[:, l] * np.exp(-scaled_tau / mu0)[None, :]
|
|
534
543
|
direct_beam = I0 * mu0 * np.exp(-tau / mu0)
|
|
535
544
|
direct_beam_scaled = I0 * mu0 * np.exp(-scaled_tau / mu0)
|
|
536
545
|
else:
|
|
@@ -548,7 +557,7 @@ def _assemble_intensity_and_fluxes(
|
|
|
548
557
|
|
|
549
558
|
if is_antiderivative_wrt_tau:
|
|
550
559
|
u0_neg = (
|
|
551
|
-
np.einsum("tij, tj -> it", GC_neg[l, :, :], np.exp(exponent) / (scale_tau[
|
|
560
|
+
np.einsum("tij, tj -> it", GC_neg[l, :, :], np.exp(exponent) / (scale_tau[:, None] * K_collect_0)[l, :])
|
|
552
561
|
+ direct_beam_contribution
|
|
553
562
|
+ _mathscr_v_contribution
|
|
554
563
|
)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from PythonicDISORT.subroutines import _mathscr_v
|
|
2
|
-
from PythonicDISORT.subroutines import
|
|
2
|
+
from PythonicDISORT.subroutines import to_diag_ordered_form
|
|
3
3
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
import scipy as sc
|
|
@@ -23,10 +23,10 @@ def _solve_for_coeffs(
|
|
|
23
23
|
there_is_beam_source, # Is there a beam source?
|
|
24
24
|
b_pos, b_neg, # Dirichlet BCs
|
|
25
25
|
b_pos_is_scalar, b_neg_is_scalar, # Is each Dirichlet BCs scalar (isotropic)?
|
|
26
|
-
s_poly_coeffs, # Polynomial coefficients of isotropic source
|
|
27
26
|
Nscoeffs, # Number of isotropic source polynomial coefficients
|
|
27
|
+
s_poly_coeffs, # Polynomial coefficients of isotropic source
|
|
28
28
|
there_is_iso_source, # Is there an isotropic source?
|
|
29
|
-
|
|
29
|
+
use_banded_solver_NLayers, # Number of layers above or equal which to use `scipy.linalg.solve_banded`
|
|
30
30
|
):
|
|
31
31
|
"""
|
|
32
32
|
Uses the boundary conditions to solve for the unknown coefficients
|
|
@@ -62,11 +62,11 @@ def _solve_for_coeffs(
|
|
|
62
62
|
| `b_pos` | `NQuad/2 x NFourier` or scalar |
|
|
63
63
|
| `b_neg` | `NQuad/2 x NFourier` or scalar |
|
|
64
64
|
| `b_pos_is_scalar` | boolean |
|
|
65
|
-
| `b_neg_is_scalar` | boolean |
|
|
66
|
-
| `s_poly_coeffs` | `NLayers x Nscoeffs` or `Nscoeffs` |
|
|
65
|
+
| `b_neg_is_scalar` | boolean |
|
|
67
66
|
| `Nscoeffs` | scalar |
|
|
67
|
+
| `s_poly_coeffs` | `NLayers x Nscoeffs` or `Nscoeffs` |
|
|
68
68
|
| `there_is_iso_source` | boolean |
|
|
69
|
-
| `
|
|
69
|
+
| `use_banded_solver_NLayers` | scalar |
|
|
70
70
|
|
|
71
71
|
Notable internal variables of _solve_for_coeffs
|
|
72
72
|
| Variable | Shape |
|
|
@@ -77,13 +77,16 @@ def _solve_for_coeffs(
|
|
|
77
77
|
################################## Solve for coefficients of homogeneous solution ##########################################
|
|
78
78
|
############# Refer to Section 3.6.2 (single-layer) and 4 (multi-layer) of the Comprehensive Documentation #################
|
|
79
79
|
|
|
80
|
+
dim = NLayers * NQuad
|
|
80
81
|
GC_collect = np.empty((NFourier, NLayers, NQuad, NQuad))
|
|
81
|
-
|
|
82
|
+
use_banded_solver = (NLayers >= use_banded_solver_NLayers)
|
|
83
|
+
if use_banded_solver:
|
|
84
|
+
sym_offset = 3 * N - 1
|
|
82
85
|
|
|
83
86
|
# The following loops can easily be parallelized, but the speed-up is unlikely to be worth the overhead
|
|
84
87
|
for m in range(NFourier):
|
|
85
88
|
m_equals_0 = (m == 0)
|
|
86
|
-
BDRF_bool = m
|
|
89
|
+
BDRF_bool = (NBDRF > m)
|
|
87
90
|
|
|
88
91
|
G_collect_m = G_collect[m, :, :, :]
|
|
89
92
|
K_collect_m = K_collect[m, :, :]
|
|
@@ -122,12 +125,12 @@ def _solve_for_coeffs(
|
|
|
122
125
|
b_neg_m = b_neg[:, m]
|
|
123
126
|
|
|
124
127
|
# _mathscr_v_contribution
|
|
125
|
-
if
|
|
128
|
+
if m_equals_0 and there_is_iso_source:
|
|
126
129
|
_mathscr_v_contribution_top = -_mathscr_v(
|
|
127
130
|
np.array([0]),
|
|
128
131
|
np.array([0]),
|
|
129
|
-
s_poly_coeffs[0:1, :],
|
|
130
132
|
Nscoeffs,
|
|
133
|
+
s_poly_coeffs[0:1, :],
|
|
131
134
|
G_collect_m[0:1, N:, :],
|
|
132
135
|
K_collect_m[0:1, :],
|
|
133
136
|
G_inv_collect_0[0:1, :, :],
|
|
@@ -140,22 +143,22 @@ def _solve_for_coeffs(
|
|
|
140
143
|
_mathscr_v_contribution_middle = (
|
|
141
144
|
_mathscr_v(
|
|
142
145
|
tau_arr[:-1],
|
|
143
|
-
indices
|
|
144
|
-
s_poly_coeffs,
|
|
146
|
+
indices,
|
|
145
147
|
Nscoeffs,
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
148
|
+
s_poly_coeffs[indices + 1],
|
|
149
|
+
G_collect_m[indices + 1],
|
|
150
|
+
K_collect_m[indices + 1],
|
|
151
|
+
G_inv_collect_0[indices + 1],
|
|
149
152
|
mu_arr,
|
|
150
153
|
)
|
|
151
154
|
- _mathscr_v(
|
|
152
155
|
tau_arr[:-1],
|
|
153
156
|
indices,
|
|
154
|
-
s_poly_coeffs,
|
|
155
157
|
Nscoeffs,
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
158
|
+
s_poly_coeffs[indices],
|
|
159
|
+
G_collect_m[indices],
|
|
160
|
+
K_collect_m[indices],
|
|
161
|
+
G_inv_collect_0[indices],
|
|
159
162
|
mu_arr,
|
|
160
163
|
)
|
|
161
164
|
).ravel(order='F')
|
|
@@ -163,8 +166,8 @@ def _solve_for_coeffs(
|
|
|
163
166
|
_mathscr_v_contribution_bottom = -_mathscr_v(
|
|
164
167
|
tau_arr[-1:],
|
|
165
168
|
np.array([0]),
|
|
166
|
-
s_poly_coeffs[-1:, :],
|
|
167
169
|
Nscoeffs,
|
|
170
|
+
s_poly_coeffs[-1:, :],
|
|
168
171
|
G_collect_m[-1:, :N, :],
|
|
169
172
|
K_collect_m[-1:, :],
|
|
170
173
|
G_inv_collect_0[-1:, :, :],
|
|
@@ -177,8 +180,8 @@ def _solve_for_coeffs(
|
|
|
177
180
|
@ _mathscr_v(
|
|
178
181
|
tau_arr[-1:],
|
|
179
182
|
np.array([0]),
|
|
180
|
-
s_poly_coeffs[-1:, :],
|
|
181
183
|
Nscoeffs,
|
|
184
|
+
s_poly_coeffs[-1:, :],
|
|
182
185
|
G_collect_m[-1:, N:, :],
|
|
183
186
|
K_collect_m[-1:, :],
|
|
184
187
|
G_inv_collect_0[-1:, :, :],
|
|
@@ -197,41 +200,45 @@ def _solve_for_coeffs(
|
|
|
197
200
|
_mathscr_v_contribution = 0
|
|
198
201
|
|
|
199
202
|
if there_is_beam_source:
|
|
200
|
-
if BDRF_bool:
|
|
201
|
-
BDRF_RHS_contribution = mathscr_X_pos + R @ B_collect_m[-1, N:]
|
|
202
|
-
else:
|
|
203
|
-
BDRF_RHS_contribution = 0
|
|
204
|
-
|
|
205
203
|
RHS_middle = np.array([])
|
|
206
204
|
if is_atmos_multilayered:
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
for l in range(NLayers - 1)
|
|
212
|
-
]
|
|
205
|
+
l_range = np.arange(1, NLayers)
|
|
206
|
+
RHS_middle = (
|
|
207
|
+
(B_collect_m[l_range, :] - B_collect_m[l_range - 1, :])
|
|
208
|
+
* np.exp(-mu0 * scaled_tau_arr_with_0)[l_range, None]
|
|
213
209
|
).ravel()
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
210
|
+
|
|
211
|
+
if BDRF_bool:
|
|
212
|
+
RHS = (
|
|
213
|
+
np.concatenate(
|
|
214
|
+
[
|
|
215
|
+
b_neg_m - B_collect_m[0, N:],
|
|
216
|
+
RHS_middle,
|
|
217
|
+
b_pos_m
|
|
218
|
+
+ (mathscr_X_pos + R @ B_collect_m[-1, N:] - B_collect_m[-1, :N])
|
|
219
|
+
* np.exp(-scaled_tau_arr_with_0[-1] / mu0),
|
|
220
|
+
]
|
|
221
|
+
)
|
|
222
|
+
+ _mathscr_v_contribution
|
|
223
|
+
)
|
|
224
|
+
else:
|
|
225
|
+
RHS = (
|
|
226
|
+
np.concatenate(
|
|
227
|
+
[
|
|
228
|
+
b_neg_m - B_collect_m[0, N:],
|
|
229
|
+
RHS_middle,
|
|
230
|
+
b_pos_m
|
|
231
|
+
- B_collect_m[-1, :N] * np.exp(-scaled_tau_arr_with_0[-1] / mu0),
|
|
232
|
+
]
|
|
233
|
+
)
|
|
234
|
+
+ _mathscr_v_contribution
|
|
224
235
|
)
|
|
225
|
-
+ _mathscr_v_contribution
|
|
226
|
-
)
|
|
227
236
|
else:
|
|
228
237
|
RHS_middle = np.zeros(NQuad * (NLayers - 1))
|
|
229
238
|
RHS = np.concatenate([b_neg_m, RHS_middle, b_pos_m]) + _mathscr_v_contribution
|
|
230
239
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
231
240
|
|
|
232
241
|
# Assemble LHS (much of this code is replicated in Section 4 of the Comprehensive Documentation)
|
|
233
|
-
dim = NLayers * NQuad
|
|
234
|
-
|
|
235
242
|
G_0_nn = G_collect_m[0, N:, :N]
|
|
236
243
|
G_0_np = G_collect_m[0, N:, N:]
|
|
237
244
|
G_L_pn = G_collect_m[-1, :N, :N]
|
|
@@ -241,147 +248,62 @@ def _solve_for_coeffs(
|
|
|
241
248
|
E_Lm1L = np.exp(
|
|
242
249
|
K_collect_m[-1, :N] * (scaled_tau_arr_with_0[-1] - scaled_tau_arr_with_0[-2])
|
|
243
250
|
)
|
|
244
|
-
if m < NBDRF:
|
|
245
|
-
BDRF_LHS_contribution_neg = R @ G_L_nn
|
|
246
|
-
BDRF_LHS_contribution_pos = R @ G_L_np
|
|
247
|
-
else:
|
|
248
|
-
BDRF_LHS_contribution_neg = 0
|
|
249
|
-
BDRF_LHS_contribution_pos = 0
|
|
250
251
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
252
|
+
LHS = np.zeros((dim, dim))
|
|
253
|
+
# BCs for the entire atmosphere
|
|
254
|
+
LHS[:N, :N] = G_0_nn
|
|
255
|
+
LHS[:N, N : NQuad] = (
|
|
256
|
+
G_0_np
|
|
257
|
+
* np.exp(K_collect_m[0, :N] * scaled_tau_arr_with_0[1])[None, :]
|
|
258
|
+
)
|
|
259
|
+
if BDRF_bool:
|
|
260
|
+
LHS[-N:, -NQuad : -N] = (G_L_pn - R @ G_L_nn) * E_Lm1L[None, :]
|
|
261
|
+
LHS[-N:, -N:] = G_L_pp - R @ G_L_np
|
|
262
|
+
else:
|
|
263
|
+
LHS[-N:, -NQuad : -N] = G_L_pn * E_Lm1L[None, :]
|
|
264
|
+
LHS[-N:, -N:] = G_L_pp
|
|
265
|
+
|
|
266
|
+
# Interlayer / continuity BCs
|
|
267
|
+
for l in range(NLayers - 1):
|
|
268
|
+
G_l_pn = G_collect_m[l, :N, :N]
|
|
269
|
+
G_l_nn = G_collect_m[l, N:, :N]
|
|
270
|
+
G_l_ap = G_collect_m[l, :, N:]
|
|
271
|
+
G_lp1_an = G_collect_m[l + 1, :, :N]
|
|
272
|
+
G_lp1_pp = G_collect_m[l + 1, :N, N:]
|
|
273
|
+
G_lp1_np = G_collect_m[l + 1, N:, N:]
|
|
274
|
+
scaled_tau_arr_lm1 = scaled_tau_arr_with_0[l]
|
|
275
|
+
scaled_tau_arr_l = scaled_tau_arr_with_0[l + 1]
|
|
276
|
+
scaled_tau_arr_lp1 = scaled_tau_arr_with_0[l + 2]
|
|
277
|
+
# Postive eigenvalues
|
|
278
|
+
K_l_pos = K_collect_m[l, N:]
|
|
279
|
+
K_lp1_pos = K_collect_m[l + 1, N:]
|
|
280
|
+
E_lm1l = np.exp(K_l_pos * (scaled_tau_arr_lm1 - scaled_tau_arr_l))
|
|
281
|
+
E_llp1 = np.exp(K_lp1_pos * (scaled_tau_arr_l - scaled_tau_arr_lp1))
|
|
257
282
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
283
|
+
start_row = N + l * NQuad
|
|
284
|
+
start_col = l * NQuad
|
|
285
|
+
LHS[start_row : N + start_row, start_col : N + start_col] = G_l_pn * E_lm1l[None, :]
|
|
286
|
+
LHS[N + start_row : 2 * N + start_row, start_col : N + start_col] = G_l_nn * E_lm1l[None, :]
|
|
287
|
+
LHS[start_row : 2 * N + start_row, N + start_col : 2 * N + start_col] = G_l_ap
|
|
288
|
+
LHS[start_row : 2 * N + start_row, 2 * N + start_col : 3 * N + start_col] = -G_lp1_an
|
|
289
|
+
LHS[start_row : N + start_row, 3 * N + start_col : 4 * N + start_col] = -G_lp1_pp * E_llp1[None, :]
|
|
290
|
+
LHS[N + start_row : 2 * N + start_row, 3 * N + start_col : 4 * N + start_col] = -G_lp1_np * E_llp1[None, :]
|
|
261
291
|
|
|
262
|
-
|
|
263
|
-
block_row_sort[N_sq : 2 * N_sq] = block_row_ind[N : 2 * N, :N].ravel()
|
|
264
|
-
block_row_sort[2 * N_sq : 4 * N_sq] = block_row_ind[:2 * N, N : 2 * N].ravel()
|
|
265
|
-
block_row_sort[4 * N_sq : 6 * N_sq] = block_row_ind[:2 * N, 2 * N : 3 * N].ravel()
|
|
266
|
-
block_row_sort[6 * N_sq : 7 * N_sq] = block_row_ind[:N, 3 * N : 4 * N].ravel()
|
|
267
|
-
block_row_sort[7 * N_sq : 8 * N_sq] = block_row_ind[N : 2 * N, 3 * N : 4 * N].ravel()
|
|
268
|
-
|
|
269
|
-
# BCs for the entire atmosphere
|
|
270
|
-
row_indices[:N_sq], col_indices[:N_sq] = _nd_slice_to_indexes(np.s_[:N, :N])
|
|
271
|
-
block_rows[:N_sq] = G_0_nn.ravel()
|
|
272
|
-
(
|
|
273
|
-
row_indices[N_sq : 2 * N_sq],
|
|
274
|
-
col_indices[N_sq : 2 * N_sq],
|
|
275
|
-
) = _nd_slice_to_indexes(np.s_[:N, N:NQuad])
|
|
276
|
-
block_rows[N_sq : 2 * N_sq] = (
|
|
277
|
-
G_0_np * np.exp(K_collect_m[0, :N] * scaled_tau_arr_with_0[1])[None, :]
|
|
278
|
-
).ravel()
|
|
279
|
-
(
|
|
280
|
-
row_indices[2 * N_sq : 3 * N_sq],
|
|
281
|
-
col_indices[2 * N_sq : 3 * N_sq],
|
|
282
|
-
) = _nd_slice_to_indexes(np.s_[dim - N : dim, dim - NQuad : dim - N])
|
|
283
|
-
block_rows[2 * N_sq : 3 * N_sq] = (
|
|
284
|
-
(G_L_pn - BDRF_LHS_contribution_neg) * E_Lm1L[None, :]
|
|
285
|
-
).ravel()
|
|
286
|
-
(
|
|
287
|
-
row_indices[3 * N_sq : 4 * N_sq],
|
|
288
|
-
col_indices[3 * N_sq : 4 * N_sq],
|
|
289
|
-
) = _nd_slice_to_indexes(np.s_[dim - N : dim, dim - N : dim])
|
|
290
|
-
block_rows[3 * N_sq : 4 * N_sq] = (
|
|
291
|
-
G_L_pp - BDRF_LHS_contribution_pos
|
|
292
|
-
).ravel()
|
|
293
|
-
|
|
294
|
-
# Interlayer / continuity BCs
|
|
295
|
-
for l in range(NLayers - 1):
|
|
296
|
-
G_l_pn = G_collect_m[l, :N, :N]
|
|
297
|
-
G_l_nn = G_collect_m[l, N:, :N]
|
|
298
|
-
G_l_ap = G_collect_m[l, :, N:]
|
|
299
|
-
G_lp1_an = G_collect_m[l + 1, :, :N]
|
|
300
|
-
G_lp1_pp = G_collect_m[l + 1, :N, N:]
|
|
301
|
-
G_lp1_np = G_collect_m[l + 1, N:, N:]
|
|
302
|
-
scaled_tau_arr_lm1 = scaled_tau_arr_with_0[l]
|
|
303
|
-
scaled_tau_arr_l = scaled_tau_arr_with_0[l + 1]
|
|
304
|
-
scaled_tau_arr_lp1 = scaled_tau_arr_with_0[l + 2]
|
|
305
|
-
# Postive eigenvalues
|
|
306
|
-
K_l_pos = K_collect_m[l, N:]
|
|
307
|
-
K_lp1_pos = K_collect_m[l + 1, N:]
|
|
308
|
-
E_lm1l = np.exp(K_l_pos * (scaled_tau_arr_lm1 - scaled_tau_arr_l))
|
|
309
|
-
E_llp1 = np.exp(K_lp1_pos * (scaled_tau_arr_l - scaled_tau_arr_lp1))
|
|
310
|
-
|
|
311
|
-
row_indices_l, col_indices_l = _nd_slice_to_indexes(
|
|
312
|
-
np.s_[N + l * NQuad : N + (l + 1) * NQuad, l * NQuad : (l + 2) * NQuad]
|
|
313
|
-
)
|
|
314
|
-
row_indices[
|
|
315
|
-
4 * N_sq + l * block_row_len : 4 * N_sq + (l + 1) * block_row_len
|
|
316
|
-
] = row_indices_l[block_row_sort]
|
|
317
|
-
col_indices[
|
|
318
|
-
4 * N_sq + l * block_row_len : 4 * N_sq + (l + 1) * block_row_len
|
|
319
|
-
] = col_indices_l[block_row_sort]
|
|
320
|
-
|
|
321
|
-
start_ind = 4 * N_sq + l * block_row_len
|
|
322
|
-
block_rows[start_ind : N_sq + start_ind] = (G_l_pn * E_lm1l[None, :]).ravel()
|
|
323
|
-
block_rows[start_ind + N_sq : 2 * N_sq + start_ind] = (G_l_nn * E_lm1l[None, :]).ravel()
|
|
324
|
-
block_rows[start_ind + 2 * N_sq : 4 * N_sq + start_ind] = G_l_ap.ravel()
|
|
325
|
-
block_rows[start_ind + 4 * N_sq : 6 * N_sq + start_ind] = -G_lp1_an.ravel()
|
|
326
|
-
block_rows[start_ind + 6 * N_sq : 7 * N_sq + start_ind] = -(G_lp1_pp * E_llp1[None, :]).ravel()
|
|
327
|
-
block_rows[start_ind + 7 * N_sq : 8 * N_sq + start_ind] = -(G_lp1_np * E_llp1[None, :]).ravel()
|
|
328
|
-
|
|
329
|
-
LHS = sc.sparse.coo_matrix(
|
|
330
|
-
(
|
|
331
|
-
block_rows,
|
|
332
|
-
(
|
|
333
|
-
row_indices,
|
|
334
|
-
col_indices,
|
|
335
|
-
),
|
|
336
|
-
),
|
|
337
|
-
shape=(dim, dim),
|
|
338
|
-
)
|
|
339
|
-
|
|
340
|
-
# Solve the system
|
|
341
|
-
C_m = sc.sparse.linalg.spsolve(LHS.tocsr(), RHS).reshape(NLayers, NQuad)
|
|
292
|
+
# --------------------------------------------------------------------------------------------------------------------------
|
|
342
293
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
294
|
+
# Solve the system
|
|
295
|
+
if use_banded_solver:
|
|
296
|
+
C_m = sc.linalg.solve_banded(
|
|
297
|
+
(sym_offset, sym_offset),
|
|
298
|
+
to_diag_ordered_form(LHS, sym_offset),
|
|
299
|
+
RHS,
|
|
300
|
+
True,
|
|
301
|
+
True,
|
|
302
|
+
False,
|
|
351
303
|
)
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
# Interlayer / continuity BCs
|
|
356
|
-
for l in range(NLayers - 1):
|
|
357
|
-
G_l_pn = G_collect_m[l, :N, :N]
|
|
358
|
-
G_l_nn = G_collect_m[l, N:, :N]
|
|
359
|
-
G_l_ap = G_collect_m[l, :, N:]
|
|
360
|
-
G_lp1_an = G_collect_m[l + 1, :, :N]
|
|
361
|
-
G_lp1_pp = G_collect_m[l + 1, :N, N:]
|
|
362
|
-
G_lp1_np = G_collect_m[l + 1, N:, N:]
|
|
363
|
-
scaled_tau_arr_lm1 = scaled_tau_arr_with_0[l]
|
|
364
|
-
scaled_tau_arr_l = scaled_tau_arr_with_0[l + 1]
|
|
365
|
-
scaled_tau_arr_lp1 = scaled_tau_arr_with_0[l + 2]
|
|
366
|
-
# Postive eigenvalues
|
|
367
|
-
K_l_pos = K_collect_m[l, N:]
|
|
368
|
-
K_lp1_pos = K_collect_m[l + 1, N:]
|
|
369
|
-
E_lm1l = np.exp(K_l_pos * (scaled_tau_arr_lm1 - scaled_tau_arr_l))
|
|
370
|
-
E_llp1 = np.exp(K_lp1_pos * (scaled_tau_arr_l - scaled_tau_arr_lp1))
|
|
371
|
-
|
|
372
|
-
start_row = N + l * NQuad
|
|
373
|
-
start_col = l * NQuad
|
|
374
|
-
LHS[start_row : N + start_row, start_col : N + start_col] = G_l_pn * E_lm1l[None, :]
|
|
375
|
-
LHS[N + start_row : 2 * N + start_row, start_col : N + start_col] = G_l_nn * E_lm1l[None, :]
|
|
376
|
-
LHS[start_row : 2 * N + start_row, N + start_col : 2 * N + start_col] = G_l_ap
|
|
377
|
-
LHS[start_row : 2 * N + start_row, 2 * N + start_col : 3 * N + start_col] = -G_lp1_an
|
|
378
|
-
LHS[start_row : N + start_row, 3 * N + start_col : 4 * N + start_col] = -G_lp1_pp * E_llp1[None, :]
|
|
379
|
-
LHS[N + start_row : 2 * N + start_row, 3 * N + start_col : 4 * N + start_col] = -G_lp1_np * E_llp1[None, :]
|
|
380
|
-
|
|
381
|
-
# Solve the system
|
|
382
|
-
C_m = np.linalg.solve(LHS, RHS).reshape(NLayers, NQuad)
|
|
383
|
-
# --------------------------------------------------------------------------------------------------------------------------
|
|
304
|
+
else:
|
|
305
|
+
C_m = np.linalg.solve(LHS, RHS)
|
|
384
306
|
|
|
385
|
-
GC_collect[m, :, :, :] = G_collect_m * C_m[:, None, :]
|
|
307
|
+
GC_collect[m, :, :, :] = G_collect_m * C_m.reshape(NLayers, NQuad)[:, None, :]
|
|
386
308
|
|
|
387
309
|
return GC_collect
|
|
@@ -53,7 +53,6 @@ def _solve_for_gen_and_part_sols(
|
|
|
53
53
|
| `K_collect` | `NFourier*NLayers x NQuad` | Reshaped to NFourier x NLayers x NQuad
|
|
54
54
|
| `alpha_arr` | `NFourier*NLayers x NQuad/2 x NQuad/2` | Reshaped to NFourier x NLayers x NQuad/2 x NQuad/2
|
|
55
55
|
| `beta_arr` | `NFourier*NLayers x NQuad/2 x NQuad/2` | Reshaped to NFourier x NLayers x NQuad/2 x NQuad/2
|
|
56
|
-
| `X_tilde_arr` | `NFourier*NLayers x NQuad` | Reshaped to NFourier x NLayers x NQuad
|
|
57
56
|
| `B_collect` | `NFourier*NLayers x NQuad` or `None` | Reshaped to NFourier x NLayers x NQuad
|
|
58
57
|
| `eigenvecs_GpG_arr` | `NFourier*NLayers x NQuad/2 x NQuad |
|
|
59
58
|
| `eigenvecs_GmG_arr` | `NFourier*NLayers x NQuad/2 x NQuad |
|
|
@@ -72,7 +71,6 @@ def _solve_for_gen_and_part_sols(
|
|
|
72
71
|
K_collect = np.empty((NFourier * NLayers, NQuad))
|
|
73
72
|
alpha_arr = np.empty((NFourier * NLayers, N, N))
|
|
74
73
|
beta_arr = np.empty((NFourier * NLayers, N, N))
|
|
75
|
-
X_tilde_arr = np.empty((NFourier * NLayers, NQuad))
|
|
76
74
|
no_shortcut_indices = []
|
|
77
75
|
no_shortcut_indices_0 = []
|
|
78
76
|
|
|
@@ -103,21 +101,35 @@ def _solve_for_gen_and_part_sols(
|
|
|
103
101
|
# Loop over NLayers atmospheric layers
|
|
104
102
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
105
103
|
for l in range(NLayers):
|
|
106
|
-
# More setup
|
|
107
104
|
weighted_asso_Leg_coeffs_l = weighted_scaled_Leg_coeffs[l, :][ells] * fac
|
|
108
|
-
scaled_omega_l = scaled_omega_arr[l]
|
|
109
105
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
np.isfinite(asso_leg_term_pos)
|
|
106
|
+
if np.any(weighted_asso_Leg_coeffs_l > 0) and np.all( # Due to `fac` or the coeffs being zero
|
|
107
|
+
np.isfinite(asso_leg_term_pos) # We take precautions against overflow and underflow (this shouldn't happen though)
|
|
113
108
|
):
|
|
114
|
-
|
|
109
|
+
scaled_omega_l = scaled_omega_arr[l]
|
|
110
|
+
|
|
111
|
+
# Generate D
|
|
115
112
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
116
113
|
D_temp = weighted_asso_Leg_coeffs_l[None, :] * asso_leg_term_pos.T
|
|
117
114
|
D_pos = (scaled_omega_l / 2) * D_temp @ asso_leg_term_pos
|
|
118
115
|
D_neg = (scaled_omega_l / 2) * D_temp @ asso_leg_term_neg
|
|
116
|
+
|
|
117
|
+
# --------------------------------------------------------------------------------------------------------------------------
|
|
118
|
+
|
|
119
119
|
|
|
120
|
+
# Assemble the coefficient matrix and additional terms
|
|
121
|
+
# --------------------------------------------------------------------------------------------------------------------------
|
|
122
|
+
DW = D_pos * W[None, :]
|
|
123
|
+
np.fill_diagonal(DW, np.diag(DW) - 1)
|
|
124
|
+
alpha = M_inv[:, None] * DW
|
|
125
|
+
beta = M_inv[:, None] * D_neg * W[None, :]
|
|
126
|
+
|
|
127
|
+
# --------------------------------------------------------------------------------------------------------------------------
|
|
128
|
+
|
|
129
|
+
# Particular solution for the direct beam source (refer to Section 3.6.1 of the Comprehensive Documentation)
|
|
130
|
+
# --------------------------------------------------------------------------------------------------------------------------
|
|
120
131
|
if there_is_beam_source:
|
|
132
|
+
# Generate X
|
|
121
133
|
X_temp = (
|
|
122
134
|
(scaled_omega_l * I0 * (2 - (m == 0)) / (4 * pi))
|
|
123
135
|
* weighted_asso_Leg_coeffs_l
|
|
@@ -125,32 +137,38 @@ def _solve_for_gen_and_part_sols(
|
|
|
125
137
|
)
|
|
126
138
|
X_pos = X_temp @ asso_leg_term_pos
|
|
127
139
|
X_neg = X_temp @ asso_leg_term_neg
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
140
|
+
X_tilde = np.concatenate([-M_inv * X_pos, M_inv * X_neg])
|
|
141
|
+
|
|
142
|
+
A = np.concatenate(
|
|
143
|
+
[
|
|
144
|
+
np.concatenate([-alpha, -beta], axis=1),
|
|
145
|
+
np.concatenate([beta, alpha], axis=1),
|
|
146
|
+
],
|
|
147
|
+
axis=0,
|
|
148
|
+
)
|
|
149
|
+
np.fill_diagonal(A, np.diag(A) + 1 / mu0)
|
|
150
|
+
B_collect[ind, :] = -np.linalg.solve(A, X_tilde) # We moved the minus sign out
|
|
151
|
+
|
|
136
152
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
137
153
|
|
|
154
|
+
|
|
138
155
|
alpha_arr[ind, :, :] = alpha
|
|
139
156
|
beta_arr[ind, :, :] = beta
|
|
140
157
|
no_shortcut_indices.append(ind)
|
|
141
|
-
if
|
|
158
|
+
if m_equals_0 and there_is_iso_source:
|
|
142
159
|
no_shortcut_indices_0.append(l)
|
|
143
160
|
|
|
144
161
|
else:
|
|
145
162
|
# This is a shortcut to the diagonalization results
|
|
146
163
|
G = np.zeros((NQuad, NQuad))
|
|
147
|
-
G[N:, :N]
|
|
148
|
-
G[:N, N:]
|
|
164
|
+
np.fill_diagonal(G[N:, :N], 1)
|
|
165
|
+
np.fill_diagonal(G[:N, N:], 1)
|
|
149
166
|
|
|
150
167
|
G_collect[ind, :, :] = G
|
|
151
168
|
K_collect[ind, :] = -1 / mu_arr
|
|
152
|
-
if
|
|
169
|
+
if m_equals_0 and there_is_iso_source:
|
|
153
170
|
G_inv_collect_0[l, :, :] = G
|
|
171
|
+
|
|
154
172
|
ind += 1
|
|
155
173
|
|
|
156
174
|
if len(no_shortcut_indices) > 0:
|
|
@@ -184,26 +202,16 @@ def _solve_for_gen_and_part_sols(
|
|
|
184
202
|
),
|
|
185
203
|
axis=1,
|
|
186
204
|
)
|
|
187
|
-
G_inv_arr = np.linalg.inv(G_arr)
|
|
188
205
|
|
|
189
206
|
G_collect[no_shortcut_indices, :, :] = G_arr
|
|
190
207
|
K_collect[no_shortcut_indices, :] = K_arr
|
|
191
208
|
if len(no_shortcut_indices_0) > 0:
|
|
192
|
-
G_inv_collect_0[no_shortcut_indices_0, :, :] =
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
# Particular solution for the direct beam source (refer to Section 3.6.1 of the Comprehensive Documentation)
|
|
196
|
-
# --------------------------------------------------------------------------------------------------------------------------
|
|
197
|
-
if there_is_beam_source:
|
|
198
|
-
X_tilde_arr = X_tilde_arr[: len(no_shortcut_indices), :]
|
|
199
|
-
B_collect[no_shortcut_indices, :] = np.einsum(
|
|
200
|
-
"lij, ljk, lk -> li",
|
|
201
|
-
-G_arr / (1 / mu0 + K_arr)[:, None, :],
|
|
202
|
-
G_inv_arr,
|
|
203
|
-
X_tilde_arr,
|
|
204
|
-
optimize=True,
|
|
209
|
+
G_inv_collect_0[no_shortcut_indices_0, :, :] = np.linalg.inv(
|
|
210
|
+
G_collect[: len(no_shortcut_indices_0), :, :]
|
|
205
211
|
)
|
|
212
|
+
|
|
206
213
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
214
|
+
|
|
207
215
|
|
|
208
216
|
if there_is_beam_source:
|
|
209
217
|
if there_is_iso_source:
|
PythonicDISORT/pydisort.py
CHANGED
|
@@ -22,7 +22,7 @@ def pydisort(
|
|
|
22
22
|
NT_cor=False,
|
|
23
23
|
BDRF_Fourier_modes=[],
|
|
24
24
|
s_poly_coeffs=np.array([[]]),
|
|
25
|
-
|
|
25
|
+
use_banded_solver_NLayers=13,
|
|
26
26
|
_autograd_compatible = False,
|
|
27
27
|
):
|
|
28
28
|
"""Solves the 1D RTE for the fluxes, and optionally intensity,
|
|
@@ -75,8 +75,8 @@ def pydisort(
|
|
|
75
75
|
s_poly_coeffs : optional, array
|
|
76
76
|
Polynomial coefficients of isotropic internal sources.
|
|
77
77
|
Arrange coefficients from lowest order term to highest.
|
|
78
|
-
|
|
79
|
-
At or above how many atmospheric layers should
|
|
78
|
+
use_banded_solver_NLayers : optional, int
|
|
79
|
+
At or above how many atmospheric layers should `scipy.linalg.solve_banded` be used?
|
|
80
80
|
|
|
81
81
|
Returns
|
|
82
82
|
-------
|
|
@@ -115,25 +115,25 @@ def pydisort(
|
|
|
115
115
|
|
|
116
116
|
"""
|
|
117
117
|
Arguments of pydisort
|
|
118
|
-
|
|
|
119
|
-
|
|
|
120
|
-
| `tau_arr`
|
|
121
|
-
| `omega_arr`
|
|
122
|
-
| `NQuad`
|
|
123
|
-
| `Leg_coeffs_all`
|
|
124
|
-
| `mu0`
|
|
125
|
-
| `I0`
|
|
126
|
-
| `phi0`
|
|
127
|
-
| `NLeg`
|
|
128
|
-
| `NFourier`
|
|
129
|
-
| `b_pos`
|
|
130
|
-
| `b_neg`
|
|
131
|
-
| `only_flux`
|
|
132
|
-
| `f_arr`
|
|
133
|
-
| `NT_cor`
|
|
134
|
-
| `BDRF_Fourier_modes`
|
|
135
|
-
| `s_poly_coeffs`
|
|
136
|
-
| `
|
|
118
|
+
| Variable | Type / Shape |
|
|
119
|
+
| --------------------------- | ---------------------------------- |
|
|
120
|
+
| `tau_arr` | `NLayers` |
|
|
121
|
+
| `omega_arr` | `NLayers` |
|
|
122
|
+
| `NQuad` | scalar |
|
|
123
|
+
| `Leg_coeffs_all` | `NLeg_all` |
|
|
124
|
+
| `mu0` | scalar |
|
|
125
|
+
| `I0` | scalar |
|
|
126
|
+
| `phi0` | scalar |
|
|
127
|
+
| `NLeg` | scalar |
|
|
128
|
+
| `NFourier` | scalar |
|
|
129
|
+
| `b_pos` | `NQuad/2 x NFourier` or scalar |
|
|
130
|
+
| `b_neg` | `NQuad/2 x NFourier` or scalar |
|
|
131
|
+
| `only_flux` | boolean |
|
|
132
|
+
| `f_arr` | `NLayers` or scalar |
|
|
133
|
+
| `NT_cor` | boolean |
|
|
134
|
+
| `BDRF_Fourier_modes` | `NBDRF` |
|
|
135
|
+
| `s_poly_coeffs` | `NLayers x Nscoeffs` or `Nscoeffs` |
|
|
136
|
+
| `use_banded_solver_NLayers` | scalar |
|
|
137
137
|
|
|
138
138
|
Notable internal variables of pydisort
|
|
139
139
|
| Variable | Type / Shape |
|
|
@@ -190,7 +190,7 @@ def pydisort(
|
|
|
190
190
|
NLayers = len(tau_arr)
|
|
191
191
|
b_pos_is_scalar = False
|
|
192
192
|
b_neg_is_scalar = False
|
|
193
|
-
thickness_arr = np.
|
|
193
|
+
thickness_arr = np.append(tau_arr[0], np.diff(tau_arr))
|
|
194
194
|
NLeg_all = np.shape(Leg_coeffs_all)[1]
|
|
195
195
|
N = NQuad // 2
|
|
196
196
|
there_is_beam_source = I0 > 0
|
|
@@ -243,8 +243,8 @@ def pydisort(
|
|
|
243
243
|
assert np.shape(b_neg) == (N, NFourier)
|
|
244
244
|
# The fractional scattering must be between 0 and 1
|
|
245
245
|
assert np.all(0 <= f_arr) and np.all(f_arr <= 1)
|
|
246
|
-
# The minimum threshold is the
|
|
247
|
-
assert(
|
|
246
|
+
# The minimum threshold is 3 else the matrix will not be banded
|
|
247
|
+
assert(use_banded_solver_NLayers >= 3)
|
|
248
248
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
249
249
|
|
|
250
250
|
# Some more setup
|
|
@@ -277,9 +277,7 @@ def pydisort(
|
|
|
277
277
|
if np.any(f_arr > 0):
|
|
278
278
|
scale_tau = 1 - omega_arr * f_arr
|
|
279
279
|
scaled_thickness_arr = scale_tau * thickness_arr
|
|
280
|
-
scaled_tau_arr_with_0 = np.
|
|
281
|
-
list(map(lambda l: np.sum(scaled_thickness_arr[:l]), range(NLayers + 1)))
|
|
282
|
-
)
|
|
280
|
+
scaled_tau_arr_with_0 = np.append(0, np.cumsum(scaled_thickness_arr))
|
|
283
281
|
weighted_scaled_Leg_coeffs = ((Leg_coeffs - f_arr[:, None]) / (1 - f_arr[:, None])) * (
|
|
284
282
|
2 * np.arange(NLeg) + 1
|
|
285
283
|
)[None, :]
|
|
@@ -287,7 +285,7 @@ def pydisort(
|
|
|
287
285
|
else:
|
|
288
286
|
# This is a shortcut to the same results
|
|
289
287
|
scale_tau = np.ones(NLayers)
|
|
290
|
-
scaled_tau_arr_with_0 = np.
|
|
288
|
+
scaled_tau_arr_with_0 = np.append(0, tau_arr)
|
|
291
289
|
weighted_scaled_Leg_coeffs = Leg_coeffs * (2 * np.arange(NLeg) + 1)[None, :]
|
|
292
290
|
scaled_omega_arr = omega_arr
|
|
293
291
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
@@ -313,12 +311,12 @@ def pydisort(
|
|
|
313
311
|
there_is_beam_source,
|
|
314
312
|
b_pos, b_neg,
|
|
315
313
|
b_pos_is_scalar, b_neg_is_scalar,
|
|
316
|
-
s_poly_coeffs,
|
|
317
314
|
Nscoeffs,
|
|
315
|
+
s_poly_coeffs,
|
|
318
316
|
there_is_iso_source,
|
|
319
317
|
scale_tau,
|
|
320
318
|
only_flux,
|
|
321
|
-
|
|
319
|
+
use_banded_solver_NLayers,
|
|
322
320
|
_autograd_compatible,
|
|
323
321
|
)
|
|
324
322
|
|
|
@@ -371,14 +369,14 @@ def pydisort(
|
|
|
371
369
|
|
|
372
370
|
if is_antiderivative_wrt_tau:
|
|
373
371
|
TMS_correction_pos = (
|
|
374
|
-
np.exp(-scaled_tau / mu0)[None, :] / (-scale_tau[None, l]
|
|
372
|
+
np.exp(-scaled_tau / mu0)[None, :] / (-scale_tau / mu0)[None, l]
|
|
375
373
|
- np.exp(
|
|
376
374
|
(scaled_tau - scaled_tau_arr_l)[None, :] / mu_arr_pos[:, None]
|
|
377
375
|
- scaled_tau_arr_l[None, :] / mu0
|
|
378
376
|
) / (scale_tau[None, l] / mu_arr_pos[:, None])
|
|
379
377
|
)
|
|
380
378
|
TMS_correction_neg = (
|
|
381
|
-
np.exp(-scaled_tau / mu0)[None, :] / (-scale_tau[None, l]
|
|
379
|
+
np.exp(-scaled_tau / mu0)[None, :] / (-scale_tau / mu0)[None, l]
|
|
382
380
|
- np.exp(
|
|
383
381
|
(scaled_tau_arr_lm1 - scaled_tau)[None, :] / mu_arr_pos[:, None]
|
|
384
382
|
- scaled_tau_arr_lm1[None, :] / mu0
|
|
@@ -501,7 +499,7 @@ def pydisort(
|
|
|
501
499
|
- scaled_tau_arr_with_0_l_repeat_neg / mu0
|
|
502
500
|
)
|
|
503
501
|
)
|
|
504
|
-
/ (-
|
|
502
|
+
/ (-scale_tau_repeat_neg / mu_arr_pos[:, None])
|
|
505
503
|
)[:, :, None]
|
|
506
504
|
)
|
|
507
505
|
contribution_from_other_layers_neg = np.sum(
|
|
@@ -637,11 +635,11 @@ def pydisort(
|
|
|
637
635
|
there_is_beam_source,
|
|
638
636
|
b_pos, b_neg,
|
|
639
637
|
b_pos_is_scalar, b_neg_is_scalar,
|
|
640
|
-
s_poly_coeffs,
|
|
641
638
|
Nscoeffs,
|
|
639
|
+
s_poly_coeffs,
|
|
642
640
|
there_is_iso_source,
|
|
643
641
|
scale_tau,
|
|
644
642
|
only_flux,
|
|
645
|
-
|
|
643
|
+
use_banded_solver_NLayers,
|
|
646
644
|
_autograd_compatible,
|
|
647
645
|
)
|
PythonicDISORT/subroutines.py
CHANGED
|
@@ -136,7 +136,7 @@ def Clenshaw_Curtis_quad(Nphi, c=0, d=(2 * pi)):
|
|
|
136
136
|
Nphi_pos = Nphi // 2
|
|
137
137
|
phi_arr_pos = np.cos(pi * np.arange(Nphi_pos) / Nphi)
|
|
138
138
|
phi_arr = np.concatenate([-phi_arr_pos, [0], np.flip(phi_arr_pos)])
|
|
139
|
-
diff = np.
|
|
139
|
+
diff = np.append(2, 2 / (1 - 4 * np.arange(1, Nphi_pos + 1) ** 2))
|
|
140
140
|
weights_phi_pos = sc.fft.idct(diff, type=1)
|
|
141
141
|
weights_phi_pos[0] /= 2
|
|
142
142
|
full_weights_phi = np.hstack((weights_phi_pos, np.flip(weights_phi_pos[:-1])))
|
|
@@ -320,12 +320,47 @@ def interpolate(mu_arr_pos, u):
|
|
|
320
320
|
return np.squeeze(results)[()]
|
|
321
321
|
|
|
322
322
|
return u_interpol
|
|
323
|
-
|
|
323
|
+
|
|
324
324
|
|
|
325
|
+
def to_diag_ordered_form(A, sym_offset):
|
|
326
|
+
"""
|
|
327
|
+
Convert a matrix A to the diagonal ordered form required by `scipy.linalg.solve_banded`.
|
|
328
|
+
We assume that the matrix has the same number of super- and sub-diagonals.
|
|
329
|
+
|
|
330
|
+
Parameters
|
|
331
|
+
----------
|
|
332
|
+
A : 2darray
|
|
333
|
+
The square matrix to be converted.
|
|
334
|
+
sym_offset : int
|
|
335
|
+
The number of super- or sub-diagonals (assumed to be equal)
|
|
336
|
+
|
|
337
|
+
Returns
|
|
338
|
+
-------
|
|
339
|
+
2darray
|
|
340
|
+
The diagonal ordered form matrix as required by solve_banded.
|
|
341
|
+
"""
|
|
342
|
+
n = A.shape[0]
|
|
343
|
+
indices = np.arange(n)
|
|
344
|
+
|
|
345
|
+
return np.concatenate(
|
|
346
|
+
[
|
|
347
|
+
A[
|
|
348
|
+
indices - np.arange(sym_offset, -1, -1)[:, None],
|
|
349
|
+
indices[None, :],
|
|
350
|
+
],
|
|
351
|
+
A[
|
|
352
|
+
indices - np.arange(n - 1, n - sym_offset - 1, -1)[:, None],
|
|
353
|
+
indices[None, :],
|
|
354
|
+
],
|
|
355
|
+
],
|
|
356
|
+
axis=0,
|
|
357
|
+
)
|
|
358
|
+
|
|
359
|
+
|
|
325
360
|
def _mathscr_v(tau, # Input optical depths
|
|
326
361
|
l, # Layer index of each input optical depth
|
|
327
|
-
s_poly_coeffs, # Polynomial coefficients of isotropic source
|
|
328
362
|
Nscoeffs, # Number of isotropic source polynomial coefficients
|
|
363
|
+
s_poly_coeffs, # Polynomial coefficients of isotropic source
|
|
329
364
|
G, # Eigenvector matrices
|
|
330
365
|
K, # Eigenvalues
|
|
331
366
|
G_inv, # Inverse of eigenvector matrix
|
|
@@ -344,6 +379,7 @@ def _mathscr_v(tau, # Input optical depths
|
|
|
344
379
|
| --------------------------- | ------------------------------------- |
|
|
345
380
|
| `tau` | `Ntau` |
|
|
346
381
|
| `l` | `Ntau` |
|
|
382
|
+
| `Nscoeffs` | scalar |
|
|
347
383
|
| `s_poly_coeffs` | `NLayers x Nscoeffs` or `Nscoeffs` |
|
|
348
384
|
| `G` | `NLayers<= x NQuad x NQuad` |
|
|
349
385
|
| `K` | `NLayers<= x NQuad` |
|
|
@@ -409,30 +445,20 @@ def _mathscr_v(tau, # Input optical depths
|
|
|
409
445
|
),
|
|
410
446
|
)
|
|
411
447
|
|
|
412
|
-
powers = np.
|
|
448
|
+
powers = np.arange(Nscoeffs - 1, -1, -1)[None, :]
|
|
413
449
|
if is_antiderivative_wrt_tau:
|
|
414
450
|
tau_poly = tau[:, None] ** (powers + 1) / (powers + 1)
|
|
415
451
|
else:
|
|
416
452
|
tau_poly = tau[:, None] ** powers
|
|
417
|
-
|
|
453
|
+
|
|
418
454
|
return np.einsum(
|
|
419
|
-
"tik, tc, ctk
|
|
455
|
+
"tik, tc, ctk -> it",
|
|
420
456
|
G[l, :, :],
|
|
421
457
|
tau_poly,
|
|
422
|
-
mathscr_v_coeffs[:, l, :],
|
|
423
|
-
G_inv[l, :, :],
|
|
424
|
-
1 / mu_arr,
|
|
458
|
+
(mathscr_v_coeffs * (G_inv @ (1 / mu_arr))[None, :, :])[:, l, :],
|
|
425
459
|
optimize=True,
|
|
426
460
|
)
|
|
427
461
|
|
|
428
|
-
def _nd_slice_to_indexes(nd_slice):
|
|
429
|
-
"""Code taken from https://stackoverflow.com/questions/64097025/how-to-convert-n-d-slice-to-indexes-in-numpy.
|
|
430
|
-
This function is used to efficiently construct sparse COO matrices.
|
|
431
|
-
|
|
432
|
-
"""
|
|
433
|
-
grid = np.mgrid[{tuple: nd_slice, slice: (nd_slice,)}[type(nd_slice)]]
|
|
434
|
-
return tuple(grid[i].ravel() for i in range(grid.shape[0]))
|
|
435
|
-
|
|
436
462
|
|
|
437
463
|
def _compare(results, mu_to_compare, reorder_mu, flux_up, flux_down, u):
|
|
438
464
|
"""Performs pointwise comparisons between results from Stamnes' DISORT,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PythonicDISORT
|
|
3
|
-
Version: 0.9.
|
|
3
|
+
Version: 0.9.1
|
|
4
4
|
Summary: Discrete Ordinates Solver for the (1D) Radiative Transfer Equation in a single or multi-layer atmosphere.
|
|
5
5
|
Author-email: Dion HO Jia Xu <dh3065@columbia.edu>
|
|
6
6
|
Project-URL: Homepage, https://github.com/LDEO-CREW/Pythonic-DISORT
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
PythonicDISORT/__init__.py,sha256=V1obNzaFgqInxqYJ5h_r6JHbZRxx4VM5VgzCIS6EEzI,84
|
|
2
|
+
PythonicDISORT/_assemble_intensity_and_fluxes.py,sha256=j3w78Y8844HlI1z8JFmOgNs4ogDsma8VySbI8W2-m-8,27868
|
|
3
|
+
PythonicDISORT/_solve_for_coeffs.py,sha256=UccDeCrr0jBCKbK73Eq9SwWEkSkjVyAVheew6nYcWdw,15368
|
|
4
|
+
PythonicDISORT/_solve_for_gen_and_part_sols.py,sha256=MNNg5f4S5XY0D6btH3D-9p-eye9M_rT7GUlaHnys7Ts,13138
|
|
5
|
+
PythonicDISORT/pydisort.py,sha256=SNpTpEcRPHNZqnVL86xV5AzPPNu7AVgmpXhV6a5Rqh8,33204
|
|
6
|
+
PythonicDISORT/subroutines.py,sha256=on0VpAtUc8b7ysaQqy8VetSnTMhsE_yEDAwyRHX2IuU,20049
|
|
7
|
+
PythonicDISORT-0.9.1.dist-info/LICENSE.md,sha256=q1i1QVh0OLzK0fj6kaNRNWsM_KZca66JwWgWwbuCPlA,1092
|
|
8
|
+
PythonicDISORT-0.9.1.dist-info/METADATA,sha256=SLwWEGhdEqHtpHNN14-Y0Kd2tvIYByXubdqzpr1nqKc,7102
|
|
9
|
+
PythonicDISORT-0.9.1.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
|
10
|
+
PythonicDISORT-0.9.1.dist-info/top_level.txt,sha256=aX6kCeI1E7naZz3xfw4_mIbWh5KBh9dmF3FIvgP5m3Y,15
|
|
11
|
+
PythonicDISORT-0.9.1.dist-info/RECORD,,
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
PythonicDISORT/__init__.py,sha256=V1obNzaFgqInxqYJ5h_r6JHbZRxx4VM5VgzCIS6EEzI,84
|
|
2
|
-
PythonicDISORT/_assemble_intensity_and_fluxes.py,sha256=SFX5SMUhKNt_MU-0t3kv5lLXxc1EzVK2EIDLnggoIEw,27206
|
|
3
|
-
PythonicDISORT/_solve_for_coeffs.py,sha256=ZGThwif73zAlhzXYdVzV2nJxdxRioq4MIFsni3_5-Hc,19594
|
|
4
|
-
PythonicDISORT/_solve_for_gen_and_part_sols.py,sha256=9ScaxY7SH3lYaE2UBnEIsmsDeXdjcf74_QWaeqyOIRs,12973
|
|
5
|
-
PythonicDISORT/pydisort.py,sha256=HmAdvbDHQoHQy1xXToJmT3X5MGRudMKoI0L7zAaOd-8,33188
|
|
6
|
-
PythonicDISORT/subroutines.py,sha256=2cJLQc46ctAiqY_qARlsxQZPYVcBOwkXf0-diCtnGXo,19446
|
|
7
|
-
PythonicDISORT-0.9.0.dist-info/LICENSE.md,sha256=q1i1QVh0OLzK0fj6kaNRNWsM_KZca66JwWgWwbuCPlA,1092
|
|
8
|
-
PythonicDISORT-0.9.0.dist-info/METADATA,sha256=dLzNm79C3rWzVMzC2GIboGpMloxs4Fiy3RpQgOMIMP4,7102
|
|
9
|
-
PythonicDISORT-0.9.0.dist-info/WHEEL,sha256=R0nc6qTxuoLk7ShA2_Y-UWkN8ZdfDBG2B6Eqpz2WXbs,91
|
|
10
|
-
PythonicDISORT-0.9.0.dist-info/top_level.txt,sha256=aX6kCeI1E7naZz3xfw4_mIbWh5KBh9dmF3FIvgP5m3Y,15
|
|
11
|
-
PythonicDISORT-0.9.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|