HydPy-Dam-Pump (pumping station model)

dam_pump is a simple model for modelling pumping stations draining low-land areas. Users can define a relationship between the highest possible pumping rate and the difference between current inner and outer water levels (WaterLevelDifference2MaxForcedDischarge). Actual pumping happens when the inner water level reaches the given target level (WaterLevelMaximumThreshold) as long as the water level at a remote location does not exceed another defined threshold (RemoteWaterLevelMaximumThreshold). The latter restriction helps to prevent further increasing high flow conditions in downstream areas. If the MaxForcedDischarge is negative, the pumping process is carried out in the reverse direction (e.g. for modelling irrigation processes).

By default, dam_pump neither takes precipitation nor evaporation into account, but you can add submodels that comply with the PrecipModel_V2 or PETModel_V1 interface that supply this information.

Integration tests

Note

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

We prepare a simulation period of 20 days:

>>> from hydpy import IntegrationTest, Element, Node, pub, round_
>>> pub.timegrids = "2000-01-01", "2000-01-21", "1d"

Besides the standard inlet and outlet nodes, dam_pump requires connections with two receiver nodes. One of these nodes should inform about the water level immediately downstream. The other one should provide water levels from a “sensible” location where a certain water level should not be exceeded. We connect these nodes via the remote sequences OWL (outer water level) and RWL (remote water level):

>>> from hydpy.aliases import dam_receivers_OWL, dam_receivers_RWL
>>> inflow = Node("inflow")
>>> outflow = Node("outflow")
>>> outer = Node("outer", variable=dam_receivers_OWL)
>>> remote = Node("remote", variable=dam_receivers_RWL)
>>> dam = Element("dam", inlets=inflow, outlets=outflow, receivers=(outer, remote))

Next, we prepare a dam_pump instance and connect it to the Element instance:

>>> from hydpy.models.dam_pump import *
>>> parameterstep()
>>> dam.model = model

Parameterising dam_pump works similarly to parameterising other dam models. Please read the documentation on dam_v001, which provides in-depth information and should help understand the following settings:

>>> surfacearea(1.44)
>>> catchmentarea(86.4)
>>> watervolume2waterlevel(PPoly.from_data(xs=[0.0, 1.0], ys=[0.0, 1.0]))
>>> waterleveldifference2maxforceddischarge(PPoly.from_data(xs=[0.0], ys=[1.0]))
>>> waterlevelmaximumthreshold(1.0)
>>> waterlevelmaximumtolerance(0.1)
>>> remotewaterlevelmaximumthreshold(2.0)
>>> remotewaterlevelmaximumtolerance(0.1)
>>> correctionprecipitation(1.0)
>>> correctionevaporation(1.0)
>>> weightevaporation(0.8)
>>> thresholdevaporation(0.0)
>>> toleranceevaporation(0.001)

We add meteo_precip_io and evap_ret_io submodels that can supply predefined time series of precipitation and potential evaporation:

>>> with model.add_precipmodel_v2("meteo_precip_io"):
...     precipitationfactor(1.0)
>>> with model.add_pemodel_v1("evap_ret_io"):
...     evapotranspirationfactor(1.0)

Now, we prepare an IntegrationTest object and register zero initial conditions for all state and log sequences:

>>> test = IntegrationTest(dam)
>>> test.dateformat = "%d.%m."
>>> test.plotting_options.axis1 = fluxes.inflow, fluxes.outflow
>>> test.plotting_options.axis2 = factors.waterlevel, factors.outerwaterlevel, factors.remotewaterlevel
>>> test.inits = [(states.watervolume, 0.0),
...               (logs.loggedadjustedevaporation, 0.0),
...               (logs.loggedouterwaterlevel, 0.0),
...               (logs.loggedremotewaterlevel, 0.0)]
>>> test.reset_inits()
>>> conditions = model.conditions

We set the time series of precipitation, evaporation, inflow, and the outer water level to constant values and let the remote water level increase constantly over the entire simulation period:

>>> model.precipmodel.sequences.inputs.precipitation.series = 2.0
>>> model.pemodel.sequences.inputs.referenceevapotranspiration.series = 1.0
>>> inflow.sequences.sim.series = 2.0
>>> outer.sequences.sim.series = 0.0
>>> remote.sequences.sim.series = numpy.linspace(0.0, 3.0, 20)

drainage

The following test run shows that the pumping starts when the inner water level reaches the defined threshold of 1 m. The outflow gradually becomes closer to the constant inflow until the remote water level reaches the other defined threshold of 2 m:

>>> test("dam_pump_drainage")
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

irrigation

The following test run shows that the pumping (in reversed direction) starts when the inner water level is lower than the defined threshold of 1 m and the remote water level is above the defined threshold of 2 m. When the water level rises above 1 meter, the pumping rate quickly decreases to 0.

>>> waterleveldifference2maxforceddischarge(PPoly.from_data(xs=[0.0], ys=[-1.0]))
>>> remote.sequences.sim.series = numpy.linspace(1.0, 4.0, 20)
>>> waterlevelmaximumthreshold(2.0)
>>> test("dam_pump_irrigation")
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_pump.Model[source]

Bases: Main_PrecipModel_V2, Main_PEModel_V1

HydPy-Dam-Pump (pumping station model).

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):
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:
Users can hook submodels into the defined main model if they satisfy one of the following interfaces:
  • PrecipModel_V2 Simple interface for determining precipitation in one step.

  • PETModel_V1 Simple interface for calculating all potential evapotranspiration values in one step.

DOCNAME: DocName = ('Dam-Pump', 'pumping station model')
precipmodel: modeltools.SubmodelProperty

Optional submodel that complies with the following interface: PrecipModel_V2.

pemodel: modeltools.SubmodelProperty

Optional submodel that complies with the following interface: PETModel_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 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 via property conditions. See the integration tests of the application model dam_v001 for some examples.

REUSABLE_METHODS: ClassVar[tuple[type[ReusableMethod], ...]] = ()
class hydpy.models.dam_pump.ControlParameters(master: Parameters, cls_fastaccess: type[FastAccessParameter] | None = None, cymodel: CyModelProtocol | None = None)

Bases: SubParameters

Control parameters of model dam_pump.

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

Bases: SubParameters

Derived parameters of model dam_pump.

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

Bases: FactorSequences

Factor sequences of model dam_pump.

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

Bases: FluxSequences

Flux sequences of model dam_pump.

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

Bases: InletSequences

Inlet sequences of model dam_pump.

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

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

Bases: LogSequences

Log sequences of model dam_pump.

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

Bases: OutletSequences

Outlet sequences of model dam_pump.

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

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

Bases: ReceiverSequences

Receiver sequences of model dam_pump.

The following classes are selected:
  • OWL() The water level directly below the dam [m].

  • RWL() The water level at a remote location [m].

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

Bases: SubParameters

Solver parameters of model dam_pump.

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

Bases: StateSequences

State sequences of model dam_pump.

The following classes are selected: