diff --git a/config/config.default.yaml b/config/config.default.yaml index f68ff960..9f595401 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -417,9 +417,9 @@ sector: isentropic_compressor_efficiency: 0.8 heat_loss: 0.0 heat_pump_sources: - central_heating: + central: - air - decentral_heating: + decentral: - air - ground cluster_heat_buses: true diff --git a/rules/build_sector.smk b/rules/build_sector.smk index d6f959f3..9b2bfde6 100644 --- a/rules/build_sector.smk +++ b/rules/build_sector.smk @@ -214,6 +214,13 @@ rule build_temperature_profiles: script: "../scripts/build_temperature_profiles.py" +# def output_cop(wildcards): +# return { +# f"cop_{source}_{sink}": resources( +# "cop_" + source + "_" + sink + "_" + "elec_s{simpl}_{clusters}.nc" +# ) +# for sink, source in config["sector"]["heat_pump_sources"].items() +# } rule build_cop_profiles: params: @@ -237,21 +244,7 @@ rule build_cop_profiles: temp_soil_total=resources("temp_soil_total_elec_s{simpl}_{clusters}.nc"), temp_air_total=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"), output: - **{f"cop_{source}_{sink}": resources( - "cop_" + source + "_" + {sink} + "_" + "elec_s{simpl}_{clusters}.nc" - ) for sink, source in config_provider("sector", "heat_pump_sources").items()}, - # cop_air_decentral_heating=resources( - # "cop_air_decentral_heating_elec_s{simpl}_{clusters}.nc" - # ), - # cop_soil_decentral_heating=resources( - # "cop_soil_decentral_heating_elec_s{simpl}_{clusters}.nc" - # ), - # cop_air_central_heating=resources( - # "cop_air_central_heating_elec_s{simpl}_{clusters}.nc" - # ), - # cop_soil_central_heating=resources( - # "cop_soil_central_heating_elec_s{simpl}_{clusters}.nc" - # ), + cop_profiles=resources("cop_profiles_elec_s{simpl}_{clusters}.nc"), resources: mem_mb=20000, log: @@ -969,6 +962,7 @@ rule prepare_sector_network: adjustments=config_provider("adjustments", "sector"), emissions_scope=config_provider("energy", "emissions"), RDIR=RDIR, + heat_pump_sources=config_provider("sector", "heat_pump_sources"), input: unpack(input_profile_offwind), **rules.cluster_gas_network.output, @@ -1045,18 +1039,7 @@ rule prepare_sector_network: ), temp_soil_total=resources("temp_soil_total_elec_s{simpl}_{clusters}.nc"), temp_air_total=resources("temp_air_total_elec_s{simpl}_{clusters}.nc"), - cop_soil_decentral_heating=resources( - "cop_soil_decentral_heating_elec_s{simpl}_{clusters}.nc" - ), - cop_air_decentral_heating=resources( - "cop_air_decentral_heating_elec_s{simpl}_{clusters}.nc" - ), - cop_air_central_heating=resources( - "cop_air_central_heating_elec_s{simpl}_{clusters}.nc" - ), - cop_soil_central_heating=resources( - "cop_soil_central_heating_elec_s{simpl}_{clusters}.nc" - ), + cop_profiles=resources("cop_profiles_elec_s{simpl}_{clusters}.nc"), solar_thermal_total=lambda w: ( resources("solar_thermal_total_elec_s{simpl}_{clusters}.nc") if config_provider("sector", "solar_thermal")(w) diff --git a/rules/solve_myopic.smk b/rules/solve_myopic.smk index bf952d4d..09f25b24 100644 --- a/rules/solve_myopic.smk +++ b/rules/solve_myopic.smk @@ -9,6 +9,7 @@ rule add_existing_baseyear: sector=config_provider("sector"), existing_capacities=config_provider("existing_capacities"), costs=config_provider("costs"), + heat_pump_sources=config_provider("sector", "heat_pump_sources"), input: network=RESULTS + "prenetworks/elec_s{simpl}_{clusters}_l{ll}_{opts}_{sector_opts}_{planning_horizons}.nc", @@ -21,18 +22,7 @@ rule add_existing_baseyear: config_provider("scenario", "planning_horizons", 0)(w) ) ), - cop_soil_decentral_heating=resources( - "cop_soil_decentral_heating_elec_s{simpl}_{clusters}.nc" - ), - cop_air_decentral_heating=resources( - "cop_air_decentral_heating_elec_s{simpl}_{clusters}.nc" - ), - cop_air_central_heating=resources( - "cop_air_central_heating_elec_s{simpl}_{clusters}.nc" - ), - cop_soil_central_heating=resources( - "cop_soil_central_heating_elec_s{simpl}_{clusters}.nc" - ), + cop_profiles=resources("cop_profiles_elec_s{simpl}_{clusters}.nc"), existing_heating_distribution=resources( "existing_heating_distribution_elec_s{simpl}_{clusters}_{planning_horizons}.csv" ), diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 9770e6ce..00b5eeb7 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -442,27 +442,27 @@ def add_heating_capacities_installed_before_baseyear( """ logger.debug(f"Adding heating capacities installed before {baseyear}") - for name in existing_heating.columns.get_level_values(0).unique(): - name_type = "central" if name == "urban central" else "decentral" + for heat_system in existing_heating.columns.get_level_values(0).unique(): + system_type = "central" if heat_system == "urban central" else "decentral" - nodes = pd.Index(n.buses.location[n.buses.index.str.contains(f"{name} heat")]) + nodes = pd.Index(n.buses.location[n.buses.index.str.contains(f"{heat_system} heat")]) - if (name_type != "central") and options["electricity_distribution_grid"]: + if (system_type != "central") and options["electricity_distribution_grid"]: nodes_elec = nodes + " low voltage" else: nodes_elec = nodes - heat_pump_type = "air" if "urban" in name else "ground" - # Add heat pumps - costs_name = f"decentral {heat_pump_type}-sourced heat pump" + heat_source = snakemake.params.heat_pump_sources[system_type] + costs_name = f"{system_type} {heat_source}-sourced heat pump" efficiency = ( - cop[f"{heat_pump_type} {name_type}"][nodes] - if time_dep_hp_cop + cop.sel(heat_system=system_type, heat_source=heat_source, name=nodes).to_pandas().reindex(index=n.snapshots) + if options["time_dep_hp_cop"] else costs.at[costs_name, "efficiency"] ) + too_large_grouping_years = [gy for gy in grouping_years if gy >= int(baseyear)] if too_large_grouping_years: logger.warning( @@ -491,14 +491,14 @@ def add_heating_capacities_installed_before_baseyear( n.madd( "Link", nodes, - suffix=f" {name} {heat_pump_type} heat pump-{grouping_year}", + suffix=f" {heat_system} {heat_source} heat pump-{grouping_year}", bus0=nodes_elec, - bus1=nodes + " " + name + " heat", - carrier=f"{name} {heat_pump_type} heat pump", + bus1=nodes + " " + heat_system + " heat", + carrier=f"{heat_system} {heat_source} heat pump", efficiency=efficiency, capital_cost=costs.at[costs_name, "efficiency"] * costs.at[costs_name, "fixed"], - p_nom=existing_heating.loc[nodes, (name, f"{heat_pump_type} heat pump")] + p_nom=existing_heating.loc[nodes, (heat_system, f"{heat_source} heat pump")] * ratio / costs.at[costs_name, "efficiency"], build_year=int(grouping_year), @@ -509,66 +509,66 @@ def add_heating_capacities_installed_before_baseyear( n.madd( "Link", nodes, - suffix=f" {name} resistive heater-{grouping_year}", + suffix=f" {heat_system} resistive heater-{grouping_year}", bus0=nodes_elec, - bus1=nodes + " " + name + " heat", - carrier=name + " resistive heater", - efficiency=costs.at[f"{name_type} resistive heater", "efficiency"], + bus1=nodes + " " + heat_system + " heat", + carrier=heat_system + " resistive heater", + efficiency=costs.at[f"{system_type} resistive heater", "efficiency"], capital_cost=( - costs.at[f"{name_type} resistive heater", "efficiency"] - * costs.at[f"{name_type} resistive heater", "fixed"] + costs.at[f"{system_type} resistive heater", "efficiency"] + * costs.at[f"{system_type} resistive heater", "fixed"] ), p_nom=( - existing_heating.loc[nodes, (name, "resistive heater")] + existing_heating.loc[nodes, (heat_system, "resistive heater")] * ratio - / costs.at[f"{name_type} resistive heater", "efficiency"] + / costs.at[f"{system_type} resistive heater", "efficiency"] ), build_year=int(grouping_year), - lifetime=costs.at[f"{name_type} resistive heater", "lifetime"], + lifetime=costs.at[f"{system_type} resistive heater", "lifetime"], ) n.madd( "Link", nodes, - suffix=f" {name} gas boiler-{grouping_year}", + suffix=f" {heat_system} gas boiler-{grouping_year}", bus0="EU gas" if "EU gas" in spatial.gas.nodes else nodes + " gas", - bus1=nodes + " " + name + " heat", + bus1=nodes + " " + heat_system + " heat", bus2="co2 atmosphere", - carrier=name + " gas boiler", - efficiency=costs.at[f"{name_type} gas boiler", "efficiency"], + carrier=heat_system + " gas boiler", + efficiency=costs.at[f"{system_type} gas boiler", "efficiency"], efficiency2=costs.at["gas", "CO2 intensity"], capital_cost=( - costs.at[f"{name_type} gas boiler", "efficiency"] - * costs.at[f"{name_type} gas boiler", "fixed"] + costs.at[f"{system_type} gas boiler", "efficiency"] + * costs.at[f"{system_type} gas boiler", "fixed"] ), p_nom=( - existing_heating.loc[nodes, (name, "gas boiler")] + existing_heating.loc[nodes, (heat_system, "gas boiler")] * ratio - / costs.at[f"{name_type} gas boiler", "efficiency"] + / costs.at[f"{system_type} gas boiler", "efficiency"] ), build_year=int(grouping_year), - lifetime=costs.at[f"{name_type} gas boiler", "lifetime"], + lifetime=costs.at[f"{system_type} gas boiler", "lifetime"], ) n.madd( "Link", nodes, - suffix=f" {name} oil boiler-{grouping_year}", + suffix=f" {heat_system} oil boiler-{grouping_year}", bus0=spatial.oil.nodes, - bus1=nodes + " " + name + " heat", + bus1=nodes + " " + heat_system + " heat", bus2="co2 atmosphere", - carrier=name + " oil boiler", + carrier=heat_system + " oil boiler", efficiency=costs.at["decentral oil boiler", "efficiency"], efficiency2=costs.at["oil", "CO2 intensity"], capital_cost=costs.at["decentral oil boiler", "efficiency"] * costs.at["decentral oil boiler", "fixed"], p_nom=( - existing_heating.loc[nodes, (name, "oil boiler")] + existing_heating.loc[nodes, (heat_system, "oil boiler")] * ratio / costs.at["decentral oil boiler", "efficiency"] ), build_year=int(grouping_year), - lifetime=costs.at[f"{name_type} gas boiler", "lifetime"], + lifetime=costs.at[f"{system_type} gas boiler", "lifetime"], ) # delete links with p_nom=nan corresponding to extra nodes in country diff --git a/scripts/build_cop_profiles/DecentralHeatingCopApproximator.py b/scripts/build_cop_profiles/DecentralHeatingCopApproximator.py index d8526c39..11be7407 100644 --- a/scripts/build_cop_profiles/DecentralHeatingCopApproximator.py +++ b/scripts/build_cop_profiles/DecentralHeatingCopApproximator.py @@ -39,12 +39,12 @@ class DecentralHeatingCopApproximator(BaseCopApproximator): return_temperature_celsius : Union[xr.DataArray, np.array] The return temperature in Celsius. source: str - The source of the heat pump. Must be either 'air' or 'soil' + The source of the heat pump. Must be either 'air' or 'ground' """ self.delta_t = forward_temperature_celsius - source_inlet_temperature_celsius - if source_type not in ["air", "soil"]: - raise ValueError("'source' must be one of ['air', 'soil']") + if source_type not in ["air", "ground"]: + raise ValueError("'source' must be one of ['air', 'ground']") else: self.source_type = source_type @@ -57,7 +57,7 @@ class DecentralHeatingCopApproximator(BaseCopApproximator): """ if self.source_type == "air": return self._approximate_cop_air_source() - elif self.source_type == "soil": + elif self.source_type == "ground": return self._approximate_cop_ground_source() def _approximate_cop_air_source(self) -> Union[xr.DataArray, np.array]: diff --git a/scripts/build_cop_profiles/run.py b/scripts/build_cop_profiles/run.py index 12d012bb..5178483a 100644 --- a/scripts/build_cop_profiles/run.py +++ b/scripts/build_cop_profiles/run.py @@ -4,11 +4,39 @@ # SPDX-License-Identifier: MIT import numpy as np +import pandas as pd import xarray as xr from _helpers import set_scenario_config from CentralHeatingCopApproximator import CentralHeatingCopApproximator from DecentralHeatingCopApproximator import DecentralHeatingCopApproximator + +def get_cop( + heat_system_type: str, + heat_source: str, + source_inlet_temperature_celsius: xr.DataArray, +) -> xr.DataArray: + if heat_system_type == "decentral": + return DecentralHeatingCopApproximator( + forward_temperature_celsius=snakemake.params.heat_pump_sink_T_decentral_heating, + source_inlet_temperature_celsius=source_inlet_temperature_celsius, + source_type=heat_source, + ).approximate_cop() + + elif heat_system_type == "central": + return CentralHeatingCopApproximator( + forward_temperature_celsius=snakemake.params.forward_temperature_central_heating, + return_temperature_celsius=snakemake.params.return_temperature_central_heating, + source_inlet_temperature_celsius=source_inlet_temperature_celsius, + source_outlet_temperature_celsius=source_inlet_temperature_celsius + - snakemake.params.heat_source_cooling_central_heating, + ).approximate_cop() + else: + raise ValueError( + f"Invalid heat system type '{heat_system_type}'. Must be one of ['decentral', 'central']" + ) + + if __name__ == "__main__": if "snakemake" not in globals(): from _helpers import mock_snakemake @@ -21,30 +49,28 @@ if __name__ == "__main__": set_scenario_config(snakemake) - for source_type in ["air", "soil"]: - # source inlet temperature (air/soil) is based on weather data - source_inlet_temperature_celsius = xr.open_dataarray( - snakemake.input[f"temp_{source_type}_total"] + cop_all_system_types = [] + for heat_system_type, heat_sources in snakemake.params.heat_pump_sources.items(): + cop_this_system_type = [] + for heat_source in heat_sources: + source_inlet_temperature_celsius = xr.open_dataarray( + snakemake.input[f"temp_{heat_source.replace('ground', 'soil')}_total"] + ) + cop_da = get_cop( + heat_system_type=heat_system_type, + heat_source=heat_source, + source_inlet_temperature_celsius=source_inlet_temperature_celsius, + ) + cop_this_system_type.append(cop_da) + cop_all_system_types.append( + xr.concat( + cop_this_system_type, dim=pd.Index(heat_sources, name="heat_source") + ) ) - # Approximate COP for decentral (individual) heating - cop_individual_heating = DecentralHeatingCopApproximator( - forward_temperature_celsius=snakemake.params.heat_pump_sink_T_decentral_heating, - source_inlet_temperature_celsius=source_inlet_temperature_celsius, - source_type=source_type, - ).approximate_cop() - cop_individual_heating.to_netcdf( - snakemake.output[f"cop_{source_type}_decentral_heating"] - ) + cop_dataarray = xr.concat( + cop_all_system_types, + dim=pd.Index(snakemake.params.heat_pump_sources.keys(), name="heat_system"), + ) - # Approximate COP for central (district) heating - cop_central_heating = CentralHeatingCopApproximator( - forward_temperature_celsius=snakemake.params.forward_temperature_central_heating, - return_temperature_celsius=snakemake.params.return_temperature_central_heating, - source_inlet_temperature_celsius=source_inlet_temperature_celsius, - source_outlet_temperature_celsius=source_inlet_temperature_celsius - - snakemake.params.heat_source_cooling_central_heating, - ).approximate_cop() - cop_central_heating.to_netcdf( - snakemake.output[f"cop_{source_type}_central_heating"] - ) + cop_dataarray.to_netcdf(snakemake.output.cop_profiles) diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index d5b892ad..e59984d3 100644 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1825,23 +1825,6 @@ def add_heat(n, costs): "urban central", ] - cop = { - "air decentral": xr.open_dataarray(snakemake.input.cop_air_decentral_heating) - .to_pandas() - .reindex(index=n.snapshots), - "ground decentral": xr.open_dataarray( - snakemake.input.cop_soil_decentral_heating - ) - .to_pandas() - .reindex(index=n.snapshots), - "air central": xr.open_dataarray(snakemake.input.cop_air_central_heating) - .to_pandas() - .reindex(index=n.snapshots), - "ground central": xr.open_dataarray(snakemake.input.cop_soil_central_heating) - .to_pandas() - .reindex(index=n.snapshots), - } - if options["solar_thermal"]: solar_thermal = ( xr.open_dataarray(snakemake.input.solar_thermal_total) @@ -1851,31 +1834,32 @@ def add_heat(n, costs): # 1e3 converts from W/m^2 to MW/(1000m^2) = kW/m^2 solar_thermal = options["solar_cf_correction"] * solar_thermal / 1e3 - for name in heat_systems: - name_type = "central" if name == "urban central" else "decentral" + cop = xr.open_dataarray(snakemake.input.cop_profiles) + for heat_system in heat_systems: + system_type = "central" if heat_system == "urban central" else "decentral" - if name == "urban central": + if heat_system == "urban central": nodes = dist_fraction.index[dist_fraction > 0] else: nodes = pop_layout.index - n.add("Carrier", name + " heat") + n.add("Carrier", heat_system + " heat") n.madd( "Bus", - nodes + f" {name} heat", + nodes + f" {heat_system} heat", location=nodes, - carrier=name + " heat", + carrier=heat_system + " heat", unit="MWh_th", ) - if name == "urban central" and options.get("central_heat_vent"): + if heat_system == "urban central" and options.get("central_heat_vent"): n.madd( "Generator", - nodes + f" {name} heat vent", - bus=nodes + f" {name} heat", + nodes + f" {heat_system} heat vent", + bus=nodes + f" {heat_system} heat", location=nodes, - carrier=name + " heat vent", + carrier=heat_system + " heat vent", p_nom_extendable=True, p_max_pu=0, p_min_pu=-1, @@ -1886,18 +1870,18 @@ def add_heat(n, costs): for sector in sectors: # heat demand weighting - if "rural" in name: + if "rural" in heat_system: factor = 1 - urban_fraction[nodes] - elif "urban central" in name: + elif "urban central" in heat_system: factor = dist_fraction[nodes] - elif "urban decentral" in name: + elif "urban decentral" in heat_system: factor = urban_fraction[nodes] - dist_fraction[nodes] else: raise NotImplementedError( - f" {name} not in " f"heat systems: {heat_systems}" + f" {heat_system} not in " f"heat systems: {heat_systems}" ) - if sector in name: + if sector in heat_system: heat_load = ( heat_demand[[sector + " water", sector + " space"]] .T.groupby(level=1) @@ -1906,7 +1890,7 @@ def add_heat(n, costs): .multiply(factor) ) - if name == "urban central": + if heat_system == "urban central": heat_load = ( heat_demand.T.groupby(level=1) .sum() @@ -1919,20 +1903,17 @@ def add_heat(n, costs): n.madd( "Load", nodes, - suffix=f" {name} heat", - bus=nodes + f" {name} heat", - carrier=name + " heat", + suffix=f" {heat_system} heat", + bus=nodes + f" {heat_system} heat", + carrier=heat_system + " heat", p_set=heat_load, ) ## Add heat pumps - - heat_pump_types = ["air"] if "urban" in name else ["ground", "air"] - - for heat_pump_type in heat_pump_types: - costs_name = f"{name_type} {heat_pump_type}-sourced heat pump" + for heat_source in snakemake.params.heat_pump_sources[system_type]: + costs_name = f"{system_type} {heat_source}-sourced heat pump" efficiency = ( - cop[f"{heat_pump_type} {name_type}"][nodes] + cop.sel(heat_system=system_type, heat_source=heat_source, name=nodes).to_pandas().reindex(index=n.snapshots) if options["time_dep_hp_cop"] else costs.at[costs_name, "efficiency"] ) @@ -1940,10 +1921,10 @@ def add_heat(n, costs): n.madd( "Link", nodes, - suffix=f" {name} {heat_pump_type} heat pump", + suffix=f" {heat_system} {heat_source} heat pump", bus0=nodes, - bus1=nodes + f" {name} heat", - carrier=f"{name} {heat_pump_type} heat pump", + bus1=nodes + f" {heat_system} heat", + carrier=f"{heat_system} {heat_source} heat pump", efficiency=efficiency, capital_cost=costs.at[costs_name, "efficiency"] * costs.at[costs_name, "fixed"] @@ -1953,59 +1934,59 @@ def add_heat(n, costs): ) if options["tes"]: - n.add("Carrier", name + " water tanks") + n.add("Carrier", heat_system + " water tanks") n.madd( "Bus", - nodes + f" {name} water tanks", + nodes + f" {heat_system} water tanks", location=nodes, - carrier=name + " water tanks", + carrier=heat_system + " water tanks", unit="MWh_th", ) n.madd( "Link", - nodes + f" {name} water tanks charger", - bus0=nodes + f" {name} heat", - bus1=nodes + f" {name} water tanks", + nodes + f" {heat_system} water tanks charger", + bus0=nodes + f" {heat_system} heat", + bus1=nodes + f" {heat_system} water tanks", efficiency=costs.at["water tank charger", "efficiency"], - carrier=name + " water tanks charger", + carrier=heat_system + " water tanks charger", p_nom_extendable=True, ) n.madd( "Link", - nodes + f" {name} water tanks discharger", - bus0=nodes + f" {name} water tanks", - bus1=nodes + f" {name} heat", - carrier=name + " water tanks discharger", + nodes + f" {heat_system} water tanks discharger", + bus0=nodes + f" {heat_system} water tanks", + bus1=nodes + f" {heat_system} heat", + carrier=heat_system + " water tanks discharger", efficiency=costs.at["water tank discharger", "efficiency"], p_nom_extendable=True, ) - tes_time_constant_days = options["tes_tau"][name_type] + tes_time_constant_days = options["tes_tau"][system_type] n.madd( "Store", - nodes + f" {name} water tanks", - bus=nodes + f" {name} water tanks", + nodes + f" {heat_system} water tanks", + bus=nodes + f" {heat_system} water tanks", e_cyclic=True, e_nom_extendable=True, - carrier=name + " water tanks", + carrier=heat_system + " water tanks", standing_loss=1 - np.exp(-1 / 24 / tes_time_constant_days), - capital_cost=costs.at[name_type + " water tank storage", "fixed"], - lifetime=costs.at[name_type + " water tank storage", "lifetime"], + capital_cost=costs.at[system_type + " water tank storage", "fixed"], + lifetime=costs.at[system_type + " water tank storage", "lifetime"], ) if options["resistive_heaters"]: - key = f"{name_type} resistive heater" + key = f"{system_type} resistive heater" n.madd( "Link", - nodes + f" {name} resistive heater", + nodes + f" {heat_system} resistive heater", bus0=nodes, - bus1=nodes + f" {name} heat", - carrier=name + " resistive heater", + bus1=nodes + f" {heat_system} heat", + carrier=heat_system + " resistive heater", efficiency=costs.at[key, "efficiency"], capital_cost=costs.at[key, "efficiency"] * costs.at[key, "fixed"] @@ -2015,16 +1996,16 @@ def add_heat(n, costs): ) if options["boilers"]: - key = f"{name_type} gas boiler" + key = f"{system_type} gas boiler" n.madd( "Link", - nodes + f" {name} gas boiler", + nodes + f" {heat_system} gas boiler", p_nom_extendable=True, bus0=spatial.gas.df.loc[nodes, "nodes"].values, - bus1=nodes + f" {name} heat", + bus1=nodes + f" {heat_system} heat", bus2="co2 atmosphere", - carrier=name + " gas boiler", + carrier=heat_system + " gas boiler", efficiency=costs.at[key, "efficiency"], efficiency2=costs.at["gas", "CO2 intensity"], capital_cost=costs.at[key, "efficiency"] @@ -2034,22 +2015,22 @@ def add_heat(n, costs): ) if options["solar_thermal"]: - n.add("Carrier", name + " solar thermal") + n.add("Carrier", heat_system + " solar thermal") n.madd( "Generator", nodes, - suffix=f" {name} solar thermal collector", - bus=nodes + f" {name} heat", - carrier=name + " solar thermal", + suffix=f" {heat_system} solar thermal collector", + bus=nodes + f" {heat_system} heat", + carrier=heat_system + " solar thermal", p_nom_extendable=True, - capital_cost=costs.at[name_type + " solar thermal", "fixed"] + capital_cost=costs.at[system_type + " solar thermal", "fixed"] * overdim_factor, p_max_pu=solar_thermal[nodes], - lifetime=costs.at[name_type + " solar thermal", "lifetime"], + lifetime=costs.at[system_type + " solar thermal", "lifetime"], ) - if options["chp"] and name == "urban central": + if options["chp"] and heat_system == "urban central": # add gas CHP; biomass CHP is added in biomass section n.madd( "Link", @@ -2106,16 +2087,16 @@ def add_heat(n, costs): lifetime=costs.at["central gas CHP", "lifetime"], ) - if options["chp"] and options["micro_chp"] and name != "urban central": + if options["chp"] and options["micro_chp"] and heat_system != "urban central": n.madd( "Link", - nodes + f" {name} micro gas CHP", + nodes + f" {heat_system} micro gas CHP", p_nom_extendable=True, bus0=spatial.gas.df.loc[nodes, "nodes"].values, bus1=nodes, - bus2=nodes + f" {name} heat", + bus2=nodes + f" {heat_system} heat", bus3="co2 atmosphere", - carrier=name + " micro gas CHP", + carrier=heat_system + " micro gas CHP", efficiency=costs.at["micro CHP", "efficiency"], efficiency2=costs.at["micro CHP", "efficiency-heat"], efficiency3=costs.at["gas", "CO2 intensity"], @@ -2150,27 +2131,27 @@ def add_heat(n, costs): heat_demand["services space"] + heat_demand["residential space"] ) / heat_demand.T.groupby(level=[1]).sum().T - for name in n.loads[ + for heat_system in n.loads[ n.loads.carrier.isin([x + " heat" for x in heat_systems]) ].index: - node = n.buses.loc[name, "location"] + node = n.buses.loc[heat_system, "location"] ct = pop_layout.loc[node, "ct"] # weighting 'f' depending on the size of the population at the node - if "urban central" in name: + if "urban central" in heat_system: f = dist_fraction[node] - elif "urban decentral" in name: + elif "urban decentral" in heat_system: f = urban_fraction[node] - dist_fraction[node] else: f = 1 - urban_fraction[node] if f == 0: continue # get sector name ("residential"/"services"/or both "tot" for urban central) - if "urban central" in name: + if "urban central" in heat_system: sec = "tot" - if "residential" in name: + if "residential" in heat_system: sec = "residential" - if "services" in name: + if "services" in heat_system: sec = "services" # get floor aread at node and region (urban/rural) in m^2 @@ -2178,7 +2159,7 @@ def add_heat(n, costs): pop_layout.loc[node].fraction * floor_area.loc[ct, "value"] * 10**6 ).loc[sec] * f # total heat demand at node [MWh] - demand = n.loads_t.p_set[name] + demand = n.loads_t.p_set[heat_system] # space heat demand at node [MWh] space_heat_demand = demand * w_space[sec][node] @@ -2219,12 +2200,12 @@ def add_heat(n, costs): # add for each retrofitting strength a generator with heat generation profile following the profile of the heat demand for strength in strengths: - node_name = " ".join(name.split(" ")[2::]) + node_name = " ".join(heat_system.split(" ")[2::]) n.madd( "Generator", [node], suffix=" retrofitting " + strength + " " + node_name, - bus=name, + bus=heat_system, carrier="retrofitting", p_nom_extendable=True, p_nom_max=dE_diff[strength]