API reference
The module
PowerIO.PowerIO — Module
PowerIOJulia entry point for the PowerIO Rust core: parser, compiler package, and IR infrastructure for power system software. Parse MATPOWER, PSS/E, PowerWorld, PSLF EPC, PowerModels JSON, egret JSON, pandapower JSON, PyPSA CSV, Surge JSON, and PowerIO JSON cases, convert between supported pairs, and materialize a parsed BalancedNetwork, all through the powerio-capi C ABI.
Parse once with parse_file → BalancedNetwork, then read or transform it, all over the same C ABI:
- the rich, lossless element tables via the JSON transport (every field + extras, costs, storage, HVDC): the accessors and
to_json. to_dense: the numeric tables as dense typed arrays for matrix assembly, straight from the C ABI extractors, no JSON.to_arrow: one table over the Arrow C Data Interface (owned columns by default; zero copy withcopy=false), including matrix COO selectors when the matrix feature is present.
to_normalized derives a per unit / radian / filtered copy that preserves source bus ids, and to_matpower / convert_file serialize back out.
read_gridfm / read_gridfm_scenarios read a gridfm-datakit Parquet dataset back into a BalancedNetwork (the ML→classical return leg; lossy but complete enough for power flow, needs powerio-capi built --features gridfm).
Multiconductor distribution cases are a separate model, MulticonductorNetwork, with the same handle plus cached payload pattern as the balanced side (net.data). The bare verbs route on the format — parse_file("feeder.dss"), convert_file("feeder.dss", "bmopf"), parse_file("case.pio.json") — and the type marker forms (parse_file(MulticonductorNetwork, path)) stay as the explicit spelling. OpenDSS, PowerModelsDistribution JSON, and IEEE BMOPF JSON read and write (experimental; needs powerio-capi built --features dist, plus pkg for the element tables).
.pio.json network packages use the pio_package_* C ABI API. They can wrap balanced and multiconductor handles, run package validation, expose structured diagnostics, and explicitly lower supported multiconductor packages to balanced packages.
At first use the binding checks the library's ABI version (pio_abi_version) against the version it targets (PIO_ABI_VERSION) and refuses a stale or mismatched library with an error stating both versions. Distribution calls also check pio_dist_abi_version against PIO_DIST_ABI_VERSION.
The C library resolves automatically: the bundled lazy artifact, or a sibling powerio build during development. Point at a custom build with set_library!, the POWERIO_CAPI environment variable, or a persisted Preferences.jl override.
Parsing, conversion, serialization
PowerIO.BalancedNetwork — Type
BalancedNetworkA parsed balanced transmission case. Values stay in raw MATPOWER units with 1-based bus ids, mirroring powerio's BalancedNetwork: buses, loads, shunts, branches, generators, storage, and hvdc tables plus base_mva, name, and source_format.
A BalancedNetwork from parse_file keeps a live Rust BalancedNetworkHandle (net.handle) and leaves net.data empty until the first rich payload access. The first net.data access reads the materialized JSON payload through the C ABI and caches it. The to_* transforms (to_normalized, to_dense, to_matpower, to_arrow) work from the live handle. The handle's finalizer frees the Rust case once the BalancedNetwork is unreachable. A BalancedNetwork constructed from a bare JSON3.Object has handle === nothing; table access and to_json work on it, while handle-only transforms error.
Because data is lazy, explicitly calling finalize(net.handle) before the first net.data access leaves nothing to read: the data-backed accessors (net.data, n_buses, show, to_json) then raise a "handle was finalized" error. Access the values you need before finalizing the handle; letting the finalizer run at GC is the normal path and never hits this.
PowerIO.convert_file — Method
convert_file(path, to; from=nothing) -> (text, warnings)
convert_file(MulticonductorNetwork, path, to; from=nothing) -> (text, warnings)Convert path to format to, routing on the formats like parse_file: distribution tokens and .dss paths go through the multiconductor converter, and a cross-model request (e.g. .dss to "matpower") is a directed error — lowering is explicit, through the package pass. Within the transmission family supported writer pairs convert. A same format conversion is byte exact; a cross format one reports whatever the target can't carry in warnings. Tokens (case-insensitive): "matpower"/"m", "powermodels-json"/"powermodels"/"pm", "egret-json"/"egret", "psse"/"raw", "powerworld"/"aux", "pslf"/"epc", "pandapower-json"/"pandapower", "surge-json"/"surge", "pypsa-csv". from overrides extension inference (needed to tell egret, PowerModels, pandapower, and Surge .json files apart). Pass MulticonductorNetwork first to convert a distribution case.
PowerIO.convert_str — Method
convert_str(text, to; from) -> (text, warnings)
convert_str(MulticonductorNetwork, text, to, from) -> (text, warnings)Convert in-memory case text to format to — the string sibling of convert_file (pio_convert_str). from is required for a transmission case (there is no path to infer from): the source format token. Pass MulticonductorNetwork first for a distribution case.
PowerIO.from_json — Method
from_json(text) -> BalancedNetworkRebuild a live BalancedNetwork from the JSON transport produced by to_json. The result has a Rust handle, so to_* transforms work on it.
PowerIO.parse_bytes — Method
parse_bytes(bytes, format) -> BalancedNetworkParse in-memory case bytes under an explicit format. Accepts every parse_str token plus "pwb": PowerWorld binary has no text form, so this is the only way to read one without a file on disk. Text formats must be UTF-8.
PowerIO.parse_file — Method
parse_file(path; from=nothing) -> BalancedNetwork | MulticonductorNetwork
parse_file(io::IO, format::AbstractString)
parse_file(BalancedNetwork, path; from=nothing) -> BalancedNetwork
parse_file(MulticonductorNetwork, path; from=nothing) -> MulticonductorNetworkParse a case. The bare verb routes on the format and returns the model the file holds: transmission cases (MATPOWER, PSS/E, PowerWorld, PSLF EPC, PowerModels JSON, egret JSON, pandapower JSON, PyPSA CSV folders, Surge JSON) parse into a BalancedNetwork, multiconductor distribution cases (OpenDSS, PMD, BMOPF) into a MulticonductorNetwork, and a .pio.json package into whichever model its envelope declares.
From a file path the format is inferred: by extension (.m, .raw, .aux, .dss, .pio.json), and for a bare .json by the same top level markers the core parsers use (pio_classify_str), unless from is given. From an io stream the format is required (there is no extension); parse in-memory text by wrapping it, parse_file(IOBuffer(text), "matpower").
Accepted format tokens (case-insensitive): "matpower"/"m", "powermodels-json"/"powermodels"/"pm", "egret-json"/"egret", "psse"/"raw", "powerworld"/"aux", "pslf"/"epc", "pandapower-json"/"pandapower", "surge-json"/"surge", "pypsa-csv"; distribution: "dss"/"opendss", "pmd"/"engineering", "bmopf".
The type marker forms pin the model when the routed return type would be ambiguous to a reader: parse_file(BalancedNetwork, path) and parse_file(MulticonductorNetwork, path) — the parse(T, x) idiom.
PowerIO.parse_str — Function
parse_str(text, format="matpower") -> BalancedNetwork | MulticonductorNetwork
parse_str(MulticonductorNetwork, text, format) -> MulticonductorNetworkParse in-memory case text — the string sibling of parse_file(io, format), matching the Rust, Python, and C interfaces. A distribution format token routes to the multiconductor parser, like the bare parse_file.
PowerIO.to_format — Method
to_format(net::BalancedNetwork, to) -> (text, warnings)
to_format(net::MulticonductorNetwork, to) -> (text, warnings)Serialize a parsed network to format to without reparsing the input file. Returns the target text and any fidelity warnings. Dispatches on the handle type, so a MulticonductorNetwork writes the distribution formats.
PowerIO.to_json — Method
to_json(net::BalancedNetwork) -> StringSerialize net to the C ABI's JSON transport, the same text from_json reads back. Uses the live handle when present, else the cached net.data.
PowerIO.to_matpower — Method
to_matpower(net::BalancedNetwork) -> StringSerialize net to MATPOWER .m text, byte exact when the input was MATPOWER. For a file in one shot use convert_file(path, "matpower").
PowerIO.to_normalized — Method
to_normalized(net::BalancedNetwork; clamp_angle_bounds=false, angle_bound_pad=nothing) -> BalancedNetworkA computation-ready copy of net: per unit (powers ÷ base_mva), angles in radians, transformer tap 0 → 1, out-of-service and isolated elements dropped, source bus ids preserved, and bus types inferred (a bus with a surviving generator keeps REF if the source marked it so, else becomes PV; a generator-less bus becomes PQ). source_format of the result is "Normalized".
Needs net's live Rust handle (from parse_file). Errors if base_mva is not positive or no reference bus can be established. clamp_angle_bounds=true also applies the PowerModels angle difference repair in the Rust normalize pass.
PowerIO.to_normalized_with_options — Method
to_normalized_with_options(net::BalancedNetwork; clamp_angle_bounds=false, angle_bound_pad=nothing)Compatibility spelling for to_normalized with explicit normalize options.
PowerIO.warnings — Method
warnings(net::BalancedNetwork) -> Vector{String}
warnings(net::MulticonductorNetwork) -> Vector{String}The fidelity warnings retained on a live handle (pio_warnings) — what the reader could not represent or had to assume. Empty for a handle-less BalancedNetwork.
PowerIO.write_pypsa_csv_folder — Method
write_pypsa_csv_folder(net::BalancedNetwork, out_dir) -> (out_dir, warnings)Write net as a PyPSA CSV folder under out_dir (created if absent) — the directory inverse of parse_file(out_dir; from="pypsa-csv"), where the other writers (to_format, convert_file) emit a single text document. Returns the output directory and any fidelity warnings the writer reports for fields the PyPSA static-network CSV schema can't carry. Needs net's live Rust handle (from parse_file).
Accessors
PowerIO.branches — Method
Branches (lines and transformers), in source order.
PowerIO.bus_type_code — Method
bus_type_code(kind) -> IntMap the canonical bus-type string ("PQ", "PV", "REF", "ISOLATED") to the MATPOWER code (1, 2, 3, 4). The strings are the Rust core's BusType::as_str values.
PowerIO.buses — Method
Buses, in source order (1-based ids preserved). See the accessor API note.
PowerIO.generators — Method
Generators, one per machine (bus repeats when a bus has several).
PowerIO.hvdc — Method
Two-terminal HVDC lines (MATPOWER dcline); empty unless the source carries them.
PowerIO.is_radial — Method
is_radial(net) -> BoolWhether the in-service topology is radial (a forest), as the C ABI computes it (pio_is_radial). The same quantity as to_dense(net).is_radial, without building dense tables. Needs net's live Rust handle (from parse_file).
PowerIO.loads — Method
First-class loads (PSS/E and PowerModels keep several per bus; MATPOWER splits its bus row).
PowerIO.n_components — Method
n_components(net) -> IntNumber of connected components of the in-service topology, as the C ABI computes it (pio_n_islands). The same quantity as to_dense(net).n_components, without building dense tables. Needs net's live Rust handle (from parse_file).
PowerIO.n_gens — Method
n_gens(net) -> IntNumber of generator rows (one per machine; bus repeats). Matches pio_n_gens: every row, not in-service-filtered.
PowerIO.n_switches — Method
n_switches(net) -> IntNumber of switch rows (two-terminal ideal switches; PowerModels JSON carries them). Summary-backed like its count siblings — both summary builders always emit counts.switches, so a missing key is a schema skew and errors loudly. The dense fast path reads pio_n_switches directly (see to_dense).
PowerIO.network_name — Method
network_name(net) -> StringThe case name carried through from the source file.
PowerIO.reference_bus_id — Method
reference_bus_id(net) -> Union{Int,Nothing}The 1-based id of the reference (slack) bus, or nothing unless exactly one bus has kind == "REF". This mirrors the "exactly one" rule of the C ABI's pio_ref_bus_index (which returns a dense 0-based index, not an id), but returns the 1-based id space the other accessors use.
PowerIO.reference_bus_indices — Method
reference_bus_indices(net) -> Vector{Int}The dense [0, n) indices of every reference (slack) bus, in dense bus order. Unlike reference_bus_id — which returns a single 1-based id and only when exactly one bus is REF — this returns all of them (zero, one, or many) as dense indices. Map an index back to a 1-based id with to_dense(net).bus_ids. Needs net's live Rust handle (from parse_file).
PowerIO.shunts — Method
First-class bus shunts.
PowerIO.source_format — Method
source_format(net) -> StringThe format the case was read from, verbatim from the Rust SourceFormat enum. Examples include "Matpower", "PowerModelsJson", "EgretJson", "Psse", "PowerWorld", "PandapowerJson", "Pslf", "PypsaCsv", "Gridfm", "SurgeJson", "InMemory", and "Normalized" (the last is the output of to_normalized).
PowerIO.storage — Method
First-class storage units; empty unless the source carries them (PowerModels, egret).
Graph projections
PowerIO.to_graph — Method
to_graph(net::BalancedNetwork)Return the bus and in-service branch graph projection as a JSON3 object. buses includes every bus in dense order with source bus ids preserved; edges are in-service branches, with parallel branches kept as separate edges.
PowerIO.to_graph — Method
to_graph(net::MulticonductorNetwork)Return the collapsed bus and terminal graph projection as a JSON3 object. Needs a live handle from parse_file, parse_str, or from_package, and a v0.6.2 or newer powerio-capi library exporting pio_dist_graph_json.
Dense numeric extraction
PowerIO.to_dense — Method
to_dense(net::BalancedNetwork) -> NamedTuple
to_dense(path; from=nothing) -> NamedTuplePull a case's numeric tables as dense typed arrays straight from the C ABI, skipping the JSON transport (the fast path for matrix assembly). Takes a parsed BalancedNetwork (via its live handle) or a path to parse first (which never builds the JSON payload). Fields:
n,m,ng— bus / branch / generator counts.base_mva— system base.bus_ids::Vector{Int64}— 1-based bus ids in dense order; rowkof every per-bus table is busbus_ids[k]. Invert it to map a 1-based endpoint id to a dense row.branch— NamedTuple offrom, to(1-based bus ids),r, x, b, tap, shift(raw MATPOWER units, degrees, total charging, raw tap),in_service::Vector{UInt8}, and, with a powerio v0.7 library, the terminal charging splitg_fr, b_fr, g_to, b_to(per unit;b_fr + b_torecoversb, and a symmetric MATPOWER line splits asb/2).gen— NamedTuple ofbus(1-based id, one row per machine),pg, pmax, pmin(MW),in_service.demand,shunt— NamedTuples of per-bus(pd, qd)and(gs, bs)in dense order.reference_bus::Union{Int,Nothing}— dense 0-based index intobus_idsof the single reference bus (not a 1-based id), ornothingwhen there is no unique reference (none, or several). The C ABI spells that case-1; this binding maps it, matchingreference_bus_idand the Pythonto_dense.n_components::Int,is_radial::Bool— connectivity of the in-service topology.ns,switch(the last two fields, powerio v0.7 library) — switch count and the switch table:from, to(1-based bus ids),closed::Vector{UInt8},thermal_rating, current_rating, pf, qf, pt, qt(absent optionals are 0.0). Empty unless the source carries switches (PowerModels JSON).
The v0.7 fields (ns, switch, the charging columns) are present exactly when the resolved library exports their extractors; an older ABI-4 library returns the tuple without them instead of erroring or fabricating values.
For the rich, lossless element tables (costs, extras, storage, HVDC) use the accessors on a parse_file BalancedNetwork; for self-describing columnar export use to_arrow.
Matrices
PowerIO.AdmittanceMatrix — Type
PowerIO.AdmittanceMatrix{T}Sparse bus matrix plus the bus id mapping used by the matrix rows and columns. The layout matches PowerModels' AdmittanceMatrix: idx_to_bus[i] is the external bus id at sparse row i, bus_to_idx[id] is the row for a bus id, and matrix holds the sparse values.
PowerIO.calc_admittance_matrix — Method
calc_admittance_matrix(net::BalancedNetwork)
calc_admittance_matrix(path; from=nothing)Return the Rust computed bus admittance matrix Ybus as a PowerIO.AdmittanceMatrix{ComplexF64}. Matrix rows and columns use the dense row index chosen by Rust; idx_to_bus maps those rows back to external bus ids.
PowerIO.calc_bdoubleprime_matrix — Method
calc_bdoubleprime_matrix(net::BalancedNetwork)
calc_bdoubleprime_matrix(path; from=nothing)Return Rust's FDPF B'' matrix as a PowerIO.AdmittanceMatrix{Float64}.
PowerIO.calc_bprime_matrix — Method
calc_bprime_matrix(net::BalancedNetwork)
calc_bprime_matrix(path; from=nothing)Return Rust's FDPF B' matrix as a PowerIO.AdmittanceMatrix{Float64}. This preserves Rust's positive Laplacian convention.
PowerIO.calc_incidence_matrix — Method
calc_incidence_matrix(net::BalancedNetwork)
calc_incidence_matrix(path; from=nothing)Return the Rust computed signed incidence matrix as a SparseMatrixCSC{Float64,Int}. Rows use the matrix_bus axis and columns use the matrix_branch axis selected by Rust.
PowerIO.calc_susceptance_matrix — Method
calc_susceptance_matrix(net::BalancedNetwork)
calc_susceptance_matrix(path; from=nothing)Return a PowerModels sign convention susceptance matrix as a PowerIO.AdmittanceMatrix{Float64}. This is the sign adjusted form of Rust's B' matrix: calc_susceptance_matrix(net).matrix == -calc_bprime_matrix(net).matrix.
B' is the fast decoupled power flow matrix, so a phase shifting branch folds into the off diagonal and the result is not symmetric in general. On PowerModels' case5.m, whose 3-4 pair carries a one degree shift, the two off diagonal entries differ by 0.23.
It is therefore not the DC OPF B-theta Laplacian, which is a different matrix: that one weights each branch by DcConvention, stays symmetric, and routes phase shifts through the injection vector rather than the matrix. Build that one from calc_incidence_matrix and the branch series values.
Arrow export
PowerIO.ArrowColumn — Type
ArrowColumn{T} <: AbstractVector{T}One zero copy column of to_arrow(...; copy=false): a column over the producer's buffer that roots the shared ArrowBuffers owner, so the column alone keeps the memory alive — extracting it from its ArrowTable is safe. collect it for a plain owned Vector.
PowerIO.ArrowTable — Type
ArrowTableThe zero copy result of to_arrow(...; copy=false): a NamedTuple of ArrowColumn columns over the producer's buffers, behind property access (t.id, t.from, ...). Every property name resolves to a column — including t.columns, which would look up a column called columns — so the NamedTuple itself comes from the unexported accessor PowerIO.columns(t). The columns and the table each root the shared buffer owner, which frees the buffers once none of them is reachable; a column extracted from the table is safe on its own. close(t) frees the buffers eagerly instead of waiting for GC; surviving columns throw if read afterwards. (The default copy=true returns a plain NamedTuple of owned Vectors instead, no ArrowTable involved.)
Base.close — Method
close(t::ArrowTable)Release the producer's buffers now instead of at GC. Every ArrowColumn of t is invalid afterwards; reading one throws a Julia error. Idempotent (the release callbacks NULL themselves).
PowerIO.arrow_available — Method
arrow_available() -> BoolTrue if the resolved C library exports pio_to_arrow (built --features arrow). This checks the Arrow entry point, not that the loaded library supports every table selector this binding knows about.
PowerIO.arrow_catalog — Method
arrow_catalog() -> JSON3.ObjectThe Arrow table catalog (pio_arrow_catalog_json): what this library build can export over to_arrow, independent of any parsed network. Top level fields are powerio_version, producer, and tables; each table entry carries id, name, format, feature_requirements, available, row_axis, col_axis, units, and columns. Needs powerio-capi v0.7 built --features arrow.
PowerIO.matrix_available — Method
matrix_available() -> BoolTrue if the resolved C library exports pio_to_arrow and was built with the matrix Arrow table API.
PowerIO.release_c_data — Method
release_c_data(t::ArrowTable)
release_c_data(c::ArrowColumn)Release zero copy Arrow buffers explicitly. This mirrors the name used by the Arrow.jl C Data Interface import PR; close(t) is kept as the Julia table idiom. Calling it more than once is safe, and reads after release throw.
PowerIO.to_arrow — Method
to_arrow(net::BalancedNetwork, table::Symbol; copy=true) -> NamedTuple | ArrowTable
to_arrow(path, table::Symbol; from=nothing, copy=true) -> NamedTuple | ArrowTableExport one network table over the Arrow C Data Interface. Raw table selectors are :bus, :branch, :gen, :load, :shunt, and :switch; those columns are the parsed network fields with 1-based (external) bus ids, the same id space as to_dense. Normalized solver table selectors are :solver_bus, :solver_load, :solver_shunt, :solver_branch, :solver_switch, :solver_arc, :solver_gen, :solver_storage, and :solver_hvdc; those columns use dense 0-based row ids and per unit/radian values. Matrix selectors are :ybus, :incidence, :bprime, and :bdoubleprime; they return COO columns plus schema metadata. Matrix axis selectors are :matrix_bus and :matrix_branch; they map dense matrix rows and incidence columns back to source bus and branch rows. Takes a parsed BalancedNetwork (via its live handle) or a path to parse first. Needs powerio-capi built --features arrow; matrix selectors also need --features matrix; see arrow_available and matrix_available.
copy=true (default) returns a NamedTuple of owned Julia Vectors and releases the producer before returning: plain arrays, no lifetime caveat. copy=false returns a zero copy ArrowTable of ArrowColumn columns; each column roots the shared buffers, so columns can outlive the table until close(t) frees the buffers; reads after close throw. Both support result.<column> access, but only the copy=true NamedTuple is Tables.jl compatible (flows into Arrow.write, DataFrame, etc.); collect a zero copy column for an owned Vector. For the numeric tables alone, to_dense is a copy free, unsafe_wrap free fast path.
PowerModels.jl bridge
PowerIO.build_ref — Method
PowerIO.build_ref(network_data::Dict) -> Dict{Symbol,Any}Build a network reference dict from PowerModels network data (the to_powermodels output). The result is the flat equivalent of PowerModels.build_ref(data)[:it][:pm][:nw][0] restricted to:
:bus,:gen,:branch,:load,:shunt— integer-keyed component tables filtered to active elements on active buses (bus_type != 4, status fields ≠ 0, live endpoints):arcs_from,:arcs_to,:arcs—(branch_id, from_bus, to_bus)tuples:bus_arcs,:bus_gens,:bus_loads,:bus_shunts— per-bus index lists:ref_buses— buses withbus_type == 3:baseMVA
Not carried, unlike PowerModels: :buspairs, :storage, :switch, :dcline/:arcs_dc, and :areas — storage or dclines present in network_data do not appear in the ref. Branch angle bounds are corrected via PowerIO.correct_voltage_angle_differences! on the copies in ref[:branch]; network_data itself is not modified. Rows of every table except :branch are shared with network_data, not copied.
PowerIO.calc_branch_t — Method
PowerIO.calc_branch_t(branch::Dict) -> (Real, Real)Transformer tap components from tap ratio and phase shift angle: (tr, ti) where tr = tap*cos(shift) and ti = tap*sin(shift). Matches PowerModels.calc_branch_t.
PowerIO.calc_branch_y — Method
PowerIO.calc_branch_y(branch::Dict) -> (Real, Real)Branch conductance and susceptance (g, b) from the series impedance br_r + j*br_x. A zero impedance yields (0.0, 0.0), the scalar pseudo-inverse convention of PowerModels.calc_branch_y.
PowerIO.correct_voltage_angle_differences! — Method
PowerIO.correct_voltage_angle_differences!(network_data::Dict; default_pad=1.0472)Clamp branch angle difference bounds to ±default_pad (≈ π/3 rad). Full PowerModels network data routes through PowerIO's normalize pass when the loaded C ABI exports it; a bare branch table, or an older artifact without normalize options, keeps the PowerModels helper behavior. Angles are radians, the convention of to_powermodels output.
PowerIO.from_powermodels — Method
from_powermodels(data) -> BalancedNetworkBuild a PowerIO BalancedNetwork from PowerModels network data. data may be a Julia dictionary / NamedTuple or a JSON string.
PowerIO.to_powermodels — Method
to_powermodels(net::BalancedNetwork) -> Dict{String,Any}Convert a parsed network to a PowerModels network data dictionary through the PowerIO writer. This is the post-parse network data layout PowerModels.jl consumes.
ExaModelsPower / PowerData bridge
PowerIO.LoadSeries — Type
LoadSeries{T}A dense per-bus time series of loads over a parsed network. pd and qd are n_buses by n_periods matrices of active/reactive demand, per unit on base_mva and ordered by the network's buses; bus_ids[k] is the source id of row k, so the row-to-bus alignment is recorded rather than assumed. Read a period t off the matrices directly (series.pd[:, t]); get the counts with n_periods / n_buses.
This is a focused convenience for ExaModelsPower's multiperiod OPF, which supplies dense per-bus .Pd/.Qd load tables. PowerIO's general, format-neutral time series is the OperatingPointSeries (the type of the same name in the powerio Rust core): a time axis plus per-period sparse field updates over a base network, which represents more than loads and stores only what changes each period. A later release binds that type (gated on the construct/attach C ABI, eigenergy/powerio#236) and re-backs LoadSeries with it, but LoadSeries's surface — the pd/qd matrices, bus_ids, base_mva, and n_periods — stays stable and is not hard removed, so no consumer change is required when that lands.
Build one from a load matrix, a per-period demand multiplier, an id-keyed load table, or two whitespace-delimited files:
PowerIO.LoadSeries(net, pd_mw, qd_mw) # rows = buses in network order, MW
PowerIO.LoadSeries(net, curve) # scale the base-case loads per period
PowerIO.LoadSeries(net, pd_by_id, qd_by_id) # Dict(bus_id => per-period MW vector)
PowerIO.read_load_series(net, pd_path, qd_path) # same layout as the matrix form, from filesPowerIO.LoadSeries — Method
LoadSeries(net::BalancedNetwork, pd_by_id::AbstractDict, qd_by_id::AbstractDict; T=Float64)Build a series from id-keyed load tables: each dict maps a source bus id to its per-period MW vector. Every bus in net must have an entry and all vectors must share the same length. This removes the positional row assumption of the matrix form.
PowerIO.LoadSeries — Method
LoadSeries(net::BalancedNetwork, pd_mw, qd_mw; T=Float64)Build a series from active/reactive load matrices in MW, n_buses by n_periods, whose rows are the buses in net's order. Values are converted to per unit on the network's base MVA.
PowerIO.LoadSeries — Method
LoadSeries(net::BalancedNetwork, curve::AbstractVector; T=Float64)Build a series by scaling the base-case bus loads by curve[t] in each period t. Only the loads are scaled; fixed bus shunts stay at their base value.
PowerIO.demands_mw — Method
demands_mw(series::LoadSeries) -> (; pd, qd)The demand matrices rescaled to MW: series.pd .* series.base_mva and the same for qd. LoadSeries stores per unit, and the matrix and file constructors take MW, so this is the round trip back out for any interface that works in MW. Pass these matrices, never the per-unit fields, wherever MW is what is expected.
PowerIO.n_periods — Method
n_periods(series) -> IntNumber of periods in a LoadSeries.
PowerIO.parse_ac_power_data — Method
parse_ac_power_data(input; from=nothing, filtered=true, T=Float64) -> NamedTupleReturn the NamedTuple layout consumed by ExaModelsPower's build_polar_opf, build_rect_opf, and build_dcopf. input may be a BalancedNetwork or a path.
PowerIO.read_load_series — Method
read_load_series(net::BalancedNetwork, pd_path, qd_path; T=Float64)Read two whitespace-delimited MW load matrices (rows = buses in net's order, columns = periods) and build a LoadSeries. Reads the same .Pd / .Qd files a raw readdlm would, but dimension-checked, bus-aligned, and converted to per unit.
The files hold MW. A LoadSeries holds per unit. Reading series.pd and handing it to something that expects MW is off by baseMVA with no error; demands_mw is the conversion back out.
series = read_load_series(net, "case5.Pd", "case5.Qd")
series.pd # per unit
demands_mw(series).pd # MWPowerIO.to_powerdata — Method
to_powerdata(net; filtered=true, T=Float64) -> NamedTuple
to_powerdata(path; from=nothing, filtered=true, T=Float64) -> NamedTupleReturn a NamedTuple in ExaPowerIO's PowerData layout: version, baseMVA, bus, gen, branch, arc, and storage. Rows use the field names ExaModelsPower reads. With the default filtered=true, values are derived from to_normalized: bus_i preserves the source bus id, powers are per unit, branch angle fields are radians, and branch/generator bus references are indices into the bus vector.
This is an ExaModels-facing bridge (a Julia sibling of to_powermodels): the returned row schema is the field set ExaModelsPower's model builders read. It is not a general PowerIO representation and does not port to the Rust core / C ABI; for general numeric access use to_dense or to_arrow.
Operating point series
PowerIO.ElementUpdate — Type
ElementUpdateOne sparse per-period field overwrite: field of the row identified by source_uid (or the positional row) in table takes value. Mirrors the Rust ElementUpdate.
PowerIO.OperatingPoint — Type
OperatingPointOne period's operating state: the zero-based period index and the sparse updates applied to the base network for that period. Mirrors the Rust OperatingPoint.
PowerIO.OperatingPointSeries — Type
OperatingPointSeriesReserved skeleton for PowerIO's general, format-neutral multiperiod series — the Julia binding of the powerio Rust OperatingPointSeries (powerio-pkg/src/operating.rs). It is a TimeAxis plus a vector of OperatingPoints, each a sparse set of ElementUpdates (per-period field overwrites on any table, replayed over a base network). This is more general and more compact than the dense, loads-only LoadSeries: it carries changes to any field of any element, storing only what differs each period.
Not yet functional as a typed Julia value. The powerio C ABI reads, attaches, and materializes a series at the JSON level (pio_package_operating_points_json, pio_package_set_operating_points, pio_package_materialize_operating_point) — from Julia that is package_operating_points, set_operating_points, and materialize_operating_point on a NetworkPackage. What is still missing is a typed handle surface to back these structs directly, so the constructor and materialize_operating_point_series below throw until that binding lands; use set_operating_points with a JSON series, or LoadSeries for multiperiod bus loads. Unexported while it is a skeleton so a throwing constructor is not advertised as usable.
PowerIO.TimeAxis — Type
TimeAxisPeriod count, optional per-period durations (hours), and optional labels shared by every OperatingPoint in an OperatingPointSeries. Mirrors the Rust TimeAxis.
Distribution networks
PowerIO.MulticonductorNetwork — Type
MulticonductorNetworkA parsed multiconductor distribution case. parse_file and parse_str keep a live Rust handle and leave net.data empty until first table access. The first net.data access reads the pio-payload-multiconductor/1 JSON payload: buses, linecodes, lines, switches, transformers, loads, generators, ibrs, control_profiles, shunts, capacitors, sources, untyped, plus base_frequency, name, source_format, and parse warnings. The writer omits ibrs, control_profiles, and capacitors when they are empty; the accessors read a missing one as an empty table. String bus ids, ordered string terminal names, SI units, radians.
Build one with parse_file("feeder.dss") (the bare verb routes on the format) or the explicit parse_file(MulticonductorNetwork, path). A MulticonductorNetwork constructed from a bare payload object has handle === nothing; the accessors work on it, but the handle transforms (to_format, to_package) error. JSON carry with provenance is to_package / from_package; exchange with tools outside PowerIO is to_format(net, "bmopf").
As on BalancedNetwork, data is lazy: finalize(net.handle) before the first net.data access leaves the data-backed accessors with nothing to read and they raise a "handle was finalized" error. Access what you need before finalizing; the finalizer running at GC is the normal path and never hits this.
PowerIO.MulticonductorNetworkHandle — Type
MulticonductorNetworkHandleOpaque handle to a parsed multiconductor distribution case inside the Rust core, the distribution sibling of BalancedNetworkHandle. Freed by its finalizer; you normally go straight to parse_file, which returns a MulticonductorNetwork carrying the handle and lazily materialized element tables.
PowerIO.base_frequency — Method
base_frequency(net::MulticonductorNetwork) -> Float64The system frequency in Hz.
PowerIO.buses — Method
Buses, in source order: string ids, ordered terminals, explicit grounded terminals.
PowerIO.capacitors — Method
Rated capacitor banks (nameplate q_rated var, v_nom V). Empty when the case has none; dist_capabilities().typed_capacitors reports library support.
PowerIO.control_profiles — Method
Control profiles attached to controllable elements. Empty unless the source case carries them.
PowerIO.convert_file — Method
convert_file(MulticonductorNetwork, path, to; from=nothing) -> (text, warnings)Convert distribution case path to format to ("dss", "pmd", "bmopf") in one shot — the explicit form of the format-routed convert_file. from overrides extension inference (see parse_file(MulticonductorNetwork, ...)). Returns the converted text and the warnings (parse warnings plus the writer's fidelity losses, since there is no handle to query).
PowerIO.convert_str — Method
convert_str(MulticonductorNetwork, text, to, from) -> (text, warnings)Convert in-memory distribution case text of format from to format to (both required; "dss", "pmd", "bmopf"). The string sibling of convert_file(MulticonductorNetwork, ...).
PowerIO.dist_abi_version — Method
dist_abi_version() -> UInt32The distribution C ABI version reported by pio_dist_abi_version(). Compared against PIO_DIST_ABI_VERSION, the distribution ABI this binding targets.
PowerIO.dist_available — Method
dist_available() -> BoolTrue if the resolved C library exports pio_dist_parse_file (built --features dist, on by default in the released binaries) and reports the distribution ABI version this binding targets.
PowerIO.from_json — Method
from_json(MulticonductorNetwork, text) -> MulticonductorNetworkRebuild a live MulticonductorNetwork from the model JSON its data payload serializes to (pio_dist_to_json / JSON3.write(net.data), the same object a .pio.json package carries under model.multiconductor_network) — the distribution sibling of from_json(text). The rebuilt handle retains no source text, so a same format write is a fresh serialization. Needs powerio-capi v0.7 built --features dist.
PowerIO.generators — Method
Generators, each with a terminal_map and optional per-conductor s_max (VA) / i_max (A).
PowerIO.ibrs — Method
Inverter-based resources, each with a terminal_map. Empty unless the source case carries them.
PowerIO.linecodes — Method
Line codes: per-unit-length impedance and shunt matrices, row-major, SI. Optional source names the matrix provenance.
PowerIO.lines — Method
Lines (conductor-level), each with terminal_map_from / terminal_map_to and a linecode. Optional per-conductor i_max (A) and s_max (VA) override the linecode's ratings.
PowerIO.loads — Method
Loads, each with a terminal_map and a voltage model.
PowerIO.network_name — Method
network_name(net::MulticonductorNetwork) -> Union{String,Nothing}The case name, or nothing when the source carries none (unlike the balanced accessor, which always has one).
PowerIO.parse_file — Method
parse_file(MulticonductorNetwork, path; from=nothing) -> MulticonductorNetworkParse a distribution case file — the explicit form of the format-routed parse_file(path), selected by passing the target type first (the parse(T, x) idiom). The format is inferred from the file unless from is given: .dss is OpenDSS, a .json with the ENGINEERING data_model key is PMD, otherwise BMOPF JSON. from tokens: "dss", "pmd", "bmopf". Read parse warnings with warnings(net). Needs --features dist; see dist_available.
PowerIO.parse_str — Method
parse_str(MulticonductorNetwork, text, format) -> MulticonductorNetworkParse in-memory distribution case text of the named format ("dss", "pmd", or "bmopf"; required, there is no path to infer from) — the explicit form of the format-routed parse_str(text, format). An OpenDSS Redirect/Compile resolves against the current working directory.
PowerIO.shunts — Method
Shunts, each with a terminal_map and conductance/susceptance matrices.
PowerIO.source_format — Method
source_format(net::MulticonductorNetwork) -> Union{String,Nothing}The format the case was read from, as the payload spells it — note the casing differs from the balanced accessor's PascalCase SourceFormat names — or nothing for an in-memory model.
PowerIO.sources — Method
Voltage sources, each with a terminal_map and per-terminal magnitude/angle.
PowerIO.switches — Method
Switches, with the same terminal maps as lines.
PowerIO.to_format — Method
to_format(net::MulticonductorNetwork, to) -> (text, warnings)Serialize a MulticonductorNetwork to format to ("dss", "pmd", or "bmopf") — the distribution method of to_format. Writing back to the format the handle was parsed from echoes the source byte for byte; a cross-format write reports every fidelity loss in warnings. A balanced target is a directed error: lowering is explicit, through the package pass.
PowerIO.transformers — Method
Transformers: windings with terminal maps, connection kinds, and impedances.
PowerIO.untyped — Method
Elements the reader kept verbatim because they have no typed slot.
PowerIO.warnings — Method
warnings(net::MulticonductorNetwork) -> Vector{String}The parse warnings — everything the reader could not represent or had to assume. Read from the live handle (pio_dist_warnings) when there is one, else from the payload's warnings field, so they survive a package round trip.
.pio.json packages
PowerIO.NetworkPackage — Type
NetworkPackageJSON backed .pio.json network package envelope. A package carries one typed payload plus model kind, producer, origin, validation, summary, diagnostics, source maps, optional operating points, derived metadata, and lowering history. In Julia today the envelope remains JSON backed; solver, matrix, dense, and Arrow fast paths read live network handles, not package JSON.
PowerIO.from_package — Method
from_package(pkg::NetworkPackage) -> BalancedNetwork | MulticonductorNetwork
from_package(text::AbstractString)Read a .pio.json package back into the live model its envelope declares: a BalancedNetwork for a balanced payload, a MulticonductorNetwork for a multiconductor one. Lowering a multiconductor package to balanced stays explicit, through lower_multiconductor_to_balanced. A handle rebuilt from a package retains no source text, so a same-format write is a fresh serialization, not a byte-exact echo.
PowerIO.lower_multiconductor_to_balanced — Method
lower_multiconductor_to_balanced(pkg; base_mva=100.0) -> NetworkPackageLower a multiconductor package to a new balanced .pio.json package.
PowerIO.materialize_operating_point — Method
materialize_operating_point(pkg::NetworkPackage, index) -> NetworkPackageReturn a static package with operating point index applied. Indices are zero based to match the .pio.json payload.
PowerIO.materialize_study_commit — Method
materialize_study_commit(pkg::NetworkPackage, index) -> NetworkPackageReturn a static package with study commits 0:index applied. Indices are zero based to match the .pio.json payload.
PowerIO.multiconductor_to_balanced_preflight — Method
multiconductor_to_balanced_preflight(pkg; base_mva=100.0)Return the structured readiness report for lowering a multiconductor package to a balanced package.
PowerIO.package_available — Method
package_available() -> BoolTrue if the resolved C library exports the pio_package_* API.
PowerIO.package_diagnostics — Method
package_diagnostics(pkg::NetworkPackage)Return the package structured diagnostics array.
PowerIO.package_model_kind — Method
package_model_kind(pkg::NetworkPackage) -> SymbolReturn the explicit package model_kind, for example :balanced or :multiconductor.
PowerIO.package_operating_points — Method
package_operating_points(pkg::NetworkPackage)Return the package operating point series as a JSON3 value, or nothing.
PowerIO.package_study — Method
package_study(pkg::NetworkPackage)Return the package study block as a JSON3 value, or nothing.
PowerIO.package_validation — Method
package_validation(pkg::NetworkPackage)Return the package validation summary as a JSON3 object.
PowerIO.read_package — Method
read_package(path) -> NetworkPackageRead a .pio.json package envelope from disk. Uses the C package parser when available, with a JSON fallback so docs and pure parsing still work without a native library.
PowerIO.set_operating_points — Method
set_operating_points(pkg::NetworkPackage, series) -> NetworkPackageReturn a package with its operating point series replaced from series (pio_package_set_operating_points): JSON text, or any JSON-serializable value in the Rust OperatingPointSeries layout — time_axis (periods, duration_hours, optional labels) plus points, each an index and sparse updates of {element: {table, source_uid | row}, fields: {...}}. nothing (or JSON null, or an empty series) clears it. Package validation is recomputed before returning. Read the series back with package_operating_points and apply one point with materialize_operating_point. Needs powerio-capi v0.7 built --features pkg.
PowerIO.to_package — Method
to_package(net::BalancedNetwork; include_solver_metadata=false) -> NetworkPackage
to_package(net::MulticonductorNetwork) -> NetworkPackage
to_package(path; from=nothing, include_solver_metadata=false) -> NetworkPackageWrap a live PowerIO model in the .pio.json network package envelope. Balanced payloads come from pio_package_from_balanced_network; multiconductor payloads come from pio_package_from_multiconductor_network.
PowerIO.validate_package — Method
validate_package(pkg::NetworkPackage) -> NetworkPackageRun Rust's package semantic validation profile and return the validated package.
PowerIO.write_package — Method
write_package(path, pkg_or_net; include_solver_metadata=false) -> StringWrite a NetworkPackage, BalancedNetwork, or MulticonductorNetwork as .pio.json and return path.
GridFM reader
PowerIO.gridfm_available — Method
gridfm_available() -> BoolTrue if the resolved C library exports pio_read_dir (built --features gridfm).
PowerIO.read_gridfm — Method
read_gridfm(dir; scenario=0) -> (; network::BalancedNetwork, scenario::Int, warnings::Vector{String})Read one scenario of a gridfm-datakit Parquet dataset back into a BalancedNetwork — the inverse of the gridfm writer. dir resolves leniently: the raw/ directory holding the parquet files, a <case>/ directory with a raw/ child, or a parent with one */raw/ child. scenario selects one snapshot from a batch (0, the base case, by default).
The read is lossy but complete enough for power flow: it recovers bus types, voltages and limits, nodal load and shunt totals, generator dispatch and bounds, branch r/x/b/tap/shift/rate_a/angle-limits, and base_mva — enough to write a runnable case — but not original bus ids (synthesized 1..n), per-element load/shunt granularity, piecewise/cubic costs, or HVDC/storage. What it can't recover is listed in warnings.
The returned network carries a live Rust handle, so the to_* transforms work on it. Needs powerio-capi built --features gridfm; see gridfm_available. For every scenario in a batch use read_gridfm_scenarios.
PowerIO.read_gridfm_scenarios — Method
read_gridfm_scenarios(dir) -> VectorRead every scenario of a gridfm dataset, one read_gridfm result per scenario id (ascending) over the shared topology — the read side of a scenario batch. Each scenario is rebuilt independently, so two may differ in branch status, bus types, and reference bus. See read_gridfm for the lenient directory resolution and fidelity notes.
GO Challenge 3 helpers
PowerIO.ScopfInstance — Type
ScopfInstanceA derived, format-neutral security-constrained OPF instance built from a parsed GOC3 case by goc3_scopf_data: the SCOPF analog of the Rust core's DC-OPF OpfInstance (powerio-matrix). Every field is keyed by uid and per-class GOC3 ordering (j_ln/j_xf/j_dc/j_sh/n_p/n_q), with no model-specific stacked variable index. GOC3 is the input format, not this type: like OpfInstance, it is a projection a client reads to build a model, not a stored representation of a format.
Fields:
static: buses, shunts, AC/DC branches, transformer control sets, producers, consumers, zonal reserves, and device-zone membership sets. Producer and consumer rows carry the reactive capability block: the mutually exclusiveq_bound_capandq_linear_capflags, and thebeta_ub/beta_lb/q_0_ub/q_0_lborbeta/q_p0parameters of whichever is set. A device may set neither, in which case every parameter isNaN; read the flags before the parameters.lengths: the per-class set sizes, including the contingency countK.energy_windows: producer/consumer min and max energy windows and period memberships.price_blocks:(producer, consumer), one row per (device, period, cost block).ac_contingency_survivors:(ln, xf), per-contingency surviving AC lines/transformers.dc_contingency_flows: the flattened surviving-DC-line set.violation_cost:(p_bus, q_bus, s, e), the case's four violation prices.producers_first:truewhen the producer uid block precedes the consumer block. A model that stacks producers and consumers into one variable vector needs this to place its per-class offsets; seegoc3_scopf_datafor the check behind it.
PowerIO._goc3_ac_contingency_survivors — Method
_goc3_ac_contingency_survivors(data, lengths)Enumerate, for each contingency, the AC lines and transformers that remain in service (the branch is not among the contingency's outaged components). Returns (ln, xf) where each is a vector, in contingency order, of the surviving-branch rows for that contingency in lookup-iteration order. Rows carry the per-class fields (ctg, j_ln|j_xf, uid, to_bus, fr_bus, b_sr, s_max_ctg). The client attaches the stacked j, j_ac, the u_on status, and expands over periods.
PowerIO._goc3_dc_contingency_flows — Method
_goc3_dc_contingency_flows(data)Enumerate the surviving DC lines for each contingency and period, returning the flattened jtk_dc_flattened set. Rows carry the per-class j_dc; the client attaches the stacked j. Fully pure: no unit commitment status is involved for DC lines.
PowerIO._goc3_energy_windows — Method
_goc3_energy_windows(data)Build the multi-interval energy requirement window sets and their per-period membership sets, split by producer/consumer and by max/min. Returns a named tuple with fields W_en_max_pr, W_en_max_cs, W_en_min_pr, W_en_min_cs, T_w_en_max_pr, T_w_en_max_cs, T_w_en_min_pr, T_w_en_min_cs. Pure function of data.
PowerIO._goc3_price_blocks — Method
_goc3_price_blocks(cost_vector_pr, cost_vector_cs)Flatten the per-device energy cost curves into (p_jtm_flattened_pr, p_jtm_flattened_cs), one row per (device, period, cost block). Pure function of the cost vectors returned by _goc3_static_data.
PowerIO._goc3_producers_first — Method
_goc3_producers_first(data)Whether the producer uid block precedes the consumer block. A model that stacks both classes into one variable vector addresses a device by its uid number minus a per-class offset, which is a bijection only when each class owns one contiguous uid range.
Warns when the ranges interleave instead of throwing. The uid-suffix rule behind every per-class index here (j_ln, j_xf, j_dc, j_sh, and this one) assumes uids of the form <prefix>_<0-based index>, which official Challenge 3 scenario files use and GOCompetition's own 14-bus validation case does not: its uids are names like "Gen Bus 1 #1", so the rule reads bus numbers. Those indices are already unsound on such a file, so refusing here would reject a document the rest of this surface still parses, and the warning says so once rather than failing one field.
PowerIO._goc3_static_data — Method
_goc3_static_data(data)Build the static SCOPF index sets from a parse_goc3_json result. Returns (sc_data, lengths, cost_vector_pr, cost_vector_cs) where sc_data is the named tuple of buses, shunts, AC/DC branches, transformer control sets, producers, consumers, zonal reserves, and device-zone membership sets. Pure function of data; no unit commitment solution is used.
PowerIO._goc3_violation_cost — Method
_goc3_violation_cost(data)The case's four violation prices, typed. The document names them p_bus_vio_cost / q_bus_vio_cost / s_vio_cost / e_vio_cost; the _vio_cost suffix is dropped because the container already says violation cost.
Any of the four may be absent and then reads NaN: GOCompetition's own 14-bus validation case omits e_vio_cost, so requiring all four would reject a valid document. A model that prices a violation it did not find a cost for produces a NaN objective rather than a free violation.
PowerIO.goc3_add_status_flags! — Method
goc3_add_status_flags!(uc_data, lookup)Mutate UC output rows by adding su_status and sd_status from each row's on_status and the matching input table row's initial_status.on_status.
PowerIO.goc3_bus_id — Method
goc3_bus_id(data, uid) -> IntMap a GOC3 bus uid to its 1-based row index in the parsed bus table, using the bus_id_by_uid lookup built by parse_goc3_json. The result indexes data.bus_lookup and the per-bus vectors the SCOPF index-set builders return.
PowerIO.goc3_interval_bounds — Method
goc3_interval_bounds(dt, t)Return (a_start, a_mid, a_end) for interval t given interval durations dt.
PowerIO.goc3_scopf_data — Method
goc3_scopf_data(data) -> ScopfInstanceBuild the security-constrained OPF instance from a parse_goc3_json result in one call, superseding the internal _goc3_* builders. Pure function of data: no unit commitment solution and no model-specific variable numbering. A client reads the ScopfInstance fields and attaches its own stacked variable indices and UC status (see goc3_add_status_flags!). The instance carries every case field a SCOPF model needs, so a client reads parse_goc3_json's lookups only for the period axis (periods, dt) and to match a unit commitment solution back to devices.
producers_first reports which of the two device classes owns the lower uid block. A model that stacks producers and consumers into one variable vector derives its per-class offsets from a device's uid number, which requires each class to occupy one contiguous uid range; this errors when they interleave rather than returning offsets that would silently address the wrong device.
Retirement mirrors the DC-OPF path: the Rust core builds OpfInstance from the general IR via build_opf_instance (powerio-matrix), and the target is a canonical Rust ScopfInstance built by the same kind of projection, which this function then binds: a body swap, no consumer change. That is blocked today because the IR cannot yet represent a ScopfInstance's inputs: the Rust GOC3 reader keeps reliability, active_zonal_reserve, reactive_zonal_reserve, violation_cost, and dispatchable-device commitment/cost data source-only, and the operating-point series is a per-period field overwrite that cannot express cross-period energy budgets. Extending the IR with reserve, contingency, and temporal-constraint constructs is tracked in eigenergy/powerio#235. GOC3 stays a format and ScopfInstance is the derived instance (like OpfInstance), so no format is anointed in the core, though the GOC3 reserve-product taxonomy and energy windows leave a real tension a general model must resolve.
PowerIO.goc3_status_flags — Method
goc3_status_flags(on_status, initial_on_status)Return (on_status, su_status, sd_status) vectors using the GO Challenge 3 unit commitment transition convention used by ExaModelsPower.
PowerIO.parse_goc3_json — Method
parse_goc3_json(path)
parse_goc3_json(io)
parse_goc3_json(data)Parse a full ARPA-E GO Challenge 3 JSON input document into the lookup tables used by SCOPF clients. The returned named tuple includes the original string keyed JSON object as raw. To parse the static network into a BalancedNetwork, use parse_file(path; from="goc3-json").
Native SCOPF problem instances
PowerIO.parse_scopf — Method
parse_scopf(text; from="goc3-json") -> JSON3.ObjectParse SCOPF source text into the Rust core's native problem instance and return the versioned JSON pio_scopf_to_json produces for it. from names the source format; "goc3-json" (a full ARPA-E GO Challenge 3 input document) is the one accepted today. The returned object carries schema ("powerio.scopf.julia"), schema_version, index_base (1), and instance — static data, per-class lengths, energy windows, price blocks, and contingency survivor sets, the same fields as ScopfInstance.
This is the Rust-parsed sibling of the pure Julia goc3_scopf_data(parse_goc3_json(text)). One convention differs: pio_scopf_to_json numbers reserve zones and branches from document order, while the Julia builders derive them from uid numeric suffixes; the two agree on official GOC3 files (powerio v0.7.1 hardened the renumbering structurally, eigenergy/powerio#252).
PowerIO.scopf_available — Method
scopf_available() -> BoolTrue if the resolved C library exports the pio_scopf_* API (built --features prob, on in the released binaries from powerio v0.7.0).
Feature probes
PowerIO.build_info — Method
build_info() -> Union{NamedTuple,Nothing}Everything the loaded library reports about itself in one call: powerio_version, abi, a features table, foreign_schemas, and error_categories.
curl_version_info is the shape it follows, and the reason to prefer it over schema_versions, dist_capabilities and matrix_available: those answer one question each and need a new symbol to answer a new one, while this grows by adding a key. error_categories is the closed set of tokens that classify a C error message, for a caller that wants to branch on the kind of failure rather than match on prose.
Returns nothing when the library predates the entry point.
PowerIO.dist_capabilities — Method
dist_capabilities() -> NamedTupleReturn fine grained distribution fidelity capabilities reported by the resolved PowerIO C ABI.
The fields are dist, powerio_version, bmopf_fixed_taps, bmopf_center_tap_leakage, bmopf_delta_wye_leakage, bmopf_delta_roll, bmopf_voltage_source_merge, bmopf_transformer_diagnostics, typed_capacitors, line_and_generator_ratings, per_sequence_bus_bounds, transformer_extras_relocation, bmopf_schema_id, and bmopf_schema_version.
A library that does not export pio_dist_capabilities_json reports every flag false and every string nothing. A capability document that predates a flag reports the same false. A false flag means the library does not report the capability; a missing entry never raises an error.
bmopf_schema_id and bmopf_schema_version name the BMOPF schema vintage the library's writer targets. Both are nothing when the document predates them. Neither identifies a vintage alone; use them together.
PowerIO.features — Method
features() -> NamedTupleReturn the optional C ABI features available in the resolved library.
The fields are arrow, matrix, gridfm, dist, package, and prob. Each field reports "usable from Julia" (symbol present and, where one exists, the feature ABI handshake passes); has_feature asks the library itself what it was compiled with. Use this in downstream packages instead of probing private symbols.
PowerIO.has_feature — Method
has_feature(feature) -> BoolWhether the resolved library was compiled with the named cargo feature (pio_has_feature): "arrow", "matrix", "gridfm", "dist", "pkg" (the features field name "package" is accepted as an alias), or "prob". Unknown names return false; like the sibling probes this never throws — an unresolvable or ABI-incompatible library answers false. Unlike features, this is what the library says it was compiled with; it does not run the per-feature ABI handshakes. A pre-0.7 library without pio_has_feature is probed by each feature's representative entry point instead.
PowerIO.schema_versions — Method
schema_versions() -> NamedTupleReturn the versions the resolved library reports through pio_schema_versions_json (powerio v0.9).
The fields are powerio_version, abi, and bmopf_schema. Every document powerio authors states one version, the release that wrote it, so the per-document lineages this used to report (package, arrow) are gone. bmopf_schema names a foreign schema the IEEE task force owns, which is why it stays separate. A field the document does not carry is nothing. A library without the entry point reports every field nothing; a missing report never raises an error.
Library resolution and ABI
PowerIO.BalancedNetworkHandle — Type
BalancedNetworkHandleOpaque handle to a parsed network inside the Rust core. Freed by its finalizer; you normally go straight to parse_file, which returns a [BalancedNetwork].
PowerIO.abi_version — Method
abi_version() -> UInt32The ABI version the resolved C library was built with (see pio_abi_version). Compared against PIO_ABI_VERSION, the version this binding targets.
PowerIO.clear_library! — Method
clear_library!(; persist=false)Clear the in-session library override. Pass persist=true to also clear the saved Preferences.jl library override. POWERIO_CAPI, when set, still wins on this session's next call.
PowerIO.library_available — Method
library_available() -> BoolTrue if the C ABI library resolves and is ABI compatible with this binding (see abi_version).
PowerIO.library_version — Method
library_version() -> StringThe powerio-capi crate version string the resolved library reports (e.g. "0.3.1"). Informational; abi_version is the compatibility check.
PowerIO.set_library! — Method
set_library!(path; persist=false)Point PowerIO at a locally built libpowerio_capi (cargo build -p powerio-capi --release in the PowerIO Rust tree → target/release/libpowerio_capi.{dylib,so}). An in-session override wins over POWERIO_CAPI, the saved Preferences.jl override, and the bundled artifact. Pass persist=true to save the path in the active environment's LocalPreferences.toml.