Format Adapters Reference
Public API
Sparlectra.FormatAdapter — Type
FormatAdapterAbstract 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 byimport_case.convert_case(::A, source, opts)::SCFCase: the converter, explicit requests only.export_case(::A, net, path; opts): optional, the reverse direction.
Sparlectra.runShortCircuit! — Method
runShortCircuit!(result::CGMESImporter.CGMESImportResult; kwargs...) -> ShortCircuitResultConvenience 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.
Sparlectra.CGMESAdapterOptions — Type
CGMESAdapterOptionsThe 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.
Sparlectra.cgmes_adapter_options — Method
cgmes_adapter_options(cfg::SparlectraConfig; run_kind, name) -> CGMESAdapterOptionsThe adapter options an effective run configuration implies.
Sparlectra.cgmes_enrich_case! — Method
cgmes_enrich_case!(case, net) -> SCFCaseAttach 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).
Sparlectra.DTFAdapterOptions — Type
DTFAdapterOptionsThe 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).
Sparlectra.dtf_adapter_options — Method
dtf_adapter_options(cfg::SparlectraConfig) -> DTFAdapterOptionsThe 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.
Sparlectra.MatpowerAdapterOptions — Type
MatpowerAdapterOptionsThe 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.
Sparlectra.matpower_adapter_options — Method
matpower_adapter_options(cfg::SparlectraConfig) -> MatpowerAdapterOptionsThe 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.
Sparlectra.PGMAdapterOptions — Type
PGMAdapterOptionsThe 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.
Sparlectra.createNetFromDTFFile — Method
createNetFromDTFFile(path; baseMVA = 100.0, strict = true, bus_shunt_model = :admittance, transformer_ratio_mode = :neutral_one) -> NetRead 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.
Sparlectra.CGMESImporter.importCGMES — Method
importCGMES(config; path, name) -> CGMESImportResultImport 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.
Sparlectra._createDict — Method
_createDict() -> DictThe MATPOWER column-index tables (bus, gen, branch) the parser uses.
Sparlectra.createNetFromMatPowerFile — Method
createNetFromMatPowerFile(; filename, kwargs...) -> NetParse a MATPOWER .m/.jl case file and build the network; accepts the same options as createNetFromMatPowerCase.
Sparlectra.writeMatpowerCasefile — Method
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.busVM/VAreflect the solved node state, andmpc.branchgains 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) readsmatpower_export.write_solutionfrom the active configuration (defaulttrue, seeMatpowerExportConfig). Whentruebut the network has no solved branch flows, the exporter warns and falls back to the historical 13-column model-onlympc.branchexport instead of writing empty result columns. Whenfalse, the export is a pure model file:mpc.branchkeeps 13 columns andVM = 1.0/VA = 0.0for all non-slack/non-PV buses (slack and PV setpoints are preserved).
Example
net = Net(...)
writeMatpowerCasefile(net, "casefile.m")Sparlectra.run_matpower_case — Method
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.
Sparlectra.run_synthetic_tiled_grid_pf_perf — Method
run_synthetic_tiled_grid_pf_perf(; config_file, args, outdir)Generate a tiled synthetic grid and measure the power flow on it; the performance harness entry.
Sparlectra.run_voltage_dependent_control_demo — Method
run_voltage_dependent_control_demo(; config_file, plot_curve)Run the Q(U)/P(U) controller demonstration case and print its outcome.
Sparlectra.SCFCase — Type
SCFCaseOne 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.
Sparlectra.read_scf_json — Method
read_scf_json(path) -> SCFCaseRead 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).
Sparlectra.write_scf_json — Method
write_scf_json(case, path) -> StringSerialize a typed case to its canonical file form (deterministic bytes, see scf_json_string) and return the path.
Sparlectra.exportSCF — Method
exportSCF(net; file, kwargs...) -> StringWrite 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:metafields;case_namedefaults 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 insparlectra.measurements.provenanceand 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 namespacedsparlectrablock, 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).
Sparlectra.net_to_scf — Method
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.
Sparlectra.net_to_scfcase — Method
net_to_scfcase(net; kwargs...) -> SCFCaseThe 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.
Sparlectra.scf_is_case_config_key — Method
scf_is_case_config_key(key) -> BoolWhether 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.
Sparlectra.build_net — Method
build_net(case::SCFCase; config = active_sparlectra_config()) -> NetThe 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).
Sparlectra.importSCF — Method
importSCF(file) -> NetRead 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.
Sparlectra.scf_case_config — Method
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.
Sparlectra.scf_case_studies — Method
scf_case_studies(file) -> NamedTupleThe 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.
Sparlectra.scf_extra_names — Method
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.
Sparlectra.scf_fault_nodes — Method
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.
Sparlectra.scf_to_net — Method
scf_to_net(root::AbstractDict) -> NetBuild 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).
Sparlectra.scf_validate_dataset — Method
scf_validate_dataset(root) -> NothingRun 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.
Sparlectra.CGMESImporter — Module
CGMESImporterLean CGMES 2.4.15 / 3.0 import layer. Stage 0 provides reading and diagnostics (loadCGMES, summarizeCGMES); Net mapping follows in later stages.
Sparlectra.CGMESImporter.CGMESFile — Type
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.
Sparlectra.CGMESImporter.collectCGMESFiles — Method
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).
Sparlectra.CGMESImporter.CGMESLineShortCircuit — Type
CGMESLineShortCircuitZero-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.
Sparlectra.CGMESImporter.cgmesLineShortCircuitData — Method
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.
Sparlectra.CGMESImporter.writeCGMESFiles — Method
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.
Sparlectra.CGMESImporter.analyzeCGMES — Method
analyzeCGMES(; path)::StringLoad 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.
Sparlectra.CGMESImporter.importFailureAnalysis — Method
importFailureAnalysis(store::CGMESStore)::StringBuild a multi-line report explaining why a CGMES delivery cannot be imported (or what is incomplete about it):
- the supplied model files with profile, CGMES version, and model id;
- every
md:Model.DependentOnprerequisite 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; - a histogram of unresolved object references grouped by class and property;
- a verdict in plain language. A delivery whose
TopologicalNode.BaseVoltagereferences 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.
Sparlectra.CGMESImporter.CGMESImportResult — Type
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).
Sparlectra.CGMESImporter.CGMESShortCircuitData — Type
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.
Sparlectra.CGMESImporter.createNetFromCGMES — Method
createNetFromCGMES(; path, baseMVA=100.0, require_boundary=true, name=nothing) -> NetThin wrapper around importCGMES returning only the Net.
Sparlectra.CGMESImporter.importCGMES — Method
importCGMES(; path, baseMVA=100.0, require_boundary=true, name=nothing) -> CGMESImportResultImport 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.
Sparlectra.CGMESImporter.CGMESFileInfo — Type
Per-file metadata from the md:Model header (layer-1/2 handshake).
Sparlectra.CGMESImporter.CIMObject — Type
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.
Sparlectra.CGMESImporter.CGMESSummary — Type
Result of summarizeCGMES: everything a user needs to judge a CGMES delivery before importing it.
Sparlectra.CGMESImporter.compareWithSV — Method
compareWithSV(result::CGMESImportResult) -> NamedTupleCompare 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),:shunt—LinearShuntCompensatorat 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.
Sparlectra.CGMESImporter.printShortCircuitCoverage — Method
printShortCircuitCoverage(io, sc)Readable rendering of shortCircuitCoverage: per class the record count and each attribute's fill rate, ✓ when complete. This is what cgmes.log prints under "Short-circuit source data".
Sparlectra.CGMESImporter.shortCircuitCoverage — Method
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.
Sparlectra.CGMESImporter.summarizeCGMES — Method
summarizeCGMES(; path) -> CGMESSummaryRead 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.
Sparlectra.CGMESImporter.CGMESStore — Type
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.
Sparlectra.CGMESImporter.boolval — Function
Literal attribute as Bool ("true"/"false"), or default when absent.
Sparlectra.CGMESImporter.countOf — Method
Number of objects of class.
Sparlectra.CGMESImporter.enumval — Function
Enum attribute value (stored as Kind.value fragment), or default.
Sparlectra.CGMESImporter.loadCGMES — Method
loadCGMES(path; profile_filter=IMPORT_PROFILE_TAGS) -> CGMESStoreLoad 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.
Sparlectra.CGMESImporter.num — Function
Literal attribute as Float64, or default when absent/unparsable.
Sparlectra.CGMESImporter.objectsOf — Method
All objects of class, in file order.
Sparlectra.CGMESImporter.ref — Method
Follow the reference key of obj; returns the target CIMObject or nothing.
Sparlectra.CGMESImporter.refsAll — Method
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.
Sparlectra.CGMESImporter.str — Function
Literal attribute as String, or default when absent.
Sparlectra.CGMESImporter.unresolvedReferences — Method
unresolvedReferences(store) -> Vector{@NamedTuple{mrid, class, key, target}}All rdf:resource targets that do not exist in the store: the "boundary set missing" detection signal.
Sparlectra.CGMESImporter.CGMES_TESTSET_ALIASES — Constant
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).
Sparlectra.CGMESImporter.RELICAPGRID_ALIASES — Constant
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.
Sparlectra.CGMESImporter.RELICAPGRID_COMBINED — Constant
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
|
Nordheimrelicapgrid_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.)
Sparlectra.CGMESImporter.allCGMESTestSetAliases — Method
All known test-set aliases across both sources (conformity package and ReliCapGrid).
Sparlectra.CGMESImporter.ensureCGMESTestConfigurations — Method
ensureCGMESTestConfigurations(; cache = cgmesTestSetCacheDir()) -> StringMake 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.
Sparlectra.CGMESImporter.fetchCGMESTestSet — Method
fetchCGMESTestSet(alias; outdir) -> StringResolve 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.
Sparlectra.CGMESImporter.fetchReliCapGridSet — Method
fetchReliCapGridSet(alias; outdir) -> StringFetch 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.
Sparlectra.CGMESImporter.CGMESTopology — Type
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 bysequenceNumber(1-based positions).
Sparlectra.CGMESImporter.buildTopology — Method
buildTopology(store) -> CGMESTopologyDerive the bus set and the equipment→bus lookup from the TP profile. Deterministic bus naming per decision D-3.
Sparlectra.DTFImporter — Module
Importer for the native DTF (FOR001) format: parser, network construction and the outage bookkeeping of that format.
Sparlectra.DTFImporter.DTFParams — Type
Native DTF importer parameter card values preserved for auditing.
Sparlectra.DTFImporter.apply_single_branch_outage! — Method
Safely set exactly one branch out of service and verify no other status changed.
Sparlectra.DTFImporter.build_net — Method
build_net(case; bus_shunt_model = :admittance) -> NetBuild 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φ).
Sparlectra.DTFImporter.case_summary — Method
Return stable summary counts for a parsed DTF case.
Sparlectra.DTFImporter.dtf_branch_key — Method
Return the strict branch-matching key used for DTF parallel branches.
Sparlectra.DTFImporter.find_outage_branch_indices — Method
Find native branch indices matching a DTF outage card with strict parallel-branch keys.
Sparlectra.DTFImporter.outage_label — Method
Return a concise human-readable DTF outage label.
Sparlectra.DTFImporter.outage_match_diagnostic — Function
Build a clear diagnostic for missing or ambiguous DTF outage branch matches.
Sparlectra.DTFImporter.read_dtf — Method
read_dtf(path; baseMVA = 100.0, strict = true) -> DTFCaseRead 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.
Sparlectra.MatpowerIO.MatpowerCase — Type
Container for a MATPOWER case (case format v2/v2-ish). All matrices are stored as Float64 matrices, names as Vector{String} when available.
Sparlectra.MatpowerIO.build_ybus_matpower — Method
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.
Sparlectra.MatpowerIO.read_case — Method
read_case(path::AbstractString; legacy_compat::Bool=true) -> MatpowerCaseDispatches based on file extension:
.m=>read_case_m.jl=>read_case_julia(expects file returnsMatpowerCaseorNamedTuple)
Sparlectra.MatpowerIO.read_case_julia — Method
read_case_julia(path::AbstractString; legacy_compat::Bool=true) -> MatpowerCaseThe .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.
Sparlectra.MatpowerIO.read_case_m — Method
read_case_m(path::AbstractString; legacy_compat::Bool=true) -> MatpowerCaseBest-effort parser for typical MATPOWER case files (*.m). Parses:
mpc.baseMVAmpc.busmpc.genmpc.branch- optional:
mpc.gencost - optional:
mpc.bus_name
Sparlectra.MatpowerIO.vmva_power_mismatch_stats — Method
vmva_power_mismatch_stats(mpc::MatpowerCase) -> NamedTupleChecks 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.
Sparlectra.FetchMatpowerCase — Module
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.
Sparlectra.FetchMatpowerCase.emit_julia_case — Method
emit_julia_case(mfile, outdir; legacy_compat=true, overwrite=false) -> jlfile::StringParses a MATPOWER .m case and writes a Julia NamedTuple (.jl) compatible with MatpowerIO.readcasejulia().
Sparlectra.FetchMatpowerCase.ensure_casefile — Method
ensure_casefile(casefile; outdir=nothing, overwrite=false, to_jl=true) -> StringEnsure a MATPOWER-compatible case file exists locally.
- If
casefileis an existing path, it is returned unchanged. - If
casefileis a bare filename (e.g.case14.m), it is downloaded intooutdir. - If
casefileends with.jland is missing, the corresponding.mis downloaded and.jlis generated.
Returns the local path to the requested case file.
Sparlectra.FetchMatpowerCase.ensure_matpower_case — Method
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.
Sparlectra.FetchMatpowerCase.fetch_matpower_case — Method
fetch_matpower_case(url, outdir; overwrite=false) -> mfile::StringDownloads 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.
Sparlectra.FetchMatpowerCase.large_cases_dir — Method
large_cases_dir() -> StringThe shared directory for large MATPOWER and DTF cases, resolved in two steps:
SPARLECTRA_LARGE_CASES_DIR, if set (override for CI and special setups)- otherwise the Web UI user case directory (
~/.local/state/sparlectra/webui/data/mpoweron Linux,%LOCALAPPDATA%\Sparlectra\WebUI\data\mpoweron 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.
Sparlectra.FetchMatpowerCase.main — Function
main(args=ARGS) -> nothingCLI entry point. If no –url is provided, it prints help and returns without error.
Internals
Sparlectra.import_net — Method
import_net(::CGMESAdapter, path::AbstractString, opts::CGMESAdapterOptions; config = active_sparlectra_config()) -> NetThe 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.
Sparlectra.import_net — Method
import_net(::DTFAdapter, case, opts::DTFAdapterOptions) -> NetThe 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.
Sparlectra.import_net — Method
import_net(::MatpowerAdapter, mpc, opts::MatpowerAdapterOptions; kwargs...) -> NetThe 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.
Sparlectra.detect — Method
detect(::Type{PGMAdapter}, path) -> BoolA .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.
Sparlectra.import_net — Method
import_net(::PGMAdapter, path::AbstractString, opts::PGMAdapterOptions; config = active_sparlectra_config()) -> NetThe 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.
Sparlectra.ImportedCase — Type
ImportedCaseWhat 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 resolvescgmes_import.start_valuesagainst 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.
Sparlectra._import_cgmes — Method
_import_cgmes(path, cfg; name, phase_callback) -> NamedTupleThe 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).
Sparlectra.import_case — Method
import_case(path, general_config; requested_format, name, performance_profile, phase_callback) -> ImportedCaseImport 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.
Sparlectra._apply_matpower_reference_override! — Method
createNetFromMatPowerCase(; mpc, log=false, flatstart=false) -> NetBuilds a Sparlectra Net from a MATPOWER-like container mpc.
mpc can be either:
- a
NamedTuplewith fieldsname, baseMVA, bus, gen, branch(optionallygencost, 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.
Sparlectra._matpower_sparlectra_tap_changer_model_marker — Method
_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.
Sparlectra.createNetFromMatPowerCase — Method
createNetFromMatPowerCase(; mpc, kwargs...) -> NetBuild 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.
Sparlectra._compact_run_summary — Method
_compact_run_summary(status)Build a single-line compact summary string from a MATPOWER run status object.
Sparlectra._print_timing_coverage — Method
_print_timing_coverage(io, profile; level=:compact)Print coverage diagnostics that compare representative wall time against recorded phase timings and benchmark-event totals.
Sparlectra._record_perf! — Method
_record_perf!(profile, label, seconds)Append a benchmark/performance event to profile[:events] when a mutable profile dictionary is available.
Sparlectra._run_matpower_single — Method
_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.
Sparlectra._run_matpower_single_routed — Method
_run_matpower_single_routed(local_case, cfg, profile, status_ref; ...)Run one solve either directly to console or through captured stdio for later logfile emission.
Sparlectra._sum_perf_events — Method
_sum_perf_events(profile)Return total seconds across benchmark events recorded in profile[:events].
Sparlectra._sum_perf_timings — Method
_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.
Sparlectra.append_captured_output_to_logfile — Method
append_captured_output_to_logfile(logfile, captured; section_title="")Append captured stdout/stderr chunks to the MATPOWER logfile.
Sparlectra.emit_performance_summary — Method
emit_performance_summary(profile; ...)Emit performance output to console and/or logfile according to runner output configuration.
Sparlectra.matpower_run_logfile_path — Method
matpower_run_logfile_path(casefile, cfg)Build the per-run MATPOWER logfile path under examples/_out/.
Sparlectra.new_performance_profile — Method
new_performance_profile(cfg::PerformanceConfig)Create a lightweight mutable performance profile dictionary used by runner APIs.
Sparlectra.parse_runtime_threads_request — Method
parse_runtime_threads_request(raw)Parse runtime-thread configuration tokens ("keep", "auto", integer-like strings) into Int thread counts or nothing.
Sparlectra.print_matpower_runner_header — Method
print_matpower_runner_header(io; ...)Print the standard MATPOWER runner banner with resolved config, case, method, and logging/performance settings.
Sparlectra.print_performance_profile — Method
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.
Sparlectra.print_runtime_thread_config — Method
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.
Sparlectra.run_silent_for_benchmark — Method
run_silent_for_benchmark(f)Execute benchmark payload f via invokelatest while suppressing captured stdio output.
Sparlectra.run_with_output_capture — Method
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.
Sparlectra.runtime_thread_status — Method
runtime_thread_status(cfg)Resolve requested Julia/BLAS thread settings, apply BLAS runtime changes, and return a status tuple for reporting.
Sparlectra.with_powerflow_method — Method
with_powerflow_method(cfg, method)Create a configuration copy with powerflow.method replaced by method.
Sparlectra.write_matpower_import_auto_profile — Method
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.
:offprints nothing.:compactprints only the rows that actually RECOMMEND a change, plus one line saying how many checks were made and kept.:fullprints the original block: option list before, recommendation table, and effective options after.
Sparlectra.SCFData — Type
SCFDataThe 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.
Sparlectra.SCFSparlectra — Type
SCFSparlectraThe 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.
Sparlectra.scf_root_dict — Method
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.
Sparlectra.scfcase_from_root — Method
scfcase_from_root(root::AbstractDict) -> SCFCaseConvert 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).
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.
Sparlectra._scf_branch_vn — Method
_scf_branch_vn(net, branch) -> Float64Voltage 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.
Sparlectra._scf_bus_name — Method
_scf_bus_name(net, i) -> StringThe 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.
Sparlectra._scf_cgmes_mrids — Method
_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.
Sparlectra._scf_faults — Method
_scf_faults(net, ids, buses) -> VectorThe 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.
Sparlectra._scf_sc_sources — Method
_scf_sc_sources(net, ids) -> VectorShort-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.
Sparlectra._scf_shunt_state — Method
_scf_shunt_state(net, ids) -> VectorPer-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.
Sparlectra._scf_stable — Method
_scf_stable(pu, to_si, to_pu) -> Float64Return 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.
Sparlectra._scf_stable_step — Method
_scf_stable_step(pos, base, step) -> IntThe 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.
Sparlectra._scf_transformer3w — Method
_scf_transformer3w(net, ids) -> VectorGroup 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.
Sparlectra.scf_id_map — Method
scf_id_map(net) -> ScfIdMapAssign 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.
Sparlectra._scf_measurement_provenance — Method
_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.
Sparlectra._scf_require_current_revision — Method
_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.
Sparlectra._scf_source_reference — Method
_scf_source_reference(file) -> StringThe 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.
Sparlectra.scf_case_units — Method
scf_case_units(case::SCFCase) -> SymbolThe 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.
Sparlectra.scf_node_ids_in_build_order — Method
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.
Sparlectra._scf_json_write — Method
_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.
Sparlectra.scf_infinity_sentinel — Method
scf_infinity_sentinel(value) -> valueEncode 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.
Sparlectra.scf_json_parse — Method
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.
Sparlectra.scf_json_string — Method
scf_json_string(root::AbstractDict) -> StringSerialize an SCF root object to its canonical text form (trailing newline included). Deterministic: the same object always produces the same bytes.
Sparlectra.scf_number_or_sentinel — Method
scf_number_or_sentinel(value, context) -> Float64Read back what scf_infinity_sentinel wrote.
Sparlectra.CGMESImporter.writeSVFile — Method
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.
Sparlectra.CGMESImporter.CGMESImportError — Type
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).
Sparlectra.CGMESImporter.importabilityStats — Method
importabilityStats(store::CGMESStore) -> NamedTupleThe 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.
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!.
Sparlectra.CGMESImporter._attachTapControl! — Method
Branch tap-range fields and controller for one controlled transformer end.
Sparlectra.CGMESImporter._busDictName — Method
Bus-dictionary name of node index idx (the name geNetBusIdx accepts).
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.
Sparlectra.CGMESImporter._chooseSlack — Method
Pick the primary slack bus from the collected candidates.
Fallback chain, strongest evidence first:
referencePrioritymarkers — including the SV angle reference, which is injected at priority 0.0 because it is the reference the exporting tool actually used;- the only / the largest
ExternalNetworkInjection— a network equivalent is the natural reference; - the largest
SynchronousMachine.
Errors out when a delivery offers none of the three: an angle reference cannot be invented.
Sparlectra.CGMESImporter._curveQHull — Method
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).
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.
Sparlectra.CGMESImporter._detectHvdcPairs — Method
_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.
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>.
Sparlectra.CGMESImporter._hvdcCurrentSourceTransfer — Method
_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.
Sparlectra.CGMESImporter._hvdcDerivedSlackPower — Method
_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.
Sparlectra.CGMESImporter._logCGMESWarnings — Method
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.
Sparlectra.CGMESImporter._phaseTapRatioShift_atstep — Method
Phase-tap (ratio, shift) of ptc evaluated at an explicit step.
Sparlectra.CGMESImporter._phaseTapTableModel — Method
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).
Sparlectra.CGMESImporter._reactiveCapabilityCurvePoints — Method
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).
Sparlectra.CGMESImporter._regulatedBus — Method
Regulated bus (name, vn) of a TapChangerControl, or nothing.
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).
Sparlectra.CGMESImporter._selectSlackBuses — Method
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.
Sparlectra.CGMESImporter._svAngleRefNodes — Method
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).
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.
Sparlectra.CGMESImporter._svTapPositions — Method
SvTapStep positions: tap-changer mRID → solved position.
Sparlectra.CGMESImporter._voltageSetpoint — Method
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".
Sparlectra.CGMESImporter.CGMESMultiRefs — Type
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.
Sparlectra.CGMESImporter.readCGMESFile! — Method
readCGMESFile!(objects, byclass, file; profile_filter=IMPORT_PROFILE_TAGS) -> CGMESFileInfoParse 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.
Sparlectra.CGMESImporter.cgmesVersionFromNamespace — Method
CGMES version string derived from the cim namespace URI; "" if unknown.
Sparlectra.CGMESImporter.profileTagFromKeyword — Method
Map one dcat:keyword short code to a profile tag; :UNKNOWN if unmatched.
Sparlectra.CGMESImporter.profileTagFromURI — Method
Map one md:Model.profile URI to a profile tag (:EQ, :TP, …); :UNKNOWN if unmatched.
Sparlectra.CGMESImporter.readCGMESHeader — Method
Cheap header-only pass (no object parsing) used for read ordering.
Sparlectra.CGMESImporter._rcgMemberFiles — Method
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.
Sparlectra.CGMESImporter._rcgMembers — Method
All member aliases of key: itself for a single model, the member list for a combined one.
Sparlectra.CGMESImporter.applyNodeBreakerTopologyProcessor! — Method
applyNodeBreakerTopologyProcessor!(store, ctx) -> BoolDerive 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(SSHopenoverrides EQnormalOpen; 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, theBaseVoltagedirectly; - 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.
Sparlectra.CGMESImporter.busOfEquipment — Method
Bus name and vn for the seq-th terminal of equipment eq; returns nothing when the terminal or its TN is missing.
Sparlectra.CGMESImporter.terminalConnected — Method
SSH connected flag of terminal t (default true when absent).
Sparlectra.CGMESImporter.tnOfTerminal — Method
TopologicalNode mRID of terminal t, or nothing.
Sparlectra.CGMESImporter._inferNominalVoltages — Method
_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):
- SV seed —
SvVoltage.vis stored in kV; snapped to the standard level series it identifies the node's level directly (de-energized nodes withv ≈ 0are skipped). - Transformer seed —
PowerTransformerEnd.ratedUat the end's terminal fills nodes without an SV value. - 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.
Sparlectra.MatpowerIO._mp_bus_row_index — Method
_mp_bus_row_index(mpc) -> Dict{Int,Int}Map MATPOWER BUS_I -> row index in mpc.bus
Sparlectra.MatpowerIO._normalize_pv_voltage_source — Method
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).
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.
Sparlectra.MatpowerIO.bus_row_index — Method
bus_row_index(mpc::MatpowerCase) -> Dict{Int,Int}Map MATPOWER BUS_I -> row index in mpc.bus.
Sparlectra.MatpowerIO.has_vm_va — Method
has_vm_va(mpc::MatpowerCase) -> BoolTrue if mpc.bus has VM/VA columns (8/9) and at least one finite entry.
Sparlectra.MatpowerIO.legacy_sort_bus — Method
legacy_sort_bus(mpc::MatpowerCase) -> MatpowerCaseMimics the legacy casefileparser behavior:
- Sorts
busrows by BUS_I (column 1) ascending. - Does NOT reorder
genorbranch.
This keeps results compatible with the old importer.
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).