013b705ee4
* Cluster first: build renewable profiles and add all assets after clustering * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * correction: pass landfall_lengths through functions * assign landfall_lenghts correctly * remove parameter add_land_use_constraint * fix network_dict * calculate distance to shoreline, remove underwater_fraction * adjust simplification parameter to exclude Crete from offshore wind connections * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * remove unused geth2015 hydro capacities * removing remaining traces of {simpl} wildcard * add release notes and update workflow graphics * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: lisazeyen <lisa.zeyen@web.de>
253 lines
6.8 KiB
Python
253 lines
6.8 KiB
Python
# -*- coding: utf-8 -*-
|
|
# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors
|
|
#
|
|
# SPDX-License-Identifier: MIT
|
|
"""
|
|
Creates map of optimised gas network, storage and selected other
|
|
infrastructure.
|
|
"""
|
|
|
|
import logging
|
|
|
|
import geopandas as gpd
|
|
import matplotlib.pyplot as plt
|
|
import pandas as pd
|
|
import pypsa
|
|
from _helpers import configure_logging, set_scenario_config
|
|
from plot_power_network import assign_location, load_projection
|
|
from pypsa.plot import add_legend_circles, add_legend_lines, add_legend_patches
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def plot_ch4_map(n):
|
|
# if "gas pipeline" not in n.links.carrier.unique():
|
|
# return
|
|
|
|
assign_location(n)
|
|
|
|
bus_size_factor = 8e7
|
|
linewidth_factor = 1e4
|
|
# MW below which not drawn
|
|
line_lower_threshold = 1e3
|
|
|
|
# Drop non-electric buses so they don't clutter the plot
|
|
n.buses.drop(n.buses.index[n.buses.carrier != "AC"], inplace=True)
|
|
|
|
fossil_gas_i = n.generators[n.generators.carrier == "gas"].index
|
|
fossil_gas = (
|
|
n.generators_t.p.loc[:, fossil_gas_i]
|
|
.mul(n.snapshot_weightings.generators, axis=0)
|
|
.sum()
|
|
.groupby(n.generators.loc[fossil_gas_i, "bus"])
|
|
.sum()
|
|
/ bus_size_factor
|
|
)
|
|
fossil_gas.rename(index=lambda x: x.replace(" gas", ""), inplace=True)
|
|
fossil_gas = fossil_gas.reindex(n.buses.index).fillna(0)
|
|
# make a fake MultiIndex so that area is correct for legend
|
|
fossil_gas.index = pd.MultiIndex.from_product([fossil_gas.index, ["fossil gas"]])
|
|
|
|
methanation_i = n.links.query("carrier == 'Sabatier'").index
|
|
methanation = (
|
|
abs(
|
|
n.links_t.p1.loc[:, methanation_i].mul(
|
|
n.snapshot_weightings.generators, axis=0
|
|
)
|
|
)
|
|
.sum()
|
|
.groupby(n.links.loc[methanation_i, "bus1"])
|
|
.sum()
|
|
/ bus_size_factor
|
|
)
|
|
methanation = (
|
|
methanation.groupby(methanation.index)
|
|
.sum()
|
|
.rename(index=lambda x: x.replace(" gas", ""))
|
|
)
|
|
# make a fake MultiIndex so that area is correct for legend
|
|
methanation.index = pd.MultiIndex.from_product([methanation.index, ["methanation"]])
|
|
|
|
biogas_i = n.stores[n.stores.carrier == "biogas"].index
|
|
biogas = (
|
|
n.stores_t.p.loc[:, biogas_i]
|
|
.mul(n.snapshot_weightings.generators, axis=0)
|
|
.sum()
|
|
.groupby(n.stores.loc[biogas_i, "bus"])
|
|
.sum()
|
|
/ bus_size_factor
|
|
)
|
|
biogas = (
|
|
biogas.groupby(biogas.index)
|
|
.sum()
|
|
.rename(index=lambda x: x.replace(" biogas", ""))
|
|
)
|
|
# make a fake MultiIndex so that area is correct for legend
|
|
biogas.index = pd.MultiIndex.from_product([biogas.index, ["biogas"]])
|
|
|
|
bus_sizes = pd.concat([fossil_gas, methanation, biogas])
|
|
bus_sizes.sort_index(inplace=True)
|
|
|
|
to_remove = n.links.index[~n.links.carrier.str.contains("gas pipeline")]
|
|
n.links.drop(to_remove, inplace=True)
|
|
|
|
link_widths_rem = n.links.p_nom_opt / linewidth_factor
|
|
link_widths_rem[n.links.p_nom_opt < line_lower_threshold] = 0.0
|
|
|
|
link_widths_orig = n.links.p_nom / linewidth_factor
|
|
link_widths_orig[n.links.p_nom < line_lower_threshold] = 0.0
|
|
|
|
max_usage = n.links_t.p0[n.links.index].abs().max(axis=0)
|
|
link_widths_used = max_usage / linewidth_factor
|
|
link_widths_used[max_usage < line_lower_threshold] = 0.0
|
|
|
|
tech_colors = snakemake.params.plotting["tech_colors"]
|
|
|
|
pipe_colors = {
|
|
"gas pipeline": "#f08080",
|
|
"gas pipeline new": "#c46868",
|
|
"gas pipeline (in 2020)": "lightgrey",
|
|
"gas pipeline (available)": "#e8d1d1",
|
|
}
|
|
|
|
link_color_used = n.links.carrier.map(pipe_colors)
|
|
|
|
n.links.bus0 = n.links.bus0.str.replace(" gas", "")
|
|
n.links.bus1 = n.links.bus1.str.replace(" gas", "")
|
|
|
|
bus_colors = {
|
|
"fossil gas": tech_colors["fossil gas"],
|
|
"methanation": tech_colors["methanation"],
|
|
"biogas": "seagreen",
|
|
}
|
|
|
|
fig, ax = plt.subplots(figsize=(7, 6), subplot_kw={"projection": proj})
|
|
|
|
n.plot(
|
|
bus_sizes=bus_sizes,
|
|
bus_colors=bus_colors,
|
|
link_colors=pipe_colors["gas pipeline (in 2020)"],
|
|
link_widths=link_widths_orig,
|
|
branch_components=["Link"],
|
|
ax=ax,
|
|
**map_opts,
|
|
)
|
|
|
|
n.plot(
|
|
ax=ax,
|
|
bus_sizes=0.0,
|
|
link_colors=pipe_colors["gas pipeline (available)"],
|
|
link_widths=link_widths_rem,
|
|
branch_components=["Link"],
|
|
color_geomap=False,
|
|
boundaries=map_opts["boundaries"],
|
|
)
|
|
|
|
n.plot(
|
|
ax=ax,
|
|
bus_sizes=0.0,
|
|
link_colors=link_color_used,
|
|
link_widths=link_widths_used,
|
|
branch_components=["Link"],
|
|
color_geomap=False,
|
|
boundaries=map_opts["boundaries"],
|
|
)
|
|
|
|
sizes = [100, 10]
|
|
labels = [f"{s} TWh" for s in sizes]
|
|
sizes = [s / bus_size_factor * 1e6 for s in sizes]
|
|
|
|
legend_kw = dict(
|
|
loc="upper left",
|
|
bbox_to_anchor=(0, 1.03),
|
|
labelspacing=0.8,
|
|
frameon=False,
|
|
handletextpad=1,
|
|
title="gas sources",
|
|
)
|
|
|
|
add_legend_circles(
|
|
ax,
|
|
sizes,
|
|
labels,
|
|
srid=n.srid,
|
|
patch_kw=dict(facecolor="lightgrey"),
|
|
legend_kw=legend_kw,
|
|
)
|
|
|
|
sizes = [50, 10]
|
|
labels = [f"{s} GW" for s in sizes]
|
|
scale = 1e3 / linewidth_factor
|
|
sizes = [s * scale for s in sizes]
|
|
|
|
legend_kw = dict(
|
|
loc="upper left",
|
|
bbox_to_anchor=(0.25, 1.03),
|
|
frameon=False,
|
|
labelspacing=0.8,
|
|
handletextpad=1,
|
|
title="gas pipeline",
|
|
)
|
|
|
|
add_legend_lines(
|
|
ax,
|
|
sizes,
|
|
labels,
|
|
patch_kw=dict(color="lightgrey"),
|
|
legend_kw=legend_kw,
|
|
)
|
|
|
|
colors = list(pipe_colors.values()) + list(bus_colors.values())
|
|
labels = list(pipe_colors.keys()) + list(bus_colors.keys())
|
|
|
|
# legend on the side
|
|
# legend_kw = dict(
|
|
# bbox_to_anchor=(1.47, 1.04),
|
|
# frameon=False,
|
|
# )
|
|
|
|
legend_kw = dict(
|
|
loc="upper left",
|
|
bbox_to_anchor=(0, 1.24),
|
|
ncol=2,
|
|
frameon=False,
|
|
)
|
|
|
|
add_legend_patches(
|
|
ax,
|
|
colors,
|
|
labels,
|
|
legend_kw=legend_kw,
|
|
)
|
|
|
|
fig.savefig(snakemake.output.map, bbox_inches="tight")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
if "snakemake" not in globals():
|
|
from _helpers import mock_snakemake
|
|
|
|
snakemake = mock_snakemake(
|
|
"plot_gas_network",
|
|
opts="",
|
|
clusters="37",
|
|
ll="v1.0",
|
|
sector_opts="4380H-T-H-B-I-A-dist1",
|
|
)
|
|
|
|
configure_logging(snakemake)
|
|
set_scenario_config(snakemake)
|
|
|
|
n = pypsa.Network(snakemake.input.network)
|
|
|
|
regions = gpd.read_file(snakemake.input.regions).set_index("name")
|
|
|
|
map_opts = snakemake.params.plotting["map"]
|
|
|
|
if map_opts["boundaries"] is None:
|
|
map_opts["boundaries"] = regions.total_bounds[[0, 2, 1, 3]] + [-1, 1, -1, 1]
|
|
|
|
proj = load_projection(snakemake.params.plotting)
|
|
|
|
plot_ch4_map(n)
|