File size: 5,163 Bytes
64ab846 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | import numpy as np
## INPUT variables
# maximum temperature in Celsius
# minimum temperature in Celsius
# mean temperature in Celsius
# minimum relative humidity in percentage
# maximum relative humidity in percentage
# wind speed at 2 meters in m/s
# solar radiation in MJ/m^2/day
# doy is day of the year (1-365)
# Constants
Gsc = 0.0820 # Solar constant (MJ/m^2/min)
sigma = 4.903e-9 # Stefan-Boltzmann constant (MJ/K^4/m^2/day)
# Functions to calculate various components needed for ET0 calculation
def calculate_extraterrestrial_radiation(latitude, doy):
phi = np.radians(latitude)
dr = 1 + 0.033 * np.cos(2 * np.pi / 365 * doy)
delta = 0.409 * np.sin(2 * np.pi / 365 * doy - 1.39)
omega = np.arccos(-np.tan(phi) * np.tan(delta))
Ra = (24 * 60 / np.pi) * Gsc * dr * (omega * np.sin(phi) * np.sin(delta) + np.cos(phi) * np.cos(delta) * np.sin(omega))
return Ra
def calculate_clear_sky_radiation(Ra, elevation):
return (0.75 + 2e-5 * elevation) * Ra
def calculate_net_solar_radiation(Rs):
return (1 - 0.23) * Rs
def calculate_net_outgoing_longwave_radiation(T_max, T_min, Rs, Rso, ea):
T_max_K = T_max + 273.15 # Convert to Kelvin
T_min_K = T_min + 273.15 # Convert to Kelvin
return sigma * ((T_max_K ** 4 + T_min_K ** 4) / 2) * (0.34 - 0.14 * np.sqrt(ea)) * (1.35 * Rs / Rso - 0.35)
def calculate_slope_of_saturation_vapor_pressure_curve(T_mean):
return 4098 * (0.6108 * np.exp(17.27 * T_mean / (T_mean + 237.3))) / (T_mean + 237.3) ** 2
def calculate_psychrometric_constant(elevation):
P = 101.3 * ((293 - 0.0065 * elevation) / 293) ** 5.26
return 0.665e-3 * P
def calculate_saturation_vapor_pressure(T):
return 0.6108 * np.exp(17.27 * T / (T + 237.3))
def calculate_mean_saturation_vapor_pressure(T_max, T_min):
es_Tmax = calculate_saturation_vapor_pressure(T_max)
es_Tmin = calculate_saturation_vapor_pressure(T_min)
return (es_Tmax + es_Tmin) / 2
def calculate_actual_vapor_pressure(T_min, T_max, RH_min, RH_max):
es_min = calculate_saturation_vapor_pressure(T_min)
es_max = calculate_saturation_vapor_pressure(T_max)
ea = (es_min * RH_max / 100 + es_max * RH_min / 100) / 2
return ea
def calculate_reference_evapotranspiration(T_max, T_min, T_mean, RH_min, RH_max, u2, Rs, elevation, latitude, doy):
# Calculate radiation components
Ra = calculate_extraterrestrial_radiation(latitude, doy)
Rso = calculate_clear_sky_radiation(Ra, elevation)
Rns = calculate_net_solar_radiation(Rs)
# Calculate vapor pressure components
es = calculate_mean_saturation_vapor_pressure(T_max, T_min)
ea = calculate_actual_vapor_pressure(T_min, T_max, RH_min, RH_max)
# Calculate net outgoing longwave radiation
Rnl = calculate_net_outgoing_longwave_radiation(T_max, T_min, Rs, Rso, ea)
# Calculate net radiation
Rn = Rns - Rnl
# Calculate slope of saturation vapor pressure curve
Delta = calculate_slope_of_saturation_vapor_pressure_curve(T_mean)
# Calculate psychrometric constant
gamma = calculate_psychrometric_constant(elevation)
# Soil heat flux density (G) is 0 for daily timestep
G = 0
# Calculate reference evapotranspiration (ET0)
ET0 = (0.408 * Delta * (Rn - G) + gamma * (900 / (T_mean + 273)) * u2 * (es - ea)) / (Delta + gamma * (1 + 0.34 * u2))
return ET0
# # Define Kc values based on FAO guidelines
def calculate_kc_fao(Kcini, Kcmid, Kcend, doy):
"""Calculate the Kc value based on the day of the year (doy)"""
# Define stage durations (these are approximations, adjust based on your specific vineyard phenology)
start_day = 90 # Bud break (end of March)
mid_day = start_day + 60 # Initial stage ends
full_cover_day = mid_day + 40 # Crop development stage ends
harvest_day = full_cover_day + 70 # Midseason stage ends
end_season_day = harvest_day + 40 # Late season ends
if doy < mid_day:
return Kcini
elif doy < full_cover_day:
return Kcini + (Kcmid - Kcini) * (doy - mid_day) / (full_cover_day - mid_day)
elif doy < harvest_day:
return Kcmid
elif doy < end_season_day:
return Kcmid + (Kcend - Kcmid) * (doy - harvest_day) / (end_season_day - harvest_day)
else:
return Kcend
# Generic arable crops
def kc_generic(NDVI):
return 1.457 * NDVI - 0.1725
# Campos et al. 2010 (irrigated vineyards, La Mancha region)
def kc_campos(NDVI):
return 1.44 * NDVI - 0.10
# Er-Raki et al., 2013 (table grapes in northwest Mexico)
def kc_erraki(NDVI):
return 0.1808 * np.exp(1.3138 * NDVI)
def kc_tasumi(NDVI):
return 1.18 * NDVI + 0.04
def calculate_etc(T_max, T_min, T_mean, RH_min, RH_max, u2, Rs, elevation, latitude, doy, Kcini=0.30, Kcmid=0.70, Kcend=0.45):
et0 = calculate_reference_evapotranspiration(T_max, T_min, T_mean, RH_min, RH_max, u2, Rs, elevation, latitude, doy)
# ndvi = get_ndvi(NIR, RED) # NDVI = (NIR - RED) / (NIR + RED)
kc = calculate_kc_fao(Kcini, Kcmid, Kcend, doy)
return et0*kc |