diff --git a/doc/release_notes.rst b/doc/release_notes.rst index cbb35a530..18a52c74f 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -11,6 +11,8 @@ Release Notes Upcoming Release ================ +* Bugfix: Adjusted existing heating data in ``build_existing_heating_distribution`` and the indexing of existing heat pumps for the COP correction in ``add_brownfield`` to make the myopic code work with the geothermal district heating feature. + * Restore share policy "base" functionality to share build renewable profiles * Feature: Introduce geothermal district heating (direct utilisation and heat pumps). Potentials are based on `Manz et al. 2024: Spatial analysis of renewable and excess heat potentials for climate-neutral district heating in Europe `. diff --git a/scripts/add_brownfield.py b/scripts/add_brownfield.py index d7f66439a..0e91f7571 100644 --- a/scripts/add_brownfield.py +++ b/scripts/add_brownfield.py @@ -239,9 +239,14 @@ def update_heat_pump_efficiency(n: pypsa.Network, n_p: pypsa.Network, year: int) This function updates the efficiency in place and does not return a value. """ - # get names of heat pumps in previous iteration + # get names of heat pumps in previous iteration that cannot be replaced by direct utilisation in this iteration heat_pump_idx_previous_iteration = n_p.links.index[ n_p.links.index.str.contains("heat pump") + & n_p.links.index.str[:-4].isin( + n.links_t.efficiency.columns.str.rstrip( # sources that can be directly used are no longer represented by heat pumps in the dynamic efficiency dataframe + str(year) + ) + ) ] # construct names of same-technology heat pumps in the current iteration corresponding_idx_this_iteration = heat_pump_idx_previous_iteration.str[:-4] + str( @@ -252,6 +257,17 @@ def update_heat_pump_efficiency(n: pypsa.Network, n_p: pypsa.Network, year: int) n.links_t["efficiency"].loc[:, corresponding_idx_this_iteration].values ) + # Change efficiency2 for heat pumps that use an explicitly modelled heat source + previous_iteration_columns = heat_pump_idx_previous_iteration.intersection( + n_p.links_t["efficiency2"].columns + ) + current_iteration_columns = corresponding_idx_this_iteration.intersection( + n.links_t["efficiency2"].columns + ) + n_p.links_t["efficiency2"].loc[:, previous_iteration_columns] = ( + n.links_t["efficiency2"].loc[:, current_iteration_columns].values + ) + if __name__ == "__main__": if "snakemake" not in globals(): @@ -259,11 +275,11 @@ def update_heat_pump_efficiency(n: pypsa.Network, n_p: pypsa.Network, year: int) snakemake = mock_snakemake( "add_brownfield", - clusters="37", + clusters="39", opts="", - ll="v1.0", - sector_opts="168H-T-H-B-I-dist1", - planning_horizons=2030, + ll="vopt", + sector_opts="", + planning_horizons=2050, ) configure_logging(snakemake) diff --git a/scripts/build_existing_heating_distribution.py b/scripts/build_existing_heating_distribution.py index 804d96acb..663f27eaa 100644 --- a/scripts/build_existing_heating_distribution.py +++ b/scripts/build_existing_heating_distribution.py @@ -47,14 +47,23 @@ def build_existing_heating(): - # retrieve existing heating capacities - - # Add existing heating capacities, data comes from the study - # "Mapping and analyses of the current and future (2020 - 2030) - # heating/cooling fuel deployment (fossil/renewables) " - # https://energy.ec.europa.eu/publications/mapping-and-analyses-current-and-future-2020-2030-heatingcooling-fuel-deployment-fossilrenewables-1_en - # file: "WP2_DataAnnex_1_BuildingTechs_ForPublication_201603.xls" -> "existing_heating_raw.csv". - # data is for buildings only (i.e. NOT district heating) and represents the year 2012 + """ + Retrieve and clean existing heating capacities for the myopic code. + Data comes from the study "Mapping and analyses of the current and + future (2020 - 2030) heating/cooling fuel deployment (fossil/renewables)". + + Source + ------ + https://energy.ec.europa.eu/publications/mapping-and-analyses-current-and-future-2020-2030-heatingcooling-fuel-deployment-fossilrenewables-1_en + + File + ---- + "WP2_DataAnnex_1_BuildingTechs_ForPublication_201603.xls" -> "existing_heating_raw.csv". + + Notes + ----- + Data is for buildings only (i.e. NOT district heating) and represents the year 2012. + """ # TODO start from original file existing_heating = pd.read_csv( @@ -143,7 +152,12 @@ def build_existing_heating(): ) nodal_heat_name_tech[(f"{sector} rural", "air heat pump")] = 0.0 - nodal_heat_name_tech[("urban central", "ground heat pump")] = 0.0 + # add large-scale heat pump sources as columns for district heating with 0 capacity + + for heat_pump_source in snakemake.params.sector["heat_pump_sources"][ + "urban central" + ]: + nodal_heat_name_tech[("urban central", f"{heat_pump_source} heat pump")] = 0.0 nodal_heat_name_tech.to_csv(snakemake.output.existing_heating_distribution)