Reservoir API

Methods of the ReservoirModel are listed below. Schemes can be applied by overwriting the ReservoirModel.apply_schemes() method.

Available schemes include:

An overview of all schemes is given below.

class rtctools_simulation.reservoir._variables.InputVar(value)[source]

Reservoir model input variable.

H_OBSERVED = 'H_observed'

observed water height (m)

Q_EVAP = 'mm_evaporation_per_hour'

evaporation (mm/hour)

Q_IN = 'Q_in'

inflow (m^3/s)

Q_OUT = 'Q_out_from_input'

outflow (m^3/s)

Q_RAIN = 'mm_rain_per_hour'

rain (mm/hour)

Q_SLUICE = 'Q_sluice'

sluice outflow (m^3/s)

Q_TURBINE = 'Q_turbine'

turbine outflow (m^3/s)

class rtctools_simulation.reservoir._variables.OutputVar(value)[source]

Reservoir model output variable.

HEIGHT = 'H'

water height (m)

Q_EVAP = 'Q_evap'

evaporation (m^3/s)

Q_OUT = 'Q_out'

outflow (m^3/s)

Q_RAIN = 'Q_rain'

rain (m^3/s)

Q_SPILL = 'Q_spill'

spill (m^3/s)

VOLUME = 'V'

water volume (m^3)

rtctools_simulation.reservoir._variables.QOutControlVar

Reservoir outflow control variables.

alias of Literal[Q_OUT, Q_TURBINE, Q_SLUICE]

class rtctools_simulation.reservoir.model.ReservoirModel(config: ModelConfig, use_default_model=True, **kwargs)[source]

Class for a reservoir model.

adjust_rulecurve(periods: int, h_var: str = 'H_observed', application_time: datetime64 | None = None, extrapolate_trend_linear: bool | None = False)[source]

Adjusts the rulecurve based on deviations compared to H_observed.

This method can be applied inside ReservoirModel.pre().

Parameters:
  • periods – The number of periods over which to calculate the moving average.

  • h_var – The name of the elevation timeseries to adjust the rulecurve.

  • application_time – Optional. Time at which to start applying the correction.

  • extrapolate_trend_linear – Bool. Option to extrapolate a trend in the deviations to the rulecurve.

The function overwrites the required timeseries of ‘rule_curve’, and should be called in self.apply_schemes()

apply_adjust()[source]

Scheme to adjust simulated volume to observed volume.

This scheme can be applied inside ReservoirModel.apply_schemes(). Observed pool elevations (H_observed) can be provided to the model, internally these are converted to observed volumes (V_observed) via the lookup table h_from_v. When applying this scheme, V is set to V_observed and a corrected version of the outflow, Q_out_corrected, is calculated in order to preserve the mass balance.

apply_fillspill() float[source]

Determines the outflow from the reservoir based on the inflow and minimum required outflow (downstream water demands or power generation objectives), as well as reservoir characteristics of maximum discharge of the dam facilities or operational rules (e.g. maximum generator discharge, maximum sluice discharge). Requires preconfigured parameters for [“Spillway_H”, “Reservoir_Htarget”, “Reservoir_Qmax”, “Reservoir_Qmin”] in rtcParameterConfig.xml

apply_minq(*, h_target: float | Iterable[float] | str, h_min: float = 0, h_max: float | None = None, q_flood: float | None = 0, q_max: float | None = inf, minimize_peak_q_weight: float = 0.5, h_target_weight: float = 0.5, recalculate: bool = False)[source]

Determine and use outflow with a minimal peak.

The outflow is minimized for the given optimization parameters. If recalculate is True, the minimzed outflow will be recalculated. This is useful if some of the parameters like h_target have changed.

The model strikes a balance between minimizing outflow and meeting the target elevation. Weights can be provided to adjust this balance. By default both are given the same weight. It is recommened that both weights sum to 1.

Parameters:
  • h_target – float, Iterable[float], str. Target elevation. Can be the name of a timeseries.

  • h_min – float, optional. Minimum elevation. Default is 0.

  • h_max – float, optional. Maximum elevation. Default is no None (no maximum elevation).

  • q_flood – float, optional. Flood discharge. When computing the peak outflow, values below the flood discharge are ignored.

  • q_max – float, optional. Maximum discharge. Default is infinity (no maximum discharge). It is recommended to supply this parameter when using h_target to prevent unrealistically high outflows. This parameter can for example be set to Reservoir_Qmax (used in ReservoirModel.apply_rulecurve()).

  • minimize_peak_q_weight – float, optional. Weight for minimizing peak outflow. Default is 0.5. Can be adjusted to give more or less importance to minimizing peak outflow. A higher value gives more importance to minimizing peak outflow. It is recommended that both weights sum to 1 - otherwise variable scaling will be affected.

  • h_target_weight – float, optional. Weight for meeting the target elevation. Default is 0.5. Can be adjusted to give more or less importance to meeting the target elevation. A higher value gives more importance to meeting the target elevation. It is recommended that both weights sum to 1 - otherwise variable scaling will be affected.

  • recalculate – bool, optional. If True, the outflow will be recalculated. Default is False.

apply_passflow()[source]

Scheme to let the outflow be the same as the inflow.

This scheme can be applied inside ReservoirModel.apply_schemes().

Note

This scheme cannot be used in combination with ReservoirModel.apply_poolq(), or ReservoirModel.set_q() when the target variable is Q_out.

apply_poolq()[source]

Scheme to let the outflow be determined by a lookup table with name “qout_from_v”.

This scheme can be applied inside ReservoirModel.apply_schemes().

It is possible to impose a dependence on days using the “qout_from_v” lookup table If this is not needed then the “day” column should be constant (e.g. = 1) Otherwise a 2D lookup table is created by linear interpolation between days, Q_out and V.

Note

This scheme cannot be used in combination with ReservoirModel.apply_passflow(), or ReservoirModel.set_q() when the target variable is Q_out.

apply_rulecurve(outflow: Literal[InputVar.Q_OUT, InputVar.Q_TURBINE, InputVar.Q_SLUICE] = InputVar.Q_TURBINE, ignore_inflows: bool = False, enforce_qmin: bool = False)[source]

Scheme to set the outflow of the reservoir in order to reach a rulecurve.

This scheme can be applied inside ReservoirModel.apply_schemes(). This scheme uses the lookup table v_from_h and requires the following parameters from the rtcParameterConfig.xml file.

  • Reservoir_Qmax: Upper limiting discharge while blending pool elevation (m³/s)

  • rule_curve_blend: Number of timesteps over which to bring the pool back to the scheduled elevation.

The user must also provide a timeseries with the name rule_curve. This contains the water level target for each timestep.

Parameters:
  • outflowQOutControlVar (default: Q_TURBINE) outflow variable that is modified to reach the rulecurve.

  • ignore_inflows – bool (default: False) Whether to ignore the inflow, and solely use current volume difference.

  • enforce_qmin – bool (default: False) When True, enforces a minimum discharge floor on the computed rule curve discharge. The floor is the feasible minimum outflow as computed by get_feasible_qmin(), which combines policy-based and physical constraints. Requires Reservoir_Qmin in the parameter config (raises ValueError if missing). Optional parameters Reservoir_Hdead and Reservoir_Hbuffer control the linear reduction behavior near dead storage. See get_feasible_qmin() for details.

apply_spillway()[source]

Scheme to enable water to spill from the reservoir.

This scheme can be applied inside ReservoirModel.apply_schemes(). This scheme ensures that the spill “Q_spill” is computed from the elevation “H” using a lookuptable qspill_from_h.

calculate_cumulative_inflows()[source]

Calculate the cumulative inflows over the entire simulation period.

This can be called in pre. Reults are saved to the timeseries cumulative_inflows.

calculate_output_variables()[source]

Calculate output variables.

This method is called after the simulation has finished. The user can implement this method to calculate additional output variables.

calculate_rule_curve_deviation(h_var: str = 'H_observed', periods: int = 1, inflows: ndarray | None = None, max_inflow: float = inf, maximum_difference: float = inf)[source]

Calculate the moving average between the rule curve and a chosen elevation timeseries.

This method can be applied inside ReservoirModel.pre() is calculating deviations with input timeseries.

It can be applied in the ReservoirModel.calculate_output_variables() method to calculate deviations with the simulated timeseries.

This method calculates the moving average between the rule curve and the simulated elevations over a specified number of periods. It takes the following parameters:

Parameters:
  • h_var – The name of the elevation timeseries to compare with the rule curve. Default is “H_observed”.

  • periods – The number of periods over which to calculate the moving average.

  • inflows – Optional. The inflows to the reservoir. If provided, the moving average will be calculated only for the periods with non-zero inflows.

  • max_inflow – Optional. The maximum inflow allowed while calculating a moving average. Default is infinity, required if q_max is set.

  • maximum_difference – Optional. The maximum allowable difference between the rule curve and the observed elevations.

Note

The rule curve timeseries must be present in the timeseries import. The results are stored in the timeseries “rule_curve_deviation_<h_var>”.

calculate_single_cumulative_inflow(start_time: int = None, end_time: int = None)[source]

Calculate the cumulative inflow over a specified time period. The default behaviour is to consider the period up to and including the current timestep.

Parameters:
  • start_time – The starting timestep index of the period to sum over.

  • end_time – The ending timestep index of the period to sum over.

Returns:

The sum of inflows over the specified time period.

find_maxq(discharge_relation: str, solve_guess: float | None = nan)[source]

Utility to calculate the theoretical maximum discharge out of the reservoir. Supports four different methods for ‘discharge_relation’.

Parameters:
  • discharge_relation

    str The method used to calculate the maximum possible discharge maxq, options are

    • ’Elevation_Qmax_LUT’: maxq based on a lookup table describing maximum discharge as a function of elevation. Requires lookup table qmax_from_h.

    • ’Spillway’: maxq based on spillway Q/H + fixed Qmax. Requires parameter ‘Reservoir_Qmax’, as well as lookup_table ‘qspill_from_h’.

    • ’Fixed’: maxq based on fixed discharge only. Requires parameter ‘Reservoir_Qmax’.

    • ’Tailwater’: maxq is influenced by tailwater. Three lookup tables are required: qspill_from_h (spillway lookup table), qnotspill_from_dh (head vs (Qout-Qspill) lookup table) and qtw_from_tw (tailwater elevation vs discharge curve). maxq is calculated by determining Qspill based on the simulated elvation, and then using a solver to determine the intersection of the remaining lookup tables using the function _find_maxq_tailwater.

  • solve_guess – Optional[float] (default: np.nan) Initial guess for the solver when using the ‘Tailwater’ method. Defaults to current reservoir elevation in the supporting function ReservoirModel._find_maxq_tailwater() when it is np.nan.

This utility can be applied inside ReservoirModel.apply_schemes().

get_current_datetime() datetime[source]

Get the current datetime.

Returns:

the current time in datetime format.

get_current_time() int[source]

Get the current time (in seconds).

Returns:

the current time (in seconds).

get_feasible_qmin() float[source]

Calculate feasible minimum outflow based on current reservoir state.

Combines two constraints:

  1. Policy constraint: Qmin reduces linearly between Reservoir_Hbuffer and Reservoir_Hdead. Override _get_policy_qmin() for custom reduction schemes.

  2. Physical constraint: Cannot release more than available above dead storage. Based on mass balance.

Returns the lesser of policy and physical limits, guaranteeing feasibility.

Required parameters in rtcParameterConfig.xml:

  • Reservoir_Qmin: Full minimum outflow (m³/s) when above Reservoir_Hbuffer

Optional parameters:

  • Reservoir_Hdead: Dead storage elevation (m). Default: 0.

  • Reservoir_Hbuffer: Elevation where Qmin reduction begins (m). Must be >= Reservoir_Hdead. Default: Reservoir_Hdead.

Returns:

Feasible minimum outflow (m³/s), guaranteed achievable.

Return type:

float

Example usage:

# Preferred: use enforce_qmin in apply_rulecurve
def apply_schemes(self):
    self.apply_rulecurve(enforce_qmin=True)

# Advanced: standalone usage for custom logic
def apply_schemes(self):
    self.apply_rulecurve()
    q_min = self.get_feasible_qmin()
    # ... custom logic with q_min ...
get_flood_flag(q_out_daily_average: float, flood_elevation: float)[source]

Preprocessing step which determines and returns a flag for flooding. Can be called during pre.

Indicative elevations are calculated using inflows (Q_in) and averge daily outflows. If any indicative elevation is above the flood elevation, a the flood flag is set to True.

Parameters:
  • Q_out_daily_average – The average outflow over a 24 hour period (m^3/s).

  • flood_elevation – The elevation above which flooding occurs (m).

Returns:

A boolean flag indicating whether flooding occurs (True) or not (False).

get_output_variables()[source]

Method to get, and extend output variables

This method gets all output variables of the reservoir model, and extends the output to also include input variables like “Q_in” and “Q_turbine” such that they appear in the timeseries_export.xml.

get_var(name: str) float[source]

Get the value of a given variable at the current time.

Parameters:

var – name of the variable.

Returns:

value of the given variable.

include_evaporation()[source]

Scheme to include the effect of evaporation on the reservoir volume.

This scheme can be applied inside ReservoirModel.apply_schemes(). This scheme computes

Q_evap = Area * mm_evaporation_per_hour / 3600 / 1000 * include_evaporation.

This is then treated in the mass balance of the reservoir

der(V) = Q_in - Q_out + Q_rain - Q_evap.

include_rain()[source]

Scheme to include the effect of rainfall on the reservoir volume.

This scheme can be applied inside ReservoirModel.apply_schemes(). This scheme computes

Q_rain = max_reservoir_area * mm_rain_per_hour / 3600 / 1000 * include_rain.

This is then treated in the mass balance of the reservoir

der(V) = Q_in - Q_out + Q_rain - Q_evap.

Note

To include rainfall, make sure to set the max_reservoir_area parameter.

include_rainevap()[source]

Scheme to include the effect of both rainfall and evaporation on the reservoir volume.

This scheme can be applied inside ReservoirModel.apply_schemes(). This scheme implements both ReservoirModel.include_rain() and ReservoirModel.include_evaporation().

pre(*args, **kwargs)[source]

This method can be overwritten to perform any pre-processing before the simulation begins.

Note

Be careful if you choose to overwrite this method as default values have been carefully chosen to select the correct default schemes.

set_q(target_variable: Literal[InputVar.Q_OUT, InputVar.Q_TURBINE, InputVar.Q_SLUICE] = InputVar.Q_TURBINE, input_type: str = 'timeseries', input_data: str | float | list[float] = None, apply_func: str = 'MEAN', timestep: int = None, nan_option: str = None)[source]

Scheme to set one of the input or output discharges to a given value, or a value determined from an input list.

This scheme can be applied inside ReservoirModel.apply_schemes().

Note

This scheme cannot be used in combination with ReservoirModel.apply_poolq(), or ReservoirModel.apply_passflow() if the target variable is Q_out.

Parameters:
  • target_variableQOutControlVar (default: Q_TURBINE) The variable that is to be set. Needs to be an internal variable, limited to discharges.

  • input_type – str (default: ‘timeseries’) The type of target data. Either ‘timeseries’ or ‘parameter’. If it is a timeseries, the timeseries is assumed to have a regular time interval.

  • input_data – str | float | list[float] (default: None) Single value or a list of values for each time step to set the target. It can also be a name of a parameter or input variable.

  • apply_func

    str (default: ‘MEAN’) Function that is used to find the fixed_value if input_type = ‘timeseries’.

    • ’MEAN’ (default): Finds the average value, excluding nan-values.

    • ’MIN’: Finds the minimum value, excluding nan-values.

    • ’MAX’: Finds the maximum value, excluding nan-values.

    • ’INST’: Finds the value marked by the corresponding timestep ‘t’. If the selected value is NaN, nan_option determines the procedure to find a valid value.

  • timestep – int (default: None) The timestep at which the input data should be read at if input_type = ‘timeseries’, the default is the current timestep of the simulation run.

  • nan_option

    str (default: None) the user can indicate the action to be take if missing values are found. Usable in combination with input_type = ‘timeseries’ and apply_func = ‘INST’.

    • ’MEAN’: It will take the mean of the timeseries excluding nans.

    • ’PREV’: It attempts to find the closest previous valid data point.

    • ’NEXT’: It attempts to find the closest next valid data point.

    • ’CLOSEST’: It attempts to find the closest valid data point, either backwards or forward. If same distance, take average.

    • ’INTERP’: Interpolates linearly between the closest forward and backward data points.