From 73ea4c7ef15bc764f1fe314b585d6d75b57e5957 Mon Sep 17 00:00:00 2001 From: p-arvy Date: Tue, 18 Feb 2025 11:29:38 +0100 Subject: [PATCH 01/19] Refactor connectivity break analysis to add connectivity loss impact Signed-off-by: p-arvy --- .../dc/fastdc/ConnectivityBreakAnalysis.java | 24 ++++++++++++------- .../sa/WoodburyDcSecurityAnalysis.java | 10 ++++---- .../sensi/DcSensitivityAnalysis.java | 2 +- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java b/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java index df97155162..3feed40c78 100644 --- a/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java @@ -48,23 +48,29 @@ public static final class ConnectivityAnalysisResult { private final Set slackConnectedComponent; // buses of connected component where the slack is - private final int createdSynchronousComponents; + private final Set slackConnectedComponentBuses; // buses of connected component where the slack is private final DisabledElements disabledElements; - public ConnectivityAnalysisResult(PropagatedContingency nonBreakingConnectivityContingency, LfNetwork network) { - this(nonBreakingConnectivityContingency, network, Collections.emptySet(), DisabledElements.NO_DISABLED_ELEMENTS, Collections.emptySet(), 0); + private final int createdSynchronousComponents; + + private final Set hvdcsWithoutPower; + + public ConnectivityAnalysisResult(PropagatedContingency propagatedContingency, LfNetwork network) { + this(propagatedContingency, network, Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), 0, Collections.emptySet()); } public ConnectivityAnalysisResult(PropagatedContingency propagatedContingency, LfNetwork network, Set elementsToReconnect, - DisabledElements disabledElements, Set slackConnectedComponentBuses, - int createdSynchronousComponents) { + Set disabledBuses, Set slackConnectedComponentBuses, Set partialDisabledBranches, + int createdSynchronousComponents, Set hvdcsWithoutPower) { this.propagatedContingency = Objects.requireNonNull(propagatedContingency); this.network = Objects.requireNonNull(network); this.elementsToReconnect = elementsToReconnect; - this.disabledElements = disabledElements; - this.slackConnectedComponent = slackConnectedComponentBuses; + this.disabledBuses = disabledBuses; + this.slackConnectedComponentBuses = slackConnectedComponentBuses; + this.partialDisabledBranches = partialDisabledBranches; this.createdSynchronousComponents = createdSynchronousComponents; + this.hvdcsWithoutPower = hvdcsWithoutPower; } public PropagatedContingency getPropagatedContingency() { @@ -79,8 +85,8 @@ public Set getDisabledBuses() { return disabledElements.disabledBuses; } - public Set getSlackConnectedComponent() { - return slackConnectedComponent; + public Set getSlackConnectedComponentBuses() { + return slackConnectedComponentBuses; } public Set getPartialDisabledBranches() { diff --git a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java index 94da05d287..085059a84f 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java @@ -133,7 +133,7 @@ private double[] calculatePostContingencyAndOperatorStrategyStates(DcLoadFlowCon }); List contingencyElements = contingency.getBranchIdsToOpen().keySet().stream() - .filter(element -> !elementsToReconnect.contains(element)) + .filter(element -> !connectivityAnalysisResult.getElementsToReconnect().contains(element)) .map(contingencyElementByBranch::get) .collect(Collectors.toList()); List actionElements = operatorStrategyLfActions.stream() @@ -144,8 +144,8 @@ private double[] calculatePostContingencyAndOperatorStrategyStates(DcLoadFlowCon var lfNetwork = loadFlowContext.getNetwork(); Set disabledBranches = contingency.getBranchIdsToOpen().keySet().stream().map(lfNetwork::getBranchById).collect(Collectors.toSet()); - disabledBranches.addAll(partialDisabledBranches); - DisabledNetwork disabledNetwork = new DisabledNetwork(disabledBuses, disabledBranches); + disabledBranches.addAll(connectivityAnalysisResult.getPartialDisabledBranches()); + DisabledNetwork disabledNetwork = new DisabledNetwork(connectivityAnalysisResult.getDisabledBuses(), disabledBranches); WoodburyEngine engine = new WoodburyEngine(loadFlowContext.getParameters().getEquationSystemCreationParameters(), contingencyElements, contingenciesStates, actionElements, actionsStates); double[] newFlowStates = flowStates; @@ -153,7 +153,7 @@ private double[] calculatePostContingencyAndOperatorStrategyStates(DcLoadFlowCon // get the lost phase tap changers for this contingency Set lostPhaseControllers = contingency.getBranchIdsToOpen().keySet().stream() - .filter(element -> !elementsToReconnect.contains(element)) + .filter(element -> !connectivityAnalysisResult.getElementsToReconnect().contains(element)) .map(contingencyElementByBranch::get) .map(ComputedContingencyElement::getLfBranch) .filter(LfBranch::hasPhaseControllerCapability) @@ -161,7 +161,7 @@ private double[] calculatePostContingencyAndOperatorStrategyStates(DcLoadFlowCon // if a phase tap changer is lost or if the connectivity have changed, we must recompute load flows // same if there is an action, as they are only on pst for now - if (!disabledBuses.isEmpty() || !lostPhaseControllers.isEmpty() || !operatorStrategyLfActions.isEmpty()) { + if (!connectivityAnalysisResult.getDisabledBuses().isEmpty() || !lostPhaseControllers.isEmpty() || !operatorStrategyLfActions.isEmpty()) { newFlowStates = WoodburyEngine.runDcLoadFlowWithModifiedTargetVector(loadFlowContext, disabledNetwork, reportNode, operatorStrategyLfActions); } engine.toPostContingencyAndOperatorStrategyStates(newFlowStates); diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index 2b34c4f81b..45dc46b11e 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -331,7 +331,7 @@ private void processContingenciesBreakingConnectivity(ConnectivityBreakAnalysis. // we need to recompute the participating elements because the connectivity changed if (rhsChanged) { participatingElementsForThisConnectivity = lfParameters.isDistributedSlack() - ? getParticipatingElements(connectivityAnalysisResult.getSlackConnectedComponent(), lfParameters.getBalanceType(), lfParametersExt) // will also be used to recompute the loadflow + ? getParticipatingElements(connectivityAnalysisResult.getSlackConnectedComponentBuses(), lfParameters.getBalanceType(), lfParametersExt) // will also be used to recompute the loadflow : Collections.emptyList(); } From 58d4c0da993581900ce61fd4829fdf39fcfec403 Mon Sep 17 00:00:00 2001 From: p-arvy Date: Tue, 18 Feb 2025 11:54:09 +0100 Subject: [PATCH 02/19] Clean Signed-off-by: p-arvy --- .../openloadflow/sa/WoodburyDcSecurityAnalysis.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java index 085059a84f..94da05d287 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java @@ -133,7 +133,7 @@ private double[] calculatePostContingencyAndOperatorStrategyStates(DcLoadFlowCon }); List contingencyElements = contingency.getBranchIdsToOpen().keySet().stream() - .filter(element -> !connectivityAnalysisResult.getElementsToReconnect().contains(element)) + .filter(element -> !elementsToReconnect.contains(element)) .map(contingencyElementByBranch::get) .collect(Collectors.toList()); List actionElements = operatorStrategyLfActions.stream() @@ -144,8 +144,8 @@ private double[] calculatePostContingencyAndOperatorStrategyStates(DcLoadFlowCon var lfNetwork = loadFlowContext.getNetwork(); Set disabledBranches = contingency.getBranchIdsToOpen().keySet().stream().map(lfNetwork::getBranchById).collect(Collectors.toSet()); - disabledBranches.addAll(connectivityAnalysisResult.getPartialDisabledBranches()); - DisabledNetwork disabledNetwork = new DisabledNetwork(connectivityAnalysisResult.getDisabledBuses(), disabledBranches); + disabledBranches.addAll(partialDisabledBranches); + DisabledNetwork disabledNetwork = new DisabledNetwork(disabledBuses, disabledBranches); WoodburyEngine engine = new WoodburyEngine(loadFlowContext.getParameters().getEquationSystemCreationParameters(), contingencyElements, contingenciesStates, actionElements, actionsStates); double[] newFlowStates = flowStates; @@ -153,7 +153,7 @@ private double[] calculatePostContingencyAndOperatorStrategyStates(DcLoadFlowCon // get the lost phase tap changers for this contingency Set lostPhaseControllers = contingency.getBranchIdsToOpen().keySet().stream() - .filter(element -> !connectivityAnalysisResult.getElementsToReconnect().contains(element)) + .filter(element -> !elementsToReconnect.contains(element)) .map(contingencyElementByBranch::get) .map(ComputedContingencyElement::getLfBranch) .filter(LfBranch::hasPhaseControllerCapability) @@ -161,7 +161,7 @@ private double[] calculatePostContingencyAndOperatorStrategyStates(DcLoadFlowCon // if a phase tap changer is lost or if the connectivity have changed, we must recompute load flows // same if there is an action, as they are only on pst for now - if (!connectivityAnalysisResult.getDisabledBuses().isEmpty() || !lostPhaseControllers.isEmpty() || !operatorStrategyLfActions.isEmpty()) { + if (!disabledBuses.isEmpty() || !lostPhaseControllers.isEmpty() || !operatorStrategyLfActions.isEmpty()) { newFlowStates = WoodburyEngine.runDcLoadFlowWithModifiedTargetVector(loadFlowContext, disabledNetwork, reportNode, operatorStrategyLfActions); } engine.toPostContingencyAndOperatorStrategyStates(newFlowStates); From e12ffd7816bc2ff83468710ce7647d913e54b3ad Mon Sep 17 00:00:00 2001 From: p-arvy Date: Tue, 18 Feb 2025 12:03:31 +0100 Subject: [PATCH 03/19] Add TU Signed-off-by: p-arvy --- .../sa/OpenSecurityAnalysisTest.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index ee634bb0dd..68ab56239f 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -4176,6 +4176,33 @@ void testDcSaHvdcLineContingency(boolean dcFastMode) { assertEquals(network.getLine("l56").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l56").getP1(), LoadFlowAssert.DELTA_POWER); } + @Test + void testFastDcSaHvdcLineWithoutPowerContingency() { + Network network = HvdcNetworkFactory.createNetworkWithGenerators(); + + SecurityAnalysisParameters securityAnalysisParameters = new SecurityAnalysisParameters(); + securityAnalysisParameters.getLoadFlowParameters().setDc(true); + OpenSecurityAnalysisParameters openSecurityAnalysisParameters = new OpenSecurityAnalysisParameters(); + openSecurityAnalysisParameters.setDcFastMode(true); + securityAnalysisParameters.addExtension(OpenSecurityAnalysisParameters.class, openSecurityAnalysisParameters); + + List monitors = createAllBranchesMonitors(network); + List contingencies = List.of(new Contingency("l25", List.of(new LineContingency("l25")))); + SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors, securityAnalysisParameters); + + // apply contingency by hand + network.getLine("l25").disconnect(); + // run load flow to compare results + loadFlowRunner.run(network, securityAnalysisParameters.getLoadFlowParameters()); + + // post-contingency tests + PostContingencyResult postContingencyResult = getPostContingencyResult(result, "l25"); + assertEquals(3, postContingencyResult.getNetworkResult().getBranchResults().size()); // only branches in main synchronous component + assertEquals(network.getLine("l12").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l12").getP1(), LoadFlowAssert.DELTA_POWER); + assertEquals(network.getLine("l13").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l13").getP1(), LoadFlowAssert.DELTA_POWER); + assertEquals(network.getLine("l23").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l23").getP1(), LoadFlowAssert.DELTA_POWER); + } + @ParameterizedTest @ValueSource(booleans = {false, true}) void testDcSaHvdcLineWithPowerAfterContingency(boolean dcFastMode) { From 246acae278024fc8503421c169528cbdb76d37b7 Mon Sep 17 00:00:00 2001 From: p-arvy Date: Tue, 25 Feb 2025 14:44:46 +0100 Subject: [PATCH 04/19] Update TU Signed-off-by: p-arvy --- .../com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index 68ab56239f..d95c7ba15f 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -4178,7 +4178,7 @@ void testDcSaHvdcLineContingency(boolean dcFastMode) { @Test void testFastDcSaHvdcLineWithoutPowerContingency() { - Network network = HvdcNetworkFactory.createNetworkWithGenerators(); + Network network = HvdcNetworkFactory.createNetworkWithGenerators2(); SecurityAnalysisParameters securityAnalysisParameters = new SecurityAnalysisParameters(); securityAnalysisParameters.getLoadFlowParameters().setDc(true); @@ -4197,6 +4197,7 @@ void testFastDcSaHvdcLineWithoutPowerContingency() { // post-contingency tests PostContingencyResult postContingencyResult = getPostContingencyResult(result, "l25"); + assertEquals(1, postContingencyResult.getConnectivityResult().getCreatedSynchronousComponentCount()); assertEquals(3, postContingencyResult.getNetworkResult().getBranchResults().size()); // only branches in main synchronous component assertEquals(network.getLine("l12").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l12").getP1(), LoadFlowAssert.DELTA_POWER); assertEquals(network.getLine("l13").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l13").getP1(), LoadFlowAssert.DELTA_POWER); From 707458d9d13614a217c030da61dbaa588b6fd1ab Mon Sep 17 00:00:00 2001 From: p-arvy Date: Mon, 3 Mar 2025 17:37:51 +0100 Subject: [PATCH 05/19] Small clean Signed-off-by: p-arvy --- .../openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java | 8 ++++---- .../powsybl/openloadflow/sensi/DcSensitivityAnalysis.java | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java b/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java index 3feed40c78..c485da74ef 100644 --- a/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java @@ -48,7 +48,7 @@ public static final class ConnectivityAnalysisResult { private final Set slackConnectedComponent; // buses of connected component where the slack is - private final Set slackConnectedComponentBuses; // buses of connected component where the slack is + private final Set slackConnectedComponent; // buses of connected component where the slack is private final DisabledElements disabledElements; @@ -67,7 +67,7 @@ public ConnectivityAnalysisResult(PropagatedContingency propagatedContingency, L this.network = Objects.requireNonNull(network); this.elementsToReconnect = elementsToReconnect; this.disabledBuses = disabledBuses; - this.slackConnectedComponentBuses = slackConnectedComponentBuses; + this.slackConnectedComponent = slackConnectedComponentBuses; this.partialDisabledBranches = partialDisabledBranches; this.createdSynchronousComponents = createdSynchronousComponents; this.hvdcsWithoutPower = hvdcsWithoutPower; @@ -85,8 +85,8 @@ public Set getDisabledBuses() { return disabledElements.disabledBuses; } - public Set getSlackConnectedComponentBuses() { - return slackConnectedComponentBuses; + public Set getSlackConnectedComponent() { + return slackConnectedComponent; } public Set getPartialDisabledBranches() { diff --git a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java index 45dc46b11e..2b34c4f81b 100644 --- a/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sensi/DcSensitivityAnalysis.java @@ -331,7 +331,7 @@ private void processContingenciesBreakingConnectivity(ConnectivityBreakAnalysis. // we need to recompute the participating elements because the connectivity changed if (rhsChanged) { participatingElementsForThisConnectivity = lfParameters.isDistributedSlack() - ? getParticipatingElements(connectivityAnalysisResult.getSlackConnectedComponentBuses(), lfParameters.getBalanceType(), lfParametersExt) // will also be used to recompute the loadflow + ? getParticipatingElements(connectivityAnalysisResult.getSlackConnectedComponent(), lfParameters.getBalanceType(), lfParametersExt) // will also be used to recompute the loadflow : Collections.emptyList(); } From 99a2e44400105757ba0a5237753043907d3ea74f Mon Sep 17 00:00:00 2001 From: p-arvy Date: Mon, 3 Mar 2025 17:51:59 +0100 Subject: [PATCH 06/19] Update TU Signed-off-by: p-arvy --- .../sa/OpenSecurityAnalysisTest.java | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index d95c7ba15f..3ebac80687 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -4177,7 +4177,7 @@ void testDcSaHvdcLineContingency(boolean dcFastMode) { } @Test - void testFastDcSaHvdcLineWithoutPowerContingency() { + void testFastDcSaHvdcLineWithPowerAfterContingency() { Network network = HvdcNetworkFactory.createNetworkWithGenerators2(); SecurityAnalysisParameters securityAnalysisParameters = new SecurityAnalysisParameters(); @@ -4204,6 +4204,37 @@ void testFastDcSaHvdcLineWithoutPowerContingency() { assertEquals(network.getLine("l23").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l23").getP1(), LoadFlowAssert.DELTA_POWER); } + @Test + void testFastDcSaHvdcLineWithoutPowerAfterContingency() { + Network network = HvdcNetworkFactory.createWithHvdcInAcEmulation(); + + SecurityAnalysisParameters securityAnalysisParameters = new SecurityAnalysisParameters(); + securityAnalysisParameters.getLoadFlowParameters().setDc(true); + OpenSecurityAnalysisParameters openSecurityAnalysisParameters = new OpenSecurityAnalysisParameters(); + openSecurityAnalysisParameters.setDcFastMode(true); + securityAnalysisParameters.addExtension(OpenSecurityAnalysisParameters.class, openSecurityAnalysisParameters); + + List monitors = createAllBranchesMonitors(network); + List contingencies = List.of(new Contingency("l25+l45+l46", + List.of(new LineContingency("l25"), new LineContingency("l45"), new LineContingency("l46")))); + SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors, securityAnalysisParameters); + + // apply contingency by hand + network.getLine("l25").disconnect(); + network.getLine("l45").disconnect(); + network.getLine("l46").disconnect(); + // run load flow to compare results + loadFlowRunner.run(network, securityAnalysisParameters.getLoadFlowParameters()); + + // post-contingency tests + PostContingencyResult postContingencyResult = getPostContingencyResult(result, "l25+l45+l46"); + assertEquals(2, postContingencyResult.getConnectivityResult().getCreatedSynchronousComponentCount()); + assertEquals(3, postContingencyResult.getNetworkResult().getBranchResults().size()); // only branches in main synchronous component + assertEquals(network.getLine("l12").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l12").getP1(), LoadFlowAssert.DELTA_POWER); + assertEquals(network.getLine("l13").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l13").getP1(), LoadFlowAssert.DELTA_POWER); + assertEquals(network.getLine("l23").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l23").getP1(), LoadFlowAssert.DELTA_POWER); + } + @ParameterizedTest @ValueSource(booleans = {false, true}) void testDcSaHvdcLineWithPowerAfterContingency(boolean dcFastMode) { From bf4fae53ced78e9920da4b87e0c825dc7ecc6070 Mon Sep 17 00:00:00 2001 From: Hadrien Date: Tue, 4 Mar 2025 16:40:28 +0100 Subject: [PATCH 07/19] Clean Signed-off-by: Hadrien --- .../openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java b/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java index c485da74ef..bb4e4d71f4 100644 --- a/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java @@ -108,11 +108,9 @@ public record ConnectivityBreakAnalysisResults(List nonBr List connectivityAnalysisResults, DenseMatrix contingenciesStates, Map contingencyElementByBranch) { - } private ConnectivityBreakAnalysis() { - } private static void detectPotentialConnectivityBreak(LfNetwork lfNetwork, DenseMatrix states, List contingencies, From a4ea5f295f21d95a6f8b93683875666db0857b8a Mon Sep 17 00:00:00 2001 From: Hadrien Date: Wed, 5 Mar 2025 09:31:16 +0100 Subject: [PATCH 08/19] Refacto Signed-off-by: Hadrien --- .../dc/fastdc/ConnectivityBreakAnalysis.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java b/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java index bb4e4d71f4..2eeef1a65f 100644 --- a/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java @@ -48,29 +48,25 @@ public static final class ConnectivityAnalysisResult { private final Set slackConnectedComponent; // buses of connected component where the slack is - private final Set slackConnectedComponent; // buses of connected component where the slack is - private final DisabledElements disabledElements; private final int createdSynchronousComponents; - private final Set hvdcsWithoutPower; + private final DisabledElements disabledElements; public ConnectivityAnalysisResult(PropagatedContingency propagatedContingency, LfNetwork network) { - this(propagatedContingency, network, Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), Collections.emptySet(), 0, Collections.emptySet()); + this(propagatedContingency, network, Collections.emptySet(), new DisabledElements(Collections.emptySet(), Collections.emptySet(), Collections.emptySet()), Collections.emptySet(), 0); } public ConnectivityAnalysisResult(PropagatedContingency propagatedContingency, LfNetwork network, Set elementsToReconnect, - Set disabledBuses, Set slackConnectedComponentBuses, Set partialDisabledBranches, - int createdSynchronousComponents, Set hvdcsWithoutPower) { + DisabledElements disabledElements, Set slackConnectedComponentBuses, + int createdSynchronousComponents) { this.propagatedContingency = Objects.requireNonNull(propagatedContingency); this.network = Objects.requireNonNull(network); this.elementsToReconnect = elementsToReconnect; - this.disabledBuses = disabledBuses; + this.disabledElements = disabledElements; this.slackConnectedComponent = slackConnectedComponentBuses; - this.partialDisabledBranches = partialDisabledBranches; this.createdSynchronousComponents = createdSynchronousComponents; - this.hvdcsWithoutPower = hvdcsWithoutPower; } public PropagatedContingency getPropagatedContingency() { From a17e0f7a020a42f0e5496ac3a5696ac1c967477a Mon Sep 17 00:00:00 2001 From: p-arvy Date: Fri, 7 Mar 2025 18:29:05 +0100 Subject: [PATCH 09/19] Add NO_DISABLED_ELEMENTS Signed-off-by: p-arvy --- .../openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java b/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java index 2eeef1a65f..631fd82e0c 100644 --- a/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java @@ -54,8 +54,8 @@ public static final class ConnectivityAnalysisResult { private final DisabledElements disabledElements; - public ConnectivityAnalysisResult(PropagatedContingency propagatedContingency, LfNetwork network) { - this(propagatedContingency, network, Collections.emptySet(), new DisabledElements(Collections.emptySet(), Collections.emptySet(), Collections.emptySet()), Collections.emptySet(), 0); + public ConnectivityAnalysisResult(PropagatedContingency nonBreakingConnectivityContingency, LfNetwork network) { + this(nonBreakingConnectivityContingency, network, Collections.emptySet(), DisabledElements.NO_DISABLED_ELEMENTS, Collections.emptySet(), 0); } public ConnectivityAnalysisResult(PropagatedContingency propagatedContingency, LfNetwork network, Set elementsToReconnect, From 174c0e11913a34104236a9469d7d62855fb3a872 Mon Sep 17 00:00:00 2001 From: Hadrien Date: Mon, 10 Mar 2025 16:59:20 +0100 Subject: [PATCH 10/19] Proposal to reduce arguments in addPostContingencyAndOperatorStrategyResults Signed-off-by: Hadrien --- .../powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java index 94da05d287..50f3846633 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java @@ -356,6 +356,7 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List> operatorStrategiesByContingencyId = indexOperatorStrategiesByContingencyId(propagatedContingencies, operatorStrategies, actionsById, neededActions, true); Map lfActionById = createLfActions(lfNetwork, neededActions, network, dcParameters.getNetworkParameters()); // only convert needed actions + ActionsAndStrategiesById actionsAndStrategiesById = new ActionsAndStrategiesById(operatorStrategiesByContingencyId, lfActionById); OpenSecurityAnalysisParameters openSecurityAnalysisParameters = OpenSecurityAnalysisParameters.getOrDefault(securityAnalysisParameters); boolean createResultExtension = openSecurityAnalysisParameters.isCreateResultExtension(); @@ -423,6 +424,9 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List { ConnectivityBreakAnalysis.ConnectivityAnalysisResult connectivityAnalysisResult = new ConnectivityBreakAnalysis.ConnectivityAnalysisResult(nonBreakingConnectivityContingency, lfNetwork); From 3ef630f278a178dc41adb78c651a47e4dc976f9f Mon Sep 17 00:00:00 2001 From: p-arvy Date: Tue, 18 Mar 2025 12:36:52 +0100 Subject: [PATCH 11/19] Refactor records in WoodburyDcSecurityAnalysis Signed-off-by: p-arvy --- .../com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java index 50f3846633..f4d047d940 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java @@ -356,7 +356,6 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List> operatorStrategiesByContingencyId = indexOperatorStrategiesByContingencyId(propagatedContingencies, operatorStrategies, actionsById, neededActions, true); Map lfActionById = createLfActions(lfNetwork, neededActions, network, dcParameters.getNetworkParameters()); // only convert needed actions - ActionsAndStrategiesById actionsAndStrategiesById = new ActionsAndStrategiesById(operatorStrategiesByContingencyId, lfActionById); OpenSecurityAnalysisParameters openSecurityAnalysisParameters = OpenSecurityAnalysisParameters.getOrDefault(securityAnalysisParameters); boolean createResultExtension = openSecurityAnalysisParameters.isCreateResultExtension(); @@ -425,7 +424,6 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List { From b0e6f74c532f7b296adfc89f0df9f1ee9b5d3506 Mon Sep 17 00:00:00 2001 From: p-arvy Date: Tue, 18 Mar 2025 18:08:25 +0100 Subject: [PATCH 12/19] wip Signed-off-by: p-arvy --- .../openloadflow/network/LfContingency.java | 62 +++++++++++++------ .../sa/WoodburyDcSecurityAnalysis.java | 6 +- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfContingency.java b/src/main/java/com/powsybl/openloadflow/network/LfContingency.java index 74a9fcc9fa..4c7ff5b2ca 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfContingency.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfContingency.java @@ -147,15 +147,30 @@ public void apply(LoadFlowParameters.BalanceType balanceType) { shunt.setG(shunt.getG() - e.getValue().getG()); shunt.setB(shunt.getB() - e.getValue().getB()); } + processPowerShifts(balanceType, true); + } + + public void processPowerShifts(LoadFlowParameters.BalanceType balanceType, boolean updateAc) { + processLostLoads(balanceType, updateAc); + processLostGenerators(updateAc); + processHvdcsWithoutPower(); + } + + private void processLostLoads(LoadFlowParameters.BalanceType balanceType, boolean updateAc) { for (var e : lostLoads.entrySet()) { LfLoad load = e.getKey(); LfLostLoad lostLoad = e.getValue(); PowerShift shift = lostLoad.getPowerShift(); load.setTargetP(load.getTargetP() - getUpdatedLoadP0(load, balanceType, shift.getActive(), shift.getVariableActive(), lostLoad.getNotParticipatingLoadP0())); - load.setTargetQ(load.getTargetQ() - shift.getReactive()); + if (updateAc) { + load.setTargetQ(load.getTargetQ() - shift.getReactive()); + } load.setAbsVariableTargetP(load.getAbsVariableTargetP() - Math.abs(shift.getVariableActive())); lostLoad.getOriginalIds().forEach(loadId -> load.setOriginalLoadDisabled(loadId, true)); } + } + + private void processLostGenerators(boolean updateAc) { Set generatorBuses = new HashSet<>(); for (LfGenerator generator : lostGenerators) { generator.setTargetP(0); @@ -164,29 +179,36 @@ public void apply(LoadFlowParameters.BalanceType balanceType) { generatorBuses.add(bus); generator.setParticipating(false); generator.setDisabled(true); - if (generator.getGeneratorControlType() != LfGenerator.GeneratorControlType.OFF) { - generator.setGeneratorControlType(LfGenerator.GeneratorControlType.OFF); - bus.getGeneratorVoltageControl().ifPresent(GeneratorVoltageControl::updateReactiveKeys); - bus.getGeneratorReactivePowerControl().ifPresent(GeneratorReactivePowerControl::updateReactiveKeys); - } else { - bus.setGenerationTargetQ(bus.getGenerationTargetQ() - generator.getTargetQ()); - } - if (generator instanceof LfStaticVarCompensator svc) { - svc.getStandByAutomatonShunt().ifPresent(svcShunt -> { - // it means that the generator in contingency is a static var compensator with an active stand by automaton shunt - shuntsShift.put(svcShunt, new AdmittanceShift(0, svcShunt.getB())); - svcShunt.setB(0); - }); + if (updateAc) { + if (generator.getGeneratorControlType() != LfGenerator.GeneratorControlType.OFF) { + generator.setGeneratorControlType(LfGenerator.GeneratorControlType.OFF); + bus.getGeneratorVoltageControl().ifPresent(GeneratorVoltageControl::updateReactiveKeys); + bus.getGeneratorReactivePowerControl().ifPresent(GeneratorReactivePowerControl::updateReactiveKeys); + } else { + bus.setGenerationTargetQ(bus.getGenerationTargetQ() - generator.getTargetQ()); + } + if (generator instanceof LfStaticVarCompensator svc) { + svc.getStandByAutomatonShunt().ifPresent(svcShunt -> { + // it means that the generator in contingency is a static var compensator with an active stand by automaton shunt + shuntsShift.put(svcShunt, new AdmittanceShift(0, svcShunt.getB())); + svcShunt.setB(0); + }); + } } } - for (LfBus bus : generatorBuses) { - if (bus.getGenerators().stream().noneMatch(gen -> gen.getGeneratorControlType() == LfGenerator.GeneratorControlType.VOLTAGE)) { - bus.setGeneratorVoltageControlEnabled(false); - } - if (bus.getGenerators().stream().noneMatch(gen -> gen.getGeneratorControlType() == LfGenerator.GeneratorControlType.REMOTE_REACTIVE_POWER)) { - bus.setGeneratorReactivePowerControlEnabled(false); + if (updateAc) { + for (LfBus bus : generatorBuses) { + if (bus.getGenerators().stream().noneMatch(gen -> gen.getGeneratorControlType() == LfGenerator.GeneratorControlType.VOLTAGE)) { + bus.setGeneratorVoltageControlEnabled(false); + } + if (bus.getGenerators().stream().noneMatch(gen -> gen.getGeneratorControlType() == LfGenerator.GeneratorControlType.REMOTE_REACTIVE_POWER)) { + bus.setGeneratorReactivePowerControlEnabled(false); + } } } + } + + private void processHvdcsWithoutPower() { for (LfHvdc hvdc : hvdcsWithoutPower) { hvdc.getConverterStation1().setTargetP(0.0); hvdc.getConverterStation2().setTargetP(0.0); diff --git a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java index f4d047d940..5c3bab9a19 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java @@ -169,12 +169,12 @@ private double[] calculatePostContingencyAndOperatorStrategyStates(DcLoadFlowCon // if we have a contingency including the loss of a DC line or a generator or a load // save base state for later restoration after each contingency DcLoadFlowParameters lfParameters = loadFlowContext.getParameters(); - NetworkState networkState = NetworkState.save(lfNetwork); + List busStates = ElementState.save(lfNetwork.getBuses(), BusDcState::save); connectivityAnalysisResult.toLfContingency() - .ifPresent(lfContingency -> lfContingency.apply(lfParameters.getBalanceType())); + .ifPresent(lfContingency -> lfContingency.processPowerShifts(lfParameters.getBalanceType(), false)); newFlowStates = WoodburyEngine.runDcLoadFlowWithModifiedTargetVector(loadFlowContext, disabledNetwork, reportNode, operatorStrategyLfActions); engine.toPostContingencyAndOperatorStrategyStates(newFlowStates); - networkState.restore(); + ElementState.restore(busStates); } return newFlowStates; From d26fb3e199a7d55717e59c2ef9379162dcd88f7e Mon Sep 17 00:00:00 2001 From: p-arvy Date: Fri, 28 Mar 2025 16:43:25 +0100 Subject: [PATCH 13/19] Update TUs to include slow mode Signed-off-by: p-arvy --- .../openloadflow/sa/OpenSecurityAnalysisTest.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index 3ebac80687..0041cb1efa 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -4176,14 +4176,15 @@ void testDcSaHvdcLineContingency(boolean dcFastMode) { assertEquals(network.getLine("l56").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l56").getP1(), LoadFlowAssert.DELTA_POWER); } - @Test - void testFastDcSaHvdcLineWithPowerAfterContingency() { + @ParameterizedTest + @ValueSource(booleans = {false, true}) + void testFastDcSaHvdcLineWithPowerAfterContingency(boolean dcFastMode) { Network network = HvdcNetworkFactory.createNetworkWithGenerators2(); SecurityAnalysisParameters securityAnalysisParameters = new SecurityAnalysisParameters(); securityAnalysisParameters.getLoadFlowParameters().setDc(true); OpenSecurityAnalysisParameters openSecurityAnalysisParameters = new OpenSecurityAnalysisParameters(); - openSecurityAnalysisParameters.setDcFastMode(true); + openSecurityAnalysisParameters.setDcFastMode(dcFastMode); securityAnalysisParameters.addExtension(OpenSecurityAnalysisParameters.class, openSecurityAnalysisParameters); List monitors = createAllBranchesMonitors(network); @@ -4204,14 +4205,15 @@ void testFastDcSaHvdcLineWithPowerAfterContingency() { assertEquals(network.getLine("l23").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l23").getP1(), LoadFlowAssert.DELTA_POWER); } - @Test - void testFastDcSaHvdcLineWithoutPowerAfterContingency() { + @ParameterizedTest + @ValueSource(booleans = {false, true}) + void testFastDcSaHvdcLineWithoutPowerAfterContingency(boolean dcFastMode) { Network network = HvdcNetworkFactory.createWithHvdcInAcEmulation(); SecurityAnalysisParameters securityAnalysisParameters = new SecurityAnalysisParameters(); securityAnalysisParameters.getLoadFlowParameters().setDc(true); OpenSecurityAnalysisParameters openSecurityAnalysisParameters = new OpenSecurityAnalysisParameters(); - openSecurityAnalysisParameters.setDcFastMode(true); + openSecurityAnalysisParameters.setDcFastMode(dcFastMode); securityAnalysisParameters.addExtension(OpenSecurityAnalysisParameters.class, openSecurityAnalysisParameters); List monitors = createAllBranchesMonitors(network); From d909467ccee73837e0c2c3deed9fa01cecbecee3 Mon Sep 17 00:00:00 2001 From: p-arvy Date: Fri, 4 Apr 2025 10:28:25 +0200 Subject: [PATCH 14/19] clean Signed-off-by: p-arvy --- .../com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index 0041cb1efa..1441095bfc 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -4178,7 +4178,7 @@ void testDcSaHvdcLineContingency(boolean dcFastMode) { @ParameterizedTest @ValueSource(booleans = {false, true}) - void testFastDcSaHvdcLineWithPowerAfterContingency(boolean dcFastMode) { + void testDcSaHvdcLineWithPowerAfterContingency(boolean dcFastMode) { Network network = HvdcNetworkFactory.createNetworkWithGenerators2(); SecurityAnalysisParameters securityAnalysisParameters = new SecurityAnalysisParameters(); @@ -4207,7 +4207,7 @@ void testFastDcSaHvdcLineWithPowerAfterContingency(boolean dcFastMode) { @ParameterizedTest @ValueSource(booleans = {false, true}) - void testFastDcSaHvdcLineWithoutPowerAfterContingency(boolean dcFastMode) { + void testDcSaHvdcLineWithoutPowerAfterContingency(boolean dcFastMode) { Network network = HvdcNetworkFactory.createWithHvdcInAcEmulation(); SecurityAnalysisParameters securityAnalysisParameters = new SecurityAnalysisParameters(); From 65d5848ada8aa695126e8092e1905eae3ae507c3 Mon Sep 17 00:00:00 2001 From: p-arvy Date: Fri, 4 Apr 2025 11:58:20 +0200 Subject: [PATCH 15/19] Add comments Signed-off-by: p-arvy --- .../openloadflow/network/LfContingency.java | 23 +++++++++++-------- .../sa/WoodburyDcSecurityAnalysis.java | 6 +++-- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfContingency.java b/src/main/java/com/powsybl/openloadflow/network/LfContingency.java index 4c7ff5b2ca..6eaa369a2c 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfContingency.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfContingency.java @@ -147,22 +147,27 @@ public void apply(LoadFlowParameters.BalanceType balanceType) { shunt.setG(shunt.getG() - e.getValue().getG()); shunt.setB(shunt.getB() - e.getValue().getB()); } - processPowerShifts(balanceType, true); + processLostPowerChanges(balanceType, true); } - public void processPowerShifts(LoadFlowParameters.BalanceType balanceType, boolean updateAc) { - processLostLoads(balanceType, updateAc); - processLostGenerators(updateAc); + /** + * Process the power shifts due to the loss of loads, generators, and HVDCs. + * @param balanceType the property defining how to manage active distribution. + * @param updateAcParameters a boolean to indicate if voltage/reactive dependent parameters should be updated or not. + */ + public void processLostPowerChanges(LoadFlowParameters.BalanceType balanceType, boolean updateAcParameters) { + processLostLoads(balanceType, updateAcParameters); + processLostGenerators(updateAcParameters); processHvdcsWithoutPower(); } - private void processLostLoads(LoadFlowParameters.BalanceType balanceType, boolean updateAc) { + private void processLostLoads(LoadFlowParameters.BalanceType balanceType, boolean updateAcParameters) { for (var e : lostLoads.entrySet()) { LfLoad load = e.getKey(); LfLostLoad lostLoad = e.getValue(); PowerShift shift = lostLoad.getPowerShift(); load.setTargetP(load.getTargetP() - getUpdatedLoadP0(load, balanceType, shift.getActive(), shift.getVariableActive(), lostLoad.getNotParticipatingLoadP0())); - if (updateAc) { + if (updateAcParameters) { load.setTargetQ(load.getTargetQ() - shift.getReactive()); } load.setAbsVariableTargetP(load.getAbsVariableTargetP() - Math.abs(shift.getVariableActive())); @@ -170,7 +175,7 @@ private void processLostLoads(LoadFlowParameters.BalanceType balanceType, boolea } } - private void processLostGenerators(boolean updateAc) { + private void processLostGenerators(boolean updateAcParameters) { Set generatorBuses = new HashSet<>(); for (LfGenerator generator : lostGenerators) { generator.setTargetP(0); @@ -179,7 +184,7 @@ private void processLostGenerators(boolean updateAc) { generatorBuses.add(bus); generator.setParticipating(false); generator.setDisabled(true); - if (updateAc) { + if (updateAcParameters) { if (generator.getGeneratorControlType() != LfGenerator.GeneratorControlType.OFF) { generator.setGeneratorControlType(LfGenerator.GeneratorControlType.OFF); bus.getGeneratorVoltageControl().ifPresent(GeneratorVoltageControl::updateReactiveKeys); @@ -196,7 +201,7 @@ private void processLostGenerators(boolean updateAc) { } } } - if (updateAc) { + if (updateAcParameters) { for (LfBus bus : generatorBuses) { if (bus.getGenerators().stream().noneMatch(gen -> gen.getGeneratorControlType() == LfGenerator.GeneratorControlType.VOLTAGE)) { bus.setGeneratorVoltageControlEnabled(false); diff --git a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java index 5c3bab9a19..25f3539e52 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java @@ -167,11 +167,13 @@ private double[] calculatePostContingencyAndOperatorStrategyStates(DcLoadFlowCon engine.toPostContingencyAndOperatorStrategyStates(newFlowStates); } else { // if we have a contingency including the loss of a DC line or a generator or a load - // save base state for later restoration after each contingency + // save dc buses' base state for later restoration after processing lost power changes DcLoadFlowParameters lfParameters = loadFlowContext.getParameters(); List busStates = ElementState.save(lfNetwork.getBuses(), BusDcState::save); connectivityAnalysisResult.toLfContingency() - .ifPresent(lfContingency -> lfContingency.processPowerShifts(lfParameters.getBalanceType(), false)); + // only process the power shifts due to the loss of loads, generators, and HVDCs + // the loss of buses and phase shifts are taken into account in the override of the flow states + .ifPresent(lfContingency -> lfContingency.processLostPowerChanges(lfParameters.getBalanceType(), false)); newFlowStates = WoodburyEngine.runDcLoadFlowWithModifiedTargetVector(loadFlowContext, disabledNetwork, reportNode, operatorStrategyLfActions); engine.toPostContingencyAndOperatorStrategyStates(newFlowStates); ElementState.restore(busStates); From 33f85f8a0923e99ec1e86e771cdd5f5c39c97d49 Mon Sep 17 00:00:00 2001 From: p-arvy Date: Mon, 7 Apr 2025 14:23:41 +0200 Subject: [PATCH 16/19] Fix rebase Signed-off-by: p-arvy --- .../dc/fastdc/ConnectivityBreakAnalysis.java | 4 +- .../sa/WoodburyDcSecurityAnalysis.java | 2 - .../sa/OpenSecurityAnalysisTest.java | 61 ------------------- 3 files changed, 2 insertions(+), 65 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java b/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java index 631fd82e0c..df97155162 100644 --- a/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/dc/fastdc/ConnectivityBreakAnalysis.java @@ -48,8 +48,6 @@ public static final class ConnectivityAnalysisResult { private final Set slackConnectedComponent; // buses of connected component where the slack is - private final DisabledElements disabledElements; - private final int createdSynchronousComponents; private final DisabledElements disabledElements; @@ -104,9 +102,11 @@ public record ConnectivityBreakAnalysisResults(List nonBr List connectivityAnalysisResults, DenseMatrix contingenciesStates, Map contingencyElementByBranch) { + } private ConnectivityBreakAnalysis() { + } private static void detectPotentialConnectivityBreak(LfNetwork lfNetwork, DenseMatrix states, List contingencies, diff --git a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java index 25f3539e52..fa65de3f3b 100644 --- a/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java +++ b/src/main/java/com/powsybl/openloadflow/sa/WoodburyDcSecurityAnalysis.java @@ -425,8 +425,6 @@ protected SecurityAnalysisResult runSimulations(LfNetwork lfNetwork, List { ConnectivityBreakAnalysis.ConnectivityAnalysisResult connectivityAnalysisResult = new ConnectivityBreakAnalysis.ConnectivityAnalysisResult(nonBreakingConnectivityContingency, lfNetwork); diff --git a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java index 1441095bfc..ee634bb0dd 100644 --- a/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java +++ b/src/test/java/com/powsybl/openloadflow/sa/OpenSecurityAnalysisTest.java @@ -4237,67 +4237,6 @@ void testDcSaHvdcLineWithoutPowerAfterContingency(boolean dcFastMode) { assertEquals(network.getLine("l23").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l23").getP1(), LoadFlowAssert.DELTA_POWER); } - @ParameterizedTest - @ValueSource(booleans = {false, true}) - void testDcSaHvdcLineWithPowerAfterContingency(boolean dcFastMode) { - Network network = HvdcNetworkFactory.createNetworkWithGenerators2(); - - SecurityAnalysisParameters securityAnalysisParameters = new SecurityAnalysisParameters(); - securityAnalysisParameters.getLoadFlowParameters().setDc(true); - OpenSecurityAnalysisParameters openSecurityAnalysisParameters = new OpenSecurityAnalysisParameters(); - openSecurityAnalysisParameters.setDcFastMode(dcFastMode); - securityAnalysisParameters.addExtension(OpenSecurityAnalysisParameters.class, openSecurityAnalysisParameters); - - List monitors = createAllBranchesMonitors(network); - List contingencies = List.of(new Contingency("l25", List.of(new LineContingency("l25")))); - SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors, securityAnalysisParameters); - - // apply contingency by hand - network.getLine("l25").disconnect(); - // run load flow to compare results - loadFlowRunner.run(network, securityAnalysisParameters.getLoadFlowParameters()); - - // post-contingency tests - PostContingencyResult postContingencyResult = getPostContingencyResult(result, "l25"); - assertEquals(1, postContingencyResult.getConnectivityResult().getCreatedSynchronousComponentCount()); - assertEquals(3, postContingencyResult.getNetworkResult().getBranchResults().size()); // only branches in main synchronous component - assertEquals(network.getLine("l12").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l12").getP1(), LoadFlowAssert.DELTA_POWER); - assertEquals(network.getLine("l13").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l13").getP1(), LoadFlowAssert.DELTA_POWER); - assertEquals(network.getLine("l23").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l23").getP1(), LoadFlowAssert.DELTA_POWER); - } - - @ParameterizedTest - @ValueSource(booleans = {false, true}) - void testDcSaHvdcLineWithoutPowerAfterContingency(boolean dcFastMode) { - Network network = HvdcNetworkFactory.createWithHvdcInAcEmulation(); - - SecurityAnalysisParameters securityAnalysisParameters = new SecurityAnalysisParameters(); - securityAnalysisParameters.getLoadFlowParameters().setDc(true); - OpenSecurityAnalysisParameters openSecurityAnalysisParameters = new OpenSecurityAnalysisParameters(); - openSecurityAnalysisParameters.setDcFastMode(dcFastMode); - securityAnalysisParameters.addExtension(OpenSecurityAnalysisParameters.class, openSecurityAnalysisParameters); - - List monitors = createAllBranchesMonitors(network); - List contingencies = List.of(new Contingency("l25+l45+l46", - List.of(new LineContingency("l25"), new LineContingency("l45"), new LineContingency("l46")))); - SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors, securityAnalysisParameters); - - // apply contingency by hand - network.getLine("l25").disconnect(); - network.getLine("l45").disconnect(); - network.getLine("l46").disconnect(); - // run load flow to compare results - loadFlowRunner.run(network, securityAnalysisParameters.getLoadFlowParameters()); - - // post-contingency tests - PostContingencyResult postContingencyResult = getPostContingencyResult(result, "l25+l45+l46"); - assertEquals(2, postContingencyResult.getConnectivityResult().getCreatedSynchronousComponentCount()); - assertEquals(3, postContingencyResult.getNetworkResult().getBranchResults().size()); // only branches in main synchronous component - assertEquals(network.getLine("l12").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l12").getP1(), LoadFlowAssert.DELTA_POWER); - assertEquals(network.getLine("l13").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l13").getP1(), LoadFlowAssert.DELTA_POWER); - assertEquals(network.getLine("l23").getTerminal1().getP(), postContingencyResult.getNetworkResult().getBranchResult("l23").getP1(), LoadFlowAssert.DELTA_POWER); - } - @ParameterizedTest @ValueSource(booleans = {false, true}) void testDcSaHvdcLineInAcEmulationContingency(boolean dcFastMode) { From 1eaf8b17b711d092245d9cf006da3a1443d01a40 Mon Sep 17 00:00:00 2001 From: Hadrien Date: Tue, 8 Apr 2025 07:40:34 +0200 Subject: [PATCH 17/19] Refacto of processLostGenerators Signed-off-by: Hadrien --- .../openloadflow/network/LfContingency.java | 55 +++++++++++-------- 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfContingency.java b/src/main/java/com/powsybl/openloadflow/network/LfContingency.java index 6eaa369a2c..60454735a0 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfContingency.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfContingency.java @@ -178,37 +178,46 @@ private void processLostLoads(LoadFlowParameters.BalanceType balanceType, boolea private void processLostGenerators(boolean updateAcParameters) { Set generatorBuses = new HashSet<>(); for (LfGenerator generator : lostGenerators) { + // DC and AC parameters generator.setTargetP(0); generator.setInitialTargetP(0); LfBus bus = generator.getBus(); generatorBuses.add(bus); generator.setParticipating(false); generator.setDisabled(true); - if (updateAcParameters) { - if (generator.getGeneratorControlType() != LfGenerator.GeneratorControlType.OFF) { - generator.setGeneratorControlType(LfGenerator.GeneratorControlType.OFF); - bus.getGeneratorVoltageControl().ifPresent(GeneratorVoltageControl::updateReactiveKeys); - bus.getGeneratorReactivePowerControl().ifPresent(GeneratorReactivePowerControl::updateReactiveKeys); - } else { - bus.setGenerationTargetQ(bus.getGenerationTargetQ() - generator.getTargetQ()); - } - if (generator instanceof LfStaticVarCompensator svc) { - svc.getStandByAutomatonShunt().ifPresent(svcShunt -> { - // it means that the generator in contingency is a static var compensator with an active stand by automaton shunt - shuntsShift.put(svcShunt, new AdmittanceShift(0, svcShunt.getB())); - svcShunt.setB(0); - }); - } + + if (!updateAcParameters) { + continue; + } + + // Only AC parameters + if (generator.getGeneratorControlType() != LfGenerator.GeneratorControlType.OFF) { + generator.setGeneratorControlType(LfGenerator.GeneratorControlType.OFF); + bus.getGeneratorVoltageControl().ifPresent(GeneratorVoltageControl::updateReactiveKeys); + bus.getGeneratorReactivePowerControl().ifPresent(GeneratorReactivePowerControl::updateReactiveKeys); + } else { + bus.setGenerationTargetQ(bus.getGenerationTargetQ() - generator.getTargetQ()); + } + if (generator instanceof LfStaticVarCompensator svc) { + svc.getStandByAutomatonShunt().ifPresent(svcShunt -> { + // it means that the generator in contingency is a static var compensator with an active stand by automaton shunt + shuntsShift.put(svcShunt, new AdmittanceShift(0, svcShunt.getB())); + svcShunt.setB(0); + }); } } - if (updateAcParameters) { - for (LfBus bus : generatorBuses) { - if (bus.getGenerators().stream().noneMatch(gen -> gen.getGeneratorControlType() == LfGenerator.GeneratorControlType.VOLTAGE)) { - bus.setGeneratorVoltageControlEnabled(false); - } - if (bus.getGenerators().stream().noneMatch(gen -> gen.getGeneratorControlType() == LfGenerator.GeneratorControlType.REMOTE_REACTIVE_POWER)) { - bus.setGeneratorReactivePowerControlEnabled(false); - } + + if (!updateAcParameters) { + return; + } + + // Only AC parameters + for (LfBus bus : generatorBuses) { + if (bus.getGenerators().stream().noneMatch(gen -> gen.getGeneratorControlType() == LfGenerator.GeneratorControlType.VOLTAGE)) { + bus.setGeneratorVoltageControlEnabled(false); + } + if (bus.getGenerators().stream().noneMatch(gen -> gen.getGeneratorControlType() == LfGenerator.GeneratorControlType.REMOTE_REACTIVE_POWER)) { + bus.setGeneratorReactivePowerControlEnabled(false); } } } From 7a24aede581a88546bbe1f0a8607943c9bfca660 Mon Sep 17 00:00:00 2001 From: p-arvy Date: Thu, 10 Apr 2025 14:48:05 +0200 Subject: [PATCH 18/19] Change parameters for quantities Signed-off-by: p-arvy --- .../openloadflow/network/LfContingency.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfContingency.java b/src/main/java/com/powsybl/openloadflow/network/LfContingency.java index 60454735a0..4bfff4e740 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfContingency.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfContingency.java @@ -153,21 +153,21 @@ public void apply(LoadFlowParameters.BalanceType balanceType) { /** * Process the power shifts due to the loss of loads, generators, and HVDCs. * @param balanceType the property defining how to manage active distribution. - * @param updateAcParameters a boolean to indicate if voltage/reactive dependent parameters should be updated or not. + * @param updateAcQuantities a boolean to indicate if voltage/reactive dependent quantities should be updated or not. */ - public void processLostPowerChanges(LoadFlowParameters.BalanceType balanceType, boolean updateAcParameters) { - processLostLoads(balanceType, updateAcParameters); - processLostGenerators(updateAcParameters); + public void processLostPowerChanges(LoadFlowParameters.BalanceType balanceType, boolean updateAcQuantities) { + processLostLoads(balanceType, updateAcQuantities); + processLostGenerators(updateAcQuantities); processHvdcsWithoutPower(); } - private void processLostLoads(LoadFlowParameters.BalanceType balanceType, boolean updateAcParameters) { + private void processLostLoads(LoadFlowParameters.BalanceType balanceType, boolean updateAcQuantities) { for (var e : lostLoads.entrySet()) { LfLoad load = e.getKey(); LfLostLoad lostLoad = e.getValue(); PowerShift shift = lostLoad.getPowerShift(); load.setTargetP(load.getTargetP() - getUpdatedLoadP0(load, balanceType, shift.getActive(), shift.getVariableActive(), lostLoad.getNotParticipatingLoadP0())); - if (updateAcParameters) { + if (updateAcQuantities) { load.setTargetQ(load.getTargetQ() - shift.getReactive()); } load.setAbsVariableTargetP(load.getAbsVariableTargetP() - Math.abs(shift.getVariableActive())); @@ -175,7 +175,7 @@ private void processLostLoads(LoadFlowParameters.BalanceType balanceType, boolea } } - private void processLostGenerators(boolean updateAcParameters) { + private void processLostGenerators(boolean updateAcQuantities) { Set generatorBuses = new HashSet<>(); for (LfGenerator generator : lostGenerators) { // DC and AC parameters @@ -186,7 +186,7 @@ private void processLostGenerators(boolean updateAcParameters) { generator.setParticipating(false); generator.setDisabled(true); - if (!updateAcParameters) { + if (!updateAcQuantities) { continue; } @@ -207,7 +207,7 @@ private void processLostGenerators(boolean updateAcParameters) { } } - if (!updateAcParameters) { + if (!updateAcQuantities) { return; } From 1a3f640957adb471ceddd818b03643d1127aa09d Mon Sep 17 00:00:00 2001 From: p-arvy Date: Thu, 10 Apr 2025 14:49:29 +0200 Subject: [PATCH 19/19] Update comments Signed-off-by: p-arvy --- .../com/powsybl/openloadflow/network/LfContingency.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/powsybl/openloadflow/network/LfContingency.java b/src/main/java/com/powsybl/openloadflow/network/LfContingency.java index 4bfff4e740..cd253190f7 100644 --- a/src/main/java/com/powsybl/openloadflow/network/LfContingency.java +++ b/src/main/java/com/powsybl/openloadflow/network/LfContingency.java @@ -178,7 +178,7 @@ private void processLostLoads(LoadFlowParameters.BalanceType balanceType, boolea private void processLostGenerators(boolean updateAcQuantities) { Set generatorBuses = new HashSet<>(); for (LfGenerator generator : lostGenerators) { - // DC and AC parameters + // DC and AC quantities generator.setTargetP(0); generator.setInitialTargetP(0); LfBus bus = generator.getBus(); @@ -190,7 +190,7 @@ private void processLostGenerators(boolean updateAcQuantities) { continue; } - // Only AC parameters + // Only AC quantities if (generator.getGeneratorControlType() != LfGenerator.GeneratorControlType.OFF) { generator.setGeneratorControlType(LfGenerator.GeneratorControlType.OFF); bus.getGeneratorVoltageControl().ifPresent(GeneratorVoltageControl::updateReactiveKeys); @@ -211,7 +211,7 @@ private void processLostGenerators(boolean updateAcQuantities) { return; } - // Only AC parameters + // Only AC quantities for (LfBus bus : generatorBuses) { if (bus.getGenerators().stream().noneMatch(gen -> gen.getGeneratorControlType() == LfGenerator.GeneratorControlType.VOLTAGE)) { bus.setGeneratorVoltageControlEnabled(false);