Skip to content

Phase angle difference constraints gated by sw, not the energized predicate (b*sw != 0) #63

Description

@cameronkhanpour

Raised by Copilot review on #55 (low-confidence/suppressed); confirmed to have merit.

Inconsistency. The energized-island logic (reference_buses, the topology
cache) treats a branch as energized iff b[e] * sw[e] != 0. The DC OPF phase
angle difference constraints, however, are gated by sw alone:

phase_diff_lb = @constraint(model, network.sw .* (network.A * va) .>= network.sw .* network.angmin)
phase_diff_ub = @constraint(model, network.sw .* (network.A * va) .<= network.sw .* network.angmax)

So a branch with b[e] == 0 and sw[e] != 0 (e.g. a near-zero-impedance branch,
which the DCNetwork constructor sets to b = 0 and treats as open) is counted
as de-energized by the island partition (it splits islands / adds a reference
bus), yet its angle-difference constraint still couples the endpoint angles as if
the branch were present. This contradicts the "Open lines should not constrain
angle differences" comment and the energized-topology definition used elsewhere.

Impact. Narrow. It only triggers for b[e] == 0 with sw[e] != 0, and the
coupling is usually slack because DC angles are small relative to the default
±60° window, so it rarely changes a solution. When it does bind it couples two
islands that are otherwise independent (each referenced to its own slack), which
distorts the primal and produces a spurious cross-island angle dual, so the
congestion/energy split and switching/susceptance sensitivities would be off in
that edge case.

Scope of a proper fix. Gate the angle-difference constraints by the same
energized predicate (an effective sw_eff[e] that is zero when b[e] == 0),
then mirror that gate consistently in:

  • the KKT residual K_γ_lb / K_γ_ub (kkt_dc_opf.jl),
  • the analytic KKT Jacobian gamma columns,
  • the switching and susceptance Jacobian gamma contributions,
  • the LMP congestion decomposition gate (calc_congestion_component).

A model-only change would desync the KKT system from the solved model and
corrupt sensitivities, so this needs to land as one coherent change with
finite-difference verification near b = 0. Tracking separately rather than
expanding the already-approved #55.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions