Power Flow Overview for Developers

PowerFlows.jl solves steady-state power flow on a PowerSystems.System. The public API is built around PowerFlowEvaluationModel values (what problem to solve) and, for AC cases, an ACPowerFlowSolverType (how to solve it). See Evaluation Models vs. Solver Algorithms for that split and for the three AC formulations (ACPolarPowerFlow, ACRectangularPowerFlow, ACMixedPowerFlow).

AC solves use sparse Jacobians factorized with KLU.jl. The initial guess comes from the current bus setpoints in sys, optionally adjusted by enhanced flat start and related options on the evaluation model.

Two standalone usage modes

Most callers use one of the following patterns.

1. Solve and return results (solve_power_flow)

solve_power_flow reads injections and setpoints from sys, runs the selected evaluation model, and returns a Dict of DataFrames ("bus_results", "flow_results", and "lcc_results" when LCC HVDC is present). The System is not modified.

using PowerFlows
using PowerSystems
using PowerSystemCaseBuilder

sys = build_system(PSITestSystems, "c_sys14"; runchecks = false)
pf = ACPowerFlow()
ACPolarPowerFlow{NewtonRaphsonACPowerFlow}(false, nothing, false, false, false, nothing, true, false, false, false, PowerNetworkMatrices.NetworkReduction[], 1, String[], false, false, Dict{Symbol, Any}())
results = solve_power_flow(pf, sys)
results["bus_results"]
4 rows omitted
bus_number Vm θ P_gen P_load P_net Q_gen Q_load Q_net
Int64 Float64 Float64 Float64 Float64 Float64 Float64 Float64 Float64
1 1.06 0.0 232.55090506782906 0.0 232.55090506782906 -15.529078407207178 0.0 -15.529078407207178
2 1.045 -0.08704576237894333 40.0 21.7 18.3 46.92158629034729 12.7 34.22158629034729
3 1.01 -0.2223975863687207 0.0 94.19999999999999 -94.19999999999999 27.136399074342837 19.0 8.136399074342837
4 1.0142324081898735 -0.17900881200359442 0.0 47.8 -47.8 0.0 -3.9 3.9
5 1.017238179848024 -0.15297200104735895 0.0 7.6 -7.6 0.0 1.6 -1.6
6 1.07 -0.25163674129841473 0.0 11.200000000000001 -11.200000000000001 21.60389347429052 7.5 14.103893474290519
7 1.0503437795744979 -0.23128949300382112 0.0 0.0 0.0 0.0 0.0 0.0
8 1.09 -0.2312894930038211 0.0 0.0 0.0 24.53890523566427 0.0 24.53890523566427
9 1.0337108965111232 -0.2588720513851722 0.0 29.5 -29.5 0.0 16.6 -16.6
10 1.0325605999979304 -0.262518640571551 0.0 9.0 -9.0 0.0 5.800000000000001 -5.800000000000001

For DC formulations, pass a FlowReporting mode so branch flows use the same arc basis as the rest of the package:

keys(solve_power_flow(DCPowerFlow(), sys, FlowReporting.ARC_FLOWS))
KeySet for a Dict{String, Dict{String, DataFrame}} with 1 entry. Keys:
  "1"

2. Solve and write back into the system (solve_and_store_power_flow!)

solve_and_store_power_flow! solves the same problem and, on success, updates bus voltages, branch flows, and generator setpoints in sys. It returns true or false for convergence — useful in scripts and validation loops.

converged = solve_and_store_power_flow!(pf, sys)
true

Solver tolerances and iteration limits can be passed as keyword arguments (for example tol, maxIterations); configuration such as time_steps, network_reductions, and correct_bustypes belongs on the evaluation model constructor.

Typical uses: initializing a case before export, checking AC feasibility after a scheduling step, or batch validation when you already have a System in memory.

Capabilities relevant to developers

  • AC formulations — polar power balance (default), Da Costa rectangular current injection, and mixed current–power balance (ACMixedPowerFlow).
  • AC solvers — Newton–Raphson, trust region, Levenberg–Marquardt; robust homotopy and gradient descent on polar only.
  • DC — bus-angle DC, PTDF, and virtual PTDF; multi-period DC is supported.
  • HVDC — LCC line-commutated converters on all three AC formulations; VSC/HVDC models per package tests and docs.
  • Post-processing — optional reactive-power limit enforcement, PSS/e export via PSSEExportPowerFlow, loss and voltage-stability factors (polar only).

For formulation and solver selection at scale, see How to choose an AC formulation and solver.

Power flow in the loop (PowerSimulations.jl)

There is a third integration pattern that does not call solve_power_flow from user code directly, but still exercises the same solvers inside PowerFlows.jl.

In production-cost, unit commitment, and economic-dispatch workflows, PowerSimulations.jl (PSI) can run an AC (or DC) power flow after each optimization interval while a simulation is executing. This is often called power flow in the loop (or in-the-loop PF).

How PSI wires it

  1. You pass a PowerFlowEvaluationModel (for example ACPowerFlow with an optional PSSEExportPowerFlow exporter) into a PSI NetworkModel via the power_flow_evaluation keyword.
  2. During build! / execute!, PSI constructs a PowerFlowData container (see make_power_flow_container in the source) and maps UC/ED decision variables (dispatch, load, storage, etc.) into PF injection data for each time step.
  3. At the appropriate point in the simulation, PSI calls solve_power_flow! on that container — the same in-place solve used internally by standalone AC solves — then copies voltages, angles, and branch flows into auxiliary variables on the optimization results (for example PowerFlowVoltageMagnitude__ACBus, PowerFlowBranchActivePowerFromTo__Line).

So from a PowerFlows.jl maintainer's perspective, in-the-loop usage is still PowerFlowEvaluationModel + solve_power_flow! on PowerFlowData; PSI owns the scheduling, input mapping, and exposure of results to the simulation interface.

Why it matters for PF development

  • Changes to residual/Jacobian setup, multi-period behavior, LCC handling, or convergence reporting can surface in PSI simulations even when standalone solve_power_flow tests still pass.
  • PSI currently rejects some PF options in this path (for example network reductions on in-the-loop containers); see check_network_reduction in PowerSimulations.
  • The UC stage still optimizes over its own network model (commonly PTDF); the in-loop AC solve is a post-optimization evaluation on the committed dispatch, not a feedback loop into the MILP/LP. PSI use_slacks on the network model refers to slack variables in the optimization formulation, not to AC/PTDF reconciliation.

Learn more in PowerSimulations

PSI documents the end-to-end workflow (template setup, auxiliary variables, comparing PTDF UC flows to AC in-loop flows) in its tutorial Running Power Flow In The Loop with Unit Commitment.

Standalone PF examples and formulation trade-offs remain in the Solving a Power Flow tutorial and the Explanation pages (for example Evaluation Models vs. Solver Algorithms).