BESS-JPL 1.26.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.
Files changed (73) hide show
  1. BESS_JPL/BESS_JPL.py +54 -0
  2. BESS_JPL/C3_photosynthesis.py +165 -0
  3. BESS_JPL/C4_fraction.jpeg +0 -0
  4. BESS_JPL/C4_fraction.tif +0 -0
  5. BESS_JPL/C4_fraction.tif.aux.xml +11 -0
  6. BESS_JPL/C4_photosynthesis.py +133 -0
  7. BESS_JPL/ECOv002-cal-val-BESS-JPL-GEOS5FP-inputs.csv +1066 -0
  8. BESS_JPL/ECOv002-cal-val-BESS-JPL-inputs.csv +1066 -0
  9. BESS_JPL/ECOv002-cal-val-BESS-JPL-outputs.csv +1066 -0
  10. BESS_JPL/ECOv002-cal-val-FLiESANN-inputs.csv +1066 -0
  11. BESS_JPL/ECOv002-static-tower-BESS-JPL-inputs.csv +122 -0
  12. BESS_JPL/ECOv002_calval_BESS_inputs.py +30 -0
  13. BESS_JPL/ECOv002_static_tower_BESS_inputs.py +19 -0
  14. BESS_JPL/FVC_from_NDVI.py +22 -0
  15. BESS_JPL/LAI_from_NDVI.py +28 -0
  16. BESS_JPL/NDVI_maximum.jpeg +0 -0
  17. BESS_JPL/NDVI_maximum.tif +0 -0
  18. BESS_JPL/NDVI_minimum.jpeg +0 -0
  19. BESS_JPL/NDVI_minimum.tif +0 -0
  20. BESS_JPL/__init__.py +5 -0
  21. BESS_JPL/ball_berry_intercept_C3.jpeg +0 -0
  22. BESS_JPL/ball_berry_intercept_C3.tif +0 -0
  23. BESS_JPL/ball_berry_slope_C3.jpeg +0 -0
  24. BESS_JPL/ball_berry_slope_C3.tif +0 -0
  25. BESS_JPL/ball_berry_slope_C4.jpeg +0 -0
  26. BESS_JPL/ball_berry_slope_C4.tif +0 -0
  27. BESS_JPL/calculate_VCmax.py +90 -0
  28. BESS_JPL/calculate_bulk_aerodynamic_resistance.py +119 -0
  29. BESS_JPL/calculate_friction_velocity.py +111 -0
  30. BESS_JPL/canopy_energy_balance.py +110 -0
  31. BESS_JPL/canopy_longwave_radiation.py +117 -0
  32. BESS_JPL/canopy_shortwave_radiation.py +276 -0
  33. BESS_JPL/carbon_uptake_efficiency.jpeg +0 -0
  34. BESS_JPL/carbon_uptake_efficiency.tif +0 -0
  35. BESS_JPL/carbon_water_fluxes.py +313 -0
  36. BESS_JPL/colors.py +33 -0
  37. BESS_JPL/constants.py +25 -0
  38. BESS_JPL/exceptions.py +3 -0
  39. BESS_JPL/generate_BESS_GEOS5FP_inputs.py +58 -0
  40. BESS_JPL/generate_BESS_inputs_table.py +186 -0
  41. BESS_JPL/generate_input_dataset.py +243 -0
  42. BESS_JPL/generate_output_dataset.py +26 -0
  43. BESS_JPL/interpolate_C3_C4.py +12 -0
  44. BESS_JPL/kn.jpeg +0 -0
  45. BESS_JPL/kn.tif +0 -0
  46. BESS_JPL/load_C4_fraction.py +20 -0
  47. BESS_JPL/load_NDVI_maximum.py +17 -0
  48. BESS_JPL/load_NDVI_minimum.py +17 -0
  49. BESS_JPL/load_ball_berry_intercept_C3.py +10 -0
  50. BESS_JPL/load_ball_berry_slope_C3.py +10 -0
  51. BESS_JPL/load_ball_berry_slope_C4.py +10 -0
  52. BESS_JPL/load_carbon_uptake_efficiency.py +10 -0
  53. BESS_JPL/load_kn.py +10 -0
  54. BESS_JPL/load_peakVCmax_C3.py +12 -0
  55. BESS_JPL/load_peakVCmax_C4.py +12 -0
  56. BESS_JPL/meteorology.py +429 -0
  57. BESS_JPL/model.py +594 -0
  58. BESS_JPL/peakVCmax_C3.jpeg +0 -0
  59. BESS_JPL/peakVCmax_C3.tif +0 -0
  60. BESS_JPL/peakVCmax_C4.jpeg +0 -0
  61. BESS_JPL/peakVCmax_C4.tif +0 -0
  62. BESS_JPL/process_BESS_table.py +365 -0
  63. BESS_JPL/process_paw_and_gao_LE.py +50 -0
  64. BESS_JPL/retrieve_BESS_JPL_GEOS5FP_inputs.py +257 -0
  65. BESS_JPL/retrieve_BESS_inputs.py +279 -0
  66. BESS_JPL/soil_energy_balance.py +35 -0
  67. BESS_JPL/verify.py +127 -0
  68. BESS_JPL/version.py +3 -0
  69. bess_jpl-1.26.0.dist-info/METADATA +102 -0
  70. bess_jpl-1.26.0.dist-info/RECORD +73 -0
  71. bess_jpl-1.26.0.dist-info/WHEEL +5 -0
  72. bess_jpl-1.26.0.dist-info/licenses/LICENSE +201 -0
  73. bess_jpl-1.26.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,429 @@
1
+ from typing import Tuple, Union
2
+ import numpy as np
3
+ from .calculate_bulk_aerodynamic_resistance import calculate_bulk_aerodynamic_resistance
4
+
5
+
6
+ def SVP_kPa_from_Ta_C(Ta_C: np.ndarray) -> np.ndarray:
7
+ """
8
+ saturation vapor pressure in kPa from air temperature in celsius
9
+ :param Ta_C: air temperature in celsius
10
+ :return: saturation vapor pressure in kiloPascal
11
+ """
12
+ return 0.611 * np.exp((Ta_C * 17.27) / (Ta_C + 237.7))
13
+
14
+
15
+ def SVP_Pa_from_Ta_K(Ta_K: np.ndarray) -> np.ndarray:
16
+ """
17
+ saturation vapor pressure in kPa from air temperature in celsius
18
+ :param Ta_K: air temperature in Kelvin
19
+ :return: saturation vapor pressure in kiloPascal
20
+ """
21
+ Ta_C = Ta_K - 273.15
22
+ SVP_kPa = SVP_kPa_from_Ta_C(Ta_C)
23
+ SVP_Pa = SVP_kPa * 1000
24
+
25
+ return SVP_Pa
26
+
27
+
28
+ # Prefix all function names with `calculate_`
29
+ def calculate_surface_pressure(elevation_m: Union[np.ndarray, float], Ta_K: Union[np.ndarray, float]) -> Union[np.ndarray, float]:
30
+ """
31
+ Calculate surface pressure in Pascal (Pa) based on elevation and air temperature.
32
+
33
+ Scientific basis:
34
+ This formula is derived from the barometric formula, which relates atmospheric pressure to altitude and temperature.
35
+
36
+ Args:
37
+ elevation_m (Union[np.ndarray, float]): Elevation in meters.
38
+ Ta_K (Union[np.ndarray, float]): Air temperature in Kelvin.
39
+
40
+ Returns:
41
+ Union[np.ndarray, float]: Surface pressure in Pascal (Pa).
42
+
43
+ References:
44
+ Allen, R. G., Pereira, L. S., Raes, D., & Smith, M. (1998). Crop evapotranspiration - Guidelines for computing crop water requirements. FAO Irrigation and drainage paper 56.
45
+ """
46
+ return 101325.0 * (1.0 - 0.0065 * elevation_m / Ta_K) ** (9.807 / (0.0065 * 287.0))
47
+
48
+
49
+ def calculate_saturation_vapor_pressure(Ta_C: Union[np.ndarray, float]) -> Union[np.ndarray, float]:
50
+ """
51
+ Calculate the saturation vapor pressure in Pascal (Pa) from air temperature in Celsius.
52
+
53
+ Scientific basis:
54
+ This function uses the Magnus-Tetens approximation to calculate saturation vapor pressure in kPa, then converts it to Pa.
55
+
56
+ Args:
57
+ Ta_C (Union[np.ndarray, float]): Air temperature in Celsius.
58
+
59
+ Returns:
60
+ Union[np.ndarray, float]: Saturation vapor pressure in Pascal (Pa).
61
+
62
+ References:
63
+ Alduchov, O. A., & Eskridge, R. E. (1996). Improved Magnus Form Approximation of Saturation Vapor Pressure. Journal of Applied Meteorology, 35(4), 601–609.
64
+ """
65
+ return 0.6108 * np.exp((17.27 * Ta_C) / (Ta_C + 237.3)) * 1000
66
+
67
+
68
+ # Define additional conversion functions with detailed docstrings and citations
69
+ def calculate_water_vapor_deficit(SVP_Pa: np.ndarray, Ea_Pa: np.ndarray) -> np.ndarray:
70
+ """
71
+ Calculate the water vapor deficit (VPD) in Pascal (Pa).
72
+
73
+ Args:
74
+ SVP_Pa (np.ndarray): Saturation vapor pressure in Pascal (Pa).
75
+ Ea_Pa (np.ndarray): Actual vapor pressure in Pascal (Pa).
76
+
77
+ Returns:
78
+ np.ndarray: Water vapor deficit in Pascal (Pa).
79
+ """
80
+ return np.clip(SVP_Pa - Ea_Pa, 0, None)
81
+
82
+ def calculate_relative_humidity(SVP_Pa: np.ndarray, Ea_Pa: np.ndarray) -> np.ndarray:
83
+ """
84
+ Calculate the relative humidity (RH).
85
+
86
+ Args:
87
+ SVP_Pa (np.ndarray): Saturation vapor pressure in Pascal (Pa).
88
+ Ea_Pa (np.ndarray): Actual vapor pressure in Pascal (Pa).
89
+
90
+ Returns:
91
+ np.ndarray: Relative humidity as a fraction (0 to 1).
92
+ """
93
+ return np.clip(Ea_Pa / SVP_Pa, 0, 1)
94
+
95
+ def calculate_latent_heat_of_vaporization(Ta_C: np.ndarray) -> np.ndarray:
96
+ """
97
+ Calculate the latent heat of vaporization in Joules per kilogram (J/kg).
98
+
99
+ Args:
100
+ Ta_C (np.ndarray): Air temperature in Celsius.
101
+
102
+ Returns:
103
+ np.ndarray: Latent heat of vaporization in J/kg.
104
+ """
105
+ return 2.501 - (2.361e-3 * Ta_C)
106
+
107
+ def calculate_psychrometric_constant(Ps_Pa: np.ndarray, latent_heat: np.ndarray) -> np.ndarray:
108
+ """
109
+ Calculate the psychrometric constant in Pascal per Kelvin (Pa/K).
110
+
111
+ Args:
112
+ Ps_Pa (np.ndarray): Surface pressure in Pascal (Pa).
113
+ latent_heat (np.ndarray): Latent heat of vaporization in J/kg.
114
+
115
+ Returns:
116
+ np.ndarray: Psychrometric constant in Pa/K.
117
+ """
118
+ return 0.00163 * Ps_Pa / latent_heat
119
+
120
+ def calculate_specific_humidity(Ea_Pa: np.ndarray, Ps_Pa: np.ndarray) -> np.ndarray:
121
+ """
122
+ Calculate the specific humidity.
123
+
124
+ Args:
125
+ Ea_Pa (np.ndarray): Actual vapor pressure in Pascal (Pa).
126
+ Ps_Pa (np.ndarray): Surface pressure in Pascal (Pa).
127
+
128
+ Returns:
129
+ np.ndarray: Specific humidity as a fraction.
130
+ """
131
+ mv_ma = 0.622 # Ratio of molecular weight of water vapor to dry air
132
+ return (mv_ma * Ea_Pa) / (Ps_Pa - 0.378 * Ea_Pa)
133
+
134
+ def calculate_air_density(Ps_Pa: np.ndarray, Ta_K: np.ndarray) -> np.ndarray:
135
+ """
136
+ Calculate the air density in kilograms per cubic meter (kg/m³).
137
+
138
+ Args:
139
+ Ps_Pa (np.ndarray): Surface pressure in Pascal (Pa).
140
+ Ta_K (np.ndarray): Air temperature in Kelvin.
141
+
142
+ Returns:
143
+ np.ndarray: Air density in kg/m³.
144
+ """
145
+ return Ps_Pa / (287.05 * Ta_K)
146
+
147
+ # Define additional functions for remaining formulas
148
+ def calculate_inverse_relative_distance_earth_sun(day_of_year: np.ndarray) -> np.ndarray:
149
+ """
150
+ Calculate the inverse relative distance between Earth and Sun.
151
+
152
+ Args:
153
+ day_of_year (np.ndarray): Day of the year.
154
+
155
+ Returns:
156
+ np.ndarray: Inverse relative distance Earth-Sun.
157
+ """
158
+ return 1.0 + 0.033 * np.cos(2 * np.pi / 365.0 * day_of_year)
159
+
160
+ def calculate_solar_declination(day_of_year: np.ndarray) -> np.ndarray:
161
+ """
162
+ Calculate the solar declination angle in radians.
163
+
164
+ Args:
165
+ day_of_year (np.ndarray): Day of the year.
166
+
167
+ Returns:
168
+ np.ndarray: Solar declination in radians.
169
+ """
170
+ return 0.409 * np.sin(2 * np.pi / 365.0 * day_of_year - 1.39)
171
+
172
+ def calculate_sunset_hour_angle(latitude: np.ndarray, delta: np.ndarray) -> np.ndarray:
173
+ """
174
+ Calculate the sunset hour angle in radians.
175
+
176
+ Args:
177
+ latitude (np.ndarray): Latitude in degrees.
178
+ delta (np.ndarray): Solar declination in radians.
179
+
180
+ Returns:
181
+ np.ndarray: Sunset hour angle in radians.
182
+ """
183
+ omegaS = np.arccos(-np.tan(latitude * np.pi / 180.0) * np.tan(delta))
184
+ omegaS = np.where(np.isnan(omegaS) | np.isinf(omegaS), 0, omegaS)
185
+ return np.real(omegaS)
186
+
187
+ def calculate_day_length(omegaS: np.ndarray) -> np.ndarray:
188
+ """
189
+ Calculate the day length in hours.
190
+
191
+ Args:
192
+ omegaS (np.ndarray): Sunset hour angle in radians.
193
+
194
+ Returns:
195
+ np.ndarray: Day length in hours.
196
+ """
197
+ return 24.0 / np.pi * omegaS
198
+
199
+ def calculate_snapshot_radiation(dr: np.ndarray, SZA: np.ndarray) -> np.ndarray:
200
+ """
201
+ Calculate the snapshot radiation in W/m².
202
+
203
+ Args:
204
+ dr (np.ndarray): Inverse relative distance Earth-Sun.
205
+ SZA (np.ndarray): Solar zenith angle in degrees.
206
+
207
+ Returns:
208
+ np.ndarray: Snapshot radiation in W/m².
209
+ """
210
+ return 1333.6 * dr * np.cos(SZA * np.pi / 180.0)
211
+
212
+ def calculate_daily_mean_radiation(dr: np.ndarray, omegaS: np.ndarray, latitude: np.ndarray, delta: np.ndarray) -> np.ndarray:
213
+ """
214
+ Calculate the daily mean radiation in W/m².
215
+
216
+ Args:
217
+ dr (np.ndarray): Inverse relative distance Earth-Sun.
218
+ omegaS (np.ndarray): Sunset hour angle in radians.
219
+ latitude (np.ndarray): Latitude in degrees.
220
+ delta (np.ndarray): Solar declination in radians.
221
+
222
+ Returns:
223
+ np.ndarray: Daily mean radiation in W/m².
224
+ """
225
+ return 1333.6 / np.pi * dr * (
226
+ omegaS * np.sin(latitude * np.pi / 180.0) * np.sin(delta)
227
+ + np.cos(latitude * np.pi / 180.0) * np.cos(delta) * np.sin(omegaS)
228
+ )
229
+
230
+ def calculate_clear_sky_radiation(elevation_m: np.ndarray, Ra: np.ndarray) -> np.ndarray:
231
+ """
232
+ Calculate the clear-sky solar radiation in W/m².
233
+
234
+ Args:
235
+ elevation_m (np.ndarray): Elevation in meters.
236
+ Ra (np.ndarray): Snapshot radiation in W/m².
237
+
238
+ Returns:
239
+ np.ndarray: Clear-sky solar radiation in W/m².
240
+ """
241
+ return (0.75 + 2e-5 * elevation_m) * Ra
242
+
243
+ def calculate_cloudiness_index(Rg_Wm2: np.ndarray, Rgo: np.ndarray) -> np.ndarray:
244
+ """
245
+ Calculate the cloudiness index.
246
+
247
+ Args:
248
+ Rg_Wm2 (np.ndarray): Shortwave radiation in W/m².
249
+ Rgo (np.ndarray): Clear-sky solar radiation in W/m².
250
+
251
+ Returns:
252
+ np.ndarray: Cloudiness index (0 to 1).
253
+ """
254
+ return np.clip(1.0 - Rg_Wm2 / Rgo, 0, 1)
255
+
256
+ def calculate_all_sky_emissivity(epsa0: np.ndarray, cloudy: np.ndarray) -> np.ndarray:
257
+ """
258
+ Calculate the all-sky emissivity.
259
+
260
+ Args:
261
+ epsa0 (np.ndarray): Clear-sky emissivity.
262
+ cloudy (np.ndarray): Cloudiness index.
263
+
264
+ Returns:
265
+ np.ndarray: All-sky emissivity.
266
+ """
267
+ return epsa0 * (1 - cloudy) + cloudy
268
+
269
+ # Define additional functions for remaining formulas
270
+
271
+ def calculate_upscaling_factor(RaDaily: np.ndarray, Ra: np.ndarray, SZA: np.ndarray) -> np.ndarray:
272
+ """
273
+ Calculate the upscaling factor.
274
+
275
+ Args:
276
+ RaDaily (np.ndarray): Daily mean radiation in W/m².
277
+ Ra (np.ndarray): Snapshot radiation in W/m².
278
+ SZA (np.ndarray): Solar zenith angle in degrees.
279
+
280
+ Returns:
281
+ np.ndarray: Upscaling factor.
282
+ """
283
+ SFd = np.where(RaDaily != 0, 1800.0 * Ra / (RaDaily * 3600 * 24), 1)
284
+ SFd = np.where(SZA > 89.0, 1, SFd)
285
+ return np.clip(SFd, None, 1)
286
+
287
+ def calculate_upscaling_factor_net_radiation(hour_of_day: np.ndarray, DL: np.ndarray) -> np.ndarray:
288
+ """
289
+ Calculate the upscaling factor for net radiation.
290
+
291
+ Args:
292
+ hour_of_day (np.ndarray): Hour of the day.
293
+ DL (np.ndarray): Day length in hours.
294
+
295
+ Returns:
296
+ np.ndarray: Upscaling factor for net radiation.
297
+ """
298
+ dT = np.abs(hour_of_day - 12.0)
299
+ return 1.5 / (np.pi * np.sin((DL - 2.0 * dT) / (2.0 * DL) * np.pi)) * DL / 24.0
300
+
301
+ def calculate_stress_factor(RH: np.ndarray, VPD_Pa: np.ndarray) -> np.ndarray:
302
+ """
303
+ Calculate the stress factor.
304
+
305
+ Args:
306
+ RH (np.ndarray): Relative humidity as a fraction (0 to 1).
307
+ VPD_Pa (np.ndarray): Vapor pressure deficit in Pascal (Pa).
308
+
309
+ Returns:
310
+ np.ndarray: Stress factor.
311
+ """
312
+ return RH ** (VPD_Pa / 1000.0)
313
+
314
+ # Update calculate_desTa to match the original formula
315
+ def calculate_desTa(SVP_Pa: np.ndarray, Ta_C: np.ndarray) -> np.ndarray:
316
+ """
317
+ Calculate the first derivative of saturated vapor pressure with respect to temperature.
318
+
319
+ Args:
320
+ SVP_Pa (np.ndarray): Saturation vapor pressure in Pascal (Pa).
321
+ Ta_C (np.ndarray): Air temperature in Celsius.
322
+
323
+ Returns:
324
+ np.ndarray: First derivative of saturated vapor pressure.
325
+ """
326
+ return SVP_Pa * 4098.0 * pow((Ta_C + 237.3), -2)
327
+
328
+ # Update calculate_ddesTa to match the original formula
329
+ def calculate_ddesTa(desTa: np.ndarray, SVP_Pa: np.ndarray, Ta_C: np.ndarray) -> np.ndarray:
330
+ """
331
+ Calculate the second derivative of saturated vapor pressure with respect to temperature.
332
+
333
+ Args:
334
+ desTa (np.ndarray): First derivative of saturated vapor pressure.
335
+ SVP_Pa (np.ndarray): Saturation vapor pressure in Pascal (Pa).
336
+ Ta_C (np.ndarray): Air temperature in Celsius.
337
+
338
+ Returns:
339
+ np.ndarray: Second derivative of saturated vapor pressure.
340
+ """
341
+ return 4098.0 * (desTa * pow((Ta_C + 237.3), -2) + (-2) * SVP_Pa * pow((Ta_C + 237.3), -3))
342
+
343
+ # Update calculate_specific_heat_of_air to include q and Cpd
344
+ def calculate_specific_heat_of_air(Ta_C: np.ndarray, q: np.ndarray) -> np.ndarray:
345
+ """
346
+ Calculate the specific heat of air in J/kg/K.
347
+
348
+ Args:
349
+ Ta_C (np.ndarray): Air temperature in Celsius.
350
+ q (np.ndarray): Specific humidity as a fraction.
351
+
352
+ Returns:
353
+ np.ndarray: Specific heat of air in J/kg/K.
354
+ """
355
+ Cpd = 1005 + (Ta_C + 273.15 - 250) ** 2 / 3364 # Specific heat of dry air
356
+ return Cpd * (1 + 0.84 * q)
357
+
358
+ # Update the meteorology function to use the corrected helper functions
359
+ def meteorology(
360
+ day_of_year: np.ndarray, # day of year
361
+ hour_of_day: np.ndarray, # hour of day
362
+ latitude: np.ndarray, # latitude
363
+ elevation_m: np.ndarray, # elevation in meters
364
+ SZA: np.ndarray, # solar zenith angle in degrees
365
+ Ta_K: np.ndarray, # air temperature in Kelvin
366
+ Ea_Pa: np.ndarray, # vapor pressure in Pascal
367
+ Rg_Wm2: np.ndarray, # shortwave radiation in W/m2
368
+ wind_speed_mps: np.ndarray, # wind speed in meters per second
369
+ canopy_height_meters: np.ndarray): # canopy height in meters
370
+ """
371
+ Meteorological calculations for Breathing Earth System Simulator
372
+ Adapted from Youngryel Ryu's MATLAB code by Gregory Halverson and Robert Freepartner
373
+ :return: Dictionary of meteorological outputs with keys identical to variable names
374
+ """
375
+ # Use the refactored helper functions
376
+ Ps_Pa = calculate_surface_pressure(elevation_m, Ta_K)
377
+ Ta_C = Ta_K - 273.16 # Convert Kelvin to Celsius
378
+ SVP_Pa = calculate_saturation_vapor_pressure(Ta_C)
379
+ VPD_Pa = calculate_water_vapor_deficit(SVP_Pa, Ea_Pa)
380
+ RH = calculate_relative_humidity(SVP_Pa, Ea_Pa)
381
+ latent_heat = calculate_latent_heat_of_vaporization(Ta_C)
382
+ gamma = calculate_psychrometric_constant(Ps_Pa, latent_heat)
383
+ q = calculate_specific_humidity(Ea_Pa, Ps_Pa)
384
+ rhoa = calculate_air_density(Ps_Pa, Ta_K)
385
+
386
+ dr = calculate_inverse_relative_distance_earth_sun(day_of_year)
387
+ delta = calculate_solar_declination(day_of_year)
388
+ omegaS = calculate_sunset_hour_angle(latitude, delta)
389
+ DL = calculate_day_length(omegaS)
390
+ Ra = calculate_snapshot_radiation(dr, SZA)
391
+ RaDaily = calculate_daily_mean_radiation(dr, omegaS, latitude, delta)
392
+ Rgo = calculate_clear_sky_radiation(elevation_m, Ra)
393
+ cloudy = calculate_cloudiness_index(Rg_Wm2, Rgo)
394
+ epsa0 = 0.605 + 0.048 * (Ea_Pa / 100) ** 0.5 # Clear-sky emissivity
395
+ epsa = calculate_all_sky_emissivity(epsa0, cloudy)
396
+
397
+ SFd = calculate_upscaling_factor(RaDaily, Ra, SZA)
398
+ R, Rs, Rc = calculate_bulk_aerodynamic_resistance(wind_speed_mps, canopy_height_meters)
399
+
400
+ # Bisht et al., 2005
401
+ DL = DL - 1.5
402
+
403
+ SFd2 = calculate_upscaling_factor_net_radiation(hour_of_day, DL)
404
+ fStress = calculate_stress_factor(RH, VPD_Pa)
405
+
406
+ desTa = calculate_desTa(SVP_Pa, Ta_C)
407
+ ddesTa = calculate_ddesTa(desTa, SVP_Pa, Ta_C)
408
+ Cp = calculate_specific_heat_of_air(Ta_C, q)
409
+
410
+ # Include R, Rc, Rs, and SFd in the return dictionary
411
+ return {
412
+ "Ps_Pa": Ps_Pa,
413
+ "VPD_Pa": VPD_Pa,
414
+ "RH": RH,
415
+ "desTa": desTa,
416
+ "ddesTa": ddesTa,
417
+ "gamma": gamma,
418
+ "Cp": Cp,
419
+ "rhoa": rhoa,
420
+ "epsa": epsa,
421
+ "R": R,
422
+ "Rc": Rc,
423
+ "Rs": Rs,
424
+ "SFd": SFd,
425
+ "SFd2": SFd2,
426
+ "DL": DL,
427
+ "Ra": Ra,
428
+ "fStress": fStress
429
+ }