From 43c85dd9de863aaf3b61889e19f597783fe8623c Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Wed, 15 Oct 2025 13:45:17 +0200 Subject: [PATCH 01/42] Fix Docs --- docs/user-guide/migration-guide-v3.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/user-guide/migration-guide-v3.md b/docs/user-guide/migration-guide-v3.md index 190503dc3..898bb5377 100644 --- a/docs/user-guide/migration-guide-v3.md +++ b/docs/user-guide/migration-guide-v3.md @@ -239,9 +239,9 @@ This guide helps you migrate your flixopt code from v2.x to v3.0.0. Version 3.0. === "v2.x (Deprecated)" ```python - fx.Source('my_source', source=flow) + flow1 = fx.Source('Buy', bus='Gas) - fx.Sink('my_sink', sink=flow) + flow2 = fx.Flow('Sell', bus='Gas) fx.SourceAndSink( 'my_source_sink', @@ -254,14 +254,14 @@ This guide helps you migrate your flixopt code from v2.x to v3.0.0. Version 3.0. === "v3.0.0 (Recommended)" ```python - fx.Source('my_source', outputs=flow) + flow1 = fx.Source('Buy', bus='Gas) - fx.Sink('my_sink', inputs=flow) + flow2 = fx.Flow('Sell', bus='Gas) fx.SourceAndSink( 'my_source_sink', - outputs=flow1, - inputs=flow2, + outputs=[flow1], + inputs=[flow2], prevent_simultaneous_flow_rates=True ) ``` From fa82b5f352078688fc42cfc92b2486ddbd9a30e3 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 09:37:21 +0200 Subject: [PATCH 02/42] Update Changelog and migration guide for missing breaking changes --- CHANGELOG.md | 31 +++- docs/user-guide/migration-guide-v3.md | 233 ++++++++++++++++++++++++-- 2 files changed, 244 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2a043fc56..e4b0da8ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -139,17 +139,36 @@ 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 sharing system redesigned** (no deprecation): 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` + +**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 +183,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 898bb5377..9ab1079e9 100644 --- a/docs/user-guide/migration-guide-v3.md +++ b/docs/user-guide/migration-guide-v3.md @@ -57,25 +57,141 @@ This guide helps you migrate your flixopt code from v2.x to v3.0.0. Version 3.0. --- -### 2. Class and Variable Renaming +### 2. Variable Renaming in Results + +!!! warning "Breaking Change" + Multiple variables have been renamed in the optimization results. Update all result access accordingly. + +**Investment Variables:** + +=== "v2.x (Old)" + + ```python + # Investment decision variable + results.solution['element|is_invested'] + ``` + +=== "v3.0.0 (New)" + + ```python + # Investment decision variable + results.solution['element|invested'] + ``` + +**Switch Tracking Variables (OnOffModel):** + +=== "v2.x (Old)" + + ```python + # Switch state tracking + results.solution['component|switch_on'] + results.solution['component|switch_off'] + results.solution['component|switch_on_nr'] + ``` + +=== "v3.0.0 (New)" + + ```python + # Switch state tracking with pipe delimiter + results.solution['component|switch|on'] + results.solution['component|switch|off'] + results.solution['component|switch|count'] + ``` + +**Quick Reference Table:** + +| Old Variable Name (v2.x) | New Variable Name (v3.0.0) | Component Type | +|--------------------------|---------------------------|----------------| +| `is_invested` | `invested` | Investment | +| `switch_on` | `switch|on` | OnOff | +| `switch_off` | `switch|off` | OnOff | +| `switch_on_nr` | `switch|count` | OnOff | + +--- + +### 3. FlowSystem Independence + +!!! warning "Breaking Change" + FlowSystems can no longer be shared across multiple Calculations. + +**What changed:** Each `Calculation` now automatically creates its own copy of the FlowSystem, making calculations fully independent. + +**Impact:** +- Mutations to one calculation's FlowSystem won't affect others +- Each `Subcalculation` in `SegmentedCalculation` has its own distinct FlowSystem +- Memory usage may increase slightly due to copying === "v2.x (Old)" ```python - # In optimization results - results.solution['component|is_invested'] + # FlowSystem was shared + flow_system = fx.FlowSystem(time=timesteps) + calc1 = fx.FullCalculation('calc1', flow_system) + calc2 = fx.FullCalculation('calc2', flow_system) + + # Both calculations shared the same FlowSystem object + # Changes in one affected the other ``` === "v3.0.0 (New)" ```python - # In optimization results - results.solution['component|invested'] + # Each calculation gets its own copy + flow_system = fx.FlowSystem(time=timesteps) + calc1 = fx.FullCalculation('calc1', flow_system) # Gets a copy + calc2 = fx.FullCalculation('calc2', flow_system) # Gets another copy + + # Calculations are now independent + # Changes to calc1's FlowSystem won't affect calc2 ``` +!!! tip "Migration" + If you relied on shared FlowSystem behavior (which you most likely did not), you should copy the flow_system before passing it to another calculation. + --- -### 3. Calculation API Change +### 4. Bus and Effect Object Assignment + +!!! warning "Breaking Change" + Direct assignment of Bus and Effect objects is no longer supported. Use string labels instead. + +**Bus Assignment:** + +=== "v2.x (Old)" + + ```python + my_bus = fx.Bus('electricity') + flow = fx.Flow('P_el', bus=my_bus) # ❌ Object assignment + ``` + +=== "v3.0.0 (New)" + + ```python + my_bus = fx.Bus('electricity') + flow = fx.Flow('P_el', bus='electricity') # ✅ String label + ``` + +**Effect Shares Assignment:** + +=== "v2.x (Old)" + + ```python + CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') + costs = fx.Effect('costs', '€', 'Total costs', + share_from_temporal={CO2: 0.2}) # ❌ Effect object + ``` + +=== "v3.0.0 (New)" + + ```python + CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') + costs = fx.Effect('costs', '€', 'Total costs', + share_from_temporal={'CO2': 0.2}) # ✅ String label + ``` + +--- + +### 5. Calculation API Change !!! info "Method Chaining Support" `Calculation.do_modeling()` now returns the Calculation object to enable method chaining. @@ -106,7 +222,7 @@ This guide helps you migrate your flixopt code from v2.x to v3.0.0. Version 3.0. --- -### 4. Storage Charge State Bounds +### 6. Storage Charge State Bounds !!! warning "Array Dimensions Changed" `relative_minimum_charge_state` and `relative_maximum_charge_state` no longer have an extra timestep. @@ -139,7 +255,7 @@ This guide helps you migrate your flixopt code from v2.x to v3.0.0. Version 3.0. --- -### 5. Plotting Parameter Rename +### 7. Plotting Parameter Rename === "v2.x (Old)" @@ -155,6 +271,50 @@ This guide helps you migrate your flixopt code from v2.x to v3.0.0. Version 3.0. --- +### 8. Logging Configuration + +!!! warning "Breaking Change (from v2.2.0)" + Console and file logging are now **disabled by default**. + +**What changed:** In v2.2.0 (before v3.0.0), the default logging behavior was changed to be opt-in rather than opt-out. + +**Impact:** If you're upgrading from v2.1.x or earlier to v3.0.0, you may notice that logging output is no longer displayed unless explicitly enabled. + +=== "v2.1.x and earlier" + + ```python + import flixopt as fx + + # Logging was enabled by default + calculation = fx.FullCalculation('calc', flow_system) + calculation.solve() # Logs were shown automatically + ``` + +=== "v2.2.0+ and v3.0.0" + + ```python + import flixopt as fx + + # Enable console logging explicitly + fx.CONFIG.Logging.console = True + fx.CONFIG.Logging.level = 'INFO' + fx.CONFIG.Logging.file = 'flixopt.log' # Optional: Enable file logging + fx.CONFIG.apply() + + calculation = fx.FullCalculation('calc', flow_system) + calculation.solve() # Now logs are shown + ``` + +!!! tip "Migration" + Add logging configuration at the start of your scripts if you want to see log output: + ```python + import flixopt as fx + fx.CONFIG.Logging.console = True + fx.CONFIG.apply() + ``` + +--- + ## Deprecated Parameters (Still Supported) !!! info "Gradual Migration" @@ -524,6 +684,37 @@ flow = fx.Flow('P_el', bus='electricity') # ✅ **Solution:** Rename `SystemModel` → `FlowSystemModel` +### Issue: "KeyError when accessing results variables" + +**Solution:** Variable names have changed. Update your result access: + +```python +# Old variable names +results.solution['component|is_invested'] # ❌ +results.solution['component|switch_on'] # ❌ +results.solution['component|switch_off'] # ❌ +results.solution['component|switch_on_nr'] # ❌ + +# New variable names +results.solution['component|invested'] # ✅ +results.solution['component|switch|on'] # ✅ +results.solution['component|switch|off'] # ✅ +results.solution['component|switch|count'] # ✅ +``` + +### Issue: "FlowSystem changes affecting multiple calculations" + +**Solution:** FlowSystems are now automatically copied for each Calculation. If you need to access the FlowSystem from a calculation, use `calculation.flow_system` instead of keeping a reference to the original. + +### Issue: "No logging output" + +**Solution:** Logging is disabled by default in v2.2.0+. Enable it explicitly: + +```python +import flixopt as fx +fx.CONFIG.Logging.console = True +fx.CONFIG.apply() +``` --- @@ -537,14 +728,30 @@ flow = fx.Flow('P_el', bus='electricity') # ✅ ## Summary Checklist +**Critical (Breaking Changes):** + - [ ] Update flixopt: `pip install --upgrade flixopt` -- [ ] Update effect sharing syntax (no deprecation warning!) -- [ ] Update `Calculation.do_modeling()` usage -- [ ] Fix storage charge state array dimensions +- [ ] Update effect sharing syntax (no deprecation warning!) - move shares to receiving effect +- [ ] Update all variable names in result access (`is_invested` → `invested`, `switch_on` → `switch|on`, etc.) +- [ ] Replace Bus/Effect object assignments with string labels +- [ ] Remove any code that relies on shared FlowSystem objects across Calculations +- [ ] Update `Calculation.do_modeling()` usage if accessing return value +- [ ] Fix storage charge state array dimensions (remove extra timestep) + +**Important:** + - [ ] Rename `mode` → `style` in plotting calls +- [ ] Enable logging explicitly if needed (`fx.CONFIG.Logging.console = True; fx.CONFIG.apply()`) - [ ] Update deprecated parameter names (optional, but recommended) -- [ ] Enable logging explicitly if needed + +**Testing:** + - [ ] Test your code thoroughly -- [ ] Explore new features (periods, scenarios, enhanced I/O) +- [ ] Check for deprecation warnings +- [ ] Validate results match v2.x output (if upgrading) + +**Optional:** + +- [ ] Explore new features (periods, scenarios, enhanced I/O, balanced storage, final charge state control) **Welcome to flixopt v3.0.0!** 🎉 From a80da63cd47dd3e795056894c76d47c05fd85625 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 10:42:18 +0200 Subject: [PATCH 03/42] Update Migration guide --- docs/user-guide/migration-guide-v3.md | 784 +++++--------------------- 1 file changed, 135 insertions(+), 649 deletions(-) diff --git a/docs/user-guide/migration-guide-v3.md b/docs/user-guide/migration-guide-v3.md index 9ab1079e9..f4b6a6d87 100644 --- a/docs/user-guide/migration-guide-v3.md +++ b/docs/user-guide/migration-guide-v3.md @@ -1,15 +1,14 @@ # 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. +Quick guide for migrating flixopt from v2.x to 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 +## Quick Start + +```bash +pip install --upgrade flixopt +``` + +Review breaking changes, update deprecated parameters, and test thoroughly. --- @@ -17,348 +16,105 @@ This guide helps you migrate your flixopt code from v2.x to v3.0.0. Version 3.0. ### 1. Effect Sharing 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. - -**What changed:** Effects now "pull" shares from other effects instead of "pushing" them. - -=== "v2.x (Old)" - - ```python - # Effects "pushed" shares to other effects - CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions', - specific_share_to_other_effects_operation={'costs': 0.2}) +⚠️ **No deprecation warning** - Effects now "pull" shares instead of "pushing" them. - land = fx.Effect('land', 'm²', 'Land usage', - specific_share_to_other_effects_invest={'costs': 100}) - - costs = fx.Effect('costs', '€', 'Total costs') - ``` - -=== "v3.0.0 (New)" - - ```python - # Effects "pull" shares from other effects (clearer direction) - CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') - - land = fx.Effect('land', 'm²', 'Land usage') +**v2.x:** +```python +CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions', + 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 costs', - share_from_temporal={'CO2': 0.2}, # From temporal (operation) effects - share_from_periodic={'land': 100}) # From periodic (investment) effects - ``` +**v3.0.0:** +```python +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 effects + share_from_periodic={'land': 100}) # From periodic effects +``` -!!! 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` +**Migration:** +- Move share definitions to receiving effect +- `specific_share_to_other_effects_operation` → `share_from_temporal` +- `specific_share_to_other_effects_invest` → `share_from_periodic` --- ### 2. Variable Renaming in Results -!!! warning "Breaking Change" - Multiple variables have been renamed in the optimization results. Update all result access accordingly. - -**Investment Variables:** - -=== "v2.x (Old)" - - ```python - # Investment decision variable - results.solution['element|is_invested'] - ``` - -=== "v3.0.0 (New)" - - ```python - # Investment decision variable - results.solution['element|invested'] - ``` - -**Switch Tracking Variables (OnOffModel):** - -=== "v2.x (Old)" - - ```python - # Switch state tracking - results.solution['component|switch_on'] - results.solution['component|switch_off'] - results.solution['component|switch_on_nr'] - ``` - -=== "v3.0.0 (New)" - - ```python - # Switch state tracking with pipe delimiter - results.solution['component|switch|on'] - results.solution['component|switch|off'] - results.solution['component|switch|count'] - ``` - -**Quick Reference Table:** - -| Old Variable Name (v2.x) | New Variable Name (v3.0.0) | Component Type | -|--------------------------|---------------------------|----------------| -| `is_invested` | `invested` | Investment | -| `switch_on` | `switch|on` | OnOff | -| `switch_off` | `switch|off` | OnOff | -| `switch_on_nr` | `switch|count` | OnOff | - ---- - -### 3. FlowSystem Independence - -!!! warning "Breaking Change" - FlowSystems can no longer be shared across multiple Calculations. - -**What changed:** Each `Calculation` now automatically creates its own copy of the FlowSystem, making calculations fully independent. - -**Impact:** -- Mutations to one calculation's FlowSystem won't affect others -- Each `Subcalculation` in `SegmentedCalculation` has its own distinct FlowSystem -- Memory usage may increase slightly due to copying - -=== "v2.x (Old)" - - ```python - # FlowSystem was shared - flow_system = fx.FlowSystem(time=timesteps) - calc1 = fx.FullCalculation('calc1', flow_system) - calc2 = fx.FullCalculation('calc2', flow_system) - - # Both calculations shared the same FlowSystem object - # Changes in one affected the other - ``` - -=== "v3.0.0 (New)" - - ```python - # Each calculation gets its own copy - flow_system = fx.FlowSystem(time=timesteps) - calc1 = fx.FullCalculation('calc1', flow_system) # Gets a copy - calc2 = fx.FullCalculation('calc2', flow_system) # Gets another copy - - # Calculations are now independent - # Changes to calc1's FlowSystem won't affect calc2 - ``` - -!!! tip "Migration" - If you relied on shared FlowSystem behavior (which you most likely did not), you should copy the flow_system before passing it to another calculation. - ---- - -### 4. Bus and Effect Object Assignment - -!!! warning "Breaking Change" - Direct assignment of Bus and Effect objects is no longer supported. Use string labels instead. - -**Bus Assignment:** - -=== "v2.x (Old)" - - ```python - my_bus = fx.Bus('electricity') - flow = fx.Flow('P_el', bus=my_bus) # ❌ Object assignment - ``` - -=== "v3.0.0 (New)" +| Old (v2.x) | New (v3.0.0) | +|------------|--------------| +| `is_invested` | `invested` | +| `switch_on` | `switch\|on` | +| `switch_off` | `switch\|off` | +| `switch_on_nr` | `switch\|count` | - ```python - my_bus = fx.Bus('electricity') - flow = fx.Flow('P_el', bus='electricity') # ✅ String label - ``` - -**Effect Shares Assignment:** - -=== "v2.x (Old)" - - ```python - CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') - costs = fx.Effect('costs', '€', 'Total costs', - share_from_temporal={CO2: 0.2}) # ❌ Effect object - ``` - -=== "v3.0.0 (New)" - - ```python - CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') - costs = fx.Effect('costs', '€', 'Total costs', - share_from_temporal={'CO2': 0.2}) # ✅ String label - ``` +```python +# Old: results.solution['component|is_invested'] +# New: results.solution['component|invested'] +``` --- -### 5. Calculation API Change - -!!! info "Method Chaining Support" - `Calculation.do_modeling()` now returns the Calculation object to enable method chaining. - -=== "v2.x (Old)" - - ```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) - ``` - -=== "v3.0.0 (New)" +### 3. Use String Labels - ```python - calculation = fx.FullCalculation('my_calc', flow_system) - calculation.do_modeling() # Returns Calculation object - linopy_model = calculation.model # Access model via property +Pass string labels instead of objects: - # This enables chaining operations - fx.FullCalculation('my_calc', flow_system).do_modeling().solve() - ``` +```python +# Old: flow = fx.Flow('P_el', bus=my_bus) +# New: flow = fx.Flow('P_el', bus='electricity') +``` -!!! tip "Migration" - If you used the return value of `do_modeling()`, update to access `.model` property instead. +Applies to Bus assignments and Effect share dictionaries. --- -### 6. 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 - ) - ``` +### 4. FlowSystem Independence -=== "v3.0.0 (New)" - - ```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. +Each `Calculation` now gets its own FlowSystem copy - calculations are fully independent. --- -### 7. Plotting Parameter Rename - -=== "v2.x (Old)" +### 5. Storage Charge State Bounds - ```python - results.plot_heatmap('component|variable', mode='line') - ``` +Array length now matches timesteps (no extra element): -=== "v3.0.0 (New)" - - ```python - results.plot_heatmap('component|variable', style='line') - ``` +```python +storage = fx.Storage( + 'storage', + relative_minimum_charge_state=np.array([0.2, 0.2, 0.2, 0.2]), # Matches timesteps + relative_minimum_final_charge_state=0.3 # New: control final state explicitly +) +``` --- -### 8. Logging Configuration - -!!! warning "Breaking Change (from v2.2.0)" - Console and file logging are now **disabled by default**. - -**What changed:** In v2.2.0 (before v3.0.0), the default logging behavior was changed to be opt-in rather than opt-out. - -**Impact:** If you're upgrading from v2.1.x or earlier to v3.0.0, you may notice that logging output is no longer displayed unless explicitly enabled. - -=== "v2.1.x and earlier" - - ```python - import flixopt as fx - - # Logging was enabled by default - calculation = fx.FullCalculation('calc', flow_system) - calculation.solve() # Logs were shown automatically - ``` - -=== "v2.2.0+ and v3.0.0" - - ```python - import flixopt as fx - - # Enable console logging explicitly - fx.CONFIG.Logging.console = True - fx.CONFIG.Logging.level = 'INFO' - fx.CONFIG.Logging.file = 'flixopt.log' # Optional: Enable file logging - fx.CONFIG.apply() +### 6. Other Breaking Changes - calculation = fx.FullCalculation('calc', flow_system) - calculation.solve() # Now logs are shown - ``` - -!!! tip "Migration" - Add logging configuration at the start of your scripts if you want to see log output: - ```python - import flixopt as fx - fx.CONFIG.Logging.console = True - fx.CONFIG.apply() - ``` +- **`do_modeling()` return value:** Now returns `Calculation` object (access model via `.model` property) +- **Plotting:** `mode` parameter renamed to `style` +- **Logging:** Disabled by default (enable with `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 (Still Work) ### InvestParameters -**Parameter Changes:** - -| Old Parameter (v2.x) | New Parameter (v3.0.0) | -|---------------------|----------------------| +| Old | New | +|-----|-----| | `fix_effects` | `effects_of_investment` | | `specific_effects` | `effects_of_investment_per_size` | | `divest_effects` | `effects_of_retirement` | | `piecewise_effects` | `piecewise_effects_of_investment` | -=== "v2.x (Deprecated)" - - ```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) | -|---------------------|----------------------| +| Old | New | +|-----|-----| | `minimum_investment` | `minimum_periodic` | | `maximum_investment` | `maximum_periodic` | | `minimum_operation` | `minimum_temporal` | @@ -366,392 +122,122 @@ This guide helps you migrate your flixopt code from v2.x to v3.0.0. Version 3.0. | `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, - ) - ``` - -=== "v3.0.0 (Recommended)" - - ```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, - ) - ``` - -### Component Parameters - -=== "v2.x (Deprecated)" - - ```python - flow1 = fx.Source('Buy', bus='Gas) - - flow2 = fx.Flow('Sell', bus='Gas) - - fx.SourceAndSink( - 'my_source_sink', - source=flow1, - sink=flow2, - prevent_simultaneous_sink_and_source=True - ) - ``` - -=== "v3.0.0 (Recommended)" - - ```python - flow1 = fx.Source('Buy', bus='Gas) - - flow2 = fx.Flow('Sell', bus='Gas) - - fx.SourceAndSink( - 'my_source_sink', - outputs=[flow1], - inputs=[flow2], - prevent_simultaneous_flow_rates=True - ) - ``` - -### TimeSeriesData - -=== "v2.x (Deprecated)" +### SourceAndSink - ```python - fx.TimeSeriesData( - agg_group='group1', - agg_weight=2.0 - ) - ``` +| Old | New | +|-----|-----| +| `source` | `outputs` | +| `sink` | `inputs` | +| `prevent_simultaneous_sink_and_source` | `prevent_simultaneous_flow_rates` | -=== "v3.0.0 (Recommended)" +### TimeSeriesData - ```python - fx.TimeSeriesData( - aggregation_group='group1', - aggregation_weight=2.0 - ) - ``` +| Old | New | +|-----|-----| +| `agg_group` | `aggregation_group` | +| `agg_weight` | `aggregation_weight` | ### Calculation -=== "v2.x (Deprecated)" - - ```python - calculation = fx.FullCalculation( - 'calc', - flow_system, - active_timesteps=[0, 1, 2] - ) - ``` - -=== "v3.0.0 (Recommended)" - - ```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) - - # Or with isel for index-based selection - flow_system_subset = flow_system.isel(time=slice(0, 3)) - calculation = fx.FullCalculation('calc', flow_system_subset) - ``` +Replace `active_timesteps` with FlowSystem selection: +```python +# Old: calculation = fx.FullCalculation('calc', flow_system, active_timesteps=[0, 1, 2]) +# New: +fs_subset = flow_system.isel(time=slice(0, 3)) +calculation = fx.FullCalculation('calc', fs_subset) +``` --- -## New Features in v3.0.0 - -### 1. Multi-Period Investments +## New Features -Model transformation pathways with distinct investment decisions in each period: +### Multi-Period Investments ```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} - ) - )] -) +solar = fx.Source('solar', outputs=[fx.Flow('P_el', bus='electricity', + size=fx.InvestParameters(minimum_size=0, maximum_size=1000))]) ``` -### 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} -) - -``` +### Scenario-Based Stochastic Optimization -**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 -) +scenarios = pd.Index(['low', 'base', 'high'], name='scenario') +flow_system = fx.FlowSystem(time=timesteps, scenarios=scenarios, + scenario_weights=[0.2, 0.6, 0.2], + scenario_independent_sizes=True) # Optional: scenario-specific capacities ``` -### 3. Enhanced I/O and Data Handling +### Enhanced I/O ```python -# Save and load FlowSystem -flow_system.to_netcdf('my_system.nc') -flow_system_loaded = fx.FlowSystem.from_netcdf('my_system.nc') - -# Manipulate FlowSystem +flow_system.to_netcdf('system.nc') +fs = fx.FlowSystem.from_netcdf('system.nc') 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 +fs_resampled = flow_system.resample(time='D') ``` -### 4. Effects Per Component - -Analyze the impact of each component, including indirect effects through effect shares: +### Effects Per Component ```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) +print(effects_ds['costs']) # Costs by component ``` -### 5. Balanced Storage - -Force charging and discharging capacities to be equal: +### Balanced Storage ```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 -) +storage = fx.Storage('storage', + charging=fx.Flow('charge', bus='electricity', size=fx.InvestParameters(...)), + discharging=fx.Flow('discharge', bus='electricity', size=fx.InvestParameters(...)), + balanced=True, # Charge size == discharge size + capacity_in_flow_hours=100) ``` --- -## Configuration Changes +## Common Issues -### Logging (v2.2.0+) +**"Effect share parameters not working"** +→ Move shares to receiving effect using `share_from_temporal`/`share_from_periodic` -**Breaking change:** Console and file logging are now disabled by default. +**"Storage charge state has wrong dimensions"** +→ Remove extra timestep; use `relative_minimum_final_charge_state` -```python -import flixopt as fx +**"KeyError when accessing results"** +→ Update variable names (`is_invested` → `invested`, etc.) -# 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 -``` +**"No logging output"** +→ Enable explicitly: `fx.CONFIG.Logging.console = True; fx.CONFIG.apply()` --- -## Testing Your Migration - -### 1. Check for Deprecation Warnings - -Run your code and watch for deprecation warnings: - -```python -import warnings -warnings.filterwarnings('default', category=DeprecationWarning) - -# 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) -``` - ---- - -## 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`. - -### 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` - -### Issue: "KeyError when accessing results variables" - -**Solution:** Variable names have changed. Update your result access: - -```python -# Old variable names -results.solution['component|is_invested'] # ❌ -results.solution['component|switch_on'] # ❌ -results.solution['component|switch_off'] # ❌ -results.solution['component|switch_on_nr'] # ❌ - -# New variable names -results.solution['component|invested'] # ✅ -results.solution['component|switch|on'] # ✅ -results.solution['component|switch|off'] # ✅ -results.solution['component|switch|count'] # ✅ -``` - -### Issue: "FlowSystem changes affecting multiple calculations" - -**Solution:** FlowSystems are now automatically copied for each Calculation. If you need to access the FlowSystem from a calculation, use `calculation.flow_system` instead of keeping a reference to the original. - -### Issue: "No logging output" - -**Solution:** Logging is disabled by default in v2.2.0+. Enable it explicitly: - -```python -import flixopt as fx -fx.CONFIG.Logging.console = True -fx.CONFIG.apply() -``` - ---- - -## 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/) - ---- - -## Summary Checklist - -**Critical (Breaking Changes):** +## Migration Checklist +**Critical:** - [ ] Update flixopt: `pip install --upgrade flixopt` -- [ ] Update effect sharing syntax (no deprecation warning!) - move shares to receiving effect -- [ ] Update all variable names in result access (`is_invested` → `invested`, `switch_on` → `switch|on`, etc.) -- [ ] Replace Bus/Effect object assignments with string labels -- [ ] Remove any code that relies on shared FlowSystem objects across Calculations -- [ ] Update `Calculation.do_modeling()` usage if accessing return value -- [ ] Fix storage charge state array dimensions (remove extra timestep) - -**Important:** - -- [ ] Rename `mode` → `style` in plotting calls -- [ ] Enable logging explicitly if needed (`fx.CONFIG.Logging.console = True; fx.CONFIG.apply()`) -- [ ] Update deprecated parameter names (optional, but recommended) - -**Testing:** - -- [ ] Test your code thoroughly -- [ ] Check for deprecation warnings -- [ ] Validate results match v2.x output (if upgrading) +- [ ] Update effect sharing syntax +- [ ] Update result variable names +- [ ] Replace object assignments with string labels +- [ ] Fix storage charge state arrays +- [ ] Update `do_modeling()` usage if needed +- [ ] Rename plotting `mode` → `style` +- [ ] Enable logging if needed + +**Recommended:** +- [ ] Update deprecated parameter names +- [ ] Test thoroughly and validate results **Optional:** - -- [ ] Explore new features (periods, scenarios, enhanced I/O, balanced storage, final charge state control) +- [ ] Explore new features (periods, scenarios, balanced storage) **Welcome to flixopt v3.0.0!** 🎉 +--- + +## Resources + +- **Docs:** https://flixopt.github.io/flixopt/latest/ +- **Issues:** https://github.com/flixOpt/flixopt/issues +- **Changelog:** https://flixopt.github.io/flixopt/latest/changelog/99984-v3.0.0/ From 344cf92c659a6bdc6c1b3b8e2f54c0c4f7dd135e Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 10:46:54 +0200 Subject: [PATCH 04/42] Improve --- CHANGELOG.md | 4 +- docs/user-guide/migration-guide-v3.md | 73 ++++++++++++++++++++------- 2 files changed, 57 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4b0da8ce..f8e4c7a55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -141,7 +141,9 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir **API and Behavior Changes:** -- **Effect sharing system redesigned** (no deprecation): 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) +- **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 diff --git a/docs/user-guide/migration-guide-v3.md b/docs/user-guide/migration-guide-v3.md index f4b6a6d87..eca068ce1 100644 --- a/docs/user-guide/migration-guide-v3.md +++ b/docs/user-guide/migration-guide-v3.md @@ -14,16 +14,29 @@ Review breaking changes, update deprecated parameters, and test thoroughly. ## Breaking Changes -### 1. Effect Sharing System Redesign +### 1. Effect System Redesign -⚠️ **No deprecation warning** - Effects now "pull" shares instead of "pushing" them. +⚠️ **Multiple effect-related changes** - terminology and sharing system redesigned. + +**Terminology Changes:** + +Effect domains have been renamed for clarity: + +| Old Term (v2.x) | New Term (v3.0.0) | Meaning | +|-----------------|-------------------|-------------------------------------------------------------------------| +| `operation` | `temporal` | Time-varying effects (e.g., operational costs, occuring over time) | +| `invest` / `investment` | `periodic` | Investment-related effects (e.g., fixed costs per period, annuity, ...) | + +**Effect Sharing System (⚠️ No deprecation warning):** + +Effects now "pull" shares from other effects instead of "pushing" them. **v2.x:** ```python CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions', - specific_share_to_other_effects_operation={'costs': 0.2}) + specific_share_to_other_effects_operation={'costs': 0.2}) # operation → temporal land = fx.Effect('land', 'm²', 'Land usage', - specific_share_to_other_effects_invest={'costs': 100}) + specific_share_to_other_effects_invest={'costs': 100}) # invest → periodic costs = fx.Effect('costs', '€', 'Total costs') ``` @@ -32,14 +45,18 @@ costs = fx.Effect('costs', '€', 'Total costs') 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 effects - share_from_periodic={'land': 100}) # From periodic effects + share_from_temporal={'CO2': 0.2}, # Pulls from temporal effects + share_from_periodic={'land': 100}) # Pulls from periodic effects ``` **Migration:** -- Move share definitions to receiving effect -- `specific_share_to_other_effects_operation` → `share_from_temporal` -- `specific_share_to_other_effects_invest` → `share_from_periodic` +1. Move share definitions to the receiving effect +2. Update parameter names: + - `specific_share_to_other_effects_operation` → `share_from_temporal` + - `specific_share_to_other_effects_invest` → `share_from_periodic` +3. Update terminology throughout your code: + - Replace "operation" with "temporal" in effect-related contexts + - Replace "invest/investment" with "periodic" in effect-related contexts --- @@ -59,26 +76,25 @@ costs = fx.Effect('costs', '€', 'Total costs', --- -### 3. Use String Labels +### 3. Bus and Effect Assignment - Use String Labels Pass string labels instead of objects: +**Bus Assignment:** ```python -# Old: flow = fx.Flow('P_el', bus=my_bus) +# Old: flow = fx.Flow('P_el', bus=my_bus_object) # New: flow = fx.Flow('P_el', bus='electricity') ``` -Applies to Bus assignments and Effect share dictionaries. - ---- - -### 4. FlowSystem Independence - -Each `Calculation` now gets its own FlowSystem copy - calculations are fully independent. +**Effect Shares:** +```python +# Old: costs = fx.Effect('costs', '€', share_from_temporal={CO2_object: 0.2}) +# New: costs = fx.Effect('costs', '€', share_from_temporal={'CO2': 0.2}) +``` --- -### 5. Storage Charge State Bounds +### 4. Storage Charge State Bounds Array length now matches timesteps (no extra element): @@ -92,10 +108,29 @@ storage = fx.Storage( --- +### 5. FlowSystem Independence + +Each `Calculation` now gets its own FlowSystem copy - calculations are fully independent. + +```python +# v2.x: FlowSystem was shared across calculations +flow_system = fx.FlowSystem(time=timesteps) +calc1 = fx.FullCalculation('calc1', flow_system) # Shared reference +calc2 = fx.FullCalculation('calc2', flow_system) # Same reference + +# v3.0.0: Each calculation gets a copy +flow_system = fx.FlowSystem(time=timesteps) +calc1 = fx.FullCalculation('calc1', flow_system) +calc2 = fx.FullCalculation('calc2', flow_system) # Gets separate copy +``` + +--- + ### 6. Other Breaking Changes - **`do_modeling()` return value:** Now returns `Calculation` object (access model via `.model` property) - **Plotting:** `mode` parameter renamed to `style` +- **Class names:** `SystemModel` → `FlowSystemModel`, `Model` → `Submodel` - **Logging:** Disabled by default (enable with `fx.CONFIG.Logging.console = True; fx.CONFIG.apply()`) --- From fbac19149a36385a0b78664342f2d6ff04b25549 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 10:50:59 +0200 Subject: [PATCH 05/42] Use tabs in mkdocs --- docs/user-guide/migration-guide-v3.md | 193 ++++++++++++++++++-------- 1 file changed, 133 insertions(+), 60 deletions(-) diff --git a/docs/user-guide/migration-guide-v3.md b/docs/user-guide/migration-guide-v3.md index eca068ce1..08e06dcaa 100644 --- a/docs/user-guide/migration-guide-v3.md +++ b/docs/user-guide/migration-guide-v3.md @@ -31,23 +31,25 @@ Effect domains have been renamed for clarity: Effects now "pull" shares from other effects instead of "pushing" them. -**v2.x:** -```python -CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions', - specific_share_to_other_effects_operation={'costs': 0.2}) # operation → temporal -land = fx.Effect('land', 'm²', 'Land usage', - specific_share_to_other_effects_invest={'costs': 100}) # invest → periodic -costs = fx.Effect('costs', '€', 'Total costs') -``` - -**v3.0.0:** -```python -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}, # Pulls from temporal effects - share_from_periodic={'land': 100}) # Pulls from periodic effects -``` +=== "v2.x (Old)" + + ```python + CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions', + specific_share_to_other_effects_operation={'costs': 0.2}) # operation → temporal + land = fx.Effect('land', 'm²', 'Land usage', + specific_share_to_other_effects_invest={'costs': 100}) # invest → periodic + costs = fx.Effect('costs', '€', 'Total costs') + ``` + +=== "v3.0.0 (New)" + + ```python + 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}, # Pulls from temporal effects + share_from_periodic={'land': 100}) # Pulls from periodic effects + ``` **Migration:** 1. Move share definitions to the receiving effect @@ -69,42 +71,96 @@ costs = fx.Effect('costs', '€', 'Total costs', | `switch_off` | `switch\|off` | | `switch_on_nr` | `switch\|count` | -```python -# Old: results.solution['component|is_invested'] -# New: results.solution['component|invested'] -``` +=== "v2.x (Old)" + + ```python + # Access investment decision + results.solution['component|is_invested'] + + # Access switch tracking + results.solution['component|switch_on'] + results.solution['component|switch_off'] + results.solution['component|switch_on_nr'] + ``` + +=== "v3.0.0 (New)" + + ```python + # Access investment decision + results.solution['component|invested'] + + # Access switch tracking + results.solution['component|switch|on'] + results.solution['component|switch|off'] + results.solution['component|switch|count'] + ``` --- ### 3. Bus and Effect Assignment - Use String Labels -Pass string labels instead of objects: +Pass string labels instead of objects. **Bus Assignment:** -```python -# Old: flow = fx.Flow('P_el', bus=my_bus_object) -# New: flow = fx.Flow('P_el', bus='electricity') -``` + +=== "v2.x (Old)" + + ```python + my_bus = fx.Bus('electricity') + flow = fx.Flow('P_el', bus=my_bus) # ❌ Object + ``` + +=== "v3.0.0 (New)" + + ```python + my_bus = fx.Bus('electricity') + flow = fx.Flow('P_el', bus='electricity') # ✅ String label + ``` **Effect Shares:** -```python -# Old: costs = fx.Effect('costs', '€', share_from_temporal={CO2_object: 0.2}) -# New: costs = fx.Effect('costs', '€', share_from_temporal={'CO2': 0.2}) -``` + +=== "v2.x (Old)" + + ```python + CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') + costs = fx.Effect('costs', '€', 'Total costs', + share_from_temporal={CO2: 0.2}) # ❌ Object + ``` + +=== "v3.0.0 (New)" + + ```python + CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') + costs = fx.Effect('costs', '€', 'Total costs', + share_from_temporal={'CO2': 0.2}) # ✅ String label + ``` --- ### 4. Storage Charge State Bounds -Array length now matches timesteps (no extra element): +Array length now matches timesteps (no extra element). -```python -storage = fx.Storage( - 'storage', - relative_minimum_charge_state=np.array([0.2, 0.2, 0.2, 0.2]), # Matches timesteps - relative_minimum_final_charge_state=0.3 # New: control final state explicitly -) -``` +=== "v2.x (Old)" + + ```python + # Array had 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)" + + ```python + # Array matches timesteps exactly + 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 # New: control final state explicitly + ) + ``` --- @@ -112,17 +168,25 @@ storage = fx.Storage( Each `Calculation` now gets its own FlowSystem copy - calculations are fully independent. -```python -# v2.x: FlowSystem was shared across calculations -flow_system = fx.FlowSystem(time=timesteps) -calc1 = fx.FullCalculation('calc1', flow_system) # Shared reference -calc2 = fx.FullCalculation('calc2', flow_system) # Same reference - -# v3.0.0: Each calculation gets a copy -flow_system = fx.FlowSystem(time=timesteps) -calc1 = fx.FullCalculation('calc1', flow_system) -calc2 = fx.FullCalculation('calc2', flow_system) # Gets separate copy -``` +=== "v2.x (Old)" + + ```python + # FlowSystem was shared across calculations + flow_system = fx.FlowSystem(time=timesteps) + calc1 = fx.FullCalculation('calc1', flow_system) # Shared reference + calc2 = fx.FullCalculation('calc2', flow_system) # Same reference + # Changes in calc1's FlowSystem would affect calc2 + ``` + +=== "v3.0.0 (New)" + + ```python + # Each calculation gets a copy + flow_system = fx.FlowSystem(time=timesteps) + calc1 = fx.FullCalculation('calc1', flow_system) # Gets copy + calc2 = fx.FullCalculation('calc2', flow_system) # Gets separate copy + # Calculations are now independent + ``` --- @@ -175,18 +239,27 @@ calc2 = fx.FullCalculation('calc2', flow_system) # Gets separate copy ### Calculation Replace `active_timesteps` with FlowSystem selection: -```python -# Old: calculation = fx.FullCalculation('calc', flow_system, active_timesteps=[0, 1, 2]) -# New: -fs_subset = flow_system.isel(time=slice(0, 3)) -calculation = fx.FullCalculation('calc', fs_subset) -``` + +=== "v2.x (Deprecated)" + + ```python + calculation = fx.FullCalculation('calc', flow_system, + active_timesteps=[0, 1, 2]) + ``` + +=== "v3.0.0 (Recommended)" + + ```python + # Use FlowSystem selection methods + fs_subset = flow_system.isel(time=slice(0, 3)) + calculation = fx.FullCalculation('calc', fs_subset) + ``` --- ## New Features -### Multi-Period Investments +**Multi-Period Investments** - Model transformation pathways with distinct decisions in each period: ```python periods = pd.Index(['2020', '2030']) @@ -196,7 +269,7 @@ solar = fx.Source('solar', outputs=[fx.Flow('P_el', bus='electricity', size=fx.InvestParameters(minimum_size=0, maximum_size=1000))]) ``` -### Scenario-Based Stochastic Optimization +**Scenario-Based Stochastic Optimization** - Handle uncertainty with weighted scenarios: ```python scenarios = pd.Index(['low', 'base', 'high'], name='scenario') @@ -205,7 +278,7 @@ flow_system = fx.FlowSystem(time=timesteps, scenarios=scenarios, scenario_independent_sizes=True) # Optional: scenario-specific capacities ``` -### Enhanced I/O +**Enhanced I/O** - Save, load, and manipulate FlowSystems: ```python flow_system.to_netcdf('system.nc') @@ -214,14 +287,14 @@ fs_subset = flow_system.sel(time=slice('2020-01', '2020-06')) fs_resampled = flow_system.resample(time='D') ``` -### Effects Per Component +**Effects Per Component** - Analyze component impacts including indirect effects: ```python effects_ds = calculation.results.effects_per_component() print(effects_ds['costs']) # Costs by component ``` -### Balanced Storage +**Balanced Storage** - Force equal charging and discharging capacities: ```python storage = fx.Storage('storage', From ef35d90b2ca0e96af4e5a6798eda5da5d9bfea3b Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 10:59:02 +0200 Subject: [PATCH 06/42] Update varaibel renaming --- CHANGELOG.md | 3 ++ docs/user-guide/migration-guide-v3.md | 40 +++++++++++++++++++-------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8e4c7a55..e0b44da77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -164,6 +164,9 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir - `switch_on` → `switch|on` - `switch_off` → `switch|off` - `switch_on_nr` → `switch|count` +- Effect submodel variables (following terminology changes): + - `Effect|nontemporal|...` → `Effect|periodic|...` + - `Effect|operation|...` → `Effect|temporal|...` **Data Structure Changes:** diff --git a/docs/user-guide/migration-guide-v3.md b/docs/user-guide/migration-guide-v3.md index 08e06dcaa..8d0eeef6c 100644 --- a/docs/user-guide/migration-guide-v3.md +++ b/docs/user-guide/migration-guide-v3.md @@ -64,35 +64,53 @@ Effects now "pull" shares from other effects instead of "pushing" them. ### 2. Variable Renaming in Results -| Old (v2.x) | New (v3.0.0) | -|------------|--------------| -| `is_invested` | `invested` | -| `switch_on` | `switch\|on` | -| `switch_off` | `switch\|off` | -| `switch_on_nr` | `switch\|count` | +Multiple variables have been renamed following the terminology changes. + +**Quick Reference Table:** + +| Category | Old (v2.x) | New (v3.0.0) | +|------------------|------------------------------------|----------------| +| Investment | `is_invested` | `invested` | +| Switch tracking | `switch_on` | `switch\|on` | +| Switch tracking | `switch_off` | `switch\|off` | +| Switch tracking | `switch_on_nr` | `switch\|count` | +| Effect submodels | `Effect(invest)\|total` | `Effect(periodic)` | +| Effect submodels | `Effect(operation)\|total` | `Effect(temporal)` | +| Effect submodels | `Effect(operation)\|total_per_timestep` | `Effect(temporal)\|per_tiemstep` | +| Effect submodels | `Effect\|total` | `Effect` | + +**Examples:** === "v2.x (Old)" ```python - # Access investment decision + # Investment decision results.solution['component|is_invested'] - # Access switch tracking + # Switch tracking results.solution['component|switch_on'] results.solution['component|switch_off'] results.solution['component|switch_on_nr'] + + # Effect variables (operation → temporal, nontemporal → periodic) + results.solution['costs|nontemporal|total'] + results.solution['costs|operation|total'] ``` === "v3.0.0 (New)" ```python - # Access investment decision + # Investment decision results.solution['component|invested'] - # Access switch tracking + # Switch tracking results.solution['component|switch|on'] results.solution['component|switch|off'] results.solution['component|switch|count'] + + # Effect variables (with new terminology) + results.solution['costs|periodic|total'] + results.solution['costs|temporal|total'] ``` --- @@ -158,7 +176,7 @@ Array length now matches timesteps (no extra element). 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 # New: control final state explicitly + #relative_minimum_final_charge_state=0.3 # New: control final state explicitly if its different from the last value above ) ``` From 9f50ca243d695786d6cb011f597c80f465fa70db Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 11:00:51 +0200 Subject: [PATCH 07/42] Update variable renaming --- CHANGELOG.md | 6 ++++-- docs/user-guide/migration-guide-v3.md | 22 ++++++++++++++++------ 2 files changed, 20 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e0b44da77..c10105538 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -165,8 +165,10 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir - `switch_off` → `switch|off` - `switch_on_nr` → `switch|count` - Effect submodel variables (following terminology changes): - - `Effect|nontemporal|...` → `Effect|periodic|...` - - `Effect|operation|...` → `Effect|temporal|...` + - `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:** diff --git a/docs/user-guide/migration-guide-v3.md b/docs/user-guide/migration-guide-v3.md index 8d0eeef6c..2b0d3ebe9 100644 --- a/docs/user-guide/migration-guide-v3.md +++ b/docs/user-guide/migration-guide-v3.md @@ -92,9 +92,11 @@ Multiple variables have been renamed following the terminology changes. results.solution['component|switch_off'] results.solution['component|switch_on_nr'] - # Effect variables (operation → temporal, nontemporal → periodic) - results.solution['costs|nontemporal|total'] - results.solution['costs|operation|total'] + # Effect variables + results.solution['costs(invest)|total'] + results.solution['costs(operation)|total'] + results.solution['costs(operation)|total_per_timestep'] + results.solution['costs|total'] ``` === "v3.0.0 (New)" @@ -109,8 +111,10 @@ Multiple variables have been renamed following the terminology changes. results.solution['component|switch|count'] # Effect variables (with new terminology) - results.solution['costs|periodic|total'] - results.solution['costs|temporal|total'] + results.solution['costs(periodic)'] + results.solution['costs(temporal)'] + results.solution['costs(temporal)|per_timestep'] + results.solution['costs'] ``` --- @@ -333,7 +337,13 @@ storage = fx.Storage('storage', → Remove extra timestep; use `relative_minimum_final_charge_state` **"KeyError when accessing results"** -→ Update variable names (`is_invested` → `invested`, etc.) +→ Update variable names: + - `is_invested` → `invested` + - `switch_on` → `switch|on`, `switch_off` → `switch|off`, `switch_on_nr` → `switch|count` + - `Effect(invest)|total` → `Effect(periodic)` + - `Effect(operation)|total` → `Effect(temporal)` + - `Effect(operation)|total_per_timestep` → `Effect(temporal)|per_timestep` + - `Effect|total` → `Effect` **"No logging output"** → Enable explicitly: `fx.CONFIG.Logging.console = True; fx.CONFIG.apply()` From cd3df05bc2093c11649083ecf85c3452389da6a9 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 11:22:19 +0200 Subject: [PATCH 08/42] From main --- docs/user-guide/migration-guide-v3.md | 458 +++++++++++++++++++------- 1 file changed, 332 insertions(+), 126 deletions(-) diff --git a/docs/user-guide/migration-guide-v3.md b/docs/user-guide/migration-guide-v3.md index 2b0d3ebe9..0ba6f8114 100644 --- a/docs/user-guide/migration-guide-v3.md +++ b/docs/user-guide/migration-guide-v3.md @@ -1,24 +1,18 @@ -# Migration Guide: Upgrading to v3.0.0 +# Migration Guide: v2.x → v3.0.0 Quick guide for migrating flixopt from v2.x to v3.0.0. -## Quick Start - -```bash -pip install --upgrade flixopt -``` - -Review breaking changes, update deprecated parameters, and test thoroughly. +!!! tip "Quick Start" + ```bash + pip install --upgrade flixopt + ``` + Review breaking changes below, update deprecated parameters, and test thoroughly. --- ## Breaking Changes -### 1. Effect System Redesign - -⚠️ **Multiple effect-related changes** - terminology and sharing system redesigned. - -**Terminology Changes:** +**Effect System Redesign** - terminology and sharing system redesigned. Effect domains have been renamed for clarity: @@ -27,8 +21,6 @@ Effect domains have been renamed for clarity: | `operation` | `temporal` | Time-varying effects (e.g., operational costs, occuring over time) | | `invest` / `investment` | `periodic` | Investment-related effects (e.g., fixed costs per period, annuity, ...) | -**Effect Sharing System (⚠️ No deprecation warning):** - Effects now "pull" shares from other effects instead of "pushing" them. === "v2.x (Old)" @@ -62,24 +54,20 @@ Effects now "pull" shares from other effects instead of "pushing" them. --- -### 2. Variable Renaming in Results - -Multiple variables have been renamed following the terminology changes. +**Variable Renaming in Results** -**Quick Reference Table:** +Multiple variables renamed following terminology changes. | Category | Old (v2.x) | New (v3.0.0) | |------------------|------------------------------------|----------------| | Investment | `is_invested` | `invested` | -| Switch tracking | `switch_on` | `switch\|on` | -| Switch tracking | `switch_off` | `switch\|off` | -| Switch tracking | `switch_on_nr` | `switch\|count` | -| Effect submodels | `Effect(invest)\|total` | `Effect(periodic)` | -| Effect submodels | `Effect(operation)\|total` | `Effect(temporal)` | -| Effect submodels | `Effect(operation)\|total_per_timestep` | `Effect(temporal)\|per_tiemstep` | -| Effect submodels | `Effect\|total` | `Effect` | - -**Examples:** +| Switch tracking | `switch_on` | `switch|on` | +| Switch tracking | `switch_off` | `switch|off` | +| Switch tracking | `switch_on_nr` | `switch|count` | +| Effect submodels | `Effect(invest)|total` | `Effect(periodic)` | +| Effect submodels | `Effect(operation)|total` | `Effect(temporal)` | +| Effect submodels | `Effect(operation)|total_per_timestep` | `Effect(temporal)|per_timestep` | +| Effect submodels | `Effect|total` | `Effect` | === "v2.x (Old)" @@ -119,76 +107,83 @@ Multiple variables have been renamed following the terminology changes. --- -### 3. Bus and Effect Assignment - Use String Labels - -Pass string labels instead of objects. - -**Bus Assignment:** +**Calculation API** - `do_modeling()` now returns `Calculation` object for method chaining === "v2.x (Old)" ```python - my_bus = fx.Bus('electricity') - flow = fx.Flow('P_el', bus=my_bus) # ❌ Object + calculation = fx.FullCalculation('my_calc', flow_system) + linopy_model = calculation.do_modeling() # Returned linopy.Model + + # Access model directly from return value + print(linopy_model) ``` === "v3.0.0 (New)" ```python - my_bus = fx.Bus('electricity') - flow = fx.Flow('P_el', bus='electricity') # ✅ String label + 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() ``` -**Effect Shares:** +--- + +**Storage Charge State** - Arrays no longer have extra timestep === "v2.x (Old)" ```python - CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') - costs = fx.Effect('costs', '€', 'Total costs', - share_from_temporal={CO2: 0.2}) # ❌ Object + # 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)" ```python - CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') - costs = fx.Effect('costs', '€', 'Total costs', - share_from_temporal={'CO2': 0.2}) # ✅ String label + # 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 + ) ``` --- -### 4. Storage Charge State Bounds - -Array length now matches timesteps (no extra element). +**Bus and Effect Assignment** - Use string labels instead of objects === "v2.x (Old)" ```python - # Array had 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 - ) + my_bus = fx.Bus('electricity') + flow = fx.Flow('P_el', bus=my_bus) # ❌ Object + + CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') + costs = fx.Effect('costs', '€', 'Total costs', + share_from_temporal={CO2: 0.2}) # ❌ Object ``` === "v3.0.0 (New)" ```python - # Array matches timesteps exactly - 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 # New: control final state explicitly if its different from the last value above - ) + my_bus = fx.Bus('electricity') + flow = fx.Flow('P_el', bus='electricity') # ✅ String label + + CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') + costs = fx.Effect('costs', '€', 'Total costs', + share_from_temporal={'CO2': 0.2}) # ✅ String label ``` --- -### 5. FlowSystem Independence - -Each `Calculation` now gets its own FlowSystem copy - calculations are fully independent. +**FlowSystem Independence** - Each Calculation gets its own copy === "v2.x (Old)" @@ -212,30 +207,54 @@ Each `Calculation` now gets its own FlowSystem copy - calculations are fully ind --- -### 6. Other Breaking Changes +**Other Breaking Changes:** -- **`do_modeling()` return value:** Now returns `Calculation` object (access model via `.model` property) - **Plotting:** `mode` parameter renamed to `style` - **Class names:** `SystemModel` → `FlowSystemModel`, `Model` → `Submodel` - **Logging:** Disabled by default (enable with `fx.CONFIG.Logging.console = True; fx.CONFIG.apply()`) --- -## Deprecated Parameters (Still Work) +## Deprecated Parameters + +!!! info "Still Work" + These parameters still work but will be removed in a future version. Deprecation warnings will guide you. -### InvestParameters +**InvestParameters:** -| Old | New | -|-----|-----| +| 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` | -### Effect +=== "v2.x (Deprecated)" + + ```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:** -| Old | New | -|-----|-----| +| Old Parameter (v2.x) | New Parameter (v3.0.0) | +|---------------------|----------------------| | `minimum_investment` | `minimum_periodic` | | `maximum_investment` | `maximum_periodic` | | `minimum_operation` | `minimum_temporal` | @@ -243,87 +262,265 @@ Each `Calculation` now gets its own FlowSystem copy - calculations are fully ind | `minimum_operation_per_hour` | `minimum_per_hour` | | `maximum_operation_per_hour` | `maximum_per_hour` | -### SourceAndSink +=== "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, + ) + ``` + +=== "v3.0.0 (Recommended)" + + ```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, + ) + ``` -| Old | New | -|-----|-----| -| `source` | `outputs` | -| `sink` | `inputs` | -| `prevent_simultaneous_sink_and_source` | `prevent_simultaneous_flow_rates` | +**Component Parameters:** -### TimeSeriesData +=== "v2.x (Deprecated)" -| Old | New | -|-----|-----| -| `agg_group` | `aggregation_group` | -| `agg_weight` | `aggregation_weight` | + ```python + fx.Source('my_source', source=flow) -### Calculation + fx.Sink('my_sink', sink=flow) -Replace `active_timesteps` with FlowSystem selection: + fx.SourceAndSink( + 'my_source_sink', + source=flow1, + sink=flow2, + prevent_simultaneous_sink_and_source=True + ) + ``` + +=== "v3.0.0 (Recommended)" + + ```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 + ) + ``` + +**TimeSeriesData:** === "v2.x (Deprecated)" ```python - calculation = fx.FullCalculation('calc', flow_system, - active_timesteps=[0, 1, 2]) + fx.TimeSeriesData( + agg_group='group1', + agg_weight=2.0 + ) + ``` + +=== "v3.0.0 (Recommended)" + + ```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] + ) ``` === "v3.0.0 (Recommended)" ```python # Use FlowSystem selection methods - fs_subset = flow_system.isel(time=slice(0, 3)) - calculation = fx.FullCalculation('calc', fs_subset) + flow_system_subset = flow_system.sel(time=slice('2020-01-01', '2020-01-03')) + calculation = fx.FullCalculation('calc', flow_system_subset) + + # Or with isel for index-based selection + flow_system_subset = flow_system.isel(time=slice(0, 3)) + calculation = fx.FullCalculation('calc', flow_system_subset) ``` --- ## New Features -**Multi-Period Investments** - Model transformation pathways with distinct decisions in each period: +**Multi-Period Investments** - Model transformation pathways with distinct decisions per period: ```python +import pandas as pd + +# Define multiple investment periods periods = pd.Index(['2020', '2030']) flow_system = fx.FlowSystem(time=timesteps, periods=periods) -solar = fx.Source('solar', outputs=[fx.Flow('P_el', bus='electricity', - size=fx.InvestParameters(minimum_size=0, maximum_size=1000))]) +# 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} + ) + )] +) ``` -**Scenario-Based Stochastic Optimization** - Handle uncertainty with weighted scenarios: +**Scenario-Based Stochastic Optimization** - Model uncertainty with weighted scenarios: ```python -scenarios = pd.Index(['low', 'base', 'high'], name='scenario') -flow_system = fx.FlowSystem(time=timesteps, scenarios=scenarios, - scenario_weights=[0.2, 0.6, 0.2], - scenario_independent_sizes=True) # Optional: scenario-specific capacities +# 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} +) + ``` **Enhanced I/O** - Save, load, and manipulate FlowSystems: ```python -flow_system.to_netcdf('system.nc') -fs = fx.FlowSystem.from_netcdf('system.nc') +# 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') +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 ``` **Effects Per Component** - Analyze component impacts including indirect effects: ```python +# Get dataset showing contribution of each component to all effects effects_ds = calculation.results.effects_per_component() -print(effects_ds['costs']) # Costs by component + +print(effects_ds['costs']) # Total costs by component +print(effects_ds['CO2']) # CO2 emissions by component (including indirect) +``` + +**Balanced Storage** - Force equal charging/discharging capacities: + +```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 +) ``` -**Balanced Storage** - Force equal charging and discharging capacities: +**Final Charge State Control** - Set bounds on storage end state: ```python -storage = fx.Storage('storage', - charging=fx.Flow('charge', bus='electricity', size=fx.InvestParameters(...)), - discharging=fx.Flow('discharge', bus='electricity', size=fx.InvestParameters(...)), - balanced=True, # Charge size == discharge size - capacity_in_flow_hours=100) +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 + +**Logging (v2.2.0+)** - Console and file logging 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 +``` + +--- + +## Testing + +**Check for Deprecation Warnings:** + +```python +import warnings +warnings.filterwarnings('default', category=DeprecationWarning) + +# Run your flixopt code +# Review any DeprecationWarning messages +``` + +**Validate Results:** + +```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) ``` --- @@ -336,6 +533,19 @@ storage = fx.Storage('storage', **"Storage charge state has wrong dimensions"** → Remove extra timestep; use `relative_minimum_final_charge_state` +**"Bus assignment error"** +→ Use string labels instead of Bus objects: + +```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') # ✅ +``` + **"KeyError when accessing results"** → Update variable names: - `is_invested` → `invested` @@ -345,35 +555,31 @@ storage = fx.Storage('storage', - `Effect(operation)|total_per_timestep` → `Effect(temporal)|per_timestep` - `Effect|total` → `Effect` +**"AttributeError: SystemModel"** +→ Rename `SystemModel` → `FlowSystemModel` + **"No logging output"** → Enable explicitly: `fx.CONFIG.Logging.console = True; fx.CONFIG.apply()` --- -## Migration Checklist +## Checklist -**Critical:** - [ ] Update flixopt: `pip install --upgrade flixopt` -- [ ] Update effect sharing syntax -- [ ] Update result variable names -- [ ] Replace object assignments with string labels -- [ ] Fix storage charge state arrays -- [ ] Update `do_modeling()` usage if needed -- [ ] Rename plotting `mode` → `style` -- [ ] Enable logging if needed +- [ ] 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) -**Recommended:** -- [ ] Update deprecated parameter names -- [ ] Test thoroughly and validate results - -**Optional:** -- [ ] Explore new features (periods, scenarios, balanced storage) - -**Welcome to flixopt v3.0.0!** 🎉 --- -## Resources +**Resources:** +[Documentation](https://flixopt.github.io/flixopt/) • +[GitHub Issues](https://github.com/flixOpt/flixopt/issues) • +[Full Changelog](https://flixopt.github.io/flixopt/latest/changelog/99984-v3.0.0/) -- **Docs:** https://flixopt.github.io/flixopt/latest/ -- **Issues:** https://github.com/flixOpt/flixopt/issues -- **Changelog:** https://flixopt.github.io/flixopt/latest/changelog/99984-v3.0.0/ +**Welcome to flixopt v3.0.0!** 🎉 From 9390fcd9f5a6164ff55cbefd1c951f998e1c79e2 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 11:27:03 +0200 Subject: [PATCH 09/42] Update --- docs/user-guide/migration-guide-v3.md | 443 ++++++++++++++------------ 1 file changed, 237 insertions(+), 206 deletions(-) diff --git a/docs/user-guide/migration-guide-v3.md b/docs/user-guide/migration-guide-v3.md index 0ba6f8114..cae28228a 100644 --- a/docs/user-guide/migration-guide-v3.md +++ b/docs/user-guide/migration-guide-v3.md @@ -6,73 +6,67 @@ Quick guide for migrating flixopt from v2.x to v3.0.0. ```bash pip install --upgrade flixopt ``` - Review breaking changes below, update deprecated parameters, and test thoroughly. + Review breaking changes, update deprecated parameters, and test thoroughly. --- ## Breaking Changes -**Effect System Redesign** - terminology and sharing system redesigned. +### Effect System Redesign -Effect domains have been renamed for clarity: +Effect domains renamed and sharing system inverted (no deprecation warnings). -| Old Term (v2.x) | New Term (v3.0.0) | Meaning | -|-----------------|-------------------|-------------------------------------------------------------------------| -| `operation` | `temporal` | Time-varying effects (e.g., operational costs, occuring over time) | -| `invest` / `investment` | `periodic` | Investment-related effects (e.g., fixed costs per period, annuity, ...) | +**Terminology changes:** -Effects now "pull" shares from other effects instead of "pushing" them. +| Old (v2.x) | New (v3.0.0) | Meaning | +|------------|--------------|---------| +| `operation` | `temporal` | Time-varying effects (operational costs, emissions) | +| `invest`/`investment` | `periodic` | Investment effects (fixed costs per period) | -=== "v2.x (Old)" +**Sharing system:** Effects now "pull" shares instead of "pushing" them. +=== "v2.x" ```python CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions', - specific_share_to_other_effects_operation={'costs': 0.2}) # operation → temporal + specific_share_to_other_effects_operation={'costs': 0.2}) land = fx.Effect('land', 'm²', 'Land usage', - specific_share_to_other_effects_invest={'costs': 100}) # invest → periodic + specific_share_to_other_effects_invest={'costs': 100}) costs = fx.Effect('costs', '€', 'Total costs') ``` -=== "v3.0.0 (New)" - +=== "v3.0.0" ```python 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}, # Pulls from temporal effects - share_from_periodic={'land': 100}) # Pulls from periodic effects + share_from_temporal={'CO2': 0.2}, # Pulls from temporal + share_from_periodic={'land': 100}) # Pulls from periodic ``` -**Migration:** -1. Move share definitions to the receiving effect -2. Update parameter names: - - `specific_share_to_other_effects_operation` → `share_from_temporal` - - `specific_share_to_other_effects_invest` → `share_from_periodic` -3. Update terminology throughout your code: - - Replace "operation" with "temporal" in effect-related contexts - - Replace "invest/investment" with "periodic" in effect-related contexts +!!! success "Migration Steps" + 1. Move share definitions to receiving effect + 2. Rename: `specific_share_to_other_effects_operation` → `share_from_temporal` + 3. Rename: `specific_share_to_other_effects_invest` → `share_from_periodic` + 4. Replace "operation" → "temporal" and "invest/investment" → "periodic" throughout --- -**Variable Renaming in Results** - -Multiple variables renamed following terminology changes. +### Variable Names in Results -| Category | Old (v2.x) | New (v3.0.0) | -|------------------|------------------------------------|----------------| -| Investment | `is_invested` | `invested` | -| Switch tracking | `switch_on` | `switch|on` | -| Switch tracking | `switch_off` | `switch|off` | -| Switch tracking | `switch_on_nr` | `switch|count` | -| Effect submodels | `Effect(invest)|total` | `Effect(periodic)` | -| Effect submodels | `Effect(operation)|total` | `Effect(temporal)` | -| Effect submodels | `Effect(operation)|total_per_timestep` | `Effect(temporal)|per_timestep` | -| Effect submodels | `Effect|total` | `Effect` | - -=== "v2.x (Old)" +| Category | Old (v2.x) | New (v3.0.0) | +|----------|------------|--------------| +| Investment | `is_invested` | `invested` | +| Switch tracking | `switch_on` | `switch\|on` | +| Switch tracking | `switch_off` | `switch\|off` | +| Switch tracking | `switch_on_nr` | `switch\|count` | +| Effect submodels | `Effect(invest)\|total` | `Effect(periodic)` | +| Effect submodels | `Effect(operation)\|total` | `Effect(temporal)` | +| Effect submodels | `Effect(operation)\|total_per_timestep` | `Effect(temporal)\|per_timestep` | +| Effect submodels | `Effect\|total` | `Effect` | +=== "v2.x" ```python - # Investment decision + # Investment results.solution['component|is_invested'] # Switch tracking @@ -80,17 +74,16 @@ Multiple variables renamed following terminology changes. results.solution['component|switch_off'] results.solution['component|switch_on_nr'] - # Effect variables + # Effects results.solution['costs(invest)|total'] results.solution['costs(operation)|total'] results.solution['costs(operation)|total_per_timestep'] results.solution['costs|total'] ``` -=== "v3.0.0 (New)" - +=== "v3.0.0" ```python - # Investment decision + # Investment results.solution['component|invested'] # Switch tracking @@ -98,7 +91,7 @@ Multiple variables renamed following terminology changes. results.solution['component|switch|off'] results.solution['component|switch|count'] - # Effect variables (with new terminology) + # Effects results.solution['costs(periodic)'] results.solution['costs(temporal)'] results.solution['costs(temporal)|per_timestep'] @@ -107,130 +100,158 @@ Multiple variables renamed following terminology changes. --- -**Calculation API** - `do_modeling()` now returns `Calculation` object for method chaining +### Bus and Effect Assignment -=== "v2.x (Old)" +Use string labels instead of object references. +=== "v2.x" ```python - calculation = fx.FullCalculation('my_calc', flow_system) - linopy_model = calculation.do_modeling() # Returned linopy.Model + # Bus assignment + my_bus = fx.Bus('electricity') + flow = fx.Flow('P_el', bus=my_bus) # ❌ Object - # Access model directly from return value - print(linopy_model) + # Effect shares + CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') + costs = fx.Effect('costs', '€', 'Total costs', + share_from_temporal={CO2: 0.2}) # ❌ Object + ``` + +=== "v3.0.0" + ```python + # Bus assignment + my_bus = fx.Bus('electricity') + flow = fx.Flow('P_el', bus='electricity') # ✅ String + + # Effect shares + CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') + costs = fx.Effect('costs', '€', 'Total costs', + share_from_temporal={'CO2': 0.2}) # ✅ String ``` -=== "v3.0.0 (New)" +--- + +### FlowSystem Independence +Each Calculation now receives its own FlowSystem copy. + +=== "v2.x" ```python - calculation = fx.FullCalculation('my_calc', flow_system) - calculation.do_modeling() # Returns Calculation object - linopy_model = calculation.model # Access model via property + # FlowSystem was shared + flow_system = fx.FlowSystem(time=timesteps) + calc1 = fx.FullCalculation('calc1', flow_system) # Shared reference + calc2 = fx.FullCalculation('calc2', flow_system) # Same reference + # Changes in calc1's FlowSystem would affect calc2 + ``` - # This enables chaining operations - fx.FullCalculation('my_calc', flow_system).do_modeling().solve() +=== "v3.0.0" + ```python + # Each calculation gets a copy + flow_system = fx.FlowSystem(time=timesteps) + calc1 = fx.FullCalculation('calc1', flow_system) + calc2 = fx.FullCalculation('calc2', flow_system) # Gets separate copy + # Calculations are now independent ``` --- -**Storage Charge State** - Arrays no longer have extra timestep +### Storage Charge State -=== "v2.x (Old)" +Arrays now match timestep count (no extra element). +=== "v2.x" ```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 + relative_minimum_charge_state=np.array([0.2, 0.2, 0.2, 0.2, 0.2]) # 5 for 4 timesteps ) ``` -=== "v3.0.0 (New)" - +=== "v3.0.0" ```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 + relative_minimum_charge_state=np.array([0.2, 0.2, 0.2, 0.2]), # 4 for 4 timesteps + relative_minimum_final_charge_state=0.3 # Control final state explicitly ) ``` --- -**Bus and Effect Assignment** - Use string labels instead of objects +### Calculation API -=== "v2.x (Old)" +`do_modeling()` now returns Calculation object for method chaining. +=== "v2.x" ```python - my_bus = fx.Bus('electricity') - flow = fx.Flow('P_el', bus=my_bus) # ❌ Object + calculation = fx.FullCalculation('my_calc', flow_system) + linopy_model = calculation.do_modeling() # Returned linopy.Model - CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') - costs = fx.Effect('costs', '€', 'Total costs', - share_from_temporal={CO2: 0.2}) # ❌ Object + # Access model directly from return value + print(linopy_model) ``` -=== "v3.0.0 (New)" - +=== "v3.0.0" ```python - my_bus = fx.Bus('electricity') - flow = fx.Flow('P_el', bus='electricity') # ✅ String label + calculation = fx.FullCalculation('my_calc', flow_system) + calculation.do_modeling() # Returns Calculation object + linopy_model = calculation.model # Access model via property - CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') - costs = fx.Effect('costs', '€', 'Total costs', - share_from_temporal={'CO2': 0.2}) # ✅ String label + # Enables method chaining + fx.FullCalculation('my_calc', flow_system).do_modeling().solve() ``` --- -**FlowSystem Independence** - Each Calculation gets its own copy - -=== "v2.x (Old)" +### Other Breaking Changes +=== "Plotting" ```python - # FlowSystem was shared across calculations - flow_system = fx.FlowSystem(time=timesteps) - calc1 = fx.FullCalculation('calc1', flow_system) # Shared reference - calc2 = fx.FullCalculation('calc2', flow_system) # Same reference - # Changes in calc1's FlowSystem would affect calc2 - ``` + # v2.x + results.plot_heatmap('component|variable', mode='line') -=== "v3.0.0 (New)" + # v3.0.0 + results.plot_heatmap('component|variable', style='line') + ``` +=== "Class Names" ```python - # Each calculation gets a copy - flow_system = fx.FlowSystem(time=timesteps) - calc1 = fx.FullCalculation('calc1', flow_system) # Gets copy - calc2 = fx.FullCalculation('calc2', flow_system) # Gets separate copy - # Calculations are now independent - ``` + # v2.x + from flixopt import SystemModel, Model ---- + # v3.0.0 + from flixopt import FlowSystemModel, Submodel + ``` -**Other Breaking Changes:** +=== "Logging" + ```python + # v2.x - enabled by default + # (no explicit configuration needed) -- **Plotting:** `mode` parameter renamed to `style` -- **Class names:** `SystemModel` → `FlowSystemModel`, `Model` → `Submodel` -- **Logging:** Disabled by default (enable with `fx.CONFIG.Logging.console = True; fx.CONFIG.apply()`) + # v3.0.0 - disabled by default + import flixopt as fx + fx.CONFIG.Logging.console = True + fx.CONFIG.apply() + ``` --- ## Deprecated Parameters -!!! info "Still Work" - These parameters still work but will be removed in a future version. Deprecation warnings will guide you. +!!! info "Still Supported" + These parameters still work but will be removed in a future version. Deprecation warnings guide migration. -**InvestParameters:** +### InvestParameters -| Old Parameter (v2.x) | New Parameter (v3.0.0) | -|---------------------|----------------------| +| 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` | === "v2.x (Deprecated)" - ```python fx.InvestParameters( fix_effects=1000, @@ -241,7 +262,6 @@ Multiple variables renamed following terminology changes. ``` === "v3.0.0 (Recommended)" - ```python fx.InvestParameters( effects_of_investment=1000, @@ -251,10 +271,12 @@ Multiple variables renamed following terminology changes. ) ``` -**Effect:** +--- + +### Effect -| Old Parameter (v2.x) | New Parameter (v3.0.0) | -|---------------------|----------------------| +| Old (v2.x) | New (v3.0.0) | +|------------|--------------| | `minimum_investment` | `minimum_periodic` | | `maximum_investment` | `maximum_periodic` | | `minimum_operation` | `minimum_temporal` | @@ -263,7 +285,6 @@ Multiple variables renamed following terminology changes. | `maximum_operation_per_hour` | `maximum_per_hour` | === "v2.x (Deprecated)" - ```python fx.Effect( 'my_effect', 'unit', 'description', @@ -277,7 +298,6 @@ Multiple variables renamed following terminology changes. ``` === "v3.0.0 (Recommended)" - ```python fx.Effect( 'my_effect', 'unit', 'description', @@ -290,10 +310,17 @@ Multiple variables renamed following terminology changes. ) ``` -**Component Parameters:** +--- -=== "v2.x (Deprecated)" +### Component Parameters +| Old (v2.x) | New (v3.0.0) | +|------------|--------------| +| `source` (parameter) | `outputs` | +| `sink` (parameter) | `inputs` | +| `prevent_simultaneous_sink_and_source` | `prevent_simultaneous_flow_rates` | + +=== "v2.x (Deprecated)" ```python fx.Source('my_source', source=flow) @@ -308,7 +335,6 @@ Multiple variables renamed following terminology changes. ``` === "v3.0.0 (Recommended)" - ```python fx.Source('my_source', outputs=flow) @@ -322,10 +348,16 @@ Multiple variables renamed following terminology changes. ) ``` -**TimeSeriesData:** +--- + +### TimeSeriesData -=== "v2.x (Deprecated)" +| Old (v2.x) | New (v3.0.0) | +|------------|--------------| +| `agg_group` | `aggregation_group` | +| `agg_weight` | `aggregation_weight` | +=== "v2.x (Deprecated)" ```python fx.TimeSeriesData( agg_group='group1', @@ -334,7 +366,6 @@ Multiple variables renamed following terminology changes. ``` === "v3.0.0 (Recommended)" - ```python fx.TimeSeriesData( aggregation_group='group1', @@ -342,10 +373,11 @@ Multiple variables renamed following terminology changes. ) ``` -**Calculation:** +--- -=== "v2.x (Deprecated)" +### Calculation +=== "v2.x (Deprecated)" ```python calculation = fx.FullCalculation( 'calc', @@ -355,7 +387,6 @@ Multiple variables renamed following terminology changes. ``` === "v3.0.0 (Recommended)" - ```python # Use FlowSystem selection methods flow_system_subset = flow_system.sel(time=slice('2020-01-01', '2020-01-03')) @@ -370,7 +401,9 @@ Multiple variables renamed following terminology changes. ## New Features -**Multi-Period Investments** - Model transformation pathways with distinct decisions per period: +### Multi-Period Investments + +Model transformation pathways with distinct decisions per period. ```python import pandas as pd @@ -379,7 +412,7 @@ import pandas as pd periods = pd.Index(['2020', '2030']) flow_system = fx.FlowSystem(time=timesteps, periods=periods) -# Components can now invest differently in each period +# Components can invest differently in each period solar = fx.Source( 'solar', outputs=[fx.Flow( @@ -394,17 +427,22 @@ solar = fx.Source( ) ``` -**Scenario-Based Stochastic Optimization** - Model uncertainty with weighted scenarios: +--- + +### 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 +scenario_weights = [0.2, 0.6, 0.2] flow_system = fx.FlowSystem( time=timesteps, scenarios=scenarios, - scenario_weights=scenario_weights + scenario_weights=scenario_weights, + scenario_independent_sizes=True # Optional: scenario-specific capacities ) # Define scenario-dependent data @@ -415,49 +453,63 @@ demand = xr.DataArray( dims=['scenario', 'time'], coords={'scenario': scenarios, 'time': timesteps} ) - ``` -**Enhanced I/O** - Save, load, and manipulate FlowSystems: +--- + +### Enhanced I/O + +Save, load, and manipulate FlowSystems. ```python -# Save and load FlowSystem -flow_system.to_netcdf('my_system.nc') -flow_system_loaded = fx.FlowSystem.from_netcdf('my_system.nc') +# Save and load +flow_system.to_netcdf('system.nc') +fs = fx.FlowSystem.from_netcdf('system.nc') -# Manipulate FlowSystem +# Manipulate 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 +# Access from results +original_fs = results.flow_system # Lazily loaded ``` -**Effects Per Component** - Analyze component impacts including indirect effects: +--- + +### Effects Per Component + +Analyze component impacts including indirect effects through shares. ```python # Get dataset showing contribution of each component to all effects -effects_ds = calculation.results.effects_per_component() +effects_ds = results.effects_per_component() print(effects_ds['costs']) # Total costs by component print(effects_ds['CO2']) # CO2 emissions by component (including indirect) ``` -**Balanced Storage** - Force equal charging/discharging capacities: +--- + +### 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(), + charging=fx.Flow('charge', bus='electricity', size=fx.InvestParameters(...)), + discharging=fx.Flow('discharge', bus='electricity', size=fx.InvestParameters(...)), balanced=True, # Ensures charge_size == discharge_size capacity_in_flow_hours=100 ) ``` -**Final Charge State Control** - Set bounds on storage end state: +--- + +### Final Charge State Control + +Set bounds on storage end state. ```python storage = fx.Storage( @@ -472,31 +524,31 @@ storage = fx.Storage( --- -## Configuration +## Common Issues -**Logging (v2.2.0+)** - Console and file logging now disabled by default: +!!! failure "Effect shares not working" + **Solution:** Move shares to receiving effect using `share_from_temporal`/`share_from_periodic` -```python -import flixopt as fx +!!! failure "Storage dimensions wrong" + **Solution:** Remove extra timestep; use `relative_minimum_final_charge_state` -# Enable console logging -fx.CONFIG.Logging.console = True -fx.CONFIG.Logging.level = 'INFO' -fx.CONFIG.apply() +!!! failure "Bus assignment error" + **Solution:** Use string labels: `bus='electricity'` not `bus=my_bus` -# Enable file logging -fx.CONFIG.Logging.file = 'flixopt.log' -fx.CONFIG.apply() +!!! failure "KeyError in results" + **Solution:** Update variable names (see [Variable Names in Results](#variable-names-in-results)) -# Deprecated: change_logging_level() - will be removed in future -# fx.change_logging_level('INFO') # ❌ Old way -``` +!!! failure "No logging output" + **Solution:** Enable explicitly: `fx.CONFIG.Logging.console = True; fx.CONFIG.apply()` + +!!! failure "AttributeError: SystemModel" + **Solution:** Rename `SystemModel` → `FlowSystemModel`, `Model` → `Submodel` --- ## Testing -**Check for Deprecation Warnings:** +### Check Deprecation Warnings ```python import warnings @@ -506,7 +558,9 @@ warnings.filterwarnings('default', category=DeprecationWarning) # Review any DeprecationWarning messages ``` -**Validate Results:** +--- + +### Validate Results ```python # Save v2.x results before upgrading @@ -525,61 +579,38 @@ np.testing.assert_allclose(v2_costs, v3_costs, rtol=1e-5) --- -## Common Issues - -**"Effect share parameters not working"** -→ Move shares to receiving effect using `share_from_temporal`/`share_from_periodic` - -**"Storage charge state has wrong dimensions"** -→ Remove extra timestep; use `relative_minimum_final_charge_state` - -**"Bus assignment error"** -→ Use string labels instead of Bus objects: - -```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') # ✅ -``` - -**"KeyError when accessing results"** -→ Update variable names: - - `is_invested` → `invested` - - `switch_on` → `switch|on`, `switch_off` → `switch|off`, `switch_on_nr` → `switch|count` - - `Effect(invest)|total` → `Effect(periodic)` - - `Effect(operation)|total` → `Effect(temporal)` - - `Effect(operation)|total_per_timestep` → `Effect(temporal)|per_timestep` - - `Effect|total` → `Effect` - -**"AttributeError: SystemModel"** -→ Rename `SystemModel` → `FlowSystemModel` - -**"No logging output"** -→ Enable explicitly: `fx.CONFIG.Logging.console = True; fx.CONFIG.apply()` +## Migration Checklist + +??? abstract "Critical (Breaking Changes)" + - [x] Update flixopt: `pip install --upgrade flixopt` + - [ ] Update effect sharing syntax (move to receiving effect) + - [ ] Update result variable names (`is_invested` → `invested`, etc.) + - [ ] Replace Bus/Effect object assignments with strings + - [ ] Fix storage charge state arrays (remove extra timestep) + - [ ] Update `do_modeling()` usage if accessing return value + - [ ] Rename plotting `mode` → `style` + - [ ] Update class names (`SystemModel` → `FlowSystemModel`) + +??? tip "Recommended" + - [ ] Update deprecated parameter names + - [ ] Enable logging explicitly if needed + - [ ] Test thoroughly and validate results + +??? success "Optional" + - [ ] Explore multi-period investments + - [ ] Explore scenario-based optimization + - [ ] Try enhanced I/O features + - [ ] Use balanced storage + - [ ] Set final charge state controls --- -## Checklist +## Resources -- [ ] 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: [Documentation](https://flixopt.github.io/flixopt/) +:material-github: [GitHub Issues](https://github.com/flixOpt/flixopt/issues) +:material-text-box: [Full Changelog](https://flixopt.github.io/flixopt/latest/changelog/99984-v3.0.0/) --- -**Resources:** -[Documentation](https://flixopt.github.io/flixopt/) • -[GitHub Issues](https://github.com/flixOpt/flixopt/issues) • -[Full 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! 🎉" From 066804222a64000191dd038348c1144faacd9d1c Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 11:19:32 +0200 Subject: [PATCH 10/42] Update --- docs/user-guide/migration-guide-v3.md | 56 +++++++++++++++++++++------ 1 file changed, 45 insertions(+), 11 deletions(-) diff --git a/docs/user-guide/migration-guide-v3.md b/docs/user-guide/migration-guide-v3.md index cae28228a..81a7399fe 100644 --- a/docs/user-guide/migration-guide-v3.md +++ b/docs/user-guide/migration-guide-v3.md @@ -179,17 +179,43 @@ Arrays now match timestep count (no extra element). --- -### Calculation API +**Bus and Effect Assignment** - Use string labels instead of objects + +=== "v2.x (Old)" + + ```python + my_bus = fx.Bus('electricity') + flow = fx.Flow('P_el', bus=my_bus) # ❌ Object + + CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') + costs = fx.Effect('costs', '€', 'Total costs', + share_from_temporal={CO2: 0.2}) # ❌ Object + ``` + +=== "v3.0.0 (New)" + + ```python + my_bus = fx.Bus('electricity') + flow = fx.Flow('P_el', bus='electricity') # ✅ String label + + CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') + costs = fx.Effect('costs', '€', 'Total costs', + share_from_temporal={'CO2': 0.2}) # ✅ String label + ``` + +--- + +**FlowSystem Independence** - Each Calculation gets its own copy `do_modeling()` now returns Calculation object for method chaining. === "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) + # FlowSystem was shared across calculations + flow_system = fx.FlowSystem(time=timesteps) + calc1 = fx.FullCalculation('calc1', flow_system) # Shared reference + calc2 = fx.FullCalculation('calc2', flow_system) # Same reference + # Changes in calc1's FlowSystem would affect calc2 ``` === "v3.0.0" @@ -208,13 +234,21 @@ Arrays now match timestep count (no extra element). === "Plotting" ```python - # v2.x - results.plot_heatmap('component|variable', mode='line') - - # v3.0.0 - results.plot_heatmap('component|variable', style='line') + # Each calculation gets a copy + flow_system = fx.FlowSystem(time=timesteps) + calc1 = fx.FullCalculation('calc1', flow_system) # Gets copy + calc2 = fx.FullCalculation('calc2', flow_system) # Gets separate copy + # Calculations are now independent ``` +--- + +**Other Breaking Changes:** + +- **Plotting:** `mode` parameter renamed to `style` +- **Class names:** `SystemModel` → `FlowSystemModel`, `Model` → `Submodel` +- **Logging:** Disabled by default (enable with `fx.CONFIG.Logging.console = True; fx.CONFIG.apply()`) + === "Class Names" ```python # v2.x From 4fb6a6cfa33f5afbf4a5c3eb484420488cd62854 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 11:34:44 +0200 Subject: [PATCH 11/42] Update --- docs/user-guide/migration-guide-v3.md | 212 ++++++++++++++++++-------- 1 file changed, 152 insertions(+), 60 deletions(-) diff --git a/docs/user-guide/migration-guide-v3.md b/docs/user-guide/migration-guide-v3.md index 81a7399fe..eb701c82c 100644 --- a/docs/user-guide/migration-guide-v3.md +++ b/docs/user-guide/migration-guide-v3.md @@ -12,11 +12,14 @@ Quick guide for migrating flixopt from v2.x to v3.0.0. ## Breaking Changes -### Effect System Redesign +**Effect System Redesign** - terminology and sharing system redesigned. Effect domains renamed and sharing system inverted (no deprecation warnings). -**Terminology changes:** +| Old Term (v2.x) | New Term (v3.0.0) | Meaning | +|-----------------|-------------------|-------------------------------------------------------------------------| +| `operation` | `temporal` | Time-varying effects (e.g., operational costs, occurring over time) | +| `invest` / `investment` | `periodic` | Investment-related effects (e.g., fixed costs per period, annuity, ...) | | Old (v2.x) | New (v3.0.0) | Meaning | |------------|--------------|---------| @@ -43,11 +46,18 @@ Effect domains renamed and sharing system inverted (no deprecation warnings). share_from_periodic={'land': 100}) # Pulls from periodic ``` -!!! success "Migration Steps" - 1. Move share definitions to receiving effect - 2. Rename: `specific_share_to_other_effects_operation` → `share_from_temporal` - 3. Rename: `specific_share_to_other_effects_invest` → `share_from_periodic` - 4. Replace "operation" → "temporal" and "invest/investment" → "periodic" throughout +!!! warning "No Deprecation Warning" + This change was made WITHOUT deprecation warnings due to fundamental restructuring. + +**Migration:** + +1. Move share definitions to the receiving effect +2. Update parameter names: + - `specific_share_to_other_effects_operation` → `share_from_temporal` + - `specific_share_to_other_effects_invest` → `share_from_periodic` +3. Update terminology throughout your code: + - Replace "operation" with "temporal" in effect-related contexts + - Replace "invest/investment" with "periodic" in effect-related contexts --- @@ -152,6 +162,9 @@ Each Calculation now receives its own FlowSystem copy. # Calculations are now independent ``` +!!! tip "Migration" + If you used the return value of `do_modeling()`, update to access `.model` property instead. + --- ### Storage Charge State @@ -172,11 +185,17 @@ Arrays now match timestep count (no extra element). # Array matches timesteps storage = fx.Storage( 'storage', - relative_minimum_charge_state=np.array([0.2, 0.2, 0.2, 0.2]), # 4 for 4 timesteps - relative_minimum_final_charge_state=0.3 # Control final state explicitly + 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 if needed ) ``` +!!! note "Final State Control" + You only need to specify `relative_minimum_final_charge_state` only if it differs from the last value of `relative_minimum_charge_state`. + +!!! info "Impact" + If you provided arrays with `len(timesteps) + 1` elements, reduce to `len(timesteps)`. + --- **Bus and Effect Assignment** - Use string labels instead of objects @@ -241,6 +260,14 @@ Arrays now match timestep count (no extra element). # Calculations are now independent ``` +!!! info "Impact" + - Mutations to one calculation's FlowSystem won't affect others + - Each `Subcalculation` in `SegmentedCalculation` has its own distinct FlowSystem + - Memory usage may increase slightly due to copying + +!!! tip "Migration" + If you relied on shared FlowSystem behavior (which you most likely did not or by accident), you should copy the flow_system before passing it to another calculation. + --- **Other Breaking Changes:** @@ -463,9 +490,7 @@ solar = fx.Source( --- -### Scenario-Based Stochastic Optimization - -Model uncertainty with weighted scenarios. +**Scenario-Based Stochastic Optimization** - Model uncertainty with weighted scenarios: ```python # Define scenarios with probabilities @@ -489,9 +514,18 @@ demand = xr.DataArray( ) ``` ---- +**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 +) +``` -### Enhanced I/O +--- Save, load, and manipulate FlowSystems. @@ -511,9 +545,7 @@ original_fs = results.flow_system # Lazily loaded --- -### Effects Per Component - -Analyze component impacts including indirect effects through shares. +**Effects Per Component** - Analyze component impacts including indirect effects: ```python # Get dataset showing contribution of each component to all effects @@ -525,15 +557,14 @@ print(effects_ds['CO2']) # CO2 emissions by component (including indirect) --- -### Balanced Storage - -Force charging and discharging capacities to be equal. +**Balanced Storage** - Force equal charging/discharging capacities: ```python storage = fx.Storage( 'storage', - charging=fx.Flow('charge', bus='electricity', size=fx.InvestParameters(...)), - discharging=fx.Flow('discharge', bus='electricity', size=fx.InvestParameters(...)), + charging=fx.Flow('charge', bus='electricity', + size=fx.InvestParameters(effects_of_investment_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 ) @@ -541,9 +572,7 @@ storage = fx.Storage( --- -### Final Charge State Control - -Set bounds on storage end state. +**Final Charge State Control** - Set bounds on storage end state: ```python storage = fx.Storage( @@ -563,20 +592,44 @@ storage = fx.Storage( !!! failure "Effect shares not working" **Solution:** Move shares to receiving effect using `share_from_temporal`/`share_from_periodic` -!!! failure "Storage dimensions wrong" - **Solution:** Remove extra timestep; use `relative_minimum_final_charge_state` +=== "v2.1.x and earlier" + + ```python + import flixopt as fx -!!! failure "Bus assignment error" - **Solution:** Use string labels: `bus='electricity'` not `bus=my_bus` + # Logging was enabled by default + calculation = fx.FullCalculation('calc', flow_system) + calculation.solve() # Logs were shown automatically + ``` -!!! failure "KeyError in results" - **Solution:** Update variable names (see [Variable Names in Results](#variable-names-in-results)) +=== "v2.2.0+ and v3.0.0" -!!! failure "No logging output" - **Solution:** Enable explicitly: `fx.CONFIG.Logging.console = True; fx.CONFIG.apply()` + ```python + import flixopt as fx + + # Enable console logging explicitly + fx.CONFIG.Logging.console = True + fx.CONFIG.Logging.level = 'INFO' + fx.CONFIG.apply() + + # Enable file logging (optional) + fx.CONFIG.Logging.file = 'flixopt.log' + fx.CONFIG.apply() + + calculation = fx.FullCalculation('calc', flow_system) + calculation.solve() # Now logs are shown + ``` + +!!! warning "Breaking Change (from v2.2.0)" + If you're upgrading from v2.1.x or earlier to v3.0.0, you may notice that logging output is no longer displayed unless explicitly enabled. -!!! failure "AttributeError: SystemModel" - **Solution:** Rename `SystemModel` → `FlowSystemModel`, `Model` → `Submodel` +!!! tip "Migration" + Add logging configuration at the start of your scripts if you want to see log output: + ```python + import flixopt as fx + fx.CONFIG.Logging.console = True + fx.CONFIG.apply() + ``` --- @@ -594,7 +647,9 @@ warnings.filterwarnings('default', category=DeprecationWarning) --- -### Validate Results +**Validate Results:** + +Compare results from v2.x and v3.0.0 to ensure consistency: ```python # Save v2.x results before upgrading @@ -613,33 +668,70 @@ np.testing.assert_allclose(v2_costs, v3_costs, rtol=1e-5) --- -## Migration Checklist - -??? abstract "Critical (Breaking Changes)" - - [x] Update flixopt: `pip install --upgrade flixopt` - - [ ] Update effect sharing syntax (move to receiving effect) - - [ ] Update result variable names (`is_invested` → `invested`, etc.) - - [ ] Replace Bus/Effect object assignments with strings - - [ ] Fix storage charge state arrays (remove extra timestep) - - [ ] Update `do_modeling()` usage if accessing return value - - [ ] Rename plotting `mode` → `style` - - [ ] Update class names (`SystemModel` → `FlowSystemModel`) - -??? tip "Recommended" - - [ ] Update deprecated parameter names - - [ ] Enable logging explicitly if needed - - [ ] Test thoroughly and validate results - -??? success "Optional" - - [ ] Explore multi-period investments - - [ ] Explore scenario-based optimization - - [ ] Try enhanced I/O features - - [ ] Use balanced storage - - [ ] Set final charge state controls +## Common Issues + +!!! failure "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`. + +!!! failure "Storage charge state has wrong dimensions" + **Solution:** Remove the extra timestep from charge state bound arrays. + +!!! failure "KeyError when accessing results" + **Solution:** Variable names have changed. Update your result access: + + - `is_invested` → `invested` + - `switch_on` → `switch|on` + - `switch_off` → `switch|off` + - `switch_on_nr` → `switch|count` + - `Effect(invest)|total` → `Effect(periodic)` + - `Effect(operation)|total` → `Effect(temporal)` + - `Effect(operation)|total_per_timestep` → `Effect(temporal)|per_timestep` + - `Effect|total` → `Effect` + +!!! failure "AttributeError: Element x has no attribute `model`" + **Solution:** Rename `.model` → `.submodel` + +!!! failure "No logging output" + **Solution:** Logging is disabled by default in v2.2.0+. Enable it explicitly: + ```python + import flixopt as fx + fx.CONFIG.Logging.console = True + fx.CONFIG.apply() + ``` + +--- + +## Checklist + +**Critical (Breaking Changes):** + +- [ ] Update flixopt: `pip install --upgrade flixopt` +- [ ] Update effect sharing syntax (no deprecation warning!) +- [ ] Update all variable names in result access +- [ ] Replace Bus/Effect object assignments with string labels +- [ ] Remove any code that relies on shared FlowSystem objects across Calculations +- [ ] Update `Calculation.do_modeling()` usage if accessing return value +- [ ] Fix storage charge state array dimensions (remove extra timestep) +- [ ] Rename `mode` → `style` in plotting calls + +**Important:** + +- [ ] Enable logging explicitly if needed (`fx.CONFIG.Logging.console = True; fx.CONFIG.apply()`) +- [ ] Update deprecated parameter names (optional, but recommended) + +**Testing:** + +- [ ] Test your code thoroughly +- [ ] Check for deprecation warnings +- [ ] Validate results match v2.x output (if upgrading) + +**Optional:** + +- [ ] Explore new features (periods, scenarios, enhanced I/O, balanced storage, final charge state control) --- -## Resources +## Getting Help :material-book: [Documentation](https://flixopt.github.io/flixopt/) :material-github: [GitHub Issues](https://github.com/flixOpt/flixopt/issues) From 8cced2ab23b5c52b4b81364a92ed37e98693a22f Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 11:44:55 +0200 Subject: [PATCH 12/42] Add links --- docs/user-guide/migration-guide-v3.md | 260 ++++++++++---------------- 1 file changed, 98 insertions(+), 162 deletions(-) diff --git a/docs/user-guide/migration-guide-v3.md b/docs/user-guide/migration-guide-v3.md index eb701c82c..135e469d7 100644 --- a/docs/user-guide/migration-guide-v3.md +++ b/docs/user-guide/migration-guide-v3.md @@ -12,7 +12,7 @@ Quick guide for migrating flixopt from v2.x to v3.0.0. ## Breaking Changes -**Effect System Redesign** - terminology and sharing system redesigned. +### Effect System Redesign Effect domains renamed and sharing system inverted (no deprecation warnings). @@ -21,11 +21,6 @@ Effect domains renamed and sharing system inverted (no deprecation warnings). | `operation` | `temporal` | Time-varying effects (e.g., operational costs, occurring over time) | | `invest` / `investment` | `periodic` | Investment-related effects (e.g., fixed costs per period, annuity, ...) | -| Old (v2.x) | New (v3.0.0) | Meaning | -|------------|--------------|---------| -| `operation` | `temporal` | Time-varying effects (operational costs, emissions) | -| `invest`/`investment` | `periodic` | Investment effects (fixed costs per period) | - **Sharing system:** Effects now "pull" shares instead of "pushing" them. === "v2.x" @@ -158,10 +153,43 @@ Each Calculation now receives its own FlowSystem copy. # Each calculation gets a copy flow_system = fx.FlowSystem(time=timesteps) calc1 = fx.FullCalculation('calc1', flow_system) - calc2 = fx.FullCalculation('calc2', flow_system) # Gets separate copy + calc2 = fx.FullCalculation('calc2', flow_system) # Gets copy # Calculations are now independent ``` +!!! info "Impact" + - Mutations to one calculation's FlowSystem won't affect others + - Each `Subcalculation` in `SegmentedCalculation` has its own distinct FlowSystem + - Memory usage may increase slightly due to copying + +!!! tip "Migration" + If you relied on shared FlowSystem behavior (which you most likely did not or by accident), you should copy the flow_system before passing it to another calculation. + +--- + +### Calculation API + +`do_modeling()` now returns Calculation object for method chaining. + +=== "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) + ``` + +=== "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 + + # Enables method chaining + fx.FullCalculation('my_calc', flow_system).do_modeling().solve() + ``` + !!! tip "Migration" If you used the return value of `do_modeling()`, update to access `.model` property instead. @@ -191,90 +219,23 @@ Arrays now match timestep count (no extra element). ``` !!! note "Final State Control" - You only need to specify `relative_minimum_final_charge_state` only if it differs from the last value of `relative_minimum_charge_state`. + You only need to specify `relative_minimum_final_charge_state` if it differs from the last value of `relative_minimum_charge_state`. !!! info "Impact" If you provided arrays with `len(timesteps) + 1` elements, reduce to `len(timesteps)`. --- -**Bus and Effect Assignment** - Use string labels instead of objects - -=== "v2.x (Old)" - - ```python - my_bus = fx.Bus('electricity') - flow = fx.Flow('P_el', bus=my_bus) # ❌ Object - - CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') - costs = fx.Effect('costs', '€', 'Total costs', - share_from_temporal={CO2: 0.2}) # ❌ Object - ``` - -=== "v3.0.0 (New)" - - ```python - my_bus = fx.Bus('electricity') - flow = fx.Flow('P_el', bus='electricity') # ✅ String label - - CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') - costs = fx.Effect('costs', '€', 'Total costs', - share_from_temporal={'CO2': 0.2}) # ✅ String label - ``` - ---- - -**FlowSystem Independence** - Each Calculation gets its own copy - -`do_modeling()` now returns Calculation object for method chaining. - -=== "v2.x" - ```python - # FlowSystem was shared across calculations - flow_system = fx.FlowSystem(time=timesteps) - calc1 = fx.FullCalculation('calc1', flow_system) # Shared reference - calc2 = fx.FullCalculation('calc2', flow_system) # Same reference - # Changes in calc1's FlowSystem would affect calc2 - ``` - -=== "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 - - # Enables method chaining - fx.FullCalculation('my_calc', flow_system).do_modeling().solve() - ``` - ---- - ### Other Breaking Changes === "Plotting" ```python - # Each calculation gets a copy - flow_system = fx.FlowSystem(time=timesteps) - calc1 = fx.FullCalculation('calc1', flow_system) # Gets copy - calc2 = fx.FullCalculation('calc2', flow_system) # Gets separate copy - # Calculations are now independent - ``` - -!!! info "Impact" - - Mutations to one calculation's FlowSystem won't affect others - - Each `Subcalculation` in `SegmentedCalculation` has its own distinct FlowSystem - - Memory usage may increase slightly due to copying - -!!! tip "Migration" - If you relied on shared FlowSystem behavior (which you most likely did not or by accident), you should copy the flow_system before passing it to another calculation. - ---- - -**Other Breaking Changes:** + # v2.x + results.plot_heatmap('component|variable', mode='line') -- **Plotting:** `mode` parameter renamed to `style` -- **Class names:** `SystemModel` → `FlowSystemModel`, `Model` → `Submodel` -- **Logging:** Disabled by default (enable with `fx.CONFIG.Logging.console = True; fx.CONFIG.apply()`) + # v3.0.0 + results.plot_heatmap('component|variable', style='line') + ``` === "Class Names" ```python @@ -296,6 +257,9 @@ Arrays now match timestep count (no extra element). fx.CONFIG.apply() ``` +!!! warning "Breaking Change (from v2.2.0)" + If you're upgrading from v2.1.x or earlier to v3.0.0, logging output is no longer displayed unless explicitly enabled. See [Configuration](#configuration) for details. + --- ## Deprecated Parameters @@ -384,29 +348,17 @@ Arrays now match timestep count (no extra element). === "v2.x (Deprecated)" ```python fx.Source('my_source', source=flow) - fx.Sink('my_sink', sink=flow) - - fx.SourceAndSink( - 'my_source_sink', - source=flow1, - sink=flow2, - prevent_simultaneous_sink_and_source=True - ) + fx.SourceAndSink('my_source_sink', source=flow1, sink=flow2, + prevent_simultaneous_sink_and_source=True) ``` === "v3.0.0 (Recommended)" ```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 - ) + fx.SourceAndSink('my_source_sink', outputs=[flow1], inputs=[flow2], + prevent_simultaneous_flow_rates=True) ``` --- @@ -420,18 +372,12 @@ Arrays now match timestep count (no extra element). === "v2.x (Deprecated)" ```python - fx.TimeSeriesData( - agg_group='group1', - agg_weight=2.0 - ) + fx.TimeSeriesData(agg_group='group1', agg_weight=2.0) ``` === "v3.0.0 (Recommended)" ```python - fx.TimeSeriesData( - aggregation_group='group1', - aggregation_weight=2.0 - ) + fx.TimeSeriesData(aggregation_group='group1', aggregation_weight=2.0) ``` --- @@ -440,11 +386,7 @@ Arrays now match timestep count (no extra element). === "v2.x (Deprecated)" ```python - calculation = fx.FullCalculation( - 'calc', - flow_system, - active_timesteps=[0, 1, 2] - ) + calculation = fx.FullCalculation('calc', flow_system, active_timesteps=[0, 1, 2]) ``` === "v3.0.0 (Recommended)" @@ -490,7 +432,9 @@ solar = fx.Source( --- -**Scenario-Based Stochastic Optimization** - Model uncertainty with weighted scenarios: +### Scenario-Based Stochastic Optimization + +Model uncertainty with weighted scenarios. ```python # Define scenarios with probabilities @@ -500,8 +444,7 @@ scenario_weights = [0.2, 0.6, 0.2] flow_system = fx.FlowSystem( time=timesteps, scenarios=scenarios, - scenario_weights=scenario_weights, - scenario_independent_sizes=True # Optional: scenario-specific capacities + scenario_weights=scenario_weights ) # Define scenario-dependent data @@ -527,6 +470,8 @@ flow_system = fx.FlowSystem( --- +### Enhanced I/O + Save, load, and manipulate FlowSystems. ```python @@ -545,19 +490,23 @@ original_fs = results.flow_system # Lazily loaded --- -**Effects Per Component** - Analyze component impacts including indirect effects: +### Effects Per Component + +Analyze component impacts including indirect effects. ```python # Get dataset showing contribution of each component to all effects -effects_ds = results.effects_per_component() +effects_ds = results.effects_per_component -print(effects_ds['costs']) # Total costs by component -print(effects_ds['CO2']) # CO2 emissions by component (including indirect) +print(effects_ds['total'].sel(effect='costs')) # Total costs by component +print(effects_ds['temporal'].sel(effect='CO2')) # Temporal CO2 emissions by component (including indirect) ``` --- -**Balanced Storage** - Force equal charging/discharging capacities: +### Balanced Storage + +Force equal charging/discharging sizes. ```python storage = fx.Storage( @@ -572,7 +521,9 @@ storage = fx.Storage( --- -**Final Charge State Control** - Set bounds on storage end state: +### Final Charge State Control + +Set bounds on storage end state. ```python storage = fx.Storage( @@ -587,13 +538,13 @@ storage = fx.Storage( --- -## Common Issues +## Configuration -!!! failure "Effect shares not working" - **Solution:** Move shares to receiving effect using `share_from_temporal`/`share_from_periodic` +### Logging -=== "v2.1.x and earlier" +Console and file logging now disabled by default (changed in v2.2.0). +=== "v2.1.x and earlier" ```python import flixopt as fx @@ -603,7 +554,6 @@ storage = fx.Storage( ``` === "v2.2.0+ and v3.0.0" - ```python import flixopt as fx @@ -620,11 +570,8 @@ storage = fx.Storage( calculation.solve() # Now logs are shown ``` -!!! warning "Breaking Change (from v2.2.0)" - If you're upgrading from v2.1.x or earlier to v3.0.0, you may notice that logging output is no longer displayed unless explicitly enabled. - -!!! tip "Migration" - Add logging configuration at the start of your scripts if you want to see log output: +!!! tip "Quick Enable" + Add at the start of your scripts: ```python import flixopt as fx fx.CONFIG.Logging.console = True @@ -647,7 +594,7 @@ warnings.filterwarnings('default', category=DeprecationWarning) --- -**Validate Results:** +### Validate Results Compare results from v2.x and v3.0.0 to ensure consistency: @@ -670,34 +617,23 @@ np.testing.assert_allclose(v2_costs, v3_costs, rtol=1e-5) ## Common Issues -!!! failure "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`. +!!! failure "Effect shares not working" + **Solution:** Effect sharing was completely redesigned. See [Effect System Redesign](#effect-system-redesign). -!!! failure "Storage charge state has wrong dimensions" - **Solution:** Remove the extra timestep from charge state bound arrays. +!!! failure "Storage dimensions wrong" + **Solution:** Remove extra timestep from charge state arrays. See [Storage Charge State](#storage-charge-state). -!!! failure "KeyError when accessing results" - **Solution:** Variable names have changed. Update your result access: +!!! failure "Bus assignment error" + **Solution:** Use string labels instead of Bus objects. See [Bus and Effect Assignment](#bus-and-effect-assignment). - - `is_invested` → `invested` - - `switch_on` → `switch|on` - - `switch_off` → `switch|off` - - `switch_on_nr` → `switch|count` - - `Effect(invest)|total` → `Effect(periodic)` - - `Effect(operation)|total` → `Effect(temporal)` - - `Effect(operation)|total_per_timestep` → `Effect(temporal)|per_timestep` - - `Effect|total` → `Effect` +!!! failure "KeyError when accessing results" + **Solution:** Variable names have changed. See [Variable Names in Results](#variable-names-in-results) for the complete mapping. !!! failure "AttributeError: Element x has no attribute `model`" - **Solution:** Rename `.model` → `.submodel` + **Solution:** Rename `.model` → `.submodel`. See [Other Breaking Changes](#other-breaking-changes). !!! failure "No logging output" - **Solution:** Logging is disabled by default in v2.2.0+. Enable it explicitly: - ```python - import flixopt as fx - fx.CONFIG.Logging.console = True - fx.CONFIG.apply() - ``` + **Solution:** Logging is disabled by default. See [Configuration](#configuration) to enable it. --- @@ -706,28 +642,28 @@ np.testing.assert_allclose(v2_costs, v3_costs, rtol=1e-5) **Critical (Breaking Changes):** - [ ] Update flixopt: `pip install --upgrade flixopt` -- [ ] Update effect sharing syntax (no deprecation warning!) -- [ ] Update all variable names in result access -- [ ] Replace Bus/Effect object assignments with string labels -- [ ] Remove any code that relies on shared FlowSystem objects across Calculations -- [ ] Update `Calculation.do_modeling()` usage if accessing return value -- [ ] Fix storage charge state array dimensions (remove extra timestep) -- [ ] Rename `mode` → `style` in plotting calls +- [ ] Update [effect sharing syntax](#effect-system-redesign) (no deprecation warning!) +- [ ] Update [variable names in results](#variable-names-in-results) +- [ ] Update [Bus/Effect assignments](#bus-and-effect-assignment) to use string labels +- [ ] Update [Calculation API](#calculation-api) usage if accessing return value +- [ ] Fix [storage charge state](#storage-charge-state) array dimensions +- [ ] Rename plotting `mode` → `style` +- [ ] Update class names: `SystemModel` → `FlowSystemModel`, `Model` → `Submodel` **Important:** -- [ ] Enable logging explicitly if needed (`fx.CONFIG.Logging.console = True; fx.CONFIG.apply()`) -- [ ] Update deprecated parameter names (optional, but recommended) +- [ ] Enable [logging](#configuration) explicitly if needed +- [ ] Update [deprecated parameters](#deprecated-parameters) (optional, but recommended) **Testing:** - [ ] Test your code thoroughly -- [ ] Check for deprecation warnings -- [ ] Validate results match v2.x output (if upgrading) +- [ ] Check for [deprecation warnings](#check-deprecation-warnings) +- [ ] [Validate results](#validate-results) match v2.x output (if upgrading) **Optional:** -- [ ] Explore new features (periods, scenarios, enhanced I/O, balanced storage, final charge state control) +- [ ] Explore [new features](#new-features) --- From cd87edfb4efabd4b884aca5f8ef23044cc9de6fe Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 11:46:58 +0200 Subject: [PATCH 13/42] Add emojis --- docs/user-guide/migration-guide-v3.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/user-guide/migration-guide-v3.md b/docs/user-guide/migration-guide-v3.md index 135e469d7..73bad903e 100644 --- a/docs/user-guide/migration-guide-v3.md +++ b/docs/user-guide/migration-guide-v3.md @@ -10,7 +10,7 @@ Quick guide for migrating flixopt from v2.x to v3.0.0. --- -## Breaking Changes +## 💥 Breaking Changes ### Effect System Redesign @@ -262,7 +262,7 @@ Arrays now match timestep count (no extra element). --- -## Deprecated Parameters +## 🗑️ Deprecated Parameters !!! info "Still Supported" These parameters still work but will be removed in a future version. Deprecation warnings guide migration. @@ -402,7 +402,7 @@ Arrays now match timestep count (no extra element). --- -## New Features +## ✨ New Features ### Multi-Period Investments @@ -538,7 +538,7 @@ storage = fx.Storage( --- -## Configuration +## ⚙️ Configuration ### Logging @@ -580,7 +580,7 @@ Console and file logging now disabled by default (changed in v2.2.0). --- -## Testing +## 🧪 Testing ### Check Deprecation Warnings @@ -615,7 +615,7 @@ np.testing.assert_allclose(v2_costs, v3_costs, rtol=1e-5) --- -## Common Issues +## 🔧 Common Issues !!! failure "Effect shares not working" **Solution:** Effect sharing was completely redesigned. See [Effect System Redesign](#effect-system-redesign). @@ -637,7 +637,7 @@ np.testing.assert_allclose(v2_costs, v3_costs, rtol=1e-5) --- -## Checklist +## ✅ Checklist **Critical (Breaking Changes):** @@ -667,7 +667,7 @@ np.testing.assert_allclose(v2_costs, v3_costs, rtol=1e-5) --- -## Getting Help +## 📚 Getting Help :material-book: [Documentation](https://flixopt.github.io/flixopt/) :material-github: [GitHub Issues](https://github.com/flixOpt/flixopt/issues) From 0d03660671c0c5277cf34c7d4587eebbd84fd41d Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 11:59:11 +0200 Subject: [PATCH 14/42] compact 2 --- docs/user-guide/migration-guide-v3.md | 658 +++----------------------- 1 file changed, 75 insertions(+), 583 deletions(-) diff --git a/docs/user-guide/migration-guide-v3.md b/docs/user-guide/migration-guide-v3.md index 73bad903e..bafce112a 100644 --- a/docs/user-guide/migration-guide-v3.md +++ b/docs/user-guide/migration-guide-v3.md @@ -1,12 +1,10 @@ # Migration Guide: v2.x → v3.0.0 -Quick guide for migrating flixopt from v2.x to v3.0.0. - !!! tip "Quick Start" ```bash pip install --upgrade flixopt ``` - Review breaking changes, update deprecated parameters, and test thoroughly. + Review [breaking changes](#breaking-changes), update [deprecated parameters](#deprecated-parameters), test thoroughly. --- @@ -14,665 +12,159 @@ Quick guide for migrating flixopt from v2.x to v3.0.0. ### Effect System Redesign -Effect domains renamed and sharing system inverted (no deprecation warnings). - -| Old Term (v2.x) | New Term (v3.0.0) | Meaning | -|-----------------|-------------------|-------------------------------------------------------------------------| -| `operation` | `temporal` | Time-varying effects (e.g., operational costs, occurring over time) | -| `invest` / `investment` | `periodic` | Investment-related effects (e.g., fixed costs per period, annuity, ...) | - -**Sharing system:** Effects now "pull" shares instead of "pushing" them. +Terminology changed: `operation` → `temporal`, `invest/investment` → `periodic`. Sharing inverted: effects now "pull" shares. === "v2.x" ```python - 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" ```python - 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}, # Pulls from temporal - share_from_periodic={'land': 100}) # Pulls from periodic + CO2 = fx.Effect('CO2', 'kg', 'CO2') + costs = fx.Effect('costs', '€', 'Total', + share_from_temporal={'CO2': 0.2}) ``` -!!! warning "No Deprecation Warning" - This change was made WITHOUT deprecation warnings due to fundamental restructuring. - -**Migration:** - -1. Move share definitions to the receiving effect -2. Update parameter names: - - `specific_share_to_other_effects_operation` → `share_from_temporal` - - `specific_share_to_other_effects_invest` → `share_from_periodic` -3. Update terminology throughout your code: - - Replace "operation" with "temporal" in effect-related contexts - - Replace "invest/investment" with "periodic" in effect-related contexts +!!! warning "No deprecation warning" + - Move shares to receiving effect + - `specific_share_to_other_effects_operation` → `share_from_temporal` + - `specific_share_to_other_effects_invest` → `share_from_periodic` --- -### Variable Names in Results - -| Category | Old (v2.x) | New (v3.0.0) | -|----------|------------|--------------| -| Investment | `is_invested` | `invested` | -| Switch tracking | `switch_on` | `switch\|on` | -| Switch tracking | `switch_off` | `switch\|off` | -| Switch tracking | `switch_on_nr` | `switch\|count` | -| Effect submodels | `Effect(invest)\|total` | `Effect(periodic)` | -| Effect submodels | `Effect(operation)\|total` | `Effect(temporal)` | -| Effect submodels | `Effect(operation)\|total_per_timestep` | `Effect(temporal)\|per_timestep` | -| Effect submodels | `Effect\|total` | `Effect` | +### Variable Names -=== "v2.x" - ```python - # Investment - results.solution['component|is_invested'] - - # Switch tracking - results.solution['component|switch_on'] - results.solution['component|switch_off'] - results.solution['component|switch_on_nr'] - - # Effects - results.solution['costs(invest)|total'] - results.solution['costs(operation)|total'] - results.solution['costs(operation)|total_per_timestep'] - results.solution['costs|total'] - ``` - -=== "v3.0.0" - ```python - # Investment - results.solution['component|invested'] - - # Switch tracking - results.solution['component|switch|on'] - results.solution['component|switch|off'] - results.solution['component|switch|count'] - - # Effects - results.solution['costs(periodic)'] - results.solution['costs(temporal)'] - results.solution['costs(temporal)|per_timestep'] - results.solution['costs'] - ``` +| Old | New | Old | New | +|-----|-----|-----|-----| +| `is_invested` | `invested` | `switch_on` | `switch\|on` | +| `switch_off` | `switch\|off` | `switch_on_nr` | `switch\|count` | +| `Effect(invest)\|total` | `Effect(periodic)` | `Effect(operation)\|total` | `Effect(temporal)` | +| `Effect(operation)\|total_per_timestep` | `Effect(temporal)\|per_timestep` | `Effect\|total` | `Effect` | --- -### Bus and Effect Assignment +### String Labels -Use string labels instead of object references. +Use strings instead of objects for Bus/Effect references. === "v2.x" ```python - # Bus assignment - my_bus = fx.Bus('electricity') flow = fx.Flow('P_el', bus=my_bus) # ❌ Object - - # Effect shares - CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') - costs = fx.Effect('costs', '€', 'Total costs', - share_from_temporal={CO2: 0.2}) # ❌ Object + costs = fx.Effect('costs', '€', share_from_temporal={CO2: 0.2}) # ❌ ``` === "v3.0.0" ```python - # Bus assignment - my_bus = fx.Bus('electricity') flow = fx.Flow('P_el', bus='electricity') # ✅ String - - # Effect shares - CO2 = fx.Effect('CO2', 'kg', 'CO2 emissions') - costs = fx.Effect('costs', '€', 'Total costs', - share_from_temporal={'CO2': 0.2}) # ✅ String + costs = fx.Effect('costs', '€', share_from_temporal={'CO2': 0.2}) # ✅ ``` --- -### FlowSystem Independence +### FlowSystem & Calculation -Each Calculation now receives its own FlowSystem copy. - -=== "v2.x" - ```python - # FlowSystem was shared - flow_system = fx.FlowSystem(time=timesteps) - calc1 = fx.FullCalculation('calc1', flow_system) # Shared reference - calc2 = fx.FullCalculation('calc2', flow_system) # Same reference - # Changes in calc1's FlowSystem would affect calc2 - ``` - -=== "v3.0.0" - ```python - # Each calculation gets a copy - flow_system = fx.FlowSystem(time=timesteps) - calc1 = fx.FullCalculation('calc1', flow_system) - calc2 = fx.FullCalculation('calc2', flow_system) # Gets copy - # Calculations are now independent - ``` - -!!! info "Impact" - - Mutations to one calculation's FlowSystem won't affect others - - Each `Subcalculation` in `SegmentedCalculation` has its own distinct FlowSystem - - Memory usage may increase slightly due to copying - -!!! tip "Migration" - If you relied on shared FlowSystem behavior (which you most likely did not or by accident), you should copy the flow_system before passing it to another calculation. +- **FlowSystem**: Each `Calculation` gets its own copy (independent) +- **do_modeling()**: Returns `Calculation` (access model via `.model` property) +- **Storage**: Arrays match timestep count (no extra element) + - Use `relative_minimum_final_charge_state` for final state control --- -### Calculation API +### Other Changes -`do_modeling()` now returns Calculation object for method chaining. - -=== "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) - ``` - -=== "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 - - # Enables method chaining - fx.FullCalculation('my_calc', flow_system).do_modeling().solve() - ``` - -!!! tip "Migration" - If you used the return value of `do_modeling()`, update to access `.model` property instead. - ---- - -### Storage Charge State - -Arrays now match timestep count (no extra element). - -=== "v2.x" - ```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 for 4 timesteps - ) - ``` - -=== "v3.0.0" - ```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 if needed - ) - ``` - -!!! note "Final State Control" - You only need to specify `relative_minimum_final_charge_state` if it differs from the last value of `relative_minimum_charge_state`. - -!!! info "Impact" - If you provided arrays with `len(timesteps) + 1` elements, reduce to `len(timesteps)`. - ---- - -### Other Breaking Changes - -=== "Plotting" - ```python - # v2.x - results.plot_heatmap('component|variable', mode='line') - - # v3.0.0 - results.plot_heatmap('component|variable', style='line') - ``` - -=== "Class Names" - ```python - # v2.x - from flixopt import SystemModel, Model - - # v3.0.0 - from flixopt import FlowSystemModel, Submodel - ``` - -=== "Logging" - ```python - # v2.x - enabled by default - # (no explicit configuration needed) - - # v3.0.0 - disabled by default - import flixopt as fx - fx.CONFIG.Logging.console = True - fx.CONFIG.apply() - ``` - -!!! warning "Breaking Change (from v2.2.0)" - If you're upgrading from v2.1.x or earlier to v3.0.0, logging output is no longer displayed unless explicitly enabled. See [Configuration](#configuration) for details. +| Category | Old | New | +|----------|-----|-----| +| Plotting | `mode='line'` | `style='line'` | +| Classes | `SystemModel`, `Model` | `FlowSystemModel`, `Submodel` | +| Logging | Enabled by default | Disabled (enable: `fx.CONFIG.Logging.console = True; fx.CONFIG.apply()`) | --- ## 🗑️ Deprecated Parameters -!!! info "Still Supported" - These parameters still work but will be removed in a future version. Deprecation warnings guide migration. - -### InvestParameters - -| 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` | - -=== "v2.x (Deprecated)" - ```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 - -| 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` | - -=== "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, - ) - ``` - -=== "v3.0.0 (Recommended)" - ```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 "InvestParameters" -### Component Parameters + `fix_effects` → `effects_of_investment` • `specific_effects` → `effects_of_investment_per_size` • `divest_effects` → `effects_of_retirement` • `piecewise_effects` → `piecewise_effects_of_investment` -| Old (v2.x) | New (v3.0.0) | -|------------|--------------| -| `source` (parameter) | `outputs` | -| `sink` (parameter) | `inputs` | -| `prevent_simultaneous_sink_and_source` | `prevent_simultaneous_flow_rates` | +??? abstract "Effect" -=== "v2.x (Deprecated)" - ```python - fx.Source('my_source', source=flow) - fx.Sink('my_sink', sink=flow) - fx.SourceAndSink('my_source_sink', source=flow1, sink=flow2, - prevent_simultaneous_sink_and_source=True) - ``` + `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` -=== "v3.0.0 (Recommended)" - ```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) - ``` +??? abstract "Components" ---- + `source` → `outputs` • `sink` → `inputs` • `prevent_simultaneous_sink_and_source` → `prevent_simultaneous_flow_rates` -### TimeSeriesData +??? abstract "TimeSeriesData & Calculation" -| Old (v2.x) | New (v3.0.0) | -|------------|--------------| -| `agg_group` | `aggregation_group` | -| `agg_weight` | `aggregation_weight` | - -=== "v2.x (Deprecated)" - ```python - fx.TimeSeriesData(agg_group='group1', agg_weight=2.0) - ``` - -=== "v3.0.0 (Recommended)" - ```python - fx.TimeSeriesData(aggregation_group='group1', aggregation_weight=2.0) - ``` + - `agg_group` → `aggregation_group` + - `agg_weight` → `aggregation_weight` + - `active_timesteps` → Use `flow_system.sel()` or `flow_system.isel()` --- -### Calculation +## ✨ New Features -=== "v2.x (Deprecated)" - ```python - calculation = fx.FullCalculation('calc', flow_system, active_timesteps=[0, 1, 2]) - ``` +??? success "Multi-Period Investments" -=== "v3.0.0 (Recommended)" ```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) - - # Or with isel for index-based selection - flow_system_subset = flow_system.isel(time=slice(0, 3)) - calculation = fx.FullCalculation('calc', flow_system_subset) + periods = pd.Index(['2020', '2030']) + flow_system = fx.FlowSystem(time=timesteps, periods=periods) ``` ---- - -## ✨ New Features - -### Multi-Period Investments - -Model transformation pathways with distinct decisions per 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 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} - ) - )] -) -``` - ---- - -### 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] - -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 -) -``` - ---- - -### Enhanced I/O - -Save, load, and manipulate FlowSystems. - -```python -# Save and load -flow_system.to_netcdf('system.nc') -fs = fx.FlowSystem.from_netcdf('system.nc') - -# Manipulate -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 from results -original_fs = results.flow_system # Lazily loaded -``` - ---- - -### Effects Per Component - -Analyze component impacts including indirect effects. - -```python -# Get dataset showing contribution of each component to all effects -effects_ds = results.effects_per_component - -print(effects_ds['total'].sel(effect='costs')) # Total costs by component -print(effects_ds['temporal'].sel(effect='CO2')) # Temporal CO2 emissions by component (including indirect) -``` - ---- - -### Balanced Storage +??? success "Scenario-Based Optimization" -Force equal charging/discharging sizes. - -```python -storage = fx.Storage( - 'storage', - charging=fx.Flow('charge', bus='electricity', - size=fx.InvestParameters(effects_of_investment_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 -) -``` - ---- - -### Final Charge State Control - -Set bounds on storage end state. - -```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 - -### Logging - -Console and file logging now disabled by default (changed in v2.2.0). - -=== "v2.1.x and earlier" ```python - import flixopt as fx - - # Logging was enabled by default - calculation = fx.FullCalculation('calc', flow_system) - calculation.solve() # Logs were shown automatically + scenarios = pd.Index(['low', 'base', 'high'], name='scenario') + flow_system = fx.FlowSystem(time=timesteps, scenarios=scenarios, + scenario_weights=[0.2, 0.6, 0.2], scenario_independent_sizes=True) ``` -=== "v2.2.0+ and v3.0.0" - ```python - import flixopt as fx +??? success "Enhanced I/O" - # Enable console logging explicitly - fx.CONFIG.Logging.console = True - fx.CONFIG.Logging.level = 'INFO' - fx.CONFIG.apply() + `flow_system.to_netcdf()` • `fx.FlowSystem.from_netcdf()` • `flow_system.sel()` • `flow_system.resample()` • `results.flow_system` - # Enable file logging (optional) - fx.CONFIG.Logging.file = 'flixopt.log' - fx.CONFIG.apply() - - calculation = fx.FullCalculation('calc', flow_system) - calculation.solve() # Now logs are shown - ``` +??? success "Effects Per Component" -!!! tip "Quick Enable" - Add at the start of your scripts: ```python - import flixopt as fx - fx.CONFIG.Logging.console = True - fx.CONFIG.apply() + effects_ds = results.effects_per_component + print(effects_ds['total'].sel(effect='costs')) ``` ---- - -## 🧪 Testing - -### Check Deprecation Warnings - -```python -import warnings -warnings.filterwarnings('default', category=DeprecationWarning) - -# Run your flixopt code -# Review any DeprecationWarning messages -``` +??? success "Storage Features" ---- - -### 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) -``` + **Balanced**: `balanced=True` ensures charge_size == discharge_size + **Final State**: `relative_minimum_final_charge_state=0.5`, `relative_maximum_final_charge_state=0.8` --- ## 🔧 Common Issues -!!! failure "Effect shares not working" - **Solution:** Effect sharing was completely redesigned. See [Effect System Redesign](#effect-system-redesign). - -!!! failure "Storage dimensions wrong" - **Solution:** Remove extra timestep from charge state arrays. See [Storage Charge State](#storage-charge-state). - -!!! failure "Bus assignment error" - **Solution:** Use string labels instead of Bus objects. See [Bus and Effect Assignment](#bus-and-effect-assignment). - -!!! failure "KeyError when accessing results" - **Solution:** Variable names have changed. See [Variable Names in Results](#variable-names-in-results) for the complete mapping. - -!!! failure "AttributeError: Element x has no attribute `model`" - **Solution:** Rename `.model` → `.submodel`. See [Other Breaking Changes](#other-breaking-changes). - -!!! failure "No logging output" - **Solution:** Logging is disabled by default. See [Configuration](#configuration) to enable it. +| 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) | --- ## ✅ Checklist -**Critical (Breaking Changes):** - -- [ ] Update flixopt: `pip install --upgrade flixopt` -- [ ] Update [effect sharing syntax](#effect-system-redesign) (no deprecation warning!) -- [ ] Update [variable names in results](#variable-names-in-results) -- [ ] Update [Bus/Effect assignments](#bus-and-effect-assignment) to use string labels -- [ ] Update [Calculation API](#calculation-api) usage if accessing return value -- [ ] Fix [storage charge state](#storage-charge-state) array dimensions -- [ ] Rename plotting `mode` → `style` -- [ ] Update class names: `SystemModel` → `FlowSystemModel`, `Model` → `Submodel` - -**Important:** - -- [ ] Enable [logging](#configuration) explicitly if needed -- [ ] Update [deprecated parameters](#deprecated-parameters) (optional, but recommended) - -**Testing:** - -- [ ] Test your code thoroughly -- [ ] Check for [deprecation warnings](#check-deprecation-warnings) -- [ ] [Validate results](#validate-results) match v2.x output (if upgrading) - -**Optional:** - -- [ ] Explore [new features](#new-features) +- [ ] `pip install --upgrade flixopt` +- [ ] Update [effect sharing](#effect-system-redesign), [variable names](#variable-names), [string labels](#string-labels) +- [ ] Fix [storage arrays](#flowsystem-calculation), [Calculation API](#flowsystem-calculation) +- [ ] Rename `mode` → `style`, update [class names](#other-changes) +- [ ] Enable [logging](#other-changes) if needed +- [ ] Update [deprecated parameters](#deprecated-parameters) +- [ ] Test & validate results --- -## 📚 Getting Help - -:material-book: [Documentation](https://flixopt.github.io/flixopt/) -:material-github: [GitHub Issues](https://github.com/flixOpt/flixopt/issues) -:material-text-box: [Full Changelog](https://flixopt.github.io/flixopt/latest/changelog/99984-v3.0.0/) - ---- +: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/) !!! success "Welcome to flixopt v3.0.0! 🎉" From afb0d19711edde93bd29dc0d249ed97902aba1d1 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:02:44 +0200 Subject: [PATCH 15/42] Enable plugin --- mkdocs.yml | 1 + 1 file changed, 1 insertion(+) 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 From 5cf023e87a586dcc00cd9a16deda2ba6598059e6 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:04:12 +0200 Subject: [PATCH 16/42] Update --- docs/user-guide/migration-guide-v3.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/user-guide/migration-guide-v3.md b/docs/user-guide/migration-guide-v3.md index bafce112a..c2ff45f93 100644 --- a/docs/user-guide/migration-guide-v3.md +++ b/docs/user-guide/migration-guide-v3.md @@ -39,10 +39,10 @@ Terminology changed: `operation` → `temporal`, `invest/investment` → `period | Old | New | Old | New | |-----|-----|-----|-----| -| `is_invested` | `invested` | `switch_on` | `switch\|on` | -| `switch_off` | `switch\|off` | `switch_on_nr` | `switch\|count` | -| `Effect(invest)\|total` | `Effect(periodic)` | `Effect(operation)\|total` | `Effect(temporal)` | -| `Effect(operation)\|total_per_timestep` | `Effect(temporal)\|per_timestep` | `Effect\|total` | `Effect` | +| `is_invested` | `invested` | `switch_on` | `switch|on` | +| `switch_off` | `switch|off` | `switch_on_nr` | `switch|count` | +| `Effect(invest)|total` | `Effect(periodic)` | `Effect(operation)|total` | `Effect(temporal)` | +| `Effect(operation)|total_per_timestep` | `Effect(temporal)|per_timestep` | `Effect|total` | `Effect` | --- From e61aa0228bb884a4565f088958b274f976eba6f2 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:08:46 +0200 Subject: [PATCH 17/42] Update --- docs/user-guide/migration-guide-v3.md | 147 ++++++++++++++++++-------- 1 file changed, 105 insertions(+), 42 deletions(-) diff --git a/docs/user-guide/migration-guide-v3.md b/docs/user-guide/migration-guide-v3.md index c2ff45f93..a98824de1 100644 --- a/docs/user-guide/migration-guide-v3.md +++ b/docs/user-guide/migration-guide-v3.md @@ -12,7 +12,14 @@ ### Effect System Redesign -Terminology changed: `operation` → `temporal`, `invest/investment` → `periodic`. Sharing inverted: effects now "pull" shares. +Terminology changed and sharing system inverted: effects now "pull" shares. + +| 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 @@ -25,30 +32,35 @@ Terminology changed: `operation` → `temporal`, `invest/investment` → `period ```python CO2 = fx.Effect('CO2', 'kg', 'CO2') costs = fx.Effect('costs', '€', 'Total', - share_from_temporal={'CO2': 0.2}) + share_from_temporal={'CO2': 0.2}) # Pull from CO2 ``` !!! warning "No deprecation warning" - - Move shares to receiving effect - - `specific_share_to_other_effects_operation` → `share_from_temporal` - - `specific_share_to_other_effects_invest` → `share_from_periodic` + Move shares to receiving effect and update parameter names throughout your code. --- ### Variable Names -| Old | New | Old | New | -|-----|-----|-----|-----| -| `is_invested` | `invested` | `switch_on` | `switch|on` | -| `switch_off` | `switch|off` | `switch_on_nr` | `switch|count` | -| `Effect(invest)|total` | `Effect(periodic)` | `Effect(operation)|total` | `Effect(temporal)` | -| `Effect(operation)|total_per_timestep` | `Effect(temporal)|per_timestep` | `Effect|total` | `Effect` | +| 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` | --- ### String Labels -Use strings instead of objects for Bus/Effect references. +| 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 @@ -66,20 +78,24 @@ Use strings instead of objects for Bus/Effect references. ### FlowSystem & Calculation -- **FlowSystem**: Each `Calculation` gets its own copy (independent) -- **do_modeling()**: Returns `Calculation` (access model via `.model` property) -- **Storage**: Arrays match timestep count (no extra element) - - Use `relative_minimum_final_charge_state` for final state control +| 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` | --- ### Other Changes -| Category | Old | New | -|----------|-----|-----| -| Plotting | `mode='line'` | `style='line'` | -| Classes | `SystemModel`, `Model` | `FlowSystemModel`, `Submodel` | -| Logging | Enabled by default | Disabled (enable: `fx.CONFIG.Logging.console = True; fx.CONFIG.apply()`) | +| 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()` | --- @@ -87,21 +103,44 @@ Use strings instead of objects for Bus/Effect references. ??? abstract "InvestParameters" - `fix_effects` → `effects_of_investment` • `specific_effects` → `effects_of_investment_per_size` • `divest_effects` → `effects_of_retirement` • `piecewise_effects` → `piecewise_effects_of_investment` + | 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` | ??? abstract "Effect" - `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` + | 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` | ??? abstract "Components" - `source` → `outputs` • `sink` → `inputs` • `prevent_simultaneous_sink_and_source` → `prevent_simultaneous_flow_rates` + | Old (v2.x) | New (v3.0.0) | + |------------|--------------| + | `source` (parameter) | `outputs` | + | `sink` (parameter) | `inputs` | + | `prevent_simultaneous_sink_and_source` | `prevent_simultaneous_flow_rates` | + +??? abstract "TimeSeriesData" + + | Old (v2.x) | New (v3.0.0) | + |------------|--------------| + | `agg_group` | `aggregation_group` | + | `agg_weight` | `aggregation_weight` | -??? abstract "TimeSeriesData & Calculation" +??? abstract "Calculation" - - `agg_group` → `aggregation_group` - - `agg_weight` → `aggregation_weight` - - `active_timesteps` → Use `flow_system.sel()` or `flow_system.isel()` + | Old (v2.x) | New (v3.0.0) | + |------------|--------------| + | `active_timesteps=[0, 1, 2]` | Use `flow_system.sel()` or `flow_system.isel()` | --- @@ -116,27 +155,51 @@ Use strings instead of objects for Bus/Effect references. ??? success "Scenario-Based Optimization" + | 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 - scenarios = pd.Index(['low', 'base', 'high'], name='scenario') - flow_system = fx.FlowSystem(time=timesteps, scenarios=scenarios, - scenario_weights=[0.2, 0.6, 0.2], scenario_independent_sizes=True) + flow_system = fx.FlowSystem( + time=timesteps, + scenarios=scenarios, + scenario_weights=[0.2, 0.6, 0.2], + scenario_independent_sizes=True + ) ``` ??? success "Enhanced I/O" - `flow_system.to_netcdf()` • `fx.FlowSystem.from_netcdf()` • `flow_system.sel()` • `flow_system.resample()` • `results.flow_system` + | 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 | ??? success "Effects Per Component" ```python effects_ds = results.effects_per_component - print(effects_ds['total'].sel(effect='costs')) + + # 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 ``` ??? success "Storage Features" - **Balanced**: `balanced=True` ensures charge_size == discharge_size - **Final State**: `relative_minimum_final_charge_state=0.5`, `relative_maximum_final_charge_state=0.8` + | 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 | --- @@ -155,13 +218,13 @@ Use strings instead of objects for Bus/Effect references. ## ✅ Checklist -- [ ] `pip install --upgrade flixopt` -- [ ] Update [effect sharing](#effect-system-redesign), [variable names](#variable-names), [string labels](#string-labels) -- [ ] Fix [storage arrays](#flowsystem-calculation), [Calculation API](#flowsystem-calculation) -- [ ] Rename `mode` → `style`, update [class names](#other-changes) -- [ ] Enable [logging](#other-changes) if needed -- [ ] Update [deprecated parameters](#deprecated-parameters) -- [ ] Test & validate results +| 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 | --- From fc8288fd351e910d72dcd6d358a077880e50ac5d Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:15:39 +0200 Subject: [PATCH 18/42] Customize --- docs/stylesheets/extra.css | 223 ++++++++++++++++++++++++++++++ mkdocs.yml | 272 +++++++++++++++++++++++++++++-------- 2 files changed, 438 insertions(+), 57 deletions(-) create mode 100644 docs/stylesheets/extra.css diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css new file mode 100644 index 000000000..085d7f55c --- /dev/null +++ b/docs/stylesheets/extra.css @@ -0,0 +1,223 @@ +/* ============================================================================ + flixOpt Custom Styling + ========================================================================= */ + +/* Root variables for easy customization */ +:root { + /* Spacing */ + --content-padding: 2rem; + + /* Typography */ + --heading-font-weight: 600; + + /* Colors - enhance teal theme */ + --flixopt-teal: #009688; + --flixopt-teal-light: #4DB6AC; + --flixopt-teal-dark: #00796B; +} + +/* Dark mode adjustments */ +[data-md-color-scheme="slate"] { + --md-code-bg-color: #1e1e1e; +} + +/* ============================================================================ + Typography Improvements + ========================================================================= */ + +/* Better line height for readability */ +.md-typeset { + line-height: 1.7; +} + +/* Enhanced headings */ +.md-typeset h1 { + font-weight: var(--heading-font-weight); + letter-spacing: -0.02em; + margin-top: 0; +} + +.md-typeset h2 { + font-weight: var(--heading-font-weight); + border-bottom: 1px solid var(--md-default-fg-color--lightest); + padding-bottom: 0.3em; + margin-top: 2em; +} + +/* Better code inline */ +.md-typeset code { + padding: 0.15em 0.4em; + border-radius: 0.25em; + font-size: 0.875em; +} + +/* ============================================================================ + Navigation Enhancements + ========================================================================= */ + +/* Smooth hover effects on navigation */ +.md-nav__link:hover { + opacity: 0.7; + transition: opacity 0.2s ease; +} + +/* Active navigation item enhancement */ +.md-nav__link--active { + font-weight: 600; + border-left: 3px solid var(--md-primary-fg-color); + padding-left: calc(1.2rem - 3px) !important; +} + +/* ============================================================================ + Code Block Improvements + ========================================================================= */ + +/* Better code block styling */ +.md-typeset .highlight { + border-radius: 0.5rem; + margin: 1.5em 0; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +[data-md-color-scheme="slate"] .md-typeset .highlight { + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3); +} + +/* Line numbers styling */ +.md-typeset .highlight .linenos { + user-select: none; + opacity: 0.5; +} + +/* Copy button enhancement */ +.md-clipboard { + opacity: 0; + transition: opacity 0.2s ease; +} + +.highlight:hover .md-clipboard { + opacity: 1; +} + +/* ============================================================================ + Admonitions & Callouts + ========================================================================= */ + +/* Enhanced admonitions */ +.md-typeset .admonition { + border-radius: 0.5rem; + border-left-width: 0.25rem; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); +} + +/* ============================================================================ + Tables + ========================================================================= */ + +/* Better table styling */ +.md-typeset table:not([class]) { + border-radius: 0.5rem; + overflow: hidden; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); +} + +.md-typeset table:not([class]) th { + background-color: var(--md-primary-fg-color); + color: white; + font-weight: 600; + text-align: left; +} + +.md-typeset table:not([class]) tr:hover { + background-color: var(--md-default-fg-color--lightest); + transition: background-color 0.2s ease; +} + +/* ============================================================================ + API Documentation Styling + ========================================================================= */ + +/* Better spacing for API docs */ +.doc-heading { + margin-top: 2rem !important; +} + +/* Parameter tables */ +.doc-md-description table { + width: 100%; + font-size: 0.9em; +} + +/* Signature styling */ +.doc-signature { + font-family: var(--md-code-font); + background-color: var(--md-code-bg-color); + border-radius: 0.5rem; + padding: 1rem; + overflow-x: auto; +} + +/* ============================================================================ + Home Page Hero (optional enhancement) + ========================================================================= */ + +.hero { + text-align: center; + padding: 4rem 2rem; + background: linear-gradient(135deg, var(--flixopt-teal-light) 0%, var(--flixopt-teal-dark) 100%); + color: white; + border-radius: 1rem; + margin-bottom: 2rem; +} + +.hero h1 { + font-size: 3rem; + margin-bottom: 1rem; + color: white; + border: none; +} + +.hero p { + font-size: 1.25rem; + opacity: 0.9; +} + +/* ============================================================================ + Responsive Design + ========================================================================= */ + +@media screen and (max-width: 76.1875em) { + .md-typeset h1 { + font-size: 2rem; + } +} + +@media screen and (max-width: 44.9375em) { + :root { + --content-padding: 1rem; + } + + .hero h1 { + font-size: 2rem; + } + + .hero p { + font-size: 1rem; + } +} + +/* ============================================================================ + Print Styles + ========================================================================= */ + +@media print { + .md-typeset { + font-size: 0.9rem; + } + + .md-header, + .md-sidebar, + .md-footer { + display: none; + } +} diff --git a/mkdocs.yml b/mkdocs.yml index 8ed2c4b2c..e67328e1b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,13 +1,16 @@ -# Options: +# flixOpt Documentation Configuration # https://mkdocstrings.github.io/python/usage/configuration/docstrings/ # https://squidfunk.github.io/mkdocs-material/setup/ -site_name: flixopt +site_name: flixOpt site_description: Energy and Material Flow Optimization Framework site_url: https://flixopt.github.io/flixopt/ repo_url: https://github.com/flixOpt/flixopt repo_name: flixOpt/flixopt +# Copyright and social links +copyright: Copyright © 2024 flixOpt Contributors + nav: - Home: index.md - User Guide: @@ -39,126 +42,281 @@ nav: - API Reference: api-reference/ - Release Notes: changelog/ - theme: name: material + language: en + palette: - # Light mode + # Palette toggle for automatic mode + - media: "(prefers-color-scheme)" + toggle: + icon: material/brightness-auto + name: Switch to light mode + + # Palette toggle for light mode - media: "(prefers-color-scheme: light)" scheme: default primary: teal - accent: blue + accent: cyan toggle: icon: material/brightness-7 name: Switch to dark mode - # Dark mode + + # Palette toggle for dark mode - media: "(prefers-color-scheme: dark)" scheme: slate - primary: teal # Can be different from light mode - accent: blue + primary: teal + accent: cyan toggle: icon: material/brightness-4 - name: Switch to light mode + name: Switch to system preference + + font: + text: Inter # Modern, readable font + code: Fira Code # Beautiful code font with ligatures + logo: images/flixopt-icon.svg favicon: images/flixopt-icon.svg + icon: repo: fontawesome/brands/github + edit: material/pencil + view: material/eye + annotation: material/plus-circle + features: + # Navigation - navigation.instant - navigation.instant.progress + - navigation.instant.prefetch - navigation.tracking - navigation.tabs + - navigation.tabs.sticky - navigation.sections + - navigation.expand # Expand navigation by default + - navigation.path # Show breadcrumb path + - navigation.prune # Only render visible navigation + - navigation.indexes - navigation.top - navigation.footer + + # Table of contents - toc.follow - - navigation.indexes + - toc.integrate # Integrate TOC into navigation (optional) + + # Search - search.suggest - search.highlight + - search.share + + # Content - content.action.edit - content.action.view - content.code.copy + - content.code.select - content.code.annotate - content.tooltips - - navigation.footer.version + - content.tabs.link # Link content tabs across pages + + # Header + - announce.dismiss # Allow dismissing announcements markdown_extensions: + # Content formatting + - abbr - admonition - - markdown_include.include: - base_path: docs + - attr_list + - def_list + - footnotes + - md_in_html + - tables + - toc: + permalink: true + permalink_title: Anchor link to this section + toc_depth: 3 + + # Code blocks - pymdownx.highlight: anchor_linenums: true line_spans: __span pygments_lang_class: true + auto_title: true - pymdownx.inlinehilite + - pymdownx.snippets: + base_path: .. + check_paths: true + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + + # Enhanced content - pymdownx.details - - pymdownx.superfences - - attr_list - - abbr - - md_in_html - - footnotes - - tables - pymdownx.tabbed: alternate_style: true + combine_header_slug: true + - pymdownx.tasklist: + custom_checkbox: true + + # Typography + - pymdownx.betterem: + smart_enable: all + - pymdownx.caret + - pymdownx.mark + - pymdownx.tilde + - pymdownx.smartsymbols + - pymdownx.keys + + # Math - pymdownx.arithmatex: generic: true + + # Icons & emojis - pymdownx.emoji: emoji_index: !!python/name:material.extensions.emoji.twemoji emoji_generator: !!python/name:material.extensions.emoji.to_svg - - pymdownx.snippets: - base_path: .. + options: + custom_icons: + - overrides/.icons + + # Legacy support + - markdown_include.include: + base_path: docs plugins: - - search # Enables the search functionality in the documentation - - table-reader # Allows including tables from external files + - search: + separator: '[\s\u200b\-_,:!=\[\]()"`/]+|\.(?!\d)|&[lg]t;|(?!\b)(?=[A-Z][a-z])' + + - table-reader + - include-markdown + - mike: + alias_type: symlink + redirect_template: null + deploy_prefix: '' + canonical_version: null version_selector: true + css_dir: css + javascript_dir: js + - literate-nav: nav_file: SUMMARY.md + implicit_index: true + - gen-files: scripts: - - scripts/gen_ref_pages.py - - mkdocstrings: # Handles automatic API documentation generation - default_handler: python # Sets Python as the default language - handlers: - python: # Configuration for Python code documentation - options: - docstring_style: google # Sets google as the docstring style - modernize_annotations: true # Improves type annotations - merge_init_into_class: true # Promotes constructor parameters to class-level documentation - docstring_section_style: table # Renders parameter sections as a table (also: list, spacy) - - members_order: source # Orders members as they appear in the source code - inherited_members: false # Include members inherited from parent classes - show_if_no_docstring: false # Documents objects even if they don't have docstrings - - group_by_category: true - heading_level: 1 # Sets the base heading level for documented objects - line_length: 80 - filters: ["!^_", "^__init__$"] - show_root_heading: true # whether the documented object's name should be displayed as a heading at the beginning of its documentation - show_source: false # Shows the source code implementation from documentation - show_object_full_path: false # Displays simple class names instead of full import paths - show_docstring_attributes: true # Shows class attributes in the documentation - show_category_heading: true # Displays category headings (Methods, Attributes, etc.) for organization - show_signature: true # Shows method signatures with parameters - show_signature_annotations: true # Includes type annotations in the signatures when available - show_root_toc_entry: false # Whether to show a link to the root of the documentation in the sidebar - separate_signature: true # Displays signatures separate from descriptions for cleaner layout - - extra: - infer_type_annotations: true # Uses Python type hints to supplement docstring information + - scripts/gen_ref_pages.py + + - mkdocstrings: + enabled: !ENV [ENABLE_MKDOCSTRINGS, true] + default_handler: python + handlers: + python: + paths: [.] + import: + - https://docs.python.org/3/objects.inv + - https://numpy.org/doc/stable/objects.inv + - https://pandas.pydata.org/docs/objects.inv + options: + # Docstring parsing + docstring_style: google + docstring_section_style: table + + # Member ordering and filtering + members_order: source + inherited_members: false + show_if_no_docstring: false + filters: ["!^_", "^__init__$"] + group_by_category: true + + # Headings and structure + heading_level: 1 + show_root_heading: true + show_root_toc_entry: false + show_category_heading: true + + # Signatures + show_signature: true + show_signature_annotations: true + separate_signature: true + line_length: 80 + + # Source and paths + show_source: false + show_object_full_path: false + + # Attributes and annotations + show_docstring_attributes: true + modernize_annotations: true + merge_init_into_class: true + + # Improved type hints + annotations_path: brief + + # Optional: Add git info + - git-revision-date-localized: + enable_creation_date: true + type: timeago + fallback_to_build_date: true + + # Optional: Add better navigation + - tags: + tags_file: tags.md + + # Optional: Minify HTML in production + - minify: + minify_html: true + minify_js: true + minify_css: true + htmlmin_opts: + remove_comments: true extra: version: provider: mike default: latest + alias: true + + social: + - icon: fontawesome/brands/github + link: https://github.com/flixOpt/flixopt + name: flixOpt on GitHub + - icon: fontawesome/brands/python + link: https://pypi.org/project/flixopt/ + name: flixOpt on PyPI + + analytics: + provider: google + property: !ENV GOOGLE_ANALYTICS_KEY + feedback: + title: Was this page helpful? + ratings: + - icon: material/emoticon-happy-outline + name: This page was helpful + data: 1 + note: >- + Thanks for your feedback! + - icon: material/emoticon-sad-outline + name: This page could be improved + data: 0 + note: >- + Thanks for your feedback! Help us improve by + opening an issue. + + status: + new: Recently added + deprecated: Deprecated + +extra_css: + - stylesheets/extra.css extra_javascript: - - javascripts/mathjax.js # Custom MathJax 3 CDN Configuration - - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js #MathJax 3 CDN - - https://polyfill.io/v3/polyfill.min.js?features=es6 #Support for older browsers + - javascripts/mathjax.js + - https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js + - https://polyfill.io/v3/polyfill.min.js?features=es6 watch: - flixopt + - overrides From 3d83127a44a334ce2df01498508af36b924d7bec Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:20:12 +0200 Subject: [PATCH 19/42] Customize --- mkdocs.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index e67328e1b..ddfb3dff0 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -319,4 +319,3 @@ extra_javascript: watch: - flixopt - - overrides From 7fb19dd3c6b21a2d7a50b5e5aa52c7f18466876b Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:20:59 +0200 Subject: [PATCH 20/42] Add deps --- pyproject.toml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 9e1821a4b..0bf559b7d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -34,9 +34,9 @@ dependencies = [ # Core scientific computing "numpy >= 1.21.5, < 3", "pandas >= 2.0.0, < 3", - "xarray >= 2024.2.0, < 2026.0", # CalVer: allow through next calendar year + "xarray >= 2024.2.0, < 2026.0", # CalVer: allow through next calendar year # Optimization and data handling - "linopy >= 0.5.1, < 0.6", # Widened from patch pin to minor range + "linopy >= 0.5.1, < 0.6", # Widened from patch pin to minor range "h5netcdf>=1.0.0, < 2", # Utilities "pyyaml >= 6.0.0, < 7", @@ -44,13 +44,11 @@ dependencies = [ "tomli >= 2.0.1, < 3; python_version < '3.11'", # Only needed with python 3.10 or earlier # Default solver "highspy >= 1.5.3, < 2", - # Visualization "matplotlib >= 3.5.2, < 4", "plotly >= 5.15.0, < 7", - # Fix for numexpr compatibility issue with numpy 1.26.4 on Python 3.10 - "numexpr >= 2.8.4, < 2.14; python_version < '3.11'", # Avoid 2.14.0 on older Python + "numexpr >= 2.8.4, < 2.14; python_version < '3.11'", # Avoid 2.14.0 on older Python ] [project.optional-dependencies] @@ -108,6 +106,8 @@ docs = [ "pymdown-extensions==10.16.1", "pygments==2.19.2", "mike==2.1.3", + "mkdocs-git-revision-date-localized-plugin==1.4.7", + "mkdocs-minify-plugin==0.8.0", ] [project.urls] From 5b3262743b0b9e5ff7817cc5527ea07c4683b011 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:21:10 +0200 Subject: [PATCH 21/42] Make index.md pretty --- docs/index.md | 343 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 336 insertions(+), 7 deletions(-) diff --git a/docs/index.md b/docs/index.md index 6723c4d5e..25cad9719 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,22 +1,351 @@ +--- +title: Home +hide: + - navigation + - toc +--- + + + +
+ +# flixOpt + +

Energy and Material Flow Optimization Framework

+ +Model, optimize, and analyze complex energy systems with a powerful Python framework designed for flexibility and performance. + +
+ [Get Started :material-rocket-launch:](getting-started.md){ .md-button .md-button--primary } + [View Examples :material-code-braces:](examples/index.md){ .md-button } + [GitHub :fontawesome-brands-github:](https://github.com/flixOpt/flixopt){ .md-button } +
+ +
+ +--- + +## :material-star-four-points: Key Features + +
+ +
+ :material-lightning-bolt: +

High Performance

+

Efficient optimization algorithms powered by industry-standard solvers for fast computation of complex energy systems

+
+ +
+ :material-puzzle: +

Modular Design

+

Flexible component-based architecture allowing you to build systems from flows, buses, storage, and converters

+
+ +
+ :material-chart-line: +

Advanced Modeling

+

Support for piecewise linearization, on/off parameters, investment decisions, and duration tracking

+
+ +
+ :material-code-tags: +

Pythonic API

+

Clean, intuitive interface with comprehensive type hints and excellent documentation

+
+ +
+ :material-file-document-multiple: +

Well Documented

+

Extensive guides, mathematical notation, examples, and API reference to get you productive quickly

+
+ +
+ :material-open-source-initiative: +

Open Source

+

MIT licensed and community-driven development with contributions welcome

+
+ +
+ +--- + {% include-markdown "../README.md" + start="## Installation" + end="## License" %} --- -## Documentation Architecture +## :material-architecture: Documentation Architecture + +
![FlixOpt Conceptual Usage](./images/architecture_flixOpt.png)
Conceptual Usage and IO operations of FlixOpt
+**FlixOpt** provides a complete workflow for energy system optimization: + +- **:material-file-code:** Define** your system using Python components +- **:material-cog:** Optimize** with powerful solvers (HiGHS, Gurobi, CPLEX) +- **:material-chart-box:** Analyze** results with built-in visualization tools +- **:material-export:** Export** to various formats for further analysis + +
+ +--- + +## :material-map-marker-path: Quick Navigation + + + --- -## Next Steps +## :material-account-group: Community & Support + +
+ +
+ :fontawesome-brands-github: +

GitHub

+

Report issues, request features, and contribute to the codebase

+ Visit Repository → +
+ +
+ :material-forum: +

Discussions

+

Ask questions and share your projects with the community

+ Join Discussion → +
+ +
+ :material-book-open-page-variant: +

Contributing

+

Help improve FlixOpt by contributing code, docs, or examples

+ Learn How → +
+ +
+ +--- + +## :material-file-document-edit: Recent Updates + +!!! tip "What's New in v3.0.0" + Major improvements and breaking changes. Check the [Migration Guide](user-guide/migration-guide-v3.md) for upgrading from v2.x. + +📋 See the full [Release Notes](changelog/) for detailed version history. + +--- + +
+ +### Ready to optimize your energy system? + +[Start Building :material-arrow-right:](getting-started.md){ .md-button .md-button--primary .md-button--lg } -- **New to FlixOpt?** Start with the [Getting Started Guide](getting-started.md) -- **Want to see examples?** Check out the [Examples Gallery](examples/index.md) -- **Need API details?** Browse the [API Reference](api-reference/index.md) -- **Looking for advanced patterns?** See [Recipes](user-guide/recipes/index.md) -- **Curious about the future?** Read our [Roadmap](roadmap.md) +
From f0b0d54fe0d24972de88697e88662d51a6d13786 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:31:09 +0200 Subject: [PATCH 22/42] Fix --- docs/index.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/docs/index.md b/docs/index.md index 25cad9719..bf0d51bd6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -184,10 +184,10 @@ hide: Model, optimize, and analyze complex energy systems with a powerful Python framework designed for flexibility and performance. -
- [Get Started :material-rocket-launch:](getting-started.md){ .md-button .md-button--primary } - [View Examples :material-code-braces:](examples/index.md){ .md-button } - [GitHub :fontawesome-brands-github:](https://github.com/flixOpt/flixopt){ .md-button } +
+[:material-rocket-launch: Get Started](getting-started.md){ .md-button .md-button--primary } +[:material-code-braces: View Examples](examples/index.md){ .md-button } +[:fontawesome-brands-github: GitHub](https://github.com/flixOpt/flixopt){ .md-button }
@@ -257,10 +257,10 @@ Model, optimize, and analyze complex energy systems with a powerful Python frame **FlixOpt** provides a complete workflow for energy system optimization: -- **:material-file-code:** Define** your system using Python components -- **:material-cog:** Optimize** with powerful solvers (HiGHS, Gurobi, CPLEX) -- **:material-chart-box:** Analyze** results with built-in visualization tools -- **:material-export:** Export** to various formats for further analysis +- **:material-file-code: Define** your system using Python components +- **:material-cog: Optimize** with powerful solvers (HiGHS, Gurobi, CPLEX) +- **:material-chart-box: Analyze** results with built-in visualization tools +- **:material-export: Export** to various formats for further analysis @@ -342,10 +342,10 @@ Model, optimize, and analyze complex energy systems with a powerful Python frame --- -
+
### Ready to optimize your energy system? -[Start Building :material-arrow-right:](getting-started.md){ .md-button .md-button--primary .md-button--lg } +[:material-arrow-right: Start Building](getting-started.md){ .md-button .md-button--primary .md-button--lg }
From c374c25e3b650f818f1f2572e3ee4503cef04f9c Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:34:41 +0200 Subject: [PATCH 23/42] Fix --- docs/index.md | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/docs/index.md b/docs/index.md index bf0d51bd6..4cb9be7b7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -176,19 +176,19 @@ hide: } -
+
-# flixOpt +

flixOpt

Energy and Material Flow Optimization Framework

-Model, optimize, and analyze complex energy systems with a powerful Python framework designed for flexibility and performance. +

Model, optimize, and analyze complex energy systems with a powerful Python framework designed for flexibility and performance.

-
-[:material-rocket-launch: Get Started](getting-started.md){ .md-button .md-button--primary } -[:material-code-braces: View Examples](examples/index.md){ .md-button } -[:fontawesome-brands-github: GitHub](https://github.com/flixOpt/flixopt){ .md-button } -
+

+ 🚀 Get Started + 💡 View Examples + ⭐ GitHub +

@@ -342,10 +342,12 @@ Model, optimize, and analyze complex energy systems with a powerful Python frame --- -
+
-### Ready to optimize your energy system? +

Ready to optimize your energy system?

-[:material-arrow-right: Start Building](getting-started.md){ .md-button .md-button--primary .md-button--lg } +

+ ▶️ Start Building +

From 23a6b5b049ac906a199e93d98b2ff59405cec213 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:40:13 +0200 Subject: [PATCH 24/42] Fix icons --- docs/index.md | 127 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 83 insertions(+), 44 deletions(-) diff --git a/docs/index.md b/docs/index.md index 4cb9be7b7..e8d50266d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -185,8 +185,8 @@ hide:

Model, optimize, and analyze complex energy systems with a powerful Python framework designed for flexibility and performance.

- 🚀 Get Started - 💡 View Examples + 🚀 Get Started + 💡 View Examples ⭐ GitHub

@@ -196,42 +196,66 @@ hide: ## :material-star-four-points: Key Features -
+
+ +
+ +:material-lightning-bolt:{ .feature-icon } + +### High Performance + +Efficient optimization algorithms powered by industry-standard solvers for fast computation of complex energy systems -
- :material-lightning-bolt: -

High Performance

-

Efficient optimization algorithms powered by industry-standard solvers for fast computation of complex energy systems

-
- :material-puzzle: -

Modular Design

-

Flexible component-based architecture allowing you to build systems from flows, buses, storage, and converters

+
+ +:material-puzzle:{ .feature-icon } + +### Modular Design + +Flexible component-based architecture allowing you to build systems from flows, buses, storage, and converters +
-
- :material-chart-line: -

Advanced Modeling

-

Support for piecewise linearization, on/off parameters, investment decisions, and duration tracking

+
+ +:material-chart-line:{ .feature-icon } + +### Advanced Modeling + +Support for piecewise linearization, on/off parameters, investment decisions, and duration tracking +
-
- :material-code-tags: -

Pythonic API

-

Clean, intuitive interface with comprehensive type hints and excellent documentation

+
+ +:material-code-tags:{ .feature-icon } + +### Pythonic API + +Clean, intuitive interface with comprehensive type hints and excellent documentation +
-
- :material-file-document-multiple: -

Well Documented

-

Extensive guides, mathematical notation, examples, and API reference to get you productive quickly

+
+ +:material-file-document-multiple:{ .feature-icon } + +### Well Documented + +Extensive guides, mathematical notation, examples, and API reference to get you productive quickly +
-
- :material-open-source-initiative: -

Open Source

-

MIT licensed and community-driven development with contributions welcome

+
+ +:material-open-source-initiative:{ .feature-icon } + +### Open Source + +MIT licensed and community-driven development with contributions welcome +
@@ -306,27 +330,42 @@ hide: ## :material-account-group: Community & Support -
+
+ +
+ +:fontawesome-brands-github:{ .feature-icon } + +### GitHub + +Report issues, request features, and contribute to the codebase + +[Visit Repository →](https://github.com/flixOpt/flixopt){target="_blank"} -
- :fontawesome-brands-github: -

GitHub

-

Report issues, request features, and contribute to the codebase

- Visit Repository →
-
- :material-forum: -

Discussions

-

Ask questions and share your projects with the community

- Join Discussion → +
+ +:material-forum:{ .feature-icon } + +### Discussions + +Ask questions and share your projects with the community + +[Join Discussion →](https://github.com/flixOpt/flixopt/discussions){target="_blank"} +
-
- :material-book-open-page-variant: -

Contributing

-

Help improve FlixOpt by contributing code, docs, or examples

- Learn How → +
+ +:material-book-open-page-variant:{ .feature-icon } + +### Contributing + +Help improve FlixOpt by contributing code, docs, or examples + +[Learn How →](contribute/){target="_blank"} +
@@ -347,7 +386,7 @@ hide:

Ready to optimize your energy system?

- ▶️ Start Building + ▶️ Start Building

From c1bc3f8343d4bd2f5d9f5b967882e3421592ebc6 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:44:13 +0200 Subject: [PATCH 25/42] Fix quick nav --- docs/index.md | 58 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/docs/index.md b/docs/index.md index e8d50266d..8df8be6d1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -272,7 +272,7 @@ MIT licensed and community-driven development with contributions welcome ## :material-architecture: Documentation Architecture -
+
![FlixOpt Conceptual Usage](./images/architecture_flixOpt.png) @@ -292,36 +292,54 @@ MIT licensed and community-driven development with contributions welcome ## :material-map-marker-path: Quick Navigation - + +--- + +{% + include-markdown "../README.md" + start="## Installation" + end="## License" +%} diff --git a/mkdocs.yml b/mkdocs.yml index ddfb3dff0..81537be41 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -319,3 +319,4 @@ extra_javascript: watch: - flixopt + - docs From dcd6eadb686e4f335a86f373d7056b86a3ad5735 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 16:57:18 +0200 Subject: [PATCH 28/42] Add semantic colors --- docs/stylesheets/extra.css | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index 085d7f55c..1508bd7e5 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -10,10 +10,16 @@ /* Typography */ --heading-font-weight: 600; - /* Colors - enhance teal theme */ - --flixopt-teal: #009688; - --flixopt-teal-light: #4DB6AC; - --flixopt-teal-dark: #00796B; + /* Colors - Redefine original teal theme with new palette shades (Brand Color column) */ + --flixopt-teal: #009688; /* Brand Color 500 */ + --flixopt-teal-light: #4DB6AC; /* Brand Color 300 */ + --flixopt-teal-dark: #00796B; /* Brand Color 700 */ + + /* NEW: Semantic Colors for direct use in custom components (e.g., semantic callouts) */ + --color-success: #4BA527; + --color-info: #0290E2; + --color-warning: #EF8809; + --color-danger: #CE2947; } /* Dark mode adjustments */ From 1a1f4a7e6b7137cb80306333a8bcff431d31381c Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 17:02:50 +0200 Subject: [PATCH 29/42] Add semantic colors --- docs/stylesheets/extra.css | 78 +++++++++++++++++++++++++++++++++++++- 1 file changed, 76 insertions(+), 2 deletions(-) diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index 1508bd7e5..5191f7633 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -20,13 +20,26 @@ --color-info: #0290E2; --color-warning: #EF8809; --color-danger: #CE2947; + + /* Semantic Light Backgrounds (using 100 or 200 shades from your chart if possible, or lightened versions) */ + --color-success-light: #F0FAE9; /* Light green/Success 100 */ + --color-info-light: #E7F5FF; /* Light blue/Info 100 */ + --color-warning-light: #FFF8E6; /* Light orange/Warning 100 */ + --color-danger-light: #FFEDED; /* Light red/Danger 100 */ } /* Dark mode adjustments */ [data-md-color-scheme="slate"] { --md-code-bg-color: #1e1e1e; + + /* Dark Mode Semantic Adjustments for better visibility */ + --color-success-dark-bg: #1B3C0F; + --color-info-dark-bg: #0C2B47; + --color-warning-dark-bg: #4F380A; + --color-danger-dark-bg: #470D18; } + /* ============================================================================ Typography Improvements ========================================================================= */ @@ -106,16 +119,77 @@ } /* ============================================================================ - Admonitions & Callouts + Admonitions & Callouts - NEW SEMANTIC STYLING ========================================================================= */ -/* Enhanced admonitions */ +/* Enhanced admonitions (existing style preserved) */ .md-typeset .admonition { border-radius: 0.5rem; border-left-width: 0.25rem; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); } +/* Admonitions using the new palette */ + +/* Success and Tip (often mapped to success for positive tone) */ +.md-typeset .admonition.success, +.md-typeset .admonition.tip, +.md-typeset div.success, +.md-typeset div.tip { + --md-typeset-color-tip: var(--color-success); + --md-typeset-color-tip-bg: var(--color-success-light); +} + +/* Info, Note, and Abstract (mapped to Info blue for neutral/informational tone) */ +.md-typeset .admonition.info, +.md-typeset .admonition.note, +.md-typeset .admonition.abstract, +.md-typeset div.info, +.md-typeset div.note, +.md-typeset div.abstract { + --md-typeset-color-info: var(--color-info); + --md-typeset-color-info-bg: var(--color-info-light); +} + +/* Warning and Caution */ +.md-typeset .admonition.warning, +.md-typeset .admonition.caution, +.md-typeset div.warning, +.md-typeset div.caution { + --md-typeset-color-warning: var(--color-warning); + --md-typeset-color-warning-bg: var(--color-warning-light); +} + +/* Danger, Error, and Failure */ +.md-typeset .admonition.danger, +.md-typeset .admonition.error, +.md-typeset .admonition.failure, +.md-typeset div.danger, +.md-typeset div.error, +.md-typeset div.failure { + --md-typeset-color-danger: var(--color-danger); + --md-typeset-color-danger-bg: var(--color-danger-light); +} + +/* Dark Mode Overrides for better contrast */ +[data-md-color-scheme="slate"] { + --md-code-bg-color: #1e1e1e; + + .md-typeset .admonition.success, .md-typeset .admonition.tip { + --md-typeset-color-tip-bg: var(--color-success-dark-bg); + } + .md-typeset .admonition.info, .md-typeset .admonition.note, .md-typeset .admonition.abstract { + --md-typeset-color-info-bg: var(--color-info-dark-bg); + } + .md-typeset .admonition.warning, .md-typeset .admonition.caution { + --md-typeset-color-warning-bg: var(--color-warning-dark-bg); + } + .md-typeset .admonition.danger, .md-typeset .admonition.error, .md-typeset .admonition.failure { + --md-typeset-color-danger-bg: var(--color-danger-dark-bg); + } +} + + /* ============================================================================ Tables ========================================================================= */ From 31cf8c8a6fd141c3d3bc92aa2eb53245e24bfd0a Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 17:08:09 +0200 Subject: [PATCH 30/42] More css --- docs/stylesheets/extra.css | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index 5191f7633..78bbbf7b4 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -119,7 +119,7 @@ } /* ============================================================================ - Admonitions & Callouts - NEW SEMANTIC STYLING + Admonitions & Callouts - CORRECTED SEMANTIC STYLING ========================================================================= */ /* Enhanced admonitions (existing style preserved) */ @@ -129,18 +129,21 @@ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); } -/* Admonitions using the new palette */ - -/* Success and Tip (often mapped to success for positive tone) */ +/* Success and Tip (Green) */ .md-typeset .admonition.success, .md-typeset .admonition.tip, .md-typeset div.success, .md-typeset div.tip { + /* This sets the border, title bar, and icon color to your bold semantic color */ --md-typeset-color-tip: var(--color-success); + --md-typeset-color-success: var(--color-success); + + /* This sets the background to your defined lighter shade */ --md-typeset-color-tip-bg: var(--color-success-light); + --md-typeset-color-success-bg: var(--color-success-light); } -/* Info, Note, and Abstract (mapped to Info blue for neutral/informational tone) */ +/* Info, Note, and Abstract (Blue) */ .md-typeset .admonition.info, .md-typeset .admonition.note, .md-typeset .admonition.abstract, @@ -148,10 +151,15 @@ .md-typeset div.note, .md-typeset div.abstract { --md-typeset-color-info: var(--color-info); + --md-typeset-color-abstract: var(--color-info); /* Use info color for abstract/note */ + --md-typeset-color-note: var(--color-info); + --md-typeset-color-info-bg: var(--color-info-light); + --md-typeset-color-abstract-bg: var(--color-info-light); + --md-typeset-color-note-bg: var(--color-info-light); } -/* Warning and Caution */ +/* Warning and Caution (Orange) */ .md-typeset .admonition.warning, .md-typeset .admonition.caution, .md-typeset div.warning, @@ -160,7 +168,7 @@ --md-typeset-color-warning-bg: var(--color-warning-light); } -/* Danger, Error, and Failure */ +/* Danger, Error, and Failure (Red) */ .md-typeset .admonition.danger, .md-typeset .admonition.error, .md-typeset .admonition.failure, @@ -175,11 +183,15 @@ [data-md-color-scheme="slate"] { --md-code-bg-color: #1e1e1e; + /* Apply Dark Mode Backgrounds */ .md-typeset .admonition.success, .md-typeset .admonition.tip { --md-typeset-color-tip-bg: var(--color-success-dark-bg); + --md-typeset-color-success-bg: var(--color-success-dark-bg); } .md-typeset .admonition.info, .md-typeset .admonition.note, .md-typeset .admonition.abstract { --md-typeset-color-info-bg: var(--color-info-dark-bg); + --md-typeset-color-abstract-bg: var(--color-info-dark-bg); + --md-typeset-color-note-bg: var(--color-info-dark-bg); } .md-typeset .admonition.warning, .md-typeset .admonition.caution { --md-typeset-color-warning-bg: var(--color-warning-dark-bg); From 51cfdbf10b712122a2971abf5cbf05e9ca6950ba Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 17:08:15 +0200 Subject: [PATCH 31/42] Revert "More css" This reverts commit 31cf8c8a6fd141c3d3bc92aa2eb53245e24bfd0a. --- docs/stylesheets/extra.css | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index 78bbbf7b4..5191f7633 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -119,7 +119,7 @@ } /* ============================================================================ - Admonitions & Callouts - CORRECTED SEMANTIC STYLING + Admonitions & Callouts - NEW SEMANTIC STYLING ========================================================================= */ /* Enhanced admonitions (existing style preserved) */ @@ -129,21 +129,18 @@ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); } -/* Success and Tip (Green) */ +/* Admonitions using the new palette */ + +/* Success and Tip (often mapped to success for positive tone) */ .md-typeset .admonition.success, .md-typeset .admonition.tip, .md-typeset div.success, .md-typeset div.tip { - /* This sets the border, title bar, and icon color to your bold semantic color */ --md-typeset-color-tip: var(--color-success); - --md-typeset-color-success: var(--color-success); - - /* This sets the background to your defined lighter shade */ --md-typeset-color-tip-bg: var(--color-success-light); - --md-typeset-color-success-bg: var(--color-success-light); } -/* Info, Note, and Abstract (Blue) */ +/* Info, Note, and Abstract (mapped to Info blue for neutral/informational tone) */ .md-typeset .admonition.info, .md-typeset .admonition.note, .md-typeset .admonition.abstract, @@ -151,15 +148,10 @@ .md-typeset div.note, .md-typeset div.abstract { --md-typeset-color-info: var(--color-info); - --md-typeset-color-abstract: var(--color-info); /* Use info color for abstract/note */ - --md-typeset-color-note: var(--color-info); - --md-typeset-color-info-bg: var(--color-info-light); - --md-typeset-color-abstract-bg: var(--color-info-light); - --md-typeset-color-note-bg: var(--color-info-light); } -/* Warning and Caution (Orange) */ +/* Warning and Caution */ .md-typeset .admonition.warning, .md-typeset .admonition.caution, .md-typeset div.warning, @@ -168,7 +160,7 @@ --md-typeset-color-warning-bg: var(--color-warning-light); } -/* Danger, Error, and Failure (Red) */ +/* Danger, Error, and Failure */ .md-typeset .admonition.danger, .md-typeset .admonition.error, .md-typeset .admonition.failure, @@ -183,15 +175,11 @@ [data-md-color-scheme="slate"] { --md-code-bg-color: #1e1e1e; - /* Apply Dark Mode Backgrounds */ .md-typeset .admonition.success, .md-typeset .admonition.tip { --md-typeset-color-tip-bg: var(--color-success-dark-bg); - --md-typeset-color-success-bg: var(--color-success-dark-bg); } .md-typeset .admonition.info, .md-typeset .admonition.note, .md-typeset .admonition.abstract { --md-typeset-color-info-bg: var(--color-info-dark-bg); - --md-typeset-color-abstract-bg: var(--color-info-dark-bg); - --md-typeset-color-note-bg: var(--color-info-dark-bg); } .md-typeset .admonition.warning, .md-typeset .admonition.caution { --md-typeset-color-warning-bg: var(--color-warning-dark-bg); From a79e8289344dacfee5ff826e697ff400d7f44da3 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 17:08:16 +0200 Subject: [PATCH 32/42] Revert "Add semantic colors" This reverts commit 1a1f4a7e6b7137cb80306333a8bcff431d31381c. --- docs/stylesheets/extra.css | 78 +------------------------------------- 1 file changed, 2 insertions(+), 76 deletions(-) diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index 5191f7633..1508bd7e5 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -20,26 +20,13 @@ --color-info: #0290E2; --color-warning: #EF8809; --color-danger: #CE2947; - - /* Semantic Light Backgrounds (using 100 or 200 shades from your chart if possible, or lightened versions) */ - --color-success-light: #F0FAE9; /* Light green/Success 100 */ - --color-info-light: #E7F5FF; /* Light blue/Info 100 */ - --color-warning-light: #FFF8E6; /* Light orange/Warning 100 */ - --color-danger-light: #FFEDED; /* Light red/Danger 100 */ } /* Dark mode adjustments */ [data-md-color-scheme="slate"] { --md-code-bg-color: #1e1e1e; - - /* Dark Mode Semantic Adjustments for better visibility */ - --color-success-dark-bg: #1B3C0F; - --color-info-dark-bg: #0C2B47; - --color-warning-dark-bg: #4F380A; - --color-danger-dark-bg: #470D18; } - /* ============================================================================ Typography Improvements ========================================================================= */ @@ -119,77 +106,16 @@ } /* ============================================================================ - Admonitions & Callouts - NEW SEMANTIC STYLING + Admonitions & Callouts ========================================================================= */ -/* Enhanced admonitions (existing style preserved) */ +/* Enhanced admonitions */ .md-typeset .admonition { border-radius: 0.5rem; border-left-width: 0.25rem; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05); } -/* Admonitions using the new palette */ - -/* Success and Tip (often mapped to success for positive tone) */ -.md-typeset .admonition.success, -.md-typeset .admonition.tip, -.md-typeset div.success, -.md-typeset div.tip { - --md-typeset-color-tip: var(--color-success); - --md-typeset-color-tip-bg: var(--color-success-light); -} - -/* Info, Note, and Abstract (mapped to Info blue for neutral/informational tone) */ -.md-typeset .admonition.info, -.md-typeset .admonition.note, -.md-typeset .admonition.abstract, -.md-typeset div.info, -.md-typeset div.note, -.md-typeset div.abstract { - --md-typeset-color-info: var(--color-info); - --md-typeset-color-info-bg: var(--color-info-light); -} - -/* Warning and Caution */ -.md-typeset .admonition.warning, -.md-typeset .admonition.caution, -.md-typeset div.warning, -.md-typeset div.caution { - --md-typeset-color-warning: var(--color-warning); - --md-typeset-color-warning-bg: var(--color-warning-light); -} - -/* Danger, Error, and Failure */ -.md-typeset .admonition.danger, -.md-typeset .admonition.error, -.md-typeset .admonition.failure, -.md-typeset div.danger, -.md-typeset div.error, -.md-typeset div.failure { - --md-typeset-color-danger: var(--color-danger); - --md-typeset-color-danger-bg: var(--color-danger-light); -} - -/* Dark Mode Overrides for better contrast */ -[data-md-color-scheme="slate"] { - --md-code-bg-color: #1e1e1e; - - .md-typeset .admonition.success, .md-typeset .admonition.tip { - --md-typeset-color-tip-bg: var(--color-success-dark-bg); - } - .md-typeset .admonition.info, .md-typeset .admonition.note, .md-typeset .admonition.abstract { - --md-typeset-color-info-bg: var(--color-info-dark-bg); - } - .md-typeset .admonition.warning, .md-typeset .admonition.caution { - --md-typeset-color-warning-bg: var(--color-warning-dark-bg); - } - .md-typeset .admonition.danger, .md-typeset .admonition.error, .md-typeset .admonition.failure { - --md-typeset-color-danger-bg: var(--color-danger-dark-bg); - } -} - - /* ============================================================================ Tables ========================================================================= */ From d96514392ba73ad7cafddfc597fc647c6cd8e3d2 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 17:08:16 +0200 Subject: [PATCH 33/42] Revert "Add semantic colors" This reverts commit dcd6eadb686e4f335a86f373d7056b86a3ad5735. --- docs/stylesheets/extra.css | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index 1508bd7e5..085d7f55c 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -10,16 +10,10 @@ /* Typography */ --heading-font-weight: 600; - /* Colors - Redefine original teal theme with new palette shades (Brand Color column) */ - --flixopt-teal: #009688; /* Brand Color 500 */ - --flixopt-teal-light: #4DB6AC; /* Brand Color 300 */ - --flixopt-teal-dark: #00796B; /* Brand Color 700 */ - - /* NEW: Semantic Colors for direct use in custom components (e.g., semantic callouts) */ - --color-success: #4BA527; - --color-info: #0290E2; - --color-warning: #EF8809; - --color-danger: #CE2947; + /* Colors - enhance teal theme */ + --flixopt-teal: #009688; + --flixopt-teal-light: #4DB6AC; + --flixopt-teal-dark: #00796B; } /* Dark mode adjustments */ From 53d49c687d7c806d2a04d27cf0b81c33ba8fe32c Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 17:12:29 +0200 Subject: [PATCH 34/42] Fix --- mkdocs.yml | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 81537be41..cc108e237 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -2,15 +2,12 @@ # https://mkdocstrings.github.io/python/usage/configuration/docstrings/ # https://squidfunk.github.io/mkdocs-material/setup/ -site_name: flixOpt +site_name: flixopt site_description: Energy and Material Flow Optimization Framework site_url: https://flixopt.github.io/flixopt/ repo_url: https://github.com/flixOpt/flixopt repo_name: flixOpt/flixopt -# Copyright and social links -copyright: Copyright © 2024 flixOpt Contributors - nav: - Home: index.md - User Guide: From 666aa643cc4034b2dd7de38bc022087b7d609170 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 22:13:55 +0200 Subject: [PATCH 35/42] Pin mkdocs --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 0bf559b7d..227eca49e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -96,6 +96,7 @@ dev = [ # Documentation building docs = [ + "mkdocs==1.6.1", "mkdocs-material==9.6.21", "mkdocstrings-python==1.18.2", "mkdocs-table-reader-plugin==3.1.0", From 0337d4df137f689ab414b4c36668ed96033d0e7b Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 22:16:56 +0200 Subject: [PATCH 36/42] Add rel="noopener noreferrer" to external links opened in new --- docs/index.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/index.md b/docs/index.md index 5b7b5e66c..0b09ef9d7 100644 --- a/docs/index.md +++ b/docs/index.md @@ -187,7 +187,7 @@ hide:

🚀 Get Started 💡 View Examples - ⭐ GitHub + ⭐ GitHub

@@ -256,7 +256,7 @@ hide: Report issues, request features, and contribute to the codebase -[Visit Repository →](https://github.com/flixOpt/flixopt){target="_blank"} +[Visit Repository →](https://github.com/flixOpt/flixopt){target="_blank" rel="noopener noreferrer"}
@@ -268,7 +268,7 @@ Report issues, request features, and contribute to the codebase Ask questions and share your projects with the community -[Join Discussion →](https://github.com/flixOpt/flixopt/discussions){target="_blank"} +[Join Discussion →](https://github.com/flixOpt/flixopt/discussions){target="_blank" rel="noopener noreferrer"}
@@ -280,7 +280,7 @@ Ask questions and share your projects with the community Help improve FlixOpt by contributing code, docs, or examples -[Learn How →](contribute/){target="_blank"} +[Learn How →](contribute/){target="_blank" rel="noopener noreferrer"}
From 762990456525b03d352535f90c0db344efed9d60 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 22:20:08 +0200 Subject: [PATCH 37/42] Remove duplication --- docs/index.md | 171 ------------------------------------ docs/stylesheets/extra.css | 173 +++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 171 deletions(-) diff --git a/docs/index.md b/docs/index.md index 0b09ef9d7..a7cd67f8c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -5,177 +5,6 @@ hide: - toc --- - -

flixOpt

diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index 085d7f55c..79dfc9a15 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -221,3 +221,176 @@ display: none; } } + +/* ============================================================================ + Home Page Inline Styles (moved from docs/index.md) + ========================================================================= */ + +.hero-section { + text-align: center; + padding: 4rem 2rem 3rem 2rem; + background: linear-gradient(135deg, rgba(0, 150, 136, 0.1) 0%, rgba(0, 121, 107, 0.1) 100%); + border-radius: 1rem; + margin-bottom: 3rem; +} + +.hero-section h1 { + font-size: 3.5rem; + font-weight: 700; + margin-bottom: 1rem; + background: linear-gradient(135deg, #009688 0%, #00796B 100%); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.hero-section .tagline { + font-size: 1.5rem; + color: var(--md-default-fg-color--light); + margin-bottom: 2rem; + font-weight: 300; +} + +.hero-buttons { + display: flex; + gap: 1rem; + justify-content: center; + flex-wrap: wrap; + margin-top: 2rem; +} + +.feature-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 2rem; + margin: 3rem 0; +} + +.feature-card { + padding: 2rem; + border-radius: 0.75rem; + background: var(--md-code-bg-color); + border: 1px solid var(--md-default-fg-color--lightest); + transition: all 0.3s ease; + text-align: center; +} + +.feature-card:hover { + transform: translateY(-4px); + box-shadow: 0 8px 16px rgba(0, 0, 0, 0.1); + border-color: var(--md-primary-fg-color); +} + +.feature-icon { + font-size: 3rem; + margin-bottom: 1rem; + display: block; +} + +.feature-card h3 { + margin-top: 0; + margin-bottom: 0.5rem; + font-size: 1.25rem; +} + +.feature-card p { + color: var(--md-default-fg-color--light); + margin: 0; + font-size: 0.95rem; + line-height: 1.6; +} + +.stats-banner { + display: flex; + justify-content: space-around; + padding: 2rem; + background: var(--md-code-bg-color); + border-radius: 0.75rem; + margin: 3rem 0; + text-align: center; + flex-wrap: wrap; + gap: 2rem; +} + +.stat-item { + flex: 1; + min-width: 150px; +} + +.stat-number { + font-size: 2.5rem; + font-weight: 700; + color: var(--md-primary-fg-color); + display: block; +} + +.stat-label { + color: var(--md-default-fg-color--light); + font-size: 0.9rem; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.architecture-section { + margin: 4rem 0; + padding: 2rem; + background: var(--md-code-bg-color); + border-radius: 0.75rem; +} + +.quick-links { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); + gap: 1.5rem; + margin: 3rem 0; +} + +.quick-link-card { + padding: 1.5rem; + border-left: 4px solid var(--md-primary-fg-color); + background: var(--md-code-bg-color); + border-radius: 0.5rem; + transition: all 0.2s ease; + text-decoration: none; + display: block; +} + +.quick-link-card:hover { + background: var(--md-default-fg-color--lightest); + transform: translateX(4px); +} + +.quick-link-card h3 { + margin: 0 0 0.5rem 0; + font-size: 1.1rem; + color: var(--md-primary-fg-color); +} + +.quick-link-card p { + margin: 0; + color: var(--md-default-fg-color--light); + font-size: 0.9rem; +} + +@media screen and (max-width: 768px) { + .hero-section h1 { + font-size: 2.5rem; + } + + .hero-section .tagline { + font-size: 1.2rem; + } + + .hero-buttons { + flex-direction: column; + align-items: stretch; + } + + .feature-grid { + grid-template-columns: 1fr; + } + + .stats-banner { + flex-direction: column; + } +} From 7e1c277e6481f7f9ea809f60fc03a39fd167a411 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 22:29:19 +0200 Subject: [PATCH 38/42] Change colors --- docs/stylesheets/extra.css | 18 ++++++++++++------ mkdocs.yml | 8 ++++---- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index 79dfc9a15..86d970d4d 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -10,10 +10,16 @@ /* Typography */ --heading-font-weight: 600; - /* Colors - enhance teal theme */ - --flixopt-teal: #009688; - --flixopt-teal-light: #4DB6AC; - --flixopt-teal-dark: #00796B; + /* Colors - custom brand palette */ + --flixopt-primary: #274754; /* Primary dark blue-gray */ + --flixopt-accent: #2a9d90; /* Main accent teal-green */ + --flixopt-gold: #e8c468; /* Golden yellow */ + --flixopt-orange: #f4a462; /* Orange */ + + /* Derived colors for gradients */ + --flixopt-teal: #2a9d90; + --flixopt-teal-light: #3dbaa8; /* Lighter teal for gradients */ + --flixopt-teal-dark: #1f7a70; /* Darker teal for gradients */ } /* Dark mode adjustments */ @@ -229,7 +235,7 @@ .hero-section { text-align: center; padding: 4rem 2rem 3rem 2rem; - background: linear-gradient(135deg, rgba(0, 150, 136, 0.1) 0%, rgba(0, 121, 107, 0.1) 100%); + background: linear-gradient(135deg, rgba(42, 157, 144, 0.1) 0%, rgba(31, 122, 112, 0.1) 100%); border-radius: 1rem; margin-bottom: 3rem; } @@ -238,7 +244,7 @@ font-size: 3.5rem; font-weight: 700; margin-bottom: 1rem; - background: linear-gradient(135deg, #009688 0%, #00796B 100%); + background: linear-gradient(135deg, var(--flixopt-accent) 0%, var(--flixopt-teal-dark) 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; diff --git a/mkdocs.yml b/mkdocs.yml index cc108e237..371cf79cf 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -53,8 +53,8 @@ theme: # Palette toggle for light mode - media: "(prefers-color-scheme: light)" scheme: default - primary: teal - accent: cyan + primary: "#274754" + accent: "#2a9d90" toggle: icon: material/brightness-7 name: Switch to dark mode @@ -62,8 +62,8 @@ theme: # Palette toggle for dark mode - media: "(prefers-color-scheme: dark)" scheme: slate - primary: teal - accent: cyan + primary: "#274754" + accent: "#2a9d90" toggle: icon: material/brightness-4 name: Switch to system preference From a91372a2edfb870f67e42ed0dd0856910f27353a Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 22:39:35 +0200 Subject: [PATCH 39/42] Change colors --- docs/stylesheets/extra.css | 7 +++++++ mkdocs.yml | 8 ++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index 86d970d4d..37d348177 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -20,6 +20,13 @@ --flixopt-teal: #2a9d90; --flixopt-teal-light: #3dbaa8; /* Lighter teal for gradients */ --flixopt-teal-dark: #1f7a70; /* Darker teal for gradients */ + + /* Override Material Design primary and accent colors */ + --md-primary-fg-color: #274754; + --md-primary-fg-color--light: #3a5d6d; + --md-primary-fg-color--dark: #1a3340; + --md-accent-fg-color: #2a9d90; + --md-accent-fg-color--transparent: rgba(42, 157, 144, 0.1); } /* Dark mode adjustments */ diff --git a/mkdocs.yml b/mkdocs.yml index 371cf79cf..46f98276c 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -53,8 +53,8 @@ theme: # Palette toggle for light mode - media: "(prefers-color-scheme: light)" scheme: default - primary: "#274754" - accent: "#2a9d90" + primary: custom + accent: custom toggle: icon: material/brightness-7 name: Switch to dark mode @@ -62,8 +62,8 @@ theme: # Palette toggle for dark mode - media: "(prefers-color-scheme: dark)" scheme: slate - primary: "#274754" - accent: "#2a9d90" + primary: custom + accent: custom toggle: icon: material/brightness-4 name: Switch to system preference From 96a3407d52ab97d693f99ed51dfd18c6ac71024c Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 22:39:44 +0200 Subject: [PATCH 40/42] Revert "Change colors" This reverts commit a91372a2edfb870f67e42ed0dd0856910f27353a. --- docs/stylesheets/extra.css | 7 ------- mkdocs.yml | 8 ++++---- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index 37d348177..86d970d4d 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -20,13 +20,6 @@ --flixopt-teal: #2a9d90; --flixopt-teal-light: #3dbaa8; /* Lighter teal for gradients */ --flixopt-teal-dark: #1f7a70; /* Darker teal for gradients */ - - /* Override Material Design primary and accent colors */ - --md-primary-fg-color: #274754; - --md-primary-fg-color--light: #3a5d6d; - --md-primary-fg-color--dark: #1a3340; - --md-accent-fg-color: #2a9d90; - --md-accent-fg-color--transparent: rgba(42, 157, 144, 0.1); } /* Dark mode adjustments */ diff --git a/mkdocs.yml b/mkdocs.yml index 46f98276c..371cf79cf 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -53,8 +53,8 @@ theme: # Palette toggle for light mode - media: "(prefers-color-scheme: light)" scheme: default - primary: custom - accent: custom + primary: "#274754" + accent: "#2a9d90" toggle: icon: material/brightness-7 name: Switch to dark mode @@ -62,8 +62,8 @@ theme: # Palette toggle for dark mode - media: "(prefers-color-scheme: dark)" scheme: slate - primary: custom - accent: custom + primary: "#274754" + accent: "#2a9d90" toggle: icon: material/brightness-4 name: Switch to system preference From 336e04d597496b38642028eab196f4b7430926b7 Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Thu, 16 Oct 2025 22:39:44 +0200 Subject: [PATCH 41/42] Revert "Change colors" This reverts commit 7e1c277e6481f7f9ea809f60fc03a39fd167a411. --- docs/stylesheets/extra.css | 18 ++++++------------ mkdocs.yml | 8 ++++---- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/docs/stylesheets/extra.css b/docs/stylesheets/extra.css index 86d970d4d..79dfc9a15 100644 --- a/docs/stylesheets/extra.css +++ b/docs/stylesheets/extra.css @@ -10,16 +10,10 @@ /* Typography */ --heading-font-weight: 600; - /* Colors - custom brand palette */ - --flixopt-primary: #274754; /* Primary dark blue-gray */ - --flixopt-accent: #2a9d90; /* Main accent teal-green */ - --flixopt-gold: #e8c468; /* Golden yellow */ - --flixopt-orange: #f4a462; /* Orange */ - - /* Derived colors for gradients */ - --flixopt-teal: #2a9d90; - --flixopt-teal-light: #3dbaa8; /* Lighter teal for gradients */ - --flixopt-teal-dark: #1f7a70; /* Darker teal for gradients */ + /* Colors - enhance teal theme */ + --flixopt-teal: #009688; + --flixopt-teal-light: #4DB6AC; + --flixopt-teal-dark: #00796B; } /* Dark mode adjustments */ @@ -235,7 +229,7 @@ .hero-section { text-align: center; padding: 4rem 2rem 3rem 2rem; - background: linear-gradient(135deg, rgba(42, 157, 144, 0.1) 0%, rgba(31, 122, 112, 0.1) 100%); + background: linear-gradient(135deg, rgba(0, 150, 136, 0.1) 0%, rgba(0, 121, 107, 0.1) 100%); border-radius: 1rem; margin-bottom: 3rem; } @@ -244,7 +238,7 @@ font-size: 3.5rem; font-weight: 700; margin-bottom: 1rem; - background: linear-gradient(135deg, var(--flixopt-accent) 0%, var(--flixopt-teal-dark) 100%); + background: linear-gradient(135deg, #009688 0%, #00796B 100%); -webkit-background-clip: text; -webkit-text-fill-color: transparent; background-clip: text; diff --git a/mkdocs.yml b/mkdocs.yml index 371cf79cf..cc108e237 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -53,8 +53,8 @@ theme: # Palette toggle for light mode - media: "(prefers-color-scheme: light)" scheme: default - primary: "#274754" - accent: "#2a9d90" + primary: teal + accent: cyan toggle: icon: material/brightness-7 name: Switch to dark mode @@ -62,8 +62,8 @@ theme: # Palette toggle for dark mode - media: "(prefers-color-scheme: dark)" scheme: slate - primary: "#274754" - accent: "#2a9d90" + primary: teal + accent: cyan toggle: icon: material/brightness-4 name: Switch to system preference From db945f6f130fcb92e45ed8405d778fcbac08454d Mon Sep 17 00:00:00 2001 From: FBumann <117816358+FBumann@users.noreply.github.com> Date: Sat, 18 Oct 2025 21:43:38 +0200 Subject: [PATCH 42/42] Add entry to CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cc3be435..41dae8ad4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,6 +70,7 @@ If upgrading from v2.x, see the [Migration Guide](https://flixopt.github.io/flix ### 📦 Dependencies ### 📝 Docs +- Improve docs visually ### 👷 Development