pypsa-eur/scripts/simplify_network.py

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

454 lines
15 KiB
Python
Raw Permalink Normal View History

# -*- coding: utf-8 -*-
2024-02-19 15:21:48 +00:00
# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors
#
2021-09-14 14:37:41 +00:00
# SPDX-License-Identifier: MIT
# coding: utf-8
2019-08-11 20:34:18 +00:00
"""
Lifts electrical transmission network to a single 380 kV voltage layer, removes
dead-ends of the network, and reduces multi-hop HVDC connections to a single
link.
2019-08-11 09:40:47 +00:00
Relevant Settings
-----------------
2019-08-11 11:17:36 +00:00
.. code:: yaml
clustering:
simplify_network:
cluster_network:
aggregation_strategies:
2019-08-11 11:17:36 +00:00
links:
p_max_pu:
2019-11-14 16:50:24 +00:00
.. seealso::
Documentation of the configuration file ``config/config.yaml`` at
:ref:`electricity_cf`, :ref:`renewable_cf`,
:ref:`lines_cf`, :ref:`links_cf`
2019-08-11 09:40:47 +00:00
Inputs
------
2019-08-11 20:34:18 +00:00
- ``resources/regions_onshore.geojson``: confer :ref:`busregions`
- ``resources/regions_offshore.geojson``: confer :ref:`busregions`
- ``networks/base.nc``
2019-08-11 20:34:18 +00:00
2019-08-11 09:40:47 +00:00
Outputs
-------
- ``resources/regions_onshore_base.geojson``:
2019-08-12 17:01:53 +00:00
.. image:: img/regions_onshore_base_s.png
2019-08-12 17:01:53 +00:00
:scale: 33 %
- ``resources/regions_offshore_base.geojson``:
2019-08-12 17:01:53 +00:00
.. image:: img/regions_offshore_base_s .png
2019-08-12 17:01:53 +00:00
:scale: 33 %
- ``resources/busmap_base_s.csv``: Mapping of buses from ``networks/base.nc`` to ``networks/base_s.nc``;
- ``networks/base.nc``:
2019-08-11 20:34:18 +00:00
.. image:: img/base_s.png
2019-08-11 20:34:18 +00:00
:scale: 33 %
2019-08-11 09:40:47 +00:00
Description
-----------
The rule :mod:`simplify_network` does up to three things:
1. Create an equivalent transmission network in which all voltage levels are mapped to the 380 kV level by the function ``simplify_network(...)``.
2. DC only sub-networks that are connected at only two buses to the AC network are reduced to a single representative link in the function ``simplify_links(...)``.
3. Stub lines and links, i.e. dead-ends of the network, are sequentially removed from the network in the function ``remove_stubs(...)``.
"""
Add logging to logfiles to all snakemake workflow scripts. (#102) * Add logging to logfiles to all snakemake workflow scripts. * Fix missing quotation marks in Snakefile. * Apply suggestions from code review Co-Authored-By: Fabian Neumann <fabian.neumann@outlook.de> * Apply suggestions from code review Co-Authored-By: Fabian Neumann <fabian.neumann@outlook.de> * doc: fix _ec_ filenames in docs * Allow logging message format to be specified in config.yaml. * Add logging for Snakemake rule 'retrieve_databundle '. * Add limited logging to STDERR only for retrieve_*.py scripts. * Import progressbar module only on demand. * Fix logging to file and enable concurrent printing to STDERR for most scripts. * Add new 'logging_format' option to Travis CI test config.yaml. * Add missing parenthesis (bug fix) and cross-os compatible paths. * Fix typos in messages. * Use correct log files for logging (bug fix). * doc: fix line references * config: logging_format in all configs * doc: add doc for logging_format * environment: update to powerplantmatching 0.4.3 * doc: update line references for tutorial.rst * Change logging configuration scheme for config.yaml. * Add helper function for doing basic logging configuration. * Add logpath for prepare_links_p_nom rule. * Outsource basic logging configuration for all scripts to _helper submodule. * Update documentation for changed config.yaml structure. Instead of 'logging_level' and 'logging_format', now 'logging' with subcategories is used. * _helpers: Change configure_logging signature.
2019-11-28 07:22:52 +00:00
import logging
2024-01-19 09:34:49 +00:00
from functools import reduce
from typing import Tuple
import geopandas as gpd
import numpy as np
2019-11-14 16:50:24 +00:00
import pandas as pd
import pypsa
import scipy as sp
from _helpers import configure_logging, set_scenario_config
from base_network import append_bus_shapes
from cluster_network import cluster_regions
from pypsa.clustering.spatial import busmap_by_stubs, get_clustering_from_busmap
from scipy.sparse.csgraph import connected_components, dijkstra
logger = logging.getLogger(__name__)
def simplify_network_to_380(
n: pypsa.Network, linetype_380: str
) -> Tuple[pypsa.Network, pd.Series]:
2022-09-05 10:51:30 +00:00
"""
Fix all lines to a voltage level of 380 kV and remove all transformers.
The function preserves the transmission capacity for each line while
updating its voltage level, line type and number of parallel bundles
(num_parallel).
2022-09-05 10:51:30 +00:00
Transformers are removed and connected components are moved from
their starting bus to their ending bus. The corresponding starting
2022-09-05 10:51:30 +00:00
buses are removed as well.
"""
logger.info("Mapping all network lines onto a single 380kV layer")
n.buses["v_nom"] = 380.0
2022-09-05 10:51:30 +00:00
n.lines["type"] = linetype_380
n.lines["v_nom"] = 380
n.lines["i_nom"] = n.line_types.i_nom[linetype_380]
n.lines["num_parallel"] = n.lines.eval("s_nom / (sqrt(3) * v_nom * i_nom)")
2022-09-05 10:51:30 +00:00
trafo_map = pd.Series(n.transformers.bus1.values, n.transformers.bus0.values)
trafo_map = trafo_map[~trafo_map.index.duplicated(keep="first")]
Introducing OpenStreetMap high-voltage grid to PyPSA-Eur (#1079) * Implemented which uses the overpass API to download power features for individual countries. * Extended rule by input. * Bug fixes and improvements to clean_osm_data.py. Added in retrieve_osm_data.py. * Updated clean_osm_data and retrieve_osm_data to create clean substations. * Finished clean_osm_data function. * Added check whether line is a circle. If so, drop it. * Extended build_electricity.smk by build_osm_network.py * Added build_osm_network * Working osm-network-fast * Bug fixes. * Finalised and cleaned including docstrings. * Added try catch to retrieve_osm_data. Allows for parallelisation of downloads. * Updated cleaning process. * Set maximum number of threads for retrieving to 4, wrt. fair usage policy and potential request errors. * Intermediate update on clean_osm_data.py. Added docstrings. * Bug fix. * Bug fix. * Bug fixes in data types out of clean_osm_data * Significant improvements to retrieve_osm_data, clean_osm_data. Cleaned code. Speed improvements * Cleaned config. * Fixes. * Bug fixes. * Updated default config * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Removed overpass from required packages. Not needed anymore. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added links_relations (route = power, frequency = 0) to retrieval. This will change how HVDC links are extracted in the near future. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Work-in-progress clean_osm_data * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added clean links output to clean_osm_data. Script uses OSM relations to retrieve clean HVDC links. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * New code for integrating HVDC links. Using relations. Base network implementation functioning. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * removed manual line dropping. * Updated clean script * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * reverted Snakefile to default: sync settings * added prebuilt functionality. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Updated build_electricity.smk to work with scenario management. * removed commented-out code. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * removed commented-out code. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixed bug in pdf export by substituting pdf export with svg. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Bug-fix Snakefile * dropped not needed columns from build_osm_network. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Updated build_shapes, config.default and clean_osm_data. * pre-commit changes. * test * Added initial prepare_osm_network_release.py script * Finalised prepare_osm_network_release script to build clean and stable OSM base_network input files. * Added new rules/development.smk * Updated clean_osm_data to add substation_centroid to linestrings * Updated clean_osm_data to add substation_centroid to linestrings * Updated clean_osm_data to add substation_centroid to linestrings * Updated clean_osm_data to add substation_centroid to linestrings * Added osm-prebuilt functionality and zenodo sandbox repository. * Updated clean_osm_data to geopandas v.1.01 * Made base_network and build_osm_network function more robust for empty links. * Made base_network and build_osm_network function more robust for empty links. * Bug fix in base_network. Voltage level null is now kept (relevant e.g. for Corsica) * Merge with hcanges in upstream PR 1146. Fixing UA and MD. * Updated Zenodo and fixed prepare_osm_network_release * Updated osm network release. * Updated prepare osm network release. * Updated MD, UA scripts. * Cleaned determine_availability_matrix_MD_UA.py, removed redundant code * Bug fixes. * Bug fixes for UA MD scripts. * Rename of build script. * Bug fix: only distribute load to buses with substation. * Updated zenodo sandbox repository. * Updated config.default * Cleaned config.default.yaml: Related settings grouped together and redundant voltage settings aggregated. * Cleaned config.default.yaml: Related settings grouped together and redundant voltage settings aggregated. Added release notes. * Updated Zenodo repositories for OSM-prebuilt to offcial publication. * Updated configtables * Updated links.csv: Under_construction lines to in commission. * Updated link 8394 and parameter_corrections: Continuation of North-Sea-Link. * Major update: fix simplify_network, fix Corsica, updated build_osm_network to include lines overpassing nodes. * remove config backup * Bug fix: Carrier type of all supernodes corrected to 'AC' * Bug fix: Carrier type of all supernodes corrected to 'AC' * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Updated rules and base_network for compatibility with TYNDP projects. * Updated Zenodo repository and prebuilt network to include 150 kV HVDC connections. * Removed outdated config backup. * Implemented all comments from PR #1079. Cleaned up OSM implementation. * Bug fix: Added all voltages, 200 kV-750 kV, to default config. * Cleaning and bugfixes. * Updated Zenodo repository to https://zenodo.org/records/13358976. Added converter voltages, 'underground' property for DC lines/cables, and included Konti-Skan HVDC (DK-SE). Added compatibility with https://github.com/PyPSA/pypsa-eur/pull/1079 and https://github.com/PyPSA/pypsa-eur/pull/1085 * Apply suggestions from code review * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * simplify_network: handle complicated transformer topologies * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * syntax fix --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Fabian Neumann <fabian.neumann@outlook.de>
2024-08-22 13:01:20 +00:00
while (several_trafo_b := trafo_map.isin(trafo_map.index)).any():
trafo_map[several_trafo_b] = trafo_map[several_trafo_b].map(trafo_map)
missing_buses_i = n.buses.index.difference(trafo_map.index)
2022-01-29 15:17:46 +00:00
missing = pd.Series(missing_buses_i, missing_buses_i)
trafo_map = pd.concat([trafo_map, missing])
for c in n.one_port_components | n.branch_components:
df = n.df(c)
for col in df.columns:
if col.startswith("bus"):
df[col] = df[col].map(trafo_map)
n.mremove("Transformer", n.transformers.index)
n.mremove("Bus", n.buses.index.difference(trafo_map))
return n, trafo_map
def _remove_clustered_buses_and_branches(n: pypsa.Network, busmap: pd.Series) -> None:
buses_to_del = n.buses.index.difference(busmap)
n.mremove("Bus", buses_to_del)
for c in n.branch_components:
df = n.df(c)
n.mremove(c, df.index[df.bus0.isin(buses_to_del) | df.bus1.isin(buses_to_del)])
2023-05-19 13:42:07 +00:00
def simplify_links(
n: pypsa.Network, p_max_pu: int | float
) -> Tuple[pypsa.Network, pd.Series]:
## Complex multi-node links are folded into end-points
logger.info("Simplifying connected link components")
if n.links.empty:
return n, n.buses.index.to_series()
# Determine connected link components, ignore all links but DC
adjacency_matrix = n.adjacency_matrix(
branch_components=["Link"],
weights=dict(Link=(n.links.carrier == "DC").astype(float)),
)
_, labels = connected_components(adjacency_matrix, directed=False)
labels = pd.Series(labels, n.buses.index)
# Only span graph over the DC link components
G = n.graph(branch_components=["Link"])
2024-08-16 11:16:52 +00:00
def split_links(nodes, added_supernodes):
nodes = frozenset(nodes)
seen = set()
# Supernodes are endpoints of links, identified by having lass then two neighbours or being an AC Bus
# An example for the latter is if two different links are connected to the same AC bus.
supernodes = {
m
for m in nodes
if (
(len(G.adj[m]) < 2 or (set(G.adj[m]) - nodes))
or (n.buses.loc[m, "carrier"] == "AC")
or (m in added_supernodes)
)
}
for u in supernodes:
2021-05-25 09:29:47 +00:00
for m, ls in G.adj[u].items():
if m not in nodes or m in seen:
continue
buses = [u, m]
links = [list(ls)] # [name for name in ls]]
while m not in (supernodes | seen):
seen.add(m)
2021-05-25 09:29:47 +00:00
for m2, ls in G.adj[m].items():
if m2 in seen or m2 == u:
continue
buses.append(m2)
links.append(list(ls)) # [name for name in ls])
break
else:
# stub
break
m = m2
if m != u:
yield pd.Index((u, m)), buses, links
seen.add(u)
busmap = n.buses.index.to_series()
node_corsica = find_closest_bus(
n,
x=9.44802,
y=42.52842,
tol=2000, # Tolerance needed to only return the bus if the region is actually modelled
)
added_supernodes = []
if node_corsica is not None:
added_supernodes.append(node_corsica)
for lbl in labels.value_counts().loc[lambda s: s > 2].index:
2024-08-16 11:16:52 +00:00
for b, buses, links in split_links(
labels.index[labels == lbl], added_supernodes
):
if len(buses) <= 2:
continue
logger.debug("nodes = {}".format(labels.index[labels == lbl]))
logger.debug("b = {}\nbuses = {}\nlinks = {}".format(b, buses, links))
m = sp.spatial.distance_matrix(
n.buses.loc[b, ["x", "y"]], n.buses.loc[buses[1:-1], ["x", "y"]]
)
busmap.loc[buses] = b[np.r_[0, m.argmin(axis=0), 1]]
all_links = [i for _, i in sum(links, [])]
lengths = n.links.loc[all_links, "length"]
name = lengths.idxmax() + "+{}".format(len(links) - 1)
params = dict(
carrier="DC",
bus0=b[0],
bus1=b[1],
length=sum(
n.links.loc[[i for _, i in l], "length"].mean() for l in links
),
p_nom=min(n.links.loc[[i for _, i in l], "p_nom"].sum() for l in links),
underwater_fraction=sum(
lengths
/ lengths.sum()
* n.links.loc[all_links, "underwater_fraction"]
),
p_max_pu=p_max_pu,
p_min_pu=-p_max_pu,
underground=False,
under_construction=False,
)
logger.info(
"Joining the links {} connecting the buses {} to simple link {}".format(
", ".join(all_links), ", ".join(buses), name
)
)
n.mremove("Link", all_links)
static_attrs = n.components["Link"]["attrs"].loc[lambda df: df.static]
2022-12-27 12:16:05 +00:00
for attr, default in static_attrs.default.items():
params.setdefault(attr, default)
n.links.loc[name] = pd.Series(params)
# n.add("Link", name, **params)
logger.debug("Collecting all components using the busmap")
_remove_clustered_buses_and_branches(n, busmap)
# Change carrier type of all added super_nodes to "AC"
n.buses.loc[added_supernodes, "carrier"] = "AC"
return n, busmap
2023-05-19 13:42:07 +00:00
def remove_stubs(
n: pypsa.Network, simplify_network: dict
) -> Tuple[pypsa.Network, pd.Series]:
logger.info("Removing stubs")
across_borders = simplify_network["remove_stubs_across_borders"]
matching_attrs = [] if across_borders else ["country"]
busmap = busmap_by_stubs(n, matching_attrs)
_remove_clustered_buses_and_branches(n, busmap)
return n, busmap
def aggregate_to_substations(
n: pypsa.Network,
buses_i: pd.Index | list,
aggregation_strategies: dict | None = None,
) -> Tuple[pypsa.Network, pd.Series]:
2021-06-01 08:55:26 +00:00
# can be used to aggregate a selection of buses to electrically closest neighbors
logger.info("Aggregating buses to substations")
if aggregation_strategies is None:
aggregation_strategies = dict()
weight = pd.concat(
{
"Line": n.lines.length / n.lines.s_nom.clip(1e-3),
"Link": n.links.length / n.links.p_nom.clip(1e-3),
}
)
adj = n.adjacency_matrix(branch_components=["Line", "Link"], weights=weight)
bus_indexer = n.buses.index.get_indexer(buses_i)
dist = pd.DataFrame(
dijkstra(adj, directed=False, indices=bus_indexer), buses_i, n.buses.index
)
dist[buses_i] = (
np.inf
) # bus in buses_i should not be assigned to different bus in buses_i
for c in n.buses.country.unique():
incountry_b = n.buses.country == c
dist.loc[incountry_b, ~incountry_b] = np.inf
busmap = n.buses.index.to_series()
busmap.loc[buses_i] = dist.idxmin(1)
line_strategies = aggregation_strategies.get("lines", dict())
bus_strategies = aggregation_strategies.get("buses", dict())
bus_strategies.setdefault("substation_lv", lambda x: bool(x.sum()))
bus_strategies.setdefault("substation_off", lambda x: bool(x.sum()))
clustering = get_clustering_from_busmap(
n,
busmap,
line_length_factor=1.0,
bus_strategies=bus_strategies,
line_strategies=line_strategies,
)
return clustering.network, busmap
def find_closest_bus(n, x, y, tol=2000):
"""
Find the index of the closest bus to the given coordinates within a specified tolerance.
Parameters:
n (pypsa.Network): The network object.
x (float): The x-coordinate (longitude) of the target location.
y (float): The y-coordinate (latitude) of the target location.
tol (float): The distance tolerance in meters. Default is 2000 meters.
Returns:
int: The index of the closest bus to the target location within the tolerance.
Returns None if no bus is within the tolerance.
"""
# Conversion factors
meters_per_degree_lat = 111139 # Meters per degree of latitude
meters_per_degree_lon = 111139 * np.cos(
np.radians(y)
) # Meters per degree of longitude at the given latitude
x0 = np.array(n.buses.x)
y0 = np.array(n.buses.y)
# Calculate distances in meters
dist = np.sqrt(
((x - x0) * meters_per_degree_lon) ** 2
+ ((y - y0) * meters_per_degree_lat) ** 2
)
# Find the closest bus within the tolerance
min_dist = dist.min()
if min_dist <= tol:
return n.buses.index[dist.argmin()]
else:
return None
if __name__ == "__main__":
if "snakemake" not in globals():
Introduce mocksnakemake which acutally parses Snakefile (#107) * rewrite mocksnakemake for parsing real Snakefile * continue add function to scripts * going through all scripts, setting new mocksnakemake * fix plotting scripts * fix build_country_flh * fix build_country_flh II * adjust config files * fix make_summary for tutorial network * create dir also for output * incorporate suggestions * consistent import of mocksnakemake * consistent import of mocksnakemake II * Update scripts/_helpers.py Co-Authored-By: euronion <42553970+euronion@users.noreply.github.com> * Update scripts/_helpers.py Co-Authored-By: euronion <42553970+euronion@users.noreply.github.com> * Update scripts/_helpers.py Co-Authored-By: euronion <42553970+euronion@users.noreply.github.com> * Update scripts/_helpers.py Co-Authored-By: euronion <42553970+euronion@users.noreply.github.com> * Update scripts/plot_network.py Co-Authored-By: euronion <42553970+euronion@users.noreply.github.com> * Update scripts/plot_network.py Co-Authored-By: euronion <42553970+euronion@users.noreply.github.com> * Update scripts/retrieve_databundle.py Co-Authored-By: euronion <42553970+euronion@users.noreply.github.com> * use pathlib for mocksnakemake * rename mocksnakemake into mock_snakemake * revert change in data * Update scripts/_helpers.py Co-Authored-By: euronion <42553970+euronion@users.noreply.github.com> * remove setting logfile in mock_snakemake, use Path in configure_logging * fix fallback path and base_dir fix return type of make_io_accessable * reformulate mock_snakemake * incorporate suggestion, fix typos * mock_snakemake: apply absolute paths again, add assertion error *.py: make hard coded io path accessable for mock_snakemake * retrieve_natura_raster: use snakemake.output for fn_out * include suggestion * Apply suggestions from code review Co-Authored-By: Jonas Hörsch <jonas.hoersch@posteo.de> * linting, add return ad end of file * Update scripts/plot_p_nom_max.py Co-Authored-By: Jonas Hörsch <jonas.hoersch@posteo.de> * Update scripts/plot_p_nom_max.py fixes #112 Co-Authored-By: Jonas Hörsch <jonas.hoersch@posteo.de> * plot_p_nom_max: small correction * config.tutorial.yaml fix snapshots end * use techs instead of technology * revert try out from previous commit, complete replacing * change clusters -> clusts in plot_p_nom_max due to wildcard constraints of clusters * change clusters -> clusts in plot_p_nom_max due to wildcard constraints of clusters II
2019-12-09 20:29:15 +00:00
from _helpers import mock_snakemake
snakemake = mock_snakemake("simplify_network")
Add logging to logfiles to all snakemake workflow scripts. (#102) * Add logging to logfiles to all snakemake workflow scripts. * Fix missing quotation marks in Snakefile. * Apply suggestions from code review Co-Authored-By: Fabian Neumann <fabian.neumann@outlook.de> * Apply suggestions from code review Co-Authored-By: Fabian Neumann <fabian.neumann@outlook.de> * doc: fix _ec_ filenames in docs * Allow logging message format to be specified in config.yaml. * Add logging for Snakemake rule 'retrieve_databundle '. * Add limited logging to STDERR only for retrieve_*.py scripts. * Import progressbar module only on demand. * Fix logging to file and enable concurrent printing to STDERR for most scripts. * Add new 'logging_format' option to Travis CI test config.yaml. * Add missing parenthesis (bug fix) and cross-os compatible paths. * Fix typos in messages. * Use correct log files for logging (bug fix). * doc: fix line references * config: logging_format in all configs * doc: add doc for logging_format * environment: update to powerplantmatching 0.4.3 * doc: update line references for tutorial.rst * Change logging configuration scheme for config.yaml. * Add helper function for doing basic logging configuration. * Add logpath for prepare_links_p_nom rule. * Outsource basic logging configuration for all scripts to _helper submodule. * Update documentation for changed config.yaml structure. Instead of 'logging_level' and 'logging_format', now 'logging' with subcategories is used. * _helpers: Change configure_logging signature.
2019-11-28 07:22:52 +00:00
configure_logging(snakemake)
2023-08-15 13:02:41 +00:00
set_scenario_config(snakemake)
params = snakemake.params
n = pypsa.Network(snakemake.input.network)
Nyears = n.snapshot_weightings.objective.sum() / 8760
buses_prev, lines_prev, links_prev = len(n.buses), len(n.lines), len(n.links)
Introducing OpenStreetMap high-voltage grid to PyPSA-Eur (#1079) * Implemented which uses the overpass API to download power features for individual countries. * Extended rule by input. * Bug fixes and improvements to clean_osm_data.py. Added in retrieve_osm_data.py. * Updated clean_osm_data and retrieve_osm_data to create clean substations. * Finished clean_osm_data function. * Added check whether line is a circle. If so, drop it. * Extended build_electricity.smk by build_osm_network.py * Added build_osm_network * Working osm-network-fast * Bug fixes. * Finalised and cleaned including docstrings. * Added try catch to retrieve_osm_data. Allows for parallelisation of downloads. * Updated cleaning process. * Set maximum number of threads for retrieving to 4, wrt. fair usage policy and potential request errors. * Intermediate update on clean_osm_data.py. Added docstrings. * Bug fix. * Bug fix. * Bug fixes in data types out of clean_osm_data * Significant improvements to retrieve_osm_data, clean_osm_data. Cleaned code. Speed improvements * Cleaned config. * Fixes. * Bug fixes. * Updated default config * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Removed overpass from required packages. Not needed anymore. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added links_relations (route = power, frequency = 0) to retrieval. This will change how HVDC links are extracted in the near future. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Work-in-progress clean_osm_data * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Added clean links output to clean_osm_data. Script uses OSM relations to retrieve clean HVDC links. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * New code for integrating HVDC links. Using relations. Base network implementation functioning. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * removed manual line dropping. * Updated clean script * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * reverted Snakefile to default: sync settings * added prebuilt functionality. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Updated build_electricity.smk to work with scenario management. * removed commented-out code. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * removed commented-out code. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Fixed bug in pdf export by substituting pdf export with svg. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Bug-fix Snakefile * dropped not needed columns from build_osm_network. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Updated build_shapes, config.default and clean_osm_data. * pre-commit changes. * test * Added initial prepare_osm_network_release.py script * Finalised prepare_osm_network_release script to build clean and stable OSM base_network input files. * Added new rules/development.smk * Updated clean_osm_data to add substation_centroid to linestrings * Updated clean_osm_data to add substation_centroid to linestrings * Updated clean_osm_data to add substation_centroid to linestrings * Updated clean_osm_data to add substation_centroid to linestrings * Added osm-prebuilt functionality and zenodo sandbox repository. * Updated clean_osm_data to geopandas v.1.01 * Made base_network and build_osm_network function more robust for empty links. * Made base_network and build_osm_network function more robust for empty links. * Bug fix in base_network. Voltage level null is now kept (relevant e.g. for Corsica) * Merge with hcanges in upstream PR 1146. Fixing UA and MD. * Updated Zenodo and fixed prepare_osm_network_release * Updated osm network release. * Updated prepare osm network release. * Updated MD, UA scripts. * Cleaned determine_availability_matrix_MD_UA.py, removed redundant code * Bug fixes. * Bug fixes for UA MD scripts. * Rename of build script. * Bug fix: only distribute load to buses with substation. * Updated zenodo sandbox repository. * Updated config.default * Cleaned config.default.yaml: Related settings grouped together and redundant voltage settings aggregated. * Cleaned config.default.yaml: Related settings grouped together and redundant voltage settings aggregated. Added release notes. * Updated Zenodo repositories for OSM-prebuilt to offcial publication. * Updated configtables * Updated links.csv: Under_construction lines to in commission. * Updated link 8394 and parameter_corrections: Continuation of North-Sea-Link. * Major update: fix simplify_network, fix Corsica, updated build_osm_network to include lines overpassing nodes. * remove config backup * Bug fix: Carrier type of all supernodes corrected to 'AC' * Bug fix: Carrier type of all supernodes corrected to 'AC' * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Updated rules and base_network for compatibility with TYNDP projects. * Updated Zenodo repository and prebuilt network to include 150 kV HVDC connections. * Removed outdated config backup. * Implemented all comments from PR #1079. Cleaned up OSM implementation. * Bug fix: Added all voltages, 200 kV-750 kV, to default config. * Cleaning and bugfixes. * Updated Zenodo repository to https://zenodo.org/records/13358976. Added converter voltages, 'underground' property for DC lines/cables, and included Konti-Skan HVDC (DK-SE). Added compatibility with https://github.com/PyPSA/pypsa-eur/pull/1079 and https://github.com/PyPSA/pypsa-eur/pull/1085 * Apply suggestions from code review * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * simplify_network: handle complicated transformer topologies * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * syntax fix --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Fabian Neumann <fabian.neumann@outlook.de>
2024-08-22 13:01:20 +00:00
linetype_380 = snakemake.config["lines"]["types"][380]
n, trafo_map = simplify_network_to_380(n, linetype_380)
n, simplify_links_map = simplify_links(n, params.p_max_pu)
busmaps = [trafo_map, simplify_links_map]
if params.simplify_network["remove_stubs"]:
n, stub_map = remove_stubs(n, params.simplify_network)
busmaps.append(stub_map)
substations_i = n.buses.query("substation_lv or substation_off").index
# some entries in n.buses are not updated in previous functions, therefore can be wrong. as they are not needed
# and are lost when clustering (for example with the simpl wildcard), we remove them for consistency:
remove = [
"symbol",
"tags",
"under_construction",
"onshore_bus",
"geometry",
"underground",
handle new and upgraded TYNDP&NEP lines/links in base network (OSM compatible) (#1085) * add general implementation to add tyndp and nep. TODO: Remove duplicate? * pre_osm_merge * clean and update base_network.py update default config settings * clean and update base_network.py update default config settings * base_network.py:remove adding of transmission projects add_transmission_project.py: add new script for creating lines and link csv from transmission projects add_electricity.py: add new projects from created csv files * cluster_network.py: do not allow to group lines with different build years together-> requires pypsa update simplify_network.py: fix bug of simplify links * remove legacies of removing transmission projects from base_network * restructure folders:new folder for tranmission project csv add_transmission_projects: improve logging, cleanup * update lines csvs and add default line type for upgraded and new lines * remove duplicate lines which were already in gridkit * allow to connect ac lines only to ac buses * add manual links csv (adjusted links_tyndp.csv) and update default config * add realease note * remove links_tyndp.csv file, references in build_elec.smk and function in base_network.py to add them * add configuration options for transmission projects to documentation and add template folder for transmission projects * update pypsa version in environments * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * integrate Fabian's review comments 2 * add electricity:add import pathlib and duplicate printing out of adding line projects * update NEP line csv * address Fabian's comments * build_transmission_projects: address Fabian's final comments simplify_network: use modus to get line type which appears most often * build_transmission_project: change from .geometry to ["geometry"] * build_transmission_projects: remove redundanty line * build_transmission_projects: remove buffer for europe shape because of higher resolution default config: fix wrong key for skip argument in transmission_projects * update configtables and default config * update manual links csv and delete undetected duplicate links in tyndp2020 * final adjustments --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Fabian Neumann <fabian.neumann@outlook.de>
2024-08-15 09:42:21 +00:00
"project_status",
]
n.buses.drop(remove, axis=1, inplace=True, errors="ignore")
n.lines.drop(remove, axis=1, errors="ignore", inplace=True)
if params.simplify_network["to_substations"]:
n, substation_map = aggregate_to_substations(
n, substations_i, params.aggregation_strategies
)
busmaps.append(substation_map)
# all buses without shapes need to be clustered to their closest neighbor for HAC
if params.cluster_network["algorithm"] == "hac":
buses_i = list(n.buses.index.difference(n.shapes.idx))
logger.info(
"Preparing for HAC-Clustering. "
f"Aggregating {len(buses_i)} buses without Voronoi shapes to closest neighbor."
)
n, busmap_hac = aggregate_to_substations(
n, buses_i, params.aggregation_strategies
)
busmaps.append(busmap_hac)
2022-06-30 06:39:03 +00:00
busmap_s = reduce(lambda x, y: x.map(y), busmaps[1:], busmaps[0])
busmap_s.to_csv(snakemake.output.busmap)
for which in ["regions_onshore", "regions_offshore"]:
regions = gpd.read_file(snakemake.input[which])
clustered_regions = cluster_regions(busmaps, regions, with_country=True)
clustered_regions.to_file(snakemake.output[which])
# append_bus_shapes(n, clustered_regions, type=which.split("_")[1])
n.meta = dict(snakemake.config, **dict(wildcards=dict(snakemake.wildcards)))
n.export_to_netcdf(snakemake.output.network)
logger.info(
f"Simplified network:\n"
f"Buses: {buses_prev} to {len(n.buses)}\n"
f"Lines: {lines_prev} to {len(n.lines)}\n"
f"Links: {links_prev} to {len(n.links)}"
)