Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,8 @@ jobs:
- name: Run tests
run: |
if [[ "${{ github.event.pull_request.draft }}" == "true" ]]; then
# Draft PR: skip examples, slow, and deprecated_api
pytest -v --numprocesses=auto -m "not examples and not slow and not deprecated_api"
# Draft PR: skip examples and slow tests
pytest -v --numprocesses=auto -m "not examples and not slow"
else
# Ready PR & main push: examples excluded via addopts
pytest -v --numprocesses=auto
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ temp-plot.html
site/
*.egg-info
uv.lock

# test artifacts written to cwd
fs.json
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,25 @@ For more details regarding the individual PRs and contributors, please refer to

!!! tip

If upgrading from v7.x, see the [Migration Guide v8](https://flixopt.github.io/flixopt/latest/user-guide/migration-guide-v8/).
If upgrading from v5.x, see the [Migration Guide v6](https://flixopt.github.io/flixopt/latest/user-guide/migration-guide-v6/).
If upgrading from v2.x, see the [v3.0.0 release notes](https://github.com/flixOpt/flixOpt/releases/tag/v3.0.0) and [Migration Guide v3](https://flixopt.github.io/flixopt/latest/user-guide/migration-guide-v3/).

---

## [Unreleased]

**Summary**: Removes all v4-era APIs that were deprecated in v5/v6 and scheduled for removal in v7.0.0. Code that runs warning-free on v7.x runs unchanged on v8. See the [Migration Guide v8](https://flixopt.github.io/flixopt/latest/user-guide/migration-guide-v8/).

### 💥 Removed

- **`Optimization` / `SegmentedOptimization` / `Results`** — use `flow_system.optimize(solver)` and read results via `flow_system.solution` / `flow_system.stats`
- **`FlowSystem.sel()` / `isel()` / `resample()` / `coords`** — use `flow_system.transform.sel/isel/resample()` and `flow_system.indexes`
- **`FlowSystem.plot_network()` / `network_infos()` / `start_network_app()` / `stop_network_app()`** and the PyVis-based `topology.plot_legacy()` — use `flow_system.topology.plot()` / `infos()` / `start_app()` / `stop_app()`; **pyvis is no longer a dependency**
- **`FlowSystem.from_old_results()`** — re-run old optimizations with the current API (`from_old_dataset()` still loads pre-v5 configuration files and no longer warns)
- **`Bus(excess_penalty_per_flow_hour=...)`** — now raises `TypeError`; use `imbalance_penalty_per_flow_hour`
- **`normalize_weights` parameter** on `create_model` / `build_model` / `optimize()` — weights are always normalized

## [7.2.1](https://github.com/flixOpt/flixopt/compare/v7.2.0...v7.2.1) (2026-07-21)


Expand Down
2 changes: 1 addition & 1 deletion docs/user-guide/glossary.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ Key concepts and terminology used throughout flixOpt.
| **uptime** | Continuous duration equipment operates. Can be constrained with `min_uptime`, `max_uptime` in StatusParameters. |
| **downtime** | Continuous duration equipment is off. Can be constrained with `min_downtime`, `max_downtime` in StatusParameters. |
| **flow_hours** | Total energy delivered by a flow: sum of flow_rate * timestep_duration. Can be constrained with `flow_hours_min`, `flow_hours_max`. |
| **excess_penalty** | Penalty applied when bus has more supply than demand. Soft constraint alternative to strict balance. |
| **imbalance_penalty** | Penalty applied when a bus balance is violated (virtual supply/demand). Soft constraint alternative to strict balance. |
| **shortage_penalty** | Penalty applied when bus has more demand than supply (unmet demand). |

## Weights and Aggregation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ One effect is the **objective** (minimized). Others are tracked or constrained.

```python
fx.Bus(
excess_penalty_per_flow_hour=1e6, # Penalty for excess
imbalance_penalty_per_flow_hour=1e6, # Penalty for excess
shortage_penalty_per_flow_hour=1e6, # Penalty for shortage
)
```
Expand Down Expand Up @@ -259,7 +259,7 @@ A built-in `Penalty` effect enables soft constraints and prevents infeasibility:

```python
fx.StatusParameters(effects_per_startup={'Penalty': 1})
fx.Bus(label='heat', excess_penalty_per_flow_hour=1e5)
fx.Bus(label='heat', imbalance_penalty_per_flow_hour=1e5)
```

Penalty is weighted identically to the objective effect across all dimensions.
Expand Down
20 changes: 11 additions & 9 deletions docs/user-guide/migration-guide-v5.md
Original file line number Diff line number Diff line change
Expand Up @@ -246,20 +246,22 @@ boiler_vars = [v for v in flow_system.solution.data_vars if 'Boiler' in v]
solution = xr.open_dataset('results/solution.nc4')
```

### Migrating Old Result Files
### Migrating Old Files

If you have result files saved with the old API (v4.x), you can migrate them to the new format using `FlowSystem.from_old_results()`. This method:
If you have FlowSystem configurations saved with the old API (v4.x), load them with `FlowSystem.from_old_dataset()`. This method:

- Loads the old multi-file format (`*--flow_system.nc4`, `*--solution.nc4`)
- Loads the old `*--flow_system.nc4` file
- Renames deprecated parameters in the FlowSystem structure (e.g., `on_off_parameters` → `status_parameters`)
- Attaches the solution data to the FlowSystem
- Returns a FlowSystem without solution data

Old *result* files can no longer be loaded (`from_old_results()` was removed in v8) — re-run the optimization with the current API instead.

```python
# Load old results
flow_system = fx.FlowSystem.from_old_results('results_folder', 'my_model')
# Load an old FlowSystem configuration
flow_system = fx.FlowSystem.from_old_dataset('results_folder/my_model--flow_system.nc4')

# Access basic solution data (flow rates, sizes, charge states, etc.)
flow_system.solution['Boiler(Q_th)|flow_rate'].plot()
# Re-optimize with the current API
flow_system.optimize(solver)

# Save in new single-file format
flow_system.to_netcdf('results/my_model_migrated.nc4')
Expand Down Expand Up @@ -396,7 +398,7 @@ stats.total_effects['costs'].groupby('component_type').sum()
| **Replace Optimization class** | Use `flow_system.optimize(solver)` instead |
| **Update results access** | Use `flow_system.solution['var_name']` pattern |
| **Update I/O code** | Use `to_netcdf()` / `from_netcdf()` |
| **Migrate old result files** | Use `FlowSystem.from_old_results(folder, name)` |
| **Migrate old files** | Use `FlowSystem.from_old_dataset(path)` for configurations; re-run optimizations for results |
| **Update transform methods** | Use `flow_system.transform.sel/isel/resample()` instead |
| **Test thoroughly** | Verify results match v4.x outputs |
| **Remove deprecated imports** | Remove `fx.Optimization`, `fx.Results` |
Expand Down
5 changes: 5 additions & 0 deletions docs/user-guide/migration-guide-v7.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
The `transform.cluster()` call signature is unchanged — only the `Clustering`
result object and a few helpers changed.

!!! info "Upgrading to v8?"
v8.0.0 removes the long-deprecated v4-era APIs (`Optimization`/`Results`,
`FlowSystem.sel/isel/resample`, PyVis network plotting). See the
[Migration Guide v8](migration-guide-v8.md).

---

## Overview
Expand Down
135 changes: 135 additions & 0 deletions docs/user-guide/migration-guide-v8.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# Migration Guide: v7.x → v8.0.0

!!! tip "Quick Start"
```bash
pip install --upgrade flixopt
```
v8.0.0 removes the long-deprecated v4-era APIs. If your code runs on v7.x
**without `DeprecationWarning`s**, it will run unchanged on v8.0.0 — this
guide is only relevant if you still use the old entry points below.

---

## Overview

Every API removed in v8.0.0 has been deprecated since v5/v6 and has emitted a
`DeprecationWarning` pointing to its replacement ever since. The replacements
are unchanged — nothing new to learn, only old spellings to drop:

| Removed | Replacement |
|---------|-------------|
| `fx.Optimization`, `fx.SegmentedOptimization` | `flow_system.optimize(solver)` or `build_model()` + `solve(solver)` |
| `fx.results` / `Results` classes | `flow_system.solution`, `flow_system.stats` |
| `FlowSystem.sel()` / `isel()` / `resample()` | `flow_system.transform.sel()` / `isel()` / `resample()` |
| `FlowSystem.coords` | `flow_system.indexes` |
| `FlowSystem.plot_network()`, `network_infos()` | `flow_system.topology.plot()`, `topology.infos()` |
| `start_network_app()` / `stop_network_app()` | `topology.start_app()` / `topology.stop_app()` |
| `topology.plot_legacy()` (PyVis) | `topology.plot()` (Plotly) |
| `FlowSystem.from_old_results()` | re-run the optimization with the current API |
| `Bus(excess_penalty_per_flow_hour=...)` | `Bus(imbalance_penalty_per_flow_hour=...)` |
| `optimize(..., normalize_weights=...)` | remove the argument — weights are always normalized |

---

## 💥 Breaking Changes in v8.0.0

### Optimization & Results classes removed

The pre-v5 workflow objects are gone. Solve directly on the `FlowSystem` and
read results from it:

=== "v7.x and earlier (removed)"
```python
import flixopt as fx

optimization = fx.Optimization('my_run', flow_system)
optimization.do_modeling()
optimization.solve(fx.solvers.HighsSolver())

results = fx.results.Results.from_optimization(optimization)
results.flow_rates()
```

=== "v8.0.0"
```python
import flixopt as fx

flow_system.optimize(fx.solvers.HighsSolver())

flow_system.solution['Boiler(Q_th)|flow_rate']
flow_system.stats.flow_rates
```

`SegmentedOptimization` is removed without a direct replacement yet; a new
segmented (rolling-horizon) API is planned.

### Data methods moved to the `transform` accessor

=== "v7.x and earlier (removed)"
```python
fs_jan = flow_system.sel(time='2020-01')
fs_2h = flow_system.resample('2h', method='mean')
```

=== "v8.0.0"
```python
fs_jan = flow_system.transform.sel(time='2020-01')
fs_2h = flow_system.transform.resample('2h', method='mean')
```

### Network visualization is Plotly-only

`plot_network()`, the PyVis-based `topology.plot_legacy()`, and the network
app wrappers on `FlowSystem` are removed. **PyVis is no longer a dependency.**

=== "v7.x and earlier (removed)"
```python
flow_system.plot_network(show=True)
flow_system.start_network_app()
```

=== "v8.0.0"
```python
flow_system.topology.plot()
flow_system.topology.start_app()
```

### Renamed `Bus` argument is no longer bridged

Passing the old name now raises a `TypeError` instead of warning:

=== "v7.x and earlier (removed)"
```python
fx.Bus('Heat', excess_penalty_per_flow_hour=1e5)
```

=== "v8.0.0"
```python
fx.Bus('Heat', imbalance_penalty_per_flow_hour=1e5)
```

### Old result files can no longer be loaded

`FlowSystem.from_old_results()` (the loader for pre-v5 `*--flow_system.nc4` +
`*--solution.nc4` result pairs) is removed — re-run those optimizations with
the current API.

!!! info "Old *configuration* files still load"
`FlowSystem.from_old_dataset()` remains fully supported (and no longer warns): it loads a pre-v5
`*--flow_system.nc4` configuration, renames old parameters, and returns a
`FlowSystem` ready to re-optimize. Files saved with v5+
(`to_netcdf`/`from_netcdf`) are unaffected by any of this.

`from_old_dataset()` is planned for removal in **v9** — migrate pre-v5
files to the current single-file format before then.

---

## Checklist

1. Run your project on v7.x with warnings visible:
`python -W once::DeprecationWarning your_script.py`
2. Fix every `DeprecationWarning` using the table above.
3. Upgrade: `pip install --upgrade flixopt`.

If step 1 is silent, v8.0.0 is a drop-in upgrade.
6 changes: 3 additions & 3 deletions docs/user-guide/optimization/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -363,12 +363,12 @@ If your model has no feasible solution:
1. **Enable excess penalties on buses** to allow balance violations:
```python
# Allow imbalance with high penalty cost (default is 1e5)
heat_bus = fx.Bus('Heat', excess_penalty_per_flow_hour=1e5)
heat_bus = fx.Bus('Heat', imbalance_penalty_per_flow_hour=1e5)

# Or disable penalty to enforce strict balance
electricity_bus = fx.Bus('Electricity', excess_penalty_per_flow_hour=None)
electricity_bus = fx.Bus('Electricity', imbalance_penalty_per_flow_hour=None)
```
When `excess_penalty_per_flow_hour` is set, the optimization can violate bus balance constraints by paying a penalty, helping identify which constraints cause infeasibility.
When `imbalance_penalty_per_flow_hour` is set, the optimization can violate bus balance constraints by paying a penalty, helping identify which constraints cause infeasibility.

2. **Use Gurobi for infeasibility analysis** - When using GurobiSolver and the model is infeasible, flixOpt automatically extracts and logs the Irreducible Inconsistent Subsystem (IIS):
```python
Expand Down
6 changes: 1 addition & 5 deletions flixopt/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# - xr.Dataset.fxstats (from stats_accessor)
import xarray_plotly as _xpx # noqa: F401

from . import clustering, linear_converters, plotting, results, solvers, tutorials
from . import clustering, linear_converters, plotting, solvers, tutorials
from . import stats_accessor as _fxstats # noqa: F401
from .carrier import Carrier, CarrierContainer
from .comparison import Comparison
Expand All @@ -35,7 +35,6 @@
from .elements import Bus, Flow
from .flow_system import FlowSystem
from .interface import InvestParameters, Piece, Piecewise, PiecewiseConversion, PiecewiseEffects, StatusParameters
from .optimization import Optimization, SegmentedOptimization
from .plot_result import PlotResult

__all__ = [
Expand All @@ -55,8 +54,6 @@
'LinearConverter',
'Transmission',
'FlowSystem',
'Optimization',
'SegmentedOptimization',
'InvestParameters',
'StatusParameters',
'Piece',
Expand All @@ -66,7 +63,6 @@
'PlotResult',
'clustering',
'plotting',
'results',
'linear_converters',
'solvers',
'tutorials',
Expand Down
3 changes: 0 additions & 3 deletions flixopt/elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,9 +313,6 @@ def __init__(
**kwargs,
):
super().__init__(label, meta_data=meta_data)
imbalance_penalty_per_flow_hour = self._handle_deprecated_kwarg(
kwargs, 'excess_penalty_per_flow_hour', 'imbalance_penalty_per_flow_hour', imbalance_penalty_per_flow_hour
)
self._validate_kwargs(kwargs)
self.carrier = carrier.lower() if carrier else None # Store as lowercase string
self.imbalance_penalty_per_flow_hour = imbalance_penalty_per_flow_hour
Expand Down
Loading
Loading