dam_v008¶
Reservoir version of HydPy-Dam.
dam_v008
is a relatively simple reservoir model, similar to the “TALS” model of
LARSIM. It combines the features of dam_v006
(“controlled lake”) and dam_v007
(“retention basin”). Additionally, it allows controlling the stored water volume via
defining target values that can vary seasonally.
Like dam_v007
, dam_v008
allows for combining controlled, “harmless outflow” (via
parameter AllowedRelease
) and uncontrolled, “spillway outflow” (via parameter
WaterLevel2FloodDischarge
), and like dam_v006
, it allows to restrict the speed of
the water level decrease during periods with little inflow via parameter
AllowedWaterLevelDrop
(only through reducing the controlled outflow, of course).
Before continuing, please first read the documentation on these two application models.
The additional feature of dam_v008
is its ability to track target volumes that can
vary seasonally. We define these target volumes via parameter TargetVolume
. The
parameters VolumeTolerance
, TargetRangeAbsolute
, and TargetRangeRelative
serve to
yield more smooth and realistic reservoir responses for slight deviations from the
given target values. Setting TargetRangeRelative
to 0.2 and both other parameters to
zero corresponds to selecting the “TALSPERRE SOLLRANGE” option in LARSIM. Please
see the following examples and the documentation on method Calc_ActualRelease_V3
for
more information on setting and combining the individual parameter values for different
use cases.
Integration tests¶
Note
When new to HydPy, consider reading section How to understand integration tests? first.
We prepare a test set similar to the ones for application models dam_v006
and
dam_v007
, including an identical inflow series and an identical relationship between
stage and volume:
>>> from hydpy import IntegrationTest, Element, pub
>>> pub.timegrids = "01.01.2000", "21.01.2000", "1d"
>>> from hydpy.models.dam_v008 import *
>>> parameterstep("1d")
>>> element = Element("element", inlets="input_", outlets="output")
>>> element.model = model
>>> test = IntegrationTest(element)
>>> test.dateformat = "%d.%m."
>>> test.plotting_options.axis1 = fluxes.inflow, fluxes.outflow
>>> test.plotting_options.axis2 = states.watervolume
>>> test.inits = [
... (states.watervolume, 0.0),
... (logs.loggedadjustedevaporation, 0.0)]
>>> test.reset_inits()
>>> conditions = sequences.conditions
>>> watervolume2waterlevel(PPoly.from_data(xs=[0.0, 1.0], ys=[0.0, 1.0]))
>>> surfacearea(1.44)
>>> catchmentarea(86.4)
>>> correctionprecipitation(1.2)
>>> correctionevaporation(1.2)
>>> weightevaporation(0.8)
>>> thresholdevaporation(0.0)
>>> toleranceevaporation(0.001)
>>> inputs.precipitation.series = [
... 0.0, 50.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, 0.0, 0.0, 0.0]
>>> element.inlets.input_.sequences.sim.series = [
... 0.0, 0.0, 6.0, 12.0, 10.0, 6.0, 3.0, 2.0, 1.0, 0.0,
... 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
>>> inputs.evaporation.series = 0.0
base scenario¶
First, we again use the linear relation between discharge and stage used
throughout the integration tests of dam_v006
and in the base example of dam_v007
:
>>> waterlevel2flooddischarge(PPoly.from_data(xs=[0.0, 1.0], ys=[0.0, 10.0]))
Additionally, we set some of the remaining parameter values extremely high or low to ensure the reservoir stores all water except the one activating the spillway, which becomes “flood discharge”:
>>> targetvolume(100.0)
>>> neardischargeminimumthreshold.shape = 1
>>> neardischargeminimumthreshold.values = -100.0
>>> targetrangeabsolute(0.1)
>>> targetrangerelative(0.2)
>>> watervolumeminimumthreshold(0.0)
>>> volumetolerance(0.1)
>>> dischargetolerance(0.1)
>>> allowedrelease(100.0)
>>> allowedwaterleveldrop(100.0)
Due to the same the neural network configuration, the results are identical with the
ones of the base example of dam_v006
and the
base example of dam_v007
:
>>> test("dam_v008_base_scenario")
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
spillway¶
When we reuse the more realistic relationship between flood discharge and stage of the
spillway example on dam_v007
, we again get the same flood
discharge time series:
>>> waterlevel2flooddischarge(ANN(weights_input=10.0, weights_output=50.0,
... intercepts_hidden=-20.0, intercepts_output=0.0))
>>> test("dam_v008_spillway")
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
target volume¶
During dry periods, application model dam_v007
generally releases all its water until
the basin runs dry, as long as AllowedRelease
is larger than zero. Application model
dam_v008
instead allows defining target volumes. dam_v008
tries to control its
outflow so that the actual volume approximately equals the (potentially seasonally
varying) target volume. However, it cannot release arbitrary amounts of water to
fulfil this task due to its priority to release a predefined minimum amount of water
(for ecological reasons) and its second priority to not release too much water (for
flood protection). In this example, we activate these mechanisms by changing some
corresponding parameter values (see the documentation on method Calc_ActualRelease_V3
for more detailed examples, including the numerous corner cases):
>>> targetvolume(0.5)
>>> neardischargeminimumthreshold(0.1)
>>> allowedrelease(4.0)
>>> allowedwaterleveldrop(1.0)
Compared with the allowed release results of dam_v007
, dam_v008
dampens the given flood event less efficiently. dam_v007
releases all initial inflow,
while dam_v008
stores most of it until it reaches the target volume of 0.5 million m³.
After peak flow, dam_v008
first releases its water as fast as allowed but then again
tries to meet the target volume. The slow negative trend away from the target value at
the end of the simulation period results from the lack of inflow while still needing to
release at least 0.1 m³/s:
>>> test("dam_v008_target_volume")
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
higher accuracy¶
The first water volume calculated in the sharp transitions example is negative, resulting from the limited numerical accuracy of the underlying integration algorithm. We can decrease such errors by defining smaller error tolerances but at the risk of relevant increases in computation times (especially in case one applies zero smoothing values):
>>> solver.abserrormax(1e-6)
>>> test("dam_v008_higher_accuracy")
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
target range¶
In the last example, the reservoir behaviour changes abruptly when the actual volume
transcends the target volume. According to its documentation, LARSIM then predicts
unrealistic jumps in discharge. To solve this issue, LARSIM offers the
“TALSPERRE SOLLRANGE” option, which ensures smoother transitions between 80 % and 120 %
of the target volume, accomplished by linear interpolation. dam_v008
should never
output similar jumps as it controls the correctness of its results. As a drawback,
correcting these jumps (which still occur “unseeable” and possibly multiple times
within each affected simulation time step) costs computation time. Hence, at least
for small smoothing parameter values, dam_v008
can also benefit from this approach.
You can define the interpolation range freely via TargetRangeAbsolute
and
TargetRangeRelative
, depending on your specific needs. Setting the latter to 0.2
corresponds to the original “TALSPERRE SOLLRANGE”-configuration:
>>> targetrangerelative(0.2)
>>> test("dam_v008_target_range")
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
minimum volume¶
In all examples above, the dam would run dry entirely after a certain amount of time to
fulfil the downstream demand defined by parameter NearDischargeMinimumThreshold
.
Usually, this is neither desired nor technically possible. The following example shows
that the parameter WaterVolumeMinimumThreshold
allows setting a minimum amount of
water below which no release occurs:
>>> watervolumeminimumthreshold(0.45)
>>> test("dam_v008_minimum_volume")
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
evaporation¶
This example takes up the evaporation example of
application model dam_v006
. The reservoir can no longer maintain the target water
level at the end of the simulation period due to missing precipitation or inflow for
compensating evaporation:
>>> inputs.evaporation.series = 10 * [1.0] + 10 * [5.0]
>>> test("dam_v008_evaporation")
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.dam_v008.Model[source]¶
Bases:
ELSModel
Version 8 of HydPy-Dam.
- The following “inlet update methods” are called in the given sequence at the beginning of each simulation step:
Calc_AdjustedEvaporation_V1
Adjust the given potential evaporation.
- The following methods define the relevant components of a system of ODE equations (e.g. direct runoff):
Calc_AdjustedPrecipitation_V1
Adjust the given precipitation.Pic_Inflow_V1
Update the inlet sequenceInflow
.Calc_WaterLevel_V1
Determine the water level based on an interpolation approach approximating the relationship between water volume and water level.Calc_ActualEvaporation_V1
Calculate the actual evaporation.Calc_SurfaceArea_V1
Determine the surface area based on an interpolation approach approximating the relationship between water level and the surface area.Calc_AllowedDischarge_V2
Calculate the maximum discharge not leading to exceedance of the allowed water level drop.Calc_ActualRelease_V3
Calculate an actual water release that tries to change the water storage into the direction of the actual target volume without violating the required minimum and the allowed maximum flow.Calc_FloodDischarge_V1
Calculate the discharge during and after a flood event based on seasonally varying interpolation approaches approximating the relationship(s) between discharge and water stage.Calc_Outflow_V1
Calculate the total outflow of the dam.
- The following methods define the complete equations of an ODE system (e.g. change in storage of fast water due to effective precipitation and direct runoff):
Update_WaterVolume_V1
Update the actual water volume.
- The following “outlet update methods” are called in the given sequence at the end of each simulation step:
Calc_WaterLevel_V1
Determine the water level based on an interpolation approach approximating the relationship between water volume and water level.Pass_Outflow_V1
Update the outlet link sequenceQ
.
- check_waterbalance(initial_conditions: Dict[str, Dict[str, ArrayFloat]]) float [source]¶
Determine the water balance error of the previous simulation run in million m³.
Method
check_waterbalance()
calculates the balance error as follows:\(Seconds \cdot 10^{-6} \cdot \sum_{t=t0}^{t1} \big( AdjustedPrecipitation_t - ActualEvaporation_t + Inflow_t - Outflow_t \big) + \big( WaterVolume_{t0}^k - WaterVolume_{t1}^k \big)\)
The returned error should always be in scale with numerical precision so that it does not affect the simulation results in any relevant manner.
Pick the required initial conditions before starting the simulation run via property
conditions
. See the integration tests of the application modeldam_v008
for some examples.
- class hydpy.models.dam_v008.AideSequences(master: Sequences, cls_fastaccess: Type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
AideSequences
Aide sequences of model dam_v008.
- The following classes are selected:
SurfaceArea()
Surface area [km²].AllowedDischarge()
Discharge threshold not to be overcut by the actual discharge [m³/s].
- class hydpy.models.dam_v008.ControlParameters(master: Parameters, cls_fastaccess: Type[FastAccessParameter] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
SubParameters
Control parameters of model dam_v008.
- The following classes are selected:
SurfaceArea()
Average size of the water surface [km²].CatchmentArea()
Size of the catchment draining into the dam [km²].CorrectionPrecipitation()
Precipitation correction factor [-].CorrectionEvaporation()
Evaporation correction factor [-].WeightEvaporation()
Time weighting factor for evaporation [-].NearDischargeMinimumThreshold()
Discharge threshold of a cross-section near the dam not to be undercut by the actual discharge [m³/s].WaterVolumeMinimumThreshold()
The minimum operating water volume of the dam [million m³].ThresholdEvaporation()
The water level at which actual evaporation is 50 % of potential evaporation [m].ToleranceEvaporation()
A tolerance value defining the steepness of the transition of actual evaporation between zero and potential evaporation [m].WaterVolume2WaterLevel()
Artificial neural network describing the relationship between water level and water volume [-].WaterLevel2FloodDischarge()
Artificial neural network describing the relationship between flood discharge and water volume [-].AllowedWaterLevelDrop()
The highest allowed water level decrease [m/T].AllowedRelease()
The maximum water release not causing any harm downstream [m³/s].TargetVolume()
The desired volume of water required within the dam at specific times of the year [Mio. m³].TargetRangeAbsolute()
The absolute interpolation range related to parameterTargetVolume
[Mio. m³].TargetRangeRelative()
The relative interpolation range related to parameterTargetVolume
[-].VolumeTolerance()
Smoothing parameter for volume related smoothing operations [Mio. m³].DischargeTolerance()
Smoothing parameter for discharge related smoothing operations [m³/s].
- class hydpy.models.dam_v008.DerivedParameters(master: Parameters, cls_fastaccess: Type[FastAccessParameter] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
SubParameters
Derived parameters of model dam_v008.
- The following classes are selected:
TOY()
References thetimeofyear
index array provided by the instance of classIndexer
available in modulepub
[-].Seconds()
Length of the actual simulation step size [s].InputFactor()
Factor for converting meteorological input from mm/T to million m³/s.SmoothParEvaporation()
Smoothing parameter to be derived fromToleranceEvaporation
for smoothing kernelsmooth_logistic1()
[m].VolumeSmoothParLog1()
Smoothing parameter to be derived fromVolumeTolerance
for smoothing kernelsmooth_logistic1()
[Mio. m³].VolumeSmoothParLog2()
Smoothing parameter to be derived fromVolumeTolerance
for smoothing kernelsmooth_logistic2()
[Mio. m³].DischargeSmoothPar()
Smoothing parameter to be derived fromDischargeTolerance
for smoothing kernelssmooth_min1()
andsmooth_max1()
[m³/s].
- class hydpy.models.dam_v008.FactorSequences(master: Sequences, cls_fastaccess: Type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
FactorSequences
Factor sequences of model dam_v008.
- The following classes are selected:
WaterLevel()
Water level [m].
- class hydpy.models.dam_v008.FluxSequences(master: Sequences, cls_fastaccess: Type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
FluxSequences
Flux sequences of model dam_v008.
- The following classes are selected:
AdjustedPrecipitation()
Adjusted precipitation [m³/s].AdjustedEvaporation()
Adjusted evaporation [m³/s].ActualEvaporation()
Actual evaporation [m³/s].Inflow()
Total inflow [m³/s].ActualRelease()
Actual water release thought for reducing drought events downstream [m³/s].FloodDischarge()
Water release associated with flood events [m³/s].Outflow()
Total outflow [m³/s].
- class hydpy.models.dam_v008.InletSequences(master: Sequences, cls_fastaccess: Type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
InletSequences
Inlet sequences of model dam_v008.
- The following classes are selected:
Q()
Inflow [m³/s].
- class hydpy.models.dam_v008.InputSequences(master: Sequences, cls_fastaccess: Type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
InputSequences
Input sequences of model dam_v008.
- The following classes are selected:
Precipitation()
Precipitation [mm].Evaporation()
Potential evaporation [mm].
- class hydpy.models.dam_v008.LogSequences(master: Sequences, cls_fastaccess: Type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
LogSequences
Log sequences of model dam_v008.
- The following classes are selected:
LoggedAdjustedEvaporation()
Logged adjusted evaporation [m3/s].
- class hydpy.models.dam_v008.OutletSequences(master: Sequences, cls_fastaccess: Type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
OutletSequences
Outlet sequences of model dam_v008.
- The following classes are selected:
Q()
Outflow [m³/s].
- class hydpy.models.dam_v008.SolverParameters(master: Parameters, cls_fastaccess: Type[FastAccessParameter] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
SubParameters
Solver parameters of model dam_v008.
- The following classes are selected:
AbsErrorMax()
Absolute numerical error tolerance [m³/s].RelErrorMax()
Relative numerical error tolerance [1/T].RelDTMin()
Smallest relative integration time step size allowed [-].RelDTMax()
Largest relative integration time step size allowed [-].
- class hydpy.models.dam_v008.StateSequences(master: Sequences, cls_fastaccess: Type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)¶
Bases:
StateSequences
State sequences of model dam_v008.
- The following classes are selected:
WaterVolume()
Water volume [million m³].