Skip to content

Commit

Permalink
Merge pull request e2nIEE#2394 from e2nIEE/feature/optional_vk_updates
Browse files Browse the repository at this point in the history
Feature/optional vk updates
  • Loading branch information
vogt31337 authored Sep 19, 2024
2 parents e3fa0c6 + ab21893 commit 391a6e1
Show file tree
Hide file tree
Showing 22 changed files with 85 additions and 63 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Change Log

[upcoming release] - 2024-..-..
-------------------------------
- [ADDED] A switch to disable updating the vk and vkr values for trafo3w
- [FIXED] cast the column to the correct type before assigning values
- [FIXED] replacement for deprecated namespaces scipy.sparse.csc and scipy.sparse.csr
- [FIXED] copy array element to standard python scalar
Expand Down
67 changes: 39 additions & 28 deletions pandapower/build_branch.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@

import numpy as np
import pandas as pd
from pandapower import DC_BUS_TYPE

from pandapower.auxiliary import get_values
from pandapower.pypower.idx_brch import F_BUS, T_BUS, BR_R, BR_X, BR_B, BR_G, TAP, SHIFT, BR_STATUS, RATE_A, \
Expand All @@ -22,13 +21,13 @@
GAMMA, EPSILON, T_AMBIENT_C, T_REF_C, branch_cols_tdpf
from pandapower.pypower.idx_brch_sc import branch_cols_sc
from pandapower.pypower.idx_bus import BASE_KV, VM, VA, BUS_TYPE, BUS_AREA, ZONE, VMAX, VMIN, PQ
from pandapower.pypower.idx_bus_dc import DC_BUS_AREA, DC_VM, DC_ZONE, DC_VMAX, DC_VMIN, DC_P, DC_BASE_KV
from pandapower.pypower.idx_bus_dc import DC_BUS_AREA, DC_VM, DC_ZONE, DC_VMAX, DC_VMIN, DC_P, DC_BASE_KV, DC_BUS_TYPE
from pandapower.pypower.idx_bus_sc import C_MIN, C_MAX
from pandapower.pypower.idx_tcsc import TCSC_F_BUS, TCSC_T_BUS, TCSC_X_L, TCSC_X_CVAR, TCSC_SET_P, \
TCSC_THYRISTOR_FIRING_ANGLE, TCSC_STATUS, TCSC_CONTROLLABLE, tcsc_cols, TCSC_MIN_FIRING_ANGLE, TCSC_MAX_FIRING_ANGLE


def _build_branch_ppc(net, ppc):
def _build_branch_ppc(net, ppc, update_vk_values: bool=True):
"""
Takes the empty ppc network and fills it with the branch values. The branch
datatype will be np.complex 128 afterwards.
Expand Down Expand Up @@ -65,9 +64,9 @@ def _build_branch_ppc(net, ppc):
if "line" in lookup:
_calc_line_parameter(net, ppc)
if "trafo" in lookup:
_calc_trafo_parameter(net, ppc)
_calc_trafo_parameter(net, ppc, update_vk_values=update_vk_values)
if "trafo3w" in lookup:
_calc_trafo3w_parameter(net, ppc)
_calc_trafo3w_parameter(net, ppc, update_vk_values=update_vk_values)
if "impedance" in lookup:
_calc_impedance_parameter(net, ppc)
if "xward" in lookup:
Expand Down Expand Up @@ -141,17 +140,18 @@ def _initialize_branch_lookup(net, dc=False):
return end


def _calc_trafo3w_parameter(net, ppc):
def _calc_trafo3w_parameter(net, ppc, update_vk_values: bool=True):
bus_lookup = net["_pd2ppc_lookups"]["bus"]
branch = ppc["branch"]
f, t = net["_pd2ppc_lookups"]["branch"]["trafo3w"]
trafo_df = _trafo_df_from_trafo3w(net)
trafo_df = _trafo_df_from_trafo3w(net, update_vk_values=update_vk_values)
hv_bus = get_trafo_values(trafo_df, "hv_bus").astype(np.int64)
lv_bus = get_trafo_values(trafo_df, "lv_bus").astype(np.int64)
in_service = get_trafo_values(trafo_df, "in_service").astype(np.int64)
branch[f:t, F_BUS] = bus_lookup[hv_bus]
branch[f:t, T_BUS] = bus_lookup[lv_bus]
r, x, g, b, g_asym, b_asym, ratio, shift = _calc_branch_values_from_trafo_df(net, ppc, trafo_df)
r, x, g, b, g_asym, b_asym, ratio, shift = _calc_branch_values_from_trafo_df(net, ppc, trafo_df,
update_vk_values=update_vk_values)
branch[f:t, BR_R] = r
branch[f:t, BR_X] = x
branch[f:t, BR_G] = g
Expand Down Expand Up @@ -329,7 +329,7 @@ def _calc_line_dc_parameter(net, ppc, elm="line_dc", ppc_elm="branch_dc"):
branch_dc[f:t, DC_RATE_A] = max_load / 100. * max_i_ka * df * parallel * vr


def _calc_trafo_parameter(net, ppc):
def _calc_trafo_parameter(net, ppc, update_vk_values: bool=True):
'''
Calculates the transformer parameter in per unit.
Expand All @@ -350,7 +350,7 @@ def _calc_trafo_parameter(net, ppc):
parallel = trafo["parallel"].values
branch[f:t, F_BUS] = bus_lookup[trafo["hv_bus"].values]
branch[f:t, T_BUS] = bus_lookup[trafo["lv_bus"].values]
r, x, g, b, g_asym, b_asym, ratio, shift = _calc_branch_values_from_trafo_df(net, ppc)
r, x, g, b, g_asym, b_asym, ratio, shift = _calc_branch_values_from_trafo_df(net, ppc, update_vk_values=update_vk_values)
branch[f:t, BR_R] = r
branch[f:t, BR_X] = x
branch[f:t, BR_G] = g
Expand All @@ -377,7 +377,7 @@ def get_trafo_values(trafo_df, par):
return trafo_df[par].values


def _calc_branch_values_from_trafo_df(net, ppc, trafo_df=None, sequence=1):
def _calc_branch_values_from_trafo_df(net, ppc, trafo_df=None, sequence=1, update_vk_values=True):
"""
Calculates the MAT/PYPOWER-branch-attributes from the pandapower trafo dataframe.
Expand Down Expand Up @@ -420,16 +420,18 @@ def _calc_branch_values_from_trafo_df(net, ppc, trafo_df=None, sequence=1):
vn_trafo_hv, vn_trafo_lv, shift = _calc_tap_from_dataframe(net, trafo_df)
ratio = _calc_nominal_ratio_from_dataframe(ppc, trafo_df, vn_trafo_hv, vn_trafo_lv,
bus_lookup)
r, x, g, b, g_asym, b_asym = _calc_r_x_y_from_dataframe(net, trafo_df, vn_trafo_lv, vn_lv, ppc, sequence=sequence)
r, x, g, b, g_asym, b_asym = _calc_r_x_y_from_dataframe(net, trafo_df, vn_trafo_lv, vn_lv, ppc, sequence=sequence,
update_vk_values=update_vk_values)
return r, x, g, b, g_asym, b_asym, ratio, shift


def _calc_r_x_y_from_dataframe(net, trafo_df, vn_trafo_lv, vn_lv, ppc, sequence=1):
def _calc_r_x_y_from_dataframe(net, trafo_df, vn_trafo_lv, vn_lv, ppc, sequence=1, update_vk_values=True):
mode = net["_options"]["mode"]
trafo_model = net["_options"]["trafo_model"]

r, x = _calc_r_x_from_dataframe(mode, trafo_df, vn_lv, vn_trafo_lv, net.sn_mva,
sequence=sequence, characteristic=net.get("characteristic"))
sequence=sequence, characteristic=net.get("characteristic"),
update_vk_values=update_vk_values)

if mode == "sc":
if net._options.get("use_pre_fault_voltage", False):
Expand Down Expand Up @@ -654,35 +656,41 @@ def _get_vk_values(trafo_df, characteristic, trafotype="2W"):
vk_value = get_trafo_values(trafo_df, vk_var)
if use_tap_dependent_impedance and vk_var in char_columns:
vals += (_calc_tap_dependent_value(
trafo_df, tap_pos, vk_value, vk_var, tap_dependent_impedance,
tap_pos, vk_value, tap_dependent_impedance,
characteristic, all_characteristic_idx[:, index_column[vk_var]]),)
else:
vals += (vk_value,)

return vals


def _calc_tap_dependent_value(trafo_df, tap_pos, value, variable, tap_dependent_impedance,
characteristic, characteristic_idx):
def _calc_tap_dependent_value(tap_pos, value, tap_dependent_impedance, characteristic, characteristic_idx):
# we skip the trafos with NaN characteristics even if tap_dependent_impedance is True (we already checked for missing characteristics)
relevant_idx = tap_dependent_impedance & ~np.isnan(characteristic_idx)
vk_characteristic = np.zeros_like(tap_dependent_impedance, dtype="object")
vk_characteristic[relevant_idx] = characteristic.loc[characteristic_idx[relevant_idx], 'object'].values
# here dtype must be float otherwise the load flow calculation will fail
return np.where(relevant_idx,
[c(t).item() if f else np.nan for f, t, c in zip(relevant_idx, tap_pos, vk_characteristic)],
value)#.astype(np.float64) # astype not necessary, but if it fails then uncommenting this may help

def custom_func(f, t, c):
return c(t).item() if f else np.nan

def _calc_r_x_from_dataframe(mode, trafo_df, vn_lv, vn_trafo_lv, sn_mva, sequence=1,
characteristic=None):
custom_func_vec = np.vectorize(custom_func)
return np.where(relevant_idx, custom_func_vec(relevant_idx, tap_pos, vk_characteristic), value)


def _calc_r_x_from_dataframe(mode, trafo_df, vn_lv, vn_trafo_lv, sn_mva, sequence=1, characteristic=None,
update_vk_values=True):
"""
Calculates (Vectorized) the resitance and reactance according to the
transformer values
"""
parallel = get_trafo_values(trafo_df, "parallel")
if sequence == 1:
vk_percent, vkr_percent = _get_vk_values(trafo_df, characteristic)
if update_vk_values:
vk_percent, vkr_percent = _get_vk_values(trafo_df, characteristic)
else:
vk_percent = get_trafo_values(trafo_df, "vk_percent")
vkr_percent = get_trafo_values(trafo_df, "vkr_percent")

elif sequence == 0:
vk_percent = get_trafo_values(trafo_df, "vk0_percent")
Expand All @@ -706,7 +714,6 @@ def _calc_r_x_from_dataframe(mode, trafo_df, vn_lv, vn_trafo_lv, sn_mva, sequenc
def _calc_nominal_ratio_from_dataframe(ppc, trafo_df, vn_hv_kv, vn_lv_kv, bus_lookup):
"""
Calculates (Vectorized) the off nominal tap ratio::
(vn_hv_kv / vn_lv_kv) / (ub1_in_kv / ub2_in_kv)
INPUT:
Expand Down Expand Up @@ -1156,7 +1163,7 @@ def get_is_lines(net):
_is_elements["line"] = net["line"][net["line"]["in_service"].values.astype(bool)]


def _trafo_df_from_trafo3w(net, sequence=1):
def _trafo_df_from_trafo3w(net, sequence=1, update_vk_values=True):
trafo2 = dict()
sides = ["hv", "mv", "lv"]
mode = net._options["mode"]
Expand All @@ -1169,7 +1176,7 @@ def _trafo_df_from_trafo3w(net, sequence=1):
if sequence==1:
mode_tmp = "type_c" if mode == "sc" and net._options.get("use_pre_fault_voltage", False) else mode
_calculate_sc_voltages_of_equivalent_transformers(t3, trafo2, mode_tmp, characteristic=net.get(
'characteristic'))
'characteristic'), update_vk_values=update_vk_values)
elif sequence==0:
if mode != "sc":
raise NotImplementedError(
Expand Down Expand Up @@ -1203,8 +1210,12 @@ def _trafo_df_from_trafo3w(net, sequence=1):
return {var: np.concatenate([trafo2[var][side] for side in sides]) for var in trafo2.keys()}


def _calculate_sc_voltages_of_equivalent_transformers(t3, t2, mode, characteristic):
vk_hv, vkr_hv, vk_mv, vkr_mv, vk_lv, vkr_lv = _get_vk_values(t3, characteristic, "3W")
def _calculate_sc_voltages_of_equivalent_transformers(t3, t2, mode, characteristic, update_vk_values=True):
if update_vk_values:
vk_hv, vkr_hv, vk_mv, vkr_mv, vk_lv, vkr_lv = _get_vk_values(t3, characteristic, "3W")
else:
vk_hv, vkr_hv, vk_mv, vkr_mv, vk_lv, vkr_lv = (t3['vk_hv_percent'], t3['vkr_hv_percent'], t3['vk_mv_percent'],
t3['vkr_mv_percent'], t3['vk_lv_percent'], t3['vkr_lv_percent'])

vk_3w = np.stack([vk_hv, vk_mv, vk_lv])
vkr_3w = np.stack([vkr_hv, vkr_mv, vkr_lv])
Expand Down
3 changes: 1 addition & 2 deletions pandapower/diagnostic.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import pandas as pd
import numpy as np
import pandapower as pp
from pandapower import replace_xward_by_ward

try:
import pandaplan.core.pplog as logging
Expand All @@ -21,7 +20,7 @@
from pandapower.auxiliary import (LoadflowNotConverged, OPFNotConverged, ControllerNotConverged,
NetCalculationNotConverged)
from pandapower.run import runpp
from pandapower.toolbox import get_connected_elements
from pandapower.toolbox import get_connected_elements, replace_xward_by_ward
from pandapower.diagnostic_reports import diagnostic_report

# separator between log messages
Expand Down
2 changes: 1 addition & 1 deletion pandapower/io_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import pandas.errors
from deepdiff.diff import DeepDiff
from packaging.version import Version
from pandapower import __version__
from pandapower._version import __version__
import networkx
import numpy
import geojson
Expand Down
2 changes: 1 addition & 1 deletion pandapower/networks/ieee_europen_lv_asymmetric.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import os
import pandapower as pp
from pandapower import pp_dir
from pandapower.__init__ import pp_dir


def ieee_european_lv_asymmetric(scenario="on_peak_566", **kwargs):
Expand Down
2 changes: 1 addition & 1 deletion pandapower/networks/lv_schutterwald.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import pandapower as pp
import pandapower.topology as top
import pandapower.plotting.geo as geo
from pandapower import pp_dir
from pandapower.__init__ import pp_dir


def lv_schutterwald(separation_by_sub=False, include_heat_pumps=False, **kwargs):
Expand Down
3 changes: 1 addition & 2 deletions pandapower/networks/mv_oberrhein.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@

import pandapower as pp
import pandapower.topology as top
import pandapower.plotting.geo as geo
from pandapower import pp_dir
from pandapower.__init__ import pp_dir


def mv_oberrhein(scenario="load", cosphi_load=0.98, cosphi_pv=1.0, include_substations=False,
Expand Down
5 changes: 3 additions & 2 deletions pandapower/networks/power_system_test_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

import pandapower as pp
import pandapower.toolbox
from pandapower import pp_dir
from pandapower.file_io import from_json
from pandapower.__init__ import pp_dir
import pandapower.plotting.geo as geo


Expand Down Expand Up @@ -61,7 +62,7 @@ def _change_ref_bus(net, ref_bus_idx, ext_grid_p=0):


def sorted_from_json(path, **kwargs):
net = pp.from_json(path, **kwargs)
net = from_json(path, **kwargs)
for elm in pandapower.toolbox.pp_elements():
net[elm].sort_index(inplace=True)
return net
Expand Down
6 changes: 4 additions & 2 deletions pandapower/pd2ppc.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ def _check_slack_at_vsc_bus(ppci):
"this configuration is not implemented.")


def _pd2ppc(net, sequence=None):
def _pd2ppc(net, sequence=None, **kwargs):
"""
Converter Flow:
1. Create an empty pypower datatructure
Expand Down Expand Up @@ -153,8 +153,10 @@ def _pd2ppc(net, sequence=None):
# Calculates ppc0 branch impedances from branch elements
_build_branch_ppc_zero(net, ppc)
else:
# get config if trafo3w vk and vkr values should be recalculated
update_vk_values = kwargs.get("update_vk_values", True)
# Calculates ppc1/ppc2 branch impedances from branch elements
_build_branch_ppc(net, ppc)
_build_branch_ppc(net, ppc, update_vk_values)
_build_branch_dc_ppc(net, ppc)

_build_tcsc_ppc(net, ppc, mode)
Expand Down
2 changes: 1 addition & 1 deletion pandapower/pd2ppc_zero.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from itertools import product

import pandapower.auxiliary as aux
from pandapower import DC_NONE, DC_BUS_TYPE
from pandapower.pypower.idx_bus_dc import DC_NONE, DC_BUS_TYPE
from pandapower.build_bus import _build_bus_ppc, _build_svc_ppc, _build_ssc_ppc, _build_vsc_ppc, _build_bus_dc_ppc
from pandapower.build_gen import _build_gen_ppc
# from pandapower.pd2ppc import _ppc2ppci, _init_ppc
Expand Down
3 changes: 1 addition & 2 deletions pandapower/plotting/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,7 @@
class TextPath: # so that the test does not fail
pass

from pandapower import pandapowerNet
from pandapower.auxiliary import soft_dependency_error
from pandapower.auxiliary import soft_dependency_error, pandapowerNet
from pandapower.plotting.patch_makers import load_patches, node_patches, gen_patches, \
sgen_patches, ext_grid_patches, trafo_patches, storage_patches, ward_patches, xward_patches, vsc_patches
from pandapower.plotting.plotting_toolbox import _rotate_dim2, coords_from_node_geodata, \
Expand Down
10 changes: 5 additions & 5 deletions pandapower/plotting/geo.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from numpy import array

import pandapower
from pandapower.auxiliary import soft_dependency_error
from pandapower.auxiliary import soft_dependency_error, pandapowerNet

# get logger (same as in simple_plot)
try:
Expand Down Expand Up @@ -231,7 +231,7 @@ def convert_epsg_bus_geodata(net, epsg_in=4326, epsg_out=31467):
return net


def convert_crs(net: pandapower.pandapowerNet or 'pandapipes.pandapipesNet', epsg_in=4326, epsg_out=31467):
def convert_crs(net: pandapowerNet or 'pandapipes.pandapipesNet', epsg_in=4326, epsg_out=31467):
"""
This function works for pandapowerNet and pandapipesNet. Documentation will refer to names from pandapower.
Converts bus and line geodata in net from epsg_in to epsg_out
Expand Down Expand Up @@ -285,7 +285,7 @@ def _geo_branch_transformer(r):


def dump_to_geojson(
net: pandapower.pandapowerNet or 'pandapipes.pandapipesNet',
net: pandapowerNet or 'pandapipes.pandapipesNet',
nodes: Union[bool, List[int]] = False,
branches: Union[bool, List[int]] = False,
switches: Union[bool, List[int]] = False,
Expand Down Expand Up @@ -501,7 +501,7 @@ def update_props(r: pd.Series) -> None:


def convert_geodata_to_geojson(
net: pandapower.pandapowerNet or 'pandapipes.pandapipesNet',
net: pandapowerNet or 'pandapipes.pandapipesNet',
delete: bool = True,
lonlat: bool = False) -> None:
"""
Expand Down Expand Up @@ -566,7 +566,7 @@ def convert_geodata_to_geojson(


def convert_gis_to_geojson(
net: pandapower.pandapowerNet or 'pandapipes.pandapipesNet',
net: pandapowerNet or 'pandapipes.pandapipesNet',
delete: bool = True) -> None:
"""
Transforms the bus and line geodataframes of a net into a geojson object.
Expand Down
4 changes: 2 additions & 2 deletions pandapower/plotting/plotly/mapbox_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,15 @@ def geo_data_to_latlong(net, projection):


def set_mapbox_token(token):
from pandapower import pp_dir
from pandapower.__init__ import pp_dir
path = os.path.join(pp_dir, "plotting", "plotly")
filename = os.path.join(path, 'mapbox_token.txt')
with open(filename, "w") as mapbox_file:
mapbox_file.write(token)


def _get_mapbox_token():
from pandapower import pp_dir
from pandapower.__init__ import pp_dir
path = os.path.join(pp_dir, "plotting", "plotly")
filename = os.path.join(path, 'mapbox_token.txt')
with open(filename, "r") as mapbox_file:
Expand Down
Loading

0 comments on commit 391a6e1

Please sign in to comment.