diff --git a/CHANGELOG.md b/CHANGELOG.md
index 2a043fc56..632fcf7a4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -61,6 +61,8 @@ Please keep the format of the changelog consistent with the other releases, so t
### 📦 Dependencies
### 📝 Docs
+- Updated Migration Guide and added missing entries.
+- Improved Changelog of v3.0.0
### 👷 Development
@@ -139,17 +141,43 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir
### 💥 Breaking Changes
-- `relative_minimum_charge_state` and `relative_maximum_charge_state` don't have an extra timestep anymore.
+**API and Behavior Changes:**
+
+- **Effect system redesigned** (no deprecation):
+ - **Terminology changes**: Effect domains renamed for clarity: `operation` → `temporal`, `invest`/`investment` → `periodic`
+ - **Sharing system**: The old `specific_share_to_other_effects_*` parameters were completely replaced with the new `share_from_temporal` and `share_from_periodic` syntax (see 🔥 Removed section)
+- **FlowSystem independence**: FlowSystems cannot be shared across multiple Calculations anymore. A copy of the FlowSystem is created instead, making every Calculation independent. Each Subcalculation in `SegmentedCalculation` now has its own distinct `FlowSystem` object
+- **Bus and Effect object assignment**: Direct assignment of Bus/Effect objects is no longer supported. Use labels (strings) instead:
+ - `Flow.bus` must receive a string label, not a Bus object
+ - Effect shares must use effect labels (strings) in dictionaries, not Effect objects
+- **Logging defaults** (from v2.2.0): Console and file logging are now disabled by default. Enable explicitly with `CONFIG.Logging.console = True` and `CONFIG.apply()`
+
+**Class and Method Renaming:**
+
- Renamed class `SystemModel` to `FlowSystemModel`
- Renamed class `Model` to `Submodel`
- Renamed `mode` parameter in plotting methods to `style`
-- Renamed investment binary variable `is_invested` to `invested` in `InvestmentModel`
-- `Calculation.do_modeling()` now returns the `Calculation` object instead of its `linopy.Model`. Callers that previously accessed the linopy model directly should now use `calculation.do_modeling().model` instead of `calculation.do_modeling()`.
+- `Calculation.do_modeling()` now returns the `Calculation` object instead of its `linopy.Model`. Callers that previously accessed the linopy model directly should now use `calculation.do_modeling().model` instead of `calculation.do_modeling()`
+
+**Variable Renaming in Results:**
+
+- Investment binary variable: `is_invested` → `invested` in `InvestmentModel`
+- Switch tracking variables in `OnOffModel`:
+ - `switch_on` → `switch|on`
+ - `switch_off` → `switch|off`
+ - `switch_on_nr` → `switch|count`
+- Effect submodel variables (following terminology changes):
+ - `Effect(invest)|total` → `Effect(periodic)`
+ - `Effect(operation)|total` → `Effect(temporal)`
+ - `Effect(operation)|total_per_timestep` → `Effect(temporal)|per_timestep`
+ - `Effect|total` → `Effect`
+
+**Data Structure Changes:**
+
+- `relative_minimum_charge_state` and `relative_maximum_charge_state` don't have an extra timestep anymore. Use the new `relative_minimum_final_charge_state` and `relative_maximum_final_charge_state` parameters for final state control
### ♻️ Changed
-- FlowSystems cannot be shared across multiple Calculations anymore. A copy of the FlowSystem is created instead, making every Calculation independent
-- Each Subcalculation in `SegmentedCalculation` now has its own distinct `FlowSystem` object
- Type system overhaul - added clear separation between temporal and non-temporal data throughout codebase for better clarity
- Enhanced FlowSystem interface with improved `__repr__()` and `__str__()` methods
- Improved Model Structure - Views and organisation is now divided into:
@@ -164,8 +192,6 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir
- The `agg_group` and `agg_weight` parameters of `TimeSeriesData` are deprecated and will be removed in a future version. Use `aggregation_group` and `aggregation_weight` instead.
- The `active_timesteps` parameter of `Calculation` is deprecated and will be removed in a future version. Use the new `sel(time=...)` method on the FlowSystem instead.
-- The assignment of Bus Objects to Flow.bus is deprecated and will be removed in a future version. Use the label of the Bus instead.
-- The usage of Effects objects in Dicts to assign shares to Effects is deprecated and will be removed in a future version. Use the label of the Effect instead.
- **InvestParameters** parameters renamed for improved clarity around investment and retirement effects:
- `fix_effects` → `effects_of_investment`
- `specific_effects` → `effects_of_investment_per_size`
diff --git a/docs/user-guide/migration-guide-v3.md b/docs/user-guide/migration-guide-v3.md
index 190503dc3..a98824de1 100644
--- a/docs/user-guide/migration-guide-v3.md
+++ b/docs/user-guide/migration-guide-v3.md
@@ -1,550 +1,233 @@
-# Migration Guide: Upgrading to v3.0.0
-
-This guide helps you migrate your flixopt code from v2.x to v3.0.0. Version 3.0.0 introduces powerful new features like multi-period investments and scenario-based stochastic optimization, along with a redesigned effect sharing system.
+# Migration Guide: v2.x → v3.0.0
!!! tip "Quick Start"
- 1. **Update your installation:**
- ```bash
- pip install --upgrade flixopt
- ```
- 2. **Review breaking changes** in the sections below
- 3. **Update deprecated parameters** to their new names
- 4. **Test your code** with the new version
+ ```bash
+ pip install --upgrade flixopt
+ ```
+ Review [breaking changes](#breaking-changes), update [deprecated parameters](#deprecated-parameters), test thoroughly.
---
-## Breaking Changes
+## 💥 Breaking Changes
-### 1. Effect Sharing System Redesign
+### Effect System Redesign
-!!! warning "Breaking Change - No Deprecation"
- The effect sharing syntax has been inverted and simplified. This change was made WITHOUT deprecation warnings due to the fundamental restructuring.
+Terminology changed and sharing system inverted: effects now "pull" shares.
-**What changed:** Effects now "pull" shares from other effects instead of "pushing" them.
-
-=== "v2.x (Old)"
+| Concept | Old (v2.x) | New (v3.0.0) |
+|---------|------------|--------------|
+| Time-varying effects | `operation` | `temporal` |
+| Investment effects | `invest` / `investment` | `periodic` |
+| Share to other effects (operation) | `specific_share_to_other_effects_operation` | `share_from_temporal` |
+| Share to other effects (invest) | `specific_share_to_other_effects_invest` | `share_from_periodic` |
+=== "v2.x"
```python
- # Effects "pushed" shares to other effects
- CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions',
+ CO2 = fx.Effect('CO2', 'kg', 'CO2',
specific_share_to_other_effects_operation={'costs': 0.2})
-
- land = fx.Effect('land', 'm²', 'Land usage',
- specific_share_to_other_effects_invest={'costs': 100})
-
- costs = fx.Effect('costs', '€', 'Total costs')
+ costs = fx.Effect('costs', '€', 'Total')
```
-=== "v3.0.0 (New)"
-
+=== "v3.0.0"
```python
- # Effects "pull" shares from other effects (clearer direction)
- CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions')
-
- land = fx.Effect('land', 'm²', 'Land usage')
-
- costs = fx.Effect('costs', '€', 'Total costs',
- share_from_temporal={'CO2': 0.2}, # From temporal (operation) effects
- share_from_periodic={'land': 100}) # From periodic (investment) effects
+ CO2 = fx.Effect('CO2', 'kg', 'CO2')
+ costs = fx.Effect('costs', '€', 'Total',
+ share_from_temporal={'CO2': 0.2}) # Pull from CO2
```
-!!! success "Migration Steps"
- 1. Find all uses of `specific_share_to_other_effects_operation` and `specific_share_to_other_effects_invest`
- 2. Move the share definition to the **receiving** effect
- 3. Rename parameters:
- - `specific_share_to_other_effects_operation` → `share_from_temporal`
- - `specific_share_to_other_effects_invest` → `share_from_periodic`
+!!! warning "No deprecation warning"
+ Move shares to receiving effect and update parameter names throughout your code.
---
-### 2. Class and Variable Renaming
-
-=== "v2.x (Old)"
+### Variable Names
- ```python
- # In optimization results
- results.solution['component|is_invested']
- ```
-
-=== "v3.0.0 (New)"
-
- ```python
- # In optimization results
- results.solution['component|invested']
- ```
+| Category | Old (v2.x) | New (v3.0.0) |
+|---------------------------------|------------|--------------|
+| Investment | `is_invested` | `invested` |
+| Switching | `switch_on` | `switch|on` |
+| Switching | `switch_off` | `switch|off` |
+| Switching | `switch_on_nr` | `switch|count` |
+| Effects | `Effect(invest)|total` | `Effect(periodic)` |
+| Effects | `Effect(operation)|total` | `Effect(temporal)` |
+| Effects | `Effect(operation)|total_per_timestep` | `Effect(temporal)|per_timestep` |
+| Effects | `Effect|total` | `Effect` |
---
-### 3. Calculation API Change
-
-!!! info "Method Chaining Support"
- `Calculation.do_modeling()` now returns the Calculation object to enable method chaining.
+### String Labels
-=== "v2.x (Old)"
+| What | Old (v2.x) | New (v3.0.0) |
+|------|------------|--------------|
+| Bus assignment | `bus=my_bus` (object) | `bus='electricity'` (string) |
+| Effect shares | `{CO2: 0.2}` (object key) | `{'CO2': 0.2}` (string key) |
+=== "v2.x"
```python
- calculation = fx.FullCalculation('my_calc', flow_system)
- linopy_model = calculation.do_modeling() # Returned linopy.Model
-
- # Access model directly from return value
- print(linopy_model)
+ flow = fx.Flow('P_el', bus=my_bus) # ❌ Object
+ costs = fx.Effect('costs', '€', share_from_temporal={CO2: 0.2}) # ❌
```
-=== "v3.0.0 (New)"
-
+=== "v3.0.0"
```python
- calculation = fx.FullCalculation('my_calc', flow_system)
- calculation.do_modeling() # Returns Calculation object
- linopy_model = calculation.model # Access model via property
-
- # This enables chaining operations
- fx.FullCalculation('my_calc', flow_system).do_modeling().solve()
+ flow = fx.Flow('P_el', bus='electricity') # ✅ String
+ costs = fx.Effect('costs', '€', share_from_temporal={'CO2': 0.2}) # ✅
```
-!!! tip "Migration"
- If you used the return value of `do_modeling()`, update to access `.model` property instead.
-
---
-### 4. Storage Charge State Bounds
-
-!!! warning "Array Dimensions Changed"
- `relative_minimum_charge_state` and `relative_maximum_charge_state` no longer have an extra timestep.
-
-**Impact:** If you provided arrays with `len(timesteps) + 1` elements, reduce to `len(timesteps)`.
-
-=== "v2.x (Old)"
-
- ```python
- # Array with extra timestep
- storage = fx.Storage(
- 'storage',
- relative_minimum_charge_state=np.array([0.2, 0.2, 0.2, 0.2, 0.2]) # 5 values for 4 timesteps
- )
- ```
-
-=== "v3.0.0 (New)"
+### FlowSystem & Calculation
- ```python
- # Array matches timesteps
- storage = fx.Storage(
- 'storage',
- relative_minimum_charge_state=np.array([0.2, 0.2, 0.2, 0.2]), # 4 values for 4 timesteps
- relative_minimum_final_charge_state=0.3 # Specify the final value directly
- )
- ```
-
-!!! note "Final State Control"
- Use the new `relative_minimum_final_charge_state` and `relative_maximum_final_charge_state` parameters to explicitly control the final charge state.
+| Change | Description |
+|--------|-------------|
+| **FlowSystem copying** | Each `Calculation` gets its own copy (independent) |
+| **do_modeling() return** | Returns `Calculation` object (access model via `.model` property) |
+| **Storage arrays** | Arrays match timestep count (no extra element) |
+| **Final charge state** | Use `relative_minimum_final_charge_state` / `relative_maximum_final_charge_state` |
---
-### 5. Plotting Parameter Rename
-
-=== "v2.x (Old)"
-
- ```python
- results.plot_heatmap('component|variable', mode='line')
- ```
+### Other Changes
-=== "v3.0.0 (New)"
-
- ```python
- results.plot_heatmap('component|variable', style='line')
- ```
+| Category | Old (v2.x) | New (v3.0.0) |
+|----------|------------|--------------|
+| Plotting parameter | `mode='line'` | `style='line'` |
+| System model class | `SystemModel` | `FlowSystemModel` |
+| Element submodel | `Model` | `Submodel` |
+| Logging default | Enabled | Disabled |
+| Enable logging | (default) | `fx.CONFIG.Logging.console = True; fx.CONFIG.apply()` |
---
-## Deprecated Parameters (Still Supported)
-
-!!! info "Gradual Migration"
- These parameters still work but will be removed in a future version. Update them at your convenience - deprecation warnings will guide you.
+## 🗑️ Deprecated Parameters
-### InvestParameters
+??? abstract "InvestParameters"
-**Parameter Changes:**
+ | Old (v2.x) | New (v3.0.0) |
+ |------------|--------------|
+ | `fix_effects` | `effects_of_investment` |
+ | `specific_effects` | `effects_of_investment_per_size` |
+ | `divest_effects` | `effects_of_retirement` |
+ | `piecewise_effects` | `piecewise_effects_of_investment` |
-| Old Parameter (v2.x) | New Parameter (v3.0.0) |
-|---------------------|----------------------|
-| `fix_effects` | `effects_of_investment` |
-| `specific_effects` | `effects_of_investment_per_size` |
-| `divest_effects` | `effects_of_retirement` |
-| `piecewise_effects` | `piecewise_effects_of_investment` |
+??? abstract "Effect"
-=== "v2.x (Deprecated)"
+ | Old (v2.x) | New (v3.0.0) |
+ |------------|--------------|
+ | `minimum_investment` | `minimum_periodic` |
+ | `maximum_investment` | `maximum_periodic` |
+ | `minimum_operation` | `minimum_temporal` |
+ | `maximum_operation` | `maximum_temporal` |
+ | `minimum_operation_per_hour` | `minimum_per_hour` |
+ | `maximum_operation_per_hour` | `maximum_per_hour` |
- ```python
- fx.InvestParameters(
- fix_effects=1000,
- specific_effects={'costs': 10},
- divest_effects=100,
- piecewise_effects=my_piecewise,
- )
- ```
-
-=== "v3.0.0 (Recommended)"
-
- ```python
- fx.InvestParameters(
- effects_of_investment=1000,
- effects_of_investment_per_size={'costs': 10},
- effects_of_retirement=100,
- piecewise_effects_of_investment=my_piecewise,
- )
- ```
-
-### Effect
-
-**Parameter Changes:**
-
-| Old Parameter (v2.x) | New Parameter (v3.0.0) |
-|---------------------|----------------------|
-| `minimum_investment` | `minimum_periodic` |
-| `maximum_investment` | `maximum_periodic` |
-| `minimum_operation` | `minimum_temporal` |
-| `maximum_operation` | `maximum_temporal` |
-| `minimum_operation_per_hour` | `minimum_per_hour` |
-| `maximum_operation_per_hour` | `maximum_per_hour` |
-
-=== "v2.x (Deprecated)"
-
- ```python
- fx.Effect(
- 'my_effect', 'unit', 'description',
- minimum_investment=10,
- maximum_investment=100,
- minimum_operation=5,
- maximum_operation=50,
- minimum_operation_per_hour=1,
- maximum_operation_per_hour=10,
- )
- ```
+??? abstract "Components"
-=== "v3.0.0 (Recommended)"
+ | Old (v2.x) | New (v3.0.0) |
+ |------------|--------------|
+ | `source` (parameter) | `outputs` |
+ | `sink` (parameter) | `inputs` |
+ | `prevent_simultaneous_sink_and_source` | `prevent_simultaneous_flow_rates` |
- ```python
- fx.Effect(
- 'my_effect', 'unit', 'description',
- minimum_periodic=10,
- maximum_periodic=100,
- minimum_temporal=5,
- maximum_temporal=50,
- minimum_per_hour=1,
- maximum_per_hour=10,
- )
- ```
+??? abstract "TimeSeriesData"
-### Component Parameters
+ | Old (v2.x) | New (v3.0.0) |
+ |------------|--------------|
+ | `agg_group` | `aggregation_group` |
+ | `agg_weight` | `aggregation_weight` |
-=== "v2.x (Deprecated)"
+??? abstract "Calculation"
- ```python
- fx.Source('my_source', source=flow)
+ | Old (v2.x) | New (v3.0.0) |
+ |------------|--------------|
+ | `active_timesteps=[0, 1, 2]` | Use `flow_system.sel()` or `flow_system.isel()` |
- fx.Sink('my_sink', sink=flow)
+---
- fx.SourceAndSink(
- 'my_source_sink',
- source=flow1,
- sink=flow2,
- prevent_simultaneous_sink_and_source=True
- )
- ```
+## ✨ New Features
-=== "v3.0.0 (Recommended)"
+??? success "Multi-Period Investments"
```python
- fx.Source('my_source', outputs=flow)
-
- fx.Sink('my_sink', inputs=flow)
-
- fx.SourceAndSink(
- 'my_source_sink',
- outputs=flow1,
- inputs=flow2,
- prevent_simultaneous_flow_rates=True
- )
+ periods = pd.Index(['2020', '2030'])
+ flow_system = fx.FlowSystem(time=timesteps, periods=periods)
```
-### TimeSeriesData
+??? success "Scenario-Based Optimization"
-=== "v2.x (Deprecated)"
+ | Parameter | Description | Example |
+ |-----------|-------------|---------|
+ | `scenarios` | Scenario index | `pd.Index(['low', 'base', 'high'], name='scenario')` |
+ | `scenario_weights` | Probabilities | `[0.2, 0.6, 0.2]` |
+ | `scenario_independent_sizes` | Separate capacities per scenario | `True` / `False` (default) |
```python
- fx.TimeSeriesData(
- agg_group='group1',
- agg_weight=2.0
+ flow_system = fx.FlowSystem(
+ time=timesteps,
+ scenarios=scenarios,
+ scenario_weights=[0.2, 0.6, 0.2],
+ scenario_independent_sizes=True
)
```
-=== "v3.0.0 (Recommended)"
+??? success "Enhanced I/O"
- ```python
- fx.TimeSeriesData(
- aggregation_group='group1',
- aggregation_weight=2.0
- )
- ```
-
-### Calculation
-
-=== "v2.x (Deprecated)"
-
- ```python
- calculation = fx.FullCalculation(
- 'calc',
- flow_system,
- active_timesteps=[0, 1, 2]
- )
- ```
+ | Method | Description |
+ |--------|-------------|
+ | `flow_system.to_netcdf('file.nc')` | Save FlowSystem |
+ | `fx.FlowSystem.from_netcdf('file.nc')` | Load FlowSystem |
+ | `flow_system.sel(time=slice(...))` | Select by label |
+ | `flow_system.isel(time=slice(...))` | Select by index |
+ | `flow_system.resample(time='D')` | Resample timeseries |
+ | `flow_system.copy()` | Deep copy |
+ | `results.flow_system` | Access from results |
-=== "v3.0.0 (Recommended)"
+??? success "Effects Per Component"
```python
- # Use FlowSystem selection methods
- flow_system_subset = flow_system.sel(time=slice('2020-01-01', '2020-01-03'))
- calculation = fx.FullCalculation('calc', flow_system_subset)
+ effects_ds = results.effects_per_component
- # Or with isel for index-based selection
- flow_system_subset = flow_system.isel(time=slice(0, 3))
- calculation = fx.FullCalculation('calc', flow_system_subset)
+ # Access effect contributions by component
+ print(effects_ds['total'].sel(effect='costs')) # Total effects
+ print(effects_ds['temporal'].sel(effect='CO2')) # Temporal effects
+ print(effects_ds['periodic'].sel(effect='costs')) # Periodic effects
```
----
-
-## New Features in v3.0.0
-
-### 1. Multi-Period Investments
-
-Model transformation pathways with distinct investment decisions in each period:
-
-```python
-import pandas as pd
-
-# Define multiple investment periods
-periods = pd.Index(['2020', '2030'])
-flow_system = fx.FlowSystem(time=timesteps, periods=periods)
-
-# Components can now invest differently in each period
-solar = fx.Source(
- 'solar',
- outputs=[fx.Flow(
- 'P_el',
- bus='electricity',
- size=fx.InvestParameters(
- minimum_size=0,
- maximum_size=1000,
- effects_of_investment_per_size={'costs': 100}
- )
- )]
-)
-```
-
-### 2. Scenario-Based Stochastic Optimization
-
-Model uncertainty with weighted scenarios:
-
-```python
-# Define scenarios with probabilities
-scenarios = pd.Index(['low_demand', 'base', 'high_demand'], name='scenario')
-scenario_weights = [0.2, 0.6, 0.2] # Probabilities
-
-flow_system = fx.FlowSystem(
- time=timesteps,
- scenarios=scenarios,
- scenario_weights=scenario_weights
-)
-
-# Define scenario-dependent data
-demand = xr.DataArray(
- data=[[70, 80, 90], # low_demand scenario
- [90, 100, 110], # base scenario
- [110, 120, 130]], # high_demand scenario
- dims=['scenario', 'time'],
- coords={'scenario': scenarios, 'time': timesteps}
-)
-
-```
-
-**Control variable independence:**
-```python
-# By default: investment sizes are shared across scenarios, flow rates vary
-# To make sizes scenario-independent:
-flow_system = fx.FlowSystem(
- time=timesteps,
- scenarios=scenarios,
- scenario_independent_sizes=True # Each scenario gets its own capacity
-)
-```
-
-### 3. Enhanced I/O and Data Handling
-
-```python
-# Save and load FlowSystem
-flow_system.to_netcdf('my_system.nc')
-flow_system_loaded = fx.FlowSystem.from_netcdf('my_system.nc')
-
-# Manipulate FlowSystem
-fs_subset = flow_system.sel(time=slice('2020-01', '2020-06'))
-fs_resampled = flow_system.resample(time='D') # Resample to daily
-fs_copy = flow_system.copy()
-
-# Access FlowSystem from results (lazily loaded)
-results = calculation.results
-original_fs = results.flow_system # No manual restoration needed
-```
-
-### 4. Effects Per Component
-
-Analyze the impact of each component, including indirect effects through effect shares:
-
-```python
-# Get dataset showing contribution of each component to all effects
-effects_ds = calculation.results.effects_per_component()
-
-print(effects_ds['costs']) # Total costs by component
-print(effects_ds['CO2']) # CO2 emissions by component (including indirect)
-```
-
-### 5. Balanced Storage
-
-Force charging and discharging capacities to be equal:
-
-```python
-storage = fx.Storage(
- 'storage',
- charging=fx.Flow('charge', bus='electricity', size=fx.InvestParameters(effects_per_size=100, minimum_size=5)),
- discharging=fx.Flow('discharge', bus='electricity', size=fx.InvestParameters(),
- balanced=True, # Ensures charge_size == discharge_size
- capacity_in_flow_hours=100
-)
-```
-
-### 6. Final Charge State Control
-
-Set bounds on the storage state at the end of the optimization:
-
-```python
-storage = fx.Storage(
- 'storage',
- charging=fx.Flow('charge', bus='electricity', size=100),
- discharging=fx.Flow('discharge', bus='electricity', size=100),
- capacity_in_flow_hours=10,
- relative_minimum_final_charge_state=0.5, # End at least 50% charged
- relative_maximum_final_charge_state=0.8 # End at most 80% charged
-)
-```
-
----
-
-## Configuration Changes
-
-### Logging (v2.2.0+)
+??? success "Storage Features"
-**Breaking change:** Console and file logging are now disabled by default.
-
-```python
-import flixopt as fx
-
-# Enable console logging
-fx.CONFIG.Logging.console = True
-fx.CONFIG.Logging.level = 'INFO'
-fx.CONFIG.apply()
-
-# Enable file logging
-fx.CONFIG.Logging.file = 'flixopt.log'
-fx.CONFIG.apply()
-
-# Deprecated: change_logging_level() - will be removed in future
-# fx.change_logging_level('INFO') # ❌ Old way
-```
+ | Feature | Parameter | Description |
+ |---------|-----------|-------------|
+ | **Balanced storage** | `balanced=True` | Ensures charge_size == discharge_size |
+ | **Final state min** | `relative_minimum_final_charge_state=0.5` | End at least 50% charged |
+ | **Final state max** | `relative_maximum_final_charge_state=0.8` | End at most 80% charged |
---
-## Testing Your Migration
-
-### 1. Check for Deprecation Warnings
-
-Run your code and watch for deprecation warnings:
-
-```python
-import warnings
-warnings.filterwarnings('default', category=DeprecationWarning)
+## 🔧 Common Issues
-# Run your flixopt code
-# Review any DeprecationWarning messages
-```
-
-### 2. Validate Results
-
-Compare results from v2.x and v3.0.0 to ensure consistency:
-
-```python
-# Save v2.x results before upgrading
-calculation.results.to_file('results_v2.nc')
-
-# After upgrading, compare
-results_v3 = calculation.results
-results_v2 = fx.CalculationResults.from_file('results_v2.nc')
-
-# Check key variables match (within numerical tolerance)
-import numpy as np
-v2_costs = results_v2['effect_values'].sel(effect='costs')
-v3_costs = results_v3['effect_values'].sel(effect='costs')
-np.testing.assert_allclose(v2_costs, v3_costs, rtol=1e-5)
-```
+| Issue | Solution |
+|-------|----------|
+| Effect shares not working | See [Effect System Redesign](#effect-system-redesign) |
+| Storage dimensions wrong | See [FlowSystem & Calculation](#flowsystem-calculation) |
+| Bus assignment error | See [String Labels](#string-labels) |
+| KeyError in results | See [Variable Names](#variable-names) |
+| `AttributeError: model` | Rename `.model` → `.submodel` |
+| No logging | See [Other Changes](#other-changes) |
---
-## Common Migration Issues
-
-### Issue: "Effect share parameters not working"
-
-**Solution:** Effect sharing was completely redesigned. Move share definitions to the **receiving** effect using `share_from_temporal` and `share_from_periodic`.
+## ✅ Checklist
-### Issue: "Storage charge state has wrong dimensions"
-
-**Solution:** Remove the extra timestep from charge state bound arrays.
-
-### Issue: "Import error with Bus assignment"
-
-**Solution:** Pass bus labels (strings) instead of Bus objects to `Flow.bus`.
-
-```python
-# Old
-my_bus = fx.Bus('electricity')
-flow = fx.Flow('P_el', bus=my_bus) # ❌
-
-# New
-my_bus = fx.Bus('electricity')
-flow = fx.Flow('P_el', bus='electricity') # ✅
-```
-
-### Issue: "AttributeError: module 'flixopt' has no attribute 'SystemModel'"
-
-**Solution:** Rename `SystemModel` → `FlowSystemModel`
-
-
----
-
-## Getting Help
-
-- **Documentation:** [https://flixopt.github.io/flixopt/](https://flixopt.github.io/flixopt/)
-- **GitHub Issues:** [https://github.com/flixOpt/flixopt/issues](https://github.com/flixOpt/flixopt/issues)
-- **Changelog:** [Full v3.0.0 release notes](https://flixopt.github.io/flixopt/latest/changelog/99984-v3.0.0/)
+| Category | Tasks |
+|----------|-------|
+| **Install** | • `pip install --upgrade flixopt` |
+| **Breaking changes** | • Update [effect sharing](#effect-system-redesign)
• Update [variable names](#variable-names)
• Update [string labels](#string-labels)
• Fix [storage arrays](#flowsystem-calculation)
• Update [Calculation API](#flowsystem-calculation)
• Rename plotting `mode` → `style`
• Update [class names](#other-changes) |
+| **Configuration** | • Enable [logging](#other-changes) if needed |
+| **Deprecated** | • Update [deprecated parameters](#deprecated-parameters) (recommended) |
+| **Testing** | • Test thoroughly
• Validate results match v2.x |
---
-## Summary Checklist
-
-- [ ] Update flixopt: `pip install --upgrade flixopt`
-- [ ] Update effect sharing syntax (no deprecation warning!)
-- [ ] Update `Calculation.do_modeling()` usage
-- [ ] Fix storage charge state array dimensions
-- [ ] Rename `mode` → `style` in plotting calls
-- [ ] Update deprecated parameter names (optional, but recommended)
-- [ ] Enable logging explicitly if needed
-- [ ] Test your code thoroughly
-- [ ] Explore new features (periods, scenarios, enhanced I/O)
+:material-book: [Docs](https://flixopt.github.io/flixopt/) • :material-github: [Issues](https://github.com/flixOpt/flixopt/issues) • :material-text-box: [Changelog](https://flixopt.github.io/flixopt/latest/changelog/99984-v3.0.0/)
-**Welcome to flixopt v3.0.0!** 🎉
+!!! success "Welcome to flixopt v3.0.0! 🎉"
diff --git a/mkdocs.yml b/mkdocs.yml
index 72ecbe549..8ed2c4b2c 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -91,6 +91,7 @@ markdown_extensions:
line_spans: __span
pygments_lang_class: true
- pymdownx.inlinehilite
+ - pymdownx.details
- pymdownx.superfences
- attr_list
- abbr