pypsa-eur/scripts/plot_gas_network.py
Fabian Neumann 013b705ee4
Clustering: build renewable profiles and add all assets after clustering (#1201)
* 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>
2024-09-13 15:37:01 +02:00

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)