Merge branch 'master' into scenario-management

This commit is contained in:
Fabian Neumann 2024-02-17 17:04:36 +01:00
commit d2a66879de
17 changed files with 303 additions and 75 deletions

2
.gitignore vendored
View File

@ -30,6 +30,8 @@ doc/_build
config/config.yaml
config/scenarios.yaml
config.yaml
config/config.yaml
dconf
/data/links_p_nom.csv

View File

@ -317,7 +317,7 @@ pypsa_eur:
# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#energy
energy:
energy_totals_year: 2011
energy_totals_year: 2013
base_emissions_year: 1990
eurostat_report_year: 2016
emissions: CO2
@ -504,6 +504,7 @@ sector:
SMR_cc: true
regional_methanol_demand: false
regional_oil_demand: false
regional_coal_demand: false
regional_co2_sequestration_potential:
enable: false
attribute: 'conservative estimate Mt'
@ -541,8 +542,8 @@ sector:
efficiency_static: 0.98
efficiency_per_1000km: 0.977
H2 pipeline:
efficiency_per_1000km: 1 # 0.979
compression_per_1000km: 0.019
efficiency_per_1000km: 1 # 0.982
compression_per_1000km: 0.018
gas pipeline:
efficiency_per_1000km: 1 #0.977
compression_per_1000km: 0.01
@ -639,6 +640,15 @@ industry:
2040: 0.12
2045: 0.16
2050: 0.20
sector_ratios_fraction_future:
2020: 0.0
2025: 0.1
2030: 0.3
2035: 0.5
2040: 0.7
2045: 0.9
2050: 1.0
basic_chemicals_without_NH3_production_today: 69. #Mt/a, = 86 Mtethylene-equiv - 17 MtNH3
HVC_production_today: 52.
MWh_elec_per_tHVC_mechanical_recycling: 0.547
MWh_elec_per_tHVC_chemical_recycling: 6.9

View File

@ -0,0 +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.
1 country item 2010 2011 2012 2013 2014 2015
2 CH total residential 268.2 223.4 243.4 261.3 214.2 229.1
3 CH total residential space 192.2 149.0 168.1 185.5 139.7 154.4
4 CH total residential water 32.2 31.6 31.9 32.2 31.7 31.9
5 CH total residential cooking 9.3 9.3 9.3 9.4 9.5 9.6
6 CH electricity residential 67.9 63.7 65.7 67.6 63.0 64.4
7 CH electricity residential space 15.9 12.8 14.3 15.8 12.3 13.5
8 CH electricity residential water 8.8 8.5 8.5 8.6 8.5 8.6
9 CH electricity residential cooking 4.9 4.9 4.9 4.9 5.0 5.0
10 CH total services 145.9 127.4 136.7 144.0 124.5 132.5
11 CH total services space 80.0 62.2 70.8 77.4 58.3 64.3
12 CH total services water 10.1 10.0 10.1 10.1 10.0 10.0
13 CH total services cooking 2.5 2.4 2.3 2.3 2.4 2.3
14 CH electricity services 60.5 59.2 60.3 61.4 60.3 62.6
15 CH electricity services space 4.0 3.2 3.8 4.2 3.3 3.6
16 CH electricity services water 0.7 0.7 0.7 0.7 0.7 0.7
17 CH electricity services cooking 2.5 2.4 2.3 2.3 2.4 2.3
18 CH total rail 11.5 11.1 11.2 11.4 11.1 11.4
19 CH total road 199.4 200.4 200.4 201.2 202.0 203.1
20 CH electricity road 0. 0. 0. 0. 0. 0.
21 CH electricity rail 11.5 11.1 11.2 11.4 11.1 11.4
22 CH total domestic aviation 3.3 3.2 3.4 3.4 3.5 3.5
23 CH total international aviation 58.0 62.0 63.5 64.2 64.5 66.8
24 CH total domestic navigation 1.6 1.6 1.6 1.6 1.6 1.6
25 CH total international navigation 0. 0. 0. 0. 0. 0.

View File

@ -17,6 +17,8 @@ HVC_primary_fraction,--,float,The fraction of high value chemicals (HVC) produce
HVC_mechanical_recycling _fraction,--,float,The fraction of high value chemicals (HVC) produced using mechanical recycling
HVC_chemical_recycling _fraction,--,float,The fraction of high value chemicals (HVC) produced using chemical recycling
,,,
sector_ratios_fraction_future,--,Dictionary with planning horizons as keys.,The fraction of total progress in fuel and process switching achieved in the industry sector.
basic_chemicals_without_NH3_production_today,Mt/a,float,"The amount of basic chemicals produced without ammonia (= 86 Mtethylene-equiv - 17 MtNH3)."
HVC_production_today,MtHVC/a,float,"The amount of high value chemicals (HVC) produced. This includes ethylene, propylene and BTX. From `DECHEMA (2017) <https://dechema.de/dechema_media/Downloads/Positionspapiere/Technology_study_Low_carbon_energy_and_feedstock_for_the_European_chemical_industry-p-20002750.pdf>`_, Figure 16, page 107"
Mwh_elec_per_tHVC _mechanical_recycling,MWh/tHVC,float,"The energy amount of electricity needed to produce a ton of high value chemical (HVC) using mechanical recycling. From SI of `Meys et al (2020) <https://doi.org/10.1016/j.resconrec.2020.105010>`_, Table S5, for HDPE, PP, PS, PET. LDPE would be 0.756."
Mwh_elec_per_tHVC _chemical_recycling,MWh/tHVC,float,"The energy amount of electricity needed to produce a ton of high value chemical (HVC) using chemical recycling. The default value is based on pyrolysis and electric steam cracking. From `Material Economics (2019) <https://materialeconomics.com/latest-updates/industrial-transformation-2050>`_, page 125"

1 Unit Values Description
17 HVC_mechanical_recycling _fraction -- float The fraction of high value chemicals (HVC) produced using mechanical recycling
18 HVC_chemical_recycling _fraction -- float The fraction of high value chemicals (HVC) produced using chemical recycling
19
20 sector_ratios_fraction_future -- Dictionary with planning horizons as keys. The fraction of total progress in fuel and process switching achieved in the industry sector.
21 basic_chemicals_without_NH3_production_today Mt/a float The amount of basic chemicals produced without ammonia (= 86 Mtethylene-equiv - 17 MtNH3).
22 HVC_production_today MtHVC/a float The amount of high value chemicals (HVC) produced. This includes ethylene, propylene and BTX. From `DECHEMA (2017) <https://dechema.de/dechema_media/Downloads/Positionspapiere/Technology_study_Low_carbon_energy_and_feedstock_for_the_European_chemical_industry-p-20002750.pdf>`_, Figure 16, page 107
23 Mwh_elec_per_tHVC _mechanical_recycling MWh/tHVC float The energy amount of electricity needed to produce a ton of high value chemical (HVC) using mechanical recycling. From SI of `Meys et al (2020) <https://doi.org/10.1016/j.resconrec.2020.105010>`_, Table S5, for HDPE, PP, PS, PET. LDPE would be 0.756.
24 Mwh_elec_per_tHVC _chemical_recycling MWh/tHVC float The energy amount of electricity needed to produce a ton of high value chemical (HVC) using chemical recycling. The default value is based on pyrolysis and electric steam cracking. From `Material Economics (2019) <https://materialeconomics.com/latest-updates/industrial-transformation-2050>`_, page 125

View File

@ -17,6 +17,29 @@ Upcoming Release
names to run under ``run: name:`` in the configuration file. The latter must
be a subset of toplevel keys in the scenario file.
* Improved representation of industry transition pathways. A new script was
added to interpolate industry sector ratios from today's status quo to future
systems (i.e. specific emissions and demands for energy and feedstocks). For
each country we gradually switch industry processes from today's specific
energy carrier usage per ton material output to the best-in-class energy
consumption of tomorrow. This is done on a per-country basis. The ratio of
today to tomorrow's energy consumption is set with the ``industry:
sector_ratios_fraction_future:`` parameter.
* Fix plotting of retrofitted hydrogen pipelines with pathway optimisation.
* Bugfix: Correct units of subtracted chlorine and methanol demand in
:mod:`build_industry_sector_ratios`.
* Include all countries in ammonia production resource. This is so that the full
EU28 ammonia demand can be correctly subtracted in the rule
:mod:`build_industry_sector_ratios`.
* Regions are assigned to all buses with unique coordinates in the network with
a preference given to substations. Previously, only substations had assigned
regions, but this could lead to issues when a high spatial resolution was
applied.
* The default configuration ``config/config.default.yaml`` is now automatically
used as a base configuration file and no longer copied to
``config/config.yaml`` on first use. The file ``config/config.yaml`` should be
@ -24,6 +47,10 @@ Upcoming Release
* Merged two OPSD time series data versions into such that the option ``load:
power_statistics:`` becomes superfluous and was hence removed.
* Bugfix: The industry coal emissions for industry were not properly tracked.
* Allow industrial coal demand to be regional so its emissions can be included
in regional emission limits.
* 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
@ -120,6 +147,8 @@ Upcoming Release
workflows with foresight "myopic" and still needs to be added foresight option
"perfect".
* Switched the energy totals year from 2011 to 2013 to comply with the assumed default weather year.
PyPSA-Eur 0.9.0 (5th January 2024)
==================================

View File

@ -279,7 +279,7 @@ rule build_energy_totals:
input:
nuts3_shapes=resources("nuts3_shapes.geojson"),
co2="data/bundle-sector/eea/UNFCCC_v23.csv",
swiss="data/bundle-sector/switzerland-sfoe/switzerland-new_format.csv",
swiss="data/switzerland-new_format-all_years.csv",
idees="data/bundle-sector/jrc-idees-2015",
district_heat_share="data/district_heat_share.csv",
eurostat=input_eurostat,
@ -406,8 +406,6 @@ rule build_salt_cavern_potentials:
rule build_ammonia_production:
params:
countries=config_provider("countries"),
input:
usgs="data/bundle-sector/myb1-2017-nitro.xls",
output:
@ -447,6 +445,31 @@ rule build_industry_sector_ratios:
"../scripts/build_industry_sector_ratios.py"
rule build_industry_sector_ratios_intermediate:
params:
industry=config["industry"],
input:
industry_sector_ratios=RESOURCES + "industry_sector_ratios.csv",
industrial_energy_demand_per_country_today=RESOURCES
+ "industrial_energy_demand_per_country_today.csv",
industrial_production_per_country=RESOURCES
+ "industrial_production_per_country.csv",
output:
industry_sector_ratios=RESOURCES
+ "industry_sector_ratios_{planning_horizons}.csv",
threads: 1
resources:
mem_mb=1000,
log:
LOGS + "build_industry_sector_ratios_{planning_horizons}.log",
benchmark:
BENCHMARKS + "build_industry_sector_ratios_{planning_horizons}"
conda:
"../envs/environment.yaml"
script:
"../scripts/build_industry_sector_ratios_intermediate.py"
rule build_industrial_production_per_country:
params:
industry=config_provider("industry"),
@ -560,7 +583,7 @@ rule build_industrial_production_per_node:
rule build_industrial_energy_demand_per_node:
input:
industry_sector_ratios=resources("industry_sector_ratios.csv"),
industry_sector_ratios=resources("industry_sector_ratios_{planning_horizons}.csv"),
industrial_production_per_node=resources(
"industrial_production_elec_s{simpl}_{clusters}_{planning_horizons}.csv"
),
@ -596,7 +619,6 @@ rule build_industrial_energy_demand_per_country_today:
industry=config_provider("industry"),
input:
jrc="data/bundle-sector/jrc-idees-2015",
ammonia_production=resources("ammonia_production.csv"),
industrial_production_per_country=resources(
"industrial_production_per_country.csv"
),

View File

@ -559,6 +559,7 @@ def _set_countries_and_substations(n, config, country_shapes, offshore_shapes):
for b, df in product(("bus0", "bus1"), (n.lines, n.links)):
has_connections_b |= ~df.groupby(b).under_construction.min()
buses["onshore_bus"] = onshore_b
buses["substation_lv"] = (
lv_b & onshore_b & (~buses["under_construction"]) & has_connections_b
)

View File

@ -28,13 +28,14 @@ if __name__ == "__main__":
header=0,
index_col=0,
skipfooter=19,
na_values=["--"],
)
ammonia.index = cc.convert(ammonia.index, to="iso2")
years = [str(i) for i in range(2013, 2018)]
countries = ammonia.index.intersection(snakemake.params.countries)
ammonia = ammonia.loc[countries, years].astype(float)
ammonia = ammonia[years]
# convert from ktonN to ktonNH3
ammonia *= 17 / 14

View File

@ -136,7 +136,13 @@ if __name__ == "__main__":
c_b = n.buses.country == country
onshore_shape = country_shapes[country]
onshore_locs = n.buses.loc[c_b & n.buses.substation_lv, ["x", "y"]]
onshore_locs = (
n.buses.loc[c_b & n.buses.onshore_bus]
.sort_values(
by="substation_lv", ascending=False
) # preference for substations
.drop_duplicates(subset=["x", "y"], keep="first")[["x", "y"]]
)
onshore_regions.append(
gpd.GeoDataFrame(
{

View File

@ -74,7 +74,7 @@ def industrial_energy_demand_per_country(country, year, jrc_dir):
def get_subsector_data(sheet):
df = df_dict[sheet][year].groupby(fuels).sum()
df["ammonia"] = 0.0
df["hydrogen"] = 0.0
df["other"] = df["all"] - df.loc[df.index != "all"].sum()
@ -95,51 +95,50 @@ def industrial_energy_demand_per_country(country, year, jrc_dir):
return df
def add_ammonia_energy_demand(demand):
# MtNH3/a
fn = snakemake.input.ammonia_production
ammonia = pd.read_csv(fn, index_col=0)[str(year)] / 1e3
def separate_basic_chemicals(demand, production):
def get_ammonia_by_fuel(x):
fuels = {
"gas": params["MWh_CH4_per_tNH3_SMR"],
"electricity": params["MWh_elec_per_tNH3_SMR"],
ammonia = pd.DataFrame(
{
"hydrogen": production["Ammonia"] * params["MWh_H2_per_tNH3_electrolysis"],
"electricity": production["Ammonia"]
* params["MWh_elec_per_tNH3_electrolysis"],
}
return pd.Series({k: x * v for k, v in fuels.items()})
ammonia_by_fuel = ammonia.apply(get_ammonia_by_fuel).T
ammonia_by_fuel = ammonia_by_fuel.unstack().reindex(
index=demand.index, fill_value=0.0
)
ammonia = pd.DataFrame({"ammonia": ammonia * params["MWh_NH3_per_tNH3"]}).T
).T
chlorine = pd.DataFrame(
{
"hydrogen": production["Chlorine"] * params["MWh_H2_per_tCl"],
"electricity": production["Chlorine"] * params["MWh_elec_per_tCl"],
}
).T
methanol = pd.DataFrame(
{
"gas": production["Methanol"] * params["MWh_CH4_per_tMeOH"],
"electricity": production["Methanol"] * params["MWh_elec_per_tMeOH"],
}
).T
demand["Ammonia"] = ammonia.unstack().reindex(index=demand.index, fill_value=0.0)
demand["Chlorine"] = chlorine.unstack().reindex(index=demand.index, fill_value=0.0)
demand["Methanol"] = methanol.unstack().reindex(index=demand.index, fill_value=0.0)
demand["Basic chemicals (without ammonia)"] = (
demand["Basic chemicals"] - ammonia_by_fuel
demand["HVC"] = (
demand["Basic chemicals"]
- demand["Ammonia"]
- demand["Methanol"]
- demand["Chlorine"]
)
demand["Basic chemicals (without ammonia)"].clip(lower=0, inplace=True)
demand.drop(columns="Basic chemicals", inplace=True)
demand["HVC"].clip(lower=0, inplace=True)
return demand
def add_non_eu28_industrial_energy_demand(countries, demand):
def add_non_eu28_industrial_energy_demand(countries, demand, production):
non_eu28 = countries.difference(eu28)
if non_eu28.empty:
return demand
# output in MtMaterial/a
fn = snakemake.input.industrial_production_per_country
production = pd.read_csv(fn, index_col=0) / 1e3
# recombine HVC, Chlorine and Methanol to Basic chemicals (without ammonia)
chemicals = ["HVC", "Chlorine", "Methanol"]
production["Basic chemicals (without ammonia)"] = production[chemicals].sum(axis=1)
production.drop(columns=chemicals, inplace=True)
eu28_production = production.loc[countries.intersection(eu28)].sum()
eu28_energy = demand.groupby(level=1).sum()
@ -184,9 +183,15 @@ if __name__ == "__main__":
demand = industrial_energy_demand(countries.intersection(eu28), year)
demand = add_ammonia_energy_demand(demand)
# output in MtMaterial/a
production = (
pd.read_csv(snakemake.input.industrial_production_per_country, index_col=0)
/ 1e3
)
demand = add_non_eu28_industrial_energy_demand(countries, demand)
demand = separate_basic_chemicals(demand, production)
demand = add_non_eu28_industrial_energy_demand(countries, demand, production)
# for format compatibility
demand = demand.stack(dropna=False).unstack(level=[0, 2])

View File

@ -21,23 +21,31 @@ if __name__ == "__main__":
)
set_scenario_config(snakemake)
# import EU ratios df as csv
# import ratios
fn = snakemake.input.industry_sector_ratios
industry_sector_ratios = pd.read_csv(fn, index_col=0)
sector_ratios = pd.read_csv(fn, header=[0, 1], index_col=0)
# material demand per node and industry (kton/a)
# material demand per node and industry (Mton/a)
fn = snakemake.input.industrial_production_per_node
nodal_production = pd.read_csv(fn, index_col=0)
nodal_production = pd.read_csv(fn, index_col=0) / 1e3
# energy demand today to get current electricity
fn = snakemake.input.industrial_energy_demand_per_node_today
nodal_today = pd.read_csv(fn, index_col=0)
# final energy consumption per node and industry (TWh/a)
nodal_df = nodal_production.dot(industry_sector_ratios.T)
nodal_sector_ratios = pd.concat(
{node: sector_ratios[node[:2]] for node in nodal_production.index}, axis=1
)
# convert GWh to TWh and ktCO2 to MtCO2
nodal_df *= 0.001
nodal_production_stacked = nodal_production.stack()
nodal_production_stacked.index.names = [None, None]
# final energy consumption per node and industry (TWh/a)
nodal_df = (
(nodal_sector_ratios.multiply(nodal_production_stacked))
.T.groupby(level=0)
.sum()
)
rename_sectors = {
"elec": "electricity",

View File

@ -261,7 +261,11 @@ def separate_basic_chemicals(demand, year):
demand["Basic chemicals"].clip(lower=0.0, inplace=True)
# assume HVC, methanol, chlorine production proportional to non-ammonia basic chemicals
distribution_key = demand["Basic chemicals"] / demand["Basic chemicals"].sum()
distribution_key = (
demand["Basic chemicals"]
/ params["basic_chemicals_without_NH3_production_today"]
/ 1e3
)
demand["HVC"] = params["HVC_production_today"] * 1e3 * distribution_key
demand["Chlorine"] = params["chlorine_production_today"] * 1e3 * distribution_key
demand["Methanol"] = params["methanol_production_today"] * 1e3 * distribution_key

View File

@ -408,15 +408,15 @@ def chemicals_industry():
df.loc["methane", sector] -= ammonia_total * params["MWh_CH4_per_tNH3_SMR"]
df.loc["elec", sector] -= ammonia_total * params["MWh_elec_per_tNH3_SMR"]
# subtract chlorine demand
# subtract chlorine demand (in MtCl/a)
chlorine_total = params["chlorine_production_today"]
df.loc["hydrogen", sector] -= chlorine_total * params["MWh_H2_per_tCl"]
df.loc["elec", sector] -= chlorine_total * params["MWh_elec_per_tCl"]
df.loc["hydrogen", sector] -= chlorine_total * params["MWh_H2_per_tCl"] * 1e3
df.loc["elec", sector] -= chlorine_total * params["MWh_elec_per_tCl"] * 1e3
# subtract methanol demand
# subtract methanol demand (in MtMeOH/a)
methanol_total = params["methanol_production_today"]
df.loc["methane", sector] -= methanol_total * params["MWh_CH4_per_tMeOH"]
df.loc["elec", sector] -= methanol_total * params["MWh_elec_per_tMeOH"]
df.loc["methane", sector] -= methanol_total * params["MWh_CH4_per_tMeOH"] * 1e3
df.loc["elec", sector] -= methanol_total * params["MWh_elec_per_tMeOH"] * 1e3
# MWh/t material
df.loc[sources, sector] = df.loc[sources, sector] / s_out

View File

@ -0,0 +1,81 @@
# -*- coding: utf-8 -*-
# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors
#
# SPDX-License-Identifier: MIT
"""
Build specific energy consumption by carrier and industries and by country,
that interpolates between the current average energy consumption (from
2015-2020) and the ideal future best-in-class consumption.
"""
import pandas as pd
from prepare_sector_network import get
def build_industry_sector_ratios_intermediate():
# in TWh/a
demand = pd.read_csv(
snakemake.input.industrial_energy_demand_per_country_today,
header=[0, 1],
index_col=0,
)
# in Mt/a
production = (
pd.read_csv(snakemake.input.industrial_production_per_country, index_col=0)
/ 1e3
).stack()
production.index.names = [None, None]
# in MWh/t
future_sector_ratios = pd.read_csv(
snakemake.input.industry_sector_ratios, index_col=0
)
today_sector_ratios = demand.div(production, axis=1)
today_sector_ratios.dropna(how="all", axis=1, inplace=True)
rename = {
"waste": "biomass",
"electricity": "elec",
"solid": "coke",
"gas": "methane",
"other": "biomass",
"liquid": "naphtha",
}
today_sector_ratios = today_sector_ratios.rename(rename).groupby(level=0).sum()
fraction_future = get(params["sector_ratios_fraction_future"], year)
intermediate_sector_ratios = {}
for ct, group in today_sector_ratios.T.groupby(level=0):
today_sector_ratios_ct = (
group.droplevel(0)
.T.reindex_like(future_sector_ratios)
.fillna(future_sector_ratios)
)
intermediate_sector_ratios[ct] = (
today_sector_ratios_ct * (1 - fraction_future)
+ future_sector_ratios * fraction_future
)
intermediate_sector_ratios = pd.concat(intermediate_sector_ratios, axis=1)
intermediate_sector_ratios.to_csv(snakemake.output.industry_sector_ratios)
if __name__ == "__main__":
if "snakemake" not in globals():
from _helpers import mock_snakemake
snakemake = mock_snakemake(
"build_industry_sector_ratios_intermediate",
planning_horizons="2030",
)
year = int(snakemake.wildcards.planning_horizons[-4:])
params = snakemake.params.industry
build_industry_sector_ratios_intermediate()

View File

@ -24,6 +24,7 @@ def group_pipes(df, drop_direction=False):
"""
Group pipes which connect same buses and return overall capacity.
"""
df = df.copy()
if drop_direction:
positive_order = df.bus0 < df.bus1
df_p = df[positive_order]
@ -32,12 +33,13 @@ def group_pipes(df, drop_direction=False):
df = pd.concat([df_p, df_n])
# there are pipes for each investment period rename to AC buses name for plotting
df["index_orig"] = df.index
df.index = df.apply(
lambda x: f"H2 pipeline {x.bus0.replace(' H2', '')} -> {x.bus1.replace(' H2', '')}",
axis=1,
)
return df.groupby(level=0).agg(
{"p_nom_opt": "sum", "bus0": "first", "bus1": "first"}
{"p_nom_opt": "sum", "bus0": "first", "bus1": "first", "index_orig": "first"}
)
@ -95,17 +97,18 @@ def plot_h2_map(n, regions):
)
if not h2_retro.empty:
positive_order = h2_retro.bus0 < h2_retro.bus1
h2_retro_p = h2_retro[positive_order]
swap_buses = {"bus0": "bus1", "bus1": "bus0"}
h2_retro_n = h2_retro[~positive_order].rename(columns=swap_buses)
h2_retro = pd.concat([h2_retro_p, h2_retro_n])
if snakemake.params.foresight != "myopic":
positive_order = h2_retro.bus0 < h2_retro.bus1
h2_retro_p = h2_retro[positive_order]
swap_buses = {"bus0": "bus1", "bus1": "bus0"}
h2_retro_n = h2_retro[~positive_order].rename(columns=swap_buses)
h2_retro = pd.concat([h2_retro_p, h2_retro_n])
h2_retro["index_orig"] = h2_retro.index
h2_retro.index = h2_retro.apply(
lambda x: f"H2 pipeline {x.bus0.replace(' H2', '')} -> {x.bus1.replace(' H2', '')}",
axis=1,
)
h2_retro["index_orig"] = h2_retro.index
h2_retro.index = h2_retro.apply(
lambda x: f"H2 pipeline {x.bus0.replace(' H2', '')} -> {x.bus1.replace(' H2', '')}",
axis=1,
)
retro_w_new_i = h2_retro.index.intersection(h2_new.index)
h2_retro_w_new = h2_retro.loc[retro_w_new_i]

View File

@ -176,6 +176,13 @@ def define_spatial(nodes, options):
spatial.coal.nodes = ["EU coal"]
spatial.coal.locations = ["EU"]
if options["regional_coal_demand"]:
spatial.coal.demand_locations = nodes
spatial.coal.industry = nodes + " coal for industry"
else:
spatial.coal.demand_locations = ["EU"]
spatial.coal.industry = ["EU coal for industry"]
# lignite
spatial.lignite = SimpleNamespace()
spatial.lignite.nodes = ["EU lignite"]
@ -3052,19 +3059,40 @@ def add_industry(n, costs):
mwh_coal_per_mwh_coke = 1.366 # from eurostat energy balance
p_set = (
industrial_demand["coal"].sum()
+ mwh_coal_per_mwh_coke * industrial_demand["coke"].sum()
industrial_demand["coal"]
+ mwh_coal_per_mwh_coke * industrial_demand["coke"]
) / nhours
if not options["regional_coal_demand"]:
p_set = p_set.sum()
n.madd(
"Bus",
spatial.coal.industry,
location=spatial.coal.demand_locations,
carrier="coal for industry",
unit="MWh_LHV",
)
n.madd(
"Load",
spatial.coal.nodes,
suffix=" for industry",
bus=spatial.coal.nodes,
spatial.coal.industry,
bus=spatial.coal.industry,
carrier="coal for industry",
p_set=p_set,
)
n.madd(
"Link",
spatial.coal.industry,
bus0=spatial.coal.nodes,
bus1=spatial.coal.industry,
bus2="co2 atmosphere",
carrier="coal for industry",
p_nom_extendable=True,
efficiency2=costs.at["coal", "CO2 intensity"],
)
def add_waste_heat(n):
# TODO options?

View File

@ -612,6 +612,7 @@ if __name__ == "__main__":
"symbol",
"tags",
"under_construction",
"onshore_bus",
"substation_lv",
"substation_off",
"geometry",