dam_v003

Version 3 of HydPy-Dam.

dam_v003 is quite similar to dam_v002. Both application models provide the same flood retentions functionalities. Also, both try to meet the water demand at a remote location. The difference is that dam_v002 expects this demand to occur in the channel downstream (usually to increase low discharge values). Instead, dam_v003 supplies water to a different location (such as a drinking water treatment plant). Hence dam_v002 releases its water via a single output path while dam_v003 divides it into two separate paths.

The following explanations focus on this difference. For further information on using dam_v003, please read the documentation on dam_v001 and dam_v002.

Integration tests

Note

When new to HydPy, consider reading section How to understand integration tests? first.

To illustrate the functionalities of dam_v003, we refer back to those examples of the comprehensive documentation on application model dam_v001 we also revisited when discussing dam_v002. In contrast to the comparison between dam_v001 and dam_v002, we cannot define settings for dam_v003 that lead to identical results in cases of remote demand. In all other situations, dam_v003 works like dam_v001 and dam_v002. Hence, most examples serve more to confirm the correctness of the model’s implementation than explaining new features.

The time-related setup is identical to the ones of dam_v001 and dam_v002:

>>> from hydpy import pub, Node, Element
>>> pub.timegrids = "01.01.2000", "21.01.2000", "1d"

dam_v003 requires connections to four instead of three Node objects. Instead of one outlet node, there must be two outlet nodes. Node outflow corresponds to the outflow node of the documentation on dam_v001 and dam_v002 and passes the received outflow into the channel immediately downstream the dam. Node actual_supply is new and serves for supplying a different location with water. Node required_supply is equivalent to node demand of the documentation on dam_v002. It delivers the same information but from a different location:

>>> inflow = Node("inflow", variable="Q")
>>> outflow = Node("outflow", variable="Q")
>>> actual_supply = Node("actual_supply", variable="S")
>>> required_supply = Node("required_supply", variable="S")
>>> dam = Element("dam",
...               inlets=inflow,
...               outlets=(outflow, actual_supply),
...               receivers=required_supply)
>>> from hydpy.models.dam_v003 import *
>>> parameterstep("1d")
>>> dam.model = model

dam_v001 releases water via two outlet sequences, Q and S, and needs to know which one corresponds to which outlet node. It gathers this information when building the connection with its Element object dam in the last assignment above. Therefore, it inspects the variable attribute of each outlet node. In our example, we use the string literals “Q” and “S” to enable the correct allocation. See the documentation on method connect() for alternatives and more detailed explanations.

We define the configuration of the IntegrationTest object, the initial conditions, the input time series, and the parameter values exactly as for dam_v002:

>>> from hydpy import IntegrationTest
>>> test = IntegrationTest(dam)
>>> 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),
...             (logs.loggedrequiredremoterelease, 0.005))
>>> inflow.sequences.sim.series = 1.0
>>> inputs.precipitation.series = 0.0
>>> inputs.evaporation.series = 0.0
>>> watervolume2waterlevel(PPoly.from_data(xs=[0.0, 1.0], ys=[0.0, 0.25]))
>>> waterlevel2flooddischarge(PPoly.from_data(xs=[0.0], ys=[0.0]))
>>> catchmentarea(86.4)
>>> neardischargeminimumthreshold(0.2)
>>> neardischargeminimumtolerance(0.2)
>>> waterlevelminimumthreshold(0.0)
>>> waterlevelminimumtolerance(0.0)
>>> restricttargetedrelease(True)
>>> surfacearea(1.44)
>>> correctionprecipitation(1.2)
>>> correctionevaporation(1.2)
>>> weightevaporation(0.8)
>>> thresholdevaporation(0.0)
>>> toleranceevaporation(0.001)

Now, we prepare the two additional parameters, WaterLevelMinimumRemoteThreshold and WaterLevelMinimumRemoteTolerance:

>>> waterlevelminimumremotethreshold(0.0)
>>> waterlevelminimumremotetolerance(0.0)

smooth near minimum

This example corresponds to the smooth near minimum example of application model dam_v001 and the smooth near minimum example of application model dam_v002. We again use the same remote demand:

>>> required_supply.sequences.sim.series = [
...     0.008588, 0.010053, 0.013858, 0.027322, 0.064075, 0.235523, 0.470414,
...     0.735001, 0.891263, 0.696325, 0.349797, 0.105231, 0.111928, 0.240436,
...     0.229369, 0.058622, 0.016958, 0.008447, 0.004155, 0.0]

Due to the separate output paths, there are relevant differences to the results of dam_v001 and dam_v002. dam_v001 and dam_v002 can use the same water to both meet the near and the remote demand, which is not possible for dam_v003. Hence, it must release a larger total amount of water:

>>> test("dam_v003_smooth_near_minimum")
Click to see the table
Click to see the graph

restriction enabled

This example corresponds to the restriction enabled example of application model dam_v001 and the restriction enabled example of application model dam_v002. We update the time series of the inflow and the required remote release accordingly:

>>> inflow.sequences.sim.series[10:] = 0.1
>>> required_supply.sequences.sim.series = [
...     0.008746, 0.010632, 0.015099, 0.03006, 0.068641, 0.242578, 0.474285,
...     0.784512, 0.95036, 0.35, 0.034564, 0.299482, 0.585979, 0.557422,
...     0.229369, 0.142578, 0.068641, 0.029844, 0.012348, 0.0]
>>> neardischargeminimumtolerance(0.0)

The results show that the restriction on releasing water during low inflow conditions concerns the release into the channel downstream only:

>>> test("dam_v003_restriction_enabled")
Click to see the table
Click to see the graph

smooth stage minimum

This example corresponds to the smooth stage minimum example of application model dam_v001 and the smooth stage minimum example of application model dam_v002. We update parameters WaterLevelMinimumThreshold and WaterLevelMinimumTolerance, as well as the time series of the inflow and the required remote release, accordingly, but keep the old value of NearDischargeMinimumThreshold:

>>> waterlevelminimumtolerance(0.01)
>>> waterlevelminimumthreshold(0.005)
>>> inflow.sequences.sim.series = numpy.linspace(0.2, 0.0, 20)
>>> required_supply.sequences.sim.series = [
...     0.01232, 0.029323, 0.064084, 0.120198, 0.247367, 0.45567, 0.608464,
...     0.537314, 0.629775, 0.744091, 0.82219, 0.841916, 0.701812, 0.533258,
...     0.351863, 0.185207, 0.107697, 0.055458, 0.025948, 0.0]
>>> neardischargeminimumthreshold
neardischargeminimumthreshold(0.2)

Additionally, we illustrate the control parameters unknown to dam_v001 and dam_v002, WaterLevelMinimumRemoteThreshold and WaterLevelMinimumRemoteTolerance. Separate water level-related threshold values for the near demand (WaterLevelMinimumThreshold) and the remote demand (WaterLevelMinimumRemoteThreshold) and their smoothing parameters allows for a distinct configuration of both output paths in situations when the available storage is limited. Here, we set WaterLevelMinimumRemoteThreshold to a higher value than WaterLevelMinimumThreshold. Hence, the release into the channel downstream has priority over the supply to the remote location:

>>> waterlevelminimumremotetolerance(0.01)
>>> waterlevelminimumremotethreshold(0.01)
>>> test("dam_v003_smooth_stage_minimum")
Click to see the table
Click to see the graph

evaporation

This example corresponds to the evaporation example of application model dam_v001 and the evaporation example of application model dam_v002. We update the time series of potential evaporation and the required remote release accordingly:

>>> inputs.evaporation.series = 10 * [1.0] + 10 * [5.0]
>>> required_supply.sequences.sim.series = [
...     0.012321, 0.029352, 0.064305, 0.120897, 0.248435, 0.453671, 0.585089,
...     0.550583, 0.694398, 0.784979, 0.81852, 0.840207, 0.72592, 0.575373,
...     0.386003, 0.198088, 0.113577, 0.05798, 0.026921, 0.0]

Due to the remaining differences regarding remote demand, the following results differ from those of dam_v001 and dam_v002. However, detailed comparisons show the same patterns for adjusting given potential evaporation and its conversion to actual evaporation under water scarcity:

>>> test("dam_v003_evaporation")
Click to see the table
Click to see the graph

flood retention

This example repeats the flood retention example of application model dam_v001 and the flood retention example of application model dam_v002. We use the same parameter and input time series configuration:

>>> neardischargeminimumthreshold(0.0)
>>> neardischargeminimumtolerance(0.0)
>>> waterlevelminimumthreshold(0.0)
>>> waterlevelminimumtolerance(0.0)
>>> waterlevelminimumremotethreshold(0.0)
>>> waterlevelminimumremotetolerance(0.0)
>>> waterlevel2flooddischarge(PPoly.from_data(xs=[0.0, 1.0], ys=[0.0, 2.5]))
>>> 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]
>>> inflow.sequences.sim.series = [0.0, 0.0, 5.0, 9.0, 8.0, 5.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
>>> required_supply.sequences.sim.series = 0.0
>>> test.inits.loggedrequiredremoterelease = 0.0

The following results demonstrate that dam_v003 calculates the same outflow values as dam_v001 and dam_v002 if there is no relevant remote demand:

>>> test("dam_v003_flood_retention")
Click to see the table
Click to see the graph
class hydpy.models.dam_v003.Model[source]

Bases: ELSModel

Version 3 of HydPy-Dam.

The following “receiver update methods” are called in the given sequence before performing a simulation step:
The following “inlet update methods” are called in the given sequence at the beginning of each simulation step:
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 sequence Inflow.

  • 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_ActualRelease_V1 Calculate the actual water release that can be supplied by the dam considering the targeted release and the given water level.

  • Calc_ActualRemoteRelease_V1 Calculate the actual remote water release that can be supplied by the dam considering the required remote release and the given water level.

  • 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):
The following “outlet update methods” are called in the given sequence at the end of each simulation step:
class hydpy.models.dam_v003.ControlParameters(master: Parameters, cls_fastaccess: Type[FastAccessParameter] | None = None, cymodel: CyModelProtocol | None = None)

Bases: SubParameters

Control parameters of model dam_v003.

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

Bases: SubParameters

Derived parameters of model dam_v003.

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

Bases: FactorSequences

Factor sequences of model dam_v003.

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

Bases: FluxSequences

Flux sequences of model dam_v003.

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

Bases: InletSequences

Inlet sequences of model dam_v003.

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

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

Bases: InputSequences

Input sequences of model dam_v003.

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

Bases: LogSequences

Log sequences of model dam_v003.

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

Bases: OutletSequences

Outlet sequences of model dam_v003.

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

  • S() Actual water supply [m³/s].

class hydpy.models.dam_v003.ReceiverSequences(master: Sequences, cls_fastaccess: Type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)

Bases: ReceiverSequences

Receiver sequences of model dam_v003.

The following classes are selected:
  • S() Required water supply [m³/s].

class hydpy.models.dam_v003.SolverParameters(master: Parameters, cls_fastaccess: Type[FastAccessParameter] | None = None, cymodel: CyModelProtocol | None = None)

Bases: SubParameters

Solver parameters of model dam_v003.

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_v003.StateSequences(master: Sequences, cls_fastaccess: Type[TypeFastAccess_co] | None = None, cymodel: CyModelProtocol | None = None)

Bases: StateSequences

State sequences of model dam_v003.

The following classes are selected: