Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Getting started

Install

Rust:

cargo add powerio             # parsing, emission, PowerIO IR
cargo add powerio -F matrix   # and sparse matrices, sensitivities, graph data

Use Rust 1.88 or newer. Add the gridfm feature when your application reads or writes GridFM Parquet directories: cargo add powerio -F gridfm.

Python:

pip install powerio           # parsing, emission, PowerIO IR
pip install 'powerio[all]'    # and SciPy matrices, NetworkX graphs, Polars for GridFM

Julia:

using Pkg; Pkg.add("PowerIO")

The powerio command:

cargo install powerio-cli

For C and C++, build the shared library from a checkout and include the checked in header.

git clone https://github.com/eigenergy/powerio
cd powerio
cargo build -p powerio-capi --release --features arrow,matrix,gridfm,dist,prob
# target/release/libpowerio_capi.{so,dylib,dll}; header powerio-capi/include/powerio.h

Parse, inspect, emit

Download case9.m to your working directory for these examples. In a repository checkout, the same file is tests/data/case9.m; pass that path when running from the root.

Rust. The example is a complete program; it imports only parse, emit, and the PioValue enum, and ? hands any failure to main.

use powerio::{PioValue, emit, parse};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let module = parse("case9.m")?;
    let PioValue::BalancedNetwork(network) = module.value() else {
        panic!("expected a balanced network");
    };
    println!("{} buses", network.buses().len());
    for finding in module.diagnostics() {
        eprintln!("{}: {}", finding.code(), finding.message());
    }
    emit(&module, "matpower", "copy.m")?;      // the source bytes, unchanged
    let result = emit(&module, "psse", "case9.raw")?;
    for finding in result.diagnostics() {
        eprintln!("{}", finding.code());       // what PSS/E cannot carry
    }
    Ok(())
}

Python:

import powerio

module = powerio.parse("case9.m")
network = module.value                       # BalancedNetwork
for finding in module.diagnostics:
    print(finding.code, finding.message)
powerio.emit(module, "matpower", "copy.m")   # the source bytes, unchanged
result = powerio.emit(module, "psse")        # text in memory
result.text
result.diagnostics

Julia:

using PowerIO

module_ = parse("case9.m")
net = module_.value                          # BalancedNetwork
length(net.buses)                            # 9
module_.diagnostics
emit(module_, "matpower", "copy.m")          # the source bytes, unchanged
result = emit(module_, "psse")               # text in memory
result.diagnostics

Command line:

powerio convert case9.m --to psse -o case9.raw   # findings on stderr
powerio summary case9.m                          # counts, bases, and findings as JSON

Keep a module for later

Use serialize to save the value with its diagnostics and history, then deserialize to restore it in any PowerIO binding:

powerio::serialize(&module, "case9.pio.json")?;
let restored = powerio::deserialize("case9.pio.json")?;
powerio.serialize(module, "case9.pio.json")
restored = powerio.deserialize("case9.pio.json")
serialize(module_, "case9.pio.json")
restored = deserialize("case9.pio.json")

PowerIO IR stores the typed data and source metadata. Original input bytes stay in memory, so an unchanged parsed module can echo them, while a restored module produces fresh output. Inspect the returned emission diagnostics when exporting to another tool.

Where next