From 78b4259ca5eb91d3a9a5c8e1eb5d3d6297088330 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Tue, 21 Feb 2023 16:44:29 +0100 Subject: [PATCH 1/5] Proposal. Signed-off-by: Anne Tilloy --- .../network/impl/HvdcConverterStations.java | 8 +++- .../openloadflow/ac/AcLoadFlowVscTest.java | 43 +++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/HvdcConverterStations.java b/src/main/java/com/powsybl/openloadflow/network/impl/HvdcConverterStations.java index 06caf65099..be87284935 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/HvdcConverterStations.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/HvdcConverterStations.java @@ -13,6 +13,7 @@ import com.powsybl.iidm.network.VscConverterStation; import java.util.Objects; +import java.util.Optional; /** * @author Geoffroy Jamgotchian @@ -57,7 +58,12 @@ public static double getConverterStationTargetP(HvdcConverterStation station) // If the converter station is at side 1 and is inverter, p should be negative. // If the converter station is at side 2 and is rectifier, p should be positive. // If the converter station is at side 2 and is inverter, p should be negative. - return getSign(station) * getAbsoluteValuePAc(station); + boolean disconnectedAtOtherSide = false; + Optional> otherConverterStation = station.getOtherConverterStation(); + if (otherConverterStation.isPresent()) { + disconnectedAtOtherSide = !otherConverterStation.get().getTerminal().isConnected(); + } + return disconnectedAtOtherSide ? 0.0 : getSign(station) * getAbsoluteValuePAc(station); } /** diff --git a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowVscTest.java b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowVscTest.java index cab38e4a0f..975773e415 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowVscTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/AcLoadFlowVscTest.java @@ -227,6 +227,49 @@ void testHvdcAcEmulationNonSupported2() { VscConverterStation cs4 = network.getVscConverterStation("cs4"); assertActivePowerEquals(2.0, cs4.getTerminal()); + } + @Test + void testHvdcDisconnectedAtOneSide() { + Network network = HvdcNetworkFactory.createVsc(); + network.getVscConverterStation("cs3").getTerminal().disconnect(); + LoadFlow.Runner loadFlowRunner = new LoadFlow.Runner(new OpenLoadFlowProvider(new DenseMatrixFactory())); + LoadFlowParameters parameters = new LoadFlowParameters() + .setUseReactiveLimits(false) + .setDistributedSlack(false); + OpenLoadFlowParameters.create(parameters) + .setSlackBusSelectionMode(SlackBusSelectionMode.MOST_MESHED); + LoadFlowResult result = loadFlowRunner.run(network, parameters); + assertTrue(result.isOk()); + + Bus bus1 = network.getBusView().getBus("vl1_0"); + assertVoltageEquals(390, bus1); + assertAngleEquals(0, bus1); + + Bus bus2 = network.getBusView().getBus("vl2_0"); + assertVoltageEquals(385, bus2); + assertAngleEquals(0.18116, bus2); + + Bus bus3 = network.getBusView().getBus("vl3_0"); + assertVoltageEquals(Double.NaN, bus3); + assertAngleEquals(Double.NaN, bus3); + + Generator g1 = network.getGenerator("g1"); + assertActivePowerEquals(-102.56, g1.getTerminal()); + assertReactivePowerEquals(-632.700, g1.getTerminal()); + + VscConverterStation cs2 = network.getVscConverterStation("cs2"); + assertActivePowerEquals(0.00, cs2.getTerminal()); + assertReactivePowerEquals(614.750, cs2.getTerminal()); + + VscConverterStation cs3 = network.getVscConverterStation("cs3"); + assertActivePowerEquals(Double.NaN, cs3.getTerminal()); + assertReactivePowerEquals(Double.NaN, cs3.getTerminal()); + + Line l12 = network.getLine("l12"); + assertActivePowerEquals(52.65, l12.getTerminal1()); + assertReactivePowerEquals(632.700, l12.getTerminal1()); + assertActivePowerEquals(-50.00, l12.getTerminal2()); + assertReactivePowerEquals(-624.750, l12.getTerminal2()); } } From 9716e2a915b8dcf3a8503e2607ec4fbf9d5fa294 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Tue, 21 Feb 2023 17:06:00 +0100 Subject: [PATCH 2/5] Improve. Signed-off-by: Anne Tilloy --- .../powsybl/openloadflow/OpenLoadFlowProvider.java | 9 +++++---- .../network/LfNetworkStateUpdateParameters.java | 10 +++++++++- .../openloadflow/network/impl/AbstractLfBus.java | 8 ++++---- .../network/impl/HvdcConverterStations.java | 14 ++++++-------- .../network/impl/LfVscConverterStationImpl.java | 2 +- .../network/impl/PropagatedContingency.java | 4 ++-- .../ac/NonImpedantBranchWithBreakerIssueTest.java | 4 ++-- 7 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowProvider.java b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowProvider.java index dc32013eef..32bf73812e 100644 --- a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowProvider.java +++ b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowProvider.java @@ -126,7 +126,7 @@ private LoadFlowResult runAc(Network network, LoadFlowParameters parameters, Rep parameters.isPhaseShifterRegulationOn(), parameters.isTransformerVoltageControlOn(), parameters.isDistributedSlack() && (parameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_LOAD || parameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD) && parametersExt.isLoadPowerFactorConstant(), - parameters.isDc()); + parameters.isDc(), acParameters.getNetworkParameters().isBreakers()); result.getNetwork().updateState(updateParameters); // zero or low impedance branch flows computation @@ -180,12 +180,12 @@ private LoadFlowResult runDc(Network network, LoadFlowParameters parameters, Rep Networks.resetState(network); - List componentsResult = results.stream().map(r -> processResult(network, r, parameters)).collect(Collectors.toList()); + List componentsResult = results.stream().map(r -> processResult(network, r, parameters, dcParameters.getNetworkParameters().isBreakers())).collect(Collectors.toList()); boolean ok = results.stream().anyMatch(DcLoadFlowResult::isSucceeded); return new LoadFlowResultImpl(ok, Collections.emptyMap(), null, componentsResult); } - private LoadFlowResult.ComponentResult processResult(Network network, DcLoadFlowResult result, LoadFlowParameters parameters) { + private LoadFlowResult.ComponentResult processResult(Network network, DcLoadFlowResult result, LoadFlowParameters parameters, boolean breakers) { if (result.isSucceeded() && parameters.isWriteSlackBus()) { SlackTerminal.reset(network); } @@ -196,7 +196,8 @@ private LoadFlowResult.ComponentResult processResult(Network network, DcLoadFlow parameters.isPhaseShifterRegulationOn(), parameters.isTransformerVoltageControlOn(), false, - true); + true, + breakers); result.getNetwork().updateState(updateParameters); // zero or low impedance branch flows computation diff --git a/src/main/java/com/powsybl/openloadflow/network/LfNetworkStateUpdateParameters.java b/src/main/java/com/powsybl/openloadflow/network/LfNetworkStateUpdateParameters.java index 2a0a66bda9..c0e1300112 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfNetworkStateUpdateParameters.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfNetworkStateUpdateParameters.java @@ -23,14 +23,18 @@ public class LfNetworkStateUpdateParameters { private final boolean dc; + private final boolean breakers; + public LfNetworkStateUpdateParameters(boolean reactiveLimits, boolean writeSlackBus, boolean phaseShifterRegulationOn, - boolean transformerVoltageControlOn, boolean loadPowerFactorConstant, boolean dc) { + boolean transformerVoltageControlOn, boolean loadPowerFactorConstant, boolean dc, + boolean breakers) { this.reactiveLimits = reactiveLimits; this.writeSlackBus = writeSlackBus; this.phaseShifterRegulationOn = phaseShifterRegulationOn; this.transformerVoltageControlOn = transformerVoltageControlOn; this.loadPowerFactorConstant = loadPowerFactorConstant; this.dc = dc; + this.breakers = breakers; } public boolean isReactiveLimits() { @@ -56,4 +60,8 @@ public boolean isLoadPowerFactorConstant() { public boolean isDc() { return dc; } + + public boolean isBreakers() { + return breakers; + } } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java index db94595a5a..2b426feb13 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/AbstractLfBus.java @@ -211,10 +211,10 @@ void addLoad(Load load, LfNetworkParameters parameters) { void addLccConverterStation(LccConverterStation lccCs, LfNetworkParameters parameters) { // note that LCC converter station are out of the slack distribution. lccCsRefs.add(Ref.create(lccCs, parameters.isCacheEnabled())); - double targetP = HvdcConverterStations.getConverterStationTargetP(lccCs); + double targetP = HvdcConverterStations.getConverterStationTargetP(lccCs, parameters.isBreakers()); loadTargetP += targetP; initialLoadTargetP += targetP; - loadTargetQ += HvdcConverterStations.getLccConverterStationLoadTargetQ(lccCs); + loadTargetQ += HvdcConverterStations.getLccConverterStationLoadTargetQ(lccCs, parameters.isBreakers()); } protected void add(LfGenerator generator) { @@ -477,8 +477,8 @@ public void updateState(LfNetworkStateUpdateParameters parameters) { // update lcc converter station power for (Ref lccCsRef : lccCsRefs) { LccConverterStation lccCs = lccCsRef.get(); - double pCs = HvdcConverterStations.getConverterStationTargetP(lccCs); // A LCC station has active losses. - double qCs = HvdcConverterStations.getLccConverterStationLoadTargetQ(lccCs); // A LCC station always consumes reactive power. + double pCs = HvdcConverterStations.getConverterStationTargetP(lccCs, parameters.isBreakers()); // A LCC station has active losses. + double qCs = HvdcConverterStations.getLccConverterStationLoadTargetQ(lccCs, parameters.isBreakers()); // A LCC station always consumes reactive power. lccCs.getTerminal() .setP(pCs) .setQ(qCs); diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/HvdcConverterStations.java b/src/main/java/com/powsybl/openloadflow/network/impl/HvdcConverterStations.java index be87284935..e04444dc47 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/HvdcConverterStations.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/HvdcConverterStations.java @@ -7,10 +7,7 @@ package com.powsybl.openloadflow.network.impl; import com.powsybl.commons.PowsyblException; -import com.powsybl.iidm.network.HvdcConverterStation; -import com.powsybl.iidm.network.HvdcLine; -import com.powsybl.iidm.network.LccConverterStation; -import com.powsybl.iidm.network.VscConverterStation; +import com.powsybl.iidm.network.*; import java.util.Objects; import java.util.Optional; @@ -47,7 +44,7 @@ public static double getSign(HvdcConverterStation station) { /** * Gets targetP of an VSC converter station or load target P for a LCC converter station. */ - public static double getConverterStationTargetP(HvdcConverterStation station) { + public static double getConverterStationTargetP(HvdcConverterStation station, boolean breakers) { // For a VSC converter station, we are in generator convention. // If the converter station is at side 1 and is rectifier, targetP should be negative. // If the converter station is at side 1 and is inverter, targetP should be positive. @@ -61,7 +58,8 @@ public static double getConverterStationTargetP(HvdcConverterStation station) boolean disconnectedAtOtherSide = false; Optional> otherConverterStation = station.getOtherConverterStation(); if (otherConverterStation.isPresent()) { - disconnectedAtOtherSide = !otherConverterStation.get().getTerminal().isConnected(); + Bus bus = Networks.getBus(otherConverterStation.get().getTerminal(), breakers); + disconnectedAtOtherSide = bus == null; } return disconnectedAtOtherSide ? 0.0 : getSign(station) * getAbsoluteValuePAc(station); } @@ -69,13 +67,13 @@ public static double getConverterStationTargetP(HvdcConverterStation station) /** * Gets reactive power for an LCC converter station. */ - public static double getLccConverterStationLoadTargetQ(LccConverterStation lccCs) { + public static double getLccConverterStationLoadTargetQ(LccConverterStation lccCs, boolean breakers) { // Load convention. // If the converter station is at side 1 and is rectifier, p should be positive. // If the converter station is at side 1 and is inverter, p should be negative. // If the converter station is at side 2 and is rectifier, p should be positive. // If the converter station is at side 2 and is inverter, p should be negative. - double pCs = getConverterStationTargetP(lccCs); + double pCs = getConverterStationTargetP(lccCs, breakers); return Math.abs(pCs * Math.tan(Math.acos(lccCs.getPowerFactor()))); // A LCC station always consumes reactive power. } diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/LfVscConverterStationImpl.java b/src/main/java/com/powsybl/openloadflow/network/impl/LfVscConverterStationImpl.java index b625742729..5068549d25 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/LfVscConverterStationImpl.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/LfVscConverterStationImpl.java @@ -29,7 +29,7 @@ public class LfVscConverterStationImpl extends AbstractLfGenerator implements Lf private LfHvdc hvdc; // set only when AC emulation is activated public LfVscConverterStationImpl(VscConverterStation station, LfNetwork network, LfNetworkParameters parameters, LfNetworkLoadingReport report) { - super(network, HvdcConverterStations.getConverterStationTargetP(station)); + super(network, HvdcConverterStations.getConverterStationTargetP(station, parameters.isBreakers())); this.stationRef = Ref.create(station, parameters.isCacheEnabled()); this.lossFactor = station.getLossFactor(); diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/PropagatedContingency.java b/src/main/java/com/powsybl/openloadflow/network/impl/PropagatedContingency.java index 32a85bf325..c7e9c769cf 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/PropagatedContingency.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/PropagatedContingency.java @@ -181,8 +181,8 @@ private void complete(boolean shuntCompensatorVoltageControlOn, boolean slackDis generatorIdsToLose.add(connectable.getId()); } else { LccConverterStation lcc = (LccConverterStation) connectable; - PowerShift lccPowerShift = new PowerShift(HvdcConverterStations.getConverterStationTargetP(lcc) / PerUnit.SB, 0, - HvdcConverterStations.getLccConverterStationLoadTargetQ(lcc) / PerUnit.SB); + PowerShift lccPowerShift = new PowerShift(HvdcConverterStations.getConverterStationTargetP(lcc, breakers) / PerUnit.SB, 0, + HvdcConverterStations.getLccConverterStationLoadTargetQ(lcc, breakers) / PerUnit.SB); originalPowerShiftIds.add(lcc.getId()); addPowerShift(lcc.getTerminal(), busIdsToShift, lccPowerShift, breakers); } diff --git a/src/test/java/com/powsybl/openloadflow/ac/NonImpedantBranchWithBreakerIssueTest.java b/src/test/java/com/powsybl/openloadflow/ac/NonImpedantBranchWithBreakerIssueTest.java index 5d4c479e06..7bc93dfbda 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/NonImpedantBranchWithBreakerIssueTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/NonImpedantBranchWithBreakerIssueTest.java @@ -45,7 +45,7 @@ void busBreakerAndNonImpedantBranchIssue() { new AcloadFlowEngine(context) .run(); } - lfNetwork.updateState(new LfNetworkStateUpdateParameters(false, false, false, false, false, false)); + lfNetwork.updateState(new LfNetworkStateUpdateParameters(false, false, false, false, false, false, false)); for (Bus bus : network.getBusView().getBuses()) { assertEquals(400, bus.getV(), 0); assertEquals(0, bus.getAngle(), 0); @@ -68,7 +68,7 @@ void busBreakerAndNonImpedantBranchIssueRef() { new AcloadFlowEngine(context) .run(); } - lfNetwork.updateState(new LfNetworkStateUpdateParameters(false, false, false, false, false, false)); + lfNetwork.updateState(new LfNetworkStateUpdateParameters(false, false, false, false, false, false, false)); assertEquals(-100, network.getGenerator("G1").getTerminal().getQ(), 0); assertEquals(-100, network.getGenerator("G2").getTerminal().getQ(), 0); } From f6c03616686432a2c6f775abeeea127e1a9e6ff4 Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Tue, 21 Feb 2023 17:22:14 +0100 Subject: [PATCH 3/5] Clean Signed-off-by: Geoffroy Jamgotchian --- .../network/impl/HvdcConverterStations.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/HvdcConverterStations.java b/src/main/java/com/powsybl/openloadflow/network/impl/HvdcConverterStations.java index e04444dc47..164374ff22 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/HvdcConverterStations.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/HvdcConverterStations.java @@ -10,7 +10,6 @@ import com.powsybl.iidm.network.*; import java.util.Objects; -import java.util.Optional; /** * @author Geoffroy Jamgotchian @@ -55,12 +54,10 @@ public static double getConverterStationTargetP(HvdcConverterStation station, // If the converter station is at side 1 and is inverter, p should be negative. // If the converter station is at side 2 and is rectifier, p should be positive. // If the converter station is at side 2 and is inverter, p should be negative. - boolean disconnectedAtOtherSide = false; - Optional> otherConverterStation = station.getOtherConverterStation(); - if (otherConverterStation.isPresent()) { - Bus bus = Networks.getBus(otherConverterStation.get().getTerminal(), breakers); - disconnectedAtOtherSide = bus == null; - } + boolean disconnectedAtOtherSide = station.getOtherConverterStation().map(otherConverterStation -> { + Bus bus = Networks.getBus(otherConverterStation.getTerminal(), breakers); + return bus == null; + }).orElse(false); return disconnectedAtOtherSide ? 0.0 : getSign(station) * getAbsoluteValuePAc(station); } From 39f5a425eca2744ef081453f2b2996340d73c61d Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Tue, 21 Feb 2023 17:24:41 +0100 Subject: [PATCH 4/5] Clean Signed-off-by: Geoffroy Jamgotchian --- .../java/com/powsybl/openloadflow/OpenLoadFlowProvider.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowProvider.java b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowProvider.java index 32bf73812e..467879c8cd 100644 --- a/src/main/java/com/powsybl/openloadflow/OpenLoadFlowProvider.java +++ b/src/main/java/com/powsybl/openloadflow/OpenLoadFlowProvider.java @@ -126,7 +126,8 @@ private LoadFlowResult runAc(Network network, LoadFlowParameters parameters, Rep parameters.isPhaseShifterRegulationOn(), parameters.isTransformerVoltageControlOn(), parameters.isDistributedSlack() && (parameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_LOAD || parameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD) && parametersExt.isLoadPowerFactorConstant(), - parameters.isDc(), acParameters.getNetworkParameters().isBreakers()); + parameters.isDc(), + acParameters.getNetworkParameters().isBreakers()); result.getNetwork().updateState(updateParameters); // zero or low impedance branch flows computation From 571a80e22452b81f8cb41d2772f0b1b891352a02 Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Wed, 22 Feb 2023 09:51:51 +0100 Subject: [PATCH 5/5] Fix Signed-off-by: Geoffroy Jamgotchian --- .../openloadflow/network/impl/HvdcConverterStations.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/HvdcConverterStations.java b/src/main/java/com/powsybl/openloadflow/network/impl/HvdcConverterStations.java index 164374ff22..8928929171 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/HvdcConverterStations.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/HvdcConverterStations.java @@ -57,7 +57,7 @@ public static double getConverterStationTargetP(HvdcConverterStation station, boolean disconnectedAtOtherSide = station.getOtherConverterStation().map(otherConverterStation -> { Bus bus = Networks.getBus(otherConverterStation.getTerminal(), breakers); return bus == null; - }).orElse(false); + }).orElse(true); // it means there is no HVDC line connected to station return disconnectedAtOtherSide ? 0.0 : getSign(station) * getAbsoluteValuePAc(station); }