Format Adapters Reference

Public API

Sparlectra.FormatAdapterType
FormatAdapter

Abstract supertype of the format adapters. The model, corrected by taskimportdirect (2026-09-04, superseding the D2/D3 pivot design): an adapter owns BOTH output forms of its format. Its IMPORTER builds the network directly and hands it to the solver, with no intermediate format, no conversion, no loss; its CONVERTER turns the format into the typed SCFCase and runs ONLY when someone asks for that file (export to SCF, the Case page export action, the shipped-case builders, or the scenario engine's id index). SCF is the preferred working format but never a mandatory way station: no import path converts.

The contract per concrete adapter:

  • detect(::Type{A}, path)::Bool: content-based detection reading at most the first 4 KiB of the file.
  • options_type(::A)::Type: the adapter's option struct.
  • import_net(::A, source, opts)::Net: the importer, used by import_case.
  • convert_case(::A, source, opts)::SCFCase: the converter, explicit requests only.
  • export_case(::A, net, path; opts): optional, the reverse direction.
source
Sparlectra.runShortCircuit!Method
runShortCircuit!(result::CGMESImporter.CGMESImportResult; kwargs...) -> ShortCircuitResult

Convenience overload: run the balanced IEC 60909-0 short-circuit sweep directly on a CGMES import result (net plus harvested short-circuit data). See the core runShortCircuit! methods for the keyword surface.

source
Sparlectra.CGMESAdapterOptionsType
CGMESAdapterOptions

The adapter-scope options of the CGMES conversion (design decision D4): the cgmes_import configuration surface plus the run kind the start-value decision may depend on.

source
Sparlectra.cgmes_adapter_optionsMethod
cgmes_adapter_options(cfg::SparlectraConfig; run_kind, name) -> CGMESAdapterOptions

The adapter options an effective run configuration implies.

source
Sparlectra.cgmes_enrich_case!Method
cgmes_enrich_case!(case, net) -> SCFCase

Attach the CGMES source identity of net to its typed case: the full structural-key mRID registry as meta["cgmes_ids"], and the mRID of every component whose extra record already resolved one under the cgmes key of that record (adapter task stage 3c surface).

source
Sparlectra.DTFAdapterOptionsType
DTFAdapterOptions

The adapter-scope options of the DTF conversion (design decision D4): parser strictness and base power, the transformer ratio convention, the legacy voltage-level collapse, the model settings consumed while the case is interpreted, and the outage selection (a DTF adapter option per review point 2 of the adapter task).

source
Sparlectra.dtf_adapter_optionsMethod
dtf_adapter_options(cfg::SparlectraConfig) -> DTFAdapterOptions

The adapter options an effective run configuration implies. The DTF conventions themselves (transformer_ratio_mode, the legacy collapse) have no configuration keys yet (adapter task stage 3b inventory, open in issue #1 point 3), so they stay at the importer defaults here.

source
Sparlectra.MatpowerAdapterOptionsType
MatpowerAdapterOptions

The adapter-scope options of the MATPOWER conversion (design decision D4): the import conventions plus the model settings that are consumed WHILE the case is interpreted (the tap-changer impedance correction rewrites R/X at conversion time). Field names follow the configuration keys.

source
Sparlectra.matpower_adapter_optionsMethod
matpower_adapter_options(cfg::SparlectraConfig) -> MatpowerAdapterOptions

The adapter options an effective run configuration implies; the run path builds them here so the conversion and the historical direct import read the same keys.

source
Sparlectra.PGMAdapterOptionsType
PGMAdapterOptions

The power-grid-model conversion takes no options: the dataset is already in the case format's own vocabulary. The struct exists for the adapter contract.

source
Sparlectra.createNetFromDTFFileMethod
createNetFromDTFFile(path; baseMVA = 100.0, strict = true, bus_shunt_model = :admittance, transformer_ratio_mode = :neutral_one) -> Net

Read a legacy DTF file and build a Sparlectra Net without routing through MATPOWER. Outage cards are parsed and preserved in DTFCase by DTFImporter.read_dtf, but are not executed by this Task-1 importer MVP.

source
Sparlectra.CGMESImporter.importCGMESMethod
importCGMES(config; path, name) -> CGMESImportResult

Import a CGMES delivery with everything the configuration says about it, in one place: the thirteen cgmes_import values and the bus shunt model (the net-parameter stamping lives with the import dispatch since taskimportdirect: once per importer). The four service call sites used to unpack the same values by hand, and a new option had to be added in four places or it silently kept its default at three of them (private issue #2; the review found the accompanying stamp in the wrong function once already). The keyword form of importCGMES stays for programmatic use.

source
Sparlectra.writeMatpowerCasefileMethod
writeMatpowerCasefile(net::Net, pathfilename::String; write_solution::Union{Nothing,Bool} = nothing)

Write Matpower case files.

Arguments

  • net::Net: Network object.
  • pathfilename::String: Path and filename to write the Matpower case file.
  • write_solution::Union{Nothing,Bool}: Whether to write the solved AC power-flow state back into the export: mpc.bus VM/VA reflect the solved node state, and mpc.branch gains the MATPOWER result columns 14–17 (PF, QF, PT, QT) sourced from the existing branch-flow report path (no flow recomputation in the exporter). nothing (default) reads matpower_export.write_solution from the active configuration (default true, see MatpowerExportConfig). When true but the network has no solved branch flows, the exporter warns and falls back to the historical 13-column model-only mpc.branch export instead of writing empty result columns. When false, the export is a pure model file: mpc.branch keeps 13 columns and VM = 1.0/VA = 0.0 for all non-slack/non-PV buses (slack and PV setpoints are preserved).

Example

net = Net(...)
writeMatpowerCasefile(net, "casefile.m")
source
Sparlectra.run_matpower_caseMethod
run_matpower_case(; casefile::AbstractString = "", config_file::AbstractString = "")

Run MATPOWER import and power-flow with central typed configuration plus runner-level operational output and logging.

source
Sparlectra.SCFCaseType
SCFCase

One SCF document in memory (design decision D1): the PGM root scalars, the typed data section, and the namespaced sparlectra block (nothing for a strict-PGM file, which carries none). File reading (read_scf_json) and writing (write_scf_json) are serialization of this struct; build_net is the one network constructor over it.

source
Sparlectra.read_scf_jsonMethod
read_scf_json(path) -> SCFCase

Read one SCF case file into its typed in-memory form. Validation is the reader's staged file-level check (schema, study definitions, reference integrity) on the parsed document, so a broken file fails here with the same line of reasoning the upload path shows; the model plausibility stage runs when the network is built (build_net).

source
Sparlectra.exportSCFMethod
exportSCF(net; file, kwargs...) -> String

Write net as a Sparlectra Case Format file (.scf.json, issue #342) and return the path. The data section is a valid power-grid-model input dataset in SI units; everything Sparlectra adds (slack roles, tap-changer cascade, names and source ids, measurement detail) lives under the namespaced sparlectra key. Case-scope configuration travels in the case configuration file next to the case (write_case_config), not inside it.

Ids are deterministic (component type, then name), so exporting the same network twice produces byte-identical files and Git diffs stay readable.

Keyword arguments:

  • case_name, source_format, source_reference, notes: meta fields; case_name defaults to the network name.
  • f_nom: nominal frequency in Hz (default 50.0), needed for the line capacitance conversion.
  • intended_calculations: the contract of the file (default ["power_flow"]).
  • measurement_provenance: what is known about the measurement set (noise, generator, seed); it lands in sparlectra.measurements.provenance and is what tells a reader that a set is ideal rather than measured.
  • include_start_state: write the current bus voltages as START values (never as results). Off by default, because a stale start state on an edited net is worse than none.
  • strict_pgm: write ONLY the power-grid-model input dataset, without the namespaced sparlectra block, for a consumer that reads PGM and nothing else. Everything that block carries is then absent from the file; the export names what it dropped in a warning. Off by default.

Throws an ArgumentError when the network carries FACTS-compensated impedances (call restoreBaseImpedances! first).

source
Sparlectra.net_to_scfMethod
net_to_scf(net; kwargs...) -> Dict{String,Any}

Build the SCF root object of net (see exportSCF for the keyword arguments). Pure: the network is not modified.

source
Sparlectra.net_to_scfcaseMethod
net_to_scfcase(net; kwargs...) -> SCFCase

The typed case of net (design decision D1): what exportSCF writes, as the in-memory SCFCase. Takes the same keyword arguments as exportSCF; pure, the network is not modified. The document assembly stays the deterministic dict builder (net_to_scf), converted once at the end, so the typed form and the file bytes cannot diverge.

source
Sparlectra.scf_is_case_config_keyMethod
scf_is_case_config_key(key) -> Bool

Whether a dotted configuration key describes the CASE (its model, import conventions, solver, estimation, and short-circuit math) rather than the installation. Only case-scope keys travel inside a case file; everything else stays in the configuration file. The key must also be GUI-editable, which is the same allowlist every other configuration surface uses.

source
Sparlectra.build_netMethod
build_net(case::SCFCase; config = active_sparlectra_config()) -> Net

The one network constructor of the run path over the typed case (design decisions D2 and D12): construct through the existing public constructors, then apply the run configuration's net parameters exactly once, here. config is the EFFECTIVE run configuration (the run path passes its resolved ImportedCase configuration; interactive use takes the active one).

source
Sparlectra.importSCFMethod
importSCF(file) -> Net

Read a Sparlectra Case Format file (.scf.json, issue #342) and build the network through the existing constructors. Validation is staged: schema (unknown keys and unsupported components are hard errors), reference integrity (every id resolves, ids are unique), then the model checks validate! already performs. Wrapper over read_scf_json and build_net with the active configuration.

source
Sparlectra.scf_case_configMethod
scf_case_config(file) -> Dict{String,Any}

The dotted configuration keys a case file carries in sparlectra.config, ready to be merged as config_overrides (the case file sits below API/CLI overrides and above the YAML file in precedence). Empty when the file carries no configuration.

source
Sparlectra.scf_case_studiesMethod
scf_case_studies(file) -> NamedTuple

The study definitions a case file carries: (contingencies, short_circuit), each an empty dictionary when the file does not define that study. The blocks state WHAT to compute; the result contract of the runs themselves is unchanged.

source
Sparlectra.scf_extra_namesMethod
scf_extra_names(file) -> Dict{Int,String}

The reference name of every component id in a case file, taken from sparlectra.extra. Study blocks address components by id, so a runner that executes a study from the file resolves the ids through this map: the names are exactly the ones the network object uses, which is what makes a case list from the file addressable in the runner.

source
Sparlectra.scf_fault_nodesMethod
scf_fault_nodes(file) -> Vector{Int}

The node ids a case file's data.fault rows point at, in file order. PGM expresses "evaluate the fault here" with a fault component; a short-circuit run uses these buses when the study block does not name its own selection, so a case written in PGM vocabulary is runnable as it stands.

source
Sparlectra.scf_to_netMethod
scf_to_net(root::AbstractDict) -> Net

Build a Net from a parsed SCF root object. Every element is created through the existing public constructors and the network is validated with validate! at the end, so an SCF case behaves exactly like a case from any other importer. The document is converted to its typed form (SCFCase) first; this wrapper keeps the historical dict entry point and applies NO configuration (callers that want the run-path behavior use build_net).

source
Sparlectra.scf_validate_datasetMethod
scf_validate_dataset(root) -> Nothing

Run the file-level validation of a parsed case file: schema, study definitions, reference integrity. Throws ArgumentError with the offending key or id, and returns nothing when the document is a usable case file.

This is the check without building a network, which is what an upload path needs: an arbitrary JSON must be rejected BEFORE it is stored, and the user should see the reader's own message rather than a generic refusal.

source
Sparlectra.CGMESImporterModule
CGMESImporter

Lean CGMES 2.4.15 / 3.0 import layer. Stage 0 provides reading and diagnostics (loadCGMES, summarizeCGMES); Net mapping follows in later stages.

source
Sparlectra.CGMESImporter.CGMESFileType

One XML payload from a CGMES delivery: name is the entry path inside its source container (or the file path for plain folders), content the raw XML. Stored as String (not Vector{UInt8}) on purpose: the payload is parsed more than once (header pass + full pass), and String(bytes) would steal the byte buffer on first use.

source
Sparlectra.CGMESImporter.collectCGMESFilesMethod
collectCGMESFiles(path) -> Vector{CGMESFile}
collectCGMESFiles(paths::AbstractVector) -> Vector{CGMESFile}

Collect all XML payloads from a CGMES delivery. Accepts a folder (searched recursively), a .zip (nested ZIPs are opened in-memory, up to depth 4), a single .xml, or a vector of any of these (e.g. base case + boundary ZIP).

source
Sparlectra.CGMESImporter.CGMESLineShortCircuitType
CGMESLineShortCircuit

Zero-sequence/short-circuit data for one line, for the EquipmentShortCircuit profile. Physical units (Ohm, Siemens, °C). Only written when supplied — no zero-sequence values are invented from positive-sequence data.

source
Sparlectra.CGMESImporter.cgmesLineShortCircuitDataMethod
cgmesLineShortCircuitData(result::CGMESImportResult) -> Dict{Int,CGMESLineShortCircuit}

Build the sc_line_data input of writeCGMESFiles from the zero-sequence line attributes harvested during a CGMES import, keyed by net.linesAC index. Lines are matched through the structural identity keys recorded on the network, so parallel lines keep their own data. Only lines with a complete zero-sequence pair (r0 and x0) are included — nothing is invented for the rest.

source
Sparlectra.CGMESImporter.writeCGMESFilesMethod
writeCGMESFiles(net; path::AbstractString = pwd(),
                sc_line_data::Dict{Int,CGMESLineShortCircuit} = Dict(),
                sc_source::Union{Nothing,CGMESShortCircuitData} = nothing,
                created::Dates.DateTime = Dates.now(),
                notices::Union{Nothing,Vector{String}} = nothing,
                zip::Bool = false)

Exports a Sparlectra Net as CGMES-2.4.15 profile files: EQ + TP (buses, AC lines, transformers, loads, machines, external network injections, asynchronous machines, shunts), SSH (operating points p/q, slack referencePriority, voltage-regulation targets, shunt sections), and SV (the network's current voltage state with per-terminal SvPowerFlow rows — after a solve: the solution). sc_line_data supplies optional zero-sequence data per line index (order of net.linesAC); sc_source writes the machine/injection/motor short-circuit attributes of a CGMES import harvest back onto the units by mRID. zip = true additionally packs everything into a re-importable <name>_CGMES.zip. created sets the md:Model.scenarioTime/md:Model.created header stamp — pass a fixed value to make the output byte-reproducible.

Object mRIDs come from net.cgmes_ids (structural keys, see cgmes_keys.jl): ids recorded by the CGMES importer are reused, missing ids are minted deterministically (uuid5 over the key) and recorded. Two different keys resolving to the same mRID abort the export before any file is written.

Works for any Net — built programmatically, or imported from CGMES, MATPOWER, or DTF — since the export reads directly from the network model.

Returns a vector of the written file paths.

Transformer phase shifts travel as single-step linear phase tap changers, so the roundtrip preserves them exactly. What the profiles cannot carry yet is reported per unit: static VAr compensators and bus links. Pass a notices vector to collect these lines programmatically; without one they are emitted as warnings. Ratio tap-changer machinery is flattened into the fixed effective ratio.

Every file carries the tool provenance — a Generated by Sparlectra.jl v<version> on <stamp> header comment and a matching md:Model.description — where the stamp is the created timestamp.

source
Sparlectra.CGMESImporter.analyzeCGMESMethod
analyzeCGMES(; path)::String

Load a CGMES delivery (folder, ZIP, XML file, or a vector of those — same forms as importCGMES) without mapping it to a network, print the importFailureAnalysis report, and return it. Use this to find out why a delivery does not import — most commonly which declared boundary dependency is missing — without wading through importer errors.

source
Sparlectra.CGMESImporter.importFailureAnalysisMethod
importFailureAnalysis(store::CGMESStore)::String

Build a multi-line report explaining why a CGMES delivery cannot be imported (or what is incomplete about it):

  1. the supplied model files with profile, CGMES version, and model id;
  2. every md:Model.DependentOn prerequisite declared by the file headers, matched against the supplied model ids — missing prerequisites are the authoritative statement of what the delivery expects but did not get;
  3. a histogram of unresolved object references grouped by class and property;
  4. a verdict in plain language. A delivery whose TopologicalNode.BaseVoltage references stay unresolved depends on an external base-voltage catalog — in real ENTSO-E deliveries that catalog lives in the boundary set (EQ_BD/TP_BD), so importing without the matching boundary cannot work.

The report is purely diagnostic — building it never throws.

source
Sparlectra.CGMESImporter.CGMESImportResultType

Result of importCGMES: the Net, the merged CGMESStore, the bus-branch topology, the harvested short-circuit data, the selected slack bus and the importer's skip/notice messages. branch_side_of_terminal (CGMES Terminal mRID → (branchIdx, :from|:to)) and skipped_equipment (mRIDs that were not mapped) provide the provenance compareWithSV needs for its SvPowerFlow comparison. no_sv_buses lists the created buses whose TopologicalNode has no usable SvVoltage — they carry the importer's 1.0 pu / 0° fallback, which weakens any comparison against the delivery's SV state (fixed-reference self-check, compareWithSV).

source
Sparlectra.CGMESImporter.CGMESShortCircuitDataType

Typed short-circuit source data harvested during import. Each entry carries the CIM mRID, the object name and — where resolvable — the Sparlectra bus name. Values stay in CGMES units (Ω, S, A, pu on machine base); nothing is evaluated in Stage 1.

source
Sparlectra.CGMESImporter.importCGMESMethod
importCGMES(; path, baseMVA=100.0, require_boundary=true, name=nothing) -> CGMESImportResult

Import a CGMES delivery (EQ+SSH+TP, plus boundary set) into a Sparlectra Net (Stage 1: bus-branch topology from the TP profile, fixed SSH tap positions). Short-circuit source data is harvested into the result's shortcircuit container (read, not evaluated). Start voltages are taken from the SV profile where present.

With tap_control = true the SSH tap positions are the start point and the CGMES-defined tap changers become outer-loop controllers. With machine_control = true a machine whose voltage RegulatingControl points at a different bus becomes a PQ injection with an outer-loop MachineVoltageControl regulating that remote bus (instead of being held PV at its own bus); plans whose target bus is already voltage-held, isolated, or claimed by another machine fall back to the held-PV behavior with a notice in result.messages.

source
Sparlectra.CGMESImporter.CIMObjectType

One CIM instance as a property bag. attrs holds literal values and enum fragments, refs holds mRID targets of rdf:resource="#…" references. Keys are the property local names without their class prefix (ACLineSegment.r:r, IdentifiedObject.name:name); when two different property names share a suffix inside one object, the full dotted name is kept as an additional key.

source is the name of the file whose rdf:ID created the object (overlays via rdf:about do not change it). In a multi-area delivery this is the only way to tell which area contributed a piece of equipment — the sides of an assembled border are otherwise indistinguishable.

source
Sparlectra.CGMESImporter.compareWithSVMethod
compareWithSV(result::CGMESImportResult) -> NamedTuple

Compare the solved state of result.net (after runpf!) with the SV profile of the imported data set — the numeric acceptance oracle of the importer.

Voltages: per-bus Δvm/Δva vs SvVoltage (max/RMS + rows). Angles are only defined up to one constant per island — an IGM cut out of the continental CGM keeps the CGM's global angle reference while the local solve pins its own slack, which shows up as a uniform offset of tens of degrees that says nothing about the state. The comparison therefore removes the median angle offset PER ISLAND and judges the aligned deltas (dva_aligned, feeding max_dva/rms_dva); the raw dva stays in the rows. va_ref_offset_deg reports the offset of the largest island, the one that describes the delivery against the CGM reference. Aligning every island with the main island's offset would measure the island reference instead of the state.

The alignment removes REFERENCE differences, never state differences. A large dva_aligned on a bus inside the main island is therefore a real disagreement with the SV profile and has to be explained from the model, not from the reference: on the FullGrid test configuration the largest angle deltas sit at the HVDC converter buses, whose SSH data declare 150 MW drawn at one end and 0 MW injected at the other while cgmes_import.hvdc_mode = injections maps the two ends as independent fixed injections without DC coupling.

Flows (.flows): per-terminal comparison vs SvPowerFlow in the CGMES sign convention (power flowing into the equipment):

  • :branch_from/:branch_to — line/transformer terminals, model flow computed from the solved voltages (real exchanges carry these; the ENTSO-E conformity sets only ship injection terminals),
  • :shuntLinearShuntCompensator at the solved bus voltage,
  • :load — SSH load values (data-consistency check),
  • :units — machines/ENIs/EquivalentInjections aggregated per bus against the solved bus balance (covers PV and slack units).

Terminals of skipped equipment are excluded.

source
Sparlectra.CGMESImporter.shortCircuitCoverageMethod
shortCircuitCoverage(sc::CGMESShortCircuitData) -> Vector{NamedTuple}

Per-class completeness of the harvested short-circuit source data: one row per element class with the record count and, per attribute, how many records actually carry a value (attribute => filled/total). Identification fields (mrid, name, bus) are excluded — coverage describes the electrical attributes a future IEC 60909 evaluation (issue #277) would consume.

source
Sparlectra.CGMESImporter.summarizeCGMESMethod
summarizeCGMES(; path) -> CGMESSummary

Read a CGMES delivery (folder, ZIP, or vector of paths — e.g. base case + boundary) and produce a diagnostic summary without building a Net. Works on incomplete data sets; unresolved TopologicalNode/ConnectivityNode references raise the boundary_missing_hint.

source
Sparlectra.CGMESImporter.CGMESStoreType

Merged CGMES data set: all profiles of one delivery in a single object store. boundary holds the mRIDs of objects defined in boundary-profile files (EQBD/TPBD) — needed to recognize X-nodes in assembled models.

source
Sparlectra.CGMESImporter.loadCGMESMethod
loadCGMES(path; profile_filter=IMPORT_PROFILE_TAGS) -> CGMESStore

Load a CGMES delivery (folder / ZIP / vector of paths, see collectCGMESFiles) into a merged store. EQ is read before the overlay profiles so that rdf:about updates hit existing objects; DifferenceModel files and out-of-filter profiles are recorded as skipped.

source
Sparlectra.CGMESImporter.refsAllMethod
refsAll(store, obj, name) -> Vector{String}

Every target mRID of the (possibly multi-valued) reference name on obj, in document order. obj.refs[name] keeps only the first value — repeated properties (TopologicalIsland.TopologicalNodes, md:Model.DependentOn) overflow into store.multirefs. Returns an empty vector when the reference is absent.

source
Sparlectra.CGMESImporter.CGMES_TESTSET_ALIASESConstant

Known test-set aliases for fetchCGMESTestSet (and the Web UI cgmes: case entry): alias → subdirectories of the extracted package that form the delivery (base case plus boundary set where one exists).

source
Sparlectra.CGMESImporter.RELICAPGRID_ALIASESConstant

ReliCapGrid aliases: alias → (model folder, grid file names, boundary file names). The models are CGMES 3.0; their boundary set is published per border, so a model may need more than one boundary file.

source
Sparlectra.CGMESImporter.RELICAPGRID_COMBINEDConstant

Combined ReliCapGrid deliveries: alias → member aliases of RELICAPGRID_ALIASES, fetched and packed into ONE delivery.

A single ReliCapGrid model is one area of a multi-area system. Imported alone, the nodes on its borders hang free — there is nothing behind them — so the power flow has no chance of producing a meaningful result no matter how good the solver is. Combining the areas across a shared boundary file closes those borders.

The family has exactly six borders:

Svedala — Espheim — Portheim
   |
Belgovia — Galia — Britheim
              |
           Nordheim

relicapgrid_cgm therefore takes all seven models and is the only fully closed combination. svedala_neighbours is the cheap variant that closes Svedala's own two borders but leaves Espheim—Portheim and Belgovia—Galia open.

(Jotunheim exists in the repository but ships only TP and SV — no EQ/SSH and no border — so it cannot be imported and is not offered.)

source
Sparlectra.CGMESImporter.ensureCGMESTestConfigurationsMethod
ensureCGMESTestConfigurations(; cache = cgmesTestSetCacheDir()) -> String

Make sure the ENTSO-E test-configuration package is downloaded and extracted under cache; returns the extracted directory. Downloads once (~22 MB); if every URL fails, the error explains where to place the ZIP manually.

source
Sparlectra.CGMESImporter.fetchCGMESTestSetMethod
fetchCGMESTestSet(alias; outdir) -> String

Resolve a test-set alias (see CGMES_TESTSET_ALIASES, e.g. "microgrid_be", "smallgrid", "realgrid") and pack the delivery — base case plus boundary where one exists — into <outdir>/cgmes_<alias>.zip. Returns the ZIP path; the file is reused when it already exists. Downloads and extracts the ENTSO-E package on first use.

source
Sparlectra.CGMESImporter.fetchReliCapGridSetMethod
fetchReliCapGridSet(alias; outdir) -> String

Fetch a ReliCapGrid delivery (CGMES 3.0) — grid profiles plus the boundary files of its borders — from GitHub and pack it into <outdir>/cgmes_<alias>.zip. Downloaded files are cached under the CGMES cache directory, so repeated calls do not hit the network.

alias is either a single model ("svedala") or a combined delivery ("relicapgrid_cgm", see RELICAPGRID_COMBINED); a combined delivery packs all its members plus the shared boundary files into one ZIP.

source
Sparlectra.CGMESImporter.CGMESTopologyType

Bus-branch view of a CGMES delivery (TP profile present).

  • bus_name: TopologicalNode mRID → unique Sparlectra bus name (IdentifiedObject.name, mRID-suffixed only on collision).
  • vn_kV: TopologicalNode mRID → nominal voltage.
  • terminals: ConductingEquipment mRID → its terminals sorted by sequenceNumber (1-based positions).
source
Sparlectra.DTFImporterModule

Importer for the native DTF (FOR001) format: parser, network construction and the outage bookkeeping of that format.

source
Sparlectra.DTFImporter.build_netMethod
build_net(case; bus_shunt_model = :admittance) -> Net

Build a Sparlectra Net from a parsed native DTF case. Branch R/X/G/B are converted with the branch voltage-level index as reference voltage, not with the from-side bus voltage. Outages remain parsed metadata and are not executed by this Task-1 MVP.

tap_changer_model selects the tap-changer model applied to all transformers (model.tap_changer_model in the central configuration; nothing reads the active configuration). :ideal keeps the neutral-position series impedance; :impedance_correction re-refers R/X through the tapped winding via the central calcTapCorrectedRX using the parsed regulating vector 1 + f·e^(jφ).

source
Sparlectra.DTFImporter.read_dtfMethod
read_dtf(path; baseMVA = 100.0, strict = true) -> DTFCase

Read a legacy DTF fixed-column input file into a typed DTFCase. This MVP parses outage cards into DTFOutage records but intentionally does not execute outage simulations.

source
Sparlectra.MatpowerIO.build_ybus_matpowerMethod
build_ybus_matpower(bus, branch, baseMVA) -> SparseMatrixCSC{ComplexF64,Int}

MATPOWER-style Ybus stamping (π-model + tap/shift + bus shunts):

  • series r/x
  • line charging b split as b/2 on each end
  • off-nominal tap ratio and phase shift on from-side
  • bus shunts GS/BS added on diagonal: (GS + j*BS)/baseMVA

Optional matpower_shift_sign and matpower_shift_unit convert branch SHIFT before stamping. matpower_ratio controls whether branch TAP is used as stored ("normal", default) or inverted first ("reciprocal"). Defaults preserve MATPOWER degrees/from-side semantics.

source
Sparlectra.MatpowerIO.read_caseMethod
read_case(path::AbstractString; legacy_compat::Bool=true) -> MatpowerCase

Dispatches based on file extension:

  • .m => read_case_m
  • .jl => read_case_julia (expects file returns MatpowerCase or NamedTuple)
source
Sparlectra.MatpowerIO.read_case_juliaMethod
read_case_julia(path::AbstractString; legacy_compat::Bool=true) -> MatpowerCase

The .jl file should either: (A) return a MatpowerCase, OR (B) return a NamedTuple with fields: baseMVA, bus, gen, branch and optional gencost, bus_name, name.

source
Sparlectra.MatpowerIO.read_case_mMethod
read_case_m(path::AbstractString; legacy_compat::Bool=true) -> MatpowerCase

Best-effort parser for typical MATPOWER case files (*.m). Parses:

  • mpc.baseMVA
  • mpc.bus
  • mpc.gen
  • mpc.branch
  • optional: mpc.gencost
  • optional: mpc.bus_name
source
Sparlectra.MatpowerIO.vmva_power_mismatch_statsMethod
vmva_power_mismatch_stats(mpc::MatpowerCase) -> NamedTuple

Checks whether mpc.bus[:, 8:9] (VM/VA) are internally consistent with MATPOWER power balance equations for this case data.

Important PF semantics:

  • Active-power equation is enforced for PQ/PV buses (not slack).
  • Reactive-power equation is enforced for PQ buses only.

Returns maxima of residuals in p.u. and MW/MVar for those enforced equation sets, plus equation counts.

source
Sparlectra.FetchMatpowerCaseModule

Utilities for downloading MATPOWER-compatible case files on demand.

Note:

  • Downloaded files are stored locally and are not part of the Sparlectra source distribution.
  • Users are responsible for complying with the license terms of the respective upstream sources.
source
Sparlectra.FetchMatpowerCase.emit_julia_caseMethod
emit_julia_case(mfile, outdir; legacy_compat=true, overwrite=false) -> jlfile::String

Parses a MATPOWER .m case and writes a Julia NamedTuple (.jl) compatible with MatpowerIO.readcasejulia().

source
Sparlectra.FetchMatpowerCase.ensure_casefileMethod
ensure_casefile(casefile; outdir=nothing, overwrite=false, to_jl=true) -> String

Ensure a MATPOWER-compatible case file exists locally.

  • If casefile is an existing path, it is returned unchanged.
  • If casefile is a bare filename (e.g. case14.m), it is downloaded into outdir.
  • If casefile ends with .jl and is missing, the corresponding .m is downloaded and .jl is generated.

Returns the local path to the requested case file.

source
Sparlectra.FetchMatpowerCase.ensure_matpower_caseMethod
ensure_matpower_case(; url, outdir, to_jl=true, overwrite=false, legacy_compat=true, verbose=true)
    -> (mfile::String, jlfile::Union{Nothing,String})

Ensures the MATPOWER .m file exists in outdir by downloading it if missing. Optionally emits a Julia NamedTuple case (.jl).

This is intended to be called from examples and other code.

source
Sparlectra.FetchMatpowerCase.fetch_matpower_caseMethod
fetch_matpower_case(url, outdir; overwrite=false) -> mfile::String

Downloads a MATPOWER *.m file from url into outdir (unless already present). Returns the local path to the downloaded file.

Transient failures (raw.githubusercontent.com rate limits hit CI runners regularly) are retried three times with a short backoff before giving up.

source
Sparlectra.FetchMatpowerCase.large_cases_dirMethod
large_cases_dir() -> String

The shared directory for large MATPOWER and DTF cases, resolved in two steps:

  1. SPARLECTRA_LARGE_CASES_DIR, if set (override for CI and special setups)
  2. otherwise the Web UI user case directory (~/.local/state/sparlectra/webui/data/mpower on Linux, %LOCALAPPDATA%\Sparlectra\WebUI\data\mpower on Windows)

ensure_casefile downloads here, the Web UI keeps its imported cases here, and the test suite reads large cases from here, so a case fetched once is available to all three and one variable moves the location for all of them.

This function only resolves a path. It does not write, and it does not create the directory; callers that need it to exist say so themselves.

It is deliberately not the checkout. Downloading used to write into <repo>/data/mpower, where the test suite gates several legs on files being present: having used the package decided how many assertions the suite ran, 7180 against 7121 on a fresh tree, and nothing said so.

source

Internals

Sparlectra.import_netMethod
import_net(::CGMESAdapter, path::AbstractString, opts::CGMESAdapterOptions; config = active_sparlectra_config()) -> Net

The CGMES importer of the adapter contract (taskimportdirect): the delivery builds natively through importCGMES. The method maps the adapter options that the importer consumes; the SV start-value decision and the run-kind gating live in the config-rich service layer (importcgmes carries the thirteen cgmes_import values), which stays the path the services use.

source
Sparlectra.import_netMethod
import_net(::DTFAdapter, case, opts::DTFAdapterOptions) -> Net

The DTF importer of the adapter contract (taskimportdirect): builds the network DIRECTLY through DTFImporter.build_net; the adapter options carry every model knob the build takes.

source
Sparlectra.import_netMethod
import_net(::MatpowerAdapter, mpc, opts::MatpowerAdapterOptions; kwargs...) -> Net

The MATPOWER importer of the adapter contract (taskimportdirect): builds the network DIRECTLY from the parsed case; createNetFromMatPowerCase is its implementation and keeps its exported name and signature. The opts cover the adapter scope; run-scope knobs (bus shunt model, flatstart, cooldown, preallocation) ride through as keywords exactly as the import dispatch passes them.

source
Sparlectra.detectMethod
detect(::Type{PGMAdapter}, path) -> Bool

A .json file with the PGM dataset markers in its first 4 KiB. An SCF case matches too, because the canonical writer sorts the namespaced block to the end of the file, beyond any bounded probe: the registry resolves that tie by probing SCF FIRST (D3, SCF detection keeps precedence), and both formats run the same parse and build pipeline, so the tie costs correctness nothing; the format label is refined at parse time by the presence of the sparlectra key.

source
Sparlectra.import_netMethod
import_net(::PGMAdapter, path::AbstractString, opts::PGMAdapterOptions; config = active_sparlectra_config()) -> Net

The PGM importer of the adapter contract (taskimportdirect): a plain power-grid-model dataset reads through the shared SCF reader (the SCF data section IS a PGM dataset) and builds directly through build_net.

source
Sparlectra.ImportedCaseType
ImportedCase

What one case import hands to a service run:

  • net: the constructed network, configuration parameters stamped.
  • config: the effective run configuration AFTER the import. It can differ from the general configuration that went in: the MATPOWER path may apply an auto profile and a projected start, the CGMES path resolves cgmes_import.start_values against the delivery it actually read.
  • format: the detected (or requested) case format.
  • provenance: source path, per-format import records (the CGMES import result with its short-circuit data and SV bookkeeping, the parsed DTF case, the auto-profile decision), for the artifacts a service writes.
  • studies: the study definitions a case file carries (contingencies, short_circuit); empty for every foreign format.
  • overrides: reserved for auto-profile recommendations as override level (design decision D11); empty in stage 0, where the MATPOWER context still rewrites the run configuration itself.
source
Sparlectra._import_cgmesMethod
_import_cgmes(path, cfg; name, phase_callback) -> NamedTuple

The one CGMES import of the run path: delivery-path resolution, the configured import, and the cgmes_import.start_values decision, which belongs to the import because auto can only resolve against the delivery that was actually read (does it carry a usable SvVoltage state or not). Returns the import result, the run configuration with the start decision applied, and the records the service artifacts need. Import errors propagate; the caller owns the failure reporting (the power-flow service writes a diagnostic cgmes.log from what can still be read).

source
Sparlectra.import_caseMethod
import_case(path, general_config; requested_format, name, performance_profile, phase_callback) -> ImportedCase

Import a case of any format for a service run. Detection follows _detect_case_format unless requested_format names the format explicitly. Construction goes through the same per-format paths the power-flow service used, so every service gets the identical network for the identical file: the shared context for MATPOWER and the case format (auto profile, net cache, projected start, configuration stamping), the configured CGMES import with the start-values decision, and the DTF build with its DC-line rejection.

Format policy stays with the caller: a service that does not accept a format checks ImportedCase.format and words its own refusal, because the wording of those refusals is part of each service's contract.

source
Sparlectra._apply_matpower_reference_override!Method
createNetFromMatPowerCase(; mpc, log=false, flatstart=false) -> Net

Builds a Sparlectra Net from a MATPOWER-like container mpc.

mpc can be either:

  • a NamedTuple with fields name, baseMVA, bus, gen, branch (optionally gencost, bus_name)
  • or a struct with the same field names (e.g. MatpowerCase)

All matrices are expected in MATPOWER v2 column conventions.

bus_shunt_model controls how MATPOWER bus Gs/Bs values are represented: "admittance" stamps them into Ybus (default), while "voltage_dependent_injection" keeps them out of Ybus and evaluates their |V|²-dependent contribution in the rectangular mismatch path.

matpower_shift_sign and matpower_shift_unit control how MATPOWER branch SHIFT values are converted before they are stored as Sparlectra transformer phase shifts. Defaults preserve MATPOWER convention: SHIFT is in degrees, positive on the branch from side. PEGASE-style data sets may require matpower_shift_unit = "rad" and/or matpower_shift_sign = -1.

matpower_ratio controls MATPOWER branch TAP import. The default "normal" uses the TAP value directly (with MATPOWER 0 treated as 1). Set matpower_ratio = "reciprocal" when an input data set stores the inverse tap ratio expected by Sparlectra.

tap_changer_model selects the tap-changer model applied to all transformers (transformer.tap_changer_model in the central configuration). :ideal (default) keeps the imported series impedance unchanged; :impedance_correction re-refers R/X through the tapped winding via calcTapCorrectedRX, interpreting the effective off-nominal tap ratio as the tap deviation of the tapped winding.

source
Sparlectra._matpower_sparlectra_tap_changer_model_markerMethod
_matpower_sparlectra_tap_changer_model_marker(mpc) -> Union{Nothing,String}

Read the optional mpc.sparlectra.tap_changer_model roundtrip marker written by writeMatpowerCasefile. When it is "impedance_correction", the exported BR_R/BR_X values already carry the tap-impedance correction, so createNetFromMatPowerCase must not reapply calcTapCorrectedRX on reimport (that would stack a second, differently-derived correction factor on top of the already-corrected values). Absent the marker, import behavior is unchanged so standard third-party MATPOWER cases are unaffected.

source
Sparlectra.createNetFromMatPowerCaseMethod
createNetFromMatPowerCase(; mpc, kwargs...) -> Net

Build a network from an already parsed MATPOWER case object mpc (a MatpowerIO.MatpowerCase as MatpowerIO.read_case returns). This is the construction core behind createNetFromMatPowerFile: bus, branch, generator, and shunt import, PQ generator controllers, and the MATPOWER convention switches (matpower_shift_sign, matpower_shift_unit, matpower_ratio, tap_changer_model). flatstart discards the case voltage state, bus_shunt_model selects how bus shunts are modeled, and profile collects per-stage import timings when given. Throws on inconsistent case data.

source
Sparlectra._print_timing_coverageMethod
_print_timing_coverage(io, profile; level=:compact)

Print coverage diagnostics that compare representative wall time against recorded phase timings and benchmark-event totals.

source
Sparlectra._record_perf!Method
_record_perf!(profile, label, seconds)

Append a benchmark/performance event to profile[:events] when a mutable profile dictionary is available.

source
Sparlectra._run_matpower_singleMethod
_run_matpower_single(local_case, cfg, profile, status_ref)

Run one MATPOWER power-flow solve and update status_ref with elapsed-time and result-output timing metadata.

source
Sparlectra._sum_perf_timingsMethod
_sum_perf_timings(profile; top_level_only=false)

Return accumulated timing seconds from profile[:timings].

When top_level_only=true, only major runner phases are included so coverage can be compared against representative wall time.

source
Sparlectra.print_performance_profileMethod
print_performance_profile(io, profile; ...)

Render a human-readable performance report from the MATPOWER runner profile.

Supports compact and full output levels, optional allocation columns, and optional iteration diagnostics.

source
Sparlectra.print_runtime_thread_configMethod
print_runtime_thread_config(io, status)

Print runtime thread request/active/apply status, including startup guidance when Julia thread requests cannot be applied in-process.

source
Sparlectra.run_with_output_captureMethod
run_with_output_capture(f; capture_stdout=true, capture_stderr=true)

Run f() with redirected stdio and return (result, stdout, stderr).

Used by the runner to isolate diagnostic output for logfile routing.

source
Sparlectra.write_matpower_import_auto_profileMethod
write_matpower_import_auto_profile(io, auto_profile_result, cfg; casefile)

Report the import-convention analysis, at the verbosity output.console_auto_profile asks for. That setting existed with values :off, :compact (the default) and :full but was read by nobody, so every run printed the full block: about seventy console lines for a case where every single check said "keep". A study tool should not narrate its importer that loudly, least of all in another product's vocabulary.

  • :off prints nothing.
  • :compact prints only the rows that actually RECOMMEND a change, plus one line saying how many checks were made and kept.
  • :full prints the original block: option list before, recommendation table, and effective options after.
source
Sparlectra.SCFDataType
SCFData

The PGM-compatible data section of one SCF document as typed component vectors (design decision D1: no stringly-typed row access on the build path). A component key is written to the file exactly when its vector is non-empty, which is the writer's behavior for every revision so far.

source
Sparlectra.SCFSparlectraType
SCFSparlectra

The namespaced sparlectra block of one SCF document. roles, components and start_state are typed (the adapters construct them); the genuinely free-form sub-objects (per-id extra records, controller declarations, study definitions, measurement rows) stay dictionaries and every consumer addresses them by key. meta, roles and extra are always written; every other block only when non-empty, exactly like the writer.

source
Sparlectra.scf_root_dictMethod
scf_root_dict(case::SCFCase) -> Dict{String,Any}

The document form of a typed case, ready for scf_json_string. Component keys appear exactly when their vector is non-empty; the namespaced block writes meta, roles and extra always and every other sub-block only when non-empty, matching the writer's shape.

source
Sparlectra.scfcase_from_rootMethod
scfcase_from_root(root::AbstractDict) -> SCFCase

Convert a parsed (and validated) SCF root object into its typed form. The converter mirrors the reader's field vocabulary exactly; unknown row fields of a foreign PGM file are dropped here, which is the documented scope of the round-trip contract (it covers files Sparlectra wrote).

source
Sparlectra._scf_apply_controllers!Method
_scf_apply_controllers!(net, entries; branch_by_name)

Instantiate the case file's controllers on net. The entries are the declarative control.controllers schema, so they go through applyConfiguredControllers! unchanged: one construction path, one validation, one vocabulary. branch_by_name maps the file's HUMAN branch names (extra block) to built branch indices: the importer regenerates in-memory component names, so a trafo/followers reference written with the case's own names would otherwise not resolve. References that already resolve (generated names, index strings) are passed through untouched.

source
Sparlectra._scf_branch_vnMethod
_scf_branch_vn(net, branch) -> Float64

Voltage base of a branch's impedance in kV. Sparlectra stamps the tap on the FROM side (ui /= tap in the Y-bus), so r_pu/x_pu are referenced to the TO side, which is exactly PGM's generic_branch convention.

source
Sparlectra._scf_bus_nameMethod
_scf_bus_name(net, i) -> String

The REFERENCE name of a bus: the busDict key. That is the name measurements, controllers, contingencies, and reports resolve against, and the name the reader has to restore; the internal component name ("Bus1110", "Aux12380") is kept separately in extra.component_name when it differs.

source
Sparlectra._scf_cgmes_mridsMethod
_scf_cgmes_mrids(net) -> (buses, branches, links)

Resolve the CGMES mRIDs of a delivery-sourced net by their structural keys (TN|<bus>, ACL|<a>|<b>|<k>, PT|<a>|<b>|<k>, SW|...), so external_id carries the source-system identity instead of the internal component id. Empty dictionaries on nets from other formats.

source
Sparlectra._scf_faultsMethod
_scf_faults(net, ids, buses) -> Vector

The buses a short-circuit study evaluates, in PGM's own fault vocabulary (fault_object, fault_type, r_f/x_f). Sparlectra computes the balanced three-phase bolted fault, so the rows state exactly that; the block is only written when a study names buses, and it is the PGM-readable twin of short_circuit.buses.

source
Sparlectra._scf_sc_sourcesMethod
_scf_sc_sources(net, ids) -> Vector

Short-circuit source data (IEC 60909 feeders and machines) as a sparlectra.components.sc_source list. The data is stored on the net by the CGMES importer and by addExternalGrid!; PGM's source component carries only sk/rx_ratio, so the full set travels here and stays lossless.

source
Sparlectra._scf_shunt_stateMethod
_scf_shunt_state(net, ids) -> Vector

Per-shunt state that PGM's shunt (g1/b1 only) has no slot for: whether the shunt is in service, which model it uses (a voltage-dependent injection is NOT an admittance), and whether its susceptance is released as a state-estimation state. Only shunts that deviate from the defaults produce a row, so an ordinary case file stays free of noise.

source
Sparlectra._scf_stableMethod
_scf_stable(pu, to_si, to_pu) -> Float64

Return the SI number to WRITE for the per-unit value pu: the one that the reader turns back into exactly pu. to_si is this writer's conversion, to_pu the reader's.

Unit conversion is not exactly invertible in floating point, and the naive value cost both guarantees at once: the re-read network differed in the last bit (so the Y-bus was not bit-identical), and the next export wrote that neighbour, so a file could drift on EVERY cycle instead of being a fixed point (seen on case14/case118/case300). Checking the two neighbouring floats finds an exact preimage in practice; if none exists, the value that maps to itself keeps at least the byte-identical round trip. The correction is at most one ulp.

source
Sparlectra._scf_stable_stepMethod
_scf_stable_step(pos, base, step) -> Int

The band position to WRITE. The reader rebuilds the ratio edge as base / (1 + pos * step), and a second export derives the position from that edge again. Rounding can land on the other side of a tie there, so the file would not be a fixed point (measured on case13659pegase: 6674 branches moved their band edge by one step on re-export). Pick the neighbour that reproduces itself; the ratio edge stays within the documented one-step snap either way.

source
Sparlectra._scf_transformer3wMethod
_scf_transformer3w(net, ids) -> Vector

Group the three star legs of a three-winding transformer. Sparlectra builds the same star equivalent PGM documents for generic_branch: three legs and one auxiliary star node. The electrical parameters therefore live exactly once, in data.generic_branch; this block only says which three branches belong together, which node is their star point, and which end is which.

Leg direction is Sparlectra's own: from_node is the star node, to_node the terminal, and each end names both explicitly, so no reader has to guess an orientation.

source
Sparlectra.scf_id_mapMethod
scf_id_map(net) -> ScfIdMap

Assign SCF ids deterministically: components are walked in a fixed type order and, inside a type, in lexicographic name order (ties broken by the internal index). Rebuilding the same net therefore produces the same ids and the same file bytes.

source
Sparlectra._scf_measurement_provenanceMethod
_scf_measurement_provenance(file) -> Dict{String,Any}

What a case file records about its own measurement set (sparlectra. measurements.provenance): whether the values carry noise, which generator and seed produced them, the per-row truth values, and the tap deviations the generator applied. Empty for a case without measurements, without a provenance block, or for anything that is not an SCF file, so callers can ask unconditionally.

source
Sparlectra._scf_require_current_revisionMethod
_scf_require_current_revision(spar)

The revision decides whether this reader understands the file at all. Backward compatibility across revisions is not promised while the format is young, so a file from another revision is refused BY NAME instead of being read with today's meaning. Every reader that feeds a RUN goes through this: the full import, and the config/studies accessors that are consulted before the import. A file written by power-grid-model has no namespaced block and never reaches the check; the display-only readers (measurement provenance, source reference) stay lenient on purpose, so a stale file still renders enough for the user to select it and be told to re-export.

source
Sparlectra._scf_source_referenceMethod
_scf_source_reference(file) -> String

The case file the SCF case was exported from (sparlectra.meta. source_reference), empty when unknown. It is what lets a run tell a set generated for the SOURCE case apart from a genuinely foreign one.

source
Sparlectra.scf_case_unitsMethod
scf_case_units(case::SCFCase) -> Symbol

The declared unit system of the electrical parameters (taskscfunitsv0100): :pu or :si. An ABSENT declaration means :si, which is what every file before the declaration meant, so existing files read unchanged. Unknown values are a hard error. For :pu the conversion base must be complete (D2): `meta.sbase(VA, positive and finite) and a positive finiteu_rated` on every node; per-unit numbers without their base are not interpretable, so a missing piece is a hard error naming the field.

source
Sparlectra.scf_node_ids_in_build_orderMethod
scf_node_ids_in_build_order(case) -> Vector{Int}

The file node ids in the order build_net creates the buses (recorded extra.bus_index, id as the tie break), so a consumer can map net node index k to its file id, for example to look up the raw start values of start_state.

source
Sparlectra._scf_json_writeMethod
_scf_json_write(io, value; indent = 0, key_order = nothing)

Write value as pretty JSON: objects and the objects inside a list break one key per line. Only a vector of plain scalars stays inline ([1, 2, 3]), because breaking a list of node ids over twenty lines helps nobody.

Component rows used to be written as ONE compact line each, which kept diffs narrow but read like a stream of data rather than a document. The expanded form is what JSON tooling produces and what a reader expects; a diff now points at the changed FIELD instead of the changed component.

source
Sparlectra.scf_infinity_sentinelMethod
scf_infinity_sentinel(value) -> value

Encode a possibly non-finite nameplate number for the namespaced sparlectra block. JSON cannot carry Inf, and an unlimited rating is real data (MATPOWER writes rateA = 0 for "no limit", which arrives as Inf), so it travels as the string "inf" / "-inf" and comes back as a number on read. Finite values pass through unchanged. The PGM data section never uses this: a value it cannot express is omitted there.

source
Sparlectra.scf_json_parseMethod
scf_json_parse(text) -> Dict{String,Any}

Parse an SCF case file. Object keys become String, integers stay Int (component ids), numbers with a fraction or exponent become Float64.

source
Sparlectra.scf_json_stringMethod
scf_json_string(root::AbstractDict) -> String

Serialize an SCF root object to its canonical text form (trailing newline included). Deterministic: the same object always produces the same bytes.

source
Sparlectra.CGMESImporter.writeSVFileMethod

Write the SV profile from the network's CURRENT voltage state: after a solve this is the solution, right after an import it is the start state (for a CGMES import: the delivery's own SV values). SvPowerFlow rows follow the same conventions compareWithSV reads back — loads and units in load convention, branch-terminal flows from the branch model at the current voltages — so a re-import validates cleanly against this profile.

source
Sparlectra.CGMESImporter.CGMESImportErrorType
CGMESImportError(message, analysis)

Import abort that carries the full importFailureAnalysis report. showerror prints only the one-line message; consumers that own a log or a UI (the powerflow service, the Web UI) read the analysis field and write the report where their users actually look (cgmes.log).

source
Sparlectra.CGMESImporter.importabilityStatsMethod
importabilityStats(store::CGMESStore) -> NamedTuple

The abort conditions the importer itself enforces, as data: missing_dependencies (declared md:Model.DependentOn ids absent from the input), unresolved_count, base_voltage_gap (nodes without a resolvable voltage level), topology_gap (terminals pointing at absent topological nodes), and the combined importable verdict. Shared by the service-mode run and the Web UI upload check so both judge a delivery identically.

source
Sparlectra.CGMESImporter._attachMachineControls!Method

Attach the surviving machine-control plans as MachineVoltageControl instances. Runs only after refreshBusTypesFromProsumers! and isolation marking, so the final node types and isoNodes are authoritative — a plan whose buses did not end up solvable PQ is dropped with a notice, mirroring _disableIneffectiveTapControllers!.

source
Sparlectra.CGMESImporter._busForTerminal!Method

Bus for one terminal of eq, honoring the per-side split of non-cancelling boundary nodes: when the terminal's CN is split, the equipment lands on its own area's side bus; everything else falls back to the TN bus.

source
Sparlectra.CGMESImporter._chooseSlackMethod

Pick the primary slack bus from the collected candidates.

Fallback chain, strongest evidence first:

  1. referencePriority markers — including the SV angle reference, which is injected at priority 0.0 because it is the reference the exporting tool actually used;
  2. the only / the largest ExternalNetworkInjection — a network equivalent is the natural reference;
  3. the largest SynchronousMachine.

Errors out when a delivery offers none of the three: an angle reference cannot be invented.

source
Sparlectra.CGMESImporter._curveQHullMethod

Q limits from a capability curve, evaluated at the machine's scheduled active power p_machine (CGMES machine convention, i.e. the raw SSH value): linear interpolation between curve points, clamped to the curve's P domain outside it.

The interpolated (y1, y2) pair then goes through the SAME sign-convention hull as the scalar minQ/maxQ path — the ENTSO-E sets are inconsistent about machine Q signs, and a capability curve is no more trustworthy in that respect than the scalars next to it. For the symmetric curves the test sets ship this is the identity; for asymmetric data it is deliberately safe rather than strictly faithful (the same Stage-2 note as for the scalars applies).

source
Sparlectra.CGMESImporter._deEnergizeSourcelessComponents!Method

De-energize every connected component that contains no source.

A CGMES snapshot regularly carries network parts that are switched off in reality: open bays, stub connections, feeders parked out of service. They still appear as buses with loads attached. Left alone, such a component has load but no generation and no reference — an unsolvable subsystem that would fail the power flow for a reason that has nothing to do with the interesting network.

The pass therefore zeroes the injections, opens the branches and marks the buses Isolated. This changes the imported model, so every affected component is reported.

Connectivity is evaluated over in-service branches AND closed links — the electrical view, since a component fed through a closed switch is energized.

source
Sparlectra.CGMESImporter._detectHvdcPairsMethod
_detectHvdcPairs(store) -> Vector{@NamedTuple{from::String, to::String, extra::Int, segments::Bool}}

Group the HVDC converters (VsConverter/CsConverter) by their DC-side connectivity: every ACDCConverterDCTerminal/DCTerminal joins its DC conducting equipment's nodes (DCBaseTerminal.DCNode, node-breaker deliveries use DCTopologicalNode), so two converters joined through DC nodes, segments, or switches land in one component. A component with exactly two converters is a link candidate (back-to-back when no DCLineSegment participates, point-to-point otherwise); other component sizes are reported via extra so the caller can notice them. Reads the raw store only, no electrical DC model.

source
Sparlectra.CGMESImporter._detectNonCancellingBoundarySides!Method

Detect assembled boundary nodes whose equivalent injections do not cancel and assign each contributing area (source file) its own side bus.

An AC X-node with both sides present carries two declarations of the same exchange — they cancel, the equivalents are discarded, and the node joins the areas galvanically. When the pair does NOT cancel, the two injections are two different devices (in practice: the HVDC converters of a DC border crossing; the residue is the DC loss). Joining the sides galvanically is then wrong twice over: it creates an AC corridor where none exists, and it violates KCL against the delivery's own SV state (ReliCapGrid BP_SD-EH_DC1: 94.8 MW flow into the node on one side, 72.6 MW out on the other — impossible through one node). Each side therefore keeps its line and its converter injection on its own bus.

The side of a piece of equipment is the file that defined it — the only criterion that exists, since both sides' terminals reference the same CN (and here even the same TN). The first source (sorted) keeps the base bus name, further sides get <bus>@<k>.

source
Sparlectra.CGMESImporter._hvdcCurrentSourceTransferMethod
_hvdcCurrentSourceTransfer(a, b) -> (p_dc, from_mrid, to_mrid, note)

DC power of a current-source (LCC) HVDC link whose two converters state their operating point as a DC current and a DC voltage instead of an active power, so ACDCConverter.p reads zero at BOTH ends.

The operating point is fully determined all the same: one converter declares CsConverter.targetIdc (its pPccControl is dcCurrent), the other declares ACDCConverter.targetUdc (pPccControl is dcVoltage), and their product is the DC power. from_mrid is the end that DRAWS from the AC grid, taken from CsConverter.operatingMode (rectifier draws, inverter delivers); without a usable operating mode the current-controlled end is treated as the rectifier, which is the normal LCC arrangement.

Returns p_dc === nothing when the pair states neither a current nor a voltage target, so the caller can report the gap instead of inventing a number. The DC line resistance is deliberately NOT applied here: it would split the transfer into a different value per end (on FullGrid 75.625 MW drawn against 75.0 MW delivered, matching SV to the converters' pole losses), which needs the DC-side model this importer does not build. The note states the inputs so the import message can show them.

source
Sparlectra.CGMESImporter._hvdcDerivedSlackPowerMethod
_hvdcDerivedSlackPower(store, ctx) -> Dict{String,Float64}

Derived SSH active power for HVDC converters that regulate the DC VOLTAGE instead of their PCC power, keyed by converter mRID (load convention, the same sign ACDCConverter.p uses).

Why this exists: in CIM the active power of a DC-voltage-controlling converter is a RESULT of the DC power balance, not a setpoint. An SSH snapshot may therefore legitimately carry ACDCConverter.p = 0 for that end while the opposite end carries the scheduled transfer. Reading both ends literally, as the Stage-0 mapping did, injects the transfer at one end and nothing at the other: the link swallows its whole throughput. On the FullGrid test configuration that is 150 MW entering at BEBusbarHVDC2 and 0 MW leaving at BEBusbarHVDC1, and it produced the largest angle deviations of the whole delivery against the SV profile (measured 2026-09-06: max |dva| 21.9 degrees, halved to 10.8 by this derivation).

The derivation is deliberately narrow and fires only when the current reading is provably wrong: a detected two-converter link, exactly one end at (numerically) zero power, that end declaring targetUdc > 0, and the other end carrying a nonzero schedule. The derived value is the opposite end's power reduced by both converters' declared idleLoss, the only loss term CIM states as a plain active power (resistiveLoss is an ohmic value and switchingLoss a power per current, both of which need the DC-side model this importer deliberately does not build).

A pair with BOTH ends at zero is NOT derived: its transfer lives only in targetUdc/CsConverter.pPccControl and cannot be recovered from the SSH power at all. Those pairs get a notice instead of a guessed number.

source
Sparlectra.CGMESImporter._logCGMESWarningsMethod

Emit the collected warning: messages through the logging system.

The mapping functions only collect strings; a data defect that made the importer substitute a derived value has to reach the user's log as well, not just result.messages. Grouped into a single @warn so a delivery with many defective objects does not flood the log.

source
Sparlectra.CGMESImporter._phaseTapTableModelMethod

Tabular phase-tap model of ptc (#294 point 2): build a :tabular PhaseTapChangerModel from the referenced PhaseTapChangerTable rows. Returns (model, impedance_note) or nothing when the table is unresolvable or empty. impedance_note flags rows with non-zero r/x/g/b percent corrections — those per-step impedance deviations are NOT folded into the branch in this stage (ratio and angle are).

source
Sparlectra.CGMESImporter._reactiveCapabilityCurvePointsMethod

Collect ReactiveCapabilityCurve points: curve mRID → CurveData tuples (x = P, y1 = minQ, y2 = maxQ), sorted by P. The x axis is the machine's own active power in the CGMES machine convention (negative = injecting), so it can legitimately span both signs (MicroGrid BE-G1: −100 … +100 MW).

source
Sparlectra.CGMESImporter._resolveMachineControlPlans!Method

Decide which remote machine-control plans survive (#294 point 3).

A plan falls back to the Stage-1 behavior (machine held PV at its own bus) when its target bus is not part of the built network, is already voltage-held (PV/slack), or the machine's own bus is voltage-held. Fallbacks themselves create new PV buses, so the scan runs to a fixpoint before the surviving plans claim their targets (one controller per target bus, document order).

source
Sparlectra.CGMESImporter._selectSlackBusesMethod

Decide the slack bus set. With multi_slack every electrical island — in the sense of electricalIslandComponents, i.e. closed links count as connections — receives at most one reference: the candidate with the highest referencePriority wins, further SV angle references in the same island are not promoted and keep the bus type their own injection produces (PV for a regulating machine, PQ otherwise — their voltage setpoint comes from the SV state anyway). Two references in one island would be physically wrong. On clean data the guard is a no-op — Svedala's two references sit in two electrical islands once Equipment.inService is honored — but it protects against deliveries whose island declarations and switch states disagree.

source
Sparlectra.CGMESImporter._svAngleRefNodesMethod

Angle-reference nodes declared by the SV profile: TopologicalIsland names one AngleRefTopologicalNode per island. That is the exporting tool's own reference choice — the most reliable slack information a delivery can carry, and the only one that scales to multi-island models (ReliCapGrid/Svedala ships two islands).

Two different island notions

A CIM TopologicalIsland is the exporting tool's partitioning and need not agree with the AC island Sparlectra sees after evaluating the switch states — which is why _selectSlackBuses re-checks the references against electricalIslandOfBus instead of trusting the CIM island count. Instructive history: Svedala appeared to disagree (both references in one electrical island), but that was an importer artifact — switches with SSH Equipment.inService = false were treated as closed and merged the two islands. With inService honored, the electrical view agrees with the delivery's two TopologicalIslands exactly. The cross-check stays: it costs little and catches deliveries where the disagreement is real.

source
Sparlectra.CGMESImporter._voltageSetpointMethod

Voltage setpoint of a regulating unit, as (vset_pu, is_voltage_regulating, remote_bus).

vset_pu === nothing together with true means "regulates voltage, but no usable local setpoint" — the caller then holds the unit PV at its own bus voltage (see _pvVoltage). That is the fallback for remote controls (unless allow_remote is set) and for implausible target values.

With allow_remote = true (machine control, #294 point 3) a resolvable remote voltage control returns the target bus name in remote_bus and vset_pu in p.u. of the remote bus's nominal voltage; the same plausibility band applies there. remote_bus === nothing always means "regulate locally or not at all".

source
Sparlectra.CGMESImporter.CGMESMultiRefsType

Store-level overflow for multi-valued references (#294 point 9): RDF/XML may repeat the same property on one object (TopologicalIsland. TopologicalNodes lists thousands of members). CIMObject.refs keeps its one-value-per-key shape — the 1:1 fast path stays allocation-free — and every additional value lands here under (mrid, key), in document order, excluding the first value (which stays in refs). Query via refsAll.

source
Sparlectra.CGMESImporter.readCGMESFile!Method
readCGMESFile!(objects, byclass, file; profile_filter=IMPORT_PROFILE_TAGS) -> CGMESFileInfo

Parse one CGMES XML payload into the shared object store. DifferenceModel files and files outside profile_filter are classified but not parsed (skipped = true). Returns the file metadata.

source
Sparlectra.CGMESImporter._rcgMemberFilesMethod

Files one ReliCapGrid member contributes, as (zip_entry, repo_path, cache_dir).

Grid files are cached per model folder (mirroring the repository layout); boundary and commonData files are shared between models and therefore cached once in a common folder, so a combined fetch does not download them per member.

source
Sparlectra.CGMESImporter.applyNodeBreakerTopologyProcessor!Method
applyNodeBreakerTopologyProcessor!(store, ctx) -> Bool

Derive the bus partition of a node-breaker delivery WITHOUT a TP profile: aggregate ConnectivityNodes across closed, non-retained switches into derived topological nodes (union-find over the connectivity graph) and register them as synthetic TopologicalNode objects in the store, wiring every terminal's Terminal.TopologicalNode reference. Downstream stages (buildTopology, the whole element mapping) then run untouched.

Semantics, reused unchanged from the mapping layer:

  • switch openness via _switchIsOpen (SSH open overrides EQ normalOpen; out of service counts as open), classes _SWITCH_CLASSES;
  • Switch.retained: retained closed switches are NOT merged away, their connectivity nodes stay separate buses and the existing switch-link mapping turns them into bus links;
  • nominal voltages resolve through the existing fallback chain: the synthetic node carries its group's ConnectivityNodeContainer (VoltageLevel) and, when resolvable, the BaseVoltage directly;
  • a group containing a connectivity node that ALREADY maps to a topological node (TP_BD boundary nodes) adopts that node instead of a synthetic one.

Runs only when connectivity nodes exist and no non-boundary topological node does; returns whether it ran. TP-carrying deliveries are untouched.

source
Sparlectra.CGMESImporter._inferNominalVoltagesMethod
_inferNominalVoltages(store::CGMESStore) -> (vn::Dict{String,Float64}, sv_n, trafo_n, prop_n)

Reconstruct nominal voltages for topological nodes whose BaseVoltage does not resolve (missing boundary catalog):

  1. SV seedSvVoltage.v is stored in kV; snapped to the standard level series it identifies the node's level directly (de-energized nodes with v ≈ 0 are skipped).
  2. Transformer seedPowerTransformerEnd.ratedU at the end's terminal fills nodes without an SV value.
  3. Propagation — nodes joined by level-preserving equipment (anything but a PowerTransformer) share their level; a BFS spreads the seeded levels across switches, lines, and equivalent branches.

Returns the per-TN map plus the per-source counts for the summary message. Nodes that stay unresolved are simply absent from the map — the caller keeps its regular missing-voltage handling for them.

source
Sparlectra.MatpowerIO._normalize_pv_voltage_sourceMethod
compare_vm_va(net, mpc; show_diff=false, tol_vm=1e-6, tol_va=1e-4, maxlines=20)

Compare net results (node.vmpu/vadeg) against MATPOWER reference (mpc.bus VM/VA). Skips isolated buses (BUS_TYPE==4) by default. Returns (ok::Bool, stats::NamedTuple).

source
Sparlectra.MatpowerIO.apply_matpower_bus_voltage!Method
apply_matpower_bus_voltage!(net, mpc; flatstart, verbose=0)

Policy:

  • flatstart=true -> do NOT write bus VM/VA into net (true flat start)
  • flatstart=false -> write bus VM/VA as initial guess (only if node has no meaningful voltage yet)

Never warn; debug-only on conflicts.

source
Sparlectra.MatpowerIO.legacy_sort_busMethod
legacy_sort_bus(mpc::MatpowerCase) -> MatpowerCase

Mimics the legacy casefileparser behavior:

  • Sorts bus rows by BUS_I (column 1) ascending.
  • Does NOT reorder gen or branch.

This keeps results compatible with the old importer.

source
Sparlectra.MatpowerIO.normalize_branch_tap!Method
normalize_branch_tap!(branch)

MATPOWER semantics:

  • column 9 (TAP) == 0 means "no transformer tap specified" and is treated electrically as 1.0 by Y-bus stamping and import code.

This helper is kept for callers that explicitly want normalized data, but read_case preserves raw TAP values so import code can distinguish lines (TAP == 0) from explicit nominal-tap transformers (TAP == 1).

source