NLP
Solver: Ipopt
ACR is the AC OPF rewritten in rectangular voltage coordinates: instead of magnitude and angle (|Vi|, θi), each bus voltage is decomposed into real and imaginary parts (vir, vii). The two formulations describe the same feasible set — identical physics, identical optimal solutions in principle — but the algebraic structure they expose to a nonlinear solver is markedly different.
Use ACR when the trigonometric functions in polar AC cause numerical trouble: ill-conditioned Jacobians near singular operating points, convergence stagnation on heavily loaded networks, or when warm-starting from a load flow whose phase angles are unreliable. The rectangular formulation replaces sin/cos with polynomials, producing a Jacobian sparsity pattern that Ipopt sometimes prefers — particularly on networks with HVDC links or phase-shifting transformers where polar angles wrap problematically.
Each bus voltage phasor is written as a sum of real and imaginary parts:
Voltage magnitude bounds become quadratic, and the angle reference is enforced by fixing the imaginary part of the slack bus to zero (vslacki = 0). The Y-bus relation I = YV is unchanged — Yik = Gik + jBik still holds, only the voltage representation differs.
Substituting the rectangular decomposition into the complex-power equation Si = Vi · (Σk Yik Vk)* and separating real and imaginary parts yields polynomial expressions for active and reactive power injections:
No trigonometric functions appear — only bilinear products of voltage components. Branch flows Sij follow the same pattern, producing degree-4 polynomials in (vr, vi) when squared for thermal limits. The problem remains non-convex (bilinear terms are non-convex), but the structure is purely polynomial.
The complete formulation reads:
The optimization variables double in count compared to polar AC (2 voltage components per bus instead of magnitude + angle), but constraints remain at the same algebraic complexity. The slack-bus anchor vslacki = 0 removes the rotational invariance of the problem.
ACR and polar AC describe the same physical problem and reach the same global optimum when a unique solution exists. In practice, however, interior-point solvers can converge to different local optima depending on the formulation — neither is universally better. Ipopt typically performs comparably on both, with ACR slightly preferred on networks where angle wrapping or near-singular Jacobians cause issues in polar form.
The bilinear/polynomial structure of ACR is also the entry point for global optimization methods: SDP and moment-based relaxations build naturally on rectangular variables. Within Lirion, the practical advice is: try AC first, switch to ACR when polar fails to converge or when downstream tooling expects rectangular output (e.g., piecewise convex envelopes for spatial branch-and-bound).
Solving ACR OPF on a MATPOWER case file requires a single call to solve:
using Lirion
# Solve ACR — same problem as AC, different coordinates
out = solve("case118.m"; model = acr(), algorithm = centralized())
# Rectangular voltage components
vr = out.solution["bus"]["vr"] # real parts
vi = out.solution["bus"]["vi"] # imaginary parts
# Reconstruct magnitudes and angles
V_mag = sqrt.(vr.^2 .+ vi.^2)
V_ang = atan.(vi, vr)
println("Objective: \$", round(out.objective, digits=2))
println("Solve time: ", round(out.solve_time, digits=3), " s") The out object follows the PowerModels.jl result schema. Branch flows are available under out.solution["branch"]["pf"].