Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
7a822c3
New lower case parameter names for flows in linear_converters.py
FBumann Nov 15, 2025
bcead8a
Improve setting of conversion factors
FBumann Nov 15, 2025
b45618b
Add deprectaed parameter access
FBumann Nov 15, 2025
46f8f6c
Add deprectaed parameter access
FBumann Nov 15, 2025
b1f6f6c
Update CHANGELOG.md
FBumann Nov 15, 2025
59f82cc
Add setters
FBumann Nov 15, 2025
79df1cb
Merge branch 'main' into feature/rename-parameters-linear-converters
FBumann Nov 15, 2025
8a46d03
Merge from main
FBumann Nov 15, 2025
10efff3
Ensure flows are present
FBumann Nov 15, 2025
c7ad0e9
Improve logging
FBumann Nov 15, 2025
c3bb047
Remove special handling for TimeSeriesData
FBumann Nov 15, 2025
633e977
Backward Compatibility for HeatPump and HeatPumpWithSource
FBumann Nov 15, 2025
a048d1b
Renamed eta → thermal_efficiency
FBumann Nov 16, 2025
1c57f83
Rename power_flow to electrical_flow
FBumann Nov 16, 2025
f5d6ebe
Update CHANGELOG.md
FBumann Nov 16, 2025
fe7edbc
Merge remote-tracking branch 'origin/main' into feature/rename-parame…
FBumann Nov 16, 2025
60b2bf6
Update all tests and examples
FBumann Nov 16, 2025
5666470
Update remaining tests
FBumann Nov 16, 2025
8b35f0c
use the explicit thermal_efficiency keyword argument
FBumann Nov 16, 2025
ed051db
Update test to new porperty
FBumann Nov 16, 2025
3ebfeb6
Rename lastValueOfSim to equals_last
FBumann Nov 17, 2025
33e2278
Remove white space
FBumann Nov 17, 2025
34543fc
Fix CHANGELOG.md
FBumann Nov 17, 2025
eafd934
Merge remote-tracking branch 'origin/feature/rename-parameters-linear…
FBumann Nov 17, 2025
71c2c7e
Typo
FBumann Nov 17, 2025
809f20b
Typo
FBumann Nov 17, 2025
7cf22f2
Improve CHANGELOG.md
FBumann Nov 17, 2025
385e260
Merge remote-tracking branch 'origin/main' into feature/rename-parame…
FBumann Nov 18, 2025
2373dea
Update Changelog
FBumann Nov 18, 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
26 changes: 25 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ If upgrading from v2.x, see the [v3.0.0 release notes](https://github.com/flixOp

## [Unreleased] - ????-??-??

**Summary**: Internal architecture improvements to simplify FlowSystem-Element coupling and eliminate circular dependencies.
**Summary**: Renaming parameters in Linear Transformers for readability & Internal architecture improvements to simplify FlowSystem-Element coupling and eliminate circular dependencies. Old parameters till work but emmit warnings.

If upgrading from v2.x, see the [v3.0.0 release notes](https://github.com/flixOpt/flixOpt/releases/tag/v3.0.0) and [Migration Guide](https://flixopt.github.io/flixopt/latest/user-guide/migration-guide-v3/).

Expand All @@ -71,9 +71,33 @@ If upgrading from v2.x, see the [v3.0.0 release notes](https://github.com/flixOp
- **Two-phase modeling pattern within _do_modeling()**: Clarified the pattern where `_do_modeling()` creates nested submodels first (so their variables exist), then creates constraints that reference those variables - eliminates circular dependencies in Submodel architecture
- **Improved cache invalidation**: Cache invalidation in `add_elements()` now happens once after all additions rather than per element
- **Better logging**: Centralized element registration logging to show element type and full label
- **Parameter renaming in `linear_converters.py`**: Renamed parameters to use lowercase, descriptive names for better consistency and clarity:
- **Flow parameters** (deprecated uppercase abbreviations → descriptive names):
- `Boiler`: `Q_fu` → `fuel_flow`, `Q_th` → `thermal_flow`
- `Power2Heat`: `P_el` → `electrical_flow`, `Q_th` → `thermal_flow`
- `HeatPump`: `COP` → `cop`, `P_el` → `electrical_flow`, `Q_th` → `thermal_flow`
- `CoolingTower`: `P_el` → `electrical_flow`, `Q_th` → `thermal_flow`
- `CHP`: `Q_fu` → `fuel_flow`, `P_el` → `electrical_flow`, `Q_th` → `thermal_flow`
- `HeatPumpWithSource`: `COP` → `cop`, `P_el` → `electrical_flow`, `Q_ab` → `heat_source_flow`, `Q_th` → `thermal_flow`
- **Efficiency parameters** (abbreviated → descriptive names):
- `Boiler`: `eta` → `thermal_efficiency`
- `Power2Heat`: `eta` → `thermal_efficiency`
- `CHP`: `eta_th` → `thermal_efficiency`, `eta_el` → `electrical_efficiency`
- `HetaPump`: `COP` → `cop`
- `HetaPumpWithSource`: `COP` → `cop`
- **Storage Parameters**:
- `Storage`: `initial_charge_state="lastValueOfSim"` → `initial_charge_state="equals_last"`

### 🗑️ Deprecated
- **Old parameter names in `linear_converters.py`**: The following parameter names are now deprecated and accessible as properties/kwargs that emit `DeprecationWarning`. They will be removed in v4.0.0:
- **Flow parameters**: `Q_fu`, `Q_th`, `P_el`, `Q_ab` (use `fuel_flow`, `thermal_flow`, `electrical_flow`, `heat_source_flow` instead)
- **Efficiency parameters**: `eta`, `eta_th`, `eta_el` (use `thermal_efficiency`, `electrical_efficiency` instead)
- **COP parameter**: `COP` (use lowercase `cop` instead)
- **Storage Parameter**: `Storage`: `initial_charge_state="lastValueOfSim"` (use `initial_charge_state="equals_last"`)

### 🐛 Fixed
- Fixed inconsistent argument passing in `_fit_effect_coords()` - standardized all calls to use named arguments (`prefix=`, `effect_values=`, `suffix=`) instead of mix of positional and named arguments
- Fixed `check_bounds` function in `linear_converters.py` to normalize array inputs before comparisons, ensuring correct boundary checks with DataFrames, Series, and other array-like types

### 👷 Development
- **Eliminated circular dependencies**: Implemented two-phase modeling pattern within `_do_modeling()` where nested submodels are created first (creating their variables), then constraints are created that can safely reference those submodel variables
Expand Down
6 changes: 3 additions & 3 deletions examples/00_Minmal/minimal_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
fx.Effect('Costs', '€', 'Cost', is_standard=True, is_objective=True),
fx.linear_converters.Boiler(
'Boiler',
eta=0.5,
Q_th=fx.Flow(label='Heat', bus='Heat', size=50),
Q_fu=fx.Flow(label='Gas', bus='Gas'),
thermal_efficiency=0.5,
thermal_flow=fx.Flow(label='Heat', bus='Heat', size=50),
fuel_flow=fx.Flow(label='Gas', bus='Gas'),
),
fx.Sink(
'Sink',
Expand Down
16 changes: 8 additions & 8 deletions examples/01_Simple/simple_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,19 @@
# Boiler: Converts fuel (gas) into thermal energy (heat)
boiler = fx.linear_converters.Boiler(
label='Boiler',
eta=0.5,
Q_th=fx.Flow(label='Q_th', bus='Fernwärme', size=50, relative_minimum=0.1, relative_maximum=1),
Q_fu=fx.Flow(label='Q_fu', bus='Gas'),
thermal_efficiency=0.5,
thermal_flow=fx.Flow(label='Q_th', bus='Fernwärme', size=50, relative_minimum=0.1, relative_maximum=1),
fuel_flow=fx.Flow(label='Q_fu', bus='Gas'),
)

# Combined Heat and Power (CHP): Generates both electricity and heat from fuel
chp = fx.linear_converters.CHP(
label='CHP',
eta_th=0.5,
eta_el=0.4,
P_el=fx.Flow('P_el', bus='Strom', size=60, relative_minimum=5 / 60),
Q_th=fx.Flow('Q_th', bus='Fernwärme'),
Q_fu=fx.Flow('Q_fu', bus='Gas'),
thermal_efficiency=0.5,
electrical_efficiency=0.4,
electrical_flow=fx.Flow('P_el', bus='Strom', size=60, relative_minimum=5 / 60),
thermal_flow=fx.Flow('Q_th', bus='Fernwärme'),
fuel_flow=fx.Flow('Q_fu', bus='Gas'),
)

# Storage: Energy storage system with charging and discharging capabilities
Expand Down
16 changes: 8 additions & 8 deletions examples/02_Complex/complex_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,11 @@
# A gas boiler that converts fuel into thermal output, with investment and on-off parameters
Gaskessel = fx.linear_converters.Boiler(
'Kessel',
eta=0.5, # Efficiency ratio
thermal_efficiency=0.5, # Efficiency ratio
on_off_parameters=fx.OnOffParameters(
effects_per_running_hour={Costs.label: 0, CO2.label: 1000}
), # CO2 emissions per hour
Q_th=fx.Flow(
thermal_flow=fx.Flow(
label='Q_th', # Thermal output
bus='Fernwärme', # Linked bus
size=fx.InvestParameters(
Expand All @@ -79,19 +79,19 @@
switch_on_total_max=1000, # Max number of starts
),
),
Q_fu=fx.Flow(label='Q_fu', bus='Gas', size=200),
fuel_flow=fx.Flow(label='Q_fu', bus='Gas', size=200),
)

# 2. Define CHP Unit
# Combined Heat and Power unit that generates both electricity and heat from fuel
bhkw = fx.linear_converters.CHP(
'BHKW2',
eta_th=0.5,
eta_el=0.4,
thermal_efficiency=0.5,
electrical_efficiency=0.4,
on_off_parameters=fx.OnOffParameters(effects_per_switch_on=0.01),
P_el=fx.Flow('P_el', bus='Strom', size=60, relative_minimum=5 / 60),
Q_th=fx.Flow('Q_th', bus='Fernwärme', size=1e3),
Q_fu=fx.Flow('Q_fu', bus='Gas', size=1e3, previous_flow_rate=20), # The CHP was ON previously
electrical_flow=fx.Flow('P_el', bus='Strom', size=60, relative_minimum=5 / 60),
thermal_flow=fx.Flow('Q_th', bus='Fernwärme', size=1e3),
fuel_flow=fx.Flow('Q_fu', bus='Gas', size=1e3, previous_flow_rate=20), # The CHP was ON previously
)

# 3. Define CHP with Piecewise Conversion
Expand Down
16 changes: 8 additions & 8 deletions examples/03_Calculation_types/example_calculation_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@
# 1. Boiler
a_gaskessel = fx.linear_converters.Boiler(
'Kessel',
eta=0.85,
Q_th=fx.Flow(label='Q_th', bus='Fernwärme'),
Q_fu=fx.Flow(
thermal_efficiency=0.85,
thermal_flow=fx.Flow(label='Q_th', bus='Fernwärme'),
fuel_flow=fx.Flow(
label='Q_fu',
bus='Gas',
size=95,
Expand All @@ -86,12 +86,12 @@
# 2. CHP
a_kwk = fx.linear_converters.CHP(
'BHKW2',
eta_th=0.58,
eta_el=0.22,
thermal_efficiency=0.58,
electrical_efficiency=0.22,
on_off_parameters=fx.OnOffParameters(effects_per_switch_on=24000),
P_el=fx.Flow('P_el', bus='Strom', size=200),
Q_th=fx.Flow('Q_th', bus='Fernwärme', size=200),
Q_fu=fx.Flow('Q_fu', bus='Kohle', size=288, relative_minimum=87 / 288, previous_flow_rate=100),
electrical_flow=fx.Flow('P_el', bus='Strom', size=200),
thermal_flow=fx.Flow('Q_th', bus='Fernwärme', size=200),
fuel_flow=fx.Flow('Q_fu', bus='Kohle', size=288, relative_minimum=87 / 288, previous_flow_rate=100),
)

# 3. Storage
Expand Down
18 changes: 10 additions & 8 deletions examples/04_Scenarios/scenario_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,27 +114,29 @@
# Modern condensing gas boiler with realistic efficiency
boiler = fx.linear_converters.Boiler(
label='Boiler',
eta=0.92, # Realistic efficiency for modern condensing gas boiler (92%)
Q_th=fx.Flow(
thermal_efficiency=0.92, # Realistic efficiency for modern condensing gas boiler (92%)
thermal_flow=fx.Flow(
label='Q_th',
bus='Fernwärme',
size=50,
relative_minimum=0.1,
relative_maximum=1,
on_off_parameters=fx.OnOffParameters(),
),
Q_fu=fx.Flow(label='Q_fu', bus='Gas'),
fuel_flow=fx.Flow(label='Q_fu', bus='Gas'),
)

# Combined Heat and Power (CHP): Generates both electricity and heat from fuel
# Modern CHP unit with realistic efficiencies (total efficiency ~88%)
chp = fx.linear_converters.CHP(
label='CHP',
eta_th=0.48, # Realistic thermal efficiency (48%)
eta_el=0.40, # Realistic electrical efficiency (40%)
P_el=fx.Flow('P_el', bus='Strom', size=60, relative_minimum=5 / 60, on_off_parameters=fx.OnOffParameters()),
Q_th=fx.Flow('Q_th', bus='Fernwärme'),
Q_fu=fx.Flow('Q_fu', bus='Gas'),
thermal_efficiency=0.48, # Realistic thermal efficiency (48%)
electrical_efficiency=0.40, # Realistic electrical efficiency (40%)
electrical_flow=fx.Flow(
'P_el', bus='Strom', size=60, relative_minimum=5 / 60, on_off_parameters=fx.OnOffParameters()
),
thermal_flow=fx.Flow('Q_th', bus='Fernwärme'),
fuel_flow=fx.Flow('Q_fu', bus='Gas'),
)

# Storage: Thermal energy storage system with charging and discharging capabilities
Expand Down
18 changes: 9 additions & 9 deletions examples/05_Two-stage-optimization/two_stage_optimization.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@
fx.Effect('PE', 'kWh_PE', 'Primärenergie'),
fx.linear_converters.Boiler(
'Kessel',
eta=0.85,
Q_th=fx.Flow(label='Q_th', bus='Fernwärme'),
Q_fu=fx.Flow(
thermal_efficiency=0.85,
thermal_flow=fx.Flow(label='Q_th', bus='Fernwärme'),
fuel_flow=fx.Flow(
label='Q_fu',
bus='Gas',
size=fx.InvestParameters(
Expand All @@ -60,14 +60,14 @@
),
fx.linear_converters.CHP(
'BHKW2',
eta_th=0.58,
eta_el=0.22,
thermal_efficiency=0.58,
electrical_efficiency=0.22,
on_off_parameters=fx.OnOffParameters(
effects_per_switch_on=1_000, consecutive_on_hours_min=10, consecutive_off_hours_min=10
),
P_el=fx.Flow('P_el', bus='Strom'),
Q_th=fx.Flow('Q_th', bus='Fernwärme'),
Q_fu=fx.Flow(
electrical_flow=fx.Flow('P_el', bus='Strom'),
thermal_flow=fx.Flow('Q_th', bus='Fernwärme'),
fuel_flow=fx.Flow(
'Q_fu',
bus='Kohle',
size=fx.InvestParameters(
Expand All @@ -82,7 +82,7 @@
capacity_in_flow_hours=fx.InvestParameters(
minimum_size=10, maximum_size=1000, effects_of_investment_per_size={'costs': 60}
),
initial_charge_state='lastValueOfSim',
initial_charge_state='equals_final',
eta_charge=1,
eta_discharge=1,
relative_loss_per_hour=0.001,
Expand Down
24 changes: 15 additions & 9 deletions flixopt/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ class Storage(Component):
Scalar for fixed size or InvestParameters for optimization.
relative_minimum_charge_state: Minimum charge state (0-1). Default: 0.
relative_maximum_charge_state: Maximum charge state (0-1). Default: 1.
initial_charge_state: Charge at start. Numeric or 'lastValueOfSim'. Default: 0.
initial_charge_state: Charge at start. Numeric or 'equals_final'. Default: 0.
minimal_final_charge_state: Minimum absolute charge required at end (optional).
maximal_final_charge_state: Maximum absolute charge allowed at end (optional).
relative_minimum_final_charge_state: Minimum relative charge at end.
Expand Down Expand Up @@ -345,7 +345,7 @@ class Storage(Component):
),
eta_charge=0.85, # Pumping efficiency
eta_discharge=0.90, # Turbine efficiency
initial_charge_state='lastValueOfSim', # Ensuring no deficit compared to start
initial_charge_state='equals_final', # Ensuring no deficit compared to start
relative_loss_per_hour=0.0001, # Minimal evaporation
)
```
Expand Down Expand Up @@ -394,7 +394,7 @@ def __init__(
capacity_in_flow_hours: Numeric_PS | InvestParameters,
relative_minimum_charge_state: Numeric_TPS = 0,
relative_maximum_charge_state: Numeric_TPS = 1,
initial_charge_state: Numeric_PS | Literal['lastValueOfSim'] = 0,
initial_charge_state: Numeric_PS | Literal['equals_final'] = 0,
minimal_final_charge_state: Numeric_PS | None = None,
maximal_final_charge_state: Numeric_PS | None = None,
relative_minimum_final_charge_state: Numeric_PS | None = None,
Expand All @@ -414,6 +414,13 @@ def __init__(
prevent_simultaneous_flows=[charging, discharging] if prevent_simultaneous_charge_and_discharge else None,
meta_data=meta_data,
)
if isinstance(initial_charge_state, str) and initial_charge_state == 'lastValueOfSim':
warnings.warn(
f'{initial_charge_state=} is deprecated. Use "equals_final" instead.',
DeprecationWarning,
stacklevel=2,
)
initial_charge_state = 'equals_final'

self.charging = charging
self.discharging = discharging
Expand Down Expand Up @@ -491,12 +498,11 @@ def _plausibility_checks(self) -> None:
super()._plausibility_checks()

# Validate string values and set flag
initial_is_last = False
initial_equals_final = False
if isinstance(self.initial_charge_state, str):
if self.initial_charge_state == 'lastValueOfSim':
initial_is_last = True
else:
if not self.initial_charge_state == 'equals_final':
raise PlausibilityError(f'initial_charge_state has undefined value: {self.initial_charge_state}')
initial_equals_final = True

# Use new InvestParameters methods to get capacity bounds
if isinstance(self.capacity_in_flow_hours, InvestParameters):
Expand All @@ -510,8 +516,8 @@ def _plausibility_checks(self) -> None:
minimum_initial_capacity = maximum_capacity * self.relative_minimum_charge_state.isel(time=0)
maximum_initial_capacity = minimum_capacity * self.relative_maximum_charge_state.isel(time=0)

# Only perform numeric comparisons if not using 'lastValueOfSim'
if not initial_is_last:
# Only perform numeric comparisons if not using 'equals_final'
if not initial_equals_final:
if (self.initial_charge_state > maximum_initial_capacity).any():
raise PlausibilityError(
f'{self.label_full}: {self.initial_charge_state=} '
Expand Down
Loading