Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
COPModelType,
cop_model_factory,
BaseCOPModel,
UniversalCOPModel,
)


__all__ = ["COPModelType", "cop_model_factory", "BaseCOPModel"]
__all__ = ["COPModelType", "cop_model_factory", "BaseCOPModel", "UniversalCOPModel"]
62 changes: 38 additions & 24 deletions src/gsy_e/models/strategy/energy_parameters/heatpump/heat_pump.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
COPModelType,
cop_model_factory,
BaseCOPModel,
UniversalCOPModel,
)
from gsy_e.models.strategy.energy_parameters.heatpump.tank_parameters import (
WaterTankParameters,
Expand Down Expand Up @@ -263,19 +264,25 @@ def update_cop_after_dis_charging(
bought_energy_kWh: float,
):
"""Update the COP of the heat pump in its state class."""
if bought_energy_kWh < FLOATING_POINT_TOLERANCE:
self._hp_state.set_cop(time_slot, self._hp_state.get_cop(last_time_slot))
return
bought_energy_kW = convert_kWh_to_kW(bought_energy_kWh, GlobalConfig.slot_length)
heat_energy_kW = self._cop_model.calc_q_from_p_kW(
source_temp_C=source_temp_C,
condenser_temp_C=self._charger.get_average_inlet_temperature_C(last_time_slot),
electrical_demand_kW=bought_energy_kW,
)
if heat_energy_kW is None:
cop = self._hp_state.get_cop(last_time_slot)
if isinstance(self._cop_model, UniversalCOPModel):
cop = self._cop_model.calc_cop(
source_temp_C=source_temp_C,
condenser_temp_C=self._charger.get_average_inlet_temperature_C(last_time_slot),
)
else:
cop = heat_energy_kW / bought_energy_kW
if bought_energy_kWh < FLOATING_POINT_TOLERANCE:
self._hp_state.set_cop(time_slot, self._hp_state.get_cop(last_time_slot))
return
bought_energy_kW = convert_kWh_to_kW(bought_energy_kWh, GlobalConfig.slot_length)
heat_energy_kW = self._cop_model.calc_q_from_p_kW(
source_temp_C=source_temp_C,
condenser_temp_C=self._charger.get_average_inlet_temperature_C(last_time_slot),
electrical_demand_kW=bought_energy_kW,
)
if heat_energy_kW is None:
cop = self._hp_state.get_cop(last_time_slot)
else:
cop = heat_energy_kW / bought_energy_kW

# Set the calculated COP on both the last and the current time slot to use in calculations
self._hp_state.set_cop(last_time_slot, cop)
Expand Down Expand Up @@ -682,19 +689,25 @@ def _update_cop_after_dis_charging(
bought_energy_kWh: float,
):
"""Update the COP of the heat pump in its state class."""
if bought_energy_kWh < FLOATING_POINT_TOLERANCE:
self._hp_state.set_cop(time_slot, self._hp_state.get_cop(last_time_slot))
return
bought_energy_kW = convert_kWh_to_kW(bought_energy_kWh, GlobalConfig.slot_length)
heat_energy_kW = self._cop_model.calc_q_from_p_kW(
source_temp_C=self._source_temp_C.get_value(last_time_slot),
condenser_temp_C=self._target_temp_C.get_value(last_time_slot),
electrical_demand_kW=bought_energy_kW,
)
if heat_energy_kW is None:
cop = self.state.get_cop(last_time_slot)
if self._cop_model_type == COPModelType.UNIVERSAL:
cop = self._cop_model.calc_cop(
source_temp_C=self._source_temp_C.get_value(last_time_slot),
condenser_temp_C=self._target_temp_C.get_value(last_time_slot),
)
else:
cop = heat_energy_kW / bought_energy_kW
if bought_energy_kWh < FLOATING_POINT_TOLERANCE:
self.state.set_cop(time_slot, self.state.get_cop(last_time_slot))
return
bought_energy_kW = convert_kWh_to_kW(bought_energy_kWh, GlobalConfig.slot_length)
heat_energy_kW = self._cop_model.calc_q_from_p_kW(
source_temp_C=self._source_temp_C.get_value(last_time_slot),
condenser_temp_C=self._target_temp_C.get_value(last_time_slot),
electrical_demand_kW=bought_energy_kW,
)
if heat_energy_kW is None:
cop = self.state.get_cop(last_time_slot)
else:
cop = heat_energy_kW / bought_energy_kW

# Set the calculated COP on both the last and the current time slot to use in calculations
self.state.set_cop(last_time_slot, cop)
Expand Down Expand Up @@ -752,3 +765,4 @@ def _populate_state(self, time_slot: DateTime):
def _decrement_posted_energy(self, time_slot: DateTime, energy_kWh: float):
updated_energy_demand_kWh = max(0.0, self.get_energy_demand_kWh(time_slot) - energy_kWh)
self._state.set_energy_demand_kWh(time_slot, updated_energy_demand_kWh)
self._state.increase_total_traded_energy_kWh(energy_kWh)
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ class PCMType(Enum):

@dataclass
class BaseTankParameters:
# pylint: disable=too-many-instance-attributes)
"""Base class for tank parameters"""

type: HeatpumpTankTypes = HeatpumpTankTypes.WATER
name: str = ""
initial_temp_C: float = ConstSettings.HeatPumpSettings.INIT_TEMP_C
min_temp_C: float = ConstSettings.HeatPumpSettings.MIN_TEMP_C
max_temp_C: float = ConstSettings.HeatPumpSettings.MAX_TEMP_C
loss_per_day_percent: float = HeatPumpSettingsDefaultParameters.TANK_LOSS_PERCENT_DAY

@property
Expand All @@ -41,23 +42,15 @@ def per_market_slot_loss(self):

@dataclass
class WaterTankParameters(BaseTankParameters):
# pylint: disable=too-many-instance-attributes)
"""Nameplate parameters of a water tank."""

min_temp_C: float = ConstSettings.HeatPumpSettings.MIN_TEMP_C
max_temp_C: float = ConstSettings.HeatPumpSettings.MAX_TEMP_C
tank_volume_L: float = ConstSettings.HeatPumpSettings.TANK_VOL_L


@dataclass
class PCMTankParameters(BaseTankParameters):
# pylint: disable=too-many-instance-attributes)
"""Nameplate parameters of a pcm tank."""

min_temp_htf_C: float = ConstSettings.HeatPumpSettings.MIN_TEMP_C
max_temp_htf_C: float = ConstSettings.HeatPumpSettings.MAX_TEMP_C
min_temp_pcm_C: float = ConstSettings.HeatPumpSettings.MIN_TEMP_C
max_temp_pcm_C: float = ConstSettings.HeatPumpSettings.MAX_TEMP_C
pcm_tank_type: PCMType = PCMType.OM37
volume_flow_rate_l_min: float = 10
number_of_plates: int = 15
8 changes: 3 additions & 5 deletions src/gsy_e/models/strategy/state/heatpump_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,11 +106,11 @@ def restore_state(self, state_dict: Dict):
self._heat_demand_kJ = convert_str_to_pendulum_in_dict(state_dict["heat_demand_kJ"])

def get_results_dict(self, current_time_slot: DateTime) -> Dict:
retval = {
return {
"cop": self.get_cop(current_time_slot),
"heat_demand_kJ": self.get_heat_demand_kJ(current_time_slot),
"total_traded_energy_kWh": self._total_traded_energy_kWh,
}
return retval


class HeatPumpState(HeatPumpStateBase):
Expand Down Expand Up @@ -207,16 +207,14 @@ def delete_past_state_values(self, current_time_slot: DateTime):
self._delete_time_slots(self._heat_demand_kJ, last_time_slot)

def get_results_dict(self, current_time_slot: DateTime) -> Dict:
retval = {
return {
**super().get_results_dict(current_time_slot),
"energy_consumption_kWh": self.get_energy_consumption_kWh(current_time_slot),
"max_energy_demand_kWh": self.get_max_energy_demand_kWh(current_time_slot),
"min_energy_demand_kWh": self.get_min_energy_demand_kWh(current_time_slot),
"cop": self.get_cop(current_time_slot),
"total_traded_energy_kWh": self._total_traded_energy_kWh,
"heat_demand_kJ": self.get_heat_demand_kJ(current_time_slot),
}
return retval

def __str__(self):
return self.__class__.__name__
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,8 @@ def serialize(self):
"""Return serializable dict of class parameters."""
return {
"initial_temp_C": self._params.initial_temp_C,
"min_temp_htf_C": self._params.min_temp_htf_C,
"max_temp_htf_C": self._params.max_temp_htf_C,
"min_temp_pcm_C": self._params.min_temp_pcm_C,
"max_temp_pcm_C": self._params.max_temp_pcm_C,
"min_temp_C": self._params.min_temp_C,
"max_temp_C": self._params.max_temp_C,
"type": self._params.type.value,
"pcm_tank_type": self._params.pcm_tank_type.value,
}
Expand Down Expand Up @@ -102,8 +100,25 @@ def _get_heat_demand_kJ(self, time_slot: DateTime):
def _set_heat_demand_kJ(self, energy_kJ: float, time_slot: DateTime):
self._heat_demand_kJ[time_slot] = energy_kJ

def _set_condenser_temp_C(self, temp_C: float, time_slot: DateTime):
self._condenser_temp_C[time_slot] = temp_C
def _set_condenser_temp_C(self, condenser_temp_C: float, time_slot: DateTime):
if (self._params.min_temp_C - condenser_temp_C) > FLOATING_POINT_TOLERANCE:
log.warning(
"The PCM storage tank reached it's minimum (%s), discharging "
"condensor temperature of %s is limited to the minimum",
self._params.min_temp_C,
round(condenser_temp_C, 2),
)
condenser_temp_C = self._params.min_temp_C
if (condenser_temp_C - self._params.max_temp_C) > FLOATING_POINT_TOLERANCE:
log.warning(
"The PCM storage tank reached it's maximum (%s), charging "
"condensor temperature of %s is limited to the maximum",
self._params.max_temp_C,
round(condenser_temp_C, 2),
)
condenser_temp_C = self._params.max_temp_C

self._condenser_temp_C[time_slot] = condenser_temp_C

def _get_condenser_temp_C(self, time_slot: DateTime):
return self._condenser_temp_C.get(time_slot, self.get_htf_temp_C(time_slot))
Expand Down Expand Up @@ -133,25 +148,6 @@ def _get_condenser_temp_from_heat_demand_kWh(
assert 0 < condenser_temp_C < 100, f"unrealistic condenser temp {condenser_temp_C}"
return condenser_temp_C

def _limit_condenser_temp(self, condenser_temp_C: float) -> float:
if (self._params.min_temp_htf_C - condenser_temp_C) > FLOATING_POINT_TOLERANCE:
log.warning(
"The PCM storage tank reached it's minimum (%s), discharging "
"condensor temperature of %s is limited to the minimum",
self._params.min_temp_htf_C,
round(condenser_temp_C, 2),
)
return self._params.min_temp_htf_C
if (condenser_temp_C - self._params.max_temp_htf_C) > FLOATING_POINT_TOLERANCE:
log.warning(
"The PCM storage tank reached it's maximum (%s), charging "
"condensor temperature of %s is limited to the maximum",
self._params.max_temp_htf_C,
round(condenser_temp_C, 2),
)
return self._params.max_temp_htf_C
return condenser_temp_C

def increase_tank_temp_from_heat_energy(self, heat_energy_kWh: float, time_slot: DateTime):
"""Increase the temperature of the water tank with the provided heat energy."""
assert heat_energy_kWh > FLOATING_POINT_TOLERANCE
Expand All @@ -168,35 +164,41 @@ def decrease_tank_temp_from_heat_energy(self, heat_energy_kWh: float, time_slot:
)
self._decrease_storage_temp_from_condenser_temp(temp_cond_C, time_slot)

def _limit_temps_after_dis_charging(self, temps: list[float]):
temps = [
temp if temp <= self._params.max_temp_C else self._params.max_temp_C for temp in temps
]
return [
temp if temp >= self._params.min_temp_C else self._params.min_temp_C for temp in temps
]

def _increase_storage_temp_from_condenser_temp(
self, condenser_temp_C: float, time_slot: DateTime
):
"""Increase storage temperatures for provided condenser temperature."""
condenser_temp_C = self._limit_condenser_temp(condenser_temp_C)
self._set_condenser_temp_C(condenser_temp_C, time_slot)
htf_temps, pcm_temps = self._pcm_charge_model.get_temp_after_charging(
current_htf_temps_C=self._get_htf_temps_C(self._last_time_slot(time_slot)),
current_pcm_temps_C=self._get_pcm_temps_C(self._last_time_slot(time_slot)),
charging_temp=condenser_temp_C,
)
self._htf_temps_C[time_slot] = htf_temps
self._pcm_temps_C[time_slot] = pcm_temps
self._htf_temps_C[time_slot] = self._limit_temps_after_dis_charging(htf_temps)
self._pcm_temps_C[time_slot] = self._limit_temps_after_dis_charging(pcm_temps)

self._set_soc_after_charging(time_slot)

def _decrease_storage_temp_from_condenser_temp(
self, condenser_temp_C: float, time_slot: DateTime
):
"""Decrease storage temperatures for provided condenser temperature."""
condenser_temp_C = self._limit_condenser_temp(condenser_temp_C)
self._set_condenser_temp_C(condenser_temp_C, time_slot)
htf_temps, pcm_temps = self._pcm_discharge_model.get_temp_after_discharging(
current_htf_temps_C=self._get_htf_temps_C(self._last_time_slot(time_slot)),
current_pcm_temps_C=self._get_pcm_temps_C(self._last_time_slot(time_slot)),
discharging_temp=condenser_temp_C,
)
self._htf_temps_C[time_slot] = htf_temps
self._pcm_temps_C[time_slot] = pcm_temps
self._htf_temps_C[time_slot] = self._limit_temps_after_dis_charging(htf_temps)
self._pcm_temps_C[time_slot] = self._limit_temps_after_dis_charging(pcm_temps)

self._set_soc_after_discharging(time_slot)

Expand Down Expand Up @@ -241,10 +243,8 @@ def restore_state(self, state_dict: Dict):
self._pcm_temps_C = convert_str_to_pendulum_in_dict(state_dict["pcm_temps_C"])
self._condenser_temp_C = convert_str_to_pendulum_in_dict(state_dict["condenser_temp_C"])
self._soc = convert_str_to_pendulum_in_dict(state_dict["soc"])
self._params.min_temp_htf_C = state_dict["min_temp_htf_C"]
self._params.max_temp_htf_C = state_dict["max_temp_htf_C"]
self._params.min_temp_pcm_C = state_dict["min_temp_pcm_C"]
self._params.max_temp_pcm_C = state_dict["max_temp_pcm_C"]
self._params.min_temp_C = state_dict["min_temp_C"]
self._params.max_temp_C = state_dict["max_temp_C"]
self._params.initial_temp_C = state_dict["initial_temp_C"]

def delete_past_state_values(self, current_time_slot: DateTime):
Expand All @@ -263,12 +263,12 @@ def get_min_heat_energy_consumption_kJ(self, time_slot: DateTime, heat_demand_kJ

def get_soc_energy_kJ(self, time_slot: DateTime) -> float:
"""Return the available energy stored in the tank."""
if self.get_pcm_temp_C(time_slot) - self._params.min_temp_pcm_C < FLOATING_POINT_TOLERANCE:
if self.get_pcm_temp_C(time_slot) - self._params.min_temp_C < FLOATING_POINT_TOLERANCE:
return 0

return convert_kWh_to_kJ(
self._get_heat_demand_kWh_from_deltaT(
self.get_pcm_temp_C(time_slot) - self._params.min_temp_pcm_C
self.get_pcm_temp_C(time_slot) - self._params.min_temp_C
)
)

Expand All @@ -286,12 +286,12 @@ def _get_heat_demand_kWh_from_deltaT(self, temperature_difference: float) -> flo

def get_dod_energy_kJ(self, time_slot: DateTime) -> float:
"""Return depth of discharge as an energy value in kJ."""
if self._params.max_temp_pcm_C - self.get_pcm_temp_C(time_slot) < FLOATING_POINT_TOLERANCE:
if self._params.max_temp_C - self.get_pcm_temp_C(time_slot) < FLOATING_POINT_TOLERANCE:
return 0

return convert_kWh_to_kJ(
self._get_heat_demand_kWh_from_deltaT(
self._params.max_temp_pcm_C - self.get_pcm_temp_C(time_slot)
self._params.max_temp_C - self.get_pcm_temp_C(time_slot)
)
)

Expand Down
Loading
Loading