This site is version 0.0.1. Most of the code on this site is drafted by an agent and needs review. I apologize for the AI-speak, we are working on rewriting it!
viv-lang.org

vp.power.runpf

Solve the AC or DC power flow of a MATPOWER case: bus voltages, generator outputs and branch flows.

Part of the distribution vipyr; it runs from a checkout of the repository. Planned on PyPI as pip install vipyr.

vp.power.runpf is MATPOWER's runpf: give it a case and it returns the steady state of the network, every bus voltage (magnitude and angle), every generator's real and reactive output and the power entering each end of every branch, in MATPOWER's units and column order.

The case is a MATPOWER case file, by name for the ones shipped with vipyr ("case9", "case14", "case30", "case118", "case300", "case2383wp", from the MATPOWER repository), by path for any other .m file in MATPOWER's case format, or as a dict of MATPOWER's arrays (baseMVA, bus, gen, branch), the form PYPOWER and pandapower call ppc.

Three methods, as in MATPOWER:

  • "nr": Newton-Raphson in polar coordinates, the default. Converges in 2 to 6 iterations on the shipped cases.
  • "fdxb": the fast-decoupled method, XB version. Two constant matrices, factored once; more iterations, each much cheaper.
  • "dc": the linear DC model (flat voltage magnitudes, lossless branches), one sparse solve.

enforce_q_lims=True holds every generator that would exceed its reactive limits at the limit and solves again, as MATPOWER's ENFORCE_Q_LIMS option does; a slack generator held at a limit hands the reference role to the first remaining PV bus, and the angles are shifted back afterwards.

The whole computation runs in compiled Viv: the case's admittance matrix and Jacobian are assembled sparse, and each Newton step is solved by the sparse LU of lib/power/splu.viv (left-looking, threshold partial pivoting, a minimum-degree column order). The first call compiles the solver once (a few seconds); later calls load it from vipyr's cache.

Signature

vp.power.runpf(case, *, method='nr', enforce_q_lims=False, tol=1e-08, max_it=None)

Parameters

case : str | dict, required
A shipped MATPOWER case by name ('case9', 'case14', 'case30', 'case118', 'case300', 'case2383wp'), a path to a MATPOWER .m file, or a dict with baseMVA, bus, gen and branch (MATPOWER's columns, as in PYPOWER's ppc).
method : str, default 'nr'
'nr' (Newton-Raphson, polar), 'fdxb' (fast-decoupled, XB) or 'dc'.
enforce_q_lims : bool, default False
Hold generators at their reactive limits, turning their buses into PQ buses, and solve again until no limit is violated (AC methods only).
tol : float, default 1e-08
The largest power mismatch allowed, per unit (MATPOWER's pf.tol).
max_it : int, default None
The most iterations: None for MATPOWER's defaults, 10 for 'nr' and 30 for 'fdxb'.

Returns

A frozen PowerFlowResult. Iterating it gives the fields below in order; it also has params, tests, log and check().

success : bool
Whether the flow converged.
iterations : int
Newton or fast-decoupled iterations (summed over the Q-limit passes).
method : str
The method used.
mismatch : float
The largest power mismatch left, per unit (0 for 'dc').
vm : ndarray[float64]
Bus voltage magnitudes, per unit, in the case's bus order.
va : ndarray[float64]
Bus voltage angles, degrees.
pg : ndarray[float64]
Generator real outputs, MW, in the case's gen order.
qg : ndarray[float64]
Generator reactive outputs, MVAr.
pf : ndarray[float64]
Real power entering each branch at its from end, MW.
qf : ndarray[float64]
Reactive power entering each branch at its from end, MVAr.
pt : ndarray[float64]
Real power entering each branch at its to end, MW.
qt : ndarray[float64]
Reactive power entering each branch at its to end, MVAr.
bus : ndarray[float64]
The bus matrix with VM and VA filled, MATPOWER's columns.
gen : ndarray[float64]
The gen matrix with PG and QG filled.
branch : ndarray[float64]
The branch matrix widened to 17 columns, PF, QF, PT, QT filled.
baseMVA : float
The system base, MVA.

Raises

ValueError
An unknown method, a case name that is not shipped, or a case dict without baseMVA, bus, gen and branch.
module.VivStop
The case has no bus that can be the reference, or every generator is at a reactive limit.
TypeError
An argument of the wrong type, or an unknown keyword.
vipyr.VivBuildError
An ImportError: no C compiler, or the program's C does not build.

Notes

The equations. With bus voltages and the bus admittance matrix , the power injected at bus is . The power flow solves : the real part at every PV and PQ bus, the imaginary part at every PQ bus, for the angles of the PV and PQ buses and the magnitudes of the PQ buses.

Newton-Raphson. The Jacobian has the closed forms and , assembled entry by entry from 's sparsity. The minimum-degree order is found once, from the first Jacobian; every iteration factors anew, with row pivoting decided on the values.

Fast-decoupled. is of the network with no shunts, no line charging, unit tap ratios and no series resistance; is with no phase shifts. An iteration solves , then .

DC. with , the reference angle held fixed; branch flows are plus the phase shifter's term.

Generator outputs. After the solve the reference bus's first generator takes the slack in P, and Q at a bus with several generators is shared in proportion to their Q ranges, as MATPOWER's pfsoln does.

References

  1. R. D. Zimmerman, C. E. Murillo-Sanchez, R. J. Thomas, MATPOWER: steady-state operations, planning and analysis tools for power systems research and education, IEEE Trans. Power Systems 26 (2011) 12-19 doi:10.1109/TPWRS.2010.2051168
  2. MATPOWER (cases and the reference solution soln9_pf.mat) https://github.com/MATPOWER/matpower
  3. B. Stott, O. Alsac, Fast decoupled load flow, IEEE Trans. PAS 93 (1974) 859-869 doi:10.1109/TPAS.1974.293985
  4. R. A. M. van Amerongen, A general-purpose version of the fast decoupled load flow, IEEE Trans. Power Systems 4 (1989) 760-770 doi:10.1109/59.193851
  5. J. R. Gilbert, T. Peierls, Sparse partial pivoting in time proportional to arithmetic operations, SIAM Journal on Scientific and Statistical Computing 9 (1988) 862-874 doi:10.1137/0909058

Examples

import vipyr as vp
r = vp.power.runpf("case118")               # Newton-Raphson
print(r.success, r.iterations, r.vm.min(), r.va.max())
d = vp.power.runpf("case118", method="dc")  # the linear model
print(abs(d.va - r.va).max())               # degrees between the two
assert r.check()
True 3 0.9429999999999998 39.74834338937072
5.309803267993082

Each example ran as written when these pages were generated, and the output shown is what it printed.

Checked against

Reference
MATPOWER's own solution of its test case t_case9_pf (lib/t/soln9_pf.mat and soln9_dcpf.mat): every voltage, generator and branch result to 10−12 by NR and DC, and by FDXB to its convergence tolerance; and an independent NumPy/SciPy power flow (lib/power/oracle/pf_scipy.py) on case9 to case2383wp, where the largest differences are 2 × 10−13 per unit in Vm and 4 × 10−11 degrees in Va by NR (lib/power/compare.py, lib/power/COMPARISON.md).

Credits

  • The methods follow MATPOWER's (BSD-3-Clause). The test cases are MATPOWER's case files, each with its source named in its header.

Source