2W transformer `rating`/`rating_b`/`rating_c`/flows scaled by winding base instead of system base when `SBASE1-2 ≠ SBASE`

Cerrado
#74 0 comentarios 0 reacciones 1 asignado Ver en GitHub

Los mantenedores suelen responder en 6 días

@luke-kiernan ya está trabajando en esto.

Desde el 14/10/2026.

  • #75 de @luke-kiernan — fusionado

Evaluación

Este issue todavía no se ha evaluado.

Descripción

Summary

For PSS/E 2-winding transformers whose winding base (SBASE1-2) differs from the system base, the OpenAPI reader produces ratings and initial flows scaled by SBASE1-2 / SBASE. Impedances are correct.

Reproducer

A 100 MVA system with three 2W transformers, each with RATA1 = RATB1 = RATC1 = 55 MVA and impedances given on the system base (CZ = 1), differing only in SBASE1-2 (.raw below):

import PowerSystems as PSY
import PowerFlowFileParser as PFP
import PowerSystemCaseBuilder: system_from_openapi
using PowerSystems.Unitful: @u_str
using InfrastructureSystems.PerUnit

sys = system_from_openapi(PFP.PowerModelsData("transformer_rating_base.raw"); runchecks = false)
for t in PSY.get_components(PSY.TwoWindingTransformer, sys)
    c = PSY.get_circuit(t)
    println(PSY.get_name(t), "  rating = ", PSY.get_rating(c, u"MW"), " MW  x = ", PSY.get_x(c, u"SU"))
end
transformer SBASE1-2 rating (MW) expected x (SU)
XFMR_SB50 50 27.5 55 0.2 ✓
XFMR_SB100 100 55.0 55 0.2 ✓
XFMR_SB200 200 110.0 55 0.2 ✓

(Run against the in-development psy6 branches of PowerSystems.jl and PowerFlowFileParser.jl; their Project.toml versions, 5.10.0 and 0.3.0, have not been bumped yet. The bug is in PFP, so it does not depend on the PSY version.)

transformer_rating_base.raw
0,   100.00, 33, 0, 1, 60.00     / PSS(R)E 33 RAW
TRANSFORMER RATING BASE REPRODUCER
THREE 2W TRANSFORMERS, ALL RATA1 = 55 MVA, SBASE1-2 = 50 / 100 / 200 MVA
     1,'HV138       ', 138.0000,3,   1,   1,   1,1.00000,   0.0000,1.10000,0.90000,1.10000,0.90000
     2,'LV50        ',  13.8000,1,   1,   1,   1,1.00000,   0.0000,1.10000,0.90000,1.10000,0.90000
     3,'LV100       ',  13.8000,1,   1,   1,   1,1.00000,   0.0000,1.10000,0.90000,1.10000,0.90000
     4,'LV200       ',  13.8000,1,   1,   1,   1,1.00000,   0.0000,1.10000,0.90000,1.10000,0.90000
0 / END OF BUS DATA, BEGIN LOAD DATA
     2,'1 ',1,   1,   1,    20.000,     5.000,     0.000,     0.000,     0.000,     0.000,   1,1,0
     3,'1 ',1,   1,   1,    20.000,     5.000,     0.000,     0.000,     0.000,     0.000,   1,1,0
     4,'1 ',1,   1,   1,    20.000,     5.000,     0.000,     0.000,     0.000,     0.000,   1,1,0
0 / END OF LOAD DATA, BEGIN FIXED SHUNT DATA
0 / END OF FIXED SHUNT DATA, BEGIN GENERATOR DATA
     1,'1 ',    60.000,    15.000,   100.000,  -100.000,1.00000,     0,   200.000, 0.00000E+0, 1.00000E+0, 0.00000E+0, 0.00000E+0,1.00000,1,  100.0,   200.000,     0.000,   1,1.0000
0 / END OF GENERATOR DATA, BEGIN BRANCH DATA
0 / END OF BRANCH DATA, BEGIN TRANSFORMER DATA
     1,     2,     0,'1 ',1,1,1, 0.00000E+0, 0.00000E+0,2,'XFMR_SB50   ',1,   1,1.0000,   0,1.0000,   0,1.0000,   0,1.0000,'            '
 1.00000E-2, 2.00000E-1,    50.00
1.00000,   0.000,   0.000,    55.00,    55.00,    55.00, 0,      0, 1.10000, 0.90000, 1.10000, 0.90000,  33, 0, 0.00000, 0.00000,  0.000
1.00000,   0.000
     1,     3,     0,'1 ',1,1,1, 0.00000E+0, 0.00000E+0,2,'XFMR_SB100  ',1,   1,1.0000,   0,1.0000,   0,1.0000,   0,1.0000,'            '
 1.00000E-2, 2.00000E-1,   100.00
1.00000,   0.000,   0.000,    55.00,    55.00,    55.00, 0,      0, 1.10000, 0.90000, 1.10000, 0.90000,  33, 0, 0.00000, 0.00000,  0.000
1.00000,   0.000
     1,     4,     0,'1 ',1,1,1, 0.00000E+0, 0.00000E+0,2,'XFMR_SB200  ',1,   1,1.0000,   0,1.0000,   0,1.0000,   0,1.0000,'            '
 1.00000E-2, 2.00000E-1,   200.00
1.00000,   0.000,   0.000,    55.00,    55.00,    55.00, 0,      0, 1.10000, 0.90000, 1.10000, 0.90000,  33, 0, 0.00000, 0.00000,  0.000
1.00000,   0.000
0 / END OF TRANSFORMER DATA, BEGIN AREA DATA
   1,     1,     0.000,    10.000,'AREA1       '
0 / END OF AREA DATA, BEGIN TWO-TERMINAL DC DATA
0 / END OF TWO-TERMINAL DC DATA, BEGIN VSC DC LINE DATA
0 / END OF VSC DC LINE DATA, BEGIN IMPEDANCE CORRECTION DATA
0 / END OF IMPEDANCE CORRECTION DATA, BEGIN MULTI-TERMINAL DC DATA
0 / END OF MULTI-TERMINAL DC DATA, BEGIN MULTI-SECTION LINE DATA
0 / END OF MULTI-SECTION LINE DATA, BEGIN ZONE DATA
   1,'ZONE1       '
0 / END OF ZONE DATA, BEGIN INTER-AREA TRANSFER DATA
0 / END OF INTER-AREA TRANSFER DATA, BEGIN OWNER DATA
   1,'OWNER1      '
0 / END OF OWNER DATA, BEGIN FACTS DEVICE DATA
0 / END OF FACTS DEVICE DATA, BEGIN SWITCHED SHUNT DATA
0 / END OF SWITCHED SHUNT DATA, BEGIN GNE DATA
0 / END OF GNE DATA, BEGIN INDUCTION MACHINE DATA
0 / END OF INDUCTION MACHINE DATA
Q

Root cause

The header comment in src/openapi/branch.jl (lines 8–18) already describes it:

  1. _make_per_unit! divides rate_a/rate_b/rate_c/pf/qf by baseMVA, which puts them in system-base pu (pm_io/data.jl:403, :415).
  2. psse.jl rebases br_r/br_x/g_fr/b_fr onto the winding base, d["base_power"], which puts them in device-base pu.
  3. The 2W builder converts everything back with the device base:
    rating = _natural_value(rate_a, base_power),            # branch.jl:435-437, same for rate_b/rate_c
    active_power_flow = get(d, "pf", 0.0) * base_power,     # branch.jl:442-443
    
    Impedances are correct because they really are device-base. Ratings and flows are system-base, so they pick up a stray base_power / sys_mbase factor.

Lines don't show the bug because their base_power == baseMVA. The 3W path doesn't either, because its ratings come straight from the raw MVA fields and skip _make_per_unit!.

Why it wasn't caught

The header comment says the behavior was deliberately ported from the old PSCB converter (the "oracle") for parity: "this reader reproduces exactly that." It also notes that every fixture on hand, and all MATPOWER input, has winding base equal to system base, "so no real fixture can distinguish them." So parity tests pass by construction, and the bug only appears on real PSS/E cases with non-default SBASE1-2.

Proposed fix

  • In the 2W builder, convert rate_a/rate_b/rate_c/pf/qf with sys_mbase, as the line builder does (branch.jl:326-330).
  • Rewrite the header comment so it records the correct convention instead of defending the inherited one.
  • Add the reproducer above as a regression fixture, since no existing fixture has SBASE1-2 ≠ SBASE.
  • Decide whether the PSCB oracle should be fixed too, or whether the parity test should stop treating this field as ground truth.
  • Worth a look: dc_branch.jl:443 notes a similar oracle scaling quirk ("multiplies an already-natural number by sys_mbase") that may be the same kind of copied bug.

The pf/qf part is inferred from the code; the reproducer only checks ratings.

🤖 Generated with Claude Code

Lenguaje dominante
Julia
Estrellas
1
Forks
3
Merge medio
7 d 8 h
PR fusionados (30 d)
9

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de Sienna-Platform/PowerFlowFileParser.jl

Todos los issues de Sienna-Platform/PowerFlowFileParser.jl

Issues similares

Más issues de Julia

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.