From ea07d2d459acb6f17320e316938d3caababa1dd2 Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Wed, 24 Aug 2022 23:54:51 +0200 Subject: [PATCH 01/51] Support multiple add and remove of the same edge in connectivity Signed-off-by: Geoffroy Jamgotchian --- pom.xml | 3 ++ .../graph/AbstractGraphConnectivity.java | 7 +++- .../openloadflow/graph/ConnectivityTest.java | 22 ++++++++++++ .../graph/NetworkConnectivityTest.java | 35 ------------------- 4 files changed, 31 insertions(+), 36 deletions(-) diff --git a/pom.xml b/pom.xml index 020e5956b0..f7906c2932 100644 --- a/pom.xml +++ b/pom.xml @@ -49,6 +49,8 @@ 1.6.3 4.10.0-alpha-1 + + 1.5.1 @@ -99,6 +101,7 @@ org.jgrapht jgrapht-core + ${jgrapht.version} org.usefultoys diff --git a/src/main/java/com/powsybl/openloadflow/graph/AbstractGraphConnectivity.java b/src/main/java/com/powsybl/openloadflow/graph/AbstractGraphConnectivity.java index f7359b6495..a1388c8441 100644 --- a/src/main/java/com/powsybl/openloadflow/graph/AbstractGraphConnectivity.java +++ b/src/main/java/com/powsybl/openloadflow/graph/AbstractGraphConnectivity.java @@ -49,6 +49,10 @@ public void addVertex(V vertex) { public void addEdge(V vertex1, V vertex2, E edge) { Objects.requireNonNull(vertex1); Objects.requireNonNull(vertex2); + Objects.requireNonNull(edge); + if (graph.containsEdge(edge)) { + return; + } EdgeAdd edgeAdd = new EdgeAdd<>(vertex1, vertex2, edge); edgeAdd.apply(graph); if (!graphModifications.isEmpty()) { @@ -59,8 +63,9 @@ public void addEdge(V vertex1, V vertex2, E edge) { @Override public void removeEdge(E edge) { + Objects.requireNonNull(edge); if (!graph.containsEdge(edge)) { - throw new PowsyblException("No such edge in graph: " + edge); + return; } V vertex1 = graph.getEdgeSource(edge); V vertex2 = graph.getEdgeTarget(edge); diff --git a/src/test/java/com/powsybl/openloadflow/graph/ConnectivityTest.java b/src/test/java/com/powsybl/openloadflow/graph/ConnectivityTest.java index 8c3535c74e..786f33e061 100644 --- a/src/test/java/com/powsybl/openloadflow/graph/ConnectivityTest.java +++ b/src/test/java/com/powsybl/openloadflow/graph/ConnectivityTest.java @@ -45,6 +45,13 @@ void exceptionsTest() { exceptionsTest(new MinimumSpanningTreeGraphConnectivity<>()); } + @Test + void multipleEdgesTest() { + multipleEdgesTest(new NaiveGraphConnectivity<>(s -> Integer.parseInt(s) - 1)); + multipleEdgesTest(new EvenShiloachGraphDecrementalConnectivity<>()); + multipleEdgesTest(new MinimumSpanningTreeGraphConnectivity<>()); + } + private void circleTest(GraphConnectivity c) { String o1 = "1"; String o2 = "2"; @@ -190,4 +197,19 @@ private void exceptionsTest(GraphConnectivity c) { PowsyblException e3 = assertThrows(PowsyblException.class, c::undoTemporaryChanges); assertEquals("Cannot reset, no remaining saved connectivity", e3.getMessage()); } + + private void multipleEdgesTest(GraphConnectivity c) { + String o1 = "1"; + String o2 = "2"; + String e12 = "1-2"; + c.addVertex(o1); + c.addVertex(o2); + c.addEdge(o1, o2, e12); + c.addEdge(o1, o2, e12); + c.startTemporaryChanges(); + assertEquals(1, c.getNbConnectedComponents()); + c.removeEdge(e12); + c.removeEdge(e12); + assertEquals(2, c.getNbConnectedComponents()); + } } diff --git a/src/test/java/com/powsybl/openloadflow/graph/NetworkConnectivityTest.java b/src/test/java/com/powsybl/openloadflow/graph/NetworkConnectivityTest.java index f3410103a0..96d02c7900 100644 --- a/src/test/java/com/powsybl/openloadflow/graph/NetworkConnectivityTest.java +++ b/src/test/java/com/powsybl/openloadflow/graph/NetworkConnectivityTest.java @@ -8,7 +8,6 @@ import com.powsybl.commons.PowsyblException; import com.powsybl.iidm.network.Network; -import com.powsybl.iidm.network.test.BatteryNetworkFactory; import com.powsybl.openloadflow.network.*; import com.powsybl.openloadflow.network.impl.Networks; import org.junit.jupiter.api.BeforeEach; @@ -59,26 +58,6 @@ void testReaddEdge() { testReaddEdge(new MinimumSpanningTreeGraphConnectivity<>(), true); } - @Test - void testDoubleCut() { - // Testing cutting twice an edge - testDoubleCut(new NaiveGraphConnectivity<>(LfBus::getNum)); - testDoubleCut(new EvenShiloachGraphDecrementalConnectivity<>()); - testDoubleCut(new MinimumSpanningTreeGraphConnectivity<>()); - } - - @Test - void testUnknownCut() { - // Testing cutting unknown edge - Network otherNetwork = BatteryNetworkFactory.create(); - LfNetwork otherLfNetwork = Networks.load(otherNetwork, new FirstSlackBusSelector()).get(0); - LfBranch otherNetworkBranch = otherLfNetwork.getBranchById("NHV1_NHV2_1"); - - testUnknownCut(new NaiveGraphConnectivity<>(LfBus::getNum), otherNetworkBranch); - testUnknownCut(new EvenShiloachGraphDecrementalConnectivity<>(), otherNetworkBranch); - testUnknownCut(new MinimumSpanningTreeGraphConnectivity<>(), otherNetworkBranch); - } - @Test void testNonConnected() { // Testing with a non-connected graph @@ -161,20 +140,6 @@ private void testReaddEdge(GraphConnectivity connectivity, bool } } - private void testDoubleCut(GraphConnectivity connectivity) { - updateConnectivity(connectivity); - - PowsyblException e = assertThrows(PowsyblException.class, () -> cutBranches(connectivity, "l34", "l48", "l34")); - assertEquals("No such edge in graph: l34", e.getMessage()); - } - - private void testUnknownCut(GraphConnectivity connectivity, LfBranch unknownBranch) { - updateConnectivity(connectivity); - - PowsyblException e = assertThrows(PowsyblException.class, () -> connectivity.removeEdge(unknownBranch)); - assertEquals("No such edge in graph: NHV1_NHV2_1", e.getMessage()); - } - private void testNonConnectedComponents(GraphConnectivity connectivity) { updateConnectivity(connectivity); cutBranches(connectivity, "l34", "l48"); From 3dcf4b61753018bb6552a766487cc95169415e1a Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Thu, 25 Aug 2022 00:00:16 +0200 Subject: [PATCH 02/51] Fix unit test Signed-off-by: Geoffroy Jamgotchian --- .../openloadflow/graph/ConnectivityTest.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/powsybl/openloadflow/graph/ConnectivityTest.java b/src/test/java/com/powsybl/openloadflow/graph/ConnectivityTest.java index 786f33e061..d845e9f95c 100644 --- a/src/test/java/com/powsybl/openloadflow/graph/ConnectivityTest.java +++ b/src/test/java/com/powsybl/openloadflow/graph/ConnectivityTest.java @@ -47,9 +47,9 @@ void exceptionsTest() { @Test void multipleEdgesTest() { - multipleEdgesTest(new NaiveGraphConnectivity<>(s -> Integer.parseInt(s) - 1)); - multipleEdgesTest(new EvenShiloachGraphDecrementalConnectivity<>()); - multipleEdgesTest(new MinimumSpanningTreeGraphConnectivity<>()); + multipleEdgesTest(new NaiveGraphConnectivity<>(s -> Integer.parseInt(s) - 1), true); + multipleEdgesTest(new EvenShiloachGraphDecrementalConnectivity<>(), false); + multipleEdgesTest(new MinimumSpanningTreeGraphConnectivity<>(), true); } private void circleTest(GraphConnectivity c) { @@ -198,7 +198,7 @@ private void exceptionsTest(GraphConnectivity c) { assertEquals("Cannot reset, no remaining saved connectivity", e3.getMessage()); } - private void multipleEdgesTest(GraphConnectivity c) { + private void multipleEdgesTest(GraphConnectivity c, boolean incrementalSupport) { String o1 = "1"; String o2 = "2"; String e12 = "1-2"; @@ -209,7 +209,13 @@ private void multipleEdgesTest(GraphConnectivity c) { c.startTemporaryChanges(); assertEquals(1, c.getNbConnectedComponents()); c.removeEdge(e12); + assertEquals(2, c.getNbConnectedComponents()); + c.removeEdge(e12); c.removeEdge(e12); assertEquals(2, c.getNbConnectedComponents()); + if (incrementalSupport) { + c.addEdge(o1, o2, e12); + assertEquals(1, c.getNbConnectedComponents()); + } } } From bb753a25c01751fddf4116e8818d7e7ca3c28863 Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Thu, 25 Aug 2022 00:18:37 +0200 Subject: [PATCH 03/51] Fix comment Signed-off-by: Geoffroy Jamgotchian --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f7906c2932..58c820eed6 100644 --- a/pom.xml +++ b/pom.xml @@ -49,7 +49,7 @@ 1.6.3 4.10.0-alpha-1 - + 1.5.1 From eb55d677adcbbfc78e1fb1ca0d7ef09555d20570 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Wed, 27 Jul 2022 14:25:04 +0200 Subject: [PATCH 04/51] new API Signed-off-by: Florian Dupuy --- ...nningTreeGraphDecrementalConnectivity.java | 0 .../graph/NaiveGraphConnectivity.java | 76 ------------------- .../openloadflow/network/LfNetwork.java | 1 + 3 files changed, 1 insertion(+), 76 deletions(-) create mode 100644 src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphDecrementalConnectivity.java diff --git a/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphDecrementalConnectivity.java b/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphDecrementalConnectivity.java new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphConnectivity.java b/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphConnectivity.java index 5102772c00..e69de29bb2 100644 --- a/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphConnectivity.java +++ b/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphConnectivity.java @@ -1,76 +0,0 @@ -/** - * Copyright (c) 2020, RTE (http://www.rte-france.com) - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at http://mozilla.org/MPL/2.0/. - */ -package com.powsybl.openloadflow.graph; - -import org.jgrapht.alg.connectivity.ConnectivityInspector; - -import java.util.Comparator; -import java.util.Deque; -import java.util.Objects; -import java.util.Set; -import java.util.function.ToIntFunction; -import java.util.stream.Collectors; - -/** - * @author Geoffroy Jamgotchian - */ -public class NaiveGraphConnectivity extends AbstractGraphConnectivity { - - private int[] components; - - private final ToIntFunction numGetter; - - public NaiveGraphConnectivity(ToIntFunction numGetter) { - this.numGetter = Objects.requireNonNull(numGetter); - } - - protected void updateComponents() { - if (components == null) { - components = new int[getGraph().vertexSet().size()]; - componentSets = new ConnectivityInspector<>(getGraph()) - .connectedSets() - .stream() - .sorted(Comparator.comparing(Set::size).reversed()) - .collect(Collectors.toList()); - for (int componentIndex = 0; componentIndex < componentSets.size(); componentIndex++) { - Set vertices = componentSets.get(componentIndex); - for (V vertex : vertices) { - components[numGetter.applyAsInt(vertex)] = componentIndex; - } - } - } - } - - @Override - protected void resetConnectivity(Deque> m) { - invalidateComponents(); - } - - @Override - protected int getQuickComponentNumber(V vertex) { - return components[numGetter.applyAsInt(vertex)]; - } - - @Override - protected void updateConnectivity(EdgeRemove edgeRemove) { - invalidateComponents(); - } - - @Override - protected void updateConnectivity(EdgeAdd edgeAdd) { - invalidateComponents(); - } - - @Override - protected void updateConnectivity(VertexAdd vertexAdd) { - invalidateComponents(); - } - - private void invalidateComponents() { - components = null; - } -} diff --git a/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java b/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java index daa6cb40a5..70933e6fab 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java @@ -571,6 +571,7 @@ public GraphConnectivity getConnectivity() { getBranches().stream() .filter(b -> b.getBus1() != null && b.getBus2() != null) .forEach(b -> connectivity.addEdge(b.getBus1(), b.getBus2(), b)); + connectivity.save(); } return connectivity; } From 9c61eadde7ed90fb1e626f29bfcfe0677d87463f Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Wed, 27 Jul 2022 17:55:20 +0200 Subject: [PATCH 05/51] Adapt MinimumSpanningTreeConnectivity to new API Signed-off-by: Florian Dupuy --- .../graph/MinimumSpanningTreeGraphDecrementalConnectivity.java | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphDecrementalConnectivity.java diff --git a/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphDecrementalConnectivity.java b/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphDecrementalConnectivity.java deleted file mode 100644 index e69de29bb2..0000000000 From 9f10f61d14532d4bd49628a6c3ca2c631549f4c8 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Fri, 29 Jul 2022 10:19:45 +0200 Subject: [PATCH 06/51] Fix implementation and connectivity calls Signed-off-by: Florian Dupuy --- src/test/java/com/powsybl/openloadflow/graph/BridgesTest.java | 1 + .../com/powsybl/openloadflow/graph/NetworkConnectivityTest.java | 1 + 2 files changed, 2 insertions(+) diff --git a/src/test/java/com/powsybl/openloadflow/graph/BridgesTest.java b/src/test/java/com/powsybl/openloadflow/graph/BridgesTest.java index e0f0cdb030..d054865897 100644 --- a/src/test/java/com/powsybl/openloadflow/graph/BridgesTest.java +++ b/src/test/java/com/powsybl/openloadflow/graph/BridgesTest.java @@ -169,6 +169,7 @@ private static void initGraphDc(LfNetwork lfNetwork, GraphConnectivity connectivity) for (LfBranch lfBranch : lfNetwork.getBranches()) { connectivity.addEdge(lfBranch.getBus1(), lfBranch.getBus2(), lfBranch); } + connectivity.save(); } private Set createVerticesSet(String... busIds) { From 79949cf40e7c033a135f22d879d5b71a93740c82 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Wed, 3 Aug 2022 18:56:56 +0200 Subject: [PATCH 07/51] Always check before calling reset that some modifications were made Signed-off-by: Florian Dupuy --- .../com/powsybl/openloadflow/ac/PhaseControlOuterLoop.java | 5 ++--- .../java/com/powsybl/openloadflow/network/LfNetwork.java | 2 ++ .../openloadflow/network/impl/PropagatedContingency.java | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/PhaseControlOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/PhaseControlOuterLoop.java index 9fcd1a59fa..b08e6febcb 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/PhaseControlOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/PhaseControlOuterLoop.java @@ -50,6 +50,7 @@ public void initialize(OuterLoopContext context) { if (!controllerBranches.isEmpty()) { List disabledBranches = context.getNetwork().getBranches().stream() .filter(LfElement::isDisabled) + .filter(b -> b.getBus1() != null && b.getBus2() != null) .collect(Collectors.toList()); for (LfBranch controllerBranch : controllerBranches) { var phaseControl = controllerBranch.getDiscretePhaseControl().orElseThrow(); @@ -58,9 +59,7 @@ public void initialize(OuterLoopContext context) { connectivity.startTemporaryChanges(); // apply contingency (in case we are inside a security analysis) - disabledBranches.stream() - .filter(b -> b.getBus1() != null && b.getBus2() != null) - .forEach(connectivity::removeEdge); + disabledBranches.forEach(connectivity::removeEdge); int componentsCountBeforePhaseShifterLoss = connectivity.getNbConnectedComponents(); // then the phase shifter controlled branch diff --git a/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java b/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java index 70933e6fab..eec46fac50 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java @@ -606,10 +606,12 @@ public void fixTransformerVoltageControls() { if (branch.isDisabled() && branch.getBus1() != null && branch.getBus2() != null) { // apply contingency (in case we are inside a security analysis) getConnectivity().removeEdge(branch); + edgesRemoved = true; } } for (LfBranch branch : controllerBranches) { getConnectivity().removeEdge(branch); + edgesRemoved = true; } int disabledTransformerCount = 0; Map componentNoPVBusesMap = new HashMap<>(); 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 566490703c..893350dc50 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/PropagatedContingency.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/PropagatedContingency.java @@ -299,7 +299,8 @@ public Optional toLfContingency(LfNetwork network, boolean useSma connectivity.startTemporaryChanges(); branches.stream() .filter(b -> b.getBus1() != null && b.getBus2() != null) - .forEach(connectivity::removeEdge); + .collect(Collectors.toList()); + edgesRemoved.forEach(connectivity::removeEdge); // add to contingency description buses and branches that won't be part of the main connected // component in post contingency state From 14a066fb7bdd96604bc9ed0d62b6ca7e0b723c94 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Thu, 4 Aug 2022 19:09:27 +0200 Subject: [PATCH 08/51] Fix reset Signed-off-by: Florian Dupuy --- .../graph/MinimumSpanningTreeGraphConnectivity.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphConnectivity.java b/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphConnectivity.java index 63ecfca9ab..f40d6150f5 100644 --- a/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphConnectivity.java +++ b/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphConnectivity.java @@ -64,6 +64,12 @@ protected void resetConnectivity(Deque> m) { componentSets = null; } + @Override + protected void resetConnectivityToSecondToLastSave(Deque> m) { + mstSaved.removeLast(); + resetConnectivityToLastSave(m); + } + @Override protected int getQuickComponentNumber(V vertex) { Set cc = mst.forest.getConnectedComponent(vertex); From 38ddfa70e29dbfc145aaa8447b690f2bdb3269d7 Mon Sep 17 00:00:00 2001 From: Florian Dupuy Date: Thu, 4 Aug 2022 19:51:35 +0200 Subject: [PATCH 09/51] Replace save/reset mechanism by startTmpChanges/undoTmpChanges mechanism Signed-off-by: Florian Dupuy --- .../com/powsybl/openloadflow/ac/PhaseControlOuterLoop.java | 5 +++-- .../graph/MinimumSpanningTreeGraphConnectivity.java | 6 ------ .../java/com/powsybl/openloadflow/network/LfNetwork.java | 3 --- .../openloadflow/network/impl/PropagatedContingency.java | 3 +-- .../java/com/powsybl/openloadflow/graph/BridgesTest.java | 1 - .../powsybl/openloadflow/graph/NetworkConnectivityTest.java | 1 - 6 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/PhaseControlOuterLoop.java b/src/main/java/com/powsybl/openloadflow/ac/PhaseControlOuterLoop.java index b08e6febcb..9fcd1a59fa 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/PhaseControlOuterLoop.java +++ b/src/main/java/com/powsybl/openloadflow/ac/PhaseControlOuterLoop.java @@ -50,7 +50,6 @@ public void initialize(OuterLoopContext context) { if (!controllerBranches.isEmpty()) { List disabledBranches = context.getNetwork().getBranches().stream() .filter(LfElement::isDisabled) - .filter(b -> b.getBus1() != null && b.getBus2() != null) .collect(Collectors.toList()); for (LfBranch controllerBranch : controllerBranches) { var phaseControl = controllerBranch.getDiscretePhaseControl().orElseThrow(); @@ -59,7 +58,9 @@ public void initialize(OuterLoopContext context) { connectivity.startTemporaryChanges(); // apply contingency (in case we are inside a security analysis) - disabledBranches.forEach(connectivity::removeEdge); + disabledBranches.stream() + .filter(b -> b.getBus1() != null && b.getBus2() != null) + .forEach(connectivity::removeEdge); int componentsCountBeforePhaseShifterLoss = connectivity.getNbConnectedComponents(); // then the phase shifter controlled branch diff --git a/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphConnectivity.java b/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphConnectivity.java index f40d6150f5..63ecfca9ab 100644 --- a/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphConnectivity.java +++ b/src/main/java/com/powsybl/openloadflow/graph/MinimumSpanningTreeGraphConnectivity.java @@ -64,12 +64,6 @@ protected void resetConnectivity(Deque> m) { componentSets = null; } - @Override - protected void resetConnectivityToSecondToLastSave(Deque> m) { - mstSaved.removeLast(); - resetConnectivityToLastSave(m); - } - @Override protected int getQuickComponentNumber(V vertex) { Set cc = mst.forest.getConnectedComponent(vertex); diff --git a/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java b/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java index eec46fac50..daa6cb40a5 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java @@ -571,7 +571,6 @@ public GraphConnectivity getConnectivity() { getBranches().stream() .filter(b -> b.getBus1() != null && b.getBus2() != null) .forEach(b -> connectivity.addEdge(b.getBus1(), b.getBus2(), b)); - connectivity.save(); } return connectivity; } @@ -606,12 +605,10 @@ public void fixTransformerVoltageControls() { if (branch.isDisabled() && branch.getBus1() != null && branch.getBus2() != null) { // apply contingency (in case we are inside a security analysis) getConnectivity().removeEdge(branch); - edgesRemoved = true; } } for (LfBranch branch : controllerBranches) { getConnectivity().removeEdge(branch); - edgesRemoved = true; } int disabledTransformerCount = 0; Map componentNoPVBusesMap = new HashMap<>(); 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 893350dc50..566490703c 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/PropagatedContingency.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/PropagatedContingency.java @@ -299,8 +299,7 @@ public Optional toLfContingency(LfNetwork network, boolean useSma connectivity.startTemporaryChanges(); branches.stream() .filter(b -> b.getBus1() != null && b.getBus2() != null) - .collect(Collectors.toList()); - edgesRemoved.forEach(connectivity::removeEdge); + .forEach(connectivity::removeEdge); // add to contingency description buses and branches that won't be part of the main connected // component in post contingency state diff --git a/src/test/java/com/powsybl/openloadflow/graph/BridgesTest.java b/src/test/java/com/powsybl/openloadflow/graph/BridgesTest.java index d054865897..e0f0cdb030 100644 --- a/src/test/java/com/powsybl/openloadflow/graph/BridgesTest.java +++ b/src/test/java/com/powsybl/openloadflow/graph/BridgesTest.java @@ -169,7 +169,6 @@ private static void initGraphDc(LfNetwork lfNetwork, GraphConnectivity connectivity) for (LfBranch lfBranch : lfNetwork.getBranches()) { connectivity.addEdge(lfBranch.getBus1(), lfBranch.getBus2(), lfBranch); } - connectivity.save(); } private Set createVerticesSet(String... busIds) { From c4e727d09ea914627335fb1c94ce0ffc079ec797 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Wed, 17 Aug 2022 10:57:19 +0200 Subject: [PATCH 10/51] Save work. Signed-off-by: Anne Tilloy --- .../openloadflow/network/LfAction.java | 108 +++++++++++ .../sa/AbstractSecurityAnalysis.java | 9 +- .../openloadflow/sa/AcSecurityAnalysis.java | 181 +++++++++++++++++- .../openloadflow/sa/DcSecurityAnalysis.java | 4 +- .../sa/OpenSecurityAnalysisProvider.java | 2 +- .../powsybl/openloadflow/sa/LfActionTest.java | 57 ++++++ .../sa/OpenSecurityAnalysisGraphTest.java | 2 +- .../sa/OpenSecurityAnalysisTest.java | 88 +++++++++ 8 files changed, 437 insertions(+), 14 deletions(-) create mode 100644 src/main/java/com/powsybl/openloadflow/network/LfAction.java create mode 100644 src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java new file mode 100644 index 0000000000..81e80fa3af --- /dev/null +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -0,0 +1,108 @@ +/** + * Copyright (c) 2022, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package com.powsybl.openloadflow.network; + +import com.powsybl.commons.PowsyblException; +import com.powsybl.openloadflow.graph.GraphConnectivity; +import com.powsybl.openloadflow.network.impl.LfSwitch; +import com.powsybl.security.action.Action; +import com.powsybl.security.action.SwitchAction; + +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * @author Anne Tilloy + */ +public class LfAction { + + private final String id; + + private LfBranch disabledBranch; // switch to open + + private LfBranch enabledBranch; // switch to close + + private LfNetwork network; + + public LfAction(Action action, LfNetwork network) { + this.id = Objects.requireNonNull(action.getId()); + this.network = Objects.requireNonNull(network); + switch (action.getType()) { + case "SWITCH": + SwitchAction switchAction = (SwitchAction) action; + LfBranch branch = network.getBranchById(switchAction.getSwitchId()); + if (branch == null) { + throw new PowsyblException("Branch " + switchAction.getSwitchId() + " not found in the network"); + } + if (switchAction.isOpen()) { + disabledBranch = branch; + } else { + enabledBranch = branch; + } + break; + default: + throw new UnsupportedOperationException("Unsupported action type: " + action.getType()); + } + } + + public String getId() { + return id; + } + + public LfBranch getDisabledBranch() { + return disabledBranch; + } + + public LfBranch getEnabledBranch() { + return enabledBranch; + } + + public void apply() { + if (disabledBranch != null) { + disabledBranch.setDisabled(true); + } + if (enabledBranch != null) { + enabledBranch.setDisabled(false); + enabledBranch.getBus1().setDisabled(false); + enabledBranch.getBus2().setDisabled(false); + } + + // update connectivity with disabled branches + List disabledBranches = network.getBranches().stream() + .filter(LfElement::isDisabled) + .collect(Collectors.toList()); + GraphConnectivity connectivity = network.getConnectivity(); + connectivity.startTemporaryChanges(); + disabledBranches.stream() + .filter(b -> b.getBus1() != null && b.getBus2() != null) + .filter(b -> !(b instanceof LfSwitch)) // FIXME + .forEach(connectivity::removeEdge); + // update connectivity with enabled branches. + if (enabledBranch != null) { + connectivity.addEdge(enabledBranch.getBus1(), enabledBranch.getBus2(), enabledBranch); + } + + // add to contingency description buses and branches that won't be part of the main connected + // component in post contingency state + Set buses = connectivity.getSmallComponents().stream().flatMap(Set::stream).collect(Collectors.toSet()); + for (LfBus bus : buses) { + bus.setDisabled(true); + bus.getBranches().forEach(branch -> branch.setDisabled(true)); + } + connectivity.undoTemporaryChanges(); + + System.out.println("Action " + id); + for (LfBus bus : network.getBuses()) { + System.out.println("Bus " + bus.getId() + " is disabled: " + bus.isDisabled()); + } + for (LfBranch branch : network.getBranches()) { + System.out.println("Branch " + branch.getId() + " is disabled: " + branch.isDisabled()); + } + } +} diff --git a/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java index f8b27cb9d9..c6db45d334 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AbstractSecurityAnalysis.java @@ -17,8 +17,10 @@ import com.powsybl.openloadflow.network.LfBus; import com.powsybl.security.SecurityAnalysisParameters; import com.powsybl.security.SecurityAnalysisReport; +import com.powsybl.security.action.Action; import com.powsybl.security.monitor.StateMonitor; import com.powsybl.security.monitor.StateMonitorIndex; +import com.powsybl.security.strategy.OperatorStrategy; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -53,7 +55,8 @@ protected AbstractSecurityAnalysis(Network network, MatrixFactory matrixFactory, } public CompletableFuture run(String workingVariantId, SecurityAnalysisParameters securityAnalysisParameters, - ContingenciesProvider contingenciesProvider, ComputationManager computationManager) { + ContingenciesProvider contingenciesProvider, ComputationManager computationManager, + List operatorStrategies, List actions) { Objects.requireNonNull(workingVariantId); Objects.requireNonNull(securityAnalysisParameters); Objects.requireNonNull(contingenciesProvider); @@ -61,7 +64,7 @@ public CompletableFuture run(String workingVariantId, Se String oldWorkingVariantId = network.getVariantManager().getWorkingVariantId(); network.getVariantManager().setWorkingVariant(workingVariantId); try { - return runSync(workingVariantId, securityAnalysisParameters, contingenciesProvider, computationManager); + return runSync(workingVariantId, securityAnalysisParameters, contingenciesProvider, computationManager, operatorStrategies, actions); } finally { network.getVariantManager().setWorkingVariant(oldWorkingVariantId); } @@ -69,5 +72,5 @@ public CompletableFuture run(String workingVariantId, Se } abstract SecurityAnalysisReport runSync(String workingVariantId, SecurityAnalysisParameters securityAnalysisParameters, ContingenciesProvider contingenciesProvider, - ComputationManager computationManager); + ComputationManager computationManager, List operatorStrategies, List actions); } diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index b836fb56c3..3f4a381d9c 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -11,6 +11,7 @@ import com.powsybl.computation.ComputationManager; import com.powsybl.contingency.ContingenciesProvider; import com.powsybl.contingency.Contingency; +import com.powsybl.iidm.network.Identifiable; import com.powsybl.iidm.network.Network; import com.powsybl.iidm.network.Switch; import com.powsybl.iidm.network.TopologyKind; @@ -33,11 +34,19 @@ import com.powsybl.security.SecurityAnalysisParameters; import com.powsybl.security.SecurityAnalysisReport; import com.powsybl.security.SecurityAnalysisResult; +import com.powsybl.security.action.Action; +import com.powsybl.security.action.SwitchAction; +import com.powsybl.security.condition.AllViolationCondition; +import com.powsybl.security.condition.AtLeastOneViolationCondition; import com.powsybl.security.monitor.StateMonitor; +import com.powsybl.security.results.NetworkResult; +import com.powsybl.security.results.OperatorStrategyResult; import com.powsybl.security.results.PostContingencyResult; +import com.powsybl.security.strategy.OperatorStrategy; import java.util.*; import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; public class AcSecurityAnalysis extends AbstractSecurityAnalysis { @@ -52,7 +61,7 @@ private static SecurityAnalysisResult createNoResult() { @Override SecurityAnalysisReport runSync(String workingVariantId, SecurityAnalysisParameters securityAnalysisParameters, ContingenciesProvider contingenciesProvider, - ComputationManager computationManager) { + ComputationManager computationManager, List operatorStrategies, List actions) { var saReporter = Reports.createAcSecurityAnalysis(reporter, network.getId()); Stopwatch stopwatch = Stopwatch.createStarted(); @@ -73,10 +82,14 @@ SecurityAnalysisReport runSync(String workingVariantId, SecurityAnalysisParamete lfParameters.isShuntCompensatorVoltageControlOn(), lfParameters.getBalanceType() == LoadFlowParameters.BalanceType.PROPORTIONAL_TO_CONFORM_LOAD, lfParameters.isHvdcAcEmulation(), securityAnalysisParametersExt.isContingencyPropagation()); + // try for find all switches to be operated as actions. + Set allSwitchesToClose = new HashSet<>(); + getAllSwitchesToOperate(network, actions, allSwitchesToClose, allSwitchesToOpen); + AcLoadFlowParameters acParameters = OpenLoadFlowParameters.createAcParameters(network, lfParameters, lfParametersExt, matrixFactory, connectivityFactory, saReporter, true, false); // create networks including all necessary switches - List lfNetworks = createNetworks(allSwitchesToOpen, acParameters.getNetworkParameters(), saReporter); + List lfNetworks = createNetworks(allSwitchesToOpen, allSwitchesToClose, acParameters.getNetworkParameters(), saReporter); // run simulation on largest network SecurityAnalysisResult result; @@ -85,7 +98,10 @@ SecurityAnalysisReport runSync(String workingVariantId, SecurityAnalysisParamete } else { LfNetwork largestNetwork = lfNetworks.get(0); if (largestNetwork.isValid()) { - result = runSimulations(largestNetwork, propagatedContingencies, acParameters, securityAnalysisParameters); + HashMap lfActionById = getLfActions(largestNetwork, actions); + HashMap operatorStrategyByContingencyId = indexOperatorStrategyByContingencyId(propagatedContingencies, operatorStrategies); + result = runSimulations(largestNetwork, propagatedContingencies, acParameters, securityAnalysisParameters, operatorStrategyByContingencyId, lfActionById, allSwitchesToClose); + } else { result = createNoResult(); } @@ -98,18 +114,25 @@ SecurityAnalysisReport runSync(String workingVariantId, SecurityAnalysisParamete return new SecurityAnalysisReport(result); } - List createNetworks(Set allSwitchesToOpen, LfNetworkParameters networkParameters, + List createNetworks(Set allSwitchesToOpen, Set allSwitchesToClose, LfNetworkParameters networkParameters, Reporter saReporter) { List lfNetworks; String tmpVariantId = "olf-tmp-" + UUID.randomUUID(); + String variantId = network.getVariantManager().getWorkingVariantId(); network.getVariantManager().cloneVariant(network.getVariantManager().getWorkingVariantId(), tmpVariantId); + network.getVariantManager().setWorkingVariant(tmpVariantId); try { network.getSwitchStream().filter(sw -> sw.getVoltageLevel().getTopologyKind() == TopologyKind.NODE_BREAKER) .forEach(sw -> sw.setRetained(false)); allSwitchesToOpen.forEach(sw -> sw.setRetained(true)); + allSwitchesToClose.forEach(sw -> { + sw.setRetained(true); + sw.setOpen(false); // in order to be present in the network. + }); lfNetworks = Networks.load(network, networkParameters, saReporter); } finally { network.getVariantManager().removeVariant(tmpVariantId); + network.getVariantManager().setWorkingVariant(variantId); } return lfNetworks; } @@ -122,8 +145,39 @@ public static void distributedMismatch(LfNetwork network, double mismatch, LoadF } } + public static void getAllSwitchesToOperate(Network network, List actions, Set allSwitchesToClose, Set allSwitchesToOpen) { + actions.stream().filter(action -> action.getType().equals("SWITCH")) + .map(action -> ((SwitchAction) action).getSwitchId()) + .forEach(id -> { + Switch sw = network.getSwitch(id); + if (sw.isOpen()) { + allSwitchesToClose.add(sw); + } else { + allSwitchesToOpen.add(sw); + } + }); + } + + public static HashMap getLfActions(LfNetwork network, List actions) { + return new HashMap(actions.stream().collect(Collectors.toMap(Action::getId, action -> new LfAction(action, network)))); + } + + public static HashMap indexOperatorStrategyByContingencyId(List propagatedContingencies, List operatorStrategies) { + List contingencyIds = propagatedContingencies.stream().map(propagatedContingency -> propagatedContingency.getContingency().getId()).collect(Collectors.toList()); + HashMap operatorStrategyByContingencyId = new HashMap<>(); + for (OperatorStrategy operatorStrategy : operatorStrategies) { + if (contingencyIds.contains(operatorStrategy.getContingencyId())) { + operatorStrategyByContingencyId.put(operatorStrategy.getContingencyId(), operatorStrategy); + } else { + LOGGER.warn("An operator strategy linked to Contingency {} that is not present in the list of Contingencies", operatorStrategy.getContingencyId()); + } + } + return operatorStrategyByContingencyId; + } + private SecurityAnalysisResult runSimulations(LfNetwork network, List propagatedContingencies, AcLoadFlowParameters acParameters, - SecurityAnalysisParameters securityAnalysisParameters) { + SecurityAnalysisParameters securityAnalysisParameters, HashMap operatorStrategyByContingencyId, + HashMap lfActionById, Set allSwitchesToClose) { LoadFlowParameters loadFlowParameters = securityAnalysisParameters.getLoadFlowParameters(); OpenLoadFlowParameters openLoadFlowParameters = OpenLoadFlowParameters.get(loadFlowParameters); OpenSecurityAnalysisParameters openSecurityAnalysisParameters = OpenSecurityAnalysisParameters.getOrDefault(securityAnalysisParameters); @@ -135,13 +189,31 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List { + LfBranch branch = network.getBranchById(id); + branch.setDisabled(true); + if (branch.getBus1() != null && branch.getBus2() != null) { + connectivity.removeEdge(branch); + } + }); + preContingencyLoadFlowResult = engine.run(); + } boolean preContingencyComputationOk = preContingencyLoadFlowResult.getNewtonRaphsonStatus() == NewtonRaphsonStatus.CONVERGED; var preContingencyLimitViolationManager = new LimitViolationManager(); List postContingencyResults = new ArrayList<>(); var preContingencyNetworkResult = new PreContingencyNetworkResult(network, monitorIndex, createResultExtension); + List operatorStrategyResults = new ArrayList<>(); // only run post-contingency simulations if pre-contingency simulation is ok if (preContingencyComputationOk) { @@ -173,6 +245,18 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List optionalOperatorStrategyResult = runActionSimulation(network, context, propagatedContingency.getContingency(), + operatorStrategyByContingencyId.get(lfContingency.getId()), preContingencyLimitViolationManager, + securityAnalysisParameters.getIncreasedViolationsParameters(), postContingencyResult.getLimitViolationsResult(), lfActionById, + preContingencyNetworkResult, createResultExtension); + if (optionalOperatorStrategyResult.isPresent()) { + operatorStrategyResults.add(optionalOperatorStrategyResult.get()); + } + } + if (contingencyIt.hasNext()) { // restore base state networkState.restore(); @@ -187,7 +271,7 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List runActionSimulation(LfNetwork network, AcLoadFlowContext context, Contingency contingency, OperatorStrategy operatorStrategy, + LimitViolationManager preContingencyLimitViolationManager, + SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, + LimitViolationsResult postContingencyLimitViolations, HashMap lfActionById, + PreContingencyNetworkResult preContingencyNetworkResult, boolean createResultExtension) { + + Optional optionalOperatorStrategyResult = Optional.empty(); + + if (checkCondition(operatorStrategy, postContingencyLimitViolations)) { + LOGGER.info("Start operator strategy {} after contingency '{}' simulation on network {}", operatorStrategy.getId(), + operatorStrategy.getContingencyId(), network); + + List operatorStrategyLfActions = operatorStrategy.getActionIds().stream() + .map(id -> lfActionById.getOrDefault(id, null)).collect(Collectors.toList()); // FIXME: null as default value? + operatorStrategyLfActions.stream().forEach(LfAction::apply); + + Stopwatch stopwatch = Stopwatch.createStarted(); + + // restart LF on post contingency and post actions equation system + context.getParameters().setVoltageInitializer(new PreviousValueVoltageInitializer()); + AcLoadFlowResult postActionsLoadFlowResult = new AcloadFlowEngine(context) + .run(); + + boolean postActionsComputationOk = postActionsLoadFlowResult.getNewtonRaphsonStatus() == NewtonRaphsonStatus.CONVERGED; + // FIXME: to be checked. + var postActionsViolationManager = new LimitViolationManager(preContingencyLimitViolationManager, violationsParameters); + var postActionsNetworkResult = new PostContingencyNetworkResult(network, monitorIndex, createResultExtension, preContingencyNetworkResult, contingency); + + if (postActionsComputationOk) { + // update network result + postActionsNetworkResult.update(); + + // detect violations + postActionsViolationManager.detectViolations(network); + } + + stopwatch.stop(); + + LOGGER.info("Operator strategy {} after contingency '{}' simulation done on network {} in {} ms", operatorStrategy.getId(), + operatorStrategy.getContingencyId(), network, stopwatch.elapsed(TimeUnit.MILLISECONDS)); + + optionalOperatorStrategyResult = Optional.of(new OperatorStrategyResult(operatorStrategy, + new LimitViolationsResult(postActionsComputationOk, + postActionsViolationManager.getLimitViolations()), + new NetworkResult(postActionsNetworkResult.getBranchResults(), + postActionsNetworkResult.getBusResults(), + postActionsNetworkResult.getThreeWindingsTransformerResults()))); + } + + return optionalOperatorStrategyResult; + } + + private boolean checkCondition(OperatorStrategy operatorStrategy, LimitViolationsResult limitViolationsResult) { + // FIXME: add logs. + HashSet limitViolationEquipmentIds = (HashSet) limitViolationsResult.getLimitViolations().stream() + .map(limitViolation -> limitViolation.getSubjectId()).collect(Collectors.toSet()); + HashSet commonEquipmentIds; + switch (operatorStrategy.getCondition().getType()) { + case "TRUE_CONDITION": + return true; + case "ANY_VIOLATION_CONDITION": + return limitViolationEquipmentIds.size() > 0; + case "AT_LEAST_ONE_VIOLATION": + AtLeastOneViolationCondition atLeastCondition = (AtLeastOneViolationCondition) operatorStrategy.getCondition(); + commonEquipmentIds = (HashSet) atLeastCondition.getViolationIds().stream() + .distinct() + .filter(limitViolationEquipmentIds::contains) + .collect(Collectors.toSet()); + return !commonEquipmentIds.isEmpty(); + case "ALL_VIOLATION": + AllViolationCondition allCondition = (AllViolationCondition) operatorStrategy.getCondition(); + commonEquipmentIds = (HashSet) allCondition.getViolationIds().stream() + .distinct() + .filter(limitViolationEquipmentIds::contains) + .collect(Collectors.toSet()); + return commonEquipmentIds.equals(allCondition.getViolationIds()); + default: + throw new UnsupportedOperationException("Unsupported condition type: " + operatorStrategy.getCondition().getType()); + } + } } diff --git a/src/main/java/com/powsybl/openloadflow/sa/DcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/DcSecurityAnalysis.java index 1caddbd80c..72da2138c4 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/DcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/DcSecurityAnalysis.java @@ -18,11 +18,13 @@ import com.powsybl.openloadflow.network.LfBus; import com.powsybl.openloadflow.sensi.OpenSensitivityAnalysisProvider; import com.powsybl.security.*; +import com.powsybl.security.action.Action; import com.powsybl.security.detectors.DefaultLimitViolationDetector; import com.powsybl.security.detectors.LoadingLimitType; import com.powsybl.security.monitor.StateMonitor; import com.powsybl.security.results.BranchResult; import com.powsybl.security.results.PostContingencyResult; +import com.powsybl.security.strategy.OperatorStrategy; import com.powsybl.sensitivity.*; import org.apache.commons.lang3.tuple.Pair; @@ -37,7 +39,7 @@ protected DcSecurityAnalysis(Network network, MatrixFactory matrixFactory, Graph @Override SecurityAnalysisReport runSync(String workingVariantId, SecurityAnalysisParameters securityAnalysisParameters, ContingenciesProvider contingenciesProvider, - ComputationManager computationManager) { + ComputationManager computationManager, List operatorStrategies, List actions) { // load contingencies List contingencies = contingenciesProvider.getContingencies(network); diff --git a/src/main/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisProvider.java b/src/main/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisProvider.java index 8c070188a9..7b207be02d 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisProvider.java +++ b/src/main/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisProvider.java @@ -71,7 +71,7 @@ public CompletableFuture run(Network network, String wor securityAnalysis = new AcSecurityAnalysis(network, matrixFactory, connectivityFactory, stateMonitors, reporter); } - return securityAnalysis.run(workingVariantId, securityAnalysisParameters, contingenciesProvider, computationManager); + return securityAnalysis.run(workingVariantId, securityAnalysisParameters, contingenciesProvider, computationManager, operatorStrategies, actions); } @Override diff --git a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java new file mode 100644 index 0000000000..edb17d4ff5 --- /dev/null +++ b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2020, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package com.powsybl.openloadflow.sa; + +import com.powsybl.commons.AbstractConverterTest; +import com.powsybl.commons.reporter.Reporter; +import com.powsybl.iidm.network.Network; +import com.powsybl.loadflow.LoadFlowParameters; +import com.powsybl.math.matrix.DenseMatrixFactory; +import com.powsybl.openloadflow.OpenLoadFlowParameters; +import com.powsybl.openloadflow.ac.outerloop.AcLoadFlowParameters; +import com.powsybl.openloadflow.graph.EvenShiloachGraphDecrementalConnectivityFactory; +import com.powsybl.openloadflow.network.*; +import com.powsybl.security.action.SwitchAction; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; + +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Set; + +/** + * @author Anne Tilloy + */ +class LfActionTest extends AbstractConverterTest { + + @Override + @BeforeEach + public void setUp() throws IOException { + super.setUp(); + } + + @Override + @AfterEach + public void tearDown() throws IOException { + super.tearDown(); + } + + @Test + void test() throws IOException { + Network network = NodeBreakerNetworkFactory.create(); + SwitchAction switchAction = new SwitchAction("switchAction", "C", true); + var matrixFactory = new DenseMatrixFactory(); + AcSecurityAnalysis securityAnalysis = new AcSecurityAnalysis(network, matrixFactory, new EvenShiloachGraphDecrementalConnectivityFactory<>(), Collections.emptyList(), Reporter.NO_OP); + AcLoadFlowParameters acParameters = OpenLoadFlowParameters.createAcParameters(network, + new LoadFlowParameters(), new OpenLoadFlowParameters(), matrixFactory, new EvenShiloachGraphDecrementalConnectivityFactory<>(), Reporter.NO_OP, true, false); + List lfNetworks = securityAnalysis.createNetworks(Collections.emptySet(), Set.of(network.getSwitch("C")), acParameters.getNetworkParameters(), Reporter.NO_OP); + LfAction lfAction = new LfAction(switchAction, lfNetworks.get(0)); + lfAction.apply(); + } +} diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisGraphTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisGraphTest.java index f2534de64f..f1a30ab4fb 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisGraphTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisGraphTest.java @@ -157,7 +157,7 @@ List> getLoadFlowContingencies(GraphConnectivityFactory lfNetworks = securityAnalysis.createNetworks(allSwitchesToOpen, acParameters.getNetworkParameters(), Reporter.NO_OP); + List lfNetworks = securityAnalysis.createNetworks(allSwitchesToOpen, Collections.emptySet(), acParameters.getNetworkParameters(), Reporter.NO_OP); // run simulation on each network start = System.currentTimeMillis(); diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index 5856463f8f..5a4b698012 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -31,9 +31,13 @@ import com.powsybl.openloadflow.network.impl.OlfBranchResult; import com.powsybl.openloadflow.util.LoadFlowAssert; import com.powsybl.security.*; +import com.powsybl.security.action.Action; +import com.powsybl.security.action.SwitchAction; +import com.powsybl.security.condition.TrueCondition; import com.powsybl.security.detectors.DefaultLimitViolationDetector; import com.powsybl.security.monitor.StateMonitor; import com.powsybl.security.results.*; +import com.powsybl.security.strategy.OperatorStrategy; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -151,6 +155,26 @@ private SecurityAnalysisResult runSecurityAnalysis(Network network, List contingencies, List monitors, + SecurityAnalysisParameters saParameters, List operatorStrategies, + List actions, Reporter reporter) { + ContingenciesProvider provider = n -> contingencies; + SecurityAnalysisReport report = securityAnalysisProvider.run(network, + network.getVariantManager().getWorkingVariantId(), + new DefaultLimitViolationDetector(), + new LimitViolationFilter(), + computationManager, + saParameters, + provider, + Collections.emptyList(), + operatorStrategies, + actions, + monitors, + reporter) + .join(); + return report.getResult(); + } + private SecurityAnalysisResult runSecurityAnalysis(Network network, List contingencies, List monitors) { return runSecurityAnalysis(network, contingencies, monitors, new LoadFlowParameters()); } @@ -196,11 +220,22 @@ private static Optional getOptionalPostContingencyResult( .findFirst(); } + private static Optional getOptionalOperatorStrategyResult(SecurityAnalysisResult result, String operatorStrategyId) { + return result.getOperatorStrategyResults().stream() + .filter(r -> r.getOperatorStrategy().getId().equals(operatorStrategyId)) + .findFirst(); + } + private static PostContingencyResult getPostContingencyResult(SecurityAnalysisResult result, String contingencyId) { return getOptionalPostContingencyResult(result, contingencyId) .orElseThrow(); } + private static OperatorStrategyResult getOperatorStrategyResult(SecurityAnalysisResult result, String operatorStrategyId) { + return getOptionalOperatorStrategyResult(result, operatorStrategyId) + .orElseThrow(); + } + private static void assertAlmostEquals(BusResult expected, BusResult actual, double epsilon) { assertEquals(expected.getVoltageLevelId(), actual.getVoltageLevelId()); assertEquals(expected.getBusId(), actual.getBusId()); @@ -1697,4 +1732,57 @@ void reportTest() throws IOException { assertEquals(refLogExport, logExport); } + + @Test + void testSecurityAnalysisWithOperatorStrategy() { + MatrixFactory matrixFactory = new DenseMatrixFactory(); + GraphDecrementalConnectivityFactory connectivityFactory = new NaiveGraphDecrementalConnectivityFactory<>(LfBus::getNum); + securityAnalysisProvider = new OpenSecurityAnalysisProvider(matrixFactory, connectivityFactory); + + Network network = NodeBreakerNetworkFactory.create3Bars(); + network.getSwitch("C1").setOpen(true); + network.getSwitch("C2").setOpen(true); + network.getLineStream().forEach(line -> { + if (line.getCurrentLimits1().isPresent()) { + line.getCurrentLimits1().orElseThrow().setPermanentLimit(310); + } + if (line.getCurrentLimits2().isPresent()) { + line.getCurrentLimits2().orElseThrow().setPermanentLimit(310); + } + }); + + List contingencies = Stream.of("L1", "L3") + .map(id -> new Contingency(id, new BranchContingency(id))) + .collect(Collectors.toList()); + + List actions = new ArrayList<>(); + actions.add(new SwitchAction("action1", "C1", false)); + actions.add(new SwitchAction("action3", "C2", false)); + + List operatorStrategies = new ArrayList<>(); + operatorStrategies.add(new OperatorStrategy("strategyL1", "L1", new TrueCondition(), List.of("action1"))); + operatorStrategies.add(new OperatorStrategy("strategyL3", "L3", new TrueCondition(), List.of("action3"))); + + List monitors = createAllBranchesMonitors(network); + + LoadFlowParameters parameters = new LoadFlowParameters(); + parameters.setDistributedSlack(false); + setSlackBusId(parameters, "VL2_0"); + SecurityAnalysisParameters securityAnalysisParameters = new SecurityAnalysisParameters(); + securityAnalysisParameters.setLoadFlowParameters(parameters); + + SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors, securityAnalysisParameters, + operatorStrategies, actions, Reporter.NO_OP); + assertEquals(578.3, result.getPreContingencyResult().getNeworkResult().getBranchResult("L1").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(0.0, result.getPreContingencyResult().getNeworkResult().getBranchResult("L2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(292.0, result.getPreContingencyResult().getNeworkResult().getBranchResult("L3").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(0.0, getPostContingencyResult(result, "L1").getNetworkResult().getBranchResult("L2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(318.3, getPostContingencyResult(result, "L1").getNetworkResult().getBranchResult("L3").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(583.5, getOperatorStrategyResult(result, "strategyL1").getNetworkResult().getBranchResult("L2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(302.0, getOperatorStrategyResult(result, "strategyL1").getNetworkResult().getBranchResult("L3").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(0.0, getPostContingencyResult(result, "L3").getNetworkResult().getBranchResult("L2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(431.0, getPostContingencyResult(result, "L3").getNetworkResult().getBranchResult("L1").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(302.2, getOperatorStrategyResult(result, "strategyL3").getNetworkResult().getBranchResult("L2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(583.5, getOperatorStrategyResult(result, "strategyL3").getNetworkResult().getBranchResult("L1").getI1(), LoadFlowAssert.DELTA_I); + } } From 5c7c2cfb92f61c5ef050cf565521b89513b0a74c Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Wed, 17 Aug 2022 16:27:00 +0200 Subject: [PATCH 11/51] Fix some code smells. Signed-off-by: Anne Tilloy --- .../com/powsybl/openloadflow/sa/AcSecurityAnalysis.java | 9 +++------ .../java/com/powsybl/openloadflow/sa/LfActionTest.java | 5 +++++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index 3f4a381d9c..657790a409 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -30,10 +30,7 @@ import com.powsybl.openloadflow.network.util.ActivePowerDistribution; import com.powsybl.openloadflow.network.util.PreviousValueVoltageInitializer; import com.powsybl.openloadflow.util.Reports; -import com.powsybl.security.LimitViolationsResult; -import com.powsybl.security.SecurityAnalysisParameters; -import com.powsybl.security.SecurityAnalysisReport; -import com.powsybl.security.SecurityAnalysisResult; +import com.powsybl.security.*; import com.powsybl.security.action.Action; import com.powsybl.security.action.SwitchAction; import com.powsybl.security.condition.AllViolationCondition; @@ -370,13 +367,13 @@ private Optional runActionSimulation(LfNetwork network, private boolean checkCondition(OperatorStrategy operatorStrategy, LimitViolationsResult limitViolationsResult) { // FIXME: add logs. HashSet limitViolationEquipmentIds = (HashSet) limitViolationsResult.getLimitViolations().stream() - .map(limitViolation -> limitViolation.getSubjectId()).collect(Collectors.toSet()); + .map(LimitViolation::getSubjectId).collect(Collectors.toSet()); HashSet commonEquipmentIds; switch (operatorStrategy.getCondition().getType()) { case "TRUE_CONDITION": return true; case "ANY_VIOLATION_CONDITION": - return limitViolationEquipmentIds.size() > 0; + return !limitViolationEquipmentIds.isEmpty(); case "AT_LEAST_ONE_VIOLATION": AtLeastOneViolationCondition atLeastCondition = (AtLeastOneViolationCondition) operatorStrategy.getCondition(); commonEquipmentIds = (HashSet) atLeastCondition.getViolationIds().stream() diff --git a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java index edb17d4ff5..1cb5024c22 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java @@ -25,6 +25,9 @@ import java.util.List; import java.util.Set; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; + /** * @author Anne Tilloy */ @@ -52,6 +55,8 @@ void test() throws IOException { new LoadFlowParameters(), new OpenLoadFlowParameters(), matrixFactory, new EvenShiloachGraphDecrementalConnectivityFactory<>(), Reporter.NO_OP, true, false); List lfNetworks = securityAnalysis.createNetworks(Collections.emptySet(), Set.of(network.getSwitch("C")), acParameters.getNetworkParameters(), Reporter.NO_OP); LfAction lfAction = new LfAction(switchAction, lfNetworks.get(0)); + assertFalse(lfNetworks.get(0).getBranchById("C").isDisabled()); lfAction.apply(); + assertTrue(lfNetworks.get(0).getBranchById("C").isDisabled()); } } From f94e2e1cec864bce2f58aedf78e045925314b49c Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Wed, 17 Aug 2022 16:57:10 +0200 Subject: [PATCH 12/51] Support a list of actions for an operator strategy. Signed-off-by: Anne Tilloy --- .../openloadflow/network/LfAction.java | 64 ++++++++++--------- .../openloadflow/sa/AcSecurityAnalysis.java | 18 ++---- .../sa/OpenSecurityAnalysisTest.java | 7 +- 3 files changed, 48 insertions(+), 41 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index 81e80fa3af..4f3dd49c0c 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -8,10 +8,10 @@ import com.powsybl.commons.PowsyblException; import com.powsybl.openloadflow.graph.GraphConnectivity; -import com.powsybl.openloadflow.network.impl.LfSwitch; import com.powsybl.security.action.Action; import com.powsybl.security.action.SwitchAction; +import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; @@ -64,6 +64,10 @@ public LfBranch getEnabledBranch() { } public void apply() { + apply(false, Collections.emptyList()); + } + + public void apply(boolean withConnectivity, List alreadyRemovedEdges) { if (disabledBranch != null) { disabledBranch.setDisabled(true); } @@ -73,36 +77,38 @@ public void apply() { enabledBranch.getBus2().setDisabled(false); } - // update connectivity with disabled branches - List disabledBranches = network.getBranches().stream() - .filter(LfElement::isDisabled) - .collect(Collectors.toList()); - GraphConnectivity connectivity = network.getConnectivity(); - connectivity.startTemporaryChanges(); - disabledBranches.stream() - .filter(b -> b.getBus1() != null && b.getBus2() != null) - .filter(b -> !(b instanceof LfSwitch)) // FIXME - .forEach(connectivity::removeEdge); - // update connectivity with enabled branches. - if (enabledBranch != null) { - connectivity.addEdge(enabledBranch.getBus1(), enabledBranch.getBus2(), enabledBranch); - } + if (withConnectivity) { + // update connectivity with disabled branches + List disabledBranches = network.getBranches().stream() + .filter(LfElement::isDisabled) + .collect(Collectors.toList()); + GraphConnectivity connectivity = network.getConnectivity(); + connectivity.startTemporaryChanges(); + disabledBranches.stream() + .filter(b -> b.getBus1() != null && b.getBus2() != null) + .filter(b -> !alreadyRemovedEdges.contains(b.getId())) // FIXME + .forEach(connectivity::removeEdge); + // update connectivity with enabled branches. + if (enabledBranch != null) { + connectivity.addEdge(enabledBranch.getBus1(), enabledBranch.getBus2(), enabledBranch); + } - // add to contingency description buses and branches that won't be part of the main connected - // component in post contingency state - Set buses = connectivity.getSmallComponents().stream().flatMap(Set::stream).collect(Collectors.toSet()); - for (LfBus bus : buses) { - bus.setDisabled(true); - bus.getBranches().forEach(branch -> branch.setDisabled(true)); - } - connectivity.undoTemporaryChanges(); + // add to contingency description buses and branches that won't be part of the main connected + // component in post contingency state + Set buses = connectivity.getSmallComponents().stream().flatMap(Set::stream).collect(Collectors.toSet()); + for (LfBus bus : buses) { + bus.setDisabled(true); + bus.getBranches().forEach(branch -> branch.setDisabled(true)); + } + connectivity.undoTemporaryChanges(); - System.out.println("Action " + id); - for (LfBus bus : network.getBuses()) { - System.out.println("Bus " + bus.getId() + " is disabled: " + bus.isDisabled()); - } - for (LfBranch branch : network.getBranches()) { - System.out.println("Branch " + branch.getId() + " is disabled: " + branch.isDisabled()); + System.out.println("Action " + id); + for (LfBus bus : network.getBuses()) { + System.out.println("Bus " + bus.getId() + " is disabled: " + bus.isDisabled()); + } + for (LfBranch branch : network.getBranches()) { + System.out.println("Branch " + branch.getId() + " is disabled: " + branch.isDisabled()); + } } } } diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index 657790a409..04d3002fa3 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -186,14 +186,8 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List { @@ -203,8 +197,8 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List optionalOperatorStrategyResult = runActionSimulation(network, context, propagatedContingency.getContingency(), operatorStrategyByContingencyId.get(lfContingency.getId()), preContingencyLimitViolationManager, securityAnalysisParameters.getIncreasedViolationsParameters(), postContingencyResult.getLimitViolationsResult(), lfActionById, - preContingencyNetworkResult, createResultExtension); + preContingencyNetworkResult, createResultExtension, allSwitchesToClose.stream().map(sw -> sw.getId()).collect(Collectors.toList())); if (optionalOperatorStrategyResult.isPresent()) { operatorStrategyResults.add(optionalOperatorStrategyResult.get()); } @@ -316,7 +310,8 @@ private Optional runActionSimulation(LfNetwork network, LimitViolationManager preContingencyLimitViolationManager, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, LimitViolationsResult postContingencyLimitViolations, HashMap lfActionById, - PreContingencyNetworkResult preContingencyNetworkResult, boolean createResultExtension) { + PreContingencyNetworkResult preContingencyNetworkResult, boolean createResultExtension, + List allSwitchesToCloseIds) { Optional optionalOperatorStrategyResult = Optional.empty(); @@ -326,7 +321,8 @@ private Optional runActionSimulation(LfNetwork network, List operatorStrategyLfActions = operatorStrategy.getActionIds().stream() .map(id -> lfActionById.getOrDefault(id, null)).collect(Collectors.toList()); // FIXME: null as default value? - operatorStrategyLfActions.stream().forEach(LfAction::apply); + operatorStrategyLfActions.stream().limit(operatorStrategyLfActions.size() - 1).forEach(LfAction::apply); + operatorStrategyLfActions.get(operatorStrategyLfActions.size() - 1).apply(true, allSwitchesToCloseIds); // the last apply compute the final connectivity. Stopwatch stopwatch = Stopwatch.createStarted(); diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index 5a4b698012..65b10e50f0 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -1751,7 +1751,7 @@ void testSecurityAnalysisWithOperatorStrategy() { } }); - List contingencies = Stream.of("L1", "L3") + List contingencies = Stream.of("L1", "L3", "L2") .map(id -> new Contingency(id, new BranchContingency(id))) .collect(Collectors.toList()); @@ -1762,6 +1762,7 @@ void testSecurityAnalysisWithOperatorStrategy() { List operatorStrategies = new ArrayList<>(); operatorStrategies.add(new OperatorStrategy("strategyL1", "L1", new TrueCondition(), List.of("action1"))); operatorStrategies.add(new OperatorStrategy("strategyL3", "L3", new TrueCondition(), List.of("action3"))); + operatorStrategies.add(new OperatorStrategy("strategyL2", "L2", new TrueCondition(), List.of("action1", "action3"))); List monitors = createAllBranchesMonitors(network); @@ -1784,5 +1785,9 @@ void testSecurityAnalysisWithOperatorStrategy() { assertEquals(431.0, getPostContingencyResult(result, "L3").getNetworkResult().getBranchResult("L1").getI1(), LoadFlowAssert.DELTA_I); assertEquals(302.2, getOperatorStrategyResult(result, "strategyL3").getNetworkResult().getBranchResult("L2").getI1(), LoadFlowAssert.DELTA_I); assertEquals(583.5, getOperatorStrategyResult(result, "strategyL3").getNetworkResult().getBranchResult("L1").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(583.5, getPostContingencyResult(result, "L2").getNetworkResult().getBranchResult("L1").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(302.2, getPostContingencyResult(result, "L2").getNetworkResult().getBranchResult("L3").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(441.5, getOperatorStrategyResult(result, "strategyL2").getNetworkResult().getBranchResult("L1").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(441.5, getOperatorStrategyResult(result, "strategyL2").getNetworkResult().getBranchResult("L3").getI1(), LoadFlowAssert.DELTA_I); } } From 469648ab226d22cd7f8b2064723226b1d84ea2f8 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Wed, 17 Aug 2022 17:13:37 +0200 Subject: [PATCH 13/51] Fix bug. Signed-off-by: Anne Tilloy --- .../java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java | 2 +- src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index 04d3002fa3..9611f0c37e 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -321,7 +321,7 @@ private Optional runActionSimulation(LfNetwork network, List operatorStrategyLfActions = operatorStrategy.getActionIds().stream() .map(id -> lfActionById.getOrDefault(id, null)).collect(Collectors.toList()); // FIXME: null as default value? - operatorStrategyLfActions.stream().limit(operatorStrategyLfActions.size() - 1).forEach(LfAction::apply); + operatorStrategyLfActions.stream().limit((long) (operatorStrategyLfActions.size() - 1)).forEach(LfAction::apply); operatorStrategyLfActions.get(operatorStrategyLfActions.size() - 1).apply(true, allSwitchesToCloseIds); // the last apply compute the final connectivity. Stopwatch stopwatch = Stopwatch.createStarted(); diff --git a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java index 1cb5024c22..456158607e 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java @@ -56,7 +56,7 @@ void test() throws IOException { List lfNetworks = securityAnalysis.createNetworks(Collections.emptySet(), Set.of(network.getSwitch("C")), acParameters.getNetworkParameters(), Reporter.NO_OP); LfAction lfAction = new LfAction(switchAction, lfNetworks.get(0)); assertFalse(lfNetworks.get(0).getBranchById("C").isDisabled()); - lfAction.apply(); + lfAction.apply(true, Collections.emptyList()); assertTrue(lfNetworks.get(0).getBranchById("C").isDisabled()); } } From 973ab64b0d614328fe131d9722d5204c25519bc1 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Wed, 17 Aug 2022 17:47:07 +0200 Subject: [PATCH 14/51] Add unit test. Signed-off-by: Anne Tilloy --- .../sa/OpenSecurityAnalysisTest.java | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index 65b10e50f0..7e77db0213 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -33,6 +33,7 @@ import com.powsybl.security.*; import com.powsybl.security.action.Action; import com.powsybl.security.action.SwitchAction; +import com.powsybl.security.condition.AnyViolationCondition; import com.powsybl.security.condition.TrueCondition; import com.powsybl.security.detectors.DefaultLimitViolationDetector; import com.powsybl.security.monitor.StateMonitor; @@ -1790,4 +1791,61 @@ void testSecurityAnalysisWithOperatorStrategy() { assertEquals(441.5, getOperatorStrategyResult(result, "strategyL2").getNetworkResult().getBranchResult("L1").getI1(), LoadFlowAssert.DELTA_I); assertEquals(441.5, getOperatorStrategyResult(result, "strategyL2").getNetworkResult().getBranchResult("L3").getI1(), LoadFlowAssert.DELTA_I); } + + @Test + void testSecurityAnalysisWithOperatorStrategy2() { + MatrixFactory matrixFactory = new DenseMatrixFactory(); + GraphDecrementalConnectivityFactory connectivityFactory = new NaiveGraphDecrementalConnectivityFactory<>(LfBus::getNum); + securityAnalysisProvider = new OpenSecurityAnalysisProvider(matrixFactory, connectivityFactory); + + Network network = NodeBreakerNetworkFactory.create3Bars(); + network.getSwitch("C1").setOpen(true); + network.getSwitch("C2").setOpen(true); + network.getLine("L1").getCurrentLimits1().orElseThrow().setPermanentLimit(580.0); + network.getLine("L1").getCurrentLimits2().orElseThrow().setPermanentLimit(580.0); + network.getLine("L2").getCurrentLimits1().orElseThrow().setPermanentLimit(500.0); + network.getLine("L2").getCurrentLimits2().orElseThrow().setPermanentLimit(500.0); + + List contingencies = Stream.of("L1", "L3", "L2") + .map(id -> new Contingency(id, new BranchContingency(id))) + .collect(Collectors.toList()); + + List actions = new ArrayList<>(); + actions.add(new SwitchAction("action1", "C1", false)); + actions.add(new SwitchAction("action3", "C2", false)); + + List operatorStrategies = new ArrayList<>(); + operatorStrategies.add(new OperatorStrategy("strategyL1", "L1", new AnyViolationCondition(), List.of("action1"))); + operatorStrategies.add(new OperatorStrategy("strategyL3", "L3", new AnyViolationCondition(), List.of("action3"))); + operatorStrategies.add(new OperatorStrategy("strategyL2", "L2", new AnyViolationCondition(), List.of("action1", "action3"))); + + List monitors = createAllBranchesMonitors(network); + + LoadFlowParameters parameters = new LoadFlowParameters(); + parameters.setDistributedSlack(false); + setSlackBusId(parameters, "VL2_0"); + SecurityAnalysisParameters securityAnalysisParameters = new SecurityAnalysisParameters(); + securityAnalysisParameters.setLoadFlowParameters(parameters); + + SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors, securityAnalysisParameters, + operatorStrategies, actions, Reporter.NO_OP); + assertEquals(578.3, result.getPreContingencyResult().getNeworkResult().getBranchResult("L1").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(0.0, result.getPreContingencyResult().getNeworkResult().getBranchResult("L2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(292.0, result.getPreContingencyResult().getNeworkResult().getBranchResult("L3").getI1(), LoadFlowAssert.DELTA_I); + // L1 contingency + assertEquals(0.0, getPostContingencyResult(result, "L1").getNetworkResult().getBranchResult("L2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(318.3, getPostContingencyResult(result, "L1").getNetworkResult().getBranchResult("L3").getI1(), LoadFlowAssert.DELTA_I); + assertTrue(getPostContingencyResult(result, "L1").getLimitViolationsResult().getLimitViolations().isEmpty()); + assertTrue(getOptionalOperatorStrategyResult(result, "strategyL1").isEmpty()); + // L3 contingency + assertEquals(0.0, getPostContingencyResult(result, "L3").getNetworkResult().getBranchResult("L2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(431.0, getPostContingencyResult(result, "L3").getNetworkResult().getBranchResult("L1").getI1(), LoadFlowAssert.DELTA_I); + assertFalse(getPostContingencyResult(result, "L3").getLimitViolationsResult().getLimitViolations().isEmpty()); // HIGH_VOLTAGE + assertFalse(getOptionalOperatorStrategyResult(result, "strategyL3").isEmpty()); + // L2 contingency + assertEquals(583.5, getPostContingencyResult(result, "L2").getNetworkResult().getBranchResult("L1").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(302.2, getPostContingencyResult(result, "L2").getNetworkResult().getBranchResult("L3").getI1(), LoadFlowAssert.DELTA_I); + assertFalse(getPostContingencyResult(result, "L2").getLimitViolationsResult().getLimitViolations().isEmpty()); + assertFalse(getOptionalOperatorStrategyResult(result, "strategyL2").isEmpty()); // CURRENT on L1 + } } From 12c68da38be61884b97ecfcbd498fa10ce4fd76f Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Wed, 17 Aug 2022 20:13:36 +0200 Subject: [PATCH 15/51] Add unit test. Signed-off-by: Anne Tilloy --- .../openloadflow/sa/AcSecurityAnalysis.java | 39 ++++++++------- .../sa/OpenSecurityAnalysisTest.java | 50 ++++++++++++++++++- 2 files changed, 70 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index 9611f0c37e..55e549da82 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -96,8 +96,8 @@ SecurityAnalysisReport runSync(String workingVariantId, SecurityAnalysisParamete LfNetwork largestNetwork = lfNetworks.get(0); if (largestNetwork.isValid()) { HashMap lfActionById = getLfActions(largestNetwork, actions); - HashMap operatorStrategyByContingencyId = indexOperatorStrategyByContingencyId(propagatedContingencies, operatorStrategies); - result = runSimulations(largestNetwork, propagatedContingencies, acParameters, securityAnalysisParameters, operatorStrategyByContingencyId, lfActionById, allSwitchesToClose); + HashMap> operatorStrategiesByContingencyId = indexOperatorStrategiesByContingencyId(propagatedContingencies, operatorStrategies); + result = runSimulations(largestNetwork, propagatedContingencies, acParameters, securityAnalysisParameters, operatorStrategiesByContingencyId, lfActionById, allSwitchesToClose); } else { result = createNoResult(); @@ -159,21 +159,22 @@ public static HashMap getLfActions(LfNetwork network, List new LfAction(action, network)))); } - public static HashMap indexOperatorStrategyByContingencyId(List propagatedContingencies, List operatorStrategies) { + public static HashMap> indexOperatorStrategiesByContingencyId(List propagatedContingencies, + List operatorStrategies) { List contingencyIds = propagatedContingencies.stream().map(propagatedContingency -> propagatedContingency.getContingency().getId()).collect(Collectors.toList()); - HashMap operatorStrategyByContingencyId = new HashMap<>(); + HashMap> operatorStrategiesByContingencyId = new HashMap<>(); for (OperatorStrategy operatorStrategy : operatorStrategies) { if (contingencyIds.contains(operatorStrategy.getContingencyId())) { - operatorStrategyByContingencyId.put(operatorStrategy.getContingencyId(), operatorStrategy); + operatorStrategiesByContingencyId.computeIfAbsent(operatorStrategy.getContingencyId(), key -> new LinkedList<>()).add(operatorStrategy); } else { LOGGER.warn("An operator strategy linked to Contingency {} that is not present in the list of Contingencies", operatorStrategy.getContingencyId()); } } - return operatorStrategyByContingencyId; + return operatorStrategiesByContingencyId; } private SecurityAnalysisResult runSimulations(LfNetwork network, List propagatedContingencies, AcLoadFlowParameters acParameters, - SecurityAnalysisParameters securityAnalysisParameters, HashMap operatorStrategyByContingencyId, + SecurityAnalysisParameters securityAnalysisParameters, HashMap> operatorStrategiesByContingencyId, HashMap lfActionById, Set allSwitchesToClose) { LoadFlowParameters loadFlowParameters = securityAnalysisParameters.getLoadFlowParameters(); OpenLoadFlowParameters openLoadFlowParameters = OpenLoadFlowParameters.get(loadFlowParameters); @@ -236,15 +237,19 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List optionalOperatorStrategyResult = runActionSimulation(network, context, propagatedContingency.getContingency(), - operatorStrategyByContingencyId.get(lfContingency.getId()), preContingencyLimitViolationManager, - securityAnalysisParameters.getIncreasedViolationsParameters(), postContingencyResult.getLimitViolationsResult(), lfActionById, - preContingencyNetworkResult, createResultExtension, allSwitchesToClose.stream().map(sw -> sw.getId()).collect(Collectors.toList())); - if (optionalOperatorStrategyResult.isPresent()) { - operatorStrategyResults.add(optionalOperatorStrategyResult.get()); + List operatorStrategiesForThisContingency = operatorStrategiesByContingencyId.get(lfContingency.getId()); + if (operatorStrategiesForThisContingency != null) { + // we have at least an operator strategy for this contingency. + if (operatorStrategiesForThisContingency.size() == 1) { + Optional optionalOperatorStrategyResult = runActionSimulation(network, context, propagatedContingency.getContingency(), + operatorStrategiesForThisContingency.get(0), preContingencyLimitViolationManager, + securityAnalysisParameters.getIncreasedViolationsParameters(), postContingencyResult.getLimitViolationsResult(), lfActionById, + preContingencyNetworkResult, createResultExtension, allSwitchesToClose.stream().map(sw -> sw.getId()).collect(Collectors.toList())); + if (optionalOperatorStrategyResult.isPresent()) { + operatorStrategyResults.add(optionalOperatorStrategyResult.get()); + } + } else { + LOGGER.warn("A contingency has several operator strategies: not supported yet"); } } @@ -383,7 +388,7 @@ private boolean checkCondition(OperatorStrategy operatorStrategy, LimitViolation .distinct() .filter(limitViolationEquipmentIds::contains) .collect(Collectors.toSet()); - return commonEquipmentIds.equals(allCondition.getViolationIds()); + return commonEquipmentIds.equals(allCondition.getViolationIds().stream().collect(Collectors.toSet())); default: throw new UnsupportedOperationException("Unsupported condition type: " + operatorStrategy.getCondition().getType()); } diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index 7e77db0213..17dd83dc53 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -33,7 +33,9 @@ import com.powsybl.security.*; import com.powsybl.security.action.Action; import com.powsybl.security.action.SwitchAction; +import com.powsybl.security.condition.AllViolationCondition; import com.powsybl.security.condition.AnyViolationCondition; +import com.powsybl.security.condition.AtLeastOneViolationCondition; import com.powsybl.security.condition.TrueCondition; import com.powsybl.security.detectors.DefaultLimitViolationDetector; import com.powsybl.security.monitor.StateMonitor; @@ -1817,7 +1819,8 @@ void testSecurityAnalysisWithOperatorStrategy2() { List operatorStrategies = new ArrayList<>(); operatorStrategies.add(new OperatorStrategy("strategyL1", "L1", new AnyViolationCondition(), List.of("action1"))); operatorStrategies.add(new OperatorStrategy("strategyL3", "L3", new AnyViolationCondition(), List.of("action3"))); - operatorStrategies.add(new OperatorStrategy("strategyL2", "L2", new AnyViolationCondition(), List.of("action1", "action3"))); + operatorStrategies.add(new OperatorStrategy("strategyL2_1", "L2", new AtLeastOneViolationCondition(List.of("L1")), List.of("action1", "action3"))); + operatorStrategies.add(new OperatorStrategy("strategyL2_2", "L2", new AllViolationCondition(List.of("L1", "L3")), List.of("action1", "action3"))); List monitors = createAllBranchesMonitors(network); @@ -1846,6 +1849,49 @@ void testSecurityAnalysisWithOperatorStrategy2() { assertEquals(583.5, getPostContingencyResult(result, "L2").getNetworkResult().getBranchResult("L1").getI1(), LoadFlowAssert.DELTA_I); assertEquals(302.2, getPostContingencyResult(result, "L2").getNetworkResult().getBranchResult("L3").getI1(), LoadFlowAssert.DELTA_I); assertFalse(getPostContingencyResult(result, "L2").getLimitViolationsResult().getLimitViolations().isEmpty()); - assertFalse(getOptionalOperatorStrategyResult(result, "strategyL2").isEmpty()); // CURRENT on L1 + assertTrue(getOptionalOperatorStrategyResult(result, "strategyL2_1").isEmpty()); // several operator strategies: not supported yet. + assertTrue(getOptionalOperatorStrategyResult(result, "strategyL2_2").isEmpty()); // several operator strategies: not supported yet. + } + + @Test + void testSecurityAnalysisWithOperatorStrategy3() { + MatrixFactory matrixFactory = new DenseMatrixFactory(); + GraphDecrementalConnectivityFactory connectivityFactory = new NaiveGraphDecrementalConnectivityFactory<>(LfBus::getNum); + securityAnalysisProvider = new OpenSecurityAnalysisProvider(matrixFactory, connectivityFactory); + + Network network = NodeBreakerNetworkFactory.create3Bars(); + network.getSwitch("C1").setOpen(true); + network.getSwitch("C2").setOpen(true); + network.getLine("L1").getCurrentLimits1().orElseThrow().setPermanentLimit(580.0); + network.getLine("L1").getCurrentLimits2().orElseThrow().setPermanentLimit(580.0); + network.getLine("L2").getCurrentLimits1().orElseThrow().setPermanentLimit(500.0); + network.getLine("L2").getCurrentLimits2().orElseThrow().setPermanentLimit(500.0); + + List contingencies = Stream.of("L3", "L2") + .map(id -> new Contingency(id, new BranchContingency(id))) + .collect(Collectors.toList()); + + List actions = new ArrayList<>(); + actions.add(new SwitchAction("action1", "C1", false)); + actions.add(new SwitchAction("action3", "C2", false)); + + List operatorStrategies = new ArrayList<>(); + operatorStrategies.add(new OperatorStrategy("strategyL3", "L3", new AllViolationCondition(List.of("VL1", "VL2")), List.of("action3"))); + operatorStrategies.add(new OperatorStrategy("strategyL2", "L2", new AtLeastOneViolationCondition(List.of("L1", "L3")), List.of("action1", "action3"))); + + List monitors = createAllBranchesMonitors(network); + + LoadFlowParameters parameters = new LoadFlowParameters(); + parameters.setDistributedSlack(false); + setSlackBusId(parameters, "VL2_0"); + SecurityAnalysisParameters securityAnalysisParameters = new SecurityAnalysisParameters(); + securityAnalysisParameters.setLoadFlowParameters(parameters); + + SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors, securityAnalysisParameters, + operatorStrategies, actions, Reporter.NO_OP); + // L3 contingency + assertFalse(getOptionalOperatorStrategyResult(result, "strategyL3").isEmpty()); + // L2 contingency + assertFalse(getOptionalOperatorStrategyResult(result, "strategyL2").isEmpty()); } } From 8cacc54461b7f0c1fbfcd58c03c3fbdf17d18cb6 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Wed, 17 Aug 2022 20:22:43 +0200 Subject: [PATCH 16/51] Add unit test. Signed-off-by: Anne Tilloy --- src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java index 456158607e..a95a247417 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java @@ -25,8 +25,7 @@ import java.util.List; import java.util.Set; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.*; /** * @author Anne Tilloy @@ -58,5 +57,7 @@ void test() throws IOException { assertFalse(lfNetworks.get(0).getBranchById("C").isDisabled()); lfAction.apply(true, Collections.emptyList()); assertTrue(lfNetworks.get(0).getBranchById("C").isDisabled()); + assertEquals("C", lfAction.getDisabledBranch().getId()); + assertNull(lfAction.getEnabledBranch()); } } From d308bd3cf1102f6e1c93b347077e1e886cf14f1f Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Wed, 17 Aug 2022 23:43:55 +0200 Subject: [PATCH 17/51] Fix merge Signed-off-by: Geoffroy Jamgotchian --- .../graph/NaiveGraphConnectivity.java | 76 +++++++++++++++++++ .../sa/OpenSecurityAnalysisTest.java | 7 +- 2 files changed, 80 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphConnectivity.java b/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphConnectivity.java index e69de29bb2..5102772c00 100644 --- a/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphConnectivity.java +++ b/src/main/java/com/powsybl/openloadflow/graph/NaiveGraphConnectivity.java @@ -0,0 +1,76 @@ +/** + * Copyright (c) 2020, RTE (http://www.rte-france.com) + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +package com.powsybl.openloadflow.graph; + +import org.jgrapht.alg.connectivity.ConnectivityInspector; + +import java.util.Comparator; +import java.util.Deque; +import java.util.Objects; +import java.util.Set; +import java.util.function.ToIntFunction; +import java.util.stream.Collectors; + +/** + * @author Geoffroy Jamgotchian + */ +public class NaiveGraphConnectivity extends AbstractGraphConnectivity { + + private int[] components; + + private final ToIntFunction numGetter; + + public NaiveGraphConnectivity(ToIntFunction numGetter) { + this.numGetter = Objects.requireNonNull(numGetter); + } + + protected void updateComponents() { + if (components == null) { + components = new int[getGraph().vertexSet().size()]; + componentSets = new ConnectivityInspector<>(getGraph()) + .connectedSets() + .stream() + .sorted(Comparator.comparing(Set::size).reversed()) + .collect(Collectors.toList()); + for (int componentIndex = 0; componentIndex < componentSets.size(); componentIndex++) { + Set vertices = componentSets.get(componentIndex); + for (V vertex : vertices) { + components[numGetter.applyAsInt(vertex)] = componentIndex; + } + } + } + } + + @Override + protected void resetConnectivity(Deque> m) { + invalidateComponents(); + } + + @Override + protected int getQuickComponentNumber(V vertex) { + return components[numGetter.applyAsInt(vertex)]; + } + + @Override + protected void updateConnectivity(EdgeRemove edgeRemove) { + invalidateComponents(); + } + + @Override + protected void updateConnectivity(EdgeAdd edgeAdd) { + invalidateComponents(); + } + + @Override + protected void updateConnectivity(VertexAdd vertexAdd) { + invalidateComponents(); + } + + private void invalidateComponents() { + components = null; + } +} diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index 17dd83dc53..b2801ac991 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -27,6 +27,7 @@ import com.powsybl.openloadflow.OpenLoadFlowProvider; import com.powsybl.openloadflow.graph.EvenShiloachGraphDecrementalConnectivityFactory; import com.powsybl.openloadflow.graph.GraphConnectivityFactory; +import com.powsybl.openloadflow.graph.NaiveGraphConnectivityFactory; import com.powsybl.openloadflow.network.*; import com.powsybl.openloadflow.network.impl.OlfBranchResult; import com.powsybl.openloadflow.util.LoadFlowAssert; @@ -1739,7 +1740,7 @@ void reportTest() throws IOException { @Test void testSecurityAnalysisWithOperatorStrategy() { MatrixFactory matrixFactory = new DenseMatrixFactory(); - GraphDecrementalConnectivityFactory connectivityFactory = new NaiveGraphDecrementalConnectivityFactory<>(LfBus::getNum); + GraphConnectivityFactory connectivityFactory = new NaiveGraphConnectivityFactory<>(LfBus::getNum); securityAnalysisProvider = new OpenSecurityAnalysisProvider(matrixFactory, connectivityFactory); Network network = NodeBreakerNetworkFactory.create3Bars(); @@ -1797,7 +1798,7 @@ void testSecurityAnalysisWithOperatorStrategy() { @Test void testSecurityAnalysisWithOperatorStrategy2() { MatrixFactory matrixFactory = new DenseMatrixFactory(); - GraphDecrementalConnectivityFactory connectivityFactory = new NaiveGraphDecrementalConnectivityFactory<>(LfBus::getNum); + GraphConnectivityFactory connectivityFactory = new NaiveGraphConnectivityFactory<>(LfBus::getNum); securityAnalysisProvider = new OpenSecurityAnalysisProvider(matrixFactory, connectivityFactory); Network network = NodeBreakerNetworkFactory.create3Bars(); @@ -1856,7 +1857,7 @@ void testSecurityAnalysisWithOperatorStrategy2() { @Test void testSecurityAnalysisWithOperatorStrategy3() { MatrixFactory matrixFactory = new DenseMatrixFactory(); - GraphDecrementalConnectivityFactory connectivityFactory = new NaiveGraphDecrementalConnectivityFactory<>(LfBus::getNum); + GraphConnectivityFactory connectivityFactory = new NaiveGraphConnectivityFactory<>(LfBus::getNum); securityAnalysisProvider = new OpenSecurityAnalysisProvider(matrixFactory, connectivityFactory); Network network = NodeBreakerNetworkFactory.create3Bars(); From 33da1587382c7ece46e757d83eafe1b65986b6c2 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Thu, 18 Aug 2022 11:13:09 +0200 Subject: [PATCH 18/51] Increase coverage. Signed-off-by: Anne Tilloy --- .../com/powsybl/openloadflow/network/LfAction.java | 14 +++++++------- .../com/powsybl/openloadflow/sa/LfActionTest.java | 4 ++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index 4f3dd49c0c..9a7eb7847a 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -10,6 +10,8 @@ import com.powsybl.openloadflow.graph.GraphConnectivity; import com.powsybl.security.action.Action; import com.powsybl.security.action.SwitchAction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Collections; import java.util.List; @@ -22,6 +24,8 @@ */ public class LfAction { + private static final Logger LOGGER = LoggerFactory.getLogger(LfAction.class); + private final String id; private LfBranch disabledBranch; // switch to open @@ -102,13 +106,9 @@ public void apply(boolean withConnectivity, List alreadyRemovedEdges) { } connectivity.undoTemporaryChanges(); - System.out.println("Action " + id); - for (LfBus bus : network.getBuses()) { - System.out.println("Bus " + bus.getId() + " is disabled: " + bus.isDisabled()); - } - for (LfBranch branch : network.getBranches()) { - System.out.println("Branch " + branch.getId() + " is disabled: " + branch.isDisabled()); - } + LOGGER.info("Network state after action " + id); + network.getBuses().stream().forEach(bus -> LOGGER.info("LfBus " + bus.getId() + " is disabled: " + bus.isDisabled())); + network.getBranches().stream().forEach(branch -> LOGGER.info("LfBranch " + branch.getId() + " is disabled: " + branch.isDisabled())); } } } diff --git a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java index a95a247417..c44c0513b3 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java @@ -7,6 +7,7 @@ package com.powsybl.openloadflow.sa; import com.powsybl.commons.AbstractConverterTest; +import com.powsybl.commons.PowsyblException; import com.powsybl.commons.reporter.Reporter; import com.powsybl.iidm.network.Network; import com.powsybl.loadflow.LoadFlowParameters; @@ -59,5 +60,8 @@ void test() throws IOException { assertTrue(lfNetworks.get(0).getBranchById("C").isDisabled()); assertEquals("C", lfAction.getDisabledBranch().getId()); assertNull(lfAction.getEnabledBranch()); + + SwitchAction switchAction2 = new SwitchAction("switchAction", "S", true); + assertThrows(PowsyblException.class, () -> new LfAction(switchAction2, lfNetworks.get(0)), "Branch S not found in the network"); } } From bddb21a59697ec05e50456c88cc6231e19a6ebf3 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Thu, 18 Aug 2022 11:31:10 +0200 Subject: [PATCH 19/51] Fix code smells. Signed-off-by: Anne Tilloy --- .../powsybl/openloadflow/network/LfAction.java | 6 +++--- .../openloadflow/sa/AcSecurityAnalysis.java | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index 9a7eb7847a..ba2504b04d 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -106,9 +106,9 @@ public void apply(boolean withConnectivity, List alreadyRemovedEdges) { } connectivity.undoTemporaryChanges(); - LOGGER.info("Network state after action " + id); - network.getBuses().stream().forEach(bus -> LOGGER.info("LfBus " + bus.getId() + " is disabled: " + bus.isDisabled())); - network.getBranches().stream().forEach(branch -> LOGGER.info("LfBranch " + branch.getId() + " is disabled: " + branch.isDisabled())); + LOGGER.info("Network state after action {}", id); + network.getBuses().stream().forEach(bus -> LOGGER.info("LfBus {} is disabled: {}", bus.getId(), bus.isDisabled())); + network.getBranches().stream().forEach(branch -> LOGGER.info("LfBranch {} is disabled: {}", branch.getId(), branch.isDisabled())); } } } diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index 55e549da82..c95041afe0 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -95,8 +95,8 @@ SecurityAnalysisReport runSync(String workingVariantId, SecurityAnalysisParamete } else { LfNetwork largestNetwork = lfNetworks.get(0); if (largestNetwork.isValid()) { - HashMap lfActionById = getLfActions(largestNetwork, actions); - HashMap> operatorStrategiesByContingencyId = indexOperatorStrategiesByContingencyId(propagatedContingencies, operatorStrategies); + Map lfActionById = getLfActions(largestNetwork, actions); + Map> operatorStrategiesByContingencyId = indexOperatorStrategiesByContingencyId(propagatedContingencies, operatorStrategies); result = runSimulations(largestNetwork, propagatedContingencies, acParameters, securityAnalysisParameters, operatorStrategiesByContingencyId, lfActionById, allSwitchesToClose); } else { @@ -155,11 +155,11 @@ public static void getAllSwitchesToOperate(Network network, List actions }); } - public static HashMap getLfActions(LfNetwork network, List actions) { - return new HashMap(actions.stream().collect(Collectors.toMap(Action::getId, action -> new LfAction(action, network)))); + public static Map getLfActions(LfNetwork network, List actions) { + return new HashMap<>(actions.stream().collect(Collectors.toMap(Action::getId, action -> new LfAction(action, network)))); } - public static HashMap> indexOperatorStrategiesByContingencyId(List propagatedContingencies, + public static Map> indexOperatorStrategiesByContingencyId(List propagatedContingencies, List operatorStrategies) { List contingencyIds = propagatedContingencies.stream().map(propagatedContingency -> propagatedContingency.getContingency().getId()).collect(Collectors.toList()); HashMap> operatorStrategiesByContingencyId = new HashMap<>(); @@ -174,8 +174,8 @@ public static HashMap> indexOperatorStrategiesByC } private SecurityAnalysisResult runSimulations(LfNetwork network, List propagatedContingencies, AcLoadFlowParameters acParameters, - SecurityAnalysisParameters securityAnalysisParameters, HashMap> operatorStrategiesByContingencyId, - HashMap lfActionById, Set allSwitchesToClose) { + SecurityAnalysisParameters securityAnalysisParameters, Map> operatorStrategiesByContingencyId, + Map lfActionById, Set allSwitchesToClose) { LoadFlowParameters loadFlowParameters = securityAnalysisParameters.getLoadFlowParameters(); OpenLoadFlowParameters openLoadFlowParameters = OpenLoadFlowParameters.get(loadFlowParameters); OpenSecurityAnalysisParameters openSecurityAnalysisParameters = OpenSecurityAnalysisParameters.getOrDefault(securityAnalysisParameters); @@ -244,7 +244,7 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List optionalOperatorStrategyResult = runActionSimulation(network, context, propagatedContingency.getContingency(), operatorStrategiesForThisContingency.get(0), preContingencyLimitViolationManager, securityAnalysisParameters.getIncreasedViolationsParameters(), postContingencyResult.getLimitViolationsResult(), lfActionById, - preContingencyNetworkResult, createResultExtension, allSwitchesToClose.stream().map(sw -> sw.getId()).collect(Collectors.toList())); + preContingencyNetworkResult, createResultExtension, allSwitchesToClose.stream().map(Switch::getId).collect(Collectors.toList())); if (optionalOperatorStrategyResult.isPresent()) { operatorStrategyResults.add(optionalOperatorStrategyResult.get()); } @@ -314,7 +314,7 @@ private PostContingencyResult runPostContingencySimulation(LfNetwork network, Ac private Optional runActionSimulation(LfNetwork network, AcLoadFlowContext context, Contingency contingency, OperatorStrategy operatorStrategy, LimitViolationManager preContingencyLimitViolationManager, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, - LimitViolationsResult postContingencyLimitViolations, HashMap lfActionById, + LimitViolationsResult postContingencyLimitViolations, Map lfActionById, PreContingencyNetworkResult preContingencyNetworkResult, boolean createResultExtension, List allSwitchesToCloseIds) { From 1b36f587561ef8f6f8e17eb0720e942af29f890a Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Thu, 18 Aug 2022 23:23:21 +0200 Subject: [PATCH 20/51] Cleanup Signed-off-by: Geoffroy Jamgotchian --- .../openloadflow/network/LfAction.java | 6 +- .../openloadflow/sa/AcSecurityAnalysis.java | 67 +++++++++++-------- 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index ba2504b04d..21ba0d0062 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -38,7 +38,7 @@ public LfAction(Action action, LfNetwork network) { this.id = Objects.requireNonNull(action.getId()); this.network = Objects.requireNonNull(network); switch (action.getType()) { - case "SWITCH": + case SwitchAction.NAME: SwitchAction switchAction = (SwitchAction) action; LfBranch branch = network.getBranchById(switchAction.getSwitchId()); if (branch == null) { @@ -107,8 +107,8 @@ public void apply(boolean withConnectivity, List alreadyRemovedEdges) { connectivity.undoTemporaryChanges(); LOGGER.info("Network state after action {}", id); - network.getBuses().stream().forEach(bus -> LOGGER.info("LfBus {} is disabled: {}", bus.getId(), bus.isDisabled())); - network.getBranches().stream().forEach(branch -> LOGGER.info("LfBranch {} is disabled: {}", branch.getId(), branch.isDisabled())); + network.getBuses().forEach(bus -> LOGGER.info("LfBus {} is disabled: {}", bus.getId(), bus.isDisabled())); + network.getBranches().forEach(branch -> LOGGER.info("LfBranch {} is disabled: {}", branch.getId(), branch.isDisabled())); } } } diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index c95041afe0..137b022351 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -7,6 +7,7 @@ package com.powsybl.openloadflow.sa; import com.google.common.base.Stopwatch; +import com.powsybl.commons.PowsyblException; import com.powsybl.commons.reporter.Reporter; import com.powsybl.computation.ComputationManager; import com.powsybl.contingency.ContingenciesProvider; @@ -34,7 +35,9 @@ import com.powsybl.security.action.Action; import com.powsybl.security.action.SwitchAction; import com.powsybl.security.condition.AllViolationCondition; +import com.powsybl.security.condition.AnyViolationCondition; import com.powsybl.security.condition.AtLeastOneViolationCondition; +import com.powsybl.security.condition.TrueCondition; import com.powsybl.security.monitor.StateMonitor; import com.powsybl.security.results.NetworkResult; import com.powsybl.security.results.OperatorStrategyResult; @@ -95,10 +98,9 @@ SecurityAnalysisReport runSync(String workingVariantId, SecurityAnalysisParamete } else { LfNetwork largestNetwork = lfNetworks.get(0); if (largestNetwork.isValid()) { - Map lfActionById = getLfActions(largestNetwork, actions); + Map lfActionsById = createLfActions(largestNetwork, actions); Map> operatorStrategiesByContingencyId = indexOperatorStrategiesByContingencyId(propagatedContingencies, operatorStrategies); - result = runSimulations(largestNetwork, propagatedContingencies, acParameters, securityAnalysisParameters, operatorStrategiesByContingencyId, lfActionById, allSwitchesToClose); - + result = runSimulations(largestNetwork, propagatedContingencies, acParameters, securityAnalysisParameters, operatorStrategiesByContingencyId, lfActionsById, allSwitchesToClose); } else { result = createNoResult(); } @@ -143,7 +145,7 @@ public static void distributedMismatch(LfNetwork network, double mismatch, LoadF } public static void getAllSwitchesToOperate(Network network, List actions, Set allSwitchesToClose, Set allSwitchesToOpen) { - actions.stream().filter(action -> action.getType().equals("SWITCH")) + actions.stream().filter(action -> action.getType().equals(SwitchAction.NAME)) .map(action -> ((SwitchAction) action).getSwitchId()) .forEach(id -> { Switch sw = network.getSwitch(id); @@ -155,17 +157,17 @@ public static void getAllSwitchesToOperate(Network network, List actions }); } - public static Map getLfActions(LfNetwork network, List actions) { - return new HashMap<>(actions.stream().collect(Collectors.toMap(Action::getId, action -> new LfAction(action, network)))); + private static Map createLfActions(LfNetwork network, List actions) { + return actions.stream().collect(Collectors.toMap(Action::getId, action -> new LfAction(action, network))); } - public static Map> indexOperatorStrategiesByContingencyId(List propagatedContingencies, - List operatorStrategies) { - List contingencyIds = propagatedContingencies.stream().map(propagatedContingency -> propagatedContingency.getContingency().getId()).collect(Collectors.toList()); - HashMap> operatorStrategiesByContingencyId = new HashMap<>(); + private static Map> indexOperatorStrategiesByContingencyId(List propagatedContingencies, + List operatorStrategies) { + Set contingencyIds = propagatedContingencies.stream().map(propagatedContingency -> propagatedContingency.getContingency().getId()).collect(Collectors.toSet()); + Map> operatorStrategiesByContingencyId = new HashMap<>(); for (OperatorStrategy operatorStrategy : operatorStrategies) { if (contingencyIds.contains(operatorStrategy.getContingencyId())) { - operatorStrategiesByContingencyId.computeIfAbsent(operatorStrategy.getContingencyId(), key -> new LinkedList<>()).add(operatorStrategy); + operatorStrategiesByContingencyId.computeIfAbsent(operatorStrategy.getContingencyId(), key -> new ArrayList<>()).add(operatorStrategy); } else { LOGGER.warn("An operator strategy linked to Contingency {} that is not present in the list of Contingencies", operatorStrategy.getContingencyId()); } @@ -317,16 +319,23 @@ private Optional runActionSimulation(LfNetwork network, LimitViolationsResult postContingencyLimitViolations, Map lfActionById, PreContingencyNetworkResult preContingencyNetworkResult, boolean createResultExtension, List allSwitchesToCloseIds) { - - Optional optionalOperatorStrategyResult = Optional.empty(); + OperatorStrategyResult operatorStrategyResult = null; if (checkCondition(operatorStrategy, postContingencyLimitViolations)) { LOGGER.info("Start operator strategy {} after contingency '{}' simulation on network {}", operatorStrategy.getId(), operatorStrategy.getContingencyId(), network); List operatorStrategyLfActions = operatorStrategy.getActionIds().stream() - .map(id -> lfActionById.getOrDefault(id, null)).collect(Collectors.toList()); // FIXME: null as default value? - operatorStrategyLfActions.stream().limit((long) (operatorStrategyLfActions.size() - 1)).forEach(LfAction::apply); + .map(id -> { + LfAction lfAction = lfActionById.get(id); + if (lfAction == null) { + throw new PowsyblException("Action '" + id + "' of operator strategy '" + operatorStrategy.getId() + "' not found"); + } + return lfAction; + }) + .collect(Collectors.toList()); + // FIXME to remove when connectivity will be fixed + operatorStrategyLfActions.stream().limit((long) operatorStrategyLfActions.size() - 1).forEach(LfAction::apply); operatorStrategyLfActions.get(operatorStrategyLfActions.size() - 1).apply(true, allSwitchesToCloseIds); // the last apply compute the final connectivity. Stopwatch stopwatch = Stopwatch.createStarted(); @@ -354,41 +363,43 @@ private Optional runActionSimulation(LfNetwork network, LOGGER.info("Operator strategy {} after contingency '{}' simulation done on network {} in {} ms", operatorStrategy.getId(), operatorStrategy.getContingencyId(), network, stopwatch.elapsed(TimeUnit.MILLISECONDS)); - optionalOperatorStrategyResult = Optional.of(new OperatorStrategyResult(operatorStrategy, + operatorStrategyResult = new OperatorStrategyResult(operatorStrategy, new LimitViolationsResult(postActionsComputationOk, postActionsViolationManager.getLimitViolations()), new NetworkResult(postActionsNetworkResult.getBranchResults(), postActionsNetworkResult.getBusResults(), - postActionsNetworkResult.getThreeWindingsTransformerResults()))); + postActionsNetworkResult.getThreeWindingsTransformerResults())); } - return optionalOperatorStrategyResult; + return Optional.ofNullable(operatorStrategyResult); } private boolean checkCondition(OperatorStrategy operatorStrategy, LimitViolationsResult limitViolationsResult) { // FIXME: add logs. - HashSet limitViolationEquipmentIds = (HashSet) limitViolationsResult.getLimitViolations().stream() - .map(LimitViolation::getSubjectId).collect(Collectors.toSet()); - HashSet commonEquipmentIds; + Set limitViolationEquipmentIds = limitViolationsResult.getLimitViolations().stream() + .map(LimitViolation::getSubjectId) + .collect(Collectors.toSet()); switch (operatorStrategy.getCondition().getType()) { - case "TRUE_CONDITION": + case TrueCondition.NAME: return true; - case "ANY_VIOLATION_CONDITION": + case AnyViolationCondition.NAME: return !limitViolationEquipmentIds.isEmpty(); - case "AT_LEAST_ONE_VIOLATION": + case AtLeastOneViolationCondition.NAME: { AtLeastOneViolationCondition atLeastCondition = (AtLeastOneViolationCondition) operatorStrategy.getCondition(); - commonEquipmentIds = (HashSet) atLeastCondition.getViolationIds().stream() + Set commonEquipmentIds = atLeastCondition.getViolationIds().stream() .distinct() .filter(limitViolationEquipmentIds::contains) .collect(Collectors.toSet()); return !commonEquipmentIds.isEmpty(); - case "ALL_VIOLATION": + } + case AllViolationCondition.NAME: { AllViolationCondition allCondition = (AllViolationCondition) operatorStrategy.getCondition(); - commonEquipmentIds = (HashSet) allCondition.getViolationIds().stream() + Set commonEquipmentIds = allCondition.getViolationIds().stream() .distinct() .filter(limitViolationEquipmentIds::contains) .collect(Collectors.toSet()); - return commonEquipmentIds.equals(allCondition.getViolationIds().stream().collect(Collectors.toSet())); + return commonEquipmentIds.equals(new HashSet<>(allCondition.getViolationIds())); + } default: throw new UnsupportedOperationException("Unsupported condition type: " + operatorStrategy.getCondition().getType()); } From fb97b1dfa7f2ae2afcd1be7dae5c513cdcd27148 Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Thu, 18 Aug 2022 23:28:37 +0200 Subject: [PATCH 21/51] Cleanup Signed-off-by: Geoffroy Jamgotchian --- .../sa/OpenSecurityAnalysisTest.java | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index b2801ac991..d3774ee0da 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -1759,14 +1759,12 @@ void testSecurityAnalysisWithOperatorStrategy() { .map(id -> new Contingency(id, new BranchContingency(id))) .collect(Collectors.toList()); - List actions = new ArrayList<>(); - actions.add(new SwitchAction("action1", "C1", false)); - actions.add(new SwitchAction("action3", "C2", false)); + List actions = List.of(new SwitchAction("action1", "C1", false), + new SwitchAction("action3", "C2", false)); - List operatorStrategies = new ArrayList<>(); - operatorStrategies.add(new OperatorStrategy("strategyL1", "L1", new TrueCondition(), List.of("action1"))); - operatorStrategies.add(new OperatorStrategy("strategyL3", "L3", new TrueCondition(), List.of("action3"))); - operatorStrategies.add(new OperatorStrategy("strategyL2", "L2", new TrueCondition(), List.of("action1", "action3"))); + List operatorStrategies = List.of(new OperatorStrategy("strategyL1", "L1", new TrueCondition(), List.of("action1")), + new OperatorStrategy("strategyL3", "L3", new TrueCondition(), List.of("action3")), + new OperatorStrategy("strategyL2", "L2", new TrueCondition(), List.of("action1", "action3"))); List monitors = createAllBranchesMonitors(network); @@ -1813,15 +1811,13 @@ void testSecurityAnalysisWithOperatorStrategy2() { .map(id -> new Contingency(id, new BranchContingency(id))) .collect(Collectors.toList()); - List actions = new ArrayList<>(); - actions.add(new SwitchAction("action1", "C1", false)); - actions.add(new SwitchAction("action3", "C2", false)); + List actions = List.of(new SwitchAction("action1", "C1", false), + new SwitchAction("action3", "C2", false)); - List operatorStrategies = new ArrayList<>(); - operatorStrategies.add(new OperatorStrategy("strategyL1", "L1", new AnyViolationCondition(), List.of("action1"))); - operatorStrategies.add(new OperatorStrategy("strategyL3", "L3", new AnyViolationCondition(), List.of("action3"))); - operatorStrategies.add(new OperatorStrategy("strategyL2_1", "L2", new AtLeastOneViolationCondition(List.of("L1")), List.of("action1", "action3"))); - operatorStrategies.add(new OperatorStrategy("strategyL2_2", "L2", new AllViolationCondition(List.of("L1", "L3")), List.of("action1", "action3"))); + List operatorStrategies = List.of(new OperatorStrategy("strategyL1", "L1", new AnyViolationCondition(), List.of("action1")), + new OperatorStrategy("strategyL3", "L3", new AnyViolationCondition(), List.of("action3")), + new OperatorStrategy("strategyL2_1", "L2", new AtLeastOneViolationCondition(List.of("L1")), List.of("action1", "action3")), + new OperatorStrategy("strategyL2_2", "L2", new AllViolationCondition(List.of("L1", "L3")), List.of("action1", "action3"))); List monitors = createAllBranchesMonitors(network); @@ -1872,13 +1868,11 @@ void testSecurityAnalysisWithOperatorStrategy3() { .map(id -> new Contingency(id, new BranchContingency(id))) .collect(Collectors.toList()); - List actions = new ArrayList<>(); - actions.add(new SwitchAction("action1", "C1", false)); - actions.add(new SwitchAction("action3", "C2", false)); + List actions = List.of(new SwitchAction("action1", "C1", false), + new SwitchAction("action3", "C2", false)); - List operatorStrategies = new ArrayList<>(); - operatorStrategies.add(new OperatorStrategy("strategyL3", "L3", new AllViolationCondition(List.of("VL1", "VL2")), List.of("action3"))); - operatorStrategies.add(new OperatorStrategy("strategyL2", "L2", new AtLeastOneViolationCondition(List.of("L1", "L3")), List.of("action1", "action3"))); + List operatorStrategies = List.of(new OperatorStrategy("strategyL3", "L3", new AllViolationCondition(List.of("VL1", "VL2")), List.of("action3")), + new OperatorStrategy("strategyL2", "L2", new AtLeastOneViolationCondition(List.of("L1", "L3")), List.of("action1", "action3"))); List monitors = createAllBranchesMonitors(network); From 5940385946b23e96210635a0b0d7aa62f8ca4c3c Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Fri, 19 Aug 2022 10:20:33 +0200 Subject: [PATCH 22/51] Apply review comments. Signed-off-by: Anne Tilloy --- .../openloadflow/sa/AcSecurityAnalysis.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index 137b022351..4c481b8316 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -146,12 +146,13 @@ public static void distributedMismatch(LfNetwork network, double mismatch, LoadF public static void getAllSwitchesToOperate(Network network, List actions, Set allSwitchesToClose, Set allSwitchesToOpen) { actions.stream().filter(action -> action.getType().equals(SwitchAction.NAME)) - .map(action -> ((SwitchAction) action).getSwitchId()) - .forEach(id -> { - Switch sw = network.getSwitch(id); - if (sw.isOpen()) { + .forEach(action -> { + String switchId = ((SwitchAction) action).getSwitchId(); + Switch sw = network.getSwitch(switchId); + Boolean toOpen = ((SwitchAction) action).isOpen(); + if (sw.isOpen() && !toOpen) { // the switch is open and the action will close it. allSwitchesToClose.add(sw); - } else { + } else if (!sw.isOpen() && toOpen) { // the switch is closed and the action will open it. allSwitchesToOpen.add(sw); } }); @@ -169,7 +170,8 @@ private static Map> indexOperatorStrategiesByCont if (contingencyIds.contains(operatorStrategy.getContingencyId())) { operatorStrategiesByContingencyId.computeIfAbsent(operatorStrategy.getContingencyId(), key -> new ArrayList<>()).add(operatorStrategy); } else { - LOGGER.warn("An operator strategy linked to Contingency {} that is not present in the list of Contingencies", operatorStrategy.getContingencyId()); + throw new PowsyblException("An operator strategy associated to contingency '" + operatorStrategy.getContingencyId() + + "' but this contingency is not present in the list of contingencies"); } } return operatorStrategiesByContingencyId; @@ -334,9 +336,10 @@ private Optional runActionSimulation(LfNetwork network, return lfAction; }) .collect(Collectors.toList()); - // FIXME to remove when connectivity will be fixed + // apply actions, the last apply compute the final connectivity. + // FIXME: as an edge cannot be removed twice, we need as argument allSwitchesToCloseIds. operatorStrategyLfActions.stream().limit((long) operatorStrategyLfActions.size() - 1).forEach(LfAction::apply); - operatorStrategyLfActions.get(operatorStrategyLfActions.size() - 1).apply(true, allSwitchesToCloseIds); // the last apply compute the final connectivity. + operatorStrategyLfActions.get(operatorStrategyLfActions.size() - 1).apply(true, allSwitchesToCloseIds); Stopwatch stopwatch = Stopwatch.createStarted(); @@ -347,6 +350,8 @@ private Optional runActionSimulation(LfNetwork network, boolean postActionsComputationOk = postActionsLoadFlowResult.getNewtonRaphsonStatus() == NewtonRaphsonStatus.CONVERGED; // FIXME: to be checked. + // the violation manager compares the post action violations with the pre-contingency violations. Is it what we want? + // the flow transfer is still computed for the branch in contingency and with the pre-contingency state as reference. Is it what we want? var postActionsViolationManager = new LimitViolationManager(preContingencyLimitViolationManager, violationsParameters); var postActionsNetworkResult = new PostContingencyNetworkResult(network, monitorIndex, createResultExtension, preContingencyNetworkResult, contingency); From 5e04f886f2c19a1f410ff3241b74409759ada9da Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Fri, 19 Aug 2022 11:27:16 +0200 Subject: [PATCH 23/51] Fixes after review. Signed-off-by: Anne Tilloy --- .../openloadflow/sa/AcSecurityAnalysis.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index 4c481b8316..f7e2f44452 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -245,10 +245,10 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List optionalOperatorStrategyResult = runActionSimulation(network, context, propagatedContingency.getContingency(), + Optional optionalOperatorStrategyResult = runActionSimulation(network, context, operatorStrategiesForThisContingency.get(0), preContingencyLimitViolationManager, securityAnalysisParameters.getIncreasedViolationsParameters(), postContingencyResult.getLimitViolationsResult(), lfActionById, - preContingencyNetworkResult, createResultExtension, allSwitchesToClose.stream().map(Switch::getId).collect(Collectors.toList())); + createResultExtension, allSwitchesToClose.stream().map(Switch::getId).collect(Collectors.toList())); if (optionalOperatorStrategyResult.isPresent()) { operatorStrategyResults.add(optionalOperatorStrategyResult.get()); } @@ -315,12 +315,11 @@ private PostContingencyResult runPostContingencySimulation(LfNetwork network, Ac postContingencyNetworkResult.getThreeWindingsTransformerResults()); } - private Optional runActionSimulation(LfNetwork network, AcLoadFlowContext context, Contingency contingency, OperatorStrategy operatorStrategy, + private Optional runActionSimulation(LfNetwork network, AcLoadFlowContext context, OperatorStrategy operatorStrategy, LimitViolationManager preContingencyLimitViolationManager, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, LimitViolationsResult postContingencyLimitViolations, Map lfActionById, - PreContingencyNetworkResult preContingencyNetworkResult, boolean createResultExtension, - List allSwitchesToCloseIds) { + boolean createResultExtension, List allSwitchesToCloseIds) { OperatorStrategyResult operatorStrategyResult = null; if (checkCondition(operatorStrategy, postContingencyLimitViolations)) { @@ -349,11 +348,8 @@ private Optional runActionSimulation(LfNetwork network, .run(); boolean postActionsComputationOk = postActionsLoadFlowResult.getNewtonRaphsonStatus() == NewtonRaphsonStatus.CONVERGED; - // FIXME: to be checked. - // the violation manager compares the post action violations with the pre-contingency violations. Is it what we want? - // the flow transfer is still computed for the branch in contingency and with the pre-contingency state as reference. Is it what we want? var postActionsViolationManager = new LimitViolationManager(preContingencyLimitViolationManager, violationsParameters); - var postActionsNetworkResult = new PostContingencyNetworkResult(network, monitorIndex, createResultExtension, preContingencyNetworkResult, contingency); + var postActionsNetworkResult = new PreContingencyNetworkResult(network, monitorIndex, createResultExtension); if (postActionsComputationOk) { // update network result From f37978fbc034de07a964f5812ff09d0d6cf89d29 Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Fri, 26 Aug 2022 22:03:16 +0200 Subject: [PATCH 24/51] Clean Signed-off-by: Geoffroy Jamgotchian --- .../powsybl/openloadflow/sa/AcSecurityAnalysis.java | 12 +++++------- .../com/powsybl/openloadflow/sa/LfActionTest.java | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index f7e2f44452..8a0a443223 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -144,12 +144,12 @@ public static void distributedMismatch(LfNetwork network, double mismatch, LoadF } } - public static void getAllSwitchesToOperate(Network network, List actions, Set allSwitchesToClose, Set allSwitchesToOpen) { + private static void getAllSwitchesToOperate(Network network, List actions, Set allSwitchesToClose, Set allSwitchesToOpen) { actions.stream().filter(action -> action.getType().equals(SwitchAction.NAME)) .forEach(action -> { String switchId = ((SwitchAction) action).getSwitchId(); Switch sw = network.getSwitch(switchId); - Boolean toOpen = ((SwitchAction) action).isOpen(); + boolean toOpen = ((SwitchAction) action).isOpen(); if (sw.isOpen() && !toOpen) { // the switch is open and the action will close it. allSwitchesToClose.add(sw); } else if (!sw.isOpen() && toOpen) { // the switch is closed and the action will open it. @@ -245,13 +245,11 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List optionalOperatorStrategyResult = runActionSimulation(network, context, + runActionSimulation(network, context, operatorStrategiesForThisContingency.get(0), preContingencyLimitViolationManager, securityAnalysisParameters.getIncreasedViolationsParameters(), postContingencyResult.getLimitViolationsResult(), lfActionById, - createResultExtension, allSwitchesToClose.stream().map(Switch::getId).collect(Collectors.toList())); - if (optionalOperatorStrategyResult.isPresent()) { - operatorStrategyResults.add(optionalOperatorStrategyResult.get()); - } + createResultExtension, allSwitchesToClose.stream().map(Switch::getId).collect(Collectors.toList())) + .ifPresent(operatorStrategyResults::add); } else { LOGGER.warn("A contingency has several operator strategies: not supported yet"); } diff --git a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java index c44c0513b3..8ed4d24a2f 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java @@ -46,7 +46,7 @@ public void tearDown() throws IOException { } @Test - void test() throws IOException { + void test() { Network network = NodeBreakerNetworkFactory.create(); SwitchAction switchAction = new SwitchAction("switchAction", "C", true); var matrixFactory = new DenseMatrixFactory(); From 185ae3e7b1e0276fbc3f48fb0c9b2d17fbb97e35 Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Fri, 26 Aug 2022 22:05:18 +0200 Subject: [PATCH 25/51] Remove workaround Signed-off-by: Geoffroy Jamgotchian --- .../java/com/powsybl/openloadflow/network/LfAction.java | 6 ++---- .../com/powsybl/openloadflow/sa/AcSecurityAnalysis.java | 2 +- src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java | 2 +- 3 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index 21ba0d0062..b0fd307810 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -13,7 +13,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.Collections; import java.util.List; import java.util.Objects; import java.util.Set; @@ -68,10 +67,10 @@ public LfBranch getEnabledBranch() { } public void apply() { - apply(false, Collections.emptyList()); + apply(false); } - public void apply(boolean withConnectivity, List alreadyRemovedEdges) { + public void apply(boolean withConnectivity) { if (disabledBranch != null) { disabledBranch.setDisabled(true); } @@ -90,7 +89,6 @@ public void apply(boolean withConnectivity, List alreadyRemovedEdges) { connectivity.startTemporaryChanges(); disabledBranches.stream() .filter(b -> b.getBus1() != null && b.getBus2() != null) - .filter(b -> !alreadyRemovedEdges.contains(b.getId())) // FIXME .forEach(connectivity::removeEdge); // update connectivity with enabled branches. if (enabledBranch != null) { diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index 8a0a443223..15cf573bc9 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -336,7 +336,7 @@ private Optional runActionSimulation(LfNetwork network, // apply actions, the last apply compute the final connectivity. // FIXME: as an edge cannot be removed twice, we need as argument allSwitchesToCloseIds. operatorStrategyLfActions.stream().limit((long) operatorStrategyLfActions.size() - 1).forEach(LfAction::apply); - operatorStrategyLfActions.get(operatorStrategyLfActions.size() - 1).apply(true, allSwitchesToCloseIds); + operatorStrategyLfActions.get(operatorStrategyLfActions.size() - 1).apply(true); Stopwatch stopwatch = Stopwatch.createStarted(); diff --git a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java index 8ed4d24a2f..8257868d3b 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java @@ -56,7 +56,7 @@ void test() { List lfNetworks = securityAnalysis.createNetworks(Collections.emptySet(), Set.of(network.getSwitch("C")), acParameters.getNetworkParameters(), Reporter.NO_OP); LfAction lfAction = new LfAction(switchAction, lfNetworks.get(0)); assertFalse(lfNetworks.get(0).getBranchById("C").isDisabled()); - lfAction.apply(true, Collections.emptyList()); + lfAction.apply(true); assertTrue(lfNetworks.get(0).getBranchById("C").isDisabled()); assertEquals("C", lfAction.getDisabledBranch().getId()); assertNull(lfAction.getEnabledBranch()); From bf89e632e5598d616ec28ff3f81571e88f697779 Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Fri, 26 Aug 2022 22:15:59 +0200 Subject: [PATCH 26/51] Refactoring Signed-off-by: Geoffroy Jamgotchian --- .../openloadflow/network/LfAction.java | 61 ++++++++----------- .../openloadflow/sa/AcSecurityAnalysis.java | 6 +- .../powsybl/openloadflow/sa/LfActionTest.java | 2 +- 3 files changed, 29 insertions(+), 40 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index b0fd307810..d2f0384afe 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -31,11 +31,9 @@ public class LfAction { private LfBranch enabledBranch; // switch to close - private LfNetwork network; - public LfAction(Action action, LfNetwork network) { this.id = Objects.requireNonNull(action.getId()); - this.network = Objects.requireNonNull(network); + Objects.requireNonNull(network); switch (action.getType()) { case SwitchAction.NAME: SwitchAction switchAction = (SwitchAction) action; @@ -66,47 +64,40 @@ public LfBranch getEnabledBranch() { return enabledBranch; } - public void apply() { - apply(false); + public static void apply(List actions, LfNetwork network) { + Objects.requireNonNull(actions); + Objects.requireNonNull(network); + + var connectivity = network.getConnectivity(); + connectivity.startTemporaryChanges(); + + for (LfAction action : actions) { + action.apply(connectivity); + } + + Set buses = connectivity.getSmallComponents().stream().flatMap(Set::stream).collect(Collectors.toSet()); + for (LfBus bus : buses) { + bus.setDisabled(true); + bus.getBranches().forEach(branch -> branch.setDisabled(true)); + } + connectivity.undoTemporaryChanges(); + + network.getBuses().forEach(bus -> LOGGER.info("LfBus {} is disabled: {}", bus.getId(), bus.isDisabled())); + network.getBranches().forEach(branch -> LOGGER.info("LfBranch {} is disabled: {}", branch.getId(), branch.isDisabled())); } - public void apply(boolean withConnectivity) { + public void apply(GraphConnectivity connectivity) { if (disabledBranch != null) { disabledBranch.setDisabled(true); + if (disabledBranch.getBus1() != null && disabledBranch.getBus2() != null) { + connectivity.removeEdge(disabledBranch); + } } if (enabledBranch != null) { enabledBranch.setDisabled(false); enabledBranch.getBus1().setDisabled(false); enabledBranch.getBus2().setDisabled(false); - } - - if (withConnectivity) { - // update connectivity with disabled branches - List disabledBranches = network.getBranches().stream() - .filter(LfElement::isDisabled) - .collect(Collectors.toList()); - GraphConnectivity connectivity = network.getConnectivity(); - connectivity.startTemporaryChanges(); - disabledBranches.stream() - .filter(b -> b.getBus1() != null && b.getBus2() != null) - .forEach(connectivity::removeEdge); - // update connectivity with enabled branches. - if (enabledBranch != null) { - connectivity.addEdge(enabledBranch.getBus1(), enabledBranch.getBus2(), enabledBranch); - } - - // add to contingency description buses and branches that won't be part of the main connected - // component in post contingency state - Set buses = connectivity.getSmallComponents().stream().flatMap(Set::stream).collect(Collectors.toSet()); - for (LfBus bus : buses) { - bus.setDisabled(true); - bus.getBranches().forEach(branch -> branch.setDisabled(true)); - } - connectivity.undoTemporaryChanges(); - - LOGGER.info("Network state after action {}", id); - network.getBuses().forEach(bus -> LOGGER.info("LfBus {} is disabled: {}", bus.getId(), bus.isDisabled())); - network.getBranches().forEach(branch -> LOGGER.info("LfBranch {} is disabled: {}", branch.getId(), branch.isDisabled())); + connectivity.addEdge(enabledBranch.getBus1(), enabledBranch.getBus2(), enabledBranch); } } } diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index 15cf573bc9..85392bc29e 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -333,10 +333,8 @@ private Optional runActionSimulation(LfNetwork network, return lfAction; }) .collect(Collectors.toList()); - // apply actions, the last apply compute the final connectivity. - // FIXME: as an edge cannot be removed twice, we need as argument allSwitchesToCloseIds. - operatorStrategyLfActions.stream().limit((long) operatorStrategyLfActions.size() - 1).forEach(LfAction::apply); - operatorStrategyLfActions.get(operatorStrategyLfActions.size() - 1).apply(true); + + LfAction.apply(operatorStrategyLfActions, network); Stopwatch stopwatch = Stopwatch.createStarted(); diff --git a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java index 8257868d3b..f4058fcf3f 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java @@ -56,7 +56,7 @@ void test() { List lfNetworks = securityAnalysis.createNetworks(Collections.emptySet(), Set.of(network.getSwitch("C")), acParameters.getNetworkParameters(), Reporter.NO_OP); LfAction lfAction = new LfAction(switchAction, lfNetworks.get(0)); assertFalse(lfNetworks.get(0).getBranchById("C").isDisabled()); - lfAction.apply(true); + LfAction.apply(List.of(lfAction), lfNetworks.get(0)); assertTrue(lfNetworks.get(0).getBranchById("C").isDisabled()); assertEquals("C", lfAction.getDisabledBranch().getId()); assertNull(lfAction.getEnabledBranch()); From 2f4b49c195cb09909149080caa3aa147f4b06d2b Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Fri, 2 Sep 2022 10:05:53 +0200 Subject: [PATCH 27/51] Fixes after review. Signed-off-by: Anne Tilloy --- src/main/java/com/powsybl/openloadflow/network/LfAction.java | 2 +- .../java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index d2f0384afe..ee5a373c6a 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -95,7 +95,7 @@ public void apply(GraphConnectivity connectivity) { } if (enabledBranch != null) { enabledBranch.setDisabled(false); - enabledBranch.getBus1().setDisabled(false); + enabledBranch.getBus1().setDisabled(false); // FIXME, not enough several buses ard branches can be reconnected. enabledBranch.getBus2().setDisabled(false); connectivity.addEdge(enabledBranch.getBus1(), enabledBranch.getBus2(), enabledBranch); } diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index 85392bc29e..dc2077473c 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -248,7 +248,7 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List runActionSimulation(LfNetwork network, LimitViolationManager preContingencyLimitViolationManager, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, LimitViolationsResult postContingencyLimitViolations, Map lfActionById, - boolean createResultExtension, List allSwitchesToCloseIds) { + boolean createResultExtension) { OperatorStrategyResult operatorStrategyResult = null; if (checkCondition(operatorStrategy, postContingencyLimitViolations)) { From 10d28f54bfaef9a4df5a49ba930abcd86536c136 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Fri, 2 Sep 2022 15:06:00 +0200 Subject: [PATCH 28/51] Increase coverage and fixes. Signed-off-by: Anne Tilloy --- .../openloadflow/network/LfAction.java | 8 ++++- .../openloadflow/sa/AcSecurityAnalysis.java | 16 ++++----- .../AbstractLoadFlowNetworkFactory.java | 16 +++++++++ .../ConnectedComponentNetworkFactory.java | 36 +++++++++++++++++++ .../powsybl/openloadflow/sa/LfActionTest.java | 23 ++++++++---- .../sa/OpenSecurityAnalysisTest.java | 33 +++++++++++++++++ 6 files changed, 116 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index ee5a373c6a..ead8135ff9 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -64,13 +64,19 @@ public LfBranch getEnabledBranch() { return enabledBranch; } - public static void apply(List actions, LfNetwork network) { + public static void apply(List actions, LfNetwork network, LfContingency contingency) { Objects.requireNonNull(actions); Objects.requireNonNull(network); var connectivity = network.getConnectivity(); connectivity.startTemporaryChanges(); + contingency.getDisabledBranches().forEach(branch -> { + if (branch.getBus1() != null && branch.getBus2() != null) { + connectivity.removeEdge(branch); + } + }); + for (LfAction action : actions) { action.apply(connectivity); } diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index dc2077473c..f2875d0309 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -123,11 +123,11 @@ List createNetworks(Set allSwitchesToOpen, Set allSwi try { network.getSwitchStream().filter(sw -> sw.getVoltageLevel().getTopologyKind() == TopologyKind.NODE_BREAKER) .forEach(sw -> sw.setRetained(false)); - allSwitchesToOpen.forEach(sw -> sw.setRetained(true)); - allSwitchesToClose.forEach(sw -> { - sw.setRetained(true); - sw.setOpen(false); // in order to be present in the network. - }); + allSwitchesToOpen.stream().filter(sw -> sw.getVoltageLevel().getTopologyKind() == TopologyKind.NODE_BREAKER) + .forEach(sw -> sw.setRetained(true)); + allSwitchesToClose.stream().filter(sw -> sw.getVoltageLevel().getTopologyKind() == TopologyKind.NODE_BREAKER) + .forEach(sw -> sw.setRetained(true)); + allSwitchesToClose.stream().forEach(sw -> sw.setOpen(false)); // in order to be present in the network. lfNetworks = Networks.load(network, networkParameters, saReporter); } finally { network.getVariantManager().removeVariant(tmpVariantId); @@ -248,7 +248,7 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List runActionSimulation(LfNetwork network, LimitViolationManager preContingencyLimitViolationManager, SecurityAnalysisParameters.IncreasedViolationsParameters violationsParameters, LimitViolationsResult postContingencyLimitViolations, Map lfActionById, - boolean createResultExtension) { + boolean createResultExtension, LfContingency contingency) { OperatorStrategyResult operatorStrategyResult = null; if (checkCondition(operatorStrategy, postContingencyLimitViolations)) { @@ -334,7 +334,7 @@ private Optional runActionSimulation(LfNetwork network, }) .collect(Collectors.toList()); - LfAction.apply(operatorStrategyLfActions, network); + LfAction.apply(operatorStrategyLfActions, network, contingency); Stopwatch stopwatch = Stopwatch.createStarted(); diff --git a/src/test/java/com/powsybl/openloadflow/network/AbstractLoadFlowNetworkFactory.java b/src/test/java/com/powsybl/openloadflow/network/AbstractLoadFlowNetworkFactory.java index 8c3e13cd96..8187beb070 100644 --- a/src/test/java/com/powsybl/openloadflow/network/AbstractLoadFlowNetworkFactory.java +++ b/src/test/java/com/powsybl/openloadflow/network/AbstractLoadFlowNetworkFactory.java @@ -43,6 +43,13 @@ protected static Bus createBus(Network network, String substationId, String id, .add(); } + protected static Bus createOtherBus(Network network, String id, String voltageLevelId) { + VoltageLevel vl = network.getVoltageLevel(voltageLevelId); + return vl.getBusBreakerView().newBus() + .setId(id) + .add(); + } + protected static Generator createGenerator(Bus b, String id, double p) { return createGenerator(b, id, p, 1); } @@ -111,6 +118,15 @@ protected static Line createLine(Network network, Bus b1, Bus b2, String id, dou .add(); } + protected static Switch createSwitch(Network network, Bus b1, Bus b2, String id) { + return network.getVoltageLevel(b1.getVoltageLevel().getId()).getBusBreakerView().newSwitch() + .setId(id) + .setBus1(b1.getId()) + .setBus2(b2.getId()) + .setOpen(false) + .add(); + } + protected static TwoWindingsTransformer createTransformer(Network network, String substationId, Bus b1, Bus b2, String id, double x, double rho) { return network.getSubstation(substationId).newTwoWindingsTransformer() .setId(id) diff --git a/src/test/java/com/powsybl/openloadflow/network/ConnectedComponentNetworkFactory.java b/src/test/java/com/powsybl/openloadflow/network/ConnectedComponentNetworkFactory.java index ae3a782773..563efecd16 100644 --- a/src/test/java/com/powsybl/openloadflow/network/ConnectedComponentNetworkFactory.java +++ b/src/test/java/com/powsybl/openloadflow/network/ConnectedComponentNetworkFactory.java @@ -708,4 +708,40 @@ public static Network createSubComp() { return network; } + + /** + *
+     * b1 ----------+
+     * |            |
+     * b2 -------- b3
+     *              |
+     * b5 -------- b4
+     * |            |
+     * b6 ----------+
+     * 
+ * + * @return network + */ + public static Network createTwoCcLinkedBySwitches() { + Network network = Network.create("test", "code"); + Bus b1 = createBus(network, "b1"); + Bus b2 = createBus(network, "b2"); + Bus b3 = createBus(network, "b3"); + Bus b4 = createOtherBus(network, "b4", "b3_vl"); + Bus b5 = createOtherBus(network, "b5", "b2_vl"); + Bus b6 = createBus(network, "b6"); + createLine(network, b1, b2, "l12", 0.1f); + createLine(network, b1, b3, "l13", 0.1f); + createLine(network, b2, b3, "l23", 0.1f); + createSwitch(network, b3, b4, "s34"); + createLine(network, b4, b5, "l45", 0.1f); + createLine(network, b4, b6, "l46", 0.1f); + createLine(network, b5, b6, "l56", 0.1f); + createSwitch(network, b2, b5, "s25"); + createGenerator(b1, "g1", 3); + createGenerator(b5, "g3", 1); + createLoad(b4, "d4", 3); + createLoad(b2, "d2", 1); + return network; + } } diff --git a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java index f4058fcf3f..b355b4cd40 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java @@ -9,6 +9,8 @@ import com.powsybl.commons.AbstractConverterTest; import com.powsybl.commons.PowsyblException; import com.powsybl.commons.reporter.Reporter; +import com.powsybl.contingency.Contingency; +import com.powsybl.contingency.LoadContingency; import com.powsybl.iidm.network.Network; import com.powsybl.loadflow.LoadFlowParameters; import com.powsybl.math.matrix.DenseMatrixFactory; @@ -16,15 +18,14 @@ import com.powsybl.openloadflow.ac.outerloop.AcLoadFlowParameters; import com.powsybl.openloadflow.graph.EvenShiloachGraphDecrementalConnectivityFactory; import com.powsybl.openloadflow.network.*; +import com.powsybl.openloadflow.network.impl.PropagatedContingency; import com.powsybl.security.action.SwitchAction; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import java.io.IOException; -import java.util.Collections; -import java.util.List; -import java.util.Set; +import java.util.*; import static org.junit.jupiter.api.Assertions.*; @@ -56,10 +57,18 @@ void test() { List lfNetworks = securityAnalysis.createNetworks(Collections.emptySet(), Set.of(network.getSwitch("C")), acParameters.getNetworkParameters(), Reporter.NO_OP); LfAction lfAction = new LfAction(switchAction, lfNetworks.get(0)); assertFalse(lfNetworks.get(0).getBranchById("C").isDisabled()); - LfAction.apply(List.of(lfAction), lfNetworks.get(0)); - assertTrue(lfNetworks.get(0).getBranchById("C").isDisabled()); - assertEquals("C", lfAction.getDisabledBranch().getId()); - assertNull(lfAction.getEnabledBranch()); + + String loadId = "LOAD"; + Contingency contingency = new Contingency(loadId, new LoadContingency("LD")); + PropagatedContingency propagatedContingency = PropagatedContingency.createListForSecurityAnalysis(network, + Collections.singletonList(contingency), new HashSet<>(), false, false, false, true).get(0); + Optional lfContingency = propagatedContingency.toLfContingency(lfNetworks.get(0), true); + if (lfContingency.isPresent()) { + LfAction.apply(List.of(lfAction), lfNetworks.get(0), lfContingency.get()); + assertTrue(lfNetworks.get(0).getBranchById("C").isDisabled()); + assertEquals("C", lfAction.getDisabledBranch().getId()); + assertNull(lfAction.getEnabledBranch()); + } SwitchAction switchAction2 = new SwitchAction("switchAction", "S", true); assertThrows(PowsyblException.class, () -> new LfAction(switchAction2, lfNetworks.get(0)), "Branch S not found in the network"); diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index d3774ee0da..f624e13aa2 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -1889,4 +1889,37 @@ void testSecurityAnalysisWithOperatorStrategy3() { // L2 contingency assertFalse(getOptionalOperatorStrategyResult(result, "strategyL2").isEmpty()); } + + @Test + void testWithSeveralConnectedComponents() { + MatrixFactory matrixFactory = new DenseMatrixFactory(); + GraphConnectivityFactory connectivityFactory = new NaiveGraphConnectivityFactory<>(LfBus::getNum); + securityAnalysisProvider = new OpenSecurityAnalysisProvider(matrixFactory, connectivityFactory); + + Network network = ConnectedComponentNetworkFactory.createTwoCcLinkedBySwitches(); + + List contingencies = Stream.of("s25") + .map(id -> new Contingency(id, new SwitchContingency(id))) + .collect(Collectors.toList()); + + List actions = List.of(new SwitchAction("action1", "s34", true)); + + List operatorStrategies = List.of(new OperatorStrategy("strategyS25", "s25", new TrueCondition(), List.of("action1"))); + + List monitors = createAllBranchesMonitors(network); + + SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors, new SecurityAnalysisParameters(), + operatorStrategies, actions, Reporter.NO_OP); + assertEquals(1.255, result.getPreContingencyResult().getNeworkResult().getBranchResult("l12").getP1(), LoadFlowAssert.DELTA_POWER); + assertEquals(1.745, result.getPreContingencyResult().getNeworkResult().getBranchResult("l13").getP1(), LoadFlowAssert.DELTA_POWER); + assertEquals(0.502, result.getPreContingencyResult().getNeworkResult().getBranchResult("l23").getP1(), LoadFlowAssert.DELTA_POWER); + // s25 contingency + assertEquals(1.332, getPostContingencyResult(result, "s25").getNetworkResult().getBranchResult("l12").getP1(), LoadFlowAssert.DELTA_POWER); + assertEquals(1.667, getPostContingencyResult(result, "s25").getNetworkResult().getBranchResult("l13").getP1(), LoadFlowAssert.DELTA_POWER); + assertEquals(0.335, getPostContingencyResult(result, "s25").getNetworkResult().getBranchResult("l23").getP1(), LoadFlowAssert.DELTA_POWER); + // strategyS25 operator strategy + assertEquals(0.666, getOperatorStrategyResult(result, "strategyS25").getNetworkResult().getBranchResult("l12").getP1(), LoadFlowAssert.DELTA_POWER); + assertEquals(0.333, getOperatorStrategyResult(result, "strategyS25").getNetworkResult().getBranchResult("l13").getP1(), LoadFlowAssert.DELTA_POWER); + assertEquals(-0.333, getOperatorStrategyResult(result, "strategyS25").getNetworkResult().getBranchResult("l23").getP1(), LoadFlowAssert.DELTA_POWER); + } } From c902c328c56e47506b0469662a04e9dd37562038 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Tue, 4 Oct 2022 13:03:03 +0200 Subject: [PATCH 29/51] Fix checkstyle. Signed-off-by: Anne Tilloy --- src/main/java/com/powsybl/openloadflow/network/LfAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index ead8135ff9..185d4c0940 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -48,7 +48,7 @@ public LfAction(Action action, LfNetwork network) { } break; default: - throw new UnsupportedOperationException("Unsupported action type: " + action.getType()); + throw new UnsupportedOperationException("Unsupported action type: " + action.getType()); } } From beeaef0760a551b5aa43dd98d2d8528c0430429b Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Tue, 4 Oct 2022 19:40:53 +0200 Subject: [PATCH 30/51] Clean action connectivity. Signed-off-by: Anne Tilloy --- .../openloadflow/network/LfAction.java | 45 +++++++++++-------- .../powsybl/openloadflow/sa/LfActionTest.java | 5 +-- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index 185d4c0940..bf84af4e92 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -16,7 +16,6 @@ import java.util.List; import java.util.Objects; import java.util.Set; -import java.util.stream.Collectors; /** * @author Anne Tilloy @@ -68,41 +67,49 @@ public static void apply(List actions, LfNetwork network, LfContingenc Objects.requireNonNull(actions); Objects.requireNonNull(network); - var connectivity = network.getConnectivity(); + GraphConnectivity connectivity = network.getConnectivity(); + connectivity.setMainComponentVertex(network.getSlackBus()); connectivity.startTemporaryChanges(); - - contingency.getDisabledBranches().forEach(branch -> { - if (branch.getBus1() != null && branch.getBus2() != null) { - connectivity.removeEdge(branch); - } - }); + contingency.getDisabledBranches().stream() + .filter(Objects::nonNull) // could be in another component + .filter(b -> b.getBus1() != null && b.getBus2() != null) + .forEach(connectivity::removeEdge); + Set postContingencyRemovedBuses = connectivity.getVerticesRemovedFromMainComponent(); + postContingencyRemovedBuses.stream().forEach(bus -> bus.setDisabled(false)); // undo. + Set postContingencyRemovedBranches = connectivity.getEdgesRemovedFromMainComponent(); + postContingencyRemovedBranches.stream().forEach(branch -> branch.setDisabled(false)); // undo. for (LfAction action : actions) { - action.apply(connectivity); + action.updateConnectivity(connectivity); } - Set buses = connectivity.getSmallComponents().stream().flatMap(Set::stream).collect(Collectors.toSet()); - for (LfBus bus : buses) { - bus.setDisabled(true); - bus.getBranches().forEach(branch -> branch.setDisabled(true)); - } + // add to action description buses and branches that won't be part of the main connected + // component in post action state. + Set removedBuses = connectivity.getVerticesRemovedFromMainComponent(); + removedBuses.stream().forEach(bus -> bus.setDisabled(true)); + Set removedBranches = connectivity.getEdgesRemovedFromMainComponent(); + removedBranches.stream() .forEach(branch -> branch.setDisabled(true)); + // add to action description buses and branches that will be part of the main connected + // component in post action state. + Set addedBuses = connectivity.getVerticesAddedToMainComponent(); + addedBuses.stream().forEach(bus -> bus.setDisabled(false)); + Set addedBranches = connectivity.getEdgesAddedToMainComponent(); + addedBranches.stream().forEach(branch -> branch.setDisabled(false)); + + // reset connectivity to discard triggered branches connectivity.undoTemporaryChanges(); network.getBuses().forEach(bus -> LOGGER.info("LfBus {} is disabled: {}", bus.getId(), bus.isDisabled())); network.getBranches().forEach(branch -> LOGGER.info("LfBranch {} is disabled: {}", branch.getId(), branch.isDisabled())); } - public void apply(GraphConnectivity connectivity) { + public void updateConnectivity(GraphConnectivity connectivity) { if (disabledBranch != null) { - disabledBranch.setDisabled(true); if (disabledBranch.getBus1() != null && disabledBranch.getBus2() != null) { connectivity.removeEdge(disabledBranch); } } if (enabledBranch != null) { - enabledBranch.setDisabled(false); - enabledBranch.getBus1().setDisabled(false); // FIXME, not enough several buses ard branches can be reconnected. - enabledBranch.getBus2().setDisabled(false); connectivity.addEdge(enabledBranch.getBus1(), enabledBranch.getBus2(), enabledBranch); } } diff --git a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java index 967d5111f2..3b31d101e0 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java @@ -56,14 +56,11 @@ void test() { new LoadFlowParameters(), new OpenLoadFlowParameters(), matrixFactory, new EvenShiloachGraphDecrementalConnectivityFactory<>(), Reporter.NO_OP, true, false); List lfNetworks = Networks.load(network, acParameters.getNetworkParameters(), Set.of(network.getSwitch("C")), Collections.emptySet(), Reporter.NO_OP); LfAction lfAction = new LfAction(switchAction, lfNetworks.get(0)); - lfAction.apply(lfNetworks.get(0).getConnectivity()); - assertTrue(lfNetworks.get(0).getBranchById("C").isDisabled()); - String loadId = "LOAD"; Contingency contingency = new Contingency(loadId, new LoadContingency("LD")); PropagatedContingency propagatedContingency = PropagatedContingency.createList(network, Collections.singletonList(contingency), new HashSet<>(), false, false, false, true).get(0); - Optional lfContingency = propagatedContingency.toLfContingency(lfNetworks.get(0), true); + Optional lfContingency = propagatedContingency.toLfContingency(lfNetworks.get(0)); if (lfContingency.isPresent()) { LfAction.apply(List.of(lfAction), lfNetworks.get(0), lfContingency.get()); assertTrue(lfNetworks.get(0).getBranchById("C").isDisabled()); From bde6467bb4614746fbada1f3601e916094b39c57 Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Tue, 4 Oct 2022 21:20:49 +0200 Subject: [PATCH 31/51] Clean Signed-off-by: Geoffroy Jamgotchian --- .../powsybl/openloadflow/network/LfAction.java | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index bf84af4e92..9f4d7bc0d8 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -75,9 +75,9 @@ public static void apply(List actions, LfNetwork network, LfContingenc .filter(b -> b.getBus1() != null && b.getBus2() != null) .forEach(connectivity::removeEdge); Set postContingencyRemovedBuses = connectivity.getVerticesRemovedFromMainComponent(); - postContingencyRemovedBuses.stream().forEach(bus -> bus.setDisabled(false)); // undo. + postContingencyRemovedBuses.forEach(bus -> bus.setDisabled(false)); // undo. Set postContingencyRemovedBranches = connectivity.getEdgesRemovedFromMainComponent(); - postContingencyRemovedBranches.stream().forEach(branch -> branch.setDisabled(false)); // undo. + postContingencyRemovedBranches.forEach(branch -> branch.setDisabled(false)); // undo. for (LfAction action : actions) { action.updateConnectivity(connectivity); @@ -86,15 +86,15 @@ public static void apply(List actions, LfNetwork network, LfContingenc // add to action description buses and branches that won't be part of the main connected // component in post action state. Set removedBuses = connectivity.getVerticesRemovedFromMainComponent(); - removedBuses.stream().forEach(bus -> bus.setDisabled(true)); + removedBuses.forEach(bus -> bus.setDisabled(true)); Set removedBranches = connectivity.getEdgesRemovedFromMainComponent(); - removedBranches.stream() .forEach(branch -> branch.setDisabled(true)); + removedBranches.forEach(branch -> branch.setDisabled(true)); // add to action description buses and branches that will be part of the main connected // component in post action state. Set addedBuses = connectivity.getVerticesAddedToMainComponent(); - addedBuses.stream().forEach(bus -> bus.setDisabled(false)); + addedBuses.forEach(bus -> bus.setDisabled(false)); Set addedBranches = connectivity.getEdgesAddedToMainComponent(); - addedBranches.stream().forEach(branch -> branch.setDisabled(false)); + addedBranches.forEach(branch -> branch.setDisabled(false)); // reset connectivity to discard triggered branches connectivity.undoTemporaryChanges(); @@ -104,10 +104,8 @@ public static void apply(List actions, LfNetwork network, LfContingenc } public void updateConnectivity(GraphConnectivity connectivity) { - if (disabledBranch != null) { - if (disabledBranch.getBus1() != null && disabledBranch.getBus2() != null) { - connectivity.removeEdge(disabledBranch); - } + if (disabledBranch != null && disabledBranch.getBus1() != null && disabledBranch.getBus2() != null) { + connectivity.removeEdge(disabledBranch); } if (enabledBranch != null) { connectivity.addEdge(enabledBranch.getBus1(), enabledBranch.getBus2(), enabledBranch); From 69db0bf3594154f29f1071e62c0f4f0a318e8b5e Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Thu, 13 Oct 2022 11:49:19 +0200 Subject: [PATCH 32/51] Support of several operator strategies by contingency. Signed-off-by: Anne Tilloy --- .../powsybl/openloadflow/sa/AcSecurityAnalysis.java | 11 ++++++++++- .../openloadflow/sa/OpenSecurityAnalysisTest.java | 7 +++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index cd88d4aa35..d3fedb89b2 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -230,7 +230,16 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List operatorStrategies = List.of(new OperatorStrategy("strategyL1", "L1", new AnyViolationCondition(), List.of("action1")), new OperatorStrategy("strategyL3", "L3", new AnyViolationCondition(), List.of("action3")), new OperatorStrategy("strategyL2_1", "L2", new AtLeastOneViolationCondition(List.of("L1")), List.of("action1", "action3")), - new OperatorStrategy("strategyL2_2", "L2", new AllViolationCondition(List.of("L1", "L3")), List.of("action1", "action3"))); + new OperatorStrategy("strategyL2_2", "L2", new AllViolationCondition(List.of("L1")), List.of("action1", "action3"))); List monitors = createAllBranchesMonitors(network); @@ -1853,9 +1853,8 @@ void testSecurityAnalysisWithOperatorStrategy2() { // L2 contingency assertEquals(583.5, getPostContingencyResult(result, "L2").getNetworkResult().getBranchResult("L1").getI1(), LoadFlowAssert.DELTA_I); assertEquals(302.2, getPostContingencyResult(result, "L2").getNetworkResult().getBranchResult("L3").getI1(), LoadFlowAssert.DELTA_I); - assertFalse(getPostContingencyResult(result, "L2").getLimitViolationsResult().getLimitViolations().isEmpty()); - assertTrue(getOptionalOperatorStrategyResult(result, "strategyL2_1").isEmpty()); // several operator strategies: not supported yet. - assertTrue(getOptionalOperatorStrategyResult(result, "strategyL2_2").isEmpty()); // several operator strategies: not supported yet. + assertEquals(441.5, getOperatorStrategyResult(result, "strategyL2_1").getNetworkResult().getBranchResult("L1").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(441.5, getOperatorStrategyResult(result, "strategyL2_2").getNetworkResult().getBranchResult("L1").getI1(), LoadFlowAssert.DELTA_I); } @Test From 0c6507c3bfc0e2fcbbffa565af459af45f1f5c6f Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Thu, 13 Oct 2022 12:20:12 +0200 Subject: [PATCH 33/51] Add Metrix tutorial. Signed-off-by: Anne Tilloy --- .../sa/OpenSecurityAnalysisTest.java | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index da83ef8417..12281ba489 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -18,6 +18,7 @@ import com.powsybl.iidm.network.extensions.LoadDetailAdder; import com.powsybl.iidm.network.test.EurostagTutorialExample1Factory; import com.powsybl.iidm.network.test.FourSubstationsNodeBreakerFactory; +import com.powsybl.iidm.xml.test.MetrixTutorialSixBusesFactory; import com.powsybl.loadflow.LoadFlow; import com.powsybl.loadflow.LoadFlowParameters; import com.powsybl.loadflow.LoadFlowResult; @@ -1929,4 +1930,29 @@ void testWithSeveralConnectedComponents() { assertEquals(0.333, getOperatorStrategyResult(result, "strategyS25").getNetworkResult().getBranchResult("l13").getP1(), LoadFlowAssert.DELTA_POWER); assertEquals(-0.333, getOperatorStrategyResult(result, "strategyS25").getNetworkResult().getBranchResult("l23").getP1(), LoadFlowAssert.DELTA_POWER); } + + @Test + void testMetrixTutorial() { + MatrixFactory matrixFactory = new DenseMatrixFactory(); + GraphConnectivityFactory connectivityFactory = new NaiveGraphConnectivityFactory<>(LfBus::getNum); + securityAnalysisProvider = new OpenSecurityAnalysisProvider(matrixFactory, connectivityFactory); + + Network network = MetrixTutorialSixBusesFactory.create(); + network.getGenerator("SO_G2").setTargetP(960); + network.getLoad("SE_L1").setP0(960); + + List contingencies = List.of(new Contingency("S_SO_1", new BranchContingency("S_SO_1"))); + + List monitors = createAllBranchesMonitors(network); + + List actions = List.of(new SwitchAction("openSwitchS0", "SOO1_SOO1_DJ_OMN", true)); + List operatorStrategies = List.of(new OperatorStrategy("strategy1", "S_SO_1", new AllViolationCondition(List.of("S_SO_2")), List.of("openSwitchS0"))); + + SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors, new SecurityAnalysisParameters(), + operatorStrategies, actions, Reporter.NO_OP); + assertEquals(444.091, result.getPreContingencyResult().getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(827.751, getPostContingencyResult(result, "S_SO_1").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(530.223, getOperatorStrategyResult(result, "strategy1").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); + } + } From 2b87a2452dc2415f6655c35b0297b45402270fd1 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Thu, 13 Oct 2022 12:56:07 +0200 Subject: [PATCH 34/51] Continue Metrix tutorial. Signed-off-by: Anne Tilloy --- .../powsybl/openloadflow/network/LfAction.java | 14 +++++++++++++- .../sa/OpenSecurityAnalysisTest.java | 16 +++++++++++----- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index 9f4d7bc0d8..82c72828cb 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -9,6 +9,7 @@ import com.powsybl.commons.PowsyblException; import com.powsybl.openloadflow.graph.GraphConnectivity; import com.powsybl.security.action.Action; +import com.powsybl.security.action.LineConnectionAction; import com.powsybl.security.action.SwitchAction; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,10 +34,11 @@ public class LfAction { public LfAction(Action action, LfNetwork network) { this.id = Objects.requireNonNull(action.getId()); Objects.requireNonNull(network); + LfBranch branch; switch (action.getType()) { case SwitchAction.NAME: SwitchAction switchAction = (SwitchAction) action; - LfBranch branch = network.getBranchById(switchAction.getSwitchId()); + branch = network.getBranchById(switchAction.getSwitchId()); if (branch == null) { throw new PowsyblException("Branch " + switchAction.getSwitchId() + " not found in the network"); } @@ -46,6 +48,16 @@ public LfAction(Action action, LfNetwork network) { enabledBranch = branch; } break; + case LineConnectionAction.NAME: + LineConnectionAction lineConnectionAction = (LineConnectionAction) action; + branch = network.getBranchById(lineConnectionAction.getLineId()); + if (branch == null) { + throw new PowsyblException("Branch " + lineConnectionAction.getLineId() + " not found in the network"); + } + if (lineConnectionAction.isOpenSide1() && lineConnectionAction.isOpenSide2()) { + disabledBranch = branch; + } + break; default: throw new UnsupportedOperationException("Unsupported action type: " + action.getType()); } diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index 12281ba489..220bd3921e 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -34,6 +34,7 @@ import com.powsybl.openloadflow.util.LoadFlowAssert; import com.powsybl.security.*; import com.powsybl.security.action.Action; +import com.powsybl.security.action.LineConnectionAction; import com.powsybl.security.action.SwitchAction; import com.powsybl.security.condition.AllViolationCondition; import com.powsybl.security.condition.AnyViolationCondition; @@ -1939,20 +1940,25 @@ void testMetrixTutorial() { Network network = MetrixTutorialSixBusesFactory.create(); network.getGenerator("SO_G2").setTargetP(960); + network.getGenerator("SO_G1").setTargetP(0); network.getLoad("SE_L1").setP0(960); List contingencies = List.of(new Contingency("S_SO_1", new BranchContingency("S_SO_1"))); List monitors = createAllBranchesMonitors(network); - List actions = List.of(new SwitchAction("openSwitchS0", "SOO1_SOO1_DJ_OMN", true)); - List operatorStrategies = List.of(new OperatorStrategy("strategy1", "S_SO_1", new AllViolationCondition(List.of("S_SO_2")), List.of("openSwitchS0"))); + List actions = List.of(new SwitchAction("openSwitchS0", "SOO1_SOO1_DJ_OMN", true), + new LineConnectionAction("openLineSSO2", "S_SO_2", true, true)); + List operatorStrategies = List.of(new OperatorStrategy("strategy1", "S_SO_1", new AllViolationCondition(List.of("S_SO_2")), List.of("openSwitchS0")), + new OperatorStrategy("strategy2", "S_SO_1", new AllViolationCondition(List.of("S_SO_2")), List.of("openLineSSO2"))); SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors, new SecurityAnalysisParameters(), operatorStrategies, actions, Reporter.NO_OP); - assertEquals(444.091, result.getPreContingencyResult().getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); - assertEquals(827.751, getPostContingencyResult(result, "S_SO_1").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); - assertEquals(530.223, getOperatorStrategyResult(result, "strategy1").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(395.413, result.getPreContingencyResult().getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(735.862, getPostContingencyResult(result, "S_SO_1").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(287.129, getOperatorStrategyResult(result, "strategy1").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(1938.36, getOperatorStrategyResult(result, "strategy1").getNetworkResult().getBranchResult("SO_NO_1").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(683.392, getOperatorStrategyResult(result, "strategy2").getNetworkResult().getBranchResult("SO_NO_1").getI1(), LoadFlowAssert.DELTA_I); } } From 7b941a168550664d22ee7b0f490fc633af7916ad Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Thu, 13 Oct 2022 13:10:37 +0200 Subject: [PATCH 35/51] Clean. Signed-off-by: Anne Tilloy --- .../powsybl/openloadflow/network/LfAction.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index 82c72828cb..46ce3b1f74 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -39,9 +39,7 @@ public LfAction(Action action, LfNetwork network) { case SwitchAction.NAME: SwitchAction switchAction = (SwitchAction) action; branch = network.getBranchById(switchAction.getSwitchId()); - if (branch == null) { - throw new PowsyblException("Branch " + switchAction.getSwitchId() + " not found in the network"); - } + checkBranch(branch, switchAction.getSwitchId()); if (switchAction.isOpen()) { disabledBranch = branch; } else { @@ -51,11 +49,11 @@ public LfAction(Action action, LfNetwork network) { case LineConnectionAction.NAME: LineConnectionAction lineConnectionAction = (LineConnectionAction) action; branch = network.getBranchById(lineConnectionAction.getLineId()); - if (branch == null) { - throw new PowsyblException("Branch " + lineConnectionAction.getLineId() + " not found in the network"); - } + checkBranch(branch, lineConnectionAction.getLineId()); if (lineConnectionAction.isOpenSide1() && lineConnectionAction.isOpenSide2()) { disabledBranch = branch; + } else { + throw new UnsupportedOperationException("Line connection action: only open line at both sides is supported yet."); } break; default: @@ -123,4 +121,11 @@ public void updateConnectivity(GraphConnectivity connectivity) connectivity.addEdge(enabledBranch.getBus1(), enabledBranch.getBus2(), enabledBranch); } } + + private void checkBranch(LfBranch branch, String branchId) { + if (branch == null) { + throw new PowsyblException("Branch " + branchId + " not found in the network"); + } + } + } From 7db0284df6b82dc4b01375db339721defd7122f5 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Fri, 14 Oct 2022 13:15:04 +0200 Subject: [PATCH 36/51] Save. Signed-off-by: Anne Tilloy --- .../openloadflow/network/LfAction.java | 22 +++++++++++++++++++ .../powsybl/openloadflow/network/PiModel.java | 2 ++ .../openloadflow/network/PiModelArray.java | 6 +++++ .../openloadflow/network/SimplePiModel.java | 5 +++++ .../sa/OpenSecurityAnalysisTest.java | 12 ++++++++-- 5 files changed, 45 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index 46ce3b1f74..5e59e50691 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -10,7 +10,9 @@ import com.powsybl.openloadflow.graph.GraphConnectivity; import com.powsybl.security.action.Action; import com.powsybl.security.action.LineConnectionAction; +import com.powsybl.security.action.PhaseTapChangerTapPositionAction; import com.powsybl.security.action.SwitchAction; +import org.apache.commons.lang3.tuple.Pair; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -31,6 +33,8 @@ public class LfAction { private LfBranch enabledBranch; // switch to close + private Pair> branchAndTapPosition; + public LfAction(Action action, LfNetwork network) { this.id = Objects.requireNonNull(action.getId()); Objects.requireNonNull(network); @@ -56,6 +60,16 @@ public LfAction(Action action, LfNetwork network) { throw new UnsupportedOperationException("Line connection action: only open line at both sides is supported yet."); } break; + case PhaseTapChangerTapPositionAction.NAME: + PhaseTapChangerTapPositionAction phaseTapChangerTapPositionAction = (PhaseTapChangerTapPositionAction) action; + branch = network.getBranchById(phaseTapChangerTapPositionAction.getTransformerId()); // only two windings transformer for the moment. + checkBranch(branch, phaseTapChangerTapPositionAction.getTransformerId()); // how to check that it is really a phase tap changer? + if (branch.getPiModel() instanceof SimplePiModel) { + throw new UnsupportedOperationException("Phase tap changer tap connection action: only one tap in the branch {" + phaseTapChangerTapPositionAction.getTransformerId() + "}"); + } else { + branchAndTapPosition = Pair.of(branch, Pair.of(phaseTapChangerTapPositionAction.getValue(), phaseTapChangerTapPositionAction.isRelativeValue())); + } + break; default: throw new UnsupportedOperationException("Unsupported action type: " + action.getType()); } @@ -91,6 +105,7 @@ public static void apply(List actions, LfNetwork network, LfContingenc for (LfAction action : actions) { action.updateConnectivity(connectivity); + action.apply(network); } // add to action description buses and branches that won't be part of the main connected @@ -122,6 +137,13 @@ public void updateConnectivity(GraphConnectivity connectivity) } } + public void apply(LfNetwork network) { + if (branchAndTapPosition != null) { + LfBranch branch = branchAndTapPosition.getLeft(); + branch.getPiModel().updateA1(branchAndTapPosition.getRight().getLeft(), branchAndTapPosition.getRight().getRight()); + } + } + private void checkBranch(LfBranch branch, String branchId) { if (branch == null) { throw new PowsyblException("Branch " + branchId + " not found in the network"); diff --git a/src/main/java/com/powsybl/openloadflow/network/PiModel.java b/src/main/java/com/powsybl/openloadflow/network/PiModel.java index 58093d9aa8..b0768321cc 100644 --- a/src/main/java/com/powsybl/openloadflow/network/PiModel.java +++ b/src/main/java/com/powsybl/openloadflow/network/PiModel.java @@ -76,6 +76,8 @@ enum AllowedDirection { boolean updateTapPositionA1(Direction direction); + void updateA1(int tapPosition, boolean delta); + Optional updateTapPositionR1(double deltaR1, int maxTapShift, AllowedDirection allowedDirection); boolean setMinZ(double minZ, boolean dc); diff --git a/src/main/java/com/powsybl/openloadflow/network/PiModelArray.java b/src/main/java/com/powsybl/openloadflow/network/PiModelArray.java index 13166f99ba..b0c8a8c6c9 100644 --- a/src/main/java/com/powsybl/openloadflow/network/PiModelArray.java +++ b/src/main/java/com/powsybl/openloadflow/network/PiModelArray.java @@ -195,6 +195,12 @@ public boolean updateTapPositionA1(Direction direction) { return hasChanged; } + @Override + public void updateA1(int tapPosition, boolean delta) { + this.tapPosition = delta ? this.tapPosition + tapPosition : tapPosition; + a1 = Double.NaN; + } + private Range getAllowedPositionRange(AllowedDirection allowedDirection) { switch (allowedDirection) { case INCREASE: diff --git a/src/main/java/com/powsybl/openloadflow/network/SimplePiModel.java b/src/main/java/com/powsybl/openloadflow/network/SimplePiModel.java index 709b1920dd..e696549a8b 100644 --- a/src/main/java/com/powsybl/openloadflow/network/SimplePiModel.java +++ b/src/main/java/com/powsybl/openloadflow/network/SimplePiModel.java @@ -142,6 +142,11 @@ public boolean updateTapPositionA1(Direction direction) { throw new IllegalStateException("No tap position change in simple Pi model implementation"); } + @Override + public void updateA1(int tapPosition, boolean delta) { + throw new IllegalStateException("No tap position change in simple Pi model implementation"); + } + @Override public Optional updateTapPositionR1(double deltaR1, int maxTapShift, AllowedDirection allowedDirection) { throw new IllegalStateException("No tap position change in simple Pi model implementation"); diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index 220bd3921e..d91777faf8 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -35,6 +35,7 @@ import com.powsybl.security.*; import com.powsybl.security.action.Action; import com.powsybl.security.action.LineConnectionAction; +import com.powsybl.security.action.PhaseTapChangerTapPositionAction; import com.powsybl.security.action.SwitchAction; import com.powsybl.security.condition.AllViolationCondition; import com.powsybl.security.condition.AnyViolationCondition; @@ -1948,17 +1949,24 @@ void testMetrixTutorial() { List monitors = createAllBranchesMonitors(network); List actions = List.of(new SwitchAction("openSwitchS0", "SOO1_SOO1_DJ_OMN", true), - new LineConnectionAction("openLineSSO2", "S_SO_2", true, true)); + new LineConnectionAction("openLineSSO2", "S_SO_2", true, true), + new PhaseTapChangerTapPositionAction("pst", "NE_NO_1", false, 1)); List operatorStrategies = List.of(new OperatorStrategy("strategy1", "S_SO_1", new AllViolationCondition(List.of("S_SO_2")), List.of("openSwitchS0")), - new OperatorStrategy("strategy2", "S_SO_1", new AllViolationCondition(List.of("S_SO_2")), List.of("openLineSSO2"))); + new OperatorStrategy("strategy2", "S_SO_1", new AllViolationCondition(List.of("S_SO_2")), List.of("openLineSSO2")), + new OperatorStrategy("strategy3", "S_SO_1", new TrueCondition(), List.of("pst"))); SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors, new SecurityAnalysisParameters(), operatorStrategies, actions, Reporter.NO_OP); assertEquals(395.413, result.getPreContingencyResult().getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); assertEquals(735.862, getPostContingencyResult(result, "S_SO_1").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(2, getPostContingencyResult(result, "S_SO_1").getLimitViolationsResult().getLimitViolations().size()); assertEquals(287.129, getOperatorStrategyResult(result, "strategy1").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); assertEquals(1938.36, getOperatorStrategyResult(result, "strategy1").getNetworkResult().getBranchResult("SO_NO_1").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(4, getOperatorStrategyResult(result, "strategy1").getLimitViolationsResult().getLimitViolations().size()); assertEquals(683.392, getOperatorStrategyResult(result, "strategy2").getNetworkResult().getBranchResult("SO_NO_1").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(4, getOperatorStrategyResult(result, "strategy2").getLimitViolationsResult().getLimitViolations().size()); + assertEquals(732.726, getOperatorStrategyResult(result, "strategy3").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(2, getOperatorStrategyResult(result, "strategy3").getLimitViolationsResult().getLimitViolations().size()); } } From f1bc076ea261623070c4b305c1360741a0aa61f5 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Fri, 14 Oct 2022 13:25:27 +0200 Subject: [PATCH 37/51] Fix code smells. Signed-off-by: Anne Tilloy --- .../java/com/powsybl/openloadflow/network/LfAction.java | 4 ++-- .../com/powsybl/openloadflow/network/SimplePiModel.java | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index 5e59e50691..1e13018e86 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -105,7 +105,7 @@ public static void apply(List actions, LfNetwork network, LfContingenc for (LfAction action : actions) { action.updateConnectivity(connectivity); - action.apply(network); + action.apply(); } // add to action description buses and branches that won't be part of the main connected @@ -137,7 +137,7 @@ public void updateConnectivity(GraphConnectivity connectivity) } } - public void apply(LfNetwork network) { + public void apply() { if (branchAndTapPosition != null) { LfBranch branch = branchAndTapPosition.getLeft(); branch.getPiModel().updateA1(branchAndTapPosition.getRight().getLeft(), branchAndTapPosition.getRight().getRight()); diff --git a/src/main/java/com/powsybl/openloadflow/network/SimplePiModel.java b/src/main/java/com/powsybl/openloadflow/network/SimplePiModel.java index e696549a8b..47d98bcfd8 100644 --- a/src/main/java/com/powsybl/openloadflow/network/SimplePiModel.java +++ b/src/main/java/com/powsybl/openloadflow/network/SimplePiModel.java @@ -24,6 +24,8 @@ public class SimplePiModel implements PiModel { private double r1 = 1; private double a1 = 0; + private static final String NO_TAP_POSITION_ERROR = "No tap position change in simple Pi model implementation"; + @Override public double getR() { return r; @@ -139,17 +141,17 @@ public void roundR1ToClosestTap() { @Override public boolean updateTapPositionA1(Direction direction) { - throw new IllegalStateException("No tap position change in simple Pi model implementation"); + throw new IllegalStateException(NO_TAP_POSITION_ERROR); } @Override public void updateA1(int tapPosition, boolean delta) { - throw new IllegalStateException("No tap position change in simple Pi model implementation"); + throw new IllegalStateException(NO_TAP_POSITION_ERROR); } @Override public Optional updateTapPositionR1(double deltaR1, int maxTapShift, AllowedDirection allowedDirection) { - throw new IllegalStateException("No tap position change in simple Pi model implementation"); + throw new IllegalStateException(NO_TAP_POSITION_ERROR); } private void rescaleZ(double z) { From e104e73f8fbf766a3ebce1f5ecfafb36cc85b5b5 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Fri, 14 Oct 2022 13:48:34 +0200 Subject: [PATCH 38/51] Clean. Signed-off-by: Anne Tilloy --- .../openloadflow/network/BranchState.java | 7 +++++++ .../openloadflow/network/LfAction.java | 5 ++++- .../powsybl/openloadflow/network/PiModel.java | 6 ++++-- .../openloadflow/network/PiModelArray.java | 19 +++++++++++++------ .../openloadflow/network/SimplePiModel.java | 15 ++++++++++----- .../sa/OpenSecurityAnalysisTest.java | 8 ++++++-- 6 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/BranchState.java b/src/main/java/com/powsybl/openloadflow/network/BranchState.java index fb841f45e0..38d3ea8666 100644 --- a/src/main/java/com/powsybl/openloadflow/network/BranchState.java +++ b/src/main/java/com/powsybl/openloadflow/network/BranchState.java @@ -15,12 +15,16 @@ public class BranchState extends ElementState { private final double r1; private final boolean phaseControlEnabled; private final boolean voltageControlEnabled; + private int tapPosition; public BranchState(LfBranch branch) { super(branch); PiModel piModel = branch.getPiModel(); a1 = piModel.getA1(); r1 = piModel.getR1(); + if (piModel instanceof PiModelArray) { + tapPosition = piModel.getTapPosition(); + } phaseControlEnabled = branch.isPhaseControlEnabled(); voltageControlEnabled = branch.isVoltageControlEnabled(); } @@ -29,6 +33,9 @@ public BranchState(LfBranch branch) { public void restore() { super.restore(); PiModel piModel = element.getPiModel(); + if (piModel instanceof PiModelArray) { + piModel.setTapPosition(tapPosition); + } piModel.setA1(a1); piModel.setR1(r1); element.setPhaseControlEnabled(phaseControlEnabled); diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index 1e13018e86..3831d5589c 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -140,7 +140,10 @@ public void updateConnectivity(GraphConnectivity connectivity) public void apply() { if (branchAndTapPosition != null) { LfBranch branch = branchAndTapPosition.getLeft(); - branch.getPiModel().updateA1(branchAndTapPosition.getRight().getLeft(), branchAndTapPosition.getRight().getRight()); + int tapPosition = branch.getPiModel().getTapPosition(); + int value = branchAndTapPosition.getRight().getLeft(); + int newTapPosition = branchAndTapPosition.getRight().getRight() ? tapPosition + value : value; + branch.getPiModel().setTapPosition(newTapPosition); } } diff --git a/src/main/java/com/powsybl/openloadflow/network/PiModel.java b/src/main/java/com/powsybl/openloadflow/network/PiModel.java index b0768321cc..cb9d4dd5e7 100644 --- a/src/main/java/com/powsybl/openloadflow/network/PiModel.java +++ b/src/main/java/com/powsybl/openloadflow/network/PiModel.java @@ -76,11 +76,13 @@ enum AllowedDirection { boolean updateTapPositionA1(Direction direction); - void updateA1(int tapPosition, boolean delta); - Optional updateTapPositionR1(double deltaR1, int maxTapShift, AllowedDirection allowedDirection); boolean setMinZ(double minZ, boolean dc); void setBranch(LfBranch branch); + + int getTapPosition(); + + PiModel setTapPosition(int tapPosition); } diff --git a/src/main/java/com/powsybl/openloadflow/network/PiModelArray.java b/src/main/java/com/powsybl/openloadflow/network/PiModelArray.java index b0c8a8c6c9..9a40d61f4f 100644 --- a/src/main/java/com/powsybl/openloadflow/network/PiModelArray.java +++ b/src/main/java/com/powsybl/openloadflow/network/PiModelArray.java @@ -195,12 +195,6 @@ public boolean updateTapPositionA1(Direction direction) { return hasChanged; } - @Override - public void updateA1(int tapPosition, boolean delta) { - this.tapPosition = delta ? this.tapPosition + tapPosition : tapPosition; - a1 = Double.NaN; - } - private Range getAllowedPositionRange(AllowedDirection allowedDirection) { switch (allowedDirection) { case INCREASE: @@ -258,4 +252,17 @@ public boolean setMinZ(double minZ, boolean dc) { public void setBranch(LfBranch branch) { this.branch = Objects.requireNonNull(branch); } + + @Override + public int getTapPosition() { + return this.tapPosition; + } + + @Override + public PiModel setTapPosition(int tapPosition) { + this.tapPosition = tapPosition; + r1 = Double.NaN; + a1 = Double.NaN; + return this; + } } diff --git a/src/main/java/com/powsybl/openloadflow/network/SimplePiModel.java b/src/main/java/com/powsybl/openloadflow/network/SimplePiModel.java index 47d98bcfd8..207b266618 100644 --- a/src/main/java/com/powsybl/openloadflow/network/SimplePiModel.java +++ b/src/main/java/com/powsybl/openloadflow/network/SimplePiModel.java @@ -144,11 +144,6 @@ public boolean updateTapPositionA1(Direction direction) { throw new IllegalStateException(NO_TAP_POSITION_ERROR); } - @Override - public void updateA1(int tapPosition, boolean delta) { - throw new IllegalStateException(NO_TAP_POSITION_ERROR); - } - @Override public Optional updateTapPositionR1(double deltaR1, int maxTapShift, AllowedDirection allowedDirection) { throw new IllegalStateException(NO_TAP_POSITION_ERROR); @@ -181,4 +176,14 @@ public boolean setMinZ(double minZ, boolean dc) { public void setBranch(LfBranch branch) { // nothing to set } + + @Override + public int getTapPosition() { + throw new IllegalStateException(NO_TAP_POSITION_ERROR); + } + + @Override + public PiModel setTapPosition(int tapPosition) { + throw new IllegalStateException(NO_TAP_POSITION_ERROR); + } } diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index d91777faf8..188432ff36 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -1950,10 +1950,12 @@ void testMetrixTutorial() { List actions = List.of(new SwitchAction("openSwitchS0", "SOO1_SOO1_DJ_OMN", true), new LineConnectionAction("openLineSSO2", "S_SO_2", true, true), - new PhaseTapChangerTapPositionAction("pst", "NE_NO_1", false, 1)); + new PhaseTapChangerTapPositionAction("pst", "NE_NO_1", false, 1), // PST at tap position 17. + new PhaseTapChangerTapPositionAction("pst2", "NE_NO_1", true, -16)); List operatorStrategies = List.of(new OperatorStrategy("strategy1", "S_SO_1", new AllViolationCondition(List.of("S_SO_2")), List.of("openSwitchS0")), new OperatorStrategy("strategy2", "S_SO_1", new AllViolationCondition(List.of("S_SO_2")), List.of("openLineSSO2")), - new OperatorStrategy("strategy3", "S_SO_1", new TrueCondition(), List.of("pst"))); + new OperatorStrategy("strategy3", "S_SO_1", new TrueCondition(), List.of("pst")), + new OperatorStrategy("strategy4", "S_SO_1", new TrueCondition(), List.of("pst2"))); SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors, new SecurityAnalysisParameters(), operatorStrategies, actions, Reporter.NO_OP); @@ -1967,6 +1969,8 @@ void testMetrixTutorial() { assertEquals(4, getOperatorStrategyResult(result, "strategy2").getLimitViolationsResult().getLimitViolations().size()); assertEquals(732.726, getOperatorStrategyResult(result, "strategy3").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); assertEquals(2, getOperatorStrategyResult(result, "strategy3").getLimitViolationsResult().getLimitViolations().size()); + assertEquals(732.726, getOperatorStrategyResult(result, "strategy4").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(2, getOperatorStrategyResult(result, "strategy4").getLimitViolationsResult().getLimitViolations().size()); } } From a4f72f48d60b2f535ca8c2a91f1558f4ddfc6575 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Fri, 14 Oct 2022 15:33:01 +0200 Subject: [PATCH 39/51] Fix code smell. Signed-off-by: Anne Tilloy --- src/main/java/com/powsybl/openloadflow/network/LfAction.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index 3831d5589c..46c87f501a 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -142,7 +142,7 @@ public void apply() { LfBranch branch = branchAndTapPosition.getLeft(); int tapPosition = branch.getPiModel().getTapPosition(); int value = branchAndTapPosition.getRight().getLeft(); - int newTapPosition = branchAndTapPosition.getRight().getRight() ? tapPosition + value : value; + int newTapPosition = Boolean.TRUE.equals(branchAndTapPosition.getRight().getRight()) ? tapPosition + value : value; branch.getPiModel().setTapPosition(newTapPosition); } } From a5106c49c7b7d4c3eed43f0146c7f545dbaa627b Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Fri, 14 Oct 2022 16:44:12 +0200 Subject: [PATCH 40/51] Refactoring Signed-off-by: Geoffroy Jamgotchian --- .../openloadflow/network/BranchState.java | 21 ++++++----- .../openloadflow/network/LfAction.java | 36 +++++++++++-------- .../powsybl/openloadflow/sa/LfActionTest.java | 6 ++-- 3 files changed, 38 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/BranchState.java b/src/main/java/com/powsybl/openloadflow/network/BranchState.java index 38d3ea8666..7fb2c50bb4 100644 --- a/src/main/java/com/powsybl/openloadflow/network/BranchState.java +++ b/src/main/java/com/powsybl/openloadflow/network/BranchState.java @@ -11,19 +11,20 @@ */ public class BranchState extends ElementState { - private final double a1; - private final double r1; + private double a1 = Double.NaN; + private double r1 = Double.NaN; private final boolean phaseControlEnabled; private final boolean voltageControlEnabled; - private int tapPosition; + private Integer tapPosition; public BranchState(LfBranch branch) { super(branch); PiModel piModel = branch.getPiModel(); - a1 = piModel.getA1(); - r1 = piModel.getR1(); if (piModel instanceof PiModelArray) { tapPosition = piModel.getTapPosition(); + } else { + a1 = piModel.getA1(); + r1 = piModel.getR1(); } phaseControlEnabled = branch.isPhaseControlEnabled(); voltageControlEnabled = branch.isVoltageControlEnabled(); @@ -33,11 +34,15 @@ public BranchState(LfBranch branch) { public void restore() { super.restore(); PiModel piModel = element.getPiModel(); - if (piModel instanceof PiModelArray) { + if (tapPosition != null) { piModel.setTapPosition(tapPosition); } - piModel.setA1(a1); - piModel.setR1(r1); + if (!Double.isNaN(a1)) { + piModel.setA1(a1); + } + if (!Double.isNaN(r1)) { + piModel.setR1(r1); + } element.setPhaseControlEnabled(phaseControlEnabled); element.setVoltageControlEnabled(voltageControlEnabled); } diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index 46c87f501a..3fea973804 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -91,21 +91,30 @@ public static void apply(List actions, LfNetwork network, LfContingenc Objects.requireNonNull(actions); Objects.requireNonNull(network); + // first process connectivity part of actions + updateConnectivity(actions, network, contingency); + + // then process remaining changes of actions + for (LfAction action : actions) { + action.apply(); + } + + network.getBuses().forEach(bus -> LOGGER.info("LfBus {} is disabled: {}", bus.getId(), bus.isDisabled())); + network.getBranches().forEach(branch -> LOGGER.info("LfBranch {} is disabled: {}", branch.getId(), branch.isDisabled())); + } + + private static void updateConnectivity(List actions, LfNetwork network, LfContingency contingency) { GraphConnectivity connectivity = network.getConnectivity(); connectivity.setMainComponentVertex(network.getSlackBus()); + + // re-update connectivity according to post contingency state (revert after LfContingency apply) connectivity.startTemporaryChanges(); - contingency.getDisabledBranches().stream() - .filter(Objects::nonNull) // could be in another component - .filter(b -> b.getBus1() != null && b.getBus2() != null) - .forEach(connectivity::removeEdge); - Set postContingencyRemovedBuses = connectivity.getVerticesRemovedFromMainComponent(); - postContingencyRemovedBuses.forEach(bus -> bus.setDisabled(false)); // undo. - Set postContingencyRemovedBranches = connectivity.getEdgesRemovedFromMainComponent(); - postContingencyRemovedBranches.forEach(branch -> branch.setDisabled(false)); // undo. + contingency.getDisabledBranches().forEach(connectivity::removeEdge); + // update connectivity according to post action state + connectivity.startTemporaryChanges(); for (LfAction action : actions) { action.updateConnectivity(connectivity); - action.apply(); } // add to action description buses and branches that won't be part of the main connected @@ -114,6 +123,7 @@ public static void apply(List actions, LfNetwork network, LfContingenc removedBuses.forEach(bus -> bus.setDisabled(true)); Set removedBranches = connectivity.getEdgesRemovedFromMainComponent(); removedBranches.forEach(branch -> branch.setDisabled(true)); + // add to action description buses and branches that will be part of the main connected // component in post action state. Set addedBuses = connectivity.getVerticesAddedToMainComponent(); @@ -121,11 +131,9 @@ public static void apply(List actions, LfNetwork network, LfContingenc Set addedBranches = connectivity.getEdgesAddedToMainComponent(); addedBranches.forEach(branch -> branch.setDisabled(false)); - // reset connectivity to discard triggered branches + // reset connectivity to discard post contingency connectivity and post action connectivity + connectivity.undoTemporaryChanges(); connectivity.undoTemporaryChanges(); - - network.getBuses().forEach(bus -> LOGGER.info("LfBus {} is disabled: {}", bus.getId(), bus.isDisabled())); - network.getBranches().forEach(branch -> LOGGER.info("LfBranch {} is disabled: {}", branch.getId(), branch.isDisabled())); } public void updateConnectivity(GraphConnectivity connectivity) { @@ -147,7 +155,7 @@ public void apply() { } } - private void checkBranch(LfBranch branch, String branchId) { + private static void checkBranch(LfBranch branch, String branchId) { if (branch == null) { throw new PowsyblException("Branch " + branchId + " not found in the network"); } diff --git a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java index 3b31d101e0..b0e2274e81 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java @@ -16,14 +16,14 @@ import com.powsybl.math.matrix.DenseMatrixFactory; import com.powsybl.openloadflow.OpenLoadFlowParameters; import com.powsybl.openloadflow.ac.outerloop.AcLoadFlowParameters; -import com.powsybl.openloadflow.graph.EvenShiloachGraphDecrementalConnectivityFactory; +import com.powsybl.openloadflow.graph.NaiveGraphConnectivityFactory; import com.powsybl.openloadflow.network.*; import com.powsybl.openloadflow.network.impl.Networks; import com.powsybl.openloadflow.network.impl.PropagatedContingency; import com.powsybl.security.action.SwitchAction; -import org.junit.jupiter.api.Test; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; import java.io.IOException; import java.util.*; @@ -53,7 +53,7 @@ void test() { SwitchAction switchAction = new SwitchAction("switchAction", "C", true); var matrixFactory = new DenseMatrixFactory(); AcLoadFlowParameters acParameters = OpenLoadFlowParameters.createAcParameters(network, - new LoadFlowParameters(), new OpenLoadFlowParameters(), matrixFactory, new EvenShiloachGraphDecrementalConnectivityFactory<>(), Reporter.NO_OP, true, false); + new LoadFlowParameters(), new OpenLoadFlowParameters(), matrixFactory, new NaiveGraphConnectivityFactory<>(LfBus::getNum), Reporter.NO_OP, true, false); List lfNetworks = Networks.load(network, acParameters.getNetworkParameters(), Set.of(network.getSwitch("C")), Collections.emptySet(), Reporter.NO_OP); LfAction lfAction = new LfAction(switchAction, lfNetworks.get(0)); String loadId = "LOAD"; From e2885fa519aada2576753f99b39235cc2880a89d Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Fri, 14 Oct 2022 21:44:49 +0200 Subject: [PATCH 41/51] Refactoring Signed-off-by: Geoffroy Jamgotchian --- .../openloadflow/network/impl/Networks.java | 2 +- .../openloadflow/sa/AcSecurityAnalysis.java | 29 +++++++++++-------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/impl/Networks.java b/src/main/java/com/powsybl/openloadflow/network/impl/Networks.java index 9132b33473..75ebc62de8 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/Networks.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/Networks.java @@ -130,7 +130,7 @@ public static List load(Network network, LfNetworkParameters networkP .forEach(sw -> sw.setRetained(true)); switchesToClose.stream().filter(sw -> sw.getVoltageLevel().getTopologyKind() == TopologyKind.NODE_BREAKER) .forEach(sw -> sw.setRetained(true)); - switchesToClose.stream().forEach(sw -> sw.setOpen(false)); // in order to be present in the network. + switchesToClose.forEach(sw -> sw.setOpen(false)); // in order to be present in the network. return load(network, networkParameters, reporter); } finally { network.getVariantManager().removeVariant(tmpVariantId); diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index d3fedb89b2..d8dbc5e5a6 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -86,7 +86,7 @@ SecurityAnalysisReport runSync(String workingVariantId, SecurityAnalysisParamete // try for find all switches to be operated as actions. Set allSwitchesToClose = new HashSet<>(); - getAllSwitchesToOperate(network, actions, allSwitchesToClose, allSwitchesToOpen); + findAllSwitchesToOperate(network, actions, allSwitchesToClose, allSwitchesToOpen); boolean breakers = !(allSwitchesToOpen.isEmpty() && allSwitchesToClose.isEmpty()); AcLoadFlowParameters acParameters = OpenLoadFlowParameters.createAcParameters(network, lfParameters, lfParametersExt, matrixFactory, connectivityFactory, saReporter, breakers, false); @@ -123,7 +123,7 @@ public static void distributedMismatch(LfNetwork network, double mismatch, LoadF } } - private static void getAllSwitchesToOperate(Network network, List actions, Set allSwitchesToClose, Set allSwitchesToOpen) { + private static void findAllSwitchesToOperate(Network network, List actions, Set allSwitchesToClose, Set allSwitchesToOpen) { actions.stream().filter(action -> action.getType().equals(SwitchAction.NAME)) .forEach(action -> { String switchId = ((SwitchAction) action).getSwitchId(); @@ -156,6 +156,20 @@ private static Map> indexOperatorStrategiesByCont return operatorStrategiesByContingencyId; } + private static void restoreInitialTopology(LfNetwork network, Set allSwitchesToClose) { + if (allSwitchesToClose.isEmpty()) { + return; + } + var connectivity = network.getConnectivity(); + allSwitchesToClose.stream().map(Identifiable::getId).forEach(id -> { + LfBranch branch = network.getBranchById(id); + branch.setDisabled(true); + if (branch.getBus1() != null && branch.getBus2() != null) { + connectivity.removeEdge(branch); + } + }); + } + private SecurityAnalysisResult runSimulations(LfNetwork network, List propagatedContingencies, AcLoadFlowParameters acParameters, SecurityAnalysisParameters securityAnalysisParameters, Map> operatorStrategiesByContingencyId, Map lfActionById, Set allSwitchesToClose) { @@ -172,16 +186,7 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List { - LfBranch branch = network.getBranchById(id); - branch.setDisabled(true); - if (branch.getBus1() != null && branch.getBus2() != null) { - connectivity.removeEdge(branch); - } - }); - } + restoreInitialTopology(network, allSwitchesToClose); AcLoadFlowResult preContingencyLoadFlowResult = engine.run(); boolean preContingencyComputationOk = preContingencyLoadFlowResult.getNewtonRaphsonStatus() == NewtonRaphsonStatus.CONVERGED; From d1f79dbca32526d2c83861f56dd09e571221406f Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Fri, 14 Oct 2022 22:02:38 +0200 Subject: [PATCH 42/51] Fix initial topo restoration Signed-off-by: Geoffroy Jamgotchian --- .../java/com/powsybl/openloadflow/network/LfNetwork.java | 1 + .../openloadflow/network/impl/PropagatedContingency.java | 1 - .../com/powsybl/openloadflow/sa/AcSecurityAnalysis.java | 8 ++++---- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java b/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java index fc6e7b78de..1febf6fa31 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfNetwork.java @@ -546,6 +546,7 @@ public GraphConnectivity getConnectivity() { getBranches().stream() .filter(b -> b.getBus1() != null && b.getBus2() != null) .forEach(b -> connectivity.addEdge(b.getBus1(), b.getBus2(), b)); + connectivity.setMainComponentVertex(getSlackBus()); } return connectivity; } 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 1907bda7b6..f72ae9c097 100644 --- a/src/main/java/com/powsybl/openloadflow/network/impl/PropagatedContingency.java +++ b/src/main/java/com/powsybl/openloadflow/network/impl/PropagatedContingency.java @@ -279,7 +279,6 @@ private static Identifiable getIdentifiable(Network network, ContingencyEleme public Optional toLfContingency(LfNetwork network) { // update connectivity with triggered branches of this network GraphConnectivity connectivity = network.getConnectivity(); - connectivity.setMainComponentVertex(network.getSlackBus()); connectivity.startTemporaryChanges(); branchIdsToOpen.stream() .map(network::getBranchById) diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index d8dbc5e5a6..a74e42930b 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -161,13 +161,13 @@ private static void restoreInitialTopology(LfNetwork network, Set allSwi return; } var connectivity = network.getConnectivity(); + connectivity.startTemporaryChanges(); allSwitchesToClose.stream().map(Identifiable::getId).forEach(id -> { LfBranch branch = network.getBranchById(id); - branch.setDisabled(true); - if (branch.getBus1() != null && branch.getBus2() != null) { - connectivity.removeEdge(branch); - } + connectivity.removeEdge(branch); }); + connectivity.getEdgesRemovedFromMainComponent().forEach(branch -> branch.setDisabled(true)); + connectivity.getVerticesRemovedFromMainComponent().forEach(bus -> bus.setDisabled(true)); } private SecurityAnalysisResult runSimulations(LfNetwork network, List propagatedContingencies, AcLoadFlowParameters acParameters, From 1d5aafead7aa312dfa83c8995143097d978764be Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Fri, 14 Oct 2022 23:01:34 +0200 Subject: [PATCH 43/51] Clean Signed-off-by: Geoffroy Jamgotchian --- ...stractHvdcAcEmulationFlowEquationTerm.java | 8 ++- .../AbstractShuntCompensatorEquationTerm.java | 3 +- .../ac/equations/AcEquationSystem.java | 60 +++++++++---------- .../equations/AbstractBranchEquationTerm.java | 3 +- .../equations/AbstractBusEquationTerm.java | 3 +- .../equations/AbstractEquationTerm.java | 10 +++- .../equations/AbstractNamedEquationTerm.java | 4 ++ .../openloadflow/equations/Equation.java | 3 +- .../equations/EquationSystem.java | 16 +++++ .../openloadflow/sa/AcSecurityAnalysis.java | 5 +- .../openloadflow/ac/AcEquationsTest.java | 3 + 11 files changed, 77 insertions(+), 41 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/ac/equations/AbstractHvdcAcEmulationFlowEquationTerm.java b/src/main/java/com/powsybl/openloadflow/ac/equations/AbstractHvdcAcEmulationFlowEquationTerm.java index 1778de9d10..8c7f539a05 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AbstractHvdcAcEmulationFlowEquationTerm.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AbstractHvdcAcEmulationFlowEquationTerm.java @@ -14,12 +14,15 @@ import com.powsybl.openloadflow.network.LfHvdc; import java.util.List; +import java.util.Objects; /** * @author Anne Tilloy */ public abstract class AbstractHvdcAcEmulationFlowEquationTerm extends AbstractNamedEquationTerm { + protected final LfHvdc hvdc; + protected final Variable ph1Var; protected final Variable ph2Var; @@ -30,17 +33,16 @@ public abstract class AbstractHvdcAcEmulationFlowEquationTerm extends AbstractNa protected final double p0; - protected final LfHvdc hvdc; - protected final double lossFactor1; protected final double lossFactor2; protected AbstractHvdcAcEmulationFlowEquationTerm(LfHvdc hvdc, LfBus bus1, LfBus bus2, VariableSet variableSet) { + super(!Objects.requireNonNull(hvdc).isDisabled()); + this.hvdc = hvdc; ph1Var = variableSet.getVariable(bus1.getNum(), AcVariableType.BUS_PHI); ph2Var = variableSet.getVariable(bus2.getNum(), AcVariableType.BUS_PHI); variables = List.of(ph1Var, ph2Var); - this.hvdc = hvdc; k = hvdc.getDroop() * 180 / Math.PI; p0 = hvdc.getP0(); lossFactor1 = hvdc.getConverterStation1().getLossFactor() / 100; diff --git a/src/main/java/com/powsybl/openloadflow/ac/equations/AbstractShuntCompensatorEquationTerm.java b/src/main/java/com/powsybl/openloadflow/ac/equations/AbstractShuntCompensatorEquationTerm.java index 26cd7df585..82683b339a 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AbstractShuntCompensatorEquationTerm.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AbstractShuntCompensatorEquationTerm.java @@ -25,7 +25,8 @@ public abstract class AbstractShuntCompensatorEquationTerm extends AbstractNamed protected final Variable vVar; protected AbstractShuntCompensatorEquationTerm(LfShunt shunt, LfBus bus, VariableSet variableSet) { - this.shunt = Objects.requireNonNull(shunt); + super(!Objects.requireNonNull(shunt).isDisabled()); + this.shunt = shunt; Objects.requireNonNull(bus); Objects.requireNonNull(variableSet); vVar = variableSet.getVariable(bus.getNum(), AcVariableType.BUS_V); diff --git a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java index 9cbb8f376e..934d1e6ef0 100644 --- a/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/ac/equations/AcEquationSystem.java @@ -26,13 +26,13 @@ private AcEquationSystem() { private static void createBusEquation(LfBus bus, EquationSystem equationSystem, AcEquationSystemCreationParameters creationParameters) { - var p = equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_P); + var p = equationSystem.createEquation(bus, AcEquationType.BUS_TARGET_P); bus.setP(p); - var q = equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_Q); + var q = equationSystem.createEquation(bus, AcEquationType.BUS_TARGET_Q); bus.setQ(q); if (bus.isSlack()) { - equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_PHI) + equationSystem.createEquation(bus, AcEquationType.BUS_TARGET_PHI) .addTerm(equationSystem.getVariable(bus.getNum(), AcVariableType.BUS_PHI) .createTerm()); p.setActive(false); @@ -50,7 +50,7 @@ private static void createBusEquation(LfBus bus, // deactivated if (!equationSystem.hasEquation(bus.getNum(), AcEquationType.BUS_TARGET_V)) { EquationTerm vTerm = equationSystem.getVariable(bus.getNum(), AcVariableType.BUS_V).createTerm(); - equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_V) + equationSystem.createEquation(bus, AcEquationType.BUS_TARGET_V) .addTerm(vTerm) .setActive(false); bus.setCalculatedV(vTerm); @@ -94,18 +94,18 @@ private static void createLocalVoltageControlEquation(LfBus bus, // we only support one generator controlling voltage with a non zero slope at a bus. // equation is: V + slope * qSVC = targetV // which is modeled here with: V + slope * (sum_branch qBranch) = TargetV - slope * qLoads + slope * qGenerators - equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_V_WITH_SLOPE) + equationSystem.createEquation(bus, AcEquationType.BUS_TARGET_V_WITH_SLOPE) .addTerm(vTerm) .addTerms(createReactiveTerms(bus, equationSystem.getVariableSet(), creationParameters) .stream() .map(term -> term.multiply(slope)) .collect(Collectors.toList())); } else { - equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_V) + equationSystem.createEquation(bus, AcEquationType.BUS_TARGET_V) .addTerm(vTerm); } - equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_Q); + equationSystem.createEquation(bus, AcEquationType.BUS_TARGET_Q); } private static void createReactivePowerControlBranchEquation(LfBranch branch, LfBus bus1, LfBus bus2, EquationSystem equationSystem, @@ -115,11 +115,11 @@ private static void createReactivePowerControlBranchEquation(LfBranch branch, Lf EquationTerm q = rpc.getControlledSide() == ReactivePowerControl.ControlledSide.ONE ? new ClosedBranchSide1ReactiveFlowEquationTerm(branch, bus1, bus2, equationSystem.getVariableSet(), deriveA1, deriveR1) : new ClosedBranchSide2ReactiveFlowEquationTerm(branch, bus1, bus2, equationSystem.getVariableSet(), deriveA1, deriveR1); - equationSystem.createEquation(branch.getNum(), AcEquationType.BRANCH_TARGET_Q) + equationSystem.createEquation(branch, AcEquationType.BRANCH_TARGET_Q) .addTerm(q); // if bus has both voltage and remote reactive power controls, then only voltage control has been kept - equationSystem.createEquation(rpc.getControllerBus().getNum(), AcEquationType.BUS_TARGET_Q); + equationSystem.createEquation(rpc.getControllerBus(), AcEquationType.BUS_TARGET_Q); updateReactivePowerControlBranchEquations(rpc, equationSystem); }); @@ -139,15 +139,15 @@ public static void updateReactivePowerControlBranchEquations(ReactivePowerContro private static void createShuntEquations(LfBus bus, EquationSystem equationSystem) { bus.getShunt().ifPresent(shunt -> { ShuntCompensatorReactiveFlowEquationTerm q = new ShuntCompensatorReactiveFlowEquationTerm(shunt, bus, equationSystem.getVariableSet(), false); - equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_Q).addTerm(q); + equationSystem.createEquation(bus, AcEquationType.BUS_TARGET_Q).addTerm(q); ShuntCompensatorActiveFlowEquationTerm p = new ShuntCompensatorActiveFlowEquationTerm(shunt, bus, equationSystem.getVariableSet()); - equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_P).addTerm(p); + equationSystem.createEquation(bus, AcEquationType.BUS_TARGET_P).addTerm(p); }); bus.getControllerShunt().ifPresent(shunt -> { ShuntCompensatorReactiveFlowEquationTerm q = new ShuntCompensatorReactiveFlowEquationTerm(shunt, bus, equationSystem.getVariableSet(), shunt.hasVoltageControlCapability()); - equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_Q).addTerm(q); + equationSystem.createEquation(bus, AcEquationType.BUS_TARGET_Q).addTerm(q); ShuntCompensatorActiveFlowEquationTerm p = new ShuntCompensatorActiveFlowEquationTerm(shunt, bus, equationSystem.getVariableSet()); - equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_P).addTerm(p); + equationSystem.createEquation(bus, AcEquationType.BUS_TARGET_P).addTerm(p); }); } @@ -158,12 +158,12 @@ private static void createRemoteVoltageControlEquations(VoltageControl voltageCo // create voltage equation at voltage controlled bus EquationTerm vTerm = equationSystem.getVariable(controlledBus.getNum(), AcVariableType.BUS_V).createTerm(); - equationSystem.createEquation(controlledBus.getNum(), AcEquationType.BUS_TARGET_V) + equationSystem.createEquation(controlledBus, AcEquationType.BUS_TARGET_V) .addTerm(vTerm); controlledBus.setCalculatedV(vTerm); for (LfBus controllerBus : voltageControl.getControllerBuses()) { - equationSystem.createEquation(controllerBus.getNum(), AcEquationType.BUS_TARGET_Q); + equationSystem.createEquation(controllerBus, AcEquationType.BUS_TARGET_Q); // create reactive power distribution equations at voltage controller buses @@ -172,7 +172,7 @@ private static void createRemoteVoltageControlEquations(VoltageControl voltageCo // 0 = qPercent_i * sum_j(q_j) - q_i // which can be rewritten in a more simple way // 0 = (qPercent_i - 1) * q_i + qPercent_i * sum_j(q_j) where j are all the voltage controller buses except i - Equation zero = equationSystem.createEquation(controllerBus.getNum(), AcEquationType.DISTR_Q) + Equation zero = equationSystem.createEquation(controllerBus, AcEquationType.DISTR_Q) .addTerms(createReactiveTerms(controllerBus, equationSystem.getVariableSet(), creationParameters).stream() .map(term -> term.multiply(() -> controllerBus.getRemoteVoltageControlReactivePercent() - 1)) .collect(Collectors.toList())); @@ -326,7 +326,7 @@ private static void createNonImpedantBranch(LfBranch branch, LfBus bus1, LfBus b .createTerm(); EquationTerm bus2vTerm = equationSystem.getVariable(bus2.getNum(), AcVariableType.BUS_V) .createTerm(); - equationSystem.createEquation(branch.getNum(), AcEquationType.ZERO_V) + equationSystem.createEquation(branch, AcEquationType.ZERO_V) .addTerm(vTerm) .addTerm(bus2vTerm.multiply(-rho)); bus1.setCalculatedV(vTerm); @@ -344,9 +344,9 @@ private static void createNonImpedantBranch(LfBranch branch, LfBus bus1, LfBus b // create an inactive dummy reactive power target equation set to zero that could be activated // on case of switch opening - equationSystem.createEquation(branch.getNum(), AcEquationType.DUMMY_TARGET_Q) + equationSystem.createEquation(branch, AcEquationType.DUMMY_TARGET_Q) .addTerm(dummyQ.createTerm()) - .setActive(false); + .setActive(branch.isDisabled()); // inverted logic } else { // nothing to do in case of v1 and v2 are found, we just have to ensure // target v are equals. @@ -357,7 +357,7 @@ private static void createNonImpedantBranch(LfBranch branch, LfBus bus1, LfBus b if (!(hasPhi1 && hasPhi2)) { // create voltage angle coupling equation // alpha = phi1 - phi2 - equationSystem.createEquation(branch.getNum(), AcEquationType.ZERO_PHI) + equationSystem.createEquation(branch, AcEquationType.ZERO_PHI) .addTerm(equationSystem.getVariable(bus1.getNum(), AcVariableType.BUS_PHI).createTerm()) .addTerm(equationSystem.getVariable(bus2.getNum(), AcVariableType.BUS_PHI).createTerm() .minus()); @@ -376,9 +376,9 @@ private static void createNonImpedantBranch(LfBranch branch, LfBus bus1, LfBus b // create an inactive dummy active power target equation set to zero that could be activated // on case of switch opening - equationSystem.createEquation(branch.getNum(), AcEquationType.DUMMY_TARGET_P) + equationSystem.createEquation(branch, AcEquationType.DUMMY_TARGET_P) .addTerm(dummyP.createTerm()) - .setActive(false); + .setActive(branch.isDisabled()); // inverted logic } else { throw new IllegalStateException("Cannot happen because only there is one slack bus per model"); } @@ -390,7 +390,7 @@ private static void createTransformerPhaseControlEquations(LfBranch branch, LfBu EquationTerm a1 = equationSystem.getVariable(branch.getNum(), AcVariableType.BRANCH_ALPHA1) .createTerm(); branch.setA1(a1); - equationSystem.createEquation(branch.getNum(), AcEquationType.BRANCH_TARGET_ALPHA1) + equationSystem.createEquation(branch, AcEquationType.BRANCH_TARGET_ALPHA1) .addTerm(a1); } @@ -404,7 +404,7 @@ private static void createTransformerPhaseControlEquations(LfBranch branch, LfBu EquationTerm p = phaseControl.getControlledSide() == DiscretePhaseControl.ControlledSide.ONE ? new ClosedBranchSide1ActiveFlowEquationTerm(branch, bus1, bus2, equationSystem.getVariableSet(), deriveA1, deriveR1) : new ClosedBranchSide2ActiveFlowEquationTerm(branch, bus1, bus2, equationSystem.getVariableSet(), deriveA1, deriveR1); - equationSystem.createEquation(branch.getNum(), AcEquationType.BRANCH_TARGET_P) + equationSystem.createEquation(branch, AcEquationType.BRANCH_TARGET_P) .addTerm(p) .setActive(false); // by default BRANCH_TARGET_ALPHA1 is active and BRANCH_TARGET_P inactive } @@ -440,7 +440,7 @@ private static void createTransformerVoltageControlEquations(LfBus bus, Equation // create voltage target equation at controlled bus EquationTerm vTerm = equationSystem.getVariable(bus.getNum(), AcVariableType.BUS_V) .createTerm(); - equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_V).addTerm(vTerm); + equationSystem.createEquation(bus, AcEquationType.BUS_TARGET_V).addTerm(vTerm); bus.setCalculatedV(vTerm); // add transformer ratio distribution equations @@ -448,7 +448,7 @@ private static void createTransformerVoltageControlEquations(LfBus bus, Equation // we also create an equation per controller that will be used later to maintain R1 variable constant for (LfBranch controllerBranch : voltageControl.getControllers()) { - equationSystem.createEquation(controllerBranch.getNum(), AcEquationType.BRANCH_TARGET_RHO1) + equationSystem.createEquation(controllerBranch, AcEquationType.BRANCH_TARGET_RHO1) .addTerm(equationSystem.getVariable(controllerBranch.getNum(), AcVariableType.BRANCH_RHO1).createTerm()); } @@ -467,7 +467,7 @@ public static void createR1DistributionEquations(List controllerBranch // 0 = (1 / controller_count - 1) * r1_i + sum_j(r1_j) / controller_count where j are all the controller branches except i EquationTerm r1 = equationSystem.getVariable(controllerBranch.getNum(), AcVariableType.BRANCH_RHO1) .createTerm(); - Equation zero = equationSystem.createEquation(controllerBranch.getNum(), AcEquationType.DISTR_RHO) + Equation zero = equationSystem.createEquation(controllerBranch, AcEquationType.DISTR_RHO) .addTerm(r1.multiply(() -> 1d / controllerBranches.stream().filter(b -> !b.isDisabled()).count() - 1)); for (LfBranch otherControllerBranch : controllerBranches) { if (otherControllerBranch != controllerBranch) { @@ -541,7 +541,7 @@ private static void createShuntVoltageControlEquations(LfBus bus, EquationSystem .ifPresent(voltageControl -> { EquationTerm vTerm = equationSystem.getVariable(bus.getNum(), AcVariableType.BUS_V) .createTerm(); - equationSystem.createEquation(bus.getNum(), AcEquationType.BUS_TARGET_V).addTerm(vTerm); + equationSystem.createEquation(bus, AcEquationType.BUS_TARGET_V).addTerm(vTerm); bus.setCalculatedV(vTerm); // add shunt distribution equations @@ -550,7 +550,7 @@ private static void createShuntVoltageControlEquations(LfBus bus, EquationSystem for (LfShunt controllerShunt : voltageControl.getControllers()) { // we also create an equation that will be used later to maintain B variable constant // this equation is now inactive - equationSystem.createEquation(controllerShunt.getNum(), AcEquationType.SHUNT_TARGET_B) + equationSystem.createEquation(controllerShunt, AcEquationType.SHUNT_TARGET_B) .addTerm(equationSystem.getVariable(controllerShunt.getNum(), AcVariableType.SHUNT_B).createTerm()); } @@ -568,7 +568,7 @@ public static void createShuntSusceptanceDistributionEquations(List con // 0 = (1 / controller_count - 1) * b_i + sum_j(b_j) / controller_count where j are all the controller buses except i EquationTerm shuntB = equationSystem.getVariable(controllerShunt.getNum(), AcVariableType.SHUNT_B) .createTerm(); - Equation zero = equationSystem.createEquation(controllerShunt.getNum(), AcEquationType.DISTR_SHUNT_B) + Equation zero = equationSystem.createEquation(controllerShunt, AcEquationType.DISTR_SHUNT_B) .addTerm(shuntB.multiply(() -> 1d / controllerShunts.stream().filter(b -> !b.isDisabled()).count() - 1)); for (LfShunt otherControllerShunt : controllerShunts) { if (otherControllerShunt != controllerShunt) { diff --git a/src/main/java/com/powsybl/openloadflow/equations/AbstractBranchEquationTerm.java b/src/main/java/com/powsybl/openloadflow/equations/AbstractBranchEquationTerm.java index d71d0e454a..b8ccc56120 100644 --- a/src/main/java/com/powsybl/openloadflow/equations/AbstractBranchEquationTerm.java +++ b/src/main/java/com/powsybl/openloadflow/equations/AbstractBranchEquationTerm.java @@ -19,7 +19,8 @@ public abstract class AbstractBranchEquationTerm & Quantity, E protected final LfBranch branch; protected AbstractBranchEquationTerm(LfBranch branch) { - this.branch = Objects.requireNonNull(branch); + super(!Objects.requireNonNull(branch).isDisabled()); + this.branch = branch; } @Override diff --git a/src/main/java/com/powsybl/openloadflow/equations/AbstractBusEquationTerm.java b/src/main/java/com/powsybl/openloadflow/equations/AbstractBusEquationTerm.java index 1f107e6e97..6f0529df9b 100644 --- a/src/main/java/com/powsybl/openloadflow/equations/AbstractBusEquationTerm.java +++ b/src/main/java/com/powsybl/openloadflow/equations/AbstractBusEquationTerm.java @@ -19,7 +19,8 @@ public abstract class AbstractBusEquationTerm & Quantity, E ex protected final LfBus bus; protected AbstractBusEquationTerm(LfBus bus) { - this.bus = Objects.requireNonNull(bus); + super(!Objects.requireNonNull(bus).isDisabled()); + this.bus = bus; } @Override diff --git a/src/main/java/com/powsybl/openloadflow/equations/AbstractEquationTerm.java b/src/main/java/com/powsybl/openloadflow/equations/AbstractEquationTerm.java index 66fa2e8b9a..884d00febe 100644 --- a/src/main/java/com/powsybl/openloadflow/equations/AbstractEquationTerm.java +++ b/src/main/java/com/powsybl/openloadflow/equations/AbstractEquationTerm.java @@ -17,12 +17,20 @@ public abstract class AbstractEquationTerm & Quantity, E exten private Equation equation; - private boolean active = true; + private boolean active; protected StateVector sv; protected EquationTerm self = this; + protected AbstractEquationTerm() { + this(true); + } + + protected AbstractEquationTerm(boolean active) { + this.active = active; + } + @Override public void setStateVector(StateVector sv) { this.sv = Objects.requireNonNull(sv); diff --git a/src/main/java/com/powsybl/openloadflow/equations/AbstractNamedEquationTerm.java b/src/main/java/com/powsybl/openloadflow/equations/AbstractNamedEquationTerm.java index 5842709846..3a918e9743 100644 --- a/src/main/java/com/powsybl/openloadflow/equations/AbstractNamedEquationTerm.java +++ b/src/main/java/com/powsybl/openloadflow/equations/AbstractNamedEquationTerm.java @@ -15,6 +15,10 @@ */ public abstract class AbstractNamedEquationTerm & Quantity, E extends Enum & Quantity> extends AbstractEquationTerm { + protected AbstractNamedEquationTerm(boolean active) { + super(active); + } + protected abstract String getName(); @Override diff --git a/src/main/java/com/powsybl/openloadflow/equations/Equation.java b/src/main/java/com/powsybl/openloadflow/equations/Equation.java index d399ebce3f..8a898a06a1 100644 --- a/src/main/java/com/powsybl/openloadflow/equations/Equation.java +++ b/src/main/java/com/powsybl/openloadflow/equations/Equation.java @@ -66,11 +66,12 @@ public boolean isActive() { return active; } - public void setActive(boolean active) { + public Equation setActive(boolean active) { if (active != this.active) { this.active = active; equationSystem.notifyEquationChange(this, active ? EquationEventType.EQUATION_ACTIVATED : EquationEventType.EQUATION_DEACTIVATED); } + return this; } public Equation addTerm(EquationTerm term) { diff --git a/src/main/java/com/powsybl/openloadflow/equations/EquationSystem.java b/src/main/java/com/powsybl/openloadflow/equations/EquationSystem.java index c48b4d6c41..6d4c2a3236 100644 --- a/src/main/java/com/powsybl/openloadflow/equations/EquationSystem.java +++ b/src/main/java/com/powsybl/openloadflow/equations/EquationSystem.java @@ -8,6 +8,7 @@ import com.powsybl.commons.PowsyblException; import com.powsybl.openloadflow.network.ElementType; +import com.powsybl.openloadflow.network.LfElement; import com.powsybl.openloadflow.network.LfNetwork; import org.apache.commons.lang3.tuple.Pair; @@ -101,6 +102,21 @@ public > T getEquationTerm(ElementType elementType, .orElseThrow(() -> new PowsyblException("Equation term not found")); } + public Equation createEquation(LfElement element, E type) { + Objects.requireNonNull(element); + Objects.requireNonNull(type); + if (element.getType() != type.getElementType()) { + throw new PowsyblException("Incorrect equation type: " + type); + } + Pair p = Pair.of(element.getNum(), type); + Equation equation = equations.get(p); + if (equation == null) { + equation = addEquation(p) + .setActive(!element.isDisabled()); + } + return equation; + } + public Equation createEquation(int num, E type) { Pair p = Pair.of(num, type); Equation equation = equations.get(p); diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index a74e42930b..5632a92359 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -184,10 +184,9 @@ private SecurityAnalysisResult runSimulations(LfNetwork network, List term, void branchTest() { var branch = Mockito.mock(LfBranch.class, ANSWER); Mockito.doReturn(0).when(branch).getNum(); + Mockito.doReturn(false).when(branch).isDisabled(); PiModel piModel = Mockito.mock(PiModel.class, ANSWER); Mockito.doReturn(piModel).when(branch).getPiModel(); Mockito.doReturn(R).when(piModel).getR(); @@ -188,6 +189,7 @@ void branchTest() { void shuntTest() { var shunt = Mockito.mock(LfShunt.class, new RuntimeExceptionAnswer()); Mockito.doReturn(0).when(shunt).getNum(); + Mockito.doReturn(false).when(shunt).isDisabled(); var bus = Mockito.mock(LfBus.class, ANSWER); Mockito.doReturn(0).when(bus).getNum(); @@ -210,6 +212,7 @@ void shuntTest() { void hvdcTest() { var hvdc = Mockito.mock(LfHvdc.class, new RuntimeExceptionAnswer()); Mockito.doReturn(0).when(hvdc).getNum(); + Mockito.doReturn(false).when(hvdc).isDisabled(); Mockito.doReturn(DROOP).when(hvdc).getDroop(); Mockito.doReturn(P_0).when(hvdc).getP0(); LfVscConverterStationImpl station1 = Mockito.mock(LfVscConverterStationImpl.class, new RuntimeExceptionAnswer()); From 496635b3b92fa91bcff532d2d15d2b03b3112a23 Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Fri, 14 Oct 2022 23:18:51 +0200 Subject: [PATCH 44/51] Clean Signed-off-by: Geoffroy Jamgotchian --- .../openloadflow/network/LfAction.java | 46 +++++++++++++------ .../powsybl/openloadflow/sa/LfActionTest.java | 26 +++++++---- 2 files changed, 48 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index 3fea973804..dde4922e6b 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -12,9 +12,6 @@ import com.powsybl.security.action.LineConnectionAction; import com.powsybl.security.action.PhaseTapChangerTapPositionAction; import com.powsybl.security.action.SwitchAction; -import org.apache.commons.lang3.tuple.Pair; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import java.util.List; import java.util.Objects; @@ -25,7 +22,32 @@ */ public class LfAction { - private static final Logger LOGGER = LoggerFactory.getLogger(LfAction.class); + private static final class TapPositionChange { + + private final LfBranch branch; + + private final int value; + + private final boolean relative; + + private TapPositionChange(LfBranch branch, int value, boolean relative) { + this.branch = Objects.requireNonNull(branch); + this.value = value; + this.relative = relative; + } + + public LfBranch getBranch() { + return branch; + } + + public int getValue() { + return value; + } + + public boolean isRelative() { + return relative; + } + } private final String id; @@ -33,7 +55,7 @@ public class LfAction { private LfBranch enabledBranch; // switch to close - private Pair> branchAndTapPosition; + private TapPositionChange tapPositionChange; public LfAction(Action action, LfNetwork network) { this.id = Objects.requireNonNull(action.getId()); @@ -67,7 +89,7 @@ public LfAction(Action action, LfNetwork network) { if (branch.getPiModel() instanceof SimplePiModel) { throw new UnsupportedOperationException("Phase tap changer tap connection action: only one tap in the branch {" + phaseTapChangerTapPositionAction.getTransformerId() + "}"); } else { - branchAndTapPosition = Pair.of(branch, Pair.of(phaseTapChangerTapPositionAction.getValue(), phaseTapChangerTapPositionAction.isRelativeValue())); + tapPositionChange = new TapPositionChange(branch, phaseTapChangerTapPositionAction.getValue(), phaseTapChangerTapPositionAction.isRelativeValue()); } break; default: @@ -98,9 +120,6 @@ public static void apply(List actions, LfNetwork network, LfContingenc for (LfAction action : actions) { action.apply(); } - - network.getBuses().forEach(bus -> LOGGER.info("LfBus {} is disabled: {}", bus.getId(), bus.isDisabled())); - network.getBranches().forEach(branch -> LOGGER.info("LfBranch {} is disabled: {}", branch.getId(), branch.isDisabled())); } private static void updateConnectivity(List actions, LfNetwork network, LfContingency contingency) { @@ -146,11 +165,11 @@ public void updateConnectivity(GraphConnectivity connectivity) } public void apply() { - if (branchAndTapPosition != null) { - LfBranch branch = branchAndTapPosition.getLeft(); + if (tapPositionChange != null) { + LfBranch branch = tapPositionChange.getBranch(); int tapPosition = branch.getPiModel().getTapPosition(); - int value = branchAndTapPosition.getRight().getLeft(); - int newTapPosition = Boolean.TRUE.equals(branchAndTapPosition.getRight().getRight()) ? tapPosition + value : value; + int value = tapPositionChange.getValue(); + int newTapPosition = tapPositionChange.isRelative() ? tapPosition + value : value; branch.getPiModel().setTapPosition(newTapPosition); } } @@ -160,5 +179,4 @@ private static void checkBranch(LfBranch branch, String branchId) { throw new PowsyblException("Branch " + branchId + " not found in the network"); } } - } diff --git a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java index b0e2274e81..119e74e7c9 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/LfActionTest.java @@ -1,5 +1,5 @@ /** - * Copyright (c) 2020, RTE (http://www.rte-france.com) + * Copyright (c) 2022, RTE (http://www.rte-france.com) * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. @@ -17,7 +17,10 @@ import com.powsybl.openloadflow.OpenLoadFlowParameters; import com.powsybl.openloadflow.ac.outerloop.AcLoadFlowParameters; import com.powsybl.openloadflow.graph.NaiveGraphConnectivityFactory; -import com.powsybl.openloadflow.network.*; +import com.powsybl.openloadflow.network.LfAction; +import com.powsybl.openloadflow.network.LfBus; +import com.powsybl.openloadflow.network.LfNetwork; +import com.powsybl.openloadflow.network.NodeBreakerNetworkFactory; import com.powsybl.openloadflow.network.impl.Networks; import com.powsybl.openloadflow.network.impl.PropagatedContingency; import com.powsybl.security.action.SwitchAction; @@ -26,7 +29,10 @@ import org.junit.jupiter.api.Test; import java.io.IOException; -import java.util.*; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; import static org.junit.jupiter.api.Assertions.*; @@ -55,20 +61,20 @@ void test() { AcLoadFlowParameters acParameters = OpenLoadFlowParameters.createAcParameters(network, new LoadFlowParameters(), new OpenLoadFlowParameters(), matrixFactory, new NaiveGraphConnectivityFactory<>(LfBus::getNum), Reporter.NO_OP, true, false); List lfNetworks = Networks.load(network, acParameters.getNetworkParameters(), Set.of(network.getSwitch("C")), Collections.emptySet(), Reporter.NO_OP); - LfAction lfAction = new LfAction(switchAction, lfNetworks.get(0)); + LfNetwork lfNetwork = lfNetworks.get(0); + LfAction lfAction = new LfAction(switchAction, lfNetwork); String loadId = "LOAD"; Contingency contingency = new Contingency(loadId, new LoadContingency("LD")); PropagatedContingency propagatedContingency = PropagatedContingency.createList(network, Collections.singletonList(contingency), new HashSet<>(), false, false, false, true).get(0); - Optional lfContingency = propagatedContingency.toLfContingency(lfNetworks.get(0)); - if (lfContingency.isPresent()) { - LfAction.apply(List.of(lfAction), lfNetworks.get(0), lfContingency.get()); - assertTrue(lfNetworks.get(0).getBranchById("C").isDisabled()); + propagatedContingency.toLfContingency(lfNetwork).ifPresent(lfContingency -> { + LfAction.apply(List.of(lfAction), lfNetwork, lfContingency); + assertTrue(lfNetwork.getBranchById("C").isDisabled()); assertEquals("C", lfAction.getDisabledBranch().getId()); assertNull(lfAction.getEnabledBranch()); - } + }); SwitchAction switchAction2 = new SwitchAction("switchAction", "S", true); - assertThrows(PowsyblException.class, () -> new LfAction(switchAction2, lfNetworks.get(0)), "Branch S not found in the network"); + assertThrows(PowsyblException.class, () -> new LfAction(switchAction2, lfNetwork), "Branch S not found in the network"); } } From 3b281fa3f171695c62a1cefc4f8e64f59bc0d6ec Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Fri, 14 Oct 2022 23:24:20 +0200 Subject: [PATCH 45/51] Clean Signed-off-by: Geoffroy Jamgotchian --- .../java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index 5632a92359..bb74559e86 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -362,7 +362,6 @@ private Optional runActionSimulation(LfNetwork network, } private boolean checkCondition(OperatorStrategy operatorStrategy, LimitViolationsResult limitViolationsResult) { - // FIXME: add logs. Set limitViolationEquipmentIds = limitViolationsResult.getLimitViolations().stream() .map(LimitViolation::getSubjectId) .collect(Collectors.toSet()); From d0d15d568940a9a91a261f9624932e790a79459d Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Mon, 17 Oct 2022 08:56:03 +0200 Subject: [PATCH 46/51] Improve unit test. Signed-off-by: Anne Tilloy --- .../sa/OpenSecurityAnalysisTest.java | 46 ++++++++++++------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index 188432ff36..69fa83b66d 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -1940,9 +1940,13 @@ void testMetrixTutorial() { securityAnalysisProvider = new OpenSecurityAnalysisProvider(matrixFactory, connectivityFactory); Network network = MetrixTutorialSixBusesFactory.create(); - network.getGenerator("SO_G2").setTargetP(960); - network.getGenerator("SO_G1").setTargetP(0); - network.getLoad("SE_L1").setP0(960); + network.getGenerator("SO_G2").setTargetP(628); + + SecurityAnalysisParameters securityAnalysisParameters = new SecurityAnalysisParameters(); + LoadFlowParameters parameters = new LoadFlowParameters(); + parameters.setBalanceType(LoadFlowParameters.BalanceType.PROPORTIONAL_TO_LOAD); + parameters.setHvdcAcEmulation(false); + securityAnalysisParameters.setLoadFlowParameters(parameters); List contingencies = List.of(new Contingency("S_SO_1", new BranchContingency("S_SO_1"))); @@ -1957,20 +1961,28 @@ void testMetrixTutorial() { new OperatorStrategy("strategy3", "S_SO_1", new TrueCondition(), List.of("pst")), new OperatorStrategy("strategy4", "S_SO_1", new TrueCondition(), List.of("pst2"))); - SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors, new SecurityAnalysisParameters(), + SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors, securityAnalysisParameters, operatorStrategies, actions, Reporter.NO_OP); - assertEquals(395.413, result.getPreContingencyResult().getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); - assertEquals(735.862, getPostContingencyResult(result, "S_SO_1").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); - assertEquals(2, getPostContingencyResult(result, "S_SO_1").getLimitViolationsResult().getLimitViolations().size()); - assertEquals(287.129, getOperatorStrategyResult(result, "strategy1").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); - assertEquals(1938.36, getOperatorStrategyResult(result, "strategy1").getNetworkResult().getBranchResult("SO_NO_1").getI1(), LoadFlowAssert.DELTA_I); - assertEquals(4, getOperatorStrategyResult(result, "strategy1").getLimitViolationsResult().getLimitViolations().size()); - assertEquals(683.392, getOperatorStrategyResult(result, "strategy2").getNetworkResult().getBranchResult("SO_NO_1").getI1(), LoadFlowAssert.DELTA_I); - assertEquals(4, getOperatorStrategyResult(result, "strategy2").getLimitViolationsResult().getLimitViolations().size()); - assertEquals(732.726, getOperatorStrategyResult(result, "strategy3").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); - assertEquals(2, getOperatorStrategyResult(result, "strategy3").getLimitViolationsResult().getLimitViolations().size()); - assertEquals(732.726, getOperatorStrategyResult(result, "strategy4").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); - assertEquals(2, getOperatorStrategyResult(result, "strategy4").getLimitViolationsResult().getLimitViolations().size()); - } + assertEquals(271.99, result.getPreContingencyResult().getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(504.40, getPostContingencyResult(result, "S_SO_1").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(298.70, getOperatorStrategyResult(result, "strategy1").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(488.99, getOperatorStrategyResult(result, "strategy2").getNetworkResult().getBranchResult("SO_NO_1").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(499.984, getOperatorStrategyResult(result, "strategy3").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); + assertEquals(499.984, getOperatorStrategyResult(result, "strategy4").getNetworkResult().getBranchResult("S_SO_2").getI1(), LoadFlowAssert.DELTA_I); + + network.getGenerator("SO_G2").setTargetP(628); + network.getLine("S_SO_1").getTerminal1().disconnect(); + network.getLine("S_SO_1").getTerminal2().disconnect(); + LoadFlowParameters parameters2 = new LoadFlowParameters(); + parameters2.setBalanceType(LoadFlowParameters.BalanceType.PROPORTIONAL_TO_LOAD); + parameters2.setHvdcAcEmulation(false); + + LoadFlow.run(network, parameters); + assertEquals(504.40, network.getLine("S_SO_2").getTerminal1().getI(), LoadFlowAssert.DELTA_I); + + network.getTwoWindingsTransformer("NE_NO_1").getPhaseTapChanger().setTapPosition(1); + LoadFlow.run(network, parameters); + assertEquals(499.989, network.getLine("S_SO_2").getTerminal1().getI(), LoadFlowAssert.DELTA_I); + } } From 322ff5612f8e24ae8608cc85106929a17bf52ca7 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Mon, 17 Oct 2022 09:52:45 +0200 Subject: [PATCH 47/51] Fix indentation. Signed-off-by: Anne Tilloy --- .../sa/OpenSecurityAnalysisTest.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index 69fa83b66d..e5d986d886 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -1879,10 +1879,10 @@ void testSecurityAnalysisWithOperatorStrategy3() { .collect(Collectors.toList()); List actions = List.of(new SwitchAction("action1", "C1", false), - new SwitchAction("action3", "C2", false)); + new SwitchAction("action3", "C2", false)); List operatorStrategies = List.of(new OperatorStrategy("strategyL3", "L3", new AllViolationCondition(List.of("VL1", "VL2")), List.of("action3")), - new OperatorStrategy("strategyL2", "L2", new AtLeastOneViolationCondition(List.of("L1", "L3")), List.of("action1", "action3"))); + new OperatorStrategy("strategyL2", "L2", new AtLeastOneViolationCondition(List.of("L1", "L3")), List.of("action1", "action3"))); List monitors = createAllBranchesMonitors(network); @@ -1953,13 +1953,13 @@ void testMetrixTutorial() { List monitors = createAllBranchesMonitors(network); List actions = List.of(new SwitchAction("openSwitchS0", "SOO1_SOO1_DJ_OMN", true), - new LineConnectionAction("openLineSSO2", "S_SO_2", true, true), - new PhaseTapChangerTapPositionAction("pst", "NE_NO_1", false, 1), // PST at tap position 17. - new PhaseTapChangerTapPositionAction("pst2", "NE_NO_1", true, -16)); + new LineConnectionAction("openLineSSO2", "S_SO_2", true, true), + new PhaseTapChangerTapPositionAction("pst", "NE_NO_1", false, 1), // PST at tap position 17. + new PhaseTapChangerTapPositionAction("pst2", "NE_NO_1", true, -16)); List operatorStrategies = List.of(new OperatorStrategy("strategy1", "S_SO_1", new AllViolationCondition(List.of("S_SO_2")), List.of("openSwitchS0")), - new OperatorStrategy("strategy2", "S_SO_1", new AllViolationCondition(List.of("S_SO_2")), List.of("openLineSSO2")), - new OperatorStrategy("strategy3", "S_SO_1", new TrueCondition(), List.of("pst")), - new OperatorStrategy("strategy4", "S_SO_1", new TrueCondition(), List.of("pst2"))); + new OperatorStrategy("strategy2", "S_SO_1", new AllViolationCondition(List.of("S_SO_2")), List.of("openLineSSO2")), + new OperatorStrategy("strategy3", "S_SO_1", new TrueCondition(), List.of("pst")), + new OperatorStrategy("strategy4", "S_SO_1", new TrueCondition(), List.of("pst2"))); SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors, securityAnalysisParameters, operatorStrategies, actions, Reporter.NO_OP); From f68755139368793227ae87c88a6deaf23a442e59 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Mon, 17 Oct 2022 09:54:42 +0200 Subject: [PATCH 48/51] Clean. Signed-off-by: Anne Tilloy --- src/main/java/com/powsybl/openloadflow/network/LfAction.java | 1 - .../com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java | 1 - 2 files changed, 2 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index dde4922e6b..4fc0ca9d6b 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -124,7 +124,6 @@ public static void apply(List actions, LfNetwork network, LfContingenc private static void updateConnectivity(List actions, LfNetwork network, LfContingency contingency) { GraphConnectivity connectivity = network.getConnectivity(); - connectivity.setMainComponentVertex(network.getSlackBus()); // re-update connectivity according to post contingency state (revert after LfContingency apply) connectivity.startTemporaryChanges(); diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index 1ed5df0637..73d58608d3 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -580,7 +580,6 @@ private static List computeConnectivityData(LfNetwor Map, ConnectivityAnalysisResult> connectivityAnalysisResults = new LinkedHashMap<>(); GraphConnectivity connectivity = lfNetwork.getConnectivity(); - connectivity.setMainComponentVertex(lfNetwork.getSlackBus()); for (Map.Entry, List> e : contingenciesByGroupOfElementsBreakingConnectivity.entrySet()) { Set breakingConnectivityCandidates = e.getKey(); List contingencyList = e.getValue(); From fb670cad489e0757c49fb0697d7726eed9f949d5 Mon Sep 17 00:00:00 2001 From: Anne Tilloy Date: Tue, 18 Oct 2022 13:55:47 +0200 Subject: [PATCH 49/51] Try to fix open lines. Signed-off-by: Anne Tilloy --- .../openloadflow/network/LfAction.java | 13 ++++++++++-- .../util/PreviousValueVoltageInitializer.java | 5 ++--- .../openloadflow/sa/AcSecurityAnalysis.java | 10 ++++++++-- .../sa/OpenSecurityAnalysisTest.java | 20 +++++++++++++++++++ 4 files changed, 41 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfAction.java b/src/main/java/com/powsybl/openloadflow/network/LfAction.java index 4fc0ca9d6b..55cf76d7c2 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfAction.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfAction.java @@ -13,6 +13,7 @@ import com.powsybl.security.action.PhaseTapChangerTapPositionAction; import com.powsybl.security.action.SwitchAction; +import java.util.HashSet; import java.util.List; import java.util.Objects; import java.util.Set; @@ -139,14 +140,22 @@ private static void updateConnectivity(List actions, LfNetwork network // component in post action state. Set removedBuses = connectivity.getVerticesRemovedFromMainComponent(); removedBuses.forEach(bus -> bus.setDisabled(true)); - Set removedBranches = connectivity.getEdgesRemovedFromMainComponent(); + Set removedBranches = new HashSet<>(connectivity.getEdgesRemovedFromMainComponent()); + // we should manage branches open at one side. + for (LfBus bus : removedBuses) { + bus.getBranches().stream().filter(b -> !b.isConnectedAtBothSides()).forEach(removedBranches::add); + } removedBranches.forEach(branch -> branch.setDisabled(true)); // add to action description buses and branches that will be part of the main connected // component in post action state. Set addedBuses = connectivity.getVerticesAddedToMainComponent(); addedBuses.forEach(bus -> bus.setDisabled(false)); - Set addedBranches = connectivity.getEdgesAddedToMainComponent(); + Set addedBranches = new HashSet<>(connectivity.getEdgesAddedToMainComponent()); + // we should manage branches open at one side. + for (LfBus bus : addedBuses) { + bus.getBranches().stream().filter(b -> !b.isConnectedAtBothSides()).forEach(addedBranches::add); + } addedBranches.forEach(branch -> branch.setDisabled(false)); // reset connectivity to discard post contingency connectivity and post action connectivity diff --git a/src/main/java/com/powsybl/openloadflow/network/util/PreviousValueVoltageInitializer.java b/src/main/java/com/powsybl/openloadflow/network/util/PreviousValueVoltageInitializer.java index 890a9bd48c..579140d034 100644 --- a/src/main/java/com/powsybl/openloadflow/network/util/PreviousValueVoltageInitializer.java +++ b/src/main/java/com/powsybl/openloadflow/network/util/PreviousValueVoltageInitializer.java @@ -6,7 +6,6 @@ */ package com.powsybl.openloadflow.network.util; -import com.powsybl.commons.PowsyblException; import com.powsybl.openloadflow.network.LfBus; import com.powsybl.openloadflow.network.LfNetwork; @@ -24,7 +23,7 @@ public void prepare(LfNetwork network) { public double getMagnitude(LfBus bus) { double v = bus.getV(); if (Double.isNaN(v)) { - throw new PowsyblException("Voltage magnitude is undefined for bus '" + bus.getId() + "'"); + v = 1.0; } return v; } @@ -33,7 +32,7 @@ public double getMagnitude(LfBus bus) { public double getAngle(LfBus bus) { double angle = bus.getAngle(); if (Double.isNaN(angle)) { - throw new PowsyblException("Voltage angle is undefined for bus '" + bus.getId() + "'"); + angle = 0.0; } return angle; } diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index bb74559e86..0cee2bf6d5 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -166,8 +166,14 @@ private static void restoreInitialTopology(LfNetwork network, Set allSwi LfBranch branch = network.getBranchById(id); connectivity.removeEdge(branch); }); - connectivity.getEdgesRemovedFromMainComponent().forEach(branch -> branch.setDisabled(true)); - connectivity.getVerticesRemovedFromMainComponent().forEach(bus -> bus.setDisabled(true)); + Set removedBuses = connectivity.getVerticesRemovedFromMainComponent(); + removedBuses.forEach(bus -> bus.setDisabled(true)); + Set removedBranches = new HashSet<>(connectivity.getEdgesRemovedFromMainComponent()); + // we should manage branches open at one side. + for (LfBus bus : removedBuses) { + bus.getBranches().stream().filter(b -> !b.isConnectedAtBothSides()).forEach(removedBranches::add); + } + removedBranches.forEach(branch -> branch.setDisabled(true)); } private SecurityAnalysisResult runSimulations(LfNetwork network, List propagatedContingencies, AcLoadFlowParameters acParameters, diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index ce9a0ae80c..d0da7b0ede 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -1995,4 +1995,24 @@ void testMetrixTutorial() { LoadFlow.run(network, parameters); assertEquals(499.989, network.getLine("S_SO_2").getTerminal1().getI(), LoadFlowAssert.DELTA_I); } + + @Test + void testBranchOpenAtOneSideRecovery() { + MatrixFactory matrixFactory = new DenseMatrixFactory(); + GraphConnectivityFactory connectivityFactory = new NaiveGraphConnectivityFactory<>(LfBus::getNum); + securityAnalysisProvider = new OpenSecurityAnalysisProvider(matrixFactory, connectivityFactory); + + var network = ConnectedComponentNetworkFactory.createTwoCcLinkedBySwitches(); + network.getLine("l46").getTerminal1().disconnect(); + network.getSwitch("s25").setOpen(true); + network.getSwitch("s34").setOpen(true); + List contingencies = List.of(new Contingency("line", new BranchContingency("l12"))); + List actions = List.of(new SwitchAction("closeSwitch", "s25", false)); + List operatorStrategies = List.of(new OperatorStrategy("strategy", "line", new TrueCondition(), List.of("closeSwitch"))); + List monitors = createAllBranchesMonitors(network); + SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors, new SecurityAnalysisParameters(), + operatorStrategies, actions, Reporter.NO_OP); + assertEquals(-2.996, getOperatorStrategyResult(result, "strategy").getNetworkResult().getBranchResult("l23").getP1(), LoadFlowAssert.DELTA_POWER); + assertEquals(-3.000, getOperatorStrategyResult(result, "strategy").getNetworkResult().getBranchResult("l45").getP1(), LoadFlowAssert.DELTA_POWER); + } } From 02479797db3a71833592823e0e4cb648bbafaab8 Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Tue, 18 Oct 2022 15:38:52 +0200 Subject: [PATCH 50/51] Force naive algo in case of operator stategies Signed-off-by: Geoffroy Jamgotchian --- .../sa/OpenSecurityAnalysisProvider.java | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisProvider.java b/src/main/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisProvider.java index 7b207be02d..fbfe14e81c 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisProvider.java +++ b/src/main/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisProvider.java @@ -18,6 +18,7 @@ import com.powsybl.math.matrix.SparseMatrixFactory; import com.powsybl.openloadflow.graph.EvenShiloachGraphDecrementalConnectivityFactory; import com.powsybl.openloadflow.graph.GraphConnectivityFactory; +import com.powsybl.openloadflow.graph.NaiveGraphConnectivityFactory; import com.powsybl.openloadflow.network.LfBranch; import com.powsybl.openloadflow.network.LfBus; import com.powsybl.openloadflow.util.PowsyblOpenLoadFlowVersion; @@ -27,6 +28,8 @@ import com.powsybl.security.interceptors.SecurityAnalysisInterceptor; import com.powsybl.security.monitor.StateMonitor; import com.powsybl.security.strategy.OperatorStrategy; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.*; import java.util.concurrent.CompletableFuture; @@ -37,6 +40,8 @@ @AutoService(SecurityAnalysisProvider.class) public class OpenSecurityAnalysisProvider implements SecurityAnalysisProvider { + private static final Logger LOGGER = LoggerFactory.getLogger(OpenSecurityAnalysisProvider.class); + private final MatrixFactory matrixFactory; private final GraphConnectivityFactory connectivityFactory; @@ -58,17 +63,30 @@ public CompletableFuture run(Network network, String wor List stateMonitors, Reporter reporter) { Objects.requireNonNull(network); Objects.requireNonNull(workingVariantId); + Objects.requireNonNull(limitViolationDetector); Objects.requireNonNull(computationManager); Objects.requireNonNull(securityAnalysisParameters); Objects.requireNonNull(contingenciesProvider); + Objects.requireNonNull(interceptors); + Objects.requireNonNull(operatorStrategies); + Objects.requireNonNull(actions); Objects.requireNonNull(stateMonitors); Objects.requireNonNull(reporter); + // FIXME implement a fast incremental connectivity algorithm + GraphConnectivityFactory selectedConnectivityFactory; + if (operatorStrategies.isEmpty()) { + selectedConnectivityFactory = connectivityFactory; + } else { + LOGGER.warn("Naive (and slow!!!) connectivity algorithm has been selected because at least one operator strategy is configured"); + selectedConnectivityFactory = new NaiveGraphConnectivityFactory<>(LfBus::getNum); + } + AbstractSecurityAnalysis securityAnalysis; if (securityAnalysisParameters.getLoadFlowParameters().isDc()) { - securityAnalysis = new DcSecurityAnalysis(network, matrixFactory, connectivityFactory, stateMonitors, reporter); + securityAnalysis = new DcSecurityAnalysis(network, matrixFactory, selectedConnectivityFactory, stateMonitors, reporter); } else { - securityAnalysis = new AcSecurityAnalysis(network, matrixFactory, connectivityFactory, stateMonitors, reporter); + securityAnalysis = new AcSecurityAnalysis(network, matrixFactory, selectedConnectivityFactory, stateMonitors, reporter); } return securityAnalysis.run(workingVariantId, securityAnalysisParameters, contingenciesProvider, computationManager, operatorStrategies, actions); From 6acd8ffcae9eae7d283b5827eea133adfa928398 Mon Sep 17 00:00:00 2001 From: Geoffroy Jamgotchian Date: Tue, 18 Oct 2022 15:50:33 +0200 Subject: [PATCH 51/51] Fix PreviousValueVoltageInitializer Signed-off-by: Geoffroy Jamgotchian --- .../util/PreviousValueVoltageInitializer.java | 25 +++++++++++++++++-- .../openloadflow/sa/AcSecurityAnalysis.java | 2 +- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/util/PreviousValueVoltageInitializer.java b/src/main/java/com/powsybl/openloadflow/network/util/PreviousValueVoltageInitializer.java index 579140d034..bd6986e258 100644 --- a/src/main/java/com/powsybl/openloadflow/network/util/PreviousValueVoltageInitializer.java +++ b/src/main/java/com/powsybl/openloadflow/network/util/PreviousValueVoltageInitializer.java @@ -6,6 +6,7 @@ */ package com.powsybl.openloadflow.network.util; +import com.powsybl.commons.PowsyblException; import com.powsybl.openloadflow.network.LfBus; import com.powsybl.openloadflow.network.LfNetwork; @@ -14,6 +15,18 @@ */ public class PreviousValueVoltageInitializer implements VoltageInitializer { + private final UniformValueVoltageInitializer defaultVoltageInitializer = new UniformValueVoltageInitializer(); + + private final boolean defaultToUniformValue; + + public PreviousValueVoltageInitializer() { + this(false); + } + + public PreviousValueVoltageInitializer(boolean defaultToUniformValue) { + this.defaultToUniformValue = defaultToUniformValue; + } + @Override public void prepare(LfNetwork network) { // nothing to do @@ -23,7 +36,11 @@ public void prepare(LfNetwork network) { public double getMagnitude(LfBus bus) { double v = bus.getV(); if (Double.isNaN(v)) { - v = 1.0; + if (defaultToUniformValue) { + return defaultVoltageInitializer.getMagnitude(bus); + } else { + throw new PowsyblException("Voltage magnitude is undefined for bus '" + bus.getId() + "'"); + } } return v; } @@ -32,7 +49,11 @@ public double getMagnitude(LfBus bus) { public double getAngle(LfBus bus) { double angle = bus.getAngle(); if (Double.isNaN(angle)) { - angle = 0.0; + if (defaultToUniformValue) { + return defaultVoltageInitializer.getAngle(bus); + } else { + throw new PowsyblException("Voltage angle is undefined for bus '" + bus.getId() + "'"); + } } return angle; } diff --git a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java index 0cee2bf6d5..bb51f66fb4 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/AcSecurityAnalysis.java @@ -335,7 +335,7 @@ private Optional runActionSimulation(LfNetwork network, Stopwatch stopwatch = Stopwatch.createStarted(); // restart LF on post contingency and post actions equation system - context.getParameters().setVoltageInitializer(new PreviousValueVoltageInitializer()); + context.getParameters().setVoltageInitializer(new PreviousValueVoltageInitializer(true)); AcLoadFlowResult postActionsLoadFlowResult = new AcloadFlowEngine(context) .run();