Believe BINIT only where PSS/E would not have moved it - #59
Open
luke-kiernan wants to merge 2 commits into
Open
luke-kiernan wants to merge 2 commits into
luke-kiernan wants to merge 2 commits into
Conversation
Closes #57. A v35 SWITCHED SHUNT block carries a status Si, not a step count, so block i contributes Si * Ni * Bi. `number_engaged` counts engaged steps and was being filled with the bare status, understating every multi-step block by a factor of Ni. BINIT is the device's actual admittance only where PSS/E would not have adjusted the shunt itself: locked (MODSW 0), on a type 3 bus, continuously controlled (MODSW 2, whose admittance is off the step ladder and cannot be reconstructed from block statuses at all), or read from a version with no Si column. For a discretely adjusted shunt (MODSW 1/3/4/5) on a type 1/2 bus, BINIT is only where PSS/E's own solution started, and the engaged blocks are what the record asserts; `solved_admittance` is then left off and PowerFlows falls through to `number_engaged .* Y_increase`. A new `solved_case` keyword on `parse_file`/`PowerModelsData` declares a RAW written out after a converged power flow, restoring BINIT everywhere. `_switched_shunt_blocks` replaces `_is_switched_shunt_block` and reads the blocks as the POM defines them -- a contiguous run from block 1, ended by the first zero Ni or Bi -- rather than filtering zeros out of all eight columns independently. The two agree on every well-formed record; they differ only on one with a gap, which the run now reads as PSS/E does. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
luke-kiernan
requested review from
jd-lara and
mcllerena
and
a lite review from Copilot
September 15, 2026 17:01
There was a problem hiding this comment.
🟡 Changes recommended
Moderate findings remain on node-breaker source-bus handling and v35 remote-mode coverage, with one comment nit also outstanding.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Updates PSS/E v35 switched-shunt parsing for status semantics, BINIT handling, and block termination.
Changes:
- Corrects engaged-step reconstruction and contiguous block parsing.
- Adds conditional BINIT handling and
solved_casepropagation. - Adds regression fixtures and parser tests.
File summaries
| File | Summary |
|---|---|
test/test_parse_psse.jl |
Adds v35 switched-shunt regression coverage. |
test/fixtures/v35_switched_shunt.raw |
Provides cases for BINIT branches, termination, and solved_case. |
src/power_models_data.jl |
Exposes the solved_case option. |
src/pm_io/psse.jl |
Implements switched-shunt logic. Findings: moderate (3 votes) source-bus type handling; moderate (1 vote) v35 remote-mode coverage; nit (2 votes) malformed comment. |
src/pm_io/common.jl |
Threads solved_case through parsing. |
Review details
Suppressed comments (1)
src/pm_io/psse.jl:853
- The new v35 behavior depends on all four discrete modes in this tuple, but the fixture only exercises v35
MODSW=1; the existingMODSW=3test is pre-v35, wherehas_block_statusshort-circuits the decision and cannot validate this membership. Please add v35 cases for the remote discrete modes (at least 3, with 4/5 if supported) so a mode-specific regression cannot silently restore BINIT.
const _DISCRETE_SWITCHED_SHUNT_MODES = (1, 3, 4, 5)
- Files reviewed: 5/5 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
In a node-breaker case `_nb_target` routes a switched shunt onto an injected node-bus, which `_prepare_node_breaker!` initializes to PQ; only `_migrate_node_breaker_gen_bus_type!` promotes one back to PV/REF, and that runs after this section. Reading the type off `shunt_bus` therefore dropped BINIT for a shunt declared on the swing bus. PSS/E's rule is about the RAW's own bus I, so it now reads `bus_number`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #57.
Siis a status, not a step countA v35
SWITCHED SHUNTblock carries a statusSi— in service or out — so blockicontributesSi * Ni * Bi.number_engagedcounts engaged steps, and was being filled with the bare status, understating every multi-step block by a factor ofNi. An in-service block now engages allNiof its steps; the RAW has no way to say a v35 block is partly in.BINIT is believed only where PSS/E would not have moved it
BINITis the device's actual admittance only where PSS/E would not have adjusted the shunt itself:MODSW == 0MODSWsaysMODSW == 2Sicolumn (pre-v35)solved_case = trueOtherwise — a discretely adjusted shunt (
MODSW1/3/4/5) on a type 1/2 bus —BINITis only where PSS/E's own solution started, while the engaged blocks are what the record asserts about the device.solved_admittanceis then left off entirely, and PowerFlows.jl falls through tonumber_engaged .* Y_increase;_apply_func!and the OpenAPI reader are both alreadyhaskey-guarded, so the absent key needs no other handling.solved_case(defaultfalse) is threaded throughparse_file→parse_psse→_pti_to_powermodels!, and is available as aPowerModelsDatakeyword.Only v35 cases change behaviour. Pre-v35 records keep
BINITunconditionally and keep their zero-fillednumber_engaged.Block reading follows the POM's terminator
_switched_shunt_blocksreplaces_is_switched_shunt_block. The v36 DataFormats manual: "Number of steps for block i (1 through 8). The first zero value of Ni or Bi is interpreted as the end of the switched shunt blocks for bus I." The blocks are a contiguous run from block 1 ended by that terminator, so they are now read as one rather than by filtering zeros out of all eightNiandBicolumns independently.The two agree on every well-formed record. They differ only on a record with a gap (
N2 = 0alongside a nonzeroB3), which the run now reads the way PSS/E does — one block — instead of promoting the columns past the terminator to blocks of their own.Testing
New fixture
test/fixtures/v35_switched_shunt.rawcovers each branch: adjusted, locked, continuous, swing-bus, the terminator, andsolved_case = true.774/774 PSS/E parse tests pass (19 new), formatter clean.
test/Manifest.tomlpointed at a deleted path, and re-resolving fails onOpenAPI—PowerCoreOpenAPIModelsrequires 1.1.x while this branch's compat pins 0.2. That is what #58 fixes; these tests were run against the root project instead. Nothing here touchessrc/openapi/, so #58 and this PR should not conflict.Related, not fixed here
PowerFlows.jl's v35 exporter has the mirror image of the
Sibug:_build_switched_shunt_steps_v35writesS_i = engaged[i], pushing a step count into a field PSS/E reads as a 0/1 status. Round-trippingnumber_engaged = [3, 0]emitsS1 = 3.🤖 Generated with Claude Code