HydPy-Musk-Classic (classic Muskingum routing, compatible with SMHI-IHMS-HBV96)

The HydPy-Musk family member musk_classic realises the well-known Muskingum routing method (McCarthy, 1940). The Muskingum method is a simple “hydrological” routing approach that applies a finite difference approximation of the continuity equation with fixed coefficients. Users are free to define these coefficients manually or let musk_classic calculate them based on the travel time k and the weighting coefficient x (see the documentation on parameter Coefficients for further information). Either way, one should note these coefficients apply to each channel segment. Hence, when increasing the number of segments (via parameter NmbSegments), the net travel time through the whole channel increases, too.

musk_classic also supports a simplified version of the Muskingum method that is part of HBV96 (Lindström et al., 1997) and relies on the parameters lag, describing lag time, and damp, describing the damping of the hydrograph along the channel. See the documentation on the parameters NmbSegments and Coefficients on how to use this information to calculate the coefficients of the Muskingum working equation.

Integration tests

Note

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

We perform the following examples over a simulation period of 20 hours:

>>> from hydpy import pub, Nodes, Element
>>> pub.timegrids = "01.01.2000 00:00", "01.01.2000 20:00", "1h"

We also set the time step size of the parameter values defined below to one hour:

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

The musk_classic model, handled by Element stream, queries its inflow from two Node objects (input1 and input2) and passes its outflow to a single Node object (output):

>>> nodes = Nodes("input1", "input2", "output")
>>> stream = Element("stream", inlets=["input1", "input2"], outlets="output")
>>> stream.model = model

The test function object sets the initial flow into all segment endpoints (Discharge) to zero before each simulation run:

>>> from hydpy.core.testtools import IntegrationTest
>>> test = IntegrationTest(stream, inits=((states.discharge, 0.0),))
>>> test.dateformat = "%H:%M"

We define two flood events, one for each inflow node:

>>> nodes.input1.sequences.sim.series = [
...     0.0, 0.0, 1.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, 0.0, 0.0, 0.0]
>>> nodes.input2.sequences.sim.series = [
...     0.0, 1.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]

Because of its good clarity, we use the HBV96 style to configure the coefficients of the working equation in all integration tests.

Zero lag time

With zero lag time, there are no river segments. Hence, there is only one segment endpoint, which lies both at the whole channel’s start and end. Accordingly, the outflow is always equal to the inflow, regardless of the values chosen for the Muskingum coefficients:

>>> nmbsegments(lag=0.0)
>>> coefficients(damp=1.0)
>>> test("musk_classic_zero_lag_time")
Click to see the table
Click to see the graph

Translation

With a lag time of three hours and zero damping, musk_classic simply passes the flow values from one segment to the next within each simulation time step. A number of three segments gives an overall time shift of three hours:

>>> nmbsegments(lag=3.0)
>>> coefficients(damp=0.0)
>>> test("musk_classic_no_translation")
Click to see the table
Click to see the graph

Diffusion

Parameter Coefficients controls the diffusion (or damping) of flood waves within each river segment. We demonstrate its functioning by keeping the lag value of three hours but setting damp to one:

>>> nmbsegments(lag=3.0)
>>> coefficients(damp=1.0)
>>> test("musk_classic_diffusion")
Click to see the table
Click to see the graph
class hydpy.models.musk_classic.NmbRuns(subvars)[source]

Bases: NmbRuns

The number of runs of the RUN_METHODS of the musk_classic model per simulation step [-].

As opposed to other members of the HydPy-Musk model family, repeating the “run methods” of musk_classic does not improve the accuracy of the simulated results. Hence, we restrict the highest value of parameter NmbRuns to one:

>>> from hydpy.models.musk_classic import *
>>> parameterstep()
>>> solver.nmbruns(2)
Traceback (most recent call last):
...
ValueError: The value `2` of parameter `nmbruns` of element `?` is not valid.
INIT: int | float | bool = 1
SPAN: tuple[int | float | bool | None, int | float | bool | None] = (1, 1)
name: str = 'nmbruns'

Name of the variable in lowercase letters.

unit: str = '-'

Unit of the variable.

class hydpy.models.musk_classic.Model[source]

Bases: SegmentModel

HydPy-Musk-Classic (classic Muskingum routing, compatible with SMHI-IHMS-HBV96).

The following “inlet update methods” are called in the given sequence at the beginning of each simulation step:
  • Pick_Inflow_V1 Assign the actual value of the inlet sequence to the inflow sequence.

  • Update_Discharge_V1 Assign the inflow to the start point of the first channel segment.

The following “run methods” are called in the given sequence during each simulation step:
The following “outlet update methods” are called in the given sequence at the end of each simulation step:
  • Calc_Outflow_V1 Take the discharge at the last segment endpoint as the channel’s outflow.

  • Pass_Outflow_V1 Pass the channel’s outflow to the outlet sequence.

DOCNAME: DocName = ('Musk-Classic', 'classic Muskingum routing, compatible with SMHI-IHMS-HBV96')
REUSABLE_METHODS: ClassVar[tuple[type[ReusableMethod], ...]] = ()
class hydpy.models.musk_classic.Masks[source]

Bases: Masks

Masks applicable to musk_classic.

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

Bases: SubParameters

Control parameters of model musk_classic.

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

Bases: FluxSequences

Flux sequences of model musk_classic.

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

Bases: InletSequences

Inlet sequences of model musk_classic.

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

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

Bases: OutletSequences

Outlet sequences of model musk_classic.

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

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

Bases: SubParameters

Solver parameters of model musk_classic.

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

Bases: StateSequences

State sequences of model musk_classic.

The following classes are selected:
  • Discharge() Current discharge at the segment endpoints [m³/s].