PythonicDISORT 0.9.5__py3-none-any.whl → 1.0.0__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 +71 -68
- PythonicDISORT/_solve_for_coeffs.py +79 -74
- PythonicDISORT/_solve_for_gen_and_part_sols.py +14 -14
- PythonicDISORT/pydisort.py +97 -58
- PythonicDISORT/subroutines.py +277 -38
- {PythonicDISORT-0.9.5.dist-info → PythonicDISORT-1.0.0.dist-info}/METADATA +20 -4
- PythonicDISORT-1.0.0.dist-info/RECORD +11 -0
- PythonicDISORT-0.9.5.dist-info/RECORD +0 -11
- {PythonicDISORT-0.9.5.dist-info → PythonicDISORT-1.0.0.dist-info}/LICENSE.md +0 -0
- {PythonicDISORT-0.9.5.dist-info → PythonicDISORT-1.0.0.dist-info}/WHEEL +0 -0
- {PythonicDISORT-0.9.5.dist-info → PythonicDISORT-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -16,12 +16,13 @@ def _assemble_intensity_and_fluxes(
|
|
|
16
16
|
is_atmos_multilayered, # Is the atmosphere multilayered?
|
|
17
17
|
weighted_scaled_Leg_coeffs, # Weighted and delta-scaled Legendre coefficients
|
|
18
18
|
BDRF_Fourier_modes, # BDRF Fourier modes
|
|
19
|
-
mu0, I0,
|
|
19
|
+
mu0, I0, rescale_factor, phi0, # Properties of the direct beam
|
|
20
20
|
there_is_beam_source, # Is there a beam source?
|
|
21
21
|
b_pos, b_neg, # Dirichlet BCs
|
|
22
|
-
b_pos_is_scalar, b_neg_is_scalar, # Is each Dirichlet BCs scalar
|
|
22
|
+
b_pos_is_scalar, b_neg_is_scalar, # Is each Dirichlet BCs scalar and so isotropic?
|
|
23
|
+
b_pos_is_vector, b_neg_is_vector, # Is each Dirichlet BCs vector?
|
|
23
24
|
Nscoeffs, # Number of isotropic source polynomial coefficients
|
|
24
|
-
|
|
25
|
+
scaled_s_poly_coeffs, # Delta-scaled polynomial coefficients of isotropic source
|
|
25
26
|
there_is_iso_source, # Is there an isotropic source?
|
|
26
27
|
scale_tau, # Delta-scale factor for tau
|
|
27
28
|
only_flux, # Only compute fluxes?
|
|
@@ -40,40 +41,42 @@ def _assemble_intensity_and_fluxes(
|
|
|
40
41
|
documentation, explanation and derivation.
|
|
41
42
|
|
|
42
43
|
Arguments of _assemble_intensity_and_fluxes
|
|
43
|
-
| Variable |
|
|
44
|
-
| ------------------------------ |
|
|
45
|
-
| `scaled_omega_arr` | `NLayers`
|
|
46
|
-
| `tau_arr` | `NLayers`
|
|
47
|
-
| `scaled_tau_arr_with_0` | `NLayers + 1`
|
|
48
|
-
| `mu_arr_pos` | `NQuad/2`
|
|
49
|
-
| `mu_arr` | `NQuad`
|
|
50
|
-
| `M_inv` | `NQuad/2`
|
|
51
|
-
| `W` | `NQuad/2`
|
|
52
|
-
| `N` | scalar
|
|
53
|
-
| `NQuad` | scalar
|
|
54
|
-
| `NLeg` | scalar
|
|
55
|
-
| `NFourier` | scalar
|
|
56
|
-
| `NLayers` | scalar
|
|
57
|
-
| `NBDRF` | scalar
|
|
58
|
-
| `is_atmos_multilayered` | boolean
|
|
59
|
-
| `weighted_scaled_Leg_coeffs` | `NLayers x NLeg`
|
|
60
|
-
| `BDRF_Fourier_modes` | `NBDRF`
|
|
61
|
-
| `mu0` | scalar
|
|
62
|
-
| `I0` | scalar
|
|
63
|
-
| `
|
|
64
|
-
| `phi0` | scalar
|
|
65
|
-
| `there_is_beam_source` | scalar
|
|
66
|
-
| `b_pos` | `NQuad/2 x NFourier` or scalar
|
|
67
|
-
| `b_neg` | `NQuad/2 x NFourier` or scalar
|
|
68
|
-
| `b_pos_is_scalar` | boolean
|
|
69
|
-
| `b_neg_is_scalar` | boolean
|
|
70
|
-
| `
|
|
71
|
-
| `
|
|
72
|
-
| `
|
|
73
|
-
| `
|
|
74
|
-
| `
|
|
75
|
-
| `
|
|
76
|
-
| `
|
|
44
|
+
| Variable | Type / Shape |
|
|
45
|
+
| ------------------------------ | -------------------------------------------- |
|
|
46
|
+
| `scaled_omega_arr` | `NLayers` |
|
|
47
|
+
| `tau_arr` | `NLayers` |
|
|
48
|
+
| `scaled_tau_arr_with_0` | `NLayers + 1` |
|
|
49
|
+
| `mu_arr_pos` | `NQuad/2` |
|
|
50
|
+
| `mu_arr` | `NQuad` |
|
|
51
|
+
| `M_inv` | `NQuad/2` |
|
|
52
|
+
| `W` | `NQuad/2` |
|
|
53
|
+
| `N` | scalar |
|
|
54
|
+
| `NQuad` | scalar |
|
|
55
|
+
| `NLeg` | scalar |
|
|
56
|
+
| `NFourier` | scalar |
|
|
57
|
+
| `NLayers` | scalar |
|
|
58
|
+
| `NBDRF` | scalar |
|
|
59
|
+
| `is_atmos_multilayered` | boolean |
|
|
60
|
+
| `weighted_scaled_Leg_coeffs` | `NLayers x NLeg` |
|
|
61
|
+
| `BDRF_Fourier_modes` | `NBDRF` |
|
|
62
|
+
| `mu0` | scalar |
|
|
63
|
+
| `I0` | scalar |
|
|
64
|
+
| `rescale_factor` | scalar |
|
|
65
|
+
| `phi0` | scalar |
|
|
66
|
+
| `there_is_beam_source` | scalar |
|
|
67
|
+
| `b_pos` | `NQuad/2 x NFourier` or `NQuad/2` or scalar |
|
|
68
|
+
| `b_neg` | `NQuad/2 x NFourier` or `NQuad/2` or scalar |
|
|
69
|
+
| `b_pos_is_scalar` | boolean |
|
|
70
|
+
| `b_neg_is_scalar` | boolean |
|
|
71
|
+
| `b_pos_is_vector` | boolean |
|
|
72
|
+
| `b_neg_is_vector` | boolean |
|
|
73
|
+
| `Nscoeffs` | scalar |
|
|
74
|
+
| `scaled_s_poly_coeffs` | `NLayers x Nscoeffs` |
|
|
75
|
+
| `there_is_iso_source` | boolean |
|
|
76
|
+
| `scale_tau` | `NLayers` |
|
|
77
|
+
| `only_flux` | boolean |
|
|
78
|
+
| `use_banded_solver_NLayers` | scalar |
|
|
79
|
+
| `autograd_compatible` | boolean |
|
|
77
80
|
|
|
78
81
|
Notable internal variables of _assemble_intensity_and_fluxes
|
|
79
82
|
| Variable | Type / Shape |
|
|
@@ -136,7 +139,6 @@ def _assemble_intensity_and_fluxes(
|
|
|
136
139
|
K_collect,
|
|
137
140
|
B_collect,
|
|
138
141
|
G_inv_collect_0,
|
|
139
|
-
tau_arr,
|
|
140
142
|
scaled_tau_arr_with_0,
|
|
141
143
|
mu_arr, mu_arr_pos, mu_arr_pos * W,
|
|
142
144
|
N, NQuad,
|
|
@@ -147,8 +149,9 @@ def _assemble_intensity_and_fluxes(
|
|
|
147
149
|
there_is_beam_source,
|
|
148
150
|
b_pos, b_neg,
|
|
149
151
|
b_pos_is_scalar, b_neg_is_scalar,
|
|
152
|
+
b_pos_is_vector, b_neg_is_vector,
|
|
150
153
|
Nscoeffs,
|
|
151
|
-
|
|
154
|
+
scaled_s_poly_coeffs,
|
|
152
155
|
there_is_iso_source,
|
|
153
156
|
use_banded_solver_NLayers,
|
|
154
157
|
)
|
|
@@ -160,7 +163,7 @@ def _assemble_intensity_and_fluxes(
|
|
|
160
163
|
|
|
161
164
|
if not only_flux:
|
|
162
165
|
|
|
163
|
-
# Construct the intensity function (refer to
|
|
166
|
+
# Construct the intensity function (refer to section 3.7 of the Comprehensive Documentation)
|
|
164
167
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
165
168
|
def u(tau, phi, is_antiderivative_wrt_tau=False, return_Fourier_error=False, return_tau_arr=False):
|
|
166
169
|
"""
|
|
@@ -173,7 +176,7 @@ def _assemble_intensity_and_fluxes(
|
|
|
173
176
|
"""
|
|
174
177
|
tau = np.atleast_1d(tau)
|
|
175
178
|
phi = np.atleast_1d(phi)
|
|
176
|
-
if np.
|
|
179
|
+
if np.any(tau < 0) or np.any(tau > tau_arr[-1]):
|
|
177
180
|
raise ValueError("tau input outside the tau range specified for the atmosphere (check `tau_arr`).")
|
|
178
181
|
|
|
179
182
|
# Atmospheric layer indices
|
|
@@ -228,8 +231,8 @@ def _assemble_intensity_and_fluxes(
|
|
|
228
231
|
if there_is_iso_source:
|
|
229
232
|
l_uniq, l_inv = np.unique(l, return_inverse=True)
|
|
230
233
|
_mathscr_v_contribution = _mathscr_v(
|
|
231
|
-
|
|
232
|
-
|
|
234
|
+
scaled_tau, l_inv, Nscoeffs,
|
|
235
|
+
scaled_s_poly_coeffs[l_uniq],
|
|
233
236
|
G_collect_0[l_uniq],
|
|
234
237
|
K_collect_0[l_uniq],
|
|
235
238
|
G_inv_collect_0[l_uniq],
|
|
@@ -300,14 +303,14 @@ def _assemble_intensity_and_fluxes(
|
|
|
300
303
|
)
|
|
301
304
|
|
|
302
305
|
if return_tau_arr:
|
|
303
|
-
return
|
|
306
|
+
return rescale_factor * np.squeeze(u), Fourier_error, tau_arr
|
|
304
307
|
else:
|
|
305
|
-
return
|
|
308
|
+
return rescale_factor * np.squeeze(u), Fourier_error
|
|
306
309
|
else:
|
|
307
310
|
if return_tau_arr:
|
|
308
|
-
return
|
|
311
|
+
return rescale_factor * np.squeeze(u), tau_arr
|
|
309
312
|
else:
|
|
310
|
-
return
|
|
313
|
+
return rescale_factor * np.squeeze(u)
|
|
311
314
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
312
315
|
|
|
313
316
|
# Construct u0
|
|
@@ -323,7 +326,7 @@ def _assemble_intensity_and_fluxes(
|
|
|
323
326
|
to switch to an antiderivative of the function with respect to `tau`.
|
|
324
327
|
"""
|
|
325
328
|
tau = np.atleast_1d(tau)
|
|
326
|
-
if np.
|
|
329
|
+
if np.any(tau < 0) or np.any(tau > tau_arr[-1]):
|
|
327
330
|
raise ValueError("tau input outside the tau range given for the atmosphere (check `tau_arr`).")
|
|
328
331
|
|
|
329
332
|
# Atmospheric layer indices
|
|
@@ -390,8 +393,8 @@ def _assemble_intensity_and_fluxes(
|
|
|
390
393
|
if there_is_iso_source:
|
|
391
394
|
l_uniq, l_inv = np.unique(l, return_inverse=True)
|
|
392
395
|
_mathscr_v_contribution = _mathscr_v(
|
|
393
|
-
|
|
394
|
-
|
|
396
|
+
scaled_tau, l_inv, Nscoeffs,
|
|
397
|
+
scaled_s_poly_coeffs[l_uniq],
|
|
395
398
|
G_collect_0[l_uniq],
|
|
396
399
|
K_collect_0[l_uniq],
|
|
397
400
|
G_inv_collect_0[l_uniq],
|
|
@@ -402,16 +405,16 @@ def _assemble_intensity_and_fluxes(
|
|
|
402
405
|
u0 = u0 + _mathscr_v_contribution
|
|
403
406
|
|
|
404
407
|
if return_tau_arr and _return_act_dscale_for_reclass:
|
|
405
|
-
return
|
|
408
|
+
return rescale_factor * np.squeeze(u0), tau_arr, act_dscale_reclassification
|
|
406
409
|
elif return_tau_arr and not _return_act_dscale_for_reclass:
|
|
407
|
-
return
|
|
410
|
+
return rescale_factor * np.squeeze(u0), tau_arr
|
|
408
411
|
elif not return_tau_arr and _return_act_dscale_for_reclass:
|
|
409
|
-
return
|
|
412
|
+
return rescale_factor * np.squeeze(u0), act_dscale_reclassification
|
|
410
413
|
else:
|
|
411
|
-
return
|
|
414
|
+
return rescale_factor * np.squeeze(u0)
|
|
412
415
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
413
416
|
|
|
414
|
-
# Construct the flux functions (refer to
|
|
417
|
+
# Construct the flux functions (refer to section 3.8 of the Comprehensive Documentation)
|
|
415
418
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
416
419
|
GC_pos = GC_collect_0[:, :N, :]
|
|
417
420
|
GC_neg = GC_collect_0[:, N:, :]
|
|
@@ -428,7 +431,7 @@ def _assemble_intensity_and_fluxes(
|
|
|
428
431
|
to switch to an antiderivative of the function with respect to `tau`.
|
|
429
432
|
"""
|
|
430
433
|
tau = np.atleast_1d(tau)
|
|
431
|
-
if np.
|
|
434
|
+
if np.any(tau < 0) or np.any(tau > tau_arr[-1]):
|
|
432
435
|
raise ValueError("tau input outside the tau range given for the atmosphere (check `tau_arr`).")
|
|
433
436
|
|
|
434
437
|
# Atmospheric layer indices
|
|
@@ -447,8 +450,8 @@ def _assemble_intensity_and_fluxes(
|
|
|
447
450
|
if there_is_iso_source:
|
|
448
451
|
l_uniq, l_inv = np.unique(l, return_inverse=True)
|
|
449
452
|
_mathscr_v_contribution = _mathscr_v(
|
|
450
|
-
|
|
451
|
-
|
|
453
|
+
scaled_tau, l_inv, Nscoeffs,
|
|
454
|
+
scaled_s_poly_coeffs[l_uniq],
|
|
452
455
|
G_collect_0[l_uniq, :N, :],
|
|
453
456
|
K_collect_0[l_uniq],
|
|
454
457
|
G_inv_collect_0[l_uniq],
|
|
@@ -495,9 +498,9 @@ def _assemble_intensity_and_fluxes(
|
|
|
495
498
|
flux = 2 * pi * (mu_arr_pos * W) @ u0_pos
|
|
496
499
|
|
|
497
500
|
if return_tau_arr:
|
|
498
|
-
return
|
|
501
|
+
return rescale_factor * np.squeeze(flux)[()], tau_arr
|
|
499
502
|
else:
|
|
500
|
-
return
|
|
503
|
+
return rescale_factor * np.squeeze(flux)[()]
|
|
501
504
|
|
|
502
505
|
|
|
503
506
|
def flux_down(tau, is_antiderivative_wrt_tau=False, return_tau_arr=False):
|
|
@@ -509,7 +512,7 @@ def _assemble_intensity_and_fluxes(
|
|
|
509
512
|
to switch to an antiderivative of the function with respect to `tau`.
|
|
510
513
|
"""
|
|
511
514
|
tau = np.atleast_1d(tau)
|
|
512
|
-
if np.
|
|
515
|
+
if np.any(tau < 0) or np.any(tau > tau_arr[-1]):
|
|
513
516
|
raise ValueError("tau input outside the tau range given for the atmosphere (check `tau_arr`).")
|
|
514
517
|
|
|
515
518
|
# Atmospheric layer indices
|
|
@@ -528,8 +531,8 @@ def _assemble_intensity_and_fluxes(
|
|
|
528
531
|
if there_is_iso_source:
|
|
529
532
|
l_uniq, l_inv = np.unique(l, return_inverse=True)
|
|
530
533
|
_mathscr_v_contribution = _mathscr_v(
|
|
531
|
-
|
|
532
|
-
|
|
534
|
+
scaled_tau, l_inv, Nscoeffs,
|
|
535
|
+
scaled_s_poly_coeffs[l_uniq],
|
|
533
536
|
G_collect_0[l_uniq, N:, :],
|
|
534
537
|
K_collect_0[l_uniq],
|
|
535
538
|
G_inv_collect_0[l_uniq],
|
|
@@ -577,18 +580,18 @@ def _assemble_intensity_and_fluxes(
|
|
|
577
580
|
|
|
578
581
|
if return_tau_arr:
|
|
579
582
|
return (
|
|
580
|
-
|
|
581
|
-
|
|
583
|
+
rescale_factor * np.squeeze(diffuse_flux)[()],
|
|
584
|
+
rescale_factor * np.squeeze(direct_beam)[()],
|
|
582
585
|
tau_arr
|
|
583
586
|
)
|
|
584
587
|
else:
|
|
585
588
|
return (
|
|
586
|
-
|
|
587
|
-
|
|
589
|
+
rescale_factor * np.squeeze(diffuse_flux)[()],
|
|
590
|
+
rescale_factor * np.squeeze(direct_beam)[()],
|
|
588
591
|
)
|
|
589
592
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
590
593
|
|
|
591
594
|
if only_flux:
|
|
592
|
-
return flux_up, flux_down, u0
|
|
595
|
+
return flux_up, flux_down, u0#, GC_collect_0, K_collect_0
|
|
593
596
|
else:
|
|
594
597
|
return flux_up, flux_down, u0, u
|
|
@@ -7,26 +7,26 @@ from math import pi
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
def _solve_for_coeffs(
|
|
10
|
-
NFourier,
|
|
11
|
-
G_collect,
|
|
12
|
-
K_collect,
|
|
13
|
-
B_collect,
|
|
14
|
-
G_inv_collect_0,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
Nscoeffs,
|
|
27
|
-
|
|
28
|
-
there_is_iso_source,
|
|
29
|
-
use_banded_solver_NLayers,
|
|
10
|
+
NFourier, # Number of intensity Fourier modes
|
|
11
|
+
G_collect, # Eigenvector matrices
|
|
12
|
+
K_collect, # Eigenvalues
|
|
13
|
+
B_collect, # Coefficients vectors for particular solutions
|
|
14
|
+
G_inv_collect_0, # Inverse of eigenvector matrix for the 0th Fourier mode
|
|
15
|
+
scaled_tau_arr_with_0, # Delta-scaled lower boundary of layers with 0 inserted in front
|
|
16
|
+
mu_arr, mu_arr_pos, mu_arr_pos_times_W, # Quadrature nodes for 1) both 2) upper hemispheres; 3) upper hemisphere quadrature nodes times weights
|
|
17
|
+
N, NQuad, # Number of 1) upper 2) both hemispheres quadrature nodes
|
|
18
|
+
NLayers, NBDRF, # Number of 1) layers; 2) BDRF Fourier modes
|
|
19
|
+
is_atmos_multilayered, # Is the atmosphere multilayered?
|
|
20
|
+
BDRF_Fourier_modes, # BDRF Fourier modes
|
|
21
|
+
mu0, I0, # Properties of the direct beam
|
|
22
|
+
there_is_beam_source, # Is there a beam source?
|
|
23
|
+
b_pos, b_neg, # Dirichlet BCs
|
|
24
|
+
b_pos_is_scalar, b_neg_is_scalar, # Is each Dirichlet BCs scalar and so isotropic?
|
|
25
|
+
b_pos_is_vector, b_neg_is_vector, # Is each Dirichlet BCs vector?
|
|
26
|
+
Nscoeffs, # Number of isotropic source polynomial coefficients
|
|
27
|
+
scaled_s_poly_coeffs, # Polynomial coefficients of isotropic source
|
|
28
|
+
there_is_iso_source, # Is there an isotropic source?
|
|
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
|
|
@@ -38,35 +38,36 @@ def _solve_for_coeffs(
|
|
|
38
38
|
The labels in this file reference labels in the Jupyter Notebook, especially sections 3 and 4.
|
|
39
39
|
|
|
40
40
|
Arguments of _solve_for_coeffs
|
|
41
|
-
| Variable |
|
|
42
|
-
| ------------------------------ |
|
|
43
|
-
| `NFourier` | scalar
|
|
44
|
-
| `G_collect` | `NFourier x NLayers x NQuad x NQuad`
|
|
45
|
-
| `K_collect` | `NFourier x NLayers x NQuad`
|
|
46
|
-
| `B_collect` | `NFourier x NLayers x NQuad` or `None`
|
|
47
|
-
| `G_inv_collect_0` | `NLayers x NQuad x NQuad` or `None`
|
|
48
|
-
| `
|
|
49
|
-
| `
|
|
50
|
-
| `
|
|
51
|
-
| `
|
|
52
|
-
| `
|
|
53
|
-
| `
|
|
54
|
-
| `
|
|
55
|
-
| `
|
|
56
|
-
| `
|
|
57
|
-
| `
|
|
58
|
-
| `
|
|
59
|
-
| `
|
|
60
|
-
| `
|
|
61
|
-
| `
|
|
62
|
-
| `
|
|
63
|
-
| `
|
|
64
|
-
| `
|
|
65
|
-
| `
|
|
66
|
-
| `
|
|
67
|
-
| `
|
|
68
|
-
| `
|
|
69
|
-
| `
|
|
41
|
+
| Variable | Type / Shape |
|
|
42
|
+
| ------------------------------ | -------------------------------------------- |
|
|
43
|
+
| `NFourier` | scalar |
|
|
44
|
+
| `G_collect` | `NFourier x NLayers x NQuad x NQuad` |
|
|
45
|
+
| `K_collect` | `NFourier x NLayers x NQuad` |
|
|
46
|
+
| `B_collect` | `NFourier x NLayers x NQuad` or `None` |
|
|
47
|
+
| `G_inv_collect_0` | `NLayers x NQuad x NQuad` or `None` |
|
|
48
|
+
| `scaled_tau_arr_with_0` | `NLayers + 1` |
|
|
49
|
+
| `mu_arr` | `NQuad` |
|
|
50
|
+
| `mu_arr_pos` | `NQuad/2` |
|
|
51
|
+
| `mu_arr_pos_times_W` | `NQuad/2` |
|
|
52
|
+
| `N` | scalar |
|
|
53
|
+
| `NQuad` | scalar |
|
|
54
|
+
| `NLayers` | scalar |
|
|
55
|
+
| `NBDRF` | scalar |
|
|
56
|
+
| `is_atmos_multilayered` | boolean |
|
|
57
|
+
| `BDRF_Fourier_modes` | `NBDRF` |
|
|
58
|
+
| `mu0` | scalar |
|
|
59
|
+
| `I0` | scalar |
|
|
60
|
+
| `there_is_beam_source` | boolean |
|
|
61
|
+
| `b_pos` | `NQuad/2 x NFourier` or `NQuad/2` or scalar |
|
|
62
|
+
| `b_neg` | `NQuad/2 x NFourier` or `NQuad/2` or scalar |
|
|
63
|
+
| `b_pos_is_scalar` | boolean |
|
|
64
|
+
| `b_neg_is_scalar` | boolean |
|
|
65
|
+
| `b_pos_is_vector` | boolean |
|
|
66
|
+
| `b_neg_is_vector` | boolean |
|
|
67
|
+
| `Nscoeffs` | scalar |
|
|
68
|
+
| `scaled_s_poly_coeffs` | `NLayers x Nscoeffs` |
|
|
69
|
+
| `there_is_iso_source` | boolean |
|
|
70
|
+
| `use_banded_solver_NLayers` | scalar |
|
|
70
71
|
|
|
71
72
|
Notable internal variables of _solve_for_coeffs
|
|
72
73
|
| Variable | Shape |
|
|
@@ -75,7 +76,7 @@ def _solve_for_coeffs(
|
|
|
75
76
|
|
|
76
77
|
"""
|
|
77
78
|
################################## Solve for coefficients of homogeneous solution ##########################################
|
|
78
|
-
############# Refer to
|
|
79
|
+
############# Refer to section 3.6.2 (single-layer) and 4 (multi-layer) of the Comprehensive Documentation #################
|
|
79
80
|
|
|
80
81
|
dim = NLayers * NQuad
|
|
81
82
|
GC_collect = np.empty((NFourier, NLayers, NQuad, NQuad))
|
|
@@ -94,15 +95,15 @@ def _solve_for_coeffs(
|
|
|
94
95
|
B_collect_m = B_collect[m, :, :]
|
|
95
96
|
|
|
96
97
|
# Generate mathscr_D and mathscr_X (BDRF terms)
|
|
97
|
-
# Just for this part, refer to
|
|
98
|
+
# Just for this part, refer to section 3.4.2 of the Comprehensive Documentation
|
|
98
99
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
99
100
|
if BDRF_bool:
|
|
100
|
-
mathscr_D_neg = (1 + m_equals_0 * 1) * BDRF_Fourier_modes[m](mu_arr_pos,
|
|
101
|
+
mathscr_D_neg = (1 + m_equals_0 * 1) * BDRF_Fourier_modes[m](mu_arr_pos, mu_arr_pos)
|
|
101
102
|
R = mathscr_D_neg * mu_arr_pos_times_W[None, :]
|
|
102
103
|
|
|
103
104
|
if there_is_beam_source:
|
|
104
105
|
mathscr_X_pos = (mu0 * I0 / pi) * BDRF_Fourier_modes[m](
|
|
105
|
-
mu_arr_pos,
|
|
106
|
+
mu_arr_pos, np.array([mu0])
|
|
106
107
|
)[:, 0]
|
|
107
108
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
108
109
|
|
|
@@ -111,14 +112,18 @@ def _solve_for_coeffs(
|
|
|
111
112
|
# Ensure the BCs are of the correct shape
|
|
112
113
|
if b_pos_is_scalar and m_equals_0:
|
|
113
114
|
b_pos_m = np.full(N, b_pos)
|
|
114
|
-
elif
|
|
115
|
+
elif b_pos_is_vector and m_equals_0:
|
|
116
|
+
b_pos_m = b_pos
|
|
117
|
+
elif (b_pos_is_scalar or b_pos_is_vector) and not m_equals_0:
|
|
115
118
|
b_pos_m = np.zeros(N)
|
|
116
119
|
else:
|
|
117
120
|
b_pos_m = b_pos[:, m]
|
|
118
121
|
|
|
119
122
|
if b_neg_is_scalar and m_equals_0:
|
|
120
123
|
b_neg_m = np.full(N, b_neg)
|
|
121
|
-
elif
|
|
124
|
+
elif b_neg_is_vector and m_equals_0:
|
|
125
|
+
b_neg_m = b_neg
|
|
126
|
+
elif (b_neg_is_scalar or b_neg_is_vector) and not m_equals_0:
|
|
122
127
|
b_neg_m = np.zeros(N)
|
|
123
128
|
else:
|
|
124
129
|
b_neg_m = b_neg[:, m]
|
|
@@ -129,10 +134,10 @@ def _solve_for_coeffs(
|
|
|
129
134
|
np.array([0]),
|
|
130
135
|
np.array([0]),
|
|
131
136
|
Nscoeffs,
|
|
132
|
-
|
|
133
|
-
G_collect_m[0
|
|
134
|
-
K_collect_m[0
|
|
135
|
-
G_inv_collect_0[0
|
|
137
|
+
scaled_s_poly_coeffs[[0], :],
|
|
138
|
+
G_collect_m[[0], N:, :],
|
|
139
|
+
K_collect_m[[0], :],
|
|
140
|
+
G_inv_collect_0[[0], :, :],
|
|
136
141
|
mu_arr,
|
|
137
142
|
).ravel()
|
|
138
143
|
|
|
@@ -141,20 +146,20 @@ def _solve_for_coeffs(
|
|
|
141
146
|
indices = np.arange(NLayers - 1)
|
|
142
147
|
_mathscr_v_contribution_middle = (
|
|
143
148
|
_mathscr_v(
|
|
144
|
-
|
|
149
|
+
scaled_tau_arr_with_0[1:-1],
|
|
145
150
|
indices,
|
|
146
151
|
Nscoeffs,
|
|
147
|
-
|
|
152
|
+
scaled_s_poly_coeffs[indices + 1],
|
|
148
153
|
G_collect_m[indices + 1],
|
|
149
154
|
K_collect_m[indices + 1],
|
|
150
155
|
G_inv_collect_0[indices + 1],
|
|
151
156
|
mu_arr,
|
|
152
157
|
)
|
|
153
158
|
- _mathscr_v(
|
|
154
|
-
|
|
159
|
+
scaled_tau_arr_with_0[1:-1],
|
|
155
160
|
indices,
|
|
156
161
|
Nscoeffs,
|
|
157
|
-
|
|
162
|
+
scaled_s_poly_coeffs[indices],
|
|
158
163
|
G_collect_m[indices],
|
|
159
164
|
K_collect_m[indices],
|
|
160
165
|
G_inv_collect_0[indices],
|
|
@@ -163,13 +168,13 @@ def _solve_for_coeffs(
|
|
|
163
168
|
).ravel(order='F')
|
|
164
169
|
|
|
165
170
|
_mathscr_v_contribution_bottom = -_mathscr_v(
|
|
166
|
-
|
|
171
|
+
scaled_tau_arr_with_0[[-1]],
|
|
167
172
|
np.array([0]),
|
|
168
173
|
Nscoeffs,
|
|
169
|
-
|
|
170
|
-
G_collect_m[-1
|
|
171
|
-
K_collect_m[-1
|
|
172
|
-
G_inv_collect_0[-1
|
|
174
|
+
scaled_s_poly_coeffs[[-1], :],
|
|
175
|
+
G_collect_m[[-1], :N, :],
|
|
176
|
+
K_collect_m[[-1], :],
|
|
177
|
+
G_inv_collect_0[[-1], :, :],
|
|
173
178
|
mu_arr
|
|
174
179
|
).ravel()
|
|
175
180
|
if NBDRF > 0:
|
|
@@ -177,13 +182,13 @@ def _solve_for_coeffs(
|
|
|
177
182
|
_mathscr_v_contribution_bottom
|
|
178
183
|
+ R
|
|
179
184
|
@ _mathscr_v(
|
|
180
|
-
|
|
185
|
+
scaled_tau_arr_with_0[[-1]],
|
|
181
186
|
np.array([0]),
|
|
182
187
|
Nscoeffs,
|
|
183
|
-
|
|
184
|
-
G_collect_m[-1
|
|
185
|
-
K_collect_m[-1
|
|
186
|
-
G_inv_collect_0[-1
|
|
188
|
+
scaled_s_poly_coeffs[[-1], :],
|
|
189
|
+
G_collect_m[[-1], N:, :],
|
|
190
|
+
K_collect_m[[-1], :],
|
|
191
|
+
G_inv_collect_0[[-1], :, :],
|
|
187
192
|
mu_arr
|
|
188
193
|
).ravel()
|
|
189
194
|
)
|
|
@@ -237,7 +242,7 @@ def _solve_for_coeffs(
|
|
|
237
242
|
RHS = np.concatenate([b_neg_m, RHS_middle, b_pos_m]) + _mathscr_v_contribution
|
|
238
243
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
239
244
|
|
|
240
|
-
# Assemble LHS (much of this code is replicated in
|
|
245
|
+
# Assemble LHS (much of this code is replicated in section 4 of the Comprehensive Documentation)
|
|
241
246
|
G_0_nn = G_collect_m[0, N:, :N]
|
|
242
247
|
G_0_np = G_collect_m[0, N:, N:]
|
|
243
248
|
G_L_pn = G_collect_m[-1, :N, :N]
|
|
@@ -4,17 +4,17 @@ from math import pi
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
def _solve_for_gen_and_part_sols(
|
|
7
|
-
NFourier,
|
|
8
|
-
scaled_omega_arr,
|
|
9
|
-
mu_arr_pos, mu_arr,
|
|
10
|
-
M_inv, W,
|
|
11
|
-
N, NQuad, NLeg,
|
|
12
|
-
NLayers,
|
|
13
|
-
weighted_scaled_Leg_coeffs,
|
|
14
|
-
mu0, I0,
|
|
15
|
-
there_is_beam_source,
|
|
16
|
-
Nscoeffs,
|
|
17
|
-
there_is_iso_source,
|
|
7
|
+
NFourier, # Number of intensity Fourier modes
|
|
8
|
+
scaled_omega_arr, # Delta-scaled single-scattering albedos
|
|
9
|
+
mu_arr_pos, mu_arr, # Quadrature nodes for 1) upper 2) both hemispheres
|
|
10
|
+
M_inv, W, # 1) 1 / mu; 2) quadrature weights for each hemisphere
|
|
11
|
+
N, NQuad, NLeg, # Number of 1) upper 2) both hemispheres quadrature nodes; 3) phase function Legendre coefficients
|
|
12
|
+
NLayers, # Number of layers
|
|
13
|
+
weighted_scaled_Leg_coeffs, # Weighted and delta-scaled Legendre coefficients
|
|
14
|
+
mu0, I0, # Properties of the direct beam
|
|
15
|
+
there_is_beam_source, # Is there a beam source?
|
|
16
|
+
Nscoeffs, # Number of isotropic source polynomial coefficients
|
|
17
|
+
there_is_iso_source, # Is there an isotropic source?
|
|
18
18
|
):
|
|
19
19
|
"""
|
|
20
20
|
Diagonalizes the coefficient matrix of the system of ordinary differential equations (ODEs)
|
|
@@ -60,7 +60,7 @@ def _solve_for_gen_and_part_sols(
|
|
|
60
60
|
|
|
61
61
|
"""
|
|
62
62
|
############################### Assemble system and diagonalize coefficient matrix #########################################
|
|
63
|
-
########################### Refer to
|
|
63
|
+
########################### Refer to section 3.4.2 of the Comprehensive Documentation #####################################
|
|
64
64
|
|
|
65
65
|
# Initialization
|
|
66
66
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
@@ -124,7 +124,7 @@ def _solve_for_gen_and_part_sols(
|
|
|
124
124
|
|
|
125
125
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
126
126
|
|
|
127
|
-
# Particular solution for the direct beam source (refer to
|
|
127
|
+
# Particular solution for the direct beam source (refer to section 3.6.1 of the Comprehensive Documentation)
|
|
128
128
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
129
129
|
if there_is_beam_source:
|
|
130
130
|
# Generate X
|
|
@@ -171,7 +171,7 @@ def _solve_for_gen_and_part_sols(
|
|
|
171
171
|
|
|
172
172
|
if len(no_shortcut_indices) > 0:
|
|
173
173
|
|
|
174
|
-
# Diagonalization of coefficient matrix (refer to
|
|
174
|
+
# Diagonalization of coefficient matrix (refer to section 3.4.2 of the Comprehensive Documentation)
|
|
175
175
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
176
176
|
alpha_arr = alpha_arr[: len(no_shortcut_indices), :, :]
|
|
177
177
|
beta_arr = beta_arr[: len(no_shortcut_indices), :, :]
|