Merge branch 'master' into multiyear

This commit is contained in:
Fabian Neumann 2024-03-06 16:34:53 +01:00
commit 579cd0c756
15 changed files with 327 additions and 211 deletions

View File

@ -19,7 +19,7 @@ on:
- cron: "0 5 * * TUE"
env:
DATA_CACHE_NUMBER: 2
DATA_CACHE_NUMBER: 1
jobs:
build:

View File

@ -319,9 +319,8 @@ pypsa_eur:
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#energy
energy:
energy_totals_year: 2013
energy_totals_year: 2019
base_emissions_year: 1990
eurostat_report_year: 2016
emissions: CO2
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#biomass
@ -360,7 +359,7 @@ solar_thermal:
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#existing-capacities
existing_capacities:
grouping_years_power: [1980, 1985, 1990, 1995, 2000, 2005, 2010, 2015, 2020, 2025, 2030]
grouping_years_power: [1960, 1965, 1970, 1975, 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

View File

@ -1,25 +1,25 @@
country,item,2010,2011,2012,2013,2014,2015
CH,total residential,268.2,223.4,243.4,261.3,214.2,229.1
CH,total residential space,192.2,149.0,168.1,185.5,139.7,154.4
CH,total residential water,32.2,31.6,31.9,32.2,31.7,31.9
CH,total residential cooking,9.3,9.3,9.3,9.4,9.5,9.6
CH,electricity residential,67.9,63.7,65.7,67.6,63.0,64.4
CH,electricity residential space,15.9,12.8,14.3,15.8,12.3,13.5
CH,electricity residential water,8.8,8.5,8.5,8.6,8.5,8.6
CH,electricity residential cooking,4.9,4.9,4.9,4.9,5.0,5.0
CH,total services,145.9,127.4,136.7,144.0,124.5,132.5
CH,total services space,80.0,62.2,70.8,77.4,58.3,64.3
CH,total services water,10.1,10.0,10.1,10.1,10.0,10.0
CH,total services cooking,2.5,2.4,2.3,2.3,2.4,2.3
CH,electricity services,60.5,59.2,60.3,61.4,60.3,62.6
CH,electricity services space,4.0,3.2,3.8,4.2,3.3,3.6
CH,electricity services water,0.7,0.7,0.7,0.7,0.7,0.7
CH,electricity services cooking,2.5,2.4,2.3,2.3,2.4,2.3
CH,total rail,11.5,11.1,11.2,11.4,11.1,11.4
CH,total road,199.4,200.4,200.4,201.2,202.0,203.1
CH,electricity road,0.,0.,0.,0.,0.,0.
CH,electricity rail,11.5,11.1,11.2,11.4,11.1,11.4
CH,total domestic aviation,3.3,3.2,3.4,3.4,3.5,3.5
CH,total international aviation,58.0,62.0,63.5,64.2,64.5,66.8
CH,total domestic navigation,1.6,1.6,1.6,1.6,1.6,1.6
CH,total international navigation,0.,0.,0.,0.,0.,0.
country,item,2010,2011,2012,2013,2014,2015,2016,2017,2018,2019,2020,2021,2022
CH,total residential,268.2,223.4,243.4,261.3,214.2,229.1,241.2,236.5,223.7,226.5,219.1,241.2,211.3
CH,total residential space,192.2,149,168.1,185.5,139.7,154.4,167.3,161.5,147.2,150.4,140.2,166.2,131.9
CH,total residential water,32.2,31.6,31.9,32.2,31.7,31.9,31.8,31.8,31.8,31.7,33.3,32.5,32.5
CH,total residential cooking,9.3,9.3,9.3,9.4,9.5,9.6,9.9,10,10.1,10.2,10.5,10.3,10.3
CH,electricity residential,67.9,63.7,65.7,67.6,63,64.4,69.7,69.2,67.7,68.1,68.7,70.8,66.8
CH,electricity residential space,15.9,12.8,14.3,15.8,12.3,13.5,15.8,15.6,14.7,15.3,14.8,17.8,14.8
CH,electricity residential water,8.8,8.5,8.5,8.6,8.5,8.6,8.9,9,9.2,9.3,9.7,9.5,9.5
CH,electricity residential cooking,4.9,4.9,4.9,4.9,5,5,5,5.1,5.1,5.1,5.4,5.2,5.3
CH,total services,145.9,127.4,136.7,144,124.5,132.5,150.5,147.7,141.5,143.1,129.7,144.2,122.5
CH,total services space,80,62.2,70.8,77.4,58.3,64.3,77,74.4,68.2,69.8,64.3,75.7,58.7
CH,total services water,10.1,10,10.1,10.1,10,10,11.4,11.3,11.2,11.1,9.7,10.4,12
CH,total services cooking,2.5,2.4,2.3,2.3,2.4,2.3,3.1,3.1,3.2,3.3,2.1,2.6,3.2
CH,electricity services,60.5,59.2,60.3,61.4,60.3,62.6,65.9,65.7,65.5,65.6,58.8,61.6,61.6
CH,electricity services space,4,3.2,3.8,4.2,3.3,3.6,2.7,2.5,2.3,2.3,2.2,2.5,2.5
CH,electricity services water,0.7,0.7,0.7,0.7,0.7,0.7,1.2,1.1,1.1,1.1,0.9,1,1
CH,electricity services cooking,2.5,2.4,2.3,2.3,2.4,2.3,3.1,3.1,3.1,3.2,3.3,2.1,3.2
CH,total rail,11.5,11.1,11.2,11.4,11.1,11.4,11.6,11.4,11.2,11,10.2,10.6,10.8
CH,total road,199.4,200.4,200.4,201.2,202,203.1,203.9,203.7,202.6,200.5,182.6,188.3,193.3
CH,electricity road,0,0,0,0,0,0,0.1,0.2,0.3,0.4,0.5,0.8,1.3
CH,electricity rail,11.5,11.1,11.2,11.4,11.1,11.4,11.5,11.3,11.1,11,10.1,10.6,10.7
CH,total domestic aviation,3.3,3.2,3.4,3.4,3.5,3.5,3.6,3.1,3.1,2.9,2.5,2.8,3
CH,total international aviation,58,62,63.5,64.2,64.5,66.8,70.6,72.8,77.2,78.2,28.2,31.2,56.8
CH,total domestic navigation,1.6,1.6,1.6,1.6,1.6,1.6,1.4,1.4,1.4,1.4,1.4,1.4,1.4
CH,total international navigation,0,0,0,0,0,0,0,0,0,0,0,0,0

1 country item 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022
2 CH total residential 268.2 223.4 243.4 261.3 214.2 229.1 241.2 236.5 223.7 226.5 219.1 241.2 211.3
3 CH total residential space 192.2 149.0 149 168.1 185.5 139.7 154.4 167.3 161.5 147.2 150.4 140.2 166.2 131.9
4 CH total residential water 32.2 31.6 31.9 32.2 31.7 31.9 31.8 31.8 31.8 31.7 33.3 32.5 32.5
5 CH total residential cooking 9.3 9.3 9.3 9.4 9.5 9.6 9.9 10 10.1 10.2 10.5 10.3 10.3
6 CH electricity residential 67.9 63.7 65.7 67.6 63.0 63 64.4 69.7 69.2 67.7 68.1 68.7 70.8 66.8
7 CH electricity residential space 15.9 12.8 14.3 15.8 12.3 13.5 15.8 15.6 14.7 15.3 14.8 17.8 14.8
8 CH electricity residential water 8.8 8.5 8.5 8.6 8.5 8.6 8.9 9 9.2 9.3 9.7 9.5 9.5
9 CH electricity residential cooking 4.9 4.9 4.9 4.9 5.0 5 5.0 5 5 5.1 5.1 5.1 5.4 5.2 5.3
10 CH total services 145.9 127.4 136.7 144.0 144 124.5 132.5 150.5 147.7 141.5 143.1 129.7 144.2 122.5
11 CH total services space 80.0 80 62.2 70.8 77.4 58.3 64.3 77 74.4 68.2 69.8 64.3 75.7 58.7
12 CH total services water 10.1 10.0 10 10.1 10.1 10.0 10 10.0 10 11.4 11.3 11.2 11.1 9.7 10.4 12
13 CH total services cooking 2.5 2.4 2.3 2.3 2.4 2.3 3.1 3.1 3.2 3.3 2.1 2.6 3.2
14 CH electricity services 60.5 59.2 60.3 61.4 60.3 62.6 65.9 65.7 65.5 65.6 58.8 61.6 61.6
15 CH electricity services space 4.0 4 3.2 3.8 4.2 3.3 3.6 2.7 2.5 2.3 2.3 2.2 2.5 2.5
16 CH electricity services water 0.7 0.7 0.7 0.7 0.7 0.7 1.2 1.1 1.1 1.1 0.9 1 1
17 CH electricity services cooking 2.5 2.4 2.3 2.3 2.4 2.3 3.1 3.1 3.1 3.2 3.3 2.1 3.2
18 CH total rail 11.5 11.1 11.2 11.4 11.1 11.4 11.6 11.4 11.2 11 10.2 10.6 10.8
19 CH total road 199.4 200.4 200.4 201.2 202.0 202 203.1 203.9 203.7 202.6 200.5 182.6 188.3 193.3
20 CH electricity road 0. 0 0. 0 0. 0 0. 0 0. 0 0. 0 0.1 0.2 0.3 0.4 0.5 0.8 1.3
21 CH electricity rail 11.5 11.1 11.2 11.4 11.1 11.4 11.5 11.3 11.1 11 10.1 10.6 10.7
22 CH total domestic aviation 3.3 3.2 3.4 3.4 3.5 3.5 3.6 3.1 3.1 2.9 2.5 2.8 3
23 CH total international aviation 58.0 58 62.0 62 63.5 64.2 64.5 66.8 70.6 72.8 77.2 78.2 28.2 31.2 56.8
24 CH total domestic navigation 1.6 1.6 1.6 1.6 1.6 1.6 1.4 1.4 1.4 1.4 1.4 1.4 1.4
25 CH total international navigation 0. 0 0. 0 0. 0 0. 0 0. 0 0. 0 0 0 0 0 0 0 0

View File

@ -1,7 +1,4 @@
,Unit,Values,Description
energy_totals_year ,--,"{1990,1995,2000,2005,2010,2011,…} ",The year for the sector energy use. The year must be avaliable in the Eurostat report
base_emissions_year ,--,"YYYY; e.g. 1990","The base year for the sector emissions. See `European Environment Agency (EEA) <https://www.eea.europa.eu/data-and-maps/data/national-emissions-reported-to-the-unfccc-and-to-the-eu-greenhouse-gas-monitoring-mechanism-16>`_."
eurostat_report_year ,--,"{2016,2017,2018}","The publication year of the Eurostat report. 2016 includes Bosnia and Herzegovina, 2017 does not"
emissions ,--,"{CO2, All greenhouse gases - (CO2 equivalent)}","Specify which sectoral emissions are taken into account. Data derived from EEA. Currently only CO2 is implemented."

1 Unit Values Description
2 energy_totals_year -- {1990,1995,2000,2005,2010,2011,…} The year for the sector energy use. The year must be avaliable in the Eurostat report
3 base_emissions_year -- YYYY; e.g. 1990 The base year for the sector emissions. See `European Environment Agency (EEA) <https://www.eea.europa.eu/data-and-maps/data/national-emissions-reported-to-the-unfccc-and-to-the-eu-greenhouse-gas-monitoring-mechanism-16>`_.
eurostat_report_year -- {2016,2017,2018} The publication year of the Eurostat report. 2016 includes Bosnia and Herzegovina, 2017 does not
emissions -- {CO2, All greenhouse gases - (CO2 equivalent)} Specify which sectoral emissions are taken into account. Data derived from EEA. Currently only CO2 is implemented.
4 emissions -- {CO2, All greenhouse gases - (CO2 equivalent)} Specify which sectoral emissions are taken into account. Data derived from EEA. Currently only CO2 is implemented.

View File

@ -9,6 +9,23 @@ Release Notes
Upcoming Release
================
* Corrected a bug leading to power plants operating after their DateOut
(https://github.com/PyPSA/pypsa-eur/pull/958). Added additional grouping years
before 1980.
* The Eurostat data was updated to the 2023 version in :mod:`build_energy_totals`.
* The latest `Swiss energy totals
<https://www.bfe.admin.ch/bfe/de/home/versorgung/statistik-und-geodaten/energiestatistiken/energieverbrauch-nach-verwendungszweck.html/>`_
have been updated to the 2023 version.
* The JRC-IDEES data is only available until 2015. For energy totals years (``energy: energy_totals_year``) after
2015, the data scaled using the ratio of Eurostat data reported for the energy
totals year and 2015.
* The default energy totals year (``energy: energy_totals_year``) was updated to 2019.
* Upgrade default techno-economic assumptions to ``technology-data`` v0.8.1.
* Linearly interpolate missing investment periods in year-dependent

View File

@ -291,7 +291,7 @@ rule build_energy_totals:
swiss="data/switzerland-new_format-all_years.csv",
idees="data/bundle-sector/jrc-idees-2015",
district_heat_share="data/district_heat_share.csv",
eurostat="data/eurostat-energy_balances-june_2021_edition",
eurostat="data/eurostat/eurostat-energy_balances-april_2023_edition",
output:
energy_name=resources("energy_totals.csv"),
co2_name=resources("co2_totals.csv"),
@ -508,7 +508,7 @@ rule build_industrial_production_per_country:
input:
ammonia_production=resources("ammonia_production.csv"),
jrc="data/bundle-sector/jrc-idees-2015",
eurostat="data/bundle-sector/eurostat-energy_balances-may_2018_edition",
eurostat="data/eurostat/eurostat-energy_balances-april_2023_edition",
output:
industrial_production_per_country=resources(
"industrial_production_per_country.csv"
@ -878,7 +878,6 @@ rule prepare_sector_network:
countries=config_provider("countries"),
adjustments=config_provider("adjustments", "sector"),
emissions_scope=config_provider("energy", "emissions"),
eurostat_report_year=config_provider("energy", "eurostat_report_year"),
RDIR=RDIR,
input:
unpack(input_profile_offwind),
@ -909,7 +908,7 @@ rule prepare_sector_network:
),
network=resources("networks/elec_s{simpl}_{clusters}_ec_l{ll}_{opts}.nc"),
energy_totals_name=resources("energy_totals.csv"),
eurostat=input_eurostat,
eurostat="data/eurostat/eurostat-energy_balances-april_2023_edition",
pop_weighted_energy_totals=resources(
"pop_weighted_energy_totals_s{simpl}_{clusters}.csv"
),

View File

@ -130,12 +130,6 @@ def has_internet_access(url="www.zenodo.org") -> bool:
conn.close()
def input_eurostat(w):
# 2016 includes BA, 2017 does not
report_year = config_provider("energy", "eurostat_report_year")(w)
return f"data/bundle-sector/eurostat-energy_balances-june_{report_year}_edition"
def solved_previous_horizon(w):
planning_horizons = config_provider("scenario", "planning_horizons")(w)
i = planning_horizons.index(int(w.planning_horizons))

View File

@ -237,7 +237,6 @@ rule plot_summary:
countries=config_provider("countries"),
planning_horizons=config_provider("scenario", "planning_horizons"),
emissions_scope=config_provider("energy", "emissions"),
eurostat_report_year=config_provider("energy", "eurostat_report_year"),
plotting=config_provider("plotting"),
foresight=config_provider("foresight"),
co2_budget=config_provider("co2_budget"),
@ -247,7 +246,7 @@ rule plot_summary:
costs=RESULTS + "csvs/costs.csv",
energy=RESULTS + "csvs/energy.csv",
balances=RESULTS + "csvs/supply_energy.csv",
eurostat=input_eurostat,
eurostat="data/eurostat/eurostat-energy_balances-april_2023_edition",
co2="data/bundle-sector/eea/UNFCCC_v23.csv",
output:
costs=RESULTS + "graphs/costs.pdf",

View File

@ -135,21 +135,10 @@ if config["enable"]["retrieve"] and config["enable"].get(
"h2_salt_caverns_GWh_per_sqkm.geojson",
]
# TODO: check which versions of eurostat to keep
datafolders = [
protected(
directory("data/bundle-sector/eurostat-energy_balances-june_2016_edition")
),
protected(
directory("data/bundle-sector/eurostat-energy_balances-may_2018_edition")
),
protected(directory("data/bundle-sector/jrc-idees-2015")),
]
rule retrieve_sector_databundle:
output:
protected(expand("data/bundle-sector/{files}", files=datafiles)),
*datafolders,
protected(directory("data/bundle-sector/jrc-idees-2015")),
log:
"logs/retrieve_sector_databundle.log",
retries: 2
@ -158,6 +147,15 @@ if config["enable"]["retrieve"] and config["enable"].get(
script:
"../scripts/retrieve_sector_databundle.py"
rule retrieve_eurostat_data:
output:
directory("data/eurostat/eurostat-energy_balances-april_2023_edition"),
log:
"logs/retrieve_eurostat_data.log",
retries: 2
script:
"../scripts/retrieve_eurostat_data.py"
if config["enable"]["retrieve"]:
datafiles = [

View File

@ -171,10 +171,6 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas
phased_out = df_agg[df_agg["DateOut"] < baseyear].index
df_agg.drop(phased_out, inplace=True)
# calculate remaining lifetime before phase-out (+1 because assuming
# phase out date at the end of the year)
df_agg["lifetime"] = df_agg.DateOut - df_agg.DateIn + 1
# assign clustered bus
busmap_s = pd.read_csv(snakemake.input.busmap_s, index_col=0).squeeze()
busmap = pd.read_csv(snakemake.input.busmap, index_col=0).squeeze()
@ -195,6 +191,10 @@ def add_power_capacities_installed_before_baseyear(n, grouping_years, costs, bas
grouping_years, np.digitize(df_agg.DateIn, grouping_years, right=True)
)
# calculate (adjusted) remaining lifetime before phase-out (+1 because assuming
# phase out date at the end of the year)
df_agg["lifetime"] = df_agg.DateOut - df_agg["grouping_year"] + 1
df = df_agg.pivot_table(
index=["grouping_year", "Fueltype"],
columns="cluster_bus",

View File

@ -8,6 +8,7 @@ Build total energy demands per country using JRC IDEES, eurostat, and EEA data.
import logging
import multiprocessing as mp
import os
from functools import partial
import country_converter as coco
@ -36,8 +37,6 @@ def reverse(dictionary):
return {v: k for k, v in dictionary.items()}
non_EU = ["NO", "CH", "ME", "MK", "RS", "BA", "AL"]
idees_rename = {"GR": "EL", "GB": "UK"}
eu28 = cc.EU28as("ISO2").ISO2.tolist()
@ -70,60 +69,57 @@ to_ipcc = {
}
def eurostat_per_country(country):
country_fn = idees_rename.get(country, country)
fn = (
snakemake.input.eurostat
+ f"/{country_fn}-Energy-balance-sheets-June-2021-edition.xlsb"
)
df = pd.read_excel(
fn,
sheet_name=None,
skiprows=4,
index_col=list(range(3)),
na_values=["+", "-", "=", "Z", ":"],
)
df.pop("Cover")
return pd.concat(df)
def build_eurostat(countries, year=None):
def build_eurostat(input_eurostat, countries, year):
"""
Return multi-index for all countries' energy data in TWh/a.
"""
df = {}
countries = {idees_rename.get(country, country) for country in countries} - {"CH"}
for country in countries:
filename = (
f"{input_eurostat}/{country}-Energy-balance-sheets-April-2023-edition.xlsb"
)
sheet = pd.read_excel(
filename,
engine="pyxlsb",
sheet_name=str(year),
skiprows=4,
index_col=list(range(4)),
)
df[country] = sheet
df = pd.concat(df, axis=0)
nprocesses = snakemake.threads
tqdm_kwargs = dict(
ascii=False,
unit=" country",
total=len(countries),
desc="Build from eurostat database",
# drop columns with all NaNs
unnamed_cols = df.columns[df.columns.astype(str).str.startswith("Unnamed")]
df.drop(unnamed_cols, axis=1, inplace=True)
df.drop(year, axis=1, inplace=True)
# make numeric values where possible
df.replace("Z", 0, inplace=True)
df = df.apply(pd.to_numeric, errors="coerce")
df = df.select_dtypes(include=[np.number])
# write 'International aviation' to the 2nd level of the multiindex
int_avia = df.index.get_level_values(2) == "International aviation"
temp = df.loc[int_avia]
temp.index = pd.MultiIndex.from_frame(
temp.index.to_frame().fillna("International aviation")
)
with mp.Pool(processes=nprocesses) as pool:
dfs = list(tqdm(pool.imap(eurostat_per_country, countries), **tqdm_kwargs))
df = pd.concat([temp, df.loc[~int_avia]])
index_names = ["country", "year", "lvl1", "lvl2", "lvl3"]
df = pd.concat(dfs, keys=countries, names=index_names)
# Renaming some indices
index_rename = {
"Households": "Residential",
"Commercial & public services": "Services",
"Domestic navigation": "Domestic Navigation",
"International maritime bunkers": "Bunkers",
}
columns_rename = {"Total": "Total all products", "UK": "GB"}
df.rename(index=index_rename, columns=columns_rename, inplace=True)
df.sort_index(inplace=True)
df.index.names = [None] * len(df.index.names)
df.dropna(how="all", axis=0, inplace=True)
df.dropna(how="all", axis=1, inplace=True)
df = df[df.index.get_level_values("lvl1") != "ktoe"]
i = df.index.to_frame(index=False)
i.loc[i.lvl2 == "Primary production", ["lvl1", "lvl3"]] = "Main"
i.loc[i.lvl2 == "Gross electricity production", "lvl1"] = "Gross production"
i.ffill(inplace=True)
df.index = pd.MultiIndex.from_frame(i)
df.drop(list(range(1990, 2020)), axis=1, inplace=True)
df.drop("Unnamed: 7", axis=1, inplace=True)
df.fillna(0.0, inplace=True)
# convert ktoe/a to TWh/a
# convert to TWh/a from ktoe/a
df *= 11.63 / 1e3
df.index = df.index.set_levels(df.index.levels[1].astype(int), level=1)
@ -659,7 +655,8 @@ def build_eea_co2(input_co2, year=1990, emissions_scope="CO2"):
return emissions / 1e3
def build_eurostat_co2(countries, eurostat=None, year=1990):
def build_eurostat_co2(input_eurostat, countries, year=1990):
eurostat = build_eurostat(input_eurostat, countries, year)
if eurostat is None:
df = build_eurostat(countries, year)
@ -688,57 +685,17 @@ def build_co2_totals(countries, eea_co2, eurostat_co2):
for ct in pd.Index(countries).intersection(["BA", "RS", "AL", "ME", "MK"]):
mappings = {
"electricity": (
ct,
"Transformation input",
"Electricity & heat generation",
"Main",
),
"residential non-elec": (
ct,
"Final energy consumption",
"Other sectors",
"Households",
),
"services non-elec": (
ct,
"Final energy consumption",
"Other sectors",
"Commercial & public services",
),
"road non-elec": (
ct,
"Final energy consumption",
"Transport sector",
"Road",
),
"rail non-elec": (
ct,
"Final energy consumption",
"Transport sector",
"Rail",
),
"domestic navigation": (
ct,
"Final energy consumption",
"Transport sector",
"Domestic navigation",
),
"international navigation": (ct, "Main", "International maritime bunkers"),
"domestic aviation": (
ct,
"Final energy consumption",
"Transport sector",
"Domestic aviation",
),
"international aviation": (ct, "Main", "International aviation"),
"electricity": (ct, "+", "Electricity & heat generation", np.nan),
"residential non-elec": (ct, "+", "+", "Residential"),
"services non-elec": (ct, "+", "+", "Services"),
"road non-elec": (ct, "+", "+", "Road"),
"rail non-elec": (ct, "+", "+", "Rail"),
"domestic navigation": (ct, "+", "+", "Domestic Navigation"),
"international navigation": (ct, "-", "Bunkers"),
"domestic aviation": (ct, "+", "+", "Domestic aviation"),
"international aviation": (ct, "-", "International aviation"),
# does not include industrial process emissions or fuel processing/refining
"industrial non-elec": (
ct,
"Final energy consumption",
"Industry sector",
"Non-energy use in industry sector",
),
"industrial non-elec": (ct, "+", "Industry sector"),
# does not include non-energy emissions
"agriculture": (eurostat_co2.index.get_level_values(0) == ct)
& eurostat_co2.index.isin(["Agriculture & forestry", "Fishing"], level=3),
@ -786,6 +743,131 @@ def build_transport_data(countries, population, idees):
return transport_data
def rescale_idees_from_eurostat(
idees_countries, energy, eurostat, input_eurostat, countries
):
"""
Takes JRC IDEES data from 2015 and rescales it by the ratio of the eurostat
data and the 2015 eurostat data.
missing data: ['passenger car efficiency', 'passenger cars']
"""
main_cols = ["Total all products", "Electricity"]
# read in the eurostat data for 2015
eurostat_2015 = build_eurostat(input_eurostat, countries, 2015)[main_cols]
eurostat_year = eurostat[main_cols]
# calculate the ratio of the two data sets
ratio = eurostat_year / eurostat_2015
ratio = ratio.droplevel([1, 4])
cols_rename = {"Total all products": "total", "Electricity": "ele"}
index_rename = {v: k for k, v in idees_rename.items()}
ratio.rename(columns=cols_rename, index=index_rename, inplace=True)
mappings = {
"Residential": {
"total": [
"total residential space",
"total residential water",
"total residential cooking",
"total residential",
"derived heat residential",
"thermal uses residential",
],
"elec": [
"electricity residential space",
"electricity residential water",
"electricity residential cooking",
"electricity residential",
],
},
"Services": {
"total": [
"total services space",
"total services water",
"total services cooking",
"total services",
"derived heat services",
"thermal uses services",
],
"elec": [
"electricity services space",
"electricity services water",
"electricity services cooking",
"electricity services",
],
},
"Agriculture & forestry": {
"total": [
"total agriculture heat",
"total agriculture machinery",
"total agriculture",
],
"elec": [
"total agriculture electricity",
],
},
"Road": {
"total": [
"total road",
"total passenger cars",
"total other road passenger",
"total light duty road freight",
],
"elec": [
"electricity road",
"electricity passenger cars",
"electricity other road passenger",
"electricity light duty road freight",
],
},
"Rail": {
"total": [
"total rail",
"total rail passenger",
"total rail freight",
],
"elec": [
"electricity rail",
"electricity rail passenger",
"electricity rail freight",
],
},
}
avia_inter = [
"total aviation passenger",
"total aviation freight",
"total international aviation passenger",
"total international aviation freight",
"total international aviation",
]
avia_domestic = [
"total domestic aviation passenger",
"total domestic aviation freight",
"total domestic aviation",
]
navigation = [
"total domestic navigation",
]
for country in idees_countries:
for sector, mapping in mappings.items():
sector_ratio = ratio.loc[(country, slice(None), sector)]
energy.loc[country, mapping["total"]] *= sector_ratio["total"].iloc[0]
energy.loc[country, mapping["elec"]] *= sector_ratio["ele"].iloc[0]
avi_d = ratio.loc[(country, slice(None), "Domestic aviation"), "total"]
avi_i = ratio.loc[(country, "International aviation", slice(None)), "total"]
energy.loc[country, avia_inter] *= avi_i.iloc[0]
energy.loc[country, avia_domestic] *= avi_d.iloc[0]
nav = ratio.loc[(country, slice(None), "Domestic Navigation"), "total"]
energy.loc[country, navigation] *= nav.iloc[0]
return energy
if __name__ == "__main__":
if "snakemake" not in globals():
from _helpers import mock_snakemake
@ -805,22 +887,32 @@ if __name__ == "__main__":
countries_without_ch = pd.Index(countries).difference(["CH"])
data_year = params["energy_totals_year"]
report_year = snakemake.params.energy["eurostat_report_year"]
input_eurostat = snakemake.input.eurostat
eurostat = build_eurostat(countries_without_ch)
swiss = build_swiss()
idees = build_idees(idees_countries, data_year)
eurostat = build_eurostat(input_eurostat, countries, data_year)
swiss = build_swiss(data_year)
# data from idees only exists from 2000-2015. read in latest data and rescale later
idees = build_idees(idees_countries, min(2015, data_year))
energy = build_energy_totals(countries, eurostat, swiss, idees)
if data_year > 2015:
logger.info("Data year is after 2015. Rescaling IDEES data based on eurostat.")
energy = rescale_idees_from_eurostat(
idees_countries, energy, eurostat, input_eurostat, countries
)
energy.to_csv(snakemake.output.energy_name)
district_heat_share = build_district_heat_share(countries, idees)
# use rescaled idees data to calculate district heat share
district_heat_share = build_district_heat_share(
countries, energy.loc[idees_countries]
)
district_heat_share.to_csv(snakemake.output.district_heat_share)
base_year_emissions = params["base_emissions_year"]
emissions_scope = snakemake.params.energy["emissions"]
eea_co2 = build_eea_co2(snakemake.input.co2, base_year_emissions, emissions_scope)
eurostat_co2 = build_eurostat_co2(countries, eurostat, base_year_emissions)
eurostat_co2 = build_eurostat_co2(input_eurostat, countries, base_year_emissions)
co2 = build_co2_totals(countries, eea_co2, eurostat_co2)
co2.to_csv(snakemake.output.co2_name)

View File

@ -97,33 +97,18 @@ fields = {
"Other Industrial Sectors": "Physical output (index)",
}
eb_names = {
"NO": "Norway",
"AL": "Albania",
"BA": "Bosnia and Herzegovina",
"MK": "FYR of Macedonia",
"GE": "Georgia",
"IS": "Iceland",
"KO": "Kosovo",
"MD": "Moldova",
"ME": "Montenegro",
"RS": "Serbia",
"UA": "Ukraine",
"TR": "Turkey",
}
eb_sectors = {
"Iron & steel industry": "Iron and steel",
"Chemical and Petrochemical industry": "Chemicals Industry",
"Non-ferrous metal industry": "Non-metallic mineral products",
"Paper, Pulp and Print": "Pulp, paper and printing",
"Food and Tabacco": "Food, beverages and tobacco",
"Non-metallic Minerals (Glass, pottery & building mat. Industry)": "Non Ferrous Metals",
"Transport Equipment": "Transport Equipment",
"Iron & steel": "Iron and steel",
"Chemical & petrochemical": "Chemicals Industry",
"Non-ferrous metals": "Non-metallic mineral products",
"Paper, pulp & printing": "Pulp, paper and printing",
"Food, beverages & tobacco": "Food, beverages and tobacco",
"Non-metallic minerals": "Non Ferrous Metals",
"Transport equipment": "Transport Equipment",
"Machinery": "Machinery Equipment",
"Textile and Leather": "Textiles and leather",
"Wood and Wood Products": "Wood and wood products",
"Non-specified (Industry)": "Other Industrial Sectors",
"Textile & leather": "Textiles and leather",
"Wood & wood products": "Wood and wood products",
"Not elsewhere specified (industry)": "Other Industrial Sectors",
}
# TODO: this should go in a csv in `data`
@ -160,12 +145,15 @@ def get_energy_ratio(country, eurostat_dir, jrc_dir, year):
e_country = e_switzerland * tj_to_ktoe
else:
# estimate physical output, energy consumption in the sector and country
fn = f"{eurostat_dir}/{eb_names[country]}.XLSX"
with mute_print():
df = pd.read_excel(
fn, sheet_name="2016", index_col=2, header=0, skiprows=1
).squeeze("columns")
e_country = df.loc[eb_sectors.keys(), "Total all products"].rename(eb_sectors)
fn = f"{eurostat_dir}/{country}-Energy-balance-sheets-April-2023-edition.xlsb"
df = pd.read_excel(
fn,
sheet_name=str(min(2021, year)),
index_col=2,
header=0,
skiprows=4,
)
e_country = df.loc[eb_sectors.keys(), "Total"].rename(eb_sectors)
fn = f"{jrc_dir}/JRC-IDEES-2015_Industry_EU28.xlsx"

View File

@ -462,7 +462,6 @@ def plot_carbon_budget_distribution(input_eurostat, options):
plt.rcParams["ytick.labelsize"] = 20
emissions_scope = snakemake.params.emissions_scope
report_year = snakemake.params.eurostat_report_year
input_co2 = snakemake.input.co2
# historic emissions
@ -472,7 +471,6 @@ def plot_carbon_budget_distribution(input_eurostat, options):
input_eurostat,
options,
emissions_scope,
report_year,
input_co2,
year=1990,
)

View File

@ -248,7 +248,7 @@ def get(item, investment_year=None):
def co2_emissions_year(
countries, input_eurostat, options, emissions_scope, report_year, input_co2, year
countries, input_eurostat, options, emissions_scope, input_co2, year
):
"""
Calculate CO2 emissions in one specific year (e.g. 1990 or 2018).
@ -258,11 +258,9 @@ def co2_emissions_year(
# TODO: read Eurostat data from year > 2014
# this only affects the estimation of CO2 emissions for BA, RS, AL, ME, MK
if year > 2014:
eurostat_co2 = build_eurostat_co2(
input_eurostat, countries, report_year, year=2014
)
eurostat_co2 = build_eurostat_co2(input_eurostat, countries, 2014)
else:
eurostat_co2 = build_eurostat_co2(input_eurostat, countries, report_year, year)
eurostat_co2 = build_eurostat_co2(input_eurostat, countries, year)
co2_totals = build_co2_totals(countries, eea_co2, eurostat_co2)
@ -277,9 +275,7 @@ def co2_emissions_year(
# TODO: move to own rule with sector-opts wildcard?
def build_carbon_budget(
o, input_eurostat, fn, emissions_scope, report_year, input_co2, options
):
def build_carbon_budget(o, input_eurostat, fn, emissions_scope, input_co2, options):
"""
Distribute carbon budget following beta or exponential transition path.
"""
@ -300,7 +296,6 @@ def build_carbon_budget(
input_eurostat,
options,
emissions_scope,
report_year,
input_co2,
year=1990,
)
@ -311,7 +306,6 @@ def build_carbon_budget(
input_eurostat,
options,
emissions_scope,
report_year,
input_co2,
year=2018,
)
@ -3678,14 +3672,12 @@ if __name__ == "__main__":
fn = "results/" + snakemake.params.RDIR + "/csvs/carbon_budget_distribution.csv"
if not os.path.exists(fn):
emissions_scope = snakemake.params.emissions_scope
report_year = snakemake.params.eurostat_report_year
input_co2 = snakemake.input.co2
build_carbon_budget(
co2_budget,
snakemake.input.eurostat,
fn,
emissions_scope,
report_year,
input_co2,
options,
)

View File

@ -0,0 +1,43 @@
# -*- coding: utf-8 -*-
# SPDX-FileCopyrightText: : 2024- The PyPSA-Eur Authors
#
# SPDX-License-Identifier: MIT
"""
Retrieve and extract eurostat energy balances data.
"""
import logging
import zipfile
from pathlib import Path
from _helpers import configure_logging, progress_retrieve, set_scenario_config
logger = logging.getLogger(__name__)
if __name__ == "__main__":
if "snakemake" not in globals():
from _helpers import mock_snakemake
snakemake = mock_snakemake("retrieve_eurostat_data")
rootpath = ".."
else:
rootpath = "."
configure_logging(snakemake)
set_scenario_config(snakemake)
disable_progress = snakemake.config["run"].get("disable_progressbar", False)
url_eurostat = "https://ec.europa.eu/eurostat/documents/38154/4956218/Balances-December2022.zip/f7cf0d19-5c0f-60ad-4e48-098a5ddd6e48?t=1671184070589"
tarball_fn = Path(f"{rootpath}/data/eurostat/eurostat_2023.zip")
to_fn = Path(
f"{rootpath}/data/eurostat/eurostat-energy_balances-april_2023_edition/"
)
logger.info(f"Downloading Eurostat data from '{url_eurostat}'.")
progress_retrieve(url_eurostat, tarball_fn, disable=disable_progress)
logger.info("Extracting Eurostat data.")
with zipfile.ZipFile(tarball_fn, "r") as zip_ref:
zip_ref.extractall(to_fn)
logger.info(f"Eurostat data available in '{to_fn}'.")