diff --git a/config/config.default.yaml b/config/config.default.yaml index 93b0568e..b24f2ceb 100644 --- a/config/config.default.yaml +++ b/config/config.default.yaml @@ -357,6 +357,7 @@ existing_capacities: grouping_years_power: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2020, 2025, 2030] grouping_years_heat: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2019] # these should not extend 2020 threshold_capacity: 10 + default_heating_lifetime: 20 conventional_carriers: - lignite - coal @@ -482,6 +483,7 @@ sector: resistive_heaters: true oil_boilers: false biomass_boiler: true + overdimension_individual_heating: 1.1 #to cover demand peaks bigger than data chp: true micro_chp: false solar_thermal: true diff --git a/doc/configtables/existing_capacities.csv b/doc/configtables/existing_capacities.csv index 87519193..eacae35b 100644 --- a/doc/configtables/existing_capacities.csv +++ b/doc/configtables/existing_capacities.csv @@ -3,4 +3,5 @@ grouping_years_power ,--,A list of years,Intervals to group existing capacities grouping_years_heat ,--,A list of years below 2020,Intervals to group existing capacities for heat threshold_capacity ,MW,float,Capacities generators and links of below threshold are removed during add_existing_capacities +default_heating_lifetime ,years,int,Default lifetime for heating technologies conventional_carriers ,--,"Any subset of {uranium, coal, lignite, oil} ",List of conventional power plants to include in the sectoral network diff --git a/doc/configtables/licenses-sector.csv b/doc/configtables/licenses-sector.csv index a297b2f6..7f20b5a6 100644 --- a/doc/configtables/licenses-sector.csv +++ b/doc/configtables/licenses-sector.csv @@ -10,7 +10,7 @@ BASt emobility statistics,emobility/,unknown,http://www.bast.de/DE/Verkehrstechn BDEW heating profile,heat_load_profile_BDEW.csv,unknown,https://github.com/oemof/demandlib heating profiles for Aarhus,heat_load_profile_DK_AdamJensen.csv,unknown,Adam Jensen MA thesis at Aarhus University co2 budgets,co2_budget.csv,CC BY 4.0,https://arxiv.org/abs/2004.11009 -existing heating potentials,existing_infrastructure/existing_heating_raw.csv,unknown,https://ec.europa.eu/energy/studies/mapping-and-analyses-current-and-future-2020-2030-heatingcooling-fuel-deployment_en?redir=1 +existing heating potentials,existing_infrastructure/existing_heating_raw.csv,unknown,https://energy.ec.europa.eu/publications/mapping-and-analyses-current-and-future-2020-2030-heatingcooling-fuel-deployment-fossilrenewables-1_en IRENA existing VRE capacities,existing_infrastructure/{solar|onwind|offwind}_capcity_IRENA.csv,unknown,https://www.irena.org/Statistics/Download-Data USGS ammonia production,myb1-2017-nitro.xls,unknown,https://www.usgs.gov/centers/nmic/nitrogen-statistics-and-information hydrogen salt cavern potentials,h2_salt_caverns_GWh_per_sqkm.geojson,CC BY 4.0,https://doi.org/10.1016/j.ijhydene.2019.12.161 https://doi.org/10.20944/preprints201910.0187.v1 diff --git a/doc/configtables/sector.csv b/doc/configtables/sector.csv index 338cf34e..d8cc3288 100644 --- a/doc/configtables/sector.csv +++ b/doc/configtables/sector.csv @@ -66,6 +66,7 @@ boilers,--,"{true, false}",Add option for transforming gas into heat using gas b resistive_heaters,--,"{true, false}",Add option for transforming electricity into heat using resistive heaters (independently from gas boilers) oil_boilers,--,"{true, false}",Add option for transforming oil into heat using boilers biomass_boiler,--,"{true, false}",Add option for transforming biomass into heat using boilers +overdimension_individual_heating,--,"float",Add option for overdimensioning individual heating systems by a certain factor. This allows them to cover heat demand peaks e.g. 10% higher than those in the data with a setting of 1.1. chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP) micro_chp,--,"{true, false}",Add option for using Combined Heat and Power (CHP) for decentral areas. solar_thermal,--,"{true, false}",Add option for using solar thermal to generate heat. diff --git a/doc/release_notes.rst b/doc/release_notes.rst index b1511dd7..ee7bd64b 100644 --- a/doc/release_notes.rst +++ b/doc/release_notes.rst @@ -10,6 +10,19 @@ Release Notes Upcoming Release ================ +* Add new default to overdimension heating in individual buildings. This allows + them to cover heat demand peaks e.g. 10% higher than those in the data. The + disadvantage of manipulating the costs is that the capacity is then not quite + right. This way at least the costs are right. + +* Add option to specify to set a default heating lifetime for existing heating + (``existing_capacities: default_heating_lifetime:``). + +* Correctly source the existing heating technologies for buildings since the + source URL has changed. It represents the year 2012 and is only for + buildings, not district heating. So the capacities for urban central are now + set to zero from this source. + * Remove long-deprecated function ``attach_extendable_generators`` in :mod:`add_electricity`. * The filtering of power plants in the ``config.default.yaml`` has been updated regarding phased-out power plants in 2023. diff --git a/scripts/add_existing_baseyear.py b/scripts/add_existing_baseyear.py index 4f476b4d..c0d37a5b 100644 --- a/scripts/add_existing_baseyear.py +++ b/scripts/add_existing_baseyear.py @@ -402,13 +402,6 @@ def add_heating_capacities_installed_before_baseyear( """ logger.debug(f"Adding heating capacities installed before {baseyear}") - # 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://ec.europa.eu/energy/studies/mapping-and-analyses-current-and-future-2020-2030-heatingcooling-fuel-deployment_en?redir=1 - # file: "WP2_DataAnnex_1_BuildingTechs_ForPublication_201603.xls" -> "existing_heating_raw.csv". - # TODO start from original file - existing_heating = pd.read_csv( snakemake.input.existing_heating_distribution, header=[0, 1], index_col=0 ) @@ -436,7 +429,7 @@ def add_heating_capacities_installed_before_baseyear( if int(grouping_year) + default_lifetime <= int(baseyear): continue - # installation is assumed to be linear for the past 25 years (default lifetime) + # installation is assumed to be linear for the past default_lifetime years ratio = (int(grouping_year) - int(grouping_years[i - 1])) / default_lifetime n.madd( @@ -543,12 +536,6 @@ def add_heating_capacities_installed_before_baseyear( ], ) - # drop assets which are at the end of their lifetime - links_i = n.links[(n.links.build_year + n.links.lifetime <= baseyear)].index - logger.info("Removing following links because at end of their lifetime:") - logger.info(links_i) - n.mremove("Link", links_i) - if __name__ == "__main__": if "snakemake" not in globals(): @@ -605,7 +592,9 @@ if __name__ == "__main__": .to_pandas() .reindex(index=n.snapshots) ) - default_lifetime = snakemake.params.costs["fill_values"]["lifetime"] + default_lifetime = snakemake.params.existing_capacities[ + "default_heating_lifetime" + ] add_heating_capacities_installed_before_baseyear( n, baseyear, diff --git a/scripts/build_existing_heating_distribution.py b/scripts/build_existing_heating_distribution.py index 67993c29..78518597 100644 --- a/scripts/build_existing_heating_distribution.py +++ b/scripts/build_existing_heating_distribution.py @@ -16,6 +16,14 @@ cc = coco.CountryConverter() 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 + # TODO start from original file + existing_heating = pd.read_csv( snakemake.input.existing_heating, index_col=0, header=0 ) @@ -67,17 +75,17 @@ def build_existing_heating(): nodal_sectoral_totals.sum(axis=1), axis=0 ) - nodal_heat_name_fraction = pd.DataFrame(dtype=float) + nodal_heat_name_fraction = pd.DataFrame(index=district_heat_info.index, dtype=float) - nodal_heat_name_fraction["urban central"] = dist_fraction + nodal_heat_name_fraction["urban central"] = 0.0 for sector in sectors: nodal_heat_name_fraction[f"{sector} rural"] = nodal_sectoral_fraction[ sector ] * (1 - urban_fraction) - nodal_heat_name_fraction[f"{sector} urban decentral"] = nodal_sectoral_fraction[ - sector - ] * (urban_fraction - dist_fraction) + nodal_heat_name_fraction[f"{sector} urban decentral"] = ( + nodal_sectoral_fraction[sector] * urban_fraction + ) nodal_heat_name_tech = pd.concat( { diff --git a/scripts/prepare_sector_network.py b/scripts/prepare_sector_network.py index 394a67f8..eb24d9cf 100755 --- a/scripts/prepare_sector_network.py +++ b/scripts/prepare_sector_network.py @@ -1680,6 +1680,8 @@ def add_heat(n, costs): heat_demand = build_heat_demand(n) + overdim_factor = options["overdimension_individual_heating"] + district_heat_info = pd.read_csv(snakemake.input.district_heat_share, index_col=0) dist_fraction = district_heat_info["district fraction of node"] urban_fraction = district_heat_info["urban fraction"] @@ -1814,7 +1816,8 @@ def add_heat(n, costs): carrier=f"{name} {heat_pump_type} heat pump", efficiency=efficiency, capital_cost=costs.at[costs_name, "efficiency"] - * costs.at[costs_name, "fixed"], + * costs.at[costs_name, "fixed"] + * overdim_factor, p_nom_extendable=True, lifetime=costs.at[costs_name, "lifetime"], ) @@ -1883,7 +1886,9 @@ def add_heat(n, costs): bus1=nodes + f" {name} heat", carrier=name + " resistive heater", efficiency=costs.at[key, "efficiency"], - capital_cost=costs.at[key, "efficiency"] * costs.at[key, "fixed"], + capital_cost=costs.at[key, "efficiency"] + * costs.at[key, "fixed"] + * overdim_factor, p_nom_extendable=True, lifetime=costs.at[key, "lifetime"], ) @@ -1901,7 +1906,9 @@ def add_heat(n, costs): carrier=name + " gas boiler", efficiency=costs.at[key, "efficiency"], efficiency2=costs.at["gas", "CO2 intensity"], - capital_cost=costs.at[key, "efficiency"] * costs.at[key, "fixed"], + capital_cost=costs.at[key, "efficiency"] + * costs.at[key, "fixed"] + * overdim_factor, lifetime=costs.at[key, "lifetime"], ) @@ -1915,7 +1922,8 @@ def add_heat(n, costs): bus=nodes + f" {name} heat", carrier=name + " solar thermal", p_nom_extendable=True, - capital_cost=costs.at[name_type + " solar thermal", "fixed"], + capital_cost=costs.at[name_type + " solar thermal", "fixed"] + * overdim_factor, p_max_pu=solar_thermal[nodes], lifetime=costs.at[name_type + " solar thermal", "lifetime"], ) @@ -2348,7 +2356,8 @@ def add_biomass(n, costs): carrier=name + " biomass boiler", efficiency=costs.at["biomass boiler", "efficiency"], capital_cost=costs.at["biomass boiler", "efficiency"] - * costs.at["biomass boiler", "fixed"], + * costs.at["biomass boiler", "fixed"] + * options["overdimension_individual_heating"], marginal_cost=costs.at["biomass boiler", "pelletizing cost"], lifetime=costs.at["biomass boiler", "lifetime"], ) @@ -2806,7 +2815,8 @@ def add_industry(n, costs): 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"], + * costs.at["decentral oil boiler", "fixed"] + * options["overdimension_individual_heating"], lifetime=costs.at["decentral oil boiler", "lifetime"], )