Internal - Solvers and Utilities

Iterative Methods

PowerFlows.StateVectorCacheType

Cache for non-linear methods.

Fields

  • x::Vector{Float64}: the current state vector.
  • r::Vector{Float64}: the current residual.
  • Δx_nr::Vector{Float64}: the step under the Newton-Raphson method.

The remainder of the fields are only used in the TrustRegionACPowerFlow:

  • r_predict::Vector{Float64}: the predicted residual at x+Δx_proposed, under a linear approximation: i.e J_x⋅(x+Δx_proposed).
  • Δx_proposed::Vector{Float64}: the suggested step Δx, selected among Δx_nr, Δx_cauchy, and the dogleg interpolation between the two. The first is chosen when x+Δx_nr is inside the trust region, the second when both x+Δx_cauchy and x+Δx_nr are outside the trust region, and the third when x+Δx_cauchy is inside and x+Δx_nr outside. The dogleg step selects the point where the line from x+Δx_cauchy to x+Δx_nr crosses the boundary of the trust region.
  • Δx_cauchy::Vector{Float64}: the step to the Cauchy point if the Cauchy point lies within the trust region, otherwise a step in that direction.
source
PowerFlows._accept_trust_region_step!Method

Accept a trust region step: update cached residual and autoscale vector d. The caller is responsible for recomputing the Jacobian via J(time_step) before calling this, so that Jv reflects the new state.

source
PowerFlows._do_refinement!Method

Compute the relative residual ‖A·Δx_nr − r‖₁ / ‖r‖₁ of the linear solve and, if it exceeds refinement_threshold, run iterative refinement and recompute it. Returns the (post-refinement) relative residual; the caller uses it as a backend-agnostic singularity signal (see _set_Δx_nr!).

source
PowerFlows._dogleg!Method

Sets Δx_proposed equal to the Δx by which we should update x. Decides between the Cauchy step Δx_cauchy, Newton-Raphson step Δx_nr, and the dogleg interpolation between the two, based on which fall within the trust region.

source
PowerFlows._finalize_formulation!Method

Formulation-specific post-Newton step. Polar needs nothing; the rectangular CI formulation distributes the converged subnetwork slack into the bus injection arrays.

source
PowerFlows._iwamoto_fallback!Method

Attempt Iwamoto damping on a rejected trust region step.

Uses the already-evaluated trial-point residual to compute an optimal damped step. Returns true if the damped step was accepted, false if reverted.

source
PowerFlows._iwamoto_multiplierMethod

Optimal Iwamoto multiplier μ ∈ [IWAMOTOMUMIN, IWAMOTOMUMAX] minimizing g̃(μ) = q₁μ + q₂μ² + q₃μ³ + q₄μ⁴ (coefficients from _iwamoto_quadratic_dots). Stationary points solve the cubic g̃'(μ) = 4q₄μ³ + 3q₃μ² + 2q₂μ + q₁ = 0, found analytically (depressed-cubic Cardano/trig form). Exact for the dogleg step; reduces to classical Iwamoto & Tamura (1981) when b = −f₀ (Newton step).

source
PowerFlows._iwamoto_multiplierMethod

Classical Iwamoto & Tamura (1981) multiplier for the Newton step (b = −f₀), with g₀ = ‖f₀‖², g₁ = f₀ᵀf₁, g₂ = ‖f₁‖², f₁ = F(x+Δx).

source
PowerFlows._iwamoto_objectiveMethod

Iwamoto objective minus its μ-independent constant: g̃(μ) = q₁μ + q₂μ² + q₃μ³ + q₄μ⁴. Dropping the constant preserves the minimizer.

source
PowerFlows._iwamoto_quadratic_dotsMethod

Inner products for the quadratic model F(x+μΔx) = f₀ + μ·b + μ²·a with b = J·Δx, a = F(x+Δx) − f₀ − b. From f₀, rpred = f₀ + b, and rv = F(x+Δx) returns (f₀·b, b·b, f₀·a, b·a, a·a).

source
PowerFlows._iwamoto_stepFunction

Does a single iteration of Newton-Raphson with Iwamoto step control. Computes the Newton step, takes a full trial step, and checks whether the residual norm decreased. If not, computes an optimal damping multiplier μ and applies a damped step instead. When the damped step also fails to reduce the residual, the step is reverted to avoid divergence.

Returns true if the step made progress (residual decreased), false if the step was reverted. Consecutive reverts signal stagnation and the caller should terminate early.

source
PowerFlows._run_power_flow_methodMethod

Runs the full NewtonRaphsonACPowerFlow.

Keyword arguments:

  • maxIterations::Int: maximum iterations. Default: 50.
  • tol::Float64: tolerance. The iterative search ends when norm(abs.(residual)) < tol. Default: 1.0e-9.
  • refinement_threshold::Float64: If the solution to J_x Δx = r satisfies norm(J_x Δx - r, 1)/norm(r, 1) > refinement_threshold, do iterative refinement to improve the accuracy. Default: 0.05.
  • refinement_eps::Float64: run iterative refinement on J_x Δx = r until norm(Δx_{i}-Δx_{i+1}, 1)/norm(r,1) < refinement_eps. Default: 1.0e-6
source
PowerFlows._run_power_flow_methodMethod

Runs the full TrustRegionNRMethod.

Keyword arguments:

  • maxIterations::Int: maximum iterations. Default: 50.
  • tol::Float64: tolerance. The iterative search ends when maximum(abs.(residual)) < tol. Default: 1.0e-9.
  • factor::Float64: the trust region starts out with radius factor*norm(x_0, 1), where x_0 is our initial guess, taken from data. Default: 1.0.
  • eta::Float64: improvement threshold. If the observed improvement in our residual exceeds eta times the predicted improvement, we accept the new x_i. Default: 0.0001.
  • iwamoto_fallback::Bool: when a trust region step is rejected, attempt Iwamoto damping to salvage the step before reverting. Default: true.
source
PowerFlows._simple_stepFunction

Does a single iteration of NewtonRaphsonACPowerFlow. Updates the r and x fields of the stateVector, and computes the Jacobian at the new x.

source
PowerFlows._solve_Δx_nr!Method

Solve for the Newton-Raphson step, given the factorization object for J.Jv (if non-singular) or its stand-in (if singular).

source
PowerFlows._trust_region_stepMethod

Does a single iteration of the TrustRegionNRMethod: updates the x and r fields of the stateVector and computes the value of the Jacobian at the new x, if needed. Unlike _simple_step, this has a return value, the updated value of delta`.

source
PowerFlows._warn_small_lcc_anglesMethod

Warn if any LCC's converged thyristor angle lies outside the physical operating window (LCC_SMALL_ANGLE_THRESHOLD, π/2 − LCC_SMALL_ANGLE_THRESHOLD) (≈ 5° to 85° by default). Real PSS/E LCCs operate well inside this range (rectifier αr ≈ 10-20°, inverter γi ≈ 14-18°). Either extreme sits near an arccos clamp boundary where Q_s's second derivatives are singular (1/sin³ϕ): low α puts the rectifier-side u_r → +1 or the inverter-side u_i → −1; high α (approaching π/2) puts them on the other boundary, and beyond π/2 the converter's rectifying/inverting role would reverse. Hessian-based solvers (LM, RobustHomotopy) degrade in either regime, and even direct Newton hitting one of these bounds is a sign the input data is non-physical.

source
PowerFlows.AdamStateType
AdamState(n::Int)

Pre-allocated mutable state for the Adam optimizer. All working arrays are allocated once before the iteration loop to ensure a zero-allocation inner loop.

Fields

  • g::Vector{Float64}: gradient vector (length n)
  • m::Vector{Float64}: 1st moment estimate (length n)
  • v::Vector{Float64}: 2nd moment estimate (length n)
  • t::Int: step counter for bias correction
source
PowerFlows._interpolate_x!Method

Interpolate x between x_save (α=0) and current x (α=1) at fraction α. Computes x .= x_save .+ α .* (x .- x_save) in-place without allocation.

source
PowerFlows._newton_power_flowMethod

Driver for the GradientDescentACPowerFlow method: sets up the data structures, runs the Adam-based power flow method with backtracking line search, then handles post-processing.

source
PowerFlows.adam_step!Method
adam_step!(x::Vector{Float64}, state::AdamState, cfg::AdamConfig)

Applies one Adam update to x in-place. All intermediate quantities are written directly into state.m and state.v; bias-corrected values are computed as scalars.

source
PowerFlows.compute_gradient!Method
compute_gradient!(state::AdamState, J::ACPowerFlowJacobian, R::ACPowerFlowResidual)

Overwrites state.g with Jᵀ·F in-place. Uses mul! with the Transpose wrapper so the CSC column structure is traversed without materializing a new sparse matrix.

source

Fast/Fixed Decoupled Newton-Raphson

PowerFlows.FDBppCacheType
FDBppCache

A factored B″ over a specific PQ set. Produced by extract_bpp; the cache is reusable across iterations and time steps that return to the same PQ set (Q-limit / multi-period reuse).

Fields

  • pq::Vector{Int}: PQ bus indices defining the submatrix (sorted).
  • bpp::SparseMatrixCSC{Float64, J_INDEX_TYPE}: the [pq, pq] submatrix of bpp_full.
  • bpp_cache::PFLinearSolverCache: its factorization.
source
PowerFlows.FDMatricesType
FDMatrices{S <: FDScheme}

Container for the constant fast-decoupled matrices for one (data, scheme). Parametrized on the scheme type S so scheme is a concretely-typed field.

Fields

  • scheme::S: the B′/B″ scheme instance, FDSchemeXB or FDSchemeBX.
  • recovered::FDRecoveredParams: cached arc/shunt recovery (shared by B′ and B″_full).
  • pvpq::Vector{Int}: non-REF bus indices (rows/cols of B′), sorted.
  • bp::SparseMatrixCSC{Float64, J_INDEX_TYPE}: B′ over pvpq (assembled; symmetric except with phase shifters).
  • bp_cache::PFLinearSolverCache: B′ factorization (built once, reused across iterations/steps).
  • bpp_full::SparseMatrixCSC{Float64, J_INDEX_TYPE}: B″ assembled over ALL buses; the [pq, pq] submatrix is extracted per driver invocation via extract_bpp.
source
PowerFlows.FDRecoveredParamsType
FDRecoveredParams

Per-arc π-model parameters recovered from the PowerNetworkMatrices arc-admittance matrices, plus per-bus shunt admittances. Promoted to ComplexF64 from the stored ComplexF32.

Fields

  • nbus::Int: number of buses (Ybus dimension).
  • from::Vector{Int} / to::Vector{Int}: per-arc from/to bus row indices (Ybus order).
  • tau::Vector{ComplexF64}: per-arc complex tap ratio τ = |τ|·e^{jθτ} (tap on the from side).
  • ys::Vector{ComplexF64}: per-arc series admittance.
  • bc::Vector{Float64}: per-arc total line charging b_c (sum of both π half-shunts).
  • shunt::Vector{ComplexF64}: per-bus shunt admittance (residual of Ybus[i,i] minus the reconstructed incident arc self-terms).
source
PowerFlows._assemble_bp_fullMethod
_assemble_bp_full(p::FDRecoveredParams, scheme::Symbol)
    -> SparseMatrixCSC{Float64, J_INDEX_TYPE}

Assemble the full-bus B′ matrix −imag(Ybus_temp), where Ybus_temp is stamped with b_c = 0, bus shunts = 0, |τ| = 1 (phase shift retained → mildly unsymmetric only with phase shifters). The REF rows/cols are removed later by the pvpq restriction.

source
PowerFlows._assemble_bpp_fullMethod
_assemble_bpp_full(p::FDRecoveredParams, scheme::Symbol)
    -> SparseMatrixCSC{Float64, J_INDEX_TYPE}

Assemble the full-bus B″ matrix −imag(Ybus_temp), where Ybus_temp is stamped with phase shift = 0 (|τ| retained), and b_c + bus shunts INCLUDED. The [pq, pq] submatrix is extracted per driver invocation by extract_bpp.

source
PowerFlows._recover_arc_paramsMethod
_recover_arc_params(data::ACPowerFlowData) -> FDRecoveredParams

Recover per-arc π-model parameters (τ, ys, b_c) and per-bus shunt admittances from the PowerNetworkMatrices arc-admittance matrices and the Ybus diagonal. See the file header for the stamp/recovery conventions. Guards |τ| ≥ FD_TAU_FLOOR and NaN/Inf. Recovered ys/b_c/shunt are left at their true values (the near-zero-reactance cap lives in _fd_series, applied only on the resistance-drop stamp path), so the restamp invariant holds exactly for every branch.

source
PowerFlows._restamp_ybusMethod
_restamp_ybus(p::FDRecoveredParams) -> SparseMatrixCSC{ComplexF64, Int}

Rebuild the full Ybus from recovered π-model parameters plus per-bus shunts. Used by the WP1 restamp-reconstruction tests; should match the original Ybus within ComplexF32 noise.

source
PowerFlows._warn_low_reactanceMethod
_warn_low_reactance(p::FDRecoveredParams)

Warn (once) if any recovered branch reactance |x| = |imag(1/ys)| is below FD_LOW_REACTANCE_WARNING: such super-low reactances make the B′/B″ decoupling ill-conditioned, so the :decoupled variant converges only at a slow linear rate. The :fixed_jacobian variant and the Newton family are unaffected.

source
PowerFlows.build_fd_matricesMethod
build_fd_matrices(data::ACPowerFlowData, time_step::Int64, scheme::FDScheme) -> FDMatrices

Build the constant fast-decoupled matrices for the given scheme (FDSchemeXB or FDSchemeBX):

  • recover per-arc params + per-bus shunts (cached on the result),
  • assemble B′ over the non-REF (pvpq) buses for time_step's bus types and factor it once,
  • assemble the full-bus B″ (the [pq, pq] submatrix is extracted later via extract_bpp).

pvpq/pq are the bus-type index sets at time_step (frozen within a driver invocation; the Q-limit outer loop re-invokes the driver after switching). The B′ factorization is reusable across all iterations and time steps with the same pvpq.

source
PowerFlows.extract_bppMethod
extract_bpp(fd::FDMatrices, pq_set::AbstractVector{<:Integer};
            linear_solver = nothing) -> FDBppCache

Extract and factor the [pq, pq] submatrix of the full B″. Called once per distinct PQ set; the result is cached by the driver so Q-limit retries and multi-period steps that return to the same PQ set reuse the factorization (no refactorization).

source
PowerFlows.FDCacheKeyType
FDCacheKey{S <: FDScheme}

Invalidation key for a FastDecoupledCache: the cached B′/B″ are valid only while the network identity, the B′/B″ scheme, and the linear-solver backend are unchanged. Bundled into one value so the cache-hit test is a single == (== falls back to field-wise === for this immutable struct). Parametrized on the scheme type S so scheme is a concretely-typed field; keys with different schemes are different concrete types, so a scheme change never compares equal.

Fields

  • ybus_id::UInt: objectid(data.power_network_matrix) — network identity.
  • scheme::S: the scheme instance, FDSchemeXB/FDSchemeBX.
  • backend_id::DataType: typeof(resolve_linear_solver_backend(linear_solver)).
source
PowerFlows.FDPQDataType
FDPQData

Per-PQ-set (per bus-type signature) data for the polar :decoupled loop: the factored B″ submatrix over that PQ set, plus the preallocated reactive half-step buffers/index vectors. Built once per distinct PQ set by _get_pq_data! and reused on repeat signatures (Q-limit retries / multi-period steps that return to the same PQ set).

Fields

  • bpp::FDBppCache: factored [pq, pq] B″ submatrix.
  • pq::Vector{Int}: PQ bus indices (sorted; == bpp.pq).
  • v_x_idx::Vector{Int}: x-indices of the |V| state at pq (2i-1).
  • q_row_idx::Vector{Int}: Rv-indices of the Q-mismatch rows at pq (2i).
  • rq::Vector{Float64}: preallocated reactive half-step buffer (length length(pq)).
  • dvlim_pos::Vector{Int}: 1:length(pq) (DVLIM operates on rq positionally).
source
PowerFlows.FDSafeguardStateType
FDSafeguardState

Mutable bookkeeping for the shared FD safeguards across iterations of a single driver invocation. Tracks the previous cycle's sum-of-squares mismatch (for the non-divergent improvement test), the best (smallest) sum-of-squares mismatch seen and a snapshot of the state vector that achieved it (for best-state restore on non-divergent termination), and the cycle-start state snapshot (for re-applying a halved step from a clean base).

source
PowerFlows.FastDecoupledCacheType
FastDecoupledCache{S <: FDScheme}

Factor-once cache for the polar :decoupled FD loop, stored in data.solver_cache[] (a SolverCache subtype, type-disjoint from the DC path's DCSolverCache). Holds the FDCacheKey invalidation key, the constant FDMatrices (recovered params + factored B′ + assembled B″full), the pvpq-invariant half-step buffers/index vectors (factored ONCE per (data, scheme, backend) lifetime), and a Dict of per-PQ-set FDPQData keyed on a bus-type signature. `bpfactorcount/bppfactorcountcount B′ and B″ factorizations for testability (factor-once verification). Parametrized on the scheme typeS(shared withkey/fd) so all fields are concretely typed; every field the hot half-step loop reads isS-independent, so retrieval through the abstractsolvercache` slot stays type-stable.

Fields

  • key::FDCacheKey{S}: invalidation key (network identity, scheme, backend).
  • fd::FDMatrices{S}: recovered params + factored B′ + B″_full.
  • pvpq::Vector{Int}: non-REF bus indices (== fd.pvpq).
  • theta_x_idx::Vector{Int}: x-indices of the θ state at pvpq (2i).
  • p_row_idx::Vector{Int}: Rv-indices of the P-mismatch rows at pvpq (2i-1).
  • rp::Vector{Float64}: preallocated active half-step buffer (length length(pvpq)).
  • pq_data::Dict{Vector{PSY.ACBusTypes}, FDPQData}: bus-type column → per-PQ-set data (the materialized column is the key, so distinct PQ sets can never collide).
  • bp_factor_count::Int: number of B′ factorizations (must be 1 over the cache lifetime).
  • bpp_factor_count::Int: number of B″ factorizations (one per distinct PQ signature).
source
PowerFlows._fd_backend_idMethod
_fd_backend_id(linear_solver) -> DataType

The backend identity used as a FastDecoupledCache invalidation key: the concrete type of the resolved linear-solver backend (e.g. PNM.KLUSolver). Matches the DC path's typeof(cached_backend) === typeof(backend) reuse test.

source
PowerFlows._fd_blowupMethod
_fd_blowup(Δx, blowup) -> Bool

BLOWUP safeguard (used when non-divergent backtracking is disabled): returns true if the largest-magnitude component of the proposed step exceeds blowup, signalling the FD stage should abort.

source
PowerFlows._fd_decoupled_power_flowMethod
_fd_decoupled_power_flow(pf, data, time_step; ...) -> (converged::Bool, iters::Int)

Polar classic fast-decoupled (B′/B″ half-iteration) FD loop. Builds the constant B′/B″ matrices once (factor-once via build_fd_matrices/extract_bpp), then iterates strict P-θ → Q-V half-steps with an exact residual re-evaluation after EACH half-step (the mid-cycle refresh prevents convergence cycling — do NOT skip it). Shared WP2 safeguards (non-divergent backtracking with best-state restore, BLOWUP, DVLIM, V≈0 abort) protect the documented FD failure modes. The FD stage converges on ‖Rv‖∞ < stage_tol, where stage_tol is the real tol for pure FD (handoff_solver === nothing) or the loose handoff_tol when an opt-in handoff (WP4) is configured — the handoff then refines to the real tol (_fd_maybe_handoff!).

Distributed slack is supported via the per-iteration rank-1 slack sync in [_sync_explicit_state!] (decision recorded in WP3 / T6). Returns (converged, iters); the public driver returns only converged, so this is wrapped by _newton_power_flow. When _return_iters = true the tuple is returned directly (used by T2 to assert the FD iteration count); when _return_stage_iters = true it returns (converged, fd_iters, handoff_iters) (used by T4 to assert the FD stage ran and the handoff was small/skipped).

source
PowerFlows._fd_dvlim_clamp!Method
_fd_dvlim_clamp!(Δx, v_state_idx, v_vals, dvlim) -> Bool

DVLIM safeguard. v_state_idx are the x-indices whose entries are voltage magnitudes (the "ΔV portion" of the step) and v_vals the matching current |V| values. Uniformly scales the ENTIRE step Δx so the largest applied |ΔV| ≤ dvlim, and additionally guards the positivity constraint ΔV/V > −1 (a step that would drive a bus voltage to ≤ 0). Returns true if any clamping was applied. No-op (returns false) when v_state_idx is empty (e.g. all-PV systems, or formulations without a scalar |V| state).

source
PowerFlows._fd_fixed_jacobian_power_flowMethod
_fd_fixed_jacobian_power_flow(pf, data, time_step; ...) -> Bool

The :fixed_jacobian (frozen-Jacobian / "dishonest Newton") FD loop for ALL three formulations. Factors the formulation Jacobian ONCE at x0 and reuses the factorization across every iteration. Exact residual every iteration ⇒ converges to the same solution as NR (linear rate). Shared safeguards (non-divergent backtracking with best-state restore, BLOWUP, DVLIM, V≈0 abort) protect against the documented FD failure modes.

source
PowerFlows._fd_lcc_substep!Method
_fd_lcc_substep!(sv, residual, data, time_step)

Sequential AC–DC step for the polar :decoupled loop when LCC HVDC is present: solve each LCC's converter control equations for the current AC voltages (_fd_converter_substep!), write the converged converter states back into the trailing 4·n_lcc slots of sv.x (_write_lcc_state_to_x!), then re-sync explicit rows and re-evaluate the residual so Rv (AC rows + LCC tail rows) reflects the refreshed DC boundary conditions.

source
PowerFlows._fd_maybe_handoff!Method
_fd_maybe_handoff!(pf, sv, residual, J, time_step, handoff_solver, tol, linear_solver,
                   solver_name, fd_iters) -> (converged::Bool, handoff_iters::Int)

Run the opt-in handoff solver (NewtonRaphsonACPowerFlow / TrustRegionACPowerFlow / LevenbergMarquardtACPowerFlow) from the current FD state sv.x for final refinement to the real tol. No-op (returns the current convergence status and 0 handoff iterations) when handoff_solver === nothing or the FD state already meets tol. Otherwise refreshes the formulation Jacobian VALUES at the current FD state and calls the matching inner method: NR/TR via the shared _run_power_flow_method(::StateVectorCache, ::PFLinearSolverCache, ...); LM via its workspace-based _run_power_flow_method(x0::Vector, ::LMWorkspace, ...) adapter. All paths mutate sv.x / residual / J in place (the SAME objects the FD loop used), so the caller's subsequent J(time_step) / _finalize_* see the refined solution. fd_iters and solver_name are used only for the @info handoff log line.

source
PowerFlows._fd_reset_safeguard!Method

Reset the non-divergence bookkeeping (used after a one-shot refreeze): the previous sum-of-squares becomes the current ss; the best-state record is preserved.

source
PowerFlows._fd_restore_best!Method

Restore the best-Σ(Rv²) state recorded in sg into sv.x and re-evaluate the residual there (syncing data). Used on non-divergent termination, V≈0 abort, and before a one-shot refreeze.

source
PowerFlows._fd_runMethod
_fd_run(variant::FDVariant, scheme::FDScheme, pf, data, time_step; kwargs...) -> Bool

Variant dispatch for the FD driver. FDDecoupled runs the polar B′/B″ loop with scheme; when LCC HVDC is present it uses the sequential AC–DC method (the B′/B″ half-steps solve the AC network while a per-LCC converter sub-solve refreshes the DC boundary conditions each cycle — see _fd_converter_substep!). FDFixedJacobian runs the frozen-Jacobian loop (scheme unused). Each inner loop absorbs any extra safeguard kwargs via its own _ignored....

source
PowerFlows._fd_stage_tolMethod

The FD-stage exit tolerance: the loose handoff_tol when a handoff will polish the result to the real tol, else tol itself (pure FD).

source
PowerFlows._fd_v_state_indicesMethod

The x-indices that hold a scalar voltage magnitude (the DVLIM "ΔV portion"). For the polar formulation these are the PQ-bus |V| entries (precomputed on the residual as validate_indices). The rectangular-CI / mixed-CPB formulations carry (e, f) voltage state with no scalar |V| entry, so DVLIM voltage clamping does not apply there (returns an empty vector); their blowup / non-divergent / V≈0 safeguards still operate on the full step.

source
PowerFlows._fd_vm_abortMethod
_fd_vm_abort(vm, vm_abort) -> Bool

V≈0 abort: returns true if any bus voltage magnitude has been driven below vm_abort.

source
PowerFlows._fd_vsc_substep!Method
_fd_vsc_substep!(sv, residual, data, time_step)

Sequential AC–DC step for the polar :decoupled loop when a VSC/DC network is present: re-solve the DC tail (converter Pc, Qc and node Vdc) for the current AC voltages ([`vscwarmstart!](@ref)), write it back into the trailing tail slots ofsv.x`, then re-sync explicit rows and re-evaluate the residual. The B′/B″ half-steps never touch the tail, so without this sub-step the tail states would stay frozen at their initial values and any AC↔DC coupling (converter losses in particular) would keep the tail rows from converging.

source
PowerFlows._get_or_build_fd_cache!Method
_get_or_build_fd_cache!(data, time_step, scheme, backend_id, linear_solver)
    -> FastDecoupledCache

Fetch the cached FastDecoupledCache from data.solver_cache[], or build it. Reuse requires the slot to hold a FastDecoupledCache whose FDCacheKey (Ybus objectid, scheme, backend identity) matches — then B′ and any per-PQ-set B″ are reused with NO refactorization. The reuse test (_reuse_fd_cache) dispatches on the slot's type, so an empty slot rebuilds and a stray non-FD SolverCache (cross-use, impossible today) is a loud MethodError. Otherwise builds via build_fd_matrices (B′ factored once ⇒ bp_factor_count = 1), precomputes the pvpq-invariant buffers, and stores the cache.

source
PowerFlows._get_pq_data!Method
_get_pq_data!(cache, data, time_step, linear_solver) -> FDPQData

Fetch the FDPQData for time_step's PQ set from cache.pq_data, or build it. The materialized bus-type column collect(view(data.bus_type, :, time_step)) keys the dict: identical bus-type columns (across time steps or Q-limit retries returning to a previously-seen PQ set) hit the cache with NO refactorization. Keying on the column itself (rather than a hash of it) makes the lookup collision-free — distinct PQ sets can never alias to the same entry. On a miss, extract_bpp factors the [pq, pq] B″ submatrix once (bumping cache.bpp_factor_count), the half-step buffers/index vectors are preallocated, and the result is stored.

source
PowerFlows._newton_power_flowMethod
_newton_power_flow(pf::AbstractACPowerFlow{<:FastDecoupledACPowerFlow}, data, time_step; ...)

Driver for the FastDecoupledACPowerFlow solver. Reads the variant/scheme from the solver's type parameters (_fd_variant/_fd_scheme), validates the handoff_solver, then dispatches on the variant via _fd_run to _fd_decoupled_power_flow (polar B′/B″ half-steps) or _fd_fixed_jacobian_power_flow (frozen Jacobian). Returns converged::Bool.

source
PowerFlows._solve_Δx_nr_frozen!Method

Frozen-Jacobian Newton step: reuse _solve_Δx_nr! (Δx ← cache \ r) then negate, so the update is x .+= Δx. Does NOT refactor the cache — that is the whole point of the fixed-Jacobian variant (cf. _set_Δx_nr!, which refactors every call).

source
PowerFlows._sync_explicit_state!Method
_sync_explicit_state!(sv, residual, time_step)

Set the REF/PV "explicit" state entries (subnetwork slack P, REF Q, PV Q) to the values that zero their own residual rows given the current (V, θ). Per subnetwork (residual.subnetworks maps a REF bus to its member buses) the slack scalar s = x[2·ref−1] gets the rank-1 distributed-slack update s −= sign·Σ_{i∈subnet} Rv[2i−1] (Σγ = 1 ⇒ exact; reduces to the classic REF-row update when participation is REF-only). REF Q: x[2·ref] −= sign·Rv[2·ref]. PV Q: x[2i−1] −= sign·Rv[2i]. sign = FD_EXPLICIT_SYNC_SIGN (same solve-then-negate contract as the half-steps; T2 NR-parity is the arbiter). The caller must re-evaluate the residual after this to refresh data/Rv.

source
PowerFlows._validate_fd_handoff_solverMethod
_validate_fd_handoff_solver(handoff_solver)

Validate the FastDecoupledACPowerFlow handoff_solver setting. Throws a descriptive ArgumentError on an unsupported value. The fd_variant/fd_scheme choices are now carried as FastDecoupledACPowerFlow type parameters, so invalid values are unrepresentable (the type system rejects them) and the FDDecoupled-is-polar-only constraint is enforced at construction (see _reject_fd_decoupled_on_nonpolar). Returns nothing when valid.

source

Robust Homotopy Method

PowerFlows.A_plus_eq_BT_B!Method

Does A += B' * B, in a way that preserves the sparse structure of A, if possible. A workaround for the fact that Julia seems to run dropzeros!(A) automatically if I just do A .+= B' * B.

source
PowerFlows._update_hessian_lcc_contributions!Method
_update_hessian_lcc_contributions!(Hv, F, data, time_step)

Add per-LCC contributions to the residual-Hessian sum ∑_k F_k ∇² F_k.

For each LCC, the residual rows that depend on LCC state are the bus (P, Q)-balance rows at both AC terminals plus the two tail rows (F_{t_r}, F_{t_i}). (The two α-constraint tail rows are linear, so ∇² F = 0.) The bus-row contributions to the Hessian come from the LCC self-admittance terms P_s(V_s, t_s, α_s) and Q_s(V_s, t_s, α_s), which the network-only Hessian assembly above does not include. The tail rows are linear combinations of P_r and P_i, so they also reduce to the same ∇² P_s blocks.

The Hessian additions are block-diagonal between the rectifier (V_{f_b}, t_r, α_r) and inverter (V_{t_b}, t_i, α_i) coordinates of each LCC: P_r, Q_r have no inverter-state dependence and vice versa. The sparsity pattern of these entries is already covered by J' * J (every rectifier-side column has structural support at rows {P_{f_b}, Q_{f_b}, F_{t_r}, F_{t_i}}, so all 3×3 cross-terms exist).

source
PowerFlows._update_hessian_matrix_values!Method
_update_hessian_matrix_values!(
    Hv::SparseMatrixCSC{Float64, Int32},
    F_value::Vector{Float64},
    data::ACPowerFlowData,
    time_step::Int64
)

Update the Hessian matrix values for the robust homotopy power flow solver.

Description

This function sets Hv equal to:

\[\sum_{k=1}^{2n} F_k(x) H_{F_k}(x)\]

where $F_k$ denotes the $k$th power balance equation and $H_{F_k}$ denotes its Hessian matrix.

This computes only the terms in the Hessian that come from the second derivatives of the power balance equations. The full Hessian of the objective function also includes a $J^T J$ term, which is computed separately.

Sparse Structure

The Hessian is organized into 2×2 blocks, each corresponding to a pair of buses. For a pair of buses $i$ and $k$ connected by a branch, the sparse structure of their block depends on the bus types:

\[\begin{array}{c|cc|cc|cc} & \text{REF} & & \text{PV} & & \text{PQ} & \\ & P_i & Q_i & Q_i & V_i & V_i & \theta_i \\ \hline \text{REF: } P_k & & & & & & \\ Q_k & & & & & & \\ \hline \text{PV: } Q_k & & & & & & \\ V_k & & & & \bullet & \bullet & \bullet \\ \hline \text{PQ: } V_k & & & & \bullet & \bullet & \bullet \\ \theta_k & & & & \bullet & \bullet & \bullet \end{array}\]

where $\bullet$ represents a potentially non-zero entry.

Diagonal blocks (where $i = k$) follow the same pattern as if each bus is its own neighbor. Off-diagonal blocks for pairs of buses not connected by a branch are structurally zero.

Arguments

  • Hv::SparseMatrixCSC{Float64, Int32}: The Hessian matrix to be updated (modified in-place).
  • F_value::Vector{Float64}: Current values of the power balance residuals.
  • data::ACPowerFlowData: The power flow data containing bus and network information.
  • time_step::Int64: The time step for which to compute the Hessian.
source

Levenberg-Marquardt Method

PowerFlows.LMWorkspaceType

Pre-allocated workspace for the Levenberg-Marquardt solver.

Holds the augmented matrix [J; √λ·D] with a fixed sparsity pattern, a mapping to update its entries in-place, and a cached QR factorization. D is the Marquardt column scaling (identity when disabled).

source
PowerFlows.LMWorkspaceMethod

Build the augmented matrix [J; D] once, recording which A.nzval entries correspond to J values vs the damping diagonal.

source
PowerFlows._default_marquardt_scalingMethod

Marquardt column scaling default per formulation: the rectangular CI state columns (e, f, Q, P_gen) differ in natural scale, so identity damping is ill-conditioned there — default it on. The polar state is well-scaled; keep it off so the polar solver is bit-identical to before.

source
PowerFlows._newton_power_flowMethod

Driver for the LevenbergMarquardtACPowerFlow method: sets up the data structures (e.g. residual), runs the power flow method via calling _run_power_flow_method on them, then handles post-processing (e.g. loss factors).

source
PowerFlows.compute_errorMethod

Compute one LM trial step. Assumes residual and J are already evaluated at x by the caller. Returns the gain ratio ρ.

source
PowerFlows.update_column_scale!Method

Update ws.D, the per-column damping scale: each entry is the running maximum (across iterations) of the corresponding Jacobian column's 2-norm. It is used as the Levenberg-Marquardt diagonal damping √λ·D in update_lambda!. A column whose running max is still zero is floored to 1.0, keeping D > 0 so the damped block stays nonsingular.

source

Discrete Control via λ-Continuation

PowerFlows.ControlledFACTSType

Continuous shunt SVC/STATCOM (FACTSControlDevice). Holds vset at controlled_ix (the regulated bus, possibly remote via FCREG) by varying a symmetric shunt susceptance b ∈ [-b_lim, b_lim] (negative = inductive, positive = capacitive); the injected reactive power is b·|V|². Applied through the constant-Z reactive-withdrawal slot (never the Y-bus), so a step does not invalidate a fast-decoupled B″ factorization. svc selects the limit law (_facts_b_limit); b_lim is the current effective |b| bound, refreshed each outer iteration from the measured controlled-bus voltage. At a susceptance limit the clamp holds it there — the homotopy equivalent of the PV→PQ Q-limit release.

source
PowerFlows.ControlledTapType

Voltage-controlling tap transformer. nz_offsets are the 4 cached nzval linear indices of the (from,to)×(from,to) Y-bus block. The control orientation is NOT stored: it comes from the measured plant sensitivity dV/dp (see _control_target), which is correct for any wiring of the controlled bus.

source
PowerFlows._sync_arc_admittances!Method

One-shot post-continuation sync: bring the arc-admittance rows of every moved tap device in line with its final parameter so the branch flows reported by solve_power_flow! match the network the voltages were solved on. Shunt-side devices never touch the arc matrices. No-op when the arc admittance matrices were not built.

source
PowerFlows.get_control_symbolic_factor_countMethod

Number of KLU/AA SYMBOLIC factorizations performed inside the last discrete-control continuation. With PolarNRCache symbolic reuse this stays O(1) per continuation even as inner_solves grows; without it, it tracks inner_solves. 0 when built without control.

source
PowerFlows.load_device_state!Method

Load time step ts's persisted state into the device scratch _control_continuation! mutates. Shunt/FACTS is a plain scalar swap; taps instead reset to their enrollment baseline (d.initial) via a Y-bus delta-update, since they mutate the shared Y-bus and every step must regulate from the same baseline network (reset-to-baseline design; a no-op on step 1).

source
PowerFlows.save_device_state!Method

Persist the device scratch for time step ts into the per-ts store after _control_continuation! runs for that step. Taps persist their converged position for reporting; the next load_device_state! resets the Y-bus to baseline before the next step regulates.

source
PowerFlows.validate_device_store_widthMethod

Guard the per-ts store width against the data horizon at the solve seam: without it a set built for a different horizon would only surface as a BoundsError deep inside the solve.

source
PowerFlows._tap_metadataMethod

Tap-control metadata for one TapTransformer, read from its first-class PSY fields. get_tap_limits is already in tap-ratio units (the PSS/E parser scales RMI1/RMA1 by WINDV2); get_regulated_bus_number is 0 for local (to-bus) control.

source
PowerFlows._validate_shuntMethod

Shunt susceptance invariants; false (with a @warn) de-enrolls the device, leaving it locked at its current setting (the safe posture for bad control data).

source
PowerFlows._validate_tapMethod

Tap invariants; false (with a @warn) de-enrolls the device, leaving the tap locked at its current ratio (the safe posture for bad control data).

source
PowerFlows.build_controlled_device_setMethod

Build the type-stable device set from a PSY.System.

bus_lookup maps PSY bus number → network index in the (possibly reduced) network; reverse_bus_search_map maps reduction-merged bus numbers to their surviving parent; ybus is the assembled AC_Ybus_Matrix from data.power_network_matrix. n_time_steps sizes the returned set's per-ts shunt/FACTS state store (see ControlledDeviceSet).

Per-device data problems (unresolvable buses, degenerate ranges, unsupported control modes) de-enroll the device with a @warn — the device stays at its current setting (a warn-and-lock posture) — and never abort construction.

source
PowerFlows.get_controlled_device_resultsMethod
get_controlled_device_results(data) -> DataFrames.DataFrame

Solved discrete-control device settings: one row per enrolled device per time step, with its family, name, time step, control band, enrollment-time (initial) and solved (final) parameter for that step. Every family (including taps) reports its own per-time-step state. For a single-time-step solve (time_steps == 1), the solved settings are also written back to the PSY.System by solve_and_store_power_flow! under active controls, and applied to PSS/E exports by update_exporter! — see write_device_settings!. For time_steps > 1, a PSY component cannot hold a per-time-step schedule, so this DataFrame is the only place the full per-step results are available. Returns an empty frame when the data was built without discrete control.

source

Linear Algebra Backends

Robust Homotopy

PowerFlows.set_values!Method
set_values!(mat::FixedStructureCHOLMOD, new_vals::AbstractVector{Float64})

In-place update of the numeric values in the CHOLMOD matrix.

source

Newton-Raphson

PowerFlows.PFLinearSolverCacheType

Union of the KLU, AppleAccelerate, and MKLPardiso solver caches. Every member is concrete so the 4-way union stays within Julia's small-union splitting. Both KLU index types are listed: the AC Newton cache and its fallback are built from J.Jv::SparseMatrixCSC{Float64, J_INDEX_TYPE} (Int32 off Apple, Int64 on Apple), while PNM's DC ABA factorization is always KLULinSolveCache{Float64, Int64} regardless of platform — so the DC solve path needs the Int64 member even where J_INDEX_TYPE === Int32.

source
PowerFlows.PardisoLinSolveCacheType

Cache for the MKLPardiso backend. ps (the Pardiso.MKLPardisoSolver handle) is held as Any: its type is only available once the Pardiso.jl extension loads, and keeping it untyped also keeps this struct concrete so it stays a splittable member of PFLinearSolverCache (the cost is confined to the Pardiso solve path). A is snapshotted because Pardiso reads it at solve time; Ti is left abstract since Pardiso converts indices to Int32 internally.

source
PowerFlows.condest!Method

1-norm condition-number estimate of the cached factorization. KLU-only (libklu's klu_condest); AppleAccelerate exposes no condition estimate. Used by the per-iteration solver diagnostics (run_solver_diagnostics!).

source
PowerFlows.resolve_linear_solver_backendMethod

Resolve the active linear-solver backend tag.

Returns a PNM backend singleton: PNM.KLUSolver(), PNM.AppleAccelerateLUSolver(), or PNM.MKLPardisoSolver(). When override === nothing, the platform default from PNM's preference logic is used. Throws if AppleAccelerate is requested off an Apple platform, or if MKLPardiso is requested on a non-x86_64 architecture or without the PowerFlowsPardisoExt extension loaded (import Pardiso).

source
PowerFlows.solve_w_refinementMethod

Adapter: PowerFlows historically calls solve_w_refinement(cache, A, b, eps) with a step-tolerance eps. Map onto PNM's residual-based refined solve.

source
PowerFlows.tsolve!Method

Transpose solve Aᵀ x = b in place. KLU-only (AppleAccelerate has no transpose solve).

source

Solver Diagnostics

PowerFlows._decide_eig_sign_switch!Method

Update state.eig_sign from λ_min and decide the fold bail-out. A non-converged or non-finite real(λ_min) is a conservative bail (warn + abort), never a silent no-op. An exact-zero real part keeps the prior sign. Returns true to abort.

source
PowerFlows._diag_condestMethod

Condition estimate κ̂(J), or NaN when the backend exposes none. The NaN fallback is restricted to the non-KLU PFLinearSolverCache members so the concrete KLULinSolveCache doesn't shadow the KLU method onto the NaN path.

source
PowerFlows._schur_min_eigenvalueMethod

Smallest-magnitude eigenvalue of the Schur complement S by inverse iteration: KrylovKit finds the largest-magnitude eigenvalue μ of S⁻¹ and returns 1/μ. S is non-symmetric, so the result may be complex. Returns (λ_min, converged), with converged = false (and λ_min = NaN ± NaN im) on any failure.

source
PowerFlows.run_solver_diagnostics!Method

Run one iteration's diagnostics against the current J/residual. Does the single per-iteration refactor of cache on J.Jv (NR/TR pass linSolveCache, LM its own KLU diag_cache) and, on success, the single eigensolve shared by the monitor line (monitor) and the fold bail-out (bail). Returns true iff the caller should abort. A SingularException is itself a fold signature: under bail it aborts, under monitor-only it reports singular and continues; any other exception is rethrown.

source
PowerFlows.setup_solver_diagnosticsMethod

Set up a solver loop's diagnostics: returns (monitor, diag_state), allocating the scratch only when a diagnostic or the bail-out is on so the default solve path allocates nothing. diag_state is nothing when neither is requested.

source

Misc.

PSSE Export

PowerFlows._fix_3w_transformer_ratingMethod

Setting a value of zero 0.0 when having a value greater than or equal to INFINITE_BOUND reverses the operation done in the PSY parsing side, according to PSSE Manual.

source
PowerFlows._load_transformer_components_and_mappingsMethod

Load transformer components and create circuit ID mappings.

Returns a tuple of:

  • transformerswithnumbers: 2-winding transformers with their bus numbers
  • transformers3wwith_numbers: 3-winding transformers with their bus numbers
  • transformercktmapping: Circuit ID mapping for 2-winding transformers
  • transformer3wckt_mapping: Circuit ID mapping for 3-winding transformers
source
PowerFlows._make_gens_from_hvdcMethod

Create a synthetic generator (PSY.ThermalStandard) representing one end of a TwoTerminalGenericHVDCLine for export purposes. The generator is initialized with parameters reflecting the HVDC line's state.

Notes

- The generator's name is constructed as "<hvdc_line_name>_<suffix>".
- The `ext` field includes `"HVDC_END"` to indicate the end ("FR"/"TO").
source
PowerFlows._psse_bus_namesMethod

Given a vector of Sienna bus names, create a dictionary from Sienna bus name to PSS/E-compatible bus name. Guarantees determinism and minimal changes.

source
PowerFlows._psse_bus_numbersMethod

Given a vector of Sienna bus numbers, create a dictionary from Sienna bus number to PSS/E-compatible bus number. Assumes that the Sienna bus numbers are positive and unique. Guarantees determinism: if the input contains the same bus numbers in the same order, the output will. Guarantees minimal changes: that if an existing bus number is compliant, it will not be changed.

source
PowerFlows._psse_transformer_namesMethod

Given a vector of Sienna transformer names, create a dictionary from Sienna transformer name to PSS/E-compatible transformer name. Guarantees determinism and minimal changes.

source
PowerFlows._to_floatMethod

Parse a value to Int64, handling strings, floats, and PSSEDEFAULT. Returns PSSEDEFAULT for non-whole numbers or invalid values.

source
PowerFlows._update_gens_from_hvdc!Method

Update the parameters of synthetic generators created from HVDC lines, so they reflect the current setpoints and limits of the HVDC devices in the system.

source
PowerFlows.convert_emptyMethod

If val is empty, returns T(); if not, asserts that val isa T and returns val. Has nice type checker semantics.

Examples

convert_empty(Vector{String}, [])  # -> String[]
convert_empty(Vector{String}, ["a"])  # -> ["a"]
convert_empty(Vector{String}, [2])  # -> TypeError: in typeassert, expected Vector{String}, got a value of type Vector{Int64}
Base.return_types(Base.Fix1(convert_empty, Vector{String}))  # -> [Vector{String}]
source
PowerFlows.create_component_idsMethod

Given a vector of component names and a corresponding vector of container IDs (e.g., bus numbers), create unique-per-container PSS/E-compatible IDs, output a dictionary from (container ID, component name) to PSS/E-compatible component ID. The "singlesto1" flag detects components that are the only one on their bus and gives them the name "1".

source
PowerFlows.get_branches_with_numbersMethod

Collects all AC branches (Line, MonitoredLine, DiscreteControlledACBranch) from the system, sorts them by their bus numbers, and returns a vector of tuples (branch, bus_numbers).

Arguments

  • exporter::PSSEExporter: The exporter containing the system.

Returns

  • Vector{Tuple{PSY.ACBranch, Tuple{Int, Int}}}: Each tuple contains a branch and its associated bus numbers.
source

Post-Processing

PowerFlows._apply_flow_entries!Method

Apply BranchFlowEntry results to branch objects. Entries and branches are matched by iterating in the same order they were generated. Returns the number of entries consumed.

source
PowerFlows._branch_flow_entriesMethod

Non-AC: distribute pre-computed arc-level flows to individual branches. When arc_P_losses are provided (e.g. from lossy DC power flow), they are passed through to _distribute_arc_flows instead of being recomputed as R·P².

source
PowerFlows._compute_segment_flowsMethod
_compute_segment_flows(arc_entry, data, arc, time_step) -> Vector{BranchFlowEntry}

Compute per-segment branch flow entries from arc-level data and endpoint voltages. Dispatches on the arc entry type (direct, 3WT, parallel, series).

source
PowerFlows._distribute_arc_flowsMethod

Distribute pre-computed arc-level flows to individual branches for non-AC power flow. Returns a Vector{BranchFlowEntry}, analogous to _compute_segment_flows for AC. Uses the precomputed arc_P_losses (e.g. from lossy DC P_ft + P_tf) directly.

source
PowerFlows._segment_flow_entryMethod
_segment_flow_entry(segment, V_from, V_to)

Compute a BranchFlowEntry for a single segment given its endpoint voltages. Returns the from-to and to-from complex power flows, plus losses.

source
PowerFlows._set_series_interior_voltages!Method
_set_series_interior_voltages!(sys, segment_sequence, equivalent_arc, V_endpoints, temp_bus_map)

Set the voltages at interior buses of a series chain from the solved interior voltages.

Method

Number the nodes in the series segment 0, 1, ..., n. Number the segments by their concluding node: 1, 2, ... n. The currents in the segments are given by:

\[\begin{bmatrix} y^i_{ff} & y^i_{ft} \\ y^i_{tf} & y^i_{tt} \end{bmatrix} \begin{bmatrix} V_{i-1} \\ V_i \end{bmatrix} = \begin{bmatrix} I_{i-1, i} \\ I_{i, i-1} \end{bmatrix}\]

where upper indices denote the segment number.

There are no loads or generators at the internal nodes, so $I_{i, i+1} + I_{i, i-1} = 0$. Substitute the above expressions for the currents and group by $V_i$:

\[y^i_{tf} V_{i-1} + (y_{tt}^i + y_{ff}^{i+1}) V_i + y_{ft}^{i+1} V_{i+1} = 0\]

For $i = 1$ and $i = n-1$, move the terms involving $V_0$ and $V_n$ (known) to the other side. This gives a tridiagonal system for $x = [V_1, \ldots, V_{n-1}]$:

\[A x = [-y^1_{tf} V_0, 0, \ldots, 0, -y^{n}_{ft} V_n]\]

where $A$ has diagonal entries $y_{tt}^i + y_{ff}^{i+1}$, subdiagonal entries $y_{tf}^{i+1}$, and superdiagonal entries $y_{ft}^i$.

In the implementation, $y_{11}$ is used instead of $y_{ff}$, $y_{12}$ instead of $y_{ft}$, etc.

source
PowerFlows._solve_series_interior_voltagesMethod
_solve_series_interior_voltages(segment_sequence, equivalent_arc, V_endpoints)

Solve for the complex voltages at the interior nodes of a series chain by constructing and solving the tridiagonal system. Returns a Vector{ComplexF64} of length n-1 where n is the number of segments (i.e. one voltage per interior node). See the docstring of _set_series_interior_voltages! for the mathematical derivation.

source
PowerFlows.get_arc_namesMethod

Return the names of the arcs in the power flow data. Each arc is named by its from-to bus number pair, e.g. "123-456".

source
PowerFlows.update_system!Method
 update_system!(sys::PSY.System, data::PowerFlowData; time_step = 1)

Modify the values in the given PowerSystems.System to correspond to the given PowerFlowData such that if a new PowerFlowData is constructed from the resulting system it is the same as data. See also write_power_flow_solution!. NOTE this assumes that data was initialized from sys and then solved with no further modifications.

source
PowerFlows.write_power_flow_solution!Function

Store a DC power-flow solution into the system: bus angles, unit voltage magnitudes, bus types, and redistributed active generation at REF buses and any bus with a nonzero slack participation factor. Branch flows are not written (the DC flow model differs from the voltage-recomputed AC flows; use the solve_power_flow DataFrame output for DC flows).

source
PowerFlows.write_resultsMethod
write_results(
    ::AbstractACPowerFlow{<:ACPowerFlowSolverType},
    sys::PSY.System,
    data::ACPowerFlowData,
    time_step::Int64,
) -> Dict{String, DataFrames.DataFrame}

Returns a dictionary containing the AC power flow results.

Only single-period evaluation is supported at the moment for AC Power flows. The resulting dictionary will therefore feature just one key linked to one DataFrame.

Arguments:

  • ::ACPowerFlow: use ACPowerFlow() storing AC power flow results.
  • sys::PSY.System: container storing the system information.
  • result::Vector{Float64}: vector containing the results for one single time-period.
source
PowerFlows.write_resultsMethod
write_results(
    data::Union{PTDFPowerFlowData, vPTDFPowerFlowData, ABAPowerFlowData},
    sys::PSY.System,
)

Returns a dictionary containing the DC power flow results. Each key corresponds to the name of the considered time periods, storing a DataFrame with the power flow results.

Arguments:

  • data::Union{PTDFPowerFlowData, vPTDFPowerFlowData, ABAPowerFlowData}: PowerFlowData structure containing power flows and bus angles.
  • sys::PSY.System: A PowerSystems.System object storing the system information.
source

Power Systems Utilities

PowerFlows.can_be_PVMethod

Return set of all bus numbers that can be PV: i.e. have an available generator, or certain voltage regulation devices.

source

Common Utilities and Definitions

PowerFlows._compute_bus_active_power_range!Function

Compute per-bus active power range Rk = sum(Pmax - P_setpoint) for generators at REF/PV buses. Used for headroom-proportional distributed slack.

Only writes to column 1: PF uses single-value active power limits and setpoints (not time-varying). The caller copies column 1 to all time steps. For time-varying headroom, compute slack weights in PSI.

source
PowerFlows._pq_validate_indicesMethod

Precompute, once per solve, the x-indices holding |V| for PQ buses in the polar state layout (x[2i-1] = |V| of bus i). Bus types are invariant across NR/TR iterations, so this filtering is hoisted out of the per-iteration validator. Only PQ is checked (PV/REF have |V| pinned to a set-point).

source
PowerFlows._pqpv_validate_offsetsMethod

Precompute, once per solve, the x-offsets of PQ/PV buses for the per-bus block (rectangular CI / mixed CPB) state layout. Bus types and the state layout are invariant across NR/TR iterations, so this filtering is hoisted out of the per-iteration validator. offsets[i] is the start of bus i's block; (e, f) = (x[off], x[off + 1]). REF is fixed and excluded here.

source
PowerFlows._validate_squared_voltage_magnitudesMethod

Validate squared voltage magnitudes for the per-bus-block (rectangular CI / mixed CPB) state layout, scanning the precomputed PQ/PV offset list (_pqpv_validate_offsets) instead of re-filtering all buses every iteration. Unlike the polar check (PQ only), PV is included: (e, f) are genuine state variables for PV here, so |V|² can drift out of range before the |V|²−V_set² row pins it — a flagged PV iterate is a real diagnostic. REF is fixed and was excluded at offset-precompute time.

source
PowerFlows.my_mul_mtMethod

Matrix multiplication A*x. Written this way because a VirtualPTDF matrix does not store all of its entries: instead, it calculates them (or retrieves them from cache), one element or one row at a time.

source