monee.model.formulation

The package is organised by optimization class first, sector second:

  • nlp: smooth non-convex NLPs (polar AC, smooth Weymouth, smooth Darcy-Weisbach) for IPOPT/APOPT.

  • milp: LP/MILP models (PWL Weymouth, McCormick district heating, fixed-flow heat exchanger).

  • convex: certifiable relaxations (branch-flow MISOCP, epigraph-relaxed Weymouth).

  • nonconvex: exact quadratic models for global solvers (exact branch flow, exact Weymouth, bilinear Darcy-Weisbach).

Core

class monee.model.formulation.core.BranchFormulation[source]

Bases: Formulation

equations(branch, grid, from_node_model, to_node_model, **kwargs)[source]
minimize(branch, grid, from_node_model, to_node_model, **kwargs)[source]
class monee.model.formulation.core.ChildFormulation[source]

Bases: Formulation

equations(child, grid, node, **kwargs)[source]
minimize(child, grid, node, **kwargs)[source]
overwrite(child, node_model, grid)[source]
class monee.model.formulation.core.CompoundFormulation[source]

Bases: Formulation

equations(compound, network, **kwargs)[source]
minimize(compound, network, **kwargs)[source]
class monee.model.formulation.core.Formulation[source]

Bases: object

ensure_var(model, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

class monee.model.formulation.core.NetworkFormulation(branch_type_to_formulations=None, node_type_to_formulations=None, child_type_to_formulations=None, compound_type_to_formulations=None)[source]

Bases: object

branch_type_to_formulations: dict[tuple[type, type], BranchFormulation]
child_type_to_formulations: dict[tuple[type, type], ChildFormulation]
compound_type_to_formulations: dict[tuple[type, type], CompoundFormulation]
items()[source]

All (model_type | (model_type, grid_type), formulation) pairs.

lookup(model, grid)[source]

The registered formulation matching model (and grid), or None.

Mirrors monee.model.network.Network.apply_formulation() matching: isinstance on the model type, exact type match on the grid when the key is a (model_type, grid_type) tuple; on multiple matches the last registration wins.

Return type:

monee.model.formulation.core.Formulation | None

node_type_to_formulations: dict[tuple[type, type], NodeFormulation]
class monee.model.formulation.core.NodeFormulation[source]

Bases: Formulation

equations(node, grid, from_branch_models, to_branch_models, connected_child_models, **kwargs)[source]
minimize(node, grid, from_branch_models, to_branch_models, connected_child_models, **kwargs)[source]

Bundles & sector constants

Sector constants (EL_*, GAS_*, HEAT_*), the sector-complete bundles (SMOOTH_NLP_FORMULATION, CONVEX_MIQCQP_FORMULATION, NONCONVEX_MIQCQP_FORMULATION) and the combine() helper. All of them are importable directly from monee.model.formulation.

Sector formulation constants and sector-complete network bundles.

Per-sector building blocks follow <SECTOR>_<CLASS>_FORMULATION; the network-wide bundles cover all three sectors with one consistent optimization class:

  • SMOOTH_NLP_FORMULATION - smooth non-convex NLP (IPOPT/APOPT): polar AC + smooth Weymouth + smooth Darcy-Weisbach.

  • CONVEX_MIQCQP_FORMULATION - convex relaxations a MISOCP/MIQCQP solver can certify: branch-flow MISOCP + epigraph-relaxed Weymouth + McCormick district heating (incl. convex heat-exchanger variants).

  • NONCONVEX_MIQCQP_FORMULATION - the exact quadratic models for global solvers (SCIP, Gurobi): exact branch flow + exact Weymouth + bilinear Darcy-Weisbach.

  • DEFAULT_SIMULATION_FORMULATION - the deliberate hybrid Network applies by default (polar-AC NLP + relaxed Weymouth + bilinear Darcy-Weisbach).

monee.model.formulation.bundles.combine(*network_formulations: monee.model.formulation.core.NetworkFormulation)[source]

Merge per-sector NetworkFormulation objects into one apply. Later arguments win on type collisions.

Return type:

monee.model.formulation.core.NetworkFormulation

monee.model.formulation.bundles.make_convex_miqcqp_formulation(num_partitions: int = 1)[source]

Convex MIQCQP across all three carriers: branch-flow MISOCP electricity, epigraph-relaxed Weymouth gas and McCormick district heating (incl. the convex heat-exchanger variants). Every constraint is certifiable by a convex MIQCQP/MISOCP solver; solutions are relaxation optima - check the documented gap bounds where exactness matters.

Return type:

monee.model.formulation.core.NetworkFormulation

monee.model.formulation.bundles.make_gas_milp_pwl_formulation(n_breakpoints: int = 12)[source]

Variable-friction Weymouth via per-pipe PWL of \(\varphi(m) = friction(Re(m)) \cdot m^2\).

Opt-in alternative to GAS_CONVEX_MIQCQP_FORMULATION for networks where laminar-regime accuracy matters (Re < 2300 on lightly-loaded pipes). See monee.model.formulation.milp.gas.PwlWeymouthBranchFormulation for details and trade-offs.

Return type:

monee.model.formulation.core.NetworkFormulation

monee.model.formulation.bundles.make_gas_nlp_formulation(friction_model: str = 'constant', smoothing_eps: float = 0.001, n_breakpoints: int = 12)[source]

Pure-NLP Weymouth gas formulation for GEKKO IPOPT/APOPT.

Binary-free (no direction switch), numerically smooth signed pressure drop. friction_model selects "constant" / "pwl" / "nonlinear" friction. Opt-in alternative to GAS_CONVEX_MIQCQP_FORMULATION for full-MES solves where the MISOCP-shaped default stalls IPOPT.

Return type:

monee.model.formulation.core.NetworkFormulation

monee.model.formulation.bundles.make_heat_convex_milp_formulation(num_partitions: int = 1, include_heat_exchangers: bool = True)[source]

McCormick district-heating relaxation: LP for num_partitions == 1, piecewise MILP above. Raise the partition count only when mccormick_dhs_gap_bound_k() shows the LP corner is non-physical on the network at hand.

include_heat_exchangers also maps the active/passive heat exchangers to their convex variants so the sector has no non-convex fallback; disable it to reproduce the legacy pipes-only McCormick apply.

Return type:

monee.model.formulation.core.NetworkFormulation

monee.model.formulation.bundles.make_heat_nlp_formulation(friction_model: str = 'constant', smoothing_eps: float = 0.001, n_breakpoints: int = 12)[source]

Pure-NLP Darcy-Weisbach water/heat formulation for GEKKO IPOPT/APOPT.

Binary-free smooth signed flow, smooth temperature upwinding and an active / passive heat-exchanger pair with their direction binaries removed. friction_model selects "constant" / "pwl" / "nonlinear". Opt-in alternative to HEAT_NONCONVEX_MIQCQP_FORMULATION.

Return type:

monee.model.formulation.core.NetworkFormulation

monee.model.formulation.bundles.make_heat_nonconvex_pwl_formulation(n_breakpoints: int = 12)[source]

Variable-friction Darcy-Weisbach via per-pipe PWL of \(\varphi(m)\).

Opt-in alternative to HEAT_NONCONVEX_MIQCQP_FORMULATION for laminar-heavy networks (Re < 2300); the default’s asymptotic shortcut under-estimates pressure drop there. HeatExchanger formulations are unaffected.

Return type:

monee.model.formulation.core.NetworkFormulation

monee.model.formulation.bundles.make_smooth_nlp_formulation(friction_model: str = 'constant')[source]

Combined polar-AC + smooth gas + smooth heat formulation in one apply.

Pure-NLP across all three carriers. Solve with run_energy_flow for a fast square steady-state simulation (GEKKO IMODE=1, falls back to IMODE=3 if not square), or pass an optimization problem for an IMODE=3 optimize. The simulation squaring (phantom-var pinning, flow-limit drop, vm_pu_squared demotion) is applied by the solver from its simulation flag - there is no separate simulation formulation.

Registry & solve-time attachment

Formulations belong to the solve, not to the network data. Each solver backend calls attach_formulations() on its own network copy just before model assembly. Use the string keys in FORMULATIONS to pick a formulation without imports, for example solve(net, formulation="convex_miqcqp").

Formulation registry and solve-time attachment.

Formulations are a property of the solve, not of the network data: the solver backends call attach_formulations() on their internal network copy right before model assembly. The registry maps short string keys to the built-in bundles so a solve can be parameterised as solve(net, formulation="convex_miqcqp") without imports.

Resolution order per component (most specific wins):

  1. a per-component formulation pinned via the formulation= keyword of the Network builder methods,

  2. the formulation argument handed to the solver,

  3. the network-level choice recorded by apply_formulation(),

  4. DEFAULT_SIMULATION_FORMULATION.

monee.model.formulation.registry.attach_formulations(network, formulation=None, simulation: bool = False)[source]

Attach the effective formulation to every component of network and declare its variables (ensure_var).

Called by the solver backends on their internal network copy, after extension prepare() and before problem application / variable injection. formulation is any spec accepted by resolve_formulation(); it overrides the network-level apply_formulation choice but not per-component pinned formulations.

Return type:

None

monee.model.formulation.registry.register_formulation(key: str, formulation)[source]

Register formulation (a NetworkFormulation or a zero-arg factory returning one) under key for use as a solve-time shortcut.

Return type:

None

monee.model.formulation.registry.resolve_formulation(spec)[source]

Resolve a formulation spec into a single NetworkFormulation.

Accepts None (no solver-level formulation), a registry key string, a NetworkFormulation, or a sequence of either - sequences are merged left to right via combine() (later entries win on type collisions), e.g. ("smooth_nlp", EL_MISOCP_FORMULATION).

Return type:

monee.model.formulation.core.NetworkFormulation | None

Shared node formulations

Sector node formulations shared across optimization classes.

The junction (node) side of the gas and water/heat sectors is the same for every branch formulation family: it only declares the pressure state and the reporting intermediates. The class-specific physics (relaxed / exact / smooth / PWL) lives entirely on the branch side, so the node formulations are defined once here and reused by nlp, milp and miqcqp.

class monee.model.formulation.common.GasNodeFormulation[source]

Bases: NodeFormulation

Gas junction working in pressure-squared space.

pressure_squared_pu is the decision variable (Weymouth is linear in \(p^2\)); pressure_pu is a reporting intermediate.

Pressure convention: the node pressure (and the reported pressure_pa) follows the grid’s convention - it is ABSOLUTE when the gas grid’s pressure_ambient_pa is 0 (the default) and GAUGE when it is set (e.g. to STANDARD_ATMOSPHERE_PA). In gauge mode the Weymouth/density physics add the ambient internally; only the reported value stays gauge.

ensure_var(model, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

equations(node, grid, from_branch_models, to_branch_models, connected_child_models, **kwargs)[source]
class monee.model.formulation.common.WaterNodeFormulation[source]

Bases: NodeFormulation

Water/heat junction working directly in pressure space.

ensure_var(model, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

equations(node, grid, from_branch_models, to_branch_models, connected_child_models, **kwargs)[source]

Smooth NLP (nlp)

Polar AC electricity

Polar AC power flow: a smooth non-convex NLP (sin/cos in the flow equations). The exact model - no relaxation involved.

class monee.model.formulation.nlp.el.AcPolarNlpBranchFormulation[source]

Bases: BranchFormulation

ensure_var(branch, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

equations(branch, grid, from_node_model, to_node_model, **kwargs)[source]
class monee.model.formulation.nlp.el.AcPolarNlpNodeFormulation[source]

Bases: NodeFormulation

ensure_var(model, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

Smooth Weymouth gas

Binary-free smooth Weymouth physics for pure-NLP solves (IPOPT/APOPT).

Smooth Weymouth gas formulation: a non-convex NLP, binary-free.

class monee.model.formulation.nlp.gas.SmoothWeymouthBranchFormulation(friction_model='constant', smoothing_eps=0.001, n_breakpoints=12)[source]

Bases: BranchFormulation

Pure-NLP Weymouth gas pipe for GEKKO IPOPT/APOPT.

One signed mass-flow var drives a smooth pressure drop \((p_i^2-p_j^2) \cdot C^2 \cdot \text{on\_off} = -friction \cdot m \cdot |m|\). mass_flow_pos_kgs/neg are kept as the public interface (consumed by the nodal balance) but bound to the smooth split of m, so no direction binary and no epigraph relaxation are needed. on_off stays an optional switch.

friction_model:

  • "constant" - fully-rough turbulent asymptote per pipe (Reynolds-independent).

  • "hybrid" - laminar Hagen-Poiseuille term (\(64/Re\), linear in \(m\)) plus the fully-rough turbulent term; equals pandapipes’ default nikuradse law and is QCQP-representable (see smooth.hybrid_drop_term()).

  • "nonlinear" - smooth laminar\(\leftrightarrow\) turbulent Swamee-Jain blend (\(\approx\) Colebrook), Reynolds-coupled.

  • "pwl" - piecewise-linear (odd cubic spline) of the full drop term.

ensure_var(model, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

equations(branch, grid, from_node_model, to_node_model, **kwargs)[source]

Smooth Darcy-Weisbach heat

Binary-free smooth pipe and heat-exchanger formulations for pure-NLP solves.

Smooth Darcy-Weisbach water/heat formulations: non-convex NLPs, binary-free.

class monee.model.formulation.nlp.heat.SmoothDarcyWeisbachBranchFormulation(friction_model='constant', smoothing_eps=0.001, n_breakpoints=12)[source]

Bases: BranchFormulation

Pure-NLP Darcy-Weisbach water/heat pipe for GEKKO IPOPT/APOPT.

Smooth signed flow + smooth temperature upwinding; insulation losses via the alpha attenuation factor. No direction binary. See monee.model.formulation.nlp.gas.SmoothWeymouthBranchFormulation for the friction_model options.

ensure_var(model, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

equations(branch, grid, from_node_model, to_node_model, **kwargs)[source]
class monee.model.formulation.nlp.heat.SmoothHeatExchangerFormulation[source]

Bases: FixedFlowHeatExchangerFormulation

Active HE driven by a fixed design mass flow. Same balance as the fixed-flow formulation but with the direction binary pinned to a constant (and its direction == 0 equation dropped) so the model stays a pure NLP.

ensure_var(model, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

equations(branch, grid, from_node_model, to_node_model, **kwargs)[source]
class monee.model.formulation.nlp.heat.SmoothPassiveHeatExchangerFormulation(friction_model='constant', smoothing_eps=0.001, n_breakpoints=12)[source]

Bases: BranchFormulation

Passive HE: free mass flow, fixed q_mw sets the outlet temperature change. Smooth Darcy pressure drop; no insulation losses (alpha = 1).

ensure_var(model, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

equations(branch, grid, from_node_model, to_node_model, **kwargs)[source]

LP / MILP (milp)

PWL Weymouth gas

Piecewise-linear Weymouth gas formulation: a MILP (PWL of \(\varphi(m)\) plus the direction binaries; the pressure equation is linear in \(p^2\)-space).

class monee.model.formulation.milp.gas.PwlWeymouthBranchFormulation(n_breakpoints: int = 12)[source]

Bases: BranchFormulation

Variable-friction Weymouth via per-pipe PWL of \(\varphi(m) = friction(Re(m)) \cdot m^2\).

Opt-in alternative to the relaxed (convex MIQCQP) Weymouth for networks where laminar-regime accuracy matters (Re < 2300 on lightly-loaded pipes); the constant-friction turbulent asymptote under-estimates the pressure drop there.

ensure_var(model, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

equations(branch, grid, from_node_model, to_node_model, **kwargs)[source]

McCormick district heating & fixed-flow heat exchanger

LP/MILP relaxation of district heating including the gap-bound diagnostics mccormick_dhs_gap_bound_mw() and mccormick_dhs_gap_bound_k().

McCormick-tightened district-heating formulation (Deng et al., 2021, https://doi.org/10.1016/j.eng.2021.06.006) plus the fixed-flow heat exchanger.

Heating side as a convex relaxation:

  • \(H_{out} = c \cdot m \cdot \tau_{send}\), \(H_{in} = c \cdot m \cdot \tau_{recv}\) (eq. 9c/9d) \(\to\) linear nodal balance (eq. 9a) including H_G / H_L from HeatGenerator/HeatLoad.

  • Taylor-linearised heat loss (eq. 9b).

  • McCormick envelopes (eq. 17b-17e) relax \(H_{out} = c \cdot m \cdot \tau\); num_partitions > 1 upgrades to the piecewise MILP form (eq. 18).

This is a relaxation - the bilinear is not pinned, the objective must drive H_out toward the surface. Tighten via WaterGrid.t_pu_min_env / t_pu_max_env. Hydraulics omitted (paper §2.1); pipes are unidirectional.

Boundary children contribute \(c \cdot m \cdot \tau_{node} \cdot t_{ref,k}\) using the node’s own \(\tau\).

The heat-exchanger pair (McCormickHeatExchangerFormulation / McCormickPassiveHeatExchangerFormulation) extends the same H-space balance to HE branches so a network with HEs stays convex end to end.

class monee.model.formulation.milp.heat.FixedFlowHeatExchangerFormulation[source]

Bases: BranchFormulation

Active heat exchanger driven by a prescribed (design) mass flow.

LP while the through-flow is prescribed - the energy balance \(t_{out} \cdot (m \cdot c \cdot t_{ref,k}) = t_{in} \cdot (m \cdot c \cdot t_{ref,k}) - q_{delivered}\) is linear in that case. When the surrounding network determines the flow instead (_he_flow_prescribed == False), the balance runs on the actual flow magnitude and turns bilinear.

ensure_var(model, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

equations(branch, grid, from_node_model, to_node_model, **kwargs)[source]
minimize(branch, grid, from_node_model, to_node_model, **kwargs)[source]
class monee.model.formulation.milp.heat.McCormickHeatBranchFormulation(num_partitions: int = 1)[source]

Bases: BranchFormulation

Per-pipe McCormick-tightened DH formulation. \(H_{out} = c \cdot m \cdot \tau\) is relaxed by the four McCormick inequalities (eq. 17b-17e); with num_partitions > 1 it becomes piecewise (eq. 18b). Heat loss is Taylor-linearised (eq. 9b). Hydraulics omitted.

ensure_var(model, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

equations(branch, grid, from_node_model, to_node_model, **kwargs)[source]
class monee.model.formulation.milp.heat.McCormickHeatExchangerFormulation[source]

Bases: FixedFlowHeatExchangerFormulation

Active fixed-flow HE feeding the McCormick nodal heat balance.

Adds \(H_{out,mw} = c \cdot m_{design} \cdot \tau_{send}\) (linear - the flow is a constant) and H_in_mw = H_out_mw - q_delivered so the HE’s extraction/injection shows up in eq. 9a; without these the McCormick junctions would not see the HE at all. direction is pinned to Const so no binary survives; on_off switching of the HE flow itself is not modelled here (an off HE degrades to a zero-q pass-through at design flow).

ensure_var(model, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

equations(branch, grid, from_node_model, to_node_model, **kwargs)[source]
class monee.model.formulation.milp.heat.McCormickHeatNodeFormulation(num_partitions: int = 1)[source]

Bases: NodeFormulation

Linear nodal heat balance (eq. 9a) plus piecewise-McCormick \(\tau\) disaggregation (eq. 18c/18e/18g). Sets _mccormick_dhs_active so Junction.calc_signed_heat_flow() skips its degenerate balance.

TPU_PULL_EPS = 1e-06
ensure_var(model, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

equations(node, grid, from_branch_models, to_branch_models, connected_child_models, **kwargs)[source]
minimize(node, grid, from_branch_models, to_branch_models, connected_child_models, **kwargs)[source]
class monee.model.formulation.milp.heat.McCormickPassiveHeatExchangerFormulation(num_partitions: int = 1)[source]

Bases: McCormickHeatBranchFormulation

Passive HE in the McCormick H-space: free (unidirectional) mass flow, fixed q_mw deducted exactly from the enthalpy flow instead of the pipe’s Taylor heat loss. Same algebra as the bilinear formulation’s H_in = H_out - q_mw, but the \(H = c \cdot m \cdot \tau\) surface is McCormick-relaxed, so the branch stays LP/MILP.

monee.model.formulation.milp.heat.mccormick_dhs_gap_bound_k(grid, num_partitions: int = 1, branch=None, mass_flow_kgs=None)[source]

Worst-case gap as a sender-temperature error [K]: \(t_{ref,k} \cdot (\tau_U - \tau_L)/(4 \cdot S)\) at \(m = m_U\), scaling as m_U/m below.

Return type:

float

monee.model.formulation.milp.heat.mccormick_dhs_gap_bound_mw(branch, grid, num_partitions: int = 1)[source]

Worst-case H_out_mw gap [MW]: \((c \cdot t_{ref,k}/10^6) \cdot m_U \cdot (\tau_U - \tau_L) / (4 \cdot S)\).

Return type:

float

Convex MIQCQP (miqcqp.convex)

Branch-flow MISOCP electricity

Branch-flow MISOCP electricity formulation: convex SOC relaxation \(P^2 + Q^2 \le (W/tap^2) \cdot ell\) plus big-M switching binaries.

class monee.model.formulation.miqcqp.convex.el.MISOCPElectricityBranchFormulation[source]

Bases: BranchFormulation

ensure_var(branch, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

equations(branch, grid, from_node_model, to_node_model, **kwargs)[source]
minimize(branch, grid, from_node_model, to_node_model, **kwargs)[source]
class monee.model.formulation.miqcqp.convex.el.MISOCPElectricityNodeFormulation[source]

Bases: NodeFormulation

ensure_var(node, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

equations(node, grid, from_branch_models, to_branch_models, connected_child_models, **kwargs)[source]

Epigraph-relaxed Weymouth gas

Epigraph-relaxed Weymouth gas formulation: a convex MIQCQP (MISOCP-shaped).

Weymouth is linear in pressure-squared space; the only quadratics are the convex epigraph relaxations \(m \cdot m \le m_{sq}\), kept tight by a small \(\varepsilon\) objective term, plus the direction/on_off binaries.

class monee.model.formulation.miqcqp.convex.gas.RelaxedWeymouthBranchFormulation[source]

Bases: BranchFormulation

EPIGRAPH_TIGHTENING_EPS = 1e-05
ensure_var(model, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

equations(branch, grid, from_node_model, to_node_model, **kwargs)[source]
minimize(branch, grid, from_node_model, to_node_model, **kwargs)[source]

Non-convex MIQCQP (miqcqp.nonconvex)

Exact branch-flow electricity

Exact branch-flow electricity formulation: the MISOCP with the SOC pinned to equality \(P^2 + Q^2 = (W/tap^2) \cdot ell\) - a non-convex MIQCQP for global solvers (SCIP, Gurobi).

class monee.model.formulation.miqcqp.nonconvex.el.ExactBranchFlowBranchFormulation[source]

Bases: MISOCPElectricityBranchFormulation

Branch-flow model with the SOC constraint as an equality - exact AC power flow in the \((P, Q, W, ell)\) variables, no relaxation gap.

minimize(branch, grid, from_node_model, to_node_model, **kwargs)[source]

Exact Weymouth gas

Exact Weymouth gas formulation: the epigraph pinned to equality \(m \cdot m = m_{sq}\) - a non-convex MIQCQP for global solvers.

class monee.model.formulation.miqcqp.nonconvex.gas.ExactWeymouthBranchFormulation[source]

Bases: RelaxedWeymouthBranchFormulation

Weymouth with mass_flow_*_squared pinned exactly - no relaxation gap and no \(\varepsilon\) tightening term in the objective.

minimize(branch, grid, from_node_model, to_node_model, **kwargs)[source]

Bilinear Darcy-Weisbach heat

Bilinear Darcy-Weisbach water/heat formulations: non-convex MIQCQPs.

The hydraulics mirror the gas-side epigraph relaxation, but the temperature side carries true continuous bilinears (\(alpha \cdot mag\), \(alpha \cdot t_{in}\), \(direction \cdot t\)), so the model needs a global MIQCQP solver.

class monee.model.formulation.miqcqp.nonconvex.heat.BilinearDarcyWeisbachBranchFormulation[source]

Bases: BranchFormulation

EPIGRAPH_TIGHTENING_EPS = 1e-05
ensure_var(model, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

equations(branch, grid, from_node_model, to_node_model, **kwargs)[source]
minimize(branch, grid, from_node_model, to_node_model, **kwargs)[source]
class monee.model.formulation.miqcqp.nonconvex.heat.BilinearPassiveHeatExchangerFormulation[source]

Bases: BilinearDarcyWeisbachBranchFormulation

Passive HE: free mass flow, fixed q_mw. \(\text{mass\_flow\_mag\_kgs} \cdot t_{inc,pu} = -q_w / (cp \cdot t_{ref,k})\) sets the outlet temperature change. Pressure drop follows the plain water-pipe form.

ensure_var(model, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

equations(branch, grid, from_node_model, to_node_model, **kwargs)[source]
class monee.model.formulation.miqcqp.nonconvex.heat.PwlDarcyWeisbachBranchFormulation(n_breakpoints: int = 12)[source]

Bases: BranchFormulation

Variable-friction Darcy-Weisbach via a PWL of \(\varphi(m) = friction(Re(m)) \cdot m^2\).

Opt-in alternative to BilinearDarcyWeisbachBranchFormulation for laminar-heavy networks (Re < 2300) where the turbulent asymptote under-estimates pressure drop by 5–50\(\times\). Two PWLs (one per direction) preserve bidirectional flow gated by direction. The hydraulics turn MILP-shaped, but the temperature bilinears keep the model a non-convex MIQCQP.

ensure_var(model, simulation=False, grid=None)[source]

Declare/adjust the model’s Vars for this formulation.

grid is the component’s grid (None for grid-less components); it lets formulations express grid-derived bounds on the Var abstraction itself instead of mutating backend variables in equations().

equations(branch, grid, from_node_model, to_node_model, **kwargs)[source]