CGMES Adapter Reference
Public API
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: the cgmes_import configuration surface plus the run kind the start-value decision may depend on, and the system frequency f_nom in Hz the conversion writes into the case (model.nominal_frequency_hz; the CGMES deliveries tested state none).
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.
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,Sparlectra.NativeShortCircuitData} = 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, the referencePriority of every machine and network injection: its stored ProSumer.referencePriority, 1 for a slack unit without one; a unit off the slack buses that is as strong as the slack is named in notices, 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 (none, or one with v <= 0); they start at the voltage of a neighbour with an SV voltage, or at 1.0 pu / 0° where there is none, which weakens any comparison against the delivery's SV state (fixed-reference self-check, compareWithSV). sv_tap_step_fits lists the tap changers whose SvPowerFlow fits another step clearly better than their SvTapStep (transformer, tap changer, both steps and both mismatches in MVA); the import counts them in one notice.
element_by_mrid maps the mRID of every CGMES object the importer turned into a network element to (kind, index), recorded where the element is created:
:branch:ACLineSegment,SeriesCompensator(also a boundary line built as a ratio branch),EquivalentBranch(across two voltage levels a branch with ratio 1); index intonet.branchVec.:transformer: a two-windingPowerTransformerunder its own mRID; a three-winding one under the mRID of eachPowerTransformerEnd, one star leg each (thePowerTransformermRID itself is not a key); index intonet.branchVec.:shunt:LinearShuntCompensator,NonlinearShuntCompensator, and the charging of a line whose two terminals sit on one TopologicalNode under"<line mRID>#charging"; index intonet.shuntVec.:load:EnergyConsumer,ConformLoad,NonConformLoad,StationSupply,AsynchronousMachine; index intonet.prosumpsVec.:generator:SynchronousMachine,StaticVarCompensator,EnergySourcewhenmap_energy_source = true, andPowerElectronicsConnection(CGMES 3.0) whenmap_power_electronics = true; index intonet.prosumpsVec.:external_grid:ExternalNetworkInjection,EquivalentInjection,VsConverter,CsConverter; index intonet.prosumpsVec.:link: a closed switch between two buses; index intonet.linkVec.:tap_controller: aRatioTapChangeror phase tap changer that became a controller (tap_control = true); index into_tap_controllers(net). A tap changer that joins another one's group as follower has no entry.
Skipped objects have no entry; they are in skipped_equipment, which also holds every EnergySource of an import with map_energy_source = false and every PowerElectronicsConnection of an import with map_power_electronics = false. Buses are addressed by their TopologicalNode (topo.bus_name), not here.
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. importCGMES keeps the records of the sources it mapped onto the network (ExternalNetworkInjection, SynchronousMachine, EquivalentInjection, AsynchronousMachine); a skipped one (terminal disconnected, out of service) feeds no fault current.
power_electronics_connections holds one record per PowerElectronicsConnection (CGMES 3.0) that the import mapped (only with map_power_electronics = true), with maxIFault_pu (the maximum fault current in per unit of the rated current), ratedS_MVA and ratedU_kV. maxIFault is a CIM17 attribute that no CGMES 3.0 profile defines; it is read where a delivery carries it, and is nothing otherwise.
A SynchronousMachine record carries converter_unit, the class name of its generating unit when that is a WindGeneratingUnit or a SolarGeneratingUnit (nothing otherwise), and for such a machine pmax_MW = GeneratingUnit.maxOperatingP. runShortCircuit! takes such a machine as a converter current source, not as a voltage source behind x''d. windGenUnitType holds the delivered WindGeneratingUnit.windGenUnitType (onshore, offshore, nothing when absent or not a wind unit); the CGMES export writes the unit class and this value back.
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. A three-winding star point has no SV voltage; it starts at the voltage at which no current leaves it, given the SV voltages of its sides.
path is a folder, a ZIP or a vector of either, or a CGMESStore already loaded with loadCGMES. The store is not modified: a delivery without a TP profile gets its topological nodes from the node-breaker topology processor, which writes them into the store, so the import then works on a deepcopy. Otherwise result.store is the given store itself.
result.element_by_mrid names the element every mapped CGMES object became (see CGMESImportResult).
An EquivalentBranch with both terminals connected and in service becomes a branch without charging: on one voltage level a pi branch with r, x on that base, across two levels a branch with per-unit ratio 1 and the impedance on the base of terminal 1. One whose terminals sit on the same TopologicalNode builds nothing and gets a notice. One whose impedance lies below equivalent_branch_min_z_pu (per unit on the base of terminal 1, both directions, default 1e-6) builds no branch either: its two buses are joined as a bus link, with a notice. With r21/x21 other than r/x the object becomes a transformer branch with ratio 1, phase shift arg(z21/z12)/2, series impedance of magnitude sqrt(|z12| |z21|) and unequal shunt arms with zero row sums (phase stamp, on both level kinds). It reproduces the two-port exactly for |z21| = |z12|; otherwise each admittance entry is off in magnitude by sqrt(|z21|/|z12|) or its inverse. One notice counts the mapped, skipped and stamped objects and the largest magnitude difference.
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.
A SynchronousMachine, ExternalNetworkInjection or StaticVarCompensator with SSH controlEnabled = false does not regulate: it is a PQ injection at its SSH p/q with its Q limits, whatever its RegulatingControl says, and a machine gets no MachineVoltageControl; an absent flag counts as true. The flag does not touch the slack choice: referencePriority and the SV angle reference still apply, and as slack the unit holds its bus at the start voltage (the SV value where present). One notice per class counts these units. An EquivalentInjection has no controlEnabled; it regulates only with EQ regulationCapability = true, SSH regulationStatus = true and a positive regulationTarget (an absent flag counts as false). One notice counts the units with regulationCapability = true and no regulationStatus.
An active power limit of 9999 MW and above in magnitude (GeneratingUnit.minOperatingP/maxOperatingP, minP/maxP of an ExternalNetworkInjection or EquivalentInjection) is a placeholder and arrives as no limit (nothing): the unit is not ranked by it in a slack choice and gets no weight from it in the distributed slack. One notice counts these units per class. Q limits keep their delivered values.
With map_energy_source = true every in-service, connected EnergySource on a TopologicalNode becomes a fixed PQ injection (GENERATOR prosumer, p = -activePower, q = -reactivePower from the SSH, no regulation, no Q limits, no slack candidate of the delivery), addressed as :generator in element_by_mrid; one notice counts the mapped and skipped objects with their P and Q sums. In an island whose only infeed is EnergySource the importer makes the largest of them the slack, by the rule for islands without a reference, with a warning (its P then follows the island balance). With multi_slack = false such an island gets no slack: the island-wise solve makes the strongest of them its reference, and one notice per such island says so. With the default false the objects stay out of the network, are listed in skipped_equipment, and one notice names the key that maps them; their count and P sum stand in the table of classes not mapped.
With map_power_electronics = true every in-service, connected PowerElectronicsConnection (CGMES 3.0) on a TopologicalNode becomes an injection prosumer of component type PowerElectronicsConnection with p = -p and q = -q from the SSH, addressed as :generator in element_by_mrid. With controlEnabled and an enabled voltage RegulatingControl with a target above zero it regulates like a SynchronousMachine (local target: PV at its bus; a target outside vset_min_pu/vset_max_pu: held PV at its bus voltage with a warning; remote target: held PV at its bus, or an outer-loop controller with machine_control = true), otherwise it is a fixed PQ injection. Q limits come from the minQ/maxQ hull (a regulating one without them gets ±max(ratedS, baseMVA)), P limits from the summed minP/maxP of its PowerElectronicsUnits. It is no slack candidate of the delivery; an island whose only sources are such PQ injections is treated like an EnergySource island (an importer slack, or with multi_slack = false the same notice). One notice counts the mapped, regulating and skipped objects with their P and Q sums. Each mapped connection leaves a record in shortcircuit.power_electronics_connections (maxIFault, ratedS, ratedU), from which runShortCircuit! forms its fault current. maxIFault is a CIM17 attribute outside the CGMES 3.0 profiles, so a conforming delivery has none and its connections flag their island in the short circuit instead. With the default false the connections stay out of the network like unmapped EnergySource objects: listed in skipped_equipment, one notice naming the key, count and P sum in the table of classes not mapped. An EquivalentInjection with IdentifiedObject.description = PowerElectronicsConnection (the CGMES 2.4.15 export writes a connection so) gets the component type PowerElectronicsConnection, whatever the key: it has no fault current, so the short circuit flags its island.
A SynchronousMachine on a WindGeneratingUnit or SolarGeneratingUnit is mapped like any machine for the power flow; its short-circuit record names the unit class (converter_unit) and carries GeneratingUnit.maxOperatingP, so runShortCircuit! takes it as a converter current source (short_circuit.converter_current_factor times the rated current from ratedS, else from maxOperatingP).
With shunt_control = true every mapped LinearShuntCompensator with SSH controlEnabled and an enabled voltage RegulatingControl at its own bus gets a switched-bank ShuntVoltageControl that takes over its shunt: blocks of bPerSection at the nominal voltage from 0 to maximumSections, the SSH sections as start, the target in pu of the bus, half the targetDeadband as deadband. A remote target, a target outside the vset band, a conductance per section, a bus that is not PQ, a second bank on one bus and a NonlinearShuntCompensator keep the shunt fixed with a notice.
Every class with terminals or with an SSH active power value of which no object outside the boundary set is mapped gets one row class not mapped: with its object count and the sum of its SSH P in MW, below one header notice that states the load sign (positive means flow out of the node). A row whose objects carry no SSH active power has no P sum. An object is mapped when it became a network element (also as a three-winding leg or as the charging shunt of a line on one node). The topology consumes BusbarSection and Junction, and a switch (Switch, Breaker, Disconnector, LoadBreakSwitch, Jumper, ProtectedSwitch, Fuse, GroundDisconnector, Cut, DisconnectingCircuitBreaker) that is open, disconnected or inside one TopologicalNode; a closed switch between two nodes is a bus link for the first six classes and missing for the others. Parts of a mapped object (transformer ends, tap changers, generating units) and the connectivity carry no terminal of their own and get no row. An object out of service or without a connected terminal on a TopologicalNode does not count when its class is one the importer maps.
Sparlectra.CGMESImporter.cgmesMeasurementKeys — Method
cgmesMeasurementKeys(result::CGMESImportResult) -> MeasurementKeyIndexThe key index of a CGMES import for importMeasurementTable: every terminal, TopologicalNode, ConnectivityNode, BusbarSection and Analog of the delivery, resolved to the bus, branch end or bus group of result.net.
- A terminal of a line or transformer end resolves to that branch end. A branch out of service or open at one terminal resolves to
:not_modelledat both ends (the estimator does not take flow measurements on a partially open branch yet). - A terminal of a load, machine, external grid, equivalent injection, SVC, power electronics connection or mapped energy source resolves to
:injection, a terminal of a shunt compensator to:shunt, as long as the equipment is mapped, its terminal connected and its bus energized; each such terminal is a member of the group sum at its bus. - Every other terminal (switches, equipment the importer skips or does not map, de-energized nodes) resolves to
:not_modelledwith the reason. - A node resolves to its bus, a ConnectivityNode through its TopologicalNode, a BusbarSection through its terminal. A node that is not energized resolves to bus 0.
- A bus or branch end without any mRID (the star point of a three-winding transformer, the legs ending there, auxiliary buses of the import) takes its name key from
nameMeasurementKeys, in canonical form; a name never replaces an mRID key. - An Analog resolves to its terminal (or, without one, to its PowerSystemResource when that is a node or busbar) and its
measurementType: active powerP, reactive powerQ, line currentI, line-to-line voltageU; other types keep an empty type and are reported when a row uses them.
Sparlectra.CGMESImporter.generateMeasurementTableFromSV — Method
generateMeasurementTableFromSV(result::CGMESImportResult; kwargs...) -> Vector{NamedTuple}Synthetic measurement table from the SV profile of a CGMES delivery: U at every energized TopologicalNode with an SvVoltage, and P and Q at both terminals of every line and transformer end closed at both terminals, computed with the network model at the SV voltage state (a delivery often carries SvPowerFlow only at injections). Rows are keyed by terminal_mrid and node_mrid and sorted by key, so the output does not depend on the order of the delivery.
Keywords:
timestamp = "": the timestamp column of every row.include_injections = false: also write the deliveredSvPowerFlowof injection terminals (P and Q) and shunt terminals (Q).sigma_pq_rel = 0.01,sigma_pq_floor = 0.1: sigma of P and Q asmax(sigma_pq_rel * |value|, sigma_pq_floor)in MW/MVAr.sigma_u_rel = 0.002: sigma of U relative to the reading (kV).sigma_pq_floorandsigma_u_relmust be positive,sigma_pq_relandbad_data_sigmasfinite and at least 0 (anArgumentErrorotherwise), so every row passes the reader.sigma_by_voltage_level(default: the activestate_estimation.sigma_by_voltage_level): where the level of the measuring bus (the node, the branch end, the injection or shunt) has a row with a column for the type, that sigma (max(absolute, rel_pct/100 * |value|), MW, MVAr, kV) replaces the three keywords above, for the written sigma and the noise alike.noise = true: add Gaussian noise with that sigma;falsewrites the SV values unchanged.bad_data_fraction = 0.0: share of rows that get a gross error ofbad_data_sigmassigma (random sign) instead of the noise. They carrysource = "synthetic;bad_data", all otherssource = "synthetic".bad_data_sigmas = 20.0,seed = 1: size of the gross error and the seed of the random stream; equal arguments give equal rows.
The rows have the fields of the table header and can be written with writeMeasurementTable.
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). Isolated buses are skipped, except a bus that a closed switch joins to a bus with a branch: the solver merges it with that bus, and it is compared at the voltage of its switch group. 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 (the islands the power flow solves: branches and closed bus links both connect, also through a bus isolated only for lack of a branch of its own) 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:LinearShuntCompensatorandNonlinearShuntCompensatorat the solved bus voltage (the nonlinear one with the admittance the import summed from its characteristic points up to the SSH section),:load— SSH load values (data-consistency check),:units: machines/ENIs/EquivalentInjections aggregated per closed-link cluster against the solved balance of the cluster (covers PV and slack units; a bus without links is a cluster of one).
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.
Internals
Sparlectra.import_net — Method
import_net(::CGMESAdapter, path::AbstractString, opts::CGMESAdapterOptions; config = active_sparlectra_config()) -> NetThe CGMES importer of the adapter contract: 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 fifteen cgmes_import values), which stays the path the services use.
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!.
A machine whose remote regulation is the only source of its island (no slack, no PV bus, no unit with infeed; _deEnergizeSourcelessComponents! kept the island energized for that regulation) gets no controller either: the importer gives such an island no slack, and the solve would hold the machine bus at its start voltage as island reference, where a Q controller has nothing to act on. The machine is held PV at its own bus at its start voltage instead, as without machine_control, with a notice.
Sparlectra.CGMESImporter._attachTapControl! — Method
Branch tap-range fields and controller for one controlled transformer end. Returns the tap changers that got a controller or joined a controller group, each with on_from_side.
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 (markIsolatedBuses! later sets their voltage to 0). This changes the imported model, so every affected component is reported, and one notice counts the components, their buses and the load left unsupplied.
A source is a generator-type unit with P > 0 (generator sign) or with voltage regulation (_isCGMESSource). Voltage regulation includes a machine that regulates a remote bus of the same component with machine_control = true. A unit without regulation that has P = 0 or draws power (P < 0) does not keep a component energized, so a component whose units only draw power is de-energized as well. A load is never a source, also not one that feeds power in (P < 0 in load sign). The unsupplied P of a component is the P its loads consume plus the P its drawing units drew; the P that feeding loads put in is reported as dropped load infeed and not netted against it.
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 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; the model carries ratio and angle, the corrections of the step reach the branch through _tapTableImpedanceFactors.
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.
An island that has a source but neither an angle reference here nor a voltage-regulating unit gets its slack later, from _slackForIslandsWithoutReference!, once de-energization and isolation have decided which islands exist.
Sparlectra.CGMESImporter._slackForIslandsWithoutReference! — Method
Give every energized electrical island that has infeed but no reference a slack.
Without this, such an island leaves the import without a Slack or PV bus. The island-wise solve then promotes one of its units to the reference and keeps that bus at its start voltage, so the result there depends on the start value only. Real deliveries carry such islands as fragments of a network equivalent: two buses, one branch, two EquivalentInjections without referencePriority or maxP.
Runs after _deEnergizeSourcelessComponents! and markIsolatedBuses!, when the islands are final. The islands are those the power flow solves (Sparlectra._power_flow_islands): a bus the marking isolates only because it hangs on the network through closed switches alone belongs to the island of its switch group, so the parts it joins get one slack, not one each. An island qualifies when it has no Slack bus, no PV bus and at least one generator-type unit with infeed (pVal > 0, generator sign). An island whose units only draw power has no source and is already de-energized; one whose only source regulates its voltage has a PV bus, and one whose only source is a machine regulating a remote bus is left to _attachMachineControls!, which holds that machine PV at its own bus.
Slack candidates are only the units with infeed; a unit with P = 0 or drawing power is never one, and a static var compensator neither. Among them (_islandSlackUnit): the strongest referencePriority, else the largest active power reserve maxP - pVal on a bus of degree greater than 1 (degree: neighbour buses over closed in-service branches and closed links; the only bus of a single-bus island counts as such a bus), else the largest infeed on a bus of degree greater than 1, and only when no such bus carries infeed, the largest infeed on a bus of degree 1. The unit becomes the slack exactly as the importer's own slack choice does it: referencePri on its bus, isRegulated, and as voltage setpoint the start voltage of its bus (the SV voltage, 1.0 pu without one); none of its units regulates, so no local setpoint exists. Each choice is a warning: message naming island, unit, reason and setpoint, and one notice counts the islands. Called only with multi_slack = true.
Sparlectra.CGMESImporter._startNoSvBusesFromNeighbours! — Method
_startNoSvBusesFromNeighbours!(net, ctx, no_sv_buses) -> IntStart voltage of the buses without a usable SvVoltage from a neighbour.
Such a bus gets 1.0 pu / 0° from _ensureBus!. Where its neighbours sit far from 0°, that start can lead Newton to a second solution: a leaf bus without load behind a branch converges at 0 V, a short circuit behind the branch impedance that pulls its neighbour down (seen on a real delivery with neighbours at -22° to -26°). Each listed bus therefore takes magnitude and angle of the neighbour reached over the closed branch or closed link of the smallest |z| (a link counts as zero impedance, a tie goes to the lower bus index). The search runs breadth-first from the buses with a start of their own, so a chain of such buses is covered; a bus picks only from buses set before its layer, so the result does not depend on the order within a layer. A bus whose group touches no bus with a start keeps the default. Three-winding star points are left alone (_startStarBuses! sets them by their node balance) and are no source either; isolated buses carry no start and are neither. Returns the number of buses set.
Sparlectra.CGMESImporter._startStarBuses! — Method
_startStarBuses!(net, ctx, topo, svmap) -> IntStart voltage of every three-winding star point from its own node balance.
The star point has no SvVoltage. Its provisional start, the SV voltage of end 1, is off by the tap of that end and by the drop across the winding, so at the SV state a current flows out of the star that the delivery does not have, and Newton can end on a second solution at low voltage. With the start voltages V_k of the sides, the star row of the admittance matrix gives the one voltage at which no current leaves the star:
V_s = -sum_k Y_sk V_k / Y_ssThe stamps are those createYBUS builds, summed over the branches at the star (a leg with its side end open adds its input admittance to Y_ss only). Applied when the star has at least one closed leg and every closed leg reaches a side whose TopologicalNode carries an SV voltage above zero; otherwise the provisional start stays. Runs once every branch is built, so the stamps hold every ratio and impedance the mapping set, and Y_ss holds the magnetizing admittance of the ends, which the legs carry as their arm at the star. The importer puts no bus shunt on a star bus. Returns the number of star buses set.
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._rcgZipComplete — Method
_rcgZipComplete(dest, key) -> BoolWhether the packed ZIP dest of ReliCapGrid set key carries every member file the current layout expects (grid profiles, boundary files, commonData). A ZIP packed under an older layout is refreshed instead of being reused.
Sparlectra.CGMESImporter.cgmesTestSetCacheDir — Method
Cache directory for the ENTSO-E test configurations (data/CGMES, override via SPARLECTRA_CGMES_CACHE).
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.