HydPy-L-DD (adoption of LARSIM with degree day-based snow modelling)

lland_dd is the simplest of our LARSIM-type models. In contrast to lland_knauf, it calculates snowmelt using the straightforward degree-day method. We created lland_dd on behalf of the German Federal Institute of Hydrology (BfG) for large-scale hydrological applications in central Europe.

The following list summarises the main components of lland_dd:

  • Simple routines for adjusting the meteorological input data

  • Configurable evapotranspiration methods by supporting the AETModel_V1 interface

  • Mixed precipitation within a definable temperature-range

  • An enhanced degree-day method for calculating snowmelt

  • A simple snow retention routine

  • Direct runoff generation based on the Xinanjiang model (Zhao, 1977)

  • Optional inclusion of a soil submodel following the SoilModel_V1 interface

  • One base flow, two interflow and two direct flow components

  • A freely configurable capillary rise routine

  • Options to limit the capacity of the base flow storage

  • Separate linear storages for modelling runoff concentration

  • Additional evaporation from water areas within the subcatchment

  • Optional evaporation from inflowing runoff

The following figure shows the general structure of lland_dd. Besides water areas and sealed surfaces, all land-use types rely on the same process equations:

_images/HydPy-L-DD.png

Integration tests

Note

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

We perform all integration tests over five days, including an extreme precipitation event:

>>> from hydpy import pub
>>> pub.timegrids = "2000-01-01", "2000-01-05", "1h"

Next, we prepare a model instance:

>>> from hydpy.models.lland_dd import *
>>> parameterstep("1h")

lland_dd provides a type of optional routing approach, which adds the runoff from the upstream sub-catchments to the runoff generated by the actual sub-catchment (see example acre (routing)). This approach allows lland_dd to subtract water area evaporation not only from the runoff generated within the actual sub-catchment but from the total runoff flowing through it (see example water (routing)). The documentation on method Calc_QAH_V1 gives further information.

The optionality of this routing approach results in different configuration possibilities of the related Element objects. The element only requires an outlet node if you do not want to use the routing approach (generally or because the relevant catchment is a headwater catchment):

>>> from hydpy import Node, Element
>>> outlet = Node("outlet")
>>> land = Element("land", outlets=outlet)
>>> land.model = model

If you want to use the routing approach, you also need to define one or more inlet nodes, providing the inflowing runoff (we rely on such an element throughout the following examples but make our catchment effectively to a headwater by setting the inflow to zero most of the time):

>>> inlet = Node("inlet")
>>> land = Element("land", inlets=inlet, outlets=outlet)
>>> land.model = model

We focus on a single hydrological response unit with one square kilometre:

>>> nhru(1)
>>> ft(1.0)
>>> fhru(1.0)

acre (summer)

In the first example, arable land is the land-use class of our choice (for all other land-use types, except the ones mentioned below, the results were the same):

>>> lnk(ACKER)

The following set of control parameter values tries to configure application model lland_dd in a manner that allows retracing the influence of most of the different implemented methods on the shown results:

>>> kg(1.2)
>>> kt(0.8)
>>> hinz(0.2)
>>> lai(4.0)
>>> treft(0.0)
>>> trefn(0.0)
>>> tgr(1.0)
>>> tsp(2.0)
>>> gtf(0.5)
>>> pwmax(1.4)
>>> wmax(200.0)
>>> fk(relative=0.5)
>>> pwp(relative=0.05)
>>> kapgrenz(option="0_WMax/10")
>>> kapmax(0.08)
>>> beta(0.005)
>>> fbeta(1.0)
>>> rbeta(False)
>>> dmax(1.0)
>>> dmin(0.1)
>>> bsf(0.4)
>>> volbmax(inf)
>>> gsbmax(1.0)
>>> gsbgrad1(inf)
>>> gsbgrad2(inf)
>>> a1(1.0)
>>> a2(1.0)
>>> tind(1.0)
>>> eqb(100.0)
>>> eqi1(20.0)
>>> eqi2(10.0)
>>> eqd1(5.0)
>>> eqd2(2.0)
>>> negq(False)

We select evap_ret_tw2002 as the submodel for calculating reference evapotranspiration, which implements the Turc-Wendling method (despite the following examples working on an hourly step size while the Turc-Wendling should be applied on at least daily time steps), and wrap this submodel into another submodel of type evap_pet_mlc for converting reference evapotranspiration to potential evapotranspiration. Finally, these two submodels are wrapped by a submodel of type evap_aet_minhas that essentially uses the Minhas equation to reduce potential evapotranspiration to actual evapotranspiration:

>>> with model.add_aetmodel_v1("evap_aet_minhas"):
...     dissefactor(5.0)
...     with model.add_petmodel_v1("evap_pet_mlc"):
...         landmonthfactor(0.5)
...         dampingfactor(1.0)
...         with model.add_retmodel_v1("evap_ret_tw2002"):
...             hrualtitude(100.0)
...             coastfactor(0.6)
...             evapotranspirationfactor(0.4)
...             with model.add_radiationmodel_v2("meteo_glob_io"):
...                 pass

We initialise a test function object that prepares and runs the tests and prints and plots their results:

>>> from hydpy import IntegrationTest
>>> test = IntegrationTest(land)

Initially, relative soil moisture is 10 %, but all other storages are empty (this setting is not very realistic but makes it easier to understand the results of the different integration tests):

>>> test.inits = (
...     (states.inzp, 0.0),
...     (states.wats, 0.0),
...     (states.waes, 0.0),
...     (states.bowa, 20.0),
...     (states.sdg1, 0.0),
...     (states.sdg2, 0.0),
...     (states.sig1, 0.0),
...     (states.sig2, 0.0),
...     (states.sbg, 0.0),
...     (model.aetmodel.petmodel.sequences.logs.loggedpotentialevapotranspiration, 0.0),
... )

The first input data set mimics an extreme summer precipitation event and sets the inflow to zero:

>>> inputs.nied.series = (
...     0.0, 0.0,  0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
...     0.2, 0.0, 0.0, 1.3, 5.6, 2.9, 4.9, 10.6, 0.1, 0.7, 3.0, 2.1, 10.4, 3.5, 3.4,
...     1.2, 0.1, 0.0, 0.0, 0.4, 0.1, 3.6, 5.9, 1.1, 20.7, 37.9, 8.2, 3.6, 7.5, 18.5,
...     15.4, 6.3, 1.9, 4.9, 2.7, 0.5, 0.2, 0.5, 2.4, 0.4, 0.2, 0.0, 0.0, 0.3, 2.6,
...     0.7, 0.3, 0.3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.3,
...     0.0, 0.0, 0.0, 0.7, 0.4, 0.1, 0.4, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
...     0.0, 0.0, 0.0, 0.0)
>>> inputs.teml.series = (
...     21.2, 19.4, 18.9, 18.3, 18.9, 22.5, 25.1, 28.3, 27.8, 31.4, 32.2, 35.2, 37.1,
...     31.2, 24.3, 25.4, 25.9, 23.7, 21.6, 21.2, 20.4, 19.8, 19.6, 19.2, 19.2, 19.2,
...     18.9, 18.7, 18.5, 18.3, 18.5, 18.8, 18.8, 19.0, 19.2, 19.3, 19.0, 18.8, 18.7,
...     17.8, 17.4, 17.3, 16.8, 16.5, 16.3, 16.2, 15.5, 14.6, 14.7, 14.6, 14.1, 14.3,
...     14.9, 15.7, 16.0, 16.7, 17.1, 16.2, 15.9, 16.3, 16.3, 16.4, 16.5, 18.4, 18.3,
...     18.1, 16.7, 15.2, 13.4, 12.4, 11.6, 11.0, 10.5, 11.7, 11.9, 11.2, 11.1, 11.9,
...     12.2, 11.8, 11.4, 11.6, 13.0, 17.1, 18.2, 22.4, 21.4, 21.8, 22.2, 20.1, 17.8,
...     15.2, 14.5, 12.4, 11.7, 11.9)
>>> inlet.sequences.sim.series = 0.0
>>> model.aetmodel.petmodel.retmodel.radiationmodel.sequences.inputs.globalradiation.series = (
...     0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 11.2, 105.5, 248.3, 401.3, 449.7, 493.4, 261.5,
...     363.6, 446.2, 137.6, 103.0, 63.7, 41.4, 7.9, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
...     0.0, 0.0, 0.0, 6.1, 77.9, 196.7, 121.9, 156.6, 404.7, 217.9, 582.0, 263.9,
...     136.8, 146.6, 190.6, 103.5, 13.8, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
...     0.0, 4.4, 26.1, 74.2, 287.1, 299.8, 363.5, 368.4, 317.8, 534.7, 319.4, 350.6,
...     215.4, 97.8, 13.1, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 17.0,
...     99.7, 239.4, 391.2, 525.6, 570.2, 559.1, 668.0, 593.4, 493.0, 391.2, 186.0,
...     82.4, 17.0, 0.0, 0.0, 0.0, 0.0)

The following results show that all relevant model components, except the snow routines, are activated at least once within the simulation period. Take your time to select different time series and see, for example, how the soil moisture content BoWa varies over time. One might realise the “linear storage” type of relationship between input Nied and outflow QAH. This pattern is due to the dominance of the direct runoff generation (QDGZ) based on the Xinanjiang model and modelling runoff concentration via linear storages (inspectable through clicking on QDGZ1 and QDGA1):

>>> test.reset_inits()
>>> conditions = model.conditions
>>> test("lland_dd_acker_summer",
...      axis1=(inputs.nied, fluxes.qah), axis2=states.bowa)
Click to see the table
Click to see the graph

There is no indication of an error in the water balance:

>>> from hydpy import round_
>>> round_(model.check_waterbalance(conditions))
0.0

acre (GARTO)

By default, lland_dd estimates direct runoff generation after the Xinanjiang approach, which predicts infiltration based on the current soil water content and the amount of precipitation over the considered simulation interval. Such simple volume-based methods are robust but tend to underestimate infiltration rates during short, high-intensity rainfall events. To improve simulations under such conditions, one can couple submodels following the SoilModel_V1 interface to lland_dd. Here, we demonstrate using ga_garto_submodel1 as a soil submodel, which predicts surface runoff based on the infiltration-excess mechanism as simulated by a modified Green-Ampt method. We define most of its parameter values as in the initial examples of the documentation on ga_garto_submodel1 and its stand-alone counterpart ga_garto (soil type loam), but set the soil depth so that the maximum soil water content (200.0 mm) and the initial relative soil moisture (20 mm) agree with the previous acre (summer) example:

>>> from hydpy import pub
>>> with model.add_soilmodel_v1("ga_garto_submodel1"):
...     nmbsoils(1)
...     nmbbins(4)
...     with pub.options.parameterstep("1m"):
...         dt(1.0)
...     sealed(False)
...     soildepth(200.0 / 0.434)
...     residualmoisture(0.027)
...     saturationmoisture(0.434)
...     saturatedconductivity(13.2)
...     poresizedistribution(0.252)
...     airentrypotential(111.5)
...     states.moisture = 20.0 / 200.0 * 0.434
...     states.frontdepth = 0.0
...     states.moisturechange = 0.0

The documentation on the method Calc_BoWa_SoilModel_V1 explains the interaction between lland_dd and ga_garto_submodel1 in much detail. When comparing the following results with the acre (summer) example, one sees a huge difference in the runoff response caused by the two rainfall events on late January 2. Without a submodel, lland_dd calculates similar direct runoff peaks for the first (9.5 mm/h) and the second event (7.2 mm/h), despite the first event showing a much higher rainfall rate (37.9 mm/h) than the second one (18.5 mm/h), because the second event falls on a soil already wetted by the first event. However, after connecting ga_garto_submodel1 to lland_dd, the estimated infiltration rates are considerably larger for the first event (21.4 mm/h) due to its high rainfall intensity and a little smaller for the second event (6.4 mm/h) due to the more moderate soil water increase resulting from lower infiltration rates during the first event:

>>> test("lland_dd_acker_garto",
...      axis1=(inputs.nied, fluxes.qah), axis2=states.bowa)
Click to see the table
Click to see the graph

There is no indication of an error in the water balance:

>>> round_(model.check_waterbalance(conditions))
0.0

acre (routing)

We remove the soil submodel before performing the following examples:

>>> del model.soilmodel

For all non-water areas, lland_dd effectively just adds the inflow to the catchment-specific outflow:

There is no indication of an error in the water balance:

>>> round_(model.check_waterbalance(conditions))
0.0

water

HydPy-L defines three types of water areas. The first one, WASSER, is also implemented in the original LARSIM model. To represent the effects of water areas in a straightforward manner, lland_dd adds precipitation (NKor) to and tries to remove maximum evaporation (returned by the evaporation submodel and, at first, handled by the water-related entries of sequence EvI) from the total discharge (QAH.

In the following example (again with zero inflow), this simple approach has the unfavourable side effect of discharge dropping to zero in periods with no precipitation but relevant maximum evaporation during the daytime. Similar problems arise when WASSER is only one of many selected land-use types, possibly even when the water area is below 1 % of the total catchment area. Hence, using the land-use types FLUSS and SEE seems advisable under most circumstances. Note that sequence EvI contains the actual evaporation values of WASSER (and other water-type) response units at the end of each simulation step:

>>> lnk(WASSER)
>>> inlet.sequences.sim.series = 0.0
>>> test("lland_dd_wasser",
...      axis1=(fluxes.nkor, fluxes.evi, fluxes.qah))
Click to see the table
Click to see the graph

There is no indication of an error in the water balance:

>>> round_(model.check_waterbalance(conditions))
0.0

water (damped evaporation)

As discussed in the last example, handling evaporation from water surfaces can be problematic. Therefore, some potential evapotranspiration submodels offer a damping option. In principle, you can apply this mechanism to all land-use classes. However, its original intention is to consider the temporal persistence of (large) water bodies. We demonstrate this functionality by setting the parameter DampingFactor of the selected evap_pet_mlc submodel to a value smaller than one and defining a suitable “old” evaporation value for the start of the simulation:

>>> lnk(WASSER)
>>> model.aetmodel.petmodel.parameters.control.dampingfactor(0.01)
>>> test.inits.loggedpotentialevapotranspiration = 0.5
>>> inlet.sequences.sim.series = 0.0
>>> test("lland_dd_wasser_delayed",
...      axis1=(fluxes.nkor, fluxes.evi, fluxes.qah))
Click to see the table
Click to see the graph

There is no indication of an error in the water balance:

>>> round_(model.check_waterbalance(conditions))
0.0

water (routing)

With available inflow, more water is available for evaporation, and the differences between potential and actual evaporation are less pronounced (hence, the routing approach offers the opportunity to capture the evaporation effects of small lakes one does not want to represent by a separate specialised lake model like dam_llake):

>>> model.aetmodel.petmodel.parameters.control.dampingfactor(1.0)
>>> inlet.sequences.sim.series = 0.3
>>> test("lland_dd_wasser_routing",
...      axis1=(fluxes.nkor, fluxes.evi, fluxes.qah))
Click to see the table
Click to see the graph

There is no indication of an error in the water balance:

>>> round_(model.check_waterbalance(conditions))
0.0

water (negative runoff)

In the integration test water, discharge is zero in all periods, with evaporation exceeding precipitation but never negative. This non-negativity is due to trimming flux sequence EvI, which we can disable by setting parameter NegQ to True (negative values might be problematic for the models downstream, so set NegQ to True only for good reasons):

>>> negq(True)
>>> inlet.sequences.sim.series = 0.0
>>> test("lland_dd_wasser_negq",
...      axis1=(fluxes.nkor, fluxes.evi, fluxes.qah))
Click to see the table
Click to see the graph

There is no indication of an error in the water balance:

>>> round_(model.check_waterbalance(conditions))
0.0

lakes

As an alternative for water type WASSER, HydPy-L offers water type SEE for representing lakes not directly connected to the stream network but to the groundwater. In some agreement with the implementation of “internal lakes” in the HBV96 model (see hland), precipitation and evaporation values are directly added and removed from the input of the linear storage for base flow (QBGZ). Hence, defining SEE areas results in reduced responsiveness of a catchment.

Note that we again disable the NegQ option. However, in contrast to integration test water, the actual evaporation (EvI) is never trimmed during and after the precipitation event. The only slight trimming occurs at the beginning of the simulation period due to starting the test with zero groundwater storage (method Calc_QAH_V1 gives more information on the adjustment of QAH and EvI):

>>> lnk(SEE)
>>> negq(False)
>>> test("lland_dd_see",
...      axis1=(fluxes.nkor, fluxes.evi, fluxes.qah))
Click to see the table
Click to see the graph

There is no indication of an error in the water balance:

>>> round_(model.check_waterbalance(conditions))
0.0

streams

The second alternative for water type WASSER is water type FLUSS for representing streams. Precipitation and evaporation values of FLUSS areas are directly added and removed from the (not yet separated) input of the linear storages for direct flow (QDGZ). In contrast to water type SEE (see integration test lakes), using water type FLUSS increases the responsiveness of a catchment, but to a lesser extent than using water type WASSER (see test water).

Using FLUSS instead of WASSER reduces the discussed problem during low flow conditions. However, it may persist for catchments with a very dense stream network. See how method Calc_QAH_V1 adjusts the actual evaporation in the most extreme case of a “stream network only” catchment, resulting even in some condensation periods with negative EvI values:

>>> lnk(FLUSS)
>>> test("lland_dd_fluss",
...      axis1=(fluxes.nkor, fluxes.evi, fluxes.qah))
Click to see the table
Click to see the graph

There is no indication of an error in the water balance:

>>> round_(model.check_waterbalance(conditions))
0.0

sealed surfaces

We assume retention processes below the surface to be negligible for sealed surfaces. Therefore, all water reaching the sealed surface becomes direct discharge immediately:

>>> lnk(VERS)
>>> test("lland_dd_vers",
...      axis1=(inputs.nied, fluxes.qah, states.bowa))
Click to see the table
Click to see the graph

There is no indication of an error in the water balance:

>>> round_(model.check_waterbalance(conditions))
0.0

acre (limited groundwater volume)

Usually, HydPy-L represents groundwater processes by a simple linear runoff concentration storage, capturing the aspect of the relative slowness of groundwater but leaving other relevant characteristics aside. The control parameter VolBMax offers the chance to explicitly account for another groundwater characteristic: the aquifer’s limited size.

In this example, we set the maximum capacity of the groundwater storage to 25 mm, corresponding to a maximum outflow of 0.25 mm/h. As soon as groundwater discharge (QBGA) reaches this threshold, it converts all recharge excess (QBGZ) into direct runoff (QDGZ, see the documentation on method Calc_QBGA_SBG_QBGZ_QDGZ_V1 for further information). This additional generation of direct runoff leads to a small increase in total runoff (QAH) at the end of the simulation period:

>>> lnk(ACKER)
>>> volbmax(25.0)
>>> test("lland_dd_acker_gw_vol",
...      axis1=(fluxes.qbgz, fluxes.qdgz, fluxes.qbga, fluxes.qah),
...      axis2=states.sbg)
Click to see the table
Click to see the graph

There is no indication of an error in the water balance:

>>> round_(model.check_waterbalance(conditions))
0.0

acre (limited groundwater rise)

Similar to restricting an aquifer’s capacity (acre (limited groundwater volume)), HydPy-L allows limiting the speed of the rise of the water table (see the documentation on method Calc_QBGA_SBG_QBGZ_QDGZ_V1 for further information). After setting the related threshold parameters to 0.4 mm/h (GSBGrad1) and 0.6 mm/h (GSBGrad2), we see an increase in runoff due to the redirection of groundwater recharge to direct runoff at the end of the event:

>>> volbmax(inf)
>>> gsbgrad1(0.4)
>>> gsbgrad2(0.6)
>>> test("lland_dd_acker_gw_rise",
...      axis1=(fluxes.qbgz, fluxes.qdgz, fluxes.qbga, fluxes.qah),
...      axis2=states.sbg)
Click to see the table
Click to see the graph

There is no indication of an error in the water balance:

>>> round_(model.check_waterbalance(conditions))
0.0

acre (capillary rise, water balance error)

Now we focus on the capillary rise (QKap), being configurable via the parameters KapMax and KapGrenz. Please first read the documentation on parameter KapGrenz to understand its keyword argument option.

In integration test acre (summer), capillary rise occurs only for a short period where the soil water content (BoWa) is less than 10 % of its capacity (WMax) due to the selected option 0_WMax/10. Additionally, there is no deep percolation (QBB) during this short period due to parameter RBeta being set to False. (A note for LARSIM users: this combination of parameter settings corresponds to the option KOPPELUNG BODEN/GRUNDWASSER.)

Now we assign FK to parameter KapGrenz and True to parameter RBeta. Consequently, capillary rise and deep percolation exclude each other, and there is an abrupt transition from capillary rise to deep percolation when the soil moisture exceeds FK (which agrees with the LARSIM option KAPILLARER AUFSTIEG):

>>> gsbgrad2(inf)
>>> gsbgrad1(inf)
>>> kapgrenz(option="FK")
>>> rbeta(True)
>>> test("lland_dd_acker_qkap_negq-false",
...      axis1=(fluxes.qbb, fluxes.qkap), axis2=states.bowa)
Click to see the table
Click to see the graph

There is an error in the water balance for this particularly dry situation:

>>> round_(model.check_waterbalance(conditions))
-0.066414

Generally, the calculated capillary rise depends solemnly on the soil moisture deficit. In our example, the base flow storage is empty but must supply the water required for the capillary rise. Hence, its content and, subsequently, its outflow QBGA becomes negative. To prevent negative discharges at the catchment’s outlet (due to the disabled option NegQ, see the documentation on method Calc_QAH_V1 for further information), lland_dd simply sets it to zero without trying to compensate for the resulting water balance error.

acre (capillary rise, negative discharge)

If we repeat the acre (capillary rise, water balance error) experiment but set NegQ to False, the water balance error vanishes at the price of temporarily negative discharge at the catchment’s outlet:

>>> negq(True)
>>> test("lland_dd_acker_qkap_negq-true",
...      axis1=(fluxes.qbb, fluxes.qkap), axis2=states.bowa)
Click to see the table
Click to see the graph

There is no indication of an error in the water balance:

>>> round_(model.check_waterbalance(conditions))
0.0

acre (winter)

In the next example, we modify the input temperature series TemL to demonstrate the functioning of the snow routine. For simplicity, TemL increases linearly from -20 to +20 °C. The ice content of the snow layer (WATS) starts to melt when the temperature crosses the threshold temperature TGr. However, snow layer’s actual water release (WaDa) starts one day later when the liquid water content of the snow layer finally exceeds its holding capacity:

>>> inputs.teml.series = numpy.linspace(-20.0, 20.0, 96)
>>> test("lland_dd_acker_winter",
...      axis1=(inputs.nied, fluxes.wada), axis2=(states.waes, states.wats))
Click to see the table
Click to see the graph

There is no indication of an error in the water balance:

>>> round_(model.check_waterbalance(conditions))
0.0
class hydpy.models.lland_dd.Model[source]

Bases: Main_AETModel_V1A, Main_SoilModel_V1, Sub_TempModel_V1, Sub_PrecipModel_V1, Sub_IntercModel_V1, Sub_SoilWaterModel_V1, Sub_SnowCoverModel_V1

HydPy-L-DD (adoption of LARSIM with degree day-based snow modelling).

The following “inlet update methods” are called in the given sequence at the beginning of each simulation step:
  • Pick_QZ_V1 Query the current inflow from all inlet nodes.

The following “run methods” are called in the given sequence during each simulation step:
  • Calc_QZH_V1 Calculate the inflow in mm.

  • Calc_NKor_V1 Adjust the given precipitation value according to LEG (2020).

  • Calc_TKor_V1 Adjust the given air temperature value.

  • Calc_NBes_Inzp_V1 Calculate stand precipitation and update the interception storage accordingly.

  • Calc_SNRatio_V1 Calculate the ratio of frozen to total precipitation according to LEG (2020).

  • Calc_SBes_V1 Calculate the frozen part of stand precipitation.

  • Calc_WATS_V1 Add the snow fall to the frozen water equivalent of the snow cover.

  • Calc_WGTF_V1 Calculate the heat flux according to the degree-day method according to LEG (2020).

  • Calc_WNied_V1 Calculate the heat flux into the snow layer due to the total amount of ingoing precipitation (LEG (2020), modified).

  • Calc_SchmPot_V1 Calculate the potential snow melt according to the day degree method.

  • Calc_Schm_WATS_V1 Calculate the actual amount of water melting within the snow layer.

  • Calc_WaDa_WAeS_V1 Add as much liquid precipitation to the snow cover as it is able to hold.

  • Calc_EvI_Inzp_V1 Let a submodel that follows the AETModel_V1 submodel interface calculate interception evaporation and adjust the amount of intercepted water.

  • Calc_EvB_V1 Let a submodel that follows the AETModel_V1 submodel interface calculate soil evapotranspiration.

  • Calc_QKap_V1 Calculate the capillary rise.

  • Calc_QBB_V1 Calculate the amount of base flow released from the soil.

  • Calc_QIB1_V1 Calculate the first inflow component released from the soil.

  • Calc_QIB2_V1 Calculate the second inflow component released from the soil.

  • Calc_QDB_V1 Calculate direct runoff released from the soil.

  • Calc_BoWa_V1 Update the soil moisture.

  • Calc_QBGZ_V1 Aggregate the amount of base flow released by all “soil type” HRUs and the “net precipitation” above water areas of type SEE.

  • Calc_QIGZ1_V1 Aggregate the amount of the first interflow component released by all HRUs.

  • Calc_QIGZ2_V1 Aggregate the amount of the second interflow component released by all HRUs.

  • Calc_QDGZ_V1 Aggregate the amount of total direct flow released by all HRUs.

  • Calc_QBGA_SBG_QBGZ_QDGZ_V1 Update the base flow storage and calculate its outflow, taking possible “groundwater restrictions” into account.

  • Calc_QIGA1_SIG1_V1 Update the storage of the first interflow component and calculate its outflow.

  • Calc_QIGA2_SIG2_V1 Update the storage of the second interflow component and calculate its outflow.

  • Calc_QDGZ1_QDGZ2_V1 Separate total direct flow into a slower and a faster component.

  • Calc_QDGA1_SDG1_V1 Update the storage of the slow direct runoff component and calculate its outflow.

  • Calc_QDGA2_SDG2_V1 Update the storage of the fast direct runoff component and calculate its outflow.

  • Calc_QAH_V1 Calculate the final runoff in mm.

  • Calc_QA_V1 Calculate the final runoff in m³/s.

The following “outlet update methods” are called in the given sequence at the end of 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:
  • Calc_EvI_Inzp_AETModel_V1 Let a submodel that follows the AETModel_V1 submodel interface calculate interception evaporation and adjust the amount of intercepted water.

  • Calc_EvB_AETModel_V1 Let a submodel that follows the AETModel_V1 submodel interface calculate soil evapotranspiration.

  • Return_SG_V1 Return the new storage value after applying the analytical solution for the linear storage differential equation under the assumption of constant inflow.

  • Calc_BoWa_Default_V1 Update the soil moisture and (if necessary) correct the fluxes to be added or subtracted.

  • Calc_BoWa_SoilModel_V1 Apply a submodel following the SoilModel_V1 interface to include additional direct runoff and groundwater recharge components into the soil moisture update.

Users can hook submodels into the defined main model if they satisfy one of the following interfaces:
  • AETModel_V1 Interface for calculating interception evaporation, evapotranspiration from soils, evaporation from water areas in separate steps.

  • SoilModel_V1 Soil submodel interface for calculating infiltration and percolation in multiple soil compartments.

DOCNAME: DocName = ('L-DD', 'adoption of LARSIM with degree day-based snow modelling')
aetmodel: modeltools.SubmodelProperty

Required submodel that complies with the following interface: AETModel_V1.

soilmodel: modeltools.SubmodelProperty

Optional submodel that complies with the following interface: SoilModel_V1.

check_waterbalance(initial_conditions: dict[str, dict[str, dict[str, float | ndarray[Any, dtype[float64]]]]]) float[source]

Determine the water balance error of the previous simulation run in mm.

Method check_waterbalance() calculates the balance error as follows:

\[\sum_{t=t0}^{t1} \Bigg( NKor_t + QZH_t - \bigg( \sum_{k=1}^{nhru} fhru^k \cdot \Big( EvI_t^k + EvB_t^k \Big) \bigg) - QAH_t \Bigg) + \sum_{k=1}^{nhru} fhru^k \cdot \bigg( \Big( Inzp_{t0}^k - Inzp_{t1}^k \Big) + \Big( WAeS_{t0}^{k} - WAeS_{t1}^{k} \Big) + \Big( BoWa_{t0}^{k} - BoWa_{t1}^{k} \Big) \bigg) - \bigg( \Big( SDG2_{t0} - SDG2_{t1} \Big) + \Big( SDG1_{t0} - SDG1_{t1} \Big) + \Big( SIG2_{t0} - SIG2_{t1} \Big) + \Big( SIG1_{t0} - SIG1_{t1} \Big) + \Big( SBG_{t0} - SBG_{t1} \Big) \bigg)\]

The returned error should usually be in scale with numerical precision so that it does not affect the simulation results in any relevant manner. The only exception we are aware of is the “generation” of additional water when the base flow storage cannot meet the water demand required for the calculated capillary rise (see acre (capillary rise, water balance error)).

Pick the required initial conditions before starting the simulation run via property conditions. See the integration tests of the application model lland_dd for some examples.

REUSABLE_METHODS: ClassVar[tuple[type[ReusableMethod], ...]] = ()
cymodel: CyModelProtocol | None
parameters: parametertools.Parameters
sequences: sequencetools.Sequences
masks: masktools.Masks
class hydpy.models.lland_dd.Masks[source]

Bases: Masks

Masks applicable to lland_dd.

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

Bases: AideSequences

Aide sequences of model lland_dd.

The following classes are selected:
  • SNRatio() Ratio of frozen precipitation to total precipitation [-].

class hydpy.models.lland_dd.ControlParameters(master: Parameters, cls_fastaccess: type[FastAccessParameter] | None = None, cymodel: CyModelProtocol | None = None)

Bases: SubParameters

Control parameters of model lland_dd.

The following classes are selected:
  • FT() Teileinzugsgebietsfläche (subbasin area) [km²].

  • NHRU() Anzahl der Hydrotope (number of hydrological response units) [-].

  • Lnk() Landnutzungsklasse (land use class) [-].

  • FHRU() Flächenanteile der Hydrotope (area percentages of the respective HRUs) [-].

  • KG() Niederschlagskorrekturfaktor (adjustment factor for precipitation) [-].

  • KT() Temperaturkorrektursummand (adjustment summand for air temperature) [°C].

  • LAI() Blattflächenindex (leaf area index) [-].

  • HInz() Interzeptionskapazität bezogen auf die Blattoberfläche (interception capacity normalized to the leaf surface area) [mm].

  • TRefT() Lufttemperaturgrenzwert des Grad-Tag-Verfahrens (air temperature threshold of the degree-day method) [°C].

  • TRefN() Niederschlagstemperaturgrenzwert des zur Berechnung des Wärmeeintrags durch Regen (precipitation temperature threshold to calculate heat flux caused by liquid precipitation on snow) [°C].

  • TGr() Temperaturgrenzwert flüssiger/fester Niederschlag (threshold temperature liquid/frozen precipitation) [°C].

  • TSp() Temperaturspanne flüssiger/fester Niederschlag (temperature range with mixed precipitation) [°C].

  • GTF() Grad-Tag-Faktor (factor of the degree-day method) [mm/°C/T].

  • PWMax() Maximalverhältnis Gesamt- zu Trockenschnee (maximum ratio of the total and the frozen water equivalent stored in the snow cover) [-].

  • WMax() Maximaler Bodenwasserspeicher (maximum soil water storage) [mm].

  • FK() Feldkapazität / Mindestbodenfeuchte für die Interflowentstehung (field capacity / threshold value of soil moisture for interflow generation) [mm].

  • PWP() Permanenter Welkepunkt / Mindestbodenfeuchte für die Basisabflussentstehung (permanent wilting point threshold value of soil moisture for base flow generation) [mm].

  • BSf() Bodenfeuchte-Sättigungsfläche-Parameter (shape parameter for the relation between the avarage soil moisture and the relative saturated area of a subbasin) [-].

  • DMin() Drainageindex des mittleren Bodenspeichers (flux rate for releasing interflow from the middle soil compartment) [mm/T].

  • DMax() Drainageindex des oberen Bodenspeichers (additional flux rate for releasing interflow from the upper soil compartment) [mm/T].

  • Beta() Drainageindex des tiefen Bodenspeichers (storage coefficient for releasing base flow from the lower soil compartment) [1/T].

  • FBeta() Faktor zur Erhöhung der Perkolation im Grobporenbereich (factor for increasing percolation under wet conditions) [-].

  • KapMax() Maximale kapillare Aufstiegsrate (maximum capillary rise) [mm/T].

  • KapGrenz() Grenzwerte für den kapillaren Aufstieg (threshold values related to the capillary rise) [mm].

  • RBeta() Boolscher Parameter der steuert, ob the Perkolation unterhalb der Feldkapazität auf Null reduziert wird (flag to indicate if seepage is reduced to zero below field capacity) [-].

  • VolBMax() Maximaler Inhalt des Gebietsspeichers für Basisabfluss (highest possible base flow storage) [mm].

  • GSBMax() Faktor zur Anpassung von VolBMax (factor for adjusting VolBMax) [-].

  • GSBGrad1() Höchste Volumenzunahme des Gebietsspeichers für Basisabfluss ohne Begrenzung des Zuflusses (highest possible baseflow storage increase without inflow reductions) [mm/T].

  • GSBGrad2() Volumenzunahme des Gebietsspeichers für Basisabfluss, oberhalb der jeglicher Zufluss ausgeschlossen ist (highest possible baseflow storage increase) [mm/T].

  • A1() Parameter für die kontinuierliche Aufteilung der Direktabflusskomponenten (threshold value for the continuous seperation of direct runoff in a slow and a fast component) [mm/T]

  • A2() Parameter für die diskontinuierliche Aufteilung der Direktabflusskomponenten (threshold value for the discontinuous seperation of direct runoff in a slow and a fast component) [mm/T]

  • TInd() Fließzeitindex (factor related to the time of concentration) [T].

  • EQB() Kalibrierfaktor für die Basisabflusskonzentration (factor for adjusting the concentration time of baseflow). [-].

  • EQI1() Kalibrierfaktor für die “untere” Zwischenabflusskonzentration (factor for adjusting the concentration time of the first interflow component) [-].

  • EQI2() Kalibrierfaktor für die “obere” Zwischenabflusskonzentration (factor for adjusting the concentration time of the second interflow component) [-].

  • EQD1() Kalibrierfaktor für die langsamere Direktabflusskonzentration (factor for adjusting the concentration time of the slower component of direct runoff). [-].

  • EQD2() Kalibrierfaktor für die schnellere Direktabflusskonzentration (factor for adjusting the concentration time of the faster component of direct runoff). [-].

  • NegQ() Option: sind negative Abflüsse erlaubt (flag that indicated whether negative discharge values are allowed or not) [-].

class hydpy.models.lland_dd.DerivedParameters(master: Parameters, cls_fastaccess: type[FastAccessParameter] | None = None, cymodel: CyModelProtocol | None = None)

Bases: SubParameters

Derived parameters of model lland_dd.

The following classes are selected:
  • MOY() References the “global” month of the year index array [-].

  • AbsFHRU() Flächen der Hydrotope (areas of the respective HRUs) [km²].

  • KInz() Interzeptionskapazität bezogen auf die Bodenoberfläche (interception capacity normalized to the soil surface area) [mm].

  • KB() Konzentrationszeit des Basisabflusses (concentration time of the baseflow storage) [T].

  • KI1() Konzentrationszeit des “unteren” Zwischenabflusses (concentration time of the first interflow storage) [T].

  • KI2() Konzentrationszeit des “oberen” Zwischenabflusses” (concentration time of the second interflow storage) [T].

  • KD1() Konzentrationszeit des “langsamen” Direktabflusses (concentration time of the slow direct runoff storage) [T].

  • KD2() Konzentrationszeit des “schnellen” Direktabflusses (concentration time of the fast direct runoff storage) [T].

  • QFactor() Factor for converting mm/T to m³/s.

class hydpy.models.lland_dd.FixedParameters(master: Parameters, cls_fastaccess: type[FastAccessParameter] | None = None, cymodel: CyModelProtocol | None = None)

Bases: SubParameters

Fixed parameters of model lland_dd.

The following classes are selected:
  • CPWasser() Spezifische Wärmekapazität von Wasser (specific heat capacity of water) [WT/kg/K].

  • CPEis() Spezifische Wärmekapazität von Eis bei 0 °C (specific heat capacity of ice at a temperature of 0 °C) [WT/kg/K].

  • RSchmelz() Spezifische Schmelzwärme von Wasser (specific melt heat of water) [WT/kg].

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

Bases: FluxSequences

Flux sequences of model lland_dd.

The following classes are selected:
  • QZ() Zufluss in das Teilgebiet (inflow into the subcatchment) [m³/s].

  • QZH() Abflussspende in das Teilgebiet (inflow into the subcatchment) [mm/T].

  • NKor() Korrigierter Niederschlag (corrected precipitation) [mm/T].

  • TKor() Korrigierte Lufttemperatur (corrected air temperature) [°C].

  • NBes() Gesamter Bestandsniederschlag (total stand precipitation) [mm/T].

  • SBes() Schneeanteil Bestandsniederschlag (frozen stand precipitation) [mm/T].

  • EvI() Tatsächliche Verdunstung von Interzeptions- und permanenten Wasserflächen (actual evaporation from interception storages and water areas) [mm/T].

  • EvB() Tatsächliche Verdunstung von Bodenwasser (actual evaporation of soil water) [mm/T].

  • WGTF() Mit dem Grad-Tag-Verfahren berechneter Wärmeestrom in die Schneedecke (heat flux into the snow layer calculated with the degree-day method) [W/m²].

  • WNied() Niederschlagsbedingter Wärmestrom in die Schneedecke (heat flux into the snow layer due to precipitation) [W/m²].

  • SchmPot() Potentielle Schneeschmelze (potential amount of water melting within the snow cover) [mm/T].

  • Schm() Tatsächliche Schneeschmelze (actual amount of water melting within the snow cover) [mm/T].

  • WaDa() Wasserdargebot (water reaching the soil routine) [mm/T].

  • QDB() Direktabfluss-Abgabe aus dem Bodenspeicher (direct runoff release from the soil storage) [mm/T].

  • QIB1() Erste Komponente der Interflow-Abgabe aus dem Bodenspeicher (first component of the interflow release from the soil storage) [mm/T].

  • QIB2() Zweite Komponente der Interflow-Abgabe aus dem Bodenspeicher (second component of the interflow release from the soil storage) [mm/T].

  • QBB() Basisabfluss-Abgabe aus dem Bodenspeicher (base flow release from the soil storage) [mm/T].

  • QKap() Kapillarer Aufstieg in den Bodenspeicher (capillary rise to soil storage) [mm/T].

  • QDGZ() Gesamtzufluss in beide Direktabfluss-Gebietsspeicher (total inflow to both direct runoff storages) [mm/T].

  • QDGZ1() Zufluss in den trägeren Direktabfluss-Gebietsspeicher (inflow to the slow direct runoff storage) [mm/T].

  • QDGZ2() Zufluss in den dynamischeren Direktabfluss-Gebietsspeicher (inflow to the fast direct runoff storage) [mm/T].

  • QIGZ1() “Zufluss in den ersten Zwischenabfluss-Gebietsspeicher (inflow to the first interflow storage) [mm/T].

  • QIGZ2() Zufluss in den zweiten Zwischenabfluss-Gebietsspeicher (inflow to the second interflow storage) [mm/T].

  • QBGZ() Zufluss in den Basisabfluss-Gebietsspeicher (inflow to the base flow storage) [mm/T].

  • QDGA1() Abfluss aus dem trägeren Direktabfluss-Gebietsspeicher (outflow from the slow direct runoff storage) [mm/T].

  • QDGA2() Abfluss aus dem dynamischeren Direktabfluss-Gebietsspeicher (outflow from the fast direct runoff storage) [mm/T].

  • QIGA1() Abfluss aus dem “unteren” Zwischenabfluss-Gebietsspeicher (outflow from the first interflow storage) [mm/T].

  • QIGA2() Abfluss aus dem “oberen” Zwischenabfluss-Gebietsspeicher (outflow from the second interflow storage) [mm/T].

  • QBGA() Abfluss aus dem Basisabfluss-Gebietsspeicher (outflow from the base flow storage) [mm/T].

  • QAH() Abflussspende des Teilgebiets (runoff at the catchment outlet) [mm/T].

  • QA() Abfluss des Teilgebiets (runoff at the catchment outlet) [m³/s].

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

Bases: InletSequences

Inlet sequences of model lland_dd.

The following classes are selected:
  • Q() Abfluss (runoff) [m³/s].

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

Bases: InputSequences

Input sequences of model lland_dd.

The following classes are selected:
  • Nied() Niederschlag (precipitation) [mm/T].

  • TemL() Lufttemperatur (air temperature) [°C].

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

Bases: OutletSequences

Outlet sequences of model lland_dd.

The following classes are selected:
  • Q() Abfluss (runoff) [m³/s].

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

Bases: StateSequences

State sequences of model lland_dd.

The following classes are selected:
  • Inzp() Interzeptionsspeicherung (interception storage) [mm].

  • WATS() Wasseräquivalent Trockenschnee auf der Bodenoberfläche (frozen water equivalent of the snow cover) [mm].

  • WAeS() Wasseräquivalent Gesamtschnee auf der Bodenoberfläche (total water equivalent of the snow cover) [mm].

  • BoWa() Bodenwasserspeicherung (soil water storage) [mm].

  • SDG1() Träger Direktabfluss-Gebietsspeicher (slow direct runoff storage) [mm].

  • SDG2() Dynamischer Direktabfluss-Gebietsspeicher (fast direct runoff storage) [mm].

  • SIG1() Erster Zwischenabfluss-Gebietsspeicher (first interflow storage) [mm].

  • SIG2() Zweiter Zwischenabfluss-Gebietsspeicher (second interflow storage) [mm].

  • SBG() Basisabfluss-Gebietsspeicher (base flow storage) [mm].