Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

AC Power Flow (Fixed-Point Iteration)

The AC PF solver implements an OpenDSS-style fixed-point iteration for distribution systems. Unlike the AC OPF which optimises voltage magnitudes within bounds, the AC PF solves the standard power-flow equations: given fixed P/Q injections at PQ buses and a fixed voltage at the slack bus, find the voltage magnitude and angle at every bus.

Formulation

The solver works directly in SI units (volts, amps, siemens) — no per-unit conversion — to avoid the ill-conditioning that arises when nominal voltages span 120 V–40 kV (a 331:1 ratio causing Y-pu diagonal ratios exceeding 325 million).

Fixed-Point Iteration

At each iteration, the current injection at each non-slack node is computed from the specified power and current voltage:

Ii(k)=SispecVi(k)islackI_i^{(k)} = \frac{\overline{S_i^{\text{spec}}}}{\overline{V_i^{(k)}}} \quad \forall i \notin \text{slack}

The updated voltage is obtained by solving the linear system:

Vns(k+1)=Yns1(Ins(k)Yns,slackVslack)V_{\text{ns}}^{(k+1)} = Y_{\text{ns}}^{-1} \left( I_{\text{ns}}^{(k)} - Y_{\text{ns,slack}} \cdot V_{\text{slack}} \right)

where YnsY_{\text{ns}} is the Y-bus submatrix for non-slack nodes and Yns,slackY_{\text{ns,slack}} couples non-slack nodes to the fixed slack voltages.

An acceleration factor α=0.5\alpha = 0.5 damps the update:

Vns(k+1)=Vns(k)+α(Vns,calcVns(k))V_{\text{ns}}^{(k+1)} = V_{\text{ns}}^{(k)} + \alpha \left( V_{\text{ns,calc}} - V_{\text{ns}}^{(k)} \right)

Convergence Criterion

Convergence is measured by the maximum relative voltage change across all non-slack nodes:

maxiVi(k+1)Vi(k)Vbase,i<tolerance\max_i \frac{|V_i^{(k+1)} - V_i^{(k)}|}{V_{\text{base},i}} < \text{tolerance}

Initial Voltage Estimate

Rather than starting from a flat 1.0 pu profile, the solver builds an initial voltage by solving V=Y1IsourceV = Y^{-1} \cdot I_{\text{source}} with loads modeled as constant impedances. This direct solve accounts for all transformer ratios and connections, giving a physically correct starting point.

Key Features

Usage

Low-level interface

from gdm.distribution import DistributionSystem
from gdm_flow import solve_ac_power_flow

system = DistributionSystem.from_json("model.json")

result = solve_ac_power_flow(
    system,
    p_spec_w={("bus_5", "A"): -20_000.0},
    q_spec_var={("bus_5", "A"): -5_000.0},
    max_iterations=100,
    tolerance=1e-6,
)

print(result.success, result.iterations)
print(result.max_mismatch_pu)

Component-based interface

from gdm.distribution import DistributionSystem
from gdm_flow import solve_ac_power_flow_from_components

system = DistributionSystem.from_json("model.json")

result = solve_ac_power_flow_from_components(
    system,
    include_loads=True,
    include_solar=True,
    include_capacitor=True,
    load_scale=1.0,
    solar_scale=1.0,
)

print(f"Converged: {result.success}")
print(f"Iterations: {result.iterations}")
print(f"Max voltage change: {result.max_mismatch_pu:.2e} pu")

Result Object

ACPowerFlowResult contains:

FieldTypeDescription
successboolWhether solver converged within tolerance
messagestrConvergence status message
ybus_resultYBusResultY-bus matrix and node mapping
voltagenp.ndarrayComplex bus voltages in SI volts
voltage_punp.ndarrayPer-unit voltage magnitudes
power_injectionnp.ndarrayComplex power injection at each bus (W + j·var)
iterationsintNumber of fixed-point iterations
max_mismatch_pufloatFinal maximum per-unit voltage change

AC PF vs AC OPF

AspectAC PFAC OPF
MethodFixed-point iteration (current injection)Nonlinear least-squares (optimisation)
UnitsSI (volts, amps, siemens)Per-unit
Slack busFixed at nominal voltageAdjusted within bounds
Voltage boundsNone — reports actual voltagesEnforced via vm_min_pu / vm_max_pu
Regulator targetsNot modeledSoft voltage targets via penalty
Use caseClassical power flow baselineVoltage regulation studies

Both solvers share the same Y-bus construction and produce compatible result objects, making them easy to compare side-by-side.