Skip to content

Commit

Permalink
kpis and opex/capex costs in generic_heat_source
Browse files Browse the repository at this point in the history
  • Loading branch information
k-rieck committed Oct 21, 2024
1 parent 95007a7 commit 0e37fc1
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 62 deletions.
150 changes: 89 additions & 61 deletions hisim/components/generic_heat_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ def get_main_classname(cls):

@classmethod
def get_default_config_heating(
cls,
building_name: str = "BUI1",
thermal_power_in_watt: float = 6200.0,
cls, building_name: str = "BUI1", thermal_power_in_watt: float = 6200.0,
) -> "HeatSourceConfig":
"""Returns default configuration of a Heat Source used for heating."""
config = HeatSourceConfig(
Expand All @@ -77,11 +75,10 @@ def get_default_config_heating(
efficiency=1.0,
co2_footprint=0,
cost=0,
lifetime=1
lifetime=1,
)
return config


@classmethod
def get_default_config_waterheating(
cls,
Expand Down Expand Up @@ -110,8 +107,7 @@ def get_default_config_waterheating(
* scaling_factor_according_to_number_of_apartments
)
efficiency = get_heating_system_efficiency(
heating_system_installed=heating_system,
water_vs_heating=lt.InandOutputType.WATER_HEATING,
heating_system_installed=heating_system, water_vs_heating=lt.InandOutputType.WATER_HEATING,
)

if heating_system == lt.HeatingSystems.GAS_HEATING:
Expand All @@ -121,7 +117,9 @@ def get_default_config_waterheating(
elif heating_system == lt.HeatingSystems.DISTRICT_HEATING:
fuel = lt.LoadTypes.DISTRICTHEATING
else:
raise ValueError(f"Heating sytem {heating_system} not acceptable for generic heat source component. Muste be ags, oil or district heating.")
raise ValueError(
f"Heating sytem {heating_system} not acceptable for generic heat source component. Muste be ags, oil or district heating."
)

config = HeatSourceConfig(
building_name=building_name,
Expand Down Expand Up @@ -192,11 +190,7 @@ def __init__(

# Inputs - Mandatories
self.l1_heatsource_taget_percentage: cp.ComponentInput = self.add_input(
self.component_name,
self.L1HeatSourceTargetPercentage,
lt.LoadTypes.ANY,
lt.Units.PERCENT,
mandatory=True,
self.component_name, self.L1HeatSourceTargetPercentage, lt.LoadTypes.ANY, lt.Units.PERCENT, mandatory=True,
)

# Outputs
Expand All @@ -213,11 +207,7 @@ def __init__(
field_name=self.FuelDelivered,
load_type=self.config.fuel,
unit=lt.Units.ANY,
postprocessing_flag=[
lt.InandOutputType.FUEL_CONSUMPTION,
config.fuel,
config.water_vs_heating,
],
postprocessing_flag=[lt.InandOutputType.FUEL_CONSUMPTION, config.fuel, config.water_vs_heating],
output_description="Fuel Delivered",
)

Expand All @@ -228,9 +218,7 @@ def __init__(

self.add_default_connections(self.get_default_connections_controller_l1_heatpump())

def get_default_connections_controller_l1_heatpump(
self,
) -> List[cp.ComponentConnection]:
def get_default_connections_controller_l1_heatpump(self,) -> List[cp.ComponentConnection]:
"""Sets default connections of heat source controller."""
log.information("setting l1 default connections in Generic Heat Source")
connections = []
Expand Down Expand Up @@ -287,8 +275,7 @@ def i_simulate(self, timestep: int, stsv: cp.SingleTimeStepValues, force_converg
power_modifier = min(power_modifier, 1)

stsv.set_output_value(
self.thermal_power_delivered_channel,
self.config.power_th * power_modifier * self.config.efficiency,
self.thermal_power_delivered_channel, self.config.power_th * power_modifier * self.config.efficiency,
)

if self.config.fuel == lt.LoadTypes.OIL:
Expand All @@ -310,63 +297,104 @@ def i_simulate(self, timestep: int, stsv: cp.SingleTimeStepValues, force_converg
@staticmethod
def get_cost_capex(config: HeatSourceConfig, simulation_parameters: SimulationParameters) -> CapexCostDataClass:
"""Returns investment cost, CO2 emissions and lifetime."""
if config.fuel == lt.LoadTypes.GAS:
seconds_per_year = 365 * 24 * 60 * 60
capex_per_simulated_period = (config.cost / config.lifetime) * (
simulation_parameters.duration.total_seconds() / seconds_per_year
)
device_co2_footprint_per_simulated_period = (config.co2_footprint / config.lifetime) * (
simulation_parameters.duration.total_seconds() / seconds_per_year
)

capex_cost_data_class = CapexCostDataClass(
capex_investment_cost_in_euro=config.cost,
device_co2_footprint_in_kg=config.co2_footprint,
lifetime_in_years=config.lifetime,
capex_investment_cost_for_simulated_period_in_euro=capex_per_simulated_period,
device_co2_footprint_for_simulated_period_in_kg=device_co2_footprint_per_simulated_period,
kpi_tag=KpiTagEnumClass.GAS_HEATER_DOMESTIC_HOT_WATER
)
seconds_per_year = 365 * 24 * 60 * 60
capex_per_simulated_period = (config.cost / config.lifetime) * (
simulation_parameters.duration.total_seconds() / seconds_per_year
)
device_co2_footprint_per_simulated_period = (config.co2_footprint / config.lifetime) * (
simulation_parameters.duration.total_seconds() / seconds_per_year
)
capex_cost_data_class = CapexCostDataClass(
capex_investment_cost_in_euro=config.cost,
device_co2_footprint_in_kg=config.co2_footprint,
lifetime_in_years=config.lifetime,
capex_investment_cost_for_simulated_period_in_euro=capex_per_simulated_period,
device_co2_footprint_for_simulated_period_in_kg=device_co2_footprint_per_simulated_period,
)
if config.fuel == lt.LoadTypes.GAS and config.water_vs_heating == lt.InandOutputType.WATER_HEATING:
capex_cost_data_class.kpi_tag = KpiTagEnumClass.GAS_HEATER_DOMESTIC_HOT_WATER
elif config.fuel == lt.LoadTypes.GAS and config.water_vs_heating == lt.InandOutputType.HEATING:
capex_cost_data_class.kpi_tag = KpiTagEnumClass.GAS_HEATER_SPACE_HEATING
elif config.fuel == lt.LoadTypes.OIL and config.water_vs_heating == lt.InandOutputType.WATER_HEATING:
capex_cost_data_class.kpi_tag = KpiTagEnumClass.OIL_HEATER_DOMESTIC_HOT_WATER
elif config.fuel == lt.LoadTypes.OIL and config.water_vs_heating == lt.InandOutputType.HEATING:
capex_cost_data_class.kpi_tag = KpiTagEnumClass.OIL_HEATER_SPACE_HEATING
elif (
config.fuel == lt.LoadTypes.DISTRICTHEATING and config.water_vs_heating == lt.InandOutputType.WATER_HEATING
):
capex_cost_data_class.kpi_tag = KpiTagEnumClass.DISTRICT_HEATING_DOMESTIC_HOT_WATER
elif config.fuel == lt.LoadTypes.DISTRICTHEATING and config.water_vs_heating == lt.InandOutputType.HEATING:
capex_cost_data_class.kpi_tag = KpiTagEnumClass.DISTRICT_HEATING_SPACE_HEATING
else:
capex_cost_data_class = CapexCostDataClass.get_default_capex_cost_data_class()

return capex_cost_data_class

def get_cost_opex(
self,
all_outputs: List,
postprocessing_results: pd.DataFrame,
) -> OpexCostDataClass:
def get_cost_opex(self, all_outputs: List, postprocessing_results: pd.DataFrame,) -> OpexCostDataClass:
"""Calculate OPEX costs, consisting of energy and maintenance costs."""
gas_consumption_in_kilowatt_hour: Optional[float] = None
for index, output in enumerate(all_outputs):
if output.component_name == self.component_name and output.load_type == lt.LoadTypes.GAS:
gas_consumption_in_kilowatt_hour = round(sum(postprocessing_results.iloc[:, index]) * 1e-3, 1)
if gas_consumption_in_kilowatt_hour is not None:
fuel_consumption_in_kilowatt_hour_or_liter: Optional[float] = None
fuel_consumption_in_kilowatt_hour: Optional[float] = None
output: Optional[cp.ComponentOutput] = None
kpi_tag = None
for index, output_ in enumerate(all_outputs):
if output_.component_name == self.component_name and output_.field_name == self.FuelDelivered:
fuel_consumption_in_kilowatt_hour_or_liter = round(sum(postprocessing_results.iloc[:, index]) * 1e-3, 1)
output = output_
break

if fuel_consumption_in_kilowatt_hour_or_liter is not None and output is not None:
emissions_and_cost_factors = EmissionFactorsAndCostsForFuelsConfig.get_values_for_year(
self.my_simulation_parameters.year
)
co2_per_unit = emissions_and_cost_factors.gas_footprint_in_kg_per_kwh
co2_per_simulated_period_in_kg = gas_consumption_in_kilowatt_hour * co2_per_unit
if output.load_type == lt.LoadTypes.GAS:
co2_per_unit = emissions_and_cost_factors.gas_footprint_in_kg_per_kwh
euro_per_unit = emissions_and_cost_factors.gas_costs_in_euro_per_kwh
fuel_consumption_in_kilowatt_hour = fuel_consumption_in_kilowatt_hour_or_liter
if self.config.water_vs_heating == lt.InandOutputType.WATER_HEATING:
kpi_tag = KpiTagEnumClass.GAS_HEATER_DOMESTIC_HOT_WATER
elif self.config.water_vs_heating == lt.InandOutputType.HEATING:
kpi_tag = KpiTagEnumClass.GAS_HEATER_SPACE_HEATING

elif output.load_type == lt.LoadTypes.OIL:
co2_per_unit = emissions_and_cost_factors.oil_footprint_in_kg_per_l
euro_per_unit = emissions_and_cost_factors.oil_costs_in_euro_per_l
# calculate fuel consumption from liter to kWh for oil
# https://www.energieheld.de/heizung/ratgeber/durchschnittliche-heizkosten#:~:text=Zur%20Veranschaulichung%3A%20Heiz%C3%B6l%20wird%20meistens,etwa%209%2C8%20Kilowattstunden%20Heizenergie.
# 1l oil = 10 kWh
fuel_consumption_in_kilowatt_hour = fuel_consumption_in_kilowatt_hour_or_liter * 10
if self.config.water_vs_heating == lt.InandOutputType.WATER_HEATING:
kpi_tag = KpiTagEnumClass.OIL_HEATER_DOMESTIC_HOT_WATER
elif self.config.water_vs_heating == lt.InandOutputType.HEATING:
kpi_tag = KpiTagEnumClass.OIL_HEATER_SPACE_HEATING

elif output.load_type == lt.LoadTypes.DISTRICTHEATING:
co2_per_unit = emissions_and_cost_factors.contracting_heating_footprint_in_kg_per_kwh
euro_per_unit = emissions_and_cost_factors.contracting_heating_costs_in_euro_per_kwh
fuel_consumption_in_kilowatt_hour = fuel_consumption_in_kilowatt_hour_or_liter
if self.config.water_vs_heating == lt.InandOutputType.WATER_HEATING:
kpi_tag = KpiTagEnumClass.DISTRICT_HEATING_DOMESTIC_HOT_WATER
elif self.config.water_vs_heating == lt.InandOutputType.HEATING:
kpi_tag = KpiTagEnumClass.DISTRICT_HEATING_SPACE_HEATING
else:
raise ValueError("This loadtype is not implemented for the generic heat source.")

# energy costs and co2 and everything will be considered in gas meter
co2_per_simulated_period_in_kg = fuel_consumption_in_kilowatt_hour_or_liter * co2_per_unit
opex_energy_cost_per_simulated_period_in_euro = fuel_consumption_in_kilowatt_hour_or_liter * euro_per_unit
opex_cost_data_class = OpexCostDataClass(
opex_energy_cost_in_euro=0,
opex_energy_cost_in_euro=opex_energy_cost_per_simulated_period_in_euro,
opex_maintenance_cost_in_euro=0, # TODO: needs o be implemented still
co2_footprint_in_kg=co2_per_simulated_period_in_kg,
consumption_in_kwh=gas_consumption_in_kilowatt_hour,
loadtype=lt.LoadTypes.GAS,
kpi_tag=KpiTagEnumClass.GAS_HEATER_DOMESTIC_HOT_WATER
consumption_in_kwh=fuel_consumption_in_kilowatt_hour,
loadtype=output.load_type,
kpi_tag=kpi_tag,
)
else:
opex_cost_data_class = OpexCostDataClass.get_default_opex_cost_data_class()

return opex_cost_data_class

def get_component_kpi_entries(
self,
all_outputs: List,
postprocessing_results: pd.DataFrame,
) -> List[KpiEntry]:
def get_component_kpi_entries(self, all_outputs: List, postprocessing_results: pd.DataFrame,) -> List[KpiEntry]:
"""Calculates KPIs for the respective component and return all KPI entries as list."""
gas_consumption_in_kilowatt_hour: Optional[float] = None
list_of_kpi_entries: List[KpiEntry] = []
Expand Down
6 changes: 5 additions & 1 deletion hisim/postprocessing/kpi_computation/kpi_structure.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,11 @@ class KpiTagEnumClass(Enum):
COSTS_DISTRICT_GRID = "Costs Of District Grid"
EMISSIONS_DISTRICT_GRID = "Emissions Of District Grid"
CONTRACTING = "Contracting"
GENERIC_HEAT_SOURCE = "Generic Heat Source"
OIL_HEATER_SPACE_HEATING = "Oil Heater For Space Heating"
OIL_HEATER_DOMESTIC_HOT_WATER = "Oil Heater For Domestic Hot Water"
DISTRICT_HEATING_SPACE_HEATING = "District Heating For Space Heating"
DISTRICT_HEATING_DOMESTIC_HOT_WATER = "District Heating For Domestic Hot Water"
GENERIC_HEAT_SOURCE = "Generic Heat Source" # used in simple_heat_source.py


@dataclass
Expand Down

0 comments on commit 0e37fc1

Please sign in to comment.