Skip to content

Commit

Permalink
renamed contribution_factor to slack_weight; renamed CON_FAC to SL_FA…
Browse files Browse the repository at this point in the history
…C; start working on J with numba
  • Loading branch information
rbolgaryn committed Jul 14, 2021
1 parent 35b446c commit c1c412c
Show file tree
Hide file tree
Showing 14 changed files with 178 additions and 86 deletions.
2 changes: 1 addition & 1 deletion CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Change Log
- [ADDED] CharacteristicControl that implements adjusting values in net based on some other input values in the grid
- [ADDED] USetTapControl that adjusts the setpoint for a transformer tap changer, based on a specified result variable (e.g. i_lv_ka)
- [CHANGED] replaced naming for "inductive" or "ind" by "underexcited" and "capacitive" or "cap" for "overexcited"
- [ADDED] Added distributed slack calculation to newton-raphson load flow; new column "contribution_factors" for ext_grid, gen and xward (xward not implemented yet); gen with contribution_factor>0 must have slack=True
- [ADDED] Added distributed slack calculation to newton-raphson load flow; new column "slack_weights" for ext_grid, gen and xward (xward not implemented yet); gen with slack_weight>0 must have slack=True

[2.6.0]- 2021-03-09
----------------------
Expand Down
2 changes: 1 addition & 1 deletion pandapower/build_bus.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

from pandapower.auxiliary import _sum_by_group, phase_to_sequence
from pandapower.pypower.idx_bus import BUS_I, BASE_KV, PD, QD, GS, BS, VMAX, VMIN, BUS_TYPE, NONE, VM, VA, \
CID, CZD, bus_cols, REF, CON_FAC
CID, CZD, bus_cols, REF, SL_FAC

try:
from numba import jit
Expand Down
23 changes: 11 additions & 12 deletions pandapower/build_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
import numpy as np

from pandapower.pf.ppci_variables import bustypes
from pandapower.pypower.idx_bus import PV, REF, VA, VM, BUS_TYPE, NONE, VMAX, VMIN, CON_FAC as CON_FAC_BUS
from pandapower.pypower.idx_gen import QMIN, QMAX, PMIN, PMAX, GEN_BUS, PG, VG, QG, MBASE, CON_FAC
from pandapower.pypower.idx_bus import PV, REF, VA, VM, BUS_TYPE, NONE, VMAX, VMIN, SL_FAC as SL_FAC_BUS
from pandapower.pypower.idx_gen import QMIN, QMAX, PMIN, PMAX, GEN_BUS, PG, VG, QG, MBASE, SL_FAC
from pandapower.auxiliary import _subnetworks, _sum_by_group

try:
Expand Down Expand Up @@ -107,7 +107,7 @@ def _build_pp_ext_grid(net, ppc, f, t):
eg_buses = bus_lookup[net["ext_grid"]["bus"].values[eg_is]]
ppc["gen"][f:t, GEN_BUS] = eg_buses
ppc["gen"][f:t, VG] = net["ext_grid"]["vm_pu"].values[eg_is]
ppc["gen"][f:t, CON_FAC] = net["ext_grid"]["contribution_factor"].values[eg_is]
ppc["gen"][f:t, SL_FAC] = net["ext_grid"]["slack_weight"].values[eg_is]

# set bus values for external grid buses
if ppc.get("sequence", 1) == 1:
Expand Down Expand Up @@ -207,7 +207,7 @@ def _build_pp_gen(net, ppc, f, t):
ppc["gen"][f:t, GEN_BUS] = gen_buses
ppc["gen"][f:t, PG] = (net["gen"]["p_mw"].values[gen_is] * net["gen"]["scaling"].values[gen_is])
ppc["gen"][f:t, MBASE] = net["gen"]["sn_mva"].values[gen_is]
ppc["gen"][f:t, CON_FAC] = net["gen"]["contribution_factor"].values[gen_is]
ppc["gen"][f:t, SL_FAC] = net["gen"]["slack_weight"].values[gen_is]
ppc["gen"][f:t, VG] = gen_is_vm

# set bus values for generator buses
Expand All @@ -232,7 +232,7 @@ def _build_pp_xward(net, ppc, f, t, update_lookup=True):
xw_is = net["_is_elements"]['xward']
ppc["gen"][f:t, GEN_BUS] = bus_lookup[aux_buses[xw_is]]
ppc["gen"][f:t, VG] = xw["vm_pu"][xw_is].values
ppc["gen"][f:t, CON_FAC] = net["xward"]["contribution_factor"].values[xw_is]
ppc["gen"][f:t, SL_FAC] = net["xward"]["slack_weight"].values[xw_is]
ppc["gen"][f:t, PMIN] = - delta
ppc["gen"][f:t, PMAX] = + delta
ppc["gen"][f:t, QMIN] = -q_lim_default
Expand Down Expand Up @@ -340,13 +340,12 @@ def _normalise_slack_weights(ppc):
""" Unitise the slack contribution factors in each island to sum to 1. """
subnets = _subnetworks(ppc)
gen_buses = ppc['gen'][:, GEN_BUS].astype(np.int32)
con_fac_gen = ppc['gen'][:, CON_FAC].astype(np.float64)
con_fac_gen = ppc['gen'][:, SL_FAC].astype(np.float64)

# todo: flip the logic, only 1 ext_grid and all others PV, show logger warning that 1 ext_grid is used
# as slack and others are converted to PV nodes internally;
# todo: calculate dist_slack for all SL and PV nodes that have non-zero slack weight
# todo: rename contribution_factor to slack_weight
buses_with_con_fac = ppc['gen'][ppc['gen'][:, CON_FAC] != 0, GEN_BUS].astype(np.int32)
buses_with_con_fac = ppc['gen'][ppc['gen'][:, SL_FAC] != 0, GEN_BUS].astype(np.int32)
if not np.all(ppc['bus'][buses_with_con_fac, BUS_TYPE] == REF):
raise UserWarning("Distributed slack calculation is implemented only for reference type buses. "
"Specify net.gen.slack=True for generators that have a non-zero contribution factor. "
Expand All @@ -356,16 +355,16 @@ def _normalise_slack_weights(ppc):
subnet_gen_mask = np.isin(gen_buses, subnet)
sum_dist_weights = np.sum(con_fac_gen[subnet_gen_mask])
if np.isclose(sum_dist_weights, 0):
# ppc['gen'][subnet_gen_mask, CON_FAC] = 0
# ppc['gen'][subnet_gen_mask, SL_FAC] = 0
raise ValueError('Distributed slack contribution factors in an '
'island sum to zero.')
else:
# ppc['gen'][subnet_gen_mask, CON_FAC] /= sum_dist_weights
# ppc['gen'][subnet_gen_mask, SL_FAC] /= sum_dist_weights
con_fac_gen /= sum_dist_weights
buses, con_fac_bus, _ = _sum_by_group(gen_buses[subnet_gen_mask], con_fac_gen[subnet_gen_mask], con_fac_gen[subnet_gen_mask])
ppc['bus'][buses, CON_FAC_BUS] = con_fac_bus
ppc['bus'][buses, SL_FAC_BUS] = con_fac_bus

# raise NotImplementedError if there are several separate zones for distributed slack:
if not np.isclose(sum(ppc['bus'][:, CON_FAC_BUS]), 1):
if not np.isclose(sum(ppc['bus'][:, SL_FAC_BUS]), 1):
raise NotImplementedError("Distributed slack calculation is not implemented for several separate zones at once, "
"please calculate the zones separately.")
12 changes: 6 additions & 6 deletions pandapower/convert_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,14 +232,14 @@ def _add_missing_columns(net):
net.controller.at[ctrl.name, 'initial_run'] = ctrl['object'].initial_powerflow

# distributed slack
if "contribution_factor" not in net.ext_grid:
net.ext_grid['contribution_factor'] = 1.0
if "slack_weight" not in net.ext_grid:
net.ext_grid['slack_weight'] = 1.0

if "contribution_factor" not in net.gen:
net.gen['contribution_factor'] = 0.0
if "slack_weight" not in net.gen:
net.gen['slack_weight'] = 0.0

if "contribution_factor" not in net.xward:
net.xward['contribution_factor'] = 0.0
if "slack_weight" not in net.xward:
net.xward['slack_weight'] = 0.0


def _update_trafo_type_parameter_names(net):
Expand Down
36 changes: 18 additions & 18 deletions pandapower/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def create_empty_network(name="", f_hz=50., sn_mva=1, add_stdtypes=True):
("scaling", "f8"),
("slack", "bool"),
("in_service", 'bool'),
("contribution_factor", 'f8'),
("slack_weight", 'f8'),
("type", dtype(object))],
"switch": [("bus", "i8"),
("element", "i8"),
Expand All @@ -150,7 +150,7 @@ def create_empty_network(name="", f_hz=50., sn_mva=1, add_stdtypes=True):
("bus", "u4"),
("vm_pu", "f8"),
("va_degree", "f8"),
("contribution_factor", 'f8'),
("slack_weight", 'f8'),
("in_service", 'bool')],
"line": [("name", dtype(object)),
("std_type", dtype(object)),
Expand Down Expand Up @@ -258,7 +258,7 @@ def create_empty_network(name="", f_hz=50., sn_mva=1, add_stdtypes=True):
("r_ohm", "f8"),
("x_ohm", "f8"),
("vm_pu", "f8"),
("contribution_factor", 'f8'),
("slack_weight", 'f8'),
("in_service", "bool")],
"measurement": [("name", dtype(object)),
("measurement_type", dtype(object)),
Expand Down Expand Up @@ -1343,7 +1343,7 @@ def create_gen(net, bus, p_mw, vm_pu=1., sn_mva=nan, name=None, index=None, max_
min_q_mvar=nan, min_p_mw=nan, max_p_mw=nan, min_vm_pu=nan, max_vm_pu=nan,
scaling=1., type=None, slack=False, controllable=nan, vn_kv=nan,
xdss_pu=nan, rdss_ohm=nan, cos_phi=nan, pg_percent=nan, power_station_trafo=None,
in_service=True, contribution_factor=0.0):
in_service=True, slack_weight=0.0):
"""
Adds a generator to the network.
Expand Down Expand Up @@ -1377,7 +1377,7 @@ def create_gen(net, bus, p_mw, vm_pu=1., sn_mva=nan, name=None, index=None, max_
False: p_mw and vm_pu setpoints are enforced and *limits are ignored*.
defaults to True if "controllable" column exists in DataFrame
**contribution_factor** (float, default 0.0) - Slack power contribution factor
**slack_weight** (float, default 0.0) - Slack power contribution factor
powerflow
Expand Down Expand Up @@ -1423,8 +1423,8 @@ def create_gen(net, bus, p_mw, vm_pu=1., sn_mva=nan, name=None, index=None, max_
index = _get_index_with_check(net, "gen", index, name="generator")

columns = ["name", "bus", "p_mw", "vm_pu", "sn_mva", "type", "slack", "in_service",
"scaling", "contribution_factor"]
variables = [name, bus, p_mw, vm_pu, sn_mva, type, slack, bool(in_service), scaling, contribution_factor]
"scaling", "slack_weight"]
variables = [name, bus, p_mw, vm_pu, sn_mva, type, slack, bool(in_service), scaling, slack_weight]

_set_entries(net, "gen", index, True, **dict(zip(columns, variables)))

Expand Down Expand Up @@ -1461,7 +1461,7 @@ def create_gens(net, buses, p_mw, vm_pu=1., sn_mva=nan, name=None, index=None, m
min_q_mvar=None, min_p_mw=None, max_p_mw=None, min_vm_pu=None, max_vm_pu=None,
scaling=1., type=None, slack=False, controllable=None, vn_kv=None,
xdss_pu=None, rdss_ohm=None, cos_phi=None, pg_percent=None, power_station_trafo=None,
in_service=True, contribution_factor=0.0, **kwargs):
in_service=True, slack_weight=0.0, **kwargs):
"""
Adds generators to the specified buses network.
Expand Down Expand Up @@ -1518,7 +1518,7 @@ def create_gens(net, buses, p_mw, vm_pu=1., sn_mva=nan, name=None, index=None, m
**in_service** (bool, True) - True for in_service or False for out of service
**contribution_factor** (float, default 0.0) - Slack power contribution factor
**slack_weight** (float, default 0.0) - Slack power contribution factor
**max_p_mw** (list of float, default NaN) - Maximum active power injection - necessary for\
OPF
Expand Down Expand Up @@ -1552,7 +1552,7 @@ def create_gens(net, buses, p_mw, vm_pu=1., sn_mva=nan, name=None, index=None, m
index = _get_multiple_index_with_check(net, "gen", index, len(buses))

entries = {"bus": buses, "p_mw": p_mw, "vm_pu": vm_pu, "sn_mva": sn_mva, "scaling": scaling,
"in_service": in_service, "contribution_factor": contribution_factor, "name": name, "type": type, "slack": slack}
"in_service": in_service, "slack_weight": slack_weight, "name": name, "type": type, "slack": slack}

_add_series_to_entries(entries, index, "min_p_mw", min_p_mw)
_add_series_to_entries(entries, index, "max_p_mw", max_p_mw)
Expand Down Expand Up @@ -1644,7 +1644,7 @@ def create_ext_grid(net, bus, vm_pu=1.0, va_degree=0., name=None, in_service=Tru
s_sc_max_mva=nan, s_sc_min_mva=nan, rx_max=nan, rx_min=nan,
max_p_mw=nan, min_p_mw=nan, max_q_mvar=nan, min_q_mvar=nan,
index=None, r0x0_max=nan, x0x_max=nan, controllable=nan,
contribution_factor=1.0, **kwargs):
slack_weight=1.0, **kwargs):
"""
Creates an external grid connection.
Expand Down Expand Up @@ -1691,7 +1691,7 @@ def create_ext_grid(net, bus, vm_pu=1.0, va_degree=0., name=None, in_service=Tru
**x0x_max** (float, NaN) - maximal X0/X-ratio to calculate Zero sequence
internal impedance of ext_grid
**contribution_factor** (float, default 1.0) - Slack power contribution factor
**slack_weight** (float, default 1.0) - Slack power contribution factor
** only considered in loadflow if calculate_voltage_angles = True
Expand All @@ -1716,8 +1716,8 @@ def create_ext_grid(net, bus, vm_pu=1.0, va_degree=0., name=None, in_service=Tru

index = _get_index_with_check(net, "ext_grid", index, name="external grid")

entries = dict(zip(["bus", "name", "vm_pu", "va_degree", "in_service", "contribution_factor"],
[bus, name, vm_pu, va_degree, bool(in_service), contribution_factor]))
entries = dict(zip(["bus", "name", "vm_pu", "va_degree", "in_service", "slack_weight"],
[bus, name, vm_pu, va_degree, bool(in_service), slack_weight]))
_set_entries(net, "ext_grid", index, **entries, **kwargs)

# OPF limits
Expand Down Expand Up @@ -3262,7 +3262,7 @@ def create_ward(net, bus, ps_mw, qs_mvar, pz_mw, qz_mvar, name=None, in_service=


def create_xward(net, bus, ps_mw, qs_mvar, pz_mw, qz_mvar, r_ohm, x_ohm, vm_pu, in_service=True,
name=None, index=None, contribution_factor=0.0):
name=None, index=None, slack_weight=0.0):
"""
Creates an extended ward equivalent.
Expand All @@ -3288,7 +3288,7 @@ def create_xward(net, bus, ps_mw, qs_mvar, pz_mw, qz_mvar, r_ohm, x_ohm, vm_pu,
**vm_pu** (float) - voltage magnitude at the additional PV-node
**contribution_factor** (float, default 1.0) - Slack power contribution factor
**slack_weight** (float, default 1.0) - Slack power contribution factor
OUTPUT:
xward id
Expand All @@ -3298,8 +3298,8 @@ def create_xward(net, bus, ps_mw, qs_mvar, pz_mw, qz_mvar, r_ohm, x_ohm, vm_pu,
index = _get_index_with_check(net, "xward", index, "extended ward equivalent")

columns = ["bus", "ps_mw", "qs_mvar", "pz_mw", "qz_mvar", "r_ohm", "x_ohm", "vm_pu", "name",
"contribution_factor", "in_service"]
values = [bus, ps_mw, qs_mvar, pz_mw, qz_mvar, r_ohm, x_ohm, vm_pu, name, contribution_factor, in_service]
"slack_weight", "in_service"]
values = [bus, ps_mw, qs_mvar, pz_mw, qz_mvar, r_ohm, x_ohm, vm_pu, name, slack_weight, in_service]
_set_entries(net, "xward", index, **dict(zip(columns, values)))

return index
Expand Down
13 changes: 7 additions & 6 deletions pandapower/pf/create_jacobian.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def _create_J_with_numba(Ybus, V, pvpq, pq, createJ, pvpq_lookup, npv, npq):
Ibus = zeros(len(V), dtype=complex128)
# create Jacobian from fast calc of dS_dV
dVm_x, dVa_x = dSbus_dV_numba_sparse(Ybus.data, Ybus.indptr, Ybus.indices, V, V / abs(V), Ibus)

# todo: initialize J also for extra column and extra row, for the rows where slack_weight != 0
# data in J, space preallocated is bigger than acutal Jx -> will be reduced later on
Jx = empty(len(dVm_x) * 4, dtype=float64)
# row pointer, dimension = pvpq.shape[0] + pq.shape[0] + 1
Expand All @@ -38,11 +38,12 @@ def _create_J_with_numba(Ybus, V, pvpq, pq, createJ, pvpq_lookup, npv, npq):
return J


def _create_J_without_numba(Ybus, V, ref, pvpq, pq, contribution_factors, dist_slack):
def _create_J_without_numba(Ybus, V, ref, pvpq, pq, slack_weights, dist_slack):
# create Jacobian with standard pypower implementation.
dS_dVm, dS_dVa = dSbus_dV(Ybus, V)

## evaluate Jacobian

if dist_slack:
rows_pvpq = array(r_[ref, pvpq]).T
cols_pvpq = r_[ref[1:], pvpq]
Expand All @@ -57,7 +58,7 @@ def _create_J_without_numba(Ybus, V, ref, pvpq, pq, contribution_factors, dist_s
J21 = dS_dVa[array([pq]).T, cols_pvpq].imag
J22 = dS_dVm[array([pq]).T, pq].imag
if dist_slack:
J13 = sparse(contribution_factors.reshape(-1,1))
J13 = sparse(slack_weights.reshape(-1,1))
J23 = sparse(zeros(shape=(len(pq), 1)))
J = vstack([
hstack([J11, J12, J13]),
Expand All @@ -75,16 +76,16 @@ def _create_J_without_numba(Ybus, V, ref, pvpq, pq, contribution_factors, dist_s
return J


def create_jacobian_matrix(Ybus, V, ref, pvpq, pq, createJ, pvpq_lookup, npv, npq, numba, contribution_factors, dist_slack):
def create_jacobian_matrix(Ybus, V, ref, pvpq, pq, createJ, pvpq_lookup, npv, npq, numba, slack_weights, dist_slack):
if numba:
J = _create_J_with_numba(Ybus, V, pvpq, pq, createJ, pvpq_lookup, npv, npq)
else:
J = _create_J_without_numba(Ybus, V, ref, pvpq, pq, contribution_factors, dist_slack)
J = _create_J_without_numba(Ybus, V, ref, pvpq, pq, slack_weights, dist_slack)
return J


def get_fastest_jacobian_function(pvpq, pq, numba, dist_slack):
if numba and not dist_slack:
if numba:
if len(pvpq) == len(pq):
create_jacobian = create_J2
else:
Expand Down
Loading

0 comments on commit c1c412c

Please sign in to comment.