arma_v1¶
Version 1 of the HydPy-A model generalises the RIMO/RIDO flood routing approach.
RIMO/RIDO is based on the translation diffusion equation, which is a linear approximation on the Saint-Venant equations involving only two parameters - one for the celerity and one for the diffusivity of the flood wave. The linearity of the approach allows for constructing Unit Hydrograph ordinates for each specific combination of celerity, diffusivity, and the length of the considered river section. One can understand these ordinates as coefficients of a moving average (MA) process.
RIMO/RIDO adds two additional features to this conventional approach.
Firstly, RIMO/RIDO approximates the response function described by the MA coefficients by an ARMA process, which is useful for response functions with long tails. Very often, autoregressive (AR) models are capable of approximating long-tailed responses sufficiently with few parameters. Hence, using ARMA models (which reflect the rising limb of a response function with their MA coefficients its falling limb with their AR coefficients) is often more parameter efficient than using pure MA models.
Secondly, RIMO/RIDO separates the flow into the river section into different “portions” based on discharge threshold. Each portion is routed by a separate ARMA model, allowing to factor in the nonlinearity of rating curves to a certain degree. For example, the bank-full discharge can serve as a threshold. Then one can apply smaller celerity values and larger diffusivity values on the “upper” flow portion to simulate retention processes on flood-plains.
If you want to apply arma_v1
precisely like RIMO/RIDO, consider
using TranslationDiffusionEquation
for calculating its coefficients.
But you are free to define other parameters, e.g. those of the
LinearStorageCascade
. Additionally, you are free to apply combined
ARMA coefficients or pure MA coefficients only, as described in the
following examples.
Integration tests¶
Note
When new to HydPy, consider reading section How to understand integration tests? first.
The following tests are performed over a period of 20 hours:
>>> from hydpy import pub, Nodes, Element
>>> pub.timegrids = "01.01.2000 00:00", "01.01.2000 20:00", "1h"
Import the model and define the time settings:
>>> from hydpy.models.arma_v1 import *
>>> parameterstep("1h")
For testing purposes, the model input shall be retrieved from the nodes input1 and input2 and the model output shall be passed to node output. Firstly, define all nodes:
>>> nodes = Nodes("input1", "input2", "output")
Define the element stream and build the connections between
the nodes defined above and the arma_v1
model instance:
>>> stream = Element("stream",
... inlets=["input1", "input2"],
... outlets="output")
>>> stream.model = model
Prepare a test function object, which prints the respective values
of the model sequences QIn
, QPIn
, QPOut
, and QOut
. The node
sequence sim is added in order to prove that the values calculated
for QOut
are actually passed to sim:
>>> from hydpy import IntegrationTest
>>> IntegrationTest.plotting_options.activated=(
... fluxes.qin, fluxes.qout)
>>> test = IntegrationTest(
... stream,
... seqs=(fluxes.qin, fluxes.qpin, fluxes.qpout,
... fluxes.qout, nodes.output.sequences.sim))
To start the respective example runs from stationary conditions, a
base flow value of 2 m³/s is set for all values of the log sequences
LogIn
and LogOut
:
>>> test.inits = ((logs.login, 2.0),
... (logs.logout, 2.0))
Print just the time instead of the whole date:
>>> test.dateformat = "%H:%M"
Define two flood events, one for each lake inflow:
>>> nodes.input1.sequences.sim.series = (
... 1.0, 1.0, 2.0, 4.0, 3.0, 2.0, 1.0, 1.0, 1.0, 1.0,
... 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
>>> nodes.input2.sequences.sim.series = (
... 1.0, 2.0, 6.0, 9.0, 8.0, 6.0, 4.0, 3.0, 2.0, 1.0,
... 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)
MA coefficients¶
In the first example, a pure fourth order moving avarage (MA) process is
defined via the control parameter Responses
:
>>> responses(((), (0.2, 0.4, 0.3, 0.1)))
This leads to a usual “unit hydrograph” convolution result, where all inflow “impulses” are separated onto the actual and the three subsequent time steps:
>>> test("arma_v1_ma")
Click to see the table
Click to see the graph
ARMA coefficients¶
Now we set the order of the MA process to the smalles possible value, which is one. The autoregression (AR) process is of order two. Note that negative AR coefficients are allowed (also note the opposite signs of the coefficients in contrast to the statistical literature):
>>> responses(((1.1, -0.3), (0.2,)))
Due to the AR process, the maximum time delay of some fractions of each input impulse is theoretically infinite:
>>> test("arma_v1_arma")
Click to see the table
Click to see the graph
Increased delay¶
This example equals the second one, except in the additional time delay of exactly one hour, due to the changed MA process:
>>> responses(((1.1, -0.3), (0.0, 0.2)))
>>> test("arma_v1_delay")
Click to see the table
Click to see the graph
Negative discharge¶
In some hydrological applications, the inflow into a channel might be lower
than 0 m³/s at times. arma
generally routes such negative discharges
using the response function with the lowest discharge threshold. When
we repeat the calculation of the Increased delay example with inflow
constantly decreased by 3 m³/s, the outflow is also constantly decreased
by 3 m³/s and many simulated values are negative:
>>> nodes.input1.sequences.sim.series -= 3.0
>>> test.inits = ((logs.login, -1.0),
... (logs.logout, -1.0))
>>> test("arma_v1_negative_discharge")
Click to see the table
Click to see the graph
>>> nodes.input1.sequences.sim.series += 3.0
>>> test.inits = ((logs.login, 2.0),
... (logs.logout, 2.0))
Plausibility¶
Be aware that neither parameter Responses
does check the assigned
coefficients nor does model arma_v1
check the calculated outflow
for plausibility (one can use the features provided in modules
iuhtools
and armatools
to calculate reliable coefficients).
The fourth example increases the span of the AR coefficients used
in the third example. The complete ARMA process is still mass
conservative, but some response values of the recession curve
are negative:
>>> responses(((1.5, -0.7), (0.0, 0.2)))
>>> test("arma_v1_plausibility")
Click to see the table
Click to see the graph
Nonlinearity¶
In the next example, the coefficients of the first two examples are combined. For inflow discharges between 0 and 7 m³/s, the pure AR process is applied. For inflow discharges exceeding 7 m³/s, inflow is separated. The AR process is still applied on a portion of 7 m³/s, but for the inflow exceeding the threshold the mixed ARMA model is applied:
>>> responses(_0=((), (0.2, 0.4, 0.3, 0.1)),
... _7=((1.1, -0.3), (0.2,)))
To again start from stationary conditions, one has to apply different values to both log sequences. The base flow value of 2 m³/s is only given to the (low flow) MA model, the (high flow) ARMA model is initialized with zero values instead:
>>> test.inits.login = [[2.0], [0.0]]
>>> test.inits.logout = [[2.0], [0.0]]
The separate handling of the inflow can be studied by inspecting the
columns of sequence QPIn
and sequence QPOut
. The respective left
columns show the input and output of the MA model, the respective
right colums show the input and output of the ARMA model:
>>> test("arma_v1_nonlinearity")
Click to see the table
Click to see the graph
-
class
hydpy.models.arma_v1.
Model
[source]¶ Bases:
hydpy.core.modeltools.AdHocModel
Rimo/Rido version of ARMA (arma_v1).
- The following “inlet update methods” are called in the given sequence at the beginning of each simulation step:
Pick_Q_V1
Update inflow.
- The following “run methods” are called in the given sequence during each simulation step:
Calc_QPIn_V1
Calculate the input discharge portions of the different response functions.Update_LogIn_V1
Refresh the input log sequence for the different MA processes.Calc_QMA_V1
Calculate the discharge responses of the different MA processes.Calc_QAR_V1
Calculate the discharge responses of the different AR processes.Calc_QPOut_V1
Calculate the ARMA results for the different response functions.Update_LogOut_V1
Refresh the log sequence for the different AR processes.Calc_QOut_V1
Sum up the results of the different response functions.
- The following “outlet update methods” are called in the given sequence at the end of each simulation step:
Pass_Q_V1
Update outflow.
-
class
hydpy.models.arma_v1.
ControlParameters
(master: hydpy.core.parametertools.Parameters, cls_fastaccess: Optional[Type[hydpy.core.parametertools.FastAccessParameter]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)¶ Bases:
hydpy.core.variabletools.SubVariables
[hydpy.core.parametertools.Parameters
,Parameter
,hydpy.core.parametertools.FastAccessParameter
]Control parameters of model arma_v1.
- The following classes are selected:
Responses()
Assigns different ARMA models to different discharge thresholds.
-
class
hydpy.models.arma_v1.
DerivedParameters
(master: hydpy.core.parametertools.Parameters, cls_fastaccess: Optional[Type[hydpy.core.parametertools.FastAccessParameter]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)¶ Bases:
hydpy.core.variabletools.SubVariables
[hydpy.core.parametertools.Parameters
,Parameter
,hydpy.core.parametertools.FastAccessParameter
]Derived parameters of model arma_v1.
- The following classes are selected:
Nmb()
Number of response functions [-].MaxQ()
Maximum discharge values of the respective ARMA models [m³/s].AR_Order()
Number of AR coefficients of the different responses [-].MA_Order()
Number of MA coefficients of the different responses [-].AR_Coefs()
AR coefficients of the different responses [-].MA_Coefs()
MA coefficients of the different responses [-].
-
class
hydpy.models.arma_v1.
FluxSequences
(master: hydpy.core.sequencetools.Sequences, cls_fastaccess: Optional[Type[FastAccessType]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)¶ Bases:
hydpy.core.sequencetools.OutputSequences
[FluxSequence
]Flux sequences of model arma_v1.
- The following classes are selected:
QIn()
Total inflow [m³/s].QPIn()
Inflow portions corresponding to the different thresholds [m³/s].QMA()
MA result for the different thresholds [m³/s].QAR()
AR result for the different thresholds [m³/s].QPOut()
Outflow portions corresponding to the different thresholds [m³/s].QOut()
Total outflow [m³/s].
-
class
hydpy.models.arma_v1.
InletSequences
(master: hydpy.core.sequencetools.Sequences, cls_fastaccess: Optional[Type[FastAccessType]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)¶ Bases:
hydpy.core.sequencetools.LinkSequences
[InletSequence
]Inlet sequences of model arma_v1.
- The following classes are selected:
Q()
Runoff [m³/s].
-
class
hydpy.models.arma_v1.
LogSequences
(master: hydpy.core.sequencetools.Sequences, cls_fastaccess: Optional[Type[FastAccessType]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)¶ Bases:
hydpy.core.sequencetools.ModelSequences
[LogSequence
,hydpy.core.variabletools.FastAccess
]Log sequences of model arma_v1.
-
class
hydpy.models.arma_v1.
OutletSequences
(master: hydpy.core.sequencetools.Sequences, cls_fastaccess: Optional[Type[FastAccessType]] = None, cymodel: Optional[hydpy.core.typingtools.CyModelProtocol] = None)¶ Bases:
hydpy.core.sequencetools.LinkSequences
[OutletSequence
]Outlet sequences of model arma_v1.
- The following classes are selected:
Q()
Runoff [m³/s].