SOCP
Solver: Clarabel
SOCBF is the second-order cone relaxation of the branch-flow model, introduced by Farivar and Low in 2013. Where SOCWR (Jabr) operates in the W-space of bus voltage products, SOCBF parameterizes the network by branch flows Pij, Qij and squared current magnitudes ℓij — variables that align naturally with the physical structure of radial distribution feeders. On trees, SOCBF and SOCWR are mathematically equivalent (Low 2014); their differences emerge in mesh topologies and in how easily each formulation scales to large distribution networks.
Use SOCBF on radial or weakly meshed distribution networks where branch-flow variables are the natural decision variables — for instance, in DER hosting capacity studies, optimal capacitor placement, or network reconfiguration. The branch-flow parameterization gives sparser constraint matrices than SOCWR on radial topologies, often translating to faster solves. SOCBF is also the canonical relaxation that the LinDistFlow approximation (BFA) is built on top of — turning BFA into a special case obtained by dropping a single SOC constraint.
SOCBF tracks each branch (i,j) via the active and reactive power sent from the upstream bus, Pij and Qij, plus the squared current magnitude ℓij = |Iij|². Bus voltages are tracked as squared magnitudes vi = |Vi|². The exact AC branch-flow equations on a radial network read:
The first equation expresses voltage drop along a branch including resistive and reactive losses; the second equation defines the current magnitude from power and voltage. The second relation is the only non-convex constraint — and it is exactly the place where the SOC relaxation acts.
Active and reactive power balance at each bus accounts for branch flows in (deducting losses) and out, plus generator dispatch and demand:
Losses rijℓij and xijℓij are subtracted from incoming flows — the branch-flow accounting that BFA discards in its linearization, but that SOCBF retains exactly.
The non-convex equality ℓij · vi = Pij² + Qij² is relaxed to inequality:
This is a rotated second-order cone constraint — the same convex object that SOCWR uses on bus products, here expressed on branch flows and the upstream bus voltage. The relaxation is exact on radial networks under conditions analogous to SOCWR (Farivar–Low 2013, Gan et al. 2015): when load profiles are well-behaved and voltage limits are not binding, the optimal SOCBF solution satisfies the original equality and equals the AC optimum.
The complete formulation reads:
The branch-flow parameterization yields constraints with locality: each constraint touches only one branch and its two endpoints, producing a tree-structured constraint graph on radial networks. This sparsity is what makes SOCBF particularly efficient on large distribution feeders.
SOCBF and SOCWR are equivalent on radial networks (Low 2014, Subhonmesh et al. 2012) — they describe the same convex set and yield identical optimal costs. The choice between them is computational: SOCBF’s sparsity favors radial topologies and very large feeders (thousands of buses), while SOCWR’s W-space variables scale better on meshed transmission networks. Lirion exposes both so that users can benchmark on their specific topology.
The relaxation is exact (equality holds at the optimum) on radial networks under sufficient conditions involving load monotonicity and voltage-limit slackness. When exact, SOCBF returns the AC global optimum with a convex-optimization certificate. When the gap is non-zero, the solution provides a tight lower bound and a starting point for branch-and-bound or sequential SOC tightening (Kocuk et al. 2016). On distribution networks with PV inverters and DER aggregators, SOCBF is the workhorse formulation for real-time market clearing.
Solving SOCBF on a MATPOWER case file requires a single call to solve:
using Lirion
# Solve SOCBF on a radial distribution feeder
out = solve("case33bw.m"; model = socbf(), algorithm = centralized())
# Branch-flow solution
P_ij = out.solution["branch"]["pf"] # active branch flows
Q_ij = out.solution["branch"]["qf"] # reactive branch flows
l_ij = out.solution["branch"]["ccm"] # squared currents
v_sq = out.solution["bus"]["w"] # squared voltage magnitudes
# Check exactness: does the SOC constraint hold with equality?
slack = l_ij .* v_sq[1:length(l_ij)] .- (P_ij.^2 .+ Q_ij.^2)
println("SOCBF lower bound: \$", round(out.objective, digits=2))
println("Max SOC slack: ", round(maximum(slack), digits=6))
println("Relaxation exact? ", maximum(slack) < 1e-5) The out object follows the PowerModels.jl result schema. Branch flows are available under out.solution["branch"]["pf"].