Skip to content

Commit 351751a

Browse files
authored
Feature/rename parameters linear converters (#468)
* New lower case parameter names for flows in linear_converters.py * Improve setting of conversion factors * Add deprectaed parameter access * Add deprectaed parameter access * Update CHANGELOG.md * Add setters * Merge from main * Ensure flows are present * Improve logging * Remove special handling for TimeSeriesData * Backward Compatibility for HeatPump and HeatPumpWithSource Robust Type Handling in check_bounds * Renamed eta → thermal_efficiency Renamed eta_th → thermal_efficiency Renamed eta_el → electrical_efficiency - Fixed to use value_arr for comparisons instead of value * Rename power_flow to electrical_flow * Update CHANGELOG.md * Update all tests and examples * Update remaining tests * use the explicit thermal_efficiency keyword argument * Update test to new porperty * Rename lastValueOfSim to equals_last * Remove white space * Fix CHANGELOG.md * Typo * Typo * Improve CHANGELOG.md * Update Changelog
1 parent 3945200 commit 351751a

17 files changed

Lines changed: 877 additions & 366 deletions

CHANGELOG.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ If upgrading from v2.x, see the [v3.0.0 release notes](https://github.com/flixOp
5151
5252
## [Unreleased] - ????-??-??
5353
54-
**Summary**: Internal architecture improvements to simplify FlowSystem-Element coupling and eliminate circular dependencies.
54+
**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.
5555
5656
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/).
5757
@@ -71,9 +71,33 @@ If upgrading from v2.x, see the [v3.0.0 release notes](https://github.com/flixOp
7171
- **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
7272
- **Improved cache invalidation**: Cache invalidation in `add_elements()` now happens once after all additions rather than per element
7373
- **Better logging**: Centralized element registration logging to show element type and full label
74+
- **Parameter renaming in `linear_converters.py`**: Renamed parameters to use lowercase, descriptive names for better consistency and clarity:
75+
- **Flow parameters** (deprecated uppercase abbreviations → descriptive names):
76+
- `Boiler`: `Q_fu` → `fuel_flow`, `Q_th` → `thermal_flow`
77+
- `Power2Heat`: `P_el` → `electrical_flow`, `Q_th` → `thermal_flow`
78+
- `HeatPump`: `COP` → `cop`, `P_el` → `electrical_flow`, `Q_th` → `thermal_flow`
79+
- `CoolingTower`: `P_el` → `electrical_flow`, `Q_th` → `thermal_flow`
80+
- `CHP`: `Q_fu` → `fuel_flow`, `P_el` → `electrical_flow`, `Q_th` → `thermal_flow`
81+
- `HeatPumpWithSource`: `COP` → `cop`, `P_el` → `electrical_flow`, `Q_ab` → `heat_source_flow`, `Q_th` → `thermal_flow`
82+
- **Efficiency parameters** (abbreviated → descriptive names):
83+
- `Boiler`: `eta` → `thermal_efficiency`
84+
- `Power2Heat`: `eta` → `thermal_efficiency`
85+
- `CHP`: `eta_th` → `thermal_efficiency`, `eta_el` → `electrical_efficiency`
86+
- `HetaPump`: `COP` → `cop`
87+
- `HetaPumpWithSource`: `COP` → `cop`
88+
- **Storage Parameters**:
89+
- `Storage`: `initial_charge_state="lastValueOfSim"` → `initial_charge_state="equals_last"`
90+
91+
### 🗑️ Deprecated
92+
- **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:
93+
- **Flow parameters**: `Q_fu`, `Q_th`, `P_el`, `Q_ab` (use `fuel_flow`, `thermal_flow`, `electrical_flow`, `heat_source_flow` instead)
94+
- **Efficiency parameters**: `eta`, `eta_th`, `eta_el` (use `thermal_efficiency`, `electrical_efficiency` instead)
95+
- **COP parameter**: `COP` (use lowercase `cop` instead)
96+
- **Storage Parameter**: `Storage`: `initial_charge_state="lastValueOfSim"` (use `initial_charge_state="equals_last"`)
7497
7598
### 🐛 Fixed
7699
- 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
100+
- 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
77101
78102
### 👷 Development
79103
- **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

examples/00_Minmal/minimal_example.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
1818
fx.Effect('Costs', '€', 'Cost', is_standard=True, is_objective=True),
1919
fx.linear_converters.Boiler(
2020
'Boiler',
21-
eta=0.5,
22-
Q_th=fx.Flow(label='Heat', bus='Heat', size=50),
23-
Q_fu=fx.Flow(label='Gas', bus='Gas'),
21+
thermal_efficiency=0.5,
22+
thermal_flow=fx.Flow(label='Heat', bus='Heat', size=50),
23+
fuel_flow=fx.Flow(label='Gas', bus='Gas'),
2424
),
2525
fx.Sink(
2626
'Sink',

examples/01_Simple/simple_example.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,19 +46,19 @@
4646
# Boiler: Converts fuel (gas) into thermal energy (heat)
4747
boiler = fx.linear_converters.Boiler(
4848
label='Boiler',
49-
eta=0.5,
50-
Q_th=fx.Flow(label='Q_th', bus='Fernwärme', size=50, relative_minimum=0.1, relative_maximum=1),
51-
Q_fu=fx.Flow(label='Q_fu', bus='Gas'),
49+
thermal_efficiency=0.5,
50+
thermal_flow=fx.Flow(label='Q_th', bus='Fernwärme', size=50, relative_minimum=0.1, relative_maximum=1),
51+
fuel_flow=fx.Flow(label='Q_fu', bus='Gas'),
5252
)
5353

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

6464
# Storage: Energy storage system with charging and discharging capabilities

examples/02_Complex/complex_example.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,11 @@
5050
# A gas boiler that converts fuel into thermal output, with investment and on-off parameters
5151
Gaskessel = fx.linear_converters.Boiler(
5252
'Kessel',
53-
eta=0.5, # Efficiency ratio
53+
thermal_efficiency=0.5, # Efficiency ratio
5454
on_off_parameters=fx.OnOffParameters(
5555
effects_per_running_hour={Costs.label: 0, CO2.label: 1000}
5656
), # CO2 emissions per hour
57-
Q_th=fx.Flow(
57+
thermal_flow=fx.Flow(
5858
label='Q_th', # Thermal output
5959
bus='Fernwärme', # Linked bus
6060
size=fx.InvestParameters(
@@ -79,19 +79,19 @@
7979
switch_on_total_max=1000, # Max number of starts
8080
),
8181
),
82-
Q_fu=fx.Flow(label='Q_fu', bus='Gas', size=200),
82+
fuel_flow=fx.Flow(label='Q_fu', bus='Gas', size=200),
8383
)
8484

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

9797
# 3. Define CHP with Piecewise Conversion

examples/03_Calculation_types/example_calculation_types.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@
7171
# 1. Boiler
7272
a_gaskessel = fx.linear_converters.Boiler(
7373
'Kessel',
74-
eta=0.85,
75-
Q_th=fx.Flow(label='Q_th', bus='Fernwärme'),
76-
Q_fu=fx.Flow(
74+
thermal_efficiency=0.85,
75+
thermal_flow=fx.Flow(label='Q_th', bus='Fernwärme'),
76+
fuel_flow=fx.Flow(
7777
label='Q_fu',
7878
bus='Gas',
7979
size=95,
@@ -86,12 +86,12 @@
8686
# 2. CHP
8787
a_kwk = fx.linear_converters.CHP(
8888
'BHKW2',
89-
eta_th=0.58,
90-
eta_el=0.22,
89+
thermal_efficiency=0.58,
90+
electrical_efficiency=0.22,
9191
on_off_parameters=fx.OnOffParameters(effects_per_switch_on=24000),
92-
P_el=fx.Flow('P_el', bus='Strom', size=200),
93-
Q_th=fx.Flow('Q_th', bus='Fernwärme', size=200),
94-
Q_fu=fx.Flow('Q_fu', bus='Kohle', size=288, relative_minimum=87 / 288, previous_flow_rate=100),
92+
electrical_flow=fx.Flow('P_el', bus='Strom', size=200),
93+
thermal_flow=fx.Flow('Q_th', bus='Fernwärme', size=200),
94+
fuel_flow=fx.Flow('Q_fu', bus='Kohle', size=288, relative_minimum=87 / 288, previous_flow_rate=100),
9595
)
9696

9797
# 3. Storage

examples/04_Scenarios/scenario_example.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -114,27 +114,29 @@
114114
# Modern condensing gas boiler with realistic efficiency
115115
boiler = fx.linear_converters.Boiler(
116116
label='Boiler',
117-
eta=0.92, # Realistic efficiency for modern condensing gas boiler (92%)
118-
Q_th=fx.Flow(
117+
thermal_efficiency=0.92, # Realistic efficiency for modern condensing gas boiler (92%)
118+
thermal_flow=fx.Flow(
119119
label='Q_th',
120120
bus='Fernwärme',
121121
size=50,
122122
relative_minimum=0.1,
123123
relative_maximum=1,
124124
on_off_parameters=fx.OnOffParameters(),
125125
),
126-
Q_fu=fx.Flow(label='Q_fu', bus='Gas'),
126+
fuel_flow=fx.Flow(label='Q_fu', bus='Gas'),
127127
)
128128

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

140142
# Storage: Thermal energy storage system with charging and discharging capabilities

examples/05_Two-stage-optimization/two_stage_optimization.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,9 @@
4545
fx.Effect('PE', 'kWh_PE', 'Primärenergie'),
4646
fx.linear_converters.Boiler(
4747
'Kessel',
48-
eta=0.85,
49-
Q_th=fx.Flow(label='Q_th', bus='Fernwärme'),
50-
Q_fu=fx.Flow(
48+
thermal_efficiency=0.85,
49+
thermal_flow=fx.Flow(label='Q_th', bus='Fernwärme'),
50+
fuel_flow=fx.Flow(
5151
label='Q_fu',
5252
bus='Gas',
5353
size=fx.InvestParameters(
@@ -60,14 +60,14 @@
6060
),
6161
fx.linear_converters.CHP(
6262
'BHKW2',
63-
eta_th=0.58,
64-
eta_el=0.22,
63+
thermal_efficiency=0.58,
64+
electrical_efficiency=0.22,
6565
on_off_parameters=fx.OnOffParameters(
6666
effects_per_switch_on=1_000, consecutive_on_hours_min=10, consecutive_off_hours_min=10
6767
),
68-
P_el=fx.Flow('P_el', bus='Strom'),
69-
Q_th=fx.Flow('Q_th', bus='Fernwärme'),
70-
Q_fu=fx.Flow(
68+
electrical_flow=fx.Flow('P_el', bus='Strom'),
69+
thermal_flow=fx.Flow('Q_th', bus='Fernwärme'),
70+
fuel_flow=fx.Flow(
7171
'Q_fu',
7272
bus='Kohle',
7373
size=fx.InvestParameters(
@@ -82,7 +82,7 @@
8282
capacity_in_flow_hours=fx.InvestParameters(
8383
minimum_size=10, maximum_size=1000, effects_of_investment_per_size={'costs': 60}
8484
),
85-
initial_charge_state='lastValueOfSim',
85+
initial_charge_state='equals_final',
8686
eta_charge=1,
8787
eta_discharge=1,
8888
relative_loss_per_hour=0.001,

flixopt/components.py

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ class Storage(Component):
281281
Scalar for fixed size or InvestParameters for optimization.
282282
relative_minimum_charge_state: Minimum charge state (0-1). Default: 0.
283283
relative_maximum_charge_state: Maximum charge state (0-1). Default: 1.
284-
initial_charge_state: Charge at start. Numeric or 'lastValueOfSim'. Default: 0.
284+
initial_charge_state: Charge at start. Numeric or 'equals_final'. Default: 0.
285285
minimal_final_charge_state: Minimum absolute charge required at end (optional).
286286
maximal_final_charge_state: Maximum absolute charge allowed at end (optional).
287287
relative_minimum_final_charge_state: Minimum relative charge at end.
@@ -345,7 +345,7 @@ class Storage(Component):
345345
),
346346
eta_charge=0.85, # Pumping efficiency
347347
eta_discharge=0.90, # Turbine efficiency
348-
initial_charge_state='lastValueOfSim', # Ensuring no deficit compared to start
348+
initial_charge_state='equals_final', # Ensuring no deficit compared to start
349349
relative_loss_per_hour=0.0001, # Minimal evaporation
350350
)
351351
```
@@ -394,7 +394,7 @@ def __init__(
394394
capacity_in_flow_hours: Numeric_PS | InvestParameters,
395395
relative_minimum_charge_state: Numeric_TPS = 0,
396396
relative_maximum_charge_state: Numeric_TPS = 1,
397-
initial_charge_state: Numeric_PS | Literal['lastValueOfSim'] = 0,
397+
initial_charge_state: Numeric_PS | Literal['equals_final'] = 0,
398398
minimal_final_charge_state: Numeric_PS | None = None,
399399
maximal_final_charge_state: Numeric_PS | None = None,
400400
relative_minimum_final_charge_state: Numeric_PS | None = None,
@@ -414,6 +414,13 @@ def __init__(
414414
prevent_simultaneous_flows=[charging, discharging] if prevent_simultaneous_charge_and_discharge else None,
415415
meta_data=meta_data,
416416
)
417+
if isinstance(initial_charge_state, str) and initial_charge_state == 'lastValueOfSim':
418+
warnings.warn(
419+
f'{initial_charge_state=} is deprecated. Use "equals_final" instead.',
420+
DeprecationWarning,
421+
stacklevel=2,
422+
)
423+
initial_charge_state = 'equals_final'
417424

418425
self.charging = charging
419426
self.discharging = discharging
@@ -491,12 +498,11 @@ def _plausibility_checks(self) -> None:
491498
super()._plausibility_checks()
492499

493500
# Validate string values and set flag
494-
initial_is_last = False
501+
initial_equals_final = False
495502
if isinstance(self.initial_charge_state, str):
496-
if self.initial_charge_state == 'lastValueOfSim':
497-
initial_is_last = True
498-
else:
503+
if not self.initial_charge_state == 'equals_final':
499504
raise PlausibilityError(f'initial_charge_state has undefined value: {self.initial_charge_state}')
505+
initial_equals_final = True
500506

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

513-
# Only perform numeric comparisons if not using 'lastValueOfSim'
514-
if not initial_is_last:
519+
# Only perform numeric comparisons if not using 'equals_final'
520+
if not initial_equals_final:
515521
if (self.initial_charge_state > maximum_initial_capacity).any():
516522
raise PlausibilityError(
517523
f'{self.label_full}: {self.initial_charge_state=} '

0 commit comments

Comments
 (0)