From a27c2412c4a674b73854ee85e2bf5437c6de11ab Mon Sep 17 00:00:00 2001 From: samtalki <10187005+samtalki@users.noreply.github.com> Date: Mon, 8 Jun 2026 13:56:29 -0400 Subject: [PATCH 1/2] Add Surge JSON support across the hub, bindings, docs, fixtures, and the --- README.md | 47 +- benchmarks/run_validation.sh | 25 +- benchmarks/validate_surge.py | 103 +++ docs/format-fidelity.md | 61 +- powerio-capi/README.md | 3 + powerio-capi/include/powerio.h | 5 +- powerio-cli/src/main.rs | 4 + powerio-matrix/src/lib.rs | 4 +- powerio-py/src/lib.rs | 3 +- powerio/src/format/mod.rs | 67 +- powerio/src/format/surge.rs | 1226 ++++++++++++++++++++++++++ powerio/src/lib.rs | 6 +- powerio/src/network.rs | 1 + powerio/tests/convert.rs | 164 +++- powerio/tests/roundtrip_formats.rs | 26 +- python/powerio/__init__.py | 12 +- python/powerio/__init__.pyi | 2 +- python/tests/test_powerio.py | 18 +- tests/data/surge/case14.surge.json | 1 + tests/data/surge/case30.surge.json | 1 + tests/data/surge/case57.surge.json | 1 + tests/data/surge/market30.surge.json | 1 + 22 files changed, 1696 insertions(+), 85 deletions(-) create mode 100644 benchmarks/validate_surge.py create mode 100644 powerio/src/format/surge.rs create mode 100644 tests/data/surge/case14.surge.json create mode 100644 tests/data/surge/case30.surge.json create mode 100644 tests/data/surge/case57.surge.json create mode 100644 tests/data/surge/market30.surge.json diff --git a/README.md b/README.md index 6ba94a4..c5b297b 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,12 @@ # PowerIO Lossless IO and format conversion for power system case files. Parse MATPOWER -`.m`, PSS/E `.raw`, PowerWorld `.aux`, PowerModels JSON, and EGRET JSON into one -format neutral `Network`; write any of them back (same-format round trips are byte -for byte); convert between them with explicit fidelity reporting; and emit the -sparse matrices and graph views a solver needs. The same Rust core is callable -from Rust, Python, C/C++, and Julia. The core crate has six dependencies and no -matrix or solver stack. +`.m`, PSS/E `.raw`, PowerWorld `.aux`, PowerModels JSON, EGRET JSON, and Surge +JSON into one format neutral `Network`; write any of them back (same format +round trips are byte for byte); convert between them with explicit fidelity +reporting; and emit the sparse matrices and graph views a solver needs. The +same Rust core is callable from Rust, Python, C/C++, and Julia. The core crate +has six dependencies and no matrix or solver stack. ## Workspace @@ -36,29 +36,34 @@ Every reader produces a `Network` and every writer consumes one, so a new format is one module at the hub, not an NΓ—M matrix of pairwise converters. **Readers and writers**: MATPOWER `.m`, PowerModels JSON, PSS/E `.raw` (v33), -PowerWorld `.aux`, and EGRET JSON. +PowerWorld `.aux`, EGRET JSON, and Surge JSON. Legend: 🟩 byte-exact Β· 🟦 full Β· 🟨 partial (drops are logged in `Conversion::warnings`) -| reader ↓ \ writer β†’ | MATPOWER | PowerModels JSON | PSS/E | PowerWorld | EGRET JSON | -| --- | --- | --- | --- | --- | --- | -| **MATPOWER** | 🟩 | 🟦 | 🟨 | 🟨 | 🟨 | -| **PowerModels JSON** | 🟦 | 🟩 | 🟨 | 🟨 | 🟨 | -| **PSS/E** | 🟦 | 🟦 | 🟩 | 🟨 | 🟨 | -| **PowerWorld** | 🟦 | 🟦 | 🟨 | 🟩 | 🟨 | -| **EGRET JSON** | 🟦 | 🟦 | 🟨 | 🟨 | 🟩 | +| reader ↓ \ writer β†’ | MATPOWER | PowerModels JSON | PSS/E | PowerWorld | EGRET JSON | Surge JSON | +| --- | --- | --- | --- | --- | --- | --- | +| **MATPOWER** | 🟩 | 🟦 | 🟨 | 🟨 | 🟨 | 🟨 | +| **PowerModels JSON** | 🟦 | 🟩 | 🟨 | 🟨 | 🟨 | 🟨 | +| **PSS/E** | 🟦 | 🟦 | 🟩 | 🟨 | 🟨 | 🟦 | +| **PowerWorld** | 🟦 | 🟦 | 🟨 | 🟩 | 🟨 | 🟦 | +| **EGRET JSON** | 🟦 | 🟦 | 🟨 | 🟨 | 🟩 | 🟦 | +| **Surge JSON** | 🟨 | 🟨 | 🟨 | 🟨 | 🟨 | 🟩 | **🟩 byte-exact**: writing back to the source format reproduces the file verbatim, comments and exact tokens like `7e-05` included. **🟦 full**: every field the source carries survives. **🟨 partial**: the target cannot represent some fields (PSS/E and PowerWorld have no cost curves; EGRET has no HVDC or storage), and each dropped -field is reported in `Conversion::warnings`, not dropped silently. Two target -caveats fold into this: canonical MATPOWER output omits dcline and storage, and the -PowerModels writer maps them best-effort. - -Every reader and writer is validated against an independent tool, PowerModels.jl, -the EGRET package, ExaPowerIO.jl, and pandapower, over the full conversion matrix. -See [benchmarks/RESULTS.md](benchmarks/RESULTS.md) and +field is reported in `Conversion::warnings`, not dropped silently. Three target +caveats fold into this: canonical MATPOWER output omits dcline and storage, the +PowerModels writer maps them best-effort, and Surge JSON carries the core network +profile only. Rich Surge dispatch, result, market, controls, ZIP load, +converter, and DC grid data are reported on cross format writes. Compressed +`.surge.json.zst` and `.surge.bin` files are out of scope for the runtime reader. + +Every reader and writer is validated against an independent tool where one exists: +PowerModels.jl, the EGRET package, ExaPowerIO.jl, pandapower, and an optional +Surge CLI oracle through `SURGE_BIN` or `SURGE_CHECKOUT`. See +[benchmarks/RESULTS.md](benchmarks/RESULTS.md) and [docs/format-fidelity.md](docs/format-fidelity.md). ## Matrices diff --git a/benchmarks/run_validation.sh b/benchmarks/run_validation.sh index 03cf9e1..9291ad8 100644 --- a/benchmarks/run_validation.sh +++ b/benchmarks/run_validation.sh @@ -12,13 +12,17 @@ # benchmarks/validate_exapowerio.jl # pp β€” powerio's parse + Y_bus vs pandapower (_m2ppc + makeYbus). # benchmarks/validate_pandapower.py +# Surge β€” optional: powerio's Surge JSON writer vs Surge's own parser. +# Set SURGE_BIN=/path/to/surge-solve or SURGE_CHECKOUT=/path/to/surge. +# benchmarks/validate_surge.py # # Then the read sides and the full conversion matrix: # PSSE-read β€” powerio reads a real PSS/E .raw, emits PowerModels JSON, compared # against PowerModels.jl reading the same .raw. # EGRET-read β€” powerio reads a real EGRET .json (egret's own output), emits # PowerModels JSON, checked against the matching MATPOWER case. -# matrix(5x5) β€” every reader -> every writer over the fixtures, each output's +# matrix(5x5) β€” every reader -> every writer over the fixtures covered by the +# independent PowerModels and egret oracles, each output's # electrical core checked against the ground-truth MATPOWER case # (PowerModels.jl for MATPOWER/PowerModels/PSS-E/PowerWorld, the # egret package for EGRET), byte-exact on the diagonal. @@ -28,7 +32,8 @@ # built into .venv (`maturin develop --release`), the Julia env instantiated # (`julia --project=benchmarks -e 'using Pkg; Pkg.instantiate()'`), and the Python # oracle tools (`pip install -r benchmarks/requirements.txt`, for the pandapower -# and EGRET checks). All oracle tools are benchmark-scoped, not powerio deps. +# and EGRET checks). Surge is optional through SURGE_BIN or SURGE_CHECKOUT. All +# oracle tools are benchmark-scoped, not powerio deps. # # bash benchmarks/run_validation.sh # @@ -48,6 +53,11 @@ trap 'rm -rf "$TMP"' EXIT HAVE_EGRET=1 "$PY" -c "import egret" 2>/dev/null || HAVE_EGRET=0 +HAVE_SURGE=0 +if [ -n "${SURGE_BIN:-}" ] || [ -n "${SURGE_CHECKOUT:-}" ]; then + HAVE_SURGE=1 +fi + MCASES=( tests/data/case9.m tests/data/case14.m @@ -126,6 +136,17 @@ for m in "${MCASES[@]}"; do mark "$PY" benchmarks/validate_pandapower.py "$m" row+=" pp:$MARK" + if [ "$HAVE_SURGE" -eq 0 ]; then + MARK="SKIP" + elif [ "$base" = "case2869pegase" ]; then + MARK="SKIP(nonfinite)" + elif convert "$m" surge-json "$TMP/$base.surge.json" 2>"$TMP/err"; then + mark "$PY" benchmarks/validate_surge.py "$m" "$TMP/$base.surge.json" + else + echo " Surge: convert failed"; cat "$TMP/err"; MARK="FAIL"; fails=$((fails + 1)) + fi + row+=" Surge:$MARK" + rows+=("$row") done diff --git a/benchmarks/validate_surge.py b/benchmarks/validate_surge.py new file mode 100644 index 0000000..d5d002f --- /dev/null +++ b/benchmarks/validate_surge.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python +"""Optional Surge oracle for powerio's Surge JSON writer. + +Usage: + SURGE_BIN=/path/to/surge-solve benchmarks/validate_surge.py ref.m out.surge.json + SURGE_CHECKOUT=/path/to/surge benchmarks/validate_surge.py ref.m out.surge.json + +The oracle loads powerio's `.surge.json` output with Surge's own CLI +`--parse-only --output json` and compares counts and totals against the +reference case parsed by powerio. It is benchmark scoped: no Surge crate or +Python package is a dependency of powerio. +""" + +from __future__ import annotations + +import json +import math +import os +import subprocess +import sys +from pathlib import Path + +import powerio + + +def surge_command() -> list[str] | None: + if bin_path := os.environ.get("SURGE_BIN"): + return [bin_path] + if checkout := os.environ.get("SURGE_CHECKOUT"): + manifest = Path(checkout) / "Cargo.toml" + return [ + "cargo", + "run", + "--quiet", + "--manifest-path", + str(manifest), + "-p", + "surge-bindings", + "--bin", + "surge-solve", + "--", + ] + return None + + +def powerio_core(path: str) -> dict[str, float]: + case = powerio.parse(path) + return { + "n_buses": case.n, + "n_branches": case.n_branches, + "n_generators": case.n_gens, + "total_load_mw": sum(load["p"] for load in case.loads), + "total_gen_mw": sum(gen["pg"] for gen in case.gens), + "base_mva": case.base_mva, + } + + +def surge_core(path: str) -> dict[str, float]: + cmd = surge_command() + if cmd is None: + print("SKIP: set SURGE_BIN or SURGE_CHECKOUT for the Surge oracle") + raise SystemExit(77) + out = subprocess.run( + [*cmd, path, "--parse-only", "--output", "json"], + capture_output=True, + text=True, + ) + if out.returncode != 0: + print(out.stderr or out.stdout, file=sys.stderr) + raise SystemExit(out.returncode) + data = json.loads(out.stdout) + return { + "n_buses": data["n_buses"], + "n_branches": data["n_branches"], + "n_generators": data["n_generators"], + "total_load_mw": data["total_load_mw"], + "total_gen_mw": data["total_gen_mw"], + "base_mva": data["base_mva"], + } + + +def main() -> None: + if len(sys.argv) != 3: + print("usage: validate_surge.py ", file=sys.stderr) + raise SystemExit(2) + ref, out = sys.argv[1], sys.argv[2] + ref_core = powerio_core(ref) + out_core = surge_core(out) + problems = [] + for key in ("n_buses", "n_branches", "n_generators"): + if int(ref_core[key]) != int(out_core[key]): + problems.append(f"{key} {ref_core[key]}!={out_core[key]}") + for key in ("total_load_mw", "total_gen_mw", "base_mva"): + if not math.isclose(ref_core[key], out_core[key], rel_tol=1e-6, abs_tol=1e-6): + problems.append(f"{key} {ref_core[key]}!={out_core[key]}") + if problems: + print("; ".join(problems), file=sys.stderr) + raise SystemExit(1) + print("ok") + + +if __name__ == "__main__": + main() diff --git a/docs/format-fidelity.md b/docs/format-fidelity.md index 708807d..019df25 100644 --- a/docs/format-fidelity.md +++ b/docs/format-fidelity.md @@ -6,8 +6,9 @@ this document covers the conventions and the proof behind it. ## Conventions -powerio's numeric conventions match MATPOWER and PowerModels.jl. The reference -implementations and the matching powerio code: +powerio's numeric conventions match MATPOWER and PowerModels.jl. Surge stores +angles in radians; powerio normalizes them to the same degree based model used by +the other formats. The reference implementations and the matching powerio code: | Quantity | Convention | Reference | powerio | | --- | --- | --- | --- | @@ -16,9 +17,12 @@ implementations and the matching powerio code: | Line charging `b` | split half to each end (`b_fr = b_to = BR_B/2`) | PowerModels `matpower.jl` | `format::powermodels` | | Tap ratio | `0` means a line (treated as `1`); nonzero is a transformer | MATPOWER `idx_brch` `TAP` | `Branch::effective_tap` | | Phase shift, angle | degrees in the model; PowerModels JSON carries radians | PowerModels `make_per_unit!` | `format::powermodels` | +| Surge phase shift, angle | degrees in the model; Surge JSON carries bus angles, branch shifts, and branch angle limits in radians | Surge data model | `format::surge` | | Angle limits | `angmin`/`angmax` default Β±360 (unconstrained) | MATPOWER `idx_brch` `ANGMIN`/`ANGMAX` | `Branch::has_angle_limits` | +| Surge tap ratio | `1.0` on a plain line maps back to MATPOWER raw tap `0`; nonzero transformer taps are preserved | Surge data model | `format::surge` | | dcline `Pt`/`Qf`/`Qt` | sign flips vs MATPOWER | PowerModels `matpower.jl` | `format::powermodels` | | Generator cost | `c2 pΒ² + c1 p` β†’ `q = 2c2`, `c = c1`; coefficients high order first | MATPOWER `idx_cost`, EGRET `matpower_parser` | `GenCost::quadratic` | +| Surge generator cost | polynomial coefficients are high order first; piecewise curves are point lists | Surge data model | `format::surge` | | `source_id` | `["bus", id]` for bus-tied elements | PowerModels `matpower.jl` | `format::powermodels` | EGRET's own MATPOWER parser uses the same reductions (bus type as @@ -28,8 +32,9 @@ MATPOWER case taken through powerio to EGRET matches egret's direct import. ## Validation -The harness `benchmarks/run_validation.sh` checks powerio against four independent -tools. Every reader and writer, and every conversion pair, is exercised. +The harness `benchmarks/run_validation.sh` checks powerio against independent +tools. The Rust suite exercises every reader and writer, and every conversion +pair, including Surge. - **PowerModels.jl** (`validate_powermodels.jl`, `validate_psse.jl`, `core_json.jl`). Reads MATPOWER, PowerModels JSON, and PSS/E. The MATPOWER to @@ -41,23 +46,29 @@ tools. Every reader and writer, and every conversion pair, is exercised. - **ExaPowerIO.jl** (`validate_exapowerio.jl`). Reads MATPOWER through powerio's C ABI and compares value for value. - **pandapower** (`validate_pandapower.py`). Cross-checks the parse and the `Y_bus`. +- **Surge CLI** (`validate_surge.py`). Optional. Set `SURGE_BIN=/path/to/surge-solve` + or `SURGE_CHECKOUT=/path/to/surge`; the script loads powerio's Surge JSON + output with Surge's parser and compares counts and totals. ### The conversion matrix -`benchmarks/validate_matrix.py` converts each source to every target and checks -the electrical core of the output (bus/branch/generator counts and the per unit -demand, generation, and shunt totals) against the source's own core, read by an -independent oracle. The diagonal is checked byte-exact: writing back to the source -format reproduces the file. Sources use the real native files where they exist -(the vendored PSS/E `.raw` and EGRET `.json`) and representative MATPOWER cases -otherwise: basic (`case9`), shunts and transformers (`case14`, `case30`), size -(`case118`, `case2869pegase`), HVDC with a mixed piecewise/polynomial gencost +`benchmarks/validate_matrix.py` converts each source to every target covered by +the PowerModels and egret oracles and checks the electrical core of the output +(bus/branch/generator counts and the per unit demand, generation, and shunt +totals) against the source's own core, read by an independent oracle. The +diagonal is checked byte-exact: writing back to the source format reproduces the +file. Sources use the real native files where they exist (the vendored PSS/E +`.raw` and EGRET `.json`) and representative MATPOWER cases otherwise: basic +(`case9`), shunts and transformers (`case14`, `case30`), size (`case118`, +`case2869pegase`), HVDC with a mixed piecewise/polynomial gencost (`t_case9_dcline`), and a piecewise-cost case (`pglib_opf_case5_pjm`). -All 65 cells pass (13 source cases Γ— 5 targets). The core is preserved by every -writer regardless of fidelity tier, so it is the invariant checked across the -whole matrix; cost, HVDC, and angle limits are tier-specific and covered by the -dedicated checks above and the Rust suite. +The benchmark matrix has 65 cells (13 source cases Γ— 5 oracle targets). The Rust +all pairs suite adds Surge as a sixth format and checks byte-exact same format +echo plus approximate JSON equality where numeric formatting changes. The core +is preserved by every writer regardless of fidelity tier, so it is the invariant +checked across the whole matrix; cost, HVDC, storage, source-only fields, and +angle limits are covered by dedicated checks and the Rust suite. ### Running it @@ -69,9 +80,10 @@ pip install -r benchmarks/requirements.txt # pandapower + egret oracles bash benchmarks/run_validation.sh ``` -The oracle tools (PowerModels.jl, egret, ExaPowerIO.jl, pandapower) are -benchmark-scoped: they are declared in `benchmarks/Project.toml` and -`benchmarks/requirements.txt`, never as dependencies of the powerio package. +The oracle tools (PowerModels.jl, egret, ExaPowerIO.jl, pandapower, and optional +Surge) are benchmark scoped: they are declared in `benchmarks/Project.toml`, +`benchmarks/requirements.txt`, or supplied by `SURGE_BIN`/`SURGE_CHECKOUT`, never +as dependencies of the powerio package. ## Known limits @@ -90,3 +102,14 @@ These are reported in `Conversion::warnings`, not dropped silently. - **EGRET** output drops HVDC and storage. The reader takes the power flow ModelData subset (numeric bus ids, scalar values); unit commitment cases (`system.time_keys`) are rejected. +- **Surge** runtime support is limited to decompressed `.surge.json` network + documents. `.surge.json.zst`, `.surge.bin`, native dispatch profiles, and + native result profiles are out of scope. If a Surge JSON document carries + `dispatch` or `solution`, the reader models `network` and cross format writers + report the ignored sections. ZIP and CMPLDW load fields, frequency, + ownership, classification, market data, topology metadata, branch control + bounds, richer storage metadata, DC grid data, converter details, reactive + limits, losses, and controls are warned on cross format conversion. Surge + tagged nonfinite floats are rejected by the reader; the writer emits JSON + `null` for nonfinite values through the shared JSON number helper and reports + format loss where applicable. diff --git a/powerio-capi/README.md b/powerio-capi/README.md index c2edae1..e78df07 100644 --- a/powerio-capi/README.md +++ b/powerio-capi/README.md @@ -7,6 +7,9 @@ Python ctypes, …) can drive powerio through it. The header is [`include/powerio.h`](include/powerio.h). +Format names are the same aliases the Rust hub accepts, including `matpower`, +`powermodels-json`, `egret-json`, `surge-json`, `psse`, and `powerworld`. + ## Build ``` diff --git a/powerio-capi/include/powerio.h b/powerio-capi/include/powerio.h index c015ada..7beb109 100644 --- a/powerio-capi/include/powerio.h +++ b/powerio-capi/include/powerio.h @@ -34,8 +34,9 @@ extern "C" { typedef struct PioCase PioCase; /* Parse `path`; format from the file extension, or forced by `from` - * ("matpower","powermodels","psse","powerworld") when non-NULL. Returns NULL on - * error and writes the message into errbuf (a char[errlen]). */ + * ("matpower","powermodels","egret","surge","psse","powerworld") when + * non-NULL. Returns NULL on error and writes the message into errbuf + * (a char[errlen]). */ PioCase *pio_parse(const char *path, const char *from, char *errbuf, size_t errlen); void pio_case_free(PioCase *c); diff --git a/powerio-cli/src/main.rs b/powerio-cli/src/main.rs index be92842..8b5cd78 100644 --- a/powerio-cli/src/main.rs +++ b/powerio-cli/src/main.rs @@ -152,6 +152,8 @@ enum FormatArg { PowerModelsJson, #[value(name = "egret-json", alias = "egret")] EgretJson, + #[value(name = "surge-json", alias = "surge")] + SurgeJson, #[value(name = "psse", alias = "raw")] Psse, #[value(name = "powerworld", alias = "aux")] @@ -164,6 +166,7 @@ impl From for powerio_matrix::TargetFormat { FormatArg::Matpower => Self::Matpower, FormatArg::PowerModelsJson => Self::PowerModelsJson, FormatArg::EgretJson => Self::EgretJson, + FormatArg::SurgeJson => Self::SurgeJson, FormatArg::Psse => Self::Psse, FormatArg::PowerWorld => Self::PowerWorld, } @@ -177,6 +180,7 @@ impl FormatArg { FormatArg::Matpower => "matpower", FormatArg::PowerModelsJson => "powermodels-json", FormatArg::EgretJson => "egret-json", + FormatArg::SurgeJson => "surge-json", FormatArg::Psse => "psse", FormatArg::PowerWorld => "powerworld", } diff --git a/powerio-matrix/src/lib.rs b/powerio-matrix/src/lib.rs index 5eedb6f..3401a1c 100644 --- a/powerio-matrix/src/lib.rs +++ b/powerio-matrix/src/lib.rs @@ -40,8 +40,8 @@ pub use powerio::{ GenCost, Generator, Hvdc, IndexCore, IndexedNetwork, Load, Network, Result, ScenarioMismatch, Shunt, SourceFormat, Storage, TargetFormat, error, format, indexed, network, parse, parse_matpower, parse_matpower_file, parse_powermodels_json, parse_powerworld, parse_psse, - parse_str, read_path, target_format_from_name, write_as, write_egret_json, write_matpower, - write_powermodels_json, write_powerworld, write_psse, + parse_str, parse_surge_json, read_path, target_format_from_name, write_as, write_egret_json, + write_matpower, write_powermodels_json, write_powerworld, write_psse, write_surge_json, }; pub mod io; diff --git a/powerio-py/src/lib.rs b/powerio-py/src/lib.rs index 48cac05..c820ee3 100644 --- a/powerio-py/src/lib.rs +++ b/powerio-py/src/lib.rs @@ -513,7 +513,8 @@ fn parse(path: &str) -> PyResult { } /// Parse a case from in-memory text in the named `format` (`matpower`, -/// `powermodels-json`, `psse`, `powerworld`; aliases `m`/`pm`/`raw`/`aux`). +/// `powermodels-json`, `egret-json`, `surge-json`, `psse`, `powerworld`; +/// aliases `m`/`pm`/`egret`/`surge`/`raw`/`aux`). #[pyfunction] #[pyo3(signature = (text, format=None))] fn parse_str(text: &str, format: Option<&str>) -> PyResult { diff --git a/powerio/src/format/mod.rs b/powerio/src/format/mod.rs index 6c79eba..160b7c6 100644 --- a/powerio/src/format/mod.rs +++ b/powerio/src/format/mod.rs @@ -2,11 +2,12 @@ //! meeting at the shared [`Network`]. //! //! Each format is one module here, owning its reader and/or writer β€” MATPOWER -//! `.m`, PowerModels JSON, PSS/E `.raw`, PowerWorld `.aux`, and EGRET -//! `ModelData` JSON. Every input and output format meets at the hub, so adding a -//! format is one module, not a change to any other. [`parse`] reads a file, -//! detecting the format from its extension; [`write_as`] serializes a `Network` -//! to a target. Non-finite numeric values (a MATPOWER `Inf`/`NaN` angle limit, +//! `.m`, PowerModels JSON, PSS/E `.raw`, PowerWorld `.aux`, EGRET +//! `ModelData` JSON, and Surge JSON. Every input and output format meets at the +//! hub, so adding a format is one module, not a change to any other. +//! [`parse`] reads a file, detecting the format from its extension; +//! [`write_as`] serializes a `Network` to a target. Non-finite numeric values +//! (a MATPOWER `Inf`/`NaN` angle limit, //! say) are written as JSON `null`. //! //! # Fidelity contract @@ -33,12 +34,14 @@ mod matpower; mod powermodels; mod powerworld; mod psse; +mod surge; pub use egret::{parse_egret_json, write_egret_json}; pub use matpower::{parse_matpower, parse_matpower_file, write_matpower}; pub use powermodels::{parse_powermodels_json, write_powermodels_json}; pub use powerworld::{parse_powerworld, write_powerworld}; pub use psse::{parse_psse, write_psse}; +pub use surge::{parse_surge_json, write_surge_json}; /// A target interchange format. See [`write_as`]. #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -48,6 +51,8 @@ pub enum TargetFormat { PowerModelsJson, /// EGRET `ModelData` JSON. EgretJson, + /// Surge native network JSON. + SurgeJson, /// PSS/E `.raw` (v33). Psse, /// PowerWorld auxiliary `.aux`. @@ -62,6 +67,7 @@ impl TargetFormat { pub fn extension(self) -> &'static str { match self { TargetFormat::PowerModelsJson | TargetFormat::EgretJson => "json", + TargetFormat::SurgeJson => "surge.json", TargetFormat::Psse => "raw", TargetFormat::PowerWorld => "aux", TargetFormat::Matpower => "m", @@ -71,15 +77,16 @@ impl TargetFormat { /// Map a format name (with the common aliases) to a [`TargetFormat`], or `None` /// if unrecognized. Accepts `matpower`/`m`, `powermodels-json`/`powermodels`/`pm`, -/// `egret-json`/`egret`, `psse`/`raw`, `powerworld`/`aux`. Case-insensitive. The -/// one place the bindings (Python, C ABI) share, so a new format means one new -/// arm here, not three. +/// `egret-json`/`egret`, `surge-json`/`surge`, `psse`/`raw`, +/// `powerworld`/`aux`. Case-insensitive. The one place the bindings (Python, C +/// ABI) share, so a new format means one new arm here, not three. #[must_use] pub fn target_format_from_name(name: &str) -> Option { Some(match name.to_ascii_lowercase().as_str() { "matpower" | "m" => TargetFormat::Matpower, "powermodels-json" | "powermodels" | "pm" => TargetFormat::PowerModelsJson, "egret-json" | "egret" => TargetFormat::EgretJson, + "surge-json" | "surge" => TargetFormat::SurgeJson, "psse" | "raw" => TargetFormat::Psse, "powerworld" | "aux" => TargetFormat::PowerWorld, _ => return None, @@ -89,7 +96,8 @@ pub fn target_format_from_name(name: &str) -> Option { /// Read the case at `path` into a [`Network`], choosing the reader from `from` /// (a format name, see [`target_format_from_name`]) or, when `None`, from the /// file extension (`m`/`json`/`raw`/`aux`). A `.json` file is sniffed for the -/// EGRET vs PowerModels shape (see [`sniff_json`]); pass `from` to force one. +/// Surge vs EGRET vs PowerModels shape (see [`sniff_json`]); pass `from` to +/// force one. /// The one reader the CLI and the Python/C bindings share, so adding a source /// format is one edit here, not one per binding. /// @@ -136,13 +144,15 @@ fn read_source(source: Arc, fmt: TargetFormat, name_hint: Option<&str>) TargetFormat::Psse => psse::parse_psse_source(source, name_hint), TargetFormat::PowerWorld => powerworld::parse_powerworld_source(source, name_hint), TargetFormat::EgretJson => egret::parse_egret_source(source, name_hint), + TargetFormat::SurgeJson => surge::parse_surge_json_source(source, name_hint), } } -/// Both interchange JSON formats use the `.json` extension, so an explicit -/// source format isn't always given. EGRET `ModelData` has top-level `elements` -/// and `system`; PowerModels network data does not. Sniff that and fall back to -/// PowerModels (the more common input) when the text isn't EGRET-shaped. +/// The interchange JSON formats share the `.json` extension, so an explicit +/// source format isn't always given. Surge has top-level `format = +/// "surge-json"` plus `network`; EGRET `ModelData` has top-level `elements` and +/// `system`; PowerModels network data does not. Sniff those and fall back to +/// PowerModels when the text is neither Surge nor EGRET shaped. /// /// Deserializing into [`IgnoredAny`] fields scans the JSON to find the two /// top-level keys without building the whole `Value` tree, so a large @@ -152,13 +162,21 @@ fn sniff_json(text: &str) -> TargetFormat { use serde::de::IgnoredAny; #[derive(serde::Deserialize)] struct Shape { + format: Option, + network: Option, elements: Option, system: Option, } match serde_json::from_str::(text) { + Ok(Shape { + format: Some(format), + network: Some(_), + .. + }) if format == "surge-json" => TargetFormat::SurgeJson, Ok(Shape { elements: Some(_), system: Some(_), + .. }) => TargetFormat::EgretJson, _ => TargetFormat::PowerModelsJson, } @@ -214,16 +232,18 @@ pub fn write_as(net: &Network, format: TargetFormat) -> Conversion { }; } } - match format { + let conversion = match format { TargetFormat::PowerModelsJson => write_powermodels_json(net), TargetFormat::EgretJson => write_egret_json(net), + TargetFormat::SurgeJson => write_surge_json(net), TargetFormat::Psse => write_psse(net), TargetFormat::PowerWorld => write_powerworld(net), // From another source (or no retained source): canonical MATPOWER from // the folded model, which itemizes what it can't carry (HVDC, gen caps, // extras, a partial-cost case). TargetFormat::Matpower => matpower::write_matpower_conversion(net), - } + }; + with_source_warnings(conversion, net, format) } /// Whether a write target is the same format the network was read from. @@ -233,11 +253,28 @@ fn same_format(target: TargetFormat, source: SourceFormat) -> bool { (TargetFormat::Matpower, SourceFormat::Matpower) | (TargetFormat::PowerModelsJson, SourceFormat::PowerModelsJson) | (TargetFormat::EgretJson, SourceFormat::EgretJson) + | (TargetFormat::SurgeJson, SourceFormat::Surge) | (TargetFormat::Psse, SourceFormat::Psse) | (TargetFormat::PowerWorld, SourceFormat::PowerWorld) ) } +fn with_source_warnings( + mut conversion: Conversion, + net: &Network, + target: TargetFormat, +) -> Conversion { + if same_format(target, net.source_format) { + return conversion; + } + if matches!(net.source_format, SourceFormat::Surge) { + conversion.warnings.extend(surge::source_loss_warnings(net)); + conversion.warnings.sort(); + conversion.warnings.dedup(); + } + conversion +} + /// JSON number for a finite `f64`; `Value::Null` for `NaN`/`Β±Inf`. pub(crate) fn jnum(x: f64) -> Value { serde_json::Number::from_f64(x).map_or(Value::Null, Value::Number) diff --git a/powerio/src/format/surge.rs b/powerio/src/format/surge.rs new file mode 100644 index 0000000..4c9873b --- /dev/null +++ b/powerio/src/format/surge.rs @@ -0,0 +1,1226 @@ +//! Read and write Surge native `surge-json` network documents. +//! +//! This module deliberately depends only on `serde_json` and the `Network` hub. +//! Surge's native JSON envelope is versioned and the network body is richer than +//! powerio's neutral model, so the reader maps the electrical core and the writer +//! emits a network profile document that Surge can load. Same-format byte-exact +//! writes still use the retained source in the format hub. + +use std::collections::BTreeMap; +use std::sync::Arc; + +use serde_json::{Map, Value}; + +use super::{Conversion, finish, jnum}; +use crate::network::{ + Branch, Bus, BusId, BusType, Extras, GEN_EXTRA_KEYS, GenCaps, GenCost, Generator, Hvdc, Load, + Network, Shunt, SourceFormat, Storage, +}; +use crate::{Error, Result}; + +const FMT: &str = "Surge JSON"; +const FORMAT_VALUE: &str = "surge-json"; +const SCHEMA_VERSION: &str = "0.1.0"; +const DEG_PER_RAD: f64 = 180.0 / std::f64::consts::PI; +const EPS: f64 = 1e-12; + +#[must_use] +pub fn write_surge_json(net: &Network) -> Conversion { + let mut warnings = Vec::new(); + let mut network = Map::new(); + + network.insert("name".into(), Value::String(net.name.clone())); + network.insert("base_mva".into(), jnum(net.base_mva)); + network.insert("freq_hz".into(), jnum(60.0)); + + let buses = net.buses.iter().map(bus_obj).collect(); + network.insert("buses".into(), Value::Array(buses)); + + let loads = net.loads.iter().enumerate().map(load_obj).collect(); + network.insert("loads".into(), Value::Array(loads)); + + let shunts = net.shunts.iter().enumerate().map(shunt_obj).collect(); + network.insert("fixed_shunts".into(), Value::Array(shunts)); + + let branches = net.branches.iter().enumerate().map(branch_obj).collect(); + network.insert("branches".into(), Value::Array(branches)); + + let mut gen_counts: BTreeMap = BTreeMap::new(); + let mut generators = Vec::new(); + for g in &net.generators { + generators.push(gen_obj(g, &mut gen_counts, &mut warnings)); + } + for st in &net.storage { + generators.push(storage_gen_obj(st, &mut gen_counts)); + } + network.insert("generators".into(), Value::Array(generators)); + + if !net.hvdc.is_empty() { + let links = net + .hvdc + .iter() + .enumerate() + .map(|(i, dc)| hvdc_link_obj(dc, i, &mut warnings)) + .collect(); + let mut hvdc = Map::new(); + hvdc.insert("links".into(), Value::Array(links)); + network.insert("hvdc".into(), Value::Object(hvdc)); + } + + network.insert("metadata".into(), Value::Object(Map::new())); + network.insert("market_data".into(), Value::Object(Map::new())); + network.insert("controls".into(), Value::Object(Map::new())); + network.insert("cim".into(), Value::Object(Map::new())); + + let mut meta = Map::new(); + meta.insert("producer".into(), Value::String("surge".into())); + meta.insert("profile".into(), Value::String("network".into())); + + let mut root = Map::new(); + root.insert("format".into(), Value::String(FORMAT_VALUE.into())); + root.insert( + "schema_version".into(), + Value::String(SCHEMA_VERSION.into()), + ); + root.insert("meta".into(), Value::Object(meta)); + root.insert("network".into(), Value::Object(network)); + + finish(root, warnings) +} + +fn bus_type(kind: BusType) -> &'static str { + match kind { + BusType::Pq => "PQ", + BusType::Pv => "PV", + BusType::Ref => "Slack", + BusType::Isolated => "Isolated", + } +} + +fn bus_obj(b: &Bus) -> Value { + let mut m = Map::new(); + m.insert("number".into(), Value::from(b.id.0 as u64)); + m.insert( + "name".into(), + Value::String(b.name.clone().unwrap_or_default()), + ); + m.insert("bus_type".into(), Value::String(bus_type(b.kind).into())); + m.insert("base_kv".into(), jnum(b.base_kv)); + m.insert("voltage_magnitude_pu".into(), jnum(b.vm)); + m.insert("voltage_angle_rad".into(), jnum(b.va.to_radians())); + m.insert("voltage_min_pu".into(), jnum(b.vmin)); + m.insert("voltage_max_pu".into(), jnum(b.vmax)); + m.insert("shunt_conductance_mw".into(), jnum(0.0)); + m.insert("shunt_susceptance_mvar".into(), jnum(0.0)); + m.insert("area".into(), Value::from(b.area as u64)); + m.insert("zone".into(), Value::from(b.zone as u64)); + m.insert("island_id".into(), Value::from(0_u64)); + Value::Object(m) +} + +fn load_obj((i, l): (usize, &Load)) -> Value { + let mut m = Map::new(); + m.insert("id".into(), Value::String(format!("load_{}", i + 1))); + m.insert("bus".into(), Value::from(l.bus.0 as u64)); + m.insert("active_power_demand_mw".into(), jnum(l.p)); + m.insert("reactive_power_demand_mvar".into(), jnum(l.q)); + m.insert("in_service".into(), Value::Bool(l.in_service)); + m.insert("conforming".into(), Value::Bool(true)); + m.insert("connection".into(), Value::String("WyeGrounded".into())); + m.insert("zip_p_impedance_frac".into(), jnum(0.0)); + m.insert("zip_p_current_frac".into(), jnum(0.0)); + m.insert("zip_p_power_frac".into(), jnum(1.0)); + m.insert("zip_q_impedance_frac".into(), jnum(0.0)); + m.insert("zip_q_current_frac".into(), jnum(0.0)); + m.insert("zip_q_power_frac".into(), jnum(1.0)); + Value::Object(m) +} + +fn shunt_obj((i, s): (usize, &Shunt)) -> Value { + let mut m = Map::new(); + m.insert("id".into(), Value::String(format!("shunt_{}", i + 1))); + m.insert("bus".into(), Value::from(s.bus.0 as u64)); + m.insert("g_mw".into(), jnum(s.g)); + m.insert("b_mvar".into(), jnum(s.b)); + m.insert("in_service".into(), Value::Bool(s.in_service)); + m.insert( + "shunt_type".into(), + Value::String(if s.b < 0.0 { "Reactor" } else { "Capacitor" }.into()), + ); + Value::Object(m) +} + +fn branch_obj((_i, br): (usize, &Branch)) -> Value { + let mut m = Map::new(); + m.insert("from_bus".into(), Value::from(br.from.0 as u64)); + m.insert("to_bus".into(), Value::from(br.to.0 as u64)); + m.insert("circuit".into(), Value::String("1".into())); + m.insert("r".into(), jnum(br.r)); + m.insert("x".into(), jnum(br.x)); + m.insert("b".into(), jnum(br.b)); + m.insert("tap".into(), jnum(br.effective_tap())); + m.insert("phase_shift_rad".into(), jnum(br.shift.to_radians())); + m.insert("rating_a_mva".into(), jnum(br.rate_a)); + m.insert("rating_b_mva".into(), jnum(br.rate_b)); + m.insert("rating_c_mva".into(), jnum(br.rate_c)); + m.insert("in_service".into(), Value::Bool(br.in_service)); + m.insert( + "branch_type".into(), + Value::String( + if br.is_transformer() { + "Transformer" + } else { + "Line" + } + .into(), + ), + ); + m.insert("angle_diff_min_rad".into(), jnum(br.angmin.to_radians())); + m.insert("angle_diff_max_rad".into(), jnum(br.angmax.to_radians())); + m.insert("g_pi".into(), jnum(0.0)); + m.insert("g_mag".into(), jnum(0.0)); + m.insert("b_mag".into(), jnum(0.0)); + Value::Object(m) +} + +fn next_id(prefix: &str, counts: &mut BTreeMap, bus: BusId) -> String { + let count = counts.entry(bus).or_insert(0); + *count += 1; + format!("{prefix}_{}_{}", bus.0, *count) +} + +fn gen_obj( + g: &Generator, + counts: &mut BTreeMap, + warnings: &mut Vec, +) -> Value { + let mut m = Map::new(); + m.insert("id".into(), Value::String(next_id("gen", counts, g.bus))); + m.insert("bus".into(), Value::from(g.bus.0 as u64)); + m.insert("p".into(), jnum(g.pg)); + m.insert("q".into(), jnum(g.qg)); + m.insert("pmax".into(), jnum(g.pmax)); + m.insert("pmin".into(), jnum(g.pmin)); + m.insert("qmax".into(), jnum(g.qmax)); + m.insert("qmin".into(), jnum(g.qmin)); + m.insert("voltage_setpoint_pu".into(), jnum(g.vg)); + m.insert("machine_base_mva".into(), jnum(g.mbase)); + m.insert("in_service".into(), Value::Bool(g.in_service)); + m.insert("gen_type".into(), Value::String("Synchronous".into())); + m.insert("pfr_eligible".into(), Value::Bool(true)); + m.insert("quick_start".into(), Value::Bool(false)); + m.insert("voltage_regulated".into(), Value::Bool(true)); + if let Some(cost) = &g.cost { + if let Some(cost) = cost_obj(cost, warnings) { + m.insert("cost".into(), cost); + } + } + if g.has_caps() { + warnings.push(format!( + "generator at bus {} has MATPOWER capability/ramp columns not represented in Surge JSON", + g.bus + )); + } + Value::Object(m) +} + +fn cost_obj(cost: &GenCost, warnings: &mut Vec) -> Option { + match cost.model { + 2 => { + let want = cost.ncost.min(cost.coeffs.len()); + let coeffs = cost.coeffs[..want].iter().copied().map(jnum).collect(); + let mut curve = Map::new(); + curve.insert("coeffs".into(), Value::Array(coeffs)); + curve.insert("startup".into(), jnum(cost.startup)); + curve.insert("shutdown".into(), jnum(cost.shutdown)); + + let mut wrapper = Map::new(); + wrapper.insert("Polynomial".into(), Value::Object(curve)); + Some(Value::Object(wrapper)) + } + 1 => { + let want = (cost.ncost * 2).min(cost.coeffs.len()); + if want % 2 != 0 { + warnings.push( + "piecewise generator cost has an odd coefficient count; cost dropped".into(), + ); + return None; + } + let mut points = Vec::new(); + for pair in cost.coeffs[..want].chunks(2) { + points.push(Value::Array(vec![jnum(pair[0]), jnum(pair[1])])); + } + let mut curve = Map::new(); + curve.insert("points".into(), Value::Array(points)); + curve.insert("startup".into(), jnum(cost.startup)); + curve.insert("shutdown".into(), jnum(cost.shutdown)); + + let mut wrapper = Map::new(); + wrapper.insert("PiecewiseLinear".into(), Value::Object(curve)); + Some(Value::Object(wrapper)) + } + _ => { + warnings.push(format!( + "unsupported generator cost model {} dropped in Surge JSON", + cost.model + )); + None + } + } +} + +fn storage_gen_obj(st: &Storage, counts: &mut BTreeMap) -> Value { + let mut m = Map::new(); + m.insert( + "id".into(), + Value::String(next_id("storage", counts, st.bus)), + ); + m.insert("bus".into(), Value::from(st.bus.0 as u64)); + m.insert("p".into(), jnum(st.ps)); + m.insert("q".into(), jnum(st.qs)); + m.insert("pmax".into(), jnum(st.discharge_rating)); + m.insert("pmin".into(), jnum(-st.charge_rating)); + m.insert("qmax".into(), jnum(st.qmax)); + m.insert("qmin".into(), jnum(st.qmin)); + m.insert("voltage_setpoint_pu".into(), jnum(1.0)); + m.insert("machine_base_mva".into(), jnum(st.thermal_rating.max(1.0))); + m.insert("in_service".into(), Value::Bool(st.in_service)); + m.insert("gen_type".into(), Value::String("Synchronous".into())); + m.insert("pfr_eligible".into(), Value::Bool(true)); + m.insert("quick_start".into(), Value::Bool(false)); + m.insert("voltage_regulated".into(), Value::Bool(false)); + + let mut storage = Map::new(); + storage.insert("energy_capacity_mwh".into(), jnum(st.energy_rating)); + storage.insert("soc_initial_mwh".into(), jnum(st.energy)); + storage.insert("soc_min_mwh".into(), jnum(0.0)); + storage.insert("soc_max_mwh".into(), jnum(st.energy_rating)); + storage.insert("charge_efficiency".into(), jnum(st.charge_efficiency)); + storage.insert("discharge_efficiency".into(), jnum(st.discharge_efficiency)); + storage.insert("variable_cost_per_mwh".into(), jnum(0.0)); + storage.insert("degradation_cost_per_mwh".into(), jnum(0.0)); + storage.insert( + "dispatch_mode".into(), + Value::String("CostMinimization".into()), + ); + m.insert("storage".into(), Value::Object(storage)); + + Value::Object(m) +} + +fn hvdc_link_obj(dc: &Hvdc, i: usize, warnings: &mut Vec) -> Value { + if dc.qf != 0.0 + || dc.qt != 0.0 + || dc.qminf != 0.0 + || dc.qmaxf != 0.0 + || dc.qmint != 0.0 + || dc.qmaxt != 0.0 + || dc.loss0 != 0.0 + || dc.loss1 != 0.0 + { + warnings.push(format!( + "dcline {} reactive limits or loss model mapped best-effort in Surge JSON", + i + 1 + )); + } + + let mut m = Map::new(); + m.insert("technology".into(), Value::String("lcc".into())); + m.insert("name".into(), Value::String(format!("dcl_{}", i + 1))); + m.insert( + "mode".into(), + Value::String( + if dc.in_service { + "PowerControl" + } else { + "Blocked" + } + .into(), + ), + ); + m.insert("rectifier".into(), lcc_terminal_obj(dc.from, dc.in_service)); + m.insert("inverter".into(), lcc_terminal_obj(dc.to, dc.in_service)); + m.insert("scheduled_setpoint".into(), jnum(dc.pf)); + m.insert("p_dc_min_mw".into(), jnum(dc.pmin)); + m.insert("p_dc_max_mw".into(), jnum(dc.pmax)); + m.insert("scheduled_voltage_kv".into(), jnum(0.0)); + m.insert("resistance_ohm".into(), jnum(0.0)); + Value::Object(m) +} + +fn lcc_terminal_obj(bus: BusId, in_service: bool) -> Value { + let mut m = Map::new(); + m.insert("bus".into(), Value::from(bus.0 as u64)); + m.insert("in_service".into(), Value::Bool(in_service)); + m.insert("n_bridges".into(), Value::from(1_u64)); + m.insert("alpha_min".into(), jnum(5.0)); + m.insert("alpha_max".into(), jnum(90.0)); + m.insert("base_voltage_kv".into(), jnum(0.0)); + m.insert("commutation_reactance_ohm".into(), jnum(0.0)); + m.insert("commutation_resistance_ohm".into(), jnum(0.0)); + m.insert("tap".into(), jnum(1.0)); + m.insert("tap_min".into(), jnum(0.9)); + m.insert("tap_max".into(), jnum(1.1)); + m.insert("tap_step".into(), jnum(0.00625)); + m.insert("turns_ratio".into(), jnum(1.0)); + Value::Object(m) +} + +pub fn parse_surge_json(content: &str) -> Result { + parse_surge_json_source(Arc::new(content.to_owned()), None) +} + +pub(crate) fn parse_surge_json_source( + source: Arc, + name_hint: Option<&str>, +) -> Result { + let content: &str = &source; + let root_value: Value = serde_json::from_str(content).map_err(|e| Error::FormatRead { + format: FMT, + message: e.to_string(), + })?; + let root = object(&root_value, "top level")?; + validate_envelope(root)?; + let network = object_field(root, "network")?; + + let mut buses = Vec::new(); + let mut shunts = Vec::new(); + for value in array_field(network, "buses", true)? { + let (bus, bus_shunt) = read_bus(value)?; + buses.push(bus); + if let Some(shunt) = bus_shunt { + shunts.push(shunt); + } + } + + shunts.extend( + array_field(network, "fixed_shunts", false)? + .into_iter() + .map(read_fixed_shunt) + .collect::>>()?, + ); + + let mut generators = Vec::new(); + let mut storage = Vec::new(); + for value in array_field(network, "generators", false)? { + let (generator, storage_record) = read_generator(value)?; + generators.push(generator); + if let Some(storage_record) = storage_record { + storage.push(storage_record); + } + } + + let name = string_map(network, "name") + .filter(|name| !name.is_empty()) + .or(name_hint) + .unwrap_or("case") + .to_string(); + + let net = Network { + name, + base_mva: f_map_or(network, "base_mva", 100.0)?, + buses, + loads: array_field(network, "loads", false)? + .into_iter() + .map(read_load) + .collect::>>()?, + shunts, + branches: array_field(network, "branches", false)? + .into_iter() + .map(read_branch) + .collect::>>()?, + generators, + storage, + hvdc: read_hvdc(network)?, + source_format: SourceFormat::Surge, + source: Some(source), + }; + net.check_references(FMT)?; + Ok(net) +} + +fn validate_envelope(root: &Map) -> Result<()> { + let format = required_string_map(root, "format")?; + if format != FORMAT_VALUE { + return Err(format_error(format!( + "unsupported `format` value `{format}`; expected `{FORMAT_VALUE}`" + ))); + } + let schema_version = required_string_map(root, "schema_version")?; + if schema_version != SCHEMA_VERSION { + return Err(format_error(format!( + "unsupported `schema_version` value `{schema_version}`; expected `{SCHEMA_VERSION}`" + ))); + } + let meta = object_field(root, "meta")?; + if let Some(producer) = string_map(meta, "producer") { + if producer != "surge" { + return Err(format_error(format!( + "unsupported `meta.producer` value `{producer}`" + ))); + } + } + if let Some(profile) = string_map(meta, "profile") { + if !matches!(profile, "network" | "dispatch" | "results") { + return Err(format_error(format!( + "unsupported `meta.profile` value `{profile}`" + ))); + } + } + if !root.contains_key("network") { + return Err(format_error("missing object `network`")); + } + Ok(()) +} + +fn read_bus(value: &Value) -> Result<(Bus, Option)> { + let obj = object(value, "bus record")?; + let id = BusId(required_usize(obj, "number")?); + let g = f_map_or(obj, "shunt_conductance_mw", 0.0)?; + let b = f_map_or(obj, "shunt_susceptance_mvar", 0.0)?; + let shunt = if g != 0.0 || b != 0.0 { + Some(Shunt { + bus: id, + g, + b, + in_service: true, + extras: Extras::new(), + }) + } else { + None + }; + let bus = Bus { + id, + kind: read_bus_type(string_map(obj, "bus_type").unwrap_or("PQ"))?, + vm: f_map_or(obj, "voltage_magnitude_pu", 1.0)?, + va: f_map_or(obj, "voltage_angle_rad", 0.0)? * DEG_PER_RAD, + base_kv: f_map_or(obj, "base_kv", 0.0)?, + vmax: f_map_or(obj, "voltage_max_pu", 1.1)?, + vmin: f_map_or(obj, "voltage_min_pu", 0.9)?, + area: usize_map_or(obj, "area", 1)?, + zone: usize_map_or(obj, "zone", 1)?, + name: string_map(obj, "name") + .filter(|name| !name.is_empty()) + .map(str::to_string), + extras: Extras::new(), + }; + Ok((bus, shunt)) +} + +fn read_bus_type(value: &str) -> Result { + match value { + "PQ" => Ok(BusType::Pq), + "PV" => Ok(BusType::Pv), + "Slack" | "REF" | "Ref" => Ok(BusType::Ref), + "Isolated" => Ok(BusType::Isolated), + other => Err(format_error(format!("unknown bus_type `{other}`"))), + } +} + +fn read_load(value: &Value) -> Result { + let obj = object(value, "load record")?; + Ok(Load { + bus: BusId(required_usize(obj, "bus")?), + p: f_map_or(obj, "active_power_demand_mw", 0.0)?, + q: f_map_or(obj, "reactive_power_demand_mvar", 0.0)?, + in_service: bool_map_or(obj, "in_service", true)?, + extras: Extras::new(), + }) +} + +fn read_fixed_shunt(value: &Value) -> Result { + let obj = object(value, "fixed_shunt record")?; + Ok(Shunt { + bus: BusId(required_usize(obj, "bus")?), + g: f_map_alias_or(obj, &["g_mw", "conductance_mw"], 0.0)?, + b: f_map_alias_or(obj, &["b_mvar", "susceptance_mvar"], 0.0)?, + in_service: bool_map_or(obj, "in_service", true)?, + extras: Extras::new(), + }) +} + +fn read_branch(value: &Value) -> Result { + let obj = object(value, "branch record")?; + let branch_type = string_map(obj, "branch_type").unwrap_or("Line"); + let tap_value = f_map_or(obj, "tap", 1.0)?; + let shift = f_map_or(obj, "phase_shift_rad", 0.0)? * DEG_PER_RAD; + let tap = if branch_type == "Line" && (tap_value - 1.0).abs() < EPS && shift.abs() < EPS { + 0.0 + } else { + tap_value + }; + Ok(Branch { + from: BusId(required_usize(obj, "from_bus")?), + to: BusId(required_usize(obj, "to_bus")?), + r: f_map_or(obj, "r", 0.0)?, + x: f_map_or(obj, "x", 0.0)?, + b: f_map_or(obj, "b", 0.0)?, + rate_a: f_map_or(obj, "rating_a_mva", 0.0)?, + rate_b: f_map_or(obj, "rating_b_mva", 0.0)?, + rate_c: f_map_or(obj, "rating_c_mva", 0.0)?, + tap, + shift, + in_service: bool_map_or(obj, "in_service", true)?, + angmin: f_map_or(obj, "angle_diff_min_rad", -std::f64::consts::TAU)? * DEG_PER_RAD, + angmax: f_map_or(obj, "angle_diff_max_rad", std::f64::consts::TAU)? * DEG_PER_RAD, + extras: Extras::new(), + }) +} + +fn read_generator(value: &Value) -> Result<(Generator, Option)> { + let obj = object(value, "generator record")?; + let mut caps: GenCaps = [None; GEN_EXTRA_KEYS.len()]; + if let Some(apf) = obj.get("agc_participation_factor").and_then(Value::as_f64) { + if let Some(slot) = GEN_EXTRA_KEYS.iter().position(|key| *key == "apf") { + caps[slot] = Some(apf); + } + } + + let bus = BusId(required_usize(obj, "bus")?); + let pg = f_map_alias_or(obj, &["p", "pg"], 0.0)?; + let qg = f_map_alias_or(obj, &["q", "qg"], 0.0)?; + let pmax = f_map_or(obj, "pmax", 0.0)?; + let pmin = f_map_or(obj, "pmin", 0.0)?; + let qmax = f_map_or(obj, "qmax", 0.0)?; + let qmin = f_map_or(obj, "qmin", 0.0)?; + let in_service = bool_map_or(obj, "in_service", true)?; + + let generator = Generator { + bus, + pg, + qg, + pmax, + pmin, + qmax, + qmin, + vg: f_map_or(obj, "voltage_setpoint_pu", 1.0)?, + mbase: f_map_or(obj, "machine_base_mva", 0.0)?, + in_service, + cost: match obj.get("cost") { + Some(Value::Null) | None => None, + Some(value) => Some(read_cost(value)?), + }, + caps, + }; + + let storage = match obj.get("storage") { + Some(Value::Null) | None => None, + Some(value) => Some(read_storage( + obj, value, bus, pg, qg, pmax, pmin, qmax, qmin, in_service, + )?), + }; + + Ok((generator, storage)) +} + +fn read_cost(value: &Value) -> Result { + let obj = object(value, "generator cost")?; + if let Some(poly) = obj.get("Polynomial") { + let poly = object(poly, "Polynomial cost")?; + let coeffs = number_array(poly, "coeffs")?; + return Ok(GenCost { + model: 2, + startup: f_map_or(poly, "startup", 0.0)?, + shutdown: f_map_or(poly, "shutdown", 0.0)?, + ncost: coeffs.len(), + coeffs, + }); + } + if let Some(piecewise) = obj.get("PiecewiseLinear").or_else(|| obj.get("Piecewise")) { + let piecewise = object(piecewise, "PiecewiseLinear cost")?; + let points = array_field(piecewise, "points", true)?; + let ncost = points.len(); + let mut coeffs = Vec::with_capacity(points.len() * 2); + for point in &points { + let pair = point + .as_array() + .ok_or_else(|| format_error("piecewise cost point must be a two-element array"))?; + if pair.len() != 2 { + return Err(format_error("piecewise cost point must have two elements")); + } + coeffs.push(value_to_f64(&pair[0], "piecewise cost MW")?); + coeffs.push(value_to_f64(&pair[1], "piecewise cost value")?); + } + return Ok(GenCost { + model: 1, + startup: f_map_or(piecewise, "startup", 0.0)?, + shutdown: f_map_or(piecewise, "shutdown", 0.0)?, + ncost, + coeffs, + }); + } + Err(format_error("unsupported generator cost curve")) +} + +#[allow(clippy::too_many_arguments)] +fn read_storage( + _generator: &Map, + storage: &Value, + bus: BusId, + pg: f64, + qg: f64, + pmax: f64, + pmin: f64, + qmax: f64, + qmin: f64, + in_service: bool, +) -> Result { + let obj = object(storage, "storage params")?; + let efficiency = f_map_or(obj, "efficiency", 1.0)?; + let split_efficiency = if efficiency >= 0.0 { + efficiency.sqrt() + } else { + 1.0 + }; + let energy_rating = f_map_alias_or(obj, &["energy_capacity_mwh", "soc_max_mwh"], 0.0)?; + Ok(Storage { + bus, + ps: pg, + qs: qg, + energy: f_map_or(obj, "soc_initial_mwh", 0.0)?, + energy_rating, + charge_rating: if pmin < 0.0 { -pmin } else { 0.0 }, + discharge_rating: pmax.max(0.0), + charge_efficiency: f_map_or(obj, "charge_efficiency", split_efficiency)?, + discharge_efficiency: f_map_or(obj, "discharge_efficiency", split_efficiency)?, + thermal_rating: pmax.abs().max(pmin.abs()), + qmin, + qmax, + r: 0.0, + x: 0.0, + p_loss: 0.0, + q_loss: 0.0, + in_service, + extras: Extras::new(), + }) +} + +fn read_hvdc(network: &Map) -> Result> { + let Some(hvdc) = network.get("hvdc") else { + return Ok(Vec::new()); + }; + if hvdc.is_null() { + return Ok(Vec::new()); + } + let hvdc = object(hvdc, "hvdc")?; + let mut out = Vec::new(); + for link in array_field(hvdc, "links", false)? { + out.push(read_hvdc_link(link)?); + } + Ok(out) +} + +fn read_hvdc_link(value: &Value) -> Result { + let obj = object(value, "hvdc link")?; + let tech = string_map(obj, "technology").unwrap_or("lcc"); + let (from_terminal, to_terminal) = match tech { + "lcc" | "Lcc" | "LCC" => ( + object_field(obj, "rectifier")?, + object_field(obj, "inverter")?, + ), + "vsc" | "Vsc" | "VSC" => ( + object_field(obj, "converter1")?, + object_field(obj, "converter2")?, + ), + other => { + return Err(format_error(format!( + "unsupported hvdc technology `{other}`" + ))); + } + }; + let from = BusId(required_usize(from_terminal, "bus")?); + let to = BusId(required_usize(to_terminal, "bus")?); + let setpoint = f_map_alias_or( + obj, + &["scheduled_setpoint", "scheduled_setpoint_mw"], + f_map_or(from_terminal, "dc_setpoint", 0.0)?, + )?; + let pmin = f_map_or(obj, "p_dc_min_mw", setpoint.min(0.0))?; + let pmax = f_map_or(obj, "p_dc_max_mw", setpoint.max(0.0))?; + let in_service = string_map(obj, "mode").unwrap_or("PowerControl") != "Blocked" + && bool_map_or(from_terminal, "in_service", true)? + && bool_map_or(to_terminal, "in_service", true)?; + + Ok(Hvdc { + from, + to, + in_service, + pf: setpoint, + pt: -setpoint, + qf: 0.0, + qt: 0.0, + vf: f_map_or(from_terminal, "ac_setpoint", 1.0)?, + vt: f_map_or(to_terminal, "ac_setpoint", 1.0)?, + pmin, + pmax, + qminf: f_map_or(from_terminal, "q_min_mvar", 0.0)?, + qmaxf: f_map_or(from_terminal, "q_max_mvar", 0.0)?, + qmint: f_map_or(to_terminal, "q_min_mvar", 0.0)?, + qmaxt: f_map_or(to_terminal, "q_max_mvar", 0.0)?, + loss0: f_map_or(from_terminal, "loss_constant_mw", 0.0)? + + f_map_or(to_terminal, "loss_constant_mw", 0.0)?, + loss1: f_map_or(from_terminal, "loss_linear", 0.0)? + + f_map_or(to_terminal, "loss_linear", 0.0)?, + extras: Extras::new(), + }) +} + +pub(crate) fn source_loss_warnings(net: &Network) -> Vec { + if !matches!(net.source_format, SourceFormat::Surge) { + return Vec::new(); + } + let Some(source) = &net.source else { + return Vec::new(); + }; + let Ok(root_value) = serde_json::from_str::(source) else { + return vec!["surge source could not be inspected for source loss warnings".into()]; + }; + let Some(root) = root_value.as_object() else { + return Vec::new(); + }; + let Some(network) = root.get("network").and_then(Value::as_object) else { + return Vec::new(); + }; + + let mut warnings = Vec::new(); + + let profile = root + .get("meta") + .and_then(Value::as_object) + .and_then(|meta| string_map(meta, "profile")); + if matches!(profile, Some("dispatch" | "results")) || has_nonempty(root, "dispatch") { + warnings.push("surge dispatch profile data ignored by powerio's Network hub".into()); + } + if matches!(profile, Some("results")) || has_nonempty(root, "solution") { + warnings.push("surge solution profile data ignored by powerio's Network hub".into()); + } + + if num_not_default(network, "freq_hz", 60.0) { + warnings.push("surge system frequency dropped".into()); + } + + let top = [ + "facts_devices", + "topology", + "controls", + "area_schedules", + "interfaces", + "flowgates", + "market_data", + "pumped_hydro_units", + "combined_cycle_plants", + "dispatchable_loads", + "induction_machines", + "power_injections", + "breaker_ratings", + "conditional_limits", + "nomograms", + "cim", + "metadata", + ]; + let dropped_top: Vec<&str> = top + .into_iter() + .filter(|key| has_nonempty(network, key)) + .collect(); + if !dropped_top.is_empty() { + warnings.push(format!( + "surge network sections dropped: {}", + dropped_top.join(", ") + )); + } + + warn_count( + &mut warnings, + network, + "loads", + "load ZIP, composition, frequency, classification, or ownership fields dropped", + load_has_source_only_fields, + ); + warn_count( + &mut warnings, + network, + "branches", + "branch control, phase-shifter bounds, sequence, thermal, cost, or circuit metadata dropped", + branch_has_source_only_fields, + ); + warn_count( + &mut warnings, + network, + "generators", + "generator commitment, ramping, fuel, market, reserve, emission, classification, or richer storage fields dropped", + generator_has_source_only_fields, + ); + if has_nonempty(network, "hvdc") { + warnings.push( + "surge HVDC converter, reactive, loss, and control details mapped best-effort".into(), + ); + } + + warnings +} + +fn warn_count( + warnings: &mut Vec, + network: &Map, + section: &str, + message: &str, + predicate: fn(&Map) -> bool, +) { + let count = network + .get(section) + .and_then(Value::as_array) + .map_or(0, |items| { + items + .iter() + .filter_map(Value::as_object) + .filter(|item| predicate(item)) + .count() + }); + if count > 0 { + warnings.push(format!("{count} surge {message}")); + } +} + +fn load_has_source_only_fields(load: &Map) -> bool { + num_not_default(load, "zip_p_impedance_frac", 0.0) + || num_not_default(load, "zip_p_current_frac", 0.0) + || num_not_default(load, "zip_p_power_frac", 1.0) + || num_not_default(load, "zip_q_impedance_frac", 0.0) + || num_not_default(load, "zip_q_current_frac", 0.0) + || num_not_default(load, "zip_q_power_frac", 1.0) + || num_not_default(load, "freq_sensitivity_p_pct_per_hz", 0.0) + || num_not_default(load, "freq_sensitivity_q_pct_per_hz", 0.0) + || num_not_default(load, "frac_static", 1.0) + || num_not_default(load, "frac_motor_a", 0.0) + || num_not_default(load, "frac_motor_b", 0.0) + || num_not_default(load, "frac_motor_c", 0.0) + || num_not_default(load, "frac_motor_d", 0.0) + || num_not_default(load, "frac_electronic", 0.0) + || bool_not_default(load, "conforming", true) + || string_not_default(load, "connection", "WyeGrounded") + || has_nonempty(load, "owners") + || has_nonempty(load, "load_class") + || has_nonempty(load, "classification") +} + +fn branch_has_source_only_fields(branch: &Map) -> bool { + [ + "g_pi", + "g_mag", + "b_mag", + "g_shunt_from", + "b_shunt_from", + "g_shunt_to", + "b_shunt_to", + "bi0", + "bj0", + "gi0", + "gj0", + "r_temp_coeff", + "skin_effect_alpha", + "cost_startup", + "cost_shutdown", + "tap_step", + "phase_step_rad", + ] + .into_iter() + .any(|key| num_not_default(branch, key, 0.0)) + || has_nonempty(branch, "phase_min_rad") + || has_nonempty(branch, "phase_max_rad") + || num_not_default(branch, "tap_min", 1.0) + || num_not_default(branch, "tap_max", 1.0) + || bool_not_default(branch, "bypassed", false) + || bool_not_default(branch, "delta_connected", false) + || string_not_default(branch, "phase_mode", "fixed") + || string_not_default(branch, "tap_mode", "fixed") + || string_not_default(branch, "circuit", "1") + || has_nonempty(branch, "opf_control") + || has_nonempty(branch, "owners") + || has_nonempty(branch, "zero_sequence") +} + +fn generator_has_source_only_fields(generator: &Map) -> bool { + [ + "commitment", + "ramping", + "market", + "reserve_offers", + "qualifications", + "emission_rates", + "fuel_type", + "machine_id", + "commitment_status", + "ramp_down_curve", + "ramp_up_curve", + "min_down_time_hr", + "min_up_time_hr", + "hours_offline", + "hours_online", + "reg_bus", + ] + .into_iter() + .any(|key| has_nonempty(generator, key)) + || bool_not_default(generator, "quick_start", false) + || bool_not_default(generator, "grid_forming", false) + || bool_not_default(generator, "curtailable", false) + || bool_not_default(generator, "voltage_regulated", true) + || generator + .get("gen_type") + .and_then(Value::as_str) + .is_some_and(|kind| kind != "Synchronous") + || generator + .get("storage") + .and_then(Value::as_object) + .is_some_and(storage_has_source_only_fields) +} + +fn storage_has_source_only_fields(storage: &Map) -> bool { + num_not_default(storage, "variable_cost_per_mwh", 0.0) + || num_not_default(storage, "degradation_cost_per_mwh", 0.0) + || num_not_default(storage, "self_schedule_mw", 0.0) + || has_nonempty(storage, "chemistry") + || string_not_default(storage, "dispatch_mode", "CostMinimization") +} + +fn format_error(message: impl Into) -> Error { + Error::FormatRead { + format: FMT, + message: message.into(), + } +} + +fn object<'a>(value: &'a Value, context: &str) -> Result<&'a Map> { + value + .as_object() + .ok_or_else(|| format_error(format!("{context} is not a JSON object"))) +} + +fn object_field<'a>(obj: &'a Map, key: &str) -> Result<&'a Map> { + let value = obj + .get(key) + .ok_or_else(|| format_error(format!("missing object `{key}`")))?; + object(value, key) +} + +fn array_field<'a>( + obj: &'a Map, + key: &str, + required: bool, +) -> Result> { + match obj.get(key) { + Some(Value::Array(items)) => Ok(items.iter().collect()), + Some(Value::Null) | None if !required => Ok(Vec::new()), + None => Err(format_error(format!("missing array `{key}`"))), + Some(_) => Err(format_error(format!("`{key}` must be an array"))), + } +} + +fn required_string_map<'a>(obj: &'a Map, key: &str) -> Result<&'a str> { + string_map(obj, key).ok_or_else(|| format_error(format!("missing string `{key}`"))) +} + +fn string_map<'a>(obj: &'a Map, key: &str) -> Option<&'a str> { + obj.get(key).and_then(Value::as_str) +} + +fn required_usize(obj: &Map, key: &str) -> Result { + let value = obj + .get(key) + .ok_or_else(|| format_error(format!("missing integer `{key}`")))?; + value_to_usize(value, key) +} + +fn usize_map_or(obj: &Map, key: &str, default: usize) -> Result { + match obj.get(key) { + Some(Value::Null) | None => Ok(default), + Some(value) => value_to_usize(value, key), + } +} + +fn f_map_or(obj: &Map, key: &str, default: f64) -> Result { + match obj.get(key) { + Some(Value::Null) | None => Ok(default), + Some(value) => value_to_f64(value, key), + } +} + +fn f_map_alias_or(obj: &Map, keys: &[&str], default: f64) -> Result { + for key in keys { + if let Some(value) = obj.get(*key) { + return if value.is_null() { + Ok(default) + } else { + value_to_f64(value, key) + }; + } + } + Ok(default) +} + +fn bool_map_or(obj: &Map, key: &str, default: bool) -> Result { + match obj.get(key) { + Some(Value::Null) | None => Ok(default), + Some(Value::Bool(value)) => Ok(*value), + Some(Value::Number(value)) => value + .as_f64() + .map(|value| value != 0.0) + .ok_or_else(|| format_error(format!("`{key}` is not a finite bool-like number"))), + Some(Value::String(value)) => match value.as_str() { + "true" | "True" | "1" => Ok(true), + "false" | "False" | "0" => Ok(false), + _ => Err(format_error(format!("`{key}` is not a bool"))), + }, + Some(_) => Err(format_error(format!("`{key}` is not a bool"))), + } +} + +fn number_array(obj: &Map, key: &str) -> Result> { + let values = array_field(obj, key, true)?; + values + .iter() + .enumerate() + .map(|(i, value)| value_to_f64(value, &format!("{key}[{i}]"))) + .collect() +} + +fn value_to_f64(value: &Value, key: &str) -> Result { + match value { + Value::Number(number) => number + .as_f64() + .ok_or_else(|| format_error(format!("`{key}` is not a finite f64"))), + Value::String(value) => value + .parse::() + .map_err(|_| format_error(format!("`{key}` string is not a f64"))), + Value::Object(obj) if obj.contains_key("$surge_float") => Err(format_error(format!( + "`{key}` uses Surge tagged non-finite float values, which powerio does not support" + ))), + _ => Err(format_error(format!("`{key}` is not a number"))), + } +} + +fn value_to_usize(value: &Value, key: &str) -> Result { + match value { + Value::Number(number) => { + if let Some(value) = number.as_u64() { + usize::try_from(value) + .map_err(|_| format_error(format!("`{key}` integer is too large"))) + } else if let Some(value) = number.as_i64() { + if value >= 0 { + usize::try_from(value as u64) + .map_err(|_| format_error(format!("`{key}` integer is too large"))) + } else { + Err(format_error(format!("`{key}` must be nonnegative"))) + } + } else if let Some(value) = number.as_f64() { + if value >= 0.0 && value.fract() == 0.0 { + Ok(value as usize) + } else { + Err(format_error(format!("`{key}` must be an integer"))) + } + } else { + Err(format_error(format!("`{key}` is not an integer"))) + } + } + Value::String(value) => value + .parse::() + .map_err(|_| format_error(format!("`{key}` string is not an integer"))), + _ => Err(format_error(format!("`{key}` is not an integer"))), + } +} + +fn has_nonempty(obj: &Map, key: &str) -> bool { + obj.get(key).is_some_and(value_nonempty) +} + +fn value_nonempty(value: &Value) -> bool { + match value { + Value::Null => false, + Value::Bool(value) => *value, + Value::Number(number) => number.as_f64().is_some_and(|value| value != 0.0), + Value::String(value) => !value.is_empty(), + Value::Array(values) => !values.is_empty(), + Value::Object(values) => !values.is_empty(), + } +} + +fn num_not_default(obj: &Map, key: &str, default: f64) -> bool { + obj.get(key) + .and_then(|value| value_to_f64(value, key).ok()) + .is_some_and(|value| (value - default).abs() > EPS) +} + +fn bool_not_default(obj: &Map, key: &str, default: bool) -> bool { + obj.get(key) + .and_then(|value| match value { + Value::Bool(value) => Some(*value), + Value::Number(number) => number.as_f64().map(|value| value != 0.0), + _ => None, + }) + .is_some_and(|value| value != default) +} + +fn string_not_default(obj: &Map, key: &str, default: &str) -> bool { + obj.get(key) + .and_then(Value::as_str) + .is_some_and(|value| value != default) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn rejects_bad_envelope() { + let err = parse_surge_json( + r#"{"format":"surge-json","schema_version":"9","meta":{},"network":{}}"#, + ) + .unwrap_err(); + assert!(matches!(err, Error::FormatRead { .. })); + } + + #[test] + fn bus_type_mapping() { + assert_eq!(read_bus_type("PQ").unwrap(), BusType::Pq); + assert_eq!(read_bus_type("PV").unwrap(), BusType::Pv); + assert_eq!(read_bus_type("Slack").unwrap(), BusType::Ref); + assert_eq!(read_bus_type("Isolated").unwrap(), BusType::Isolated); + } + + #[test] + fn cost_mapping() { + let cost = read_cost(&serde_json::json!({ + "Polynomial": {"coeffs": [1.0, 2.0, 3.0], "startup": 4.0, "shutdown": 5.0} + })) + .unwrap(); + assert_eq!(cost.model, 2); + assert_eq!(cost.coeffs, vec![1.0, 2.0, 3.0]); + + let cost = read_cost(&serde_json::json!({ + "PiecewiseLinear": {"points": [[0.0, 0.0], [10.0, 20.0]]} + })) + .unwrap(); + assert_eq!(cost.model, 1); + assert_eq!(cost.coeffs, vec![0.0, 0.0, 10.0, 20.0]); + } + + #[test] + fn branch_tap_convention() { + let branch = read_branch(&serde_json::json!({ + "from_bus": 1, + "to_bus": 2, + "branch_type": "Line", + "tap": 1.0 + })) + .unwrap(); + assert!(branch.tap.abs() < EPS); + + let branch = read_branch(&serde_json::json!({ + "from_bus": 1, + "to_bus": 2, + "branch_type": "Transformer", + "tap": 1.0 + })) + .unwrap(); + assert!((branch.tap - 1.0).abs() < EPS); + } +} diff --git a/powerio/src/lib.rs b/powerio/src/lib.rs index 5ac61aa..46d932f 100644 --- a/powerio/src/lib.rs +++ b/powerio/src/lib.rs @@ -9,7 +9,7 @@ //! `powerio-matrix` crate. //! //! Readers and writers cover MATPOWER `.m`, PowerModels JSON, PSS/E `.raw`, -//! PowerWorld `.aux`, and EGRET JSON. Every format meets at [`Network`], and +//! PowerWorld `.aux`, EGRET JSON, and Surge JSON. Every format meets at [`Network`], and //! [`write_as`] reports whatever a target format cannot represent β€” see the //! [`crate::format`] module for the two-tier fidelity contract. //! @@ -42,9 +42,9 @@ pub mod network; pub use error::{ElementCounts, Error, Result, ScenarioMismatch}; pub use format::{ Conversion, TargetFormat, parse, parse_egret_json, parse_matpower, parse_matpower_file, - parse_powermodels_json, parse_powerworld, parse_psse, parse_str, read_path, + parse_powermodels_json, parse_powerworld, parse_psse, parse_str, parse_surge_json, read_path, target_format_from_name, write_as, write_egret_json, write_matpower, write_powermodels_json, - write_powerworld, write_psse, + write_powerworld, write_psse, write_surge_json, }; pub use indexed::{ConnectivityReport, IndexCore, IndexedNetwork}; pub use network::{ diff --git a/powerio/src/network.rs b/powerio/src/network.rs index 43b0f79..113ecdf 100644 --- a/powerio/src/network.rs +++ b/powerio/src/network.rs @@ -133,6 +133,7 @@ pub enum SourceFormat { Matpower, PowerModelsJson, EgretJson, + Surge, Psse, PowerWorld, /// Built in memory (e.g. from synth or an edited case); no source text. diff --git a/powerio/tests/convert.rs b/powerio/tests/convert.rs index 6ab6326..ce602da 100644 --- a/powerio/tests/convert.rs +++ b/powerio/tests/convert.rs @@ -6,9 +6,10 @@ use std::path::{Path, PathBuf}; use powerio::{ - BusId, SourceFormat, TargetFormat, parse_matpower, parse_matpower_file, parse_powermodels_json, - parse_powerworld, parse_psse, write_as, write_egret_json, write_powermodels_json, - write_powerworld, write_psse, + BusId, SourceFormat, TargetFormat, parse, parse_matpower, parse_matpower_file, + parse_powermodels_json, parse_powerworld, parse_psse, parse_str, parse_surge_json, + target_format_from_name, write_as, write_egret_json, write_powermodels_json, write_powerworld, + write_psse, write_surge_json, }; use serde_json::Value; @@ -150,6 +151,163 @@ fn powermodels_json_same_format_is_byte_exact_echo() { assert_eq!(write_as(&net2, TargetFormat::PowerModelsJson).text, json); } +#[test] +fn surge_fixtures_parse_sniff_and_echo() { + for f in [ + "surge/case14.surge.json", + "surge/case30.surge.json", + "surge/case57.surge.json", + "surge/market30.surge.json", + ] { + let text = std::fs::read_to_string(data(f)).unwrap(); + let net = parse_surge_json(&text).unwrap(); + assert_eq!(net.source_format, SourceFormat::Surge, "{f}"); + assert_eq!( + write_as(&net, TargetFormat::SurgeJson).text, + text, + "{f}: same-format write should echo the source" + ); + + let inferred = parse(data(f)).unwrap(); + assert_eq!( + inferred.source_format, + SourceFormat::Surge, + "{f}: JSON sniffer should detect surge-json envelope" + ); + } + + let case14 = + parse_surge_json(&std::fs::read_to_string(data("surge/case14.surge.json")).unwrap()) + .unwrap(); + assert_eq!(case14.buses.len(), 14); + assert!( + case14 + .shunts + .iter() + .any(|s| s.bus == BusId(9) && (s.b - 19.0).abs() < 1e-9), + "inline bus shunts should become first-class shunts" + ); + + let market = + parse_surge_json(&std::fs::read_to_string(data("surge/market30.surge.json")).unwrap()) + .unwrap(); + assert!( + market.storage.len() >= 2, + "storage generators should map to storage records" + ); + assert_eq!( + market.hvdc.len(), + 1, + "VSC HVDC link should map to one dcline" + ); +} + +#[test] +fn surge_aliases_parse_and_convert() { + let text = std::fs::read_to_string(data("surge/case14.surge.json")).unwrap(); + assert_eq!( + target_format_from_name("surge"), + Some(TargetFormat::SurgeJson) + ); + assert_eq!( + target_format_from_name("surge-json"), + Some(TargetFormat::SurgeJson) + ); + assert_eq!( + parse_str(&text, "surge").unwrap().source_format, + SourceFormat::Surge + ); +} + +#[test] +fn surge_radians_tap_cost_and_storage_mapping() { + let json = r#"{ + "format": "surge-json", + "schema_version": "0.1.0", + "meta": {"producer": "surge", "profile": "network"}, + "network": { + "name": "tiny", + "base_mva": 100.0, + "buses": [ + {"number": 1, "bus_type": "Slack", "voltage_magnitude_pu": 1.0, "voltage_angle_rad": 0.5235987755982988, "base_kv": 230.0, "area": 1, "zone": 1}, + {"number": 2, "bus_type": "PQ", "voltage_magnitude_pu": 1.0, "voltage_angle_rad": 0.0, "base_kv": 230.0, "area": 1, "zone": 1} + ], + "branches": [ + {"from_bus": 1, "to_bus": 2, "branch_type": "Line", "tap": 1.0, "phase_shift_rad": 0.2617993877991494, "angle_diff_min_rad": -0.5235987755982988, "angle_diff_max_rad": 0.5235987755982988, "r": 0.01, "x": 0.05, "b": 0.0} + ], + "generators": [ + {"bus": 1, "p": 10.0, "q": 1.0, "pmax": 20.0, "pmin": -5.0, "qmax": 3.0, "qmin": -2.0, "voltage_setpoint_pu": 1.0, "machine_base_mva": 100.0, "cost": {"Polynomial": {"coeffs": [3.0, 2.0, 1.0]}}, "storage": {"energy_capacity_mwh": 50.0, "soc_initial_mwh": 25.0, "efficiency": 0.81}} + ], + "loads": [], + "fixed_shunts": [] + } + }"#; + let net = parse_surge_json(json).unwrap(); + assert!((net.buses[0].va - 30.0).abs() < 1e-9); + assert!( + (net.branches[0].tap - 1.0).abs() < 1e-12, + "nonzero shift makes this a transformer-like branch" + ); + assert!((net.branches[0].shift - 15.0).abs() < 1e-9); + assert!((net.branches[0].angmin + 30.0).abs() < 1e-9); + assert!((net.branches[0].angmax - 30.0).abs() < 1e-9); + assert_eq!( + net.generators[0].cost.as_ref().unwrap().coeffs, + vec![3.0, 2.0, 1.0] + ); + assert_eq!(net.storage.len(), 1); + assert!((net.storage[0].charge_rating - 5.0).abs() < 1e-9); + assert!((net.storage[0].charge_efficiency - 0.9).abs() < 1e-9); +} + +#[test] +fn matpower_surge_matpower_preserves_core() { + let orig = parse_matpower_file(data("case30.m")).unwrap(); + let surge = write_surge_json(&orig); + let from_surge = parse_surge_json(&surge.text).unwrap(); + let back = parse_matpower(&write_as(&from_surge, TargetFormat::Matpower).text).unwrap(); + assert_eq!(back.buses.len(), orig.buses.len()); + assert_eq!(back.branches.len(), orig.branches.len()); + assert_eq!(back.generators.len(), orig.generators.len()); + assert_eq!(back.loads.len(), orig.loads.len()); + assert_eq!(back.shunts.len(), orig.shunts.len()); + assert!((back.base_mva - orig.base_mva).abs() < 1e-9); + let load_p = |net: &powerio::Network| net.loads.iter().map(|l| l.p).sum::(); + let gen_p = |net: &powerio::Network| net.generators.iter().map(|g| g.pg).sum::(); + assert!((load_p(&back) - load_p(&orig)).abs() < 1e-9); + assert!((gen_p(&back) - gen_p(&orig)).abs() < 1e-9); +} + +#[test] +fn surge_cross_format_reports_source_only_fields() { + let net = + parse_surge_json(&std::fs::read_to_string(data("surge/market30.surge.json")).unwrap()) + .unwrap(); + let to_matpower = write_as(&net, TargetFormat::Matpower); + assert!( + to_matpower + .warnings + .iter() + .any(|w| w.contains("surge network sections dropped")), + "expected source section warning, got {:?}", + to_matpower.warnings + ); + assert!( + to_matpower + .warnings + .iter() + .any(|w| w.contains("surge HVDC")), + "expected HVDC source warning, got {:?}", + to_matpower.warnings + ); + + let to_pm = write_as(&net, TargetFormat::PowerModelsJson); + assert!( + to_pm.warnings.iter().any(|w| w.contains("surge")), + "cross-format PowerModels conversion should carry surge source warnings" + ); +} + #[test] // The hub round-trip must preserve base_mva exactly, so the exact compare is the assertion. #[allow(clippy::float_cmp)] diff --git a/powerio/tests/roundtrip_formats.rs b/powerio/tests/roundtrip_formats.rs index 7b1a696..962695d 100644 --- a/powerio/tests/roundtrip_formats.rs +++ b/powerio/tests/roundtrip_formats.rs @@ -8,17 +8,16 @@ //! - **same-format byte-exact echo** β€” reading a format then writing it back //! reproduces the bytes. //! -//! All five formats (MATPOWER, PowerModels JSON, PSS/E, PowerWorld, EGRET) have a -//! reader and a writer, so each runs the full set. PowerModels' and EGRET's -//! value-for-value checks against the reference tools live in -//! `benchmarks/validate_powermodels.jl` and `benchmarks/validate_egret.py`. +//! MATPOWER, PowerModels JSON, PSS/E, PowerWorld, EGRET, and Surge have readers +//! and writers, so each runs the full set. PowerModels', EGRET's, and Surge's +//! value-for-value checks against reference tools live under `benchmarks/`. use std::path::{Path, PathBuf}; use powerio::{ Network, TargetFormat, parse_egret_json, parse_matpower_file, parse_powermodels_json, - parse_powerworld, parse_psse, write_as, write_egret_json, write_powermodels_json, - write_powerworld, write_psse, + parse_powerworld, parse_psse, parse_surge_json, write_as, write_egret_json, + write_powermodels_json, write_powerworld, write_psse, write_surge_json, }; mod common; @@ -97,6 +96,12 @@ fn roundtrippable() -> Vec { write: |n| write_egret_json(n).text, read: |s| parse_egret_json(s).unwrap(), }, + Roundtrippable { + name: "Surge JSON", + format: TargetFormat::SurgeJson, + write: |n| write_surge_json(n).text, + read: |s| parse_surge_json(s).unwrap(), + }, ] } @@ -124,9 +129,12 @@ fn reader_writer_is_idempotent() { for fmt in roundtrippable() { let t0 = (fmt.write)(&net0); let t1 = (fmt.write)(&(fmt.read)(&t0)); - if fmt.format == TargetFormat::PowerModelsJson { - // PowerModels JSON is per-unit; the Γ·base / Γ—base round-trip is not - // bit-exact in f64, so compare structure and values with a tolerance. + if matches!( + fmt.format, + TargetFormat::PowerModelsJson | TargetFormat::SurgeJson + ) { + // These JSON formats convert angles or per-unit quantities through + // f64 math, so compare structure and values with a tolerance. let v0: serde_json::Value = serde_json::from_str(&t0).unwrap(); let v1: serde_json::Value = serde_json::from_str(&t1).unwrap(); assert!( diff --git a/python/powerio/__init__.py b/python/powerio/__init__.py index 76e51e4..3465d62 100644 --- a/python/powerio/__init__.py +++ b/python/powerio/__init__.py @@ -1,7 +1,7 @@ """powerio: lossless power system case file IO, conversion, and matrices. -Parse MATPOWER, PSS/E, PowerWorld, and PowerModels JSON into one format-neutral -case; write it back byte-exact; convert between formats; and pull the sparse +Parse MATPOWER, PSS/E, PowerWorld, PowerModels JSON, EGRET JSON, and Surge JSON +into one format-neutral case; write it back byte-exact; convert between formats; and pull the sparse matrices and graph views solvers need:: import powerio @@ -270,10 +270,10 @@ def convert(path: Any, to: str, from_: Optional[str] = None) -> Conversion: """Convert a case file to another format through the neutral hub. ``to`` / ``from_`` are format names: ``matpower``, ``powermodels-json``, - ``egret-json``, ``psse``, ``powerworld`` (aliases ``m``, ``pm``, ``egret``, - ``raw``, ``aux``). The input format is inferred from the file extension - unless ``from_`` overrides it. Returns a :class:`Conversion` with the text - and any fidelity warnings. + ``egret-json``, ``surge-json``, ``psse``, ``powerworld`` (aliases ``m``, + ``pm``, ``egret``, ``surge``, ``raw``, ``aux``). The input format is + inferred from the file extension unless ``from_`` overrides it. Returns a + :class:`Conversion` with the text and any fidelity warnings. """ text, warnings = _powerio.convert(str(path), to, from_) return Conversion(text, warnings) diff --git a/python/powerio/__init__.pyi b/python/powerio/__init__.pyi index b9d2304..20c2d0c 100644 --- a/python/powerio/__init__.pyi +++ b/python/powerio/__init__.pyi @@ -120,7 +120,7 @@ class Conversion(NamedTuple): warnings: List[str] # Any reader/writer name or alias the Rust hub accepts (e.g. "matpower"/"m", -# "psse"/"raw"). Kept as `str` so aliases type-check; the binding validates it. +# "surge-json"/"surge"). Kept as `str` so aliases type-check; the binding validates it. Format = str def parse(path: Any) -> Case: ... diff --git a/python/tests/test_powerio.py b/python/tests/test_powerio.py index 88b21f8..03e7e95 100644 --- a/python/tests/test_powerio.py +++ b/python/tests/test_powerio.py @@ -393,13 +393,29 @@ def test_convert_matpower_echo_is_byte_exact(): def test_convert_matpower_to_each_format(): - for fmt in ["powermodels-json", "egret-json", "psse", "powerworld"]: + for fmt in ["powermodels-json", "egret-json", "surge-json", "psse", "powerworld"]: r = powerio.convert(str(DATA / "case30.m"), fmt) assert isinstance(r.text, str) and len(r.text) > 0 assert isinstance(r.warnings, list) # PowerModels JSON output parses as JSON and keeps the bus count. pm = json.loads(powerio.convert(str(DATA / "case30.m"), "powermodels-json").text) assert len(pm["bus"]) == 30 + surge = json.loads(powerio.convert(str(DATA / "case30.m"), "surge").text) + assert surge["format"] == "surge-json" + assert len(surge["network"]["buses"]) == 30 + + +def test_parse_and_convert_surge_json(tmp_path): + path = DATA / "surge" / "case14.surge.json" + case = powerio.parse(path) + assert case.source_format == "Surge" + assert case.n == 14 + + raw = powerio.convert(path, "matpower", from_="surge") + out = tmp_path / "case14.m" + out.write_text(raw.text) + back = powerio.parse_matpower(out) + assert back.n == 14 def test_convert_round_trip_through_psse(tmp_path): diff --git a/tests/data/surge/case14.surge.json b/tests/data/surge/case14.surge.json new file mode 100644 index 0000000..471d74b --- /dev/null +++ b/tests/data/surge/case14.surge.json @@ -0,0 +1 @@ +{"format":"surge-json","meta":{"producer":"surge","profile":"network"},"network":{"base_mva":100.0,"branches":[{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0528,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":1,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.01938,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":1.0,"to_bus":2,"x":0.05917},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0492,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":1,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.05403,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":1.0,"to_bus":5,"x":0.22304},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0438,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":2,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.04699,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":1.0,"to_bus":3,"x":0.19797},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.034,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":2,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.05811,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":1.0,"to_bus":4,"x":0.17632},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0346,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":2,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.05695,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":1.0,"to_bus":5,"x":0.17388},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0128,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":3,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.06701,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":1.0,"to_bus":4,"x":0.17103},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":4,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.01335,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":1.0,"to_bus":5,"x":0.04211},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Transformer","circuit":"1","from_bus":4,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":0.978,"to_bus":7,"x":0.20912},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Transformer","circuit":"1","from_bus":4,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":0.969,"to_bus":9,"x":0.55618},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Transformer","circuit":"1","from_bus":5,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":0.932,"to_bus":6,"x":0.25202},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":6,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.09498,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":1.0,"to_bus":11,"x":0.1989},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":6,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.12291,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":1.0,"to_bus":12,"x":0.25581},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":6,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.06615,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":1.0,"to_bus":13,"x":0.13027},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":7,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":1.0,"to_bus":8,"x":0.17615},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":7,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":1.0,"to_bus":9,"x":0.11001},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":9,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.03181,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":1.0,"to_bus":10,"x":0.0845},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":9,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.12711,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":1.0,"to_bus":14,"x":0.27038},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":10,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.08205,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":1.0,"to_bus":11,"x":0.19207},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":12,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.22092,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":1.0,"to_bus":13,"x":0.19988},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":13,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.17093,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"tap":1.0,"to_bus":14,"x":0.34802}],"buses":[{"area":1,"base_kv":132.0,"bus_type":"Slack","island_id":0,"name":"","number":1,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.06,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"area":1,"base_kv":132.0,"bus_type":"PV","island_id":0,"name":"","number":2,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.08691739674931762,"voltage_magnitude_pu":1.045,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"area":1,"base_kv":132.0,"bus_type":"PV","island_id":0,"name":"","number":3,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.22200588085367873,"voltage_magnitude_pu":1.01,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"area":1,"base_kv":132.0,"bus_type":"PQ","island_id":0,"name":"","number":4,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.18029251173101424,"voltage_magnitude_pu":1.019,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"area":1,"base_kv":132.0,"bus_type":"PQ","island_id":0,"name":"","number":5,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.15323990832510212,"voltage_magnitude_pu":1.02,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"area":1,"base_kv":33.0,"bus_type":"PV","island_id":0,"name":"","number":6,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.24818581963359368,"voltage_magnitude_pu":1.07,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"area":1,"base_kv":33.0,"bus_type":"PQ","island_id":0,"name":"","number":7,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.23335052099164186,"voltage_magnitude_pu":1.062,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"area":1,"base_kv":132.0,"bus_type":"PV","island_id":0,"name":"","number":8,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.2331759880664424,"voltage_magnitude_pu":1.09,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"area":1,"base_kv":33.0,"bus_type":"PQ","island_id":0,"name":"","number":9,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":19.0,"voltage_angle_rad":-0.2607521902479528,"voltage_magnitude_pu":1.056,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"area":1,"base_kv":33.0,"bus_type":"PQ","island_id":0,"name":"","number":10,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.26354471705114374,"voltage_magnitude_pu":1.051,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"area":1,"base_kv":33.0,"bus_type":"PQ","island_id":0,"name":"","number":11,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.2581341963699613,"voltage_magnitude_pu":1.057,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"area":1,"base_kv":33.0,"bus_type":"PQ","island_id":0,"name":"","number":12,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.2630211182755455,"voltage_magnitude_pu":1.055,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"area":1,"base_kv":33.0,"bus_type":"PQ","island_id":0,"name":"","number":13,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.2645919146023404,"voltage_magnitude_pu":1.05,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"area":1,"base_kv":33.0,"bus_type":"PQ","island_id":0,"name":"","number":14,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.2799508120198905,"voltage_magnitude_pu":1.036,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1}],"cim":{},"controls":{},"freq_hz":60.0,"generators":[{"bus":1,"cost":{"Polynomial":{"coeffs":[0.0430292599,20.0,0.0],"shutdown":0.0,"startup":0.0}},"gen_type":"Synchronous","id":"","in_service":true,"machine_base_mva":100.0,"p":232.4,"pfr_eligible":true,"pmax":332.4,"pmin":0.0,"q":-16.9,"qmax":10.0,"qmin":0.0,"quick_start":false,"voltage_regulated":true,"voltage_setpoint_pu":1.06},{"bus":2,"cost":{"Polynomial":{"coeffs":[0.25,20.0,0.0],"shutdown":0.0,"startup":0.0}},"gen_type":"Synchronous","id":"","in_service":true,"machine_base_mva":100.0,"p":40.0,"pfr_eligible":true,"pmax":140.0,"pmin":0.0,"q":42.4,"qmax":50.0,"qmin":-40.0,"quick_start":false,"voltage_regulated":true,"voltage_setpoint_pu":1.045},{"bus":3,"cost":{"Polynomial":{"coeffs":[0.01,40.0,0.0],"shutdown":0.0,"startup":0.0}},"gen_type":"Synchronous","id":"","in_service":true,"machine_base_mva":100.0,"p":0.0,"pfr_eligible":true,"pmax":100.0,"pmin":0.0,"q":23.4,"qmax":40.0,"qmin":0.0,"quick_start":false,"voltage_regulated":true,"voltage_setpoint_pu":1.01},{"bus":6,"cost":{"Polynomial":{"coeffs":[0.01,40.0,0.0],"shutdown":0.0,"startup":0.0}},"gen_type":"Synchronous","id":"","in_service":true,"machine_base_mva":100.0,"p":0.0,"pfr_eligible":true,"pmax":100.0,"pmin":0.0,"q":12.2,"qmax":24.0,"qmin":-6.0,"quick_start":false,"voltage_regulated":true,"voltage_setpoint_pu":1.07},{"bus":8,"cost":{"Polynomial":{"coeffs":[0.01,40.0,0.0],"shutdown":0.0,"startup":0.0}},"gen_type":"Synchronous","id":"","in_service":true,"machine_base_mva":100.0,"p":0.0,"pfr_eligible":true,"pmax":100.0,"pmin":0.0,"q":17.4,"qmax":24.0,"qmin":-6.0,"quick_start":false,"voltage_regulated":true,"voltage_setpoint_pu":1.09}],"loads":[{"active_power_demand_mw":21.7,"bus":2,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":12.7,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":94.2,"bus":3,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":19.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":47.8,"bus":4,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":-3.9,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":7.6,"bus":5,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.6,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":11.2,"bus":6,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":7.5,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":29.5,"bus":9,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":16.6,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":9.0,"bus":10,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":5.8,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":3.5,"bus":11,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.8,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":6.1,"bus":12,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.6,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":13.5,"bus":13,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":5.8,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":14.9,"bus":14,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":5.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0}],"market_data":{},"metadata":{},"name":"case14"},"schema_version":"0.1.0"} \ No newline at end of file diff --git a/tests/data/surge/case30.surge.json b/tests/data/surge/case30.surge.json new file mode 100644 index 0000000..bd25765 --- /dev/null +++ b/tests/data/surge/case30.surge.json @@ -0,0 +1 @@ +{"format":"surge-json","meta":{"producer":"surge","profile":"network"},"network":{"base_mva":100.0,"branches":[{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.03,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":1,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.02,"rating_a_mva":130.0,"rating_b_mva":130.0,"rating_c_mva":130.0,"tap":1.0,"to_bus":2,"x":0.06},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.02,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":1,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.05,"rating_a_mva":130.0,"rating_b_mva":130.0,"rating_c_mva":130.0,"tap":1.0,"to_bus":3,"x":0.19},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.02,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":2,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.06,"rating_a_mva":65.0,"rating_b_mva":65.0,"rating_c_mva":65.0,"tap":1.0,"to_bus":4,"x":0.17},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":3,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.01,"rating_a_mva":130.0,"rating_b_mva":130.0,"rating_c_mva":130.0,"tap":1.0,"to_bus":4,"x":0.04},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.02,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":2,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.05,"rating_a_mva":130.0,"rating_b_mva":130.0,"rating_c_mva":130.0,"tap":1.0,"to_bus":5,"x":0.2},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.02,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":2,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.06,"rating_a_mva":65.0,"rating_b_mva":65.0,"rating_c_mva":65.0,"tap":1.0,"to_bus":6,"x":0.18},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":4,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.01,"rating_a_mva":90.0,"rating_b_mva":90.0,"rating_c_mva":90.0,"tap":1.0,"to_bus":6,"x":0.04},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.01,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":5,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.05,"rating_a_mva":70.0,"rating_b_mva":70.0,"rating_c_mva":70.0,"tap":1.0,"to_bus":7,"x":0.12},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.01,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":6,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.03,"rating_a_mva":130.0,"rating_b_mva":130.0,"rating_c_mva":130.0,"tap":1.0,"to_bus":7,"x":0.08},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":6,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.01,"rating_a_mva":32.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"tap":1.0,"to_bus":8,"x":0.04},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":6,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.0,"rating_a_mva":65.0,"rating_b_mva":65.0,"rating_c_mva":65.0,"tap":1.0,"to_bus":9,"x":0.21},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":6,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.0,"rating_a_mva":32.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"tap":1.0,"to_bus":10,"x":0.56},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":9,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.0,"rating_a_mva":65.0,"rating_b_mva":65.0,"rating_c_mva":65.0,"tap":1.0,"to_bus":11,"x":0.21},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":9,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.0,"rating_a_mva":65.0,"rating_b_mva":65.0,"rating_c_mva":65.0,"tap":1.0,"to_bus":10,"x":0.11},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":4,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.0,"rating_a_mva":65.0,"rating_b_mva":65.0,"rating_c_mva":65.0,"tap":1.0,"to_bus":12,"x":0.26},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":12,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.0,"rating_a_mva":65.0,"rating_b_mva":65.0,"rating_c_mva":65.0,"tap":1.0,"to_bus":13,"x":0.14},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":12,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.12,"rating_a_mva":32.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"tap":1.0,"to_bus":14,"x":0.26},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":12,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.07,"rating_a_mva":32.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"tap":1.0,"to_bus":15,"x":0.13},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":12,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.09,"rating_a_mva":32.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"tap":1.0,"to_bus":16,"x":0.2},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":14,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.22,"rating_a_mva":16.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"tap":1.0,"to_bus":15,"x":0.2},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":16,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.08,"rating_a_mva":16.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"tap":1.0,"to_bus":17,"x":0.19},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":15,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.11,"rating_a_mva":16.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"tap":1.0,"to_bus":18,"x":0.22},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":18,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.06,"rating_a_mva":16.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"tap":1.0,"to_bus":19,"x":0.13},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":19,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.03,"rating_a_mva":32.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"tap":1.0,"to_bus":20,"x":0.07},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":10,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.09,"rating_a_mva":32.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"tap":1.0,"to_bus":20,"x":0.21},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":10,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.03,"rating_a_mva":32.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"tap":1.0,"to_bus":17,"x":0.08},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":10,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.03,"rating_a_mva":32.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"tap":1.0,"to_bus":21,"x":0.07},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":10,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.07,"rating_a_mva":32.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"tap":1.0,"to_bus":22,"x":0.15},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":21,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.01,"rating_a_mva":32.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"tap":1.0,"to_bus":22,"x":0.02},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":15,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.1,"rating_a_mva":16.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"tap":1.0,"to_bus":23,"x":0.2},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":22,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.12,"rating_a_mva":16.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"tap":1.0,"to_bus":24,"x":0.18},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":23,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.13,"rating_a_mva":16.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"tap":1.0,"to_bus":24,"x":0.27},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":24,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.19,"rating_a_mva":16.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"tap":1.0,"to_bus":25,"x":0.33},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":25,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.25,"rating_a_mva":16.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"tap":1.0,"to_bus":26,"x":0.38},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":25,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.11,"rating_a_mva":16.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"tap":1.0,"to_bus":27,"x":0.21},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":28,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.0,"rating_a_mva":65.0,"rating_b_mva":65.0,"rating_c_mva":65.0,"tap":1.0,"to_bus":27,"x":0.4},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":27,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.22,"rating_a_mva":16.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"tap":1.0,"to_bus":29,"x":0.42},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":27,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.32,"rating_a_mva":16.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"tap":1.0,"to_bus":30,"x":0.6},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":29,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.24,"rating_a_mva":16.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"tap":1.0,"to_bus":30,"x":0.45},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.02,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":8,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.06,"rating_a_mva":32.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"tap":1.0,"to_bus":28,"x":0.2},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.01,"b_mag":0.0,"branch_type":"Line","circuit":"1","from_bus":6,"g_mag":0.0,"g_pi":0.0,"in_service":true,"phase_shift_rad":0.0,"r":0.02,"rating_a_mva":32.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"tap":1.0,"to_bus":28,"x":0.06}],"buses":[{"area":1,"base_kv":135.0,"bus_type":"Slack","island_id":0,"name":"","number":1,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":1,"base_kv":135.0,"bus_type":"PV","island_id":0,"name":"","number":2,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.1,"voltage_min_pu":0.95,"zone":1},{"area":1,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":3,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":1,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":4,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":1,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":5,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.19,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":1,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":6,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":1,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":7,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":1,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":8,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":1,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":9,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":3,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":10,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":1,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":11,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":2,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":12,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":2,"base_kv":135.0,"bus_type":"PV","island_id":0,"name":"","number":13,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.1,"voltage_min_pu":0.95,"zone":1},{"area":2,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":14,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":2,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":15,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":2,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":16,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":2,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":17,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":2,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":18,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":2,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":19,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":2,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":20,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":3,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":21,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":3,"base_kv":135.0,"bus_type":"PV","island_id":0,"name":"","number":22,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.1,"voltage_min_pu":0.95,"zone":1},{"area":2,"base_kv":135.0,"bus_type":"PV","island_id":0,"name":"","number":23,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.1,"voltage_min_pu":0.95,"zone":1},{"area":3,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":24,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.04,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":3,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":25,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":3,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":26,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":3,"base_kv":135.0,"bus_type":"PV","island_id":0,"name":"","number":27,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.1,"voltage_min_pu":0.95,"zone":1},{"area":1,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":28,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":3,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":29,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"area":3,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":30,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1}],"cim":{},"controls":{},"freq_hz":60.0,"generators":[{"bus":1,"cost":{"Polynomial":{"coeffs":[0.02,2.0,0.0],"shutdown":0.0,"startup":0.0}},"gen_type":"Synchronous","id":"","in_service":true,"machine_base_mva":100.0,"p":23.54,"pfr_eligible":true,"pmax":80.0,"pmin":0.0,"q":0.0,"qmax":150.0,"qmin":-20.0,"quick_start":false,"voltage_regulated":true,"voltage_setpoint_pu":1.0},{"bus":2,"cost":{"Polynomial":{"coeffs":[0.0175,1.75,0.0],"shutdown":0.0,"startup":0.0}},"gen_type":"Synchronous","id":"","in_service":true,"machine_base_mva":100.0,"p":60.97,"pfr_eligible":true,"pmax":80.0,"pmin":0.0,"q":0.0,"qmax":60.0,"qmin":-20.0,"quick_start":false,"voltage_regulated":true,"voltage_setpoint_pu":1.0},{"bus":22,"cost":{"Polynomial":{"coeffs":[0.0625,1.0,0.0],"shutdown":0.0,"startup":0.0}},"gen_type":"Synchronous","id":"","in_service":true,"machine_base_mva":100.0,"p":21.59,"pfr_eligible":true,"pmax":50.0,"pmin":0.0,"q":0.0,"qmax":62.5,"qmin":-15.0,"quick_start":false,"voltage_regulated":true,"voltage_setpoint_pu":1.0},{"bus":27,"cost":{"Polynomial":{"coeffs":[0.00834,3.25,0.0],"shutdown":0.0,"startup":0.0}},"gen_type":"Synchronous","id":"","in_service":true,"machine_base_mva":100.0,"p":26.91,"pfr_eligible":true,"pmax":55.0,"pmin":0.0,"q":0.0,"qmax":48.7,"qmin":-15.0,"quick_start":false,"voltage_regulated":true,"voltage_setpoint_pu":1.0},{"bus":23,"cost":{"Polynomial":{"coeffs":[0.025,3.0,0.0],"shutdown":0.0,"startup":0.0}},"gen_type":"Synchronous","id":"","in_service":true,"machine_base_mva":100.0,"p":19.2,"pfr_eligible":true,"pmax":30.0,"pmin":0.0,"q":0.0,"qmax":40.0,"qmin":-10.0,"quick_start":false,"voltage_regulated":true,"voltage_setpoint_pu":1.0},{"bus":13,"cost":{"Polynomial":{"coeffs":[0.025,3.0,0.0],"shutdown":0.0,"startup":0.0}},"gen_type":"Synchronous","id":"","in_service":true,"machine_base_mva":100.0,"p":37.0,"pfr_eligible":true,"pmax":40.0,"pmin":0.0,"q":0.0,"qmax":44.7,"qmin":-15.0,"quick_start":false,"voltage_regulated":true,"voltage_setpoint_pu":1.0}],"loads":[{"active_power_demand_mw":21.7,"bus":2,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":12.7,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":2.4,"bus":3,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.2,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":7.6,"bus":4,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.6,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":22.8,"bus":7,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":10.9,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":30.0,"bus":8,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":30.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":5.8,"bus":10,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":2.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":11.2,"bus":12,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":7.5,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":6.2,"bus":14,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.6,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":8.2,"bus":15,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":2.5,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":3.5,"bus":16,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.8,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":9.0,"bus":17,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":5.8,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":3.2,"bus":18,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":0.9,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":9.5,"bus":19,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":3.4,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":2.2,"bus":20,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":0.7,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":17.5,"bus":21,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":11.2,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":3.2,"bus":23,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.6,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":8.7,"bus":24,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":6.7,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":3.5,"bus":26,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":2.3,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":2.4,"bus":29,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":0.9,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":10.6,"bus":30,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.9,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0}],"market_data":{},"metadata":{},"name":"case30"},"schema_version":"0.1.0"} \ No newline at end of file diff --git a/tests/data/surge/case57.surge.json b/tests/data/surge/case57.surge.json new file mode 100644 index 0000000..71c3245 --- /dev/null +++ b/tests/data/surge/case57.surge.json @@ -0,0 +1 @@ +{"format":"surge-json","meta":{"producer":"surge","profile":"network"},"network":{"base_mva":100.0,"branches":[{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.129,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":1,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0083,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":2,"transformer_connection":"WyeGWyeG","x":0.028,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0818,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":2,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0298,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":3,"transformer_connection":"WyeGWyeG","x":0.085,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.038,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":3,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0112,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":4,"transformer_connection":"WyeGWyeG","x":0.0366,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0258,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":4,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0625,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":5,"transformer_connection":"WyeGWyeG","x":0.132,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0348,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":4,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.043,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":6,"transformer_connection":"WyeGWyeG","x":0.148,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0276,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":6,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.02,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":7,"transformer_connection":"WyeGWyeG","x":0.102,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.047,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":6,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0339,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":8,"transformer_connection":"WyeGWyeG","x":0.173,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0548,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":8,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0099,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":9,"transformer_connection":"WyeGWyeG","x":0.0505,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.044,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":9,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0369,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":10,"transformer_connection":"WyeGWyeG","x":0.1679,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0218,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":9,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0258,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":11,"transformer_connection":"WyeGWyeG","x":0.0848,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0772,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":9,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0648,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":12,"transformer_connection":"WyeGWyeG","x":0.295,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0406,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":9,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0481,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":13,"transformer_connection":"WyeGWyeG","x":0.158,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.011,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":13,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0132,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":14,"transformer_connection":"WyeGWyeG","x":0.0434,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.023,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":13,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0269,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":15,"transformer_connection":"WyeGWyeG","x":0.0869,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0988,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":1,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0178,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":15,"transformer_connection":"WyeGWyeG","x":0.091,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0546,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":1,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0454,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":16,"transformer_connection":"WyeGWyeG","x":0.206,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0286,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":1,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0238,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":17,"transformer_connection":"WyeGWyeG","x":0.108,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0544,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":3,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0162,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":15,"transformer_connection":"WyeGWyeG","x":0.053,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Transformer","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":4,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":0.97,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":18,"transformer_connection":"WyeGWyeG","x":0.555,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Transformer","bypassed":false,"circuit":"2","delta_connected":false,"from_bus":4,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":0.978,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":18,"transformer_connection":"WyeGWyeG","x":0.43,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0124,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":5,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0302,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":6,"transformer_connection":"WyeGWyeG","x":0.0641,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0194,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":7,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0139,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":8,"transformer_connection":"WyeGWyeG","x":0.0712,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0328,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":10,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0277,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":12,"transformer_connection":"WyeGWyeG","x":0.1262,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0188,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":11,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0223,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":13,"transformer_connection":"WyeGWyeG","x":0.0732,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0604,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":12,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0178,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":13,"transformer_connection":"WyeGWyeG","x":0.058,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0216,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":12,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.018,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":16,"transformer_connection":"WyeGWyeG","x":0.0813,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0476,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":12,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0397,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":17,"transformer_connection":"WyeGWyeG","x":0.179,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0148,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":14,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0171,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":15,"transformer_connection":"WyeGWyeG","x":0.0547,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":18,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.461,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":19,"transformer_connection":"WyeGWyeG","x":0.685,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":19,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.283,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":20,"transformer_connection":"WyeGWyeG","x":0.434,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Transformer","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":21,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.043,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":20,"transformer_connection":"WyeGWyeG","x":0.7767,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":21,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0736,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":22,"transformer_connection":"WyeGWyeG","x":0.117,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":22,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0099,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":23,"transformer_connection":"WyeGWyeG","x":0.0152,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0084,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":23,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.166,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":24,"transformer_connection":"WyeGWyeG","x":0.256,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":24,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":25,"transformer_connection":"WyeGWyeG","x":1.182,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"2","delta_connected":false,"from_bus":24,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":25,"transformer_connection":"WyeGWyeG","x":1.23,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Transformer","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":24,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.043,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":26,"transformer_connection":"WyeGWyeG","x":0.0473,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":26,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.165,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":27,"transformer_connection":"WyeGWyeG","x":0.254,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":27,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0618,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":28,"transformer_connection":"WyeGWyeG","x":0.0954,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":28,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0418,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":29,"transformer_connection":"WyeGWyeG","x":0.0587,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Transformer","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":7,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":0.967,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":29,"transformer_connection":"WyeGWyeG","x":0.0648,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":25,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.135,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":30,"transformer_connection":"WyeGWyeG","x":0.202,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":30,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.326,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":31,"transformer_connection":"WyeGWyeG","x":0.497,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":31,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.507,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":32,"transformer_connection":"WyeGWyeG","x":0.755,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":32,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0392,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":33,"transformer_connection":"WyeGWyeG","x":0.036,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Transformer","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":34,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":0.975,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":32,"transformer_connection":"WyeGWyeG","x":0.953,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0032,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":34,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.052,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":35,"transformer_connection":"WyeGWyeG","x":0.078,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0016,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":35,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.043,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":36,"transformer_connection":"WyeGWyeG","x":0.0537,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":36,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.029,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":37,"transformer_connection":"WyeGWyeG","x":0.0366,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.002,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":37,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0651,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":38,"transformer_connection":"WyeGWyeG","x":0.1009,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":37,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0239,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":39,"transformer_connection":"WyeGWyeG","x":0.0379,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":36,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.03,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":40,"transformer_connection":"WyeGWyeG","x":0.0466,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":22,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0192,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":38,"transformer_connection":"WyeGWyeG","x":0.0295,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Transformer","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":11,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":0.955,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":41,"transformer_connection":"WyeGWyeG","x":0.749,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":41,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.207,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":42,"transformer_connection":"WyeGWyeG","x":0.352,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":41,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":43,"transformer_connection":"WyeGWyeG","x":0.412,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.002,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":38,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0289,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":44,"transformer_connection":"WyeGWyeG","x":0.0585,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Transformer","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":15,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":0.955,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":45,"transformer_connection":"WyeGWyeG","x":0.1042,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Transformer","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":14,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":0.9,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":46,"transformer_connection":"WyeGWyeG","x":0.0735,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0032,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":46,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.023,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":47,"transformer_connection":"WyeGWyeG","x":0.068,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":47,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0182,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":48,"transformer_connection":"WyeGWyeG","x":0.0233,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0048,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":48,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0834,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":49,"transformer_connection":"WyeGWyeG","x":0.129,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":49,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0801,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":50,"transformer_connection":"WyeGWyeG","x":0.128,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":50,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.1386,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":51,"transformer_connection":"WyeGWyeG","x":0.22,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Transformer","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":10,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":0.93,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":51,"transformer_connection":"WyeGWyeG","x":0.0712,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Transformer","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":13,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":0.895,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":49,"transformer_connection":"WyeGWyeG","x":0.191,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":29,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.1442,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":52,"transformer_connection":"WyeGWyeG","x":0.187,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":52,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0762,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":53,"transformer_connection":"WyeGWyeG","x":0.0984,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":53,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.1878,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":54,"transformer_connection":"WyeGWyeG","x":0.232,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":54,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.1732,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":55,"transformer_connection":"WyeGWyeG","x":0.2265,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Transformer","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":11,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":0.958,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":43,"transformer_connection":"WyeGWyeG","x":0.153,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.004,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":44,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0624,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":45,"transformer_connection":"WyeGWyeG","x":0.1242,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Transformer","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":40,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":0.958,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":56,"transformer_connection":"WyeGWyeG","x":1.195,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":56,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.553,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":41,"transformer_connection":"WyeGWyeG","x":0.549,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":56,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.2125,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":42,"transformer_connection":"WyeGWyeG","x":0.354,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Transformer","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":39,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":0.98,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":57,"transformer_connection":"WyeGWyeG","x":1.355,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":57,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.174,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":56,"transformer_connection":"WyeGWyeG","x":0.26,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.003,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":38,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.115,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":49,"transformer_connection":"WyeGWyeG","x":0.177,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":38,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0312,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":48,"transformer_connection":"WyeGWyeG","x":0.0482,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Transformer","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":9,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":0.0,"rating_b_mva":0.0,"rating_c_mva":0.0,"skin_effect_alpha":0.0,"tap":0.94,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":55,"transformer_connection":"WyeGWyeG","x":0.1205,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0}],"buses":[{"active_power_demand_mw":55.0,"area":1,"base_kv":0.0,"bus_type":"Slack","island_id":0,"name":"Kanawha V1","number":1,"reactive_power_demand_mvar":17.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.04,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":3.0,"area":1,"base_kv":0.0,"bus_type":"PV","island_id":0,"name":"Turner V1","number":2,"reactive_power_demand_mvar":88.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.020594885173533087,"voltage_magnitude_pu":1.01,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":41.0,"area":1,"base_kv":0.0,"bus_type":"PV","island_id":0,"name":"Logan V1","number":3,"reactive_power_demand_mvar":21.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.10419615634406147,"voltage_magnitude_pu":0.985,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Sprigg V1","number":4,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.12775810124598494,"voltage_magnitude_pu":0.981,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":13.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 5 V1","number":5,"reactive_power_demand_mvar":4.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.14870205226991687,"voltage_magnitude_pu":0.976,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":75.0,"area":1,"base_kv":0.0,"bus_type":"PV","island_id":0,"name":"Beaver Ck V1","number":6,"reactive_power_demand_mvar":2.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.15097098029750952,"voltage_magnitude_pu":0.98,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 7 V1","number":7,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.1322959573011702,"voltage_magnitude_pu":0.984,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":150.0,"area":1,"base_kv":0.0,"bus_type":"PV","island_id":0,"name":"Clinch Rv V1","number":8,"reactive_power_demand_mvar":22.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.07766715171374766,"voltage_magnitude_pu":1.005,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":121.0,"area":1,"base_kv":0.0,"bus_type":"PV","island_id":0,"name":"Saltville V1","number":9,"reactive_power_demand_mvar":26.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.1668534764906579,"voltage_magnitude_pu":0.98,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":5.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 10 V1","number":10,"reactive_power_demand_mvar":2.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.19949113350295186,"voltage_magnitude_pu":0.986,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Tazewell V1","number":11,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.17749998492782332,"voltage_magnitude_pu":0.974,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":377.0,"area":1,"base_kv":0.0,"bus_type":"PV","island_id":0,"name":"Glen Lyn V1","number":12,"reactive_power_demand_mvar":24.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.1825614397586069,"voltage_magnitude_pu":1.015,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":18.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 13 V1","number":13,"reactive_power_demand_mvar":2.3,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.17086773377024483,"voltage_magnitude_pu":0.979,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":10.5,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 14 V1","number":14,"reactive_power_demand_mvar":5.3,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.16283921921107095,"voltage_magnitude_pu":0.97,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":22.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 15 V1","number":15,"reactive_power_demand_mvar":5.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.12531464029319286,"voltage_magnitude_pu":0.988,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":43.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 16 V1","number":16,"reactive_power_demand_mvar":3.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.15446163880149816,"voltage_magnitude_pu":1.013,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":42.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 17 V1","number":17,"reactive_power_demand_mvar":8.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.09407324668249435,"voltage_magnitude_pu":1.017,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":27.2,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Sprigg V2","number":18,"reactive_power_demand_mvar":9.8,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":10.0,"voltage_angle_rad":-0.204378055408536,"voltage_magnitude_pu":1.001,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":3.3,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 19 V2","number":19,"reactive_power_demand_mvar":0.6,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.2303834612632515,"voltage_magnitude_pu":0.97,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":2.3,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 20 V2","number":20,"reactive_power_demand_mvar":1.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.2340486526924396,"voltage_magnitude_pu":0.964,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 21 V3","number":21,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.2249729405820691,"voltage_magnitude_pu":1.008,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 22 V3","number":22,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.2241002759560719,"voltage_magnitude_pu":1.01,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":6.3,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 23 V3","number":23,"reactive_power_demand_mvar":2.1,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.22532200643246794,"voltage_magnitude_pu":1.008,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 24 V3","number":24,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.23125612588924865,"voltage_magnitude_pu":0.999,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":6.3,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 25 V4","number":25,"reactive_power_demand_mvar":3.2,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":5.9,"voltage_angle_rad":-0.3164281933865719,"voltage_magnitude_pu":0.982,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 26 V5","number":26,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.22602013813326566,"voltage_magnitude_pu":0.959,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":9.3,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 27 V5","number":27,"reactive_power_demand_mvar":0.5,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.20036379812894903,"voltage_magnitude_pu":0.982,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":4.6,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 28 V5","number":28,"reactive_power_demand_mvar":2.3,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.18238690683340741,"voltage_magnitude_pu":0.997,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":17.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 29 V5","number":29,"reactive_power_demand_mvar":2.6,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.17016960206944712,"voltage_magnitude_pu":1.01,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":3.6,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 30 V4","number":30,"reactive_power_demand_mvar":1.8,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.32602750427254074,"voltage_magnitude_pu":0.962,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":5.8,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 31 V4","number":31,"reactive_power_demand_mvar":2.9,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.3375466773357033,"voltage_magnitude_pu":0.936,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":1.6,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 32 V4","number":32,"reactive_power_demand_mvar":0.8,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.3221877799181532,"voltage_magnitude_pu":0.949,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":3.8,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 33 V4","number":33,"reactive_power_demand_mvar":1.9,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.32288591161895097,"voltage_magnitude_pu":0.947,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 34 V3","number":34,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.24609142453120045,"voltage_magnitude_pu":0.959,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":6.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 35 V3","number":35,"reactive_power_demand_mvar":3.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.24190263432641407,"voltage_magnitude_pu":0.966,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 36 V3","number":36,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.2371902453460294,"voltage_magnitude_pu":0.976,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 37 V3","number":37,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.2340486526924396,"voltage_magnitude_pu":0.985,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":14.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 38 V3","number":38,"reactive_power_demand_mvar":7.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.2218313479284793,"voltage_magnitude_pu":1.013,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 39 V3","number":39,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.23492131731843677,"voltage_magnitude_pu":0.983,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 40 V3","number":40,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.23771384412162766,"voltage_magnitude_pu":0.973,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":6.3,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Tazewell V6","number":41,"reactive_power_demand_mvar":3.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.2452187599052033,"voltage_magnitude_pu":0.996,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":7.1,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 42 V6","number":42,"reactive_power_demand_mvar":4.4,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.27052603405912107,"voltage_magnitude_pu":0.966,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":2.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Tazewell V7","number":43,"reactive_power_demand_mvar":1.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.19774580425095753,"voltage_magnitude_pu":1.01,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":12.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 44 V3","number":44,"reactive_power_demand_mvar":1.8,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.20699604928652748,"voltage_magnitude_pu":1.017,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 45 V3","number":45,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.16144295580947549,"voltage_magnitude_pu":1.036,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 46 V3","number":46,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.2075196480621258,"voltage_magnitude_pu":1.05,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":29.7,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 47 V3","number":47,"reactive_power_demand_mvar":11.6,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.21799162357409177,"voltage_magnitude_pu":1.033,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 48 V3","number":48,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.21973695282608607,"voltage_magnitude_pu":1.027,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":18.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 49 V3","number":49,"reactive_power_demand_mvar":8.5,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.22549653935766736,"voltage_magnitude_pu":1.036,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":21.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 50 V3","number":50,"reactive_power_demand_mvar":10.5,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.23369958684204073,"voltage_magnitude_pu":1.023,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":18.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 51 V3","number":51,"reactive_power_demand_mvar":5.3,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.21851522234969006,"voltage_magnitude_pu":1.052,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":4.9,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 52 V5","number":52,"reactive_power_demand_mvar":2.2,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.2001892652037496,"voltage_magnitude_pu":0.98,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":20.0,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 53 V5","number":53,"reactive_power_demand_mvar":10.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":6.3,"voltage_angle_rad":-0.21345376751890652,"voltage_magnitude_pu":0.971,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":4.1,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 54 V5","number":54,"reactive_power_demand_mvar":1.4,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.2040289895581371,"voltage_magnitude_pu":0.996,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":6.8,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Saltville V5","number":55,"reactive_power_demand_mvar":3.4,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.1881464933649887,"voltage_magnitude_pu":1.031,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":7.6,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 56 V6","number":56,"reactive_power_demand_mvar":2.2,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.27995081201989047,"voltage_magnitude_pu":0.968,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1},{"active_power_demand_mw":6.7,"area":1,"base_kv":0.0,"bus_type":"PQ","island_id":0,"name":"Bus 57 V6","number":57,"reactive_power_demand_mvar":2.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":-0.289026524130261,"voltage_magnitude_pu":0.965,"voltage_max_pu":1.06,"voltage_min_pu":0.94,"zone":1}],"freq_hz":60.0,"generators":[{"apf":0.0,"bus":1,"commitment_status":"Market","cost":{"Polynomial":{"coeffs":[0.077579519,20.0,0.0],"shutdown":0.0,"startup":0.0}},"curtailable":false,"emission_rates":{"co2":0.0,"nox":0.0,"pm25":0.0,"so2":0.0},"gen_type":"Synchronous","grid_forming":false,"hours_offline":0.0,"hours_online":0.0,"id":"","in_service":true,"inverter_loss_a_mw":0.0,"inverter_loss_b":0.0,"machine_base_mva":100.0,"on_backup_fuel":false,"pc1":0.0,"pc2":0.0,"pfr_eligible":true,"pg":128.9,"pmax":575.88,"pmin":0.0,"qc1max":0.0,"qc1min":0.0,"qc2max":0.0,"qc2min":0.0,"qg":-16.1,"qmax":200.0,"qmin":-140.0,"quick_start":false,"voltage_regulated":true,"voltage_setpoint_pu":1.04},{"apf":0.0,"bus":2,"commitment_status":"Market","cost":{"Polynomial":{"coeffs":[0.01,40.0,0.0],"shutdown":0.0,"startup":0.0}},"curtailable":false,"emission_rates":{"co2":0.0,"nox":0.0,"pm25":0.0,"so2":0.0},"gen_type":"Synchronous","grid_forming":false,"hours_offline":0.0,"hours_online":0.0,"id":"","in_service":true,"inverter_loss_a_mw":0.0,"inverter_loss_b":0.0,"machine_base_mva":100.0,"on_backup_fuel":false,"pc1":0.0,"pc2":0.0,"pfr_eligible":true,"pg":0.0,"pmax":100.0,"pmin":0.0,"qc1max":0.0,"qc1min":0.0,"qc2max":0.0,"qc2min":0.0,"qg":-0.8,"qmax":50.0,"qmin":-17.0,"quick_start":false,"voltage_regulated":true,"voltage_setpoint_pu":1.01},{"apf":0.0,"bus":3,"commitment_status":"Market","cost":{"Polynomial":{"coeffs":[0.25,20.0,0.0],"shutdown":0.0,"startup":0.0}},"curtailable":false,"emission_rates":{"co2":0.0,"nox":0.0,"pm25":0.0,"so2":0.0},"gen_type":"Synchronous","grid_forming":false,"hours_offline":0.0,"hours_online":0.0,"id":"","in_service":true,"inverter_loss_a_mw":0.0,"inverter_loss_b":0.0,"machine_base_mva":100.0,"on_backup_fuel":false,"pc1":0.0,"pc2":0.0,"pfr_eligible":true,"pg":40.0,"pmax":140.0,"pmin":0.0,"qc1max":0.0,"qc1min":0.0,"qc2max":0.0,"qc2min":0.0,"qg":-1.0,"qmax":60.0,"qmin":-10.0,"quick_start":false,"voltage_regulated":true,"voltage_setpoint_pu":0.985},{"apf":0.0,"bus":6,"commitment_status":"Market","cost":{"Polynomial":{"coeffs":[0.01,40.0,0.0],"shutdown":0.0,"startup":0.0}},"curtailable":false,"emission_rates":{"co2":0.0,"nox":0.0,"pm25":0.0,"so2":0.0},"gen_type":"Synchronous","grid_forming":false,"hours_offline":0.0,"hours_online":0.0,"id":"","in_service":true,"inverter_loss_a_mw":0.0,"inverter_loss_b":0.0,"machine_base_mva":100.0,"on_backup_fuel":false,"pc1":0.0,"pc2":0.0,"pfr_eligible":true,"pg":0.0,"pmax":100.0,"pmin":0.0,"qc1max":0.0,"qc1min":0.0,"qc2max":0.0,"qc2min":0.0,"qg":0.8,"qmax":25.0,"qmin":-8.0,"quick_start":false,"voltage_regulated":true,"voltage_setpoint_pu":0.98},{"apf":0.0,"bus":8,"commitment_status":"Market","cost":{"Polynomial":{"coeffs":[0.0222222222,20.0,0.0],"shutdown":0.0,"startup":0.0}},"curtailable":false,"emission_rates":{"co2":0.0,"nox":0.0,"pm25":0.0,"so2":0.0},"gen_type":"Synchronous","grid_forming":false,"hours_offline":0.0,"hours_online":0.0,"id":"","in_service":true,"inverter_loss_a_mw":0.0,"inverter_loss_b":0.0,"machine_base_mva":100.0,"on_backup_fuel":false,"pc1":0.0,"pc2":0.0,"pfr_eligible":true,"pg":450.0,"pmax":550.0,"pmin":0.0,"qc1max":0.0,"qc1min":0.0,"qc2max":0.0,"qc2min":0.0,"qg":62.1,"qmax":200.0,"qmin":-140.0,"quick_start":false,"voltage_regulated":true,"voltage_setpoint_pu":1.005},{"apf":0.0,"bus":9,"commitment_status":"Market","cost":{"Polynomial":{"coeffs":[0.01,40.0,0.0],"shutdown":0.0,"startup":0.0}},"curtailable":false,"emission_rates":{"co2":0.0,"nox":0.0,"pm25":0.0,"so2":0.0},"gen_type":"Synchronous","grid_forming":false,"hours_offline":0.0,"hours_online":0.0,"id":"","in_service":true,"inverter_loss_a_mw":0.0,"inverter_loss_b":0.0,"machine_base_mva":100.0,"on_backup_fuel":false,"pc1":0.0,"pc2":0.0,"pfr_eligible":true,"pg":0.0,"pmax":100.0,"pmin":0.0,"qc1max":0.0,"qc1min":0.0,"qc2max":0.0,"qc2min":0.0,"qg":2.2,"qmax":9.0,"qmin":-3.0,"quick_start":false,"voltage_regulated":true,"voltage_setpoint_pu":0.98},{"apf":0.0,"bus":12,"commitment_status":"Market","cost":{"Polynomial":{"coeffs":[0.0322580645,20.0,0.0],"shutdown":0.0,"startup":0.0}},"curtailable":false,"emission_rates":{"co2":0.0,"nox":0.0,"pm25":0.0,"so2":0.0},"gen_type":"Synchronous","grid_forming":false,"hours_offline":0.0,"hours_online":0.0,"id":"","in_service":true,"inverter_loss_a_mw":0.0,"inverter_loss_b":0.0,"machine_base_mva":100.0,"on_backup_fuel":false,"pc1":0.0,"pc2":0.0,"pfr_eligible":true,"pg":310.0,"pmax":410.0,"pmin":0.0,"qc1max":0.0,"qc1min":0.0,"qc2max":0.0,"qc2min":0.0,"qg":128.5,"qmax":155.0,"qmin":-150.0,"quick_start":false,"voltage_regulated":true,"voltage_setpoint_pu":1.015}],"loads":[{"active_power_demand_mw":55.0,"bus":1,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":17.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":3.0,"bus":2,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":88.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":41.0,"bus":3,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":21.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":13.0,"bus":5,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":4.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":75.0,"bus":6,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":2.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":150.0,"bus":8,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":22.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":121.0,"bus":9,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":26.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":5.0,"bus":10,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":2.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":377.0,"bus":12,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":24.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":18.0,"bus":13,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":2.3,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":10.5,"bus":14,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":5.3,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":22.0,"bus":15,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":5.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":43.0,"bus":16,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":3.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":42.0,"bus":17,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":8.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":27.2,"bus":18,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":9.8,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":3.3,"bus":19,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":0.6,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":2.3,"bus":20,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":6.3,"bus":23,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":2.1,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":6.3,"bus":25,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":3.2,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":9.3,"bus":27,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":0.5,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":4.6,"bus":28,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":2.3,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":17.0,"bus":29,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":2.6,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":3.6,"bus":30,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.8,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":5.8,"bus":31,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":2.9,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":1.6,"bus":32,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":0.8,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":3.8,"bus":33,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.9,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":6.0,"bus":35,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":3.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":14.0,"bus":38,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":7.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":6.3,"bus":41,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":3.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":7.1,"bus":42,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":4.4,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":2.0,"bus":43,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":12.0,"bus":44,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.8,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":29.7,"bus":47,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":11.6,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":18.0,"bus":49,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":8.5,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":21.0,"bus":50,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":10.5,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":18.0,"bus":51,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":5.3,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":4.9,"bus":52,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":2.2,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":20.0,"bus":53,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":10.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":4.1,"bus":54,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.4,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":6.8,"bus":55,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":3.4,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":7.6,"bus":56,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":2.2,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":6.7,"bus":57,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":2.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0}],"name":"case57"},"schema_version":"0.1.0"} \ No newline at end of file diff --git a/tests/data/surge/market30.surge.json b/tests/data/surge/market30.surge.json new file mode 100644 index 0000000..51159ac --- /dev/null +++ b/tests/data/surge/market30.surge.json @@ -0,0 +1 @@ +{"format":"surge-json","meta":{"producer":"surge","profile":"network"},"network":{"base_mva":100.0,"branches":[{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.03,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":1,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.02,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":520.0,"rating_b_mva":130.0,"rating_c_mva":130.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":2,"transformer_connection":"WyeGWyeG","x":0.06,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.02,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":1,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.05,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":520.0,"rating_b_mva":130.0,"rating_c_mva":130.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":3,"transformer_connection":"WyeGWyeG","x":0.19,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.02,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":2,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.06,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":260.0,"rating_b_mva":65.0,"rating_c_mva":65.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":4,"transformer_connection":"WyeGWyeG","x":0.17,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":3,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.01,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":520.0,"rating_b_mva":130.0,"rating_c_mva":130.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":4,"transformer_connection":"WyeGWyeG","x":0.04,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.02,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":2,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.05,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":520.0,"rating_b_mva":130.0,"rating_c_mva":130.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":5,"transformer_connection":"WyeGWyeG","x":0.2,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.02,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":2,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.06,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":260.0,"rating_b_mva":65.0,"rating_c_mva":65.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":6,"transformer_connection":"WyeGWyeG","x":0.18,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":4,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.01,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":360.0,"rating_b_mva":90.0,"rating_c_mva":90.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":6,"transformer_connection":"WyeGWyeG","x":0.04,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.01,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":5,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.05,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":280.0,"rating_b_mva":70.0,"rating_c_mva":70.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":7,"transformer_connection":"WyeGWyeG","x":0.12,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.01,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":6,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.03,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":520.0,"rating_b_mva":130.0,"rating_c_mva":130.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":7,"transformer_connection":"WyeGWyeG","x":0.08,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":6,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.01,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":128.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":8,"transformer_connection":"WyeGWyeG","x":0.04,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":6,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":260.0,"rating_b_mva":65.0,"rating_c_mva":65.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":9,"transformer_connection":"WyeGWyeG","x":0.21,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":6,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":128.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":10,"transformer_connection":"WyeGWyeG","x":0.56,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":9,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":260.0,"rating_b_mva":65.0,"rating_c_mva":65.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":11,"transformer_connection":"WyeGWyeG","x":0.21,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":9,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":260.0,"rating_b_mva":65.0,"rating_c_mva":65.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":10,"transformer_connection":"WyeGWyeG","x":0.11,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":4,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":260.0,"rating_b_mva":65.0,"rating_c_mva":65.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":12,"transformer_connection":"WyeGWyeG","x":0.26,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":12,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":260.0,"rating_b_mva":65.0,"rating_c_mva":65.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":13,"transformer_connection":"WyeGWyeG","x":0.14,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":12,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.12,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":128.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":14,"transformer_connection":"WyeGWyeG","x":0.26,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":12,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.07,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":128.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":15,"transformer_connection":"WyeGWyeG","x":0.13,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":12,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.09,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":128.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":16,"transformer_connection":"WyeGWyeG","x":0.2,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":14,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.22,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":64.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":15,"transformer_connection":"WyeGWyeG","x":0.2,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":16,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.08,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":64.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":17,"transformer_connection":"WyeGWyeG","x":0.19,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":15,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.11,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":64.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":18,"transformer_connection":"WyeGWyeG","x":0.22,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":18,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.06,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":64.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":19,"transformer_connection":"WyeGWyeG","x":0.13,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":19,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.03,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":128.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":20,"transformer_connection":"WyeGWyeG","x":0.07,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":10,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.09,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":128.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":20,"transformer_connection":"WyeGWyeG","x":0.21,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":10,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.03,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":128.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":17,"transformer_connection":"WyeGWyeG","x":0.08,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":10,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.03,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":128.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":21,"transformer_connection":"WyeGWyeG","x":0.07,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":10,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.07,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":128.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":22,"transformer_connection":"WyeGWyeG","x":0.15,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":21,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.01,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":128.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":22,"transformer_connection":"WyeGWyeG","x":0.02,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":15,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.1,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":64.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":23,"transformer_connection":"WyeGWyeG","x":0.2,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":22,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.12,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":64.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":24,"transformer_connection":"WyeGWyeG","x":0.18,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":23,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.13,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":64.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":24,"transformer_connection":"WyeGWyeG","x":0.27,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":24,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.19,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":64.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":25,"transformer_connection":"WyeGWyeG","x":0.33,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":25,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.25,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":64.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":26,"transformer_connection":"WyeGWyeG","x":0.38,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":25,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.11,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":64.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":27,"transformer_connection":"WyeGWyeG","x":0.21,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":28,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.0,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":260.0,"rating_b_mva":65.0,"rating_c_mva":65.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":27,"transformer_connection":"WyeGWyeG","x":0.4,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":27,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.22,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":64.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":29,"transformer_connection":"WyeGWyeG","x":0.42,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":27,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.32,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":64.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":30,"transformer_connection":"WyeGWyeG","x":0.6,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.0,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":29,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.24,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":64.0,"rating_b_mva":16.0,"rating_c_mva":16.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":30,"transformer_connection":"WyeGWyeG","x":0.45,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.02,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":8,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.06,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":128.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":28,"transformer_connection":"WyeGWyeG","x":0.2,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0},{"angle_diff_max_rad":6.283185307179586,"angle_diff_min_rad":-6.283185307179586,"b":0.01,"b_mag":0.0,"bi0":0.0,"bj0":0.0,"branch_type":"Line","bypassed":false,"circuit":"1","delta_connected":false,"from_bus":6,"g_mag":0.0,"g_pi":0.0,"gi0":0.0,"gj0":0.0,"in_service":true,"phase_mode":"fixed","r":0.02,"r_ref_temp_c":20.0,"r_temp_coeff":0.0,"rating_a_mva":128.0,"rating_b_mva":32.0,"rating_c_mva":32.0,"skin_effect_alpha":0.0,"tap":1.0,"tap_max":1.1,"tap_min":0.9,"tap_mode":"fixed","tap_step":0.0,"to_bus":28,"transformer_connection":"WyeGWyeG","x":0.06,"phase_shift_rad":0.0,"phase_min_rad":-0.5235987755982988,"phase_max_rad":0.5235987755982988,"phase_step_rad":0.0}],"buses":[{"active_power_demand_mw":0.0,"area":1,"base_kv":135.0,"bus_type":"Slack","island_id":0,"name":"","number":1,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":34.72,"area":1,"base_kv":135.0,"bus_type":"PV","island_id":0,"name":"","number":2,"reactive_power_demand_mvar":20.32,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.1,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":3.84,"area":1,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":3,"reactive_power_demand_mvar":1.92,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":12.16,"area":1,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":4,"reactive_power_demand_mvar":2.5600000000000005,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":5,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.19,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":6,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":36.480000000000004,"area":1,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":7,"reactive_power_demand_mvar":17.44,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":48.0,"area":1,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":8,"reactive_power_demand_mvar":48.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":9,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":9.28,"area":3,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":10,"reactive_power_demand_mvar":3.2,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":11,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":17.919999999999998,"area":2,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":12,"reactive_power_demand_mvar":12.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":0.0,"area":2,"base_kv":135.0,"bus_type":"PV","island_id":0,"name":"","number":13,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.1,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":9.920000000000002,"area":2,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":14,"reactive_power_demand_mvar":2.5600000000000005,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":13.12,"area":2,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":15,"reactive_power_demand_mvar":4.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":5.6000000000000005,"area":2,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":16,"reactive_power_demand_mvar":2.8800000000000003,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":14.4,"area":2,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":17,"reactive_power_demand_mvar":9.28,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":5.120000000000001,"area":2,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":18,"reactive_power_demand_mvar":1.4400000000000002,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":15.200000000000001,"area":2,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":19,"reactive_power_demand_mvar":5.44,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":3.5200000000000005,"area":2,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":20,"reactive_power_demand_mvar":1.1199999999999999,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":28.0,"area":3,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":21,"reactive_power_demand_mvar":17.919999999999998,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":0.0,"area":3,"base_kv":135.0,"bus_type":"PV","island_id":0,"name":"","number":22,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.1,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":5.120000000000001,"area":2,"base_kv":135.0,"bus_type":"PV","island_id":0,"name":"","number":23,"reactive_power_demand_mvar":2.5600000000000005,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.1,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":13.92,"area":3,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":24,"reactive_power_demand_mvar":10.72,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.04,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":0.0,"area":3,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":25,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":5.6000000000000005,"area":3,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":26,"reactive_power_demand_mvar":3.6799999999999997,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":0.0,"area":3,"base_kv":135.0,"bus_type":"PV","island_id":0,"name":"","number":27,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.1,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":0.0,"area":1,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":28,"reactive_power_demand_mvar":0.0,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":3.84,"area":3,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":29,"reactive_power_demand_mvar":1.4400000000000002,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1},{"active_power_demand_mw":16.96,"area":3,"base_kv":135.0,"bus_type":"PQ","island_id":0,"name":"","number":30,"reactive_power_demand_mvar":3.04,"shunt_conductance_mw":0.0,"shunt_susceptance_mvar":0.0,"voltage_angle_rad":0.0,"voltage_magnitude_pu":1.0,"voltage_max_pu":1.05,"voltage_min_pu":0.95,"zone":1}],"combined_cycle_plants":[{"active_config":"GT_ONLY","configs":[{"energy_offer":null,"gen_indices":[1],"heat_rate_curve":[],"min_down_time_hr":2.0,"min_up_time_hr":2.0,"name":"GT_ONLY","no_load_cost":0.0,"p_max_mw":110.0,"p_min_mw":25.0,"ramp_down_curve":[],"ramp_up_curve":[]},{"energy_offer":null,"gen_indices":[1,2],"heat_rate_curve":[],"min_down_time_hr":3.0,"min_up_time_hr":4.0,"name":"CC_FULL","no_load_cost":0.0,"p_max_mw":170.0,"p_min_mw":45.0,"ramp_down_curve":[],"ramp_up_curve":[]}],"duct_firing_capable":false,"hours_in_config":6.0,"name":"CC1","transitions":[{"from_config":"GT_ONLY","online_transition":true,"to_config":"CC_FULL","transition_cost":900.0,"transition_time_min":60.0},{"from_config":"CC_FULL","online_transition":true,"to_config":"GT_ONLY","transition_cost":600.0,"transition_time_min":45.0}]}],"dispatchable_loads":[{"archetype":"Curtailable","bus_idx":6,"cost_model":{"LinearCurtailment":{"cost_per_mw":100.0}},"dispatch_notification_minutes":0.0,"fixed_power_factor":true,"in_service":true,"min_duration_hours":0.0,"p_max_pu":0.3,"p_min_pu":0.0,"p_sched_pu":0.3,"q_max_pu":0.0,"q_min_pu":0.0,"q_sched_pu":0.0,"rebound_fraction":0.0,"rebound_periods":0,"resource_id":""},{"archetype":"Interruptible","bus_idx":20,"cost_model":{"InterruptPenalty":{"cost_per_mw":200.0}},"dispatch_notification_minutes":0.0,"fixed_power_factor":true,"in_service":true,"min_duration_hours":0.0,"p_max_pu":0.2,"p_min_pu":0.0,"p_sched_pu":0.2,"q_max_pu":0.0,"q_min_pu":0.0,"q_sched_pu":0.0,"rebound_fraction":0.0,"rebound_periods":0,"resource_id":""},{"archetype":"Curtailable","bus_idx":29,"cost_model":{"LinearCurtailment":{"cost_per_mw":80.0}},"dispatch_notification_minutes":0.0,"fixed_power_factor":true,"in_service":true,"min_duration_hours":0.0,"p_max_pu":0.15,"p_min_pu":0.0,"p_sched_pu":0.15,"q_max_pu":0.0,"q_min_pu":0.0,"q_sched_pu":0.0,"rebound_fraction":0.0,"rebound_periods":0,"resource_id":""}],"flowgates":[{"contingency_branch":[4,12,"1"],"in_service":true,"limit_mw":50.0,"limit_mw_schedule":[],"limit_reverse_mw":0.0,"limit_reverse_mw_schedule":[],"monitored_branches":[[6,10,"1"]],"monitored_coefficients":[1.0],"name":"North-South"}],"freq_hz":60.0,"generators":[{"bus":1,"commitment_status":"Market","cost":{"Polynomial":{"coeffs":[0.002,18.0,400.0],"shutdown":0.0,"startup":0.0}},"curtailable":false,"emission_rates":{"co2":0.95,"nox":0.0,"pm25":0.0,"so2":0.0},"fuel_type":"coal","gen_type":"Synchronous","grid_forming":false,"hours_offline":0.0,"hours_online":0.0,"id":"gen_1_1","in_service":true,"inverter_loss_a_mw":0.0,"inverter_loss_b":0.0,"machine_base_mva":100.0,"machine_id":"G1","min_down_time_hr":8.0,"min_up_time_hr":8.0,"on_backup_fuel":false,"pfr_eligible":true,"pg":160.0,"pmax":200.0,"pmin":50.0,"qg":0.0,"qmax":9999.0,"qmin":-9999.0,"qualifications":{"nspin":false,"reg_dn":true,"reg_up":true,"spin":true},"quick_start":false,"ramp_down_curve":[[0.0,2.0]],"ramp_up_curve":[[0.0,2.0]],"reserve_offers":[{"capacity_mw":40.0,"cost_per_mwh":5.0,"product_id":"spin"},{"capacity_mw":10.0,"cost_per_mwh":8.0,"product_id":"reg_up"},{"capacity_mw":10.0,"cost_per_mwh":8.0,"product_id":"reg_dn"}],"voltage_regulated":true,"voltage_setpoint_pu":1.0},{"bus":2,"commitment_status":"Market","cost":{"Polynomial":{"coeffs":[0.003,24.0,150.0],"shutdown":0.0,"startup":0.0}},"curtailable":false,"emission_rates":{"co2":0.42,"nox":0.0,"pm25":0.0,"so2":0.0},"fuel_type":"gas","gen_type":"Synchronous","grid_forming":false,"hours_offline":0.0,"hours_online":0.0,"id":"gen_2_1","in_service":true,"inverter_loss_a_mw":0.0,"inverter_loss_b":0.0,"machine_base_mva":100.0,"machine_id":"CC1_GT","min_down_time_hr":2.0,"min_up_time_hr":2.0,"on_backup_fuel":false,"pfr_eligible":true,"pg":80.0,"pmax":110.0,"pmin":25.0,"qg":0.0,"qmax":9999.0,"qmin":-9999.0,"quick_start":false,"ramp_down_curve":[[0.0,6.0]],"ramp_up_curve":[[0.0,6.0]],"voltage_regulated":true,"voltage_setpoint_pu":1.0},{"bus":2,"commitment_status":"Market","cost":{"Polynomial":{"coeffs":[0.002,16.0,120.0],"shutdown":0.0,"startup":0.0}},"curtailable":false,"emission_rates":{"co2":0.18,"nox":0.0,"pm25":0.0,"so2":0.0},"fuel_type":"gas","gen_type":"Synchronous","grid_forming":false,"hours_offline":0.0,"hours_online":0.0,"id":"gen_2_2","in_service":true,"inverter_loss_a_mw":0.0,"inverter_loss_b":0.0,"machine_base_mva":100.0,"machine_id":"CC1_ST","min_down_time_hr":2.0,"min_up_time_hr":2.0,"on_backup_fuel":false,"pfr_eligible":true,"pg":35.0,"pmax":60.0,"pmin":10.0,"qg":0.0,"qmax":9999.0,"qmin":-9999.0,"quick_start":false,"ramp_down_curve":[[0.0,4.0]],"ramp_up_curve":[[0.0,4.0]],"voltage_regulated":true,"voltage_setpoint_pu":1.0},{"bus":13,"commitment_status":"Market","cost":{"Polynomial":{"coeffs":[0.005,55.0,100.0],"shutdown":0.0,"startup":0.0}},"curtailable":false,"emission_rates":{"co2":0.55,"nox":0.0,"pm25":0.0,"so2":0.0},"fuel_type":"gas","gen_type":"Synchronous","grid_forming":false,"hours_offline":0.0,"hours_online":0.0,"id":"gen_13_1","in_service":true,"inverter_loss_a_mw":0.0,"inverter_loss_b":0.0,"machine_base_mva":100.0,"machine_id":"G3","min_down_time_hr":1.0,"min_up_time_hr":1.0,"on_backup_fuel":false,"pfr_eligible":true,"pg":0.0,"pmax":80.0,"pmin":10.0,"qg":0.0,"qmax":9999.0,"qmin":-9999.0,"qualifications":{"nspin":true,"reg_dn":false,"reg_up":false,"spin":true},"quick_start":true,"ramp_down_curve":[[0.0,10.0]],"ramp_up_curve":[[0.0,10.0]],"reserve_offers":[{"capacity_mw":40.0,"cost_per_mwh":6.0,"product_id":"spin"},{"capacity_mw":80.0,"cost_per_mwh":2.0,"product_id":"nspin"}],"voltage_regulated":true,"voltage_setpoint_pu":1.0},{"bus":22,"commitment_status":"MustRun","cost":{"Polynomial":{"coeffs":[0.0,8.0,600.0],"shutdown":0.0,"startup":0.0}},"curtailable":false,"emission_rates":{"co2":0.0,"nox":0.0,"pm25":0.0,"so2":0.0},"fuel_type":"nuclear","gen_type":"Synchronous","grid_forming":false,"hours_offline":0.0,"hours_online":0.0,"id":"gen_22_1","in_service":true,"inverter_loss_a_mw":0.0,"inverter_loss_b":0.0,"machine_base_mva":100.0,"machine_id":"G4","min_down_time_hr":72.0,"min_up_time_hr":168.0,"on_backup_fuel":false,"pfr_eligible":true,"pg":95.0,"pmax":100.0,"pmin":50.0,"qg":0.0,"qmax":9999.0,"qmin":-9999.0,"qualifications":{"nspin":false,"reg_dn":false,"reg_up":false,"spin":false},"quick_start":false,"ramp_down_curve":[[0.0,0.5]],"ramp_up_curve":[[0.0,0.5]],"voltage_regulated":true,"voltage_setpoint_pu":1.0},{"bus":23,"commitment_status":"Market","cost":{"Polynomial":{"coeffs":[0.006,65.0,80.0],"shutdown":0.0,"startup":0.0}},"curtailable":false,"emission_rates":{"co2":0.6,"nox":0.0,"pm25":0.0,"so2":0.0},"fuel_type":"gas","gen_type":"Synchronous","grid_forming":false,"hours_offline":0.0,"hours_online":0.0,"id":"gen_23_1","in_service":true,"inverter_loss_a_mw":0.0,"inverter_loss_b":0.0,"machine_base_mva":100.0,"machine_id":"G5","min_down_time_hr":1.0,"min_up_time_hr":1.0,"on_backup_fuel":false,"pfr_eligible":true,"pg":0.0,"pmax":60.0,"pmin":5.0,"qg":0.0,"qmax":9999.0,"qmin":-9999.0,"qualifications":{"nspin":true,"reg_dn":false,"reg_up":false,"spin":false},"quick_start":true,"ramp_down_curve":[[0.0,10.0]],"ramp_up_curve":[[0.0,10.0]],"reserve_offers":[{"capacity_mw":60.0,"cost_per_mwh":3.0,"product_id":"nspin"}],"voltage_regulated":true,"voltage_setpoint_pu":1.0},{"bus":15,"commitment_status":"Market","cost":{"Polynomial":{"coeffs":[0.0,0.0,0.0],"shutdown":0.0,"startup":0.0}},"curtailable":false,"emission_rates":{"co2":0.0,"nox":0.0,"pm25":0.0,"so2":0.0},"fuel_type":"wind","gen_type":"Synchronous","grid_forming":false,"hours_offline":0.0,"hours_online":0.0,"id":"gen_15_1","in_service":true,"inverter_loss_a_mw":0.0,"inverter_loss_b":0.0,"machine_base_mva":100.0,"machine_id":"W1","on_backup_fuel":false,"pfr_eligible":true,"pg":36.0,"pmax":120.0,"pmin":0.0,"qg":0.0,"qmax":9999.0,"qmin":-9999.0,"qualifications":{"nspin":false,"reg_dn":false,"reg_up":false,"spin":false},"quick_start":false,"ramp_down_curve":[[0.0,120.0]],"ramp_up_curve":[[0.0,120.0]],"voltage_regulated":true,"voltage_setpoint_pu":1.0},{"bus":25,"commitment_status":"Market","cost":{"Polynomial":{"coeffs":[0.0,0.0,0.0],"shutdown":0.0,"startup":0.0}},"curtailable":false,"emission_rates":{"co2":0.0,"nox":0.0,"pm25":0.0,"so2":0.0},"fuel_type":"solar","gen_type":"Synchronous","grid_forming":false,"hours_offline":0.0,"hours_online":0.0,"id":"gen_25_1","in_service":true,"inverter_loss_a_mw":0.0,"inverter_loss_b":0.0,"machine_base_mva":100.0,"machine_id":"S1","on_backup_fuel":false,"pfr_eligible":true,"pg":0.0,"pmax":80.0,"pmin":0.0,"qg":0.0,"qmax":9999.0,"qmin":-9999.0,"qualifications":{"nspin":false,"reg_dn":false,"reg_up":false,"spin":false},"quick_start":false,"ramp_down_curve":[[0.0,80.0]],"ramp_up_curve":[[0.0,80.0]],"voltage_regulated":true,"voltage_setpoint_pu":1.0},{"bus":10,"commitment_status":"Market","cost":{"Polynomial":{"coeffs":[0.0,0.5,0.0],"shutdown":0.0,"startup":0.0}},"curtailable":false,"emission_rates":{"co2":0.0,"nox":0.0,"pm25":0.0,"so2":0.0},"gen_type":"Synchronous","grid_forming":false,"hours_offline":0.0,"hours_online":0.0,"id":"gen_10_1","in_service":true,"inverter_loss_a_mw":0.0,"inverter_loss_b":0.0,"machine_base_mva":100.0,"machine_id":"B1","on_backup_fuel":false,"pfr_eligible":true,"pg":0.0,"pmax":50.0,"pmin":-50.0,"qg":0.0,"qmax":9999.0,"qmin":-9999.0,"qualifications":{"nspin":true,"reg_dn":true,"reg_up":true,"spin":true},"quick_start":false,"ramp_down_curve":[[0.0,50.0]],"ramp_up_curve":[[0.0,50.0]],"reserve_offers":[{"capacity_mw":25.0,"cost_per_mwh":3.0,"product_id":"spin"},{"capacity_mw":25.0,"cost_per_mwh":5.0,"product_id":"reg_up"},{"capacity_mw":25.0,"cost_per_mwh":5.0,"product_id":"reg_dn"}],"storage":{"chemistry":"LFP","degradation_cost_per_mwh":2.0,"dispatch_mode":"CostMinimization","efficiency":0.92,"energy_capacity_mwh":200.0,"self_schedule_mw":0.0,"soc_initial_mwh":110.0,"soc_max_mwh":190.0,"soc_min_mwh":15.0,"variable_cost_per_mwh":1.0},"voltage_regulated":true,"voltage_setpoint_pu":1.0},{"bus":27,"commitment_status":"Market","cost":{"Polynomial":{"coeffs":[0.0,1.0,0.0],"shutdown":0.0,"startup":0.0}},"curtailable":false,"emission_rates":{"co2":0.0,"nox":0.0,"pm25":0.0,"so2":0.0},"gen_type":"Synchronous","grid_forming":false,"hours_offline":0.0,"hours_online":0.0,"id":"gen_27_1","in_service":true,"inverter_loss_a_mw":0.0,"inverter_loss_b":0.0,"machine_base_mva":100.0,"machine_id":"PH","min_down_time_hr":2.0,"min_up_time_hr":2.0,"on_backup_fuel":false,"pfr_eligible":true,"pg":0.0,"pmax":100.0,"pmin":-80.0,"qg":0.0,"qmax":9999.0,"qmin":-9999.0,"qualifications":{"nspin":true,"reg_dn":true,"reg_up":true,"spin":true},"quick_start":false,"ramp_down_curve":[[0.0,20.0]],"ramp_up_curve":[[0.0,20.0]],"reserve_offers":[{"capacity_mw":30.0,"cost_per_mwh":4.0,"product_id":"spin"},{"capacity_mw":15.0,"cost_per_mwh":6.0,"product_id":"reg_up"},{"capacity_mw":15.0,"cost_per_mwh":6.0,"product_id":"reg_dn"}],"storage":{"degradation_cost_per_mwh":0.5,"dispatch_mode":"CostMinimization","efficiency":0.89,"energy_capacity_mwh":800.0,"self_schedule_mw":0.0,"soc_initial_mwh":500.0,"soc_max_mwh":760.0,"soc_min_mwh":80.0,"variable_cost_per_mwh":1.0},"voltage_regulated":true,"voltage_setpoint_pu":1.0}],"hvdc":{"links":[{"converter1":{"ac_setpoint":1.0,"bus":12,"control_mode":"AcVoltage","dc_setpoint":40.0,"in_service":true,"loss_constant_mw":0.0,"loss_linear":0.0,"q_max_mvar":9999.0,"q_min_mvar":-9999.0,"voltage_max_pu":1.1,"voltage_min_pu":0.9},"converter2":{"ac_setpoint":1.0,"bus":30,"control_mode":"AcVoltage","dc_setpoint":-40.0,"in_service":true,"loss_constant_mw":0.0,"loss_linear":0.0,"q_max_mvar":9999.0,"q_min_mvar":-9999.0,"voltage_max_pu":1.1,"voltage_min_pu":0.9},"mode":"PowerControl","name":"HVDC_12_30","resistance_ohm":0.0,"technology":"vsc"}]},"interfaces":[{"branches":[[6,9,"1"],[6,10,"1"],[4,12,"1"]],"coefficients":[1.0,1.0,1.0],"in_service":true,"limit_forward_mw":180.0,"limit_forward_mw_schedule":[],"limit_reverse_mw":120.0,"limit_reverse_mw_schedule":[],"name":"Area1-Area2"}],"loads":[{"active_power_demand_mw":34.72,"bus":2,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":20.32,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":3.84,"bus":3,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.92,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":12.16,"bus":4,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":2.5600000000000005,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":36.480000000000004,"bus":7,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":17.44,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":48.0,"bus":8,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":48.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":9.28,"bus":10,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":3.2,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":17.919999999999998,"bus":12,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":12.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":9.920000000000002,"bus":14,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":2.5600000000000005,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":13.12,"bus":15,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":4.0,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":5.6000000000000005,"bus":16,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":2.8800000000000003,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":14.4,"bus":17,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":9.28,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":5.120000000000001,"bus":18,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.4400000000000002,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":15.200000000000001,"bus":19,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":5.44,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":3.5200000000000005,"bus":20,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.1199999999999999,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":28.0,"bus":21,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":17.919999999999998,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":5.120000000000001,"bus":23,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":2.5600000000000005,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":13.92,"bus":24,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":10.72,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":5.6000000000000005,"bus":26,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":3.6799999999999997,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":3.84,"bus":29,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":1.4400000000000002,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0},{"active_power_demand_mw":16.96,"bus":30,"conforming":true,"connection":"WyeGrounded","frac_electronic":0.0,"frac_motor_a":0.0,"frac_motor_b":0.0,"frac_motor_c":0.0,"frac_motor_d":0.0,"frac_static":1.0,"freq_sensitivity_p_pct_per_hz":0.0,"freq_sensitivity_q_pct_per_hz":0.0,"id":"","in_service":true,"reactive_power_demand_mvar":3.04,"zip_p_current_frac":0.0,"zip_p_impedance_frac":0.0,"zip_p_power_frac":1.0,"zip_q_current_frac":0.0,"zip_q_impedance_frac":0.0,"zip_q_power_frac":1.0}],"name":"market30","pumped_hydro_units":[{"condenser_capable":false,"efficiency_generate":0.9,"efficiency_pump":0.88,"forbidden_zone":null,"gen_index":9,"head_curve":[],"lower_reservoir_mwh":1.7976931348623157e+308,"min_release_mw":10.0,"mode_transition_min":5.0,"n_units":1,"name":"PH1_Hydro","pump_mw_fixed":0.0,"pump_mw_max":80.0,"pump_mw_min":20.0,"ramp_rate_mw_per_min":20.0,"shared_penstock_mw_max":null,"soc_initial_mwh":500.0,"soc_max_mwh":760.0,"soc_min_mwh":80.0,"startup_cost":500.0,"startup_time_gen_min":5.0,"startup_time_pump_min":10.0,"upper_reservoir_mwh":800.0,"variable_speed":false}]},"schema_version":"0.1.0"} \ No newline at end of file From 9318ee8081ec500fb234eee80251d215c1ba6bdb Mon Sep 17 00:00:00 2001 From: samtalki <10187005+samtalki@users.noreply.github.com> Date: Mon, 8 Jun 2026 14:31:34 -0400 Subject: [PATCH 2/2] Fix Surge JSON branch tap and numeric parsing --- powerio/src/format/surge.rs | 44 +++++++++++++++++++++++++++++++++---- powerio/tests/convert.rs | 5 +++-- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/powerio/src/format/surge.rs b/powerio/src/format/surge.rs index 4c9873b..e975c78 100644 --- a/powerio/src/format/surge.rs +++ b/powerio/src/format/surge.rs @@ -544,7 +544,7 @@ fn read_branch(value: &Value) -> Result { let branch_type = string_map(obj, "branch_type").unwrap_or("Line"); let tap_value = f_map_or(obj, "tap", 1.0)?; let shift = f_map_or(obj, "phase_shift_rad", 0.0)? * DEG_PER_RAD; - let tap = if branch_type == "Line" && (tap_value - 1.0).abs() < EPS && shift.abs() < EPS { + let tap = if branch_type == "Line" && (tap_value - 1.0).abs() < EPS { 0.0 } else { tap_value @@ -1088,9 +1088,16 @@ fn value_to_f64(value: &Value, key: &str) -> Result { Value::Number(number) => number .as_f64() .ok_or_else(|| format_error(format!("`{key}` is not a finite f64"))), - Value::String(value) => value - .parse::() - .map_err(|_| format_error(format!("`{key}` string is not a f64"))), + Value::String(value) => { + let parsed = value + .parse::() + .map_err(|_| format_error(format!("`{key}` string is not a f64")))?; + if parsed.is_finite() { + Ok(parsed) + } else { + Err(format_error(format!("`{key}` string is not a finite f64"))) + } + } Value::Object(obj) if obj.contains_key("$surge_float") => Err(format_error(format!( "`{key}` uses Surge tagged non-finite float values, which powerio does not support" ))), @@ -1214,6 +1221,17 @@ mod tests { .unwrap(); assert!(branch.tap.abs() < EPS); + let branch = read_branch(&serde_json::json!({ + "from_bus": 1, + "to_bus": 2, + "branch_type": "Line", + "tap": 1.0, + "phase_shift_rad": 0.1 + })) + .unwrap(); + assert!(branch.tap.abs() < EPS); + assert!((branch.shift - 0.1 * DEG_PER_RAD).abs() < EPS); + let branch = read_branch(&serde_json::json!({ "from_bus": 1, "to_bus": 2, @@ -1223,4 +1241,22 @@ mod tests { .unwrap(); assert!((branch.tap - 1.0).abs() < EPS); } + + #[test] + fn rejects_nonfinite_numeric_strings() { + let err = parse_surge_json( + r#"{ + "format": "surge-json", + "schema_version": "0.1.0", + "meta": {}, + "network": { + "buses": [ + {"number": 1, "voltage_angle_rad": "NaN"} + ] + } + }"#, + ) + .unwrap_err(); + assert!(matches!(err, Error::FormatRead { .. })); + } } diff --git a/powerio/tests/convert.rs b/powerio/tests/convert.rs index ce602da..1398185 100644 --- a/powerio/tests/convert.rs +++ b/powerio/tests/convert.rs @@ -245,9 +245,10 @@ fn surge_radians_tap_cost_and_storage_mapping() { let net = parse_surge_json(json).unwrap(); assert!((net.buses[0].va - 30.0).abs() < 1e-9); assert!( - (net.branches[0].tap - 1.0).abs() < 1e-12, - "nonzero shift makes this a transformer-like branch" + net.branches[0].tap.abs() < 1e-12, + "surge Line tap=1.0 maps to MATPOWER raw tap=0.0 even with phase shift" ); + assert!((net.branches[0].effective_tap() - 1.0).abs() < 1e-12); assert!((net.branches[0].shift - 15.0).abs() < 1e-9); assert!((net.branches[0].angmin + 30.0).abs() < 1e-9); assert!((net.branches[0].angmax - 30.0).abs() < 1e-9);