pyTSEB 2.1.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.
@@ -0,0 +1,385 @@
1
+ # This file is part of pyTSEB for processes related to the Monin-Obukhov Similarity Theory
2
+ # Copyright 2016 Hector Nieto and contributors listed in the README.md file.
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU Lesser General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU Lesser General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU Lesser General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ """
18
+ Created on Apr 6 2015
19
+ @author: Hector Nieto (hector.nieto@ica.csic.es)
20
+
21
+ DESCRIPTION
22
+ ===========
23
+ This package contains the main routines for estimating variables related to the
24
+ Monin-Obukhov (MO) Similarity Theory, such as MO length, adiabatic correctors
25
+ for heat and momentum transport. It requires the following package.
26
+
27
+ * :doc:`meteo_utils` for the estimation of meteorological variables.
28
+
29
+ PACKAGE CONTENTS
30
+ ================
31
+ * :func:`calc_L` Monin-Obukhov length.
32
+ * :func:`calc_richardson` Richardson number.
33
+ * :func:`calc_u_star` Friction velocity.
34
+
35
+ Stability correction functions
36
+ ------------------------------
37
+ * :func:`calc_Psi_H` Adiabatic correction factor for heat transport.
38
+ * :func:`calc_Psi_M` Adiabatic correction factor for momentum transport.
39
+ * :func:`CalcPhi_M_Brutsaert` [Brutsaert1992]_ similarity function for momentum transfer.
40
+ * :func:`CalcPhi_H_Dyer` [Dyer1974]_ similarity function for heat transfer.
41
+ * :func:`CalcPhi_M_Dyer` [Dyer1974]_ similarity function for momentum transfer.
42
+
43
+
44
+ """
45
+
46
+ import numpy as np
47
+
48
+ from . import meteo_utils as met
49
+
50
+ # ==============================================================================
51
+ # List of constants used in MO similarity
52
+ # ==============================================================================
53
+ # von Karman's constant
54
+ KARMAN = 0.41
55
+ # acceleration of gravity (m s-2)
56
+ GRAVITY = 9.8
57
+
58
+ UNSTABLE_THRES = None
59
+ STABLE_THRES = None
60
+
61
+ def calc_L(ustar, T_A_K, rho, c_p, H, LE):
62
+ '''Calculates the Monin-Obukhov length.
63
+
64
+ Parameters
65
+ ----------
66
+ ustar : float
67
+ friction velocity (m s-1).
68
+ T_A_K : float
69
+ air temperature (Kelvin).
70
+ rho : float
71
+ air density (kg m-3).
72
+ c_p : float
73
+ Heat capacity of air at constant pressure (J kg-1 K-1).
74
+ H : float
75
+ sensible heat flux (W m-2).
76
+ LE : float
77
+ latent heat flux (W m-2).
78
+
79
+ Returns
80
+ -------
81
+ L : float
82
+ Obukhov stability length (m).
83
+
84
+ References
85
+ ----------
86
+ .. [Brutsaert2005] Brutsaert, W. (2005). Hydrology: an introduction (Vol. 61, No. 8).
87
+ Cambridge: Cambridge University Press.'''
88
+
89
+ l_mo = calc_mo_length_hv(ustar, T_A_K, rho, c_p, H, LE)
90
+ return np.asarray(l_mo)
91
+
92
+
93
+ def calc_mo_length(ustar, T_A_K, rho, c_p, H):
94
+ '''Calculates the Monin-Obukhov length.
95
+
96
+ Parameters
97
+ ----------
98
+ ustar : float
99
+ friction velocity (m s-1).
100
+ T_A_K : float
101
+ air temperature (Kelvin).
102
+ rho : float
103
+ air density (kg m-3).
104
+ c_p : float
105
+ Heat capacity of air at constant pressure (J kg-1 K-1).
106
+ H : float
107
+ sensible heat flux (W m-2).
108
+ LE : float
109
+ latent heat flux (W m-2).
110
+
111
+ Returns
112
+ -------
113
+ L : float
114
+ Obukhov stability length (m).
115
+
116
+ References
117
+ ----------
118
+ .. [Brutsaert2005] Brutsaert, W. (2005). Hydrology: an introduction (Vol. 61, No. 8).
119
+ Cambridge: Cambridge University Press.'''
120
+
121
+ # Convert input scalars to numpy arrays
122
+ ustar, T_A_K, rho, c_p, H = map(
123
+ np.asarray, (ustar, T_A_K, rho, c_p, H))
124
+
125
+ L = np.asarray(np.ones(ustar.shape) * float('inf'))
126
+ i = H != 0
127
+ L[i] = - c_p[i] * T_A_K[i] * rho[i] * ustar[i]**3 / (KARMAN * GRAVITY * H[i])
128
+ return np.asarray(L)
129
+
130
+
131
+ def calc_mo_length_hv(ustar, T_A_K, rho, c_p, H, LE):
132
+ '''Calculates the Monin-Obukhov length.
133
+
134
+ Parameters
135
+ ----------
136
+ ustar : float
137
+ friction velocity (m s-1).
138
+ T_A_K : float
139
+ air temperature (Kelvin).
140
+ rho : float
141
+ air density (kg m-3).
142
+ c_p : float
143
+ Heat capacity of air at constant pressure (J kg-1 K-1).
144
+ H : float
145
+ sensible heat flux (W m-2).
146
+ LE : float
147
+ latent heat flux (W m-2).
148
+
149
+ Returns
150
+ -------
151
+ L : float
152
+ Obukhov stability length (m).
153
+
154
+ References
155
+ ----------
156
+ .. [Brutsaert2005] Brutsaert, W. (2005). Hydrology: an introduction (Vol. 61, No. 8).
157
+ Cambridge: Cambridge University Press.'''
158
+
159
+ # Convert input scalars to numpy arrays
160
+ ustar, T_A_K, rho, c_p, H, LE = map(
161
+ np.asarray, (ustar, T_A_K, rho, c_p, H, LE))
162
+ # first convert latent heat into rate of surface evaporation (kg m-2 s-1)
163
+ Lambda = met.calc_lambda(T_A_K) # in J kg-1
164
+ E = LE / Lambda
165
+ del LE, Lambda
166
+ # Virtual sensible heat flux
167
+ Hv = H + (0.61 * T_A_K * c_p * E)
168
+ del H, E
169
+
170
+ L = np.asarray(np.ones(ustar.shape) * float('inf'))
171
+ i = Hv != 0
172
+ L_const = np.asarray(KARMAN * GRAVITY / T_A_K)
173
+ L[i] = -ustar[i]**3 / (L_const[i] * (Hv[i] / (rho[i] * c_p[i])))
174
+ return np.asarray(L)
175
+
176
+ def calc_Psi_H(zoL):
177
+ ''' Calculates the adiabatic correction factor for heat transport.
178
+
179
+ Parameters
180
+ ----------
181
+ zoL : float
182
+ stability coefficient (unitless).
183
+
184
+ Returns
185
+ -------
186
+ Psi_H : float
187
+ adiabatic corrector factor fof heat transport (unitless).
188
+
189
+ References
190
+ ----------
191
+ .. [Brutsaert2005] Brutsaert, W. (2005). Hydrology: an introduction (Vol. 61, No. 8).
192
+ Cambridge: Cambridge University Press.
193
+ '''
194
+ # Avoid free convection situations
195
+ if UNSTABLE_THRES is not None or STABLE_THRES is not None:
196
+ zoL = np.clip(zoL, UNSTABLE_THRES, STABLE_THRES)
197
+ Psi_H = psi_h_brutsaert(zoL)
198
+ return np.asarray(Psi_H)
199
+
200
+ def psi_h_dyer(zol):
201
+
202
+ gamma = 16
203
+ beta = 5
204
+ # Convert input scalars to numpy array
205
+ zol = np.asarray(zol)
206
+ psi_h = np.zeros(zol.shape)
207
+ finite = np.isfinite(zol)
208
+ # for stable and netural (zoL = 0 -> Psi_H = 0) conditions
209
+ i = np.logical_and(finite, zol >= 0.0)
210
+ psi_h[i] = -beta * zol[i]
211
+ # for unstable conditions
212
+ i = np.logical_and(finite, zol < 0.0)
213
+ x = (1 - gamma * zol[i])**0.25
214
+ psi_h[i] = 2 * np.log((1 + x**2) / 2)
215
+ return psi_h
216
+
217
+
218
+ def psi_h_brutsaert(zol):
219
+ # Convert input scalars to numpy array
220
+ zol = np.asarray(zol)
221
+ psi_h = np.zeros(zol.shape)
222
+ finite = np.isfinite(zol)
223
+
224
+ # for stable and netural (zoL = 0 -> Psi_H = 0) conditions
225
+ i = np.logical_and(finite, zol >= 0.0)
226
+ a = 6.1
227
+ b = 2.5
228
+ psi_h[i] = -a * np.log(zol[i] + (1.0 + zol[i]**b)**(1. / b))
229
+
230
+ # for unstable conditions
231
+ i = np.logical_and(finite, zol < 0.0)
232
+ y = -zol[i]
233
+ del zol
234
+ c = 0.33
235
+ d = 0.057
236
+ n = 0.78
237
+ psi_h[i] = ((1.0 - d) / n) * np.log((c + y**n) / c)
238
+ return psi_h
239
+
240
+
241
+ def calc_Psi_M(zoL):
242
+ ''' Adiabatic correction factor for momentum transport.
243
+
244
+ Parameters
245
+ ----------
246
+ zoL : float
247
+ stability coefficient (unitless).
248
+
249
+ Returns
250
+ -------
251
+ Psi_M : float
252
+ adiabatic corrector factor fof momentum transport (unitless).
253
+
254
+ References
255
+ ----------
256
+ .. [Brutsaert2005] Brutsaert, W. (2005). Hydrology: an introduction (Vol. 61, No. 8).
257
+ Cambridge: Cambridge University Press.
258
+ '''
259
+ # Avoid free convection situations
260
+ if UNSTABLE_THRES is not None or STABLE_THRES is not None:
261
+ zoL = np.clip(zoL, UNSTABLE_THRES, STABLE_THRES)
262
+ Psi_M = psi_m_brutsaert(zoL)
263
+ return np.asarray(Psi_M)
264
+
265
+
266
+ def psi_m_dyer(zol):
267
+ gamma = 16
268
+ beta = 5
269
+ # Convert input scalars to numpy array
270
+ zol = np.asarray(zol)
271
+ finite = np.isfinite(zol)
272
+ psi_m = np.zeros(zol.shape)
273
+ # for stable and netural (zoL = 0 -> Psi_M = 0) conditions
274
+ i = np.logical_and(finite, zol >= 0.0)
275
+ psi_m[i] = -beta * zol[i]
276
+ # for unstable conditions
277
+ i = np.logical_and(finite, zol < 0.0)
278
+ x = (1 - gamma * zol[i]) ** 0.25
279
+ psi_m[i] = np.log((1 + x ** 2) / 2) + 2 * np.log((1 + x) / 2) \
280
+ - 2 * np.arctan(x) + np.pi / 2.
281
+
282
+ return psi_m
283
+
284
+
285
+ def psi_m_brutsaert(zol):
286
+ # Convert input scalars to numpy array
287
+ zol = np.asarray(zol)
288
+ finite = np.isfinite(zol)
289
+ psi_m = np.zeros(zol.shape)
290
+ # for stable and netural (zoL = 0 -> Psi_M = 0) conditions
291
+ i = np.logical_and(finite, zol >= 0.0)
292
+ a = 6.1
293
+ b = 2.5
294
+ psi_m[i] = -a * np.log(zol[i] + (1.0 + zol[i]**b)**(1.0 / b))
295
+ # for unstable conditions
296
+ i = np.logical_and(finite, zol < 0)
297
+ y = -zol[i]
298
+ del zol
299
+ a = 0.33
300
+ b = 0.41
301
+ x = np.asarray((y / a)**0.333333)
302
+
303
+ psi_0 = -np.log(a) + 3**0.5 * b * a**0.333333 * np.pi / 6.0
304
+ y = np.minimum(y, b**-3)
305
+ psi_m[i] = (np.log(a + y) - 3.0 * b * y**0.333333 +
306
+ (b * a**0.333333) / 2.0 * np.log((1.0 + x)**2 / (1.0 - x + x**2)) +
307
+ 3.0**0.5 * b * a**0.333333 * np.arctan((2.0 * x - 1.0) / 3**0.5) +
308
+ psi_0)
309
+
310
+ return psi_m
311
+
312
+ def calc_richardson(u, z_u, d_0, T_R0, T_R1, T_A0, T_A1):
313
+ '''Richardson number.
314
+
315
+ Estimates the Bulk Richardson number for turbulence using
316
+ time difference temperatures.
317
+
318
+ Parameters
319
+ ----------
320
+ u : float
321
+ Wind speed (m s-1).
322
+ z_u : float
323
+ Wind speed measurement height (m).
324
+ d_0 : float
325
+ Zero-plane displacement height (m).
326
+ T_R0 : float
327
+ radiometric surface temperature at time 0 (K).
328
+ T_R1 : float
329
+ radiometric surface temperature at time 1 (K).
330
+ T_A0 : float
331
+ air temperature at time 0 (K).
332
+ T_A1 : float
333
+ air temperature at time 1 (K).
334
+
335
+ Returns
336
+ -------
337
+ Ri : float
338
+ Richardson number.
339
+
340
+ References
341
+ ----------
342
+ .. [Norman2000] Norman, J. M., W. P. Kustas, J. H. Prueger, and G. R. Diak (2000),
343
+ Surface flux estimation using radiometric temperature: A dual-temperature-difference
344
+ method to minimize measurement errors, Water Resour. Res., 36(8), 2263-2274,
345
+ http://dx.doi.org/10.1029/2000WR900033.
346
+ '''
347
+
348
+ # See eq (2) from Louis 1979
349
+ Ri = -(GRAVITY * (z_u - d_0) / T_A1) * \
350
+ (((T_R1 - T_R0) - (T_A1 - T_A0)) / u**2) # equation (12) [Norman2000]
351
+ return np.asarray(Ri)
352
+
353
+
354
+ def calc_u_star(u, z_u, L, d_0, z_0M):
355
+ '''Friction velocity.
356
+
357
+ Parameters
358
+ ----------
359
+ u : float
360
+ wind speed above the surface (m s-1).
361
+ z_u : float
362
+ wind speed measurement height (m).
363
+ L : float
364
+ Monin Obukhov stability length (m).
365
+ d_0 : float
366
+ zero-plane displacement height (m).
367
+ z_0M : float
368
+ aerodynamic roughness length for momentum transport (m).
369
+
370
+ References
371
+ ----------
372
+ .. [Brutsaert2005] Brutsaert, W. (2005). Hydrology: an introduction (Vol. 61, No. 8).
373
+ Cambridge: Cambridge University Press.
374
+ '''
375
+
376
+ # Covert input scalars to numpy arrays
377
+ u, z_u, L, d_0, z_0M = map(np.asarray, (u, z_u, L, d_0, z_0M))
378
+
379
+ # calculate correction factors in other conditions
380
+ L[L == 0.0] = 1e-36
381
+ Psi_M = calc_Psi_M((z_u - d_0) / L)
382
+ Psi_M0 = calc_Psi_M(z_0M / L)
383
+ del L
384
+ u_star = u * KARMAN / (np.log((z_u - d_0) / z_0M) - Psi_M + Psi_M0)
385
+ return np.asarray(u_star)