Source code for egon.data.datasets.fix_ehv_subnetworks

"""The central module containing all code dealing with fixing ehv subnetworks
"""

import geopandas as gpd
import numpy as np
import pandas as pd

from egon.data import config, db, logger
from egon.data.config import settings
from egon.data.datasets import Dataset
from egon.data.datasets.etrago_setup import link_geom_from_buses
from egon.data.datasets.scenario_parameters import get_sector_parameters


[docs]class FixEhvSubnetworks(Dataset): """ Manually fix grid topology in the extra high voltage grid to avoid subnetworks This dataset includes fixes for the topology of the German extra high voltage grid. The initial grid topology from openstreetmap resp. osmTGmod includes some issues, eg. because of incomplete data. Thsi dataset does not fix all those issues, but deals only with subnetworks in the extra high voltage grid that would result into problems in the grid optimisation. *Dependencies* * :py:class:`Osmtgmod <egon.data.datasets.osmtgmod.Osmtgmod>` *Resulting tables* * :py:class:`grid.egon_etrago_bus <egon.data.datasets.etrago_setup.EgonPfHvBus>` is updated * :py:class:`grid.egon_etrago_line <egon.data.datasets.etrago_setup.EgonPfHvLine>` is updated * :py:class:`grid.egon_etrago_transformer <egon.data.datasets.etrago_setup.EgonPfHvTransformer>` is updated """ #: name: str = "FixEhvSubnetworks" #: version: str = "0.0.2" def __init__(self, dependencies): super().__init__( name=self.name, version=self.version, dependencies=dependencies, tasks=run, )
[docs]def select_bus_id(x, y, v_nom, scn_name, carrier, find_closest=False): bus_id = db.select_dataframe( f""" SELECT bus_id FROM grid.egon_etrago_bus WHERE x = {x} AND y = {y} AND v_nom = {v_nom} AND scn_name = '{scn_name}' AND carrier = '{carrier}' """ ) if bus_id.empty: logger.info("No bus found") if find_closest: logger.info(f"Finding closest to x = {x}, y = {y}") bus_id = db.select_dataframe( f""" SELECT bus_id, st_distance(geom, 'SRID=4326;POINT({x} {y})'::geometry) FROM grid.egon_etrago_bus WHERE v_nom = {v_nom} AND scn_name = '{scn_name}' AND carrier = '{carrier}' ORDER BY st_distance Limit 1 """ ) logger.info(f"Bus ID = {bus_id.bus_id[0]} selected") return bus_id.bus_id[0] else: logger.info("Find closest == False.") return None else: logger.info(f"Exact match with bus ID = {bus_id.bus_id[0]} found.") return bus_id.bus_id[0]
[docs]def add_bus(x, y, v_nom, scn_name): df = pd.DataFrame( index=[db.next_etrago_id("bus")], data={ "scn_name": scn_name, "v_nom": v_nom, "x": x, "y": y, "carrier": "AC", }, ) gdf = gpd.GeoDataFrame( df, geometry=gpd.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" )
[docs]def drop_bus(x, y, v_nom, scn_name): bus = select_bus_id(x, y, v_nom, scn_name, carrier="AC") if bus is not None: db.execute_sql( f""" DELETE FROM grid.egon_etrago_bus WHERE scn_name = '{scn_name}' AND bus_id = {bus} AND v_nom = {v_nom} AND carrier = 'AC' """ )
[docs]def add_line(x0, y0, x1, y1, v_nom, scn_name, cables): parameters = get_sector_parameters("electricity", scenario=scn_name) bus0 = select_bus_id( x0, y0, v_nom, scn_name, carrier="AC", find_closest=True ) bus1 = select_bus_id( x1, y1, v_nom, scn_name, carrier="AC", find_closest=True ) df = pd.DataFrame( index=[db.next_etrago_id("line")], data={ "bus0": bus0, "bus1": bus1, "scn_name": scn_name, "v_nom": v_nom, "cables": cables, "carrier": "AC", }, ) gdf = link_geom_from_buses(df, scn_name) gdf["length"] = gdf.to_crs(3035).topo.length.mul(1e-3) # all the values used for x, r and b are taken from the electrical values # reference table from oemtgmod: github.com/wupperinst/osmTGmod if v_nom == 220: s_nom = 520 x_per_km = 0.001 * 2 * np.pi * 50 r_per_km = 0.05475 b_per_km = 11 * 2 * np.pi * 50 * 1e-9 cost_per_km = parameters["capital_cost"]["ac_ehv_overhead_line"] elif v_nom == 380: s_nom = 1790 x_per_km = 0.0008 * 2 * np.pi * 50 r_per_km = 0.027375 b_per_km = 14 * 2 * np.pi * 50 * 1e-9 cost_per_km = parameters["capital_cost"]["ac_ehv_overhead_line"] gdf["s_nom"] = s_nom * gdf["cables"] / 3 gdf["s_nom_extendable"] = True gdf["lifetime"] = parameters["lifetime"]["ac_ehv_overhead_line"] gdf["s_nom_min"] = s_nom * gdf["cables"] / 3 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( "egon_etrago_line", schema="grid", con=db.engine(), if_exists="append" )
[docs]def drop_line(x0, y0, x1, y1, v_nom, scn_name): bus0 = select_bus_id(x0, y0, v_nom, scn_name, carrier="AC") bus1 = select_bus_id(x1, y1, v_nom, scn_name, carrier="AC") if (bus0 is not None) and (bus1 is not None): db.execute_sql( f""" DELETE FROM grid.egon_etrago_line WHERE scn_name = '{scn_name}' AND bus0 = {bus0} AND bus1 = {bus1} AND v_nom = {v_nom} """ )
[docs]def add_trafo(x, y, v_nom0, v_nom1, scn_name, n=1): bus0 = select_bus_id( x, y, v_nom0, scn_name, carrier="AC", find_closest=True ) bus1 = select_bus_id( x, y, v_nom1, scn_name, carrier="AC", find_closest=True ) df = pd.DataFrame( index=[db.next_etrago_id("line")], data={ "bus0": bus0, "bus1": bus1, "scn_name": scn_name, }, ) gdf = link_geom_from_buses(df, scn_name) if (v_nom0 == 220) & (v_nom1 == 380): s_nom = 600 x = 0.0002 gdf["s_nom"] = s_nom * n gdf["x"] = x / n gdf.index.name = "trafo_id" gdf.reset_index().to_postgis( "egon_etrago_transformer", schema="grid", con=db.engine(), if_exists="append", )
[docs]def drop_trafo(x, y, v_nom0, v_nom1, scn_name): bus0 = select_bus_id(x, y, v_nom0, scn_name, carrier="AC") bus1 = select_bus_id(x, y, v_nom1, scn_name, carrier="AC") if (bus0 is not None) and (bus1 is not None): db.execute_sql( f""" DELETE FROM grid.egon_etrago_transformer WHERE scn_name = '{scn_name}' AND bus0 = {bus0} AND bus1 = {bus1} """ )
[docs]def fix_subnetworks(scn_name): # Missing 220kV line to Lübeck Siems # add 220kV bus at substation Lübeck Siems add_bus(10.760835327266625, 53.90974536547805, 220, scn_name) # add 220/380kV transformer at substation Lübeck Siems add_trafo(10.760835327266625, 53.90974536547805, 220, 380, scn_name) # add 220kV line from Umspannwerk Lübeck to Lübeck Siems add_line( 10.760835327266625, # Lübeck Siems 53.90974536547805, 10.641467804496818, # Umspannwerk Lübeck 53.91916269128779, 220, scn_name, 3, ) if settings()["egon-data"]["--dataset-boundary"] == "Everything": # Missing line from USW Uchtelfangen to 'Kraftwerk Weiher' add_line( 7.032657738999395, # Kraftwerk Weiher 49.33473737285781, 6.996454674906, # Umspannwerk Uchtelfangen 49.3754149606116, 220, scn_name, 6, ) if ( select_bus_id( 12.85381530378627, 48.764209444817745, 380, scn_name, "AC" ) != None ): # Missing line from Umspannwerk Plottling to Gänsdorf UW add_line( 12.85381530378627, # Umspannwerk Plottling 48.764209444817745, 12.769768646403532, # Gänsdorf UW 48.80533685376445, 380, scn_name, 3, ) # Missing line inside Ottstedt add_line( 11.4295305, # Ottstedt 50.9115176, 11.4299277, # Ottstedt 50.911449600000005, 380, scn_name, 3, )
[docs]def run(): for scenario in config.settings()["egon-data"]["--scenarios"]: fix_subnetworks(scenario)