PythonicDISORT 0.8.0__tar.gz → 0.9.0__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.8.0
3
+ Version: 0.9.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/Pythonic-DISORT
@@ -28,8 +28,10 @@ On the other hand, PythonicDISORT should be easier to install, use, and modify t
28
28
 
29
29
  PythonicDISORT is based on Stamnes' FORTRAN DISORT (see References, in particular [2, 3, 8]) and has its main features: multi-layer solver,
30
30
  delta-M scaling, Nakajima-Tanaka (NT) corrections, only flux option, direct beam source, isotropic internal source (blackbody emission),
31
- Dirichlet boundary conditions (diffuse flux boundary sources), Bi-Directional Reflectance Function (BDRF) for surface reflection, and more.
32
- In addition, subroutine to calculate actinic fluxes was added to satisfy a user request and further feature requests as well as feedback are welcome.
31
+ Dirichlet boundary conditions (diffuse flux boundary sources), Bi-Directional Reflectance Function (BDRF) for surface reflection,
32
+ interpolation with respect to polar angle and more.
33
+ In addition, we added a subroutine to calculate actinic fluxes to satisfy a user request, and integration with respect to tau was also added.
34
+ Further feature requests as well as feedback are welcome.
33
35
 
34
36
  You may contact me, Dion, through dh3065@columbia.edu.
35
37
 
@@ -50,8 +52,8 @@ Not only are there verification tests in `Pythonic-DISORT.ipynb`,
50
52
  most of the test problems in Stamnes' `disotest.f90` (download DISORT 4.0.99 from http://www.rtatmocn.com/disort/) have also been recreated.
51
53
  In these tests, the solutions from PythonicDISORT are compared against solutions
52
54
  from a F2PY-wrapped Stamnes' DISORT (version 4.0.99; wrapper inspired by https://github.com/kconnour/pyRT_DISORT). With PyTest installed, execute the console command `pytest`
53
- in the `pydisotest` directory to run these tests. The `pydisotest` directory also contains Jupyter Notebooks that correspond to each test
54
- to show how it was implemented. These notebooks double up as examples of how to use PythonicDISORT.
55
+ in the `pydisotest` directory to run these tests. The `pydisotest` directory also contains Jupyter Notebooks to show the implementation of each test.
56
+ These notebooks double up as examples of how to use PythonicDISORT.
55
57
 
56
58
  # Installation
57
59
 
@@ -7,8 +7,10 @@ On the other hand, PythonicDISORT should be easier to install, use, and modify t
7
7
 
8
8
  PythonicDISORT is based on Stamnes' FORTRAN DISORT (see References, in particular [2, 3, 8]) and has its main features: multi-layer solver,
9
9
  delta-M scaling, Nakajima-Tanaka (NT) corrections, only flux option, direct beam source, isotropic internal source (blackbody emission),
10
- Dirichlet boundary conditions (diffuse flux boundary sources), Bi-Directional Reflectance Function (BDRF) for surface reflection, and more.
11
- In addition, subroutine to calculate actinic fluxes was added to satisfy a user request and further feature requests as well as feedback are welcome.
10
+ Dirichlet boundary conditions (diffuse flux boundary sources), Bi-Directional Reflectance Function (BDRF) for surface reflection,
11
+ interpolation with respect to polar angle and more.
12
+ In addition, we added a subroutine to calculate actinic fluxes to satisfy a user request, and integration with respect to tau was also added.
13
+ Further feature requests as well as feedback are welcome.
12
14
 
13
15
  You may contact me, Dion, through dh3065@columbia.edu.
14
16
 
@@ -29,8 +31,8 @@ Not only are there verification tests in `Pythonic-DISORT.ipynb`,
29
31
  most of the test problems in Stamnes' `disotest.f90` (download DISORT 4.0.99 from http://www.rtatmocn.com/disort/) have also been recreated.
30
32
  In these tests, the solutions from PythonicDISORT are compared against solutions
31
33
  from a F2PY-wrapped Stamnes' DISORT (version 4.0.99; wrapper inspired by https://github.com/kconnour/pyRT_DISORT). With PyTest installed, execute the console command `pytest`
32
- in the `pydisotest` directory to run these tests. The `pydisotest` directory also contains Jupyter Notebooks that correspond to each test
33
- to show how it was implemented. These notebooks double up as examples of how to use PythonicDISORT.
34
+ in the `pydisotest` directory to run these tests. The `pydisotest` directory also contains Jupyter Notebooks to show the implementation of each test.
35
+ These notebooks double up as examples of how to use PythonicDISORT.
34
36
 
35
37
  # Installation
36
38
 
@@ -8,7 +8,7 @@ dependencies = [
8
8
  "scipy>=1.8.0",
9
9
  ]
10
10
  name = "PythonicDISORT"
11
- version = "0.8.0"
11
+ version = "0.9.0"
12
12
  authors = [
13
13
  { name="Dion HO Jia Xu", email="dh3065@columbia.edu" },
14
14
  ]
@@ -233,12 +233,15 @@ def _assemble_intensity_and_fluxes(
233
233
  K_collect_0,
234
234
  G_inv_collect_0,
235
235
  mu_arr,
236
- _autograd_compatible,
237
- is_antiderivative_wrt_tau
236
+ is_antiderivative_wrt_tau,
237
+ _autograd_compatible
238
238
  )
239
239
 
240
240
  if _autograd_compatible:
241
- um = um + np.concatenate((_mathscr_v_contribution.T, np.zeros((NFourier - 1, len(tau), NQuad))))
241
+ if NFourier == 1:
242
+ um = um + _mathscr_v_contribution.T
243
+ else:
244
+ um = um + np.concatenate((_mathscr_v_contribution.T, np.zeros((NFourier - 1, len(tau), NQuad))))
242
245
  else:
243
246
  um[0, :, :] += _mathscr_v_contribution.T
244
247
 
@@ -383,8 +386,8 @@ def _assemble_intensity_and_fluxes(
383
386
  K_collect_0,
384
387
  G_inv_collect_0,
385
388
  mu_arr,
386
- _autograd_compatible,
387
- is_antiderivative_wrt_tau
389
+ is_antiderivative_wrt_tau,
390
+ _autograd_compatible
388
391
  )
389
392
  u0 = u0 + _mathscr_v_contribution
390
393
 
@@ -436,8 +439,8 @@ def _assemble_intensity_and_fluxes(
436
439
  K_collect_0,
437
440
  G_inv_collect_0,
438
441
  mu_arr,
439
- _autograd_compatible,
440
- is_antiderivative_wrt_tau
442
+ is_antiderivative_wrt_tau,
443
+ _autograd_compatible
441
444
  )[:N, :]
442
445
  else:
443
446
  _mathscr_v_contribution = 0
@@ -515,8 +518,8 @@ def _assemble_intensity_and_fluxes(
515
518
  K_collect_0,
516
519
  G_inv_collect_0,
517
520
  mu_arr,
518
- _autograd_compatible,
519
- is_antiderivative_wrt_tau
521
+ is_antiderivative_wrt_tau,
522
+ _autograd_compatible
520
523
  )[N:, :]
521
524
  else:
522
525
  _mathscr_v_contribution = 0
@@ -124,7 +124,8 @@ def _solve_for_coeffs(
124
124
  # _mathscr_v_contribution
125
125
  if there_is_iso_source and m_equals_0:
126
126
  _mathscr_v_contribution_top = -_mathscr_v(
127
- np.array([0]), np.array([0]),
127
+ np.array([0]),
128
+ np.array([0]),
128
129
  s_poly_coeffs[0:1, :],
129
130
  Nscoeffs,
130
131
  G_collect_m[0:1, N:, :],
@@ -139,38 +140,51 @@ def _solve_for_coeffs(
139
140
  _mathscr_v_contribution_middle = (
140
141
  _mathscr_v(
141
142
  tau_arr[:-1],
142
- indices,
143
- s_poly_coeffs[:-1, :],
143
+ indices + 1,
144
+ s_poly_coeffs,
144
145
  Nscoeffs,
145
- G_collect_m[:-1, :, :],
146
- K_collect_m[:-1, :],
147
- G_inv_collect_0[:-1, :, :],
146
+ G_collect_m,
147
+ K_collect_m,
148
+ G_inv_collect_0,
148
149
  mu_arr,
149
150
  )
150
151
  - _mathscr_v(
151
152
  tau_arr[:-1],
152
153
  indices,
153
- s_poly_coeffs[1:, :],
154
+ s_poly_coeffs,
154
155
  Nscoeffs,
155
- G_collect_m[1:, :, :],
156
- K_collect_m[1:, :],
157
- G_inv_collect_0[1:, :, :],
156
+ G_collect_m,
157
+ K_collect_m,
158
+ G_inv_collect_0,
158
159
  mu_arr,
159
160
  )
160
- ).ravel()
161
+ ).ravel(order='F')
161
162
 
162
- _mathscr_v_contribution_bottom = _mathscr_v(
163
- tau_arr[-1:], np.array([0]),
163
+ _mathscr_v_contribution_bottom = -_mathscr_v(
164
+ tau_arr[-1:],
165
+ np.array([0]),
164
166
  s_poly_coeffs[-1:, :],
165
167
  Nscoeffs,
166
- G_collect_m[-1:, N:, :],
168
+ G_collect_m[-1:, :N, :],
167
169
  K_collect_m[-1:, :],
168
170
  G_inv_collect_0[-1:, :, :],
169
- mu_arr).ravel()
171
+ mu_arr
172
+ ).ravel()
170
173
  if NBDRF > 0:
171
174
  _mathscr_v_contribution_bottom = (
172
- R + np.eye(N)
173
- ) @ _mathscr_v_contribution_bottom
175
+ _mathscr_v_contribution_bottom
176
+ + R
177
+ @ _mathscr_v(
178
+ tau_arr[-1:],
179
+ np.array([0]),
180
+ s_poly_coeffs[-1:, :],
181
+ Nscoeffs,
182
+ G_collect_m[-1:, N:, :],
183
+ K_collect_m[-1:, :],
184
+ G_inv_collect_0[-1:, :, :],
185
+ mu_arr
186
+ ).ravel()
187
+ )
174
188
 
175
189
  _mathscr_v_contribution = np.concatenate(
176
190
  [
@@ -111,7 +111,7 @@ def _solve_for_gen_and_part_sols(
111
111
  if np.any(weighted_asso_Leg_coeffs_l > 0) and np.all(
112
112
  np.isfinite(asso_leg_term_pos)
113
113
  ):
114
- # Generate mathscr_D and mathscr_X (BDRF terms)
114
+ # Generate D and X (phase function terms)
115
115
  # --------------------------------------------------------------------------------------------------------------------------
116
116
  D_temp = weighted_asso_Leg_coeffs_l[None, :] * asso_leg_term_pos.T
117
117
  D_pos = (scaled_omega_l / 2) * D_temp @ asso_leg_term_pos
@@ -82,7 +82,7 @@ def pydisort(
82
82
  -------
83
83
  mu_arr : array or float
84
84
  All `mu` (cosine of polar angle) quadrature nodes.
85
- Fp(tau) : function, function
85
+ Fp(tau) : function
86
86
  (Energetic) Flux function with argument `tau` (type: array or float) for positive (upward) `mu` values.
87
87
  Returns the diffuse flux magnitudes (same type and size as `tau`).
88
88
  Pass `is_antiderivative_wrt_tau = True` (defaults to `False`)
@@ -104,7 +104,7 @@ def pydisort(
104
104
  Pass `is_antiderivative_wrt_tau = True` (defaults to `False`)
105
105
  to switch to an antiderivative of the function with respect to `tau`.
106
106
  u(tau, phi) : function, optional
107
- Intensity function with arguments `(tau, phi)` of types `(array or float, array or float)`.
107
+ Intensity function with arguments `(tau, phi)` each of type array or float.
108
108
  Returns an ndarray with axes corresponding to variation with `mu, tau, phi` respectively.
109
109
  Pass `return_Fourier_error = True` (defaults to `False`) to return the
110
110
  Cauchy / Fourier convergence evaluation (type: float) for the last Fourier term.
@@ -1,7 +1,6 @@
1
1
  import numpy as np
2
2
  import scipy as sc
3
3
  from math import pi
4
- from numpy.polynomial.legendre import leggauss
5
4
 
6
5
 
7
6
  def transform_interval(arr, c, d, a, b):
@@ -71,7 +70,7 @@ def calculate_nu(mu, phi, mu_p, phi_p):
71
70
 
72
71
  Returns
73
72
  -------
74
- ndarray
73
+ nu : ndarray
75
74
  Cosine of scattering angles which axes capture variation with `mu, phi, mu_p, phi_p` respectively.
76
75
 
77
76
  """
@@ -104,7 +103,7 @@ def Gauss_Legendre_quad(N, c=0, d=1):
104
103
  Quadrature weights.
105
104
 
106
105
  """
107
- mu_arr_pos, W = leggauss(int(N))
106
+ mu_arr_pos, W = np.polynomial.legendre.leggauss(int(N))
108
107
 
109
108
  return transform_interval(mu_arr_pos, c, d, -1, 1), transform_weights(W, c, d, -1, 1)
110
109
 
@@ -224,8 +223,10 @@ def atleast_2d_append(*arys):
224
223
 
225
224
  def generate_diff_act_flux_funcs(u0):
226
225
  """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``.
226
+ This is a use case of the ``u0`` function which is an output of ``pydisort``.
228
227
  The reclassification of delta-scaled actinic flux is automatically performed.
228
+ The computation of actinic fluxes is similar to that of energetic fluxes
229
+ and the latter is discussed in section 3.8 of the Comprehensive Documentation.
229
230
 
230
231
  Parameters
231
232
  ----------
@@ -235,12 +236,12 @@ def generate_diff_act_flux_funcs(u0):
235
236
 
236
237
  Returns
237
238
  -------
238
- function
239
+ Fp_act(tau) : function
239
240
  Actinic flux function with argument `tau` (type: array) for positive (upward) `mu` values.
240
241
  Returns the diffuse flux magnitudes (type: array).
241
242
  Pass `is_antiderivative_wrt_tau = True` (defaults to `False`)
242
243
  to switch to an antiderivative of the function with respect to `tau`.
243
- function
244
+ Fm_act(tau) : function
244
245
  Actinic flux function with argument `tau` (type: array) for negative (downward) `mu` values.
245
246
  Returns the diffuse flux magnitudes (type: array).
246
247
  Pass `is_antiderivative_wrt_tau = True` (defaults to `False`)
@@ -252,16 +253,75 @@ def generate_diff_act_flux_funcs(u0):
252
253
 
253
254
  # Note that the zeroth axis of the array u0(tau) captures variation with mu
254
255
  def flux_act_up(tau, is_antiderivative_wrt_tau=False):
255
- return 2 * pi * GL_weights @ u0(tau, is_antiderivative_wrt_tau)[:N]
256
+ return np.squeeze(2 * pi * GL_weights @ u0(tau, is_antiderivative_wrt_tau)[:N])[()]
256
257
 
257
258
  def flux_act_down_diffuse(tau, is_antiderivative_wrt_tau=False):
258
259
  u0_cache, act_dscale_reclassification = u0(tau, is_antiderivative_wrt_tau, _return_act_dscale_for_reclass=True)
259
260
  result_without_reclassification = 2 * pi * GL_weights @ u0_cache[N:]
260
- return result_without_reclassification + act_dscale_reclassification
261
+ return np.squeeze(result_without_reclassification + act_dscale_reclassification)[()]
261
262
 
262
263
  return flux_act_up, flux_act_down_diffuse
263
264
 
264
265
 
266
+ def interpolate(mu_arr_pos, u):
267
+ """Polynomial (Barycentric) interpolation with respect to mu. The output
268
+ is a function that is continuous and variable in all three arguments: mu, tau and phi.
269
+ Discussed in sections 3.7 and 6.3 in the Comprehensive Documentation.
270
+
271
+ Parameters
272
+ ----------
273
+ mu_arr_pos : array
274
+ Positive `mu` (cosine of polar angle) quadrature nodes.
275
+ Equivalent to `mu_arr[:N]`.
276
+ u : function
277
+ Non-interpolated intensity function as outputted by `pydisort`.
278
+
279
+ Returns
280
+ -------
281
+ u_interpol : function
282
+ Intensity function with arguments `(mu, tau, phi)` each of type array or float.
283
+ Returns an ndarray with axes corresponding to variation with `mu, tau, phi` respectively.
284
+ Pass `return_Fourier_error = True` (defaults to `False`) to return the
285
+ Cauchy / Fourier convergence evaluation (type: float) for the last Fourier term.
286
+ Pass `is_antiderivative_wrt_tau = True` (defaults to `False`)
287
+ to switch to an antiderivative of the function with respect to `tau`.
288
+
289
+ """
290
+ N = len(mu_arr_pos)
291
+ u_pos_interpol = sc.interpolate.BarycentricInterpolator(mu_arr_pos)
292
+ u_neg_interpol = sc.interpolate.BarycentricInterpolator(-mu_arr_pos)
293
+
294
+ def u_interpol(mu, tau, phi, return_Fourier_error=False, is_antiderivative_wrt_tau=False):
295
+ assert np.all(np.abs(mu) <= 1)
296
+ mu = np.atleast_1d(mu)
297
+
298
+ if return_Fourier_error:
299
+ u_cache, Fourier_error = u(tau, phi, True, is_antiderivative_wrt_tau)
300
+ else:
301
+ u_cache = u(tau, phi, False, is_antiderivative_wrt_tau)
302
+
303
+ u_shape = np.shape(u_cache)
304
+ assert N == u_shape[0] // 2 # Check that mu_arr_pos (of length N) matches the function u
305
+
306
+ results = np.empty((len(mu),) + u_shape[1:])
307
+ mask_pos = mu > 0
308
+ mask_else = ~mask_pos
309
+
310
+ if np.any(mask_pos):
311
+ u_pos_interpol.set_yi(u_cache[:N])
312
+ results[mask_pos] = u_pos_interpol(mu[mask_pos])
313
+ if np.any(mask_else):
314
+ u_neg_interpol.set_yi(u_cache[N:])
315
+ results[mask_else] = u_neg_interpol(mu[mask_else])
316
+
317
+ if return_Fourier_error:
318
+ return np.squeeze(results)[()], Fourier_error
319
+ else:
320
+ return np.squeeze(results)[()]
321
+
322
+ return u_interpol
323
+
324
+
265
325
  def _mathscr_v(tau, # Input optical depths
266
326
  l, # Layer index of each input optical depth
267
327
  s_poly_coeffs, # Polynomial coefficients of isotropic source
@@ -270,8 +330,8 @@ def _mathscr_v(tau, # Input optical depths
270
330
  K, # Eigenvalues
271
331
  G_inv, # Inverse of eigenvector matrix
272
332
  mu_arr, # Quadrature nodes for both hemispheres
333
+ is_antiderivative_wrt_tau=False, # Switch to an antiderivative of the function?
273
334
  _autograd_compatible=False, # Should the output functions be compatible with autograd?
274
- is_antiderivative_wrt_tau=False # Switch to an antiderivative of the function?
275
335
  ):
276
336
  """Particular solution for isotropic internal sources.
277
337
  Refer to Section 3.6.1 of the Comprehensive Documentation.
@@ -289,8 +349,8 @@ def _mathscr_v(tau, # Input optical depths
289
349
  | `K` | `NLayers<= x NQuad` |
290
350
  | `G_inv` | `NLayers<= x NQuad x NQuad` or `None` |
291
351
  | `mu_arr` | `NQuad` |
292
- | `_autograd_compatible` | boolean |
293
352
  | `is_antiderivative_wrt_tau` | boolean |
353
+ | `_autograd_compatible` | boolean |
294
354
 
295
355
  Notable internal variables of _mathscr_v
296
356
  | Variable | Shape |
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: PythonicDISORT
3
- Version: 0.8.0
3
+ Version: 0.9.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/Pythonic-DISORT
@@ -28,8 +28,10 @@ On the other hand, PythonicDISORT should be easier to install, use, and modify t
28
28
 
29
29
  PythonicDISORT is based on Stamnes' FORTRAN DISORT (see References, in particular [2, 3, 8]) and has its main features: multi-layer solver,
30
30
  delta-M scaling, Nakajima-Tanaka (NT) corrections, only flux option, direct beam source, isotropic internal source (blackbody emission),
31
- Dirichlet boundary conditions (diffuse flux boundary sources), Bi-Directional Reflectance Function (BDRF) for surface reflection, and more.
32
- In addition, subroutine to calculate actinic fluxes was added to satisfy a user request and further feature requests as well as feedback are welcome.
31
+ Dirichlet boundary conditions (diffuse flux boundary sources), Bi-Directional Reflectance Function (BDRF) for surface reflection,
32
+ interpolation with respect to polar angle and more.
33
+ In addition, we added a subroutine to calculate actinic fluxes to satisfy a user request, and integration with respect to tau was also added.
34
+ Further feature requests as well as feedback are welcome.
33
35
 
34
36
  You may contact me, Dion, through dh3065@columbia.edu.
35
37
 
@@ -50,8 +52,8 @@ Not only are there verification tests in `Pythonic-DISORT.ipynb`,
50
52
  most of the test problems in Stamnes' `disotest.f90` (download DISORT 4.0.99 from http://www.rtatmocn.com/disort/) have also been recreated.
51
53
  In these tests, the solutions from PythonicDISORT are compared against solutions
52
54
  from a F2PY-wrapped Stamnes' DISORT (version 4.0.99; wrapper inspired by https://github.com/kconnour/pyRT_DISORT). With PyTest installed, execute the console command `pytest`
53
- in the `pydisotest` directory to run these tests. The `pydisotest` directory also contains Jupyter Notebooks that correspond to each test
54
- to show how it was implemented. These notebooks double up as examples of how to use PythonicDISORT.
55
+ in the `pydisotest` directory to run these tests. The `pydisotest` directory also contains Jupyter Notebooks to show the implementation of each test.
56
+ These notebooks double up as examples of how to use PythonicDISORT.
55
57
 
56
58
  # Installation
57
59
 
File without changes