Python API

Public API

HeatMixin

class rtctools_heat_network.heat_mixin.HeatMixin(*args, **kwargs)[source]

Bases: _HeadLossMixin, BaseComponentTypeMixin, CollocatedIntegratedOptimizationProblem

heat_network_options()[source]

Returns a dictionary of heat network specific options.

Option

Type

Default value

minimum_pressure_far_point

float

1.0 bar

maximum_temperature_der

float

2.0 °C/hour

maximum_flow_der

float

np.inf m3/s/hour

neglect_pipe_heat_losses

bool

False

heat_loss_disconnected_pipe

bool

True

minimum_velocity

float

0.005 m/s

head_loss_option (inherited)

enum

HeadLossOption.LINEAR

minimize_head_losses (inherited)

bool

False

include_demand_insulation_options

bool

False

The maximum_temperature_der gives the maximum temperature change per hour. Similarly, the maximum_flow_der parameter gives the maximum flow change per hour. These options together are used to constrain the maximum heat change per hour allowed in the entire network. Note the unit for flow is m3/s, but the change is expressed on an hourly basis leading to the m3/s/hour unit.

The heat_loss_disconnected_pipe option decides whether a disconnectable pipe has heat loss or not when it is disconnected on that particular time step. By default, a pipe has heat loss even if it is disconnected, as it would still contain relatively hot water in reality. We also do not want minimization of heat production to lead to overly disconnecting pipes. In some scenarios it is hydraulically impossible to supply heat to these disconnected pipes (Q is forced to zero), in which case this option can be set to False.

The neglect_pipe_heat_losses option sets the heat loss in pipes to zero. This can be useful when the insulation properties are unknown. Note that other components can still have heat loss, e.g. a buffer.

The minimum_velocity is the minimum absolute value of the velocity in every pipe. It is mostly an option to improve the stability of the solver in a possibly subsequent QTH problem: the default value of 0.005 m/s helps the solver by avoiding the difficult case where discharges get close to zero.

Note that the inherited options head_loss_option and minimize_head_losses are changed from their default values to HeadLossOption.LINEAR and False respectively.

The include_demand_insulation_options options is used, when insulations options per demand is specificied, to include heat demand and supply matching via constraints for all possible insulation options.

QTHMixin

class rtctools_heat_network.qth_mixin.QTHMixin(*args, flow_directions=None, **kwargs)[source]

Bases: _HeadLossMixin, BaseComponentTypeMixin, CollocatedIntegratedOptimizationProblem

Adds handling of QTH heat network objects in your model to your optimization problem.

Relevant parameters and variables are read from the model, and from this data a set of constraints and objectives are automatically generated, e.g. for the head loss and temperature losses in pipes.

__init__(*args, flow_directions=None, **kwargs)[source]
Parameters:

flow_directions

A dictionary mapping a pipe name to a Timeseries of the flow directions of type:

  • PipeFlowDirection

  • ControlValveDirection

  • CheckValveStatus

property heat_network_flow_directions: Dict[str, str]

Maps a pipe name to its corresponding constant_inputs Timeseries name for the direction.

heat_network_options()[source]

Returns a dictionary of heat network specific options.

Option

Type

Default value

maximum_temperature_der

float

2.0 °C/hour

max_t_der_bidirect_pipe

bool

True

minimum_velocity

float

0.005 m/s

sources_equal_output_temp

bool

False

demand_temperature_option

bool

DemandTemperatureOption.FIXED_DT

The maximum_temperature_der is the maximum temperature change allowed in the network. It is expressed in °C per hour. Note that this is a proxy constraint as it does not imply that temperature in the entire network is within the wanted limits.

When the flag max_t_der_bidirect_pipe is False, the maximum temperature change set with maximum_temperature_der is _not_ imposed on pipes when the flow direction changes. When it is True (the default), it is imposed in cases of flow reversal.

The minimum_velocity is the minimum absolute value of the velocity in every pipe. It is mostly an option to improve the stability of the solver: the default value of 0.005 m/s helps the solver by avoiding the difficult case where discharges get close to zero.

When the flag sources_equal_output_temp is set to True, all the sources in the network are forced to have the same output temperature. When it is False, the default, each source can operate its temperature independently from each other.

The demand_temperature_option option controls what the temperature drop and/or the return temperature of each demand is.

When DemandTemperatureOption.FIXED_DT is used (default), the temperature drop over each demand is fixed to its <demand>.dT parameter value. In other words, if the supply temperature drops, so does the return temperature.

When DemandTemperatureOption.MIN_RETURN_MAX_DT is used, the return temperature is required to be at least its <demand.T_return> parameter value. The temperature drop can be at most <demand>.dT, but is allowed to be lower.

When DemandTemperatureOption.FREE is used, no relationship is enforced. It is then up to the user to enforce a relationship on a demand’s temperature drop, return and/or supply temperature.

HeadLossMixin

class rtctools_heat_network.head_loss_mixin.HeadLossOption(value)[source]

Bases: IntEnum

Enumeration for the possible options to take head loss in pipes into account. Also see _HeadLossMixin.heat_network_options() for related options.

Note

Not all options are supported by HeatMixin, due to the focus on MILP formulations.

NO_HEADLOSS

The NO_HEADLOSS option assumes that there is no headloss in the pipelines. There are no constraints added relating the discharge to the head.

CQ2_INEQUALITY

As the name implies, this adds a quadratic inquality constraint between the head and the discharge in a pipe:

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

This expression of the headloss requires a system-specific estimation of the constant C.

As dH is always positive, a boolean is needed when flow directions are not fixed in a mixed-integer formulation to determine if

\[dH = H_{up} - H_{down}\]

or (when the \(Q < 0\))

\[dH = H_{down} - H_{up}\]
LINEARIZED_DW

Just like CQ2_INEQUALITY, this option adds inequality constraints:

\[\Delta H \ge \vec{a} \cdot Q + \vec{b}\]

with \(\vec{a}\) and \(\vec{b}\) the linearization coefficients.

This approach can more easily be explain with a plot, showing the Darcy-Weisbach head loss, and the linear lines approximating it. Note that the number of supporting lines is an option that can be set by the user by overriding _HeadLossMixin.heat_network_options(). Also note that, just like CQ2_INEQUALITY, a boolean is needed when flow directions are not fixed.

_images/DWlinearization.PNG
LINEAR

This option uses a linear head loss formulation. A single constraint of the type

\[H_{up} - H_{down} = dH = C \cdot Q\]

is added. Note that no boolean are required to support the case where flow directions are not fixed yet, at the cost of reduced fidelity in the head-loss relationship.

The exact velocity to use to linearize can be set by overriding _HeadLossMixin.heat_network_options().

CQ2_EQUALITY

This option adds equality constraints of the type:

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

This equation is non-convex, and can therefore lead to convergence issues.

Internal API

HeadLossMixin

class rtctools_heat_network.head_loss_mixin._HeadLossMixin(*args, **kwargs)[source]

Bases: BaseComponentTypeMixin, _GoalProgrammingMixinBase, OptimizationProblem

Adds handling of discharge - head (loss) relationship to the model.

abstract _hn_get_pipe_head_loss_option(pipe, heat_network_options, parameters, **kwargs) HeadLossOption[source]

The global user head loss option is not necessarily the same as the head loss option for a specific pipe. For example, when a control valve is present, a .LINEAR global head loss option could mean a .CQ2_INEQUALITY formulation should be used instead.

See also the explanation of head_loss_option (and its values) in heat_network_options().

_hn_pipe_head_loss(pipe: str, heat_network_options, parameters, discharge: Union[MX, float, ndarray], head_loss: Optional[MX] = None, dh: Optional[MX] = None, is_disconnected: Union[MX, int] = 0, big_m: Optional[float] = None, pipe_class: Optional[PipeClass] = None) Union[List[Tuple[MX, Union[float, ndarray, Timeseries], Union[float, ndarray, Timeseries]]], float, ndarray][source]

This function has two purposes: - return the head loss constraint expression(s) or - compute the head loss numerically (always positive).

Note that there are different head loss formulations (see HeadLossOption). Some formulations require the passing of head_loss (a symbol that is always positive by definition), and others require the passing of dh (which is negative when the flow is positive).

When head_loss or dh is its corresponding MX symbol/expression, the appropriate constraint expression is returned. When head_loss and dh are both None, the discharge is assumed numerical, and the numerical computation of the appropriate head loss formulation is returned. Note that this returned numerical value is always positive, regardless of the sign of the discharge.

is_disconnected can be used to specify whether a pipe is disconnected or not. This is most useful if a (boolean) ca.MX symbol is passed, which can then be used with a big-M formulation. The big-M itself then also needs to be passed via the big_m keyword argument.

abstract _hn_pipe_head_loss_constraints(ensemble_member) List[Tuple[MX, float, float]][source]

This method should be implemented to relate the three variables:

  • discharge: e.g. pipe.Q

  • head difference: e.g. pipe.dH

  • head loss of the pipe (note: proxy symbol that is >= abs(actual head loss))

The internal variable name/symbol for the head loss can be retried via self._hn_pipe_to_head_loss_map[pipe]. The method that should/can be called to relate these three variables is _hn_pipe_head_loss().

heat_network_options()[source]

Returns a dictionary of heat network specific options.

Option

Type

Default value

minimum_pressure_far_point

float

1.0 bar

wall_roughness

float

0.0002 m

head_loss_option

enum

HeadLossOption.CQ2_INEQUALITY

estimated_velocity

float

1.0 m/s (CQ2_* & LINEAR)

maximum_velocity

float

2.5 m/s (LINEARIZED_DW)

n_linearization_lines

int

5 (LINEARIZED_DW)

minimize_head_losses

bool

True

pipe_minimum_pressure

float

-np.inf

pipe_maximum_pressure

float

np.inf

The minimum_pressure_far_point gives the minimum pressure requirement at any demand node, which means that the pressure at the furthest point is also satisfied without inspecting the topology.

The wall_roughness of the pipes plays a role in determining the resistance of the pipes.

To model the head loss in pipes, the head_loss_option refers to one of the ways this can be done. See HeadLossOption for more explanation on what each option entails. Note that some options model the head loss as an inequality, i.e. \(\Delta H \ge f(Q)\), whereas others model it as an equality.

When HeadLossOption.CQ2_INEQUALITY is used, the wall roughness at estimated_velocity determines the C in \(\Delta H \ge C \cdot Q^2\).

When HeadLossOption.LINEARIZED_DW is used, the maximum_velocity needs to be set. The Darcy-Weisbach head loss relationship from \(v = 0\) until \(v = \text{maximum_velocity}\) will then be linearized using n_linearization lines.

When HeadLossOption.LINEAR is used, the wall roughness at estimated_velocity determines the C in \(\Delta H = C \cdot Q\). For pipes that contain a control valve, the formulation of HeadLossOption.CQ2_INEQUALITY is used.

When HeadLossOption.CQ2_EQUALITY is used, the wall roughness at estimated_velocity determines the C in \(\Delta H = C \cdot Q^2\). Note that this formulation is non-convex. At theta < 1 we therefore use the formulation HeadLossOption.LINEAR. For pipes that contain a control valve, the formulation of HeadLossOption.CQ2_INEQUALITY is used.

When minimize_head_losses is set to True (default), a last priority is inserted where the head losses and hydraulic power in the system are minimized if the head_loss_option is not NO_HEADLOSS. This is related to the assumption that control valves are present in the system to steer water in the right direction the case of multiple routes. If such control valves are not present, enabling this option will give warnings in case the found solution is not feasible. In case the option is False, both the minimization and checks are skipped.

The pipe_minimum_pressure is the global minimum pressured allowed in the network. Similarly, pipe_maximum_pressure is the maximum one.

class rtctools_heat_network.head_loss_mixin._MinimizeHeadLosses(optimization_problem: _HeadLossMixin, *args, **kwargs)[source]

Bases: Goal

function(optimization_problem: _HeadLossMixin, ensemble_member)[source]

This method returns a CasADi MX object describing the goal function.

Returns:

A CasADi MX object.

order = 1

The goal violation value is taken to the order’th power in the objective function.

priority = 2147483647

Lower priority goals take precedence over higher priority goals.