Skip to content

Commit

Permalink
Merge pull request #128 from openego/fixes/#119-Isolated-CH4-foreign-…
Browse files Browse the repository at this point in the history
…buses

Fixes/#119 isolated ch4 foreign buses
  • Loading branch information
CarlosEpia authored Nov 27, 2023
2 parents 191ef56 + b5c65de commit b444741
Show file tree
Hide file tree
Showing 3 changed files with 92 additions and 96 deletions.
1 change: 1 addition & 0 deletions src/egon/data/datasets/fix_ehv_subnetworks.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ def add_line(x0, y0, x1, y1, v_nom, scn_name, cables):
gdf["x"] = (x_per_km * gdf["length"]) / (gdf["cables"] / 3)
gdf["r"] = (r_per_km * gdf["length"]) / (gdf["cables"] / 3)
gdf["b"] = (b_per_km * gdf["length"]) * (gdf["cables"] / 3)

gdf["capital_cost"] = (cost_per_km * gdf["length"]) * (gdf["cables"] / 3)
gdf.index.name = "line_id"
gdf.reset_index().to_postgis(
Expand Down
24 changes: 16 additions & 8 deletions src/egon/data/datasets/gas_areas.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,6 @@ def __init__(self, dependencies):
)



Base = declarative_base()


Expand Down Expand Up @@ -141,7 +140,8 @@ def voronoi_egon100RE():
"""
for carrier in ["CH4", "H2_grid", "H2_saltcavern"]:
create_voronoi("eGon100RE", carrier)



def voronoi_status2019():
"""
Create voronoi polygons for all gas carriers in status2019 scenario
Expand Down Expand Up @@ -191,16 +191,24 @@ def create_voronoi(scn_name, carrier):
if len(buses) == 0:
return

buses["x"] = buses.geometry.x
buses["y"] = buses.geometry.y
# generate voronois
gdf = get_voronoi_geodataframe(buses, boundary.geometry.iloc[0])
# set scn_name
# For some scenarios it is defined that there is only 1 bus (e.g. gas). It
# means that there will be just 1 voronoi covering the entire german
# territory. For other scenarios with more buses, voronois are calculated.
if len(buses) == 1:
gdf = buses.copy()
gdf.at[0, "geom"] = boundary.at[0, "geometry"]
else:
buses["x"] = buses.geometry.x
buses["y"] = buses.geometry.y
gdf = get_voronoi_geodataframe(buses, boundary.geometry.iloc[0])
gdf.rename_geometry("geom", inplace=True)
gdf.drop(columns=["id"], inplace=True)

# set scn_name and carrier
gdf["scn_name"] = scn_name
gdf["carrier"] = carrier

gdf.rename_geometry("geom", inplace=True)
gdf.drop(columns=["id"], inplace=True)
# Insert data to db
gdf.set_crs(epsg=4326).to_postgis(
f"egon_gas_voronoi",
Expand Down
163 changes: 75 additions & 88 deletions src/egon/data/datasets/gas_grid.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import json
import os

from sqlalchemy.orm import sessionmaker
from geoalchemy2.types import Geometry
from shapely import geometry
import geopandas
Expand Down Expand Up @@ -159,14 +160,14 @@ def ch4_nodes_number_G(gas_nodes_list):

def insert_CH4_nodes_list(gas_nodes_list):
"""
Insert list of German CH4 nodes into the database for status2019
Insert list of German CH4 nodes into the database for eGon2035
Insert the list of German CH4 nodes into the database by executing
the following steps:
* Receive the buses as parameter (from SciGRID_gas IGGIELGN data)
* Add the missing information: scn_name and carrier
* Clean the database table grid.egon_etrago_bus of the
CH4 buses of the specific scenario (status2019) in Germany
CH4 buses of the specific scenario (eGon2035) in Germany
* Insert the buses in the table grid.egon_etrago_bus
Parameters
Expand Down Expand Up @@ -221,7 +222,7 @@ def insert_CH4_nodes_list(gas_nodes_list):
# A completer avec nodes related to pipelines which have an end in the selected area et evt deplacer ds define_gas_nodes_list

# Add missing columns
c = {"scn_name": "status2019", "carrier": "CH4"}
c = {"scn_name": "eGon2035", "carrier": "CH4"}
gas_nodes_list = gas_nodes_list.assign(**c)

gas_nodes_list = geopandas.GeoDataFrame(
Expand Down Expand Up @@ -259,11 +260,11 @@ def insert_CH4_nodes_list(gas_nodes_list):
)


def insert_gas_buses_abroad(scn_name="status2019"):
def insert_gas_buses_abroad(scn_name="eGon2035"):
"""
Insert CH4 buses in neighbouring countries to database for status2019
Insert CH4 buses in neighbouring countries to database for eGon2035
For the scenario status2019, insert central CH4 buses in foreign
For the scenario eGon2035, insert central CH4 buses in foreign
countries to the database. The considered foreign countries are the
direct neighbouring countries, with the addition of Russia that is
considered as a source of fossil CH4.
Expand All @@ -277,7 +278,7 @@ def insert_gas_buses_abroad(scn_name="status2019"):
* Addition of the missing information: scn_name and carrier
* Attribution of an id to each bus
* Cleaning of the database table grid.egon_etrago_bus of the
CH4 buses of the specific scenario (status2019) out of Germany
CH4 buses of the specific scenario (eGon2035) out of Germany
* Insertion of the neighbouring buses in the table grid.egon_etrago_bus.
Returns
Expand Down Expand Up @@ -319,7 +320,7 @@ def insert_gas_buses_abroad(scn_name="status2019"):
"geom",
]
)
gdf_abroad_buses["scn_name"] = "status2019"
gdf_abroad_buses["scn_name"] = "eGon2035"
gdf_abroad_buses["carrier"] = main_gas_carrier
gdf_abroad_buses["bus_id"] = range(new_id, new_id + len(gdf_abroad_buses))

Expand Down Expand Up @@ -387,14 +388,14 @@ def insert_gas_buses_abroad(scn_name="status2019"):


def insert_gas_pipeline_list(
gas_nodes_list, abroad_gas_nodes_list, scn_name="status2019"
gas_nodes_list, abroad_gas_nodes_list, scn_name="eGon2035"
):
"""
Insert list of gas pipelines into the database
The gas pipelines, modelled as Pypsa links are red from the IGGIELGN_PipeSegments
csv file previously downloded in the function :py:func:`download_SciGRID_gas_data`,
adapted and inserted in the database for the status2019 scenario.
adapted and inserted in the database for the eGon2035 scenario.
The manual corrections allows to:
* Delete gas pipelines disconnected of the rest of the gas grid
* Connect one pipeline (also connected to Norway) disconnected of
Expand Down Expand Up @@ -801,7 +802,7 @@ def insert_gas_pipeline_list(

def remove_isolated_gas_buses():
"""
Delete CH4 buses which are disconnected of the CH4 grid for the status2019 scenario
Delete CH4 buses which are disconnected of the CH4 grid for the eGon2035 scenario
This function deletes directly in the database and has no return.
Expand All @@ -812,26 +813,26 @@ def remove_isolated_gas_buses():
f"""
DELETE FROM {targets['buses']['schema']}.{targets['buses']['table']}
WHERE "carrier" = 'CH4'
AND scn_name = 'status2019'
AND scn_name = 'eGon2035'
AND country = 'DE'
AND "bus_id" NOT IN
(SELECT bus0 FROM {targets['links']['schema']}.{targets['links']['table']}
WHERE scn_name = 'status2019'
WHERE scn_name = 'eGon2035'
AND carrier = 'CH4')
AND "bus_id" NOT IN
(SELECT bus1 FROM {targets['links']['schema']}.{targets['links']['table']}
WHERE scn_name = 'status2019'
WHERE scn_name = 'eGon2035'
AND carrier = 'CH4');
"""
)


def insert_gas_data():
"""
Overall function for importing methane data for status2019
Overall function for importing methane data for eGon2035
This function import the methane data (buses and pipelines) for
status2019, by executing the following steps:
eGon2035, by executing the following steps:
* Download the SciGRID_gas datasets with the function :py:func:`download_SciGRID_gas_data`
* Define CH4 buses with the function :py:func:`define_gas_nodes_list`
* Insert the CH4 buses in Germany into the database with the
Expand All @@ -857,12 +858,12 @@ def insert_gas_data():
remove_isolated_gas_buses()


def insert_gas_data_eGon2035():
def insert_gas_data_eGon100RE():
"""
Overall function for importing methane data for eGon100RE
This function import the methane data (buses and pipelines) for
eGon2035, by copying the CH4 buses from the status2019 scenario using
eGon100RE, by copying the CH4 buses from the eGon2035 scenario using
the function :py:func:`copy_and_modify_buses <egon.data.datasets.etrago_helpers.copy_and_modify_buses>`
from the module :py:mod:`etrago_helpers <egon.data.datasets.etrago_helpers>`. The methane
pipelines are also copied and their capacities are adapted: one
Expand All @@ -874,28 +875,28 @@ def insert_gas_data_eGon2035():
"""
# copy buses
copy_and_modify_buses("status2019", "eGon2035", {"carrier": ["CH4"]})
copy_and_modify_buses("eGon2035", "eGon100RE", {"carrier": ["CH4"]})

# get CH4 pipelines and modify their nominal capacity with the
# retrofitting factor
gdf = db.select_geodataframe(
f"""
SELECT * FROM grid.egon_etrago_link
WHERE carrier = 'CH4' AND scn_name = 'status2019' AND
WHERE carrier = 'CH4' AND scn_name = 'eGon2035' AND
bus0 IN (
SELECT bus_id FROM grid.egon_etrago_bus
WHERE scn_name = 'status2019' AND country = 'DE'
WHERE scn_name = 'eGon2035' AND country = 'DE'
) AND bus1 IN (
SELECT bus_id FROM grid.egon_etrago_bus
WHERE scn_name = 'status2019' AND country = 'DE'
WHERE scn_name = 'eGon2035' AND country = 'DE'
);
""",
epsg=4326,
geom_col="topo",
)

# Update scenario specific information
scn_name = "eGon2035"
scn_name = "eGon100RE"
gdf["scn_name"] = scn_name
scn_params = get_sector_parameters("gas", scn_name)

Expand All @@ -905,6 +906,11 @@ def insert_gas_data_eGon2035():
except KeyError:
pass

# remaining CH4 share is 1 - retroffited pipeline share
gdf["p_nom"] *= (
1 - scn_params["retrofitted_CH4pipeline-to-H2pipeline_share"]
)

# delete old entries
db.execute_sql(
f"""
Expand All @@ -930,81 +936,62 @@ def insert_gas_data_eGon2035():
)


def insert_gas_data_eGon100RE():
def insert_gas_data_status2019():
"""
Overall function for importing methane data for eGon100RE
Function to deal with the gas network for the status2019 scenario.
For this scenario just one CH4 bus is consider in the center of Germany.
Since OCGTs in the foreign countries are modelled as generators and not
as links between the gas and electricity sectors, CH4 foreign buses are
considered not necessary.
This function import the methane data (buses and pipelines) for
eGon100RE, by copying the CH4 buses from the eGon2035 scenario using
the function :py:func:`copy_and_modify_buses <egon.data.datasets.etrago_helpers.copy_and_modify_buses>`
from the module :py:mod:`etrago_helpers <egon.data.datasets.etrago_helpers>`. The methane
pipelines are also copied and their capacities are adapted: one
share of the methane grid is retroffited into an hydrogen grid, so
the methane pieplines nominal capacities are reduced from this share
(calculated in the pyspa-eur-sec run).
This function does not require any input.
This function inserts data into the database and has no return.
Returns
-------
None.
"""
# copy buses
copy_and_modify_buses("eGon2035", "eGon100RE", {"carrier": ["CH4"]})

# get CH4 pipelines and modify their nominal capacity with the
# retrofitting factor
gdf = db.select_geodataframe(
f"""
SELECT * FROM grid.egon_etrago_link
WHERE carrier = 'CH4' AND scn_name = 'eGon2035' AND
bus0 IN (
SELECT bus_id FROM grid.egon_etrago_bus
WHERE scn_name = 'eGon2035' AND country = 'DE'
) AND bus1 IN (
SELECT bus_id FROM grid.egon_etrago_bus
WHERE scn_name = 'eGon2035' AND country = 'DE'
);
""",
epsg=4326,
geom_col="topo",
)

# Update scenario specific information
scn_name = "eGon100RE"
gdf["scn_name"] = scn_name
scn_params = get_sector_parameters("gas", scn_name)

for param in ["capital_cost", "marginal_cost", "efficiency"]:
try:
gdf.loc[:, param] = scn_params[param]["CH4"]
except KeyError:
pass

# remaining CH4 share is 1 - retroffited pipeline share
gdf["p_nom"] *= (
1 - scn_params["retrofitted_CH4pipeline-to-H2pipeline_share"]
)
scn_name = "status2019"

# delete old entries
db.execute_sql(
f"""
DELETE FROM grid.egon_etrago_link
WHERE carrier = 'CH4' AND scn_name = '{scn_name}' AND
bus0 NOT IN (
SELECT bus_id FROM grid.egon_etrago_bus
WHERE scn_name = '{scn_name}' AND country != 'DE'
) AND bus1 NOT IN (
SELECT bus_id FROM grid.egon_etrago_bus
WHERE scn_name = '{scn_name}' AND country != 'DE'
);
WHERE carrier = 'CH4' AND scn_name = '{scn_name}'
"""
)
db.execute_sql(
f"""
DELETE FROM grid.egon_etrago_bus
WHERE carrier = 'CH4' AND scn_name = '{scn_name}'
"""
)

gdf.to_postgis(
"egon_etrago_link",
schema="grid",
if_exists="append",
con=db.engine(),
index=False,
dtype={"geom": Geometry(), "topo": Geometry()},
# Select next id value
new_id = db.next_etrago_id("bus")

df = pd.DataFrame(
index=[new_id],
data={
"scn_name": scn_name,
"v_nom": 1,
"carrier": "CH4",
"v_mag_pu_set": 1,
"v_mag_pu_min": 0,
"v_mag_pu_max": np.inf,
"x": 10,
"y": 51,
"country": "DE",
},
)
gdf = geopandas.GeoDataFrame(
df, geometry=geopandas.points_from_xy(df.x, df.y, crs=4326)
).rename_geometry("geom")

gdf.index.name = "bus_id"

gdf.reset_index().to_postgis(
"egon_etrago_bus", schema="grid", con=db.engine(), if_exists="append"
)


Expand Down Expand Up @@ -1032,12 +1019,12 @@ class GasNodesAndPipes(Dataset):
#:
name: str = "GasNodesAndPipes"
#:
version: str = "0.0.9"
version: str = "0.0.10"

tasks = (insert_gas_data,)
tasks = (insert_gas_data_status2019,)

if "eGon2035" in config.settings()["egon-data"]["--scenarios"]:
tasks = tasks + (insert_gas_data_eGon2035,)
tasks = tasks + (insert_gas_data,)

if "eGon100RE" in config.settings()["egon-data"]["--scenarios"]:
tasks = tasks + (insert_gas_data_eGon100RE,)
Expand Down

0 comments on commit b444741

Please sign in to comment.