Building Sector-Coupled Networks

Contents

Building Sector-Coupled Networks#

The preparation process of the sector-coupled version of the PyPSA-Eur energy system model consists of a group of snakemake rules which are briefly outlined and explained in detail in the sections below.

Not all data dependencies are shipped with the git repository. Instead we provide separate data bundles which can be obtained using the retrieve* rules (Retrieving Data). Having downloaded the necessary data,

  • add_brownfield builds and stores the base network with all buses, HVAC lines and HVDC links, while

Rule add_brownfield#

Prepares brownfield data from previous planning horizon.

Rule add_existing_baseyear#

Adds existing power and heat generation capacities for initial planning horizon.

Rule build_existing_heating_distribution#

Builds table of existing heat generation capacities for initial planning horizon.

Existing heat generation capacities are distributed to nodes based on population. Within the nodes, the capacities are distributed to sectors (residential and services) based on sectoral consumption and urban/rural based population distribution.

Inputs:#

  • Existing heating generators: data/existing_heating_raw.csv per country

  • Population layout: resources/{run_name}/pop_layout_s<simpl>_<clusters>.csv. Output of scripts/build_clustered_population_layout.py

  • Population layout with energy demands: resources/<run_name>/pop_weighted_energy_totals_s<simpl>_<clusters>.csv

  • District heating share: resources/<run_name>/district_heat_share_base_s<simpl>_<clusters>_<planning_horizons>.csv

Outputs:#

  • Existing heat generation capacities distributed to nodes: resources/{run_name}/existing_heating_distribution_base_s_{clusters}_{planning_horizons}.csv

Relevant settings:#

Notes:#

  • Data for Albania, Montenegro and Macedonia is not included in input database and assumed 0.

  • Coal and oil boilers are assimilated to oil boilers.

  • All ground-source heat pumps are assumed in rural areas and all air-source heat pumps are assumed to be in urban areas.

References:#

Rule build_ammonia_production#

Build historical annual ammonia production per country in ktonNH3/a.

Inputs#

  • data/bundle-sector/myb1-2017-nitro.xls

Outputs#

  • resources/ammonia_production.csv

Description#

This functions takes data from the Minerals Yearbook

(July 2024) published by the US Geological Survey (USGS) and the National Minerals Information Center and extracts the annual ammonia production per country in ktonN/a. The data is converted to ktonNH3/a.

Rule build_biomass_potentials#

Compute biogas and solid biomass potentials for each clustered model region using data from JRC ENSPRESO.

Rule build_egs_potentials#

This rule extracts potential and cost for electricity generation through enhanced geothermal systems.

For this, we use data from “From hot rock to useful energy…” by Aghahosseini, Breyer (2020) ‘https://doi.org/10.1016/j.apenergy.2020.115769’ Note that we input data used here is not the same as in the paper, but was passed on by the authors.

The data provides a lon-lat gridded map of Europe (1° x 1°), with each grid cell assigned a heat potential (in GWh) and a cost (in EUR/MW).

This scripts overlays that map with the network’s regions, and builds a csv with CAPEX, OPEX and p_nom_max

Rule build_biomass_transport_costs#

Reads biomass transport costs for different countries of the JRC report.

“The JRC-EU-TIMES model. Bioenergy potentials for EU and neighbouring countries.” (2015)

converts them from units ‘EUR per km/ton’ -> ‘EUR/ (km MWh)’

assuming as an approximation energy content of wood pellets

@author: bw0928

Rule build_clustered_population_layouts#

Build population layouts for all clustered model regions as total as well as split by urban and rural population.

Rule build_cop_profiles#

Rule build_central_heating_temperature_profiles#

Rule build_energy_totals#

Build total energy demands and carbon emissions per country using JRC IDEES, eurostat, and EEA data.

  • Country-specific data is read in build_eurostat(), build_idees() and build_swiss.

  • build_energy_totals() then combines energy data from Eurostat, Swiss, and IDEES data and rescale_idees_from_eurostat() rescales IDEES data to match Eurostat data.

  • build_district_heat_share() calculates the share of district heating for each country from IDEES data.

  • Historical CO2 emissions are calculated in build_eea_co2() and build_eurostat_co2() and combined in build_co2_totals().

Relevant Settings#

Inputs#

  • resources/<run_name>/nuts3_shapes.gejson: NUTS3 shapes.

  • data/bundle/eea_UNFCCC_v23.csv: CO2 emissions data from EEA.

  • data/switzerland-new_format-all_years.csv: Swiss energy data.

  • data/gr-e-11.03.02.01.01-cc.csv: Swiss transport data

  • data/jrc-idees: JRC IDEES data.

  • data/district_heat_share.csv: District heating shares.

  • data/eurostat/Balances-April2023: Eurostat energy balances.

  • data/eurostat/eurostat-household_energy_balances-february_2024.csv: Eurostat household energy balances.

Outputs#

  • resources/<run_name>/energy_totals.csv: Energy totals per country, sector and year.

  • resources/<run_name>/co2_totals.csv: CO2 emissions per country, sector and year.

  • resources/<run_name>/transport_data.csv: Transport data per country and year.

  • resources/<run_name>/district_heat_share.csv: District heating share per by country and year.

Rule build_heat_totals#

Approximate heat demand for all weather years.

approximate_heat_demand() approximates annual heat demand based on energy totals and heating degree days (HDD) using a regression of heat demand on HDDs.

Inputs#

  • resources/<run_name>/energy_totals.csv: Energy consumption by sector (columns), country and year. Output of scripts.build_energy_totals.py().

  • data/era5-annual-HDD-per-country.csv: Number of heating degree days by year (columns) and country (index).

Outputs#

  • resources/<run_name>/heat_totals.csv: Approximated annual heat demand for each country.

Rule build_gas_input_locations#

Build import locations for fossil gas from entry-points, LNG terminals and production sites with data from SciGRID_gas and Global Energy Monitor.

Rule build_gas_network#

Preprocess gas network based on data from bthe SciGRID_gas project (https://www.gas.scigrid.de/).

Rule build_daily_heat_demand#

This rule builds heat demand time series using heating degree day (HDD) approximation.

Snapshots are resampled to daily time resolution and Atlite.convert.heat_demand is used to convert ambient temperature from the default weather cutout to heat demand time series for the respective cutout.

Heat demand is distributed by population to clustered onshore regions.

The rule is executed in build_sector.smk.

Relevant Settings#

snapshots:
drop_leap_day:

Inputs#

  • resources/<run_name>/pop_layout_<scope>.nc: Population layout (spatial population distribution).

  • resources/<run_name>/regions_onshore_base_s<simpl>_<clusters>.geojson: Onshore region shapes.

  • cutout: Weather data cutout, as specified in config

Outputs#

  • resources/daily_heat_demand_<scope>_base_s<simpl>_<clusters>.nc:

Relevant settings#

atlite:
    default_cutout``:

Rule build_hourly_heat_demand#

Build hourly heat demand time series from daily heat demand.

Water and space heating demand profiles are generated using intraday profiles from BDEW. Different profiles are used for the residential and services sectors as well as weekdays and weekend.

The daily heat demand is multiplied by the intraday profile to obtain the hourly heat demand time series. The rule is executed in build_sector.smk.

Relevant Settings#

snapshots:
drop_leap_day:

Inputs#

  • data/heat_load_profile_BDEW.csv: Intraday heat profile for water and space heating demand for the residential and services sectors for weekends and weekdays.

  • resources/daily_heat_demand_total_base_s<simpl>_<clusters>.nc: Daily heat demand per cluster.

Outputs#

  • resources/hourly_heat_demand_total_base_s<simpl>_<clusters>.nc:

Rule build_district_heat_share#

Build district heat shares at each node, depending on investment year.

Inputs:#

  • resources/<run_name>/pop_layout.csv: Population layout for each node: Total, urban and rural population.

  • resources/<run_name>/district_heat_share.csv: Historical district heat share at each country. Output of scripts/build_energy_totals.py.

Outputs:#

  • resources/<run_name>/district_heat_share.csv: District heat share at each node, potential for each investment year.

Relevant settings:#

Notes:#

  • The district heat share is calculated as the share of urban population at each node, multiplied by the share of district heating in the respective country.

  • The sector.district_heating.potential setting defines the max. district heating share.

  • The max. share of district heating is increased by a progress factor, depending on the investment year (See sector.district_heating.progress setting).

Rule build_industrial_distribution_key#

Build spatial distribution of industries from Hotmaps database.

Inputs#

  • resources/regions_onshore_base_s_{clusters}.geojson

  • resources/pop_layout_base_s_{clusters}.csv

Outputs#

  • resources/industrial_distribution_key_base_s_{clusters}.csv

Description#

This rule uses the Hotmaps database <https://gitlab.com/hotmaps/industrial_sites/industrial_sites_Industrial_Database>. After removing entries without valid locations, it assigns each industrial site to a bus region based on its location. Then, it calculates the nodal distribution key for each sector based on the emissions of the industrial sites in each region. This leads to a distribution key of 1 if there is only one bus per country and <1 if there are multiple buses per country. The sum over buses of one country is 1.

The following subcategories of industry are considered: - Iron and steel - Cement - Refineries - Paper and printing - Chemical industry - Glass - Non-ferrous metals - Non-metallic mineral products - Other non-classified Furthermore, the population distribution is added - Population

Rule build_industrial_energy_demand_per_country_today#

Build industrial energy demand per country.

Inputs#

  • data/jrc-idees-2021

  • industrial_production_per_country.csv

Outputs#

  • resources/industrial_energy_demand_per_country_today.csv

Description#

This rule uses the industrial_production_per_country.csv file and the JRC-IDEES data to derive an energy demand per country and sector. If the country is not in the EU28, an average energy demand depending on the production volume is derived. For each country and each subcategory of

  • Alumina production

  • Aluminium - primary production

  • Aluminium - secondary production

  • Ammonia

  • Cement

  • Ceramics & other NMM

  • Chlorine

  • Electric arc

  • Food, beverages and tobacco

  • Glass production

  • HVC

  • Integrated steelworks

  • Machinery equipment

  • Methanol

  • Other industrial sectors

  • Other chemicals

  • Other non-ferrous metals

  • Paper production

  • Pharmaceutical products etc.

  • Printing and media reproduction

  • Pulp production

  • Textiles and leather

  • Transport equipment

  • Wood and wood products

the output file contains the energy demand in TWh/a for the following carriers

  • biomass

  • electricity

  • gas

  • heat

  • hydrogen

  • liquid

  • other

  • solid

  • waste

Rule build_industrial_energy_demand_per_node_today#

Build industrial energy demand per model region.

Inputs#

  • resources/industrial_distribution_key_base_s_{clusters}.csv

  • resources/industrial_energy_demand_per_country_today.csv

Outputs#

  • resources/industrial_energy_demand_per_node_today_base_s_{clusters}.csv

Description#

This rule maps the industrial energy demand per country industrial_energy_demand_per_country_today.csv to each bus region. The energy demand per country is multiplied by the mapping value from the file industrial_distribution_key_base_s_{clusters}.csv between 0 and 1 to get the industrial energy demand per bus.

The unit of the energy demand is TWh/a.

Rule build_industrial_energy_demand_per_node#

Build industrial energy demand per model region.

Inputs#

  • resources/industrial_energy_demand_today_base_s_{clusters}.csv

  • resources/industry_sector_ratios_{planning_horizons}.csv

  • resources/industrial_production_base_s_{clusters}_{planning_horizons}.csv

Outputs#

  • resources/industrial_energy_demand_base_s_{clusters}_{planning_horizons}.csv

Description#

This rule aggregates the energy demand of the industrial sectors per model region. For each bus, the following carriers are considered: - electricity - coal - coke - solid biomass - methane - hydrogen - low-temperature heat - naphtha - ammonia - process emission - process emission from feedstock

which can later be used as values for the industry load.

Rule build_industrial_production_per_country_tomorrow#

Build future industrial production per country.

Relevant Settings#

industry:
    St_primary_fraction:
    DRI_fraction:
    Al_primary_fraction:
    HVC_primary_fraction:
    HVC_mechanical_recycling_fraction:
    HVC_chemical_recycling_fraction:

See also

Documentation of the configuration file config/config.yaml at industry

Inputs#

  • resources/industrial_production_per_country.csv

Outputs#

  • resources/industrial_production_per_country_tomorrow_{planning_horizons}.csv

Description#

This rule uses the industrial_production_per_country.csv file and the expected recycling rates to calculate the future production of the industrial sectors.

St_primary_fraction The fraction of steel that is coming from primary production. This is more energy intensive than recycling steel (secondary production).

DRI_fraction The fraction of primary steel that is produced in DRI plants.

Al_primary_fraction The fraction of aluminium that is coming from primary production. This is more energy intensive than recycling aluminium (secondary production).

HVC_primary_fraction The fraction of high value chemicals that are coming from primary production (crude oil or Fischer Tropsch).

HVC_mechanical_recycling_fraction The fraction of high value chemicals that are coming from mechanical recycling.

HVC_chemical_recycling_fraction The fraction of high value chemicals that are coming from chemical recycling.

If not already present, the information is added as new column in the output file.

The unit of the production is kt/a.

Rule build_industrial_production_per_country#

This rule builds the historical industrial production per country.

Relevant Settings#

countries:

Inputs#

  • resources/ammonia_production.csv

  • data/bundle-sector/jrc-idees-2021

  • data/eurostat

Outputs#

  • resources/industrial_production_per_country.csv

Description#

The industrial production is taken from the JRC-IDEES <https://joint-research-centre.ec.europa.eu/potencia-policy-oriented-tool-energy-and-climate-change-impact-assessment/jrc-idees_en)>. This dataset provides detailed information about the consumption of energy for various processes. If the country is not part of the EU28, the energy consumption in the industrial sectors is taken from the Eurostat <https://ec.europa.eu/eurostat/de/data/database> dataset. The industrial production is calculated for the year specified in the config[“industry”][“reference_year”].

The ammonia production is provided by the rule build_ammonia_production <https://pypsa-eur.readthedocs.io/en/latest/sector.html#module-build_ammonia_production>. Since Switzerland is not part of the EU28 nor reported by eurostat, the energy consumption in the industrial sectors is taken from the `BFE <https://pubdb.bfe.admin.ch/de/publication/download/11817> dataset. After the industrial production is calculated, the basic chemicals are separated into ammonia, chlorine, methanol and HVC. The production of these chemicals is assumed to be proportional to the production of basic chemicals without ammonia.

The following subcategories [kton/a] are considered: - Electric arc - Integrated steelworks - Other chemicals - Pharmaceutical products etc. - Cement - Ceramics & other NMM - Glass production - Pulp production - Paper production - Printing and media reproduction - Food, beverages and tobacco - Alumina production - Aluminium - primary production - Aluminium - secondary production - Other non-ferrous metals - Transport equipment - Machinery equipment - Textiles and leather - Wood and wood products - Other industrial sectors - Ammonia - HVC - Chlorine - Methanol

Rule build_industrial_production_per_node#

Build industrial production per model region.

Inputs#

  • resources/industrial_distribution_key_base_s_{clusters}.csv

  • resources/industrial_production_per_country_tomorrow_{planning_horizons}.csv

Outputs#

  • resources/industrial_production_per_node_base_s_{clusters}_{planning_horizons}.csv

Description#

This rule maps the industrial production per country from a certain time horizon to each bus region. The mapping file provides a value between 0 and 1 for each bus and industry subcategory, indicating the share of the country’s production of that sector in that bus. The industrial production per country is multiplied by the mapping value to get the industrial production per bus. The unit of the production is kt/a.

Rule build_industry_sector_ratios#

Build best case specific energy consumption by carrier and category.

Relevant Settings#

industry:
    ammonia:

Inputs#

  • resources/ammonia_production.csv

  • data/bundle-sector/jrc-idees-2021

Outputs#

  • resources/industry_sector_ratios.csv

Description#

This script uses the JRC-IDEES <https://joint-research-centre.ec.europa.eu/potencia-policy-oriented-tool-energy-and-climate-change-impact-assessment/jrc-idees_en> data to calculate an EU28 average specific energy consumption by carrier and industries. The industries are according to the rule industrial_production_per_country <https://pypsa-eur.readthedocs.io/en/latest/sector.html#module-build_industrial_production_per_country>.

The following carriers are considered: - elec - coal - coke - biomass - methane - hydrogen - heat - naphtha - process emission - process emission from feedstock - (ammonia)

If the config[“industry”][“ammonia”] <https://pypsa-eur.readthedocs.io/en/latest/configuration.html#industry> is set to true the ammonia demand is not converted to hydrogen and electricity but is considered as a separate carrier.

The unit of the specific energy consumption is MWh/t material and tCO2/t material for process emissions.

Rule build_population_layouts#

Build mapping between cutout grid cells and population (total, urban, rural).

Rule build_population_weighted_energy_totals#

Distribute country-level energy demands by population.

Rule build_retro_cost#

This script calculates the space heating savings through better insulation of the thermal envelope of a building and corresponding costs for different building types in different countries.

Methodology#

The energy savings calculations are based on the

EN ISO 13790 / seasonal method https://www.iso.org/obp/ui/#iso:std:iso:13790:ed-2:v1:en:

  • calculations heavily oriented on the TABULAWebTool

http://webtool.building-typology.eu/ http://www.episcope.eu/fileadmin/tabula/public/docs/report/TABULA_CommonCalculationMethod.pdf which is following the EN ISO 13790 / seasonal method

Basic Equations#

The basic equations:

The Energy needed for space heating E_space [W/m²] are calculated as the sum of heat losses and heat gains:

E_space = H_losses - H_gains

Heat losses constitute from the losses through heat transmission (H_tr [W/m²K]) (this includes heat transfer through building elements and thermal bridges) and losses by ventilation (H_ve [W/m²K]):

H_losses = (H_tr + H_ve) * F_red * (T_threshold - T_averaged_d_heat) * d_heat * 1/365

F_red : reduction factor, considering non-uniform heating [°C], p.16 chapter 2.6 [-] T_threshold : heating temperature threshold, assumed 15 C d_heat : Length of heating season, number of days with daily averaged temperature below T_threshold T_averaged_d_heat : mean daily averaged temperature of the days within heating season d_heat

Heat gains constitute from the gains by solar radiation (H_solar) and internal heat gains (H_int) weighted by a gain utilisation factor nu:

H_gains = nu * (H_solar + H_int)

Structure#

The script has the following structure:

  1. fixed parameters are set

  2. prepare data, bring to same format

  3. calculate space heat demand depending on additional insulation material

  4. calculate costs for corresponding additional insulation material

  5. get cost savings per retrofitting measures for each sector by weighting with heated floor area

Rule build_salt_cavern_potentials#

Build salt cavern potentials for hydrogen storage.

Technical Potential of Salt Caverns for Hydrogen Storage in Europe CC-BY 4.0 https://doi.org/10.20944/preprints201910.0187.v1 https://doi.org/10.1016/j.ijhydene.2019.12.161

Figure 6. Distribution of potential salt cavern sites across Europe with their corresponding energy densities (cavern storage potential divided by the volume).

Figure 7. Total cavern storage potential in European countries classified as onshore, offshore and within 50 km of shore.

The regional distribution is taken from the map (Figure 6) and scaled to the capacities from the bar chart split by nearshore (<50km from sea), onshore (>50km from sea), offshore (Figure 7).

Rule build_sequestration_potentials#

Build regionalised geological sequestration potential for carbon dioxide using data from CO2Stop.

Rule build_shipping_demand#

Build regional demand for international navigation based on outflow volume of ports.

Rule build_solar_thermal_profiles#

Build solar thermal collector profile time series.

Uses atlite.Cutout.solar_thermal` to compute heat generation for clustered onshore regions from population layout and weather data cutout. The rule is executed in ``build_sector.smk.

Relevant Settings#

snapshots:
drop_leap_day:
solar_thermal:
atlite:
    default_cutout:

Inputs#

  • resources/<run_name/pop_layout_<scope>.nc:

  • resources/<run_name/regions_onshore_base_s<simpl>_<clusters>.geojson:

  • cutout: Weather data cutout, as specified in config

Outputs#

  • resources/solar_thermal_<scope>_base_s<simpl>_<clusters>.nc:

Rule build_temperature_profiles#

Build time series for air and soil temperatures per clustered model region.

Uses atlite.Cutout.temperature and atlite.Cutout.soil_temperature compute temperature ambient air and soil temperature for the respective cutout. The rule is executed in ``build_sector.smk.

Relevant Settings#

snapshots:
drop_leap_day:
atlite:
    default_cutout:

Inputs#

  • resources/<run_name>/pop_layout_total.nc:

  • resources/<run_name>/regions_onshore_base_s<simpl>_<clusters>.geojson:

  • cutout: Weather data cutout, as specified in config

Outputs#

  • resources/temp_soil_total_base_s<simpl>_<clusters>.nc:

  • ``resources/temp_air_total_base_s<simpl>_<clusters>.nc`

Rule build_transport_demand#

Build land transport demand per clustered model region including efficiency improvements due to drivetrain changes, time series for electric vehicle availability and demand-side management constraints.

Rule cluster_gas_network#

Cluster gas transmission network to clustered model regions.

Rule time_aggregation#

Rule prepare_sector_network#

Adds all sector-coupling components to the network, including demand and supply technologies for the buildings, transport and industry sectors.