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

A generator-interconnection study: violations before and after the project, distribution factors, and the transfer limit.

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

vp.power.interconnect runs the steady-state part of a system impact study for a new generator of mw MW at the bus poi_bus. It solves the base case and every contingency without the project and with it, marks each violation the project creates (new) or aggravates (worsened), gives the DC distribution factor of the project's output on every branch, and finds the transfer limit: the largest output with no new violation, by bisection on the full AC N-1 between 0 and mw_max.

The project holds the POI's pre-project voltage within its reactive range (by default a 0.95 power factor either way); its power is absorbed by the reference bus or, with sink='gens', by the other generators in proportion to their output.

Signature

vp.power.interconnect(case, poi_bus, mw, *, mvar_range=None, contingencies='n-1', limits=None, sink='slack', mw_max=None, tol_mw=1.0, worse_pct=1.0)

Parameters

case : str | dict, required
A case as vp.power.runpf takes it, or a .raw path.
poi_bus : int, required
The point of interconnection, a bus number of the case.
mw : float, required
The project's output, MW.
mvar_range : tuple, default None
(qmin, qmax), MVAr: with qmin < qmax the project holds the POI's pre-project voltage; with qmin == qmax it injects that Q; None for a 0.95 power factor either way.
contingencies : str | list, default 'n-1'
As for vp.power.contingency.
limits : dict, default None
As for vp.power.contingency.
sink : str, default 'slack'
Where the project's power goes: 'slack' (the reference bus) or 'gens' (every other generator in proportion to its output).
mw_max : float, default None
The top of the transfer-limit search, MW; None for 4 times mw.
tol_mw : float, default 1.0
The transfer limit's bisection stops within this many MW.
worse_pct : float, default 1.0
A violation present before counts as worsened when its percentage rises by more than this.

Returns

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

violations_before : ndarray[float64]
The violations without the project (rows as in vp.power.contingency's violations).
violations_after : ndarray[float64]
The violations with it.
change : ndarray[int64]
Per row of violations_after: 1 new, 2 worsened, 0 neither.
new : ndarray[float64]
The new violations.
worsened : ndarray[float64]
The worsened ones.
df : ndarray[float64]
Per branch: the DC flow change per MW of the project, POI to sink.
transfer_limit_mw : float
The largest output with no new violation (mw_max if none up to it).
limit_found : bool
Whether a new violation appeared below mw_max.
steps : ndarray[float64]
The bisection: rows (MW, new violations).
kinds : ndarray[int64]
Per contingency: 1 a branch, 2 a generator.
elems : ndarray[int64]
Per contingency: its row.
converged : ndarray[bool]
Per row, with the project: whether the AC flow converged.
flows : ndarray[float64]
Rows x branches with the project: |S|, MVA.
vm : ndarray[float64]
Rows x buses with the project: Vm, per unit.
success : bool
Whether the base case with the project converged.

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. FERC Order No. 2023, Improvements to Generator Interconnection Procedures and Agreements, 184 FERC 61,054 (2023): the cluster study and its system impact studies

Examples

import vipyr as vp
r = vp.power.interconnect("case118", 38, 200.0, mw_max=1500.0)
print(len(r.new), r.transfer_limit_mw)
assert r.check()
0 971.19140625

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, brute force: the N-1 of the case with the project at the transfer limit has no violation that the case without it lacks, and at the next output the bisection tried it has one (case30 at bus 30, case118 at buses 38 and 87; 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