Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/e2nIEE/pandapower into d…
Browse files Browse the repository at this point in the history
…evelop

� Conflicts:
�	pandapower/create.py
  • Loading branch information
dlohmeier committed Nov 17, 2020
2 parents c309616 + 86003c2 commit 29ee007
Show file tree
Hide file tree
Showing 37 changed files with 1,978 additions and 800 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ matrix:
- python: 3.5
- python: 3.6
- python: 3.7
- python: 3.8
dist: xenial
sudo: true

Expand Down Expand Up @@ -57,6 +58,8 @@ script:
py.test --cov=pandapower --cov-config .coveragerc;
elif [[ "$TRAVIS_PYTHON_VERSION" == "3.7" ]]; then
py.test --cov=pandapower --cov-config .coveragerc;
elif [[ "$TRAVIS_PYTHON_VERSION" == "3.8" ]]; then
py.test --cov=pandapower --cov-config .coveragerc;
fi

after_success:
Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ Change Log
- [ADDED] documentation on how to install Gurobi as a PowerModels.jl solver
- [CHANGED] internal datastructure tutorial contains now an example of a spy plot to visiualize the admittance matrix Ybus
- [FIXED] json load for broken geom columns in bus_geodata
- [ADDED] The voltage setpoint of external grids can now be optimized by the OPF by setting net.ext_grid.controllable to True.
- [ADDED] The Powermodels AC OPF can now be used with line loading constraints formulated with respect to the maximum current net.line.max_i_ka by using pp.runpm_ac_opf(net, opf_flow_lim="I")
- [ADDED] For easier debugging of the Powermodels interface, you can now save your .json file and specify the file name by using pp.runpm(net, delete_buffer_file=False, pm_file_path="filename.json")

[2.4.0]- 2020-09-01
----------------------
Expand Down
2 changes: 1 addition & 1 deletion doc/elements/impedance_par.csv
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,4 @@ xft_pu*;float;:math:`>` 0;reactance of the impedance from 'from' to 'to' bus [p.
rtf_pu*;float;:math:`>` 0;resistance of the impedance from 'to' to 'from' bus [p.u]
xtf_pu*;float;:math:`>` 0;reactance of the impedance from 'to' to 'from' bus [p.u]
sn_mva*;float;:math:`>` 0;reference apparent power for the impedance per unit values [MVA]
in_service*;boolean;True / False;specifies if the imepdance is in service.
in_service*;boolean;True / False;specifies if the impedance is in service.
40 changes: 20 additions & 20 deletions doc/elements/line_res_3ph.csv
Original file line number Diff line number Diff line change
@@ -1,29 +1,29 @@
**Parameter**;**Datatype**;**Explanation**
"p_a_from_mw;float;""active power flow into the line at """"from"""" bus: Phase A [MW]"""
"q_a_from_mvar;float;""reactive power flow into the line at """"from"""" bus : Phase A[MVar]"""
"p_b_from_mw;float;""active power flow into the line at """"from"""" bus: Phase B [MW]"""
"q_b_from_mvar;float;""reactive power flow into the line at """"from"""" bus : Phase B[MVar]"""
"p_c_from_mw;float;""active power flow into the line at """"from"""" bus: Phase C [MW]"""
"q_c_from_mvar;float;""reactive power flow into the line at """"from"""" bus : Phase C[MVar]"""
"p_a_to_mw;float;""active power flow into the line at """"to"""" bus: Phase A [MW]"""
"q_a_to_mvar;float;""reactive power flow into the line at """"to"""" bus : Phase A[MVar]"""
"p_b_to_mw;float;""active power flow into the line at """"to"""" bus: Phase B [MW]"""
"q_b_to_mvar;float;""reactive power flow into the line at """"to"""" bus : Phase B[MVar]"""
"p_c_to_mw;float;""active power flow into the line at """"to"""" bus: Phase C [MW]"""
"q_c_to_mvar;float;""reactive power flow into the line at """"to"""" bus : Phase C[MVar]"""
p_a_from_mw;float;active power flow into the line at from bus: Phase A [MW]
q_a_from_mvar;float;reactive power flow into the line at from bus : Phase A[MVar]
p_b_from_mw;float;active power flow into the line at from bus: Phase B [MW]
q_b_from_mvar;float;reactive power flow into the line at from bus : Phase B[MVar]
p_c_from_mw;float;active power flow into the line at from bus: Phase C [MW]
q_c_from_mvar;float;reactive power flow into the line at from bus : Phase C[MVar]
p_a_to_mw;float;active power flow into the line at to bus: Phase A [MW]
q_a_to_mvar;float;reactive power flow into the line at to bus : Phase A[MVar]
p_b_to_mw;float;active power flow into the line at to bus: Phase B [MW]
q_b_to_mvar;float;reactive power flow into the line at to bus : Phase B[MVar]
p_c_to_mw;float;active power flow into the line at to bus: Phase C [MW]
q_c_to_mvar;float;reactive power flow into the line at to bus : Phase C[MVar]
pl_a_mw;float;active power losses of the line: Phase A [MW]
ql_a_mvar;float;reactive power consumption of the line: Phase A [MVar]
pl_b_mw;float;active power losses of the line: Phase B [MW]
ql_b_mvar;float;reactive power consumption of the line: Phase B [MVar]
pl_c_mw;float;active power losses of the line: Phase C [MW]
ql_c_mvar;float;reactive power consumption of the line: Phase C [MVar]
i_a_from_ka;float;Current at to bus: Phase A [kA]
i_b_from_ka;float;Current at to bus: Phase B [kA]
i_c_from_ka;float;Current at to bus: Phase C [kA]
i_n_from_ka;float;Current at to bus: Neutral [kA]
i_a_to_ka;float;Current at from bus: Phase A [kA]
i_b_to_ka;float;Current at from bus: Phase B [kA]
i_c_to_ka;float;Current at from bus: Phase C [kA]
i_n_to_ka;float;Current at from bus: Neutral [kA]
i_a_from_ka;float;Current at from bus: Phase A [kA]
i_b_from_ka;float;Current at from bus: Phase B [kA]
i_c_from_ka;float;Current at from bus: Phase C [kA]
i_n_from_ka;float;Current at from bus: Neutral [kA]
i_a_to_ka;float;Current at to bus: Phase A [kA]
i_b_to_ka;float;Current at to bus: Phase B [kA]
i_c_to_ka;float;Current at to bus: Phase C [kA]
i_n_to_ka;float;Current at to bus: Neutral [kA]
i_ka;float;Maximum of i_from_ka and i_to_ka [kA]
loading_percent;float;line loading [%]
1 change: 1 addition & 0 deletions pandapower/build_branch.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ def _calc_line_parameter(net, ppc, elm="line", ppc_elm="branch"):
vr = net.bus.loc[line["from_bus"].values, "vn_kv"].values * np.sqrt(3.)
max_i_ka = line.max_i_ka.values
df = line.df.values
# This calculates the maximum apparent power at 1.0 p.u.
branch[f:t, RATE_A] = max_load / 100. * max_i_ka * df * parallel * vr


Expand Down
29 changes: 24 additions & 5 deletions pandapower/build_gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,27 @@ def _build_pp_ext_grid(net, ppc, f, t):
if net._options["mode"] == "opf":
add_q_constraints(net, "ext_grid", eg_is, ppc, f, t, delta)
add_p_constraints(net, "ext_grid", eg_is, ppc, f, t, delta)
ppc["bus"][eg_buses, VMAX] = net["ext_grid"]["vm_pu"].values[eg_is] + delta
ppc["bus"][eg_buses, VMIN] = net["ext_grid"]["vm_pu"].values[eg_is] - delta


if "controllable" in net["ext_grid"]:
# if we do and one of them is false, do this only for the ones, where it is false
eg_constrained = net.ext_grid[eg_is][net.ext_grid.controllable==False]
if len(eg_constrained):
eg_constrained_bus = eg_constrained.bus
ppc["bus"][eg_constrained_bus, VMAX] = net["ext_grid"]["vm_pu"].values[eg_constrained.index] + delta
ppc["bus"][eg_constrained_bus, VMIN] = net["ext_grid"]["vm_pu"].values[eg_constrained.index] - delta
else:
# if we dont:
ppc["bus"][eg_buses, VMAX] = net["ext_grid"]["vm_pu"].values[eg_is] + delta
ppc["bus"][eg_buses, VMIN] = net["ext_grid"]["vm_pu"].values[eg_is] - delta








else:
ppc["gen"][f:t, QMIN] = 0
ppc["gen"][f:t, QMAX] = 0
Expand Down Expand Up @@ -213,8 +232,8 @@ 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, PMIN] = + delta
ppc["gen"][f:t, PMAX] = - delta
ppc["gen"][f:t, PMIN] = - delta
ppc["gen"][f:t, PMAX] = + delta
ppc["gen"][f:t, QMIN] = -q_lim_default
ppc["gen"][f:t, QMAX] = q_lim_default

Expand Down Expand Up @@ -313,4 +332,4 @@ def _different_values_at_one_bus(buses, values):
# have the voltage of the first generator at that bus
values_equal = first_values[buses]

return not np.allclose(values, values_equal)
return not np.allclose(values, values_equal)
4 changes: 2 additions & 2 deletions pandapower/control/run_control.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ def control_implementation(controller_order, net, run_funct, errors, max_iter, c
converged = False
# run_count is 0 before entering the loop. Is incremented in each controller loop
run_count = 0
while not converged and run_count <= max_iter and net["converged"]:
while not converged and run_count <= max_iter and (net["converged"] or net["OPF_converged"]):
converged = _control_step(net, run_count, levelorder)

# call to run function (usually runpp) after each controller was called
Expand All @@ -151,7 +151,7 @@ def control_implementation(controller_order, net, run_funct, errors, max_iter, c
run_count += 1
_control_repair(net, run_funct, continue_on_lf_divergence, levelorder, errors, **kwargs)
# raises controller not converged
check_final_convergence(run_count, max_iter, errors, net['converged'])
check_final_convergence(run_count, max_iter, errors, (net['converged'] or net["OPF_converged"]))


def _control_step(net, run_count, levelorder):
Expand Down
42 changes: 33 additions & 9 deletions pandapower/converter/powermodels/to_pm.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
def convert_pp_to_pm(net, pm_file_path=None, correct_pm_network_data=True, calculate_voltage_angles=True, ac=True,
trafo_model="t", delta=1e-8, trafo3w_losses="hv", check_connectivity=True,
pp_to_pm_callback=None, pm_model="ACPPowerModel", pm_solver="ipopt",
pm_mip_solver="cbc", pm_nl_solver="ipopt"):
pm_mip_solver="cbc", pm_nl_solver="ipopt", opf_flow_lim = "S"):
"""
Converts a pandapower net to a PowerModels.jl datastructure and saves it to a json file
Expand Down Expand Up @@ -71,7 +71,7 @@ def convert_pp_to_pm(net, pm_file_path=None, correct_pm_network_data=True, calcu
_add_opf_options(net, trafo_loading='power', ac=ac, init="flat", numba=True,
pp_to_pm_callback=pp_to_pm_callback, pm_solver=pm_solver, pm_model=pm_model,
correct_pm_network_data=correct_pm_network_data, pm_mip_solver=pm_mip_solver,
pm_nl_solver=pm_nl_solver)
pm_nl_solver=pm_nl_solver, opf_flow_lim=opf_flow_lim)

net, pm, ppc, ppci = convert_to_pm_structure(net)
buffer_file = dump_pm_json(pm, pm_file_path)
Expand All @@ -83,7 +83,7 @@ def convert_pp_to_pm(net, pm_file_path=None, correct_pm_network_data=True, calcu
logger = logging.getLogger(__name__)


def convert_to_pm_structure(net):
def convert_to_pm_structure(net, opf_flow_lim = "S"):
net["OPF_converged"] = False
net["converged"] = False
_add_auxiliary_elements(net)
Expand Down Expand Up @@ -254,9 +254,21 @@ def ppc_to_pm(net, ppci):
branch["g_to"] = - row[BR_B].imag / 2.0
branch["b_fr"] = row[BR_B].real / 2.0
branch["b_to"] = row[BR_B].real / 2.0
branch["rate_a"] = row[RATE_A].real if row[RATE_A] > 0 else row[RATE_B].real
branch["rate_b"] = row[RATE_B].real
branch["rate_c"] = row[RATE_C].real

if net._options["opf_flow_lim"] == "S": # or branch["transformer"]:
branch["rate_a"] = row[RATE_A].real if row[RATE_A] > 0 else row[RATE_B].real
branch["rate_b"] = row[RATE_B].real
branch["rate_c"] = row[RATE_C].real
elif net._options["opf_flow_lim"] == "I":
f = net._pd2ppc_lookups["branch"]["line"][0]
f = int(row[F_BUS].real) # from bus of this line
vr = ppci["bus"][f][BASE_KV]
branch["c_rating_a"] = row[RATE_A].real if row[RATE_A] > 0 else row[RATE_B].real
branch["c_rating_b"] = row[RATE_B].real
branch["c_rating_c"] = row[RATE_C].real
else:
logger.error("Branch flow limit %s not understood", net._options["opf_flow_lim"])

branch["f_bus"] = int(row[F_BUS].real) + 1
branch["t_bus"] = int(row[T_BUS].real) + 1
branch["br_status"] = int(row[BR_STATUS].real)
Expand Down Expand Up @@ -290,9 +302,21 @@ def ppc_to_pm(net, ppci):
branch["g_to"] = - row[BR_B].imag / 2.0
branch["b_fr"] = row[BR_B].real / 2.0
branch["b_to"] = row[BR_B].real / 2.0
branch["rate_a"] = row[RATE_A].real if row[RATE_A] > 0 else row[RATE_B].real
branch["rate_b"] = row[RATE_B].real
branch["rate_c"] = row[RATE_C].real

if net._options["opf_flow_lim"] == "S":
branch["rate_a"] = row[RATE_A].real if row[RATE_A] > 0 else row[RATE_B].real
branch["rate_b"] = row[RATE_B].real
branch["rate_c"] = row[RATE_C].real
elif net._options["opf_flow_lim"] == "I":
f, t = net._pd2ppc_lookups["branch"]["line"]
f = int(row[F_BUS].real) # from bus of this line
vr = ppci["bus"][f][BASE_KV]
row[RATE_A] = row[RATE_A] / (vr * np.sqrt(3))

branch["c_rating_a"] = row[RATE_A].real if row[RATE_A] > 0 else row[RATE_B].real
branch["c_rating_b"] = row[RATE_B].real
branch["c_rating_c"] = row[RATE_C].real

branch["f_bus"] = int(row[F_BUS].real) + 1
branch["t_bus"] = int(row[T_BUS].real) + 1
branch["br_status"] = int(row[BR_STATUS].real)
Expand Down
17 changes: 16 additions & 1 deletion pandapower/create.py
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,8 @@ def create_empty_network(name="", f_hz=50., sn_mva=1, add_stdtypes=True):
("i_b_lv_ka", "f8"),
("i_c_hv_ka", "f8"),
("i_c_lv_ka", "f8"),
# ("i_n_hv_ka", "f8"),
# ("i_n_lv_ka", "f8"),
("loading_a_percent", "f8"),
("loading_b_percent", "f8"),
("loading_c_percent", "f8"),
Expand Down Expand Up @@ -1654,7 +1656,7 @@ def create_motor(net, bus, pn_mech_mw, cos_phi, efficiency_percent=100., loading
def create_ext_grid(net, bus, vm_pu=1.0, va_degree=0., name=None, in_service=True,
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, **kwargs):
index=None, r0x0_max=nan, x0x_max=nan, controllable=nan, **kwargs):
"""
Creates an external grid connection.
Expand Down Expand Up @@ -1703,6 +1705,12 @@ def create_ext_grid(net, bus, vm_pu=1.0, va_degree=0., name=None, in_service=Tru
** only considered in loadflow if calculate_voltage_angles = True
**controllable** (bool, NaN) - True: p_mw, q_mvar and vm_pu limits are enforced for the ext_grid in OPF.
The voltage limits set in the ext_grid bus are enforced.
False: p_mw and vm_pu setpoints are enforced and *limits are ignored*.
The vm_pu setpoint is enforced and limits of the bus table are ignored.
defaults to False if "controllable" column exists in DataFrame
EXAMPLE:
create_ext_grid(net, 1, voltage = 1.03)
Expand All @@ -1719,6 +1727,7 @@ def create_ext_grid(net, bus, vm_pu=1.0, va_degree=0., name=None, in_service=Tru
[bus, name, vm_pu, va_degree, bool(in_service)]))
_set_entries(net, "ext_grid", index, **entries, **kwargs)

# OPF limits
_create_column_and_set_value(net, index, s_sc_max_mva, "s_sc_max_mva", "ext_grid")
_create_column_and_set_value(net, index, s_sc_min_mva, "s_sc_min_mva", "ext_grid")
_create_column_and_set_value(net, index, rx_min, "rx_min", "ext_grid")
Expand All @@ -1729,6 +1738,12 @@ def create_ext_grid(net, bus, vm_pu=1.0, va_degree=0., name=None, in_service=Tru
_create_column_and_set_value(net, index, max_q_mvar, "max_q_mvar", "ext_grid")
_create_column_and_set_value(net, index, x0x_max, "x0x_max", "ext_grid")
_create_column_and_set_value(net, index, r0x0_max, "r0x0_max", "ext_grid")
if not isnan(controllable):
if "controllable" not in net.ext_grid.columns:
net.ext_grid.loc[:, "controllable"] = False
net.ext_grid.at[index, "controllable"] = bool(controllable)
elif "controllable" in net.ext_grid.columns:
net.ext_grid.at[index, "controllable"] = False

return index

Expand Down
11 changes: 5 additions & 6 deletions pandapower/diagnostic.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ def check_greater_zero_less_equal_one(element, element_index, column):


def check_switch_type(element, element_index, column):
valid_values = ['b', 'l', 't']
valid_values = ['b', 'l', 't', 't3']
if element[column] not in valid_values:
return element_index

Expand Down Expand Up @@ -459,8 +459,7 @@ def missing_bus_indices(net):
for i, row in net[element].iterrows():
for bus_name in element_bus_names[element]:
if row[bus_name] not in bus_indices:
if not ((element == "switch") and (bus_name == "element") and (
row.et in ['l', 't'])):
if not ((element == "switch") and (bus_name == "element") and (row.et in ['l', 't', 't3'])):
element_check.append((i, bus_name, row[bus_name]))
if element_check:
check_results[element] = element_check
Expand Down Expand Up @@ -521,15 +520,15 @@ def impedance_values_close_to_zero(net, min_r_ohm, min_x_ohm, min_r_pu, min_x_pu
implausible_elements = {}

line = net.line[((net.line.r_ohm_per_km * net.line.length_km) <= min_r_ohm)
| ((net.line.x_ohm_per_km * net.line.length_km) <= min_x_ohm)].index
| ((net.line.x_ohm_per_km * net.line.length_km) <= min_x_ohm) & net.line.in_service].index

xward = net.xward[(net.xward.r_ohm <= min_r_ohm)
| (net.xward.x_ohm <= min_x_ohm)].index
| (net.xward.x_ohm <= min_x_ohm) & net.xward.in_service].index

impedance = net.impedance[(net.impedance.rft_pu <= min_r_pu)
| (net.impedance.xft_pu <= min_x_pu)
| (net.impedance.rtf_pu <= min_r_pu)
| (net.impedance.xtf_pu <= min_x_pu)].index
| (net.impedance.xtf_pu <= min_x_pu) & net.impedance.in_service].index
if len(line) > 0:
implausible_elements['line'] = list(line)
if len(xward) > 0:
Expand Down
2 changes: 1 addition & 1 deletion pandapower/io_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ def method(self):
# class_ = getattr(module, obj) # doesn't work
return self.obj

@from_serializable.register(class_name='function', module_name='pandapower.run')
@from_serializable.register(class_name='function')
def function(self):
module = importlib.import_module(self.module_name)
class_ = getattr(module, self.obj) # works
Expand Down
2 changes: 1 addition & 1 deletion pandapower/networks/power_system_test_cases.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def case5():
Studies" Its data origin is `MATPOWER <http://www.pserc.cornell.edu/matpower/>`_.
OUTPUT:
**net** - Returns the required ieee network case4gs
**net** - Returns the required ieee network case5
EXAMPLE:
import pandapower.networks as pn
Expand Down
5 changes: 3 additions & 2 deletions pandapower/opf/pp_2_pm.jl
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,15 @@ end

function get_solver(optimizer::String, nl::String="ipopt", mip::String="cbc",
log_level::Int=0, time_limit::Float64=Inf, nl_time_limit::Float64=Inf,
mip_time_limit::Float64=Inf)
mip_time_limit::Float64=Inf, ipopt_tol::Float64=1e-8)

if optimizer == "gurobi"
solver = JuMP.optimizer_with_attributes(Gurobi.Optimizer, "TimeLimit" => time_limit, "OutputFlag" => log_level)
end

if optimizer == "ipopt"
solver = JuMP.optimizer_with_attributes(Ipopt.Optimizer, "print_level" => log_level, "max_cpu_time" => time_limit)
solver = JuMP.optimizer_with_attributes(Ipopt.Optimizer, "print_level" => log_level, "max_cpu_time" => time_limit,
"tol" => ipopt_tol)
end

if optimizer == "juniper" && nl == "ipopt" && mip == "cbc"
Expand Down
Loading

0 comments on commit 29ee007

Please sign in to comment.