PythonicDISORT 1.2__py3-none-any.whl → 1.4__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 +57 -49
- PythonicDISORT/_solve_for_coeffs.py +208 -142
- PythonicDISORT/_solve_for_gen_and_part_sols.py +75 -69
- PythonicDISORT/pydisort.py +198 -197
- PythonicDISORT/subroutines.py +185 -112
- {pythonicdisort-1.2.dist-info → pythonicdisort-1.4.dist-info}/METADATA +3 -2
- pythonicdisort-1.4.dist-info/RECORD +11 -0
- {pythonicdisort-1.2.dist-info → pythonicdisort-1.4.dist-info}/WHEEL +1 -1
- pythonicdisort-1.2.dist-info/RECORD +0 -11
- {pythonicdisort-1.2.dist-info → pythonicdisort-1.4.dist-info}/LICENSE.md +0 -0
- {pythonicdisort-1.2.dist-info → pythonicdisort-1.4.dist-info}/top_level.txt +0 -0
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
from PythonicDISORT.subroutines import _mathscr_v
|
|
2
|
-
from PythonicDISORT.subroutines import to_diag_ordered_form
|
|
3
2
|
|
|
4
3
|
import numpy as np
|
|
4
|
+
from numpy.lib.stride_tricks import as_strided
|
|
5
5
|
import scipy as sc
|
|
6
|
-
from math import pi
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
def _solve_for_coeffs(
|
|
@@ -11,14 +10,14 @@ def _solve_for_coeffs(
|
|
|
11
10
|
G_collect, # Eigenvector matrices
|
|
12
11
|
K_collect, # Eigenvalues
|
|
13
12
|
B_collect, # Coefficients vectors for particular solutions
|
|
14
|
-
|
|
13
|
+
G_inv_mu_inv, # Inverse of eigenvector matrix for the 0th Fourier mode
|
|
15
14
|
scaled_tau_arr_with_0, # Delta-scaled lower boundary of layers with 0 inserted in front
|
|
16
|
-
|
|
15
|
+
mu_arr_pos, mu_arr_pos_times_W, # Upper hemisphere quadrature nodes (cosine polar angles); same but multiplied by weights
|
|
17
16
|
N, NQuad, # Number of 1) upper 2) both hemispheres quadrature nodes
|
|
18
17
|
NLayers, NBDRF, # Number of 1) layers; 2) BDRF Fourier modes
|
|
19
18
|
is_atmos_multilayered, # Is the atmosphere multilayered?
|
|
20
19
|
BDRF_Fourier_modes, # BDRF Fourier modes
|
|
21
|
-
mu0,
|
|
20
|
+
mu0, I0_div_4pi, # Primary properties of the direct beam
|
|
22
21
|
there_is_beam_source, # Is there a beam source?
|
|
23
22
|
b_pos, b_neg, # Dirichlet BCs
|
|
24
23
|
b_pos_is_scalar, b_neg_is_scalar, # Is each Dirichlet BCs scalar and so isotropic?
|
|
@@ -44,9 +43,8 @@ def _solve_for_coeffs(
|
|
|
44
43
|
| `G_collect` | `NFourier x NLayers x NQuad x NQuad` |
|
|
45
44
|
| `K_collect` | `NFourier x NLayers x NQuad` |
|
|
46
45
|
| `B_collect` | `NFourier x NLayers x NQuad` or `None` |
|
|
47
|
-
| `
|
|
46
|
+
| `G_inv_mu_inv` | `NLayers x NQuad x NQuad` or `None` |
|
|
48
47
|
| `scaled_tau_arr_with_0` | `NLayers + 1` |
|
|
49
|
-
| `mu_arr` | `NQuad` |
|
|
50
48
|
| `mu_arr_pos` | `NQuad/2` |
|
|
51
49
|
| `mu_arr_pos_times_W` | `NQuad/2` |
|
|
52
50
|
| `N` | scalar |
|
|
@@ -56,7 +54,7 @@ def _solve_for_coeffs(
|
|
|
56
54
|
| `is_atmos_multilayered` | boolean |
|
|
57
55
|
| `BDRF_Fourier_modes` | `NBDRF` |
|
|
58
56
|
| `mu0` | scalar |
|
|
59
|
-
| `
|
|
57
|
+
| `I0_div_4pi` | scalar |
|
|
60
58
|
| `there_is_beam_source` | boolean |
|
|
61
59
|
| `b_pos` | `NQuad/2 x NFourier` or `NQuad/2` or scalar |
|
|
62
60
|
| `b_neg` | `NQuad/2 x NFourier` or `NQuad/2` or scalar |
|
|
@@ -78,11 +76,36 @@ def _solve_for_coeffs(
|
|
|
78
76
|
################################## Solve for coefficients of homogeneous solution ##########################################
|
|
79
77
|
############# Refer to section 3.6.2 (single-layer) and 4 (multi-layer) of the Comprehensive Documentation #################
|
|
80
78
|
|
|
81
|
-
dim = NLayers * NQuad
|
|
82
|
-
GC_collect = np.empty((NFourier, NLayers, NQuad, NQuad))
|
|
83
79
|
use_banded_solver = (NLayers >= use_banded_solver_NLayers)
|
|
80
|
+
dim = NLayers * NQuad
|
|
81
|
+
C_collect = np.empty((NFourier, dim))
|
|
82
|
+
|
|
83
|
+
RHS = np.empty(dim)
|
|
84
|
+
i_bot = dim - N # Equals `j_bot_right`
|
|
85
|
+
j_bot_left = dim - NQuad
|
|
86
|
+
|
|
84
87
|
if use_banded_solver:
|
|
85
|
-
Nsupsubdiags = 3 * N - 1
|
|
88
|
+
Nsupsubdiags = 3 * N - 1
|
|
89
|
+
LHS_dof = np.zeros((6 * N - 1, dim), order="F") # Diagonal ordered form
|
|
90
|
+
s0, s1 = LHS_dof.strides
|
|
91
|
+
col_stride = s1 - s0 # Stride when moving +1 col and -1 row
|
|
92
|
+
|
|
93
|
+
def _view_slanted(i0, j0, nrows):
|
|
94
|
+
"""
|
|
95
|
+
Return a view into `LHS_dof` using slanted mapping.
|
|
96
|
+
The function uses `numpy.lib.stride_tricks.as_strided` which is performant but dangerous,
|
|
97
|
+
which is why this function is not exposed in `PythonicDISORT.subroutines`.
|
|
98
|
+
See https://numpy.org/devdocs/reference/generated/numpy.lib.stride_tricks.as_strided.html.
|
|
99
|
+
|
|
100
|
+
Assume the following exist in the outer scope:
|
|
101
|
+
`LHS_dof`, `Nsupsubdiags`, `s0`, `col_stride`
|
|
102
|
+
"""
|
|
103
|
+
r0 = Nsupsubdiags + i0 - j0
|
|
104
|
+
base = LHS_dof[r0 : r0 + nrows, j0 : j0 + N]
|
|
105
|
+
return as_strided(base, shape=(nrows, N), strides=(s0, col_stride))
|
|
106
|
+
|
|
107
|
+
else:
|
|
108
|
+
LHS = np.zeros((dim, dim), order="F")
|
|
86
109
|
|
|
87
110
|
# The following loops can easily be parallelized, but the speed-up is unlikely to be worth the overhead
|
|
88
111
|
for m in range(NFourier):
|
|
@@ -91,8 +114,6 @@ def _solve_for_coeffs(
|
|
|
91
114
|
|
|
92
115
|
G_collect_m = G_collect[m, :, :, :]
|
|
93
116
|
K_collect_m = K_collect[m, :, :]
|
|
94
|
-
if there_is_beam_source:
|
|
95
|
-
B_collect_m = B_collect[m, :, :]
|
|
96
117
|
|
|
97
118
|
# Generate mathscr_D and mathscr_X (BDRF terms)
|
|
98
119
|
# Just for this part, refer to section 3.4.2 of the Comprehensive Documentation
|
|
@@ -103,19 +124,21 @@ def _solve_for_coeffs(
|
|
|
103
124
|
mathscr_D_neg = (1 + m_equals_0 * 1) * BDRF_Fourier_modes_m
|
|
104
125
|
R = mathscr_D_neg * mu_arr_pos_times_W[None, :]
|
|
105
126
|
if there_is_beam_source:
|
|
106
|
-
mathscr_X_pos = (mu0 *
|
|
127
|
+
mathscr_X_pos = (mu0 * I0_div_4pi * 4) * BDRF_Fourier_modes_m
|
|
107
128
|
else:
|
|
108
129
|
mathscr_D_neg = (1 + m_equals_0 * 1) * BDRF_Fourier_modes_m(mu_arr_pos, mu_arr_pos)
|
|
109
130
|
R = mathscr_D_neg * mu_arr_pos_times_W[None, :]
|
|
110
131
|
if there_is_beam_source:
|
|
111
|
-
mathscr_X_pos = (mu0 *
|
|
132
|
+
mathscr_X_pos = (mu0 * I0_div_4pi * 4) * BDRF_Fourier_modes_m(
|
|
112
133
|
mu_arr_pos, np.array([mu0])
|
|
113
134
|
)[:, 0]
|
|
135
|
+
|
|
114
136
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
115
137
|
|
|
138
|
+
|
|
116
139
|
# Assemble RHS
|
|
117
140
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
118
|
-
# Ensure the BCs are of the correct shape
|
|
141
|
+
# Ensure the Dirchlet BCs are of the correct shape
|
|
119
142
|
if b_pos_is_scalar and m_equals_0:
|
|
120
143
|
b_pos_m = np.full(N, b_pos)
|
|
121
144
|
elif b_pos_is_vector and m_equals_0:
|
|
@@ -134,32 +157,38 @@ def _solve_for_coeffs(
|
|
|
134
157
|
else:
|
|
135
158
|
b_neg_m = b_neg[:, m]
|
|
136
159
|
|
|
137
|
-
#
|
|
160
|
+
# Top Dirichlet BC
|
|
161
|
+
RHS[:N] = b_neg_m
|
|
162
|
+
# Bottom Dirichlet BC
|
|
163
|
+
RHS[-N:] = b_pos_m
|
|
164
|
+
|
|
165
|
+
# Reset the rest of `RHS` to 0
|
|
166
|
+
RHS[N:-N] = 0
|
|
167
|
+
|
|
138
168
|
if m_equals_0 and there_is_iso_source:
|
|
139
|
-
|
|
169
|
+
# Top boundary
|
|
170
|
+
RHS[:N] -= _mathscr_v(
|
|
140
171
|
np.array([0]),
|
|
141
172
|
np.array([0]),
|
|
142
173
|
Nscoeffs,
|
|
143
174
|
scaled_s_poly_coeffs[[0], :],
|
|
144
175
|
G_collect_m[[0], N:, :],
|
|
145
176
|
K_collect_m[[0], :],
|
|
146
|
-
|
|
147
|
-
mu_arr,
|
|
177
|
+
G_inv_mu_inv[[0]],
|
|
148
178
|
).ravel()
|
|
149
179
|
|
|
150
|
-
_mathscr_v_contribution_middle = np.array([])
|
|
151
180
|
if is_atmos_multilayered:
|
|
152
181
|
indices = np.arange(NLayers - 1)
|
|
153
|
-
|
|
182
|
+
indicesp1 = indices + 1
|
|
183
|
+
RHS[N:-N] += (
|
|
154
184
|
_mathscr_v(
|
|
155
185
|
scaled_tau_arr_with_0[1:-1],
|
|
156
186
|
indices,
|
|
157
187
|
Nscoeffs,
|
|
158
|
-
scaled_s_poly_coeffs[
|
|
159
|
-
G_collect_m[
|
|
160
|
-
K_collect_m[
|
|
161
|
-
|
|
162
|
-
mu_arr,
|
|
188
|
+
scaled_s_poly_coeffs[indicesp1],
|
|
189
|
+
G_collect_m[indicesp1],
|
|
190
|
+
K_collect_m[indicesp1],
|
|
191
|
+
G_inv_mu_inv[indicesp1],
|
|
163
192
|
)
|
|
164
193
|
- _mathscr_v(
|
|
165
194
|
scaled_tau_arr_with_0[1:-1],
|
|
@@ -168,25 +197,24 @@ def _solve_for_coeffs(
|
|
|
168
197
|
scaled_s_poly_coeffs[indices],
|
|
169
198
|
G_collect_m[indices],
|
|
170
199
|
K_collect_m[indices],
|
|
171
|
-
|
|
172
|
-
mu_arr,
|
|
200
|
+
G_inv_mu_inv[indices],
|
|
173
201
|
)
|
|
174
202
|
).ravel(order='F')
|
|
203
|
+
|
|
204
|
+
# Bottom boundary
|
|
205
|
+
RHS[-N:] -= _mathscr_v(
|
|
206
|
+
scaled_tau_arr_with_0[[-1]],
|
|
207
|
+
np.array([0]),
|
|
208
|
+
Nscoeffs,
|
|
209
|
+
scaled_s_poly_coeffs[[-1], :],
|
|
210
|
+
G_collect_m[[-1], :N, :],
|
|
211
|
+
K_collect_m[[-1], :],
|
|
212
|
+
G_inv_mu_inv[[-1]],
|
|
213
|
+
).ravel()
|
|
175
214
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
Nscoeffs,
|
|
180
|
-
scaled_s_poly_coeffs[[-1], :],
|
|
181
|
-
G_collect_m[[-1], :N, :],
|
|
182
|
-
K_collect_m[[-1], :],
|
|
183
|
-
G_inv_collect_0[[-1], :, :],
|
|
184
|
-
mu_arr
|
|
185
|
-
).ravel()
|
|
186
|
-
if NBDRF > 0:
|
|
187
|
-
_mathscr_v_contribution_bottom = (
|
|
188
|
-
_mathscr_v_contribution_bottom
|
|
189
|
-
+ R
|
|
215
|
+
if there_is_BDRF_mode:
|
|
216
|
+
RHS[-N:] += (
|
|
217
|
+
R
|
|
190
218
|
@ _mathscr_v(
|
|
191
219
|
scaled_tau_arr_with_0[[-1]],
|
|
192
220
|
np.array([0]),
|
|
@@ -194,126 +222,164 @@ def _solve_for_coeffs(
|
|
|
194
222
|
scaled_s_poly_coeffs[[-1], :],
|
|
195
223
|
G_collect_m[[-1], N:, :],
|
|
196
224
|
K_collect_m[[-1], :],
|
|
197
|
-
|
|
198
|
-
mu_arr
|
|
225
|
+
G_inv_mu_inv[[-1]],
|
|
199
226
|
).ravel()
|
|
200
227
|
)
|
|
201
|
-
|
|
202
|
-
_mathscr_v_contribution = np.concatenate(
|
|
203
|
-
[
|
|
204
|
-
_mathscr_v_contribution_top,
|
|
205
|
-
_mathscr_v_contribution_middle,
|
|
206
|
-
_mathscr_v_contribution_bottom,
|
|
207
|
-
]
|
|
208
|
-
)
|
|
209
|
-
else:
|
|
210
|
-
_mathscr_v_contribution = 0
|
|
211
228
|
|
|
212
229
|
if there_is_beam_source:
|
|
213
|
-
|
|
230
|
+
B_collect_m = B_collect[m, :, :]
|
|
231
|
+
|
|
232
|
+
# Top boundary
|
|
233
|
+
RHS[:N] -= B_collect_m[0, N:]
|
|
234
|
+
|
|
214
235
|
if is_atmos_multilayered:
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
(B_collect_m[
|
|
218
|
-
* np.exp(-scaled_tau_arr_with_0 / mu0)[
|
|
236
|
+
indicesp1 = np.arange(1, NLayers)
|
|
237
|
+
RHS[N:-N] += (
|
|
238
|
+
(B_collect_m[indicesp1, :] - B_collect_m[indicesp1 - 1, :])
|
|
239
|
+
* np.exp(-scaled_tau_arr_with_0 / mu0)[indicesp1, None]
|
|
219
240
|
).ravel()
|
|
220
|
-
|
|
241
|
+
|
|
242
|
+
# Bottom boundary
|
|
221
243
|
if there_is_BDRF_mode:
|
|
222
|
-
RHS
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
RHS_middle,
|
|
227
|
-
b_pos_m
|
|
228
|
-
+ (mathscr_X_pos + R @ B_collect_m[-1, N:] - B_collect_m[-1, :N])
|
|
229
|
-
* np.exp(-scaled_tau_arr_with_0[-1] / mu0),
|
|
230
|
-
]
|
|
231
|
-
)
|
|
232
|
-
+ _mathscr_v_contribution
|
|
233
|
-
)
|
|
244
|
+
RHS[-N:] += (
|
|
245
|
+
mathscr_X_pos + R @ B_collect_m[-1, N:] - B_collect_m[-1, :N]
|
|
246
|
+
) * np.exp(-scaled_tau_arr_with_0[-1] / mu0)
|
|
247
|
+
|
|
234
248
|
else:
|
|
235
|
-
RHS
|
|
236
|
-
|
|
237
|
-
[
|
|
238
|
-
b_neg_m - B_collect_m[0, N:],
|
|
239
|
-
RHS_middle,
|
|
240
|
-
b_pos_m
|
|
241
|
-
- B_collect_m[-1, :N] * np.exp(-scaled_tau_arr_with_0[-1] / mu0),
|
|
242
|
-
]
|
|
243
|
-
)
|
|
244
|
-
+ _mathscr_v_contribution
|
|
245
|
-
)
|
|
246
|
-
else:
|
|
247
|
-
RHS_middle = np.zeros(NQuad * (NLayers - 1))
|
|
248
|
-
RHS = np.concatenate([b_neg_m, RHS_middle, b_pos_m]) + _mathscr_v_contribution
|
|
249
|
+
RHS[-N:] -= B_collect_m[-1, :N] * np.exp(-scaled_tau_arr_with_0[-1] / mu0)
|
|
250
|
+
|
|
249
251
|
# --------------------------------------------------------------------------------------------------------------------------
|
|
250
252
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
253
|
+
|
|
254
|
+
# Assemble LHS and solve (much of this code is replicated in section 4 of the Comprehensive Documentation)
|
|
255
|
+
# --------------------------------------------------------------------------------------------------------------------------
|
|
256
|
+
G_0 = G_collect_m[0]
|
|
257
|
+
G_0_nn = G_0[N:, :N]
|
|
258
|
+
G_0_np = G_0[N:, N:]
|
|
259
|
+
E_01 = np.exp(K_collect_m[0, :N] * scaled_tau_arr_with_0[1])[None, :]
|
|
260
|
+
|
|
261
|
+
G_L = G_collect_m[-1]
|
|
262
|
+
G_L_pn = G_L[:N, :N]
|
|
263
|
+
G_L_nn = G_L[N:, :N]
|
|
264
|
+
G_L_pp = G_L[:N, N:]
|
|
265
|
+
G_L_np = G_L[N:, N:]
|
|
258
266
|
E_Lm1L = np.exp(
|
|
259
267
|
K_collect_m[-1, :N] * (scaled_tau_arr_with_0[-1] - scaled_tau_arr_with_0[-2])
|
|
260
|
-
)
|
|
268
|
+
)[None, :]
|
|
261
269
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
LHS[-N:, -NQuad : -N] = (G_L_pn - R @ G_L_nn) * E_Lm1L[None, :]
|
|
271
|
-
LHS[-N:, -N:] = G_L_pp - R @ G_L_np
|
|
272
|
-
else:
|
|
273
|
-
LHS[-N:, -NQuad : -N] = G_L_pn * E_Lm1L[None, :]
|
|
274
|
-
LHS[-N:, -N:] = G_L_pp
|
|
270
|
+
################################## Use `sc.linalg.solve_banded` ##################################
|
|
271
|
+
if use_banded_solver:
|
|
272
|
+
|
|
273
|
+
# Directly assemble diagonal ordered form of LHS matrix
|
|
274
|
+
# ---------------- Top BC ----------------
|
|
275
|
+
G_0 = G_collect_m[0]
|
|
276
|
+
G_0_nn = G_0[N:, :N] # (N,N)
|
|
277
|
+
G_0_np = G_0[N:, N:] # (N,N)
|
|
275
278
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
#
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
279
|
+
_view_slanted(0, 0, N)[:] = G_0_nn # `_view_slanted` was defined with respect to `LHS_dof`
|
|
280
|
+
_view_slanted(0, N, N)[:] = G_0_np * E_01
|
|
281
|
+
|
|
282
|
+
# ---------------- Bottom BC ----------------
|
|
283
|
+
if there_is_BDRF_mode:
|
|
284
|
+
_view_slanted(i_bot, j_bot_left, N)[:] = (G_L_pn - R @ G_L_nn) * E_Lm1L
|
|
285
|
+
_view_slanted(i_bot, i_bot, N)[:] = G_L_pp - R @ G_L_np
|
|
286
|
+
else:
|
|
287
|
+
_view_slanted(i_bot, j_bot_left, N)[:] = G_L_pn * E_Lm1L
|
|
288
|
+
_view_slanted(i_bot, i_bot, N)[:] = G_L_pp
|
|
289
|
+
|
|
290
|
+
# ---------------- Interlayer / continuity BCs ----------------
|
|
291
|
+
for l in range(NLayers - 1):
|
|
292
|
+
G_l = G_collect_m[l]
|
|
293
|
+
G_l_pn = G_l[:N, :N] # (N,N)
|
|
294
|
+
G_l_nn = G_l[N:, :N] # (N,N)
|
|
295
|
+
G_l_ap = G_l[:, N:] # (2N,N)
|
|
296
|
+
|
|
297
|
+
G_lp1 = G_collect_m[l + 1]
|
|
298
|
+
G_lp1_an = G_lp1[:, :N] # (2N,N)
|
|
299
|
+
G_lp1_pp = G_lp1[:N, N:] # (N,N)
|
|
300
|
+
G_lp1_np = G_lp1[N:, N:] # (N,N)
|
|
301
|
+
|
|
302
|
+
tau_lm1 = scaled_tau_arr_with_0[l]
|
|
303
|
+
tau_l = scaled_tau_arr_with_0[l + 1]
|
|
304
|
+
tau_lp1 = scaled_tau_arr_with_0[l + 2]
|
|
305
|
+
|
|
306
|
+
E_lm1l = np.exp(K_collect_m[l, N:] * (tau_lm1 - tau_l))[None, :] # (N,)
|
|
307
|
+
E_llp1 = np.exp(K_collect_m[l + 1, N:] * (tau_l - tau_lp1))[None, :] # (N,)
|
|
308
|
+
|
|
309
|
+
start_row = N + l * NQuad
|
|
310
|
+
start_col = l * NQuad
|
|
311
|
+
|
|
312
|
+
_view_slanted(start_row, start_col, N)[:] = G_l_pn * E_lm1l
|
|
313
|
+
_view_slanted(start_row + N, start_col, N)[:] = G_l_nn * E_lm1l
|
|
314
|
+
_view_slanted(start_row, start_col + N, NQuad)[:] = G_l_ap
|
|
315
|
+
|
|
316
|
+
_view_slanted(start_row, start_col + NQuad, NQuad)[:] = -G_lp1_an
|
|
317
|
+
_view_slanted(start_row, start_col + 3 * N, N)[:] = -G_lp1_pp * E_llp1
|
|
318
|
+
_view_slanted(start_row + N, start_col + 3 * N, N)[:] = -G_lp1_np * E_llp1
|
|
303
319
|
|
|
304
|
-
|
|
305
|
-
if use_banded_solver:
|
|
320
|
+
# Solve the system
|
|
306
321
|
C_m = sc.linalg.solve_banded(
|
|
307
322
|
(Nsupsubdiags, Nsupsubdiags),
|
|
308
|
-
|
|
323
|
+
LHS_dof,
|
|
309
324
|
RHS,
|
|
310
|
-
|
|
325
|
+
False,
|
|
311
326
|
True,
|
|
312
327
|
False,
|
|
313
328
|
)
|
|
329
|
+
|
|
330
|
+
##################################################################################################
|
|
331
|
+
##################################### Use `np.linalg.solve` ######################################
|
|
314
332
|
else:
|
|
315
|
-
|
|
333
|
+
|
|
334
|
+
# ---------------- Top BC ----------------
|
|
335
|
+
LHS[:N, :N] = G_0_nn
|
|
336
|
+
LHS[:N, N : NQuad] = G_0_np * E_01
|
|
337
|
+
|
|
338
|
+
# ---------------- Bottom BC ----------------
|
|
339
|
+
if there_is_BDRF_mode:
|
|
340
|
+
LHS[-N:, -NQuad : -N] = (G_L_pn - R @ G_L_nn) * E_Lm1L
|
|
341
|
+
LHS[-N:, -N:] = G_L_pp - R @ G_L_np
|
|
342
|
+
else:
|
|
343
|
+
LHS[-N:, -NQuad : -N] = G_L_pn * E_Lm1L
|
|
344
|
+
LHS[-N:, -N:] = G_L_pp
|
|
316
345
|
|
|
317
|
-
|
|
346
|
+
# ---------------- Interlayer / continuity BCs ----------------
|
|
347
|
+
for l in range(NLayers - 1):
|
|
348
|
+
G_l = G_collect_m[l]
|
|
349
|
+
G_l_pn = G_l[:N, :N]
|
|
350
|
+
G_l_nn = G_l[N:, :N]
|
|
351
|
+
G_l_ap = G_l[:, N:]
|
|
352
|
+
|
|
353
|
+
G_lp1 = G_collect_m[l + 1]
|
|
354
|
+
G_lp1_an = G_lp1[:, :N]
|
|
355
|
+
G_lp1_pp = G_lp1[:N, N:]
|
|
356
|
+
G_lp1_np = G_lp1[N:, N:]
|
|
357
|
+
|
|
358
|
+
scaled_tau_arr_lm1 = scaled_tau_arr_with_0[l]
|
|
359
|
+
scaled_tau_arr_l = scaled_tau_arr_with_0[l + 1]
|
|
360
|
+
scaled_tau_arr_lp1 = scaled_tau_arr_with_0[l + 2]
|
|
361
|
+
|
|
362
|
+
# Postive eigenvalues
|
|
363
|
+
E_lm1l = np.exp(K_collect_m[l, N:] * (scaled_tau_arr_lm1 - scaled_tau_arr_l))
|
|
364
|
+
E_llp1 = np.exp(K_collect_m[l + 1, N:] * (scaled_tau_arr_l - scaled_tau_arr_lp1))
|
|
365
|
+
|
|
366
|
+
start_row = N + l * NQuad
|
|
367
|
+
start_col = l * NQuad
|
|
368
|
+
|
|
369
|
+
LHS[start_row : N + start_row, start_col : N + start_col] = G_l_pn * E_lm1l
|
|
370
|
+
LHS[N + start_row : NQuad + start_row, start_col : N + start_col] = G_l_nn * E_lm1l
|
|
371
|
+
LHS[start_row : NQuad + start_row, N + start_col : NQuad + start_col] = G_l_ap
|
|
372
|
+
|
|
373
|
+
LHS[start_row : NQuad + start_row, NQuad + start_col : 3 * N + start_col] = -G_lp1_an
|
|
374
|
+
LHS[start_row : N + start_row, 3 * N + start_col : 4 * N + start_col] = -G_lp1_pp * E_llp1
|
|
375
|
+
LHS[N + start_row : NQuad + start_row, 3 * N + start_col : 4 * N + start_col] = -G_lp1_np * E_llp1
|
|
376
|
+
|
|
377
|
+
# Solve the system
|
|
378
|
+
C_m = np.linalg.solve(LHS, RHS)
|
|
379
|
+
|
|
380
|
+
##################################################################################################
|
|
381
|
+
# --------------------------------------------------------------------------------------------------------------------------
|
|
382
|
+
|
|
383
|
+
C_collect[m, :] = C_m
|
|
318
384
|
|
|
319
|
-
return
|
|
385
|
+
return G_collect * C_collect.reshape((NFourier, NLayers, 1, NQuad))
|