Interop
| Target | Direction | Mechanism |
|---|---|---|
| PowerModels.jl | both | to_powermodels, from_powermodels through PowerModels JSON |
| ExaModelsPower.jl | out | to_powerdata, to_ac_power_data, LoadSeries |
| GridFM | both | parse of a Parquet dataset, emit(m, "gridfm") |
| PyPSA | both | parse of a CSV folder, emit(m, "pypsa-csv", dir) |
| PowerModelsDistribution.jl | both | emit(m, "pmd"), parse of PMD JSON |
| BMOPF | both | emit(m, "bmopf"), parse of BMOPF JSON |
| Other PowerIO consumers | both | serialize, deserialize (PowerIO IR) |
PowerModels.jl
to_powermodels writes the module through the PowerModels JSON writer and returns the network data dictionary PowerModels.jl reads: per unit powers, angles in radians, string keyed component tables. from_powermodels parses such a dictionary (or its JSON text) back into a PioModule{BalancedNetwork}.
case = parse("case14.m")
data = to_powermodels(case)
data["bus"]["1"]["bus_type"] # 3
back = from_powermodels(data) # PioModule{BalancedNetwork}build_powermodels_ref builds the flat reference dictionary (:bus, :gen, :branch, :arcs, :bus_arcs, :ref_buses, ...) that PowerModels models index, and repair_powermodels_angle_bounds! clamps branch angle difference bounds the way PowerModels.correct_voltage_angle_differences! does.
ExaModelsPower.jl
to_powerdata returns ExaPowerIO's PowerData layout (bus, gen, branch, arc, storage rows with the fields ExaModelsPower reads), and to_ac_power_data adds the bound and initial value vectors its build_*_opf functions take. Powers are per unit, angles are radians, and bus references are positions in the bus table.
data = to_ac_power_data("case118.m")
data.ref_buses
data.pmaxPowerIO.LoadSeries builds dense per bus load matrices over several periods for the multiperiod models, from a matrix in MW, a per period multiplier, an id keyed table, or two files.
GridFM
A GridFM Parquet dataset parses into a ScenarioSet{BalancedNetwork} with one network per scenario, and emit(m, "gridfm", dir) writes a dataset. Both need a powerio library built with the gridfm feature. The release binaries include it; a build without it reports a coded parse error naming the feature.
PowerIO IR
serialize and deserialize pass a complete module, with its diagnostics and history, to another PowerIO consumer in Rust, Python, Julia, or C. The document is JSON with "schema": "pio-ir" and an integer generation, "version": 2. The producer record separately names the PowerIO release that wrote it, and library_version reports the library's own release. PowerIO 0.11.1 reads generation 2. Existing types keep their representation; LinDist3Flow types require a reader implementing them.
PowerIO.to_powermodels — Function
to_powermodels(m::PioModule{BalancedNetwork}) -> Dict{String,Any}
to_powermodels(net::BalancedNetwork) -> Dict{String,Any}The network as a PowerModels network data dictionary, written by the PowerIO PowerModels JSON writer: per unit powers, radian angles, string keyed component tables. A bare BalancedNetwork works when it came straight from a module; a network reached through a collection or an instance has no module of its own, so pass the module instead.
PowerIO.from_powermodels — Function
from_powermodels(data) -> PioModule{BalancedNetwork}Parse PowerModels network data, given as a dictionary, a NamedTuple, or a JSON string, into a network module.
PowerIO.build_powermodels_ref — Function
build_powermodels_ref(network_data::Dict) -> Dict{Symbol,Any}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 nonzero, 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.
Storage, switches, DC lines, and areas are not carried. Branch angle bounds in ref[:branch] are repaired with repair_powermodels_angle_bounds! on copies; every other table shares its rows with network_data.
PowerIO.repair_powermodels_angle_bounds! — Function
repair_powermodels_angle_bounds!(network_data::Dict; default_pad=1.0472)Clamp every branch angle difference bound in a PowerModels network data dictionary to [-default_pad, default_pad] radians, the correction PowerModels.correct_voltage_angle_differences! applies: a lower bound at or below -pi/2 becomes -default_pad, an upper bound at or above pi/2 becomes default_pad, and a zero width band opens to the full pad. Returns the dictionary.
PowerIO.to_powerdata — Function
to_powerdata(net; T=Float64, strict=true, zero_impedance=:error) -> NamedTuple
to_powerdata(m::PioModule{BalancedNetwork}; kwargs...) -> NamedTuple
to_powerdata(path; format=nothing, kwargs...) -> NamedTupleThe network in ExaPowerIO's PowerData layout: version, baseMVA, bus, gen, branch, arc, and storage, with the row fields ExaModelsPower reads. Powers are per unit on baseMVA, angles are radians (bus.va included), bus_i keeps the source bus id, and branch and generator bus references are 1-based positions in bus. Bus types are reconciled with the generator table: a bus with an in-service generator is at least PV, a bus without one is PQ, and when no bus is the reference the bus with the largest generator becomes it.
Every row is emitted with its status; the caller selects on it. Validation runs only on rows that are in service: a field may be Inf only where a source format spells an absent limit that way (generator and storage power limits, branch ratings, and angle difference bounds), every other non-finite value is refused with the element and field named, and a polynomial cost that cannot fit a quadratic is refused. An out of service row is copied as stated, its cost coefficients zero. strict=false copies in-service rows as stated too.
Each generator row carries model: 0 without a cost record, otherwise cost.model verbatim (1 piecewise linear, 2 polynomial), beside model_poly.
Each branch row carries the eight admittance coefficients ExaModelsPower reads: c1 + im*c2 = y_tf, c3 + im*c4 = y_ft, c5 + im*c6 = y_ff, and c7 + im*c8 = y_tt in MATPOWER's makeYbus notation; see calc_branch_admittances. An in-service branch with zero series impedance is a PowerIOError with code BUILD.OPERATOR.ZERO_IMPEDANCE (zero_impedance=:error, the convention of the DC calculations and calc_admittance_matrix); zero_impedance=:open states it as an open circuit instead, c1..c4 zero and c5..c8 carrying the charging alone.
PowerIO.to_ac_power_data — Function
to_ac_power_data(net; T=Float64) -> NamedTuple
to_ac_power_data(m::PioModule{BalancedNetwork}; T=Float64) -> NamedTuple
to_ac_power_data(path; format=nothing, T=Float64) -> NamedTupleThe layout ExaModelsPower's build_polar_opf, build_rect_opf, and build_dcopf consume: the to_powerdata tables plus the bound and initial value vectors they read (ref_buses, vmax, vmin, pmax, pmin, qmax, qmin, angmax, angmin, rate_a, vm0, va0, pg0, qg0, and the storage ratings).
PowerIO.LoadSeries — Type
LoadSeries{T}Dense per bus loads over several periods for ExaModelsPower's multiperiod OPF. pd and qd are n_buses by n_periods matrices per unit on base_mva, ordered like the network's bus table; bus_ids[k] is the source id of row k.
PowerIO.LoadSeries(net, pd_mw, qd_mw) # rows are 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) # the matrix form, from two filesPowerIO.n_periods — Function
n_periods(series::LoadSeries) -> IntNumber of periods in a LoadSeries.
PowerIO.demands_mw — Function
demands_mw(series::LoadSeries) -> (; pd, qd)The demand matrices in MW: series.pd .* series.base_mva and the same for qd.
PowerIO.read_load_series — Function
read_load_series(net::BalancedNetwork, pd_path, qd_path; T=Float64)Read two whitespace delimited MW load matrices (rows are buses in net's order, columns are periods) into a LoadSeries. The files hold MW; the series holds per unit; demands_mw converts back.