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
- 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.19140625Each 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
- Viv: lib/power/study.viv
- Viv: lib/power/contingency.viv
- Viv: lib/power/api.viv