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.cpf

The continuation power flow: the PV curve of a transfer into one bus, through the nose.

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

vp.power.cpf traces the bus voltages as the power injected at poi_bus (and taken out at the sink) grows, past the point where the plain power flow stops converging. It is the pseudo-arclength continuation of MATPOWER's runcpf: the transfer is an unknown, a tangent predictor steps along the curve and Newton's method corrects on the power flow augmented with the step equation, which stays solvable at the nose. The nose is the voltage-stability limit of that transfer.

Signature

vp.power.cpf(case, poi_bus, *, sink='slack', step=0.5, max_step=2.0, stop_frac=0.7, max_steps=300, tol=1e-10, nose_tol=0.0001, singular_values=False)

Parameters

case : str | dict, required
A case as vp.power.runpf takes it, or a .raw path.
poi_bus : int, required
The bus receiving the transfer, a bus number.
sink : str, default 'slack'
'slack' or 'gens', as for vp.power.interconnect.
step : float, default 0.5
The first step along the curve (arc length, per unit).
max_step : float, default 2.0
The largest step.
stop_frac : float, default 0.7
Stop once the transfer falls below this fraction of the nose's.
max_steps : int, default 300
The most steps.
tol : float, default 1e-10
The corrector's tolerance, per unit.
nose_tol : float, default 0.0001
Past the nose the trace steps back and shrinks its step until the step is below this; the nose is then located to about its square.
singular_values : bool, default False
Also compute the smallest singular value of the power-flow Jacobian at each point (dense SVD).

Returns

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

mw : ndarray[float64]
The transfer at each point, MW.
v_poi : ndarray[float64]
Vm at the POI, per unit.
v_min : ndarray[float64]
The lowest Vm in the network.
vm : ndarray[float64]
Points x buses: Vm.
va : ndarray[float64]
Points x buses: Va, radians.
nose_mw : float
The largest transfer on the curve, MW.
nose : int
The point of the nose.
smin : ndarray[float64]
The smallest singular value of the Jacobian per point (0 if not asked).
success : bool
Whether the trace passed a nose.

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.

References

  1. V. Ajjarapu, C. Christy, The continuation power flow: a tool for steady state voltage stability analysis, IEEE Trans. Power Systems 7 (1992) 416-423 doi:10.1109/59.141737

Examples

import vipyr as vp
r = vp.power.cpf("case118", 38, step=0.2, max_step=1.0)
print(round(r.nose_mw, 1), r.v_poi[r.nose])
assert r.check()
1990.7 0.6914210369321251

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

Checked against

Reference
PYPOWER 5.1.21's runcpf (pseudo-arclength, full trace) and the largest transfer at which PYPOWER's Newton power flow converges, on case9, case30 and case118; every curve point re-solved by PYPOWER at its transfer agrees in Vm; the Jacobian's smallest singular value at the nose is a small fraction of its base-case value (lib/power/compare_study.py).

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