Skip to content

Commit

Permalink
Merge branch 'main' into memory-efficiency-ariadne-report
Browse files Browse the repository at this point in the history
  • Loading branch information
lindnemi authored Nov 19, 2024
2 parents 3fe33fd + f406e1b commit c780a3c
Show file tree
Hide file tree
Showing 8 changed files with 574 additions and 61 deletions.
10 changes: 5 additions & 5 deletions config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

# docs in https://pypsa-eur.readthedocs.io/en/latest/configuration.html#run
run:
prefix: 20241108-limit-ft-meoh
prefix: 20241113-export-kernnetz-invest

name:
# - CurrentPolicies
Expand Down Expand Up @@ -253,6 +253,8 @@ wasserstoff_kernnetz:
pipes_segment_length: 10
border_crossing: true
aggregate_build_years: "mean"
recalculate_length: true
aggregate_parallel_pipes: true
ipcei_pci_only: false
cutoff_year: 2028
force_all_ipcei_pci: true
Expand Down Expand Up @@ -415,15 +417,13 @@ solving:
DC: 1000
gas pipeline: 1500
gas pipeline new: 1500
H2 pipeline: 13000
H2 pipeline (Kernnetz): 13000
H2 pipeline retrofitted: 13000
H2 pipeline: 4700
H2 pipeline retrofitted: 4700
link_threshold:
DC: 0.3
gas pipeline: 0.3
gas pipeline new: 0.3
H2 pipeline: 0.05
H2 pipeline (Kernnetz): 0.05
H2 pipeline retrofitted: 0.05
fractional_last_unit_size: true
constraints:
Expand Down
1 change: 1 addition & 0 deletions workflow/Snakefile
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,7 @@ rule plot_ariadne_variables:
NEP_Trassen_plot=RESULTS + "ariadne/NEP_Trassen_plot.png",
transmission_investment_csv=RESULTS + "ariadne/transmission_investment.csv",
trassenlaenge_csv=RESULTS + "ariadne/trassenlaenge.csv",
Kernnetz_Investment_plot=RESULTS + "ariadne/Kernnetz_Investment_plot.png",
log:
RESULTS + "logs/plot_ariadne_variables.log",
script:
Expand Down
12 changes: 7 additions & 5 deletions workflow/scripts/build_wasserstoff_kernnetz.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,18 @@ def diameter_to_capacity_h2(pipe_diameter_mm):
Calculate pipe capacity in MW based on diameter in mm. Linear
interpolation.
20 inch (500 mm) 50 bar -> 1.2 GW H2 pipe capacity (LHV) 36 inch
(900 mm) 50 bar -> 4.7 GW H2 pipe capacity (LHV) 48 inch (1200
mm) 80 bar -> 16.9 GW H2 pipe capacity (LHV)
20 inch (500 mm) 50 bar -> 1.2 GW H2 pipe capacity (LHV)
36 inch (900 mm) 50 bar -> 4.7 GW H2 pipe capacity (LHV)
48 inch (1200mm) 80 bar -> 13.0 GW H2 pipe capacity (LHV)
Based on table 4 of
old source: table 4 of
https://ehb.eu/files/downloads/EHB-Analysing-the-future-demand-supply-and-transport-of-hydrogen-June-2021-v3.pdf
new source: https://github.com/PyPSA/pypsa-ariadne/pull/167
"""
# slopes definitions
m0 = (1200 - 0) / (500 - 0)
m1 = (4700 - 1200) / (900 - 500)
m2 = (16900 - 4700) / (1200 - 900)
m2 = (13000 - 4700) / (1200 - 900)
# intercepts
a0 = 0
a1 = 1200 - m1 * 500
Expand Down Expand Up @@ -569,6 +570,7 @@ def filter_kernnetz(
snakemake.input.wasserstoff_kernnetz_3,
)
logger.info("Data retrievel successful. Preparing dataset ...")

wasserstoff_kernnetz = prepare_dataset(wasserstoff_kernnetz)

if kernnetz_cf["reload_locations"]:
Expand Down
101 changes: 88 additions & 13 deletions workflow/scripts/cluster_wasserstoff_kernnetz.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,19 @@
import os
import sys

import geopandas as gpd
import pandas as pd
import pyproj
from _helpers import configure_logging
from pypsa.geo import haversine_pts
from shapely import wkt
from shapely.geometry import LineString, Point
from shapely.ops import transform

paths = ["workflow/submodules/pypsa-eur/scripts", "../submodules/pypsa-eur/scripts"]
for path in paths:
sys.path.insert(0, os.path.abspath(path))
from cluster_gas_network import (
build_clustered_gas_network,
load_bus_regions,
reindex_pipes,
)
from _helpers import configure_logging
from cluster_gas_network import load_bus_regions, reindex_pipes

# Define a function for projecting points to meters
project_to_meters = pyproj.Transformer.from_proj(
Expand Down Expand Up @@ -125,6 +123,48 @@ def divide_pipes(df, segment_length=10):
return result


def build_clustered_h2_network(
df, bus_regions, recalculate_length=True, length_factor=1.25
):
for i in [0, 1]:
gdf = gpd.GeoDataFrame(geometry=df[f"point{i}"], crs="EPSG:4326")

bus_mapping = gpd.sjoin(gdf, bus_regions, how="left", predicate="within")[
"name"
]
bus_mapping = bus_mapping.groupby(bus_mapping.index).first()

df[f"bus{i}"] = bus_mapping

df[f"point{i}"] = df[f"bus{i}"].map(
bus_regions.to_crs(3035).centroid.to_crs(4326)
)

# drop pipes where not both buses are inside regions
df = df.loc[~df.bus0.isna() & ~df.bus1.isna()]

# drop pipes within the same region
df = df.loc[df.bus1 != df.bus0]

if df.empty:
return df

if recalculate_length:
logger.info("Recalculating pipe lengths as center to center * length factor")
# recalculate lengths as center to center * length factor
df["length"] = df.apply(
lambda p: length_factor
* haversine_pts([p.point0.x, p.point0.y], [p.point1.x, p.point1.y]),
axis=1,
)

# tidy and create new numbered index
df.drop(["point0", "point1"], axis=1, inplace=True)
df.reset_index(drop=True, inplace=True)

return df


def aggregate_parallel_pipes(df, aggregate_build_years="mean"):
strategies = {
"bus0": "first",
Expand All @@ -137,6 +177,7 @@ def aggregate_parallel_pipes(df, aggregate_build_years="mean"):
"length": "mean",
"name": " ".join,
"p_min_pu": "min",
"investment_costs (Mio. Euro)": "sum",
"removed_gas_cap": "sum",
"ipcei": " ".join,
"pci": " ".join,
Expand All @@ -158,7 +199,12 @@ def aggregate_parallel_pipes(df, aggregate_build_years="mean"):
snakemake = mock_snakemake(
"cluster_wasserstoff_kernnetz",
simpl="",
clusters=22,
clusters=27,
run="KN2045_Bal_v4",
opts="",
ll="vopt",
sector_opts="none",
planning_horizons="2020",
)

configure_logging(snakemake)
Expand All @@ -178,7 +224,31 @@ def aggregate_parallel_pipes(df, aggregate_build_years="mean"):
segment_length = kernnetz_cf["pipes_segment_length"]
df = divide_pipes(df, segment_length=segment_length)

wasserstoff_kernnetz = build_clustered_gas_network(df, bus_regions)
wasserstoff_kernnetz = build_clustered_h2_network(
df,
bus_regions,
recalculate_length=kernnetz_cf["recalculate_length"],
length_factor=1.25,
)

if kernnetz_cf["divide_pipes"] & (not kernnetz_cf["aggregate_parallel_pipes"]):
# Set length to 0 for duplicates from the 2nd occurrence onwards and make name unique
logger.info(
f"Setting length to 0 for splitted pipes as Kernnetz pipes are segmented (divide pipes: {kernnetz_cf["divide_pipes"]}) and paralle pipes not aggregated (aggregate_parallel_pipes: {kernnetz_cf["aggregate_parallel_pipes"]})."
)
wasserstoff_kernnetz["occurrence"] = (
wasserstoff_kernnetz.groupby("name").cumcount() + 1
)
wasserstoff_kernnetz.loc[wasserstoff_kernnetz["occurrence"] > 1, "length"] = 0
wasserstoff_kernnetz["name"] = wasserstoff_kernnetz.apply(
lambda row: (
f"{row['name']}-split{row['occurrence']}"
if row["occurrence"] > 1
else row["name"]
),
axis=1,
)
wasserstoff_kernnetz = wasserstoff_kernnetz.drop(columns="occurrence")

if not wasserstoff_kernnetz.empty:
wasserstoff_kernnetz[["bus0", "bus1"]] = (
Expand All @@ -187,12 +257,17 @@ def aggregate_parallel_pipes(df, aggregate_build_years="mean"):
.apply(pd.Series)
)

reindex_pipes(wasserstoff_kernnetz, prefix="H2 pipeline")

wasserstoff_kernnetz["p_min_pu"] = 0
wasserstoff_kernnetz["p_nom_diameter"] = 0
wasserstoff_kernnetz = aggregate_parallel_pipes(
wasserstoff_kernnetz, kernnetz_cf["aggregate_build_years"]
)

if kernnetz_cf["aggregate_parallel_pipes"]:

reindex_pipes(wasserstoff_kernnetz, prefix="H2 pipeline")
wasserstoff_kernnetz = aggregate_parallel_pipes(
wasserstoff_kernnetz, kernnetz_cf["aggregate_build_years"]
)

else:
wasserstoff_kernnetz.index = wasserstoff_kernnetz.name.astype(str)

wasserstoff_kernnetz.to_csv(snakemake.output.clustered_h2_network)
Loading

0 comments on commit c780a3c

Please sign in to comment.