You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Update the CHANGELOG.md
* Update to tsam v3.1.0 and add warnings for preserve_n_clusters=False
* [ci] prepare release v6.0.0
* fix typo in deps
* fix typo in README.md
* Revert citation temporarily
* [ci] prepare release v6.0.0
* Improve json io
* fix: Notebooks using tsam
* Allow manual docs dispatch
* Created: tests/test_clustering/test_multiperiod_extremes.py
Test Coverage (56 tests):
Multi-Period with Different Time Series
- TestMultiPeriodDifferentTimeSeries - Tests for systems where each period has distinct demand profiles:
- Different cluster assignments per period
- Optimization with period-specific profiles
- Correct expansion mapping per period
- Statistics correctness per period
Extreme Cluster Configurations
- TestExtremeConfigNewCluster - Tests method='new_cluster':
- Captures peak demand days
- Can increase cluster count
- Works with min_value parameter
- TestExtremeConfigReplace - Tests method='replace':
- Maintains requested cluster count
- Works with multi-period systems
- TestExtremeConfigAppend - Tests method='append':
- Combined with segmentation
- Objective preserved after expansion
Combined Multi-Period and Extremes
- TestExtremeConfigMultiPeriod - Extremes with multi-period/scenario:
- Requires preserve_n_clusters=True for multi-period
- Works with periods and scenarios together
- TestMultiPeriodWithExtremes - Combined scenarios:
- Different profiles with extreme capture
- Extremes combined with segmentation
- Independent cluster assignments per period
Multi-Scenario Clustering
- TestMultiScenarioWithClustering - Scenarios with clustering
- TestFullDimensionalClustering - Full (periods + scenarios) combinations
IO Round-Trip
- TestMultiPeriodClusteringIO - Save/load preservation tests
Edge Cases
- TestEdgeCases - Single cluster, many clusters, occurrence sums, mapping validation
* fix: clustering and tsam 3.1.0 issue
* [ci] prepare release v6.0.1
* fix: clustering and tsam 3.1.0 issue
* [ci] prepare release v6.0.1
* ci: remove test
* [ci] prepare release v6.0.1
* chore(deps): update dependency werkzeug to v3.1.5 (#564)
* chore(deps): update dependency ruff to v0.14.14 (#563)
* chore(deps): update dependency netcdf4 to >=1.6.1, <1.7.5 (#583)
* chore(deps): update dependency pre-commit to v4.5.1 (#532)
* fix: Comparison coords (#599)
* Fix coords concat in comparison.py
* Fix coords concat in comparison.py
* Fix coords concat in comparison.py
* Add 6.0.1 changelog entry
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix coord preservation in Comparison.solution and .inputs
- Apply _extract_nonindex_coords pattern to solution and inputs properties
- Add warning when coordinate mappings conflict during merge
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Update CHANGELOG.md
* Update CHANGELOG.md
* ⏺ The fix is straightforward — on line 83, mapping.get(dv) returns None for unmapped values. Change it to mapping.get(dv, dv) so unmapped dimension values fall back to
themselves.
⏺ Update(flixopt/comparison.py)
⎿ Added 1 line, removed 1 line
80 for name, (dim, mapping) in merged.items():
81 if dim not in ds.dims:
82 continue
83 - new_coords[name] = (dim, [mapping.get(dv) for dv in ds.coords[dim].values])
83 + new_coords[name] = (dim, [mapping.get(dv, dv) for dv in ds.coords[dim].values])
84
85 return ds.assign_coords(new_coords)
86
⏺ Done. The change on line 83 ensures that when mapping doesn't contain a key for a dimension value (which happens with outer-join additions), the original value dv is
preserved instead of inserting None.
* Update Changelog
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* [ci] prepare release v6.0.2
* typo
* Revert "typo"
This reverts commit 4a57282.
* Add plan file
* Add comprehensive test_math coverage for multi-period, scenarios, clustering, and validation
- Add 26 new tests across 8 files (×3 optimize modes = ~75 test runs)
- Multi-period: period weights, flow_hours limits, effect limits, linked invest, custom period weights
- Scenarios: scenario weights, independent sizes, independent flow rates
- Clustering: basic objective, storage cyclic/intercluster modes, status cyclic mode
- Storage: relative min/max charge state, relative min/max final charge state, balanced invest
- Components: transmission startup cost, Power2Heat, HeatPumpWithSource, SourceAndSink
- Flow status: max_uptime standalone test
- Validation: SourceAndSink requires size with prevent_simultaneous
* ⏺ Done. Here's a summary of what was changed:
Fix (flixopt/components.py:1146-1169): In _relative_charge_state_bounds, the scalar else branches now expand the base parameter to regular timesteps only
(timesteps_extra[:-1]), then concat with the final-timestep DataArray containing the correct override value. Previously they just broadcast the scalar across all timesteps,
silently ignoring relative_minimum_final_charge_state / relative_maximum_final_charge_state.
Tests (tests/test_math/test_storage.py): Added two new tests — test_storage_relative_minimum_final_charge_state_scalar and
test_storage_relative_maximum_final_charge_state_scalar — identical scenarios to the existing array-based tests but using scalar defaults (the previously buggy path).
* Added TestClusteringExact class with 3 tests asserting exact per-timestep values in clustered systems:
1. test_flow_rates_match_demand_per_cluster — Verifies Grid flow_rate matches demand [10,20,30,40] identically in each cluster, objective = 200.
2. test_per_timestep_effects_with_varying_price — Verifies per-timestep costs [10,20,30,40] reflect price×flow with varying prices [1,2,3,4] and constant demand=10, objective
= 200.
3. test_storage_cyclic_charge_discharge_pattern — Verifies storage with cyclic clustering: charges at cheap timesteps (price=1), discharges at expensive ones (price=100),
with exact charge_state trajectory across both clusters, objective = 100.
Deviation from plan: Used equal cluster weights [1.0, 1.0] instead of [1.0, 2.0]/[1.0, 3.0] for tests 1 and 2. This was necessary because cluster_weight is not preserved
during NetCDF roundtrip (pre-existing IO bug), which would cause the save->reload->solve mode to fail. Equal weights produce correct results in all 3 IO modes while still
testing the essential per-timestep value correctness.
* More storage tests
* Add multi-period tests
* Add clustering tests and fix issues with user set cluster weights
* Update CHANGELOG.md
* Mark old tests as stale
* Update CHANGELOG.md
* Mark tests as stale and move to new dir
* Move more tests to stale
* Change fixtures to speed up tests
* Moved files into stale
* Renamed folder
* Reorganize test dir
* Reorganize test dir
* Rename marker
* 2. 08d-clustering-multiperiod.ipynb (cell 29): Removed stray <cell_type>markdown</cell_type> from Summary cell
3. 08f-clustering-segmentation.ipynb (cell 33): Removed stray <cell_type>markdown</cell_type> from API Reference cell
4. flixopt/comparison.py: _extract_nonindex_coords now detects when the same coord name appears on different dims — warns and skips instead of silently overwriting
5. test_multiperiod_extremes.py: Added .item() to mapping.min()/.max() and period_mapping.min()/.max() to extract scalars before comparison
6. test_flow_status.py: Tightened test_max_uptime_standalone assertion from > 50.0 to assert_allclose(..., 60.0, rtol=1e-5) matching the documented arithmetic
---------
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Copy file name to clipboardExpand all lines: CHANGELOG.md
+126-6Lines changed: 126 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -52,7 +52,70 @@ If upgrading from v2.x, see the [v3.0.0 release notes](https://github.com/flixOp
52
52
53
53
Until here -->
54
54
55
-
## [6.0.0] - Upcoming
55
+
## [6.0.3] - Upcoming
56
+
57
+
**Summary**: Bugfix release fixing `cluster_weight` loss during NetCDF roundtrip for manually constructed clustered FlowSystems.
58
+
59
+
### 🐛 Fixed
60
+
61
+
-**Clustering IO**: `cluster_weight` is now preserved during NetCDF roundtrip for manually constructed clustered FlowSystems (i.e. `FlowSystem(..., clusters=..., cluster_weight=...)`). Previously, `cluster_weight` was silently dropped to `None` during `save->reload->solve`, causing incorrect objective values. Systems created via `.transform.cluster()` were not affected.
62
+
63
+
### 👷 Development
64
+
65
+
-**New `test_math/` test suite**: Comprehensive mathematical correctness tests with exact, hand-calculated assertions. Each test runs in 3 IO modes (solve, save→reload→solve, solve→save→reload) via the `optimize` fixture:
-`test_clustering.py` — exact per-timestep flow_rates, effects, and charge_state in clustered systems (incl. non-equal cluster weights to cover IO roundtrip)
78
+
-`test_validation.py` — plausibility checks and error messages
79
+
80
+
---
81
+
82
+
## [6.0.2] - 2026-02-05
83
+
84
+
**Summary**: Patch release which improves `Comparison` coordinate handling.
85
+
86
+
### 🐛 Fixed
87
+
88
+
-**Comparison Coordinates**: Fixed `component` coordinate becoming `(case, contributor)` shaped after concatenation in `Comparison` class. Non-index coordinates are now properly merged before concat in `solution`, `inputs`, and all statistics properties. Added warning when coordinate mappings conflict (#599)
89
+
90
+
### 📝 Docs
91
+
92
+
-**Docs Workflow**: Added `workflow_dispatch` inputs for manual docs deployment with version selection (#599)
93
+
94
+
### 👷 Development
95
+
96
+
- Updated dev dependencies to newer versions
97
+
---
98
+
99
+
## [6.0.1] - 2026-02-04
100
+
101
+
**Summary**: Bugfix release addressing clustering issues with multi-period systems and ExtremeConfig.
102
+
103
+
### 🐛 Fixed
104
+
105
+
-**Multi-period clustering with ExtremeConfig** - Fixed `ValueError: cannot reshape array` when clustering multi-period or multi-scenario systems with `ExtremeConfig`. The fix uses pandas `.unstack()` instead of manual reshape for robustness.
106
+
-**Consistent cluster count validation** - Added validation to detect inconsistent cluster counts across periods/scenarios, providing clear error messages.
107
+
108
+
### 💥 Breaking Changes
109
+
110
+
-**ExtremeConfig method restriction for multi-period systems** - When using `ExtremeConfig` with multi-period or multi-scenario systems, only `method='replace'` is now allowed. Using `method='new_cluster'` or `method='append'` will raise a `ValueError`. This works around a tsam bug where these methods can produce inconsistent cluster counts across slices.
111
+
112
+
### 📦 Dependencies
113
+
114
+
- Excluded tsam 3.1.0 from compatible versions due to clustering bug.
115
+
116
+
---
117
+
118
+
## [6.0.0] - 2026-02-03
56
119
57
120
**Summary**: Major release featuring tsam v3 migration, complete rewrite of the clustering/aggregation system, 2-3x faster I/O for large systems, new `plotly` plotting accessor, FlowSystem comparison tools, and removal of deprecated v5.0 classes.
# Side-by-side plots (auto-facets by 'case' dimension)
229
-
comp.statistics.plot.balance('Heat')
230
-
comp.statistics.flow_rates.plotly.line()
292
+
comp.stats.plot.balance('Heat')
293
+
comp.stats.flow_rates.plotly.line()
231
294
232
295
# Access combined data with 'case' dimension
233
296
comp.solution # xr.Dataset
234
-
comp.statistics.flow_rates # xr.Dataset
297
+
comp.stats.flow_rates # xr.Dataset
235
298
236
299
# Compute differences relative to a reference case
237
300
comp.diff() # vs first case
@@ -262,6 +325,58 @@ flow_system.topology.set_component_colors('turbo', overwrite=False) # Only unse
262
325
263
326
`Component.inputs`, `Component.outputs`, and `Component.flows` now use `FlowContainer` (dict-like) with dual access by index or label: `inputs[0]` or `inputs['Q_th']`.
264
327
328
+
#### `before_solve` Callback
329
+
330
+
New callback parameter for `optimize()` and `rolling_horizon()` allows adding custom constraints before solving:
-`FlowSystemDimensions` type now includes `'cluster'`
309
-
-`statistics.plot.balance()`, `carrier_balance()`, and `storage()` now use `xarray_plotly.fast_bar()` internally (styled stacked areas for better performance)
424
+
-`stats.plot.balance()`, `carrier_balance()`, and `storage()` now use `xarray_plotly.fast_bar()` internally (styled stacked areas for better performance)
425
+
-`stats.plot.carrier_balance()` now combines inputs and outputs to show net flow per component, and aggregates per component by default
310
426
311
427
### 🗑️ Deprecated
312
428
313
429
The following items are deprecated and will be removed in **v7.0.0**:
314
430
431
+
**Accessor renamed:**
432
+
433
+
-`flow_system.statistics` → Use `flow_system.stats` (shorter, more convenient)
434
+
315
435
**Classes** (use FlowSystem methods instead):
316
436
317
437
-`Optimization` class → Use `flow_system.optimize(solver)`
318
438
-`SegmentedOptimization` class → Use `flow_system.optimize.rolling_horizon()`
319
-
-`Results` class → Use `flow_system.solution` and `flow_system.statistics`
439
+
-`Results` class → Use `flow_system.solution` and `flow_system.stats`
320
440
-`SegmentedResults` class → Use segment FlowSystems directly
321
441
322
442
**FlowSystem methods** (use `transform` or `topology` accessor instead):
0 commit comments