PythonicDISORT 0.9.5__py3-none-any.whl → 1.0.0__py3-none-any.whl

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