PythonicDISORT 0.6.0__tar.gz → 0.6.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PythonicDISORT
3
- Version: 0.6.0
3
+ Version: 0.6.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
@@ -32,25 +32,25 @@ In addition, upon the request of a user, we added a subroutine to calculate acti
32
32
 
33
33
  You may contact me, Dion, through dh3065@columbia.edu.
34
34
 
35
- This repository also includes our F2PY-wrapped Stamnes DISORT (version 4.0.99) in the `disort4.0.99_f2py` directory.
35
+ Our **GitHub repository:** https://github.com/LDEO-CREW/Pythonic-DISORT also includes our F2PY-wrapped Stamnes DISORT (version 4.0.99) in the `disort4.0.99_f2py` directory.
36
36
  The original was downloaded from http://www.rtatmocn.com/disort/. The wrapper is inspired by https://github.com/kconnour/pyRT_DISORT.
37
37
 
38
38
  # Documentation
39
39
  https://pythonic-disort.readthedocs.io/en/latest/
40
40
 
41
- Also see the accompanying Jupyter Notebook: `Pythonic-DISORT.ipynb` in the `docs` directory
42
- of our GitHub repository: https://github.com/LDEO-CREW/Pythonic-DISORT.
41
+ Also see the accompanying Jupyter Notebook `Pythonic-DISORT.ipynb` in the `docs` directory
42
+ of our GitHub repository.
43
43
  The Jupyter Notebook provides comprehensive documentation, suggested inputs, explanations,
44
44
  mathematical derivations and verification tests.
45
45
  We highly recommend reading the non-optional parts of sections 1 and 2 before use.
46
46
 
47
47
  ## PyTest and examples of how to use PythonicDISORT
48
48
 
49
- Separate from the verification tests in the Jupyter Notebook, we used PyTest to recreate most of the test problems in Stamnes' `disotest.f90`,
50
- which is included in the `disort4.0.99_f2py` directory in this repository. In these tests, the solutions from PythonicDISORT are compared
49
+ Not only do we have verification tests in the Jupyter Notebook, we also used PyTest to recreate most of the test problems in Stamnes' `disotest.f90`;
50
+ `disotest.f90` is included in the `disort4.0.99_f2py` directory of our GitHub repository. In these tests, the solutions from PythonicDISORT are compared
51
51
  against solutions from our F2PY-wrapped Stamnes' DISORT (version 4.0.99). With PyTest installed, execute the console command `pytest`
52
52
  in the `pydisotest` directory to run these tests. The `pydisotest` directory also contains Jupyter Notebooks, one for each test,
53
- to show how the test was implemented. These notebooks double up as examples of how to use PythonicDISORT.
53
+ to show how the tests were implemented. These notebooks double up as examples of how to use PythonicDISORT.
54
54
 
55
55
  # Installation
56
56
 
@@ -74,16 +74,16 @@ must be set up to run the last section (section 6).
74
74
 
75
75
  ## Compatibility
76
76
 
77
- The PythonicDISORT package should be system agnostic given its minimal dependencies and pure Python code.
77
+ The PythonicDISORT package *should* be system agnostic given its minimal dependencies and pure Python code.
78
78
  We do not guarantee that our Jupyter Notebook and F2PY-wrapped Stamnes' DISORT will work on other systems though.
79
79
  The latter will almost certainly need user edits to work and in any case it requires FORTRAN compilers which
80
- are not included in this repository. Everything in this repository was built and tested on Windows 11 and
80
+ are not included in our GitHub repository. Everything in the repository was built and tested on Windows 11 but
81
81
  not yet tested on other systems.
82
82
 
83
83
  # Acknowledgements
84
84
 
85
85
  I acknowledge funding from NSF through the Learning the Earth with Artificial intelligence and Physics (LEAP)
86
- Science and Technology Center (STC) (Award #2019625).
86
+ Science and Technology Center (STC) (Award #2019625) under which this package was initially created.
87
87
 
88
88
  # References
89
89
  1) S. Chandrasekhar. 1960. *Radiative Transfer.*
@@ -11,25 +11,25 @@ In addition, upon the request of a user, we added a subroutine to calculate acti
11
11
 
12
12
  You may contact me, Dion, through dh3065@columbia.edu.
13
13
 
14
- This repository also includes our F2PY-wrapped Stamnes DISORT (version 4.0.99) in the `disort4.0.99_f2py` directory.
14
+ Our **GitHub repository:** https://github.com/LDEO-CREW/Pythonic-DISORT also includes our F2PY-wrapped Stamnes DISORT (version 4.0.99) in the `disort4.0.99_f2py` directory.
15
15
  The original was downloaded from http://www.rtatmocn.com/disort/. The wrapper is inspired by https://github.com/kconnour/pyRT_DISORT.
16
16
 
17
17
  # Documentation
18
18
  https://pythonic-disort.readthedocs.io/en/latest/
19
19
 
20
- Also see the accompanying Jupyter Notebook: `Pythonic-DISORT.ipynb` in the `docs` directory
21
- of our GitHub repository: https://github.com/LDEO-CREW/Pythonic-DISORT.
20
+ Also see the accompanying Jupyter Notebook `Pythonic-DISORT.ipynb` in the `docs` directory
21
+ of our GitHub repository.
22
22
  The Jupyter Notebook provides comprehensive documentation, suggested inputs, explanations,
23
23
  mathematical derivations and verification tests.
24
24
  We highly recommend reading the non-optional parts of sections 1 and 2 before use.
25
25
 
26
26
  ## PyTest and examples of how to use PythonicDISORT
27
27
 
28
- Separate from the verification tests in the Jupyter Notebook, we used PyTest to recreate most of the test problems in Stamnes' `disotest.f90`,
29
- which is included in the `disort4.0.99_f2py` directory in this repository. In these tests, the solutions from PythonicDISORT are compared
28
+ Not only do we have verification tests in the Jupyter Notebook, we also used PyTest to recreate most of the test problems in Stamnes' `disotest.f90`;
29
+ `disotest.f90` is included in the `disort4.0.99_f2py` directory of our GitHub repository. In these tests, the solutions from PythonicDISORT are compared
30
30
  against solutions from our F2PY-wrapped Stamnes' DISORT (version 4.0.99). With PyTest installed, execute the console command `pytest`
31
31
  in the `pydisotest` directory to run these tests. The `pydisotest` directory also contains Jupyter Notebooks, one for each test,
32
- to show how the test was implemented. These notebooks double up as examples of how to use PythonicDISORT.
32
+ to show how the tests were implemented. These notebooks double up as examples of how to use PythonicDISORT.
33
33
 
34
34
  # Installation
35
35
 
@@ -53,16 +53,16 @@ must be set up to run the last section (section 6).
53
53
 
54
54
  ## Compatibility
55
55
 
56
- The PythonicDISORT package should be system agnostic given its minimal dependencies and pure Python code.
56
+ The PythonicDISORT package *should* be system agnostic given its minimal dependencies and pure Python code.
57
57
  We do not guarantee that our Jupyter Notebook and F2PY-wrapped Stamnes' DISORT will work on other systems though.
58
58
  The latter will almost certainly need user edits to work and in any case it requires FORTRAN compilers which
59
- are not included in this repository. Everything in this repository was built and tested on Windows 11 and
59
+ are not included in our GitHub repository. Everything in the repository was built and tested on Windows 11 but
60
60
  not yet tested on other systems.
61
61
 
62
62
  # Acknowledgements
63
63
 
64
64
  I acknowledge funding from NSF through the Learning the Earth with Artificial intelligence and Physics (LEAP)
65
- Science and Technology Center (STC) (Award #2019625).
65
+ Science and Technology Center (STC) (Award #2019625) under which this package was initially created.
66
66
 
67
67
  # References
68
68
  1) S. Chandrasekhar. 1960. *Radiative Transfer.*
@@ -87,4 +87,4 @@ Science and Technology Center (STC) (Award #2019625).
87
87
 
88
88
  11) T. Nakajima and M. Tanaka. 1988. *Algorithms for radiative intensity calculations in moderately thick atmospheres using a truncation approximation.* https://www.sciencedirect.com/science/article/pii/0022407388900313.
89
89
 
90
- 12) K. Connour and A. Stcherbinine. 2022. *pyRT_DISORT.* https://github.com/kconnour/pyRT_DISORT.
90
+ 12) K. Connour and A. Stcherbinine. 2022. *pyRT_DISORT.* https://github.com/kconnour/pyRT_DISORT.
@@ -8,7 +8,7 @@ dependencies = [
8
8
  "scipy>=1.8.0",
9
9
  ]
10
10
  name = "PythonicDISORT"
11
- version = "0.6.0"
11
+ version = "0.6.2"
12
12
  authors = [
13
13
  { name="Dion HO Jia Xu", email="dh3065@columbia.edu" },
14
14
  ]
@@ -11,7 +11,7 @@ def _assemble_solution_functions(
11
11
  scaled_tau_arr_with_0,
12
12
  mu_arr_pos, mu_arr,
13
13
  M_inv, W,
14
- N, NQuad, NLeg, NLoops,
14
+ N, NQuad, NLeg, NFourier,
15
15
  NLayers, NBDRF,
16
16
  atmos_is_multilayered,
17
17
  weighted_scaled_Leg_coeffs,
@@ -46,7 +46,7 @@ def _assemble_solution_functions(
46
46
  # Compute all the necessary quantities
47
47
  # --------------------------------------------------------------------------------------------------------------------------
48
48
  outputs = _diagonalize(
49
- NLoops,
49
+ NFourier,
50
50
  scaled_omega_arr,
51
51
  mu_arr_pos, mu_arr,
52
52
  M_inv, W,
@@ -74,7 +74,7 @@ def _assemble_solution_functions(
74
74
  B_collect = None
75
75
 
76
76
  GC_collect = _solve_for_coefs(
77
- NLoops,
77
+ NFourier,
78
78
  G_collect,
79
79
  K_collect,
80
80
  B_collect,
@@ -154,14 +154,14 @@ def _assemble_solution_functions(
154
154
  )
155
155
 
156
156
  if _is_compatible_with_autograd:
157
- um = um + np.concatenate((_mathscr_v_contribution.T, np.zeros((NLoops - 1, len(tau), NQuad))))
157
+ um = um + np.concatenate((_mathscr_v_contribution.T, np.zeros((NFourier - 1, len(tau), NQuad))))
158
158
  else:
159
159
  um[0, :, :] += _mathscr_v_contribution.T
160
160
 
161
161
  intensities = np.einsum(
162
162
  "mti, mp -> itp",
163
163
  um,
164
- np.cos(np.arange(NLoops)[:, None] * (phi0 - phi)[None, :]),
164
+ np.cos(np.arange(NFourier)[:, None] * (phi0 - phi)[None, :]),
165
165
  optimize=True,
166
166
  )
167
167
 
@@ -183,7 +183,7 @@ def _assemble_solution_functions(
183
183
  )
184
184
  intensities_abs = np.abs(intensities)
185
185
  Fourier_error = np.max(
186
- np.abs(ulast[:, :, None] * np.cos((NLoops - 1) * (phi0 - phi))[None, None, :]),
186
+ np.abs(ulast[:, :, None] * np.cos((NFourier - 1) * (phi0 - phi))[None, None, :]),
187
187
  intensities_abs,
188
188
  out=np.zeros_like(intensities_abs),
189
189
  where=intensities_abs > 1e-8,
@@ -4,7 +4,7 @@ from math import pi
4
4
 
5
5
 
6
6
  def _diagonalize(
7
- NLoops,
7
+ NFourier,
8
8
  scaled_omega_arr,
9
9
  mu_arr_pos, mu_arr,
10
10
  M_inv, W,
@@ -29,24 +29,24 @@ def _diagonalize(
29
29
  ells_all = np.arange(NLeg)
30
30
  ind = 0
31
31
 
32
- G_collect = np.empty((NLoops * NLayers, NQuad, NQuad))
33
- K_collect = np.empty((NLoops * NLayers, NQuad))
34
- alpha_arr = np.empty((NLoops * NLayers, N, N))
35
- beta_arr = np.empty((NLoops * NLayers, N, N))
36
- X_tilde_arr = np.empty((NLoops * NLayers, NQuad))
32
+ G_collect = np.empty((NFourier * NLayers, NQuad, NQuad))
33
+ K_collect = np.empty((NFourier * NLayers, NQuad))
34
+ alpha_arr = np.empty((NFourier * NLayers, N, N))
35
+ beta_arr = np.empty((NFourier * NLayers, N, N))
36
+ X_tilde_arr = np.empty((NFourier * NLayers, NQuad))
37
37
  no_shortcut_indices = []
38
38
  no_shortcut_indices_0 = []
39
39
 
40
40
  if there_is_beam_source:
41
- B_collect = np.zeros((NLoops * NLayers, NQuad))
41
+ B_collect = np.zeros((NFourier * NLayers, NQuad))
42
42
  if there_is_iso_source:
43
43
  G_inv_collect_0 = np.empty((NLayers, NQuad, NQuad))
44
44
  # --------------------------------------------------------------------------------------------------------------------------
45
45
 
46
- # Loop over NLoops Fourier modes
46
+ # Loop over NFourier Fourier modes
47
47
  # These can easily be parallelized, but the speed-up is unlikely to be worth the overhead
48
48
  # --------------------------------------------------------------------------------------------------------------------------
49
- for m in range(NLoops):
49
+ for m in range(NFourier):
50
50
  # Setup
51
51
  # --------------------------------------------------------------------------------------------------------------------------
52
52
  m_equals_0 = (m == 0)
@@ -169,26 +169,26 @@ def _diagonalize(
169
169
  if there_is_beam_source:
170
170
  if there_is_iso_source:
171
171
  return (
172
- G_collect.reshape((NLoops, NLayers, NQuad, NQuad)),
173
- K_collect.reshape((NLoops, NLayers, NQuad)),
174
- B_collect.reshape((NLoops, NLayers, NQuad)),
172
+ G_collect.reshape((NFourier, NLayers, NQuad, NQuad)),
173
+ K_collect.reshape((NFourier, NLayers, NQuad)),
174
+ B_collect.reshape((NFourier, NLayers, NQuad)),
175
175
  G_inv_collect_0,
176
176
  )
177
177
  else:
178
178
  return (
179
- G_collect.reshape((NLoops, NLayers, NQuad, NQuad)),
180
- K_collect.reshape((NLoops, NLayers, NQuad)),
181
- B_collect.reshape((NLoops, NLayers, NQuad)),
179
+ G_collect.reshape((NFourier, NLayers, NQuad, NQuad)),
180
+ K_collect.reshape((NFourier, NLayers, NQuad)),
181
+ B_collect.reshape((NFourier, NLayers, NQuad)),
182
182
  )
183
183
  else:
184
184
  if there_is_iso_source:
185
185
  return (
186
- G_collect.reshape((NLoops, NLayers, NQuad, NQuad)),
187
- K_collect.reshape((NLoops, NLayers, NQuad)),
186
+ G_collect.reshape((NFourier, NLayers, NQuad, NQuad)),
187
+ K_collect.reshape((NFourier, NLayers, NQuad)),
188
188
  G_inv_collect_0,
189
189
  )
190
190
  else:
191
191
  return (
192
- G_collect.reshape((NLoops, NLayers, NQuad, NQuad)),
193
- K_collect.reshape((NLoops, NLayers, NQuad)),
192
+ G_collect.reshape((NFourier, NLayers, NQuad, NQuad)),
193
+ K_collect.reshape((NFourier, NLayers, NQuad)),
194
194
  )
@@ -7,7 +7,7 @@ from math import pi
7
7
 
8
8
 
9
9
  def _solve_for_coefs(
10
- NLoops,
10
+ NFourier,
11
11
  G_collect,
12
12
  K_collect,
13
13
  B_collect,
@@ -36,11 +36,11 @@ def _solve_for_coefs(
36
36
  """
37
37
  ################################## Solve for coefficients of homogeneous solution ##########################################
38
38
 
39
- GC_collect = np.empty((NLoops, NLayers, NQuad, NQuad))
39
+ GC_collect = np.empty((NFourier, NLayers, NQuad, NQuad))
40
40
  use_sparse_framework = NLayers >= use_sparse_NLayers
41
41
 
42
42
  # The following loops can easily be parallelized, but the speed-up is unlikely to be worth the overhead
43
- for m in range(NLoops):
43
+ for m in range(NFourier):
44
44
  m_equals_0 = (m == 0)
45
45
  BDRF_bool = m < NBDRF
46
46
 
@@ -89,7 +89,7 @@ def _solve_for_coefs(
89
89
  K_collect_m[0:1, :],
90
90
  G_inv_collect_0[0:1, :, :],
91
91
  mu_arr,
92
- ).flatten()
92
+ ).ravel()
93
93
 
94
94
  _mathscr_v_contribution_middle = np.array([])
95
95
  if atmos_is_multilayered:
@@ -115,7 +115,7 @@ def _solve_for_coefs(
115
115
  G_inv_collect_0[1:, :, :],
116
116
  mu_arr,
117
117
  )
118
- ).flatten()
118
+ ).ravel()
119
119
 
120
120
  _mathscr_v_contribution_bottom = _mathscr_v(
121
121
  tau_arr[-1:], np.array([0]),
@@ -124,7 +124,7 @@ def _solve_for_coefs(
124
124
  G_collect_m[-1:, N:, :],
125
125
  K_collect_m[-1:, :],
126
126
  G_inv_collect_0[-1:, :, :],
127
- mu_arr).flatten()
127
+ mu_arr).ravel()
128
128
  if NBDRF > 0:
129
129
  _mathscr_v_contribution_bottom = (
130
130
  R + np.eye(N)
@@ -154,7 +154,7 @@ def _solve_for_coefs(
154
154
  * np.exp(-mu0 * scaled_tau_arr_with_0[l + 1])
155
155
  for l in range(NLayers - 1)
156
156
  ]
157
- ).flatten()
157
+ ).ravel()
158
158
 
159
159
  RHS = (
160
160
  np.concatenate(
@@ -203,37 +203,37 @@ def _solve_for_coefs(
203
203
  block_row_ind = np.arange(block_row_len).reshape(NQuad, 2 * NQuad)
204
204
  block_row_sort = np.empty(block_row_len, dtype='int')
205
205
 
206
- block_row_sort[:N_squared] = block_row_ind[:N, :N].flatten()
207
- block_row_sort[N_squared : 2 * N_squared] = block_row_ind[N : 2 * N, :N].flatten()
208
- block_row_sort[2 * N_squared : 4 * N_squared] = block_row_ind[:2 * N, N : 2 * N].flatten()
209
- block_row_sort[4 * N_squared : 6 * N_squared] = block_row_ind[:2 * N, 2 * N : 3 * N].flatten()
210
- block_row_sort[6 * N_squared : 7 * N_squared] = block_row_ind[:N, 3 * N : 4 * N].flatten()
211
- block_row_sort[7 * N_squared : 8 * N_squared] = block_row_ind[N : 2 * N, 3 * N : 4 * N].flatten()
206
+ block_row_sort[:N_squared] = block_row_ind[:N, :N].ravel()
207
+ block_row_sort[N_squared : 2 * N_squared] = block_row_ind[N : 2 * N, :N].ravel()
208
+ block_row_sort[2 * N_squared : 4 * N_squared] = block_row_ind[:2 * N, N : 2 * N].ravel()
209
+ block_row_sort[4 * N_squared : 6 * N_squared] = block_row_ind[:2 * N, 2 * N : 3 * N].ravel()
210
+ block_row_sort[6 * N_squared : 7 * N_squared] = block_row_ind[:N, 3 * N : 4 * N].ravel()
211
+ block_row_sort[7 * N_squared : 8 * N_squared] = block_row_ind[N : 2 * N, 3 * N : 4 * N].ravel()
212
212
 
213
213
  # BCs for the entire atmosphere
214
214
  row_indices[:N_squared], col_indices[:N_squared] = _nd_slice_to_indexes(np.s_[:N, :N])
215
- block_rows[:N_squared] = G_0_nn.flatten()
215
+ block_rows[:N_squared] = G_0_nn.ravel()
216
216
  (
217
217
  row_indices[N_squared : 2 * N_squared],
218
218
  col_indices[N_squared : 2 * N_squared],
219
219
  ) = _nd_slice_to_indexes(np.s_[:N, N:NQuad])
220
220
  block_rows[N_squared : 2 * N_squared] = (
221
221
  G_0_np * np.exp(K_collect_m[0, :N] * scaled_tau_arr_with_0[1])[None, :]
222
- ).flatten()
222
+ ).ravel()
223
223
  (
224
224
  row_indices[2 * N_squared : 3 * N_squared],
225
225
  col_indices[2 * N_squared : 3 * N_squared],
226
226
  ) = _nd_slice_to_indexes(np.s_[dim - N : dim, dim - NQuad : dim - N])
227
227
  block_rows[2 * N_squared : 3 * N_squared] = (
228
228
  (G_L_pn - BDRF_LHS_contribution_neg) * E_Lm1L[None, :]
229
- ).flatten()
229
+ ).ravel()
230
230
  (
231
231
  row_indices[3 * N_squared : 4 * N_squared],
232
232
  col_indices[3 * N_squared : 4 * N_squared],
233
233
  ) = _nd_slice_to_indexes(np.s_[dim - N : dim, dim - N : dim])
234
234
  block_rows[3 * N_squared : 4 * N_squared] = (
235
235
  G_L_pp - BDRF_LHS_contribution_pos
236
- ).flatten()
236
+ ).ravel()
237
237
 
238
238
  # Interlayer / continuity BCs
239
239
  for l in range(NLayers - 1):
@@ -263,12 +263,12 @@ def _solve_for_coefs(
263
263
  ] = col_indices_l[block_row_sort]
264
264
 
265
265
  starting_ind = 4 * N_squared + l * block_row_len
266
- block_rows[starting_ind : N_squared + starting_ind] = (G_l_pn * E_lm1l[None, :]).flatten()
267
- block_rows[starting_ind + N_squared : 2 * N_squared + starting_ind] = (G_l_nn * E_lm1l[None, :]).flatten()
268
- block_rows[starting_ind + 2 * N_squared : 4 * N_squared + starting_ind] = G_l_ap.flatten()
269
- block_rows[starting_ind + 4 * N_squared : 6 * N_squared + starting_ind] = -G_lp1_an.flatten()
270
- block_rows[starting_ind + 6 * N_squared : 7 * N_squared + starting_ind] = -(G_lp1_pp * E_llp1[None, :]).flatten()
271
- block_rows[starting_ind + 7 * N_squared : 8 * N_squared + starting_ind] = -(G_lp1_np * E_llp1[None, :]).flatten()
266
+ block_rows[starting_ind : N_squared + starting_ind] = (G_l_pn * E_lm1l[None, :]).ravel()
267
+ block_rows[starting_ind + N_squared : 2 * N_squared + starting_ind] = (G_l_nn * E_lm1l[None, :]).ravel()
268
+ block_rows[starting_ind + 2 * N_squared : 4 * N_squared + starting_ind] = G_l_ap.ravel()
269
+ block_rows[starting_ind + 4 * N_squared : 6 * N_squared + starting_ind] = -G_lp1_an.ravel()
270
+ block_rows[starting_ind + 6 * N_squared : 7 * N_squared + starting_ind] = -(G_lp1_pp * E_llp1[None, :]).ravel()
271
+ block_rows[starting_ind + 7 * N_squared : 8 * N_squared + starting_ind] = -(G_lp1_np * E_llp1[None, :]).ravel()
272
272
 
273
273
  LHS = sc.sparse.coo_matrix(
274
274
  (
@@ -14,7 +14,7 @@ def pydisort(
14
14
  Leg_coeffs_all,
15
15
  mu0, I0, phi0,
16
16
  NLeg=None,
17
- NLoops=None,
17
+ NFourier=None,
18
18
  b_pos=0,
19
19
  b_neg=0,
20
20
  only_flux=False,
@@ -42,9 +42,10 @@ def pydisort(
42
42
  omega_arr : array
43
43
  Single-scattering albedo of each atmospheric layer.
44
44
  NQuad : int
45
- Number of mu quadrature nodes.
45
+ Number of `mu` quadrature nodes.
46
46
  Leg_coeffs_all : ndarray
47
- All available unweighted phase function Legendre coefficients.
47
+ All available unweighted phase function Legendre coefficients.
48
+ Each coefficient should be between 0 and 1 inclusive.
48
49
  mu0 : float
49
50
  Cosine of polar angle of the incident beam.
50
51
  I0 : float
@@ -53,7 +54,7 @@ def pydisort(
53
54
  Azimuthal angle of the incident beam.
54
55
  NLeg : optional, int
55
56
  Number of phase function Legendre coefficients.
56
- NLoops : optional, int
57
+ NFourier : optional, int
57
58
  Number of Fourier modes to use in the intensity function.
58
59
  b_pos : optional, 2darray or float
59
60
  Dirichlet boundary condition for the upward direction.
@@ -66,7 +67,7 @@ def pydisort(
66
67
  NT_cor : optional, bool
67
68
  Perform Nakajima-Tanaka intensity corrections?
68
69
  BDRF_Fourier_modes : optional, list
69
- BDRF Fourier modes, each a function with arguments mu, -mup of type array
70
+ BDRF Fourier modes, each a function with arguments `mu, -mu_p` of type array
70
71
  and which output has the same dimensions as the outer product of the two arrays.
71
72
  s_poly_coeffs : optional, array
72
73
  Polynomial coefficients of isotropic internal sources.
@@ -77,21 +78,22 @@ def pydisort(
77
78
  Returns
78
79
  -------
79
80
  array
80
- All mu (cosine of polar angle) quadrature nodes.
81
+ All `mu` (cosine of polar angle) quadrature nodes.
81
82
  function
82
- (Energetic) Flux function with argument tau (type: array) for positive (upward) mu values.
83
+ (Energetic) Flux function with argument `tau` (type: array) for positive (upward) `mu` values.
83
84
  Returns the diffuse flux magnitudes (type: array).
84
85
  function
85
- (Energetic) Flux function with argument tau (type: array) for negative (downward) mu values.
86
+ (Energetic) Flux function with argument `tau` (type: array) for negative (downward) `mu` values.
86
87
  Returns a tuple of the diffuse and direct flux magnitudes respectively (type: (array, array)).
87
88
  function
88
- Zeroth Fourier mode of the intensity with argument tau (type: array).
89
- Returns an ndarray with axes corresponding to variation with mu and tau respectively.
89
+ Zeroth Fourier mode of the intensity with argument `tau` (type: array).
90
+ Returns an ndarray with axes corresponding to variation with `mu` and `tau` respectively.
90
91
  This function is useful for calculating actinic fluxes and other quantities of interest,
91
- but reclassification of delta-scaled flux and other corrections must be done manually.
92
+ but reclassification of delta-scaled flux and other corrections must be done manually
93
+ (for actinic flux `generate_diff_act_flux_funcs` will automatically perform the reclassification).
92
94
  function, optional
93
- Intensity function with arguments (tau, phi, return_Fourier_error=False) of types (array, array, bool).
94
- Returns an ndarray with axes corresponding to variation with mu, tau, phi respectively.
95
+ Intensity function with arguments `(tau, phi, return_Fourier_error=False)` of types `(array, array, bool)`.
96
+ Returns an ndarray with axes corresponding to variation with `mu, tau, phi` respectively.
95
97
  The optional flag `return_Fourier_error` determines whether the function will also return
96
98
  the Cauchy / Fourier convergence evaluation (type: float) for the last Fourier term.
97
99
 
@@ -114,8 +116,8 @@ def pydisort(
114
116
  # --------------------------------------------------------------------------------------------------------------------------
115
117
  if NLeg is None:
116
118
  NLeg = NQuad
117
- if NLoops is None:
118
- NLoops = NQuad
119
+ if NFourier is None:
120
+ NFourier = NQuad
119
121
  if np.all(b_pos == 0):
120
122
  b_pos = 0
121
123
  if np.all(b_neg == 0):
@@ -147,7 +149,7 @@ def pydisort(
147
149
  # The user must supply at least as many phase function Legendre coefficients as intended for use
148
150
  assert NLeg > 0
149
151
  assert np.all(Leg_coeffs_all[:, 0] == 1)
150
- assert np.all(np.abs(Leg_coeffs_all) <= 1)
152
+ assert np.all(0 <= Leg_coeffs_all) and np.all(Leg_coeffs_all <= 1)
151
153
  assert np.all(np.array([f.__code__.co_argcount for f in BDRF_Fourier_modes]) == 2)
152
154
  assert NLeg <= NLeg_all
153
155
  # Ensure that the first dimension of the following inputs corresponds to the number of layers
@@ -157,13 +159,13 @@ def pydisort(
157
159
  assert len(f_arr) == NLayers
158
160
  if there_is_iso_source:
159
161
  assert np.shape(s_poly_coeffs)[0] == NLayers
160
- # Conditions on the number of quadrature angles (NQuad), Legendre coefficients (NLeg) and loops (NLoops)
162
+ # Conditions on the number of quadrature angles (NQuad), Legendre coefficients (NLeg) and loops (NFourier)
161
163
  assert NQuad >= 2
162
164
  assert NQuad % 2 == 0
163
- assert NLoops > 0
164
- assert NLoops <= NLeg
165
+ assert NFourier > 0
166
+ assert NFourier <= NLeg
165
167
  # Not strictly necessary but there will be tremendous inaccuracies if this is violated
166
- assert NQuad >= NLeg
168
+ assert NLeg <= NQuad
167
169
  # We require principal angles and a downward incident beam
168
170
  assert I0 >= 0
169
171
  if there_is_beam_source:
@@ -173,11 +175,11 @@ def pydisort(
173
175
  if len(np.atleast_1d(b_pos)) == 1:
174
176
  b_pos_is_scalar = True
175
177
  else:
176
- assert np.shape(b_pos) == (N, NLoops)
178
+ assert np.shape(b_pos) == (N, NFourier)
177
179
  if len(np.atleast_1d(b_neg)) == 1:
178
180
  b_neg_is_scalar = True
179
181
  else:
180
- assert np.shape(b_neg) == (N, NLoops)
182
+ assert np.shape(b_neg) == (N, NFourier)
181
183
  # The fractional scattering must be between 0 and 1
182
184
  assert np.all(0 <= f_arr) and np.all(f_arr <= 1)
183
185
  # The minimum threshold is the minimum numbers of layers: 1
@@ -238,7 +240,7 @@ def pydisort(
238
240
  scaled_tau_arr_with_0,
239
241
  mu_arr_pos, mu_arr,
240
242
  M_inv, W,
241
- N, NQuad, NLeg, NLoops,
243
+ N, NQuad, NLeg, NFourier,
242
244
  NLayers, NBDRF,
243
245
  atmos_is_multilayered,
244
246
  weighted_scaled_Leg_coeffs,
@@ -319,159 +321,100 @@ def pydisort(
319
321
  )
320
322
 
321
323
  ## Contribution from other layers
322
- # TODO: Despite being vectorized and otherwise optimized, this block of code is slower than desired
323
- # and is the bottleneck for the TMS correction
324
+ # TODO: Despite being vectorized and despite many attempts at further optimization,
325
+ # this block of code is slower than desired and is the bottleneck for the TMS correction.
324
326
  # --------------------------------------------------------------------------------------------------------------------------
325
327
  if atmos_is_multilayered:
326
328
  layers_arr = np.arange(NLayers)[:, None]
327
- pos_contribution_mask = (l[None, :] < layers_arr).flatten()
328
- neg_contribution_mask = (l[None, :] > layers_arr).flatten()
329
-
329
+ pos_contribution_mask = (l[None, :] < layers_arr).ravel()
330
+ neg_contribution_mask = (l[None, :] > layers_arr).ravel()
331
+
330
332
  layers_arr_repeat = np.repeat(layers_arr, Ntau)
331
333
  scaled_tau_tile = np.tile(scaled_tau, NLayers)
332
334
  scaled_tau_arr_with_0_repeat = np.repeat(scaled_tau_arr_with_0, Ntau)
333
-
334
- if True:
335
- if np.any(pos_contribution_mask):
336
- contribution_from_other_layers_pos = np.zeros((N, NLayers * Ntau, Nphi))
337
- scaled_tau_l_tile_pos = scaled_tau_tile[pos_contribution_mask]
338
- mathscr_B_l_repeat_posmasked = mathscr_B[:N, layers_arr_repeat[pos_contribution_mask], :]
339
- scaled_tau_arr_with_0_l_tile_posmasked = scaled_tau_arr_with_0_repeat[:-Ntau][
340
- pos_contribution_mask
341
- ]
342
- scaled_tau_arr_with_0_lp1_tile_posmasked = scaled_tau_arr_with_0_repeat[Ntau:][
343
- pos_contribution_mask
344
- ]
345
-
346
- contribution_from_other_layers_pos[:, pos_contribution_mask, :] = (
347
- mathscr_B_l_repeat_posmasked
348
- * (
349
- np.exp(
350
- (scaled_tau_l_tile_pos - scaled_tau_arr_with_0_l_tile_posmasked)
351
- / mu_arr_pos[:, None]
352
- - scaled_tau_arr_with_0_l_tile_posmasked / mu0
353
- )
354
- - np.exp(
355
- (scaled_tau_l_tile_pos - scaled_tau_arr_with_0_lp1_tile_posmasked)
356
- / mu_arr_pos[:, None]
357
- - scaled_tau_arr_with_0_lp1_tile_posmasked / mu0
358
- )
359
- )[:, :, None]
360
- )
361
- contribution_from_other_layers_pos = np.sum(
362
- contribution_from_other_layers_pos.reshape((N, NLayers, Ntau, Nphi)), axis=1
363
- )
364
- if np.any(neg_contribution_mask):
365
- contribution_from_other_layers_neg = np.zeros((N, NLayers * Ntau, Nphi))
366
- scaled_tau_l_tile_neg = scaled_tau_tile[neg_contribution_mask]
367
- mathscr_B_l_repeat_negmasked = mathscr_B[N:, layers_arr_repeat[neg_contribution_mask], :]
368
- scaled_tau_arr_with_0_l_tile_negmasked = scaled_tau_arr_with_0_repeat[:-Ntau][
369
- neg_contribution_mask
370
- ]
371
- scaled_tau_arr_with_0_lp1_tile_negmasked = scaled_tau_arr_with_0_repeat[Ntau:][
372
- neg_contribution_mask
373
- ]
374
-
375
- contribution_from_other_layers_neg[:, neg_contribution_mask, :] = (
376
- mathscr_B_l_repeat_negmasked
377
- * (
378
- np.exp(
379
- (scaled_tau_arr_with_0_lp1_tile_negmasked - scaled_tau_l_tile_neg)
380
- / mu_arr_pos[:, None]
381
- - scaled_tau_arr_with_0_lp1_tile_negmasked / mu0
382
- )
383
- - np.exp(
384
- (scaled_tau_arr_with_0_l_tile_negmasked - scaled_tau_l_tile_neg)
385
- / mu_arr_pos[:, None]
386
- - scaled_tau_arr_with_0_l_tile_negmasked / mu0
387
- )
388
- )[:, :, None]
389
- )
390
- contribution_from_other_layers_neg = np.sum(
391
- contribution_from_other_layers_neg.reshape((N, NLayers, Ntau, Nphi)), axis=1
392
- )
393
-
394
- return (
335
+
336
+ if np.any(pos_contribution_mask):
337
+ contribution_from_each_other_layer_pos = np.zeros((N, NLayers * Ntau, Nphi))
338
+ scaled_tau_l_tile_pos = scaled_tau_tile[pos_contribution_mask]
339
+ mathscr_B_l_repeat_posmasked = mathscr_B[
340
+ :N, layers_arr_repeat[pos_contribution_mask], :
341
+ ]
342
+ scaled_tau_arr_with_0_l_tile_posmasked = scaled_tau_arr_with_0_repeat[:-Ntau][
343
+ pos_contribution_mask
344
+ ]
345
+ scaled_tau_arr_with_0_lp1_tile_posmasked = scaled_tau_arr_with_0_repeat[Ntau:][
346
+ pos_contribution_mask
347
+ ]
348
+
349
+ contribution_from_each_other_layer_pos[:, pos_contribution_mask, :] = (
350
+ mathscr_B_l_repeat_posmasked
351
+ * (
352
+ np.exp(
353
+ (scaled_tau_l_tile_pos - scaled_tau_arr_with_0_l_tile_posmasked)
354
+ / mu_arr_pos[:, None]
355
+ - scaled_tau_arr_with_0_l_tile_posmasked / mu0
356
+ )
357
+ - np.exp(
358
+ (scaled_tau_l_tile_pos - scaled_tau_arr_with_0_lp1_tile_posmasked)
359
+ / mu_arr_pos[:, None]
360
+ - scaled_tau_arr_with_0_lp1_tile_posmasked / mu0
361
+ )
362
+ )[:, :, None]
363
+ )
364
+ contribution_from_other_layers_pos = np.sum(
365
+ contribution_from_each_other_layer_pos.reshape((N, NLayers, Ntau, Nphi)),
366
+ axis=1,
367
+ )
368
+ if np.any(neg_contribution_mask):
369
+ contribution_from_each_other_layer_neg = np.zeros((N, NLayers * Ntau, Nphi))
370
+ scaled_tau_l_tile_neg = scaled_tau_tile[neg_contribution_mask]
371
+ mathscr_B_l_repeat_negmasked = mathscr_B[
372
+ N:, layers_arr_repeat[neg_contribution_mask], :
373
+ ]
374
+ scaled_tau_arr_with_0_l_tile_negmasked = scaled_tau_arr_with_0_repeat[:-Ntau][
375
+ neg_contribution_mask
376
+ ]
377
+ scaled_tau_arr_with_0_lp1_tile_negmasked = scaled_tau_arr_with_0_repeat[Ntau:][
378
+ neg_contribution_mask
379
+ ]
380
+
381
+ contribution_from_each_other_layer_neg[:, neg_contribution_mask, :] = (
382
+ mathscr_B_l_repeat_negmasked
383
+ * (
384
+ np.exp(
385
+ (scaled_tau_arr_with_0_lp1_tile_negmasked - scaled_tau_l_tile_neg)
386
+ / mu_arr_pos[:, None]
387
+ - scaled_tau_arr_with_0_lp1_tile_negmasked / mu0
388
+ )
389
+ - np.exp(
390
+ (scaled_tau_arr_with_0_l_tile_negmasked - scaled_tau_l_tile_neg)
391
+ / mu_arr_pos[:, None]
392
+ - scaled_tau_arr_with_0_l_tile_negmasked / mu0
393
+ )
394
+ )[:, :, None]
395
+ )
396
+ contribution_from_other_layers_neg = np.sum(
397
+ contribution_from_each_other_layer_neg.reshape((N, NLayers, Ntau, Nphi)),
398
+ axis=1,
399
+ )
400
+
401
+ if _is_compatible_with_autograd:
402
+ solution = (
395
403
  mathscr_B[:, l, :]
396
404
  * np.vstack((TMS_correction_pos, TMS_correction_neg))[:, :, None]
397
- + np.concatenate(
398
- (contribution_from_other_layers_pos, contribution_from_other_layers_neg), axis=0
399
- )
400
405
  )
401
-
406
+ solution[:N, :, :] += contribution_from_other_layers_pos
407
+ solution[N:, :, :] += contribution_from_other_layers_neg
408
+ return solution
409
+
402
410
  else:
403
- solution_movedaxis = np.moveaxis(
404
- mathscr_B[:, l, :]
405
- * np.vstack((TMS_correction_pos, TMS_correction_neg))[:, :, None],
406
- 0,
407
- 1,
411
+ return mathscr_B[:, l, :] * np.vstack((TMS_correction_pos, TMS_correction_neg))[
412
+ :, :, None
413
+ ] + np.concatenate(
414
+ (contribution_from_other_layers_pos, contribution_from_other_layers_neg),
415
+ axis=0,
408
416
  )
409
- tau_ind_tile = np.tile(np.arange(Ntau), NLayers)
410
-
411
- if np.any(pos_contribution_mask):
412
- scaled_tau_l_tile_pos = scaled_tau_tile[pos_contribution_mask]
413
- mathscr_B_l_repeat_posmasked = mathscr_B[:N, layers_arr_repeat[pos_contribution_mask], :]
414
- scaled_tau_arr_with_0_l_tile_posmasked = scaled_tau_arr_with_0_repeat[:-Ntau][
415
- pos_contribution_mask
416
- ]
417
- scaled_tau_arr_with_0_lp1_tile_posmasked = scaled_tau_arr_with_0_repeat[Ntau:][
418
- pos_contribution_mask
419
- ]
420
-
421
- np.add.at(
422
- solution_movedaxis[:, :N, :],
423
- tau_ind_tile[pos_contribution_mask],
424
- np.moveaxis(
425
- mathscr_B_l_repeat_posmasked
426
- * (
427
- np.exp(
428
- (scaled_tau_l_tile_pos - scaled_tau_arr_with_0_l_tile_posmasked)
429
- / mu_arr_pos[:, None]
430
- - scaled_tau_arr_with_0_l_tile_posmasked / mu0
431
- )
432
- - np.exp(
433
- (scaled_tau_l_tile_pos - scaled_tau_arr_with_0_lp1_tile_posmasked)
434
- / mu_arr_pos[:, None]
435
- - scaled_tau_arr_with_0_lp1_tile_posmasked / mu0
436
- )
437
- )[:, :, None],
438
- 0,
439
- 1,
440
- ),
441
- )
442
- if np.any(neg_contribution_mask):
443
- scaled_tau_l_tile_neg = scaled_tau_tile[neg_contribution_mask]
444
- mathscr_B_l_repeat_negmasked = mathscr_B[N:, layers_arr_repeat[neg_contribution_mask], :]
445
- scaled_tau_arr_with_0_l_tile_negmasked = scaled_tau_arr_with_0_repeat[:-Ntau][
446
- neg_contribution_mask
447
- ]
448
- scaled_tau_arr_with_0_lp1_tile_negmasked = scaled_tau_arr_with_0_repeat[Ntau:][
449
- neg_contribution_mask
450
- ]
451
-
452
- np.add.at(
453
- solution_movedaxis[:, N:, :],
454
- tau_ind_tile[neg_contribution_mask],
455
- np.moveaxis(
456
- mathscr_B_l_repeat_negmasked
457
- * (
458
- np.exp(
459
- (scaled_tau_arr_with_0_lp1_tile_negmasked - scaled_tau_l_tile_neg)
460
- / mu_arr_pos[:, None]
461
- - scaled_tau_arr_with_0_lp1_tile_negmasked / mu0
462
- )
463
- - np.exp(
464
- (scaled_tau_arr_with_0_l_tile_negmasked - scaled_tau_l_tile_neg)
465
- / mu_arr_pos[:, None]
466
- - scaled_tau_arr_with_0_l_tile_negmasked / mu0
467
- )
468
- )[:, :, None],
469
- 0,
470
- 1,
471
- ),
472
- )
473
417
 
474
- return np.moveaxis(solution_movedaxis, 0, 1)
475
418
  # --------------------------------------------------------------------------------------------------------------------------
476
419
 
477
420
  else:
@@ -544,14 +487,14 @@ def pydisort(
544
487
 
545
488
  else:
546
489
  if only_flux:
547
- NLoops = 1 # We only need to solve for the 0th Fourier mode to compute the flux
490
+ NFourier = 1 # We only need to solve for the 0th Fourier mode to compute the flux
548
491
  return (mu_arr,) + _assemble_solution_functions(
549
492
  scaled_omega_arr,
550
493
  tau_arr,
551
494
  scaled_tau_arr_with_0,
552
495
  mu_arr_pos, mu_arr,
553
496
  M_inv, W,
554
- N, NQuad, NLeg, NLoops,
497
+ N, NQuad, NLeg, NFourier,
555
498
  NLayers, NBDRF,
556
499
  atmos_is_multilayered,
557
500
  weighted_scaled_Leg_coeffs,
@@ -30,7 +30,7 @@ def transform_interval(arr, c, d, a=-1, b=1):
30
30
 
31
31
 
32
32
  def transform_weights(weights, c, d, a=-1, b=1):
33
- """Transforms quadrature weights from interval [a, b] to [c, d].
33
+ """Transforms an array of quadrature weights from interval [a, b] to [c, d].
34
34
 
35
35
  Parameters
36
36
  ----------
@@ -55,8 +55,8 @@ def transform_weights(weights, c, d, a=-1, b=1):
55
55
 
56
56
 
57
57
  def calculate_nu(mu, phi, mu_p, phi_p):
58
- """Calculates the cosine of the scattering angle nu
59
- between incident angle (mu_p, phi_p) and scattering angle (mu, phi).
58
+ """Calculates the cosine of the scattering angle `nu`
59
+ between incident angle `(mu_p, phi_p)` and scattering angle `(mu, phi)`.
60
60
 
61
61
  Parameters
62
62
  ----------
@@ -72,7 +72,7 @@ def calculate_nu(mu, phi, mu_p, phi_p):
72
72
  Returns
73
73
  -------
74
74
  ndarray
75
- Cosine of scattering angles which axes capture variation with mu, phi, mu_p, phi_p respectively.
75
+ Cosine of scattering angles which axes capture variation with `mu, phi, mu_p, phi_p` respectively.
76
76
 
77
77
  """
78
78
  mu, phi, mu_p, phi_p = np.atleast_1d(mu, phi, mu_p, phi_p)
@@ -110,7 +110,7 @@ def Gauss_Legendre_quad(N, c=0, d=1):
110
110
 
111
111
 
112
112
  def Clenshaw_Curtis_quad(Nphi, c=0, d=(2 * pi)):
113
- """Generates Clenshaw_Curtis quadrature weights and zero points for integration from c to d.
113
+ """Generates Clenshaw-Curtis quadrature zero points and weights for integration from c to d.
114
114
 
115
115
  Parameters
116
116
  ----------
@@ -146,9 +146,9 @@ def Clenshaw_Curtis_quad(Nphi, c=0, d=(2 * pi)):
146
146
 
147
147
 
148
148
  def generate_FD_mat(Ntau, a, b):
149
- """Generates a sparse first derivative matrix in `csr` format with second-order accuracy
150
- on [a,b] with `Ntau` grid points.
151
- We use second order forward or backward differences at the boundaries.
149
+ """Generates a sparse first derivative central difference (second-order accuracy)
150
+ matrix on [a,b] in `csr` format with `Ntau` grid points.
151
+ Second order forward or backward differences are used at the boundaries.
152
152
 
153
153
  Parameters
154
154
  ----------
@@ -181,15 +181,15 @@ def generate_FD_mat(Ntau, a, b):
181
181
  first_deriv[-1, -2] = -2 / h
182
182
  first_deriv[-1, -3] = 1 / (2 * h)
183
183
 
184
- return tau_arr, first_deriv.asformat("csr")
184
+ return tau_arr, first_deriv.tocsr()
185
185
 
186
186
 
187
187
  def atleast_2d_append(*arys):
188
188
  """View inputs as arrays with at least two dimensions.
189
- Dimensions are added, when necessary, to the back of the shape tuple rather than to the front.
189
+ Dimensions are added as necessary to the back of the shape tuple rather than to the front.
190
190
 
191
- This is exactly NumPy's `atleast_2d` function but altered to add dimensions to the back of the shape tuple rather than to the front.
192
- View the documentation for NumPy's `atleast_2d` function at https://numpy.org/doc/stable/reference/generated/numpy.atleast_2d.html.
191
+ This is exactly NumPy's ``numpy.atleast_2d`` function but altered to add dimensions to the back of the shape tuple rather than to the front.
192
+ View the documentation for ``numpy.atleast_2d`` at https://numpy.org/doc/stable/reference/generated/numpy.atleast_2d.html.
193
193
 
194
194
  Parameters
195
195
  ----------
@@ -223,23 +223,23 @@ def atleast_2d_append(*arys):
223
223
 
224
224
 
225
225
  def generate_diff_act_flux_funcs(u0):
226
- """Generates respectively the up and down diffuse actinic flux functions.
227
- This a use case of the u0 function that is an output of pydisort.
226
+ """Generates the up and down diffuse actinic flux functions respectively.
227
+ This is a use case of the ``u0`` function that is an output of ``pydisort``.
228
228
  The reclassification of delta-scaled actinic flux is automatically performed.
229
229
 
230
230
  Parameters
231
231
  ----------
232
232
  u0 : func
233
233
  Zeroth Fourier mode of the intensity.
234
- See the fourth "return" of the `pydisort` function.
234
+ See the fourth "return" of the ``pydisort`` function.
235
235
 
236
236
  Returns
237
237
  -------
238
238
  function
239
- Actinic flux function with argument tau (type: array) for positive (upward) mu values.
239
+ Actinic flux function with argument `tau` (type: array) for positive (upward) `mu` values.
240
240
  Returns the diffuse flux magnitudes (type: array).
241
241
  function
242
- Actinic flux function with argument tau (type: array) for negative (downward) mu values.
242
+ Actinic flux function with argument `tau` (type: array) for negative (downward) `mu` values.
243
243
  Returns the diffuse flux magnitudes (type: array).
244
244
 
245
245
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PythonicDISORT
3
- Version: 0.6.0
3
+ Version: 0.6.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
@@ -32,25 +32,25 @@ In addition, upon the request of a user, we added a subroutine to calculate acti
32
32
 
33
33
  You may contact me, Dion, through dh3065@columbia.edu.
34
34
 
35
- This repository also includes our F2PY-wrapped Stamnes DISORT (version 4.0.99) in the `disort4.0.99_f2py` directory.
35
+ Our **GitHub repository:** https://github.com/LDEO-CREW/Pythonic-DISORT also includes our F2PY-wrapped Stamnes DISORT (version 4.0.99) in the `disort4.0.99_f2py` directory.
36
36
  The original was downloaded from http://www.rtatmocn.com/disort/. The wrapper is inspired by https://github.com/kconnour/pyRT_DISORT.
37
37
 
38
38
  # Documentation
39
39
  https://pythonic-disort.readthedocs.io/en/latest/
40
40
 
41
- Also see the accompanying Jupyter Notebook: `Pythonic-DISORT.ipynb` in the `docs` directory
42
- of our GitHub repository: https://github.com/LDEO-CREW/Pythonic-DISORT.
41
+ Also see the accompanying Jupyter Notebook `Pythonic-DISORT.ipynb` in the `docs` directory
42
+ of our GitHub repository.
43
43
  The Jupyter Notebook provides comprehensive documentation, suggested inputs, explanations,
44
44
  mathematical derivations and verification tests.
45
45
  We highly recommend reading the non-optional parts of sections 1 and 2 before use.
46
46
 
47
47
  ## PyTest and examples of how to use PythonicDISORT
48
48
 
49
- Separate from the verification tests in the Jupyter Notebook, we used PyTest to recreate most of the test problems in Stamnes' `disotest.f90`,
50
- which is included in the `disort4.0.99_f2py` directory in this repository. In these tests, the solutions from PythonicDISORT are compared
49
+ Not only do we have verification tests in the Jupyter Notebook, we also used PyTest to recreate most of the test problems in Stamnes' `disotest.f90`;
50
+ `disotest.f90` is included in the `disort4.0.99_f2py` directory of our GitHub repository. In these tests, the solutions from PythonicDISORT are compared
51
51
  against solutions from our F2PY-wrapped Stamnes' DISORT (version 4.0.99). With PyTest installed, execute the console command `pytest`
52
52
  in the `pydisotest` directory to run these tests. The `pydisotest` directory also contains Jupyter Notebooks, one for each test,
53
- to show how the test was implemented. These notebooks double up as examples of how to use PythonicDISORT.
53
+ to show how the tests were implemented. These notebooks double up as examples of how to use PythonicDISORT.
54
54
 
55
55
  # Installation
56
56
 
@@ -74,16 +74,16 @@ must be set up to run the last section (section 6).
74
74
 
75
75
  ## Compatibility
76
76
 
77
- The PythonicDISORT package should be system agnostic given its minimal dependencies and pure Python code.
77
+ The PythonicDISORT package *should* be system agnostic given its minimal dependencies and pure Python code.
78
78
  We do not guarantee that our Jupyter Notebook and F2PY-wrapped Stamnes' DISORT will work on other systems though.
79
79
  The latter will almost certainly need user edits to work and in any case it requires FORTRAN compilers which
80
- are not included in this repository. Everything in this repository was built and tested on Windows 11 and
80
+ are not included in our GitHub repository. Everything in the repository was built and tested on Windows 11 but
81
81
  not yet tested on other systems.
82
82
 
83
83
  # Acknowledgements
84
84
 
85
85
  I acknowledge funding from NSF through the Learning the Earth with Artificial intelligence and Physics (LEAP)
86
- Science and Technology Center (STC) (Award #2019625).
86
+ Science and Technology Center (STC) (Award #2019625) under which this package was initially created.
87
87
 
88
88
  # References
89
89
  1) S. Chandrasekhar. 1960. *Radiative Transfer.*
File without changes