Connection¶
The Connection class models unidirectional power flow between elements.
It composes ordered segments that apply efficiency, limits, and pricing to the flow.
Bidirectional paths are modelled as two separate Connection elements.
Overview¶
Connection is the primary model for power flow:
- Unidirectional: Each connection flows from
sourcetotarget. - Composable: Ordered segment chain defines behavior.
- Lossless by default: A passthrough segment is created when no segments are provided.
- Extensible: Segment outputs are exposed for adapters and diagnostics.
Segments are provided as an ordered mapping.
The mapping keys become segment names and drive the nested segments output.
Segment types¶
Connections compose ordered segments. See segments for details on each type.
Model formulation¶
Decision variables¶
The Connection creates per-tag LP variables for the input power flow — one per tag per time step:
| Variable | Domain | Description |
|---|---|---|
| \(P_{\\text{in},k}(t)\) | \(\\mathbb{R}_{\\geq 0}\) | Power entering the connection for tag \(k\) |
When no tags are specified, a single default tag is used (always-tagged paradigm).
Segments do not create their own variables (except SOC pricing, which creates auxiliary slack variables).
Instead, the Connection passes its power variables through the segment chain.
Each segment receives a power_in expression and exposes a power_out expression.
Parameters¶
| Parameter | Description |
|---|---|
source |
Name of the source element |
target |
Name of the target element |
periods |
Time period durations (hours) |
segments |
Ordered mapping of segment names to segment specifications |
tags |
Set of tag IDs for per-source power decomposition (see Tagged Power) |
If segments is omitted or empty, a passthrough segment is created automatically.
Segment parameters can be scalars or per-period arrays.
Scalar values are broadcast across all periods.
Functional segment composition¶
Segments are functional transforms on power expressions. The Connection chains them:
flow = power_in # The only LP variables (one per time step)
for segment in chain:
flow = segment.power_out # Each segment transforms the flow
# Segments add constraints/costs as side effects
# Most return input unchanged (identity transforms)
# Efficiency returns input * factor (an expression, not a new variable)
power_out = flow # Final output expression
This eliminates all inter-segment linking constraints. The variable count equals the connection flow decisions (T) plus any auxiliary variables (e.g., SOC slack).
Constraints¶
Each segment contributes constraints during construction. Power limits constrain the input expressions. No linking constraints between segments are needed.
Power balance interface¶
Connections provide power_into_source and power_into_target properties that elements use for power balance:
Power leaves the source and enters the target. Efficiency losses are applied inside the segment chain.
Cost contribution¶
Connection aggregates cost expressions from all segments. PricingSegment instances contribute energy costs to the primary objective (index 0).
Connections also contribute a time-preference term to the secondary objective (index 1). This term weights energy transfer with monotonically increasing per-period weights:
Where \(p\) is the connection's priority (auto-computed from endpoint element types), \(T\) is the number of periods, and \(t\) is the time step. The time-preference objective for a connection with priority \(p\) is:
Connections with different priorities receive non-overlapping weight ranges. Lower-priority connections are preferred when breaking ties, which the optimizer uses to select among cost-equivalent solutions. Connections with the same priority share a weight range, so ties between them are broken by time step only.
The secondary objective does not affect the minimum cost—it only selects among cost-equivalent solutions. The network solves this lexicographically: primary cost is minimized first, then the secondary objective is minimized subject to the primary remaining optimal.
Outputs¶
Connection exposes power flow and segment outputs:
connection_power— power flow through this connectionsegments— nested map of segment names to constraint shadow outputs
The segments output groups segment outputs using the segment names provided in the configuration.
Adapters use this map to surface segment-specific shadow prices.
Tag decomposition¶
The connection decomposes its power flow into per-tag LP variables. This enables tagged power tracking and per-source cost differentiation.
Per-tag variables¶
For each tag \(k\) in the tag set, a per-tag flow variable is created:
The total flow is the sum of all per-tag flows:
Per-tag segment transforms¶
Segments that transform power (e.g., efficiency) are applied proportionally to each tag flow. For an efficiency segment with factor \(\eta\):
The sum of per-tag outputs equals the segment's total output.
Tag prices¶
Each entry in tag_prices adds a price for power flowing on a specific tag:
This enables per-source pricing (e.g., charging a premium for battery-sourced power exported to the grid).
Per-tag power balance interface¶
Connections provide per-tag versions of the power balance interface used by elements:
Bidirectional paths¶
To model bidirectional flow (e.g., grid import/export), create two connections:
- A forward connection from source to target
- A reverse connection from target to source
Each connection has its own segment chain with independent parameters. The adapter layer is responsible for combining outputs from both connections into the appropriate device-level outputs (e.g., grid import power, grid export power).
When to use¶
Use Connection for all power-flow paths. Select the segment chain that matches the physical behavior you need.
Next steps¶
-
Segments
Segment catalog and formulations.
-
Elements
Battery and Node model elements.
-
Implementation
View the source code.