Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
280 commits
Select commit Hold shift + click to select a range
967174c
Bugfix plot_node_balance_pie()
FBumann Apr 17, 2025
d24b5e7
Scenarios/fixes (#252)
FBumann Apr 22, 2025
a3c7d47
Scenarios/filter (#253)
FBumann Apr 22, 2025
0977c1f
Scenarios/drop suffix (#251)
FBumann Apr 22, 2025
5cf6e0e
Scenarios/bar plot (#254)
FBumann Apr 22, 2025
4cfa27f
Bugfix plotting
FBumann Apr 22, 2025
16fd74c
Fix example_calculation_types.py
FBumann Apr 22, 2025
67d1716
Scenarios/fixes (#255)
FBumann Apr 24, 2025
b968027
Scenarios/effects (#256)
FBumann Apr 25, 2025
9f2f38b
Scenarios/datasets results (#257)
FBumann Apr 28, 2025
dbfb1b5
ruff check
FBumann Apr 28, 2025
6738d34
ruff check
FBumann Apr 28, 2025
c64d12e
Scenarios/deprecation (#258)
FBumann Apr 28, 2025
0499497
Bugfix in plausibility_check: Index 0
FBumann Apr 28, 2025
ee00577
Set bargap to 0 in stacked bars
FBumann Apr 29, 2025
a11ed92
Ensure the size is always properly indexed in results.
FBumann Apr 29, 2025
2400244
ruff check
FBumann Apr 29, 2025
0f9b30a
BUGFIX in extract data, that causes coords in linopy to be incorrect …
FBumann May 5, 2025
26e89a9
Improve yaml formatting for model documentation (#259)
FBumann May 5, 2025
c0cbaae
Make the size/capacity a TimeSeries (#260)
FBumann May 5, 2025
67ebfbb
Scenarios/plot network (#262)
FBumann May 13, 2025
9edd1fa
Update deploy-docs.yaml:
FBumann May 13, 2025
d3c0c48
Bugfix DataConverter and add tests (#263)
FBumann May 13, 2025
e6e680c
Fix doc deployment to not publish on non stable releases
FBumann May 13, 2025
3d89b74
Remove unused code
FBumann May 15, 2025
cc772a4
Remove legend placing for better auto placing in plotly
FBumann May 16, 2025
d92349e
Fix plotly dependency
FBumann May 16, 2025
5c2900a
Improve validation when adding new effects
FBumann May 19, 2025
8e2e949
Merge branch 'main' into scenarios/main
FBumann Jun 14, 2025
8d3bbe9
Moved release notes to CHANGELOG.md
FBumann Jun 14, 2025
be6572d
Try to add to_dataset to Elements
FBumann Jun 23, 2025
f63db8b
Remove TimeSeries
FBumann Jun 23, 2025
167fb2c
Remove TimeSeries
FBumann Jun 23, 2025
fc76adf
Rename conversion method to pattern: to_...
FBumann Jun 23, 2025
cc7b155
Move methods to FlowSystem
FBumann Jun 23, 2025
ec6e792
Drop nan values across time dimension if present
FBumann Jun 23, 2025
b42aad2
Allow lists of values to create DataArray
FBumann Jun 24, 2025
b55af45
Update resolving of FlowSystem
FBumann Jun 24, 2025
d5ace96
Simplify TimeSeriesData
FBumann Jun 24, 2025
4187f30
Move TImeSeriesData to Structure and simplyfy to inherrit from xarray…
FBumann Jun 24, 2025
617600f
Adjust IO
FBumann Jun 24, 2025
e80bba0
Move TimeSeriesData back to core.py and fix Conversion
FBumann Jun 24, 2025
387cac6
Adjust IO to account for attrs of DataArrays in a Dataset
FBumann Jun 24, 2025
27734cf
Rename transforming and connection methods in FlowSystem
FBumann Jun 24, 2025
4915b81
Compacted IO methods
FBumann Jun 24, 2025
fc5549a
Remove infos()
FBumann Jun 24, 2025
299ff43
remove from_dict() and to_dict()
FBumann Jun 24, 2025
abc22b1
Update __str__ of Interface
FBumann Jun 24, 2025
9b4c44c
Improve str and repr
FBumann Jun 24, 2025
0ab7ea6
Improve str and repr
FBumann Jun 24, 2025
1dcbbb0
Add docstring
FBumann Jun 24, 2025
9aec990
Unify IO stuff in Interface class
FBumann Jun 24, 2025
e370311
Improve test tu utilize __eq__ method
FBumann Jun 24, 2025
793e820
Make Interface class more robust and improve exceptions
FBumann Jun 24, 2025
b87d979
Add option to copy Interfaces (And the FlowSystem)
FBumann Jun 24, 2025
8ec265e
Make a copy of a FLowSytsem that gets reused in a second Calculation
FBumann Jun 25, 2025
a46fe64
Remove test_timeseries.py
FBumann Jun 25, 2025
201d066
Reorganizing Datatypes
FBumann Jun 25, 2025
10d2925
Remove TImeSeries and TimeSeriesCollection entirely
FBumann Jun 25, 2025
cf9d17f
Remove old method
FBumann Jun 25, 2025
bd52e05
Add option to get structure with stats of dataarrays
FBumann Jun 25, 2025
aa36689
Change __str__ method
FBumann Jun 25, 2025
63b1c92
Remove old methods
FBumann Jun 25, 2025
29062fa
remove old imports
FBumann Jun 25, 2025
18c43e4
Add isel, sel and resample methods to FlowSystem
FBumann Jun 26, 2025
1f9ef07
Remove need for timeseries with extra timestep
FBumann Jun 26, 2025
5d88fde
Simplify IO of FLowSystem
FBumann Jun 26, 2025
1e94de3
Remove parameter timesteps from IO
FBumann Jun 26, 2025
e5828ad
Improve Exceptions and Docstrings
FBumann Jun 26, 2025
870efee
Improve isel sel and resample methods
FBumann Jun 26, 2025
e97ec5f
Change test
FBumann Jun 26, 2025
f15113e
Bugfix
FBumann Jun 26, 2025
284072e
Improve
FBumann Jun 26, 2025
ebbb5dd
Improve
FBumann Jun 26, 2025
a501e05
Add test for Storage Bounds
FBumann Jun 26, 2025
1825089
Add test for Storage Bounds
FBumann Jun 26, 2025
126b07f
CHANGELOG.md
FBumann Jun 26, 2025
94d841d
ruff check
FBumann Jun 26, 2025
c19edc8
Improve types
FBumann Jun 26, 2025
36cf47d
CHANGELOG.md
FBumann Jun 26, 2025
8f1261d
Bugfix in Storage
FBumann Jun 26, 2025
89d69f0
Revert changes in example_calculation_types.py
FBumann Jun 26, 2025
76f51a8
Revert changes in simple_example.py
FBumann Jun 26, 2025
0ff4d29
Add convenient access to Elements in FlowSystem
FBumann Jun 26, 2025
84c850b
Get Aggregated Calculation Working
FBumann Jun 27, 2025
8b9dabb
Segmented running with wrong results
FBumann Jun 27, 2025
7e72ab5
Use new persistent FLowSystem to create Calculations upfront
FBumann Jun 27, 2025
17632f3
Improve SegmentedCalcualtion
FBumann Jun 27, 2025
3c355c9
Improve SegmentedCalcualtion
FBumann Jun 27, 2025
f473ce5
Fix SegmentedResults IO
FBumann Jun 27, 2025
7869a72
ruff check
FBumann Jun 27, 2025
bb29ef2
Update example
FBumann Jun 27, 2025
8d96a49
Updated logger essages to use .label_full instead of .label
FBumann Jun 27, 2025
8240da1
Re-add parameters. Use deprecation warning instead
FBumann Jun 27, 2025
8ac2664
Update changelog
FBumann Jun 27, 2025
43a64ea
Improve warning message
FBumann Jun 27, 2025
7b67f8d
Merge branch 'unify-timesteps' into scenarios-no-ts/main
FBumann Jun 27, 2025
b3fe443
Merge
FBumann Jun 27, 2025
483ba12
Merge
FBumann Jun 28, 2025
dee1de4
Fit scenario weights to model coords when transforming
FBumann Jun 28, 2025
4ec3914
Merge
FBumann Jun 28, 2025
2554d8a
Removing logic between minimum, maximum and fixed size from InvestPar…
FBumann Jun 28, 2025
d062727
Remove selected_timesteps
FBumann Jun 28, 2025
6dc23f5
Improve TypeHints
FBumann Jun 28, 2025
e6100d6
New property on InvestParameters for min/max/fixed size
FBumann Jun 28, 2025
46f2035
Move logic for InvestParameters in Transmission to from Model to Inte…
FBumann Jun 28, 2025
6baeb8e
Make transformation of data more hierarchical (Flows after Components)
FBumann Jun 28, 2025
aeaaa83
Add scenario validation
FBumann Jun 28, 2025
15fd124
Change Transmission to have a "balanced" attribute. Change Tests acco…
FBumann Jun 28, 2025
d0b231d
Improve index validations
FBumann Jun 28, 2025
4ebe6a5
rename method in tests
FBumann Jun 29, 2025
6b56dac
Update DataConverter
FBumann Jun 29, 2025
a7ec994
Add DataFrame Support back
FBumann Jun 29, 2025
2a75ed3
Add copy() to DataConverter
FBumann Jun 29, 2025
dae9f01
Update fit_to_model_coords to take a list of coords
FBumann Jun 29, 2025
ba195ff
Make the DataConverter more universal by accepting a list of coords/dims
FBumann Jun 29, 2025
605f034
Update DataConverter for n-d arrays
FBumann Jun 29, 2025
6560006
Update DataConverter for n-d arrays
FBumann Jun 29, 2025
78132ef
Add extra tests for 3-dims
FBumann Jun 29, 2025
a53c116
Add FLowSystemDimension Type
FBumann Jun 30, 2025
2cb551b
Revert some logic about the fit_to_model coords
FBumann Jun 30, 2025
d7be766
Adjust FLowSystem IO for scenarios
FBumann Jun 30, 2025
e60dd07
BUGFIX: Raise Exception instead of logging
FBumann Jun 30, 2025
bd2f1b8
Change usage of TimeSeriesData
FBumann Jun 30, 2025
a7da9d2
Adjust logic to handle non scalars
FBumann Jun 30, 2025
b8f0e22
Adjust logic to _resolve_dataarray_reference into separate method
FBumann Jun 30, 2025
7123b6b
Update IO of FlowSystem
FBumann Jun 30, 2025
fa5475d
Improve get_coords()
FBumann Jul 2, 2025
80cb161
Adjust FlowSystem init for correct IO
FBumann Jul 2, 2025
81ad3ba
Add scenario to sel and isel methods, and dont normalize scenario wei…
FBumann Jul 2, 2025
691a45e
Improve scenario_weights_handling
FBumann Jul 2, 2025
3931ac5
Add warning for not scaled weights
FBumann Jul 2, 2025
75a45e1
Update test_scenarios.py
FBumann Jul 2, 2025
2882147
Improve util method
FBumann Jul 2, 2025
50491ff
Add objective to solution dataset.
FBumann Jul 2, 2025
4f3a798
Update handling of scenario_weights update tests
FBumann Jul 2, 2025
314aef9
Ruff check. Fix type hints
FBumann Jul 2, 2025
0302947
Fix type hints and improve None handling
FBumann Jul 3, 2025
40c437a
Fix coords in AggregatedCalculation
FBumann Jul 3, 2025
8d2d208
Improve Error Messages of DataConversion
FBumann Jul 3, 2025
9c0c95f
Allow multi dim data conversion and broadcasting by length
FBumann Jul 3, 2025
d568ad6
Improve DataConverter to handle multi-dim arrays
FBumann Jul 3, 2025
ffc196a
Rename methods and remove unused code
FBumann Jul 5, 2025
6142f44
Improve DataConverter by better splitting handling per datatype. Seri…
FBumann Jul 5, 2025
cec7367
Add test for error handling
FBumann Jul 5, 2025
eba1ec4
Update scenario example
FBumann Jul 5, 2025
5f97bf3
Fix Handling of TimeSeriesData
FBumann Jul 7, 2025
9351083
Improve DataConverter
FBumann Jul 7, 2025
99e6b19
Fix resampling of the FlowSystem
FBumann Jul 15, 2025
4981a9c
Improve Warning Message
FBumann Jul 15, 2025
516f45b
Add example that leverages resampling
FBumann Jul 15, 2025
ef0acfc
Add example that leverages resampling adn fixing of Investments
FBumann Jul 16, 2025
706c1ec
Add flag to Calculation if its modeled
FBumann Jul 16, 2025
a4cdb43
Make flag for connected_and_transformed FLowSystem public
FBumann Jul 16, 2025
148a852
Make Calcualtion Methods return themselfes to make them chainable
FBumann Jul 16, 2025
61755f9
Improve example
FBumann Jul 16, 2025
66f6a86
Improve Unreleased CHANGELOG.md
FBumann Jul 16, 2025
a757e7f
Add year coord to FlowSystem
FBumann Jul 8, 2025
941d93f
Improve dimension handling
FBumann Jul 8, 2025
745e885
Change plotting to use an indexer instead
FBumann Jul 8, 2025
c9bae2a
Change plotting to use an indexer instead
FBumann Jul 15, 2025
d1b5509
Use tuples to set dimensions in Models
FBumann Jul 16, 2025
c7568dd
Bugfix in validation logic and test
FBumann Jul 16, 2025
fc62634
Improve Errors
FBumann Jul 16, 2025
e320b9f
Improve weights handling and rescaling if None
FBumann Jul 16, 2025
33a22aa
Fix typehint
FBumann Jul 16, 2025
904211f
Update Broadcasting in Storage Bounds and improve type hints
FBumann Jul 16, 2025
3c6c08b
Make .get_model_coords() return an actual xr.Coordinates Object
FBumann Jul 16, 2025
22a1cef
Improve get_coords()
FBumann Jul 17, 2025
44dbefc
Rename SystemModel to FlowSystemModel
FBumann Jul 17, 2025
f82556a
First steps
FBumann Jul 18, 2025
33460a0
Improve Feature Patterns
FBumann Jul 18, 2025
ff70674
Improve acess to variables via short names
FBumann Jul 18, 2025
fa5e30a
Improve
FBumann Jul 18, 2025
a3511f9
Add naming options to big_m_binary_bounds()
FBumann Jul 18, 2025
404dc03
Fix and improve FLowModeling with Investment
FBumann Jul 18, 2025
1ad74ce
Improve
FBumann Jul 18, 2025
d1408a4
Tyring to improve the Methods for bounding variables in different sce…
FBumann Jul 18, 2025
ab000ca
Improve BoundingPatterns
FBumann Jul 18, 2025
2afc24e
Improve BoundingPatterns
FBumann Jul 18, 2025
b248f58
Improve BoundingPatterns
FBumann Jul 18, 2025
d34445c
Fix duration Modeling
FBumann Jul 18, 2025
bde07b4
Fix On + Size
FBumann Jul 18, 2025
5861b28
Fix InvestmentModel
FBumann Jul 19, 2025
7809ee4
Fix Models
FBumann Jul 19, 2025
2bbdb44
Update constraint names in test
FBumann Jul 19, 2025
2a01abe
Fix OnOffModel for multiple Flows
FBumann Jul 19, 2025
1f1ebb7
Update constraint names in tests
FBumann Jul 19, 2025
c7b351f
Simplify
FBumann Jul 19, 2025
5d9b591
Improve handling of vars/cons and models
FBumann Jul 19, 2025
5c56b63
Revising the basic structure of a class Model
FBumann Jul 20, 2025
9d242b6
Revising the basic structure of a class Model
FBumann Jul 20, 2025
0997843
Simplify and focus more on own Model class
FBumann Jul 21, 2025
1d6ef97
Update tests
FBumann Jul 21, 2025
972cb90
Improve state computation in ModelingUtilities
FBumann Jul 21, 2025
29bec8c
Improve handling of previous flowrates
FBumann Jul 21, 2025
370ac94
Imropove repr and submodel acess
FBumann Jul 21, 2025
0f89ff0
Update access pattern in tests
FBumann Jul 21, 2025
4781cff
Fix PiecewiseEffects and StorageModel
FBumann Jul 21, 2025
333ab83
Fix StorageModel and Remove PreventSimultaniousUseModel
FBumann Jul 21, 2025
9702303
Fix Aggregation and SegmentedCalculation
FBumann Jul 21, 2025
91bd461
Update tests
FBumann Jul 21, 2025
94314c3
Loosen precision in tests
FBumann Jul 21, 2025
50cc2cb
Update test_on_hours_computation.py and some types
FBumann Jul 21, 2025
e52f800
Rename class Model to Submodel
FBumann Jul 21, 2025
9281256
rename sub_model to submodel everywhere
FBumann Jul 21, 2025
9001c6a
rename self.model to self.submodel everywhere
FBumann Jul 21, 2025
286a8b7
Rename .model with .submodel if its only a submodel
FBumann Jul 21, 2025
ae1752b
Rename .sub_models with .submodels
FBumann Jul 21, 2025
1822384
Improve repr
FBumann Jul 22, 2025
2aa9d4b
Improve repr
FBumann Jul 22, 2025
5ca9707
Include def do_modeling() into __init__() of models
FBumann Jul 22, 2025
7e04399
Make properties private
FBumann Jul 22, 2025
4f95ebc
Improve Inheritance of Models
FBumann Jul 22, 2025
f73fe99
Merge branch 'main' into v3.0.0/main
FBumann Jul 22, 2025
2d9c920
V3.0.0/plotting (#285)
FBumann Jul 22, 2025
5fd05e3
ruff check
FBumann Jul 22, 2025
20a1964
Improve typehints
FBumann Jul 22, 2025
9b05f8f
Update CHANGELOG.md
FBumann Jul 22, 2025
4d7fd29
Bugfix from renaming to .submodel
FBumann Jul 22, 2025
3626517
Bugfix from renaming to .submodel
FBumann Jul 23, 2025
50fbb67
Improve indexer in results plotting
FBumann Jul 23, 2025
9368985
rename register_submodel() to .add_submodels() adn add SUbmodels coll…
FBumann Jul 23, 2025
e4ec410
Add nice repr to FlowSystemModel and Submodel
FBumann Jul 23, 2025
66283cb
Bugfix .variables and .constraints
FBumann Jul 23, 2025
a84dfad
Add type checks to modeling.py
FBumann Jul 23, 2025
d2182aa
Improve assertion in tests
FBumann Jul 23, 2025
75c05ee
Improve docstrings and register ElementModels directly in FlowSystemM…
FBumann Jul 23, 2025
66a6ff1
Improve __repr__()
FBumann Jul 23, 2025
e2e1f13
ruff check
FBumann Jul 23, 2025
62b18b6
Use new method to compare sets in tests
FBumann Jul 23, 2025
5f0b503
ruff check
FBumann Jul 23, 2025
15a08e9
Update Contribute.md, some dependencies and add pre-commit
FBumann Jul 23, 2025
97de53c
Pre commit hook
FBumann Jul 23, 2025
25f726e
Run Pre-Commit Hook for the first time
FBumann Jul 23, 2025
1716607
Fix link in README.md
FBumann Jul 23, 2025
b4a9236
Update Effect name in tests to be 'costs' instead of 'Costs' Everywhere
FBumann Jul 23, 2025
b7734f8
Improve some of the modeling and coord handling
FBumann Jul 23, 2025
e06692b
Add tests with years and scenarios
FBumann Jul 23, 2025
cf0186c
Update tests to run with multiple coords
FBumann Jul 23, 2025
5510297
Fix Effects dataset computation in case of empty effects
FBumann Jul 23, 2025
b694dbe
Update Test for multiple dims
FBumann Jul 24, 2025
262e8b4
Fix test with multiple dims
FBumann Jul 28, 2025
2a469f1
Fix test with multiple dims
FBumann Jul 28, 2025
159bcb3
New test
FBumann Jul 28, 2025
e764a13
New test for previous flow_rates
FBumann Jul 28, 2025
20f74f3
Merge pull request #286 from flixOpt/v3.0.0/testing
FBumann Jul 28, 2025
1474af6
V3.0.0/main fit to model coords improve (#295)
FBumann Aug 13, 2025
be6bd42
Merge main into v3.0.0/main
FBumann Sep 12, 2025
26e091a
Improve CHANGELOG.md
FBumann Sep 13, 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
Empty file.
104 changes: 103 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,109 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]
## [Unreleased - New Model dimensions]

### Changed
* **BREAKING**: `relative_minimum_charge_state` and `relative_maximum_charge_state` don't have an extra timestep anymore. The final charge state can now be constrained by parameters `relative_minimum_final_charge_state` and `relative_maximum_final_charge_state` instead
* **BREAKING**: Calculation.do_modeling() now returns the Calculation object instead of its linopy.Model
* **BREAKING**: Renamed class `SystemModel` to `FlowSystemModel`
* **BREAKING**: Renamed class `Model` to `Submodel`
* **BREAKING**: Renamed `mode` parameter in plotting methods to `style`
* FlowSystems can not 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:
* Model: The main Model (linopy.Model) that is used to create and store the variables and constraints for the flow_system.
* Submodel: The base class for all submodels. Each is a subset of the Model, for simpler acess and clearer code.
*

#### Internal:
* **BREAKING**: Calculation.do_modeling() now returns the Calculation object instead of its linopy.Model
* **BREAKING**: Renamed class `SystemModel` to `FlowSystemModel`
* **BREAKING**: Renamed class `Model` to `Submodel`
* FlowSystem data management simplified - removed `time_series_collection` pattern in favor of direct timestep properties
* Change modeling hierarchy to allow for more flexibility in future development. This leads to minimal changes in the access and creation of Submodels and their variables.
* Added new module `.modeling`that contains Modelling primitives and utilities


### Added
* FlowSystem Restoring: The used FlowSystem will now get restired from the results (lazily). ALll Parameters can be safely acessed anytime after the solve.
* FLowResults added as a new class to store the results of Flows. They can now be accessed directly.
* Added precomputed DataArrays for `size`s, `flow_rate`s and `flow_hour`s.
* Added `effects_per_component()`-Dataset to Results that stores the direct (and indirect) effects of each component. This greatly improves the evaluation of the impact of individual Components, even with many and complex effects.
* Improved filter methods for Results

#### Scenarios
Scenarios are a new feature of flixopt. They can be used to model uncertainties in the flow system, such as:
* Different demand profiles
* Different price forecasts
* Different weather conditions

Common use cases are:
* Find the best overall investment decision for possible scenarios (robust decision-making)
* Find the best dispatch for the most important assets under uncertain price and weather conditions

The weighted sum of the total objective effect of each scenario is used as the objective of the optimization.

#### Years (Investment periods)
A flixopt model might be modeled with a "year" dimension.
This enables to model transformation pathways over multiple years.

%%%%% TODO: New Interfaces to model sizes changing over time, annuity, etc.

#### Improved Data handling: IO, resampling and more through xarray
* Complete serialization infrastructure through `Interface` base class
* IO for all Interfaces and the FlowSystem with round-trip serialization support
* Automatic DataArray extraction and restoration
* NetCDF export/import capabilities for all Interface objects and FlowSystem
* JSON export for documentation purposes
* Recursive handling of nested Interface objects
* FlowSystem data manipulation methods
* `sel()` and `isel()` methods for temporal data selection
* `resample()` method for temporal resampling
* `copy()` method to create a copy of a FlowSystem, including all underlying Elements and their data
* `__eq__()` method for FlowSystem comparison
* Storage component enhancements
* `relative_minimum_final_charge_state` parameter for final state control
* `relative_maximum_final_charge_state` parameter for final state control
* Core data handling improvements
* `get_dataarray_stats()` function for statistical summaries
* Enhanced `DataConverter` class with better TimeSeriesData support
* Internal: Enhanced data handling methods
* `fit_to_model_coords()` method for data alignment
* `fit_effects_to_model_coords()` method for effect data processing
* `connect_and_transform()` method replacing several operations

#### Internal: Improved Model organisation and access
* Clearer separation between the main Model and "Submodels"
* Improved access to the Submodels and their variables, constraints and submodels
* Added __repr__() for Submodels to easily inspect its content


#### Other new features
* Balanced storage - Storage charging and discharging sizes can now be forced to be equal in when optimizing their size.

#### Examples:
* Added Example for 2-stage Investment decisions leveraging the resampling of a FlowSystem


### Fixed
* Enhanced NetCDF I/O with proper attribute preservation for DataArrays
* Improved error handling and validation in serialization processes
* Better type consistency across all framework components


### Know Issues
* Plotly >= 6 may raise errors if "nbformat" is not installed. We pinned plotly to <6, but this may be fixed in the future.
* IO for single Interfaces/Elemenets to Datasets might not work properly if the Interface/Element is not part of a fully transformed and connected FlowSystem. This arrises from Numeric Data not being stored as xr.DataArray by the user. To avoid this, always use the `to_dataset()` on Elements inside a FlowSystem thats connected and transformed.


### Deprecated
* 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.


## [2.1.6] - 2025-09-02
Expand Down
2 changes: 1 addition & 1 deletion docs/images/flixopt-icon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
115 changes: 115 additions & 0 deletions docs/user-guide/Mathematical Notation/Investment.md
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be redone probably.

Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Investments

## Current state
$$
\beta_{\text{invest}} \cdot \text{max}(\epsilon, \text V^{\text L}) \leq V \leq \beta_{\text{invest}} \cdot \text V^{\text U}
$$
With:
- $V$ = size
- $V^{\text L}$ = minimum size
- $V^{\text U}$ = maximum size
- $\epsilon$ = epsilon, a small number (such as $1e^{-5}$)
- $\beta_{invest} \in {0,1}$ = wether the size is invested or not
Comment on lines +5 to +12
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix LaTeX and definition typos in the core inequality.

Use proper LaTeX for max, symbols, and sets; also fix spelling/wording in definitions.

Apply:

-$$
-\beta_{\text{invest}} \cdot \text{max}(\epsilon, \text V^{\text L}) \leq V \leq  \beta_{\text{invest}} \cdot \text V^{\text U}
-$$
+$$
+\beta_{\mathrm{invest}} \cdot \max(\varepsilon, V^{\mathrm L}) \le V \le \beta_{\mathrm{invest}} \cdot V^{\mathrm U}
+$$
@@
-- $\epsilon$ = epsilon, a small number (such as $1e^{-5}$)
-- $\beta_{invest} \in {0,1}$ = wether the size is invested or not
+- $\varepsilon$ = small positive number (e.g., $10^{-5}$)
+- $\beta_{\mathrm{invest}} \in \{0,1\}$ = whether the size is invested
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
\beta_{\text{invest}} \cdot \text{max}(\epsilon, \text V^{\text L}) \leq V \leq \beta_{\text{invest}} \cdot \text V^{\text U}
$$
With:
- $V$ = size
- $V^{\text L}$ = minimum size
- $V^{\text U}$ = maximum size
- $\epsilon$ = epsilon, a small number (such as $1e^{-5}$)
- $\beta_{invest} \in {0,1}$ = wether the size is invested or not
$$
\beta_{\mathrm{invest}} \cdot \max(\varepsilon, V^{\mathrm L}) \le V \le \beta_{\mathrm{invest}} \cdot V^{\mathrm U}
$$
With:
- $V$ = size
- $V^{\text L}$ = minimum size
- $V^{\text U}$ = maximum size
- $\varepsilon$ = small positive number (e.g., $10^{-5}$)
- $\beta_{\mathrm{invest}} \in \{0,1\}$ = whether the size is invested
🤖 Prompt for AI Agents
In docs/user-guide/Mathematical Notation/Investment.md around lines 5–12, the
inequality and variable definitions contain LaTeX and typing errors; replace
\text and spacing with proper math commands, use \max for the max, use \mathrm
or \text for superscripts (e.g. V^{\mathrm{L}}, V^{\mathrm{U}}), render the
epsilon as \epsilon (and a standard small value like 10^{-5} or 1\times10^{-5}),
and write the set membership as \beta_{\text{invest}}\in\{0,1\}; also fix
wording typos (“whether” not “wether”) and ensure each bullet shows the variable
name then the description consistently.


_Please edit the use cases as needed_
## Quickfix 1: Optimize the single best size overall
### Single variable
This is already possible and should be, as this is a needed use case
An additional factor to when the size is actually available might me practical (Which indicates the (fixed) time of investment)
## Math
$$
V(p) = V * a(p)
$$
with:
- $V$ = size
- $a(p)$ = factor for availlability per period

Factor $a(p)$ is simply multiplied with relative minimum or maximum(t). This is already possible by doing this yourself.
Effectively, the relative minimum or maximum are altered before using the same constraiints as before.
THis might lead to some issues regariding minimum_load factor, or others, as the size is not 0 in a scenario where the component cant produce.
**Therefore this might not be the best choice. See (#Variable per Scenario)

Comment on lines +27 to +31
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Typos, grammar, and anchor link.

-Factor $a(p)$ is simply multiplied with relative minimum or maximum(t). This is already possible by doing this yourself.
-Effectively, the relative minimum or maximum are altered before using the same constraiints as before.
-THis might lead to some issues regariding minimum_load factor, or others, as the size is not 0 in a scenario where the component cant produce.
-**Therefore this might not be the best choice. See (#Variable per Scenario)
+Factor $a(p)$ is simply multiplied with the relative minimum or maximum(t). This is already possible to express externally.
+Effectively, the relative minimum or maximum are altered before applying the same constraints as before.
+This might lead to issues regarding a minimum_load factor or others, since the size is not 0 in a scenario where the component can't produce.
+**Therefore this might not be the best choice. See [Variable per Scenario](#variable-per-scenario).**
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Factor $a(p)$ is simply multiplied with relative minimum or maximum(t). This is already possible by doing this yourself.
Effectively, the relative minimum or maximum are altered before using the same constraiints as before.
THis might lead to some issues regariding minimum_load factor, or others, as the size is not 0 in a scenario where the component cant produce.
**Therefore this might not be the best choice. See (#Variable per Scenario)
Factor $a(p)$ is simply multiplied with the relative minimum or maximum(t). This is already possible to express externally.
Effectively, the relative minimum or maximum are altered before applying the same constraints as before.
This might lead to issues regarding a minimum_load factor or others, since the size is not 0 in a scenario where the component can't produce.
**Therefore this might not be the best choice. See [Variable per Scenario](#variable-per-scenario).**
🤖 Prompt for AI Agents
In docs/user-guide/Mathematical Notation/Investment.md around lines 27-31, fix
multiple typos, grammar and the anchor link: rephrase the first sentence to "The
factor a(p) is applied multiplicatively to the relative minimum or maximum t;
this can be done manually.", change "Effectively, the relative minimum or
maximum are altered before using the same constraiints as before." to
"Effectively, the relative minimum or maximum are altered before using the same
constraints as before.", correct "THis"→"This", "regariding"→"regarding",
"cant"→"can't", and "size is not 0"→"the size is non-zero", and replace the raw
"(#Variable per Scenario)" with a proper Markdown link like "[Variable per
Scenario](#variable-per-scenario)".

## Variable per Scenario
- **size** and **invest** as a variable per period $V(s)$ and $\beta_{invest}(s)$
- with scenario $s \in S$

### Usecase 1: Optimize the size for each Scenario independently
Restrictions are seperatly for each scenario
No changes needed. This could be the default behaviour.

### Usecase 2: Optimize ONE size for ALL scenarios
The size is the same globally, but not a scalar, but a variable per scenario $V(s)$
#### 2a: The same size in all scenarios
$$
V(s) = V(s') \quad \forall s,s' \in S
$$

With:
- $V(s)$ and $V(s')$ = size
- $S$ = set of scenarios

#### 2b: The same size, but can be 0 prior to the first increment
- Find the Optimal time of investment.
- Force an investment in a certain scenario (parameter optional as a list/array ob booleans)
- Combine optional and minimum/maximum size to force an investment inside a range if scenarios

$$
\beta_{\text{invest}}(s) \leq \beta_{\text{invest}}(s+1) \quad \forall s \in \{1,2,\ldots,S-1\}
$$

$$
V(s') - V(s) \leq M \cdot (2 - \beta_{\text{invest}}(s) - \beta_{\text{invest}}(s')) \quad \forall s, s' \in S
$$
$$
V(s') - V(s) \geq M \cdot (2 - \beta_{\text{invest}}(s) - \beta_{\text{invest}}(s')) \quad \forall s, s' \in S
$$

Comment on lines +56 to +66
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Big‑M pair: lower bound sign is wrong; define M.

The second inequality must use a negative RHS; otherwise it forces a large positive difference when any beta is 0.

 \beta_{\text{invest}}(s) \leq \beta_{\text{invest}}(s+1) \quad \forall s \in \{1,2,\ldots,S-1\}
@@
-V(s') - V(s) \geq M \cdot (2 - \beta_{\text{invest}}(s) - \beta_{\text{invest}}(s')) \quad \forall s, s' \in S
+V(s') - V(s) \geq -\,M \cdot (2 - \beta_{\text{invest}}(s) - \beta_{\text{invest}}(s')) \quad \forall s, s' \in S
@@
-This could be the default behaviour. (which would be consistent with other variables)
+Here, $M$ is a sufficiently large constant (Big‑M). This could be the default behaviour (consistent with other variables).
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
$$
\beta_{\text{invest}}(s) \leq \beta_{\text{invest}}(s+1) \quad \forall s \in \{1,2,\ldots,S-1\}
$$
$$
V(s') - V(s) \leq M \cdot (2 - \beta_{\text{invest}}(s) - \beta_{\text{invest}}(s')) \quad \forall s, s' \in S
$$
$$
V(s') - V(s) \geq M \cdot (2 - \beta_{\text{invest}}(s) - \beta_{\text{invest}}(s')) \quad \forall s, s' \in S
$$
$$
\beta_{\text{invest}}(s) \leq \beta_{\text{invest}}(s+1) \quad \forall s \in \{1,2,\ldots,S-1\}
$$
$$
V(s') - V(s) \leq M \cdot (2 - \beta_{\text{invest}}(s) - \beta_{\text{invest}}(s')) \quad \forall s, s' \in S
$$
$$
V(s') - V(s) \geq -\,M \cdot (2 - \beta_{\text{invest}}(s) - \beta_{\text{invest}}(s')) \quad \forall s, s' \in S
$$
Here, $M$ is a sufficiently large constant (Big‑M). This could be the default behaviour (consistent with other variables).
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

56-56: Unordered list indentation
Expected: 2; Actual: 3

(MD007, ul-indent)


58-58: Unordered list indentation
Expected: 2; Actual: 3

(MD007, ul-indent)


59-59: Unordered list indentation
Expected: 2; Actual: 3

(MD007, ul-indent)


60-60: Unordered list indentation
Expected: 2; Actual: 3

(MD007, ul-indent)


61-61: Unordered list indentation
Expected: 2; Actual: 3

(MD007, ul-indent)


63-63: Unordered list indentation
Expected: 2; Actual: 3

(MD007, ul-indent)


64-64: Unordered list indentation
Expected: 2; Actual: 3

(MD007, ul-indent)


66-66: Unordered list indentation
Expected: 2; Actual: 3

(MD007, ul-indent)

🤖 Prompt for AI Agents
In docs/user-guide/Mathematical Notation/Investment.md around lines 56–66, the
lower‑bound constraint currently uses a positive RHS which is incorrect; change
the third inequality to use a negative big‑M (i.e. V(s') - V(s) >= -M * (2 -
beta_invest(s) - beta_invest(s')) for all s,s'), and add a clear definition of M
(a sufficiently large constant upper bound on |V(s')-V(s)| or an explicit
numeric bound) so readers know how to choose it.

This could be the default behaviour. (which would be consistent with other variables)


### Switch

$$
\begin{aligned}
& \text{SWITCH}_s \in \{0,1\} \quad \forall s \in \{1,2,\ldots,S\} \\
& \sum_{s=1}^{S} \text{SWITCH}_s = 1 \\
& \beta_{\text{invest}}(s) = \sum_{s'=1}^{s} \text{SWITCH}_{s'} \quad \forall s \in \{1,2,\ldots,S\} \\
\end{aligned}
$$

$$
\begin{aligned}
& V(s) \leq V_{\text{actual}} \quad \forall s \in \{1,2,\ldots,S\} \\
& V(s) \geq V_{\text{actual}} - M \cdot (1 - \beta_{\text{invest}}(s)) \quad \forall s \in \{1,2,\ldots,S\}
\end{aligned}
$$
Comment on lines +70 to +85
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Define V_actual and add non‑negativity (or lower bound).

 \sum_{s=1}^{S} \text{SWITCH}_s = 1 \\
 \beta_{\text{invest}}(s) = \sum_{s'=1}^{s} \text{SWITCH}_{s'} \quad \forall s \in \{1,2,\ldots,S\} \\
@@
-& V(s) \leq V_{\text{actual}} \quad \forall s \in \{1,2,\ldots,S\} \\
-& V(s) \geq V_{\text{actual}} - M \cdot (1 - \beta_{\text{invest}}(s)) \quad \forall s \in \{1,2,\ldots,S\}
+& V(s) \leq V_{\text{actual}} \quad \forall s \in \{1,2,\ldots,S\} \\
+& V(s) \geq V_{\text{actual}} - M \cdot (1 - \beta_{\text{invest}}(s)) \quad \forall s \in \{1,2,\ldots,S\} \\
+& V(s) \ge 0 \quad \forall s \in \{1,2,\ldots,S\}

Add a short sentence after the block:

+where $V_{\text{actual}}$ is the global size variable shared across scenarios.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
### Switch
$$
\begin{aligned}
& \text{SWITCH}_s \in \{0,1\} \quad \forall s \in \{1,2,\ldots,S\} \\
& \sum_{s=1}^{S} \text{SWITCH}_s = 1 \\
& \beta_{\text{invest}}(s) = \sum_{s'=1}^{s} \text{SWITCH}_{s'} \quad \forall s \in \{1,2,\ldots,S\} \\
\end{aligned}
$$
$$
\begin{aligned}
& V(s) \leq V_{\text{actual}} \quad \forall s \in \{1,2,\ldots,S\} \\
& V(s) \geq V_{\text{actual}} - M \cdot (1 - \beta_{\text{invest}}(s)) \quad \forall s \in \{1,2,\ldots,S\}
\end{aligned}
$$
### Switch
$$
\begin{aligned}
& \text{SWITCH}_s \in \{0,1\} \quad \forall s \in \{1,2,\ldots,S\} \\
& \sum_{s=1}^{S} \text{SWITCH}_s = 1 \\
& \beta_{\text{invest}}(s) = \sum_{s'=1}^{s} \text{SWITCH}_{s'} \quad \forall s \in \{1,2,\ldots,S\} \\
\end{aligned}
$$
$$
\begin{aligned}
& V(s) \leq V_{\text{actual}} \quad \forall s \in \{1,2,\ldots,S\} \\
& V(s) \geq V_{\text{actual}} - M \cdot (1 - \beta_{\text{invest}}(s)) \quad \forall s \in \{1,2,\ldots,S\} \\
& V(s) \ge 0 \quad \forall s \in \{1,2,\ldots,S\}
\end{aligned}
$$
where $V_{\text{actual}}$ is the global size variable shared across scenarios.
🧰 Tools
🪛 markdownlint-cli2 (0.17.2)

70-70: Unordered list indentation
Expected: 2; Actual: 3

(MD007, ul-indent)


71-71: Unordered list indentation
Expected: 2; Actual: 3

(MD007, ul-indent)


76-76: Strong style
Expected: asterisk; Actual: underscore

(MD050, strong-style)


76-76: Strong style
Expected: asterisk; Actual: underscore

(MD050, strong-style)


82-82: Trailing punctuation in heading
Punctuation: ':'

(MD026, no-trailing-punctuation)

🤖 Prompt for AI Agents
In docs/user-guide/Mathematical Notation/Investment.md around lines 70 to 85,
the variable V_actual is used but not defined and no lower bound is given; add a
one‑line definition after the displayed equations that defines V_actual (e.g.,
"V_actual is the actual investment value") and state its lower bound or
non‑negativity (e.g., "V_actual ≥ 0" or a specific lower bound if applicable),
ensuring the sentence uses the same math notation style as the surrounding text.





### Usecase 3: Find the best scenario to increment the size (Timing of the investment)
The size can only increment once (based on a starting point). This allows to optimize the timing of an investment.
#### Math
Treat $\beta_{invest}$ like an ON/OFF variable, and introduce a SwitchOn, that can only be active once.

*Thoughts:*
- Treating $\beta_{invest}$ like an ON/OFF variable suggest using the already presentconstraints linked to On/OffModel
- The timing could be constraint to be first in scenario x, or last in scenario y
- Restrict the number of consecutive scenarios
THis might needs the OnOffModel to be more generic (HOURS). Further, the span between scenarios needs to be weighted (like dt_in_hours), or the scenarios need to be measureable (integers)


### Others

#### Usecase 4: Only increase/decrease the size
Start from a certain size. For each scenario, the size can increase, but never decrease. (Or the other way around).
This would mean that a size expansion is possible,

#### Usecase 5: Restrict the increment in size per scenario
Restrict how much the size can increase/decrease for in scenario, based on the prior scenario.





Many more are possible
3 changes: 2 additions & 1 deletion examples/01_Simple/simple_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@
discharging=fx.Flow('Q_th_unload', bus='Fernwärme', size=1000),
capacity_in_flow_hours=fx.InvestParameters(fix_effects=20, fixed_size=30, optional=False),
initial_charge_state=0, # Initial storage state: empty
relative_maximum_charge_state=1 / 100 * np.array([80, 70, 80, 80, 80, 80, 80, 80, 80, 80]),
relative_maximum_charge_state=1 / 100 * np.array([80, 70, 80, 80, 80, 80, 80, 80, 80]),
relative_maximum_final_charge_state=0.8,
eta_charge=0.9,
eta_discharge=1, # Efficiency factors for charging/discharging
relative_loss_per_hour=0.08, # 8% loss per hour. Absolute loss depends on current charge state
Expand Down
23 changes: 12 additions & 11 deletions examples/03_Calculation_types/example_calculation_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,9 @@

# TimeSeriesData objects
TS_heat_demand = fx.TimeSeriesData(heat_demand)
TS_electricity_demand = fx.TimeSeriesData(electricity_demand, agg_weight=0.7)
TS_electricity_price_sell = fx.TimeSeriesData(-(electricity_demand - 0.5), agg_group='p_el')
TS_electricity_price_buy = fx.TimeSeriesData(electricity_price + 0.5, agg_group='p_el')
TS_electricity_demand = fx.TimeSeriesData(electricity_demand, aggregation_weight=0.7)
TS_electricity_price_sell = fx.TimeSeriesData(-(electricity_demand - 0.5), aggregation_group='p_el')
TS_electricity_price_buy = fx.TimeSeriesData(electricity_price + 0.5, aggregation_group='p_el')

Comment on lines +51 to 54
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix sell-price series: using demand instead of price

TS_electricity_price_sell is derived from electricity_demand. It should use electricity_price to encode revenue as negative costs.

Apply:

-TS_electricity_price_sell = fx.TimeSeriesData(-(electricity_demand - 0.5), aggregation_group='p_el')
+TS_electricity_price_sell = fx.TimeSeriesData(-(electricity_price - 0.5), aggregation_group='p_el')
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
TS_electricity_demand = fx.TimeSeriesData(electricity_demand, aggregation_weight=0.7)
TS_electricity_price_sell = fx.TimeSeriesData(-(electricity_demand - 0.5), aggregation_group='p_el')
TS_electricity_price_buy = fx.TimeSeriesData(electricity_price + 0.5, aggregation_group='p_el')
TS_electricity_demand = fx.TimeSeriesData(electricity_demand, aggregation_weight=0.7)
TS_electricity_price_sell = fx.TimeSeriesData(-(electricity_price - 0.5), aggregation_group='p_el')
TS_electricity_price_buy = fx.TimeSeriesData(electricity_price + 0.5, aggregation_group='p_el')
🤖 Prompt for AI Agents
In examples/03_Calculation_types/example_calculation_types.py around lines
51–54, TS_electricity_price_sell incorrectly uses electricity_demand; replace
that operand with electricity_price and negate it so the series represents
revenue as negative costs, e.g., use fx.TimeSeriesData(-electricity_price,
aggregation_group='p_el') while keeping the aggregation_group unchanged.

flow_system = fx.FlowSystem(timesteps)
flow_system.add_elements(
Expand Down Expand Up @@ -164,12 +164,12 @@
if full:
calculation = fx.FullCalculation('Full', flow_system)
calculation.do_modeling()
calculation.solve(fx.solvers.HighsSolver(0, 60))
calculation.solve(fx.solvers.HighsSolver(0.01 / 100, 60))
calculations.append(calculation)

if segmented:
calculation = fx.SegmentedCalculation('Segmented', flow_system, segment_length, overlap_length)
calculation.do_modeling_and_solve(fx.solvers.HighsSolver(0, 60))
calculation.do_modeling_and_solve(fx.solvers.HighsSolver(0.01 / 100, 60))
calculations.append(calculation)

if aggregated:
Expand All @@ -178,7 +178,7 @@
aggregation_parameters.time_series_for_low_peaks = [TS_electricity_demand, TS_heat_demand]
calculation = fx.AggregatedCalculation('Aggregated', flow_system, aggregation_parameters)
calculation.do_modeling()
calculation.solve(fx.solvers.HighsSolver(0, 60))
calculation.solve(fx.solvers.HighsSolver(0.01 / 100, 60))
calculations.append(calculation)

# Get solutions for plotting for different calculations
Expand All @@ -194,34 +194,35 @@ def get_solutions(calcs: List, variable: str) -> xr.Dataset:
# --- Plotting for comparison ---
fx.plotting.with_plotly(
get_solutions(calculations, 'Speicher|charge_state').to_dataframe(),
mode='line',
style='line',
title='Charge State Comparison',
ylabel='Charge state',
).write_html('results/Charge State.html')

Comment on lines 195 to 201
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Ensure 'results' directory exists before writing HTML

Prevent FileNotFoundError when writing plots.

 fx.plotting.with_plotly(
     get_solutions(calculations, 'Speicher|charge_state').to_dataframe(),
     style='line',
     title='Charge State Comparison',
     ylabel='Charge state',
 ).write_html('results/Charge State.html')
+
+# Create once before first write_html
+pathlib.Path('results').mkdir(parents=True, exist_ok=True)

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In examples/03_Calculation_types/example_calculation_types.py around lines 195
to 201, the code writes an HTML file to 'results/Charge State.html' without
ensuring the 'results' directory exists; add a directory-creation step before
calling write_html (e.g., import os and call os.makedirs('results',
exist_ok=True) or use pathlib.Path('results').mkdir(parents=True,
exist_ok=True)) so the folder is created if missing, then proceed to call
write_html as before.

fx.plotting.with_plotly(
get_solutions(calculations, 'BHKW2(Q_th)|flow_rate').to_dataframe(),
mode='line',
style='line',
title='BHKW2(Q_th) Flow Rate Comparison',
ylabel='Flow rate',
).write_html('results/BHKW2 Thermal Power.html')

fx.plotting.with_plotly(
get_solutions(calculations, 'costs(operation)|total_per_timestep').to_dataframe(),
mode='line',
style='line',
title='Operation Cost Comparison',
ylabel='Costs [€]',
).write_html('results/Operation Costs.html')

fx.plotting.with_plotly(
pd.DataFrame(get_solutions(calculations, 'costs(operation)|total_per_timestep').to_dataframe().sum()).T,
mode='bar',
style='stacked_bar',
title='Total Cost Comparison',
ylabel='Costs [€]',
).update_layout(barmode='group').write_html('results/Total Costs.html')

fx.plotting.with_plotly(
pd.DataFrame([calc.durations for calc in calculations], index=[calc.name for calc in calculations]), 'bar'
pd.DataFrame([calc.durations for calc in calculations], index=[calc.name for calc in calculations]),
'stacked_bar',
).update_layout(title='Duration Comparison', xaxis_title='Calculation type', yaxis_title='Time (s)').write_html(
'results/Speed Comparison.html'
)
Loading