PythonicDISORT 0.2.4__py3-none-any.whl → 0.4.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/_loop_and_assemble_results.py +4 -4
- PythonicDISORT/_one_Fourier_mode.py +83 -76
- PythonicDISORT/pydisort.py +15 -18
- PythonicDISORT/subroutines.py +33 -2
- {PythonicDISORT-0.2.4.dist-info → PythonicDISORT-0.4.0.dist-info}/METADATA +3 -3
- PythonicDISORT-0.4.0.dist-info/RECORD +9 -0
- PythonicDISORT-0.2.4.dist-info/RECORD +0 -9
- {PythonicDISORT-0.2.4.dist-info → PythonicDISORT-0.4.0.dist-info}/WHEEL +0 -0
- {PythonicDISORT-0.2.4.dist-info → PythonicDISORT-0.4.0.dist-info}/top_level.txt +0 -0
|
@@ -15,7 +15,7 @@ def _loop_and_assemble_results(
|
|
|
15
15
|
N, NQuad, NLeg, NLoops,
|
|
16
16
|
NLayers, NBDRF,
|
|
17
17
|
weighted_scaled_Leg_coeffs,
|
|
18
|
-
|
|
18
|
+
BDRF_Fourier_modes,
|
|
19
19
|
mu0, I0, I0_orig, phi0,
|
|
20
20
|
b_pos, b_neg,
|
|
21
21
|
scalar_b_pos, scalar_b_neg,
|
|
@@ -46,7 +46,7 @@ def _loop_and_assemble_results(
|
|
|
46
46
|
N, NQuad, NLeg,
|
|
47
47
|
NLayers, NBDRF,
|
|
48
48
|
weighted_scaled_Leg_coeffs,
|
|
49
|
-
|
|
49
|
+
BDRF_Fourier_modes,
|
|
50
50
|
mu0, I0,
|
|
51
51
|
b_pos, b_neg,
|
|
52
52
|
scalar_b_pos, scalar_b_neg,
|
|
@@ -91,7 +91,7 @@ def _loop_and_assemble_results(
|
|
|
91
91
|
N, NQuad, NLeg,
|
|
92
92
|
NLayers, NBDRF,
|
|
93
93
|
weighted_scaled_Leg_coeffs,
|
|
94
|
-
|
|
94
|
+
BDRF_Fourier_modes,
|
|
95
95
|
mu0, I0,
|
|
96
96
|
b_pos, b_neg,
|
|
97
97
|
scalar_b_pos, scalar_b_neg,
|
|
@@ -116,7 +116,7 @@ def _loop_and_assemble_results(
|
|
|
116
116
|
N, NQuad, NLeg,
|
|
117
117
|
NLayers, NBDRF,
|
|
118
118
|
weighted_scaled_Leg_coeffs,
|
|
119
|
-
|
|
119
|
+
BDRF_Fourier_modes,
|
|
120
120
|
mu0, I0,
|
|
121
121
|
b_pos, b_neg,
|
|
122
122
|
scalar_b_pos, scalar_b_neg,
|
|
@@ -15,7 +15,7 @@ def _one_Fourier_mode(
|
|
|
15
15
|
N, NQuad, NLeg,
|
|
16
16
|
NLayers, NBDRF,
|
|
17
17
|
weighted_scaled_Leg_coeffs,
|
|
18
|
-
|
|
18
|
+
BDRF_Fourier_modes,
|
|
19
19
|
mu0, I0,
|
|
20
20
|
b_pos, b_neg,
|
|
21
21
|
scalar_b_pos, scalar_b_neg,
|
|
@@ -45,45 +45,39 @@ def _one_Fourier_mode(
|
|
|
45
45
|
|
|
46
46
|
# Generate mathscr_D and mathscr_X (BDRF terms)
|
|
47
47
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
if m < NBDRF and np.all(np.isfinite(asso_leg_term_pos[:NBDRF, :])):
|
|
51
|
-
weighted_asso_Leg_coeffs_BDRF = (
|
|
52
|
-
weighted_Leg_coeffs_BDRF[ells[: (NBDRF - m)]] * fac[: (NBDRF - m)]
|
|
53
|
-
)
|
|
54
|
-
mathscr_D_temp = (
|
|
55
|
-
weighted_asso_Leg_coeffs_BDRF[None, :] * asso_leg_term_pos.T[:, :NBDRF]
|
|
56
|
-
)
|
|
57
|
-
mathscr_D_neg = 2 * mathscr_D_temp @ asso_leg_term_neg[:NBDRF, :]
|
|
48
|
+
if m < NBDRF:
|
|
49
|
+
mathscr_D_neg = (1 + (m == 0) * 1) * BDRF_Fourier_modes[m](mu_arr_pos, -mu_arr_pos)
|
|
58
50
|
R = mathscr_D_neg * (mu_arr_pos * W)[None, :]
|
|
59
51
|
|
|
60
52
|
if I0 > 0:
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
* asso_leg_term_mu0[:NBDRF]
|
|
65
|
-
)
|
|
66
|
-
mathscr_X_pos = mathscr_X_temp @ asso_leg_term_pos[:NBDRF, :]
|
|
53
|
+
mathscr_X_pos = (mu0 * I0 / pi) * BDRF_Fourier_modes[m](
|
|
54
|
+
mu_arr_pos, -np.array([mu0])
|
|
55
|
+
)[:, 0]
|
|
67
56
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
68
57
|
|
|
69
58
|
# Loop over NLayers atmospheric layers
|
|
70
59
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
71
60
|
if Nscoeffs > 0 and m == 0:
|
|
72
61
|
G_inv_collect_0 = np.empty((NLayers, NQuad, NQuad))
|
|
73
|
-
G_collect_m = np.empty((NLayers, NQuad, NQuad))
|
|
74
|
-
K_collect_m = np.empty((NLayers, NQuad))
|
|
75
62
|
if I0 > 0:
|
|
76
63
|
B_collect_m = np.zeros((NLayers, NQuad))
|
|
64
|
+
|
|
65
|
+
G_collect_m = np.empty((NLayers, NQuad, NQuad))
|
|
66
|
+
K_collect_m = np.empty((NLayers, NQuad))
|
|
67
|
+
alpha_list = []
|
|
68
|
+
beta_list = []
|
|
69
|
+
X_tilde_list=[]
|
|
70
|
+
if_indices = []
|
|
77
71
|
|
|
78
72
|
for l in range(NLayers):
|
|
79
73
|
# More setup
|
|
80
74
|
weighted_asso_Leg_coeffs_l = weighted_scaled_Leg_coeffs[l, :][ells] * fac
|
|
81
75
|
scaled_omega_l = scaled_omega_arr[l]
|
|
82
76
|
|
|
83
|
-
# We take precautions against overflow and underflow
|
|
77
|
+
# We take precautions against overflow and underflow (this shouldn't happen though)
|
|
84
78
|
if np.any(weighted_asso_Leg_coeffs_l > 0) and np.all(
|
|
85
79
|
np.isfinite(asso_leg_term_pos)
|
|
86
|
-
):
|
|
80
|
+
):
|
|
87
81
|
# Generate mathscr_D and mathscr_X (BDRF terms)
|
|
88
82
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
89
83
|
D_temp = weighted_asso_Leg_coeffs_l[None, :] * asso_leg_term_pos.T
|
|
@@ -104,63 +98,81 @@ def _one_Fourier_mode(
|
|
|
104
98
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
105
99
|
alpha = M_inv[:, None] * (D_pos * W[None, :] - np.eye(N))
|
|
106
100
|
beta = M_inv[:, None] * D_neg * W[None, :]
|
|
107
|
-
A = np.vstack([np.hstack([-alpha, -beta]), np.hstack([beta, alpha])])
|
|
108
|
-
if I0 > 0:
|
|
109
|
-
X_tilde = np.concatenate([-M_inv * X_pos, M_inv * X_neg])
|
|
110
|
-
# --------------------------------------------------------------------------------------------------------------------------
|
|
111
|
-
|
|
112
|
-
# Diagonalization of coefficient matrix
|
|
113
|
-
# --------------------------------------------------------------------------------------------------------------------------
|
|
114
|
-
K_squared, eigenvecs_GpG = np.linalg.eig((alpha - beta) @ (alpha + beta))
|
|
115
|
-
if m == 0:
|
|
116
|
-
if np.any(K_squared < 1e-9): # Then |K| < 1e-3
|
|
117
|
-
warn(
|
|
118
|
-
"Single-scattering albedo for layer "
|
|
119
|
-
+ str(l)
|
|
120
|
-
+ " (counting from 0) is too close to 1. Results may be inaccurate."
|
|
121
|
-
)
|
|
122
|
-
|
|
123
|
-
# Eigenvalues arranged negative then positive, from largest to smallest magnitude
|
|
124
|
-
K = np.concatenate([-np.sqrt(K_squared), np.sqrt(K_squared)])
|
|
125
|
-
eigenvecs_GpG = np.hstack([eigenvecs_GpG, eigenvecs_GpG])
|
|
126
|
-
eigenvecs_GmG = (alpha + beta) @ eigenvecs_GpG / K
|
|
127
|
-
|
|
128
|
-
# Eigenvector matrix
|
|
129
|
-
G_pos = (eigenvecs_GpG - eigenvecs_GmG) / 2
|
|
130
|
-
G_neg = (eigenvecs_GpG + eigenvecs_GmG) / 2
|
|
131
|
-
G = np.vstack([G_pos, G_neg])
|
|
132
|
-
# We only need G^{-1} in special cases
|
|
133
|
-
if Nscoeffs > 0 and m == 0:
|
|
134
|
-
G_inv = np.linalg.inv(G)
|
|
135
|
-
# --------------------------------------------------------------------------------------------------------------------------
|
|
136
|
-
|
|
137
|
-
# Particular solution for the sunbeam source
|
|
138
|
-
# --------------------------------------------------------------------------------------------------------------------------
|
|
139
101
|
if I0 > 0:
|
|
140
|
-
|
|
141
|
-
B = -G / (1 / mu0 + K)[None, :] @ G_inv @ X_tilde
|
|
142
|
-
else:
|
|
143
|
-
# This method is more numerically stable
|
|
144
|
-
LHS = A.copy()
|
|
145
|
-
np.fill_diagonal(LHS, 1 / mu0 + np.diag(A))
|
|
146
|
-
B = np.linalg.solve(LHS, -X_tilde)
|
|
147
|
-
|
|
148
|
-
B_collect_m[l, :] = B
|
|
102
|
+
X_tilde_list.append(np.concatenate([-M_inv * X_pos, M_inv * X_neg]))
|
|
149
103
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
104
|
+
|
|
105
|
+
if_indices.append(l)
|
|
106
|
+
alpha_list.append(alpha)
|
|
107
|
+
beta_list.append(beta)
|
|
108
|
+
|
|
150
109
|
else:
|
|
151
|
-
# This is a shortcut to the
|
|
152
|
-
K = -1 / mu_arr
|
|
110
|
+
# This is a shortcut to the diagonalization results
|
|
153
111
|
G = np.zeros((NQuad, NQuad))
|
|
154
112
|
G[N:, :N] = np.eye(N)
|
|
155
113
|
G[:N, N:] = np.eye(N)
|
|
114
|
+
|
|
115
|
+
G_collect_m[l, :, :] = G
|
|
116
|
+
K_collect_m[l, :] = -1 / mu_arr
|
|
156
117
|
if Nscoeffs > 0 and m == 0:
|
|
157
|
-
|
|
118
|
+
G_inv_collect_0[l, :, :] = G
|
|
119
|
+
|
|
120
|
+
if len(if_indices) > 0:
|
|
121
|
+
|
|
122
|
+
# Diagonalization of coefficient matrix
|
|
123
|
+
# --------------------------------------------------------------------------------------------------------------------------
|
|
124
|
+
alpha_list = np.atleast_3d(np.array(alpha_list))
|
|
125
|
+
beta_list = np.atleast_3d(np.array(beta_list))
|
|
126
|
+
|
|
127
|
+
K_squared_arr, eigenvecs_GpG_arr = np.linalg.eig(
|
|
128
|
+
np.einsum(
|
|
129
|
+
"lij, ljk -> lik", alpha_list - beta_list, alpha_list + beta_list, optimize=True
|
|
130
|
+
),
|
|
131
|
+
)
|
|
132
|
+
if m == 0:
|
|
133
|
+
if np.any(K_squared_arr < 1e-9): # Then |K| < 1e-3
|
|
134
|
+
warn(
|
|
135
|
+
"Some single-scattering albedos are too close to 1. Results may be inaccurate."
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
# Eigenvalues arranged negative then positive, from largest to smallest magnitude
|
|
139
|
+
K_arr = np.concatenate((-np.sqrt(K_squared_arr), np.sqrt(K_squared_arr)), axis=1)
|
|
140
|
+
eigenvecs_GpG_arr = np.concatenate((eigenvecs_GpG_arr, eigenvecs_GpG_arr), axis=2)
|
|
141
|
+
eigenvecs_GmG_arr = (
|
|
142
|
+
np.einsum(
|
|
143
|
+
"lij, ljk -> lik", alpha_list + beta_list, eigenvecs_GpG_arr, optimize=True
|
|
144
|
+
)
|
|
145
|
+
/ K_arr[:, None, :]
|
|
146
|
+
)
|
|
158
147
|
|
|
159
|
-
|
|
160
|
-
|
|
148
|
+
# Eigenvector matrix
|
|
149
|
+
G_arr = np.concatenate(
|
|
150
|
+
(
|
|
151
|
+
(eigenvecs_GpG_arr - eigenvecs_GmG_arr) / 2,
|
|
152
|
+
(eigenvecs_GpG_arr + eigenvecs_GmG_arr) / 2,
|
|
153
|
+
),
|
|
154
|
+
axis=1,
|
|
155
|
+
)
|
|
156
|
+
G_inv_arr = np.linalg.inv(G_arr)
|
|
157
|
+
|
|
158
|
+
G_collect_m[if_indices, :, :] = G_arr
|
|
159
|
+
K_collect_m[if_indices, :] = K_arr
|
|
161
160
|
if Nscoeffs > 0 and m == 0:
|
|
162
|
-
G_inv_collect_0[
|
|
163
|
-
|
|
161
|
+
G_inv_collect_0[if_indices, :, :] = G_inv_arr
|
|
162
|
+
# --------------------------------------------------------------------------------------------------------------------------
|
|
163
|
+
|
|
164
|
+
# Particular solution for the sunbeam source
|
|
165
|
+
# --------------------------------------------------------------------------------------------------------------------------
|
|
166
|
+
if I0 > 0:
|
|
167
|
+
X_tilde_list = np.atleast_2d(np.array(X_tilde_list))
|
|
168
|
+
B_collect_m[if_indices, :] = np.einsum(
|
|
169
|
+
"lij, ljk, lk -> li",
|
|
170
|
+
-G_arr / (1 / mu0 + K_arr)[:, None, :],
|
|
171
|
+
G_inv_arr,
|
|
172
|
+
X_tilde_list,
|
|
173
|
+
optimize=True,
|
|
174
|
+
)
|
|
175
|
+
# --------------------------------------------------------------------------------------------------------------------------
|
|
164
176
|
|
|
165
177
|
################################## Solve for coefficients of homogeneous solution ##########################################
|
|
166
178
|
|
|
@@ -243,7 +255,6 @@ def _one_Fourier_mode(
|
|
|
243
255
|
else:
|
|
244
256
|
_mathscr_v_contribution = 0
|
|
245
257
|
|
|
246
|
-
# If h_\ell = 0 for all \ell >= m, then there is no BDRF contribution
|
|
247
258
|
if I0 > 0:
|
|
248
259
|
if m < NBDRF:
|
|
249
260
|
BDRF_RHS_contribution = mathscr_X_pos + R @ B_collect_m[-1, N:]
|
|
@@ -279,11 +290,7 @@ def _one_Fourier_mode(
|
|
|
279
290
|
|
|
280
291
|
# Assemble LHS
|
|
281
292
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
282
|
-
|
|
283
|
-
if NLayers >= use_sparse_NLayers:
|
|
284
|
-
LHS = sc.sparse.lil_matrix((dim, dim))
|
|
285
|
-
else:
|
|
286
|
-
LHS = np.zeros((dim, dim))
|
|
293
|
+
LHS = np.zeros((NLayers * NQuad, NLayers * NQuad))
|
|
287
294
|
|
|
288
295
|
G_0_nn = G_collect_m[0, N:, :N]
|
|
289
296
|
G_0_np = G_collect_m[0, N:, N:]
|
|
@@ -343,7 +350,7 @@ def _one_Fourier_mode(
|
|
|
343
350
|
# Solve the system and return computations
|
|
344
351
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
345
352
|
if NLayers >= use_sparse_NLayers:
|
|
346
|
-
C_m = sc.sparse.linalg.spsolve(
|
|
353
|
+
C_m = sc.sparse.linalg.spsolve(sc.sparse.csr_matrix(LHS), RHS).reshape(NLayers, NQuad)
|
|
347
354
|
else:
|
|
348
355
|
C_m = np.linalg.solve(LHS, RHS).reshape(NLayers, NQuad)
|
|
349
356
|
|
PythonicDISORT/pydisort.py
CHANGED
|
@@ -22,9 +22,9 @@ def pydisort(
|
|
|
22
22
|
only_flux=False,
|
|
23
23
|
f_arr=0,
|
|
24
24
|
NT_cor=False,
|
|
25
|
-
|
|
25
|
+
BDRF_Fourier_modes=[],
|
|
26
26
|
s_poly_coeffs=np.array([[]]),
|
|
27
|
-
use_sparse_NLayers=
|
|
27
|
+
use_sparse_NLayers=13,
|
|
28
28
|
n_jobs=1
|
|
29
29
|
):
|
|
30
30
|
"""Solves the 1D RTE for the fluxes, and optionally intensity,
|
|
@@ -67,8 +67,9 @@ def pydisort(
|
|
|
67
67
|
Fractional scattering into peak for each atmospheric layer.
|
|
68
68
|
NT_cor : optional, bool
|
|
69
69
|
Perform Nakajima-Tanaka intensity corrections?
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
BDRF_Fourier_modes : optional, list
|
|
71
|
+
BDRF Fourier modes, each a function with arguments mu, -mup of type array
|
|
72
|
+
and which output has the same dimensions as the outer product of the two arrays.
|
|
72
73
|
s_poly_coeffs : optional, array
|
|
73
74
|
Polynomial coefficients of isotropic internal sources.
|
|
74
75
|
Arrange coefficients from lowest order term to highest.
|
|
@@ -85,19 +86,19 @@ def pydisort(
|
|
|
85
86
|
array
|
|
86
87
|
All mu (cosine of polar angle) quadrature nodes.
|
|
87
88
|
function
|
|
88
|
-
Flux function with argument tau (type: array) for positive (upward) mu values.
|
|
89
|
+
(Energetic) Flux function with argument tau (type: array) for positive (upward) mu values.
|
|
89
90
|
Returns the diffuse flux magnitudes (type: array).
|
|
90
91
|
function
|
|
91
|
-
Flux function with argument tau (type: array)
|
|
92
|
+
(Energetic) Flux function with argument tau (type: array) for negative (downward) mu values.
|
|
92
93
|
Returns a tuple of the diffuse and direct flux magnitudes respectively (type: (array, array)).
|
|
93
94
|
function
|
|
94
95
|
Zeroth Fourier mode of the intensity with argument tau (type: array).
|
|
95
|
-
Returns an ndarray with axes corresponding to
|
|
96
|
+
Returns an ndarray with axes corresponding to variation with mu and tau respectively.
|
|
96
97
|
This function is useful for calculating actinic fluxes and other quantities of interest,
|
|
97
98
|
but reclassification of delta-scaled flux and other corrections must be done manually.
|
|
98
99
|
function, optional
|
|
99
100
|
Intensity function with arguments (tau, phi, return_Fourier_error=False) of types (array, array, bool).
|
|
100
|
-
Returns an ndarray with axes corresponding to
|
|
101
|
+
Returns an ndarray with axes corresponding to variation with mu, tau, phi respectively.
|
|
101
102
|
The optional flag `return_Fourier_error` determines whether the function will also return
|
|
102
103
|
the Cauchy / Fourier convergence evaluation (type: float) for the last Fourier term.
|
|
103
104
|
|
|
@@ -125,10 +126,6 @@ def pydisort(
|
|
|
125
126
|
Nscoeffs = 0
|
|
126
127
|
else:
|
|
127
128
|
Nscoeffs = np.shape(s_poly_coeffs)[1]
|
|
128
|
-
if np.all(Leg_coeffs_BDRF == 0):
|
|
129
|
-
NBDRF = 0
|
|
130
|
-
else:
|
|
131
|
-
NBDRF = len(Leg_coeffs_BDRF)
|
|
132
129
|
NLayers = len(tau_arr)
|
|
133
130
|
scalar_b_pos = False
|
|
134
131
|
scalar_b_neg = False
|
|
@@ -150,7 +147,7 @@ def pydisort(
|
|
|
150
147
|
assert NLeg > 0
|
|
151
148
|
assert np.all(Leg_coeffs_all[:, 0] == 1)
|
|
152
149
|
assert np.all(np.abs(Leg_coeffs_all) <= 1)
|
|
153
|
-
assert np.all(np.
|
|
150
|
+
assert np.all(np.array([f.__code__.co_argcount for f in BDRF_Fourier_modes]) == 2)
|
|
154
151
|
assert NLeg <= NLeg_all
|
|
155
152
|
# Ensure that the first dimension of the following inputs corresponds to the number of layers
|
|
156
153
|
assert np.shape(Leg_coeffs_all)[0] == NLayers
|
|
@@ -188,7 +185,7 @@ def pydisort(
|
|
|
188
185
|
|
|
189
186
|
# Some more setup
|
|
190
187
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
191
|
-
|
|
188
|
+
NBDRF = len(BDRF_Fourier_modes)
|
|
192
189
|
weighted_Leg_coeffs_all = (2 * np.arange(NLeg_all) + 1) * Leg_coeffs_all
|
|
193
190
|
Leg_coeffs = Leg_coeffs_all[:, :NLeg]
|
|
194
191
|
if (scalar_b_pos and b_pos == 0) and (scalar_b_neg and b_neg == 0) and Nscoeffs == 0 and I0 > 0:
|
|
@@ -243,7 +240,7 @@ def pydisort(
|
|
|
243
240
|
N, NQuad, NLeg, NLoops,
|
|
244
241
|
NLayers, NBDRF,
|
|
245
242
|
weighted_scaled_Leg_coeffs,
|
|
246
|
-
|
|
243
|
+
BDRF_Fourier_modes,
|
|
247
244
|
mu0, I0, I0_orig, phi0,
|
|
248
245
|
b_pos, b_neg,
|
|
249
246
|
scalar_b_pos, scalar_b_neg,
|
|
@@ -368,7 +365,7 @@ def pydisort(
|
|
|
368
365
|
)
|
|
369
366
|
return (
|
|
370
367
|
mathscr_B[:, l, :]
|
|
371
|
-
* np.vstack(
|
|
368
|
+
* np.vstack((TMS_correction_pos, TMS_correction_neg))[:, :, None]
|
|
372
369
|
+ Contribution_from_other_layers
|
|
373
370
|
)
|
|
374
371
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
@@ -376,7 +373,7 @@ def pydisort(
|
|
|
376
373
|
else:
|
|
377
374
|
return (
|
|
378
375
|
mathscr_B[:, l, :]
|
|
379
|
-
* np.vstack(
|
|
376
|
+
* np.vstack((TMS_correction_pos, TMS_correction_neg))[:, :, None]
|
|
380
377
|
)
|
|
381
378
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
382
379
|
|
|
@@ -453,7 +450,7 @@ def pydisort(
|
|
|
453
450
|
N, NQuad, NLeg, NLoops,
|
|
454
451
|
NLayers, NBDRF,
|
|
455
452
|
weighted_scaled_Leg_coeffs,
|
|
456
|
-
|
|
453
|
+
BDRF_Fourier_modes,
|
|
457
454
|
mu0, I0, I0_orig, phi0,
|
|
458
455
|
b_pos, b_neg,
|
|
459
456
|
scalar_b_pos, scalar_b_neg,
|
PythonicDISORT/subroutines.py
CHANGED
|
@@ -75,7 +75,7 @@ def calculate_nu(mu, phi, mu_p, phi_p):
|
|
|
75
75
|
Returns
|
|
76
76
|
-------
|
|
77
77
|
ndarray
|
|
78
|
-
Cosine of scattering angles.
|
|
78
|
+
Cosine of scattering angles which axes capture variation with mu, phi, mu_p, phi_p respectively.
|
|
79
79
|
|
|
80
80
|
"""
|
|
81
81
|
mu, phi, mu_p, phi_p = np.atleast_1d(mu, phi, mu_p, phi_p)
|
|
@@ -88,7 +88,7 @@ def calculate_nu(mu, phi, mu_p, phi_p):
|
|
|
88
88
|
|
|
89
89
|
|
|
90
90
|
def Gauss_Legendre_quad(N, c=0, d=1):
|
|
91
|
-
"""Generates Gauss-Legendre quadrature
|
|
91
|
+
"""Generates Gauss-Legendre quadrature zero points and weights for integration from c to d.
|
|
92
92
|
|
|
93
93
|
Parameters
|
|
94
94
|
----------
|
|
@@ -223,6 +223,37 @@ def atleast_2d_append(*arys):
|
|
|
223
223
|
return res[0]
|
|
224
224
|
else:
|
|
225
225
|
return res
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def generate_diff_act_flux_funcs(u0):
|
|
229
|
+
"""Generates respectively the up and down diffuse actinic flux functions.
|
|
230
|
+
This a use case of the u0 function that is an output of pydisort.
|
|
231
|
+
Reclassification of delta-scaled flux is not performed and must be done manually.
|
|
232
|
+
|
|
233
|
+
Parameters
|
|
234
|
+
----------
|
|
235
|
+
u0 : func
|
|
236
|
+
Zeroth Fourier mode of the intensity.
|
|
237
|
+
See the fourth "return" of the `pydisort` function.
|
|
238
|
+
|
|
239
|
+
Returns
|
|
240
|
+
-------
|
|
241
|
+
function
|
|
242
|
+
Actinic flux function with argument tau (type: array) for positive (upward) mu values.
|
|
243
|
+
Returns the diffuse flux magnitudes (type: array).
|
|
244
|
+
function
|
|
245
|
+
Actinic flux function with argument tau (type: array) for negative (downward) mu values.
|
|
246
|
+
Returns the diffuse flux magnitudes (type: array).
|
|
247
|
+
|
|
248
|
+
"""
|
|
249
|
+
N = np.shape(u0(0))[0] // 2
|
|
250
|
+
GL_weights = Gauss_Legendre_quad(N, 0, 1)[1]
|
|
251
|
+
|
|
252
|
+
# Note that the zeroth axis of the array u0(tau) captures variation with mu
|
|
253
|
+
flux_act_up = lambda tau: 2 * pi * GL_weights @ u0(tau)[:N]
|
|
254
|
+
flux_act_down_diffuse = lambda tau: 2 * pi * GL_weights @ u0(tau)[N:]
|
|
255
|
+
|
|
256
|
+
return flux_act_up, flux_act_down_diffuse
|
|
226
257
|
|
|
227
258
|
|
|
228
259
|
def _mathscr_v(tau, l, s_poly_coeffs, Nscoeffs, G, K, G_inv, mu_arr):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: PythonicDISORT
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
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/PythonicDISORT
|
|
@@ -9,7 +9,7 @@ Classifier: License :: OSI Approved :: MIT License
|
|
|
9
9
|
Classifier: Operating System :: OS Independent
|
|
10
10
|
Requires-Python: >=3.8
|
|
11
11
|
Description-Content-Type: text/markdown
|
|
12
|
-
Requires-Dist: numpy >=1.
|
|
12
|
+
Requires-Dist: numpy >=1.8.0
|
|
13
13
|
Requires-Dist: scipy >=1.8.0
|
|
14
14
|
Provides-Extra: joblib
|
|
15
15
|
Requires-Dist: joblib >=1.0.0 ; extra == 'joblib'
|
|
@@ -53,7 +53,7 @@ With PyTest installed, execute the console command `pytest` in the `pydisotest`
|
|
|
53
53
|
|
|
54
54
|
## Requirements to run PythonicDISORT
|
|
55
55
|
* Python 3.8+
|
|
56
|
-
* `numpy >= 1.
|
|
56
|
+
* `numpy >= 1.8.0`
|
|
57
57
|
* `scipy >= 1.8.0`
|
|
58
58
|
* (OPTIONAL) `joblib >= 1.0.0` (Required for parallelization)
|
|
59
59
|
* (OPTIONAL) `pytest >= 6.2.5` (Required for non-Notebook tests)
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
PythonicDISORT/__init__.py,sha256=V1obNzaFgqInxqYJ5h_r6JHbZRxx4VM5VgzCIS6EEzI,84
|
|
2
|
+
PythonicDISORT/_loop_and_assemble_results.py,sha256=JjQApo_EXbEkqOsw4jDI6WkhN5DJc9Pl9kgxCGUQGeM,15746
|
|
3
|
+
PythonicDISORT/_one_Fourier_mode.py,sha256=FZL1isE2dxRRAHExH_g4J9ygkbBIq2wNMg-3INp1vac,15191
|
|
4
|
+
PythonicDISORT/pydisort.py,sha256=KX6g45CvwazVrdj7m7QEGraosWSalcvKtHesurG-oC8,21449
|
|
5
|
+
PythonicDISORT/subroutines.py,sha256=G3-LwkAsCkiVwPT_PzJkzmqVRdV1U0alsVyFeGtub7Q,11756
|
|
6
|
+
PythonicDISORT-0.4.0.dist-info/METADATA,sha256=Z9pjwzDjt-wMih3lUTdiAkCeznQtoVjIvEB7iiEvFxc,5828
|
|
7
|
+
PythonicDISORT-0.4.0.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
|
8
|
+
PythonicDISORT-0.4.0.dist-info/top_level.txt,sha256=aX6kCeI1E7naZz3xfw4_mIbWh5KBh9dmF3FIvgP5m3Y,15
|
|
9
|
+
PythonicDISORT-0.4.0.dist-info/RECORD,,
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
PythonicDISORT/__init__.py,sha256=V1obNzaFgqInxqYJ5h_r6JHbZRxx4VM5VgzCIS6EEzI,84
|
|
2
|
-
PythonicDISORT/_loop_and_assemble_results.py,sha256=WiSX14S2R7OUNqTdxUA2QHxZ4ZPX6U77mIFkfwtKuIw,15770
|
|
3
|
-
PythonicDISORT/_one_Fourier_mode.py,sha256=Lo13JHcLPQTEqIy60-_RrXjybKPX7PCSwC_fEGO9ksw,15498
|
|
4
|
-
PythonicDISORT/pydisort.py,sha256=YcFOsMAVwiU9jWHhDvUUSMQN6JRdW_aweauUk5kgeMU,21389
|
|
5
|
-
PythonicDISORT/subroutines.py,sha256=zYj5nPG_XCAvR0Rj6ae4XtEKaY2Gxsyjr_Yw41BLI_E,10495
|
|
6
|
-
PythonicDISORT-0.2.4.dist-info/METADATA,sha256=vRrKIs4Pfu1P1ZLPUBN-tjSfCGN5EU_RETk1WfpCzW0,5830
|
|
7
|
-
PythonicDISORT-0.2.4.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
|
8
|
-
PythonicDISORT-0.2.4.dist-info/top_level.txt,sha256=aX6kCeI1E7naZz3xfw4_mIbWh5KBh9dmF3FIvgP5m3Y,15
|
|
9
|
-
PythonicDISORT-0.2.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|