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 farThe 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)| Source | Value 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, BMOPF | MulticonductorNetwork |
| PyPSA CSV with several snapshots | TimeSeries{BalancedNetwork} or TimeSeries{OperatingPoint{BalancedNetwork}}, depending on which quantities vary |
| GridFM Parquet | ScenarioSet{BalancedNetwork} |
| GO Challenge 3 problem, or problem and solution | AcScucInstance, AcScucSolution |
| OPFData | AcOpfSolution |
| Geographic data or a PowerWorld PWD display | UnknownValue 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
endA 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)
endEmit
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 fileresult.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.PioModule — Type
PioModule{T}One typed value together with the records that describe how it was produced.
m.value::T: the value. Dispatch onPioModule{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.
PowerIO.Producer — Type
Producer(name, version)The program identity recorded with a module.
PowerIO.ModuleSource — Type
ModuleSourceOne 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.
PowerIO.HistoryEntry — Type
HistoryEntryOne 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.
PowerIO.Diagnostic — Type
DiagnosticOne 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, ornothing.target: locator of the value element concerned, ornothing.suggested_action: what to do about it, ornothing.spans: source byte ranges.related: identities of related diagnostics.details: structured details as aDict{String,Any}, ornothing.
PowerIO.SourceSpan — Type
SourceSpan(source, byte_start, byte_end)One byte range in a named source, attached to a Diagnostic.
PowerIO.PowerIOError — Type
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.
PowerIO.UnknownValue — Type
UnknownValueA module value whose structural type name this PowerIO.jl release does not bind. value.type_name is the name the library reports.
PowerIO.emit — Function
emit(m::PioModule, format, destination=nothing) -> EmitResultWrite 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.
PowerIO.EmitResult — Type
EmitResultWhat 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 aString, ornothingwhen the result holds anything else.
PowerIO.Artifact — Type
ArtifactOne 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.
PowerIO.serialize — Function
serialize(m::PioModule, destination=nothing) -> EmitResultWrite 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.
PowerIO.deserialize — Function
deserialize(path::AbstractString) -> PioModule
deserialize(io::IO) -> PioModule
deserialize(bytes::AbstractVector{UInt8}) -> PioModuleRead 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.