Expand description
Outer loops: the controls that sit around a Newton-Raphson solve.
A Newton solve answers “what is the state, given these injections, these bus types and these tap positions”. Several real controls are not expressible that way, because they decide one of those inputs from the solved state: a generator that runs out of reactive capability stops holding its voltage, an imbalance is shared across governors rather than dumped on one slack, an on-load tap changer moves until its controlled bus is inside a deadband. Each is a loop around the solve, not a term inside it.
§Why this module exists
gridoxide grew two such loops as standalone entry points —
newton_raphson_enforcing_q_limits and
newton_raphson_distributing_slack — each constructing its own
PersistentSolver and running its own
pass counter. The consequence was that they could not be used together:
a caller picked one. Real transmission networks want both, and tap control
would have been a third.
So the loops are OuterLoop implementations now, and
solve_with_loops drives an ordered list of them.
§Ordering is a physical claim
The list is innermost first. Each loop is run to its own stability
before the next is consulted, and any loop that moves something sends the
driver back to the start of the list, so an outer loop’s decision is
re-examined by the inner ones. solve_with_loops documents the schedule;
ordered gives the order powsybl-open-loadflow uses, which encodes
that generators respond faster than tap changers.
§Invalidation is the driver’s job, never a loop’s
Three things must happen together after a tap move — write
Transformer::tap, restamp the Y-bus
entries derived from it, drop the cached Jacobian — and a loop that does
one or two of them is a bug that surfaces as a wrong answer on the next
pass rather than as a failure on this one. A loop therefore declares what
it invalidated (Invalidates) and the driver acts on it.
Re-exports§
pub use area::AreaDefinition;pub use area::AreaInterchange;pub use area::AreaInterchangeReport;pub use qlimits::QLimitReport;pub use qlimits::ReactiveLimits;pub use remote::RemoteControlReport;pub use remote::RemoteOutcome;pub use remote::RemoteVoltageControl;pub use slack::DistributedSlack;pub use slack::SlackDistribution;pub use slack::SlackDistributionReport;pub use taps::ControllerOutcome;pub use taps::ControllerReport;pub use taps::PhaseControl;pub use taps::RegulationMode;pub use taps::TapControlReport;pub use taps::TapRegulation;pub use taps::TransformerVoltageControl;
Modules§
- area
- Area interchange control: holding each control area’s net export at its scheduled value.
- qlimits
- Reactive-limit enforcement: the
PV → PQswitch. - remote
- Remote voltage control: holding a bus the machine is not connected to.
- slack
- Distributed slack: sharing the system imbalance across generators instead of dumping all of it on one bus.
- taps
- Transformer tap control: the on-load tap changer as a control rather than a constant.
Structs§
- Loop
Report - Per-loop accounting from one
solve_with_loopsrun. - Outer
Loop Context - The mutable network a loop is allowed to act on, plus the last solve’s result.
- Outer
Loop Report - What the whole outer-loop run did.
- Solve
Context - The network a solve runs against.
Enums§
- Invalidates
- What a loop invalidated when it reported
OuterLoopStatus::Unstable. - Outer
Loop Status - What a loop decided after looking at a converged state.
Traits§
- Outer
Loop - What a loop is allowed to do to a solve.
Functions§
- ordered
- The order powsybl-open-loadflow applies by default, restricted to the loops gridoxide has: distributed slack innermost, then reactive limits, then the two tap controls.
- solve_
with_ loops - Solve, then run an ordered list of outer loops to a fixed point.