Skip to content

Commit

Permalink
Switch contingency support (#501)
Browse files Browse the repository at this point in the history
Signed-off-by: Geoffroy Jamgotchian <[email protected]>
Co-authored-by: Anne Tilloy <[email protected]>
  • Loading branch information
geofjamg and annetill authored Apr 19, 2022
1 parent 9b673a0 commit 65997de
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ public Set<String> getBranchIdsToOpen() {
return branchIdsToOpen;
}

public Set<Switch> getSwitchesToOpen() {
return switchesToOpen;
}

public Set<String> getHvdcIdsToOpen() {
return hvdcIdsToOpen;
}
Expand Down Expand Up @@ -191,6 +195,13 @@ private static PropagatedContingency create(Network network, Contingency conting
}
shuntsToLose.add(shuntCompensator);
break;
case SWITCH:
Switch aSwitch = network.getSwitch(element.getId());
if (aSwitch == null) {
throw new PowsyblException("Switch '" + element.getId() + "' not found in the network");
}
switchesToOpen.add(aSwitch);
break;
default:
throw new UnsupportedOperationException("Unsupported contingency element type: " + element.getType());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -685,31 +685,43 @@ protected SensitivityFactorHolder<V, E> writeInvalidFactors(SensitivityFactorHol
return validFactorHolder;
}

private static void cleanBranchIdsToOpen(LfNetwork lfNetwork, PropagatedContingency contingency) {
// Elements have already been checked and found in PropagatedContingency, so there is no need to
// check them again
Set<String> branchesToRemove = new HashSet<>(); // branches connected to one side, or switches
for (String branchId : contingency.getBranchIdsToOpen()) {
LfBranch lfBranch = lfNetwork.getBranchById(branchId);
if (lfBranch == null) {
branchesToRemove.add(branchId); // disconnected branch
continue;
}
if (lfBranch.getBus2() == null || lfBranch.getBus1() == null) {
branchesToRemove.add(branchId); // branch connected only on one side
}
}
contingency.getBranchIdsToOpen().removeAll(branchesToRemove);
}

public void checkContingencies(LfNetwork lfNetwork, List<PropagatedContingency> contingencies) {
Set<String> contingenciesIds = new HashSet<>();
for (PropagatedContingency contingency : contingencies) {
if (!contingency.getSwitchesToOpen().isEmpty()) {
throw new PowsyblException("Switch opening not supported in sensitivity analysis");
}

// check ID are unique because, later contingency are indexed by their IDs
String contingencyId = contingency.getContingency().getId();
if (contingenciesIds.contains(contingencyId)) {
throw new PowsyblException("Contingency '" + contingencyId + "' already exists");
}
contingenciesIds.add(contingencyId);

// Elements have already been checked and found in PropagatedContingency, so there is no need to
// check them again
Set<String> branchesToRemove = new HashSet<>(); // branches connected to one side, or switches
for (String branchId : contingency.getBranchIdsToOpen()) {
LfBranch lfBranch = lfNetwork.getBranchById(branchId);
if (lfBranch == null) {
branchesToRemove.add(branchId); // disconnected branch
continue;
}
if (lfBranch.getBus2() == null || lfBranch.getBus1() == null) {
branchesToRemove.add(branchId); // branch connected only on one side
}
}
contingency.getBranchIdsToOpen().removeAll(branchesToRemove);
if (contingency.getBranchIdsToOpen().isEmpty() && contingency.getHvdcIdsToOpen().isEmpty() && contingency.getGeneratorIdsToLose().isEmpty() && contingency.getLoadIdsToShift().isEmpty()) {
cleanBranchIdsToOpen(lfNetwork, contingency);

if (contingency.getBranchIdsToOpen().isEmpty()
&& contingency.getHvdcIdsToOpen().isEmpty()
&& contingency.getGeneratorIdsToLose().isEmpty()
&& contingency.getLoadIdsToShift().isEmpty()) {
LOGGER.warn("Contingency {} has no impact", contingency.getContingency().getId());
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/
package com.powsybl.openloadflow.sa;

import com.powsybl.commons.PowsyblException;
import com.powsybl.computation.ComputationManager;
import com.powsybl.contingency.*;
import com.powsybl.ieeecdf.converter.IeeeCdfNetworkFactory;
Expand Down Expand Up @@ -1336,4 +1337,45 @@ void testDivergenceStatus() {
SecurityAnalysisResult result = runSecurityAnalysis(network);
assertFalse(result.getPreContingencyResult().getLimitViolationsResult().isComputationOk());
}

@Test
void testSwitchContingency() {
Network network = createNodeBreakerNetwork();

List<Contingency> contingencies = List.of(new Contingency("C", new SwitchContingency("C")));

List<StateMonitor> monitors = createAllBranchesMonitors(network);

SecurityAnalysisResult result = runSecurityAnalysis(network, contingencies, monitors);

assertTrue(result.getPreContingencyResult().getLimitViolationsResult().isComputationOk());
assertTrue(result.getPostContingencyResults().get(0).getLimitViolationsResult().isComputationOk());

// pre-contingency tests
PreContingencyResult preContingencyResult = result.getPreContingencyResult();
assertEquals(301.884, preContingencyResult.getPreContingencyBranchResult("L1").getP1(), LoadFlowAssert.DELTA_POWER);
assertEquals(-300, preContingencyResult.getPreContingencyBranchResult("L1").getP2(), LoadFlowAssert.DELTA_POWER);
assertEquals(301.884, preContingencyResult.getPreContingencyBranchResult("L2").getP1(), LoadFlowAssert.DELTA_POWER);
assertEquals(-300, preContingencyResult.getPreContingencyBranchResult("L2").getP2(), LoadFlowAssert.DELTA_POWER);

// post-contingency tests
PostContingencyResult postContingencyResult = getPostContingencyResult(result, "C");
assertEquals(3.912, postContingencyResult.getBranchResult("L1").getP1(), LoadFlowAssert.DELTA_POWER);
assertEquals(-3.895, postContingencyResult.getBranchResult("L1").getP2(), LoadFlowAssert.DELTA_POWER);
assertEquals(603.769, postContingencyResult.getBranchResult("L2").getP1(), LoadFlowAssert.DELTA_POWER);
assertEquals(-596.104, postContingencyResult.getBranchResult("L2").getP2(), LoadFlowAssert.DELTA_POWER);
}

@Test
void testSwitchContingencyNotFound() {
Network network = createNodeBreakerNetwork();

List<Contingency> contingencies = List.of(new Contingency("X", new SwitchContingency("X")));

List<StateMonitor> monitors = createAllBranchesMonitors(network);

var e = assertThrows(CompletionException.class, () -> runSecurityAnalysis(network, contingencies, monitors));
assertTrue(e.getCause() instanceof PowsyblException);
assertEquals("Switch 'X' not found in the network", e.getCause().getMessage());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.powsybl.contingency.BranchContingency;
import com.powsybl.contingency.Contingency;
import com.powsybl.contingency.ContingencyContext;
import com.powsybl.contingency.SwitchContingency;
import com.powsybl.iidm.network.Branch;
import com.powsybl.iidm.network.Injection;
import com.powsybl.iidm.network.Network;
Expand All @@ -24,9 +25,11 @@
import com.powsybl.openloadflow.OpenLoadFlowParameters;
import com.powsybl.openloadflow.OpenLoadFlowProvider;
import com.powsybl.openloadflow.network.HvdcNetworkFactory;
import com.powsybl.openloadflow.network.NodeBreakerNetworkFactory;
import com.powsybl.openloadflow.network.SlackBusSelectionMode;
import com.powsybl.openloadflow.util.LoadFlowAssert;
import com.powsybl.sensitivity.*;
import org.junit.jupiter.api.Test;

import java.util.Collections;
import java.util.List;
Expand Down Expand Up @@ -427,4 +430,21 @@ protected void testGlskPartiallyOutsideMainComponent(boolean dc) {

assertEquals(resultInjection.getValues().iterator().next().getValue(), result.getValues().iterator().next().getValue(), LoadFlowAssert.DELTA_POWER);
}

@Test
void testSwitchContingency() {
Network network = NodeBreakerNetworkFactory.create();

SensitivityAnalysisParameters sensiParameters = createParameters(false, "VL1_0");

List<SensitivityFactor> factors = List.of(createBranchFlowPerInjectionIncrease("L1", "LD"));

List<Contingency> contingencies = List.of(new Contingency("C", new SwitchContingency("C")));

List<SensitivityVariableSet> variableSets = Collections.emptyList();

var e = assertThrows(CompletionException.class, () -> sensiRunner.run(network, factors, contingencies, variableSets, sensiParameters));
assertTrue(e.getCause() instanceof PowsyblException);
assertEquals("Switch opening not supported in sensitivity analysis", e.getCause().getMessage());
}
}

0 comments on commit 65997de

Please sign in to comment.