Skip to content

Commit

Permalink
Merge branch 'develop' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
SteffenMeinecke authored Nov 29, 2023
2 parents 4c4a381 + f3c8d3a commit bb2f611
Show file tree
Hide file tree
Showing 73 changed files with 19,917 additions and 2,400 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/github_test_action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
- name: Install Julia
if: ${{ matrix.python-version == '3.9' }}
run: |
./.install_julia.sh 1.8
./.install_julia.sh 1.9.3
pip install julia
python ./.install_pycall.py
- name: List of installed packages
Expand Down Expand Up @@ -181,7 +181,7 @@ jobs:
run: |
python -m pip install --upgrade pip
python -m pip install pytest nbmake pytest-xdist igraph numba seaborn
./.install_julia.sh 1.8
./.install_julia.sh 1.9.3
python -m pip install julia
python ./.install_pycall.py
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
Expand Down
8 changes: 8 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,18 @@ Change Log
- [FIXED] in converter from PowerFactory, collect all buses (even not relevant for the calculation) for connectivity issues
- [FIXED] bug in coords conversion in cim2pp, small fixes
- [CHANGED] cim2pp: added support for multi diagram usage for DL profiles
- [CHANGED] cim2pp: made build_pp_net modular by introducing classes
- [ADDED] cim2pp: added option to opt out of internal powerflow calculation
- [FIXED] error handling in :code:`plotly/mapbox_plot.py` not raising :code`ImportError` if :code:`geopy` or :code:`pyproj` are missing
- [FIXED] powerfactory2pandapower-converter error if a line has two identical coordinates
- [ADDED] logger messages about the probabilistic load flow calculation (simultaneities) in the powerfactory2pandapower-converter for low voltage loads
- [ADDED] matplotlib v3.8.0 support (fixed :code:`plotting_colormaps.ipynb`)
- [CHANGED] PowerFactory converter - name :code:`for_name` as :code:`equipment` for all elements; also add to line
- [ADDED] option to use a second tap changer for the trafo element
- [CHANGED] parameters of function merge_internal_net_and_equivalent_external_net()
- [FIXED] :code:`convert_format.py`: update the attributes of the characteristic objects to match the new characteristic
- [FIXED] additional arguments from mpc saved to net._options: create "_options" if it does not exist
- [CHANGED] cim2pp: extracted getting default classes, added generic setting datatypes from CGMES XMI schema


[2.13.1] - 2023-05-12
Expand Down
2 changes: 1 addition & 1 deletion doc/elements/trafo.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Input Parameters
:delim: ;
:widths: 15, 10, 25, 40

\*necessary for executing a balanced power flow calculation |br| \*\*optimal power flow parameter |br| \*\*\*necessary for executing a three phase power flow / single phase short circuit
\*necessary for executing a balanced power flow calculation |br| \*\*optimal power flow parameter |br| \*\*\*necessary for executing a three phase power flow / single phase short circuit |br| \*\*\*\*optional, for modeling a second tap changer

.. note:: The transformer loading constraint for the optimal power flow corresponds to the option trafo_loading="current":

Expand Down
8 changes: 8 additions & 0 deletions doc/elements/trafo_par.csv
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,11 @@ df;float;1 :math:`\geq` df :math:`>` 0;derating factor: maximal current of trans
in_service*;boolean;True / False;specifies if the transformer is in service
oltc*;boolean;True / False; specifies if the transformer has an OLTC (short-circuit relevant)
power_station_unit*;boolean;True / False; specifies if the transformer is part of a power_station_unit (short-circuit relevant).
tap2_side****;string;"""hv"", ""lv""";defines if tap changer is at the high- or low voltage side
tap2_neutral****;integer;;rated tap position
tap2_min****;integer;;minimum tap position
tap2_max****;integer;;maximum tap position
tap2_step_percent****;float;:math:`>` 0;tap step size for voltage magnitude [%]
tap2_step_degree****;float;:math:`\geq` 0;tap step size for voltage angle
tap2_pos****;integer;;current position of tap changer
tap2_phase_shifter****;bool;;defines whether the transformer is an ideal phase shifter
2 changes: 1 addition & 1 deletion pandapower/_version.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
__version__ = "2.13.1"
__format_version__ = "2.12.0"
__format_version__ = "2.13.1"
4 changes: 2 additions & 2 deletions pandapower/auxiliary.py
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,9 @@ def __repr__(self): # pragma: no cover

def plural_s(number):
if number > 1:
return ""
else:
return "s"
else:
return ""

def _preserve_dtypes(df, dtypes):
for item, dtype in list(dtypes.items()):
Expand Down
75 changes: 39 additions & 36 deletions pandapower/build_branch.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,42 +412,45 @@ def _calc_tap_from_dataframe(net, trafo_df):
if mode == "sc" and not net._options.get("use_pre_fault_voltage", False): # todo type c?
return vnh, vnl, trafo_shift

tap_pos = get_trafo_values(trafo_df, "tap_pos")
tap_neutral = get_trafo_values(trafo_df, "tap_neutral")
tap_diff = tap_pos - tap_neutral
tap_phase_shifter = get_trafo_values(trafo_df, "tap_phase_shifter")
tap_side = get_trafo_values(trafo_df, "tap_side")
tap_step_percent = get_trafo_values(trafo_df, "tap_step_percent")
tap_step_degree = get_trafo_values(trafo_df, "tap_step_degree")

cos = lambda x: np.cos(np.deg2rad(x))
sin = lambda x: np.sin(np.deg2rad(x))
arctan = lambda x: np.rad2deg(np.arctan(x))

for side, vn, direction in [("hv", vnh, 1), ("lv", vnl, -1)]:
phase_shifters = tap_phase_shifter & (tap_side == side)
tap_complex = np.isfinite(tap_step_percent) & np.isfinite(tap_pos) & (tap_side == side) & \
~phase_shifters
if tap_complex.any():
tap_steps = tap_step_percent[tap_complex] * tap_diff[tap_complex] / 100
tap_angles = _replace_nan(tap_step_degree[tap_complex])
u1 = vn[tap_complex]
du = u1 * _replace_nan(tap_steps)
vn[tap_complex] = np.sqrt((u1 + du * cos(tap_angles)) ** 2 + (du * sin(tap_angles)) ** 2)
trafo_shift[tap_complex] += (arctan(direction * du * sin(tap_angles) /
(u1 + du * cos(tap_angles))))
if phase_shifters.any():
degree_is_set = _replace_nan(tap_step_degree[phase_shifters]) != 0
percent_is_set = _replace_nan(tap_step_percent[phase_shifters]) != 0
if (degree_is_set & percent_is_set).any():
raise UserWarning(
"Both tap_step_degree and tap_step_percent set for ideal phase shifter")
trafo_shift[phase_shifters] += np.where(
(degree_is_set),
(direction * tap_diff[phase_shifters] * tap_step_degree[phase_shifters]),
(direction * 2 * np.rad2deg(np.arcsin(tap_diff[phase_shifters] * \
tap_step_percent[phase_shifters] / 100 / 2)))
)
for t in ("", "2"):
if f"tap{t}_pos" not in trafo_df:
continue
tap_pos = get_trafo_values(trafo_df, f"tap{t}_pos")
tap_neutral = get_trafo_values(trafo_df, f"tap{t}_neutral")
tap_diff = tap_pos - tap_neutral
tap_phase_shifter = get_trafo_values(trafo_df, f"tap{t}_phase_shifter")
tap_side = get_trafo_values(trafo_df, f"tap{t}_side")
tap_step_percent = get_trafo_values(trafo_df, f"tap{t}_step_percent")
tap_step_degree = get_trafo_values(trafo_df, f"tap{t}_step_degree")

cos = lambda x: np.cos(np.deg2rad(x))
sin = lambda x: np.sin(np.deg2rad(x))
arctan = lambda x: np.rad2deg(np.arctan(x))

for side, vn, direction in [("hv", vnh, 1), ("lv", vnl, -1)]:
phase_shifters = tap_phase_shifter & (tap_side == side)
tap_complex = np.isfinite(tap_step_percent) & np.isfinite(tap_pos) & (tap_side == side) & \
~phase_shifters
if tap_complex.any():
tap_steps = tap_step_percent[tap_complex] * tap_diff[tap_complex] / 100
tap_angles = _replace_nan(tap_step_degree[tap_complex])
u1 = vn[tap_complex]
du = u1 * _replace_nan(tap_steps)
vn[tap_complex] = np.sqrt((u1 + du * cos(tap_angles)) ** 2 + (du * sin(tap_angles)) ** 2)
trafo_shift[tap_complex] += (arctan(direction * du * sin(tap_angles) /
(u1 + du * cos(tap_angles))))
if phase_shifters.any():
degree_is_set = _replace_nan(tap_step_degree[phase_shifters]) != 0
percent_is_set = _replace_nan(tap_step_percent[phase_shifters]) != 0
if (degree_is_set & percent_is_set).any():
raise UserWarning(
"Both tap_step_degree and tap_step_percent set for ideal phase shifter")
trafo_shift[phase_shifters] += np.where(
(degree_is_set),
(direction * tap_diff[phase_shifters] * tap_step_degree[phase_shifters]),
(direction * 2 * np.rad2deg(np.arcsin(tap_diff[phase_shifters] * \
tap_step_percent[phase_shifters] / 100 / 2)))
)
return vnh, vnl, trafo_shift


Expand Down
14 changes: 14 additions & 0 deletions pandapower/convert_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ def convert_format(net, elements_to_deserialize=None):
if isinstance(net.format_version, float) and net.format_version < 1.6:
set_data_type_of_columns_to_default(net)
_convert_objects(net, elements_to_deserialize)
_update_characteristics(net, elements_to_deserialize)
correct_dtypes(net, error=False)
_add_missing_std_type_tables(net)
net.format_version = __format_version__
Expand Down Expand Up @@ -453,3 +454,16 @@ def _check_elements_to_deserialize(element, elements_to_deserialize):
def _add_missing_std_type_tables(net):
if "fuse" not in net.std_types:
net.std_types["fuse"] = {}


def _update_characteristics(net, elements_to_deserialize):
# new interpolator type has been added to SplineCharacteristic - "pchip", and the attributes have been refactored
if not _check_elements_to_deserialize("characteristic", elements_to_deserialize) or \
"characteristic" not in net or net.characteristic.empty:
return
for c in net.characteristic.object.values:
# meta check for old SplineCharacteristic (cannot import it here to use isinstance):
if not (hasattr(c, "kind") and hasattr(c, "fill_value")):
continue
c.interpolator_kind = "interp1d"
c.kwargs = {"kind": c.__dict__.pop("kind"), "bounds_error": False, "fill_value": c.__dict__.pop("fill_value")}
1 change: 1 addition & 0 deletions pandapower/converter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@
from pandapower.converter.pypower import *
from pandapower.converter.pandamodels import *
from pandapower.converter.cim import *
from pandapower.converter.powerfactory import *
1 change: 1 addition & 0 deletions pandapower/converter/cim/cim2pp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@

# Copyright (c) 2016-2023 by University of Kassel and Fraunhofer Institute for Energy Economics
# and Energy System Technology (IEE), Kassel. All rights reserved.
from . import converter_classes
Loading

0 comments on commit bb2f611

Please sign in to comment.