Expand description
GridFM output: a parsed case as the gridfm-datakit Parquet schema.
gridfm-datakit writes per-scenario Parquet
tables that gridfm-graphkit’s
HeteroGridDatasetDisk trains a GNN on. This module emits the same four
tables — bus_data, gen_data, branch_data, y_bus_data — from one
parsed BalancedNetwork, so graphkit can train on powerio output directly and the
scenario-batch path (issue #14) has its on-disk format.
The reverse — powerio::gridfm::read_gridfm_dataset /
read_gridfm_scenarios / read_gridfm_base_case, with the pure
read_gridfm_network over in-memory batches — lives in the facade and
rebuilds a BalancedNetwork from such a dataset (lossy but
power flow complete), the ML→classical return leg
(issue #60). One reader plus the existing writers means gridfm → any classical
format. y_bus_data is ignored on read; branches carry raw r/x/b.
§Snapshots and scenarios
powerio has no power flow solver. One parsed case is one snapshot
(scenario = 0): voltages and generator dispatch are the case’s stored
values. Branch flows pf/qf/pt/qt use an explicit crate::network::BranchSolution
when present; otherwise they are evaluated from those voltages and the
branch admittances (branch_flows). For an unsolved or flat-start case the
evaluated values are flows at the stored voltages, not a re-solved dispatch.
A scenario batch (emit_gridfm_batch / to_gridfm_record_batches)
row-stacks many snapshots into the four tables, keyed by the scenario
column. The snapshots share a base element set — the same bus/branch/gen
counts, system base, and bus/branch/generator row identities, so every dense
index means the same element across scenarios — enforced by the shape check
(Error::ScenarioShapeMismatch). Scenario ids are unique within a batch.
Within that, load, dispatch, voltages, branch status, bus type, and costs may
all differ per snapshot. This matches datakit, whose topology scenarios (N-K,
random component drop) toggle BR_STATUS/GEN_STATUS on a fixed element set,
and graphkit’s HeteroGridDatasetDisk, which groups by scenario and
rebuilds the graph independently for each one. powerio doesn’t generate the
perturbations; a caller (e.g. a scenario generator) supplies the snapshots.
§Units
Pd, Qd, Pg, Qg, p_mw, q_mvarare MW/MVAr, passed through from the case (loads and generator setpoints are already MW/MVAr). The branch flowspf, qf, pt, qtare MW/MVAr too, computed in per-unit and scaled bybase_mva.Vmper-unit,Vadegrees;r, x, band theY**admittances per-unit.GS, BSare the MATPOWER shunt values (MW/MVAr at V = 1) divided bybase_mva, matching datakit’s normalization.- Costs are the raw MATPOWER coefficients:
cp2 = c2,cp1 = c1,cp0 = c0. A cost row gridfm can’t represent (piecewise, missing, malformed, or cubic and higher) emits zeros — graphkit ignores the cost columns — and is counted in the manifest. The_eursuffixes are datakit’s column names, not a unit powerio converts to. bus,from_bus,to_busare dense[0, n)indices;idxis the 0-based generator/branch row. An out of service branch keeps its physicalY**admittances but carries zero flows (itsbr_statusis 0).
Structs§
- Gridfm
Dataset - A complete GridFM directory ready for one
powerio_core::Destination. - Gridfm
Options - Options for the gridfm export — the batch-wide knobs. The scenario id is a
per-snapshot property (set via
GridfmSnapshot::new/number_snapshots, or the explicit argument to the single-caseemit_gridfm_dataset/to_gridfm_record_batches_single), not an option here. - Gridfm
Outputs - What
emit_gridfm_datasetwrote, plus the counts of columns it had to zero (see the manifest) so a caller can surface them. - Gridfm
Snapshot - One snapshot in a gridfm scenario batch: a parsed
BalancedNetworkand the scenario id stamped into its rows. - Gridfm
Tables - The gridfm-datakit tables as Arrow record batches. The Parquet writer builds from these; a deferred gridfm-schema Arrow C Data Interface export (issue #38) would reuse them. (The raw network Arrow export that ships in powerio-capi is a different, lighter schema.)
Functions§
- build_
gridfm_ batch - Build one GridFM artifact inventory for a batch of numbered snapshots.
- build_
gridfm_ dataset - Build the GridFM artifacts for one balanced network without writing them.
- emit_
gridfm_ batch - Write a batch of scenarios as one gridfm-datakit dataset under
out_dir/<sanitized network name>/raw/(seesanitize_stem), row-stacking every snapshot’s tables and keying them by thescenariocolumn. The dataset name and the base element counts come from the first snapshot (shared across the batch by the shape check); the dropped/degenerate counts are summed over every snapshot, whilereference_bus/n_branches_in_servicerecord the first snapshot only (they can differ per scenario, so the manifest documents them as scenario 0’s). - emit_
gridfm_ dataset - Write the gridfm-datakit Parquet dataset for one case under
out_dir/<sanitized network name>/raw/(seesanitize_stem), matching datakit’s directory layout. Stampsscenariointo the id columns. Writesbus_data.parquet,gen_data.parquet,branch_data.parquet, optionallyy_bus_data.parquet, and agridfm_meta.jsonmanifest. - number_
snapshots - Number a list of networks into snapshots, stamping the k-th
base + k— the one place the “k-th input is scenariobase + k” rule lives, so the CLI and the Python binding can’t drift. Checked: returnsError::ScenarioIdOverflowrather than wrapping or panicking if a scenario id exceedsi64. - to_
gridfm_ record_ batches - Build the four gridfm tables for a batch of scenarios, row stacked and keyed
by the
scenariocolumn. Pure (no I/O). Each snapshot carries its own scenario id; theinclude_y_bus/taps/shifts flags apply to every snapshot. - to_
gridfm_ record_ batches_ single - Build the four gridfm tables for one network, stamping
scenariointo the id columns. Pure (no I/O). A thin wrapper overto_gridfm_record_batchesfor one snapshot.