Internal - Solvers and Utilities
Iterative Methods
PowerFlows.StateVectorCache — Type
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 atx+Δx_proposed, under a linear approximation: i.eJ_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 whenx+Δx_nris inside the trust region, the second when bothx+Δx_cauchyandx+Δx_nrare outside the trust region, and the third whenx+Δx_cauchyis inside andx+Δx_nroutside. The dogleg step selects the point where the line fromx+Δx_cauchytox+Δx_nrcrosses 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.
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.
PowerFlows._build_singular_J_fallback — Method
Returns a freshly-allocated stand-in matrix -(JᵀJ + λI) for a singular J. The result defines the sparsity pattern that _refresh_singular_J_fallback! reuses in place.
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!).
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.
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.
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.
PowerFlows._iwamoto_multiplier — Method
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).
PowerFlows._iwamoto_multiplier — Method
Classical Iwamoto & Tamura (1981) multiplier for the Newton step (b = −f₀), with g₀ = ‖f₀‖², g₁ = f₀ᵀf₁, g₂ = ‖f₁‖², f₁ = F(x+Δx).
PowerFlows._iwamoto_objective — Method
Iwamoto objective minus its μ-independent constant: g̃(μ) = q₁μ + q₂μ² + q₃μ³ + q₄μ⁴. Dropping the constant preserves the minimizer.
PowerFlows._iwamoto_quadratic_dots — Method
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).
PowerFlows._iwamoto_step — Function
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.
PowerFlows._refresh_singular_J_fallback! — Method
Refresh M = -(JᵀJ + λI) in place (λ as in _build_singular_J_fallback). Returns false without touching M when the JᵀJ pattern no longer matches M's, so the caller rebuilds.
PowerFlows._report_power_flow_convergence — Method
Log the final residual size and convergence/non-convergence, returning converged. Shared by both _finalize_power_flow methods (Jacobian and Jacobian-free).
PowerFlows._run_power_flow_method — Method
Runs the full NewtonRaphsonACPowerFlow.
Keyword arguments:
maxIterations::Int: maximum iterations. Default: 50.tol::Float64: tolerance. The iterative search ends whennorm(abs.(residual)) < tol. Default: 1.0e-9.refinement_threshold::Float64: If the solution toJ_x Δx = rsatisfiesnorm(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 onJ_x Δx = runtilnorm(Δx_{i}-Δx_{i+1}, 1)/norm(r,1) < refinement_eps. Default: 1.0e-6
PowerFlows._run_power_flow_method — Method
Runs the full TrustRegionNRMethod.
Keyword arguments:
maxIterations::Int: maximum iterations. Default: 50.tol::Float64: tolerance. The iterative search ends whenmaximum(abs.(residual)) < tol. Default: 1.0e-9.factor::Float64: the trust region starts out with radiusfactor*norm(x_0, 1), wherex_0is our initial guess, taken fromdata. Default: 1.0.eta::Float64: improvement threshold. If the observed improvement in our residual exceedsetatimes the predicted improvement, we accept the newx_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.
PowerFlows._set_Δx_nr! — Method
Sets the Newton-Raphson step. Usually, this is just J.Jv \ stateVector.r, but J.Jv might be singular.
PowerFlows._simple_step — Function
Does a single iteration of NewtonRaphsonACPowerFlow. Updates the r and x fields of the stateVector, and computes the Jacobian at the new x.
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).
PowerFlows._trust_region_step — Method
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`.
PowerFlows._try_iwamoto_candidate — Method
If μ ∈ [IWAMOTOMUMIN, IWAMOTOMUMAX] and g̃(μ) < bestg, return the improved (μ, g̃(μ)); otherwise return (bestμ, best_g) unchanged.
PowerFlows._warn_small_lcc_angles — Method
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.
PowerFlows.AdamConfig — Type
AdamConfig(; learning_rate=0.01, beta1=0.9, beta2=0.999, epsilon=1e-8)
AdamConfig(settings::Dict{Symbol, Any})Configuration for the Adam optimizer used by GradientDescentACPowerFlow.
PowerFlows.AdamState — Type
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 (lengthn)m::Vector{Float64}: 1st moment estimate (lengthn)v::Vector{Float64}: 2nd moment estimate (lengthn)t::Int: step counter for bias correction
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.
PowerFlows._newton_power_flow — Method
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.
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.
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.
Fast/Fixed Decoupled Newton-Raphson
PowerFlows.FDBppCache — Type
FDBppCacheA 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 ofbpp_full.bpp_cache::PFLinearSolverCache: its factorization.
PowerFlows.FDMatrices — Type
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,FDSchemeXBorFDSchemeBX.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′ overpvpq(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 viaextract_bpp.
PowerFlows.FDRecoveredParams — Type
FDRecoveredParamsPer-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 chargingb_c(sum of both π half-shunts).shunt::Vector{ComplexF64}: per-bus shunt admittance (residual ofYbus[i,i]minus the reconstructed incident arc self-terms).
PowerFlows._assemble_bp_full — Method
_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.
PowerFlows._assemble_bpp_full — Method
_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.
PowerFlows._recover_arc_params — Method
_recover_arc_params(data::ACPowerFlowData) -> FDRecoveredParamsRecover 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.
PowerFlows._restamp_ybus — Method
_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.
PowerFlows._warn_low_reactance — Method
_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.
PowerFlows.build_fd_matrices — Method
build_fd_matrices(data::ACPowerFlowData, time_step::Int64, scheme::FDScheme) -> FDMatricesBuild 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 fortime_step's bus types and factor it once, - assemble the full-bus B″ (the
[pq, pq]submatrix is extracted later viaextract_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.
PowerFlows.extract_bpp — Method
extract_bpp(fd::FDMatrices, pq_set::AbstractVector{<:Integer};
linear_solver = nothing) -> FDBppCacheExtract 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).
PowerFlows.get_bp_matrix — Method
Accessor for the assembled (unfactored) B′ matrix. Used by tests and diagnostics.
PowerFlows.get_bpp_matrix — Method
Accessor for the assembled (unfactored) B″ submatrix. Used by tests and diagnostics.
PowerFlows.FDCacheKey — Type
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)).
PowerFlows.FDPQData — Type
FDPQDataPer-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 atpq(2i-1).q_row_idx::Vector{Int}:Rv-indices of the Q-mismatch rows atpq(2i).rq::Vector{Float64}: preallocated reactive half-step buffer (lengthlength(pq)).dvlim_pos::Vector{Int}:1:length(pq)(DVLIM operates onrqpositionally).
PowerFlows.FDSafeguardState — Type
FDSafeguardStateMutable 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).
PowerFlows.FastDecoupledCache — Type
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 atpvpq(2i).p_row_idx::Vector{Int}:Rv-indices of the P-mismatch rows atpvpq(2i-1).rp::Vector{Float64}: preallocated active half-step buffer (lengthlength(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).
PowerFlows._default_fd_variant — Method
_default_fd_variant(pf::AbstractACPowerFlow) -> FDVariantThe default FDVariant for a bare (unparametrized) FastDecoupledACPowerFlow on a given formulation: FDDecoupled (classic B′/B″) for the polar formulation, FDFixedJacobian (frozen Jacobian) for the rectangular current-injection and mixed current-power-balance formulations.
PowerFlows._fd_backend_id — Method
_fd_backend_id(linear_solver) -> DataTypeThe 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.
PowerFlows._fd_begin_cycle! — Method
Record the start-of-cycle snapshot and update the best-state record if the current state improved on it.
PowerFlows._fd_blowup — Method
_fd_blowup(Δx, blowup) -> BoolBLOWUP 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.
PowerFlows._fd_decoupled_power_flow — Method
_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).
PowerFlows._fd_dvlim_clamp! — Method
_fd_dvlim_clamp!(Δx, v_state_idx, v_vals, dvlim) -> BoolDVLIM 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).
PowerFlows._fd_fixed_jacobian_power_flow — Method
_fd_fixed_jacobian_power_flow(pf, data, time_step; ...) -> BoolThe :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.
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.
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.
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.
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.
PowerFlows._fd_run — Method
_fd_run(variant::FDVariant, scheme::FDScheme, pf, data, time_step; kwargs...) -> BoolVariant 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....
PowerFlows._fd_stage_tol — Method
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).
PowerFlows._fd_update_best! — Method
Record x as the best-seen state if its sum-of-squares mismatch ss improved on the record.
PowerFlows._fd_v_state_indices — Method
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.
PowerFlows._fd_vm_abort — Method
_fd_vm_abort(vm, vm_abort) -> BoolV≈0 abort: returns true if any bus voltage magnitude has been driven below vm_abort.
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.
PowerFlows._get_or_build_fd_cache! — Method
_get_or_build_fd_cache!(data, time_step, scheme, backend_id, linear_solver)
-> FastDecoupledCacheFetch 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.
PowerFlows._get_pq_data! — Method
_get_pq_data!(cache, data, time_step, linear_solver) -> FDPQDataFetch 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.
PowerFlows._newton_power_flow — Method
_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.
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).
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.
PowerFlows._validate_fd_handoff_solver — Method
_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.
Robust Homotopy Method
PowerFlows.HomotopyHessian — Method
Compute value of gradient and Hessian at x.
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.
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).
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.
Levenberg-Marquardt Method
PowerFlows.LMWorkspace — Type
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).
PowerFlows.LMWorkspace — Method
Build the augmented matrix [J; D] once, recording which A.nzval entries correspond to J values vs the damping diagonal.
PowerFlows._default_marquardt_scaling — Method
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.
PowerFlows._newton_power_flow — Method
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).
PowerFlows.compute_error — Method
Compute one LM trial step. Assumes residual and J are already evaluated at x by the caller. Returns the gain ratio ρ.
PowerFlows.copy_jacobian! — Method
Copy current Jacobian values into the augmented matrix.
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.
PowerFlows.update_lambda! — Method
Update the √λ·D damping diagonal and re-factorize.
Discrete Control via λ-Continuation
PowerFlows.ControlledFACTS — Type
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.
PowerFlows.ControlledSwitchedShunt — Type
Voltage-controlling switched shunt, snapped onto the PSS/E cumulative block-activation chain (blocks switch on in listed order, off in reverse).
PowerFlows.ControlledTap — Type
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.
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.
PowerFlows.get_control_inner_solve_count — Method
Number of inner _solve_with_q_limits! calls the last discrete-control continuation performed (0 when the data was built without discrete control).
PowerFlows.get_control_numeric_refactor_count — Method
Number of per-NR-iteration NUMERIC refactorizations performed inside the last discrete-control continuation. 0 when the data was built without discrete control.
PowerFlows.get_control_symbolic_factor_count — Method
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.
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).
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.
PowerFlows.store_time_steps — Method
Width (number of time steps) of the per-time-step device store; all store matrices share it by construction.
PowerFlows.validate_device_store_width — Method
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.
PowerFlows._tap_metadata — Method
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.
PowerFlows._validate_shunt — Method
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).
PowerFlows._validate_tap — Method
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).
PowerFlows._validate_vset — Method
Voltage-setpoint plausibility gate shared by all voltage-controlling devices.
PowerFlows.build_controlled_device_set — Method
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.
PowerFlows.get_controlled_device_results — Method
get_controlled_device_results(data) -> DataFrames.DataFrameSolved 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.
Linear Algebra Backends
Robust Homotopy
PowerFlows.FixedStructureCHOLMOD — Type
In order to in-place modify the numeric values of a CHOLMOD matrix, we need to write our own wrapper around CHOLMOD.Sparse.
PowerFlows.set_values! — Method
set_values!(mat::FixedStructureCHOLMOD, new_vals::AbstractVector{Float64})In-place update of the numeric values in the CHOLMOD matrix.
Newton-Raphson
PowerFlows.PFLinearSolverCache — Type
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.
PowerFlows.PardisoLinSolveCache — Type
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.
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!).
PowerFlows.make_linear_solver_cache — Method
Construct (without factorizing) the cache for backend tag over matrix A.
PowerFlows.resolve_linear_solver_backend — Method
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).
PowerFlows.solve_w_refinement — Method
Adapter: PowerFlows historically calls solve_w_refinement(cache, A, b, eps) with a step-tolerance eps. Map onto PNM's residual-based refined solve.
PowerFlows.tsolve! — Method
Transpose solve Aᵀ x = b in place. KLU-only (AppleAccelerate has no transpose solve).
Solver Diagnostics
PowerFlows.SchurInverseOperator — Type
Applies S⁻¹ via a back-solve of the full J: pads v with zeros in the LCC-tail slots, applies J⁻¹, returns the leading n_bus block.
PowerFlows.SolverDiagnosticsState — Type
Per-solve scratch for run_solver_diagnostics!: previous ‖F‖∞ (prev_F), last-seen sign of real(λ_min) (eig_sign), and a reusable padded RHS (buffer) so the Schur operator allocates nothing per iteration.
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.
PowerFlows._describe_lcc_residual_entry — Method
Describe a residual entry that falls in the LCC tail (4 rows per LCC).
PowerFlows._diag_bus_number — Method
The system bus number for the bus_ix-th bus (reduced ordering).
PowerFlows._diag_condest — Method
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.
PowerFlows._fmt_eig — Method
Format a (possibly complex) eigenvalue to 4 significant figures as a or a ± b im.
PowerFlows._locate_variable_block — Method
(bus index, 1-based row within that bus's block) for variable-block formulations, from the bus_state_offset table.
PowerFlows._schur_min_eigenvalue — Method
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.
PowerFlows._sf4 — Method
Round to 4 significant figures (one more digit than siground's 3).
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.
PowerFlows.setup_solver_diagnostics — Method
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.
Misc.
PSSE Export
PowerFlows._build_generator_list — Method
Build the full generator list including optional sources, storages, condensers, and HVDC synthetics.
PowerFlows._build_switched_shunt_steps_v33 — Method
Build v33 switched shunt step data (N, B pairs padded to 8).
PowerFlows._build_switched_shunt_steps_v35 — Method
Build v35 switched shunt step data (S, N, B triplets padded to 8).
PowerFlows._build_transformer_metadata! — Method
Build all transformer-related metadata mappings (names, control objectives, winding groups, impedance, taps).
PowerFlows._calculate_3w_transformer_stat — Method
Calculate the STAT field for a 3-winding transformer based on per-winding availability.
PowerFlows._collect_3w_winding_data — Method
Collect winding data for a 3-winding transformer.
PowerFlows._compute_active_power_limits — Method
Compute active power limits considering HVDC scaling.
PowerFlows._compute_dcline_common_fields — Method
Compute common DC line fields (record 1) for Two-Terminal DC export.
PowerFlows._compute_dcline_inverter_fields — Method
Compute inverter-side fields for Two-Terminal DC export.
PowerFlows._compute_dcline_rectifier_fields — Method
Compute rectifier-side fields for Two-Terminal DC export.
PowerFlows._compute_generator_powers — Method
Compute generator active and reactive power considering HVDC scaling.
PowerFlows._compute_reactive_power_limits — Method
Compute reactive power limits considering HVDC scaling.
PowerFlows._compute_vsc_converter_fields — Method
Compute VSC converter fields for one side (from or to) of a VSC DC line.
PowerFlows._first_choice_gen_id — Method
Try to make an informative one or two character name for the load/generator/etc.
- generator-1234-AB -> AB
- 123_CT_7 -> 7
- load1234 -> 34
PowerFlows._fix_3w_transformer_rating — Method
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.
PowerFlows._load_transformer_components_and_mappings — Method
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
PowerFlows._make_gens_from_hvdc — Method
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").PowerFlows._map_psse_container_names — Method
Validate that the Sienna area/zone names parse as PSS/E-compatible area/zone numbers, output a mapping
PowerFlows._psse_bus_names — Method
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.
PowerFlows._psse_bus_numbers — Method
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.
PowerFlows._psse_transformer_names — Method
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.
PowerFlows._to_float — Method
Parse a value to Int64, handling strings, floats, and PSSEDEFAULT. Returns PSSEDEFAULT for non-whole numbers or invalid values.
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.
PowerFlows._write_2w_transformer_record1! — Method
Write the first record line for a 2-winding transformer.
PowerFlows._write_2w_transformer_record2! — Method
Write the second record line (impedance data) for a 2-winding transformer.
PowerFlows._write_2w_transformer_record3_winding1! — Method
Write the third record line (winding 1 data) for a 2-winding transformer.
PowerFlows._write_2w_transformer_record4_winding2! — Method
Write the fourth record line (winding 2 data) for a 2-winding transformer.
PowerFlows._write_3w_transformer_record2! — Method
Write the second record line (impedance data) for a 3-winding transformer.
PowerFlows._write_3w_winding_records! — Method
Write winding records for a 3-winding transformer.
PowerFlows._write_discrete_branch_record! — Method
Write a DiscreteControlledACBranch record as a non-transformer branch (v33 path).
PowerFlows._write_generator_v33_record! — Method
Write generator record for PSS/E v33 format.
PowerFlows._write_generator_v35_record! — Method
Write generator record for PSS/E v35 format.
PowerFlows._write_icd_v33_points! — Method
Write impedance correction table points in v33 format (T, F pairs).
PowerFlows._write_icd_v35_points! — Method
Write impedance correction table points in v35 format (T, Re(F), Im(F) triplets).
PowerFlows._write_regular_branch_record! — Method
Write a regular (Line/MonitoredLine) branch record to the buffer.
PowerFlows.better_float_to_buf — Method
Temporary, very specialized proof of concept patch for https://github.com/JuliaLang/julia/issues/55835
PowerFlows.check_supported_version — Method
Throw a NotImplementedError if the psse_version is not supported
PowerFlows.convert_empty — Method
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}]PowerFlows.create_component_ids — Method
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".
PowerFlows.flatten_power_flow_evaluation_model — Method
Expand a single PowerFlowEvaluationModel into its possibly multiple parts for separate evaluation. Namely, if pfem contains a non-nothing exporter, return [pfem, exporter], else return [pfem].
PowerFlows.get_branches_with_numbers — Method
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.
PowerFlows.reset_caches — Method
Force all cached information (serialized metadata, component lists, etc.) to be regenerated
PowerFlows.serialize_component_ids — Method
Take the output of create_component_ids and make it more suitable for JSON serialization
PowerFlows.write_v35_header — Method
Write v35 header comments for a given section if applicable.
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.
PowerFlows._branch_flow_entries — Method
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².
PowerFlows._branch_flow_entries — Method
AC: recompute per-segment flows from solved voltages using _compute_segment_flows.
PowerFlows._calculate_fixed_admittance_powers — Method
Returns a dictionary of bus index to power contribution at that bus from FixedAdmittance components, as a tuple of (active power, reactive power).
PowerFlows._compute_segment_flows — Method
_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).
PowerFlows._distribute_arc_flows — Method
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.
PowerFlows._get_arc_endpoint_voltages — Method
_get_arc_endpoint_voltages(data, arc, time_step)Look up the complex voltages at the two endpoints of an arc from the solved power flow data.
PowerFlows._segment_flow_entry — Method
_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.
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.
PowerFlows._solve_series_interior_voltages — Method
_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.
PowerFlows.get_arc_names — Method
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".
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.
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).
PowerFlows.write_power_flow_solution! — Function
Updates system voltages and powers with power flow results
PowerFlows.write_results — Method
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.
PowerFlows.write_results — Method
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: APowerSystems.Systemobject storing the system information.
Power Systems Utilities
PowerFlows.can_be_PV — Method
Return set of all bus numbers that can be PV: i.e. have an available generator, or certain voltage regulation devices.
PowerFlows.get_active_and_reactive_power_from_generator — Method
Return the active and reactive power generation from a generator component. It's pg=0 as default for synchronous condensers since there's no field in the component for active power.
PowerFlows.get_active_power_limits_for_power_flow — Method
Return the active power limits that should be used in power flow calculations and PSS/E exports. Redirects to PSY.get_active_power_limits in all but special cases.
PowerFlows.get_reactive_power_limits_for_power_flow — Method
Return the reactive power limits that should be used in power flow calculations and PSS/E exports. Redirects to PSY.get_reactive_power_limits in all but special cases.
PowerFlows.must_be_PV — Method
Return set of all bus numbers that must be PV: i.e. have an available generator.
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.
PowerFlows._pq_validate_indices — Method
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).
PowerFlows._pqpv_validate_offsets — Method
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.
PowerFlows._validate_squared_voltage_magnitudes — Method
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.
PowerFlows.my_mul_mt! — Method
In-place A*X → Y where X is a matrix. Pre-allocated Y avoids per-call allocation.
PowerFlows.my_mul_mt — Method
Similar to above: A*X where X is a matrix.
PowerFlows.my_mul_mt — Method
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.
PowerFlows.siground — Method
For pretty printing floats in debugging messages.
PowerFlows.wdot — Method
Weighted dot product of two vectors.
PowerFlows.wnorm — Method
Weighted norm of two vectors.
PowerFlows.FD_LOW_REACTANCE_WARNING — Constant
Warn-once threshold for branch reactance |x| in the fast/fixed-decoupled methods.
PowerFlows.contributes_active_power — Method
Check if a device has attribute 'active_power' for active power consumption or generation.