API reference

The module

PowerIO.PowerIOModule
PowerIO

Julia 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_fileBalancedNetwork, 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 with copy=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.

source

Parsing, conversion, serialization

PowerIO.BalancedNetworkType
BalancedNetwork

A 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.

source
PowerIO.convert_fileMethod
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.

source
PowerIO.convert_strMethod
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.

source
PowerIO.parse_bytesMethod
parse_bytes(bytes, format) -> BalancedNetwork

Parse 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.

source
PowerIO.parse_fileMethod
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) -> MulticonductorNetwork

Parse 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.

source
PowerIO.parse_strFunction
parse_str(text, format="matpower") -> BalancedNetwork | MulticonductorNetwork
parse_str(MulticonductorNetwork, text, format) -> MulticonductorNetwork

Parse 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.

source
PowerIO.to_formatMethod
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.

source
PowerIO.to_jsonMethod
to_json(net::BalancedNetwork) -> String

Serialize 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.

source
PowerIO.to_matpowerMethod
to_matpower(net::BalancedNetwork) -> String

Serialize net to MATPOWER .m text, byte exact when the input was MATPOWER. For a file in one shot use convert_file(path, "matpower").

source
PowerIO.to_normalizedMethod
to_normalized(net::BalancedNetwork; clamp_angle_bounds=false, angle_bound_pad=nothing) -> BalancedNetwork

A 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.

source
PowerIO.warningsMethod
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.

source
PowerIO.write_pypsa_csv_folderMethod
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).

source

Accessors

PowerIO.bus_type_codeMethod
bus_type_code(kind) -> Int

Map 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.

source
PowerIO.busesMethod

Buses, in source order (1-based ids preserved). See the accessor API note.

source
PowerIO.hvdcMethod

Two-terminal HVDC lines (MATPOWER dcline); empty unless the source carries them.

source
PowerIO.is_radialMethod
is_radial(net) -> Bool

Whether 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).

source
PowerIO.loadsMethod

First-class loads (PSS/E and PowerModels keep several per bus; MATPOWER splits its bus row).

source
PowerIO.n_componentsMethod
n_components(net) -> Int

Number 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).

source
PowerIO.n_gensMethod
n_gens(net) -> Int

Number of generator rows (one per machine; bus repeats). Matches pio_n_gens: every row, not in-service-filtered.

source
PowerIO.n_switchesMethod
n_switches(net) -> Int

Number 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).

source
PowerIO.reference_bus_idMethod
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.

source
PowerIO.reference_bus_indicesMethod
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).

source
PowerIO.source_formatMethod
source_format(net) -> String

The 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).

source
PowerIO.storageMethod

First-class storage units; empty unless the source carries them (PowerModels, egret).

source

Graph projections

PowerIO.to_graphMethod
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.

source
PowerIO.to_graphMethod
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.

source

Dense numeric extraction

PowerIO.to_denseMethod
to_dense(net::BalancedNetwork) -> NamedTuple
to_dense(path; from=nothing) -> NamedTuple

Pull 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; row k of every per-bus table is bus bus_ids[k]. Invert it to map a 1-based endpoint id to a dense row.
  • branch — NamedTuple of from, 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 split g_fr, b_fr, g_to, b_to (per unit; b_fr + b_to recovers b, and a symmetric MATPOWER line splits as b/2).
  • gen — NamedTuple of bus (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 into bus_ids of the single reference bus (not a 1-based id), or nothing when there is no unique reference (none, or several). The C ABI spells that case -1; this binding maps it, matching reference_bus_id and the Python to_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.

source

Matrices

PowerIO.AdmittanceMatrixType
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.

source
PowerIO.calc_admittance_matrixMethod
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.

source
PowerIO.calc_bdoubleprime_matrixMethod
calc_bdoubleprime_matrix(net::BalancedNetwork)
calc_bdoubleprime_matrix(path; from=nothing)

Return Rust's FDPF B'' matrix as a PowerIO.AdmittanceMatrix{Float64}.

source
PowerIO.calc_bprime_matrixMethod
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.

source
PowerIO.calc_incidence_matrixMethod
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.

source
PowerIO.calc_susceptance_matrixMethod
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.

source

Arrow export

PowerIO.ArrowColumnType
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.

source
PowerIO.ArrowTableType
ArrowTable

The 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.)

source
Base.closeMethod
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).

source
PowerIO.arrow_availableMethod
arrow_available() -> Bool

True 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.

source
PowerIO.arrow_catalogMethod
arrow_catalog() -> JSON3.Object

The 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.

source
PowerIO.matrix_availableMethod
matrix_available() -> Bool

True if the resolved C library exports pio_to_arrow and was built with the matrix Arrow table API.

source
PowerIO.release_c_dataMethod
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.

source
PowerIO.to_arrowMethod
to_arrow(net::BalancedNetwork, table::Symbol; copy=true) -> NamedTuple | ArrowTable
to_arrow(path, table::Symbol; from=nothing, copy=true) -> NamedTuple | ArrowTable

Export 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.

source

PowerModels.jl bridge

PowerIO.build_refMethod
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 with bus_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.

source
PowerIO.calc_branch_tMethod
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.

source
PowerIO.calc_branch_yMethod
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.

source
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.

source
PowerIO.to_powermodelsMethod
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.

source

ExaModelsPower / PowerData bridge

PowerIO.LoadSeriesType
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 files
source
PowerIO.LoadSeriesMethod
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.

source
PowerIO.LoadSeriesMethod
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.

source
PowerIO.LoadSeriesMethod
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.

source
PowerIO.demands_mwMethod
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.

source
PowerIO.parse_ac_power_dataMethod
parse_ac_power_data(input; from=nothing, filtered=true, T=Float64) -> NamedTuple

Return the NamedTuple layout consumed by ExaModelsPower's build_polar_opf, build_rect_opf, and build_dcopf. input may be a BalancedNetwork or a path.

source
PowerIO.read_load_seriesMethod
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.

Units

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  # MW
source
PowerIO.to_powerdataMethod
to_powerdata(net; filtered=true, T=Float64) -> NamedTuple
to_powerdata(path; from=nothing, filtered=true, T=Float64) -> NamedTuple

Return 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.

source

Operating point series

PowerIO.ElementUpdateType
ElementUpdate

One 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.

source
PowerIO.OperatingPointType
OperatingPoint

One 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.

source
PowerIO.OperatingPointSeriesType
OperatingPointSeries

Reserved 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.

source

Distribution networks

PowerIO.MulticonductorNetworkType
MulticonductorNetwork

A 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.

source
PowerIO.busesMethod

Buses, in source order: string ids, ordered terminals, explicit grounded terminals.

source
PowerIO.capacitorsMethod

Rated capacitor banks (nameplate q_rated var, v_nom V). Empty when the case has none; dist_capabilities().typed_capacitors reports library support.

source
PowerIO.convert_fileMethod
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).

source
PowerIO.convert_strMethod
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, ...).

source
PowerIO.dist_abi_versionMethod
dist_abi_version() -> UInt32

The distribution C ABI version reported by pio_dist_abi_version(). Compared against PIO_DIST_ABI_VERSION, the distribution ABI this binding targets.

source
PowerIO.dist_availableMethod
dist_available() -> Bool

True 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.

source
PowerIO.from_jsonMethod
from_json(MulticonductorNetwork, text) -> MulticonductorNetwork

Rebuild 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.

source
PowerIO.generatorsMethod

Generators, each with a terminal_map and optional per-conductor s_max (VA) / i_max (A).

source
PowerIO.ibrsMethod

Inverter-based resources, each with a terminal_map. Empty unless the source case carries them.

source
PowerIO.linecodesMethod

Line codes: per-unit-length impedance and shunt matrices, row-major, SI. Optional source names the matrix provenance.

source
PowerIO.linesMethod

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.

source
PowerIO.network_nameMethod
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).

source
PowerIO.parse_fileMethod
parse_file(MulticonductorNetwork, path; from=nothing) -> MulticonductorNetwork

Parse 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.

source
PowerIO.parse_strMethod
parse_str(MulticonductorNetwork, text, format) -> MulticonductorNetwork

Parse 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.

source
PowerIO.shuntsMethod

Shunts, each with a terminal_map and conductance/susceptance matrices.

source
PowerIO.source_formatMethod
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.

source
PowerIO.sourcesMethod

Voltage sources, each with a terminal_map and per-terminal magnitude/angle.

source
PowerIO.to_formatMethod
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.

source
PowerIO.warningsMethod
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.

source

.pio.json packages

PowerIO.NetworkPackageType
NetworkPackage

JSON 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.

source
PowerIO.from_packageMethod
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.

source
PowerIO.materialize_operating_pointMethod
materialize_operating_point(pkg::NetworkPackage, index) -> NetworkPackage

Return a static package with operating point index applied. Indices are zero based to match the .pio.json payload.

source
PowerIO.materialize_study_commitMethod
materialize_study_commit(pkg::NetworkPackage, index) -> NetworkPackage

Return a static package with study commits 0:index applied. Indices are zero based to match the .pio.json payload.

source
PowerIO.package_model_kindMethod
package_model_kind(pkg::NetworkPackage) -> Symbol

Return the explicit package model_kind, for example :balanced or :multiconductor.

source
PowerIO.read_packageMethod
read_package(path) -> NetworkPackage

Read 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.

source
PowerIO.set_operating_pointsMethod
set_operating_points(pkg::NetworkPackage, series) -> NetworkPackage

Return 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.

source
PowerIO.to_packageMethod
to_package(net::BalancedNetwork; include_solver_metadata=false) -> NetworkPackage
to_package(net::MulticonductorNetwork) -> NetworkPackage
to_package(path; from=nothing, include_solver_metadata=false) -> NetworkPackage

Wrap 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.

source
PowerIO.validate_packageMethod
validate_package(pkg::NetworkPackage) -> NetworkPackage

Run Rust's package semantic validation profile and return the validated package.

source

GridFM reader

PowerIO.read_gridfmMethod
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.

source
PowerIO.read_gridfm_scenariosMethod
read_gridfm_scenarios(dir) -> Vector

Read 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.

source

GO Challenge 3 helpers

PowerIO.ScopfInstanceType
ScopfInstance

A 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 exclusive q_bound_cap and q_linear_cap flags, and the beta_ub/beta_lb/q_0_ub/q_0_lb or beta/q_p0 parameters of whichever is set. A device may set neither, in which case every parameter is NaN; read the flags before the parameters.
  • lengths: the per-class set sizes, including the contingency count K.
  • 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: true when 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; see goc3_scopf_data for the check behind it.
source
PowerIO._goc3_ac_contingency_survivorsMethod
_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.

source
PowerIO._goc3_dc_contingency_flowsMethod
_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.

source
PowerIO._goc3_energy_windowsMethod
_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.

source
PowerIO._goc3_price_blocksMethod
_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.

source
PowerIO._goc3_producers_firstMethod
_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.

source
PowerIO._goc3_static_dataMethod
_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.

source
PowerIO._goc3_violation_costMethod
_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.

source
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.

source
PowerIO.goc3_bus_idMethod
goc3_bus_id(data, uid) -> Int

Map 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.

source
PowerIO.goc3_scopf_dataMethod
goc3_scopf_data(data) -> ScopfInstance

Build 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.

source
PowerIO.goc3_status_flagsMethod
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.

source
PowerIO.parse_goc3_jsonMethod
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").

source

Native SCOPF problem instances

PowerIO.parse_scopfMethod
parse_scopf(text; from="goc3-json") -> JSON3.Object

Parse 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).

source
PowerIO.scopf_availableMethod
scopf_available() -> Bool

True if the resolved C library exports the pio_scopf_* API (built --features prob, on in the released binaries from powerio v0.7.0).

source

Feature probes

PowerIO.build_infoMethod
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.

source
PowerIO.dist_capabilitiesMethod
dist_capabilities() -> NamedTuple

Return 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.

source
PowerIO.featuresMethod
features() -> NamedTuple

Return 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.

source
PowerIO.has_featureMethod
has_feature(feature) -> Bool

Whether 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.

source
PowerIO.schema_versionsMethod
schema_versions() -> NamedTuple

Return 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.

source

Library resolution and ABI

PowerIO.abi_versionMethod
abi_version() -> UInt32

The ABI version the resolved C library was built with (see pio_abi_version). Compared against PIO_ABI_VERSION, the version this binding targets.

source
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.

source
PowerIO.library_versionMethod
library_version() -> String

The powerio-capi crate version string the resolved library reports (e.g. "0.3.1"). Informational; abi_version is the compatibility check.

source
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.

source