1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//! The BMOPF task force JSON schema
//! (<https://github.com/distribution-system-opt/dsopt-schema>).
//!
//! Everything is explicit SI: volts, watts, vars, ohms, siemens, meters,
//! radians, string bus ids and terminal names. Both schema versions set
//! `additionalProperties: false` on electrical elements and permit free-form
//! top-level `extras` and `meta.provenance` objects, so the strict emitter drops what the target
//! version cannot carry and says so per field.
//!
//! # Two schema versions
//!
//! [`BmopfSchemaVersion`] names the version. Schema 0.1.0 is what the task force
//! accepts: ten element classes and four transformer subtypes. Schema 0.2.0
//! is the proposal that declares the classes 0.1.0 has no table for, and
//! gives the transformer taps, winding neutral impedance, and no load
//! admittance their own subtype slots.
//!
//! The reader accepts both, whatever a document states, because every class
//! 0.2.0 declares at the top level also reads from the `extras` slot 0.1.0
//! files it under. It resolves the version from `meta.$schema` and reports
//! `READ.BMOPF.SCHEMA_ABSENT` when the document states none and
//! `READ.BMOPF.SCHEMA_UNKNOWN` when the value names no version: the class
//! layout of such a document is stated nowhere, and a consumer that assumes
//! one reads a different network on the other.
//!
//! The writer targets one version, 0.2.0 by default. Writing 0.2.0 keeps supported proposal fields in place. Writing 0.1.0 relocates what that version has no slot for, listed
//! below, and reports each move.
//!
//! # What a 0.1.0 write parks under `extras`
//!
//! Some data has a physical meaning schema 0.1.0 cannot express in place but
//! can carry in the free form `extras` object, and that data is relocated
//! rather than dropped, with a warning per element. A consumer that reads the
//! document and ignores `extras` gets a network that differs physically from
//! the source and no error saying so: a tapped transformer reads as nominal
//! tap, an impedance grounded neutral loses its internal grounding branch, and the
//! magnetizing branch disappears.
//!
//! ## Transformer fields
//!
//! Schema 0.1.0 has no slot for these nine fields in the `single_phase`,
//! `center_tap`, `wye_delta`, and `delta_wye` subtype definitions, so a
//! transformer carrying any of them emits them under
//! `extras.transformer.<subtype>.<name>`, keyed by the same transformer name
//! the subtype table uses:
//!
//! `tap`, `tap_min`, `tap_max`, `r_neutral_from`, `x_neutral_from`,
//! `r_neutral_to`, `x_neutral_to`, `g_no_load`, `b_no_load`.
//!
//! Schema 0.2.0 declares all nine on those subtypes, so they stay in place
//! and only the three tap names change, to `tap_ratio`, `tap_ratio_min`, and
//! `tap_ratio_max`, the spelling its regulator subtypes use.
//!
//! Neither version defines untyped `transformer.<subtype>` passthrough
//! objects, so those keep every field in place and nothing moves. The BMOPF
//! reader folds a 0.1.0 overlay back onto the subtype objects; on a key
//! collision the field already in the subtype object wins.
//!
//! ## Whole tables
//!
//! Schema 0.1.0 has no top level slot for these classes, so under that
//! version each emits at `extras.<class>.<name>` with the keying its top
//! level table used:
//!
//! - `ibr` and `control_profile`, emitted from the typed model
//! - `dc_bus`, `dc_branch`, `dc_grounding`, `dc_load`, `dc_source`,
//! `time_series`, emitted from untyped objects of that class
//! - `capacitor`, only for a capacitor too malformed to type; a typed
//! capacitor goes to the strict top level `capacitor` table
//!
//! Schema 0.2.0 declares every one of them but `capacitor`, whose top level
//! table stays strict there too, so a malformed capacitor keeps its raw
//! properties under `extras` under either version.
//!
//! A source document's own `extras` object is stashed on read and re-emitted
//! verbatim, so consumer keys beside these survive a write and read back.
//!
//! # Regulator subtypes
//!
//! Schema 0.1.0 defines no regulator subtype; the task force's BMOPFTools
//! toolchain extends it with `single_phase_autotransformer` and
//! `open_delta_regulator`, and schema 0.2.0 declares both. This emitter
//! writes them at top level under 0.2.0 and in `extras.transformer` under 0.1.0.
//! An OpenDSS transformer a RegControl targets emits as
//! `transformer.single_phase_autotransformer` when it reads as a series
//! regulator (one phase, two windings of equal connection, voltage, and
//! rating on distinct buses), and two identical line to line legs spelling
//! one open delta connection (ABBC/BCAC/CABA) merge into one
//! `transformer.open_delta_regulator` object named after the first leg. A
//! BMOPF document that already carries either subtype re-emits it verbatim.
//!
//! # `terminal_conventions` goes stale on a rename
//!
//! The emitted `terminal_conventions` block is the source document's own
//! block re-emitted verbatim, or, absent that, one authored from the terminal
//! names in the model: `n` and `N` are neutral, and `4` in the complete
//! `1,2,3,4` convention is neutral; other names are phase labels. Either way the block describes the terminal naming
//! of the document that carries it and nothing else. A consumer that renames
//! terminals must delete the block and recompute it from the renamed
//! terminals; carried across a rename it sorts names no bus has any more, and
//! nothing else in the document contradicts it.
pub
pub use ;
pub use emit_bmopf_json_text_with_options;
pub use ;