Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
9ac4bbb
Improve __str__ of FlowSystem
FBumann Oct 26, 2025
a028980
Use ElementContainer class
FBumann Oct 26, 2025
a115d0e
Inherrit from dict
FBumann Oct 26, 2025
b04a2b3
Improve repr
FBumann Oct 26, 2025
24b440d
Assign flow.componet right away after the flow is passed to a Component
FBumann Oct 26, 2025
69e7ecf
Add FLowContainer
FBumann Oct 26, 2025
a0f55ab
Improve Error Message
FBumann Oct 26, 2025
f318174
Improve repr of FlowSystem
FBumann Oct 26, 2025
e179682
Use ElementContainer in results.py
FBumann Oct 26, 2025
7b9c786
Use a Mixin instead and use in results as well
FBumann Oct 26, 2025
c1d2882
Improve Results container usage
FBumann Oct 26, 2025
47fa30b
Simplify display
FBumann Oct 26, 2025
7b4dba0
Make CalculationResults iterable over sub containers
FBumann Oct 26, 2025
4276f3a
Create CompositeContainerMixin and use in FLowSystem and CalcualtionR…
FBumann Oct 26, 2025
11983e8
Remove from commons.py
FBumann Oct 26, 2025
d06a774
Re-add status
FBumann Oct 26, 2025
69c65dc
Remove redundant stuff and add deprecation
FBumann Oct 26, 2025
457f31a
Add type annotation to CompositeContainerMixin
FBumann Oct 26, 2025
bc603ec
Use ContainerMixin in EffectsCollection
FBumann Oct 26, 2025
5839ebb
Optimize acess patterns
FBumann Oct 26, 2025
a5081be
Remove unneded method
FBumann Oct 26, 2025
d8ead2d
Iterate group containers to collect values and pairs in one pass.
FBumann Oct 26, 2025
3615ec7
Add sorting to containers
FBumann Oct 26, 2025
48772c8
Reorder container groups
FBumann Oct 26, 2025
f668c9b
Add guardfs for flow results
FBumann Oct 26, 2025
01a2796
Rename _set_flow_labels and validate that the FLow is not already con…
FBumann Oct 26, 2025
affc771
Merge remote-tracking branch 'origin/main' into feature/containers
FBumann Oct 26, 2025
bb98bac
Add reprs
FBumann Oct 28, 2025
519ee2c
Add reprs to results classes
FBumann Oct 28, 2025
d95baa8
Improve the reprs
FBumann Oct 28, 2025
9314aec
Remove code duplication
FBumann Oct 28, 2025
0c02d1b
Improve repr of ELements
FBumann Oct 28, 2025
1c5b8ae
Improve Error message
FBumann Oct 28, 2025
c4c532c
Remove redundant sum('time')
FBumann Oct 28, 2025
df224e5
Pre compile re pattern
FBumann Oct 28, 2025
29e9a98
Make code more concise
FBumann Oct 28, 2025
75a4e40
Synchronise order of Containers in both FlowSystem and CalculationRes…
FBumann Oct 28, 2025
3385e40
Add note about caching
FBumann Oct 28, 2025
512aaa6
Update CHANGELOG.md
FBumann Oct 28, 2025
552deaf
Changed from O(n) element in self.values() to O(1) label-based checki…
FBumann Oct 28, 2025
cfd7355
Added early validation to ensure flows in prevent_simultaneous_flows …
FBumann Oct 28, 2025
b86941c
Import Statement Fix (structure.py:10, 916)
FBumann Oct 28, 2025
cf13be4
Flow repr Improvement
FBumann Oct 28, 2025
8e98bf3
Optimized Uniqueness Check
FBumann Oct 28, 2025
298b2bf
Fixed separator mangling that produced strings like "(kg)objective" i…
FBumann Oct 28, 2025
1c7829e
Flows Property Caching
FBumann Oct 28, 2025
ebbf4f4
Fixed __iter__ method (effects.py:591-592)
FBumann Oct 28, 2025
98d45bb
Deterministic Ordering for Effects
FBumann Oct 28, 2025
657bc54
Removed Redundant Import
FBumann Oct 28, 2025
8cc3093
Deterministic Ordering for Flows
FBumann Oct 28, 2025
830e64c
Deduplicate prevent_simultaneous_flows
FBumann Oct 28, 2025
5d94ce1
Improved DataArray Handling in repr
FBumann Oct 28, 2025
cd2d809
Enhanced Bus repr
FBumann Oct 28, 2025
f38e095
Enhanced Component repr
FBumann Oct 28, 2025
a4b18c6
Update CHANGELOG.md
FBumann Oct 28, 2025
ac3314a
Simplify reprs
FBumann Oct 28, 2025
10e9860
Simplify reprs
FBumann Oct 28, 2025
bf368e6
Simplify repr formating of numbers
FBumann Oct 29, 2025
08709ec
Reformat reprs
FBumann Oct 29, 2025
131e9fa
Reformat reprs
FBumann Oct 29, 2025
d9c1f70
Reformat reprs
FBumann Oct 29, 2025
30baa4b
Reformat reprs
FBumann Oct 29, 2025
44417d9
Reformat reprs
FBumann Oct 29, 2025
b738723
Reformat reprs
FBumann Oct 29, 2025
e0142c9
Reformat reprs
FBumann Oct 29, 2025
7de8576
Reformat reprs
FBumann Oct 29, 2025
907e4d3
Reformat reprs
FBumann Oct 29, 2025
aac74fb
Reformat reprs
FBumann Oct 29, 2025
b6c7c97
Use helper formats to create the reprs
FBumann Oct 29, 2025
6705011
Remove str from Interface class
FBumann Oct 29, 2025
f1d9677
Improve FlowSystem repr
FBumann Oct 29, 2025
1a16e3a
Improve Reprs of Containers
FBumann Oct 29, 2025
5b65505
Numeric formatter handles NaN/Inf/empty inputs
FBumann Oct 29, 2025
ca34159
Effect repr shows constraints for both min and max bounds
FBumann Oct 29, 2025
60df4c5
Improve repr code
FBumann Oct 29, 2025
7de0a88
Improve detection of defaults
FBumann Oct 29, 2025
2b8622c
Removed the unused _format_size method (dead code with no call sites
FBumann Oct 29, 2025
f115017
Simplified flows container construction by passing the list directly …
FBumann Oct 29, 2025
2a7ca74
Moved ResultsContainer import to module level for consistency
FBumann Oct 29, 2025
cfb9f92
prevents mutation of the original self.solution.attrs
FBumann Oct 29, 2025
5bf9ad6
Fix return type annotation to match base class.
FBumann Oct 29, 2025
e78a55e
Extract _format_value_for_repr() as dedicated method
FBumann Oct 29, 2025
e4c20d8
FIx type hint
FBumann Oct 29, 2025
5f9d589
Improve Error message
FBumann Oct 29, 2025
9507cd0
Typo in docs
FBumann Oct 29, 2025
e93693b
Fix indents in docs and CHANGELOG.md
FBumann Oct 29, 2025
dff3534
Improve documentation of the FLowSystem access
FBumann Oct 29, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 40 additions & 31 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,17 @@ If upgrading from v2.x, see the [v3.0.0 release notes](https://github.com/flixOp
### 💥 Breaking Changes

### ♻️ Changed
**Improved repr methods:**
- **Results classes** (`ComponentResults`, `BusResults`, `FlowResults`, `EffectResults`) now show concise header with key metadata followed by xarray Dataset repr
- **Element classes** (`Component`, `Bus`, `Flow`, `Effect`, `Storage`) now show one-line summaries with essential information (connections, sizes, capacities, constraints)

**Container-based access:**
- **FlowSystem** now provides dict-like access patterns for all elements
- Use `flow_system['element_label']`, `flow_system.keys()`, `flow_system.values()`, and `flow_system.items()` for unified element access
- Specialized containers (`components`, `buses`, `effects`, `flows`) offer type-specific access with helpful error messages

### 🗑️ Deprecated
- **`FlowSystem.all_elements`** property is deprecated in favor of dict-like interface (`flow_system['label']`, `.keys()`, `.values()`, `.items()`). Will be removed in v4.0.0.

### 🔥 Removed

Expand Down Expand Up @@ -91,21 +100,21 @@ If upgrading from v2.x, see the [v3.0.0 release notes](https://github.com/flixOp

**Color management:**
- **`setup_colors()` method** for `CalculationResults` and `SegmentedCalculationResults` to configure consistent colors across all plots
- Group components by colorscales: `results.setup_colors({'CHP': 'reds', 'Storage': 'blues', 'Greys': ['Grid', 'Demand']})`
- Automatically propagates to all segments in segmented calculations
- Colors persist across all plot calls unless explicitly overridden
- Group components by colorscales: `results.setup_colors({'CHP': 'reds', 'Storage': 'blues', 'Greys': ['Grid', 'Demand']})`
- Automatically propagates to all segments in segmented calculations
- Colors persist across all plot calls unless explicitly overridden
- **Flexible color inputs**: Supports colorscale names (e.g., 'turbo', 'plasma'), color lists, or label-to-color dictionaries
- **Cross-backend compatibility**: Seamless color handling for both Plotly and Matplotlib

**Plotting customization:**
- **Plotting kwargs support**: Pass additional arguments to plotting backends via `px_kwargs`, `plot_kwargs`, and `backend_kwargs` parameters
- **New `CONFIG.Plotting` configuration section**:
- `default_show`: Control default plot visibility
- `default_engine`: Choose 'plotly' or 'matplotlib'
- `default_dpi`: Set resolution for saved plots
- `default_facet_cols`: Configure default faceting columns
- `default_sequential_colorscale`: Default for heatmaps (now 'turbo')
- `default_qualitative_colorscale`: Default for categorical plots (now 'plotly')
- `default_show`: Control default plot visibility
- `default_engine`: Choose 'plotly' or 'matplotlib'
- `default_dpi`: Set resolution for saved plots
- `default_facet_cols`: Configure default faceting columns
- `default_sequential_colorscale`: Default for heatmaps (now 'turbo')
- `default_qualitative_colorscale`: Default for categorical plots (now 'plotly')

**I/O improvements:**
- Centralized JSON/YAML I/O with auto-format detection
Expand Down Expand Up @@ -272,12 +281,12 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir
**API and Behavior Changes:**

- **Effect system redesigned** (no deprecation):
- **Terminology changes**: Effect domains renamed for clarity: `operation` → `temporal`, `invest`/`investment` → `periodic`
- **Sharing system**: The old `specific_share_to_other_effects_*` parameters were completely replaced with the new `share_from_temporal` and `share_from_periodic` syntax (see 🔥 Removed section)
- **Terminology changes**: Effect domains renamed for clarity: `operation` → `temporal`, `invest`/`investment` → `periodic`
- **Sharing system**: The old `specific_share_to_other_effects_*` parameters were completely replaced with the new `share_from_temporal` and `share_from_periodic` syntax (see 🔥 Removed section)
- **FlowSystem independence**: FlowSystems cannot be shared across multiple Calculations anymore. A copy of the FlowSystem is created instead, making every Calculation independent. Each Subcalculation in `SegmentedCalculation` now has its own distinct `FlowSystem` object
- **Bus and Effect object assignment**: Direct assignment of Bus/Effect objects is no longer supported. Use labels (strings) instead:
- `Flow.bus` must receive a string label, not a Bus object
- Effect shares must use effect labels (strings) in dictionaries, not Effect objects
- `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:**
Expand All @@ -291,14 +300,14 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir

- 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`
- `switch_on` → `switch|on`
- `switch_off` → `switch|off`
- `switch_on_nr` → `switch|count`
- Effect submodel variables (following terminology changes):
- `Effect(invest)|total` → `Effect(periodic)`
- `Effect(operation)|total` → `Effect(temporal)`
- `Effect(operation)|total_per_timestep` → `Effect(temporal)|per_timestep`
- `Effect|total` → `Effect`
- `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:**

Expand Down Expand Up @@ -519,7 +528,7 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir

### ✨ Added
- **Network Visualization**: Added `FlowSystem.start_network_app()` and `FlowSystem.stop_network_app()` to easily visualize the network structure of a flow system in an interactive Dash web app
- *Note: This is still experimental and might change in the future*
- *Note: This is still experimental and might change in the future*

### ♻️ Changed
- **Multi-Flow Support**: `Sink`, `Source`, and `SourceAndSink` now accept multiple `flows` as `inputs` and `outputs` instead of just one. This enables modeling more use cases with these classes
Expand Down Expand Up @@ -561,8 +570,8 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir

### 🐛 Fixed
- Storage losses per hour were not calculated correctly, as mentioned by @brokenwings01. This might have led to issues when modeling large losses and long timesteps.
- Old implementation: $c(\text{t}_{i}) \cdot (1-\dot{\text{c}}_\text{rel,loss}(\text{t}_i)) \cdot \Delta \text{t}_{i}$
- Correct implementation: $c(\text{t}_{i}) \cdot (1-\dot{\text{c}}_\text{rel,loss}(\text{t}_i)) ^{\Delta \text{t}_{i}}$
- Old implementation: $c(\text{t}_{i}) \cdot (1-\dot{\text{c}}_\text{rel,loss}(\text{t}_i)) \cdot \Delta \text{t}_{i}$
- Correct implementation: $c(\text{t}_{i}) \cdot (1-\dot{\text{c}}_\text{rel,loss}(\text{t}_i)) ^{\Delta \text{t}_{i}}$

### 🚧 Known Issues
- Just to mention: Plotly >= 6 may raise errors if "nbformat" is not installed. We pinned plotly to <6, but this may be fixed in the future.
Expand All @@ -587,10 +596,10 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir

### 💥 Breaking Changes
- Restructured the modeling of the On/Off state of Flows or Components
- Variable renaming: `...|consecutive_on_hours` → `...|ConsecutiveOn|hours`
- Variable renaming: `...|consecutive_off_hours` → `...|ConsecutiveOff|hours`
- Constraint renaming: `...|consecutive_on_hours_con1` → `...|ConsecutiveOn|con1`
- Similar pattern for all consecutive on/off constraints
- Variable renaming: `...|consecutive_on_hours` → `...|ConsecutiveOn|hours`
- Variable renaming: `...|consecutive_off_hours` → `...|ConsecutiveOff|hours`
- Constraint renaming: `...|consecutive_on_hours_con1` → `...|ConsecutiveOn|con1`
- Similar pattern for all consecutive on/off constraints

### 🐛 Fixed
- Fixed the lower bound of `flow_rate` when using optional investments without OnOffParameters
Expand Down Expand Up @@ -636,10 +645,10 @@ This replaces `specific_share_to_other_effects_*` parameters and inverts the dir

**Variable Structure:**
- Restructured the modeling of the On/Off state of Flows or Components
- Variable renaming: `...|consecutive_on_hours` → `...|ConsecutiveOn|hours`
- Variable renaming: `...|consecutive_off_hours` → `...|ConsecutiveOff|hours`
- Constraint renaming: `...|consecutive_on_hours_con1` → `...|ConsecutiveOn|con1`
- Similar pattern for all consecutive on/off constraints
- Variable renaming: `...|consecutive_on_hours` → `...|ConsecutiveOn|hours`
- Variable renaming: `...|consecutive_off_hours` → `...|ConsecutiveOff|hours`
- Constraint renaming: `...|consecutive_on_hours_con1` → `...|ConsecutiveOn|con1`
- Similar pattern for all consecutive on/off constraints

### 🔥 Removed
- **Pyomo dependency** (replaced by linopy)
Expand Down
39 changes: 23 additions & 16 deletions docs/user-guide/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,22 @@ Every FlixOpt model starts with creating a FlowSystem. It:
- Contains and connects [components](#components), [buses](#buses), and [flows](#flows)
- Manages the [effects](#effects) (objectives and constraints)

FlowSystem provides two ways to access elements:

- **Dict-like interface**: Access any element by label: `flow_system['Boiler']`, `'Boiler' in flow_system`, `flow_system.keys()`
- **Direct containers**: Access type-specific containers: `flow_system.components`, `flow_system.buses`, `flow_system.effects`, `flow_system.flows`

Element labels must be unique across all types. See the [`FlowSystem` API reference][flixopt.flow_system.FlowSystem] for detailed examples and usage patterns.

### Flows

[`Flow`][flixopt.elements.Flow] objects represent the movement of energy or material between a [Bus](#buses) and a [Component](#components) in a predefined direction.

- Have a `size` which, generally speaking, defines how fast energy or material can be moved. Usually measured in MW, kW, m³/h, etc.
- Have a `flow_rate`, which is defines how fast energy or material is transported. Usually measured in MW, kW, m³/h, etc.
- Have a `size` which, generally speaking, defines how much energy or material can be moved. Usually measured in MW, kW, m³/h, etc.
- Have a `flow_rate`, which defines how fast energy or material is transported. Usually measured in MW, kW, m³/h, etc.
- Have constraints to limit the flow-rate (min/max, total flow hours, on/off etc.)
- Can have fixed profiles (for demands or renewable generation)
- Can have [Effects](#effects) associated by their use (operation, investment, on/off, ...)
- Can have [Effects](#effects) associated by their use (costs, emissions, labour, ...)

#### Flow Hours
While the **Flow Rate** defines the rate in which energy or material is transported, the **Flow Hours** define the amount of energy or material that is transported.
Expand All @@ -50,21 +57,21 @@ Examples:
[`Component`][flixopt.elements.Component] objects usually represent physical entities in your system that interact with [`Flows`][flixopt.elements.Flow]. The generic component types work across all domains:

- [`LinearConverters`][flixopt.components.LinearConverter] - Converts input flows to output flows with (piecewise) linear relationships
- *Energy: boilers, heat pumps, turbines*
- *Manufacturing: assembly lines, processing equipment*
- *Chemistry: reactors, separators*
- *Energy: boilers, heat pumps, turbines*
- *Manufacturing: assembly lines, processing equipment*
- *Chemistry: reactors, separators*
- [`Storages`][flixopt.components.Storage] - Stores energy or material over time
- *Energy: batteries, thermal storage, gas storage*
- *Logistics: warehouses, buffer inventory*
- *Water: reservoirs, tanks*
- *Energy: batteries, thermal storage, gas storage*
- *Logistics: warehouses, buffer inventory*
- *Water: reservoirs, tanks*
- [`Sources`][flixopt.components.Source] / [`Sinks`][flixopt.components.Sink] / [`SourceAndSinks`][flixopt.components.SourceAndSink] - Produce or consume flows
- *Energy: demands, renewable generation*
- *Manufacturing: raw material supply, product demand*
- *Supply chain: suppliers, customers*
- *Energy: demands, renewable generation*
- *Manufacturing: raw material supply, product demand*
- *Supply chain: suppliers, customers*
- [`Transmissions`][flixopt.components.Transmission] - Moves flows between locations with possible losses
- *Energy: pipelines, power lines*
- *Logistics: transport routes*
- *Water: distribution networks*
- *Energy: pipelines, power lines*
- *Logistics: transport routes*
- *Water: distribution networks*

**Pre-built specialized components** for energy systems include [`Boilers`][flixopt.linear_converters.Boiler], [`HeatPumps`][flixopt.linear_converters.HeatPump], [`CHPs`][flixopt.linear_converters.CHP], etc. These can serve as blueprints for custom domain-specific components.

Expand Down Expand Up @@ -105,7 +112,7 @@ FlixOpt offers different calculation modes:

The results of a calculation are stored in a [`CalculationResults`][flixopt.results.CalculationResults] object.
This object contains the solutions of the optimization as well as all information about the [`Calculation`][flixopt.calculation.Calculation] and the [`FlowSystem`][flixopt.flow_system.FlowSystem] it was created from.
The solutions is stored as an `xarray.Dataset`, but can be accessed through their assotiated Component, Bus or Effect.
The solution is stored as an `xarray.Dataset`, but can be accessed through their assotiated Component, Bus or Effect.

This [`CalculationResults`][flixopt.results.CalculationResults] object can be saved to file and reloaded from file, allowing you to analyze the results anytime after the solve.

Expand Down
2 changes: 1 addition & 1 deletion flixopt/calculation.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def main_results(self) -> dict[str, Scalar | dict]:
'periodic': effect.submodel.periodic.total.solution.values,
'total': effect.submodel.total.solution.values,
}
for effect in self.flow_system.effects
for effect in sorted(self.flow_system.effects.values(), key=lambda e: e.label_full.upper())
},
'Invest-Decisions': {
'Invested': {
Expand Down
10 changes: 10 additions & 0 deletions flixopt/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import numpy as np
import xarray as xr

from . import io as fx_io
from .core import PeriodicDataUser, PlausibilityError, TemporalData, TemporalDataUser
from .elements import Component, ComponentModel, Flow
from .features import InvestmentModel, PiecewiseModel
Expand Down Expand Up @@ -528,6 +529,15 @@ def _plausibility_checks(self) -> None:
f'{self.discharging.size.minimum_size=}, {self.discharging.size.maximum_size=}.'
)

def __repr__(self) -> str:
"""Return string representation."""
# Use build_repr_from_init directly to exclude charging and discharging
return fx_io.build_repr_from_init(
self,
excluded_params={'self', 'label', 'charging', 'discharging', 'kwargs'},
skip_default_size=True,
) + fx_io.format_flow_details(self)


@register_class_for_io
class Transmission(Component):
Expand Down
Loading