feat: name the DC axes, expose operating point networks, and close the geometry regression (0.11.1) - #495
feat: name the DC axes, expose operating point networks, and close the geometry regression (0.11.1)#495samtalki wants to merge 8 commits into
Conversation
…e geometry regression (0.11.1)
Additive 0.11.1 work under the 0.11.x compatibility rule: no public Rust or C
signature changes, ABI 7 unchanged, new symbols only.
- DcOperatorOptions and DcOperators::build_with; branch_rows, branch_identities
and skipped_branch_rows state the branch axis beside bus_ids. With
skip_zero_impedance a zero impedance branch leaves the axis and is listed
instead of failing the build with BUILD.OPERATOR.ZERO_IMPEDANCE, the same
choice the admittance builders offer.
- C ABI 7 gains the PioDcOperators handle: pio_calc_dc_operators, the axis
accessors, and the eight calculations over one build. The existing pio_calc_*
entry points are unchanged; the header is regenerated with cbindgen.
- Python: BalancedNetwork.calc_dc_index_map and skip_zero_impedance on every
DC calc_* method. OperatingPoint.network and
powerio::network_with_operating_point return the balanced network an
operating point states with the point's values applied.
- MCP calc_matrix reports row_ids and col_ids for every result, serves the
eight DC calculations by name (vectors as {"format": "vector"}), takes
skip_zero_impedance, and accepts an operating point entry; summarize
describes an operating point through its network; diagnostic records carry
suggested_action, related and details.
- The OpenDSS geometry regression cases from Burhan Abdullah's draft (#480)
run as ordinary tests in powerio-dist/tests/electrical_readiness.rs: a
geometry defined line is reported by READ.DSS.GEOMETRY_UNRESOLVED when it is
read and never receives the OpenDSS factory impedance or a fabricated
conductor count.
Reported from the PowerIO.jl port of PowerDiff.jl (eigenergy/PowerIO.jl#139,
#140). Version 0.11.1 with the changelog section, the release notes draft,
and the golden Arrow payloads renumbered.
Closes #479
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NoJFzdnTLwtFZLPhUeyCvR
Conversion MatrixLegendCells show A nonzero cell means the target format cannot carry what the source stated, and every warning names the field or record it cannot carry. A write or readback warning names a field of the target format; a source parse warning, which every cell of that row shares, names what the source document itself leaves unstated. A warning that named a writer PowerIO could extend instead of a limit of the format would be a defect in this table.
TransmissionSix generated cases per writable source row; one vendored case per read-only source row. Into a case format
Into an exchange format
Into a dataset directory
DistributionSeven cases per source row. Into a distribution format
Geographic LayerOne case per source row. Into the geographic layer document
A geographic layer is a Full warning details: download |
`calc_dc_index_map` returns the `DcIndexMap` TypedDict, which mypy does not accept where a `Dict[str, Any]` is declared, so the type gate failed on all three `_axis_ids` call sites. `Mapping` states what the helper actually needs: read-only keyed access. The same gate also flagged `DcIndexMap` itself as a stub-only name with no runtime object, the deviation the allowlist exists to record for every other TypedDict in the stubs. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NoJFzdnTLwtFZLPhUeyCvR
`ptdf` and `lodf` reach `calc_ptdf` and `calc_lodf`, which factor the reference grounded DC matrix and take no `skip_zero_impedance` option. The tool accepted the flag anyway, dropped it, and echoed `"skip_zero_impedance": true` back in the payload, so a caller reading the response had no way to see that the zero impedance branches were still in the axis. Reject the pair with a message that names the six DC calculations that do honor the flag, and say the same in the tool's parameter description and the guide. The guide also called those six "the eight DC calculations". The other two, `branch_flow_dc` and `bus_injection_dc`, need voltage angles and so are not matrix names at all. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NoJFzdnTLwtFZLPhUeyCvR
case9 has nine buses and nine branches, so the incidence assertion `shape == [9, 9]` held whether the result was branches by buses or its transpose. case14 has 14 buses and 20 branches; the shape now fails on a swap, and the axis ids are compared against the branch identities and bus ids `calc_dc_index_map` reports for the same case rather than only against each other. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NoJFzdnTLwtFZLPhUeyCvR
The handle shipped with no C ABI test of its own. Build a three bus, two branch case whose first branch states r = x = 0 and check the whole surface: the refused build reports BUILD.OPERATOR.ZERO_IMPEDANCE, the skipping build leaves branch row 0 out of the axis and lists it in `skipped_branch_rows`, the bus and branch axes and one branch identity read back, all eight calculations return a handle of the right shape, retain outlives its release, a NULL handle reads as an empty axis instead of faulting, and an out of range identity index returns an empty view. The C probe gains the happy path over case9, where the axes match the bus and branch counts and nothing is skipped. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NoJFzdnTLwtFZLPhUeyCvR
`network_with_balanced_operating_point` returns the network beside the diagnostics it raised, but `OperatingPoint.network` and `powerio::network_with_operating_point` return the network alone. Net bus injection quantities have no balanced network field, so they are dropped there and nothing says so; only `emit` reports the omission, as EMIT.OPERATING_POINT.DATA_OMITTED. Say this in the guide and the property's docstring so a caller knows to emit the collection when the omission matters. The facade exposes no public function that hands back both, and the 0.11.x line takes no new public signatures, so this pass documents the behavior rather than changing it. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NoJFzdnTLwtFZLPhUeyCvR
The `Generated schemas match` job runs the generator with `--check` and the committed files still carried the 0.11.0 producer version. Regenerated with `cargo run -p powerio-dist --example regen_bmopf_examples`. ieee34.json and ieee123.json change only the version strings. 4bus_dy.json also gains a `meta.provenance.powerio_bmopf_4` record: `proposal_provenance` appends a new numbered record whenever the producer version differs from every record already present, and that file has no vendored DSS source to reset them, so it already carried `_1` through `_3`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NoJFzdnTLwtFZLPhUeyCvR
calc_adjacency_matrix and calc_weighted_laplacian take no such option, so calc_matrix echoed the flag in the payload while the result ignored it, the same defect the ptdf and lodf guard closed. The refused names now live in one tuple the guard, the field text, and the docs share. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NoJFzdnTLwtFZLPhUeyCvR
Summary
Additive 0.11.1 work, all under the 0.11.x compatibility rule: no public Rust or C signature changes, ABI 7 unchanged, new symbols only.
Named DC axes (PowerIO.jl#139, #140)
DcOperatorOptionsandDcOperators::build_with;branch_rows,branch_identities, andskipped_branch_rowsstate the branch axis besidebus_ids. Withskip_zero_impedancea zero impedance branch leaves the axis and is listed instead of failing the build withBUILD.OPERATOR.ZERO_IMPEDANCE, the same choice the admittance builders offer.PioDcOperatorshandle:pio_calc_dc_operators, the axis accessors, and the eight calculations over one build. The existingpio_calc_*entry points are unchanged; the header is regenerated with cbindgen andcheck-capi-v7.shpasses against the PowerIO.jl branch of the same name (fix: correct to_powerdata, unify zero impedance handling, name the DC axes (0.11.1) PowerIO.jl#144).BalancedNetwork.calc_dc_index_mapandskip_zero_impedanceon every DCcalc_*method.calc_matrix:row_idsandcol_idson every result, the eight DC calculations by name (vectors as{"format": "vector"}), andskip_zero_impedance.Operating points:
powerio::network_with_operating_pointand PythonOperatingPoint.networkreturn the balanced network an entry states with the point's values applied, so a consumer selects a collection entry without emitting and reparsing it.summarizeandcalc_matrixaccept an operating point entry through it.Diagnostics: MCP records carry
suggested_action,related, anddetails.#479: Burhan Abdullah's regression cases from draft #480 run as ordinary tests in
powerio-dist/tests/electrical_readiness.rs: a geometry defined line is reported byREAD.DSS.GEOMETRY_UNRESOLVEDwhen read and never receives the OpenDSS factory impedance or a fabricated conductor count.Version 0.11.1, the
## 0.11.1changelog section, anddocs/release-notes/0.11.1-draft.md; the golden Arrow payloads are renumbered. Tagging stays with the maintainer.Closes #479
Validation
cargo test --workspace --exclude powerio-py,cargo test -p powerio-capi(31 passed),cargo fmt --all --check,bash scripts/check-capi-v7.sh(with the PowerIO.jl checkout),bash scripts/capi-header-regen.sh,bash scripts/check-release-versions.sh,bash scripts/terminology-gate.sh,bash scripts/check-value-types.sh,python3 scripts/check-doc-symbols.py, andmaturin build --releasepluspytest python/testsin a 3.11 venv (222 passed, 1 skipped).bash scripts/ci-clippy.shwas rerunning at the time of opening; any finding lands as a follow-up commit on this branch.Companions: eigenergy/PowerIO.jl#144 binds the new handle; samtalki/PowerMCP#2 (the follow-up to Power-Agent/PowerMCP#64) consumes
calc_matrixaxes andOperatingPoint.network.🤖 Generated with Claude Code
https://claude.ai/code/session_01NoJFzdnTLwtFZLPhUeyCvR
Generated by Claude Code