pypsa-eur/scripts/build_salt_cavern_potentials.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

91 lines
2.7 KiB
Python

# -*- coding: utf-8 -*-
# SPDX-FileCopyrightText: : 2020-2024 The PyPSA-Eur Authors
#
# SPDX-License-Identifier: MIT
"""
Build salt cavern potentials for hydrogen storage.
Technical Potential of Salt Caverns for Hydrogen Storage in Europe CC-BY
4.0
https://doi.org/10.20944/preprints201910.0187.v1
https://doi.org/10.1016/j.ijhydene.2019.12.161
Figure 6. Distribution of potential salt cavern sites across Europe with their corresponding
energy densities (cavern storage potential divided by the volume).
Figure 7. Total cavern storage potential in European countries
classified as onshore, offshore and within 50 km of shore.
The regional distribution is taken from the map (Figure 6) and scaled to the
capacities from the bar chart split by nearshore (<50km from sea),
onshore (>50km from sea), offshore (Figure 7).
"""
import geopandas as gpd
import pandas as pd
from _helpers import set_scenario_config
def concat_gdf(gdf_list, crs="EPSG:4326"):
"""
Concatenate multiple geopandas dataframes with common coordinate reference
system (crs).
"""
return gpd.GeoDataFrame(pd.concat(gdf_list), crs=crs)
def load_bus_regions(onshore_path, offshore_path):
"""
Load pypsa-eur on- and offshore regions and concat.
"""
bus_regions_offshore = gpd.read_file(offshore_path)
bus_regions_onshore = gpd.read_file(onshore_path)
bus_regions = concat_gdf([bus_regions_offshore, bus_regions_onshore])
bus_regions = bus_regions.dissolve(by="name", aggfunc="sum")
return bus_regions
def area(gdf):
"""
Returns area of GeoDataFrame geometries in square kilometers.
"""
return gdf.to_crs(epsg=3035).area.div(1e6)
def salt_cavern_potential_by_region(caverns, regions):
# calculate area of caverns shapes
caverns["area_caverns"] = area(caverns)
overlay = gpd.overlay(regions.reset_index(), caverns, keep_geom_type=True)
# calculate share of cavern area inside region
overlay["share"] = area(overlay) / overlay["area_caverns"]
overlay["e_nom"] = overlay.eval(
"capacity_per_area * share * area_caverns / 1000"
) # TWh
return overlay.groupby(["name", "storage_type"]).e_nom.sum().unstack("storage_type")
if __name__ == "__main__":
if "snakemake" not in globals():
from _helpers import mock_snakemake
snakemake = mock_snakemake("build_salt_cavern_potentials", clusters="37")
set_scenario_config(snakemake)
fn_onshore = snakemake.input.regions_onshore
fn_offshore = snakemake.input.regions_offshore
regions = load_bus_regions(fn_onshore, fn_offshore)
caverns = gpd.read_file(snakemake.input.salt_caverns) # GWh/sqkm
caverns_regions = salt_cavern_potential_by_region(caverns, regions)
caverns_regions.to_csv(snakemake.output.h2_cavern_potential)