PythonicDISORT 1.0.0__tar.gz → 1.0.2__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.0.0/src/PythonicDISORT.egg-info → pythonicdisort-1.0.2}/PKG-INFO +1 -1
- {pythonicdisort-1.0.0 → pythonicdisort-1.0.2}/pyproject.toml +1 -1
- {pythonicdisort-1.0.0 → pythonicdisort-1.0.2}/src/PythonicDISORT/_assemble_intensity_and_fluxes.py +1 -1
- {pythonicdisort-1.0.0 → pythonicdisort-1.0.2}/src/PythonicDISORT/_solve_for_coeffs.py +20 -14
- {pythonicdisort-1.0.0 → pythonicdisort-1.0.2}/src/PythonicDISORT/_solve_for_gen_and_part_sols.py +3 -3
- {pythonicdisort-1.0.0 → pythonicdisort-1.0.2}/src/PythonicDISORT/pydisort.py +11 -13
- {pythonicdisort-1.0.0 → pythonicdisort-1.0.2}/src/PythonicDISORT/subroutines.py +82 -61
- {pythonicdisort-1.0.0 → pythonicdisort-1.0.2/src/PythonicDISORT.egg-info}/PKG-INFO +1 -1
- {pythonicdisort-1.0.0 → pythonicdisort-1.0.2}/LICENSE.md +0 -0
- {pythonicdisort-1.0.0 → pythonicdisort-1.0.2}/README.md +0 -0
- {pythonicdisort-1.0.0 → pythonicdisort-1.0.2}/setup.cfg +0 -0
- {pythonicdisort-1.0.0 → pythonicdisort-1.0.2}/src/PythonicDISORT/__init__.py +0 -0
- {pythonicdisort-1.0.0 → pythonicdisort-1.0.2}/src/PythonicDISORT.egg-info/SOURCES.txt +0 -0
- {pythonicdisort-1.0.0 → pythonicdisort-1.0.2}/src/PythonicDISORT.egg-info/dependency_links.txt +0 -0
- {pythonicdisort-1.0.0 → pythonicdisort-1.0.2}/src/PythonicDISORT.egg-info/requires.txt +0 -0
- {pythonicdisort-1.0.0 → pythonicdisort-1.0.2}/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.0.
|
|
3
|
+
Version: 1.0.2
|
|
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
|
{pythonicdisort-1.0.0 → pythonicdisort-1.0.2}/src/PythonicDISORT/_assemble_intensity_and_fluxes.py
RENAMED
|
@@ -592,6 +592,6 @@ def _assemble_intensity_and_fluxes(
|
|
|
592
592
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
593
593
|
|
|
594
594
|
if only_flux:
|
|
595
|
-
return flux_up, flux_down, u0#, GC_collect_0, K_collect_0
|
|
595
|
+
return flux_up, flux_down, u0#, GC_collect_0, K_collect_0, B_collect_0
|
|
596
596
|
else:
|
|
597
597
|
return flux_up, flux_down, u0, u
|
|
@@ -82,12 +82,12 @@ def _solve_for_coeffs(
|
|
|
82
82
|
GC_collect = np.empty((NFourier, NLayers, NQuad, NQuad))
|
|
83
83
|
use_banded_solver = (NLayers >= use_banded_solver_NLayers)
|
|
84
84
|
if use_banded_solver:
|
|
85
|
-
|
|
85
|
+
Nsupsubdiags = 3 * N - 1 # The number of super-diagonals equals the number of sub-diagonals
|
|
86
86
|
|
|
87
87
|
# The following loops can easily be parallelized, but the speed-up is unlikely to be worth the overhead
|
|
88
88
|
for m in range(NFourier):
|
|
89
89
|
m_equals_0 = (m == 0)
|
|
90
|
-
|
|
90
|
+
there_is_BDRF_mode = (NBDRF > m)
|
|
91
91
|
|
|
92
92
|
G_collect_m = G_collect[m, :, :, :]
|
|
93
93
|
K_collect_m = K_collect[m, :, :]
|
|
@@ -97,14 +97,20 @@ def _solve_for_coeffs(
|
|
|
97
97
|
# Generate mathscr_D and mathscr_X (BDRF terms)
|
|
98
98
|
# Just for this part, refer to section 3.4.2 of the Comprehensive Documentation
|
|
99
99
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
100
|
-
if
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
100
|
+
if there_is_BDRF_mode:
|
|
101
|
+
BDRF_Fourier_modes_m = BDRF_Fourier_modes[m]
|
|
102
|
+
if np.isscalar(BDRF_Fourier_modes_m):
|
|
103
|
+
mathscr_D_neg = (1 + m_equals_0 * 1) * BDRF_Fourier_modes_m
|
|
104
|
+
R = mathscr_D_neg * mu_arr_pos_times_W[None, :]
|
|
105
|
+
if there_is_beam_source:
|
|
106
|
+
mathscr_X_pos = (mu0 * I0 / pi) * BDRF_Fourier_modes_m
|
|
107
|
+
else:
|
|
108
|
+
mathscr_D_neg = (1 + m_equals_0 * 1) * BDRF_Fourier_modes_m(mu_arr_pos, mu_arr_pos)
|
|
109
|
+
R = mathscr_D_neg * mu_arr_pos_times_W[None, :]
|
|
110
|
+
if there_is_beam_source:
|
|
111
|
+
mathscr_X_pos = (mu0 * I0 / pi) * BDRF_Fourier_modes_m(
|
|
112
|
+
mu_arr_pos, np.array([mu0])
|
|
113
|
+
)[:, 0]
|
|
108
114
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
109
115
|
|
|
110
116
|
# Assemble RHS
|
|
@@ -212,7 +218,7 @@ def _solve_for_coeffs(
|
|
|
212
218
|
* np.exp(-scaled_tau_arr_with_0 / mu0)[l_range, None]
|
|
213
219
|
).ravel()
|
|
214
220
|
|
|
215
|
-
if
|
|
221
|
+
if there_is_BDRF_mode:
|
|
216
222
|
RHS = (
|
|
217
223
|
np.concatenate(
|
|
218
224
|
[
|
|
@@ -260,7 +266,7 @@ def _solve_for_coeffs(
|
|
|
260
266
|
G_0_np
|
|
261
267
|
* np.exp(K_collect_m[0, :N] * scaled_tau_arr_with_0[1])[None, :]
|
|
262
268
|
)
|
|
263
|
-
if
|
|
269
|
+
if there_is_BDRF_mode:
|
|
264
270
|
LHS[-N:, -NQuad : -N] = (G_L_pn - R @ G_L_nn) * E_Lm1L[None, :]
|
|
265
271
|
LHS[-N:, -N:] = G_L_pp - R @ G_L_np
|
|
266
272
|
else:
|
|
@@ -298,8 +304,8 @@ def _solve_for_coeffs(
|
|
|
298
304
|
# Solve the system
|
|
299
305
|
if use_banded_solver:
|
|
300
306
|
C_m = sc.linalg.solve_banded(
|
|
301
|
-
(
|
|
302
|
-
to_diag_ordered_form(LHS,
|
|
307
|
+
(Nsupsubdiags, Nsupsubdiags),
|
|
308
|
+
to_diag_ordered_form(LHS, Nsupsubdiags, Nsupsubdiags),
|
|
303
309
|
RHS,
|
|
304
310
|
True,
|
|
305
311
|
True,
|
{pythonicdisort-1.0.0 → pythonicdisort-1.0.2}/src/PythonicDISORT/_solve_for_gen_and_part_sols.py
RENAMED
|
@@ -153,7 +153,7 @@ def _solve_for_gen_and_part_sols(
|
|
|
153
153
|
alpha_arr[ind, :, :] = alpha
|
|
154
154
|
beta_arr[ind, :, :] = beta
|
|
155
155
|
no_shortcut_indices.append(ind)
|
|
156
|
-
if m_equals_0 and there_is_iso_source:
|
|
156
|
+
if m_equals_0 and there_is_iso_source: # Keep the list empty if there is no isotropic source
|
|
157
157
|
no_shortcut_indices_0.append(l)
|
|
158
158
|
|
|
159
159
|
else:
|
|
@@ -192,7 +192,7 @@ def _solve_for_gen_and_part_sols(
|
|
|
192
192
|
/ K_arr[:, None, :]
|
|
193
193
|
)
|
|
194
194
|
|
|
195
|
-
# Eigenvector
|
|
195
|
+
# Eigenvector matrices
|
|
196
196
|
G_arr = np.concatenate(
|
|
197
197
|
(
|
|
198
198
|
(eigenvecs_GpG_arr - eigenvecs_GmG_arr) / 2,
|
|
@@ -203,7 +203,7 @@ def _solve_for_gen_and_part_sols(
|
|
|
203
203
|
|
|
204
204
|
G_collect[no_shortcut_indices, :, :] = G_arr
|
|
205
205
|
K_collect[no_shortcut_indices, :] = K_arr
|
|
206
|
-
if len(no_shortcut_indices_0) > 0:
|
|
206
|
+
if len(no_shortcut_indices_0) > 0: # If there is no isotropic source this list will be empty
|
|
207
207
|
G_inv_collect_0[no_shortcut_indices_0, :, :] = np.linalg.inv(
|
|
208
208
|
G_collect[: len(no_shortcut_indices_0), :, :]
|
|
209
209
|
)
|
|
@@ -44,7 +44,7 @@ def pydisort(
|
|
|
44
44
|
omega_arr : array or float
|
|
45
45
|
Single-scattering albedo of each atmospheric layer.
|
|
46
46
|
NQuad : int
|
|
47
|
-
Number of ``mu`` quadrature nodes.
|
|
47
|
+
Number of ``mu`` quadrature nodes, i.e. number of streams.
|
|
48
48
|
Leg_coeffs_all : 2darray
|
|
49
49
|
All available unweighted phase function Legendre coefficients.
|
|
50
50
|
Each row pertains to an atmospheric layer (from top to bottom).
|
|
@@ -61,10 +61,10 @@ def pydisort(
|
|
|
61
61
|
NFourier : optional, int
|
|
62
62
|
Number of Fourier modes to use to construct the intensity function.
|
|
63
63
|
b_pos : optional, 2darray or float
|
|
64
|
-
Dirichlet boundary
|
|
64
|
+
Dirichlet condition at the bottom boundary for the upward direction.
|
|
65
65
|
Each column pertains to a Fourier mode (ascending order).
|
|
66
66
|
b_neg : optional, 2darray or float
|
|
67
|
-
Dirichlet boundary
|
|
67
|
+
Dirichlet condition at the top boundary for the downward direction.
|
|
68
68
|
Each column pertains to a Fourier mode (ascending order).
|
|
69
69
|
only_flux : optional, bool
|
|
70
70
|
Do NOT compute the intensity function?
|
|
@@ -76,8 +76,8 @@ def pydisort(
|
|
|
76
76
|
NT_cor : optional, bool
|
|
77
77
|
Perform Nakajima-Tanaka intensity corrections?
|
|
78
78
|
BDRF_Fourier_modes : optional, list of functions
|
|
79
|
-
BDRF Fourier modes, each a function with arguments ``mu, -mu_p`` of type array
|
|
80
|
-
|
|
79
|
+
BDRF Fourier modes, each a scalar, or a function with arguments ``mu, -mu_p`` of type array
|
|
80
|
+
which output has the same dimensions as the outer product of the two arrays.
|
|
81
81
|
s_poly_coeffs : optional, array
|
|
82
82
|
Polynomial coefficients of isotropic internal sources.
|
|
83
83
|
Each row pertains to an atmospheric layer (from top to bottom).
|
|
@@ -86,7 +86,7 @@ def pydisort(
|
|
|
86
86
|
At or above how many atmospheric layers should ``scipy.linalg.solve_banded`` be used?
|
|
87
87
|
autograd_compatible : optional, bool
|
|
88
88
|
If ``True``, the autograd package: https://github.com/HIPS/autograd can be used to compute
|
|
89
|
-
the tau
|
|
89
|
+
the ``tau``-derivatives of the output functions but ``pydisort`` will be less efficient.
|
|
90
90
|
|
|
91
91
|
Returns
|
|
92
92
|
-------
|
|
@@ -97,9 +97,7 @@ def pydisort(
|
|
|
97
97
|
Returns the diffuse flux magnitudes (same type and size as ``tau``).
|
|
98
98
|
Pass ``is_antiderivative_wrt_tau = True`` (defaults to ``False``)
|
|
99
99
|
to switch to an antiderivative of the function with respect to ``tau``.
|
|
100
|
-
For example, ``Fp(
|
|
101
|
-
will produce the tau-integral over ``[1, 0]`` assuming both values belong to the same layer, and
|
|
102
|
-
``Fp(tau_arr, is_antiderivative_wrt_tau = True) - Fp(np.insert(tau_arr[:-1] + 1e-15, 0, 0), is_antiderivative_wrt_tau = True)``
|
|
100
|
+
For example, ``Fp(tau_arr, is_antiderivative_wrt_tau = True) - Fp(np.insert(tau_arr[:-1] + 1e-15, 0, 0), is_antiderivative_wrt_tau = True)``
|
|
103
101
|
will produce an array of the tau-integral over each layer.
|
|
104
102
|
Pass ``return_tau_arr`` to return ``tau_arr`` (defaults to ``False``).
|
|
105
103
|
Fm(tau) : function
|
|
@@ -234,8 +232,8 @@ def pydisort(
|
|
|
234
232
|
raise ValueError("The number of phase function Legendre coefficients must be positive.")
|
|
235
233
|
if not np.all(omega_arr * Leg_coeffs_all[:, 0] == omega_arr):
|
|
236
234
|
raise ValueError("The first phase function Legendre coefficient must equal 1.")
|
|
237
|
-
if not (np.all(
|
|
238
|
-
raise ValueError("The phase function Legendre coefficients must all be between
|
|
235
|
+
if not (np.all(-1 <= Leg_coeffs_all) and np.all(Leg_coeffs_all <= 1)):
|
|
236
|
+
raise ValueError("The phase function Legendre coefficients must all be between -1 and 1.")
|
|
239
237
|
if not NLeg <= NLeg_all:
|
|
240
238
|
raise ValueError("`NLeg` cannot be larger than the number of phase function Legendre coefficients provided.")
|
|
241
239
|
# Ensure that the first dimension of the following inputs corresponds to the number of layers
|
|
@@ -265,9 +263,9 @@ def pydisort(
|
|
|
265
263
|
if I0 < 0:
|
|
266
264
|
raise ValueError("The incident beam must have positive intensity.")
|
|
267
265
|
if there_is_beam_source:
|
|
268
|
-
if not 0 < mu0 and mu0 <= 1:
|
|
266
|
+
if not (0 < mu0 and mu0 <= 1):
|
|
269
267
|
raise ValueError("The cosine of the polar angle of the incident beam must be between 0 and 1, excluding 0.")
|
|
270
|
-
if not 0 <= phi0 and phi0 < 2 * pi:
|
|
268
|
+
if not (0 <= phi0 and phi0 < 2 * pi):
|
|
271
269
|
raise ValueError("Provide the principal azimuthal angle for the incident beam (must be between 0 and 2pi, excluding 2pi).")
|
|
272
270
|
# Ensure that the BC inputs are of the correct shape
|
|
273
271
|
if len(np.atleast_1d(b_pos)) == 1:
|
|
@@ -299,14 +299,14 @@ def Planck(T, WVNM):
|
|
|
299
299
|
|
|
300
300
|
Parameters
|
|
301
301
|
----------
|
|
302
|
-
T : float or
|
|
302
|
+
T : float or array
|
|
303
303
|
Temperatures in kelvin.
|
|
304
304
|
WVNM : float
|
|
305
305
|
Wavenumber with units m^-1.
|
|
306
306
|
|
|
307
307
|
Returns
|
|
308
308
|
-------
|
|
309
|
-
float or
|
|
309
|
+
float or array
|
|
310
310
|
Emitted power per unit area from a blackbody surface with units W / m^2.
|
|
311
311
|
|
|
312
312
|
"""
|
|
@@ -325,14 +325,15 @@ def Planck(T, WVNM):
|
|
|
325
325
|
|
|
326
326
|
|
|
327
327
|
def blackbody_contrib_to_BCs(T, WVNMLO, WVNMHI, **kwargs):
|
|
328
|
-
"""Compute blackbody contribution to
|
|
328
|
+
"""Compute blackbody contribution to each BC (``b_pos`` or ``b_neg``),
|
|
329
|
+
i.e. the blackbody emission of that boundary, with units W / m^2.
|
|
329
330
|
This convenience function is provided to help match the inputs for Stamnes' DISORT to those for PythonicDISORT.
|
|
330
331
|
Users will have to manually adjust emissivities but ``PythonicDISORT.subroutines.generate_emissivity_from_BDRF``
|
|
331
332
|
can help with that.
|
|
332
333
|
|
|
333
334
|
Parameters
|
|
334
335
|
----------
|
|
335
|
-
T : float or
|
|
336
|
+
T : float or array
|
|
336
337
|
Temperatures in kelvin.
|
|
337
338
|
WVNMLO : float
|
|
338
339
|
Lower bound of wavenumber interval with units m^-1. This variable is identically named in Stamnes' DISORT.
|
|
@@ -341,6 +342,10 @@ def blackbody_contrib_to_BCs(T, WVNMLO, WVNMHI, **kwargs):
|
|
|
341
342
|
**kwargs
|
|
342
343
|
Keyword arguments to pass to ``scipy.integrate.quad_vec``.
|
|
343
344
|
|
|
345
|
+
Returns
|
|
346
|
+
-------
|
|
347
|
+
float or array
|
|
348
|
+
The blackbody emission of each boundary with units W / m^2.
|
|
344
349
|
"""
|
|
345
350
|
return np.squeeze(sc.integrate.quad_vec(lambda WVNM: Planck(T, WVNM), WVNMLO, WVNMHI, **kwargs)[0])
|
|
346
351
|
|
|
@@ -351,15 +356,15 @@ def linear_spline_coefficients(x, y, check_inputs=True):
|
|
|
351
356
|
|
|
352
357
|
Parameters
|
|
353
358
|
----------
|
|
354
|
-
x :
|
|
359
|
+
x : array
|
|
355
360
|
Array of `x` data points.
|
|
356
|
-
y :
|
|
361
|
+
y : array
|
|
357
362
|
Array of `y` data points.
|
|
358
363
|
|
|
359
364
|
Returns
|
|
360
365
|
-------
|
|
361
366
|
2darray
|
|
362
|
-
The coefficients with axes (segment, ascending polynomial order)
|
|
367
|
+
The coefficients with axes (segment, ascending polynomial order) which is required by ``pydisort``.
|
|
363
368
|
|
|
364
369
|
"""
|
|
365
370
|
# Input checks
|
|
@@ -379,15 +384,16 @@ def linear_spline_coefficients(x, y, check_inputs=True):
|
|
|
379
384
|
|
|
380
385
|
|
|
381
386
|
def generate_s_poly_coeffs(tau_arr, TEMPER, WVNMLO, WVNMHI, **kwargs):
|
|
382
|
-
"""Generate ``s_poly_coeffs``
|
|
383
|
-
This convenience function is provided to help match the inputs for Stamnes' DISORT to those for PythonicDISORT
|
|
384
|
-
|
|
387
|
+
"""Generate DISORT-equivalent ``s_poly_coeffs`` for input into ``pydisort``.
|
|
388
|
+
This convenience function is provided to help match the inputs for Stamnes' DISORT to those for PythonicDISORT.
|
|
389
|
+
Users will have to manually adjust emissivities, however, and they should note that PythonicDISORT allows much
|
|
390
|
+
more flexibility in choosing blackbody emission profiles than DISORT.
|
|
385
391
|
|
|
386
392
|
Parameters
|
|
387
393
|
----------
|
|
388
394
|
tau_arr : array or float
|
|
389
395
|
Optical depth of the lower boundary of each atmospheric layer.
|
|
390
|
-
TEMPER :
|
|
396
|
+
TEMPER : array
|
|
391
397
|
Temperature in kelvin at each boundary / interface from top to bottom.
|
|
392
398
|
This variable is identically named in Stamnes' DISORT.
|
|
393
399
|
WVNMLO : float
|
|
@@ -419,7 +425,7 @@ def generate_s_poly_coeffs(tau_arr, TEMPER, WVNMLO, WVNMHI, **kwargs):
|
|
|
419
425
|
def generate_emissivity_from_BDRF(N, zeroth_BDRF_Fourier_mode):
|
|
420
426
|
"""Use Kirchoff's law of thermal radiation to determine the (directional) emissivity
|
|
421
427
|
of the surface given the zeroth Fourier mode of the Bi-Directional Reflectance Function (BDRF).
|
|
422
|
-
This computation is internal to Stamnes' DISORT.
|
|
428
|
+
This computation is automatic and internal to Stamnes' DISORT.
|
|
423
429
|
This function supplements ``PythonicDISORT.subroutines.blackbody_contrib_to_BCs``.
|
|
424
430
|
|
|
425
431
|
Parameters
|
|
@@ -432,8 +438,8 @@ def generate_emissivity_from_BDRF(N, zeroth_BDRF_Fourier_mode):
|
|
|
432
438
|
|
|
433
439
|
Returns
|
|
434
440
|
-------
|
|
435
|
-
|
|
436
|
-
Emissivity for the blackbody contribution to the lower boundary source
|
|
441
|
+
array
|
|
442
|
+
Emissivity for the blackbody contribution to the lower boundary source ``b_neg``.
|
|
437
443
|
"""
|
|
438
444
|
mu_arr_pos, W = Gauss_Legendre_quad(N)
|
|
439
445
|
return 1 - 2 * zeroth_BDRF_Fourier_mode(mu_arr_pos, mu_arr_pos) * mu_arr_pos[None, :] @ W
|
|
@@ -452,29 +458,41 @@ def cache_BDRF_Fourier_modes(N, mu0, BDRF_Fourier_modes):
|
|
|
452
458
|
mu0 : float
|
|
453
459
|
Cosine of polar angle of the incident beam.
|
|
454
460
|
BDRF_Fourier_modes : list of functions
|
|
455
|
-
BDRF Fourier modes, each a function with arguments ``mu, -mu_p`` of type array
|
|
456
|
-
|
|
461
|
+
BDRF Fourier modes, each a scalar, or a function with arguments ``mu, -mu_p`` of type array
|
|
462
|
+
which output has the same dimensions as the outer product of the two arrays.
|
|
457
463
|
|
|
458
464
|
Returns
|
|
459
465
|
-------
|
|
460
466
|
cached_BDRF_Fourier_modes : list of functions
|
|
461
467
|
Cached BDRF Fourier modes, each a function with arguments ``mu, -mu_p`` of type array
|
|
462
|
-
and which output
|
|
468
|
+
and which output is a scalar (if the Fourier mode was a scalar)
|
|
469
|
+
or has the same dimensions as the outer product of the two arrays.
|
|
463
470
|
"""
|
|
464
471
|
NBDRF = len(BDRF_Fourier_modes)
|
|
465
472
|
mu_arr_pos = Gauss_Legendre_quad(N)[0]
|
|
466
473
|
|
|
467
|
-
|
|
468
|
-
|
|
474
|
+
[
|
|
475
|
+
(
|
|
476
|
+
None
|
|
477
|
+
if np.isscalar(BDRF_Fourier_modes[m])
|
|
478
|
+
else BDRF_Fourier_modes[m](mu_arr_pos, np.append(mu_arr_pos, mu0))
|
|
479
|
+
)
|
|
480
|
+
for m in range(NBDRF)
|
|
469
481
|
]
|
|
482
|
+
|
|
470
483
|
cached_BDRF_Fourier_modes = [
|
|
471
484
|
(
|
|
472
|
-
lambda mu, neg_mup, m=m:
|
|
473
|
-
if
|
|
474
|
-
else
|
|
485
|
+
lambda mu, neg_mup, m=m: BDRF_Fourier_modes[m]
|
|
486
|
+
if np.isscalar(BDRF_Fourier_modes[m])
|
|
487
|
+
else (
|
|
488
|
+
BDRF_Fourier_modes_evaluated[m][:, [-1]]
|
|
489
|
+
if len(neg_mup) == 1
|
|
490
|
+
else BDRF_Fourier_modes_evaluated[m][:, :-1]
|
|
491
|
+
)
|
|
475
492
|
)
|
|
476
493
|
for m in range(NBDRF)
|
|
477
494
|
]
|
|
495
|
+
|
|
478
496
|
return cached_BDRF_Fourier_modes
|
|
479
497
|
|
|
480
498
|
|
|
@@ -488,9 +506,9 @@ def affine_transform_poly_coeffs(poly_coeffs, a_arr, b_arr):
|
|
|
488
506
|
poly_coeffs : 2darray
|
|
489
507
|
Array with columns [C_0, C_1, ..., C_n].
|
|
490
508
|
The rows correspond to different affine transformations.
|
|
491
|
-
a_arr :
|
|
509
|
+
a_arr : array
|
|
492
510
|
Scale factors.
|
|
493
|
-
b_arr :
|
|
511
|
+
b_arr : array
|
|
494
512
|
Translations.
|
|
495
513
|
|
|
496
514
|
Returns
|
|
@@ -518,10 +536,11 @@ def affine_transform_poly_coeffs(poly_coeffs, a_arr, b_arr):
|
|
|
518
536
|
return np.einsum("lij, lj -> li", T, poly_coeffs, optimize=True)
|
|
519
537
|
|
|
520
538
|
|
|
539
|
+
|
|
521
540
|
def interpolate(u):
|
|
522
|
-
"""Polynomial (Barycentric) interpolation with respect to mu
|
|
523
|
-
is a function that is continuous and variable in all three arguments: mu
|
|
524
|
-
Discussed in sections 3.7 and 6.3
|
|
541
|
+
"""Polynomial (Barycentric) interpolation with respect to ``mu``. The output
|
|
542
|
+
is a function that is continuous and variable in all three arguments: ``mu``, ``tau`` and ``phi``.
|
|
543
|
+
Discussed in sections 3.7 and 6.3 of the Comprehensive Documentation.
|
|
525
544
|
|
|
526
545
|
Parameters
|
|
527
546
|
----------
|
|
@@ -611,22 +630,23 @@ def interpolate(u):
|
|
|
611
630
|
|
|
612
631
|
|
|
613
632
|
|
|
614
|
-
def to_diag_ordered_form(A,
|
|
633
|
+
def to_diag_ordered_form(A, Nsuperdiags, Nsubdiags):
|
|
615
634
|
"""
|
|
616
|
-
Convert
|
|
617
|
-
We assume that the matrix has the same number of super- and sub-diagonals.
|
|
635
|
+
Convert some matrix A to the diagonal ordered form required by ``scipy.linalg.solve_banded``.
|
|
618
636
|
|
|
619
637
|
Parameters
|
|
620
638
|
----------
|
|
621
639
|
A : 2darray
|
|
622
640
|
The square matrix to be converted.
|
|
623
|
-
|
|
624
|
-
The number of super-
|
|
641
|
+
Nsuperdiags : int
|
|
642
|
+
The number of super-diagonals.
|
|
643
|
+
Nsubdiags : int
|
|
644
|
+
The number of sub-diagonals.
|
|
625
645
|
|
|
626
646
|
Returns
|
|
627
647
|
-------
|
|
628
648
|
2darray
|
|
629
|
-
The diagonal ordered form matrix as required by solve_banded
|
|
649
|
+
The diagonal ordered form matrix as required by ``scipy.linalg.solve_banded``.
|
|
630
650
|
"""
|
|
631
651
|
n = A.shape[0]
|
|
632
652
|
indices = np.arange(n)
|
|
@@ -634,28 +654,29 @@ def to_diag_ordered_form(A, sym_offset):
|
|
|
634
654
|
return np.concatenate(
|
|
635
655
|
[
|
|
636
656
|
A[
|
|
637
|
-
indices - np.arange(
|
|
657
|
+
indices - np.arange(Nsuperdiags, -1, -1)[:, None],
|
|
638
658
|
indices[None, :],
|
|
639
659
|
],
|
|
640
660
|
A[
|
|
641
|
-
indices - np.arange(n - 1, n -
|
|
661
|
+
indices - np.arange(n - 1, n - Nsubdiags - 1, -1)[:, None],
|
|
642
662
|
indices[None, :],
|
|
643
663
|
],
|
|
644
664
|
],
|
|
645
665
|
axis=0,
|
|
646
666
|
)
|
|
647
667
|
|
|
668
|
+
|
|
648
669
|
|
|
649
|
-
def _mathscr_v(tau,
|
|
650
|
-
l,
|
|
651
|
-
Nscoeffs,
|
|
652
|
-
s_poly_coeffs,
|
|
653
|
-
G,
|
|
654
|
-
K,
|
|
655
|
-
G_inv,
|
|
656
|
-
mu_arr,
|
|
670
|
+
def _mathscr_v(tau, # Input optical depths
|
|
671
|
+
l, # Layer index of each input optical depth
|
|
672
|
+
Nscoeffs, # Number of isotropic source polynomial coefficients
|
|
673
|
+
s_poly_coeffs, # Polynomial coefficients of isotropic source
|
|
674
|
+
G, # Eigenvector matrices
|
|
675
|
+
K, # Eigenvalues
|
|
676
|
+
G_inv, # Inverse of eigenvector matrix
|
|
677
|
+
mu_arr, # Quadrature nodes for both hemispheres
|
|
657
678
|
is_antiderivative_wrt_tau=False, # Switch to an antiderivative of the function?
|
|
658
|
-
autograd_compatible=False,
|
|
679
|
+
autograd_compatible=False, # Should the output functions be compatible with autograd?
|
|
659
680
|
):
|
|
660
681
|
"""Particular solution for isotropic internal sources.
|
|
661
682
|
Refer to section 3.6.1 of the Comprehensive Documentation.
|
|
@@ -664,22 +685,22 @@ def _mathscr_v(tau, # Input optical depths
|
|
|
664
685
|
and ``_solve_for_coeffs`` functions which call it.
|
|
665
686
|
|
|
666
687
|
Arguments of _mathscr_v
|
|
667
|
-
| Variable
|
|
668
|
-
|
|
|
669
|
-
| ``tau`` | ``Ntau``
|
|
670
|
-
| ``l`` | ``Ntau``
|
|
671
|
-
| ``Nscoeffs`` | scalar
|
|
672
|
-
| ``s_poly_coeffs`` | ``NLayers x Nscoeffs``
|
|
673
|
-
| ``G`` | ``NLayers<= x NQuad x NQuad``
|
|
674
|
-
| ``K`` | ``NLayers<= x NQuad``
|
|
688
|
+
| Variable | Shape |
|
|
689
|
+
| ----------------------------- | ----------------------------------------- |
|
|
690
|
+
| ``tau`` | ``Ntau`` |
|
|
691
|
+
| ``l`` | ``Ntau`` |
|
|
692
|
+
| ``Nscoeffs`` | scalar |
|
|
693
|
+
| ``s_poly_coeffs`` | ``NLayers x Nscoeffs`` |
|
|
694
|
+
| ``G`` | ``NLayers<= x NQuad x NQuad`` |
|
|
695
|
+
| ``K`` | ``NLayers<= x NQuad`` |
|
|
675
696
|
| ``G_inv`` | ``NLayers<= x NQuad x NQuad`` or ``None`` |
|
|
676
|
-
| ``mu_arr`` | ``NQuad``
|
|
677
|
-
| ``is_antiderivative_wrt_tau`` | boolean
|
|
678
|
-
| ``autograd_compatible``
|
|
697
|
+
| ``mu_arr`` | ``NQuad`` |
|
|
698
|
+
| ``is_antiderivative_wrt_tau`` | boolean |
|
|
699
|
+
| ``autograd_compatible`` | boolean |
|
|
679
700
|
|
|
680
701
|
Notable internal variables of _mathscr_v
|
|
681
|
-
| Variable | Shape
|
|
682
|
-
| ---------------- |
|
|
702
|
+
| Variable | Shape |
|
|
703
|
+
| ---------------- | ------------------------------------- |
|
|
683
704
|
| i_arr | ``Nscoeffs`` |
|
|
684
705
|
| i_arr_repeat | ``Nscoeffs*(Nscoeffs+1)/2`` | Using triangular number formula
|
|
685
706
|
| j_arr | ``Nscoeffs*(Nscoeffs+1)/2`` | Using triangular number formula
|
|
@@ -694,8 +715,8 @@ def _mathscr_v(tau, # Input optical depths
|
|
|
694
715
|
def mathscr_b(i):
|
|
695
716
|
"""
|
|
696
717
|
Notable internal variables of mathscr_b
|
|
697
|
-
| Variable |
|
|
698
|
-
| ---------------- |
|
|
718
|
+
| Variable | Shape |
|
|
719
|
+
| ---------------- | --------------------------------------- |
|
|
699
720
|
| j_arr | ``i + 1`` |
|
|
700
721
|
| s_poly_coeffs_nj | ``i + 1`` |
|
|
701
722
|
| OUTPUT | ``Nscoeffs x (i + 1) x NQuad`` |
|
|
@@ -716,7 +737,7 @@ def _mathscr_v(tau, # Input optical depths
|
|
|
716
737
|
shape = np.shape(K)
|
|
717
738
|
i_arr = np.arange(Nscoeffs)
|
|
718
739
|
i_arr_repeat = np.repeat(i_arr, i_arr + 1)
|
|
719
|
-
j_arr = np.concatenate([
|
|
740
|
+
j_arr = np.concatenate([i_arr[:i] for i in range(1, Nscoeffs + 1)])
|
|
720
741
|
s_poly_coeffs_nj = s_poly_coeffs[:, n - j_arr]
|
|
721
742
|
|
|
722
743
|
mathscr_v_coeffs = np.zeros((Nscoeffs, shape[0], shape[1]))
|
|
@@ -752,7 +773,7 @@ def _mathscr_v(tau, # Input optical depths
|
|
|
752
773
|
|
|
753
774
|
def _compare(results, mu_to_compare, reorder_mu, flux_up, flux_down, u=None):
|
|
754
775
|
"""Performs pointwise comparisons between results from Stamnes' DISORT,
|
|
755
|
-
which are stored in
|
|
776
|
+
which are stored in ``.npz`` files, against results from PythonicDISORT. Used in our PyTests.
|
|
756
777
|
|
|
757
778
|
"""
|
|
758
779
|
# Load saved results from Stamnes' DISORT
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PythonicDISORT
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.2
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{pythonicdisort-1.0.0 → pythonicdisort-1.0.2}/src/PythonicDISORT.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|