From 34e4fddb18689ff5371a230e6cb2043c8160343b Mon Sep 17 00:00:00 2001 From: hannesdiedrich Date: Tue, 14 Jan 2025 11:09:22 +0100 Subject: [PATCH] GSYE-835: Adapt TankEnergyParameters.get_min_energy_consumption so the storage temperature can drop to its mininum --- .../energy_parameters/heatpump/tank.py | 18 +++++++++-- .../models/strategy/state/heat_pump_state.py | 8 +++++ .../energy_parameters/test_heat_pump.py | 31 +++++++++++++++++-- .../test_tank_energy_parameters.py | 2 +- 4 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/gsy_e/models/strategy/energy_parameters/heatpump/tank.py b/src/gsy_e/models/strategy/energy_parameters/heatpump/tank.py index d141390f6..9723e47fb 100644 --- a/src/gsy_e/models/strategy/energy_parameters/heatpump/tank.py +++ b/src/gsy_e/models/strategy/energy_parameters/heatpump/tank.py @@ -79,8 +79,22 @@ def get_max_energy_consumption(self, cop: float, time_slot: DateTime): return max_temp_diff * self._Q_specific / cop def get_min_energy_consumption(self, cop: float, time_slot: DateTime): - """Calculate min energy consumption that a heatpump with provided COP can consume.""" - return self._state.get_temp_decrease_K(time_slot) * self._Q_specific / cop + """ + Calculate min energy consumption that a heatpump with provided COP has to consume in + order to only let the storage drop its temperature to the minimum storage temperature. + - if current_temp < min_storage_temp: charge till min_storage_temp is reached + - if current_temp = min_storage_temp: only for the demanded energy + - if current_temp > min_storage: only trade for the demand minus the heat + that can be extracted from the storage + """ + diff_to_min_temp_C = self._state.get_current_diff_to_min_temp_K(time_slot) + temp_diff_due_to_consumption = self._state.get_temp_decrease_K(time_slot) + min_temp_diff = ( + temp_diff_due_to_consumption - diff_to_min_temp_C + if diff_to_min_temp_C <= temp_diff_due_to_consumption + else 0 + ) + return min_temp_diff * self._Q_specific / cop def current_tank_temperature(self, time_slot: DateTime) -> float: """Get current tank temperature for timeslot.""" diff --git a/src/gsy_e/models/strategy/state/heat_pump_state.py b/src/gsy_e/models/strategy/state/heat_pump_state.py index 63470181d..82e158ff3 100644 --- a/src/gsy_e/models/strategy/state/heat_pump_state.py +++ b/src/gsy_e/models/strategy/state/heat_pump_state.py @@ -66,6 +66,14 @@ def get_temp_decrease_K(self, time_slot: DateTime) -> float: """Return the temperature decrease for a given time slot.""" return self._temp_decrease_K.get(time_slot, 0) + def get_current_diff_to_min_temp_K(self, time_slot: DateTime) -> float: + """ + Return the temperature difference between the current storage temp and the minimum + storage temperature + """ + min_temp_decrease_K = self.get_storage_temp_C(time_slot) - self._min_storage_temp_C + return min_temp_decrease_K + def get_temp_increase_K(self, time_slot: DateTime) -> float: """Return the temperature increase for a given time slot.""" return self._temp_increase_K.get(time_slot, 0) diff --git a/tests/strategies/energy_parameters/test_heat_pump.py b/tests/strategies/energy_parameters/test_heat_pump.py index 2d0169678..13f85f270 100644 --- a/tests/strategies/energy_parameters/test_heat_pump.py +++ b/tests/strategies/energy_parameters/test_heat_pump.py @@ -110,7 +110,9 @@ def test_event_market_cycle_populates_state(energy_params): energy_params.event_market_cycle(CURRENT_MARKET_SLOT) assert isclose(tank_state._temp_decrease_K[CURRENT_MARKET_SLOT], 56.4, abs_tol=1e-3) assert tank_state._storage_temp_C[CURRENT_MARKET_SLOT] == 20 - assert isclose(heatpump_state._min_energy_demand_kWh[CURRENT_MARKET_SLOT], 5, abs_tol=1e-3) + assert isclose( + heatpump_state._min_energy_demand_kWh[CURRENT_MARKET_SLOT], 4.113, abs_tol=1e-3 + ) assert isclose( heatpump_state._max_energy_demand_kWh[CURRENT_MARKET_SLOT], 8.546, abs_tol=1e-3 ) @@ -141,11 +143,34 @@ def test_event_traded_energy_updates_temp_increase(energy_params): assert isclose(tank_state._temp_increase_K[CURRENT_MARKET_SLOT], 1.1280172413793106) @staticmethod - def test_get_min_energy_demand_kWh_returns_correct_value(energy_params): + @pytest.mark.parametrize( + "current_temp, expected_demand", + [ + [10, 2], # storage too cold, charging with _max_energy_consumption_kWh reached + [20, 1.739], # storage too cold, charging + [30, 0.58], # storage at min temp, only trade for heat demand + [32, 0.348], # storage does not need to be charged, can drop to min + [35, 0.0], # temp decrease due to demand is equal to drop to min, do not trade + [37, 0.0], # temp decrease due to demand is higher than the drop to min, do not trade + ], + ) + def test_get_min_energy_demand_kWh_returns_correct_value( + energy_params, current_temp, expected_demand + ): + energy_params._max_energy_consumption_kWh = 2 + temp_decrease_consumption = 5 + energy_params._state.heatpump.get_cop = Mock(return_value=5) + for tank_states in energy_params._state.tanks._tanks_energy_parameters: + tank_states._state._min_storage_temp_C = 30 + tank_states._state.get_storage_temp_C = Mock(return_value=current_temp) + tank_states._state.get_temp_decrease_K = Mock(return_value=temp_decrease_consumption) energy_params.event_market_cycle(CURRENT_MARKET_SLOT) assert isclose( - energy_params.get_min_energy_demand_kWh(CURRENT_MARKET_SLOT), 5, abs_tol=1e-3 + energy_params.get_min_energy_demand_kWh(CURRENT_MARKET_SLOT), + expected_demand, + abs_tol=1e-3, ) + # assert False @staticmethod def test_get_max_energy_demand_kWh_returns_correct_value(energy_params): diff --git a/tests/strategies/energy_parameters/test_tank_energy_parameters.py b/tests/strategies/energy_parameters/test_tank_energy_parameters.py index c970ea8a7..f4d0f9167 100644 --- a/tests/strategies/energy_parameters/test_tank_energy_parameters.py +++ b/tests/strategies/energy_parameters/test_tank_energy_parameters.py @@ -80,7 +80,7 @@ def test_get_max_energy_consumption(self, cop): def test_get_min_energy_consumption(self, cop): self._tanks.decrease_tanks_temp_from_heat_energy(2000, self._datetime) min_energy_consumption = self._tanks.get_min_energy_consumption(cop, self._datetime) - assert isclose(min_energy_consumption, 0.55555 / cop, rel_tol=0.0001) + assert isclose(min_energy_consumption, 0.1851851 / cop, rel_tol=0.0001) def test_get_average_tank_temperature(self): self._tanks._tanks_energy_parameters[0]._state._storage_temp_C[self._datetime] = 30