OpenSecurityAnalysisGraphTest.java
/**
* 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/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.openloadflow.sa;
import com.powsybl.commons.report.ReportNode;
import com.powsybl.contingency.BranchContingency;
import com.powsybl.contingency.ContingenciesProvider;
import com.powsybl.contingency.Contingency;
import com.powsybl.iidm.network.Network;
import com.powsybl.openloadflow.graph.EvenShiloachGraphDecrementalConnectivityFactory;
import com.powsybl.openloadflow.graph.GraphConnectivityFactory;
import com.powsybl.openloadflow.graph.MinimumSpanningTreeGraphConnectivityFactory;
import com.powsybl.openloadflow.graph.NaiveGraphConnectivityFactory;
import com.powsybl.openloadflow.network.*;
import com.powsybl.openloadflow.network.impl.LfNetworkList;
import com.powsybl.openloadflow.network.impl.Networks;
import com.powsybl.openloadflow.network.impl.PropagatedContingency;
import com.powsybl.openloadflow.network.impl.PropagatedContingencyCreationParameters;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author Florian Dupuy {@literal <florian.dupuy at rte-france.com>}
*/
class OpenSecurityAnalysisGraphTest {
private static final Logger LOGGER = LoggerFactory.getLogger(OpenSecurityAnalysisGraphTest.class);
private Network network;
private ContingenciesProvider contingenciesProvider;
@BeforeEach
void setUp() {
network = NodeBreakerNetworkFactory.create();
// Testing all contingencies at once
contingenciesProvider = network -> network.getBranchStream()
.map(b -> new Contingency(b.getId(), new BranchContingency(b.getId())))
.collect(Collectors.toList());
}
private TestData computeReferenceLfContingencies() {
var testData = computeLfContingencies(new NaiveGraphConnectivityFactory<>(LfBus::getNum));
LOGGER.info("Reference established (naive connectivity calculation) on test network containing {} branches", network.getBranchCount());
return testData;
}
@Test
void testEvenShiloach() {
LOGGER.info("Test Even-Shiloach on test network containing {} branches", network.getBranchCount());
try (var testDataRef = computeReferenceLfContingencies();
var testData = computeLfContingencies(new EvenShiloachGraphDecrementalConnectivityFactory<>())) {
printResult(testData.getListLfContingencies());
checkResult(testData.getListLfContingencies(), testDataRef.getListLfContingencies());
}
}
@Test
void testMst() {
LOGGER.info("Test Minimum Spanning Tree on test network containing {} branches", network.getBranchCount());
try (var testDataRef = computeReferenceLfContingencies();
var testData = computeLfContingencies(new MinimumSpanningTreeGraphConnectivityFactory<>())) {
printResult(testData.getListLfContingencies());
checkResult(testData.getListLfContingencies(), testDataRef.getListLfContingencies());
}
}
@Test
void testNullVertices() {
network.getSwitch("B3").setOpen(true);
contingenciesProvider = n -> Collections.singletonList(new Contingency("L1", new BranchContingency("L1")));
try (var testDataRef = computeReferenceLfContingencies();
var testData1 = computeLfContingencies(new MinimumSpanningTreeGraphConnectivityFactory<>());
var testData2 = computeLfContingencies(new EvenShiloachGraphDecrementalConnectivityFactory<>())) {
checkResult(testData1.getListLfContingencies(), testDataRef.getListLfContingencies());
checkResult(testData2.getListLfContingencies(), testDataRef.getListLfContingencies());
}
contingenciesProvider = n -> Collections.singletonList(new Contingency("L2", new BranchContingency("L2")));
network.getSwitch("B3").setOpen(false);
network.getSwitch("B1").setOpen(true);
try (var testDataRef = computeReferenceLfContingencies();
var testData1 = computeLfContingencies(new MinimumSpanningTreeGraphConnectivityFactory<>());
var testData2 = computeLfContingencies(new EvenShiloachGraphDecrementalConnectivityFactory<>())) {
checkResult(testData1.getListLfContingencies(), testDataRef.getListLfContingencies());
checkResult(testData2.getListLfContingencies(), testDataRef.getListLfContingencies());
}
}
private static void checkResult(List<List<LfContingency>> result, List<List<LfContingency>> reference) {
assertEquals(reference.size(), result.size());
for (int iNetwork = 0; iNetwork < result.size(); iNetwork++) {
assertEquals(reference.get(iNetwork).size(), result.get(iNetwork).size());
for (int iContingency = 0; iContingency < result.get(iNetwork).size(); iContingency++) {
LfContingency contingencyReference = reference.get(iNetwork).get(iContingency);
LfContingency contingencyResult = result.get(iNetwork).get(iContingency);
assertEquals(contingencyReference.getId(), contingencyResult.getId());
Set<LfBranch> branchesReference = contingencyReference.getDisabledNetwork().getBranches();
Set<LfBranch> branchesResult = contingencyResult.getDisabledNetwork().getBranches();
assertEquals(branchesReference.size(), branchesResult.size());
branchesReference.forEach(b -> assertTrue(branchesResult.stream().anyMatch(b1 -> b1.getId().equals(b.getId()))));
Set<LfBus> busesReference = contingencyReference.getDisabledNetwork().getBuses();
Set<LfBus> busesResult = contingencyResult.getDisabledNetwork().getBuses();
assertEquals(busesReference.size(), busesResult.size());
busesReference.forEach(b -> assertTrue(busesResult.stream().anyMatch(b1 -> b1.getId().equals(b.getId()))));
}
}
}
private void printResult(List<List<LfContingency>> result) {
for (List<LfContingency> networkResult : result) {
for (LfContingency contingency : networkResult) {
LOGGER.info("Contingency {} containing {} branches - {} buses (branches: {}, buses: {})",
contingency.getId(), contingency.getDisabledNetwork().getBranches().size(), contingency.getDisabledNetwork().getBuses().size(),
contingency.getDisabledNetwork().getBranches().stream().map(LfBranch::getId).collect(Collectors.joining(",")),
contingency.getDisabledNetwork().getBuses().stream().map(LfBus::getId).collect(Collectors.joining(",")));
}
}
}
private static class TestData implements AutoCloseable {
private final LfNetworkList lfNetworks;
private final List<List<LfContingency>> listLfContingencies;
public TestData(LfNetworkList lfNetworks, List<List<LfContingency>> listLfContingencies) {
this.lfNetworks = lfNetworks;
this.listLfContingencies = listLfContingencies;
}
public LfNetworkList getLfNetworks() {
return lfNetworks;
}
public List<List<LfContingency>> getListLfContingencies() {
return listLfContingencies;
}
@Override
public void close() {
lfNetworks.close();
}
}
private TestData computeLfContingencies(GraphConnectivityFactory<LfBus, LfBranch> connectivityFactory) {
// load contingencies
List<Contingency> contingencies = contingenciesProvider.getContingencies(network);
// try to find all switches impacted by at least one contingency
LfTopoConfig topoConfig = new LfTopoConfig();
PropagatedContingencyCreationParameters creationParameters = new PropagatedContingencyCreationParameters()
.setHvdcAcEmulation(false);
List<PropagatedContingency> propagatedContingencies = PropagatedContingency.createList(network, contingencies, topoConfig, creationParameters);
LfNetworkParameters networkParameters = new LfNetworkParameters()
.setConnectivityFactory(connectivityFactory)
.setBreakers(true);
// create networks including all necessary switches
LfNetworkList lfNetworks = Networks.load(network, networkParameters, topoConfig, ReportNode.NO_OP);
// run simulation on each network
List<List<LfContingency>> listLfContingencies = new ArrayList<>();
for (LfNetwork lfNetwork : lfNetworks.getList()) {
listLfContingencies.add(propagatedContingencies.stream()
.flatMap(propagatedContingency -> propagatedContingency.toLfContingency(lfNetwork).stream())
.collect(Collectors.toList()));
}
return new TestData(lfNetworks, listLfContingencies);
}
}