From 71c71dc5dd2e515d7d88481f2c1b7895fc0df5ca Mon Sep 17 00:00:00 2001 From: Jonas Hoersch Date: Mon, 10 Mar 2025 10:08:52 +0100 Subject: [PATCH] enh(add_existing_baseyear): Pull out valid_grouping_years algorithm from heat Apply also to power. --- config/config.default.yaml | 4 +- scripts/add_existing_baseyear.py | 65 ++++++++++++++++++-------------- 2 files changed, 39 insertions(+), 30 deletions(-) diff --git a/config/config.default.yaml b/config/config.default.yaml index 100d2b9250..54b9d2de18 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -429,8 +429,8 @@ solar_thermal: # docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#existing-capacities existing_capacities: - grouping_years_power: [1920, 1950, 1955, 1960, 1965, 1970, 1975, 1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2020, 2025] - grouping_years_heat: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2019] # heat grouping years >= baseyear will be ignored + grouping_years_power: [1920, 1950, 1955, 1960, 1965, 1970, 1975, 1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2020, 2025] # power grouping years > baseyear will be ignored + grouping_years_heat: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2019] # heat grouping years > baseyear will be ignored threshold_capacity: 10 default_heating_lifetime: 20 conventional_carriers: diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 8bf39c0d55..5cfabf8b9b 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -7,6 +7,7 @@ """ import logging +from collections.abc import Sequence from types import SimpleNamespace import country_converter as coco @@ -464,6 +465,25 @@ def get_efficiency( return efficiency +def valid_grouping_years( + grouping_years: Sequence[int] | pd.Index, + baseyear: int, + max_lifetime: float | None = None, +) -> pd.Index: + grouping_years = pd.Index(sorted(grouping_years)).astype(int) + + valid = grouping_years <= baseyear + if max_lifetime is not None: + valid &= grouping_years + max_lifetime >= baseyear + if not valid.all(): + logger.warning( + "Only grouping years between [baseyear - max. lifetime, baseyear] are used." + f"Dropping {grouping_years[~valid]}." + ) + + return grouping_years[valid] + + def add_heating_capacities_installed_before_baseyear( n: pypsa.Network, costs: pd.DataFrame, @@ -490,7 +510,7 @@ def add_heating_capacities_installed_before_baseyear( Technology costs baseyear : int Base year for analysis - grouping_years : list + grouping_years : pd.Index Intervals to group capacities heat_pump_cop : xr.DataArray Heat pump coefficients of performance @@ -532,32 +552,14 @@ def add_heating_capacities_installed_before_baseyear( else: nodes_elec = nodes - too_large_grouping_years = [ - gy for gy in grouping_years if gy >= int(baseyear) - ] - if too_large_grouping_years: - logger.warning( - f"Grouping years >= baseyear are ignored. Dropping {too_large_grouping_years}." - ) - valid_grouping_years = pd.Series( - [ - int(grouping_year) - for grouping_year in grouping_years - if int(grouping_year) + default_lifetime > int(baseyear) - and int(grouping_year) < int(baseyear) - ] - ) - - assert valid_grouping_years.is_monotonic_increasing - - # get number of years of each interval - _years = valid_grouping_years.diff() - # Fill NA from .diff() with value for the first interval - _years[0] = valid_grouping_years[0] - baseyear + default_lifetime - # Installation is assumed to be linear for the past - ratios = _years / _years.sum() + # get number of years of each interval + _years = pd.Index([grouping_years[0] - baseyear + default_lifetime]).append( + grouping_years.diff() + ) + # Installation is assumed to be linear for the past + ratios = _years / np.sum(_years) - for ratio, grouping_year in zip(ratios, valid_grouping_years): + for ratio, grouping_year in zip(ratios, grouping_years): # Add heat pumps for heat_source in heat_pump_source_types[heat_system.system_type.value]: costs_name = heat_system.heat_pump_costs_name(heat_source) @@ -732,8 +734,10 @@ def add_heating_capacities_installed_before_baseyear( Nyears, ) - grouping_years_power = snakemake.params.existing_capacities["grouping_years_power"] - grouping_years_heat = snakemake.params.existing_capacities["grouping_years_heat"] + grouping_years_power = valid_grouping_years( + snakemake.params.existing_capacities["grouping_years_power"], + baseyear, + ) add_power_capacities_installed_before_baseyear( n=n, costs=costs, @@ -751,6 +755,11 @@ def add_heating_capacities_installed_before_baseyear( year = int(snakemake.params["energy_totals_year"]) heating_efficiencies = pd.read_csv(fn, index_col=[1, 0]).loc[year] + grouping_years_heat = valid_grouping_years( + snakemake.params.existing_capacities["grouping_years_heat"], + baseyear, + snakemake.params.existing_capacities["default_heating_lifetime"], + ) add_heating_capacities_installed_before_baseyear( n=n, costs=costs,