Source code for hydpy.models.dam_v007

# -*- coding: utf-8 -*-
# pylint: disable=line-too-long, wildcard-import, unused-wildcard-import
"""Retention basin version of HydPy-Dam.

.. _`LARSIM`: http://www.larsim.de/en/the-model/

|dam_v007| is a simple "retention basin" model, similar to the "RUEC"
model of `LARSIM`_.  One can understand it as an extension of |dam_v006|,
and it partly requires equal specifications.  Hence, before continuing
please first read the documentation on |dam_v006|.

In extension to |dam_v006|, |dam_v007| implements the control parameter
|AllowedRelease| (and the related parameters |WaterLevelMinimumThreshold|
and |WaterLevelMinimumTolerance|).  Usually, one takes the discharge
not causing any harm downstream as the "allowed release", making |dam_v007|
behave like a retention basin without active control.  However, one can
vary the allowed release seasonally (|AllowedRelease| inherits from class
|SeasonalParameter|).

In contrast to |dam_v006|, |dam_v007| does not allow to restrict the speed
of the water level decrease during periods with little inflow and thus does
not use the parameter |AllowedWaterLevelDrop|.

Integration tests
=================

.. how_to_understand_integration_tests::

We create the same test set as for application model |dam_v006|,
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"
>>> parameterstep("1d")
>>> element = Element("element", inlets="input_", outlets="output")
>>> element.model = model
>>> IntegrationTest.plotting_options.axis1 = fluxes.inflow, fluxes.outflow
>>> IntegrationTest.plotting_options.axis2 = states.watervolume
>>> test = IntegrationTest(element)
>>> test.dateformat = "%d.%m."
>>> test.inits = [(states.watervolume, 0.0)]
>>> watervolume2waterlevel(
...     weights_input=1.0, weights_output=1.0,
...     intercepts_hidden=0.0, intercepts_output=0.0,
...     activation=0)
>>> catchmentarea(86.4)
>>> element.inlets.input_.sequences.sim.series = [
...     0.0, 1.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]

.. _dam_v007_base_scenario:

base scenario
_____________

To show that |dam_v007| extends |dam_v006| correctly, we also define the
same quasi-linear relation between discharge and stage used throughout the
integration tests of |dam_v006| and additionally set the allowed release to
0 m³/s (which makes the values of the two water-related control parameters
irrelevant).  As expected, |dam_v007| now calculates outflow values
identical with the ones of the :ref:`dam_v006_base_scenario` example of
|dam_v006| (where |AllowedWaterLevelDrop| is |numpy.inf|):

.. integration-test::

    >>> waterlevel2flooddischarge(ann(
    ...     weights_input=1.0, weights_output=10.0,
    ...     intercepts_hidden=0.0, intercepts_output=0.0,
    ...     activation=0))
    >>> allowedrelease(0.0)
    >>> waterlevelminimumtolerance(0.1)
    >>> waterlevelminimumthreshold(0.0)
    >>> test("dam_v007_base_scenario")
    |   date | inflow | actualrelease | flooddischarge |  outflow | watervolume | input_ |   output |
    -------------------------------------------------------------------------------------------------
    | 01.01. |    0.0 |           0.0 |            0.0 |      0.0 |         0.0 |    0.0 |      0.0 |
    | 02.01. |    1.0 |           0.0 |       0.329814 | 0.329814 |    0.057904 |    1.0 | 0.329814 |
    | 03.01. |    6.0 |           0.0 |       2.370574 | 2.370574 |    0.371486 |    6.0 | 2.370574 |
    | 04.01. |   12.0 |           0.0 |       6.452959 | 6.452959 |    0.850751 |   12.0 | 6.452959 |
    | 05.01. |   10.0 |           0.0 |       8.999753 | 8.999753 |    0.937172 |   10.0 | 8.999753 |
    | 06.01. |    6.0 |           0.0 |       8.257426 | 8.257426 |    0.742131 |    6.0 | 8.257426 |
    | 07.01. |    3.0 |           0.0 |        5.96014 |  5.96014 |    0.486374 |    3.0 |  5.96014 |
    | 08.01. |    2.0 |           0.0 |       3.917326 | 3.917326 |    0.320717 |    2.0 | 3.917326 |
    | 09.01. |    1.0 |           0.0 |       2.477741 | 2.477741 |    0.193041 |    1.0 | 2.477741 |
    | 10.01. |    0.0 |           0.0 |       1.293731 | 1.293731 |    0.081262 |    0.0 | 1.293731 |
    | 11.01. |    0.0 |           0.0 |       0.544608 | 0.544608 |    0.034208 |    0.0 | 0.544608 |
    | 12.01. |    0.0 |           0.0 |       0.227669 | 0.227669 |    0.014537 |    0.0 | 0.227669 |
    | 13.01. |    0.0 |           0.0 |       0.096753 | 0.096753 |    0.006178 |    0.0 | 0.096753 |
    | 14.01. |    0.0 |           0.0 |       0.042778 | 0.042778 |    0.002482 |    0.0 | 0.042778 |
    | 15.01. |    0.0 |           0.0 |       0.017186 | 0.017186 |    0.000997 |    0.0 | 0.017186 |
    | 16.01. |    0.0 |           0.0 |       0.005664 | 0.005664 |    0.000508 |    0.0 | 0.005664 |
    | 17.01. |    0.0 |           0.0 |       0.002884 | 0.002884 |    0.000259 |    0.0 | 0.002884 |
    | 18.01. |    0.0 |           0.0 |       0.001469 | 0.001469 |    0.000132 |    0.0 | 0.001469 |
    | 19.01. |    0.0 |           0.0 |       0.000748 | 0.000748 |    0.000067 |    0.0 | 0.000748 |
    | 20.01. |    0.0 |           0.0 |       0.000381 | 0.000381 |    0.000034 |    0.0 | 0.000381 |

.. _dam_v007_spillway:

spillway
________

Now, we introduce a more realistic relationship between flood discharge
and stage, where the spillway of the retention basin starts to become
relevant when the water volume exceeds about 1.4 million m³:

>>> waterlevel2flooddischarge(ann(
...     weights_input=10.0, weights_output=50.0,
...     intercepts_hidden=-20.0, intercepts_output=0.0))
>>> waterlevel2flooddischarge.plot(0.0, 2.0)
>>> from hydpy.core.testtools import save_autofig
>>> save_autofig("dam_v007_waterlevel2flooddischarge.png")

.. image:: dam_v007_waterlevel2flooddischarge.png
   :width: 400

The initially available storage volume of about 1.4 million m³ reduces
the peak flow to 7.3 m³/s:

.. integration-test::

    >>> test("dam_v007_spillway")
    |   date | inflow | actualrelease | flooddischarge |  outflow | watervolume | input_ |   output |
    -------------------------------------------------------------------------------------------------
    | 01.01. |    0.0 |           0.0 |            0.0 |      0.0 |         0.0 |    0.0 |      0.0 |
    | 02.01. |    1.0 |           0.0 |            0.0 |      0.0 |      0.0864 |    1.0 |      0.0 |
    | 03.01. |    6.0 |           0.0 |       0.000022 | 0.000022 |    0.604798 |    6.0 | 0.000022 |
    | 04.01. |   12.0 |           0.0 |       0.125869 | 0.125869 |    1.630723 |   12.0 | 0.125869 |
    | 05.01. |   10.0 |           0.0 |       7.337517 | 7.337517 |    1.860762 |   10.0 | 7.337517 |
    | 06.01. |    6.0 |           0.0 |       6.687413 | 6.687413 |    1.801369 |    6.0 | 6.687413 |
    | 07.01. |    3.0 |           0.0 |       3.829425 | 3.829425 |    1.729707 |    3.0 | 3.829425 |
    | 08.01. |    2.0 |           0.0 |       2.462161 | 2.462161 |    1.689776 |    2.0 | 2.462161 |
    | 09.01. |    1.0 |           0.0 |       1.602443 | 1.602443 |    1.637725 |    1.0 | 1.602443 |
    | 10.01. |    0.0 |           0.0 |       0.869271 | 0.869271 |     1.56262 |    0.0 | 0.869271 |
    | 11.01. |    0.0 |           0.0 |       0.498579 | 0.498579 |    1.519543 |    0.0 | 0.498579 |
    | 12.01. |    0.0 |           0.0 |       0.348504 | 0.348504 |    1.489432 |    0.0 | 0.348504 |
    | 13.01. |    0.0 |           0.0 |       0.267917 | 0.267917 |    1.466284 |    0.0 | 0.267917 |
    | 14.01. |    0.0 |           0.0 |       0.217618 | 0.217618 |    1.447482 |    0.0 | 0.217618 |
    | 15.01. |    0.0 |           0.0 |       0.183225 | 0.183225 |    1.431651 |    0.0 | 0.183225 |
    | 16.01. |    0.0 |           0.0 |       0.158219 | 0.158219 |    1.417981 |    0.0 | 0.158219 |
    | 17.01. |    0.0 |           0.0 |       0.139064 | 0.139064 |    1.405966 |    0.0 | 0.139064 |
    | 18.01. |    0.0 |           0.0 |       0.124197 | 0.124197 |    1.395235 |    0.0 | 0.124197 |
    | 19.01. |    0.0 |           0.0 |       0.112196 | 0.112196 |    1.385542 |    0.0 | 0.112196 |
    | 20.01. |    0.0 |           0.0 |       0.102307 | 0.102307 |    1.376702 |    0.0 | 0.102307 |

.. _dam_v007_allowed_release:

allowed release
_______________

In the :ref:`dam_v007_spillway` example, |dam_v007| would not handle a
second event following the first one similarly well, due to the retention
basin not releasing the remaining 1.4 million m³ water.  Setting the allowed
release to 4 m³/s solves this problem and also decreases the amount of water
stored during the beginning of the event and thus further reduces the peak
flow to 4.6 m³/s:

.. integration-test::

    >>> allowedrelease(4.0)
    >>> waterlevelminimumthreshold(0.1)
    >>> test("dam_v007_allowed_release")
    |   date | inflow | actualrelease | flooddischarge |  outflow | watervolume | input_ |   output |
    -------------------------------------------------------------------------------------------------
    | 01.01. |    0.0 |      0.037088 |            0.0 | 0.037088 |   -0.003204 |    0.0 | 0.037088 |
    | 02.01. |    1.0 |       0.24393 |            0.0 |  0.24393 |     0.06212 |    1.0 |  0.24393 |
    | 03.01. |    6.0 |      3.512924 |       0.000001 | 3.512925 |    0.277003 |    6.0 | 3.512925 |
    | 04.01. |   12.0 |      3.999413 |       0.000827 | 4.000241 |    0.968183 |   12.0 | 4.000241 |
    | 05.01. |   10.0 |           4.0 |        0.05527 |  4.05527 |    1.481807 |   10.0 |  4.05527 |
    | 06.01. |    6.0 |           4.0 |       0.572981 | 4.572981 |    1.605102 |    6.0 | 4.572981 |
    | 07.01. |    3.0 |           4.0 |       0.508315 | 4.508315 |    1.474783 |    3.0 | 4.508315 |
    | 08.01. |    2.0 |           4.0 |       0.117913 | 4.117913 |    1.291796 |    2.0 | 4.117913 |
    | 09.01. |    1.0 |           4.0 |       0.015063 | 4.015063 |    1.031294 |    1.0 | 4.015063 |
    | 10.01. |    0.0 |           4.0 |       0.001601 | 4.001601 |    0.685556 |    0.0 | 4.001601 |
    | 11.01. |    0.0 |      3.999967 |        0.00005 | 4.000018 |    0.339954 |    0.0 | 4.000018 |
    | 12.01. |    0.0 |      3.097067 |       0.000001 | 3.097068 |    0.072368 |    0.0 | 3.097068 |
    | 13.01. |    0.0 |       0.40591 |            0.0 |  0.40591 |    0.037297 |    0.0 |  0.40591 |
    | 14.01. |    0.0 |      0.155222 |            0.0 | 0.155222 |    0.023886 |    0.0 | 0.155222 |
    | 15.01. |    0.0 |      0.096838 |            0.0 | 0.096838 |    0.015519 |    0.0 | 0.096838 |
    | 16.01. |    0.0 |      0.070215 |            0.0 | 0.070216 |    0.009452 |    0.0 | 0.070216 |
    | 17.01. |    0.0 |      0.054858 |            0.0 | 0.054858 |    0.004713 |    0.0 | 0.054858 |
    | 18.01. |    0.0 |      0.045172 |            0.0 | 0.045172 |     0.00081 |    0.0 | 0.045172 |
    | 19.01. |    0.0 |      0.038376 |            0.0 | 0.038376 |   -0.002506 |    0.0 | 0.038376 |
    | 20.01. |    0.0 |      0.033349 |            0.0 | 0.033349 |   -0.005387 |    0.0 | 0.033349 |

The initial and final water volumes shown in the last table are slightly
negative, which is due to the periods of zero inflow in combination with
the value of parameter |WaterLevelMinimumTolerance| set to 0.1 m.  One
could avoid such negative values by increasing parameter
|WaterLevelMinimumThreshold| or decreasing parameter
|WaterLevelMinimumTolerance|.  Theoretically, one could set
|WaterLevelMinimumTolerance| to zero, but at the cost of potentially
increased computation times.
"""
# import...
# ...from HydPy
from hydpy.auxs.anntools import ann  # pylint: disable=unused-import
from hydpy.exe.modelimports import *
from hydpy.core import modeltools

# ...from dam
from hydpy.models.dam import dam_model
from hydpy.models.dam import dam_solver


[docs]class Model(modeltools.ELSModel): """Version 7 of HydPy-Dam.""" SOLVERPARAMETERS = ( dam_solver.AbsErrorMax, dam_solver.RelErrorMax, dam_solver.RelDTMin, dam_solver.RelDTMax, ) SOLVERSEQUENCES = () INLET_METHODS = (dam_model.Pic_Inflow_V1,) RECEIVER_METHODS = () ADD_METHODS = () PART_ODE_METHODS = ( dam_model.Pic_Inflow_V1, dam_model.Calc_WaterLevel_V1, dam_model.Calc_ActualRelease_V2, dam_model.Calc_FloodDischarge_V1, dam_model.Calc_Outflow_V1, ) FULL_ODE_METHODS = (dam_model.Update_WaterVolume_V1,) OUTLET_METHODS = (dam_model.Pass_Outflow_V1,) SENDER_METHODS = () SUBMODELS = ()
tester = Tester() cythonizer = Cythonizer() cythonizer.finalise()