ACPFlow Runner Reference

Public API

Sparlectra.run_acpflow — Method
run_acpflow(; net=nothing, casefile=nothing, path=nothing, config=nothing, performance_profile=nothing) -> SparlectraRunResult

Compatibility alias for run_sparlectra.

This function uses the same configuration-driven framework workflow as run_sparlectra. It does not support the former keyword-heavy runner API. Solver, import, output, Q-limit, start-mode, and diagnostic behavior must be configured through SparlectraConfig or YAML.

source
Sparlectra.run_sparlectra — Method
run_sparlectra(; net=nothing, casefile=nothing, path=nothing, config=nothing, performance_profile=nothing) -> SparlectraRunResult

Run the configuration-driven Sparlectra framework workflow. Pass exactly one of net or casefile. File-based runs import a MATPOWER case using config.matpower; in-memory runs solve the supplied network directly. Solver, control-loop, and output behavior are taken from one SparlectraConfig.

source
Sparlectra.run_sparlectra_cases — Method
run_sparlectra_cases(; config=nothing, path=nothing, performance_profile=nothing) -> Vector{SparlectraRunResult}

Run configured MATPOWER cases sequentially in deterministic order. A non-empty config.runtime.cases list takes precedence over config.runtime.case. Bare case names are resolved through ensure_casefile, which downloads standard MATPOWER cases on demand. Batch-level performance-profile aggregation is not supported; profile individual run_sparlectra calls instead.

source
Sparlectra.build_qload_pu — Method
build_qload_pu(net) -> Qload_pu::Vector{Float64}

Aggregated reactive load per bus in p.u. (sum of non-generator prosmps qVal / baseMVA).

source
Sparlectra.extract_bus_types_and_vset — Method
extract_bus_types_and_vset(net) -> (bus_types::Vector{Symbol}, Vset::Vector{Float64}, slack_idx::Int)

bus_types uses :Slack/:PV/:PQ, Vset is vm setpoint (PV) or current vm default.

source
Sparlectra.solve_linear — Method
solve_linear(A, b; allow_pinv=true, svd_max_n=DEFAULT_DENSE_FALLBACK_MAX_N)

Solve A*x = b. Sparse matrices are handled by solve_sparse_system and are never converted to dense storage. Dense callers may still use the small-system SVD fallback when explicitly allowed; svd_max_n bounds the system size the SVD fallback accepts. Callers for whom rank deficiency is an EXPECTED state rather than a hard fault (the WLS normal equations of the state estimation, where released extra states can turn out collectively dependent) raise the bound so a singular system degrades to a least-squares step instead of an exception; the power-flow callers keep the small default on purpose.

source
Sparlectra.solve_sparse_system — Method
solve_sparse_system(A::SparseMatrixCSC, b; context=:powerflow, diagnostics=nothing) -> Vector

Solve the sparse linear system A*x = b. The primary path is the standard sparse solve A \ b (UMFPACK LU for a general square matrix), with sparse QR as the fallback for a singular matrix. If QR fails as well, a system of at most DEFAULT_DENSE_FALLBACK_MAX_N (64) rows and columns is solved densely through an SVD pseudo-inverse; a larger one throws LinearAlgebra.SingularException instead of being densified. Any other error is rethrown. When diagnostics is a dictionary, the backend used (:sparse_backslash, :sparse_qr_fallback or :dense_svd_fallback_small_system), context and the matrix dimensions are written into it.

source
Sparlectra.PFModel — Type
PFModel

Solver-agnostic power-flow model extracted from a Net.

Important indexing note:

  • The model uses the same "active-bus ordering" as BusData returned by getBusData(...): sorted by original bus index and excluding isolated buses.
  • Ybus must be consistent with that ordering. We build Ybus using createYBUS(...) which internally compresses indices by removing isolated buses.

Fields:

  • Ybus: bus admittance matrix (n×n), active buses only
  • baseMVA: system base power
  • busIdx_net: original bus indices (length n), increasing
  • busType: :Slack/:PV/:PQ per bus (length n)
  • slack_idx: slack index in PF-ordering (1..n)
  • Vset: voltage magnitude setpoints for PV/Slack buses (length n; dummy 1.0 for PQ)
  • Sspec: specified complex injections in per-unit (length n), P + jQ (net injection)
  • V0: initial complex voltages in per-unit (length n)
  • qmin_pu, qmax_pu: optional PV reactive limits in per-unit (length n, may be empty)
source
Sparlectra.PFSolution — Type
PFSolution

Common result object returned by any external solver.

Fields:

  • V: final complex bus voltages in PF ordering (length n)
  • converged: true if solver reached tolerance
  • iters: iteration/order count (solver-defined)
  • residual_inf: infinity-norm of canonical mismatch (if available)
  • meta: optional solver-specific payload (NamedTuple/Dict/etc.)
source
Sparlectra.applyPfSolution! — Method
applyPfSolution!(net, model, sol; write_pq_results=true, verbose=0)

Write the external solution back into net:

  • updates node Vm/Va on all active buses
  • optionally writes Slack P/Q and PV Q generation (solved injection plus the bus load, same policy as the rectangular solver)

Notes:

  • Isolated buses (not in model) are left untouched.
  • sol.V must be PF-ordered (length n == length(model.busIdx_net)).
source
Sparlectra.apslf_solver — Method
apslf_solver(; order::Int=24, nr_polish::Bool=false, mode::Symbol=:direct, convergence_radius::Bool=true) -> AbstractExternalSolver

Reachability point for the AnalyticLoadFlow.jl-backed external solver (ApslfSolver), an analytic power-series (holomorphic-embedding-style) load-flow method.

AnalyticLoadFlow.jl is a required dependency of Sparlectra, so the solver is always available: using Sparlectra is enough, and the result goes straight to solvePf or runpf_external!.

Keyword Arguments

  • order::Int = 24: highest power-series coefficient to compute.
  • nr_polish::Bool = false: run a Newton-Raphson polishing step on the series result.
  • mode::Symbol = :direct: :direct (native PV handling) or :outer (PQ-only series plus an outer secant loop for PV enforcement).
  • convergence_radius::Bool = true: evaluate and report the Padé-pole margin (the APSLF convergence radius).
source
Sparlectra.buildPfModel — Method
buildPfModel(net; opt_sparse=true, flatstart=net.flatstart, include_limits=true, verbose=0) -> PFModel

Build a canonical PF model from net:

  • active buses are defined via getBusData(net.nodeVec, net.baseMVA, flatstart; net=net), which excludes isolated buses and sorts by bus index.
  • Ybus is built via createYBUS(net=net, sparse=opt_sparse, ...) and is consistent with the same isolated-bus compression.
  • the voltage setpoint Vset of a slack or PV bus is the setpoint of its regulating generator, with the node voltage and 1.0 pu as fallbacks, the same lookup the rectangular solver uses.

include_limits=true attaches qmin/qmax in per-unit as used by your NR-with-limits code.

source
Sparlectra.mismatchInf — Method
mismatchInf(model, V) -> Float64

Compute ||F(V)||_∞ using Sparlectra's rectangular PQ/PV mismatch definition:

F = mismatch_rectangular(model.Ybus, V, model.Sspec, model.busType, model.Vset, model.slack_idx)

This is the canonical comparison metric for external solvers.

source
Sparlectra.runpf_external! — Method
runpf_external!(net, solver; tol=1e-8, opt_sparse=true, flatstart=net.flatstart, include_limits=false, verbose=0, solver_kwargs...) -> (iters, status, sol)

Convenience wrapper:

  1. build model from net
  2. call external solvePf(solver, model; solver_kwargs...)
  3. compute canonical mismatch infinity norm (unless solver provided it)
  4. apply solution back to net
  5. return (iters, status, sol) where status == 0 indicates convergence

include_limits=false by default: keep Sparlectra "clean" and let external solver decide.

source
Sparlectra.solvePf — Method
solvePf(solver, model; kwargs...) -> PFSolution

External solver hook. Must be implemented by the external solver package.

The returned voltage vector sol.V must be in PF ordering (model.busIdx_net order).

source
Sparlectra.SparlectraRunResult — Type
SparlectraRunResult

Typed result returned by run_sparlectra. The solved network is always available as net, while the remaining fields provide stable framework-level solver, validation, control-loop, timing, and rectangular diagnostic metadata.

source

Internals

Sparlectra._run_apslf_powerflow! — Method
_run_apslf_powerflow!(net, pf_cfg; verbose=0, performance_profile=nothing) -> (iterations::Int, erg::Int)

Solve net with the AnalyticLoadFlow.jl-backed APSLF solver (power_flow.solver = :apslf) instead of the internal rectangular Newton-Raphson path. Mirrors the internal path's parallel-link merge (_merged_pf_net) and per-island handling (detect_ac_islands, _prepare_island_net, _sync_island_solution!): one PFModel is built and solved per active AC island via runpf_external!. Writes a rectangular_pf_status-compatible status onto net so result building, reporting, logs, and the generic AC island diagnostics writer treat this run on the same contracts as the NR route.

power_flow.qlimits.ignore_q_limits is honored (Q-limits are passed to the solver unless explicitly disabled); all other rectangular-only start/damping/ Q-limit-switching options do not apply and are ignored, since APSLF always starts from its own canonical analytic germ and performs its own internal PV/Q-limit handling.

Callers must reject active controllers before calling this function; it does not check for them itself. That covers the outer-loop tap/PST controllers and the voltage-dependent Q(U)/P(U) controllers, which are not outer-loop: they act inside the rectangular Newton step and have no counterpart here.

source
Sparlectra._apply_auto_pf_options — Method
_apply_auto_pf_options(pf, options, user_set_keys) -> (pf2, applied, conflicts)

Apply the decision options onto a PowerFlowConfig copy. Keys the user set explicitly (dotted keys in user_set_keys) are NEVER overwritten; they are returned in conflicts as "key kept by user" entries for the decision log.

source
Sparlectra._execute_auto_sparlectra_powerflow! — Method
_execute_auto_sparlectra_powerflow!(net, cfg; performance_profile) -> execution

Auto-mode drive of the power flow: feature extraction, strategy selection, precedence-safe application, base attempt, and the bounded escalation ladder. The record (features, decision, attempts, hints) is stored on the net (auto_pf_record) for the service layer. Tolerance is never changed by any stage.

source
Sparlectra._write_auto_mode_decision_log — Method
_write_auto_mode_decision_log(path, rec)

Write the human-readable auto-mode decision artifact: feature summary, selected profile with per-rule reasons, applied options, precedence conflicts (user key kept), every escalation attempt with its changed keys, solver path, iteration count and Q-limit evidence, and the hint list.

source
Sparlectra.auto_pf_hints — Method
auto_pf_hints(features, evidence, attempts; converged) -> Vector{NamedTuple}

Generate the advisory hint list from the recorded diagnostics: each entry is (id = :stable_key, text = "..."). Purely derived from existing diagnostics; hints never mutate configuration or behavior.

source
Sparlectra.auto_pf_record — Method
auto_pf_record(net) -> Union{Nothing,NamedTuple}

The auto-mode decision/escalation record of the most recent auto run on this net (nothing when the run was manual).

source
Sparlectra.collect_auto_pf_features — Method
collect_auto_pf_features(net::Net; min_q_range_pu = 1e-4) -> AutoPfFeatures

Extract the auto-mode decision features from an imported network. Pure read-only and format independent: format specifics end at import, this works the same on MATPOWER, CGMES, and DTF nets. min_q_range_pu is the narrow-range threshold the Q-limit guard uses (power_flow.qlimits.guard_min_q_range_pu).

source
Sparlectra.select_auto_pf_strategy — Method
select_auto_pf_strategy(features::AutoPfFeatures) -> AutoPfDecision

Select the auto-mode profile and option set for a network: an ordered rule list picks the profile (first match wins), then profile-independent feature gates add islands handling, Q-limit strategy, and plausibility checks. Thresholds live in AUTO_PF_THRESHOLDS.

source
Sparlectra._cgmes_start_values_powerflow — Method
_cgmes_start_values_powerflow(pf_cfg, start_values) -> (PowerFlowConfig, overridden::Vector{String})

Apply cgmes_import.start_values to the power-flow configuration of one CGMES run. :flat forces a synthetic flat start; :sv keeps the imported SvVoltage state and force-disables every competing start-value machine — the same set the fixed-reference self-check forces off in _self_check_forced_overrides (runselfcheck.jl); keep the two lists aligned. Returns the adjusted config plus the effective config keys that were overridden (for the decision line in run.log/cgmes.log). MATPOWER/DTF runs never call this.

source
Sparlectra._flatstart_profile_config — Method
_flatstart_profile_config(cfg) -> (SparlectraConfig, overridden::Vector{String})

The flat start chooses the voltage PROFILE a run starts from and nothing else (#463): with power_flow.flatstart = true every bus starts at 1.0 pu (PV and slack buses at their setpoints) and 0 degrees instead of the imported voltages, and every start machine follows its own key and works from that flat profile: the start projection with its DC, blend and ratio-profile candidates (start_mode.start_projection), the unconditional DC seed (start_mode.dc_seed_unconditional), the current-iteration pre-solve (start_current_iteration.enabled) and the APSLF start (apslf_start.enabled). Before #463 the flat start switched all of them off, so "projection from a flat start" could not be configured as written.

What the flat start still overrides are the two start MODES, because they choose a profile as well: voltage_mode and the imported-angle angle_modes read the stored columns (the MATPOWER import applies them only under a flat start and would turn it into a blended imported start), and angle_mode = dc makes the DC angles a requested start that excludes the measured candidates. Both go classic for this run; the DC angles stay available as the projection's measured DC candidate (try_dc_start). The stored configuration is left as it is (the Web UI greys the two mode controls while the flat start is on); the returned list names every overridden key for the run log.

source
Sparlectra._net_cache_load — Method
_net_cache_load(path, components) -> Union{Nothing,SCFCase}

Returns the cached CONVERTED case (stored as its canonical SCF JSON) or nothing. Beyond the key in the file name, the stored component list must match exactly, and the JSON goes through the reader's parse and conversion, so a stale or truncated artifact silently misses instead of producing a wrong case.

source
Sparlectra.reduce_susceptance_to_nonslack — Method
reduce_susceptance_to_nonslack(Bsrc, non_slack, pos, slack_idx, nred; value_of=imag) -> B_reduced

Eliminate the slack row/column from a full n×n susceptance-like source matrix and return the (n-1)×(n-1) reduced system used by any DC-angle linear solve (_solve_dc_angle_system). value_of extracts the real susceptance entry from Bsrc[i,j]: imag for a complex Ybus (the rectangular-solver DC-angle start-value heuristic, which reduces the full AC admittance matrix), identity for an already-real B′ (a true DC power-flow matrix, series reactance only). Sparse Bsrc in gives a sparse result; dense in gives dense out. Shared between rundcpf!'s B′ reduction and the rectangular solver's internal DC-angle start projection so the two call sites never diverge into two slack-elimination implementations.

source
Sparlectra.showPfModel — Method
showPfModel(model; io=stdout, verbose=false)

Print a compact human-readable summary of the PFModel. This is intentionally separate from Base.show(model) to avoid global display side effects.

source
Sparlectra._apply_start_modes! — Method
_apply_start_modes!(net, case, start_cfg; performance_profile) -> Nothing

Apply the configured start voltage and angle modes with the RAW source start values of case.sparlectra.start_state as the reference profile. PV and slack classification and the resolved voltage setpoints come from the built net itself: the adapter resolved the source system's setpoint choice at conversion time, so the historical distinction between the raw generator setpoint and the imported setpoint collapses onto the value the machines actually regulate to.

source
Sparlectra._matpower_raw_starts — Method
_matpower_raw_starts(mpc) -> Vector

The raw per-bus start voltages of a parsed MATPOWER case, index-aligned with the direct import's node order (which is the bus row order).

source