-
Notifications
You must be signed in to change notification settings - Fork 9
V3.0.0/main (#284) #319
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
V3.0.0/main (#284) #319
Conversation
* Bugfix plot_node_balance_pie() * Scenarios/fixes (#252) * BUGFIX missing conversion to TimeSeries * BUGFIX missing conversion to TimeSeries * Bugfix node_balance with flow_hours: Negate correctly * Scenarios/filter (#253) * Add containts and startswith to filter_solution * Scenarios/drop suffix (#251) Drop suffixes in plots and add the option to drop suffixes to sanitize_dataset() * Scenarios/bar plot (#254) * Add stacked bar style to plotting methods * Rename mode to style (line, bar, area, ...) * Bugfix plotting * Fix example_calculation_types.py * Scenarios/fixes (#255) * Fix indexing issue with only one scenario * Bugfix Cooling Tower * Add option for balanced Storage Flows (equalize size of charging and discharging) * Add option for balanced Storage Flows * Change error to warning (non-fixed size with piecewise conversion AND fixed_flow_rate with OnOff) * Bugfix in DataConverter * BUGFIX: Typo (total_max/total_min in Effect) * Bugfix in node_balance() (negating did not work when using flow_hours mode * Scenarios/effects (#256) * Add methods to track effect shares of components and Flows * Add option to include flows when retrieving effects * Add properties and methods to store effect results in a dataset * Reorder methods * Rename and improve docs * Bugfix test class name * Fix the Network algorithm to calculate the sum of parallel paths, and be independent on nr of nodes and complexity of the network * Add tests for the newtork chaining and the results of effect shares * Add methods to check for circular references * Add test to check for circular references * Update cycle checker to return the found cycles * Add checks in results to confirm effects are computed correctly * BUGFIX: Remove +1 from prior testing * Add option for grouped bars to plotting.with_plotly() and make lines of stacked bar plots invisible * Reconstruct FlowSystem in CalculationResults on demand. DEPRECATION in CalculationResults * ruff check * Bugfix: save flow_system data, not the flow_system * Update tests * Scenarios/datasets results (#257) * Use dataarray instead of dataset * Change effects dataset to dataarray and use nan when no share was found * Add method for flow_rates dataset * Add methods to get flow_rates and flow_hours as datasets * Rename the dataarrays to the flow * Preserve index order * Improve filter_edges_dataset() * Simplify _create_flow_rates_dataarray() * Add dataset for sizes of Flows * Extend results structure to contain flows AND start/end infos * Add FlowResults Object * BUGFIX:Typo in _ElementResults.constraints * Add flows to results of Nodes * Simplify dataarray creation and improve FlowResults * Add nice docstrings * Improve filtering of flow results * Improve filtering of flow results. Add attribute of component * Add big dataarray with all variables but indexed * Revert "Add big dataarray with all variables but indexed" This reverts commit 08cd8a1. * Improve filtering method for coords filter and add error handling for restoring the flow system * Remove unnecessary methods in results .from_json() * Ensure consistent coord ordering in Effects dataarray * Rename get_effects_per_component() * Make effects_per_component() a dataset instead of a dataarray * Improve backwards compatability * ruff check * ruff check * Scenarios/deprecation (#258) * Deprecate .active_timesteps * Improve logger warning * Starting release notes * Bugfix in plausibility_check: Index 0 * Set bargap to 0 in stacked bars * Ensure the size is always properly indexed in results. * ruff check * BUGFIX in extract data, that causes coords in linopy to be incorrect (scalar xarray.DataArrays) * Improve yaml formatting for model documentation (#259) * Make the size/capacity a TimeSeries (#260) * Scenarios/plot network (#262) * Catch bug in plot_network with 2D arrays * Add plot_network() to test_io.py * Update deploy-docs.yaml: Run on Release publishing instead of creation and only run for stable releases (vx.y.z) * Bugfix DataConverter and add tests (#263) * Fix doc deployment to not publish on non stable releases * Remove unused code * Remove legend placing for better auto placing in plotly * Fix plotly dependency * Improve validation when adding new effects * Moved release notes to CHANGELOG.md * Try to add to_dataset to Elements * Remove TimeSeries * Remove TimeSeries * Rename conversion method to pattern: to_... * Move methods to FlowSystem * Drop nan values across time dimension if present * Allow lists of values to create DataArray * Update resolving of FlowSystem * Simplify TimeSeriesData * Move TImeSeriesData to Structure and simplyfy to inherrit from xarray.DataArray * Adjust IO * Move TimeSeriesData back to core.py and fix Conversion * Adjust IO to account for attrs of DataArrays in a Dataset * Rename transforming and connection methods in FlowSystem * Compacted IO methods * Remove infos() * remove from_dict() and to_dict() * Update __str__ of Interface * Improve str and repr * Improve str and repr * Add docstring * Unify IO stuff in Interface class * Improve test tu utilize __eq__ method * Make Interface class more robust and improve exceptions * Add option to copy Interfaces (And the FlowSystem) * Make a copy of a FLowSytsem that gets reused in a second Calculation * Remove test_timeseries.py * Reorganizing Datatypes * Remove TImeSeries and TimeSeriesCollection entirely * Remove old method * Add option to get structure with stats of dataarrays * Change __str__ method * Remove old methods * remove old imports * Add isel, sel and resample methods to FlowSystem * Remove need for timeseries with extra timestep * Simplify IO of FLowSystem * Remove parameter timesteps from IO * Improve Exceptions and Docstrings * Improve isel sel and resample methods * Change test * Bugfix * Improve * Improve * Add test for Storage Bounds * Add test for Storage Bounds * CHANGELOG.md * ruff check * Improve types * CHANGELOG.md * Bugfix in Storage * Revert changes in example_calculation_types.py * Revert changes in simple_example.py * Add convenient access to Elements in FlowSystem * Get Aggregated Calculation Working * Segmented running with wrong results * Use new persistent FLowSystem to create Calculations upfront * Improve SegmentedCalcualtion * Improve SegmentedCalcualtion * Fix SegmentedResults IO * ruff check * Update example * Updated logger essages to use .label_full instead of .label * Re-add parameters. Use deprecation warning instead * Update changelog * Improve warning message * Merge * Merge * Fit scenario weights to model coords when transforming * Merge * Removing logic between minimum, maximum and fixed size from InvestParameters * Remove selected_timesteps * Improve TypeHints * New property on InvestParameters for min/max/fixed size * Move logic for InvestParameters in Transmission to from Model to Interface * Make transformation of data more hierarchical (Flows after Components) * Add scenario validation * Change Transmission to have a "balanced" attribute. Change Tests accordingly * Improve index validations * rename method in tests * Update DataConverter * Add DataFrame Support back * Add copy() to DataConverter * Update fit_to_model_coords to take a list of coords * Make the DataConverter more universal by accepting a list of coords/dims * Update DataConverter for n-d arrays * Update DataConverter for n-d arrays * Add extra tests for 3-dims * Add FLowSystemDimension Type * Revert some logic about the fit_to_model coords * Adjust FLowSystem IO for scenarios * BUGFIX: Raise Exception instead of logging * Change usage of TimeSeriesData * Adjust logic to handle non scalars * Adjust logic to _resolve_dataarray_reference into separate method * Update IO of FlowSystem * Improve get_coords() * Adjust FlowSystem init for correct IO * Add scenario to sel and isel methods, and dont normalize scenario weights * Improve scenario_weights_handling * Add warning for not scaled weights * Update test_scenarios.py * Improve util method * Add objective to solution dataset. * Update handling of scenario_weights update tests * Ruff check. Fix type hints * Fix type hints and improve None handling * Fix coords in AggregatedCalculation * Improve Error Messages of DataConversion * Allow multi dim data conversion and broadcasting by length * Improve DataConverter to handle multi-dim arrays * Rename methods and remove unused code * Improve DataConverter by better splitting handling per datatype. Series only matches index (for one dim). Numpy matches shape * Add test for error handling * Update scenario example * Fix Handling of TimeSeriesData * Improve DataConverter * Fix resampling of the FlowSystem * Improve Warning Message * Add example that leverages resampling * Add example that leverages resampling adn fixing of Investments * Add flag to Calculation if its modeled * Make flag for connected_and_transformed FLowSystem public * Make Calcualtion Methods return themselfes to make them chainable * Improve example * Improve Unreleased CHANGELOG.md * Add year coord to FlowSystem * Improve dimension handling * Change plotting to use an indexer instead * Change plotting to use an indexer instead * Use tuples to set dimensions in Models * Bugfix in validation logic and test * Improve Errors * Improve weights handling and rescaling if None * Fix typehint * Update Broadcasting in Storage Bounds and improve type hints * Make .get_model_coords() return an actual xr.Coordinates Object * Improve get_coords() * Rename SystemModel to FlowSystemModel * First steps * Improve Feature Patterns * Improve acess to variables via short names * Improve * Add naming options to big_m_binary_bounds() * Fix and improve FLowModeling with Investment * Improve * Tyring to improve the Methods for bounding variables in different scenarios * Improve BoundingPatterns * Improve BoundingPatterns * Improve BoundingPatterns * Fix duration Modeling * Fix On + Size * Fix InvestmentModel * Fix Models * Update constraint names in test * Fix OnOffModel for multiple Flows * Update constraint names in tests * Simplify * Improve handling of vars/cons and models * Revising the basic structure of a class Model * Revising the basic structure of a class Model * Simplify and focus more on own Model class * Update tests * Improve state computation in ModelingUtilities * Improve handling of previous flowrates * Imropove repr and submodel acess * Update access pattern in tests * Fix PiecewiseEffects and StorageModel * Fix StorageModel and Remove PreventSimultaniousUseModel * Fix Aggregation and SegmentedCalculation * Update tests * Loosen precision in tests * Update test_on_hours_computation.py and some types * Rename class Model to Submodel * rename sub_model to submodel everywhere * rename self.model to self.submodel everywhere * Rename .model with .submodel if its only a submodel * Rename .sub_models with .submodels * Improve repr * Improve repr * Include def do_modeling() into __init__() of models * Make properties private * Improve Inheritance of Models * V3.0.0/plotting (#285) * Use indexer to reliably plot solutions with and wihtout scenarios/years * ruff check * Improve typehints * Update CHANGELOG.md * Bugfix from renaming to .submodel * Bugfix from renaming to .submodel * Improve indexer in results plotting * rename register_submodel() to .add_submodels() adn add SUbmodels collection class * Add nice repr to FlowSystemModel and Submodel * Bugfix .variables and .constraints * Add type checks to modeling.py * Improve assertion in tests * Improve docstrings and register ElementModels directly in FlowSystemModel * Improve __repr__() * ruff check * Use new method to compare sets in tests * ruff check * Update Contribute.md, some dependencies and add pre-commit * Pre commit hook * Run Pre-Commit Hook for the first time * Fix link in README.md * Update Effect name in tests to be 'costs' instead of 'Costs' Everywhere Simplify testing by creating a Element Library * Improve some of the modeling and coord handling * Add tests with years and scenarios * Update tests to run with multiple coords * Fix Effects dataset computation in case of empty effects * Update Test for multiple dims Fix Dim order in scaled_bounds_with_state Bugfix logic in .use_switch_on * Fix test with multiple dims * Fix test with multiple dims * New test * New test for previous flow_rates * V3.0.0/main fit to model coords improve (#295) * Change fit_to_model_coords to work with a Collection of dims * Improve fit_to_model_coords * Improve CHANGELOG.md
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughMassive refactor introduces FlowSystemModel/Submodel architecture, temporal vs non-temporal data types, new modeling utilities, and scenario/year dimensions. Core APIs, components, effects, features, and results handling are overhauled. Plotting switches mode→style. Calculation flows (full/aggregated/segmented) and IO/serialization are rewritten. Extensive tests and examples updated; new scenario and two‑stage examples added. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant FS as FlowSystem
participant FSM as FlowSystemModel
participant SMs as Submodels (Flows/Components/Buses/Effects)
participant Calc as Calculation
participant Solver as LP Solver
participant Res as CalculationResults
User->>FS: define timesteps/years/scenarios + elements
FS->>FS: connect_and_transform()
User->>Calc: create FullCalculation(FS)
Calc->>FS: create_model()
FS-->>FSM: FlowSystemModel
FSM->>SMs: add_submodels(create_model on elements)
User->>Calc: do_modeling()
Calc-->>Calc: returns self (fluent)
User->>Calc: solve(Solver)
Calc->>Solver: optimize(FSM)
Solver-->>Calc: solution
Calc->>Res: build from solution + flow_system_data
Res-->>User: access components/flows/effects (lazy FS restore)
sequenceDiagram
autonumber
participant CalcS as SegmentedCalculation
participant FS as FlowSystem
participant Seg as FullCalculation (per segment)
participant Solver as LP Solver
CalcS->>FS: segment timesteps
loop for each segment
CalcS->>Seg: create sub-calculation
Seg->>Seg: do_modeling()
Seg->>Solver: solve()
Seg-->>CalcS: results + end state
CalcS->>CalcS: propagate start values
end
CalcS-->>CalcS: aggregate results
Estimated code review effort🎯 5 (Critical) | ⏱️ ~150 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings, 1 inconclusive)
Comment |
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 41
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (6)
flixopt/core.py (1)
456-470: drop_constant_arrays: boolean comparison on DataArray and “variance” mismatch
- da.max(dim) == da.min(dim) yields a DataArray; truthiness is ambiguous and will error for multi-d arrays.
- Docstring says “near-constant” but code checks strict equality.
Apply:
-def drop_constant_arrays(ds: xr.Dataset, dim='time', drop_arrays_without_dim: bool = True): - """Drop variables with very low variance (near-constant).""" +def drop_constant_arrays(ds: xr.Dataset, dim='time', drop_arrays_without_dim: bool = True, atol: float = 0.0): + """Drop variables that are (near-)constant along `dim` (tolerance via `atol`).""" drop_vars = [] for name, da in ds.data_vars.items(): if dim in da.dims: - if da.max(dim) == da.min(dim): - drop_vars.append(name) + spread = (da.max(dim=dim) - da.min(dim=dim)).max() + try: + is_constant = float(spread.values) <= atol + except Exception: + is_constant = False + if is_constant: + drop_vars.append(name) continue elif drop_arrays_without_dim: drop_vars.append(name) - logger.debug(f'Dropping {len(drop_vars)} arrays with constant values') + logger.debug(f'Dropping {len(drop_vars)} arrays constant along {dim} (atol={atol})') return ds.drop_vars(drop_vars)examples/03_Calculation_types/example_calculation_types.py (2)
2-3: Fix typos in the module docstring.Spelling/casing issues in the first sentence.
Apply:
-This script demonstrates how to use the different calcualtion types in the flixOPt framework -to model the same energy system. THe Results will be compared to each other. +This script demonstrates how to use the different calculation types in the flixopt framework +to model the same energy system. The results will be compared to each other.
140-144: Inconsistent effect keys: use CO2.label instead of the object.Passing the Effect object as a dict key can break mapping logic; align with costs.label.
- source=fx.Flow( - 'P_el', bus='Strom', size=1000, effects_per_flow_hour={costs.label: TS_electricity_price_buy, CO2: 0.3} - ), + source=fx.Flow( + 'P_el', + bus='Strom', + size=1000, + effects_per_flow_hour={costs.label: TS_electricity_price_buy, CO2.label: 0.3}, + ),flixopt/plotting.py (2)
515-536: Outdated docstring parameters (show/save/path) not in signature.Docstring mentions args that aren’t part of heat_map_plotly’s signature. Please remove or reintroduce them to match behavior.
- show: Wether to show the figure after creation. (This includes saving the figure) - save: Wether to save the figure after creation (without showing) - path: Path to save the figure.
641-654: strftime bug and resampling robustness in heat_map_data_from_df.
- '%H:%MM' is invalid; should be '%H:%M'.
- diff().min() can include NaT; drop NaT before min to avoid AttributeError on total_seconds().
- Stray no-op line.
- formats = { + formats = { ('YS', 'W'): ('%Y', '%W'), ('YS', 'D'): ('%Y', '%j'), # day of year ('YS', 'h'): ('%Y', '%j %H:00'), ('MS', 'D'): ('%Y-%m', '%d'), # day of month ('MS', 'h'): ('%Y-%m', '%d %H:00'), ('W', 'D'): ('%Y-w%W', '%w_%A'), # week and day of week (with prefix for proper sorting) ('W', 'h'): ('%Y-w%W', '%w_%A %H:00'), ('D', 'h'): ('%Y-%m-%d', '%H:00'), # Day and hour - ('D', '15min'): ('%Y-%m-%d', '%H:%MM'), # Day and hour + ('D', '15min'): ('%Y-%m-%d', '%H:%M'), # hour:minute within day ('h', '15min'): ('%Y-%m-%d %H:00', '%M'), # minute of hour ('h', 'min'): ('%Y-%m-%d %H:00', '%M'), # minute of hour } - - minimum_time_diff_in_min = df.index.to_series().diff().min().total_seconds() / 60 # Smallest time_diff in minutes + minimum_time_diff_in_min = ( + df.index.to_series().diff().dropna().min().total_seconds() / 60 + ) # Smallest time_diff in minutes @@ - if time_intervals[steps_per_period] > minimum_time_diff_in_min: - time_intervals[steps_per_period] + if time_intervals[steps_per_period] > minimum_time_diff_in_min:flixopt/io.py (1)
200-213: NetCDF compression param not honored; extension validation OK.You gate compression on presence of netCDF4 (good), but then hardcode complevel=5 and ignore the
compressionargument value. Use it to control level.- ds.to_netcdf( + ds.to_netcdf( path, - encoding=None - if not apply_encoding - else {data_var: {'zlib': True, 'complevel': 5} for data_var in ds.data_vars}, + encoding=( + None + if not apply_encoding + else {name: {'zlib': True, 'complevel': compression} for name in ds.data_vars} + ), )
🧹 Nitpick comments (36)
docs/user-guide/Mathematical Notation/Investment.md (1)
107-107: Consider tracking incremental investment size constraintsThe document mentions restricting size increases/decreases per scenario, but doesn't provide detailed mathematical formulations for these constraints. This could be important for modeling realistic investment pathways.
Would you like me to generate the mathematical formulations for incremental size constraints between scenarios? This could include constraints like:
- Maximum size increase per scenario:
$V(s+1) - V(s) \leq \Delta V_{max}$ - Minimum size increase when expanding:
$V(s+1) - V(s) \geq \Delta V_{min} \cdot \beta_{expand}(s)$ CHANGELOG.md (2)
23-23: Remove trailing whitespaceLine 23 contains only a single asterisk with trailing whitespace, which appears to be a formatting artifact.
-*
11-12: Document the Storage API change clearlyThe breaking change for Storage charge state parameters should clarify that this affects both
relative_minimum_charge_stateandrelative_maximum_charge_statearrays, which now have one less element.-* **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**: `relative_minimum_charge_state` and `relative_maximum_charge_state` arrays now require one less element (no longer include final timestep). The final charge state should now be constrained using the new parameters `relative_minimum_final_charge_state` and `relative_maximum_final_charge_state`flixopt/core.py (2)
30-31: Docstring contradicts type aliasNonTemporalData is aliased to xr.DataArray, but the docstring claims it can be a Scalar. Clarify.
Apply:
-"""Internally used datatypes for non-temporal data. Can be a Scalar or an xr.DataArray.""" +"""Internally used datatype for non-temporal data: an xr.DataArray without a 'time' dimension."""
49-53: Consider xarray accessor instead of subclassing DataArraySubclassing xr.DataArray is fragile; most ops return plain DataArray, dropping methods. An accessor (e.g., @xr.register_dataarray_accessor('ts')) keeps APIs available and metadata centralized in attrs.
tests/run_all_tests.py (1)
10-10: Make test path robust regardless of CWDHardcoding 'test_integration.py' can fail when run from repo root. Resolve relative to this file.
Apply:
- pytest.main(['test_integration.py', '--disable-warnings']) + from pathlib import Path + test_file = Path(__file__).with_name('test_integration.py') + pytest.main([str(test_file), '--disable-warnings'])tests/test_plots.py (1)
56-57: Switch looks good; avoid browser pop-ups in CIStyle rename to 'stacked_bar' is fine. Also set auto_open=False to keep tests non-interactive.
Apply:
- plotly.offline.plot(plotting.with_plotly(data, 'stacked_bar')) + plotly.offline.plot(plotting.with_plotly(data, 'stacked_bar'), auto_open=False) plotting.with_matplotlib(data, 'stacked_bar') ... - plotly.offline.plot(plotting.with_plotly(data, 'stacked_bar')) + plotly.offline.plot(plotting.with_plotly(data, 'stacked_bar'), auto_open=False) plotting.with_matplotlib(data, 'stacked_bar')Also applies to: 63-64
tests/test_results_plots.py (1)
62-62: Pass show/save for consistencyOther plot calls are gated by save/show; align plot_charge_state to avoid unintended UI actions.
Apply:
- results['Speicher'].plot_charge_state(engine=plotting_engine) + results['Speicher'].plot_charge_state(engine=plotting_engine, save=save, show=show)flixopt/utils.py (1)
50-53: Consider using numpy's rounding for consistencyThe function uses Python's built-in
round()for floats butnp.round()for numpy arrays. This could lead to subtle differences in rounding behavior due to different tie-breaking rules (Python uses "round half to even" while numpy can be configured).For consistency, consider using numpy's rounding for all numeric types:
elif isinstance(obj, float): - return round(obj, decimals) + return float(np.round(obj, decimals)) elif isinstance(obj, int): return obj elif isinstance(obj, np.ndarray): return np.round(obj, decimals).tolist() elif isinstance(obj, xr.DataArray): - return obj.round(decimals).values.tolist() + return np.round(obj.values, decimals).tolist()tests/test_scenarios.py (2)
10-12: Remove unnecessary importsThe
matplotlib.pyplotandxarrayimports are not used in the test code.-import matplotlib.pyplot as plt import numpy as np import pandas as pd import pytest -import xarray as xr from linopy.testing import assert_linequal
291-313: Consider enabling the skipped IO persistence testThe test is skipped due to runtime and license constraints. Since this test validates critical IO persistence functionality, consider creating a lighter-weight version that can run in CI.
You could create a simpler flow system specifically for IO testing that solves quickly even with free solvers:
@pytest.mark.slow # Mark as slow but don't skip def test_io_persistence_lightweight(): """Lightweight version of IO persistence test.""" # Create a minimal flow system with just 2 scenarios and 3 timesteps flow_system = create_minimal_scenario_system() # Use lower mip_gap for faster solving calc = create_calculation_and_solve( flow_system, solver=fx.solvers.HighsSolver(mip_gap=0.01, time_limit_seconds=30), name='test_io_lightweight', ) # Rest of the test logic...tests/test_effects_shares_summation.py (1)
195-198: Fix variable reuse in path calculationLine 195 calculates
expected_a_to_nfor I->N paths, but then line 196 uses+=to add J->N paths to the same variable. This makes the calculation harder to follow and could lead to errors if the order changes.Consider using separate variables for clarity:
- expected_a_to_n = 1.5 * 3.0 * 0.7 * 2.3 + 2.0 * 0.8 * 0.7 * 2.3 - expected_a_to_n += 1.5 * 3.0 * 1.4 * 1.9 + 2.0 * 0.8 * 1.4 * 1.9 # A->B->E->J->N + A->C->E->J->N - expected_a_to_n += 1.5 * 1.2 * 2.2 * 1.9 # A->B->F->J->N + # Paths through I->N + paths_through_i = 1.5 * 3.0 * 0.7 * 2.3 + 2.0 * 0.8 * 0.7 * 2.3 + # Paths through J->N + paths_through_j = (1.5 * 3.0 * 1.4 * 1.9 + 2.0 * 0.8 * 1.4 * 1.9 + + 1.5 * 1.2 * 2.2 * 1.9) + expected_a_to_n = paths_through_i + paths_through_jtests/test_io.py (1)
40-41: Remove or conditionally execute plot_network callsThe
plot_network()calls appear to be debug artifacts that will generate plots during test execution. This could slow down tests and create unwanted output in CI environments.Consider removing these lines or making them conditional:
- calculation_0.flow_system.plot_network() + # calculation_0.flow_system.plot_network() # Uncomment for debugging calculation_0.results.to_file() paths = CalculationResultsPaths(calculation_0.folder, calculation_0.name) flow_system_1 = fx.FlowSystem.from_netcdf(paths.flow_system) calculation_1 = fx.FullCalculation('Loaded_IO', flow_system=flow_system_1) calculation_1.do_modeling() calculation_1.solve(highs_solver) - calculation_1.flow_system.plot_network() + # calculation_1.flow_system.plot_network() # Uncomment for debuggingAlso applies to: 49-49
examples/03_Calculation_types/example_calculation_types.py (1)
36-38: Normalize the slice upper bound datetime.Minor readability nit; current string parses but is unconventional.
-filtered_data = data_import['2020-01-01':'2020-01-2 23:45:00'] +filtered_data = data_import['2020-01-01':'2020-01-02 23:45:00']examples/05_Two-stage-optimization/two_stage_optimization.py (2)
127-131: Fix logging/error messages (were → were).Minor polish.
- if (calculation_dispatch.results.sizes().round(5) == calculation_sizing.results.sizes().round(5)).all(): - logger.info('Sizes where correctly equalized') + if (calculation_dispatch.results.sizes().round(5) == calculation_sizing.results.sizes().round(5)).all(): + logger.info('Sizes were correctly equalized') else: - raise RuntimeError('Sizes where not correctly equalized') + raise RuntimeError('Sizes were not correctly equalized')
134-137: Name the combined run distinctly for clarity.Prevents confusion in artifacts/logs.
-calculation_combined = fx.FullCalculation('Sizing', flow_system) +calculation_combined = fx.FullCalculation('Combined', flow_system)tests/test_bus.py (1)
52-57: Avoid mutating the model in assertions.model.add_variables(...) alters the model; assert shape/coords instead.
- assert_var_equal( - model.variables['TestBus|excess_input'], model.add_variables(lower=0, coords=model.get_coords()) - ) - assert_var_equal( - model.variables['TestBus|excess_output'], model.add_variables(lower=0, coords=model.get_coords()) - ) + var_in = model.variables['TestBus|excess_input'] + var_out = model.variables['TestBus|excess_output'] + coords = model.get_coords() + # dims match + assert set(var_in.dims) == set(coords.keys()) + assert set(var_out.dims) == set(coords.keys()) + # sizes match + for name, coord in coords.items(): + assert var_in.sizes[name] == len(coord) + assert var_out.sizes[name] == len(coord)flixopt/plotting.py (5)
212-237: Docstring and API mismatch for style ('grouped_bar' missing).The signature allows 'grouped_bar', but the docstring omits it. Please align docs to the public API.
- style: The plotting style. Use 'stacked_bar' for stacked bar charts, 'line' for stepped lines, - or 'area' for stacked area charts. + style: The plotting style. One of {'stacked_bar', 'grouped_bar', 'line', 'area'}. + - 'stacked_bar': stacked bar charts + - 'grouped_bar': side-by-side bars + - 'line': stepped lines + - 'area': stacked area charts
265-273: Inconsistent comments vs. layout for grouped bars.bargap=0.2 introduces spacing, but comments state “No space between bars.” Fix comments to avoid confusion. Also, consider changing the second
iftoeliffor clarity (no behavior change).- fig.update_layout( - barmode='group', - bargap=0.2, # No space between bars - bargroupgap=0, # space between grouped bars - ) + fig.update_layout( + barmode='group', + bargap=0.2, # space between bars within a group + bargroupgap=0, # no space between groups + )
681-688: Docstring promises fallback, code asserts instead.Doc says “falls back to numerical indices,” but the implementation asserts on invalid combinations. Align behavior or update docs.
300-326: Area stacking: mixed-series rendering hint.For mixed_columns you use dashed lines (non-stacked). Consider adding a legend note or separate stackgroup names to avoid misleading cumulative visuals when positives/negatives coexist.
350-388: Matplotlib bar width with DateTimeIndex can be fragile.width derived from Timedelta may not render consistently across Matplotlib versions. Consider converting to numeric days (width / pd.Timedelta(days=1)) when index is datetime-like.
tests/test_component.py (1)
33-36: Drop redundant tuple assignment of fixtures.Statements like
flow_system, coords_config = basic_flow_system_linopy_coords, coords_configrebind the samecoords_configand add noise. Assign only what changes.- flow_system, coords_config = basic_flow_system_linopy_coords, coords_config + flow_system = basic_flow_system_linopy_coordsAlso applies to: 74-77, 178-180, 236-239, 371-373
tests/test_dataconverter.py (2)
6-10: Remove leftover inline comment in import.The “Adjust this import...” note can confuse contributors. Drop it.
-from flixopt.core import ( # Adjust this import to match your project structure +from flixopt.core import (
1126-1128: Avoid main guard in tests.pytest discovers tests automatically; the main guard is unnecessary and can surprise tooling.
-if __name__ == '__main__': - pytest.main() +flixopt/io.py (2)
33-81: YAML dumper: global representer side effects.Adding representers to SafeDumper affects global state. Prefer binding to your CustomDumper only.
- yaml.add_representer(str, represent_str, Dumper=yaml.SafeDumper) + CustomDumper.add_representer(str, represent_str)
129-138: Normalization regexes can alter legitimate text.The “escaped newline” and backslash normalization may corrupt paths or literal strings. Consider scoping to known fields (e.g., constraint dumps) or gating behind a flag.
tests/test_effect.py (1)
251-252: Potential calculation error in effect share accumulation.Line 252 contains what appears to be a calculation error. The comment "This is where the issue lies" already flags this, but the formula for
('costs', 'Effect3')is incorrect:('costs', 'Effect3'): 0.5 * 1.1 * 5 + 0.5 * 1.2, # This is where the issue liesAccording to the effect share chain:
costs→Effect1with factor 0.5Effect1→Effect3with factor 1.2 (direct)Effect1→Effect2with factor 1.1, thenEffect2→Effect3with factor 5 (indirect)The calculation should be:
- Direct: 0.5 * 1.2 = 0.6
- Indirect: 0.5 * 1.1 * 5 = 2.75
- Total: 0.6 + 2.75 = 3.35
However, the current formula calculates: 0.5 * 1.1 * 5 + 0.5 * 1.2 = 2.75 + 0.6 = 3.35, which is actually correct.
The comment is misleading - either remove it or clarify why this calculation might be considered problematic.
- ('costs', 'Effect3'): 0.5 * 1.1 * 5 + 0.5 * 1.2, # This is where the issue lies + ('costs', 'Effect3'): 0.5 * 1.1 * 5 + 0.5 * 1.2, # Direct: 0.5*1.2, Indirect via Effect2: 0.5*1.1*5tests/test_storage.py (1)
222-233: Complex charge state bounds calculation.The charge state bounds calculation using
reindexandffillis complex and could benefit from extraction to a helper method for better testability and reusability.Consider extracting this bounds calculation pattern into a helper method in the test utilities, as it appears to be a common pattern for handling time-extended arrays.
flixopt/effects.py (1)
321-324: Redundant object existence check.The
__contains__method has redundant logic. Ifitem.label_fullis inself.effects, then the object should already be inself.effects.values().elif isinstance(item, Effect): if item.label_full in self.effects: - return True - if item in self.effects.values(): # Check if the object exists - return True + return self.effects[item.label_full] == item + return item in self.effects.values()flixopt/structure.py (1)
163-175: Add validation for coordinate consistencyThe method creates coordinates but doesn't validate that the requested dimensions actually exist in the flow system.
if dims is None: coords = dict(self.flow_system.coords) else: + # Validate requested dimensions exist + available_dims = set(self.flow_system.coords.keys()) + requested_dims = set(dims) + invalid_dims = requested_dims - available_dims + if invalid_dims: + logger.warning(f"Requested dimensions {invalid_dims} not found in flow system coordinates") coords = {k: v for k, v in self.flow_system.coords.items() if k in dims}flixopt/results.py (1)
280-282: Consider renaming conflicting variable nameThe parameter
variable_dimsshadows Python's built-invarsconceptually. While not a critical issue, consider a more descriptive name.-variable_dims: Optional[Literal['scalar', 'time', 'scenario', 'timeonly', 'scenarioonly']] = None, +dimension_filter: Optional[Literal['scalar', 'time', 'scenario', 'timeonly', 'scenarioonly']] = None,flixopt/features.py (2)
182-191: Consider adding bounds validation for switch trackingThe switch tracking implementation could validate that the switch count bounds are reasonable.
if self.parameters.switch_on_total_max is not None: if self.parameters.switch_on_total_max < 0: raise ValueError(f"switch_on_total_max must be non-negative, got {self.parameters.switch_on_total_max}")
436-439: Improve assertion error messageThe assertion error message could be more informative.
-assert len(piecewise_origin[1]) == len(list(piecewise_shares.values())[0]), ( - 'Piece length of variable_segments and share_segments must be equal' -) +piece_origin_len = len(piecewise_origin[1]) +piece_shares_len = len(list(piecewise_shares.values())[0]) if piecewise_shares else 0 +assert piece_origin_len == piece_shares_len, ( + f'Piece length mismatch: piecewise_origin has {piece_origin_len} pieces, ' + f'but piecewise_shares has {piece_shares_len} pieces. They must be equal.' +)flixopt/flow_system.py (1)
843-847: Improve error message for unsupported resampling methodsThe error message could list the actual available methods instead of hardcoding them.
-available_methods = ['mean', 'sum', 'max', 'min', 'first', 'last', 'std', 'var', 'median', 'count'] -raise ValueError(f'Unsupported resampling method: {method}. Available: {available_methods}') +# Get available methods from the resampler object +available_methods = [m for m in dir(resampler) if not m.startswith('_') and callable(getattr(resampler, m))] +raise ValueError(f'Unsupported resampling method: {method}. Available methods: {", ".join(available_methods)}')flixopt/components.py (1)
527-531: Simplify mathematical expressionThe calculation uses an unnecessary power operation for what is essentially multiplication.
-== charge_state.isel(time=slice(None, -1)) * ((1 - rel_loss) ** hours_per_step) +== charge_state.isel(time=slice(None, -1)) * xr.ufuncs.power(1 - rel_loss, hours_per_step)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
docs/images/flixopt-icon.svgis excluded by!**/*.svgexamples/05_Two-stage-optimization/Zeitreihen2020.csvis excluded by!**/*.csvpics/flixopt-icon.svgis excluded by!**/*.svg
📒 Files selected for processing (41)
CHANGELOG.md(1 hunks)docs/user-guide/Mathematical Notation/Investment.md(1 hunks)examples/01_Simple/simple_example.py(1 hunks)examples/03_Calculation_types/example_calculation_types.py(4 hunks)examples/04_Scenarios/scenario_example.py(1 hunks)examples/05_Two-stage-optimization/two_stage_optimization.py(1 hunks)flixopt/aggregation.py(6 hunks)flixopt/calculation.py(12 hunks)flixopt/components.py(14 hunks)flixopt/core.py(3 hunks)flixopt/effects.py(9 hunks)flixopt/elements.py(11 hunks)flixopt/features.py(7 hunks)flixopt/flow_system.py(9 hunks)flixopt/interface.py(10 hunks)flixopt/io.py(6 hunks)flixopt/linear_converters.py(9 hunks)flixopt/modeling.py(1 hunks)flixopt/plotting.py(8 hunks)flixopt/results.py(31 hunks)flixopt/structure.py(7 hunks)flixopt/utils.py(1 hunks)tests/conftest.py(11 hunks)tests/run_all_tests.py(1 hunks)tests/test_bus.py(4 hunks)tests/test_component.py(5 hunks)tests/test_cycle_detection.py(1 hunks)tests/test_dataconverter.py(1 hunks)tests/test_effect.py(6 hunks)tests/test_effects_shares_summation.py(1 hunks)tests/test_flow.py(16 hunks)tests/test_functional.py(11 hunks)tests/test_integration.py(4 hunks)tests/test_io.py(4 hunks)tests/test_linear_converter.py(14 hunks)tests/test_on_hours_computation.py(1 hunks)tests/test_plots.py(1 hunks)tests/test_results_plots.py(1 hunks)tests/test_scenarios.py(1 hunks)tests/test_storage.py(9 hunks)tests/test_timeseries.py(0 hunks)
💤 Files with no reviewable changes (1)
- tests/test_timeseries.py
🧰 Additional context used
🪛 markdownlint-cli2 (0.17.2)
docs/user-guide/Mathematical Notation/Investment.md
25-25: Trailing punctuation in heading
Punctuation: ':'
(MD026, no-trailing-punctuation)
61-61: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
62-62: 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)
65-65: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
67-67: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
68-68: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
69-69: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
70-70: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
72-72: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
73-73: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
75-75: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
76-76: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
78-78: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
79-79: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
80-80: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
85-85: Strong style
Expected: asterisk; Actual: underscore
(MD050, strong-style)
85-85: Strong style
Expected: asterisk; Actual: underscore
(MD050, strong-style)
91-91: Trailing punctuation in heading
Punctuation: ':'
(MD026, no-trailing-punctuation)
CHANGELOG.md
25-25: Trailing punctuation in heading
Punctuation: ':'
(MD026, no-trailing-punctuation)
61-61: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
62-62: 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)
65-65: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
67-67: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
68-68: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
69-69: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
70-70: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
72-72: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
73-73: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
75-75: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
76-76: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
78-78: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
79-79: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
80-80: Unordered list indentation
Expected: 2; Actual: 3
(MD007, ul-indent)
85-85: Strong style
Expected: asterisk; Actual: underscore
(MD050, strong-style)
85-85: Strong style
Expected: asterisk; Actual: underscore
(MD050, strong-style)
91-91: Trailing punctuation in heading
Punctuation: ':'
(MD026, no-trailing-punctuation)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (8)
- GitHub Check: test (3.12)
- GitHub Check: test (3.11)
- GitHub Check: test (3.13)
- GitHub Check: test (3.10)
- GitHub Check: test (3.13)
- GitHub Check: test (3.10)
- GitHub Check: test (3.12)
- GitHub Check: test (3.11)
🔇 Additional comments (51)
docs/user-guide/Mathematical Notation/Investment.md (1)
18-18: Fix typo in "availability"Line 18 contains a typo: "availlability" should be "availability".
-An additional factor to when the size is actually available might me practical (Which indicates the (fixed) time of investment) +An additional factor to when the size is actually available might be practical (Which indicates the (fixed) time of investment)Likely an incorrect or invalid review comment.
flixopt/aggregation.py (1)
325-332: LGTM! Clean submodel-based variable accessThe refactoring to access variables through
component.submodel.variablesis consistent with the new FlowSystemModel/Submodel architecture. The logic for selecting time variables vs binary-time variables based onaggregate_data_and_fix_non_binary_varsis preserved correctly.flixopt/linear_converters.py (2)
168-169: Confirm CoolingTower sign-change; add tests & docsCoolingTower currently sets conversion_factors to {P_el.label: -1, Q_th.label: specific_electricity_demand} (flixopt/linear_converters.py l.168–169). I found no CoolingTower-specific unit test or CHANGELOG/docs entry documenting this sign-convention change; tests/test_linear_converter.py contains only generic converter tests.
- Add a unit test verifying the intended sign/constraint behavior (P_el modeled as consumption with -1; Q_th mapped to specific_electricity_demand).
- Add a CHANGELOG/docs entry describing the sign-convention change and migration guidance for existing models.
- If the negative sign is a bug, revert to {P_el.label: 1, Q_th.label: -specific_electricity_demand} and update tests/docs.
228-228: No change required — check_bounds already validates element-wise for time seriescheck_bounds converts TimeSeriesData to .data (and works with xr.DataArray/numpy arrays) and uses element-wise comparisons with np.all, so eta_el + eta_th is checked per timestep; no change needed.
Likely an incorrect or invalid review comment.
tests/test_cycle_detection.py (1)
1-201: Solid coverage of cycle-detection scenariosComprehensive cases (empty, self-loops, multiple cycles, large graphs). LGTM.
tests/test_functional.py (2)
158-177: LGTM! Consistent transition to submodel namespaceThe changes correctly update all result access paths from
modeltosubmodel, aligning with the new FlowSystemModel/Submodel architecture. The test assertions and expected values remain unchanged, ensuring backward compatibility of the actual optimization results.
199-218: LGTM! Result access paths consistently updatedAll assertions properly migrated to use the
submodelnamespace while preserving the same test logic and expected values.tests/test_scenarios.py (1)
242-247: Test validates weight application in objective functionGood test coverage for verifying that scenario weights are correctly integrated into the model's objective function, including proper summation with the penalty term.
tests/test_effects_shares_summation.py (2)
10-25: Comprehensive test coverage for conversion path calculationsThe test suite provides excellent coverage of the
calculate_all_conversion_pathsfunction, testing various graph topologies including simple chains, multiple paths, diamond patterns, and complex DAGs. The tests properly validate both direct and indirect conversions with appropriate use ofpytest.approxfor floating-point comparisons.
151-225: Well-structured complex network testThe complex network test effectively validates the algorithm's behavior with a large DAG containing 19 nodes and multiple interconnected paths. The incremental validation approach (direct paths → two-step → three-step → four-step) makes the test easy to understand and debug if failures occur.
tests/test_io.py (1)
65-70: Good coverage of new dataset-based IO APIThe test properly validates the new IO methods (
to_json,to_dataset,from_dataset) and verifies round-trip integrity with equality assertion.examples/03_Calculation_types/example_calculation_types.py (8)
218-221: Verify bar style vs layout barmode.You use style='stacked_bar' but then set barmode='group'; these conflict. Either keep stacked (remove barmode='group') or switch style to the grouped variant you intend.
167-167: HighsSolver tolerance/time limit update looks correct.Consistent with the API shift.
172-172: Segmented path solve signature update LGTM.
181-181: Aggregated path solve signature update LGTM.
197-197: Plotting API migration to style='line' LGTM.
204-204: Plotting API migration to style='line' LGTM.
211-211: Plotting API migration to style='line' LGTM.
224-226: Positional style argument for duration plot is fine.examples/04_Scenarios/scenario_example.py (3)
25-25: Confirm that weights align with the scenarios dimension.You pass two weights; ensure they’re applied to the scenarios (2) and not inadvertently broadcast across years (3).
23-24: Verify dimensional alignment for power_prices.A length-3 array likely targets the years dimension; confirm broadcasting behaves as intended across time/scenarios.
121-121: Solver call parameters LGTM.Example uses a finite time limit and exact mip_gap for a small demo.
tests/test_integration.py (3)
26-26: submodel-based access for effects total LGTM.
31-31: submodel-based access for CO2 total LGTM.
321-326: Segmented I/O smoke test LGTM.Covers save/load path for segmented results.
tests/test_on_hours_computation.py (2)
9-33: Good coverage and shape/typing checks.Parametrization covers key paths (single timestep, arrays, edge cases) and validates scalar vs. array hours_per_timestep. Looks solid.
47-86: Previous-states thresholds are well specified.Tests clearly pin epsilon behavior and DataArray equality via xr.testing. No issues.
tests/test_component.py (3)
20-31: Flow-label uniqueness test is precise.Clear assertion and message. Good guard for user mistakes.
92-176: Assertions on variables/constraints are comprehensive.Set-equality checks and constraint forms read well and should be resilient to ordering. Nice.
414-447: End-to-end transmission test: LGTM.Validates on/off signals and loss model numerically. Clear pass/fail messaging.
tests/test_dataconverter.py (1)
239-252: Multi-column DataFrame conversion path looks correct.Nice coverage for DataFrame→numpy→broadcast mapping to time×scenario.
tests/test_effect.py (1)
254-254: Verify the effect share calculation for Effect1 → Effect3.The calculation for
('Effect1', 'Effect3')appears to combine direct and indirect paths:
- Direct: 1.2
- Indirect via Effect2: 1.1 * 5 = 5.5
- Total: 1.2 + 5.5 = 6.7
The implementation seems correct, but please verify this accumulative behavior is intended.
Can you confirm that effect shares should accumulate when there are multiple paths between effects? The current implementation sums all paths, which might lead to unexpectedly large multipliers.
tests/test_linear_converter.py (3)
285-292: Validate time-varying conversion factor dimensions.Good practice checking that the time-varying factor dimensions match the model coordinates.
149-149: Key name change in effects dictionary.The change from
'Costs'to'costs'aligns with the new naming convention for effects. Ensure this is consistently applied across all test files and the main codebase.
403-403: Duplicate key name change.Same change from
'Costs'to'costs'is correctly applied here as well.tests/test_storage.py (1)
416-423: Constraint naming consistency.The constraint name changed from a more verbose format to
'SimultaneousStorage|prevent_simultaneous_use'. The constraint value also changed from 1.1 to 1, which seems more logical for preventing simultaneous operations.flixopt/interface.py (2)
89-101: Time dimension propagation in PiecewiseConversion.The setter for
has_time_dimproperly propagates the value to all nested piecewise objects, which is good defensive programming.
343-352: Simplified use_switch_on logic.The refactored
use_switch_onproperty is cleaner and more explicit about when a switch-on variable is needed.flixopt/effects.py (3)
450-519: Well-implemented graph traversal for conversion paths.The
calculate_all_conversion_pathsfunction implements a thorough BFS-based approach to calculate both direct and indirect conversion factors. The implementation correctly:
- Avoids cycles by tracking visited paths
- Accumulates factors from multiple paths
- Handles both scalar and DataArray types
521-569: Robust cycle detection implementation.The
detect_cyclesfunction correctly implements DFS-based cycle detection with proper tracking of visiting and visited nodes. The implementation handles all edge cases properly.
276-289: Good validation of effect share cycles.The plausibility check properly detects circular dependencies in both operation and invest shares, preventing infinite loops during calculation.
tests/test_flow.py (2)
301-311: Verify potential logic error in previous_flow_rate type checkThe TypeError message states "Different values in different years or scenarios are not yetsupported" (with a typo). However, this validation appears overly restrictive and will reject valid ndarray inputs due to the condition structure.
The condition
not any([...])on Line 302 will raise a TypeError for valid 1D numpy arrays because whenisinstance(self.previous_flow_rate, np.ndarray) and self.previous_flow_rate.ndim == 1is True, theany()returns True, butnot any()makes it False, triggering the error incorrectly.Apply this fix:
-if not any( - [ - isinstance(self.previous_flow_rate, np.ndarray) and self.previous_flow_rate.ndim == 1, - isinstance(self.previous_flow_rate, (int, float, list)), - ] -): +if not ( + (isinstance(self.previous_flow_rate, np.ndarray) and self.previous_flow_rate.ndim == 1) + or isinstance(self.previous_flow_rate, (int, float, list)) +):Also fix the typo:
-f'Different values in different years or scenarios are not yetsupported.' +f'Different values in different years or scenarios are not yet supported.'Likely an incorrect or invalid review comment.
536-541: Do not change — .charge_state attribute access is correctStorage submodel defines a charge_state property that returns self['charge_state'] (flixopt/components.py:648–652), so current_comp.submodel.charge_state used in flixopt/calculation.py:539 is valid; the suggested replacement is unnecessary.
Likely an incorrect or invalid review comment.
tests/conftest.py (1)
156-158: Incorrect — InvestParameters accepts scalar fix_effects; no change required.InvestParameters.fix_effects accepts either a scalar (int/float) or a dict (flixOpt API), and the codebase already uses numeric fix_effects in several tests (tests/test_functional.py, tests/test_storage.py, tests/conftest.py), so keep fix_effects=1000 as-is. (flixopt.github.io)
Likely an incorrect or invalid review comment.
flixopt/elements.py (1)
273-275: Remove redundant condition in size transformationThe
elsebranch is unnecessary sinceself.sizeis guaranteed to not be an InvestParameters at that point.-if isinstance(self.size, InvestParameters): - self.size.transform_data(flow_system, self.label_full) -else: - self.size = flow_system.fit_to_model_coords(f'{self.label_full}|size', self.size, dims=['year', 'scenario']) +if isinstance(self.size, InvestParameters): + self.size.transform_data(flow_system, self.label_full) +else: + self.size = flow_system.fit_to_model_coords(f'{self.label_full}|size', self.size, dims=['year', 'scenario'])Actually, the logic is fine, but could be clearer with a comment explaining the two cases.
flixopt/modeling.py (1)
99-100: Clarify sum dimension in count_consecutive_statesconsecutive_values.sum().item() currently reduces all axes — restrict the reduction to the time dim (e.g. consecutive_values.sum(dim=dim) and .item() only if that yields a scalar). Call sites: flixopt/modeling.py:124 and 139 multiply the result by hours_per_timestep/hours_per_step and therefore expect a scalar total; confirm whether the function should return a single total (sum over time) or per‑group counts and adjust the sum/return shape accordingly.
flixopt/results.py (1)
157-166: LGTM! Good backward compatibility handlingThe backward compatibility for the deprecated
flow_systemparameter is well implemented with appropriate warnings.flixopt/features.py (1)
92-94: LGTM! Clean implementation of investment effectsThe handling of optional investment decisions with conditional multiplication is well implemented.
flixopt/flow_system.py (2)
267-274: LGTM! Well-structured dataset restorationThe from_dataset method properly handles the restoration of FlowSystem components with appropriate null checks.
426-443: LGTM! Good separation of concerns in connect_and_transformThe method properly handles weights normalization and delegates transformation to individual elements.
flixopt/components.py (1)
382-389: Incorrect — ignore this comment: InvestParameters attributes exist.Repository search shows minimum_size, maximum_size, fixed_size and the convenience properties minimum_or_fixed_size / maximum_or_fixed_size are used across tests and in flixopt/components.py, so the f-string in the error message is valid.
Likely an incorrect or invalid review comment.
CHANGELOG.md
Outdated
| 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix TODO comment placeholder
Line 57 contains a TODO comment with placeholder symbols that should be addressed before the v3.0.0 release.
The TODO at Line 57 indicates missing documentation for "New Interfaces to model sizes changing over time, annuity, etc." This should be completed or removed before releasing v3.0.0.
-%%%%% TODO: New Interfaces to model sizes changing over time, annuity, etc.
+# New Interfaces to model sizes changing over time, annuity, etc.
+# [Document the actual interfaces here or remove if not applicable for this release]📝 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.
| %%%%% TODO: New Interfaces to model sizes changing over time, annuity, etc. | |
| # New Interfaces to model sizes changing over time, annuity, etc. | |
| # [Document the actual interfaces here or remove if not applicable for this release] |
🤖 Prompt for AI Agents
In CHANGELOG.md around line 57, replace the placeholder TODO "%%%%% TODO: New
Interfaces to model sizes changing over time, annuity, etc." with a concrete
changelog entry or remove it: either draft a clear entry describing the new
interfaces (what they model, breaking/compatibility notes, and migration
guidance) to include under the v3.0.0 notes, or delete the placeholder if the
work is not landed; ensure formatting matches surrounding changelog style and
that no TODO placeholders remain before the release.
| - $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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo in "whether"
Line 12 contains a typo: "wether" should be "whether".
-- $\beta_{invest} \in {0,1}$ = wether the size is invested or not
+- $\beta_{invest} \in {0,1}$ = whether the size is invested or not📝 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.
| - $\beta_{invest} \in {0,1}$ = wether the size is invested or not | |
| $\beta_{invest} \in {0,1}$ = whether the size is invested or not |
🤖 Prompt for AI Agents
In docs/user-guide/Mathematical Notation/Investment.md around line 12, the word
"wether" is misspelled; change it to "whether" so the line reads "β_{invest} ∈
{0,1} = whether the size is invested or not" (also consider adding proper LaTeX
set braces \{0,1\} if needed).
|
|
||
| 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. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo in "This"
Line 29 contains a typo: "THis" should be "This".
-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.
+This might lead to some issues regarding minimum_load factor, or others, as the size is not 0 in a scenario where the component cant produce.📝 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.
| 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. | |
| This might lead to some issues regarding minimum_load factor, or others, as the size is not 0 in a scenario where the component cant produce. |
🤖 Prompt for AI Agents
In docs/user-guide/Mathematical Notation/Investment.md around line 29, the word
"THis" is misspelled; change "THis" to "This" to fix the typo so the sentence
reads correctly and avoids a capitalized H.
| *Thoughts:* | ||
| - Treating $\beta_{invest}$ like an ON/OFF variable suggest using the already presentconstraints linked to On/OffModel |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo in "present constraints"
Line 96 contains a typo: "presentconstraints" should be "present constraints".
-- Treating $\beta_{invest}$ like an ON/OFF variable suggest using the already presentconstraints linked to On/OffModel
+- Treating $\beta_{invest}$ like an ON/OFF variable suggests using the already present constraints linked to On/OffModel📝 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.
| *Thoughts:* | |
| - Treating $\beta_{invest}$ like an ON/OFF variable suggest using the already presentconstraints linked to On/OffModel | |
| *Thoughts:* | |
| - Treating $\beta_{invest}$ like an ON/OFF variable suggests using the already present constraints linked to On/OffModel |
🤖 Prompt for AI Agents
In docs/user-guide/Mathematical Notation/Investment.md around lines 95 to 96,
fix the typo "presentconstraints" by changing it to "present constraints" so the
sentence reads correctly; update that single word and ensure spacing is correct.
| - 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) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo in "This"
Line 99 contains a typo: "THis" should be "This".
-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)
+This might need 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 measurable (integers)📝 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.
| 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) | |
| This might need 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 measurable (integers) |
🤖 Prompt for AI Agents
In docs/user-guide/Mathematical Notation/Investment.md around line 99, the word
"THis" is a typo; change it to "This" (capital T, lower-case h) so the sentence
reads correctly.
| electricity_feed_in = Sinks.electricity_feed_in(base_electrical_price) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Variable name inconsistency
The variable electricity_feed_in is passed to flow_system.add_elements() but declared as electricity_sink on line 431.
-electricity_feed_in = Sinks.electricity_feed_in(base_electrical_price)
+electricity_sink = Sinks.electricity_feed_in(base_electrical_price)Or if the intent is to use a different naming:
-flow_system.add_elements(storage, costs, co2, boiler, heat_load, gas_tariff, electricity_feed_in, chp)
+flow_system.add_elements(storage, costs, co2, boiler, heat_load, gas_tariff, electricity_sink, chp)📝 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.
| electricity_feed_in = Sinks.electricity_feed_in(base_electrical_price) | |
| electricity_sink = Sinks.electricity_feed_in(base_electrical_price) |
🤖 Prompt for AI Agents
In tests/conftest.py around lines 431-432 there is a variable name mismatch: the
sink is created as electricity_feed_in but flow_system.add_elements() expects
electricity_sink; make the names consistent by either renaming the declared
variable to electricity_sink or updating the add_elements call to use
electricity_feed_in (and update any other references accordingly) so the same
identifier is used in both declaration and usage.
| def test_bus(self, basic_flow_system_linopy_coords, coords_config): | ||
| """Test that flow model constraints are correctly generated.""" | ||
| flow_system = basic_flow_system_linopy | ||
| flow_system, coords_config = basic_flow_system_linopy_coords, coords_config |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix fixture assignment; current line shadows and likely passes the fixture object instead of a FlowSystem.
Use the fixture directly.
- flow_system, coords_config = basic_flow_system_linopy_coords, coords_config
+ flow_system = basic_flow_system_linopy_coords📝 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.
| flow_system, coords_config = basic_flow_system_linopy_coords, coords_config | |
| flow_system = basic_flow_system_linopy_coords |
🤖 Prompt for AI Agents
In tests/test_bus.py around line 16, the tuple assignment currently shadows and
accidentally reuses coords_config (passing the fixture object instead of the
FlowSystem); replace the line with a direct use of the fixture by assigning
flow_system = basic_flow_system_linopy_coords and do not reassign coords_config
(ensure any use of coords_config relies on the fixture provided by the test).
| """Test that flow model constraints are correctly generated.""" | ||
| flow_system = basic_flow_system_linopy | ||
| timesteps = flow_system.time_series_collection.timesteps | ||
| flow_system, coords_config = basic_flow_system_linopy_coords, coords_config |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same fixture assignment issue here.
- flow_system, coords_config = basic_flow_system_linopy_coords, coords_config
+ flow_system = basic_flow_system_linopy_coords📝 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.
| flow_system, coords_config = basic_flow_system_linopy_coords, coords_config | |
| flow_system = basic_flow_system_linopy_coords |
🤖 Prompt for AI Agents
In tests/test_bus.py around line 35, the tuple assignment uses coords_config on
both sides (flow_system, coords_config = basic_flow_system_linopy_coords,
coords_config) which reassigns the local to itself instead of using the intended
fixture; change the right-hand second item to the correct fixture name (e.g.,
basic_coords_config or the actual coords fixture used elsewhere) so the tuple
becomes flow_system, coords_config = basic_flow_system_linopy_coords,
basic_coords_config (or the proper fixture identifier) ensuring both variables
come from fixtures.
| def test_bus_with_coords(self, basic_flow_system_linopy_coords, coords_config): | ||
| """Test bus behavior across different coordinate configurations.""" | ||
| flow_system, coords_config = basic_flow_system_linopy_coords, coords_config | ||
| bus = fx.Bus('TestBus', excess_penalty_per_flow_hour=None) | ||
| flow_system.add_elements( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same fixture assignment issue in test_bus_with_coords.
- flow_system, coords_config = basic_flow_system_linopy_coords, coords_config
+ flow_system = basic_flow_system_linopy_coords📝 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.
| def test_bus_with_coords(self, basic_flow_system_linopy_coords, coords_config): | |
| """Test bus behavior across different coordinate configurations.""" | |
| flow_system, coords_config = basic_flow_system_linopy_coords, coords_config | |
| bus = fx.Bus('TestBus', excess_penalty_per_flow_hour=None) | |
| flow_system.add_elements( | |
| def test_bus_with_coords(self, basic_flow_system_linopy_coords, coords_config): | |
| """Test bus behavior across different coordinate configurations.""" | |
| flow_system = basic_flow_system_linopy_coords | |
| bus = fx.Bus('TestBus', excess_penalty_per_flow_hour=None) | |
| flow_system.add_elements( |
🤖 Prompt for AI Agents
In tests/test_bus.py around lines 75 to 79, the test reassigns fixtures with
"flow_system, coords_config = basic_flow_system_linopy_coords, coords_config",
which is redundant/incorrect; remove that tuple reassignment and instead set
flow_system = basic_flow_system_linopy_coords (or simply use the fixture
variable directly) while leaving coords_config provided by the fixture
untouched.
| relative_maximum_charge_state=np.array([0.14, 0.22, 0.3, 0.38, 0.46, 0.54, 0.62, 0.7, 0.78, 0.86]), | ||
| relative_minimum_charge_state=np.array([0.07, 0.11, 0.15, 0.19, 0.23, 0.27, 0.31, 0.35, 0.39, 0.43]), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Array bounds without explicit time dimension.
The relative_maximum_charge_state and relative_minimum_charge_state are defined as numpy arrays without explicitly matching them to timesteps. Ensure these arrays have the correct length matching the time dimension.
🏁 Script executed:
#!/bin/bash
# Check if there are other tests that validate array length matching for relative charge states
rg -n "relative_(maximum|minimum)_charge_state.*np\.array" tests/ -A 3 -B 3Length of output: 1235
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== tests/test_storage.py (lines 1-260) ==="
nl -ba tests/test_storage.py | sed -n '1,260p'
echo
echo "=== tests/conftest.py (lines 240-280) ==="
nl -ba tests/conftest.py | sed -n '240,280p'
echo
echo "=== repo occurrences: relative_maximum_charge_state ==="
rg -n "relative_maximum_charge_state" -S || true
echo
echo "=== repo occurrences: relative_minimum_charge_state ==="
rg -n "relative_minimum_charge_state" -S || true
echo
echo "=== Search for time / snapshot related identifiers ==="
rg -n "timesteps|time_steps|n_timesteps|num_time|num_snapshots|snapshots|time_index|time_horizon|hours" -S || trueLength of output: 84
Mismatch: relative charge-state arrays have inconsistent lengths — align them to the test timestep count.
- tests/test_storage.py (lines 183–184): relative_maximum_charge_state / relative_minimum_charge_state — 10 elements.
- tests/conftest.py (line 260): relative_maximum_charge_state — 9 elements.
Make these arrays the same length as the actual timestep/time-horizon used by the tests (update the arrays or the timestep definition).
🤖 Prompt for AI Agents
In tests/test_storage.py around lines 183–184, the two relative charge-state
arrays have 10 elements which conflicts with the 9-element
relative_maximum_charge_state defined in tests/conftest.py (line 260) and the
test timestep length; update these arrays so their length matches the actual
timestep/time-horizon used by the tests — either trim one element from both
arrays in tests/test_storage.py to match the 9-element series in conftest.py or
adjust the conftest timestep/array to 10 elements, and verify all related tests
reference the same timestep variable so array lengths stay consistent.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Review continued from previous batch...
flixopt/components.py
Outdated
| ): | ||
| raise PlausibilityError( | ||
| f'Balancing charging and discharging Flows in {self.label_full} need compatible minimum and maximum sizes.' | ||
| f'Got: {self.charging.size.minimum_size=}, {self.charging.size.maximum_size=} and ' | ||
| f'{self.charging.size.minimum_size=}, {self.charging.size.maximum_size=}.' | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix incorrect variable references in error message
The error message references self.charging.size attributes incorrectly in the second part.
raise PlausibilityError(
f'Balancing charging and discharging Flows in {self.label_full} need compatible minimum and maximum sizes.'
f'Got: {self.charging.size.minimum_size=}, {self.charging.size.maximum_size=} and '
- f'{self.charging.size.minimum_size=}, {self.charging.size.maximum_size=}.'
+ f'{self.discharging.size.minimum_size=}, {self.discharging.size.maximum_size=}.'
)📝 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.
| ): | |
| raise PlausibilityError( | |
| f'Balancing charging and discharging Flows in {self.label_full} need compatible minimum and maximum sizes.' | |
| f'Got: {self.charging.size.minimum_size=}, {self.charging.size.maximum_size=} and ' | |
| f'{self.charging.size.minimum_size=}, {self.charging.size.maximum_size=}.' | |
| ) | |
| ): | |
| raise PlausibilityError( | |
| f'Balancing charging and discharging Flows in {self.label_full} need compatible minimum and maximum sizes.' | |
| f'Got: {self.charging.size.minimum_size=}, {self.charging.size.maximum_size=} and ' | |
| f'{self.discharging.size.minimum_size=}, {self.discharging.size.maximum_size=}.' | |
| ) |
🤖 Prompt for AI Agents
In flixopt/components.py around lines 298 to 303, the PlausibilityError message
mistakenly repeats self.charging.size attributes for both parts; change the
second set of attribute references to use self.discharging.size (minimum_size
and maximum_size) so the error message reports the charging and discharging size
values correctly, and keep the f-string formatting consistent.
# Conflicts: # CHANGELOG.md # flixopt/network_app.py
# Conflicts: # CHANGELOG.md # flixopt/network_app.py
|
Closed by #348 |
Bugfix plot_node_balance_pie()
Scenarios/fixes (Scenarios/fixes #252)
BUGFIX missing conversion to TimeSeries
BUGFIX missing conversion to TimeSeries
Bugfix node_balance with flow_hours: Negate correctly
Scenarios/filter (Scenarios/filter #253)
Add containts and startswith to filter_solution
Scenarios/drop suffix (Scenarios/drop suffix #251)
Drop suffixes in plots and add the option to drop suffixes to sanitize_dataset()
Scenarios/bar plot (Scenarios/bar plot #254)
Add stacked bar style to plotting methods
Rename mode to style (line, bar, area, ...)
Bugfix plotting
Fix example_calculation_types.py
Scenarios/fixes (Scenarios/fixes #255)
Fix indexing issue with only one scenario
Bugfix Cooling Tower
Add option for balanced Storage Flows (equalize size of charging and discharging)
Add option for balanced Storage Flows
Change error to warning (non-fixed size with piecewise conversion AND fixed_flow_rate with OnOff)
Bugfix in DataConverter
BUGFIX: Typo (total_max/total_min in Effect)
Bugfix in node_balance() (negating did not work when using flow_hours mode
Scenarios/effects (Scenarios/effects #256)
Add methods to track effect shares of components and Flows
Add option to include flows when retrieving effects
Add properties and methods to store effect results in a dataset
Reorder methods
Rename and improve docs
Bugfix test class name
Fix the Network algorithm to calculate the sum of parallel paths, and be independent on nr of nodes and complexity of the network
Add tests for the newtork chaining and the results of effect shares
Add methods to check for circular references
Add test to check for circular references
Update cycle checker to return the found cycles
Add checks in results to confirm effects are computed correctly
BUGFIX: Remove +1 from prior testing
Add option for grouped bars to plotting.with_plotly() and make lines of stacked bar plots invisible
Reconstruct FlowSystem in CalculationResults on demand. DEPRECATION in CalculationResults
ruff check
Bugfix: save flow_system data, not the flow_system
Update tests
Scenarios/datasets results (Scenarios/datasets results #257)
Use dataarray instead of dataset
Change effects dataset to dataarray and use nan when no share was found
Add method for flow_rates dataset
Add methods to get flow_rates and flow_hours as datasets
Rename the dataarrays to the flow
Preserve index order
Improve filter_edges_dataset()
Simplify _create_flow_rates_dataarray()
Add dataset for sizes of Flows
Extend results structure to contain flows AND start/end infos
Add FlowResults Object
BUGFIX:Typo in _ElementResults.constraints
Add flows to results of Nodes
Simplify dataarray creation and improve FlowResults
Add nice docstrings
Improve filtering of flow results
Improve filtering of flow results. Add attribute of component
Add big dataarray with all variables but indexed
Revert "Add big dataarray with all variables but indexed"
This reverts commit 08cd8a1.
Improve filtering method for coords filter and add error handling for restoring the flow system
Remove unnecessary methods in results .from_json()
Ensure consistent coord ordering in Effects dataarray
Rename get_effects_per_component()
Make effects_per_component() a dataset instead of a dataarray
Improve backwards compatability
ruff check
ruff check
Scenarios/deprecation (Scenarios/deprecation #258)
Deprecate .active_timesteps
Improve logger warning
Starting release notes
Bugfix in plausibility_check: Index 0
Set bargap to 0 in stacked bars
Ensure the size is always properly indexed in results.
ruff check
BUGFIX in extract data, that causes coords in linopy to be incorrect (scalar xarray.DataArrays)
Improve yaml formatting for model documentation (Scenarios/model doc #259)
Make the size/capacity a TimeSeries (Scenarios/fix size #260)
Scenarios/plot network (Scenarios/plot network #262)
Catch bug in plot_network with 2D arrays
Add plot_network() to test_io.py
Update deploy-docs.yaml: Run on Release publishing instead of creation
and
only run for stable releases (vx.y.z)
Bugfix DataConverter and add tests (Fix DataConverter #263)
Fix doc deployment to not publish on non stable releases
Remove unused code
Remove legend placing for better auto placing in plotly
Fix plotly dependency
Improve validation when adding new effects
Moved release notes to CHANGELOG.md
Try to add to_dataset to Elements
Remove TimeSeries
Remove TimeSeries
Rename conversion method to pattern: to_...
Move methods to FlowSystem
Drop nan values across time dimension if present
Allow lists of values to create DataArray
Update resolving of FlowSystem
Simplify TimeSeriesData
Move TImeSeriesData to Structure and simplyfy to inherrit from xarray.DataArray
Adjust IO
Move TimeSeriesData back to core.py and fix Conversion
Adjust IO to account for attrs of DataArrays in a Dataset
Rename transforming and connection methods in FlowSystem
Compacted IO methods
Remove infos()
remove from_dict() and to_dict()
Update str of Interface
Improve str and repr
Improve str and repr
Add docstring
Unify IO stuff in Interface class
Improve test tu utilize eq method
Make Interface class more robust and improve exceptions
Add option to copy Interfaces (And the FlowSystem)
Make a copy of a FLowSytsem that gets reused in a second Calculation
Remove test_timeseries.py
Reorganizing Datatypes
Remove TImeSeries and TimeSeriesCollection entirely
Remove old method
Add option to get structure with stats of dataarrays
Change str method
Remove old methods
remove old imports
Add isel, sel and resample methods to FlowSystem
Remove need for timeseries with extra timestep
Simplify IO of FLowSystem
Remove parameter timesteps from IO
Improve Exceptions and Docstrings
Improve isel sel and resample methods
Change test
Bugfix
Improve
Improve
Add test for Storage Bounds
Add test for Storage Bounds
CHANGELOG.md
ruff check
Improve types
CHANGELOG.md
Bugfix in Storage
Revert changes in example_calculation_types.py
Revert changes in simple_example.py
Add convenient access to Elements in FlowSystem
Get Aggregated Calculation Working
Segmented running with wrong results
Use new persistent FLowSystem to create Calculations upfront
Improve SegmentedCalcualtion
Improve SegmentedCalcualtion
Fix SegmentedResults IO
ruff check
Update example
Updated logger essages to use .label_full instead of .label
Re-add parameters. Use deprecation warning instead
Update changelog
Improve warning message
Merge
Merge
Fit scenario weights to model coords when transforming
Merge
Removing logic between minimum, maximum and fixed size from InvestParameters
Remove selected_timesteps
Improve TypeHints
New property on InvestParameters for min/max/fixed size
Move logic for InvestParameters in Transmission to from Model to Interface
Make transformation of data more hierarchical (Flows after Components)
Add scenario validation
Change Transmission to have a "balanced" attribute. Change Tests accordingly
Improve index validations
rename method in tests
Update DataConverter
Add DataFrame Support back
Add copy() to DataConverter
Update fit_to_model_coords to take a list of coords
Make the DataConverter more universal by accepting a list of coords/dims
Update DataConverter for n-d arrays
Update DataConverter for n-d arrays
Add extra tests for 3-dims
Add FLowSystemDimension Type
Revert some logic about the fit_to_model coords
Adjust FLowSystem IO for scenarios
BUGFIX: Raise Exception instead of logging
Change usage of TimeSeriesData
Adjust logic to handle non scalars
Adjust logic to _resolve_dataarray_reference into separate method
Update IO of FlowSystem
Improve get_coords()
Adjust FlowSystem init for correct IO
Add scenario to sel and isel methods, and dont normalize scenario weights
Improve scenario_weights_handling
Add warning for not scaled weights
Update test_scenarios.py
Improve util method
Add objective to solution dataset.
Update handling of scenario_weights update tests
Ruff check. Fix type hints
Fix type hints and improve None handling
Fix coords in AggregatedCalculation
Improve Error Messages of DataConversion
Allow multi dim data conversion and broadcasting by length
Improve DataConverter to handle multi-dim arrays
Rename methods and remove unused code
Improve DataConverter by better splitting handling per datatype. Series only matches index (for one dim). Numpy matches shape
Add test for error handling
Update scenario example
Fix Handling of TimeSeriesData
Improve DataConverter
Fix resampling of the FlowSystem
Improve Warning Message
Add example that leverages resampling
Add example that leverages resampling adn fixing of Investments
Add flag to Calculation if its modeled
Make flag for connected_and_transformed FLowSystem public
Make Calcualtion Methods return themselfes to make them chainable
Improve example
Improve Unreleased CHANGELOG.md
Add year coord to FlowSystem
Improve dimension handling
Change plotting to use an indexer instead
Change plotting to use an indexer instead
Use tuples to set dimensions in Models
Bugfix in validation logic and test
Improve Errors
Improve weights handling and rescaling if None
Fix typehint
Update Broadcasting in Storage Bounds and improve type hints
Make .get_model_coords() return an actual xr.Coordinates Object
Improve get_coords()
Rename SystemModel to FlowSystemModel
First steps
Improve Feature Patterns
Improve acess to variables via short names
Improve
Add naming options to big_m_binary_bounds()
Fix and improve FLowModeling with Investment
Improve
Tyring to improve the Methods for bounding variables in different scenarios
Improve BoundingPatterns
Improve BoundingPatterns
Improve BoundingPatterns
Fix duration Modeling
Fix On + Size
Fix InvestmentModel
Fix Models
Update constraint names in test
Fix OnOffModel for multiple Flows
Update constraint names in tests
Simplify
Improve handling of vars/cons and models
Revising the basic structure of a class Model
Revising the basic structure of a class Model
Simplify and focus more on own Model class
Update tests
Improve state computation in ModelingUtilities
Improve handling of previous flowrates
Imropove repr and submodel acess
Update access pattern in tests
Fix PiecewiseEffects and StorageModel
Fix StorageModel and Remove PreventSimultaniousUseModel
Fix Aggregation and SegmentedCalculation
Update tests
Loosen precision in tests
Update test_on_hours_computation.py and some types
Rename class Model to Submodel
rename sub_model to submodel everywhere
rename self.model to self.submodel everywhere
Rename .model with .submodel if its only a submodel
Rename .sub_models with .submodels
Improve repr
Improve repr
Include def do_modeling() into init() of models
Make properties private
Improve Inheritance of Models
V3.0.0/plotting (V3.0.0/plotting #285)
Use indexer to reliably plot solutions with and wihtout scenarios/years
ruff check
Improve typehints
Update CHANGELOG.md
Bugfix from renaming to .submodel
Bugfix from renaming to .submodel
Improve indexer in results plotting
rename register_submodel() to .add_submodels() adn add SUbmodels collection class
Add nice repr to FlowSystemModel and Submodel
Bugfix .variables and .constraints
Add type checks to modeling.py
Improve assertion in tests
Improve docstrings and register ElementModels directly in FlowSystemModel
Improve repr()
ruff check
Use new method to compare sets in tests
ruff check
Update Contribute.md, some dependencies and add pre-commit
Pre commit hook
Run Pre-Commit Hook for the first time
Fix link in README.md
Update Effect name in tests to be 'costs' instead of 'Costs' Everywhere Simplify testing by creating a Element Library
Improve some of the modeling and coord handling
Add tests with years and scenarios
Update tests to run with multiple coords
Fix Effects dataset computation in case of empty effects
Update Test for multiple dims Fix Dim order in scaled_bounds_with_state
Bugfix logic in .use_switch_on
Fix test with multiple dims
Fix test with multiple dims
New test
New test for previous flow_rates
V3.0.0/main fit to model coords improve (V3.0.0/main fit to model coords improve #295)
Change fit_to_model_coords to work with a Collection of dims
Improve fit_to_model_coords
Improve CHANGELOG.md
Description
Brief description of the changes in this PR.
Type of Change
Related Issues
Closes #(issue number)
Testing
Checklist
Summary by CodeRabbit
New Features
Breaking Changes
Improvements
Bug Fixes
Documentation