Modelica API

Pumping Station

The Modelica library Deltares.HydraulicStructures.PumpingStation is an extension to the Deltares.ChannelFlow.Hydraulic library, which is part of the ChannelFlow library. It consists of the following components:

A pump model with a QHP (discharge, head, power) relationship, to be used for optimization of e.g. costs. It extends Deltares.ChannelFlow.Hydraulic.Structures.Pump
Quadratic resistance.
Encapsulating class for Pump and Resistance objects.


Pump and Resistance objects should always be placed inside a PumpingStation object.


class Pump : Deltares::ChannelFlow::Hydraulic::Structures::Pump

Represents a single pump object. Because the power of the pump is seldom a linear function of Q and H, this class is wrapped by the Python API’s Pump which turns the power equation specified by power_coefficients into a set of inequality constraints:

\[\begin{split}\begin{aligned} \ P &\ge C_{1,1} + C_{1,2} Q + \ldots \\[5pt] \lim_{Q \to 0} P &= 0 \ \end{aligned}\end{split}\]

With minimization of pumping costs (i.e. power), the optimization results will satisfy the first inequality constraint as if it was an equality constraint.

Real power_coefficients[:, :]

The power coefficients describe the relationship between the discharge, head and power. For example, one can consider a fit of the pump power of the general form:

\[P = C_{1,1} + C_{1,2} Q + C_{2,1} H + C_{2,2} Q H + C_{1,3} Q^2 + \ldots\]

The power coefficients matrix corresponds to the coefficients C in the equation above. To guarantee that optimization finds a good and stable solution, we require the coefficients of this polynomial to be chosen such that the polynomial is convex over the entire domain.


Strictly speaking it would only have to be convex over the (automatically) extended working area domain, the size of which is not always known before run-time.

Real working_area[:, :, :]

The working area array describes the polynomials bounding the convex set of allowed Q-H coordinates. These polynomials typically arise from one of the following properties:

  • Q-H curve at minimum pump speed
  • Q-H curve at maximum pump speed
  • Minimum required efficiency (e.g. 50%)
  • Minimum and/or maximum input power constraint
  • Cavitation constraints
  • NPSH constraints

The first coordinate of the array is the polynomial number. For example, working_area[1, :, :] would describe the first working area polynomial. The order of Q and H coefficients is the same as in power_coefficients.

Real working_area_direction[:]

The polynomials in working_area describe the polynomials, but do not yet indicate what side of this polynomial the Q-H combination has to be on. So for each of the polynomials in the working area we have to specify whether the expression should evaluate to a positive expression (=1), or a negative expression (=-1).


It may become unnecessary to specify this in the future, if it is possible to figure out a way to determine this automatically based on the polynomials and their crossing points.

Integer head_option = 0

What head to use for the pump head. This can be one of the following three options:

The upstream head
The differential head (i.e. downstream head minus upstream head)
The downstream head.
Modelica::SIunits::Duration minimum_on = 0.0

The minimum amount of time in seconds a pump needs to be on before allowed to switch off again. This applies to all pumps in this pumping station.


Only multiples of the (equidistant) time step are allowed.

Modelica::SIunits::Duration minimum_off = 0.0

The minimum amount of time in seconds a pump needs to be off before allowed to switch on again. This applies to all pumps in this pumping station.


Only multiples of the (equidistant) time step are allowed.

Modelica::SIunits::Energy start_up_energy = 0.0

The energy needed to start a pump. This will be multiplied with the energy price to calculate the costs.

Real start_up_cost = 0.0

Costs in e.g. EUR or kg CO2 associated with a pump start up. Many pump switches could for example mean the pump life is shortened, or that more maintenance is needed. These could then be expressed in monetary value, and associated with pump start up.


Make sure that the units of this value are of the same units as start_up_energy times the energy price.

Modelica::SIunits::Energy shut_down_energy = 0.0

Energy needed to shut down a pump. See equivalent parameter for pump start start_up_energy for more information.

Real shut_down_cost = 0.0

Cost associated with a pump shutdown. See equivalent parameter for pump start start_up_cost for more information.


class Resistance : Deltares::ChannelFlow::Internal::HQTwoPort

Represents a single quadratic resistance object relating the head loss to the discharge:

\[dH = C \cdot Q^2\]

Because a non-linear equality constraint is not allowed in convex optimization, this class is wrapped by the Python API’s Resistance which turns it into two inequality constraints:

\[\begin{split}\begin{aligned} \ dH &\ge C \cdot Q^2 \\[5pt] \lim_{Q \to 0} dH &= 0 \ \end{aligned}\end{split}\]

With minimization of pumping costs (i.e. power), the optimization results will satisfy the first inequality constraint as if it was an equality constraint, provided the power relationship of every pump is monotonically increasing with H.


Only positive flow is allowed (read: enforced).

Real C = 0.0


class PumpingStation : Deltares::ChannelFlow::Internal::HQTwoPort

Represents a pumping station object, containing one or more Pump or Resistance objects.

Integer n_pumps

The number of pumps contained in the pumping station. This is necessary to enforce the right size of e.g. the pump_switching_matrix.

Integer pump_switching_matrix[n_pumps, n_pumps] = -999

Together with pump_switching_constraints describes which pumps are allowed to be on at the same time. The default value of -999 will make Python fill it with the default matrix. This default matrix implies that the second pump can only be on when the first pump is on, that the third pump can only be on when the second pump is on, etc.

In matrix multiplication form

\[b[:,1] \le A \cdot x \le b[:,2]\]

with \(A\) the pump_switching_matrix, \(b\) the pump_switching_constraints, and \(x\) the vector of pump statuses:

\[\begin{split}x = \left[\begin{array}{cc}S_1 \\ S_2 \\ S_3 \\ \vdots \end{array}\right]\end{split}\]

where \(S_1\) is the status of pump 1 (on = 1, off = 0).

So the default matrix, where a pump being on requires all lower numbered pumps to be on as well, can be expressed as follows:

\[\begin{split}A = \left[\begin{array}{ccc}0 & 0 & 0\\1 & -1 & 0\\1 & 1 & -2\end{array}\right]\end{split}\]

with pump_switching_constraints equal to:

\[\begin{split}b = \left[\begin{array}{cc}-\infty & \infty\\0 & \infty\\0 & \infty\end{array}\right]\end{split}\]

To allow all pumps to switch independently from each other, it is sufficient to set the coefficient matrix to all zeros (e.g. pump_switching_matrix = fill(0, n_pumps, n_pumps)). For rows in the matrix not containing any non- zero values, the accompanying constraints are not applied.


Only square matrices allowed, i.e. a single constraint per pump.

Integer pump_switching_constraints[n_pumps, 2]

See discussion in pump_switching_matrix.


class Weir : Deltares::ChannelFlow::Internal::HQTwoPort

Represents a general movable-crest weir object described by the conventional weir equation (see e.g. Swamee, Prabhata K. “Generalized rectangular weir equations.” Journal of Hydraulic Engineering 114.8 (1988): 945-949.):

\[Q = \frac{2}{3} C B \sqrt{2g} \left( H - H_w \right)^{1.5}\]

where Q is the discharge of the weir, C is the weir discharge coefficient (very well approximated by 0.61), B is the width of the weir, g is the acceleration of gravity, H is the water level, and \(H_w\) is the level of the movable weir crest. The equation assumes critical flow over the weir crest.

Modelica::SIunits::Length width

The physical width of the weir.

Modelica::SIunits::VolumeFlowRate q_min

The minimal possible discharge on this weir. It can be known from the physical characteristics of the system. The linear approximation works the best if this is set as tight as possible. It is allowed to set it to zero.

Modelica::SIunits::VolumeFlowRate q_max

The maximum physically possible flow over the weir. It should be set as tight as possible

Modelica::SIunits::Length hw_min

The minimal possible crest elevation.

Modelica::SIunits::Length hw_max

The maximum possible crest elevation.

Real weir_coef = 0.61

The discharge coefficient of the weir. Typically the default value of 0.61.