Modules

Every source parses into a PioModule, which pairs one typed value with the diagnostics, producer, sources, and history that say how it was produced.

case = parse("case118.m")
case isa PioModule{BalancedNetwork}    # true
case.value                              # the BalancedNetwork
case.diagnostics                        # Vector{Diagnostic}
case.producer                           # Producer("powerio", "0.11.0")
case.sources                            # the files it was read from
case.history                            # the operations applied so far

The type parameter follows the source, so you can dispatch on it:

summarize(m::PioModule{BalancedNetwork}) = length(m.value.buses)
summarize(m::PioModule{MulticonductorNetwork}) = length(m.value.lines)
summarize(m::PioModule{<:TimeSeries}) = length(m.value)
SourceValue type
MATPOWER, PSS/E RAW and RAWX, XIIDM and JIIDM, CGMES, UCTE-DEF, IEEE CDF, PowerWorld AUX and PWB, PSLF EPC, PowerModels JSON, Egret JSON, pandapower JSON, Surge JSON, PyPSA CSV (one snapshot)BalancedNetwork
OpenDSS, PMD JSON, BMOPFMulticonductorNetwork
PyPSA CSV with several snapshotsTimeSeries{BalancedNetwork} or TimeSeries{OperatingPoint{BalancedNetwork}}, depending on which quantities vary
GridFM ParquetScenarioSet{BalancedNetwork}
GO Challenge 3 problem, or problem and solutionAcScucInstance, AcScucSolution
OPFDataAcOpfSolution
Geographic data or a PowerWorld PWD displayUnknownValue with type_name == "powerio.GeoLayer"

If the library hands back a value type this release does not bind, you get an UnknownValue with its structural type name.

Sources

parse takes a path, an IO, or bytes. The format keyword is a canonical token such as "matpower", "psse", "xiidm", "cgmes", or "dss"; leave it out and the source name and content decide. For a source held in memory, name supplies the source name.

parse("case9.m")
parse("cgmes_case/")                                    # a directory or ZIP for a profile set
parse(IOBuffer(text); format="matpower", name="case9.m")
parse(bytes; format="pwb", name="case.pwb")
open("case9.m") do io
    parse(io)                                           # an open file keeps its path as the name
end

A failed parse throws PowerIOError with a stable code, the rendered message, and the structured diagnostics that caused it. The code is the stable part, so branch on it rather than on the message.

Diagnostics

Diagnostics belong to the module rather than to the value. Each Diagnostic has a code ("READ.MATPOWER.FIELD_DEFAULTED", "EMIT.PSSE.FIELD_DROPPED"), a severity (:error, :warning, :remark, :note), and a message. When the reader recorded them, it also has an id, a target naming the element concerned, a suggested_action, source spans, related diagnostic ids, and structured details.

for d in case.diagnostics
    d.severity == :warning || continue
    println(d.code, ": ", d.message)
end

Emit

emit writes a module as a grid exchange format and returns an EmitResult.

same = emit(case, "matpower")            # in memory
same.fidelity                            # "exact_same_format"
same.text                                # the original file content

other = emit(case, "psse")
other.fidelity                           # "canonical": freshly written
other.diagnostics                        # what PSS/E cannot carry

emit(case, "psse", "case.raw")           # one file on disk
emit(case, "pypsa-csv", "case_dir")      # a directory of files
emit(case, "matpower", stdout)           # a writable IO receives the single file

result.artifacts lists what was produced, one Artifact per file with its name and either its data (in memory) or its path (on disk). layout is "file" or "directory". fidelity is "exact_same_format" when the module was read from that format and its value is unchanged, in which case the output is the original file content; otherwise it is "canonical". text is the content of the single UTF-8 file when it was produced in memory, or nothing.

PowerIO IR

PowerIO IR is PowerIO's own serialization of a module: one JSON document ("schema": "pio-ir", integer generation "version": 2) holding the typed value with its diagnostics, producer, sources, source mappings, history, and extensions. The producer record separately names the PowerIO release that wrote the document. serialize writes it and deserialize reads it.

PowerIO 0.11 reads generation 2. The generation advances only when the serialized representation changes, and it is independent of the PowerIO release and the C ABI; library_version reports the library release. A refused document names the generation it found and what to do about it: a later generation needs a newer PowerIO, and a document with any other schema or an older generation has to be regenerated from its original power system data.

serialize(case, "case9.pio.json")
back = deserialize("case9.pio.json")     # PioModule{BalancedNetwork}

PowerIO IR is not a grid exchange format. parse does not read it, emit does not write it, and it does not appear in format discovery. Use it when both sides are PowerIO consumers and the diagnostics and history matter; use emit for every other tool. The document does not include the original file content, so a deserialized module writes canonical output rather than the original file.

Constructions

to_dc_pf_instance, to_ac_pf_instance, to_dc_opf_instance, to_ac_opf_instance, to_mc_ac_pf_instance, and to_mc_ac_opf_instance construct a calculation instance module from a network module. The network is shared, and the new module's history has an entry for the construction. See Collections and instances.

PowerIO.PioModuleType
PioModule{T}

One typed value together with the records that describe how it was produced.

  • m.value::T: the value. Dispatch on PioModule{BalancedNetwork}, PioModule{MulticonductorNetwork}, PioModule{TimeSeries{...}}, and the other concrete parameters.
  • m.diagnostics::Vector{Diagnostic}: the findings stored on the module.
  • m.producer::Producer: the program that produced the module.
  • m.sources::Vector{ModuleSource}: the sources it was read from.
  • m.history::Vector{HistoryEntry}: the operations applied so far.

parse and deserialize return modules. emit and serialize consume them. apply_updates! changes the value in place and refreshes m.value; it needs exclusive use of m while it runs.

source
PowerIO.ModuleSourceType
ModuleSource

One source recorded with a module: its id, name, byte_length, the format token when the reader recorded one, and the digest_algorithm and digest when a digest was recorded.

source
PowerIO.HistoryEntryType
HistoryEntry

One operation recorded in module history: its id, kind, name, the input_type and output_type structural names when recorded, the named parameters as a Dict{String,String} of parameter name to value kind, and the assumptions and losses the operation declared.

source
PowerIO.DiagnosticType
Diagnostic

One finding recorded by a reader, writer, or transformation.

  • code: the stable code to branch on, such as "READ.MATPOWER.FIELD_DEFAULTED".
  • severity: :error, :warning, :remark, or :note.
  • message: rendered text for people.
  • id: durable identity, or nothing.
  • target: locator of the value element concerned, or nothing.
  • suggested_action: what to do about it, or nothing.
  • spans: source byte ranges.
  • related: identities of related diagnostics.
  • details: structured details as a Dict{String,Any}, or nothing.
source
PowerIO.PowerIOErrorType
PowerIOError(code, message, diagnostics)

A failure reported by the PowerIO library. code is the stable diagnostic code to branch on, message is the rendered text, and diagnostics are the structured Diagnostic records that caused the failure.

source
PowerIO.UnknownValueType
UnknownValue

A module value whose structural type name this PowerIO.jl release does not bind. value.type_name is the name the library reports.

source
PowerIO.emitFunction
emit(m::PioModule, format, destination=nothing) -> EmitResult

Write the module's value as the grid exchange format named by format ("matpower", "psse", "xiidm", "cgmes", "dss", "pmd", "bmopf", "powermodels-json", "pypsa-csv", and the other canonical tokens). With destination === nothing the files stay in memory. A path writes one file or a directory. A writable IO receives the single file.

When the module was read from the same format and its value is unchanged, the output is the original file content (fidelity == "exact_same_format"). Anything the target cannot carry is reported in result.diagnostics.

source
PowerIO.EmitResultType
EmitResult

What one emission produced.

  • artifacts::Vector{Artifact}: one entry per file.
  • layout::String: "file" or "directory".
  • fidelity::String: "exact_same_format" when the output is the original file content the reader kept, "canonical" for freshly written output.
  • diagnostics::Vector{Diagnostic}: what the writer kept, defaulted, or could not carry.
  • text: the content of the one in-memory UTF-8 file as a String, or nothing when the result holds anything else.
source
PowerIO.ArtifactType
Artifact

One file produced by emit or serialize; the Rust, Python, and C APIs use the same name. name is the file name. data holds the content after an in-memory emission and is nothing after a write to disk; path holds the written path after a write to disk and is nothing for an in-memory emission.

source
PowerIO.serializeFunction
serialize(m::PioModule, destination=nothing) -> EmitResult

Write the module as PowerIO IR: one JSON document holding the typed value with its diagnostics, producer, sources, source mappings, history, and extensions. Read it back with deserialize. PowerIO IR carries PowerIO values between PowerIO consumers; use emit for other tools.

source
PowerIO.deserializeFunction
deserialize(path::AbstractString) -> PioModule
deserialize(io::IO) -> PioModule
deserialize(bytes::AbstractVector{UInt8}) -> PioModule

Read one PowerIO IR document written by serialize: "schema": "pio-ir" and integer generation "version": 2. The producer record names the PowerIO release that wrote it independently. This release reads generation 2 and refuses any other generation, naming the version it found. PowerIO IR is not a grid exchange format; parse does not accept it.

source