Migration Guide: v5.x → v6.0.0¶
Quick Start
v6.0.0 brings tsam v3 integration, faster I/O, and new clustering features. Review this guide to update your code.Overview¶
v6.0.0 introduces major improvements to clustering and I/O performance. The key changes are:
| Aspect | Old API (v5.x) | New API (v6.0.0) |
|---|---|---|
| Clustering config | Individual parameters | ClusterConfig, ExtremeConfig objects |
| Peak forcing | time_series_for_high_peaks | extremes=ExtremeConfig(max_value=[...]) |
| Clustering class | ClusteredOptimization (deprecated) | flow_system.transform.cluster() |
💥 Breaking Changes in v6.0.0¶
tsam v3 API Migration¶
The clustering API now uses tsam v3's configuration objects instead of individual parameters.
import flixopt as fx
fs_clustered = flow_system.transform.cluster(
n_clusters=8,
cluster_duration='1D',
cluster_method='hierarchical',
representation_method='medoid',
time_series_for_high_peaks=['HeatDemand(Q)|fixed_relative_profile'],
time_series_for_low_peaks=['SolarThermal(Q)|fixed_relative_profile'],
extreme_period_method='new_cluster',
)
import flixopt as fx
from tsam import ClusterConfig, ExtremeConfig
fs_clustered = flow_system.transform.cluster(
n_clusters=8,
cluster_duration='1D',
cluster=ClusterConfig(
method='hierarchical',
representation='medoid',
),
extremes=ExtremeConfig(
method='new_cluster',
max_value=['HeatDemand(Q)|fixed_relative_profile'],
min_value=['SolarThermal(Q)|fixed_relative_profile'],
),
)
Parameter Mapping¶
| Old Parameter (v5.x) | New Parameter (v6.0.0) |
|---|---|
cluster_method | cluster=ClusterConfig(method=...) |
representation_method | cluster=ClusterConfig(representation=...) |
time_series_for_high_peaks | extremes=ExtremeConfig(max_value=[...]) |
time_series_for_low_peaks | extremes=ExtremeConfig(min_value=[...]) |
extreme_period_method | extremes=ExtremeConfig(method=...) |
predef_cluster_order | predef_cluster_assignments |
tsam Installation
v6.0.0 requires tsam with SegmentConfig and ExtremeConfig support. Install with:
Removed: ClusteredOptimization¶
ClusteredOptimization and ClusteringParameters were deprecated in v5.0.0 and are now removed.
import flixopt as fx
from tsam import ClusterConfig, ExtremeConfig
fs_clustered = flow_system.transform.cluster(
n_clusters=8,
cluster_duration='1D',
cluster=ClusterConfig(method='hierarchical'),
extremes=ExtremeConfig(method='new_cluster', max_value=['Demand|profile']),
)
fs_clustered.optimize(solver)
# Expand back to full resolution
fs_expanded = fs_clustered.transform.expand()
Scenario Weights Normalization¶
FlowSystem.scenario_weights are now always normalized to sum to 1 when set, including after .sel() subsetting.
Clustering Backend: tsam_xarray¶
v6.0.0 replaces the per-slice tsam loop with a single tsam_xarray.aggregate() call. The Clustering object is now a thin wrapper around tsam_xarray.ClusteringResult / AggregationResult. Most code keeps working, but the items below changed.
Removed: data_vars parameter¶
Use ClusterConfig(weights={var: 0}) to exclude variables from cluster assignment while still aggregating them.
Default weight is 1.0, not 0
Variables omitted from ClusterConfig(weights={...}) keep the default weight of 1.0 and still influence cluster assignments. To exclude a variable from the clustering objective without dropping it from the aggregated FlowSystem, set its weight explicitly to 0.
Removed: TimeSeriesData(clustering_group=..., clustering_weight=...)¶
Auto-weighting from clustering_group / clustering_weight attributes has been removed. Provide weights explicitly via ClusterConfig(weights={...}).
Removed: Clustering.metrics and clustering.plot¶
metrics (RMSE/MAE), plot.compare(), plot.heatmap(), plot.clusters(), and include_original_data=... on to_netcdf / to_dataset are gone. For accuracy analysis or visualisation, use clustering.aggregation_result (a tsam_xarray AggregationResult) before serialisation, or rebuild via flow_system.transform.apply_clustering(...) after loading.
Removed: flow_system.transform.clustering_data()¶
The v5 helper that returned a Dataset of non-constant time-varying inputs is gone. It's not a rename — the v6 clustering pipeline now passes all time-varying inputs (including constants) to tsam_xarray, so the v5 set isn't a meaningful preview anymore. See cluster_inputs() below for the v6 equivalent (with different semantics).
Removed/renamed properties on Clustering¶
| Removed | Replacement |
|---|---|
Clustering.results | Clustering.clustering_result |
Clustering.dims, Clustering.coords | clustering.clustering_result.slice_dims and per-property .coords on the returned DataArrays |
Clustering.sel(period=..., scenario=...) | clustering.aggregation_result (pre-IO only) |
Clustering.get_result(...) | Same as above |
Clustering.n_representatives | clustering.n_clusters * (clustering.n_segments or clustering.timesteps_per_cluster) |
Clustering.timestep_mapping | clustering.disaggregate(da) |
Clustering.expand_data(da) | clustering.disaggregate(da) |
Clustering.build_expansion_divisor() | Internal-only, replaced by disaggregate(segment_durations).ffill('time') |
Clustering.cluster_start_positions | np.arange(0, n_clusters * step, step) |
Clustering.representative_weights | Clustering.cluster_occurrences |
AggregationResults alias | Clustering (use directly) |
Removed notebooks¶
08d-clustering-multiperiod, 08e-clustering-internals, and 08f-clustering-segmentation were merged into 08c-clustering and 08c2-clustering-storage-modes.
NetCDF compatibility¶
NetCDF files saved with v5 cannot be loaded with v6 — the on-disk format of the embedded clustering changed. Re-save by loading in v5 and writing with v6, or re-run transform.cluster() after upgrading.
✨ New Features in v6.0.0¶
Time-Series Segmentation¶
New intra-period segmentation reduces timesteps within each cluster:
from tsam import SegmentConfig, ExtremeConfig
fs_segmented = flow_system.transform.cluster(
n_clusters=8,
cluster_duration='1D',
segments=SegmentConfig(n_segments=6), # 6 segments per day instead of 24 hours
extremes=ExtremeConfig(method='new_cluster', max_value=['Demand|profile']),
)
# Variable timestep durations
print(fs_segmented.timestep_duration) # Different duration per segment
# Expand back to original resolution
fs_expanded = fs_segmented.transform.expand()
I/O Performance¶
2-3x faster NetCDF I/O for large systems:
# Save - now faster with variable stacking
flow_system.to_netcdf('system.nc')
# Load - faster DataArray construction
fs_loaded = fx.FlowSystem.from_netcdf('system.nc')
# Version tracking
ds = flow_system.to_dataset()
print(ds.attrs['flixopt_version']) # e.g., '6.0.0'
New: flow_system.transform.cluster_inputs()¶
Returns an xr.Dataset of every variable with a time dim — exactly the set cluster() will pass to tsam_xarray, constants included. Different from the removed v5 clustering_data(), which filtered constants out.
Use it to enumerate columns for ClusterConfig(weights={...}):
cols = list(flow_system.transform.cluster_inputs())
target = 'HeatDemand(Q)|fixed_relative_profile'
weights = {target: 1, **{v: 0 for v in cols if v != target}}
fs_clustered = flow_system.transform.cluster(
n_clusters=8, cluster_duration='1D',
cluster=ClusterConfig(weights=weights),
)
Variables omitted from weights keep the default weight of 1.0 (still influence cluster assignments). Set a variable's weight to 0 to exclude it from clustering while keeping it aggregated.
Clustering Metadata¶
After clustering, access structural info via fs.clustering:
fs_clustered.clustering.n_clusters
fs_clustered.clustering.cluster_assignments
fs_clustered.clustering.cluster_occurrences
# Accuracy metrics and richer access via the tsam_xarray result directly
# (pre-IO only — lost after to_netcdf / from_netcdf)
fs_clustered.clustering.aggregation_result
Apply Existing Clustering¶
Reuse clustering from one FlowSystem on another:
# Create reference clustering
fs_reference = flow_system.transform.cluster(n_clusters=8, cluster_duration='1D')
# Apply same clustering to modified system
flow_system_modified = flow_system.copy()
flow_system_modified.components['Storage'].capacity_in_flow_hours.maximum_size = 2000
fs_modified = flow_system_modified.transform.apply_clustering(fs_reference.clustering)
Migration Checklist¶
- Update
transform.cluster()calls to useClusterConfigandExtremeConfig - Replace
ClusteredOptimizationwithtransform.cluster()+optimize() - Replace
time_series_for_high_peakswithextremes=ExtremeConfig(max_value=[...]) - Replace
cluster_methodwithcluster=ClusterConfig(method=...) - Review code that depends on
scenario_weightsnot being normalized - Test clustering workflows with new API