Skip to content

flixopt.clustering.intercluster_helpers

Helper utilities for inter-cluster storage linking.

This module provides utilities for building inter-cluster storage linking constraints following the S-N model from Blanke et al. (2022).

Background

When time series are clustered (aggregated into representative periods), storage behavior needs special handling. The S-N linking model introduces:

  • SOC_boundary: Absolute state-of-charge at the boundary between original periods. With N original periods, there are N+1 boundary points.

  • Linking: SOC_boundary[d+1] = SOC_boundary[d] + delta_SOC[cluster_assignments[d]] Each boundary is connected to the next via the net charge change of the representative cluster for that period.

These utilities help construct the coordinates and bounds for SOC_boundary variables.

References

  • Blanke, T., et al. (2022). "Inter-Cluster Storage Linking for Time Series Aggregation in Energy System Optimization Models."
  • Kotzur, L., et al. (2018). "Time series aggregation for energy system design: Modeling seasonal storage."

See Also

:class:flixopt.components.InterclusterStorageModel The storage model that uses these utilities.

Classes

CapacityBounds dataclass

CapacityBounds(lower: DataArray, upper: DataArray, has_investment: bool)

Bounds for SOC_boundary variable creation.

This dataclass holds the lower and upper bounds for the SOC_boundary variable, along with a flag indicating whether investment sizing is used.

Attributes:

Name Type Description
lower DataArray

Lower bound DataArray (typically zeros).

upper DataArray

Upper bound DataArray (capacity or maximum investment size).

has_investment bool

True if the storage uses InvestParameters for sizing.

Functions

extract_capacity_bounds

extract_capacity_bounds(capacity_param: InvestParameters | int | float | None, boundary_coords: dict, boundary_dims: list[str]) -> CapacityBounds

Extract capacity bounds from storage parameters for SOC_boundary variable.

This function determines the appropriate bounds for the SOC_boundary variable based on the storage's capacity parameter:

  • Fixed capacity (numeric): Upper bound is the fixed value.
  • InvestParameters: Upper bound is maximum_size (or fixed_size if set). The actual bound is enforced via separate constraints linked to investment.size.
  • None/Unbounded: Upper bound is set to a large value (1e6).

The lower bound is always zero (SOC cannot be negative).

Parameters:

Name Type Description Default
capacity_param InvestParameters | int | float | None

Storage capacity specification. Can be: - Numeric (int/float): Fixed capacity - InvestParameters: Investment-based sizing with min/max - None: Unbounded storage

required
boundary_coords dict

Coordinate dictionary for SOC_boundary variable. Must contain 'cluster_boundary' key.

required
boundary_dims list[str]

Dimension names for SOC_boundary variable. First dimension must be 'cluster_boundary'.

required

Returns:

Type Description
CapacityBounds

CapacityBounds with lower/upper bounds and investment flag.

Example

coords, dims = build_boundary_coords(14, flow_system) bounds = extract_capacity_bounds(InvestParameters(maximum_size=10000), coords, dims) bounds.has_investment True bounds.upper.max() 10000.0

build_boundary_coords

build_boundary_coords(n_original_clusters: int, flow_system: FlowSystem) -> tuple[dict, list[str]]

Build coordinates and dimensions for SOC_boundary variable.

Creates the coordinate dictionary and dimension list needed to create the SOC_boundary variable. The primary dimension is 'cluster_boundary' with N+1 values (one for each boundary between N original periods).

Additional dimensions (period, scenario) are included if present in the FlowSystem, ensuring the SOC_boundary variable has the correct shape for multi-period or stochastic optimizations.

Parameters:

Name Type Description Default
n_original_clusters int

Number of original (non-aggregated) time periods. For example, if a year is clustered into 8 typical days but originally had 365 days, this would be 365.

required
flow_system FlowSystem

The FlowSystem containing optional period/scenario dimensions.

required

Returns:

Type Description
tuple[dict, list[str]]

Tuple of (coords, dims) where: - coords: Dictionary mapping dimension names to coordinate arrays - dims: List of dimension names in order

Example

coords, dims = build_boundary_coords(14, flow_system) dims ['cluster_boundary'] # or ['cluster_boundary', 'period'] if periods exist coords['cluster_boundary'] array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])