Skip to content

Commit

Permalink
Added shunt admittance and voltage level dependet mv-lines (#294)
Browse files Browse the repository at this point in the history
* Added shunt admittance and voltage level dependet mv-lines

* Fixes Issue #243 and #213

* Minor changes

* Fix test

Co-authored-by: birgits <birgit.schachler@rl-institut.de>
  • Loading branch information
mltja and birgits committed Sep 5, 2022
1 parent 1a96538 commit 10d0b3b
Show file tree
Hide file tree
Showing 12 changed files with 254 additions and 76 deletions.
3 changes: 2 additions & 1 deletion edisgo/config/config_grid_expansion_default.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
# Standard equipment for grid expansion measures. Source: Rehtanz et. al.: "Verteilnetzstudie für das Land Baden-Württemberg", 2017.
hv_mv_transformer = 40 MVA
mv_lv_transformer = 630 kVA
mv_line = NA2XS2Y 3x1x185 RM/25
mv_line_10kv = NA2XS2Y 3x1x185 RM/25
mv_line_20kv = NA2XS2Y 3x1x240
lv_line = NAYY 4x1x150

[grid_expansion_allowed_voltage_deviations]
Expand Down
20 changes: 10 additions & 10 deletions edisgo/equipment/equipment-parameters_LV_cables.csv
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
name,U_n,I_max_th,R_per_km,L_per_km
#-,kV,kA,ohm/km,mH/km
NAYY 4x1x300,0.4,0.419,0.1,0.279
NAYY 4x1x240,0.4,0.364,0.125,0.254
NAYY 4x1x185,0.4,0.313,0.164,0.256
NAYY 4x1x150,0.4,0.275,0.206,0.256
NAYY 4x1x120,0.4,0.245,0.253,0.256
NAYY 4x1x95,0.4,0.215,0.320,0.261
NAYY 4x1x50,0.4,0.144,0.449,0.270
NAYY 4x1x35,0.4,0.123,0.868,0.271
name,U_n,I_max_th,R_per_km,L_per_km,C_per_km
#-,kV,kA,ohm/km,mH/km,uF/km
NAYY 4x1x300,0.4,0.419,0.1,0.279,0
NAYY 4x1x240,0.4,0.364,0.125,0.254,0
NAYY 4x1x185,0.4,0.313,0.164,0.256,0
NAYY 4x1x150,0.4,0.275,0.206,0.256,0
NAYY 4x1x120,0.4,0.245,0.253,0.256,0
NAYY 4x1x95,0.4,0.215,0.320,0.261,0
NAYY 4x1x50,0.4,0.144,0.449,0.270,0
NAYY 4x1x35,0.4,0.123,0.868,0.271,0
66 changes: 39 additions & 27 deletions edisgo/flex_opt/reinforce_measures.py
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ def reinforce_lines_voltage_issues(edisgo_obj, grid, crit_nodes):
]
elif isinstance(grid, MVGrid):
standard_line = edisgo_obj.config["grid_expansion_standard_equipment"][
"mv_line"
f"mv_line_{int(grid.nominal_voltage)}kv"
]
else:
raise ValueError("Inserted grid is invalid.")
Expand Down Expand Up @@ -693,40 +693,52 @@ def _replace_by_parallel_standard_lines(lines):

lines_changes.update(number_parallel_lines.to_dict())

standard_line_type = edisgo_obj.config["grid_expansion_standard_equipment"][
"{}_line".format(voltage_level)
]

lines_changes = {}

# chose lines of right grid level
relevant_lines = edisgo_obj.topology.lines_df.loc[
crit_lines[crit_lines.voltage_level == voltage_level].index
]
if not relevant_lines.empty:
nominal_voltage = edisgo_obj.topology.buses_df.loc[
edisgo_obj.topology.lines_df.loc[relevant_lines.index[0], "bus0"], "v_nom"
]
if nominal_voltage == 0.4:
standard_line_type = edisgo_obj.config["grid_expansion_standard_equipment"][
"lv_line"
]
else:
standard_line_type = edisgo_obj.config["grid_expansion_standard_equipment"][
f"mv_line_{int(nominal_voltage)}kv"
]

# handling of standard lines
lines_standard = relevant_lines.loc[relevant_lines.type_info == standard_line_type]
if not lines_standard.empty:
_add_parallel_standard_lines(lines_standard.index)
# handling of standard lines
lines_standard = relevant_lines.loc[
relevant_lines.type_info == standard_line_type
]
if not lines_standard.empty:
_add_parallel_standard_lines(lines_standard.index)

# get lines that have not been updated yet (i.e. that are not standard
# lines)
relevant_lines = relevant_lines.loc[
~relevant_lines.index.isin(lines_standard.index)
]
# handling of cables where adding one cable is sufficient
lines_single = (
relevant_lines.loc[relevant_lines.num_parallel == 1]
.loc[relevant_lines.kind == "cable"]
.loc[crit_lines.max_rel_overload < 2]
)
if not lines_single.empty:
_add_one_parallel_line_of_same_type(lines_single.index)
# get lines that have not been updated yet (i.e. that are not standard
# lines)
relevant_lines = relevant_lines.loc[
~relevant_lines.index.isin(lines_standard.index)
]
# handling of cables where adding one cable is sufficient
lines_single = (
relevant_lines.loc[relevant_lines.num_parallel == 1]
.loc[relevant_lines.kind == "cable"]
.loc[crit_lines.max_rel_overload < 2]
)
if not lines_single.empty:
_add_one_parallel_line_of_same_type(lines_single.index)

# handle rest of lines (replace by as many parallel standard lines as
# needed)
relevant_lines = relevant_lines.loc[~relevant_lines.index.isin(lines_single.index)]
if not relevant_lines.empty:
_replace_by_parallel_standard_lines(relevant_lines.index)
# handle rest of lines (replace by as many parallel standard lines as
# needed)
relevant_lines = relevant_lines.loc[
~relevant_lines.index.isin(lines_single.index)
]
if not relevant_lines.empty:
_replace_by_parallel_standard_lines(relevant_lines.index)

return lines_changes
2 changes: 1 addition & 1 deletion edisgo/io/pypsa_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ def _set_slack(grid):
],
"Line": edisgo_object.topology.lines_df.loc[
:,
["bus0", "bus1", "x", "r", "s_nom", "num_parallel", "length"],
["bus0", "bus1", "x", "r", "b", "s_nom", "num_parallel", "length"],
],
"Transformer": edisgo_object.topology.transformers_df.loc[
:, ["bus0", "bus1", "x_pu", "r_pu", "type_info", "s_nom"]
Expand Down
52 changes: 34 additions & 18 deletions edisgo/network/topology.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
calculate_apparent_power,
calculate_line_reactance,
calculate_line_resistance,
calculate_line_susceptance,
select_cable,
)

Expand Down Expand Up @@ -48,6 +49,7 @@
"length",
"x",
"r",
"b",
"s_nom",
"num_parallel",
"type_info",
Expand Down Expand Up @@ -1247,7 +1249,7 @@ def add_line(self, bus0, bus1, length, **kwargs):
Adds line to topology.
Line name is generated automatically.
If `type_info` is provided, `x`, `r` and `s_nom` are calculated.
If `type_info` is provided, `x`, `r`, `b` and `s_nom` are calculated.
Parameters
----------
Expand All @@ -1262,8 +1264,8 @@ def add_line(self, bus0, bus1, length, **kwargs):
------------------
kwargs :
Kwargs may contain any further attributes in :py:attr:`~lines_df`.
It is necessary to either provide `type_info` to determine `x`, `r`
and `s_nom` of the line, or to provide `x`, `r` and `s_nom`
It is necessary to either provide `type_info` to determine `x`, `r`, `b`
and `s_nom` of the line, or to provide `x`, `r`, `b` and `s_nom`
directly.
"""
Expand Down Expand Up @@ -1328,17 +1330,18 @@ def _get_line_data():
# unpack optional parameters
x = kwargs.get("x", None)
r = kwargs.get("r", None)
b = kwargs.get("b", 0.0)
s_nom = kwargs.get("s_nom", None)
num_parallel = kwargs.get("num_parallel", 1)
type_info = kwargs.get("type_info", None)
kind = kwargs.get("kind", None)

# if type of line is specified calculate x, r and s_nom
if type_info is not None:
if x is not None or r is not None or s_nom is not None:
if x is not None or r is not None or b is not None or s_nom is not None:
warnings.warn(
"When line 'type_info' is provided when creating a new "
"line, x, r and s_nom are calculated and provided "
"line, x, r, b and s_nom are calculated and provided "
"parameters are overwritten."
)
line_data = _get_line_data()
Expand All @@ -1348,6 +1351,7 @@ def _get_line_data():
).iloc[0, :]
x = calculate_line_reactance(line_data.L_per_km, length, num_parallel)
r = calculate_line_resistance(line_data.R_per_km, length, num_parallel)
b = calculate_line_susceptance(line_data.C_per_km, length, num_parallel)
s_nom = calculate_apparent_power(
line_data.U_n, line_data.I_max_th, num_parallel
)
Expand All @@ -1374,6 +1378,7 @@ def _get_line_data():
"bus1": bus1,
"x": x,
"r": r,
"b": b,
"length": length,
"type_info": type_info,
"num_parallel": num_parallel,
Expand Down Expand Up @@ -1595,7 +1600,7 @@ def update_number_of_parallel_lines(self, lines_num_parallel):
"""
Changes number of parallel lines and updates line attributes.
When number of parallel lines changes, attributes x, r, and s_nom have
When number of parallel lines changes, attributes x, r, b, and s_nom have
to be adapted, which is done in this function.
Parameters
Expand All @@ -1606,12 +1611,17 @@ def update_number_of_parallel_lines(self, lines_num_parallel):
new number of parallel lines.
"""
# update x, r and s_nom
# update x, r, b and s_nom
self._lines_df.loc[lines_num_parallel.index, "x"] = (
self._lines_df.loc[lines_num_parallel.index, "x"]
* self._lines_df.loc[lines_num_parallel.index, "num_parallel"]
/ lines_num_parallel
)
self._lines_df.loc[lines_num_parallel.index, "b"] = (
self._lines_df.loc[lines_num_parallel.index, "b"]
/ self._lines_df.loc[lines_num_parallel.index, "num_parallel"]
* lines_num_parallel
)
self._lines_df.loc[lines_num_parallel.index, "r"] = (
self._lines_df.loc[lines_num_parallel.index, "r"]
* self._lines_df.loc[lines_num_parallel.index, "num_parallel"]
Expand Down Expand Up @@ -1681,19 +1691,25 @@ def change_line_type(self, lines, new_line_type):
self._lines_df.loc[lines, "num_parallel"] = 1
self._lines_df.loc[lines, "kind"] = "cable"

self._lines_df.loc[lines, "r"] = (
data_new_line.R_per_km * self.lines_df.loc[lines, "length"]
self._lines_df.loc[lines, "r"] = calculate_line_resistance(
data_new_line.R_per_km,
self.lines_df.loc[lines, "length"],
self._lines_df.loc[lines, "num_parallel"],
)
self._lines_df.loc[lines, "x"] = calculate_line_reactance(
data_new_line.L_per_km,
self.lines_df.loc[lines, "length"],
self._lines_df.loc[lines, "num_parallel"],
)
self._lines_df.loc[lines, "x"] = (
data_new_line.L_per_km
* 2
* np.pi
* 50
/ 1e3
* self.lines_df.loc[lines, "length"]
self._lines_df.loc[lines, "b"] = calculate_line_susceptance(
data_new_line.C_per_km,
self.lines_df.loc[lines, "length"],
self._lines_df.loc[lines, "num_parallel"],
)
self._lines_df.loc[lines, "s_nom"] = (
np.sqrt(3) * data_new_line.U_n * data_new_line.I_max_th
self._lines_df.loc[lines, "s_nom"] = calculate_apparent_power(
data_new_line.U_n,
data_new_line.I_max_th,
self._lines_df.loc[lines, "num_parallel"],
)

def connect_to_mv(self, edisgo_object, comp_data, comp_type="generator"):
Expand Down
99 changes: 99 additions & 0 deletions edisgo/tools/tools.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
import os

from math import pi, sqrt
Expand All @@ -20,6 +21,9 @@
from shapely.wkt import loads as wkt_loads


logger = logging.getLogger(__name__)


def select_worstcase_snapshots(edisgo_obj):
"""
Select two worst-case snapshots from time series
Expand Down Expand Up @@ -149,6 +153,28 @@ def calculate_line_resistance(line_resistance_per_km, line_length, num_parallel)
return line_resistance_per_km * line_length / num_parallel


def calculate_line_susceptance(line_capacitance_per_km, line_length, num_parallel):
"""
Calculates line shunt susceptance in Siemens.
Parameters
----------
line_capacitance_per_km : float
Line capacitance in uF/km.
line_length : float
Length of line in km.
num_parallel : int
Number of parallel lines.
Returns
-------
float
Shunt susceptance in Siemens.
"""
return line_capacitance_per_km / 1e6 * line_length * 2 * pi * 50 * num_parallel


def calculate_apparent_power(nominal_voltage, current, num_parallel):
"""
Calculates apparent power in MVA from given voltage and current.
Expand Down Expand Up @@ -532,3 +558,76 @@ def get_files_recursive(path, files=None):
files.append(file)

return files


def add_line_susceptance(
edisgo_obj,
mode="mv_b",
):
"""
Adds line susceptance information in Siemens to lines in existing grids.
Parameters
----------
edisgo_obj : :class:`~.EDisGo`
EDisGo object to which line susceptance information is added.
mode : str
Defines how the susceptance is added:
* 'no_b'
Susceptance is set to 0 for all lines.
* 'mv_b' (Default)
Susceptance is for the MV lines set according to the equipment parameters
and for the LV lines it is set to zero.
* 'all_b'
Susceptance is for the MV lines set according to the equipment parameters
and for the LV lines 0.25 uF/km is chosen.
Returns
-------
:class:`~.EDisGo`
"""
line_data_df = pd.concat(
[
edisgo_obj.topology.equipment_data["mv_overhead_lines"],
edisgo_obj.topology.equipment_data["mv_cables"],
edisgo_obj.topology.equipment_data["lv_cables"],
]
)

if mode == "no_b":
line_data_df.loc[:, "C_per_km"] = 0
elif mode == "mv_b":
line_data_df.loc[
edisgo_obj.topology.equipment_data["lv_cables"].index, "C_per_km"
] = 0
elif mode == "all_b":
line_data_df.loc[
edisgo_obj.topology.equipment_data["lv_cables"].index, "C_per_km"
] = 0.25
else:
raise ValueError("Non-existing mode.")

lines_df = edisgo_obj.topology.lines_df
buses_df = edisgo_obj.topology.buses_df

for index, bus0, type_info, length, num_parallel in lines_df[
["bus0", "type_info", "length", "num_parallel"]
].itertuples():
v_nom = buses_df.loc[bus0].v_nom

try:
line_capacitance_per_km = (
line_data_df.loc[line_data_df.U_n == v_nom].loc[type_info].C_per_km
)
except KeyError:
line_capacitance_per_km = line_data_df.loc[type_info].C_per_km
logger.warning(f"False voltage level for line {index}.")

lines_df.loc[index, "b"] = calculate_line_susceptance(
line_capacitance_per_km, length, num_parallel
)

return edisgo_obj
4 changes: 2 additions & 2 deletions tests/data/ding0_test_network_1/lines.csv
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ name,bus0,bus1,length,x,r,s_nom,num_parallel,kind,type_info
Line_10003,Bus_MVStation_1,Bus_BranchTee_MVGrid_1_1,0.083904310632546,0.031103993574751,0.031044594934042,7.27461339178928,1,line,48-AL1/8-ST1A
Line_10004,Bus_MVStation_1,Bus_BranchTee_MVGrid_1_4,0.226148217025158,0.083834938112983,0.083674840299309,7.27461339178928,1,line,48-AL1/8-ST1A
Line_10005,Bus_MVStation_1,Bus_BranchTee_MVGrid_1_5,0.543380191002877,0.201435347506981,0.201050670671064,7.27461339178928,1,line,48-AL1/8-ST1A
Line_10006,Bus_MVStation_1,Bus_BranchTee_MVGrid_1_6,0.297650465459542,0.110341388843783,0.110130672220031,7.27461339178928,1,line,NA2XS2Y 3x1x185 RM/25
Line_10007,Bus_BranchTee_MVGrid_1_1,BusBar_MVGrid_1_LVGrid_1_MV,0.722445826838636,0.267816399261118,0.267304955930295,7.27461339178928,1,line,NA2XS2Y 3x1x185 RM/25
Line_10006,Bus_MVStation_1,Bus_BranchTee_MVGrid_1_6,0.297650465459542,0.03363542166704131,0.03869456050974046,7.27461339178928,1,line,NA2XS2Y 3x1x240
Line_10007,Bus_BranchTee_MVGrid_1_1,BusBar_MVGrid_1_LVGrid_1_MV,0.722445826838636,0.08163860916459667,0.09391795748902268,7.27461339178928,1,line,NA2XS2Y 3x1x240
Line_10008,Bus_BranchTee_MVGrid_1_2,BusBar_MVGrid_1_LVGrid_1_MV,0.132867031507129,0.049254862630276,0.049160801657638,7.27461339178928,1,line,48-AL1/8-ST1A
Line_10009,Bus_BranchTee_MVGrid_1_2,BusBar_MVGrid_1_LVGrid_2_MV,0.705785336662554,0.261640223383117,0.261140574565145,7.27461339178928,1,line,48-AL1/8-ST1A
Line_10010,Bus_BranchTee_MVGrid_1_2,BusBar_MVGrid_1_LVGrid_5_MV,0.012061682815469,0.004471361506515,0.004462822641724,7.27461339178928,1,line,48-AL1/8-ST1A
Expand Down

0 comments on commit 10d0b3b

Please sign in to comment.