hybrid cpb formulation#372
Conversation
There was a problem hiding this comment.
Pull request overview
Introduces a third AC power flow formulation — ACMixedPowerFlow (Mixed Current-Power Balance, MCPB) — that uses divided current balance at PQ buses and power balance + |V|² constraint at PV buses in rectangular (e, f) coordinates. Adds optional Marquardt diagonal column scaling to the Levenberg–Marquardt solver (defaulting on for rectangular, off for polar), hardens the rectangular CI residual/Jacobian with a V_FLOOR2 = 1e-16 floor on |V|², extends voltage-magnitude validation to rectangular/mixed via squared-magnitude checks, ships extensive parity/jacobian/flat-start/LCC tests against polar and rectangular references, and adds tutorial/explanation docs plus a benchmark script.
Changes:
- New MCPB formulation (
ACMixedPowerFlow, residual, Jacobian, setup, finalize) wired throughimprove_x0,initialize_power_flow_variables, NR/TR/LM/Iwamoto step paths, and finalize. - LM workspace gains
D/marquardt_scaling, with formulation-dispatched default; LM driver acceptsmarquardt_scalingand re-scales each iteration. - Rectangular CI residual/Jacobian floored by
V_FLOOR2; new_validate_squared_voltage_magnitudesdispatched for rect and mixed.
Reviewed changes
Copilot reviewed 28 out of 28 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| src/PowerFlows.jl | Export ACMixedPowerFlow; include the three new MCPB source files. |
| src/power_flow_types.jl | New ACMixedPowerFlow{ACSolver} struct + constructor with solver-type validation; LM docstring documents marquardt_scaling. |
| src/power_flow_setup.jl | improve_x0 overload and initialize_power_flow_variables for MCPB; union-widened helpers; shared _enhanced_flat_start covers both rect and mixed layouts. |
| src/power_flow_method.jl | Union-widens step/finalize/validation helpers to accept MCPB residual/Jacobian; new _finalize_formulation! for mixed; rect/mixed _validate_state_magnitudes. |
| src/mixed_cpb_setup.jl | Offsets, fill/initial-state, update-data round-trip, and post-convergence mixed_finalize_bus_injections! (raw-Y matvec + LCC self-admittance). |
| src/mixed_cpb_power_flow_residual.jl | ACMixedCPBResidual with shared state caches, imag-first PQ rows, eq.7/eq.8 PV rows, REF rect-verbatim, LCC tail. |
| src/mixed_cpb_power_flow_jacobian.jl | ACMixedCPBJacobian with structure builder, constant-Yb PQ block fill, per-iteration diagonal + PV off-diagonal + slack + LCC updates via nzval caches. |
| src/levenberg-marquardt.jl | Adds D and marquardt_scaling to LMWorkspace; update_column_scale!, per-iteration √λ·D damping, formulation-dispatched default. |
| src/rectangular_ci_power_flow_residual.jl | V_FLOOR2 floor on ` |
| src/rectangular_ci_power_flow_jacobian.jl | Matching V_FLOOR2 floors in PQ/PV/REF diagonal blocks and slack cross-terms. |
| src/common.jl | New _validate_squared_voltage_magnitudes for rect/mixed layouts. |
| src/definitions.jl | Defines V_FLOOR2 = 1e-16. |
| test/test_mixed_cpb_*.jl (5 files) | Type validation, setup round-trip, residual zero-at-polar, Jacobian structure + FD + alloc + driver wiring, LCC residual zero, polar/rect parity matrix incl. NR/TR/LM, flat-start coverage. |
| test/test_rectangular_ci_power_flow.jl | LM scaling option tests, squared-magnitude validation, V_FLOOR2 degeneracy guard. |
| test/test_solve_power_flow.jl | Comment/testset rename "Hybrid"→"Mixed". |
| test/performance/performance_test.jl | Adds MCPB solver variants and grouped per-formulation reporting. |
| scripts/benchmarks/formulation_solver_comparison.jl | New 3×3 formulation×solver benchmark script. |
| docs/make.jl, docs/src/explanation/mixed_cpb_formulation.md, lm_vs_gauss_seidel.md, tutorials/solving_a_power_flow.jl | Doc additions describing MCPB and LM-vs-GS positioning + selection table. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…tion # Conflicts: # test/test_solve_power_flow.jl
Performance ResultsPrecompile Time
Solve TimePolar AC
Rectangular CI
Mixed CPB
DC
|
luke-kiernan
left a comment
There was a problem hiding this comment.
First pass. Big 2 comments:
- Redundant offset/block size logic for the CBP method.
- Test correctness of the CBP Jacobian by looking at asymptotic agreement with finite differences to the expected order.
Fix those and I'll take another look.
# uniformly 2; vector kept for signature parity with the rectangular formulation
fill!(block_sizes, Int8(2))
pos = REC_INDEX_TYPE(1)
for i in 1:n_buses
offsets[i] = pos
pos += REC_INDEX_TYPE(2)
endOh, so maybe leaving the offsets/block sizes was purposeful? I question the wisdom of this: as-is, I'd be pleasantly surprised if these constants were propagated by the compiler to their fullest extent. If the goal is inter-operability (being able to write code that works for both CBP and CI), then just make getters and multiple-dispatch: |
luke-kiernan
left a comment
There was a problem hiding this comment.
The one thing I'd like fixed here is the x0 = keyword argument, for overriding the "improve initial guess" stuff.
luke-kiernan
left a comment
There was a problem hiding this comment.
One misleading comment, but that's it.
| # PERF: have not investigated other factorization methods. SPQR does not allow | ||
| # for in-place updates or re-use of symbolic factorization, but with non | ||
| # square matrices--J^T J form is more unstable--we don't have a lot of options. | ||
| # SPQR: enables a cached symbolic factorization with in-place numeric |
There was a problem hiding this comment.
Wait, you figured out a way to reuse the symbolic factorization?! When I asked Claude about that a while back, it told me that SPQR simply didn't allow for separate symbolic vs numeric factorization.
Edit: Oh. We're recomputing the whole thing--ws.F = LinearAlgebra.qr(ws.A)--and this comment is just wrong.
@luke-kiernan after looking at the LM performance with the rectangular model I realized that there were structural weaknesses to LM with rectangular.
Long story short, I added a mixed formulation that uses Rectangular in PQ buses and Polar on PV buses which performs really well with LM and the other solvers too.
This PR also adds proper scaling optionality to LM to make it not as bad for rectangular and protections.
I also asked Claude to document the formulation as well as make a script to benchmark and add notes on model and solver selector.
overall is a long PR but a step forward on the search for improved algorithmic and moiling efficiencies in PF.
This PR also fixes a broken test in main from #370