HydPy-SW1D-LIAS/Sluice (submodel that extends HydPy-SW1D-LIAS with sluice functionalities)

The HydPy-SW1D model family member sw1d_lias_sluice extends the routing submodel sw1d_lias with simple sluice functionalities.

The main model sw1d_channel documentation explains sw1d_lias depth. Here, we limit the discussion to some of the additional features of sw1d_lias_sluice. Please also read the documentation on method Update_Discharge_V2, which shows how to define seasonal control schemes and additional and “closed gate” functionality, which helps to prevent source catchment from running dry during low flow periods.

Integration tests

Note

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

We create a test setting identical to the one of the sw1d_channel documentation, except replacing the sw1d_lias submodel at the central location with a sw1d_lias_sluice submodel:

>>> from hydpy import pub
>>> pub.timegrids = "2000-01-01 00:00", "2000-01-01 05:00", "5m"
>>> from hydpy.models.sw1d_channel import *
>>> parameterstep()
>>> nmbsegments(8)
>>> lengths = 2.0, 3.0, 2.0, 3.0, 2.0, 3.0, 2.0, 3.0
>>> for i, length_ in enumerate(lengths):
...     with model.add_storagemodel_v1("sw1d_storage", position=i):
...         length(length_)
...         with model.add_crosssection_v2("wq_trapeze"):
...             nmbtrapezes(1)
...             bottomlevels(5.0)
...             bottomwidths(5.0)
...             sideslopes(0.0)
>>> for i in range(1, nmbsegments.value):
...     lias = "sw1d_lias_sluice" if i == 4 else "sw1d_lias"
...     with model.add_routingmodel_v2(lias, position=i):
...         lengthupstream(2.0 if i % 2 else 3.0)
...         lengthdownstream(3.0 if i % 2 else 2.0)
...         stricklercoefficient(1.0/0.03)
...         timestepfactor(0.7)
...         diffusionfactor(0.2)
...         if i == 4:
...             bottomlowwaterthreshold(0.0)
...             upperlowwaterthreshold(0.0)
...             bottomhighwaterthreshold(5.0)
...             upperhighwaterthreshold(5.0)
...         with model.add_crosssection_v2("wq_trapeze"):
...             nmbtrapezes(1)
...             bottomlevels(5.0)
...             bottomwidths(5.0)
...             sideslopes(0.0)
>>> from hydpy import Element
>>> channel = Element("channel")
>>> channel.model = model
>>> from hydpy.core.testtools import IntegrationTest
>>> test = IntegrationTest(channel)
>>> test.plotting_options.axis1 = (factors.waterlevels,)
>>> def prepare_inits(hs):
...     if isinstance(hs, float):
...         hs = nmbsegments.value * [hs]
...     inits = []
...     for h, s in zip(hs, model.storagemodels):
...         length = s.parameters.control.length
...         c = s.crosssection.parameters.control
...         v = h * (c.bottomwidths[0] + h * c.sideslopes[0]) * length
...         inits.append((s.sequences.states.watervolume, v))
...     for r in model.routingmodels[1:-1]:
...         inits.append((r.sequences.states.discharge, 0.0))
...     test.inits = inits

LIAS comparison

We start with a close comparison with sw1d_lias by repeating the Zero inflow and outflow example. So, we neglect any inflows and outflows and set the same uneven water depths:

>>> prepare_inits(hs=[3.0, 3.0, 3.0, 3.0, 1.0, 1.0, 1.0, 1.0])

Due to the identical setting of all common parameters, the following results are identical to those of the Zero inflow and outflow example for the first four hours of the simulation period. The water levelling takes place by an unhindered downstream water movement. However, due to setting the additional parameters BottomHighWaterThreshold and UpperHighWaterThreshold to 5 m (the channel bottom), the sluice functionality is potentially active all the time, which is noticeable in the fifth hour. The excess water in the last four channel segments cannot flow back, so two different water levels (one above and one below the sluice) start to set in:

>>> conditions = test("sw1d_lias_sluice_lias_comparison", get_conditions="2000-01-01 00:00")
Click to see the table
Click to see the graph

There is no indication of an error in the water balance:

>>> from hydpy import round_
>>> round_(model.check_waterbalance(conditions))
0.0

Sharp targets

Next, we set the lower and the upper high water threshold to 6.5 m (corresponding to a water depth of 1.5 m) and reverse the initial water depths:

>>> model.routingmodels[4].parameters.control.upperhighwaterthreshold(6.5)
>>> model.routingmodels[4].parameters.control.bottomhighwaterthreshold(6.5)
>>> prepare_inits(hs=[1.0, 1.0, 1.0, 1.0, 3.0, 3.0, 3.0, 3.0])

The water should initially stream from the last to the first four segments until the upstream segments’ water levels reach 6.5 m. However, the finally reached water levels lie between 6.537 m and 6.544 m, and the third segment’s trajectory shows a strong sawtooth pattern caused by numerical problems:

>>> conditions = test("sw1d_lias_sluice_sharp_targets", get_conditions="2000-01-01 00:00")
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

Higher precision

One possible solution is increasing numerical precision (like in the Higher precision example), eventually accompanied by reducing numerical diffusion (like in the No additional diffusion example):

>>> for routingmodel in model.routingmodels.submodels[1:-1]:
...     routingmodel.parameters.control.timestepfactor(0.1)
...     routingmodel.parameters.control.diffusionfactor(0.0)

Despite the significant increase in computation time, some trajectories still appear a little unsmooth, and the reached water levels range from 6.504 m to 6.515 m, which is less of a numerical error than to due the physical effect of the water sloshing back and forth until all levels are equal:

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

Fuzzy targets

One might reach more satisfactory results by setting two different thresholds and, thus, a more fuzzy target water level. Here, we reduce the bottom threshold to 6.3 m:

>>> model.routingmodels[4].parameters.control.bottomhighwaterthreshold(6.3)
>>> model.routingmodels[4].parameters.control.upperhighwaterthreshold(6.5)

Also, we reset the initial time step and diffusion factors to reduce computation time:

>>> for routingmodel in model.routingmodels.submodels[1:-1]:
...     routingmodel.parameters.control.timestepfactor(0.7)
...     routingmodel.parameters.control.diffusionfactor(0.2)

Due to the introduced fuzziness, the third segment water level trajectory’s fluctuations disappear, and all of the first four segments’ final water levels exceed the upper threshold of 6.5 m by less than 3 mm:

>>> test("sw1d_lias_sluice_fuzzy_targets")
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.sw1d_lias_sluice.Model[source]

Bases: Main_CrossSectionModel_V2, RoutingModel_V2

HydPy-SW1D-LIAS/Sluice (submodel that extends HydPy-SW1D-LIAS with sluice functionalities).

The following interface methods are available to main models using the defined model as a submodel:
The following “additional methods” might be called by one or more of the other methods or are meant to be directly called by the user:
Users can hook submodels into the defined main model if they satisfy one of the following interfaces:
  • CrossSectionModel_V2 Interface for calculating discharge-related properties at a channel cross-section.

  • RoutingModel_V1 Interface for calculating the inflow into a channel.

  • RoutingModel_V2 Interface for calculating the discharge between two channel segments.

  • RoutingModel_V3 Interface for calculating the outflow of a channel.

  • StorageModel_V1 Interface for calculating the water amount stored in a single channel segment.

DOCNAME: DocName = ('SW1D-LIAS/Sluice', 'submodel that extends HydPy-SW1D-LIAS with sluice functionalities')
crosssection: SubmodelProperty[CrossSectionModel_V2]

Required submodel that complies with the following interface: CrossSectionModel_V2.

storagemodelupstream: modeltools.SubmodelProperty[StorageModel_V1]

Required reference to the neighbour storage model upstream.

storagemodelupstream_is_mainmodel
storagemodelupstream_typeid
storagemodeldownstream: modeltools.SubmodelProperty[StorageModel_V1]

Required reference to the neighbour storage model downstream.

storagemodeldownstream_is_mainmodel
storagemodeldownstream_typeid
routingmodelsupstream: modeltools.SubmodelsProperty[RoutingModel_V1 | RoutingModel_V2]

References to the neighbour routing models lying upstream.

routingmodelsdownstream: modeltools.SubmodelsProperty[RoutingModel_V2 | RoutingModel_V3]

References to the neighbour routing models lying downstream.

REUSABLE_METHODS: ClassVar[tuple[type[ReusableMethod], ...]] = ()
cymodel: CyModelProtocol | None
parameters: parametertools.Parameters
sequences: sequencetools.Sequences
masks: masktools.Masks
class hydpy.models.sw1d_lias_sluice.ControlParameters(master: Parameters, cls_fastaccess: type[FastAccessParameter] | None = None, cymodel: CyModelProtocol | None = None)

Bases: SubParameters

Control parameters of model sw1d_lias_sluice.

The following classes are selected:
  • LengthUpstream() The upstream channel segment’s length [km].

  • LengthDownstream() The downstream channel segment’s length [km].

  • StricklerCoefficient() The average Gauckler-Manning-Strickler coefficient [m^(1/3)/s].

  • TimeStepFactor() A factor for reducing the estimated computation time step to increase numerical stability [-].

  • DiffusionFactor() A factor for introducing numerical diffusion to increase numerical stability [-].

  • BottomLowWaterThreshold() Water level below which gates are fully closed to stop drainage during low flow periods [m].

  • UpperLowWaterThreshold() Water level below which gates are partly closed to reduce drainage during low flow periods [m].

  • BottomHighWaterThreshold() Water level above which gate operation is partly sluice-like to increase drainage during high flow periods [m].

  • UpperHighWaterThreshold() Water level above which gate operation is fully sluice-like to maximise drainage during high flow periods [m].

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

Bases: SubParameters

Derived parameters of model sw1d_lias_sluice.

The following classes are selected:
  • Seconds() The length of the actual simulation step size in seconds [s].

  • TOY() References the timeofyear index array provided by the instance of class Indexer available in module pub [-].

  • WeightUpstream() A weighting coefficient for interpolating the water level from the centroids of two adjacent segments to their shared edge [-].

  • LengthMin() The minimum length of the segments upstream and downstream of the relevant routing model [km].

  • LengthMean() The mean length of the segments upstream and downstream of the relevant routing model [km].

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

Bases: FactorSequences

Factor sequences of model sw1d_lias_sluice.

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

Bases: SubParameters

Fixed parameters of model sw1d_lias_sluice.

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

Bases: FluxSequences

Flux sequences of model sw1d_lias_sluice.

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

Bases: InletSequences

Inlet sequences of model sw1d_lias_sluice.

The following classes are selected:
  • LongQ() The longitudinal inflow into the first channel segment [m³/s].

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

Bases: OutletSequences

Outlet sequences of model sw1d_lias_sluice.

The following classes are selected:
  • LongQ() The longitudinal outflow of the last channel segment [m³/s].

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

Bases: StateSequences

State sequences of model sw1d_lias_sluice.

The following classes are selected: