diff --git a/hisim/components/generic_heat_source.py b/hisim/components/generic_heat_source.py index 75dcaeeca..de6a83d9d 100644 --- a/hisim/components/generic_heat_source.py +++ b/hisim/components/generic_heat_source.py @@ -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( @@ -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, @@ -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: @@ -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, @@ -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 @@ -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", ) @@ -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 = [] @@ -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: @@ -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] = [] diff --git a/hisim/postprocessing/kpi_computation/kpi_structure.py b/hisim/postprocessing/kpi_computation/kpi_structure.py index cf192aedb..57bffd76b 100644 --- a/hisim/postprocessing/kpi_computation/kpi_structure.py +++ b/hisim/postprocessing/kpi_computation/kpi_structure.py @@ -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