PythonicDISORT 1.3__tar.gz → 1.5__tar.gz
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-1.3/src/PythonicDISORT.egg-info → pythonicdisort-1.5}/PKG-INFO +7 -3
- {pythonicdisort-1.3 → pythonicdisort-1.5}/README.md +5 -2
- {pythonicdisort-1.3 → pythonicdisort-1.5}/pyproject.toml +2 -1
- {pythonicdisort-1.3 → pythonicdisort-1.5}/src/PythonicDISORT/_assemble_intensity_and_fluxes.py +4 -4
- {pythonicdisort-1.3 → pythonicdisort-1.5}/src/PythonicDISORT/_solve_for_coeffs.py +7 -2
- {pythonicdisort-1.3 → pythonicdisort-1.5}/src/PythonicDISORT/_solve_for_gen_and_part_sols.py +21 -5
- {pythonicdisort-1.3 → pythonicdisort-1.5}/src/PythonicDISORT/pydisort.py +31 -38
- {pythonicdisort-1.3 → pythonicdisort-1.5}/src/PythonicDISORT/subroutines.py +14 -12
- {pythonicdisort-1.3 → pythonicdisort-1.5/src/PythonicDISORT.egg-info}/PKG-INFO +7 -3
- {pythonicdisort-1.3 → pythonicdisort-1.5}/src/PythonicDISORT.egg-info/requires.txt +1 -0
- {pythonicdisort-1.3 → pythonicdisort-1.5}/LICENSE.md +0 -0
- {pythonicdisort-1.3 → pythonicdisort-1.5}/setup.cfg +0 -0
- {pythonicdisort-1.3 → pythonicdisort-1.5}/src/PythonicDISORT/__init__.py +0 -0
- {pythonicdisort-1.3 → pythonicdisort-1.5}/src/PythonicDISORT.egg-info/SOURCES.txt +0 -0
- {pythonicdisort-1.3 → pythonicdisort-1.5}/src/PythonicDISORT.egg-info/dependency_links.txt +0 -0
- {pythonicdisort-1.3 → pythonicdisort-1.5}/src/PythonicDISORT.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PythonicDISORT
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5
|
|
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
|
|
@@ -18,6 +18,7 @@ Provides-Extra: notebook-dependencies
|
|
|
18
18
|
Requires-Dist: autograd>=1.5; extra == "notebook-dependencies"
|
|
19
19
|
Requires-Dist: jupyter>1.0.0; extra == "notebook-dependencies"
|
|
20
20
|
Requires-Dist: notebook>6.5.2; extra == "notebook-dependencies"
|
|
21
|
+
Requires-Dist: matplotlib>=3.6.0; extra == "notebook-dependencies"
|
|
21
22
|
|
|
22
23
|
[](https://github.com/LDEO-CREW/Pythonic-DISORT/actions/workflows/continuous_integration.yml)
|
|
23
24
|
[](https://doi.org/10.21105/joss.06442)
|
|
@@ -70,6 +71,7 @@ These notebooks double up as examples of how to use PythonicDISORT. The tests wh
|
|
|
70
71
|
* Test Problem 8: Absorbing / Isotropic-Scattering Medium (multiple layers)
|
|
71
72
|
* Test Problem 9: General Emitting / Absorbing / Scattering Medium (multiple layers)
|
|
72
73
|
* Test Problem 11: Single-Layer vs. Multiple Layers (no corresponding Jupyter Notebook)
|
|
74
|
+
* Test Problem I: Antiderivative / integration functionality (no corresponding Jupyter Notebook)
|
|
73
75
|
|
|
74
76
|
# Installation
|
|
75
77
|
|
|
@@ -81,15 +83,16 @@ These notebooks double up as examples of how to use PythonicDISORT. The tests wh
|
|
|
81
83
|
* Python 3.8+
|
|
82
84
|
* `numpy >= 1.8.0`
|
|
83
85
|
* `scipy >= 1.8.0`
|
|
86
|
+
* (OPTIONAL) `autograd >= 1.5` (`autograd` can be used to compute gradients of the output functions)
|
|
84
87
|
* (OPTIONAL) `pytest >= 6.2.5` (Required to use the command `pytest`, see *PyTest and examples of how to use PythonicDISORT*)
|
|
85
88
|
|
|
86
89
|
## (OPTIONAL) Additional requirements to run the Jupyter Notebook
|
|
87
|
-
* `autograd >= 1.5`
|
|
88
90
|
* `jupyter > 1.0.0`
|
|
89
91
|
* `notebook > 6.5.2`
|
|
90
92
|
* `matplotlib >= 3.6.0`
|
|
91
93
|
|
|
92
|
-
In addition, a F2PY-wrapped Stamnes' DISORT
|
|
94
|
+
In addition, a F2PY-wrapped Stamnes' DISORT or equivalent (https://github.com/kconnour/pyRT_DISORT may work)
|
|
95
|
+
is required to properly run the last section (section 6).
|
|
93
96
|
|
|
94
97
|
## Compatibility
|
|
95
98
|
|
|
@@ -127,3 +130,4 @@ Science and Technology Center (STC) (Award #2019625) under which this package wa
|
|
|
127
130
|
12) T. Nakajima and M. Tanaka. 1988. *Algorithms for radiative intensity calculations in moderately thick atmospheres using a truncation approximation.* https://www.sciencedirect.com/science/article/pii/0022407388900313.
|
|
128
131
|
|
|
129
132
|
13) Connour, Kyle and Wolff, Michael. 2020. *pyRT_DISORT: A pre-processing front-end to help make DISORT simulations easier in Python.* https://github.com/kconnour/pyRT_DISORT.
|
|
133
|
+
|
|
@@ -49,6 +49,7 @@ These notebooks double up as examples of how to use PythonicDISORT. The tests wh
|
|
|
49
49
|
* Test Problem 8: Absorbing / Isotropic-Scattering Medium (multiple layers)
|
|
50
50
|
* Test Problem 9: General Emitting / Absorbing / Scattering Medium (multiple layers)
|
|
51
51
|
* Test Problem 11: Single-Layer vs. Multiple Layers (no corresponding Jupyter Notebook)
|
|
52
|
+
* Test Problem I: Antiderivative / integration functionality (no corresponding Jupyter Notebook)
|
|
52
53
|
|
|
53
54
|
# Installation
|
|
54
55
|
|
|
@@ -60,15 +61,16 @@ These notebooks double up as examples of how to use PythonicDISORT. The tests wh
|
|
|
60
61
|
* Python 3.8+
|
|
61
62
|
* `numpy >= 1.8.0`
|
|
62
63
|
* `scipy >= 1.8.0`
|
|
64
|
+
* (OPTIONAL) `autograd >= 1.5` (`autograd` can be used to compute gradients of the output functions)
|
|
63
65
|
* (OPTIONAL) `pytest >= 6.2.5` (Required to use the command `pytest`, see *PyTest and examples of how to use PythonicDISORT*)
|
|
64
66
|
|
|
65
67
|
## (OPTIONAL) Additional requirements to run the Jupyter Notebook
|
|
66
|
-
* `autograd >= 1.5`
|
|
67
68
|
* `jupyter > 1.0.0`
|
|
68
69
|
* `notebook > 6.5.2`
|
|
69
70
|
* `matplotlib >= 3.6.0`
|
|
70
71
|
|
|
71
|
-
In addition, a F2PY-wrapped Stamnes' DISORT
|
|
72
|
+
In addition, a F2PY-wrapped Stamnes' DISORT or equivalent (https://github.com/kconnour/pyRT_DISORT may work)
|
|
73
|
+
is required to properly run the last section (section 6).
|
|
72
74
|
|
|
73
75
|
## Compatibility
|
|
74
76
|
|
|
@@ -106,3 +108,4 @@ Science and Technology Center (STC) (Award #2019625) under which this package wa
|
|
|
106
108
|
12) T. Nakajima and M. Tanaka. 1988. *Algorithms for radiative intensity calculations in moderately thick atmospheres using a truncation approximation.* https://www.sciencedirect.com/science/article/pii/0022407388900313.
|
|
107
109
|
|
|
108
110
|
13) Connour, Kyle and Wolff, Michael. 2020. *pyRT_DISORT: A pre-processing front-end to help make DISORT simulations easier in Python.* https://github.com/kconnour/pyRT_DISORT.
|
|
111
|
+
|
|
@@ -8,7 +8,7 @@ dependencies = [
|
|
|
8
8
|
"scipy>=1.8.0",
|
|
9
9
|
]
|
|
10
10
|
name = "PythonicDISORT"
|
|
11
|
-
version = "1.
|
|
11
|
+
version = "1.5"
|
|
12
12
|
authors = [
|
|
13
13
|
{ name="Dion HO Jia Xu", email="dh3065@columbia.edu" },
|
|
14
14
|
]
|
|
@@ -27,6 +27,7 @@ notebook_dependencies = [
|
|
|
27
27
|
"autograd>=1.5",
|
|
28
28
|
"jupyter>1.0.0",
|
|
29
29
|
"notebook>6.5.2",
|
|
30
|
+
"matplotlib >= 3.6.0",
|
|
30
31
|
]
|
|
31
32
|
|
|
32
33
|
[project.urls]
|
{pythonicdisort-1.3 → pythonicdisort-1.5}/src/PythonicDISORT/_assemble_intensity_and_fluxes.py
RENAMED
|
@@ -236,7 +236,7 @@ def _assemble_intensity_and_fluxes(
|
|
|
236
236
|
if there_is_iso_source:
|
|
237
237
|
l_uniq, l_inv = np.unique(l, return_inverse=True)
|
|
238
238
|
_mathscr_v_contribution = _mathscr_v(
|
|
239
|
-
scaled_tau, l_inv,
|
|
239
|
+
scaled_tau, scale_tau, l_inv,
|
|
240
240
|
Nscoeffs,
|
|
241
241
|
scaled_s_poly_coeffs[l_uniq],
|
|
242
242
|
G_collect_0[l_uniq],
|
|
@@ -411,7 +411,7 @@ def _assemble_intensity_and_fluxes(
|
|
|
411
411
|
if there_is_iso_source:
|
|
412
412
|
l_uniq, l_inv = np.unique(l, return_inverse=True)
|
|
413
413
|
_mathscr_v_contribution = _mathscr_v(
|
|
414
|
-
scaled_tau, l_inv,
|
|
414
|
+
scaled_tau, scale_tau, l_inv,
|
|
415
415
|
Nscoeffs,
|
|
416
416
|
scaled_s_poly_coeffs[l_uniq],
|
|
417
417
|
G_collect_0[l_uniq],
|
|
@@ -470,7 +470,7 @@ def _assemble_intensity_and_fluxes(
|
|
|
470
470
|
if there_is_iso_source:
|
|
471
471
|
l_uniq, l_inv = np.unique(l, return_inverse=True)
|
|
472
472
|
_mathscr_v_contribution = _mathscr_v(
|
|
473
|
-
scaled_tau, l_inv,
|
|
473
|
+
scaled_tau, scale_tau, l_inv,
|
|
474
474
|
Nscoeffs,
|
|
475
475
|
scaled_s_poly_coeffs[l_uniq],
|
|
476
476
|
G_collect_0[l_uniq, :N, :],
|
|
@@ -552,7 +552,7 @@ def _assemble_intensity_and_fluxes(
|
|
|
552
552
|
if there_is_iso_source:
|
|
553
553
|
l_uniq, l_inv = np.unique(l, return_inverse=True)
|
|
554
554
|
_mathscr_v_contribution = _mathscr_v(
|
|
555
|
-
scaled_tau, l_inv,
|
|
555
|
+
scaled_tau, scale_tau, l_inv,
|
|
556
556
|
Nscoeffs,
|
|
557
557
|
scaled_s_poly_coeffs[l_uniq],
|
|
558
558
|
G_collect_0[l_uniq, N:, :],
|
|
@@ -168,7 +168,8 @@ def _solve_for_coeffs(
|
|
|
168
168
|
if m_equals_0 and there_is_iso_source:
|
|
169
169
|
# Top boundary
|
|
170
170
|
RHS[:N] -= _mathscr_v(
|
|
171
|
-
np.array([0]),
|
|
171
|
+
np.array([0]),
|
|
172
|
+
None,
|
|
172
173
|
np.array([0]),
|
|
173
174
|
Nscoeffs,
|
|
174
175
|
scaled_s_poly_coeffs[[0], :],
|
|
@@ -183,6 +184,7 @@ def _solve_for_coeffs(
|
|
|
183
184
|
RHS[N:-N] += (
|
|
184
185
|
_mathscr_v(
|
|
185
186
|
scaled_tau_arr_with_0[1:-1],
|
|
187
|
+
None,
|
|
186
188
|
indices,
|
|
187
189
|
Nscoeffs,
|
|
188
190
|
scaled_s_poly_coeffs[indicesp1],
|
|
@@ -192,6 +194,7 @@ def _solve_for_coeffs(
|
|
|
192
194
|
)
|
|
193
195
|
- _mathscr_v(
|
|
194
196
|
scaled_tau_arr_with_0[1:-1],
|
|
197
|
+
None,
|
|
195
198
|
indices,
|
|
196
199
|
Nscoeffs,
|
|
197
200
|
scaled_s_poly_coeffs[indices],
|
|
@@ -203,7 +206,8 @@ def _solve_for_coeffs(
|
|
|
203
206
|
|
|
204
207
|
# Bottom boundary
|
|
205
208
|
RHS[-N:] -= _mathscr_v(
|
|
206
|
-
scaled_tau_arr_with_0[[-1]],
|
|
209
|
+
scaled_tau_arr_with_0[[-1]],
|
|
210
|
+
None,
|
|
207
211
|
np.array([0]),
|
|
208
212
|
Nscoeffs,
|
|
209
213
|
scaled_s_poly_coeffs[[-1], :],
|
|
@@ -217,6 +221,7 @@ def _solve_for_coeffs(
|
|
|
217
221
|
R
|
|
218
222
|
@ _mathscr_v(
|
|
219
223
|
scaled_tau_arr_with_0[[-1]],
|
|
224
|
+
None,
|
|
220
225
|
np.array([0]),
|
|
221
226
|
Nscoeffs,
|
|
222
227
|
scaled_s_poly_coeffs[[-1], :],
|
{pythonicdisort-1.3 → pythonicdisort-1.5}/src/PythonicDISORT/_solve_for_gen_and_part_sols.py
RENAMED
|
@@ -198,7 +198,8 @@ def _solve_for_gen_and_part_sols(
|
|
|
198
198
|
G_collect[no_shortcut_indices, N:, :N] = GpG_m_GmG_div_2
|
|
199
199
|
|
|
200
200
|
K_collect[no_shortcut_indices, :] = K_arr
|
|
201
|
-
|
|
201
|
+
len_no_shortcut_indices_0 = len(no_shortcut_indices_0)
|
|
202
|
+
if len_no_shortcut_indices_0 > 0: # If there is no isotropic source this list will be empty
|
|
202
203
|
G_inv_collect_0[no_shortcut_indices_0, :, :] = np.linalg.inv(
|
|
203
204
|
G_collect[no_shortcut_indices_0, :, :]
|
|
204
205
|
)
|
|
@@ -209,10 +210,25 @@ def _solve_for_gen_and_part_sols(
|
|
|
209
210
|
|
|
210
211
|
# Solve for particular solution w.r.t. direct beam source (refer to section 3.6.1 of the Comprehensive Documentation)
|
|
211
212
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
213
|
+
if len_no_shortcut_indices_0 > 0: # In this case we have `G_inv_collect_0`, so use it
|
|
214
|
+
B_collect[no_shortcut_indices_0, :] = np.einsum(
|
|
215
|
+
"bij, bjk, bk -> bi",
|
|
216
|
+
# Note that the minus sign has been absorbed into `X_arr`
|
|
217
|
+
G_collect[no_shortcut_indices_0, :, :]
|
|
218
|
+
/ (1 / mu0 + K_collect[no_shortcut_indices_0, None, :]),
|
|
219
|
+
G_inv_collect_0[no_shortcut_indices_0, :, :],
|
|
220
|
+
X_arr[no_shortcut_indices_0, :],
|
|
221
|
+
optimize=True,
|
|
222
|
+
)
|
|
223
|
+
no_shortcut_indices = no_shortcut_indices[len_no_shortcut_indices_0:]
|
|
224
|
+
|
|
225
|
+
if len(no_shortcut_indices) > 0:
|
|
226
|
+
A_arr = A_arr[len_no_shortcut_indices_0:]
|
|
227
|
+
A_arr[:, :N, N:] = -A_arr[:, N:, :N]
|
|
228
|
+
A_arr[:, :N, :N] = -A_arr[:, N:, N:]
|
|
229
|
+
A_arr.reshape(-1, NQuad * NQuad)[:, ::NQuad + 1] += 1 / mu0
|
|
230
|
+
# Note that the minus sign has been absorbed into `X_arr`
|
|
231
|
+
B_collect[no_shortcut_indices, :] = np.linalg.solve(A_arr, X_arr[no_shortcut_indices, :, None]).squeeze(-1)
|
|
216
232
|
|
|
217
233
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
218
234
|
|
|
@@ -98,7 +98,7 @@ def pydisort(
|
|
|
98
98
|
Returns the diffuse flux magnitudes (same type and size as ``tau``).
|
|
99
99
|
Pass ``is_antiderivative_wrt_tau = True`` (defaults to ``False``)
|
|
100
100
|
to switch to an antiderivative of this function with respect to ``tau``.
|
|
101
|
-
For example, ``Fp(tau_arr,
|
|
101
|
+
For example, ``Fp(tau_arr, True) - Fp(np.insert(tau_arr[:-1] + 1e-15, 0, 0), True)``
|
|
102
102
|
will produce an array of the tau-integral over each layer.
|
|
103
103
|
Pass ``return_tau_arr`` to return ``tau_arr`` (defaults to ``False``).
|
|
104
104
|
Fm(tau) : function
|
|
@@ -451,40 +451,33 @@ def pydisort(
|
|
|
451
451
|
|
|
452
452
|
neg_scaled_tau_div_mu0 = -scaled_tau / mu0
|
|
453
453
|
if is_antiderivative_wrt_tau:
|
|
454
|
-
|
|
455
|
-
scale_tau_l = scale_tau[
|
|
454
|
+
|
|
455
|
+
scale_tau_l = scale_tau[l_uniq]
|
|
456
456
|
neg_scale_tau_l_div_mu0 = -scale_tau_l / mu0
|
|
457
|
-
scale_tau_l_div_mu_arr_pos = scale_tau_l / mu_arr_pos[:, None]
|
|
458
|
-
|
|
457
|
+
scale_tau_l_div_mu_arr_pos = scale_tau_l[None, :] / mu_arr_pos[:, None]
|
|
458
|
+
|
|
459
459
|
TMS_correction_pos = (
|
|
460
|
-
np.exp(neg_scaled_tau_div_mu0)
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
)
|
|
460
|
+
np.exp(neg_scaled_tau_div_mu0) / neg_scale_tau_l_div_mu0[l_inv]
|
|
461
|
+
)[None, :] - np.exp(
|
|
462
|
+
(scaled_tau - scaled_tau_arr_l)[None, :] / mu_arr_pos[:, None]
|
|
463
|
+
- scaled_tau_arr_l[None, :] / mu0
|
|
464
|
+
) / scale_tau_l_div_mu_arr_pos[:, l_inv]
|
|
466
465
|
TMS_correction_neg = (
|
|
467
|
-
np.exp(neg_scaled_tau_div_mu0)
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
)
|
|
466
|
+
np.exp(neg_scaled_tau_div_mu0) / neg_scale_tau_l_div_mu0[l_inv]
|
|
467
|
+
)[None, :] + np.exp(
|
|
468
|
+
(scaled_tau_arr_lm1 - scaled_tau)[None, :] / mu_arr_pos[:, None]
|
|
469
|
+
- scaled_tau_arr_lm1[None, :] / mu0
|
|
470
|
+
) / scale_tau_l_div_mu_arr_pos[:, l_inv]
|
|
473
471
|
else:
|
|
474
|
-
TMS_correction_pos = (
|
|
475
|
-
|
|
476
|
-
-
|
|
477
|
-
(scaled_tau - scaled_tau_arr_l)[None, :] / mu_arr_pos[:, None]
|
|
478
|
-
- scaled_tau_arr_l[None, :] / mu0
|
|
479
|
-
)
|
|
472
|
+
TMS_correction_pos = np.exp(neg_scaled_tau_div_mu0)[None, :] - np.exp(
|
|
473
|
+
(scaled_tau - scaled_tau_arr_l)[None, :] / mu_arr_pos[:, None]
|
|
474
|
+
- scaled_tau_arr_l[None, :] / mu0
|
|
480
475
|
)
|
|
481
|
-
TMS_correction_neg = (
|
|
482
|
-
|
|
483
|
-
-
|
|
484
|
-
(scaled_tau_arr_lm1 - scaled_tau)[None, :] / mu_arr_pos[:, None]
|
|
485
|
-
- scaled_tau_arr_lm1[None, :] / mu0
|
|
486
|
-
)
|
|
476
|
+
TMS_correction_neg = np.exp(neg_scaled_tau_div_mu0)[None, :] - np.exp(
|
|
477
|
+
(scaled_tau_arr_lm1 - scaled_tau)[None, :] / mu_arr_pos[:, None]
|
|
478
|
+
- scaled_tau_arr_lm1[None, :] / mu0
|
|
487
479
|
)
|
|
480
|
+
|
|
488
481
|
|
|
489
482
|
## Contribution from other layers
|
|
490
483
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
@@ -525,13 +518,13 @@ def pydisort(
|
|
|
525
518
|
# POS: pre-accumulate "contribution from below" sums Rpos[N, l, Nphi]
|
|
526
519
|
# ====================================================================
|
|
527
520
|
if any_pos:
|
|
528
|
-
# fac_pos = 1 - exp(-scaled_thickness_arr*(1/mu + 1/mu0)) = -expm1(-thickness_pos)
|
|
529
521
|
thickness_pos = scaled_thickness_arr[None, :] * (M_inv + mu0_inv)[:, None] # (N, NLayers); always > 0
|
|
530
|
-
|
|
522
|
+
# em1_pos = 1 - exp(-scaled_thickness_arr*(1/mu + 1/mu0)) = -expm1(-thickness_pos)
|
|
523
|
+
em1_pos = -np.expm1(-thickness_pos) # (N, NLayers)
|
|
531
524
|
if is_antiderivative_wrt_tau:
|
|
532
|
-
|
|
525
|
+
em1_pos = integration_factor * em1_pos
|
|
533
526
|
|
|
534
|
-
layer_term_pos =
|
|
527
|
+
layer_term_pos = em1_pos * exp_taufront_mu0_inv[None, :] # (N, NLayers)
|
|
535
528
|
|
|
536
529
|
# Reverse-scan via cumsum:
|
|
537
530
|
# Rpos[l] = (1/decay_prod[l+1]) * sum_{r=l+1..} (layer_term_pos[r] * decay_prod[r])
|
|
@@ -566,12 +559,12 @@ def pydisort(
|
|
|
566
559
|
exp_x0 = decay * exp_taufront_mu0_inv[None, :] # (N, NLayers)
|
|
567
560
|
|
|
568
561
|
# Let a = |thickness_neg| >= 0. Then expm1(-a) uses only non-positive inputs.
|
|
569
|
-
|
|
562
|
+
em1_neg = np.expm1(-np.abs(thickness_neg)) # (N, NLayers)
|
|
570
563
|
|
|
571
|
-
# thickness_neg>=0: exp_x1 * (1 - exp(-a)) = exp_x1 * (-expm1(-a)) = exp_x1 * (-
|
|
572
|
-
# thickness_neg<0 : exp_x0 * (exp(-a) - 1) = exp_x0 * expm1(-a) = exp_x0 * (
|
|
573
|
-
layer_term_negthick =
|
|
574
|
-
layer_term_posthick = -
|
|
564
|
+
# thickness_neg>=0: exp_x1 * (1 - exp(-a)) = exp_x1 * (-expm1(-a)) = exp_x1 * (-em1_neg)
|
|
565
|
+
# thickness_neg<0 : exp_x0 * (exp(-a) - 1) = exp_x0 * expm1(-a) = exp_x0 * ( em1_neg)
|
|
566
|
+
layer_term_negthick = em1_neg * exp_x0 # (N, NLayers)
|
|
567
|
+
layer_term_posthick = -em1_neg * exp_x1 # (N, NLayers)
|
|
575
568
|
layer_term_neg = layer_term_posthick * mask + layer_term_negthick * (~mask) # (N, NLayers)
|
|
576
569
|
|
|
577
570
|
if is_antiderivative_wrt_tau:
|
|
@@ -489,8 +489,8 @@ def generate_emissivity_from_BDRF(N, zeroth_BDRF_Fourier_mode):
|
|
|
489
489
|
|
|
490
490
|
def cache_BDRF_Fourier_modes(N, BDRF_Fourier_modes, mu0=0):
|
|
491
491
|
"""If the same BDRF and number of streams will be used repeatedly,
|
|
492
|
-
consider using this function to cache ``BDRF_Fourier_modes`` and
|
|
493
|
-
``cached_BDRF_Fourier_modes``
|
|
492
|
+
consider using this function to cache ``BDRF_Fourier_modes`` and pass
|
|
493
|
+
``cached_BDRF_Fourier_modes`` to ``pydisort``. It is also possible
|
|
494
494
|
to cache ``BDRF_Fourier_modes`` with respect to a fixed ``mu0``.
|
|
495
495
|
|
|
496
496
|
Parameters
|
|
@@ -744,6 +744,7 @@ def to_diag_ordered_form(A, Nsuperdiags, Nsubdiags):
|
|
|
744
744
|
|
|
745
745
|
|
|
746
746
|
def _mathscr_v(tau, # Input optical depths
|
|
747
|
+
scale_tau, # Delta-scale factor for tau
|
|
747
748
|
l, # Layer index of each input optical depth
|
|
748
749
|
Nscoeffs, # Number of isotropic source polynomial coefficients
|
|
749
750
|
s_poly_coeffs, # Polynomial coefficients of isotropic source
|
|
@@ -763,6 +764,7 @@ def _mathscr_v(tau, # Input optical depths
|
|
|
763
764
|
| Variable | Shape |
|
|
764
765
|
| ----------------------------- | ----------------------------------------- |
|
|
765
766
|
| ``tau`` | ``Ntau`` |
|
|
767
|
+
| ``scale_tau`` | `NLayers` |
|
|
766
768
|
| ``l`` | ``Ntau`` |
|
|
767
769
|
| ``Nscoeffs`` | scalar |
|
|
768
770
|
| ``s_poly_coeffs`` | ``NL x Nscoeffs`` |
|
|
@@ -784,13 +786,13 @@ def _mathscr_v(tau, # Input optical depths
|
|
|
784
786
|
if Nscoeffs == 1:
|
|
785
787
|
s0 = s_poly_coeffs[:, 0:1]
|
|
786
788
|
c0w = s0 * K_inv * G_inv_mu_inv # (NL, 1) * (NL, NQuad) -> (NL, NQuad)
|
|
789
|
+
|
|
790
|
+
d0 = np.einsum("lij, lj -> il", G, c0w, optimize=True)
|
|
787
791
|
|
|
788
792
|
if is_antiderivative_wrt_tau:
|
|
789
|
-
p0 = tau
|
|
793
|
+
p0 = tau / scale_tau
|
|
790
794
|
else:
|
|
791
795
|
p0 = np.ones_like(tau)
|
|
792
|
-
|
|
793
|
-
d0 = np.einsum("lij, lj -> il", G, c0w, optimize=True)
|
|
794
796
|
|
|
795
797
|
return d0[:, l] * p0[None, :]
|
|
796
798
|
|
|
@@ -803,19 +805,19 @@ def _mathscr_v(tau, # Input optical depths
|
|
|
803
805
|
|
|
804
806
|
c0w = s1 * K_inv * G_inv_mu_inv
|
|
805
807
|
c1w = (s0 * K_inv + s1 * K_inv2) * G_inv_mu_inv
|
|
808
|
+
|
|
809
|
+
d0 = np.einsum("lij, lj -> il", G, c0w, optimize=True) # (NQuad, NL)
|
|
810
|
+
d1 = np.einsum("lij, lj -> il", G, c1w, optimize=True) # (NQuad, NL)
|
|
806
811
|
|
|
807
812
|
if is_antiderivative_wrt_tau:
|
|
808
813
|
p0 = tau * tau / 2
|
|
809
814
|
p1 = tau
|
|
815
|
+
return (d0[:, l] * p0[None, :] + d1[:, l] * p1[None, :]) / scale_tau
|
|
810
816
|
else:
|
|
811
817
|
p0 = tau
|
|
812
818
|
p1 = np.ones_like(tau)
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
d1 = np.einsum("lij, lj -> il", G, c1w, optimize=True) # (NQuad, NL)
|
|
816
|
-
|
|
817
|
-
return d0[:, l] * p0[None, :] + d1[:, l] * p1[None, :]
|
|
818
|
-
|
|
819
|
+
return d0[:, l] * p0[None, :] + d1[:, l] * p1[None, :]
|
|
820
|
+
|
|
819
821
|
# --------------------- Nscoeffs > 2 ----------------------
|
|
820
822
|
else:
|
|
821
823
|
if Nscoeffs > 10:
|
|
@@ -853,7 +855,7 @@ def _mathscr_v(tau, # Input optical depths
|
|
|
853
855
|
powers = np.arange(Nscoeffs - 1, -1, -1)[None, :]
|
|
854
856
|
if is_antiderivative_wrt_tau:
|
|
855
857
|
p = powers + 1
|
|
856
|
-
tau_poly = (tau[:, None] ** p) / p
|
|
858
|
+
tau_poly = (tau[:, None] ** p) / (p * scale_tau)
|
|
857
859
|
else:
|
|
858
860
|
tau_poly = tau[:, None] ** powers
|
|
859
861
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PythonicDISORT
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5
|
|
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
|
|
@@ -18,6 +18,7 @@ Provides-Extra: notebook-dependencies
|
|
|
18
18
|
Requires-Dist: autograd>=1.5; extra == "notebook-dependencies"
|
|
19
19
|
Requires-Dist: jupyter>1.0.0; extra == "notebook-dependencies"
|
|
20
20
|
Requires-Dist: notebook>6.5.2; extra == "notebook-dependencies"
|
|
21
|
+
Requires-Dist: matplotlib>=3.6.0; extra == "notebook-dependencies"
|
|
21
22
|
|
|
22
23
|
[](https://github.com/LDEO-CREW/Pythonic-DISORT/actions/workflows/continuous_integration.yml)
|
|
23
24
|
[](https://doi.org/10.21105/joss.06442)
|
|
@@ -70,6 +71,7 @@ These notebooks double up as examples of how to use PythonicDISORT. The tests wh
|
|
|
70
71
|
* Test Problem 8: Absorbing / Isotropic-Scattering Medium (multiple layers)
|
|
71
72
|
* Test Problem 9: General Emitting / Absorbing / Scattering Medium (multiple layers)
|
|
72
73
|
* Test Problem 11: Single-Layer vs. Multiple Layers (no corresponding Jupyter Notebook)
|
|
74
|
+
* Test Problem I: Antiderivative / integration functionality (no corresponding Jupyter Notebook)
|
|
73
75
|
|
|
74
76
|
# Installation
|
|
75
77
|
|
|
@@ -81,15 +83,16 @@ These notebooks double up as examples of how to use PythonicDISORT. The tests wh
|
|
|
81
83
|
* Python 3.8+
|
|
82
84
|
* `numpy >= 1.8.0`
|
|
83
85
|
* `scipy >= 1.8.0`
|
|
86
|
+
* (OPTIONAL) `autograd >= 1.5` (`autograd` can be used to compute gradients of the output functions)
|
|
84
87
|
* (OPTIONAL) `pytest >= 6.2.5` (Required to use the command `pytest`, see *PyTest and examples of how to use PythonicDISORT*)
|
|
85
88
|
|
|
86
89
|
## (OPTIONAL) Additional requirements to run the Jupyter Notebook
|
|
87
|
-
* `autograd >= 1.5`
|
|
88
90
|
* `jupyter > 1.0.0`
|
|
89
91
|
* `notebook > 6.5.2`
|
|
90
92
|
* `matplotlib >= 3.6.0`
|
|
91
93
|
|
|
92
|
-
In addition, a F2PY-wrapped Stamnes' DISORT
|
|
94
|
+
In addition, a F2PY-wrapped Stamnes' DISORT or equivalent (https://github.com/kconnour/pyRT_DISORT may work)
|
|
95
|
+
is required to properly run the last section (section 6).
|
|
93
96
|
|
|
94
97
|
## Compatibility
|
|
95
98
|
|
|
@@ -127,3 +130,4 @@ Science and Technology Center (STC) (Award #2019625) under which this package wa
|
|
|
127
130
|
12) T. Nakajima and M. Tanaka. 1988. *Algorithms for radiative intensity calculations in moderately thick atmospheres using a truncation approximation.* https://www.sciencedirect.com/science/article/pii/0022407388900313.
|
|
128
131
|
|
|
129
132
|
13) Connour, Kyle and Wolff, Michael. 2020. *pyRT_DISORT: A pre-processing front-end to help make DISORT simulations easier in Python.* https://github.com/kconnour/pyRT_DISORT.
|
|
133
|
+
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|