diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfBusImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfBusImpl.java index f4c972c173..cf18fb0a6b 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfBusImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfBusImpl.java @@ -6,10 +6,7 @@ */ package com.powsybl.openloadflow.network.impl; -import com.powsybl.iidm.network.Bus; -import com.powsybl.iidm.network.Country; -import com.powsybl.iidm.network.Load; -import com.powsybl.iidm.network.Substation; +import com.powsybl.iidm.network.*; import com.powsybl.iidm.network.extensions.LoadAsymmetrical; import com.powsybl.iidm.network.extensions.SlackTerminal; import com.powsybl.openloadflow.network.LfNetwork; @@ -43,6 +40,8 @@ public class LfBusImpl extends AbstractLfBus { private final Country country; + private List bbsIds = null; + protected LfBusImpl(Bus bus, LfNetwork network, double v, double angle, LfNetworkParameters parameters, boolean participating) { super(network, v, angle, parameters.isDistributedOnConformLoad()); @@ -53,6 +52,13 @@ protected LfBusImpl(Bus bus, LfNetwork network, double v, double angle, LfNetwor this.participating = participating; this.breakers = parameters.isBreakers(); country = bus.getVoltageLevel().getSubstation().flatMap(Substation::getCountry).orElse(null); + if (bus.getVoltageLevel().getTopologyKind() == TopologyKind.NODE_BREAKER) { + bbsIds = bus.getConnectedTerminalStream() + .map(Terminal::getConnectable) + .filter(BusbarSection.class::isInstance) + .map(Connectable::getId) + .collect(Collectors.toList()); + } } private static void createAsym(Bus bus, LfBusImpl lfBus) { @@ -142,7 +148,13 @@ public boolean isParticipating() { public List createBusResults() { var bus = getBus(); if (breakers) { - return List.of(new BusResult(getVoltageLevelId(), bus.getId(), v, Math.toDegrees(angle))); + if (bbsIds.isEmpty()) { + return List.of(new BusResult(getVoltageLevelId(), bus.getId(), v, Math.toDegrees(angle))); + } else { + return bbsIds.stream() + .map(bbsId -> new BusResult(getVoltageLevelId(), bbsId, v, Math.toDegrees(angle))) + .collect(Collectors.toList()); + } } else { return bus.getVoltageLevel().getBusBreakerView().getBusesFromBusViewBusId(bus.getId()) .stream().map(b -> new BusResult(getVoltageLevelId(), b.getId(), v, Math.toDegrees(angle))).collect(Collectors.toList()); diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index 4bb58fb9db..7077a8b118 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -93,7 +93,7 @@ void testCurrentLimitViolations() { assertSame(PostContingencyComputationStatus.CONVERGED, result.getPostContingencyResults().get(1).getStatus()); assertEquals(2, result.getPostContingencyResults().get(1).getLimitViolationsResult().getLimitViolations().size()); PostContingencyResult postContingencyResult = getPostContingencyResult(result, "LD"); - assertEquals(398.0, postContingencyResult.getNetworkResult().getBusResult("VL1_0").getV(), LoadFlowAssert.DELTA_V); + assertEquals(398.0, postContingencyResult.getNetworkResult().getBusResult("BBS2").getV(), LoadFlowAssert.DELTA_V); } @Test @@ -2169,4 +2169,29 @@ void testBusContingency() { assertEquals(0.0, getPostContingencyResult(result, "NHV2").getNetworkResult().getBranchResult("NGEN_NHV1").getI1(), LoadFlowAssert.DELTA_I); // No output for NGEN and NVH1 } + + @Test + void testBusBarSectionBusResults() { + var network = NodeBreakerNetworkFactory.create3barsAndJustOneVoltageLevel(); + List contingencies = List.of(new Contingency("C1", new SwitchContingency("C1")), + new Contingency("C2", new SwitchContingency("C2"))); + List monitors = createNetworkMonitors(network); + SecurityAnalysisParameters securityAnalysisParameters = new SecurityAnalysisParameters(); + OpenLoadFlowParameters openLoadFlowParameters = new OpenLoadFlowParameters(); + openLoadFlowParameters.setSlackBusSelectionMode(SlackBusSelectionMode.NAME).setSlackBusId("VL1_1"); + securityAnalysisParameters.getLoadFlowParameters().addExtension(OpenLoadFlowParameters.class, openLoadFlowParameters); + SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors, securityAnalysisParameters, Reporter.NO_OP); + assertEquals(3, result.getPreContingencyResult().getNetworkResult().getBusResults().size()); + PreContingencyResult preContingencyResult = result.getPreContingencyResult(); + assertEquals("BBS1", preContingencyResult.getNetworkResult().getBusResults().get(0).getBusId()); + assertEquals(400.0, preContingencyResult.getNetworkResult().getBusResult("BBS1").getV(), LoadFlowAssert.DELTA_V); + assertEquals("BBS2", preContingencyResult.getNetworkResult().getBusResults().get(1).getBusId()); + assertEquals(400.0, preContingencyResult.getNetworkResult().getBusResult("BBS2").getV(), LoadFlowAssert.DELTA_V); + assertEquals("BBS3", preContingencyResult.getNetworkResult().getBusResults().get(2).getBusId()); + assertEquals(400.0, preContingencyResult.getNetworkResult().getBusResult("BBS3").getV(), LoadFlowAssert.DELTA_V); + PostContingencyResult postContingencyResult = getPostContingencyResult(result, "C1"); + assertNull(postContingencyResult.getNetworkResult().getBusResult("BBS1")); + assertEquals(400.0, postContingencyResult.getNetworkResult().getBusResult("BBS2").getV(), LoadFlowAssert.DELTA_V); + assertEquals(400.0, postContingencyResult.getNetworkResult().getBusResult("BBS3").getV(), LoadFlowAssert.DELTA_V); + } }