# Constraints

## Constraint Templates

Constraint templates help simplify data wrangling across multiple optimization formulations by providing an abstraction layer between the network data and network constraint definitions. Each constraint template's job is to extract the required parameters from a given network data structure and pass the data as arguments to the optimization formulation. These templates should be defined over `AbstractWaterModel`

and should not refer to model variables. For more details, see the files `core/constraint_template.jl`

and `core/constraint.jl`

. Here, `core/constraint_template.jl`

provides higher-level constraint interfaces by processing network data and calling methods defined in `core/constraint.jl`

.

## Nodal Constraints

`WaterModels.constraint_flow_conservation`

— Function```
constraint_flow_conservation(
wm::AbstractWaterModel,
n::Int,
i::Int,
pipe_fr::Array{Int,1},
pipe_to::Array{Int,1},
des_pipe_fr::Array{Int,1},
des_pipe_to::Array{Int,1},
pump_fr::Array{Int,1},
pump_to::Array{Int,1},
regulator_fr::Array{Int,1},
regulator_to::Array{Int,1},
short_pipe_fr::Array{Int,1},
short_pipe_to::Array{Int,1},
valve_fr::Array{Int,1},
valve_to::Array{Int,1},
reservoirs::Array{Int,1},
tanks::Array{Int,1},
dispatchable_demands::Array{Int,1},
fixed_demand::Float64
)
```

Adds a constraint that ensures volumetric flow rate (and thus mass) is conserved at node `i`

and subnetwork (or time) index `n`

in the network. Here, `pipe_fr`

, `pipe_to`

, etc., are components that are directed *from* or *to* node `i`

, respectively. Additionally, `reservoirs`

, `tanks`

, and `dispatchable_demands`

are node-attached components that variably contribute to nodal inflow and outflow at node `i`

. Finally, `fixed_demand`

is the fixed amount of flow demanded at node `i`

, which may be negative *or* nonnegative.

```
constraint_flow_conservation(
wm::AbstractWaterModel,
i::Int;
nw::Int=nw_id_default
)
```

Constraint template to add constraints that ensure volumetric flow rate (and thus mass) is conserved at node `i`

and subnetwork (or time) index `nw`

in the network. Here, `wm`

is the WaterModels object.

`WaterModels.constraint_node_directionality`

— Function```
constraint_node_directionality(
wm::AbstractWaterModel,
i::Int;
nw::Int=nw_id_default
)
```

Constraint template to add direction-based constraints (`constraint_sink_directionality`

, `constraint_source_directionality`

, or `constraint_intermediate_directionality`

) when appropriate. Here, `wm`

is the WaterModels object, `i`

is the index of the node for which the constraints will be added, if applicable, and `nw`

is the subnetwork (or time) index.

`WaterModels.constraint_sink_directionality`

— Function```
constraint_sink_directionality(
wm::AbstractNCModel,
n::Int,
i::Int,
pipe_fr::Array{Int,1},
pipe_to::Array{Int,1},
des_pipe_fr::Array{Int,1},
des_pipe_to::Array{Int,1},
pump_fr::Array{Int,1},
pump_to::Array{Int,1},
regulator_fr::Array{Int,1},
regulator_to::Array{Int,1},
short_pipe_fr::Array{Int,1},
short_pipe_to::Array{Int,1},
valve_fr::Array{Int,1},
valve_to::Array{Int,1}
)
```

Currently does nothing for models of type `AbstractNCModel`

. Here, `wm`

is the WaterModels object; `n`

is the subnetwork (time) index; `i`

is the index of the node; and `pipe_fr`

, `pipe_to`

, etc., are indices of node-connecting components that are directed *from* or *to* node `i`

, respectively.

```
constraint_sink_directionality(
wm::AbstractNCDModel,
n::Int,
i::Int,
pipe_fr::Array{Int,1},
pipe_to::Array{Int,1},
des_pipe_fr::Array{Int,1},
des_pipe_to::Array{Int,1},
pump_fr::Array{Int,1},
pump_to::Array{Int,1},
regulator_fr::Array{Int,1},
regulator_to::Array{Int,1},
short_pipe_fr::Array{Int,1},
short_pipe_to::Array{Int,1},
valve_fr::Array{Int,1},
valve_to::Array{Int,1}
)
```

Adds a constraint that ensures at least one flow direction variable implies the transport of water *to* (i.e., into) a node that has flow demands (e.g., a node with positive fixed demands). Here, `n`

is the subnetwork (time) index; `i`

is the index of the node; and `pipe_fr`

, `pipe_to`

, etc., are indices of node- connecting components that are directed *from* or *to* node `i`

, respectively.

`WaterModels.constraint_source_directionality`

— Function```
constraint_source_directionality(
wm::AbstractNCModel,
n::Int,
i::Int,
pipe_fr::Array{Int,1},
pipe_to::Array{Int,1},
des_pipe_fr::Array{Int,1},
des_pipe_to::Array{Int,1},
pump_fr::Array{Int,1},
pump_to::Array{Int,1},
regulator_fr::Array{Int,1},
regulator_to::Array{Int,1},
short_pipe_fr::Array{Int,1},
short_pipe_to::Array{Int,1},
valve_fr::Array{Int,1},
valve_to::Array{Int,1}
)
```

Currently does nothing for models of type `AbstractNCModel`

. Here, `wm`

is the WaterModels object; `n`

is the subnetwork (time) index; `i`

is the index of the node; and `pipe_fr`

, `pipe_to`

, etc., are indices of node-connecting components that are directed *from* or *to* node `i`

, respectively.

```
constraint_source_directionality(
wm::AbstractNCDModel,
n::Int,
i::Int,
pipe_fr::Array{Int,1},
pipe_to::Array{Int,1},
des_pipe_fr::Array{Int,1},
des_pipe_to::Array{Int,1},
pump_fr::Array{Int,1},
pump_to::Array{Int,1},
regulator_fr::Array{Int,1},
regulator_to::Array{Int,1},
short_pipe_fr::Array{Int,1},
short_pipe_to::Array{Int,1},
valve_fr::Array{Int,1},
valve_to::Array{Int,1}
)
```

Adds a constraint that ensures at least one flow direction variable implies the transport of water *from* (i.e., out of) a source node (e.g., a node with a reservoir). Here, `n`

is the subnetwork (time) index; `i`

is the index of the node; and `pipe_fr`

, `pipe_to`

, etc., are indices of node-connecting components that are directed *from* or *to* node `i`

, respectively.

`WaterModels.constraint_intermediate_directionality`

— Function```
constraint_intermediate_directionality(
wm::AbstractNCModel,
n::Int,
i::Int,
pipe_fr::Array{Int,1},
pipe_to::Array{Int,1},
des_pipe_fr::Array{Int,1},
des_pipe_to::Array{Int,1},
pump_fr::Array{Int,1},
pump_to::Array{Int,1},
regulator_fr::Array{Int,1},
regulator_to::Array{Int,1},
short_pipe_fr::Array{Int,1},
short_pipe_to::Array{Int,1},
valve_fr::Array{Int,1},
valve_to::Array{Int,1}
)
```

Currently does nothing for models of type `AbstractNCModel`

. Here, `wm`

is the WaterModels object; `n`

is the subnetwork (time) index; `i`

is the index of the node; and `pipe_fr`

, `pipe_to`

, etc., are indices of node-connecting components that are directed *from* or *to* node `i`

, respectively.

```
constraint_intermediate_directionality(
wm::AbstractNCDModel,
n::Int,
i::Int,
pipe_fr::Array{Int,1},
pipe_to::Array{Int,1},
des_pipe_fr::Array{Int,1},
des_pipe_to::Array{Int,1},
pump_fr::Array{Int,1},
pump_to::Array{Int,1},
regulator_fr::Array{Int,1},
regulator_to::Array{Int,1},
short_pipe_fr::Array{Int,1},
short_pipe_to::Array{Int,1},
valve_fr::Array{Int,1},
valve_to::Array{Int,1}
)
```

Adds a constraint that ensures the direction of incoming flow at the node will be equal to the direction of outgoing flow. Note that this constraint should only be applied in situations where the degree of the node is two and there is zero supply or demand (i.e., the node is a "junction" or pass-through node). Here, `n`

is the subnetwork (time) index; `i`

is the index of the node; and `pipe_fr`

, `pipe_to`

, etc., are indices of node-connecting components that are directed *from* or *to* node `i`

, respectively.

## Tank Constraints

`WaterModels.constraint_tank_volume`

— Function```
constraint_tank_volume(
wm::AbstractWaterModel,
n_1::Int,
n_2::Int,
i::Int,
time_step::Float64
)
```

Adds a constraint that integrates the volume of a tank forward in time. Here, `wm`

is the WaterModels object, `n_1`

is the index of a subnetwork within a multinetwork, `n_2`

is the index of another subnetwork forward in time, relative to `n_1`

, i is the index of the tank, and `time_step`

is the time step of the interval from network `n_1`

to `n_2`

.

```
constraint_tank_volume(
wm::AbstractWaterModel,
i::Int;
nw::Int=nw_id_default
)
```

Constraint template to add `constraint_tank_volume_fixed`

constraints when a tank is not dispatchable, usually at the first time index of a problem to fix the tank's initial volume. Here, `wm`

is the WaterModels object, `i`

is the index of the tank for which the constraints will be added, if applicable, and `nw`

is the subnetwork (or time) index at which the volume will be fixed.

```
constraint_tank_volume(
wm::AbstractWaterModel,
i::Int,
nw_1::Int,
nw_2::Int
)
```

Constraint template to add `constraint_tank_volume`

constraints that integrate the volume of a tank forward in time. Here, `wm`

is the WaterModels object, `i`

is the index of the tank for which the constraints will be added, `nw_1`

is the first time index considered in the temporal integration, and `nw_2`

is the adjacent (second) time index considered in the integration.

`WaterModels.constraint_tank_volume_fixed`

— Function```
constraint_tank_volume_fixed(
wm::AbstractWaterModel,
n::Int,
i::Int,
V_0::Float64,
time_step::Float64,
min_vol::Float64,
max_vol::Float64
)
```

Adds a constraint that ensures the volume of a tank at some time index is fixed. Here, `wm`

is the WaterModels object, `n`

is the index of a subnetwork within a multinetwork, `i`

is the index of the tank, and `V_0`

is the fixed volume of the tank that is desired. Also adds constraints that ensure, after integration of volume forward in time, the new volume will reside between predefined lower and upper bounds. To that end, `time_step`

is the time step between the current time index and the next, `min_vol`

is the minimum volume of water that must be present in the tank, and `max_vol`

is the maximum volume of water in the tank.

`WaterModels.constraint_tank_volume_recovery`

— Function```
constraint_tank_volume_recovery(
wm::AbstractWaterModel,
i::Int,
n_1::Int,
n_f::Int
)
```

Adds a constraint that ensures the volume of a tank at the end of the time horizon is greater than or equal to the volume of the tank at the beginning of the time horizon. Here, `wm`

is the WaterModels object, `i`

is the index of the tank, `n_1`

is the index of the first subnetwork within a multinetwork, and `n_f`

is the index of the final subnetwork. Also updates the minimum head in the `ref`

dictionary for node `i`

at the final subnetwork index `n_f`

to take the minimum head value at `n_1`

if it is larger, as implied by this constraint.

## Pipe Constraints

`WaterModels.constraint_pipe_flow`

— Function```
constraint_pipe_flow(
wm::AbstractWaterModel,
a::Int;
nw::Int=nw_id_default,
kwargs...
)
```

Constraint template to add `constraint_pipe_flow`

constraints that limit the volumetric flow rate across a pipe. Here, `wm`

is the WaterModels object, `a`

is the index of the pipe for which flow will be limited, and `nw`

is the subnetwork (or time) index that is considered.

```
constraint_pipe_flow(
wm::AbstractNCModel,
n::Int,
a::Int,
q_max_reverse::Float64,
q_min_forward::Float64
)
```

Currently does nothing for models of type `AbstractNCModel`

. Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the pipe for which flow will be limited, `q_max_reverse`

is the *maximum* (negative) amount of flow when flow is traveling in the negative direction (which corresponds to the *minimum* magnitude of flow when traveling in the negative direction), and `q_min_forward`

is the *minimum* (positive) amount of flow when flow is traveling in the positive (forward) direction. For `AbstractNCModel`

types, no constraints will be added, as in these formulation types, flow is not partitioned by direction, and flow bounds are instead imposed during variable instantiation in `variable_flow`

.

```
constraint_pipe_flow(
wm::AbstractNCDModel,
n::Int,
a::Int,
q_max_reverse::Float64,
q_min_forward::Float64
)
```

Adds constraints that limit the amount of flow traveling in the positive (forward) and negative (reverse) directions. Here, `wm`

is the WaterModels object, `n`

is the index of a subnetwork within a multinetwork, `a`

is the index of the pipe, `q_max_reverse`

is the *maximum* (negative) amount of flow when flow is traveling in the negative direction (which corresponds to the *minimum* magnitude of flow when traveling in the negative direction), and `q_min_forward`

is the *minimum* (positive) amount of flow when flow is traveling in the positive (forward) direction. Note that, naively, `q_max_reverse`

and `q_min_forward`

could both be assumed as zero, but the introduction of these constants allows for strengthening of flow direction variable bounds *based on the binary flow direction variables* used here.

`WaterModels.constraint_pipe_head`

— Function```
constraint_pipe_head(
wm::AbstractWaterModel,
a::Int;
nw::Int=nw_id_default,
kwargs...
)
```

Constraint template to add `constraint_pipe_head`

constraints that limit and establish relationships among head difference and head variables. Here, `wm`

is the WaterModels object, `a`

is the index of the pipe, and `nw`

is the subnetwork (or time) index that is considered.

```
constraint_pipe_head(
wm::AbstractNCModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int
)
```

Add constraints that limit the head difference (loss) along a pipe based on the lower and upper bounds of head variables at the nodes connecting that pipe. Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the pipe, `node_fr`

is the index of the tail node of the pipe, and `node_to`

is the index of the head node of the pipe.

```
constraint_pipe_head(
wm::AbstractNCDModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int,
)
```

Adds constraints that limit head losses (differences) in the positive (forward) and negative (reverse) flow directions. Here, `wm`

is the WaterModels object, `n`

is the index of a subnetwork within a multinetwork, `a`

is the index of the pipe, `node_fr`

is the index of the tail node of the arc that models the pipe, and `node_to`

is the index of the head node of the arc that models the pipe.

`WaterModels.constraint_pipe_head_loss`

— Function```
constraint_pipe_head_loss(
wm::AbstractWaterModel,
a::Int;
nw::Int=nw_id_default,
kwargs...
)
```

Constraint template to add `constraint_pipe_head_loss`

constraints that model head loss relationships along a pipe. Here, `wm`

is the WaterModels object, `a`

is the index of the pipe, and `nw`

is the subnetwork (or time) index that is considered.

```
constraint_pipe_head_loss(
wm::AbstractNCModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int,
exponent::Float64,
L::Float64,
r::Float64,
q_max_reverse::Float64,
q_min_forward::Float64
)
```

Add constraints that model frictional head loss across a pipe. Here, `wm`

is the WaterModels object; `n`

is the subnetwork (or time) index that is considered; `a`

is the index of the pipe; `node_fr`

is the index of the tail node of the pipe; `node_to`

is the index of the head node of the pipe; `exponent`

is the exponent on flow in the head loss function (i.e., 1.852 for Hazen-Williams head loss and 2.0 for Darcy-Weisbach head loss); `L`

is the length of the pipe; `r`

is the resistance per unit length of the pipe; `q_max_reverse`

is the *maximum* (negative) amount of flow when flow is traveling in the negative direction (which corresponds to the *minimum* magnitude of flow when traveling in the negative direction); and `q_min_forward`

is the *minimum* (positive) amount of flow when flow is traveling in the positive (forward) direction.

```
constraint_pipe_head_loss(
wm::AbstractNCDModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int,
exponent::Float64,
L::Float64,
r::Float64,
q_max_reverse::Float64,
q_min_forward::Float64
)
```

Add constraints that model frictional head loss across a pipe. Here, `wm`

is the WaterModels object; `n`

is the subnetwork (or time) index that is considered; `a`

is the index of the pipe; `node_fr`

is the index of the tail node of the pipe; `node_to`

is the index of the head node of the pipe; `exponent`

is the exponent on flow in the head loss function (i.e., 1.852 for Hazen-Williams head loss and 2.0 for Darcy-Weisbach head loss); `L`

is the length of the pipe; `r`

is the resistance per unit length of the pipe; `q_max_reverse`

is the *maximum* (negative) amount of flow when flow is traveling in the negative direction (which corresponds to the *minimum* magnitude of flow when traveling in the negative direction); and `q_min_forward`

is the *minimum* (positive) amount of flow when flow is traveling in the positive (forward) direction.

```
constraint_pipe_head_loss(
wm::AbstractLAModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int,
exponent::Float64,
L::Float64,
r::Float64,
q_max_reverse::Float64,
q_min_forward::Float64
)
```

Adds constraints that model frictional head loss across a pipe via a piecewise- linear approximation of the nonlinear, nonconvex head loss relationship. Here, `wm`

is the WaterModels object; `n`

is the subnetwork (or time) index that is considered; `a`

is the index of the pipe; `node_fr`

is the index of the tail node of the pipe; `node_to`

is the index of the head node of the pipe; `exponent`

is the exponent on flow in the head loss function (i.e., 1.852 for Hazen-Williams head loss and 2.0 for Darcy-Weisbach head loss); `L`

is the length of the pipe; `r`

is the resistance per unit length of the pipe; `q_max_reverse`

is the *maximum* (negative) amount of flow when flow is traveling in the negative direction (which corresponds to the *minimum* magnitude of flow when traveling in the negative direction); and `q_min_forward`

is the *minimum* (positive) amount of flow when flow is traveling in the positive (forward) direction. Note that `q_max_reverse`

and `q_min_forward`

are unused in this formulation since it is not direction-based.

```
constraint_pipe_head_loss(
wm::AbstractPWLRDModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int,
exponent::Float64,
L::Float64,
r::Float64,
q_max_reverse::Float64,
q_min_forward::Float64
)
```

Adds constraints that model frictional head loss across a pipe via outer and piecewise-linear inner approximations of the nonlinear, nonconvex head loss relationship. Here, `wm`

is the WaterModels object; `n`

is the subnetwork (or time) index that is considered; `a`

is the index of the pipe; `node_fr`

is the index of the tail node of the pipe; `node_to`

is the index of the head node of the pipe; `exponent`

is the exponent on flow in the head loss function (i.e., 1.852 for Hazen-Williams head loss and 2.0 for Darcy-Weisbach head loss); `L`

is the length of the pipe; `r`

is the resistance per unit length of the pipe; `q_max_reverse`

is the *maximum* (negative) amount of flow when flow is traveling in the negative direction (which corresponds to the *minimum* magnitude of flow when traveling in the negative direction); and `q_min_forward`

is the *minimum* (positive) amount of flow when flow is traveling in the positive (forward) direction.

```
constraint_pipe_head_loss(
wm::AbstractLRDModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int,
exponent::Float64,
L::Float64,
r::Float64,
q_max_reverse::Float64,
q_min_forward::Float64
)
```

Adds constraints that model frictional head loss across a pipe via linear outer approximations of the nonlinear, nonconvex head loss relationship. Here, `wm`

is the WaterModels object; `n`

is the subnetwork (or time) index that is considered; `a`

is the index of the pipe; `node_fr`

is the index of the tail node of the pipe; `node_to`

is the index of the head node of the pipe; `exponent`

is the exponent on flow in the head loss function (i.e., 1.852 for Hazen-Williams head loss and 2.0 for Darcy-Weisbach head loss); `L`

is the length of the pipe; `r`

is the resistance per unit length of the pipe; `q_max_reverse`

is the *maximum* (negative) amount of flow when flow is traveling in the negative direction (which corresponds to the *minimum* magnitude of flow when traveling in the negative direction); and `q_min_forward`

is the *minimum* (positive) amount of flow when flow is traveling in the positive (forward) direction.

## Design Pipe Constraints

`WaterModels.constraint_des_pipe_flow`

— Function```
constraint_des_pipe_flow(
wm::AbstractWaterModel,
k::Int,
node_fr::Int,
node_to::Int;
nw::Int=nw_id_default,
kwargs...,
)
```

Constraint template to add constraints that ensure flow variables for design pipes along an arc are equally directed (for direction-based formulations). Here, `wm`

is the WaterModels object, `k`

is the index of the arc that connects the two common nodes of each design pipe, `node_fr`

is the index of the tail node of the arc that models each design pipe, `node_to`

is the index of the head node of the arc that models each design pipe, `nw`

is the index of a subnetwork within a multinetwork, and `des_pipes`

is the vector of design pipe indices for design pipes that reside along the same arc `k`

.

```
constraint_des_pipe_flow(
wm::AbstractNCModel,
n::Int,
k::Int,
node_fr::Int,
node_to::Int,
des_pipes::Array{Int,1}
)
```

Currently does nothing for models of type `AbstractNCModel`

. Here, `wm`

is the WaterModels object, `n`

is the index of a subnetwork within a multinetwork, `k`

is the index of the arc that connects the two common nodes of each design pipe, `node_fr`

is the index of the tail node of the arc that models each design pipe, `node_to`

is the index of the head node of the arc that models each design pipe, and `des_pipes`

is the vector of design pipes that reside along the same arc `k`

. For `AbstractNCModel`

types, no constraints will be added, as in these formulation types, flow is not partitioned by direction, and flow bounds are instead imposed during variable instantiation in `variable_flow`

.

```
constraint_des_pipe_flow(
wm::AbstractNCDModel,
n::Int,
k::Int,
node_fr::Int,
node_to::Int,
des_pipes::Array{Int,1}
)
```

Adds constraint that ensures direction variables for all design pipes along an arc are equal to one another. Here, `wm`

is the WaterModels object, `n`

is the index of a subnetwork within a multinetwork, `k`

is the index of the arc that connects the two common nodes of each design pipe, `node_fr`

is the index of the tail node of the arc that models each design pipe, `node_to`

is the index of the head node of the arc that models each design pipe, and `des_pipes`

is the vector of design pipes that reside along the same arc `k`

.

`WaterModels.constraint_des_pipe_head`

— Function```
constraint_des_pipe_head(
wm::AbstractWaterModel,
k::Int,
node_fr::Int,
node_to::Int;
nw::Int=nw_id_default,
kwargs...,
)
```

Constraint template to add constraints that ensure head difference variables for design pipes along an arc sum to the actual head difference along that arc. Here, `wm`

is the WaterModels object, `k`

is the index of the arc that connects the two common nodes of each design pipe, `node_fr`

is the index of the tail node of the arc that models each design pipe, `node_to`

is the index of the head node of the arc that models each design pipe, `nw`

is the index of a subnetwork within a multinetwork, and `des_pipes`

is the vector of design pipe indices for design pipes that reside along the same arc `k`

.

```
constraint_des_pipe_head(
wm::AbstractNCModel,
n::Int,
k::Int,
node_fr::Int,
node_to::Int,
des_pipes::Array{Int,1}
)
```

Adds constraint that ensures head difference variables for design pipes along an arc sum to the actual head difference along that single arc. Here, `wm`

is the WaterModels object, `n`

is the index of a subnetwork within a multinetwork, `k`

is the index of the arc that connects the two common nodes of each design pipe, `node_fr`

is the index of the tail node of the arc that models each design pipe, `node_to`

is the index of the head node of the arc that models each design pipe, and `des_pipes`

is the vector of design pipes that reside along the same arc `k`

.

```
constraint_des_pipe_head(
wm::AbstractNCDModel,
n::Int,
k::Int,
node_fr::Int,
node_to::Int,
des_pipes::Array{Int,1}
)
```

Adds constraints that ensure head difference variables for design pipes along an arc sum to the actual head difference along that single arc. Here, `wm`

is the WaterModels object, `n`

is the index of a subnetwork within a multinetwork, `k`

is the index of the arc that connects the two common nodes of each design pipe, `node_fr`

is the index of the tail node of the arc that models each design pipe, `node_to`

is the index of the head node of the arc that models each design pipe, and `des_pipes`

is the vector of design pipes that reside along the same arc `k`

.

`WaterModels.constraint_on_off_des_pipe_flow`

— Function```
constraint_on_off_des_pipe_flow(
wm::AbstractWaterModel,
a::Int;
nw::Int=nw_id_default,
kwargs...
)
```

Constraint template to add `constraint_on_off_des_pipe_flow`

constraints that limit the amount of flow traveling across a design pipe. Here, `wm`

is the WaterModels object, `a`

is the index of the design pipe, and `nw`

is the index of a subnetwork within a multinetwork.

```
constraint_on_off_des_pipe_flow(
wm::AbstractNCModel,
n::Int,
a::Int,
q_max_reverse::Float64,
q_min_forward::Float64
)
```

Adds constraints that limit the amount of flow along a design pipe based on the construction status of the design pipe (i.e., there is unrestricted flow if the pipe is constructed and zero flow if the pipe is not constructed). Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the design pipe, `q_max_reverse`

is the *maximum* (negative) amount of flow when flow is traveling in the negative direction (which corresponds to the *minimum* magnitude of flow when traveling in the negative direction), and `q_min_forward`

is the *minimum* (positive) amount of flow when flow is traveling in the positive (forward) direction. For `AbstractNCModel`

types, however, these direction-based flow limits are unused.

```
constraint_on_off_des_pipe_flow(
wm::AbstractNCDModel,
n::Int,
a::Int,
q_max_reverse::Float64,
q_min_forward::Float64
)
```

Adds constraints that limit the amount of flow along a design pipe based on the construction status of the design pipe (i.e., there is unrestricted flow if the pipe is constructed and zero flow if the pipe is not constructed). Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the design pipe, `q_max_reverse`

is the *maximum* (negative) amount of flow when flow is traveling in the negative direction (which corresponds to the *minimum* magnitude of flow when traveling in the negative direction), and `q_min_forward`

is the *minimum* (positive) amount of flow when flow is traveling in the positive (forward) direction. Note these direction-based limits are currently unused in these constraints.

`WaterModels.constraint_on_off_des_pipe_head`

— Function```
constraint_on_off_des_pipe_head(
wm::AbstractWaterModel,
a::Int;
nw::Int=nw_id_default,
kwargs...
)
```

Constraint template to add `constraint_on_off_des_pipe_head`

constraints that limit the head differences across a design pipe. Here, `wm`

is the WaterModels object, `a`

is the index of the design pipe, and `nw`

is the index of a subnetwork within a multinetwork.

```
constraint_on_off_des_pipe_head(
wm::AbstractNCModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int
)
```

Adds constraints that limit the (design pipe-specific) head differences across a design pipe based on the construction status of the design pipe (i.e., there is zero head loss across the design pipe if it is not constructed). Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the design pipe, `node_fr`

is the index of the tail node of the pipe, and `node_to`

is the index of the head node of the pipe.

```
constraint_on_off_des_pipe_head(
wm::AbstractNCDModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int
)
```

Adds constraints that limit head differences (losses) in the positive (forward) and negative (reverse) directions for a design pipe. Also limits losses based on the construction status of the design pipe, i.e., restricting both losses to zero if a design pipe is not constructed. Here, `wm`

is the WaterModels object, `n`

is the index of a subnetwork within a multinetwork, `a`

is the index of the design pipe, `node_fr`

is the index of the tail node of the arc that models the design pipe, and `node_to`

is the index of the head node of the arc that models the design pipe.

`WaterModels.constraint_on_off_des_pipe_head_loss`

— Function```
constraint_on_off_des_pipe_head_loss(
wm::AbstractWaterModel,
a::Int;
nw::Int=nw_id_default,
kwargs...
)
```

Constraint template to add `constraint_on_off_des_pipe_head_loss`

constraints that model the head losses across a design pipe. Here, `wm`

is the WaterModels object, `a`

is the index of the design pipe, and `nw`

is the index of a subnetwork within a multinetwork.

```
constraint_on_off_des_pipe_head_loss(
wm::AbstractNCModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int,
exponent::Float64,
L::Float64,
r::Float64,
q_max_reverse::Float64,
q_min_forward::Float64
)
```

Add constraints that model frictional head loss across a design pipe. Here, `wm`

is the WaterModels object; `n`

is the subnetwork (or time) index that is considered; `a`

is the index of the design pipe; `node_fr`

is the index of the tail node of the design pipe; `node_to`

is the index of the head node of the design pipe; `exponent`

is the exponent on flow in the head loss function (i.e., 1.852 for Hazen-Williams head loss and 2.0 for Darcy-Weisbach head loss); `L`

is the length of the design pipe; `r`

is the resistance per unit length of the design pipe; `q_max_reverse`

is the *maximum* (negative) amount of flow when flow is traveling in the negative direction (which corresponds to the *minimum* magnitude of flow when traveling in the negative direction); and `q_min_forward`

is the *minimum* (positive) amount of flow when flow is traveling in the positive (forward) direction. For `AbstractNCModel`

types, however, these direction-based flow limits are unused. Note that, when a design pipe is not constructed, flow will be forced to zero by way of `constraint_on_off_des_pipe_flow`

, and head loss, here, will thus be constrained to zero by way of the head loss equation.

```
constraint_on_off_des_pipe_head_loss(
wm::AbstractNCDModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int,
exponent::Float64,
L::Float64,
r::Float64,
q_max_reverse::Float64,
q_min_forward::Float64
)
```

Add constraints that model frictional head loss across a design pipe. Here, `wm`

is the WaterModels object; `n`

is the subnetwork (or time) index that is considered; `a`

is the index of the design pipe; `node_fr`

is the index of the tail node of the design pipe; `node_to`

is the index of the head node of the design pipe; `exponent`

is the exponent on flow in the head loss function (i.e., 1.852 for Hazen-Williams head loss and 2.0 for Darcy-Weisbach head loss); `L`

is the length of the design pipe; `r`

is the resistance per unit length of the design pipe; `q_max_reverse`

is the *maximum* (negative) amount of flow when flow is traveling in the negative direction (which corresponds to the *minimum* magnitude of flow when traveling in the negative direction); and `q_min_forward`

is the *minimum* (positive) amount of flow when flow is traveling in the positive (forward) direction. Note direction-based flow limits are currently unused in these constraints. Also note that, when a design pipe is not constructed, flow will be forced to zero by way of `constraint_on_off_des_pipe_flow`

, and head loss, here, will thus be constrained to zero by way of the head loss equation.

```
constraint_on_off_des_pipe_head_loss(
wm::AbstractLAModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int,
exponent::Float64,
L::Float64,
r::Float64,
q_max_reverse::Float64,
q_min_forward::Float64
)
```

Add constraints that model frictional head loss across a design pipe via a piecewise-linear approximation of the nonlinear, nonconvex head loss relationship. Here, `wm`

is the WaterModels object; `n`

is the subnetwork (or time) index that is considered; `a`

is the index of the design pipe; `node_fr`

is the index of the tail node of the design pipe; `node_to`

is the index of the head node of the design pipe; `exponent`

is the exponent on flow in the head loss function (i.e., 1.852 for Hazen-Williams head loss and 2.0 for Darcy- Weisbach head loss); `L`

is the length of the design pipe; `r`

is the resistance per unit length of the design pipe; `q_max_reverse`

is the *maximum* (negative) amount of flow when flow is traveling in the negative direction (which corresponds to the *minimum* magnitude of flow when traveling in the negative direction); and `q_min_forward`

is the *minimum* (positive) amount of flow when flow is traveling in the positive (forward) direction. Note direction-based flow limits are currently unused in these constraints.

```
constraint_on_off_des_pipe_head_loss(
wm::AbstractPWLRDModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int,
exponent::Float64,
L::Float64,
r::Float64,
q_max_reverse::Float64,
q_min_forward::Float64
)
```

Adds constraints that model frictional head loss across a design pipe via outer and piecewise-linear inner approximations of the nonlinear, nonconvex head loss relationship. Here, `wm`

is the WaterModels object; `n`

is the subnetwork (or time) index that is considered; `a`

is the index of the design pipe; `node_fr`

is the index of the tail node of the design pipe; `node_to`

is the index of the head node of the design pipe; `exponent`

is the exponent on flow in the head loss function (i.e., 1.852 for Hazen-Williams head loss and 2.0 for Darcy- Weisbach head loss); `L`

is the length of the design pipe; `r`

is the resistance per unit length of the design pipe; `q_max_reverse`

is the *maximum* (negative) amount of flow when flow is traveling in the negative direction (which corresponds to the *minimum* magnitude of flow when traveling in the negative direction); and `q_min_forward`

is the *minimum* (positive) amount of flow when flow is traveling in the positive (forward) direction.

```
constraint_on_off_des_pipe_head_loss(
wm::AbstractLRDModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int,
exponent::Float64,
L::Float64,
r::Float64,
q_max_reverse::Float64,
q_min_forward::Float64
)
```

Adds constraints that model frictional head loss across a design pipe via linear outer approximations of the nonlinear, nonconvex head loss relationship. Here, `wm`

is the WaterModels object; `n`

is the subnetwork (or time) index that is considered; `a`

is the index of the design pipe; `node_fr`

is the index of the tail node of the design pipe; `node_to`

is the index of the head node of the design pipe; `exponent`

is the exponent on flow in the head loss function (i.e., 1.852 for Hazen-Williams head loss and 2.0 for Darcy-Weisbach head loss); `L`

is the length of the design pipe; `r`

is the resistance per unit length of the design pipe; `q_max_reverse`

is the *maximum* (negative) amount of flow when flow is traveling in the negative direction (which corresponds to the *minimum* magnitude of flow when traveling in the negative direction); and `q_min_forward`

is the *minimum* (positive) amount of flow when flow is traveling in the positive (forward) direction.

`WaterModels.constraint_des_pipe_selection`

— Function```
constraint_des_pipe_selection(
wm::AbstractWaterModel,
n::Int,
k::Int,
node_fr::Int,
node_to::Int,
des_pipes::Array{Int,1}
)
```

Adds a constraint that ensures exactly one design pipe will be selected per arc that comprises one or more design pipe possibilities. Here, `wm`

is the WaterModels object, `n`

is the index of a subnetwork within a multinetwork, `k`

is the index of the arc comprising multiple design pipes, `node_fr`

and `node_to`

are node indices that connect the arc, and `des_pipes`

is the vector of design pipes that reside along the same arc `k`

.

```
constraint_des_pipe_selection(
wm::AbstractWaterModel,
k::Int,
node_fr::Int,
node_to::Int;
nw::Int=nw_id_default,
kwargs...
)
```

Constraint template to add `constraint_des_pipe_selection`

constraints that enforce the selection of only one design pipe to be constructed along a given arc. Here, `wm`

is the WaterModels object, `k`

is the index of the arc that connects the two common nodes of each design pipe, `node_fr`

is the index of the tail node of the arc that models each design pipe, `node_to`

is the index of the head node of the arc that models each design pipe, and `nw`

is the index of a subnetwork within a multinetwork.

## Short Pipe Constraints

`WaterModels.constraint_short_pipe_flow`

— Function```
constraint_short_pipe_flow(
wm::AbstractWaterModel,
a::Int;
nw::Int=nw_id_default,
kwargs...
)
```

Constraint template to add `constraint_short_pipe_flow`

constraints that limit the volumetric flow rate across a short pipe. Here, `wm`

is the WaterModels object, `a`

is the index of the short pipe for which flow will be limited, and `nw`

is the subnetwork (or time) index that is considered.

```
constraint_short_pipe_flow(
wm::AbstractNCModel,
n::Int,
a::Int,
q_max_reverse::Float64,
q_min_forward::Float64,
)
```

Currently does nothing for models of type `AbstractNCModel`

. Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the short pipe for which flow will be limited, `q_max_reverse`

is the *maximum* (negative) amount of flow when flow is traveling in the negative direction (which corresponds to the *minimum* magnitude of flow when traveling in the negative direction), and `q_min_forward`

is the *minimum* (positive) amount of flow when flow is traveling in the positive (forward) direction. For `AbstractNCModel`

types, no constraints will be added, as in these formulation types, flow is not partitioned by direction, and flow bounds are instead imposed during variable instantiation in `variable_flow`

.

```
constraint_short_pipe_flow(
wm::AbstractNCDModel,
n::Int,
a::Int,
q_max_reverse::Float64,
q_min_forward::Float64
)
```

Adds constraints that limit the amount of flow along a short pipe based on the direction of flow through the short pipe. Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the short pipe for which flow will be limited, `q_max_reverse`

is the *maximum* (negative) amount of flow when flow is traveling in the negative direction (which corresponds to the *minimum* magnitude of flow when traveling in the negative direction), and `q_min_forward`

is the *minimum* (positive) amount of flow when flow is traveling in the positive (forward) direction.

`WaterModels.constraint_short_pipe_head`

— Function```
constraint_short_pipe_head(
wm::AbstractWaterModel,
a::Int;
nw::Int=nw_id_default,
kwargs...
)
```

Constraint template to add `constraint_short_pipe_head`

constraints that limit and establish relationships among head difference and head variables. Here, `wm`

is the WaterModels object, `a`

is the index of the short pipe, and `nw`

is the subnetwork (or time) index that is considered.

```
constraint_short_pipe_head(
wm::AbstractNCModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int,
)
```

Adds a constraint that equates the head at the tail node of a short pipe with the head at the head node of the short pipe (i.e., since short pipes have no loss). Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the short pipe, `node_fr`

is the index of the tail node of the short pipe, and `node_to`

is the index of the head node of the short pipe.

## Pump Constraints

`WaterModels.constraint_on_off_pump_flow`

— Function```
constraint_on_off_pump_flow(
wm::AbstractWaterModel,
a::Int;
nw::Int=nw_id_default,
kwargs...
)
```

Constraint template to add `constraint_on_off_pump_flow`

constraints, which restrict the amount of flow transported through a pump based on its operating status. Here, `wm`

is the WaterModels object, `a`

is the index of the pump, and `nw`

is the index of a subnetwork within a multinetwork.

```
constraint_on_off_pump_flow(
wm::AbstractNCModel,
n::Int,
a::Int,
q_min_forward::Float64
)
```

Adds constraints that limit the amount of flow across a pump based on the operating status of the pump (i.e., there is unrestricted but bounded flow if the pump is active and zero flow otherwise). Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the pump, and `q_min_forward`

is the *minimum* (positive) amount of flow when the pump is active. Here, `q_min_forward`

could be interpreted as some minimum amount of flow recommended by the pump manufacturer to avoid pump overheating, or it may be some network- or optimization-based bound (e.g., a flow bound discovered via optimization-based bound tightening).

```
constraint_on_off_pump_flow(
wm::AbstractNCDModel,
n::Int,
a::Int,
q_min_forward::Float64
)
```

Adds constraints that limit the amount of flow across a pump based on the operating status of the pump (i.e., there is unrestricted but bounded flow if the pump is active and zero flow otherwise). Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the pump, and `q_min_forward`

is the *minimum* (positive) amount of flow when the pump is active. Here, `q_min_forward`

could be interpreted as some minimum amount of flow recommended by the pump manufacturer to avoid pump overheating, or it may be some network- or optimization-based bound (e.g., a flow bound discovered via optimization-based bound tightening).

`WaterModels.constraint_on_off_pump_head`

— Function```
constraint_on_off_pump_flow(
wm::AbstractWaterModel,
a::Int;
nw::Int=nw_id_default,
kwargs...
)
```

Constraint template to add `constraint_on_off_pump_head`

constraints, which disjunctively limit the head difference between nodes connected by the pump and, if operating, ensures the head difference between nodes is equal to the head gain, constrained by (`constraint_on_off_pump_head_gain`

. Here, `wm`

is the WaterModels object, `a`

is the index of the pump, and `nw`

is the index of a subnetwork within a multinetwork.

```
constraint_on_off_pump_head(
wm::AbstractNCModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int
)
```

Adds constraints that model head differences at the nodes connected by a pump based on the operating status of the pump (i.e., heads at connecting nodes are decoupled if the pump is inactive, but if the pump is active, the head difference is computed from the pump's head gain, which is a function of flow). Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the pump, `node_fr`

is the index of the tail node of the pump, and `node_to`

is the index of the head node of the pump.

`WaterModels.constraint_on_off_pump_head_gain`

— Function```
constraint_on_off_pump_head_gain(
wm::AbstractWaterModel,
a::Int;
nw::Int=nw_id_default,
kwargs...
)
```

Constraint template to add `constraint_on_off_pump_head_gain`

constraints, which, if operating, limit the pump's head gain as a function of flow rate. Here, `wm`

is the WaterModels object, `a`

is the index of the pump, and `nw`

is the index of a subnetwork within a multinetwork.

```
constraint_on_off_pump_head_gain(
wm::AbstractNCModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int,
q_min_forward::Float64
)
```

Adds constraints that model the pump's head gain, if operating, as a possibly nonlinear function of flow rate. If the pump is inactive, the head gain is restricted to a value of zero. Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the pump, `node_fr`

is the index of the tail node of the pump, `node_to`

is the index of the head node of the pump, and `q_min_forward`

is the *minimum* (positive) amount of flow when the pump is active. Head gain is assumed to be a nonnegative quantity that is directed from `node_fr`

to `node_to`

.

```
constraint_on_off_pump_head_gain(
wm::AbstractNCDModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int,
q_min_forward::Float64
)
```

Adds constraints that model the pump's head gain, if operating, as a possibly nonlinear function of flow rate. If the pump is inactive, the head gain is restricted to a value of zero. Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the pump, `node_fr`

is the index of the tail node of the pump, `node_to`

is the index of the head node of the pump, and `q_min_forward`

is the *minimum* (positive) amount of flow when the pump is active. Head gain is assumed to be a nonnegative quantity that is directed from `node_fr`

to `node_to`

.

```
constraint_on_off_pump_head_gain(
wm::AbstractLAModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int,
q_min_forward::Float64
)
```

Adds constraints that model the pump's head gain, if operating, as a piecewise- linear approximation of a nonlinear function of flow rate. If the pump is inactive, the head gain is restricted to a value of zero. Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the pump, `node_fr`

is the index of the tail node of the pump, `node_to`

is the index of the head node of the pump, and `q_min_forward`

is the *minimum* (positive) amount of flow when the pump is active. Head gain is assumed to be nonnegative and is directed from `node_fr`

to `node_to`

.

```
constraint_on_off_pump_head_gain(
wm::AbstractPWLRDModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int,
q_min_forward::Float64
)
```

Adds constraints that model the pump's head gain, if operating, via outer and piecewise-linear inner approximations of the nonlinear function of flow rate. If the pump is inactive, the head gain is restricted to a value of zero. Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the pump, `node_fr`

is the index of the tail node of the pump, `node_to`

is the index of the head node of the pump, and `q_min_forward`

is the *minimum* (positive) amount of flow when the pump is active. Head gain is assumed to be nonnegative and is directed from `node_fr`

to `node_to`

.

```
constraint_on_off_pump_head_gain(
wm::AbstractLRDModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int,
q_min_forward::Float64
)
```

Adds constraints that model the pump's head gain, if operating, via linear outer approximations of the nonlinear function of flow rate. If the pump is inactive, the head gain is restricted to a value of zero. Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the pump, `node_fr`

is the index of the tail node of the pump, `node_to`

is the index of the head node of the pump, and `q_min_forward`

is the *minimum* (positive) amount of flow when the pump is active. Head gain is assumed to be nonnegative and is directed from `node_fr`

to `node_to`

.

`WaterModels.constraint_on_off_pump_power`

— Function```
constraint_on_off_pump_power(
wm::AbstractWaterModel,
a::Int;
nw::Int=nw_id_default,
kwargs...
)
```

Constraint template to add `constraint_on_off_pump_power`

constraints, which, if operating, model the pump's power according to certain assumptions. Here, `wm`

is the WaterModels object, `a`

is the index of the pump, and `nw`

is the index of a subnetwork within a multinetwork.

```
constraint_on_off_pump_power(
wm::AbstractNCModel,
n::Int,
a::Int,
q_min_forward::Float64
)
```

Adds constraints that model the pump's power consumption, if operating, as a quadratic function of flow rate. If the pump is inactive, the power is restricted to a value of zero. Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the pump, and `q_min_forward`

is the *minimum* (positive) amount of flow when the pump is active. Note that only a quadratic approximation is used for `AbstractNCModel`

.

```
constraint_on_off_pump_power(
wm::AbstractNCDModel,
n::Int,
a::Int,
q_min_forward::Float64
)
```

Adds constraints that model the pump's power consumption, if operating, as a quadratic function of flow rate. If the pump is inactive, the power is restricted to a value of zero. Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the pump, and `q_min_forward`

is the *minimum* (positive) amount of flow when the pump is active. Note only a quadratic approximation is used for `AbstractNCDModel`

.

```
constraint_on_off_pump_power(
wm::AbstractLAModel,
n::Int,
a::Int,
q_min_forward::Float64
)
```

Adds constraints that model the pump's power consumption, if operating, as a piecewise-linear approximation of a (potentially) nonlinear function of a more accurate model. If the pump is inactive, the power is restricted to a value of zero. Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the pump, and `q_min_forward`

is the *minimum* (positive) amount of flow when the pump is active.

```
constraint_on_off_pump_power(
wm::AbstractPWLRDModel,
n::Int,
a::Int,
q_min_forward::Float64
)
```

Adds constraints that model the pump's power consumption, if operating, as being bounded between piecewise-linear inner and outer approximations of a (potentially) nonlinear function of a more accurate model. If the pump is inactive, the power is restricted to a value of zero. Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the pump, and `q_min_forward`

is the *minimum* (positive) amount of flow when the pump is active.

`WaterModels.constraint_on_off_pump_power_best_efficiency`

— Function```
constraint_on_off_pump_power_best_efficiency(
wm::AbstractWaterModel,
n::Int,
a::Int,
density::Float64,
gravity::Float64,
q_min_forward::Float64
)
```

Adds a constraint that expresses pump power as a linear expression of flow, where coefficients of this linear expression are computed using an assumption that the pump will be operating at its best efficiency point. Here, `wm`

is the WaterModels object, `n`

is the index of the subnetwork within a multinetwork, `a`

is the index of the pump, `density`

is the density of water, `gravity`

is acceleration due to gravity, and `q_min_forward`

is the minimum amount of flow transported through the pump when it is active (and flow is directed forward).

`WaterModels.constraint_on_off_pump_power_custom`

— Function```
constraint_on_off_pump_power_custom(
wm::AbstractWaterModel,
n::Int,
a::Int,
power_fixed::Float64,
power_variable::Float64
)
```

Adds a constraint that expresses pump power as a linear expression of flow, where coefficients of this linear expression are given by `power_fixed`

and `power_variable`

. Here, `wm`

is the WaterModels object, `n`

is the index of the subnetwork within a multinetwork, `a`

is the index of the pump, `power_fixed`

is the amount of power consumed by the pump when it is active and transporting no flow (i.e., the point of intersection at zero flow on the vertical axis of a power-versus-flow curve), and `power_variable`

is the amount of power consumed by the pump per unit flow.

`WaterModels.constraint_on_off_pump_group`

— Function```
constraint_on_off_pump_group(
wm::AbstractWaterModel,
n::Int,
k::Int,
pump_indices::Set{Int}
)
```

Adds a constraint that imposes symmetry-breaking lexicographic sorting of pump activation statuses on groups of identical pumps operating in parallel along the same arc of the network. Reduces the combinatorial complexity of problems involving multiple pumps operating in parallel. Here, `wm`

is the WaterModels object, `n`

is the index of the subnetwork within a multinetwork, `k`

is the index of the arc that includes the group of identical pumps, and `pump_indices`

is the set of pump indices for pumps operating in parallel along arc `k`

.

```
constraint_on_off_pump_power(
wm::AbstractWaterModel,
a::Int;
nw::Int=nw_id_default,
kwargs...
)
```

Constraint template to add `constraint_on_off_pump_group`

constraints, which impose symmetry-breaking lexicographic sorting of pump activation statuses on groups of identical pumps operating in parallel along the same arc of the network. Here, `wm`

is the WaterModels object, `k`

is the index of the pump group, and `nw`

is the index of a subnetwork within a multinetwork.

`WaterModels.constraint_on_off_pump_switch`

— Function```
constraint_on_off_pump_switch(
wm::AbstractWaterModel,
a::Int,
network_ids::Array{Int,1},
max_switches::Int
)
```

Adds a constraint that limits the number of times a pump can be switched from off to on in a multiperiod pump scheduling problem. Here, `wm`

is the WaterModels object, `a`

is the index of the pump, `network_ids`

are the network (time) indices used in the summation that limits the number of switches, and `max_switches`

is the number of maximum switches permitted for the pump over the set of network indices.

```
constraint_on_off_pump_switch(
wm::AbstractWaterModel,
a::Int;
network_ids::Array{Int,1};
kwargs...
)
```

Constraint template to add `constraint_on_off_pump_switch`

constraint, which limits the number of times a pump can be switched from off to on in a multiperiod pump scheduling problem. Here, `wm`

is the WaterModels object, `a`

is the index of the pump, and `network_ids`

are the network (time) indices used in the summation that limits the number of switches.

`WaterModels.constraint_pump_switch_on`

— Function```
constraint_pump_switch_on(
wm::AbstractWaterModel,
a::Int,
n_1::Int,
n_2::Int,
nws_active::Array{Int,1}
)
```

Adds a constraint that models the switching of a pump from *off* to *on* and constrains its operation, if switched on, to remain on for at least some amount of time. Here, `wm`

is the WaterModels object; `a`

is the index of the pump; `n_1`

is the first time index modeled by the constraint; `n_2`

is the adjacent (next) time index modeled by the constraint, which permits limiting the change in pump status (i.e., from off to on); and `nws_active`

are the subnetwork (time) indices where the pump must be constrained to on *if* the pump is indeed switched from off to on between time indices `n_1`

and `n_2`

.

```
constraint_pump_switch_on(
wm::AbstractWaterModel,
a::Int,
n_1::Int,
n_2::Int;
kwargs...
)
```

Constraint template to add `constraint_pump_switch_on`

constraints, which model the switching of a pump from *off* to *on* and constrains its operation, if switched on, to remain on for at least some minimum amount of time. Here, `wm`

is the WaterModels object; `a`

is the index of the pump; `n_1`

is the first time index modeled by the constraint; and `n_2`

is the adjacent (next) time index modeled by the constraint, which permits limiting the change in pump status (i.e., from off to on).

`WaterModels.constraint_pump_switch_off`

— Function```
constraint_pump_switch_off(
wm::AbstractWaterModel,
a::Int,
n_1::Int,
n_2::Int,
nws_inactive::Array{Int,1}
)
```

Adds a constraint that models the switching of a pump from *on* to *off* and constrains non-operation, if switched off, to remain off for at least some amount of time. Here, `wm`

is the WaterModels object; `a`

is the index of the pump; `n_1`

is the first time index modeled by the constraint; `n_2`

is the adjacent (next) time index modeled by the constraint, which permits limiting the change in pump status (i.e., from on to off); and `nws_inactive`

are the subnetwork (time) indices where the pump must be constrained to off *if* the pump is indeed switched from on to off between time indices `n_1`

and `n_2`

.

```
function constraint_pump_switch_off(
wm::AbstractWaterModel,
a::Int,
n_1::Int,
n_2::Int;
kwargs...
)
```

Constraint template to add `constraint_pump_switch_off`

constraints, which model the switching of a pump from *on* to *off* and constrains non- operation, if switched off, to remain off for at least some minimum amount of time. Here, `wm`

is the WaterModels object; `a`

is the index of the pump; `n_1`

is the first time index modeled by the constraint; `n_2`

is the adjacent (next) time index modeled by the constraint, which permits limiting the change in pump status (i.e., from on to off).

## Valve Constraints

`WaterModels.constraint_on_off_valve_flow`

— Function```
constraint_on_off_valve_flow(
wm::AbstractWaterModel,
a::Int;
nw::Int=nw_id_default,
kwargs...
)
```

Constraint template to add `constraint_on_off_valve_flow`

constraints that limit the volumetric flow rate across a valve based on its operating status. Here, `wm`

is the WaterModels object, `a`

is the index of the valve for which flow will be limited, and `nw`

is the subnetwork (or time) index that is considered.

```
constraint_on_off_valve_flow(
wm::AbstractNCModel,
n::Int,
a::Int,
q_max_reverse::Float64,
q_min_forward::Float64
)
```

Adds constraints that limit the amount of flow along a valve based on the operating status of the valve (i.e., there is bounded flow if the valve is active and zero flow if the valve is inactive). Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the valve, `q_max_reverse`

is the *maximum* (negative) amount of flow when flow is traveling in the negative direction (which corresponds to the *minimum* magnitude of flow when traveling in the negative direction), and `q_min_forward`

is the *minimum* (positive) amount of flow when flow is traveling in the positive (forward) direction. For `AbstractNCModel`

types, however, these direction-based flow limits are unused.

```
constraint_on_off_valve_flow(
wm::AbstractNCDModel,
n::Int,
a::Int,
q_max_reverse::Float64,
q_min_forward::Float64
)
```

Adds constraints that limit the amount of flow along a valve based on the operating status of the valve (i.e., there is bounded flow if the valve is active and zero flow if the valve is inactive). Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the valve, `q_max_reverse`

is the *maximum* (negative) amount of flow when flow is traveling in the negative direction (which corresponds to the *minimum* magnitude of flow when traveling in the negative direction), and `q_min_forward`

is the *minimum* (positive) amount of flow when flow is traveling in the positive (forward) direction.

`WaterModels.constraint_on_off_valve_head`

— Function```
constraint_on_off_valve_head(
wm::AbstractWaterModel,
a::Int;
nw::Int=nw_id_default,
kwargs...
)
```

Constraint template to add `constraint_on_off_valve_head`

constraints that limit and establish relationships among head variables based on the operating status of the valve. Here, `wm`

is the WaterModels object, `a`

is the index of the valve, and `nw`

is the subnetwork (or time) index that is considered.

```
constraint_on_off_valve_head(
wm::AbstractNCModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int
)
```

Adds constraints that model head difference between the nodes connected by a valve based on the operating status of the valve (i.e., heads at connecting nodes are decoupled if the valve is inactive, but if the valve is active, the heads at connecting nodes are equal). Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the valve, `node_fr`

is the index of the tail node of the valve, and `node_to`

is the index of the head node of the valve.

## Regulator Constraints

`WaterModels.constraint_on_off_regulator_flow`

— Function```
constraint_on_off_regulator_flow(
wm::AbstractWaterModel,
a::Int;
nw::Int=nw_id_default,
kwargs...
)
```

Constraint template to add `constraint_on_off_regulator_flow`

constraints that limit the volumetric flow rate across a regulator based on its operating status. Here, `wm`

is the WaterModels object, `a`

is the index of the valve for which flow will be limited, and `nw`

is the subnetwork (or time) index that is considered.

```
constraint_on_off_regulator_flow(
wm::AbstractNCModel,
n::Int,
a::Int,
q_min_forward::Float64
)
```

Adds constraints that limit the amount of flow across a regulator based on the operating status of the regulator (i.e., there is unrestricted but bounded flow if the regulator is active and zero flow otherwise). Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the regulator, and `q_min_forward`

is the *minimum* (positive) amount of flow when the regulator is active.

```
constraint_on_off_regulator_flow(
wm::AbstractNCDModel,
n::Int,
a::Int,
q_min_forward::Float64
)
```

Adds constraints that limit the amount of flow across a regulator based on the operating status of the regulator (i.e., there is bounded flow if the regulator is active and zero flow otherwise). Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the regulator, and `q_min_forward`

is the *minimum* (positive) amount of flow when the regulator is active.

`WaterModels.constraint_on_off_regulator_head`

— Function```
constraint_on_off_regulator_head(
wm::AbstractWaterModel,
a::Int;
nw::Int=nw_id_default,
kwargs...
)
```

Constraint template to add `constraint_on_off_regulator_head`

constraints that limit and establish relationships among head variables based on the operating status of the regulator. Here, `wm`

is the WaterModels object, `a`

is the index of the regulator, and `nw`

is the subnetwork (or time) index that is considered.

```
constraint_on_off_regulator_head(
wm::AbstractNCModel,
n::Int,
a::Int,
node_fr::Int,
node_to::Int,
head_setting::Float64
)
```

Adds constraints that model the effects of a pressure-reducing valve (i.e., a regulator). When the regulator is operational (active), the regulator will ensure head at the node indexed by `node_to`

will be equal to `head_setting`

. When the regulator is inactive, heads at connecting nodes are decoupled. Here, `wm`

is the WaterModels object, `n`

is the subnetwork (or time) index that is considered, `a`

is the index of the regulator, `node_fr`

is the index of the tail node of the regulator, `node_to`

is the index of the head node of the regulator, and `head_setting`

is the value of head to be set (if the regulator is active) at the (thus downstream) node indexed by `node_to`

.