Skip to main content

powerio_dist/
lib.rs

1//! Multiconductor distribution network models and converters for OpenDSS
2//! `.dss`, PowerModelsDistribution ENGINEERING
3//! JSON ("PMD JSON"), and the draft JSON schema of the IEEE PES Task Force on
4//! Benchmarking Multiconductor OPF ("BMOPF JSON",
5//! <https://github.com/distribution-system-opt/dsopt-schema>).
6//!
7//! The model uses wire coordinates: string bus IDs, ordered terminal names,
8//! explicit grounding, terminal maps on every element, SI units, and radians.
9//! The transmission model in `powerio` is positive sequence and remains a
10//! separate type.
11//!
12//! ```no_run
13//! let source = powerio_core::Source::open("feeder.dss")?;
14//! let module = powerio_dist::parse(source)?;
15//! for line in powerio_dist::diagnostics::render_diagnostics(module.diagnostics()) {
16//!     eprintln!("parse: {line}");
17//! }
18//! let emitted = powerio_dist::emit(
19//!     &module,
20//!     powerio_dist::DistTargetFormat::PmdJson,
21//!     powerio_core::Destination::memory("feeder.pmd.json")?,
22//! )?;
23//! for line in powerio_dist::diagnostics::render_diagnostics(emitted.diagnostics()) {
24//!     eprintln!("emit: {line}");
25//! }
26//! # Ok::<(), powerio_core::Error>(())
27//! ```
28//!
29//! # Fidelity rules
30//!
31//! Emitting to the retained source format returns the original bytes. Cross
32//! format emission uses the typed model and reports fields the target cannot
33//! represent through [`powerio_core::EmitResult::diagnostics`]. The DSS reader expands OpenDSS
34//! class defaults into explicit model values and records them in
35//! [`MulticonductorNetwork::defaulted`]. BMOPF output includes those values.
36//! The per fixture results live in `docs/conversion-matrix.md`.
37//!
38//! # Float formatting
39//!
40//! Canonical output formats every number as its shortest round trip
41//! representation: Rust's `Display` for `.dss`, serde_json (ryu) for both
42//! JSON formats. The readers parse with serde_json's `float_roundtrip`
43//! feature, so a parse of canonical output recovers the exact bit pattern
44//! and canonical emissions are idempotent. JSON cannot carry `Inf`/`NaN`: the
45//! PMD emitter uses `null` (PMD restores the value from the field name
46//! suffix), and the BMOPF emitter uses `0` with a warning, since the schema
47//! requires numbers. The byte exact echo tier is unaffected; it never
48//! reformats.
49
50pub mod bmopf;
51mod collect;
52pub mod convert;
53pub mod diagnostics;
54pub mod dss;
55pub mod error;
56pub mod geo;
57pub mod graph;
58pub mod model;
59pub mod pmd;
60pub mod readiness;
61#[cfg(test)]
62pub(crate) mod testkit;
63
64pub use bmopf::{BMOPF_SCHEMA_ID, BMOPF_SCHEMA_VERSION, BmopfEmitOptions, BmopfSchemaVersion};
65pub use convert::{
66    DistTargetFormat, EmitOptions, classify_distribution_json, emit, emit_with_options, parse,
67    parse_dist_target_format,
68};
69pub use diagnostics::{Diagnostic, DiagnosticCode, DiagnosticSeverity, DiagnosticStage};
70pub use dss::{DssEmitOptions, DssLoadVoltageBounds};
71pub use error::{Error, Result};
72pub use geo::{CoordinateSpace, DistCanvas, DistCoordsKind, DistGeoMeta, DistLocation};
73pub use graph::{
74    DistGraph, DistGraphAttachment, DistGraphAttachmentKind, DistGraphBus, DistGraphEdge,
75    DistGraphEdgeKind,
76};
77pub use model::{
78    ActivePowerReference, ActivePowerUnit, ConductorMatrix, Configuration, ControlVoltageReference,
79    DistBus, DistCapacitor, DistControlProfile, DistGenerator, DistIbr, DistLine, DistLineCode,
80    DistLoad, DistLoadVoltageModel, DistShunt, DistSourceFormat, DistSwitch, DistTransformer,
81    DistWinding, DistWindingConn, Extras, IbrPrimeMover, IbrTopology, IbrVoltageAggregation,
82    MulticonductorNetwork, PowerFactorControl, ReactivePowerReference, ReactivePowerUnit,
83    UntypedObject, VoltVarControl, VoltWattControl, VoltageSource, find_unresolved_references,
84};
85pub use readiness::{
86    ElectricalReadiness, ReadinessFinding, ReadinessSeverity, audit_electrical_readiness,
87    require_electrical_readiness,
88};