HydPy-Evap-RET-FAO56 (FAO-56 Penman-Monteith reference evapotranspiration)

evap_ret_fao56 follows the guideline provided by Allen et al. (1998). However, there are some differences in input data assumptions (averaged daily temperature and relative humidity values instead of maximum and minimum values).

The primary purpose of evap_ret_fao56 is to serve as a submodel that provides estimates of potential grass reference evapotranspiration. However, you can also use it as a stand-alone model, as it does not require interaction with a main model. The following examples make use of this stand-alone functionality.

On the other hand, evap_ret_fao56 requires two submodels. One must follow the RadiationModel_V1 or the RadiationModel_V3 interface and provide clear-sky solar radiation and global radiation data; the other must follow the TempModel_V1 or the TempModel_V2 interface and provide temperature data. Regarding radiation, meteo_glob_fao56 is an obvious choice, as it follows the FAO guideline, too.

Integration tests

Note

When new to HydPy, consider reading section Integration Tests first.

Application model evap_ret_fao56 requires no input from an external model and does not supply any data to an outlet sequence. Hence, assigning a model instance to a blank Element instance is sufficient:

>>> from hydpy import Element
>>> from hydpy.models.evap_ret_fao56 import *
>>> parameterstep()
>>> element = Element("element")
>>> element.model = model

daily simulation

The first example deals with a daily simulation time step. We calculate the reference evapotranspiration on 6 July in Uccle (Brussels, Belgium) and take the following parameter values and input values from example 18 of Allen et al. (1998):

>>> from hydpy import IntegrationTest, pub
>>> pub.timegrids = "2000-07-06", "2000-07-07", "1d"
>>> nmbhru(1)
>>> hruarea(1.0)
>>> measuringheightwindspeed(10.0)
>>> evapotranspirationfactor(1.0)
>>> with model.add_radiationmodel_v3("meteo_clear_glob_io"):
...     pass
>>> with model.add_tempmodel_v2("meteo_temp_io"):
...     temperatureaddend(0.0)
>>> test = IntegrationTest(element)
>>> test.dateformat = "%Y-%d-%m"
>>> model.tempmodel.sequences.inputs.temperature.series = 16.9
>>> inputs.relativehumidity.series = 73.0
>>> inputs.windspeed.series = 10.0 * 1000.0 / 60.0 / 60.0
>>> inputs.atmosphericpressure.series = 1001.0

The following global and clear sky solar radiation values are the results of the daily simulation integration test of meteo_glob_fao56 that also recalculates example 18 of Allen et al. (1998):

>>> model.radiationmodel.sequences.inputs.clearskysolarradiation.series = 356.40121
>>> model.radiationmodel.sequences.inputs.globalradiation.series = 255.367464

The calculated reference evapotranspiration is about 0.1 mm (3 %) smaller than the one given by Allen et al. (1998). This discrepancy is mainly due to different ways to calculate SaturationVapourPressure. Allen et al. (1998) estimates it both for the minimum and maximum temperature and averages the results, while evap_ret_fao56 directly applies the corresponding formula to the average air temperature. The first approach results in higher pressure values due to the nonlinearity of the vapour pressure curve. All other methodical differences show, at least in this example, less severe impacts:

>>> test()
Click to see the table

hourly simulation

The second example deals with an hourly simulation over multiple time steps. We calculate the reference evapotranspiration from 30 September to 1 October in N’Diaye (Senegal) and take (or try to derive as well as possible) all parameter and input values from example 19 of FAO:

>>> measuringheightwindspeed(2.0)

Example 19 of ref-Allen1998 gives results for the intervals between 2 and 3 o’clock and between 14 and 15 o’clock only. We assume these clock times are referring to UTC-1:

>>> pub.options.utcoffset = -60
>>> pub.options.utclongitude = -15
>>> pub.timegrids = "2001-09-30 02:00", "2001-10-01 15:00", "1h"

This time, we do not let meteo_clear_glob_io provide the precalculated clear-sky and global radiation of the hourly simulation integration test, which corresponds to example 19 of Allen et al. (1998), but let meteo_glob_fao56 calculate it on the fly:

>>> with model.add_radiationmodel_v1("meteo_glob_fao56"):
...     latitude(16.0 + 0.13 / 60 * 100)
...     longitude(-16.25)
...     angstromconstant(0.25)
...     angstromfactor(0.5)
>>> parameters.update()
>>> test = IntegrationTest(element)
>>> test.dateformat = "%Y-%d-%m %H:00"
>>> sunshineduration = model.radiationmodel.sequences.inputs.sunshineduration
>>> sunshineduration.series = 0.0
>>> sunshineduration.series[3:16] = 0.8
>>> sunshineduration.series[27:] = numpy.linspace(0.82, 0.88, 10)

We set constant input sequence values from the start of the simulation period to the first interval and interpolate linearly between the first and the second interval, which is also the end of the simulation period:

>>> import numpy
>>> def interpolate(sequence, value1, value2):
...     sequence.series[:-13] = value1
...     sequence.series[-13:] = numpy.linspace(value1, value2, 13)
>>> interpolate(model.tempmodel.sequences.inputs.temperature, 28.0, 38.0)
>>> interpolate(inputs.relativehumidity, 90.0, 52.0)
>>> interpolate(inputs.windspeed, 1.9, 3.3)
>>> interpolate(inputs.atmosphericpressure, 1001.0, 1001.0)

To avoid calculating nan values at night within the first 24 hours, we arbitrarily set the values of both log sequences to one:

>>> logs.loggedclearskysolarradiation = 277.777778
>>> logs.loggedglobalradiation = 277.777778

Regarding reference evapotranspiration, the results match perfectly within the specified accuracy. Compared with the above example, the better agreement with the results reported by Allen et al. (1998) is due to the more consistent calculation of the saturation vapour pressure:

>>> test("evap_ret_fao56_hourly", update_parameters=False,
...      axis1=fluxes.referenceevapotranspiration)
Click to see the table
Click to see the graph
class hydpy.models.evap_ret_fao56.Model[source]

Bases: Main_TempModel_V1, Main_TempModel_V2A, Main_RadiationModel_V1, Main_RadiationModel_V3, Sub_ETModel, PETModel_V1

HydPy-Evap-RET-FAO56 (FAO-56 Penman-Monteith reference evapotranspiration).

The following “run methods” are called in the given sequence during each simulation step:
The following interface methods are available to main models using the defined model as a submodel:
The following “additional methods” might be called by one or more of the other methods or are meant to be directly called by the user:
Users can hook submodels into the defined main model if they satisfy one of the following interfaces:
  • TempModel_V1 Pure getter interface for using main models as sub-submodels.

  • TempModel_V2 Simple interface for determining the temperature in one step.

DOCNAME: DocName = ('Evap-RET-FAO56', 'FAO-56 Penman-Monteith reference evapotranspiration')
tempmodel: SubmodelProperty

Required submodel that complies with one of the following interfaces: TempModel_V1 or TempModel_V2.

radiationmodel: modeltools.SubmodelProperty

Required submodel that complies with one of the following interfaces: RadiationModel_V1 or RadiationModel_V3.

REUSABLE_METHODS: ClassVar[tuple[type[ReusableMethod], ...]] = ()
preparemethod2arguments: dict[str, tuple[tuple[Any, ...], dict[str, Any]]]
cymodel: CyModelProtocol | None
parameters: parametertools.Parameters
sequences: sequencetools.Sequences
masks: masktools.Masks
class hydpy.models.evap_ret_fao56.ControlParameters(master: Parameters, cls_fastaccess: type[FastAccessParameter] | None = None, cymodel: CyModelProtocol | None = None)

Bases: SubParameters

Control parameters of model evap_ret_fao56.

The following classes are selected:
class hydpy.models.evap_ret_fao56.DerivedParameters(master: Parameters, cls_fastaccess: type[FastAccessParameter] | None = None, cymodel: CyModelProtocol | None = None)

Bases: SubParameters

Derived parameters of model evap_ret_fao56.

The following classes are selected:
  • HRUAreaFraction() The area fraction of each hydrological response unit [-].

  • Hours() The length of the actual simulation step size in hours [h].

  • Days() The length of the actual simulation step size in days [d].

  • NmbLogEntries() The number of log entries required for a memory duration of 24 hours [-].

class hydpy.models.evap_ret_fao56.FactorSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)

Bases: FactorSequences

Factor sequences of model evap_ret_fao56.

The following classes are selected:
class hydpy.models.evap_ret_fao56.FluxSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)

Bases: FluxSequences

Flux sequences of model evap_ret_fao56.

The following classes are selected:
class hydpy.models.evap_ret_fao56.InputSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)

Bases: InputSequences

Input sequences of model evap_ret_fao56.

The following classes are selected:
class hydpy.models.evap_ret_fao56.LogSequences(master: Sequences, cls_fastaccess: type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)

Bases: LogSequences

Log sequences of model evap_ret_fao56.

The following classes are selected: