diff --git a/src/main/java/com/powsybl/openloadflow/dc/DcTargetVector.java b/src/main/java/com/powsybl/openloadflow/dc/DcTargetVector.java index ede1d1f8a7..c5bde4bdc8 100644 --- a/src/main/java/com/powsybl/openloadflow/dc/DcTargetVector.java +++ b/src/main/java/com/powsybl/openloadflow/dc/DcTargetVector.java @@ -27,6 +27,7 @@ public static void init(Equation equation, LfNet break; case BUS_TARGET_PHI: + case DUMMY_TARGET_P: targets[equation.getColumn()] = 0; break; diff --git a/src/main/java/com/powsybl/openloadflow/dc/equations/DcEquationSystem.java b/src/main/java/com/powsybl/openloadflow/dc/equations/DcEquationSystem.java index fee553af74..fbb28acafd 100644 --- a/src/main/java/com/powsybl/openloadflow/dc/equations/DcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/dc/equations/DcEquationSystem.java @@ -31,10 +31,10 @@ private DcEquationSystem() { private static void createBuses(LfNetwork network, EquationSystem equationSystem) { for (LfBus bus : network.getBuses()) { - var p = equationSystem.createEquation(bus.getNum(), DcEquationType.BUS_TARGET_P); + var p = equationSystem.createEquation(bus, DcEquationType.BUS_TARGET_P); bus.setP(p); if (bus.isSlack()) { - equationSystem.createEquation(bus.getNum(), DcEquationType.BUS_TARGET_PHI) + equationSystem.createEquation(bus, DcEquationType.BUS_TARGET_PHI) .addTerm(equationSystem.getVariable(bus.getNum(), DcVariableType.BUS_PHI).createTerm()); p.setActive(false); } @@ -48,22 +48,27 @@ public static void createNonImpedantBranch(EquationSystemcreateTerm() .minus()); // add a dummy active power variable to both sides of the non impedant branch and with an opposite sign // to ensure we have the same number of equation and variables + var dummyP = equationSystem.getVariable(branch.getNum(), DcVariableType.DUMMY_P); equationSystem.getEquation(bus1.getNum(), DcEquationType.BUS_TARGET_P) .orElseThrow() - .addTerm(equationSystem.getVariable(branch.getNum(), DcVariableType.DUMMY_P) - .createTerm()); + .addTerm(dummyP.createTerm()); equationSystem.getEquation(bus2.getNum(), DcEquationType.BUS_TARGET_P) .orElseThrow() - .addTerm(equationSystem.getVariable(branch.getNum(), DcVariableType.DUMMY_P).createTerm() - .minus()); + .addTerm(dummyP.createTerm().minus()); + + // create an inactive dummy active power target equation set to zero that could be activated + // on case of switch opening + equationSystem.createEquation(branch, DcEquationType.DUMMY_TARGET_P) + .addTerm(dummyP.createTerm()) + .setActive(branch.isDisabled()); // inverted logic } else { throw new IllegalStateException("Cannot happen because only there is one slack bus per model"); } @@ -88,7 +93,7 @@ private static void createImpedantBranch(EquationSystem a1 = equationSystem.getVariable(branch.getNum(), DcVariableType.BRANCH_ALPHA1) .createTerm(); branch.setA1(a1); - equationSystem.createEquation(branch.getNum(), DcEquationType.BRANCH_TARGET_ALPHA1) + equationSystem.createEquation(branch, DcEquationType.BRANCH_TARGET_ALPHA1) .addTerm(a1); } else { //TODO diff --git a/src/main/java/com/powsybl/openloadflow/dc/equations/DcEquationType.java b/src/main/java/com/powsybl/openloadflow/dc/equations/DcEquationType.java index f69dc8a585..1536fcbc4a 100644 --- a/src/main/java/com/powsybl/openloadflow/dc/equations/DcEquationType.java +++ b/src/main/java/com/powsybl/openloadflow/dc/equations/DcEquationType.java @@ -16,7 +16,8 @@ public enum DcEquationType implements Quantity { BUS_TARGET_P("bus_target_p", ElementType.BUS), // bus active power target BUS_TARGET_PHI("bus_target_\u03C6", ElementType.BUS), // slack bus voltage angle target BRANCH_TARGET_ALPHA1("branch_target_\u03B1", ElementType.BRANCH), // phase shifter constant shift - ZERO_PHI("zero_\u03C6", ElementType.BRANCH); // zero impedance branch, voltage angle equality + ZERO_PHI("zero_\u03C6", ElementType.BRANCH), // zero impedance branch, voltage angle equality + DUMMY_TARGET_P("dummy_target_p", ElementType.BRANCH); private final String symbol; diff --git a/src/test/java/com/powsybl/openloadflow/ac/NonImpedantBranchDisablingTest.java b/src/test/java/com/powsybl/openloadflow/ac/NonImpedantBranchDisablingTest.java index 16d7ca2b96..58a467bac4 100644 --- a/src/test/java/com/powsybl/openloadflow/ac/NonImpedantBranchDisablingTest.java +++ b/src/test/java/com/powsybl/openloadflow/ac/NonImpedantBranchDisablingTest.java @@ -6,7 +6,9 @@ */ package com.powsybl.openloadflow.ac; +import com.powsybl.commons.reporter.Reporter; import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.Switch; import com.powsybl.loadflow.LoadFlow; import com.powsybl.loadflow.LoadFlowParameters; import com.powsybl.math.matrix.DenseMatrixFactory; @@ -15,13 +17,20 @@ import com.powsybl.openloadflow.ac.outerloop.AcLoadFlowParameters; import com.powsybl.openloadflow.ac.outerloop.AcloadFlowEngine; import com.powsybl.openloadflow.graph.EvenShiloachGraphDecrementalConnectivityFactory; -import com.powsybl.openloadflow.network.LfNetwork; -import com.powsybl.openloadflow.network.NameSlackBusSelector; -import com.powsybl.openloadflow.network.NodeBreakerNetworkFactory; +import com.powsybl.openloadflow.graph.NaiveGraphConnectivityFactory; +import com.powsybl.openloadflow.network.*; +import com.powsybl.openloadflow.network.impl.LfNetworkList; import com.powsybl.openloadflow.network.impl.LfNetworkLoaderImpl; +import com.powsybl.openloadflow.network.impl.Networks; import com.powsybl.openloadflow.util.LoadFlowAssert; +import com.powsybl.openloadflow.util.PerUnit; import org.junit.jupiter.api.Test; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +import static com.powsybl.openloadflow.util.LoadFlowAssert.assertActivePowerEquals; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -78,4 +87,41 @@ void testOpenBranch() { assertEquals(-600.0, network.getLine("L2").getTerminal2().getP(), LoadFlowAssert.DELTA_POWER); assertEquals(Double.NaN, network.getLine("L1").getTerminal2().getP(), LoadFlowAssert.DELTA_POWER); } + + @Test + void testDisabledNonImpedantBranch() { + Network network = NodeBreakerNetworkFactory.create3Bars(); + Switch c1 = network.getSwitch("C1"); + c1.setOpen(true); + + LoadFlowParameters parameters = new LoadFlowParameters(); + OpenLoadFlowParameters olfParameters = OpenLoadFlowParameters.create(parameters) + .setSlackBusSelectionMode(SlackBusSelectionMode.NAME) + .setSlackBusesIds(List.of("VL2_0")); + + LoadFlow.run(network, parameters); + + assertActivePowerEquals(401.757, network.getLine("L1").getTerminal1()); + assertActivePowerEquals(100.878, network.getLine("L2").getTerminal1()); + assertActivePowerEquals(100.878, network.getLine("L3").getTerminal1()); + + AcLoadFlowParameters acLoadFlowParameters + = OpenLoadFlowParameters.createAcParameters(network, + parameters, olfParameters, + new DenseMatrixFactory(), + new NaiveGraphConnectivityFactory<>(LfElement::getNum), + true, + false); + try (LfNetworkList lfNetworks = Networks.load(network, acLoadFlowParameters.getNetworkParameters(), Collections.emptySet(), Set.of(c1), Reporter.NO_OP)) { + LfNetwork largestNetwork = lfNetworks.getLargest().orElseThrow(); + largestNetwork.getBranchById("C1").setDisabled(true); + try (AcLoadFlowContext context = new AcLoadFlowContext(largestNetwork, acLoadFlowParameters)) { + new AcloadFlowEngine(context).run(); + } + // should be the same as with previous LF + assertEquals(401.740, largestNetwork.getBranchById("L1").getP1().eval() * PerUnit.SB, LoadFlowAssert.DELTA_POWER); + assertEquals(100.870, largestNetwork.getBranchById("L2").getP1().eval() * PerUnit.SB, LoadFlowAssert.DELTA_POWER); + assertEquals(100.870, largestNetwork.getBranchById("L3").getP1().eval() * PerUnit.SB, LoadFlowAssert.DELTA_POWER); + } + } } diff --git a/src/test/java/com/powsybl/openloadflow/dc/DcLoadFlowTest.java b/src/test/java/com/powsybl/openloadflow/dc/DcLoadFlowTest.java index b1aeb73aa8..6f77bb1e3b 100644 --- a/src/test/java/com/powsybl/openloadflow/dc/DcLoadFlowTest.java +++ b/src/test/java/com/powsybl/openloadflow/dc/DcLoadFlowTest.java @@ -6,9 +6,11 @@ */ package com.powsybl.openloadflow.dc; +import com.powsybl.commons.reporter.Reporter; import com.powsybl.ieeecdf.converter.IeeeCdfNetworkFactory; import com.powsybl.iidm.network.Line; import com.powsybl.iidm.network.Network; +import com.powsybl.iidm.network.Switch; import com.powsybl.iidm.network.TwoWindingsTransformer; import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; import com.powsybl.iidm.network.test.PhaseShifterTestCaseFactory; @@ -17,16 +19,22 @@ import com.powsybl.math.matrix.DenseMatrixFactory; import com.powsybl.openloadflow.OpenLoadFlowParameters; import com.powsybl.openloadflow.OpenLoadFlowProvider; -import com.powsybl.openloadflow.network.FourBusNetworkFactory; -import com.powsybl.openloadflow.network.SlackBusSelectionMode; +import com.powsybl.openloadflow.dc.equations.DcEquationSystemCreationParameters; +import com.powsybl.openloadflow.network.*; +import com.powsybl.openloadflow.network.impl.LfNetworkList; +import com.powsybl.openloadflow.network.impl.Networks; import com.powsybl.openloadflow.util.LoadFlowAssert; +import com.powsybl.openloadflow.util.PerUnit; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.slf4j.Logger; import org.usefultoys.slf4j.LoggerFactory; +import java.util.Collections; import java.util.List; +import java.util.Set; +import static com.powsybl.openloadflow.util.LoadFlowAssert.assertActivePowerEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -257,6 +265,42 @@ void shuntCompensatorActivePowerZero() { .add() .add(); loadFlowRunner.run(network, parameters); - LoadFlowAssert.assertActivePowerEquals(0, sc.getTerminal()); + assertActivePowerEquals(0, sc.getTerminal()); + } + + @Test + void testDisabledNonImpedantBranch() { + Network network = NodeBreakerNetworkFactory.create3Bars(); + Switch c1 = network.getSwitch("C1"); + c1.setOpen(true); + + LoadFlowParameters parameters = new LoadFlowParameters() + .setDc(true); + LoadFlow.run(network, parameters); + + assertActivePowerEquals(400.0, network.getLine("L1").getTerminal1()); + assertActivePowerEquals(100.0, network.getLine("L2").getTerminal1()); + assertActivePowerEquals(100.0, network.getLine("L3").getTerminal1()); + + LfNetworkParameters lfNetworkParameters = new LfNetworkParameters() + .setDc(true) + .setBreakers(true); + DcLoadFlowParameters dcLoadFlowParameters = new DcLoadFlowParameters(lfNetworkParameters, + new DcEquationSystemCreationParameters(true, true, false, true), + new DenseMatrixFactory(), + true, + parameters.getBalanceType(), + false); + try (LfNetworkList lfNetworks = Networks.load(network, lfNetworkParameters, Collections.emptySet(), Set.of(c1), Reporter.NO_OP)) { + LfNetwork largestNetwork = lfNetworks.getLargest().orElseThrow(); + largestNetwork.getBranchById("C1").setDisabled(true); + try (DcLoadFlowContext context = new DcLoadFlowContext(largestNetwork, dcLoadFlowParameters)) { + new DcLoadFlowEngine(context).run(); + } + // should be the same as with previous LF + assertEquals(400.0, largestNetwork.getBranchById("L1").getP1().eval() * PerUnit.SB, LoadFlowAssert.DELTA_POWER); + assertEquals(100.0, largestNetwork.getBranchById("L2").getP1().eval() * PerUnit.SB, LoadFlowAssert.DELTA_POWER); + assertEquals(100.0, largestNetwork.getBranchById("L3").getP1().eval() * PerUnit.SB, LoadFlowAssert.DELTA_POWER); + } } }