The Constant-Admittance Linearization

Motivation

"Linear power flow" names two unrelated algorithms in this field, and the difference matters enough to be worth its own page.

The DC approximation discards resistance and voltage magnitude to get a real system in angles alone. That is the right trade on transmission, where flows divide by reactance and magnitudes barely move. It is the wrong trade on a distribution feeder, where the interesting quantity is the voltage drop along the feeder — precisely what DC throws away by construction.

The constant-admittance linearization makes a different sacrifice. It keeps the full complex network and keeps resistance; what it linearizes is the load model. A constant-power load is what makes power flow nonlinear — the current it draws depends on the voltage that the current itself determines. Replace each load with the fixed admittance that would draw its rated power at \(|V| = 1\), and the circuit becomes an ordinary linear one:

\[ S_i = U_i \overline{I_i} = -U_i\overline{U_i Y_{load}} ;\implies; Y_{load} = -\overline{S_i} \quad\text{at } |U| = 1 \]

Fold that into the Y-bus diagonal and one complex factorization gives every voltage, magnitude and angle alike.

What changes in the equation system

\[ Y',U = I, \qquad Y' = Y + \operatorname{diag}(-\overline{S}) \]

with fixed-voltage buses moved to the right-hand side via their known \(U\). Solved once. No iteration, no convergence criterion.

The approximation is exact when the loads really are constant-impedance — which is not a hypothetical, since gridoxide's ZipTerm/ZipKind model represents exactly that case — and degrades as loading moves away from nominal. It is at its best where DC is at its worst and vice versa:

DC (Bθ)Constant-admittance
Arithmeticrealcomplex
Keeps resistancenoyes
Produces \(|V|\)noyes
Produces Qnoyes
Exact whenangles are small and \(r \to 0\)loads are constant-impedance
Natural hometransmissiondistribution

Where this fits in gridoxide today

linear::impedance::linear_power_flow, reached through PowerFlowMethod::LinearImpedance.

gridoxide has had this algorithm since before it was a solver: it was written as Newton-Raphson's warm start, mirroring power-grid-model's own NewtonRaphsonPFSolver::initialize_derived_solver, and it remains that (network::linear_initial_guess). Both entry points share one implementation (linear::impedance::solve_constant_admittance); what the standalone mode adds is the island handling a warm start never needed — connected_components, classify and mark_unreferenced_islands, so a sourceless island is pinned rather than solved and a singular island is attributable to itself.

The two differ in one deliberate respect. linear_initial_guess runs before the solver's own classification pass, so it must not mutate bus types, and a singular result there is simply a warm start that did not happen rather than a failure to report.

This is mathematically power-grid-model's CalculationMethod.linear, down to the \(Y_{load} = -\overline{S}\) step (power_grid_model/math_solver/linear_pf_solver.hpp).

Scope: only PQ buses are unknowns

PV buses are held at their present voltage, exactly as Slack buses are. The method has no mechanism for "magnitude fixed, angle free" — that constraint is not linear in \(U\).

On power-grid-model data this costs nothing, because PGM has no PV buses at all: its sources are slacks. That is also why the comparison with PGM is exact. On data that does carry PV buses — CGMES imports, typically — treating them as fully fixed is a second approximation on top of the linearization, and it is the reason this mode is offered alongside Newton-Raphson rather than instead of it.

Validated against real data

In-module tests in crates/gridoxide-core/src/linear/impedance.rs. a_constant_impedance_load_is_reproduced_exactly checks the defining property: a load that genuinely is constant-impedance is solved exactly, so the solved voltages reproduce the specified power to round-off. agrees_with_the_warm_start_entry_point pins the promotion as a refactor rather than a reimplementation, asserting the standalone mode and network::linear_initial_guess agree to \(10^{-15}\) bus for bus.

Tool reference

ToolHas itWhere
gridoxideyeslinear::impedance::linear_power_flow
power-grid-modelyes, plus a linear_current variantCalculationMethod.linear, linear_pf_solver.hpp
VeraGridyes, as a distinct linearizationSolverType.LACPF
lightsim2gridno—
powsybl-open-loadflowno—
pandapowerno—