Format fidelity and validation

How powerio's readers and writers are validated, the conventions they follow, and the known limits. The headline fidelity table is in the README; this document covers the conventions and the proof behind it.

Conventions

powerio's numeric conventions match MATPOWER and PowerModels.jl. The reference implementations and the matching powerio code:

Quantity Convention Reference powerio
Bus type codes 1=PQ, 2=PV, 3=ref, 4=isolated MATPOWER idx_bus network::BusType
Impedance, susceptance per unit on baseMVA, never rescaled MATPOWER idx_brch (BR_B already per unit) format::matpower
Line charging b split half to each end (b_fr = b_to = BR_B/2) PowerModels matpower.jl format::powermodels
Tap ratio 0 means a line (treated as 1); nonzero is a transformer MATPOWER idx_brch TAP Branch::effective_tap
Phase shift, angle degrees in the model; PowerModels JSON carries radians PowerModels make_per_unit! format::powermodels
Angle limits angmin/angmax default ±360 (unconstrained) MATPOWER idx_brch ANGMIN/ANGMAX Branch::has_angle_limits
pandapower/PyPSA impedance line r/x are converted between per unit and ohms with Zbase = V_kV² / baseMVA; pandapower line charging is capacitance per km (c_nf_per_km, converted via 2π·f·length·Zbase); PyPSA line b is siemens pandapower PPC conversion, PyPSA static components format::pandapower, format::pypsa
dcline Pt/Qf/Qt sign flips vs MATPOWER PowerModels matpower.jl format::powermodels
Generator cost c2 p² + c1 pq = 2c2, c = c1; coefficients high order first MATPOWER idx_cost, egret matpower_parser GenCost::quadratic
source_id ["bus", id] for bus-tied elements PowerModels matpower.jl format::powermodels

egret's own MATPOWER parser uses the same reductions (bus type as matpower_bustype, polynomial coefficients reversed to a {degree: coefficient} map, piecewise to [[mw, cost], ...], impedances left per unit), which is why a MATPOWER case taken through powerio to egret JSON matches egret's direct import.

Validation

The harness script benchmarks/run_validation.sh checks powerio against five independent tools. Every classic text reader and writer runs under an oracle: the conversion matrix covers MATPOWER, PSS/E, and egret sources against all five legacy text targets, every PowerWorld output is read back and bridged to PowerModels JSON, and the PMread leg covers the PowerModels JSON read side. pandapower JSON and PyPSA CSV folders have dedicated import validators because pandapower has its own JSON schema and PyPSA is a directory format; both validate the write direction only — the pandapower JSON and PyPSA readers have no external oracle. They, and the remaining source/target pairs (PowerModels JSON and PowerWorld sources into the non-PowerModels targets), rest on the Rust round trip suite.

The conversion matrix

benchmarks/validate_matrix.py converts each source to every legacy text target and checks the electrical core of the output (bus/branch/generator counts and the per unit demand, generation, and shunt totals) against the source's own core, read by an independent oracle. The diagonal is checked byte exact: writing back to the source format reproduces the file. Sources use the real native files where they exist (the vendored PSS/E .raw and egret .json) and representative MATPOWER cases otherwise: basic (case9), shunts and transformers (case14, case30), size (case118, case2869pegase), HVDC with a mixed piecewise/polynomial gencost (t_case9_dcline), and a piecewise-cost case (pglib_opf_case5_pjm).

All 65 legacy text cells pass (13 source cases × 5 targets). The core is preserved by every writer regardless of fidelity tier, so it is the invariant checked across the whole matrix; cost, HVDC, and angle limits are tier specific and covered by the dedicated checks above and the Rust suite. The pandapower JSON and PyPSA CSV validators run alongside this matrix and are reported as separate legs.

Running it

cargo build --release -p powerio-capi
maturin develop --release                          # the powerio wheel
julia --project=benchmarks -e 'using Pkg; Pkg.instantiate()'
pip install -r benchmarks/requirements.txt         # pandapower + egret + PyPSA oracles
bash benchmarks/run_validation.sh

The oracle tools (PowerModels.jl, egret, ExaPowerIO.jl, pandapower, PyPSA) are benchmark scoped: they are declared in benchmarks/Project.toml and benchmarks/requirements.txt, never as dependencies of the powerio package.

Known limits

Write side losses are reported in Conversion::warnings; the pandapower and PyPSA readers itemize what they ignore in Parsed::warnings (read_warnings in Python), naming the table and counting the affected rows. convert_file/convert_str fold the read warnings into Conversion::warnings.