Parse BINIT into solved_admittance, rename initial_status to number_engaged - #55
Conversation
…ngaged Parser half of the SwitchedAdmittance changes in PowerSystems.jl#1774, following Sienna-Platform/SiennaSchemas#44 (merged), which added `solved_admittance` and renamed `initial_status` to `number_engaged`. BINIT was being parsed into `bs`, which `shunt.jl` writes to `Y`. A PSS/E switched shunt has no fixed base admittance -- the SWITCHED SHUNT record carries only BINIT (the solved/initial total susceptance) and the per-block increments -- so putting the solved total into `Y` forced everything downstream to disentangle the two again. Pre-v35 did it by zeroing a full-length block-status vector so the blocks could not double-count what BINIT already included; that zeroed vector then became the sentinel PowerFlows.jl read to decide which convention a shunt followed. BINIT now goes to its own `solved_admittance` key with `bs = 0.0`, so "solved total" and "fixed base + blocks" are distinguishable without inference, and the pre-v35 zero-fill means what it says: no per-block information. v35's S1..S8 keeps parsing to `number_engaged`. Three details worth review: - `_make_per_unit!` gains `solved_admittance` alongside `bs`/`y_increment`. BINIT is an admittance and must be per-unitized with them; without it the value reaches the component a factor of baseMVA too large. - `device_base.jl` classifies `("SwitchedAdmittance", :solved_admittance)` as `:skip`, matching `Y`/`Y_increase`/`admittance_limits`. It inherits the `admittance_units` discriminator, which is a representation switch rather than a natural-unit choice, and PSY's `to_openapi` scales it by the SYSTEM base in both document conventions. The registry is total, so omitting it errored by construction rather than silently mis-scaling a COMPONENT_BASE document. - `solved_admittance` is populated unconditionally, since a SWITCHED SHUNT record always carries BINIT (pti.jl defaults it to 0.0). A parsed shunt therefore always has a solved admittance and downstream reads it instead of summing blocks -- which is what PSS/E does with the value. Gating on MODSW == 0 is the alternative reading of the manual's "locked" clause. Tests updated: the pre-v35 testset now pins `gs == bs == 0.0` and a per-unitized `solved_admittance`, and the OpenAPI shunt test asserts `Y` is zero with BINIT in `solved_admittance` rather than `Y.imag == 50.0`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LP6eB1zx4eyE3hd7tpvSue
Oof I didn't notice that. @mcllerena any ideas on how to tell when we should use |
Parser half of the
SwitchedAdmittancechanges in Sienna-Platform/PowerSystems.jl#1774, following SiennaSchemas#44 (merged), which addedsolved_admittanceand renamedinitial_status→number_engaged.Important
CI on this PR will fail until PowerOpenAPIModels is regenerated.
PO.SwitchedAdmittanceonmainstill hasinitial_statusand nosolved_admittance, and the generatedunits.jlhas no unit declaration for the new field — so every OpenAPI-level test errors withSwitchedAdmittance.solved_admittance declares no unit. The pm_io-level tests pass regardless, since they never touch the generated models.That regeneration is currently blocked:
update-schema.ymlbegins withgh release view --repo Sienna-Platform/SiennaSchemas, SiennaSchemas has no releases or tags, and the job exits 1 immediately. Every scheduled run for the last several days iscompleted/failure, and.schema-versionstill holds a bare git SHA from a local run. Someone needs to cut a SiennaSchemas release for #44 to propagate. The same blocker holds PowerSystems.jl#1789.Verified locally against a hand-patched copy of the operations models carrying the regenerated struct plus the
units.jldeclaration codegen will emit from #44's annotations: full suite green, 0 failures.What was wrong
BINIT was parsed into
bs, whichshunt.jlwrites toY. A PSS/E switched shunt has no fixed base admittance — the SWITCHED SHUNT record carries only BINIT (the solved/initial total susceptance) and the per-block increments. Putting the solved total intoYforced everything downstream to disentangle the two again:ControlledSwitchedShunt.psse_convention);S1..S8are genuinely non-zero, the sentinel never matched, so the consumer added the engaged blocks on top of the total that already contained them.What changed
pm_io/psse.jlbs = 0.0; BINIT →sub_data["solved_admittance"]. v35S1..S8→number_engaged. Pre-v35 zero-fill kept, but its comment now says what it means — no per-block information — rather than every block out of service.pm_io/data.jl_make_per_unit!per-unitizessolved_admittancealongsidebs/y_increment. Without this the value reaches the component a factor ofbaseMVAtoo large.openapi/shunt.jl:number_engagedand:solved_admittance(MVAr, via the unit-convertingset_value!).openapi/device_base.jl("SwitchedAdmittance", :solved_admittance)as:skip.On the
:skipclassificationIt inherits the
admittance_unitsdiscriminator, which per that file's header is a representation switch (pu vs natural for the same field) rather than a natural-unit choice — and PSY's ownto_openapiscales it by the SYSTEM base in both document conventions. So it takes the same classification asY/Y_increase/admittance_limits, not a device-base conversion.Worth noting the registry is total by design: an unlisted instance-dispatched pair errors by construction rather than falling through. Omitting this entry surfaced as a loud failure instead of a silently mis-scaled admittance in
COMPONENT_BASEdocuments — the guard did its job.One decision worth a reviewer's eye
solved_admittanceis populated unconditionally, because a SWITCHED SHUNT record always carries BINIT (pti.jldefaults it to0.0). A parsed shunt therefore always has a solved admittance, and downstream reads it instead of summing blocks — which is what PSS/E does with the value. The alternative reading of the manual's "locked" clause is to gate onMODSW == 0. Consequence of the current choice: a case withBINIT = 0and in-service blocks yields zero susceptance rather than the block sum.Also note
number_engagedparsed from v35Siis a per-block status flag, not a step count, so the block-sum fallback under-counts any block with more than one step. It rarely matters because BINIT is always set and the exact branch wins.Tests
gs == bs == 0.0plus a per-unitizedsolved_admittance == 0.5for the fixture'sBINIT = 50on a 100 MVA base.Y == 0.0 + 0.0imwithsolved_admittance == 50.0MVAr, where it previously assertedY.imag == 50.0— the clearest single expression of the change.Related
SwitchedAdmittancestruct changes PowerSystems.jl#1774 — the issueY(follow-up to #1774) PowerSystems.jl#1788 — follow-up to remove/renameY🤖 Generated with Claude Code
https://claude.ai/code/session_01LP6eB1zx4eyE3hd7tpvSue