Skip to content

Storage

At a glance…

Storage nodes represents lakes, weirs, dams, or other reservoirs. Upstream flows accumulate in the storage and flows are passed downstream either via a spillway or regulated outlet. Each storage has 1 spillway, which overflows according to a level-flow relationship when the level of water in the storage exceeds the spillway crest. Regulated outlets allow for regulated downstream releases. Water in storages may be subject to evaporation, rainfall, and seepage.

[node.my_storage_node]
type = storage
loc = 20, 30
rain = data.climate_data_csv.by_name.rainfall
evap = data.climate_data_csv.by_name.mpot
seep = 0.82
dimensions = Level [m], Volume [ML], Area [km2], Spill [ML],
             80.0,      0,           0,          0,
             90.0,      1000,        2,          0,
             90.1,      1010,        2,          1e8,
             90.2,      1020,        2,          1e8
ds_1 = my_other_node

Node properties

Property Description
[node.?] (compulsory) Start of node declaration. This says we are creating a node, and also defines the name of the node. Node naming conventions are discussed at . Example: [node.my_inflow_node]
type (compulsory) The node type, which is “storage” in this case. type = storage
loc (compulsory) The location of the node in cartesian coordinates. Example: loc = 20, 30
rain (optional) Rainfall data [mm]. Default is zero. Example: rain = data.rex_rain_csv.by_name.value
evap (optional) Potential evapotranspiration data [mm]. Default is zero. Example: evap = data.rex_mpot_csv.by_name.value
seep (optional) Seepage rate [mm]. Default is zero. Example: seep = 0.82
initial_volume (optional) Initial volume [ML]. Default is zero. Example: initial_volume = 14000
order_through (optional) Optional boolean flag changing the ordering behaviour of the node such that downstream orders are propagated upstream verbatim. This functionality is explained in detail further down this page. Default is false. Example: order_through = true
target_level (optional) Optional target level [m] which causes this storage node to generate orders to operate the storage near the target level. This functionality is explained in detail below. This feature cannot be used in combination with order_through. Example: target_level = if(sim.month>8, 8.0, 9.5)
pond_demand (optional) Optional on-pond demand [ML]. Example: pond_demand = 15.0 * data.patterns_csv.by_name.amenities
dimensions (compulsory) A tabulated list of values: level (m), volume (ML), area (km2), spill (ML/timestep). See Table parameters to find out more about how table parameter types work in Kalix. Example: dimensions = 90, 0, 0, 0, 91, 100, 1, 0, 91.1, 101, 1, 1e8, 92, 102, 1, 1e8
ds_1_outlet, ds_2_outlet, ds_3_outlet, ds_4_outlet (optional) This allows you to specify the properties of outlets on each of the corresponding links (ds_1, ds_2, etc). At the moment just one outlet property is supported, being the minimum operating level (MOL) of the outlet. Notes: (1) Orders on ds_1 may be partly or fully met by unregulated spills. (2) There are no spills on the other links. (3) If outlet properties are not defined the outlet on this link is assumed to be active and unlimited limit. Example: ds_1_outlet = 81.1
ds_1 (optional) Name of the downstream node. This property defines a downstream link. Inflow nodes may only have 1 downstream link. Example: ds_1 = my_other_node
ds_2, ds_3, ds_4 (optional) Additional link used to represent regulated flow pathways separate to the main downstream link. ds_2 = tws_pipline

Results associated with this node

Result Description
dsflow Downstream flow [ML]
usflow Upstream flow [ML]
rain Input rainfall [mm]
evap Input evapotranspiration [mm]
seep Input seepage [mm]
rain_vol Rainfall volume [ML]
evap_vol Evaporation volume [ML]
seep_vol Seepage volume [ML]
pond_demand On-pond demand [ML].
pond_diversion Diversion associated with the pond demand [ML]
ds_1, ds_2, etc Downstream flow [ML] on link ds_1 (outlet + spill), ds_2 (outlet),
ds_1_order Order on link ds_1 [ML] (also available for other links)
ds_1_spill Flow over the spillway to ds_1 [ML] (also available for other links, but = 0)
ds_1_outlet Flow through the outlet to ds_1 [ML] (also available for other links)
volume Volume of water in the storage at the end of the timestep [ML]
level Level of water in the storage at the end of the timestep [m]
area Area of the water surface at the end of the timestep [km2]

How the node works

Solver

Storages are simulated using the Backward Euler method. The defining characteristic of this method is that the rates-of-change during the timestep are functions of the end-of-timestep state. That is to say, the storage volume is determined such that the fluxes are consistent with the storage volume vi (and area ai and level li) at the end of the timestep:

  • spill → si=s(li)

  • pond evaporation → ei=Mlake i×ai

  • pond rainfall → ri=Pi×ai

  • seepage → wi=Wi×ai

  • inflow → qin,i=previously calculated

  • regulated releases → qout,i=previously calculated

Mass balance over the timestep is:

Vi=Vi−1−si−ei+ri+qin,i−qout,i

Storages ordering upstream

The default behaviour of storages is to NOT propagate any orders upstream. However, storages can be configured to order upstream in either of two ways: (1) using the target_level, or (2) using the order_through property.

Target level

A storage configured with a target_level will operate to satisfy downstream orders to the best of its ability (same as without a target level), but while doing so will also generate its own orders requesting water from upstream as needed to bring its level up to the specified target. In practice, operating targets help operators ensure that sufficient water is available where needed for smooth operation. Target_level serves the same purpose in the model.

Ordering to meet a target_level is imperfect. In the example above, ‘kings_weir’ may not be able to precisely achieve a defined target level because:

  • lag on ‘evolution_ck’ could mean water ordered from ‘muir_lake’ does not arrive immediately, and

  • the target level may have changed in that time,

  • rainfall, evaporation, and seepage may have happened in that time,

  • user1’ and ‘user2’ may have placed orders to ‘kings_weir’ which should be released immediately.

Storages using the target_level property calculate orders as follows:

Oupstream=max(0,Vtarget−Vestimated future)

The term Vtarget is evaluated each timestep and is what we are trying to achieve by sending the current order. This is the target we are hoping to achieve when our order arrives, i.e. after n_timesteps = upstream order travel time. The term Vestimated future is an estimate of the future storage volume after n_timesteps if there were no inflows. Kalix uses a simple and conservative estimate of this:

Vestimated future=Vnow−qout known+qin expected=Vnow−Ods today+Oupstream enroute

Order through

When a storage is set with order_through = true, the storage will pass orders from the downstream link(s) to the upstream link(s) verbatim. Doing this means that downstream orders are really being satisfied from the upstream storage. This may change the ordering travel time perceived by regulated users.

The storage with order_through = true operates to release orders for downstream users as they come through. The volume in such a storage depends on the balance of inflows and outflows, and proper functioning may may depend on unregulated flows to cover losses and delivery inefficiencies.


See also

Inverted Pyramid Storage Tables

References

None.