107 lines
3.2 KiB
Python
107 lines
3.2 KiB
Python
|
# -*- coding: utf-8 -*-
|
||
|
# SPDX-FileCopyrightText: : 2017-2024 The PyPSA-Eur Authors
|
||
|
#
|
||
|
# SPDX-License-Identifier: MIT
|
||
|
"""
|
||
|
Add transmission projects and DLR to the network.
|
||
|
"""
|
||
|
|
||
|
import logging
|
||
|
from pathlib import Path
|
||
|
|
||
|
import numpy as np
|
||
|
import pandas as pd
|
||
|
import pypsa
|
||
|
import xarray as xr
|
||
|
from _helpers import configure_logging, set_scenario_config
|
||
|
|
||
|
logger = logging.getLogger(__name__)
|
||
|
|
||
|
|
||
|
def attach_transmission_projects(
|
||
|
n: pypsa.Network, transmission_projects: list[str]
|
||
|
) -> None:
|
||
|
logger.info("Adding transmission projects to network.")
|
||
|
for path in transmission_projects:
|
||
|
path = Path(path)
|
||
|
df = pd.read_csv(path, index_col=0, dtype={"bus0": str, "bus1": str})
|
||
|
if df.empty:
|
||
|
continue
|
||
|
if "new_buses" in path.name:
|
||
|
n.madd("Bus", df.index, **df)
|
||
|
elif "new_lines" in path.name:
|
||
|
n.madd("Line", df.index, **df)
|
||
|
elif "new_links" in path.name:
|
||
|
n.madd("Link", df.index, **df)
|
||
|
elif "adjust_lines" in path.name:
|
||
|
n.lines.update(df)
|
||
|
elif "adjust_links" in path.name:
|
||
|
n.links.update(df)
|
||
|
|
||
|
|
||
|
def attach_line_rating(
|
||
|
n: pypsa.Network,
|
||
|
rating: pd.DataFrame,
|
||
|
s_max_pu: float,
|
||
|
correction_factor: float,
|
||
|
max_voltage_difference: float | bool,
|
||
|
max_line_rating: float | bool,
|
||
|
) -> None:
|
||
|
logger.info("Attaching dynamic line rating to network.")
|
||
|
# TODO: Only considers overhead lines
|
||
|
n.lines_t.s_max_pu = (rating / n.lines.s_nom[rating.columns]) * correction_factor
|
||
|
if max_voltage_difference:
|
||
|
x_pu = (
|
||
|
n.lines.type.map(n.line_types["x_per_length"])
|
||
|
* n.lines.length
|
||
|
/ (n.lines.v_nom**2)
|
||
|
)
|
||
|
# need to clip here as cap values might be below 1
|
||
|
# -> would mean the line cannot be operated at actual given pessimistic ampacity
|
||
|
s_max_pu_cap = (
|
||
|
np.deg2rad(max_voltage_difference) / (x_pu * n.lines.s_nom)
|
||
|
).clip(lower=1)
|
||
|
n.lines_t.s_max_pu = n.lines_t.s_max_pu.clip(
|
||
|
lower=1, upper=s_max_pu_cap, axis=1
|
||
|
)
|
||
|
if max_line_rating:
|
||
|
n.lines_t.s_max_pu = n.lines_t.s_max_pu.clip(upper=max_line_rating)
|
||
|
n.lines_t.s_max_pu *= s_max_pu
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
if "snakemake" not in globals():
|
||
|
from _helpers import mock_snakemake
|
||
|
|
||
|
snakemake = mock_snakemake("add_transmission_projects_and_dlr")
|
||
|
configure_logging(snakemake)
|
||
|
set_scenario_config(snakemake)
|
||
|
|
||
|
params = snakemake.params
|
||
|
|
||
|
n = pypsa.Network(snakemake.input.network)
|
||
|
|
||
|
if params["transmission_projects"]["enable"]:
|
||
|
|
||
|
attach_transmission_projects(n, snakemake.input.transmission_projects)
|
||
|
|
||
|
if params["dlr"]["activate"]:
|
||
|
|
||
|
rating = xr.open_dataarray(snakemake.input.dlr).to_pandas().transpose()
|
||
|
|
||
|
s_max_pu = params["s_max_pu"]
|
||
|
correction_factor = params["dlr"]["correction_factor"]
|
||
|
max_voltage_difference = params["dlr"]["max_voltage_difference"]
|
||
|
max_line_rating = params["dlr"]["max_line_rating"]
|
||
|
|
||
|
attach_line_rating(
|
||
|
n,
|
||
|
rating,
|
||
|
s_max_pu,
|
||
|
correction_factor,
|
||
|
max_voltage_difference,
|
||
|
max_line_rating,
|
||
|
)
|
||
|
|
||
|
n.export_to_netcdf(snakemake.output[0])
|