Spaces:
Runtime error
Runtime error
| """ | |
| Library of functions for estimating reference evapotransporation (ETo) for | |
| a grass reference crop using the FAO-56 Penman-Monteith and Hargreaves | |
| equations. The library includes numerous functions for estimating missing | |
| meteorological data. | |
| :copyright: (c) 2015 by Mark Richards. | |
| :license: BSD 3-Clause, see LICENSE.txt for more details. | |
| """ | |
| import numpy as np | |
| from ._check import ( | |
| check_day_hours as _check_day_hours, | |
| check_doy as _check_doy, | |
| check_latitude_rad as _check_latitude_rad, | |
| check_sol_dec_rad as _check_sol_dec_rad, | |
| check_sunset_hour_angle_rad as _check_sunset_hour_angle_rad, | |
| ) | |
| #: Solar constant [ MJ m-2 min-1] | |
| SOLAR_CONSTANT = 0.0820 | |
| # Stefan Boltzmann constant [MJ K-4 m-2 day-1] | |
| STEFAN_BOLTZMANN_CONSTANT = 0.000000004903 # | |
| """Stefan Boltzmann constant [MJ K-4 m-2 day-1]""" | |
| def atm_pressure(altitude): | |
| """ | |
| Estimate atmospheric pressure from altitude. | |
| Calculated using a simplification of the ideal gas law, assuming 20 degrees | |
| Celsius for a standard atmosphere. Based on equation 7, page 62 in Allen | |
| et al (1998). | |
| :param altitude: Elevation/altitude above sea level [m] | |
| :return: atmospheric pressure [kPa] | |
| :rtype: float | |
| """ | |
| tmp = (293.0 - (0.0065 * altitude)) / 293.0 | |
| return np.power(tmp, 5.26) * 101.3 | |
| def avp_from_tmin(tmin): | |
| """ | |
| Estimate actual vapour pressure (*ea*) from minimum temperature. | |
| This method is to be used where humidity data are lacking or are of | |
| questionable quality. The method assumes that the dewpoint temperature | |
| is approximately equal to the minimum temperature (*tmin*), i.e. the | |
| air is saturated with water vapour at *tmin*. | |
| **Note**: This assumption may not hold in arid/semi-arid areas. | |
| In these areas it may be better to subtract 2 deg C from the | |
| minimum temperature (see Annex 6 in FAO paper). | |
| Based on equation 48 in Allen et al (1998). | |
| :param tmin: Daily minimum temperature [deg C] | |
| :return: Actual vapour pressure [kPa] | |
| :rtype: float | |
| """ | |
| return 0.611 * np.exp((17.27 * tmin) / (tmin + 237.3)) | |
| def avp_from_rhmin_rhmax(svp_tmin, svp_tmax, rh_min, rh_max): | |
| """ | |
| Estimate actual vapour pressure (*ea*) from saturation vapour pressure and | |
| relative humidity. | |
| Based on FAO equation 17 in Allen et al (1998). | |
| :param svp_tmin: Saturation vapour pressure at daily minimum temperature | |
| [kPa]. Can be estimated using ``svp_from_t()``. | |
| :param svp_tmax: Saturation vapour pressure at daily maximum temperature | |
| [kPa]. Can be estimated using ``svp_from_t()``. | |
| :param rh_min: Minimum relative humidity [%] | |
| :param rh_max: Maximum relative humidity [%] | |
| :return: Actual vapour pressure [kPa] | |
| :rtype: float | |
| """ | |
| tmp1 = svp_tmin * (rh_max / 100.0) | |
| tmp2 = svp_tmax * (rh_min / 100.0) | |
| return (tmp1 + tmp2) / 2.0 | |
| def avp_from_rhmax(svp_tmin, rh_max): | |
| """ | |
| Estimate actual vapour pressure (*e*a) from saturation vapour pressure at | |
| daily minimum temperature and maximum relative humidity | |
| Based on FAO equation 18 in Allen et al (1998). | |
| :param svp_tmin: Saturation vapour pressure at daily minimum temperature | |
| [kPa]. Can be estimated using ``svp_from_t()``. | |
| :param rh_max: Maximum relative humidity [%] | |
| :return: Actual vapour pressure [kPa] | |
| :rtype: float | |
| """ | |
| return svp_tmin * (rh_max / 100.0) | |
| def avp_from_rhmean(svp_tmin, svp_tmax, rh_mean): | |
| """ | |
| Estimate actual vapour pressure (*ea*) from saturation vapour pressure at | |
| daily minimum and maximum temperature, and mean relative humidity. | |
| Based on FAO equation 19 in Allen et al (1998). | |
| :param svp_tmin: Saturation vapour pressure at daily minimum temperature | |
| [kPa]. Can be estimated using ``svp_from_t()``. | |
| :param svp_tmax: Saturation vapour pressure at daily maximum temperature | |
| [kPa]. Can be estimated using ``svp_from_t()``. | |
| :param rh_mean: Mean relative humidity [%] (average of RH min and RH max). | |
| :return: Actual vapour pressure [kPa] | |
| :rtype: float | |
| """ | |
| return (rh_mean / 100.0) * ((svp_tmax + svp_tmin) / 2.0) | |
| def avp_from_tdew(tdew): | |
| """ | |
| Estimate actual vapour pressure (*ea*) from dewpoint temperature. | |
| Based on equation 14 in Allen et al (1998). As the dewpoint temperature is | |
| the temperature to which air needs to be cooled to make it saturated, the | |
| actual vapour pressure is the saturation vapour pressure at the dewpoint | |
| temperature. | |
| This method is preferable to calculating vapour pressure from | |
| minimum temperature. | |
| :param tdew: Dewpoint temperature [deg C] | |
| :return: Actual vapour pressure [kPa] | |
| :rtype: float | |
| """ | |
| return 0.6108 * np.exp((17.27 * tdew) / (tdew + 237.3)) | |
| def avp_from_twet_tdry(twet, tdry, svp_twet, psy_const): | |
| """ | |
| Estimate actual vapour pressure (*ea*) from wet and dry bulb temperature. | |
| Based on equation 15 in Allen et al (1998). As the dewpoint temperature | |
| is the temperature to which air needs to be cooled to make it saturated, the | |
| actual vapour pressure is the saturation vapour pressure at the dewpoint | |
| temperature. | |
| This method is preferable to calculating vapour pressure from | |
| minimum temperature. | |
| Values for the psychrometric constant of the psychrometer (*psy_const*) | |
| can be calculated using ``psyc_const_of_psychrometer()``. | |
| :param twet: Wet bulb temperature [deg C] | |
| :param tdry: Dry bulb temperature [deg C] | |
| :param svp_twet: Saturated vapour pressure at the wet bulb temperature | |
| [kPa]. Can be estimated using ``svp_from_t()``. | |
| :param psy_const: Psychrometric constant of the pyschrometer [kPa deg C-1]. | |
| Can be estimated using ``psy_const()`` or | |
| ``psy_const_of_psychrometer()``. | |
| :return: Actual vapour pressure [kPa] | |
| :rtype: float | |
| """ | |
| return svp_twet - (psy_const * (tdry - twet)) | |
| def cs_rad(altitude, et_rad): | |
| """ | |
| Estimate clear sky radiation from altitude and extraterrestrial radiation. | |
| Based on equation 37 in Allen et al (1998) which is recommended when | |
| calibrated Angstrom values are not available. | |
| :param altitude: Elevation above sea level [m] | |
| :param et_rad: Extraterrestrial radiation [MJ m-2 day-1]. Can be | |
| estimated using ``et_rad()``. | |
| :return: Clear sky radiation [MJ m-2 day-1] | |
| :rtype: float | |
| """ | |
| return (0.00002 * altitude + 0.75) * et_rad | |
| def daily_mean_t(tmin, tmax): | |
| """ | |
| Estimate mean daily temperature from the daily minimum and maximum | |
| temperatures. | |
| :param tmin: Minimum daily temperature [deg C] | |
| :param tmax: Maximum daily temperature [deg C] | |
| :return: Mean daily temperature [deg C] | |
| :rtype: float | |
| """ | |
| return (tmax + tmin) / 2.0 | |
| def daylight_hours(sha): | |
| """ | |
| Calculate daylight hours from sunset hour angle. | |
| Based on FAO equation 34 in Allen et al (1998). | |
| :param sha: Sunset hour angle [rad]. Can be calculated using | |
| ``sunset_hour_angle()``. | |
| :return: Daylight hours. | |
| :rtype: float | |
| """ | |
| _check_sunset_hour_angle_rad(sha) | |
| return (24.0 / np.pi) * sha | |
| def delta_svp(t): | |
| """ | |
| Estimate the slope of the saturation vapour pressure curve at a given | |
| temperature. | |
| Based on equation 13 in Allen et al (1998). If using in the Penman-Monteith | |
| *t* should be the mean air temperature. | |
| :param t: Air temperature [deg C]. Use mean air temperature for use in | |
| Penman-Monteith. | |
| :return: Saturation vapour pressure [kPa degC-1] | |
| :rtype: float | |
| """ | |
| tmp = 4098 * (0.6108 * np.exp((17.27 * t) / (t + 237.3))) | |
| return tmp / np.power((t + 237.3), 2) | |
| def energy2evap(energy): | |
| """ | |
| Convert energy (e.g. radiation energy) in MJ m-2 day-1 to the equivalent | |
| evaporation, assuming a grass reference crop. | |
| Energy is converted to equivalent evaporation using a conversion | |
| factor equal to the inverse of the latent heat of vapourisation | |
| (1 / lambda = 0.408). | |
| Based on FAO equation 20 in Allen et al (1998). | |
| :param energy: Energy e.g. radiation or heat flux [MJ m-2 day-1]. | |
| :return: Equivalent evaporation [mm day-1]. | |
| :rtype: float | |
| """ | |
| return 0.408 * energy | |
| def et_rad(latitude, sol_dec, sha, ird): | |
| """ | |
| Estimate daily extraterrestrial radiation (*Ra*, 'top of the atmosphere | |
| radiation'). | |
| Based on equation 21 in Allen et al (1998). If monthly mean radiation is | |
| required make sure *sol_dec*. *sha* and *irl* have been calculated using | |
| the day of the year that corresponds to the middle of the month. | |
| **Note**: From Allen et al (1998): "For the winter months in latitudes | |
| greater than 55 degrees (N or S), the equations have limited validity. | |
| Reference should be made to the Smithsonian Tables to assess possible | |
| deviations." | |
| :param latitude: Latitude [radians] | |
| :param sol_dec: Solar declination [radians]. Can be calculated using | |
| ``sol_dec()``. | |
| :param sha: Sunset hour angle [radians]. Can be calculated using | |
| ``sunset_hour_angle()``. | |
| :param ird: Inverse relative distance earth-sun [dimensionless]. Can be | |
| calculated using ``inv_rel_dist_earth_sun()``. | |
| :return: Daily extraterrestrial radiation [MJ m-2 day-1] | |
| :rtype: float | |
| """ | |
| _check_latitude_rad(latitude) | |
| _check_sol_dec_rad(sol_dec) | |
| _check_sunset_hour_angle_rad(sha) | |
| tmp1 = (24.0 * 60.0) / np.pi | |
| tmp2 = sha * np.sin(latitude) * np.sin(sol_dec) | |
| tmp3 = np.cos(latitude) * np.cos(sol_dec) * np.sin(sha) | |
| return tmp1 * SOLAR_CONSTANT * ird * (tmp2 + tmp3) | |
| def fao56_penman_monteith(net_rad, t, ws, svp, avp, delta_svp, psy, shf=0.0): | |
| """ | |
| Estimate reference evapotranspiration (ETo) from a hypothetical | |
| short grass reference surface using the FAO-56 Penman-Monteith equation. | |
| Based on equation 6 in Allen et al (1998). | |
| :param net_rad: Net radiation at crop surface [MJ m-2 day-1]. If | |
| necessary this can be estimated using ``net_rad()``. | |
| :param t: Air temperature at 2 m height [deg Kelvin]. | |
| :param ws: Wind speed at 2 m height [m s-1]. If not measured at 2m, | |
| convert using ``wind_speed_at_2m()``. | |
| :param svp: Saturation vapour pressure [kPa]. Can be estimated using | |
| ``svp_from_t()''. | |
| :param avp: Actual vapour pressure [kPa]. Can be estimated using a range | |
| of functions with names beginning with 'avp_from'. | |
| :param delta_svp: Slope of saturation vapour pressure curve [kPa degC-1]. | |
| Can be estimated using ``delta_svp()``. | |
| :param psy: Psychrometric constant [kPa deg C]. Can be estimatred using | |
| ``psy_const_of_psychrometer()`` or ``psy_const()``. | |
| :param shf: Soil heat flux (G) [MJ m-2 day-1] (default is 0.0, which is | |
| reasonable for a daily or 10-day time steps). For monthly time steps | |
| *shf* can be estimated using ``monthly_soil_heat_flux()`` or | |
| ``monthly_soil_heat_flux2()``. | |
| :return: Reference evapotranspiration (ETo) from a hypothetical | |
| grass reference surface [mm day-1]. | |
| :rtype: float | |
| """ | |
| a1 = (0.408 * (net_rad - shf) * delta_svp / | |
| (delta_svp + (psy * (1 + 0.34 * ws)))) | |
| a2 = (900 * ws / t * (svp - avp) * psy / | |
| (delta_svp + (psy * (1 + 0.34 * ws)))) | |
| return a1 + a2 | |
| def hargreaves(tmin, tmax, tmean, et_rad): | |
| """ | |
| Estimate reference evapotranspiration over grass (ETo) using the Hargreaves | |
| equation. | |
| Generally, when solar radiation data, relative humidity data | |
| and/or wind speed data are missing, it is better to estimate them using | |
| the functions available in this module, and then calculate ETo | |
| the FAO Penman-Monteith equation. However, as an alternative, ETo can be | |
| estimated using the Hargreaves ETo equation. | |
| Based on equation 52 in Allen et al (1998). | |
| :param tmin: Minimum daily temperature [deg C] | |
| :param tmax: Maximum daily temperature [deg C] | |
| :param tmean: Mean daily temperature [deg C]. If emasurements not | |
| available it can be estimated as (*tmin* + *tmax*) / 2. | |
| :param et_rad: Extraterrestrial radiation (Ra) [MJ m-2 day-1]. Can be | |
| estimated using ``et_rad()``. | |
| :return: Reference evapotranspiration over grass (ETo) [mm day-1] | |
| :rtype: float | |
| """ | |
| # Note, multiplied by 0.408 to convert extraterrestrial radiation could | |
| # be given in MJ m-2 day-1 rather than as equivalent evaporation in | |
| # mm day-1 | |
| return 0.0023 * (tmean + 17.8) * (tmax - tmin) ** 0.5 * 0.408 * et_rad | |
| def inv_rel_dist_earth_sun(day_of_year): | |
| """ | |
| Calculate the inverse relative distance between earth and sun from | |
| day of the year. | |
| Based on FAO equation 23 in Allen et al (1998). | |
| :param day_of_year: Day of the year [1 to 366] | |
| :return: Inverse relative distance between earth and the sun | |
| :rtype: float | |
| """ | |
| _check_doy(day_of_year) | |
| return 1 + (0.033 * np.cos((2.0 * np.pi / 365.0) * day_of_year)) | |
| def mean_svp(tmin, tmax): | |
| """ | |
| Estimate mean saturation vapour pressure, *es* [kPa] from minimum and | |
| maximum temperature. | |
| Based on equations 11 and 12 in Allen et al (1998). | |
| Mean saturation vapour pressure is calculated as the mean of the | |
| saturation vapour pressure at tmax (maximum temperature) and tmin | |
| (minimum temperature). | |
| :param tmin: Minimum temperature [deg C] | |
| :param tmax: Maximum temperature [deg C] | |
| :return: Mean saturation vapour pressure (*es*) [kPa] | |
| :rtype: float | |
| """ | |
| return (svp_from_t(tmin) + svp_from_t(tmax)) / 2.0 | |
| def monthly_soil_heat_flux(t_month_prev, t_month_next): | |
| """ | |
| Estimate monthly soil heat flux (Gmonth) from the mean air temperature of | |
| the previous and next month, assuming a grass crop. | |
| Based on equation 43 in Allen et al (1998). If the air temperature of the | |
| next month is not known use ``monthly_soil_heat_flux2()`` instead. The | |
| resulting heat flux can be converted to equivalent evaporation [mm day-1] | |
| using ``energy2evap()``. | |
| :param t_month_prev: Mean air temperature of the previous month | |
| [deg Celsius] | |
| :param t_month2_next: Mean air temperature of the next month [deg Celsius] | |
| :return: Monthly soil heat flux (Gmonth) [MJ m-2 day-1] | |
| :rtype: float | |
| """ | |
| return 0.07 * (t_month_next - t_month_prev) | |
| def monthly_soil_heat_flux2(t_month_prev, t_month_cur): | |
| """ | |
| Estimate monthly soil heat flux (Gmonth) [MJ m-2 day-1] from the mean | |
| air temperature of the previous and current month, assuming a grass crop. | |
| Based on equation 44 in Allen et al (1998). If the air temperature of the | |
| next month is available, use ``monthly_soil_heat_flux()`` instead. The | |
| resulting heat flux can be converted to equivalent evaporation [mm day-1] | |
| using ``energy2evap()``. | |
| Arguments: | |
| :param t_month_prev: Mean air temperature of the previous month | |
| [deg Celsius] | |
| :param t_month_cur: Mean air temperature of the current month [deg Celsius] | |
| :return: Monthly soil heat flux (Gmonth) [MJ m-2 day-1] | |
| :rtype: float | |
| """ | |
| return 0.14 * (t_month_cur - t_month_prev) | |
| def net_in_sol_rad(sol_rad, albedo=0.23): | |
| """ | |
| Calculate net incoming solar (or shortwave) radiation from gross | |
| incoming solar radiation, assuming a grass reference crop. | |
| Net incoming solar radiation is the net shortwave radiation resulting | |
| from the balance between incoming and reflected solar radiation. The | |
| output can be converted to equivalent evaporation [mm day-1] using | |
| ``energy2evap()``. | |
| Based on FAO equation 38 in Allen et al (1998). | |
| :param sol_rad: Gross incoming solar radiation [MJ m-2 day-1]. If | |
| necessary this can be estimated using functions whose name | |
| begins with 'sol_rad_from'. | |
| :param albedo: Albedo of the crop as the proportion of gross incoming solar | |
| radiation that is reflected by the surface. Default value is 0.23, | |
| which is the value used by the FAO for a short grass reference crop. | |
| Albedo can be as high as 0.95 for freshly fallen snow and as low as | |
| 0.05 for wet bare soil. A green vegetation over has an albedo of | |
| about 0.20-0.25 (Allen et al, 1998). | |
| :return: Net incoming solar (or shortwave) radiation [MJ m-2 day-1]. | |
| :rtype: float | |
| """ | |
| return (1 - albedo) * sol_rad | |
| def net_out_lw_rad(tmin, tmax, sol_rad, cs_rad, avp): | |
| """ | |
| Estimate net outgoing longwave radiation. | |
| This is the net longwave energy (net energy flux) leaving the | |
| earth's surface. It is proportional to the absolute temperature of | |
| the surface raised to the fourth power according to the Stefan-Boltzmann | |
| law. However, water vapour, clouds, carbon dioxide and dust are absorbers | |
| and emitters of longwave radiation. This function corrects the Stefan- | |
| Boltzmann law for humidity (using actual vapor pressure) and cloudiness | |
| (using solar radiation and clear sky radiation). The concentrations of all | |
| other absorbers are assumed to be constant. | |
| The output can be converted to equivalent evaporation [mm day-1] using | |
| ``energy2evap()``. | |
| Based on FAO equation 39 in Allen et al (1998). | |
| :param tmin: Absolute daily minimum temperature [degrees Kelvin] | |
| :param tmax: Absolute daily maximum temperature [degrees Kelvin] | |
| :param sol_rad: Solar radiation [MJ m-2 day-1]. If necessary this can be | |
| estimated using ``sol+rad()``. | |
| :param cs_rad: Clear sky radiation [MJ m-2 day-1]. Can be estimated using | |
| ``cs_rad()``. | |
| :param avp: Actual vapour pressure [kPa]. Can be estimated using functions | |
| with names beginning with 'avp_from'. | |
| :return: Net outgoing longwave radiation [MJ m-2 day-1] | |
| :rtype: float | |
| """ | |
| tmp1 = (STEFAN_BOLTZMANN_CONSTANT * | |
| ((np.power(tmax, 4) + np.power(tmin, 4)) / 2)) | |
| tmp2 = (0.34 - (0.14 * np.sqrt(avp))) | |
| tmp3 = 1.35 * (sol_rad / cs_rad) - 0.35 | |
| return tmp1 * tmp2 * tmp3 | |
| def net_rad(ni_sw_rad, no_lw_rad): | |
| """ | |
| Calculate daily net radiation at the crop surface, assuming a grass | |
| reference crop. | |
| Net radiation is the difference between the incoming net shortwave (or | |
| solar) radiation and the outgoing net longwave radiation. Output can be | |
| converted to equivalent evaporation [mm day-1] using ``energy2evap()``. | |
| Based on equation 40 in Allen et al (1998). | |
| :param ni_sw_rad: Net incoming shortwave radiation [MJ m-2 day-1]. Can be | |
| estimated using ``net_in_sol_rad()``. | |
| :param no_lw_rad: Net outgoing longwave radiation [MJ m-2 day-1]. Can be | |
| estimated using ``net_out_lw_rad()``. | |
| :return: Daily net radiation [MJ m-2 day-1]. | |
| :rtype: float | |
| """ | |
| return ni_sw_rad - no_lw_rad | |
| def psy_const(atmos_pres): | |
| """ | |
| Calculate the psychrometric constant. | |
| This method assumes that the air is saturated with water vapour at the | |
| minimum daily temperature. This assumption may not hold in arid areas. | |
| Based on equation 8, page 95 in Allen et al (1998). | |
| :param atmos_pres: Atmospheric pressure [kPa]. Can be estimated using | |
| ``atm_pressure()``. | |
| :return: Psychrometric constant [kPa degC-1]. | |
| :rtype: float | |
| """ | |
| return 0.000665 * atmos_pres | |
| def psy_const_of_psychrometer(psychrometer, atmos_pres): | |
| """ | |
| Calculate the psychrometric constant for different types of | |
| psychrometer at a given atmospheric pressure. | |
| Based on FAO equation 16 in Allen et al (1998). | |
| :param psychrometer: Integer between 1 and 3 which denotes type of | |
| psychrometer: | |
| 1. ventilated (Asmann or aspirated type) psychrometer with | |
| an air movement of approximately 5 m/s | |
| 2. natural ventilated psychrometer with an air movement | |
| of approximately 1 m/s | |
| 3. non ventilated psychrometer installed indoors | |
| :param atmos_pres: Atmospheric pressure [kPa]. Can be estimated using | |
| ``atm_pressure()``. | |
| :return: Psychrometric constant [kPa degC-1]. | |
| :rtype: float | |
| """ | |
| # Select coefficient based on type of ventilation of the wet bulb | |
| if psychrometer == 1: | |
| psy_coeff = 0.000662 | |
| elif psychrometer == 2: | |
| psy_coeff = 0.000800 | |
| elif psychrometer == 3: | |
| psy_coeff = 0.001200 | |
| else: | |
| raise ValueError( | |
| 'psychrometer should be in range 1 to 3: {0!r}'.format(psychrometer)) | |
| return psy_coeff * atmos_pres | |
| def rh_from_avp_svp(avp, svp): | |
| """ | |
| Calculate relative humidity as the ratio of actual vapour pressure | |
| to saturation vapour pressure at the same temperature. | |
| See Allen et al (1998), page 67 for details. | |
| :param avp: Actual vapour pressure [units do not matter so long as they | |
| are the same as for *svp*]. Can be estimated using functions whose | |
| name begins with 'avp_from'. | |
| :param svp: Saturated vapour pressure [units do not matter so long as they | |
| are the same as for *avp*]. Can be estimated using ``svp_from_t()``. | |
| :return: Relative humidity [%]. | |
| :rtype: float | |
| """ | |
| return 100.0 * avp / svp | |
| def sol_dec(day_of_year): | |
| """ | |
| Calculate solar declination from day of the year. | |
| Based on FAO equation 24 in Allen et al (1998). | |
| :param day_of_year: Day of year integer between 1 and 365 or 366). | |
| :return: solar declination [radians] | |
| :rtype: float | |
| """ | |
| _check_doy(day_of_year) | |
| return 0.409 * np.sin(((2.0 * np.pi / 365.0) * day_of_year - 1.39)) | |
| def sol_rad_from_sun_hours(daylight_hours, sunshine_hours, et_rad): | |
| """ | |
| Calculate incoming solar (or shortwave) radiation, *Rs* (radiation hitting | |
| a horizontal plane after scattering by the atmosphere) from relative | |
| sunshine duration. | |
| If measured radiation data are not available this method is preferable | |
| to calculating solar radiation from temperature. If a monthly mean is | |
| required then divide the monthly number of sunshine hours by number of | |
| days in the month and ensure that *et_rad* and *daylight_hours* was | |
| calculated using the day of the year that corresponds to the middle of | |
| the month. | |
| Based on equations 34 and 35 in Allen et al (1998). | |
| :param dl_hours: Number of daylight hours [hours]. Can be calculated | |
| using ``daylight_hours()``. | |
| :param sunshine_hours: Sunshine duration [hours]. | |
| :param et_rad: Extraterrestrial radiation [MJ m-2 day-1]. Can be | |
| estimated using ``et_rad()``. | |
| :return: Incoming solar (or shortwave) radiation [MJ m-2 day-1] | |
| :rtype: float | |
| """ | |
| _check_day_hours(sunshine_hours, 'sun_hours') | |
| _check_day_hours(daylight_hours, 'daylight_hours') | |
| # 0.5 and 0.25 are default values of regression constants (Angstrom values) | |
| # recommended by FAO when calibrated values are unavailable. | |
| return (0.5 * sunshine_hours / daylight_hours + 0.25) * et_rad | |
| def sol_rad_from_t(et_rad, cs_rad, tmin, tmax, coastal): | |
| """ | |
| Estimate incoming solar (or shortwave) radiation, *Rs*, (radiation hitting | |
| a horizontal plane after scattering by the atmosphere) from min and max | |
| temperature together with an empirical adjustment coefficient for | |
| 'interior' and 'coastal' regions. | |
| The formula is based on equation 50 in Allen et al (1998) which is the | |
| Hargreaves radiation formula (Hargreaves and Samani, 1982, 1985). This | |
| method should be used only when solar radiation or sunshine hours data are | |
| not available. It is only recommended for locations where it is not | |
| possible to use radiation data from a regional station (either because | |
| climate conditions are heterogeneous or data are lacking). | |
| **NOTE**: this method is not suitable for island locations due to the | |
| moderating effects of the surrounding water. | |
| :param et_rad: Extraterrestrial radiation [MJ m-2 day-1]. Can be | |
| estimated using ``et_rad()``. | |
| :param cs_rad: Clear sky radiation [MJ m-2 day-1]. Can be estimated | |
| using ``cs_rad()``. | |
| :param tmin: Daily minimum temperature [deg C]. | |
| :param tmax: Daily maximum temperature [deg C]. | |
| :param coastal: ``True`` if site is a coastal location, situated on or | |
| adjacent to coast of a large land mass and where air masses are | |
| influenced by a nearby water body, ``False`` if interior location | |
| where land mass dominates and air masses are not strongly influenced | |
| by a large water body. | |
| :return: Incoming solar (or shortwave) radiation (Rs) [MJ m-2 day-1]. | |
| :rtype: float | |
| """ | |
| # Determine value of adjustment coefficient [deg C-0.5] for | |
| # coastal/interior locations | |
| if coastal: | |
| adj = 0.19 | |
| else: | |
| adj = 0.16 | |
| sol_rad = adj * np.sqrt(tmax - tmin) * et_rad | |
| # The solar radiation value is constrained by the clear sky radiation | |
| return np.minimum(sol_rad, cs_rad) | |
| def sol_rad_island(et_rad): | |
| """ | |
| Estimate incoming solar (or shortwave) radiation, *Rs* (radiation hitting | |
| a horizontal plane after scattering by the atmosphere) for an island | |
| location. | |
| An island is defined as a land mass with width perpendicular to the | |
| coastline <= 20 km. Use this method only if radiation data from | |
| elsewhere on the island is not available. | |
| **NOTE**: This method is only applicable for low altitudes (0-100 m) | |
| and monthly calculations. | |
| Based on FAO equation 51 in Allen et al (1998). | |
| :param et_rad: Extraterrestrial radiation [MJ m-2 day-1]. Can be | |
| estimated using ``et_rad()``. | |
| :return: Incoming solar (or shortwave) radiation [MJ m-2 day-1]. | |
| :rtype: float | |
| """ | |
| return (0.7 * et_rad) - 4.0 | |
| def sunset_hour_angle(latitude, sol_dec): | |
| """ | |
| Calculate sunset hour angle (*Ws*) from latitude and solar | |
| declination. | |
| Based on FAO equation 25 in Allen et al (1998). | |
| :param latitude: Latitude [radians]. Note: *latitude* should be negative | |
| if it in the southern hemisphere, positive if in the northern | |
| hemisphere. | |
| :param sol_dec: Solar declination [radians]. Can be calculated using | |
| ``sol_dec()``. | |
| :return: Sunset hour angle [radians]. | |
| :rtype: float | |
| """ | |
| _check_latitude_rad(latitude) | |
| _check_sol_dec_rad(sol_dec) | |
| cos_sha = -np.tan(latitude) * np.tan(sol_dec) | |
| # If tmp is >= 1 there is no sunset, i.e. 24 hours of daylight | |
| # If tmp is <= 1 there is no sunrise, i.e. 24 hours of darkness | |
| # See http://www.itacanet.org/the-sun-as-a-source-of-energy/ | |
| # part-3-calculating-solar-angles/ | |
| # Domain of acos is -1 <= x <= 1 radians (this is not mentioned in FAO-56!) | |
| return np.arccos(np.minimum(np.maximum(cos_sha, -1.0), 1.0)) | |
| def svp_from_t(t): | |
| """ | |
| Estimate saturation vapour pressure (*es*) from air temperature. | |
| Based on equations 11 and 12 in Allen et al (1998). | |
| :param t: Temperature [deg C] | |
| :return: Saturation vapour pressure [kPa] | |
| :rtype: float | |
| """ | |
| return 0.6108 * np.exp((17.27 * t) / (t + 237.3)) | |
| def wind_speed_2m(ws, z): | |
| """ | |
| Convert wind speed measured at different heights above the soil | |
| surface to wind speed at 2 m above the surface, assuming a short grass | |
| surface. | |
| Based on FAO equation 47 in Allen et al (1998). | |
| :param ws: Measured wind speed [m s-1] | |
| :param z: Height of wind measurement above ground surface [m] | |
| :return: Wind speed at 2 m above the surface [m s-1] | |
| :rtype: float | |
| """ | |
| return ws * (4.87 / np.log((67.8 * z) - 5.42)) | |