TopologyTraverseDepthAndBreadthTest.java
/**
* Copyright (c) 2023, 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.iidm.network.impl;
import com.powsybl.iidm.network.*;
import com.powsybl.math.graph.TraversalType;
import com.powsybl.math.graph.TraverseResult;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* Small network to test topology traversal by depth first or breadth first
* Below is a diagram of the network:
* <div>
* <object data="doc-files/traversalByDepthOrBreadthNetwork.svg" type="image/svg+xml"></object>
* </div>
*
* @author Franck Lecuyer {@literal <franck.lecuyer at rte-france.com>}
*/
class TopologyTraverseDepthAndBreadthTest {
private Network network;
@BeforeEach
void setUp() {
network = Network.create("test", "test");
Substation s1 = network.newSubstation().setId("S1").setCountry(Country.FR).add();
VoltageLevel vl1 = s1.newVoltageLevel().setId("VL1").setNominalV(400f).setTopologyKind(TopologyKind.NODE_BREAKER).add();
vl1.getNodeBreakerView().newBusbarSection().setId("VL1_B1").setNode(0).add();
vl1.getNodeBreakerView().newBusbarSection().setId("VL1_B2").setNode(1).add();
vl1.newGenerator().setId("G1").setNode(2).setMinP(0).setMaxP(1).setTargetP(1).setTargetQ(0).setVoltageRegulatorOn(false).add();
vl1.newGenerator().setId("G2").setNode(5).setMinP(0).setMaxP(1).setTargetP(1).setTargetQ(0).setVoltageRegulatorOn(false).add();
vl1.getNodeBreakerView().newBreaker().setId("VL1_BREAKER3").setOpen(false).setNode1(3).setNode2(9).add();
vl1.getNodeBreakerView().newBreaker().setId("VL1_BREAKER1").setOpen(false).setNode1(3).setNode2(4).add();
vl1.getNodeBreakerView().newBreaker().setId("VL1_BREAKER2").setOpen(false).setNode1(9).setNode2(10).add();
vl1.getNodeBreakerView().newBreaker().setId("VL1_BREAKER7").setOpen(false).setNode1(6).setNode2(12).add();
vl1.getNodeBreakerView().newBreaker().setId("VL1_BREAKER5").setOpen(false).setNode1(6).setNode2(7).add();
vl1.getNodeBreakerView().newBreaker().setId("VL1_BREAKER6").setOpen(false).setNode1(12).setNode2(13).add();
vl1.getNodeBreakerView().newDisconnector().setId("VL1_DISCONNECTOR1").setOpen(false).setNode1(2).setNode2(3).add();
vl1.getNodeBreakerView().newDisconnector().setId("VL1_DISCONNECTOR2").setOpen(false).setNode1(8).setNode2(9).add();
vl1.getNodeBreakerView().newDisconnector().setId("VL1_DISCONNECTOR3").setOpen(false).setNode1(1).setNode2(4).add();
vl1.getNodeBreakerView().newDisconnector().setId("VL1_DISCONNECTOR4").setOpen(false).setNode1(0).setNode2(10).add();
vl1.getNodeBreakerView().newDisconnector().setId("VL1_DISCONNECTOR5").setOpen(false).setNode1(5).setNode2(6).add();
vl1.getNodeBreakerView().newDisconnector().setId("VL1_DISCONNECTOR6").setOpen(false).setNode1(1).setNode2(7).add();
vl1.getNodeBreakerView().newDisconnector().setId("VL1_DISCONNECTOR7").setOpen(false).setNode1(11).setNode2(12).add();
vl1.getNodeBreakerView().newDisconnector().setId("VL1_DISCONNECTOR8").setOpen(false).setNode1(0).setNode2(13).add();
Substation s2 = network.newSubstation().setId("S2").setCountry(Country.FR).add();
VoltageLevel vl2 = s2.newVoltageLevel().setId("VL2").setNominalV(400f).setTopologyKind(TopologyKind.NODE_BREAKER).add();
vl2.getNodeBreakerView().newBusbarSection().setId("VL2_B1").setNode(0).add();
vl2.getNodeBreakerView().newBreaker().setId("VL2_BREAKER1").setOpen(false).setNode1(1).setNode2(2).add();
vl2.getNodeBreakerView().newDisconnector().setId("VL2_DISCONNECTOR1").setOpen(false).setNode1(0).setNode2(2).add();
Substation s3 = network.newSubstation().setId("S3").setCountry(Country.FR).add();
VoltageLevel vl3 = s3.newVoltageLevel().setId("VL3").setNominalV(400f).setTopologyKind(TopologyKind.NODE_BREAKER).add();
vl3.getNodeBreakerView().newBusbarSection().setId("VL3_B1").setNode(0).add();
vl3.getNodeBreakerView().newBreaker().setId("VL3_BREAKER1").setOpen(false).setNode1(1).setNode2(2).add();
vl3.getNodeBreakerView().newDisconnector().setId("VL3_DISCONNECTOR1").setOpen(false).setNode1(0).setNode2(2).add();
network.newLine().setId("L1").setVoltageLevel1("VL1").setVoltageLevel2("VL2").setNode1(8).setNode2(1).setR(1).setX(1).setG1(0).setB1(0).setG2(0).setB2(0).add();
network.newLine().setId("L2").setVoltageLevel1("VL1").setVoltageLevel2("VL3").setNode1(11).setNode2(1).setR(1).setX(1).setG1(0).setB1(0).setG2(0).setB2(0).add();
}
private static class BusbarSectionFinderTraverser implements Terminal.TopologyTraverser {
private final boolean onlyConnectedBbs;
private String firstTraversedBbsId;
public BusbarSectionFinderTraverser(boolean onlyConnectedBbs) {
this.onlyConnectedBbs = onlyConnectedBbs;
}
@Override
public TraverseResult traverse(Terminal terminal, boolean connected) {
if (terminal.getConnectable().getType() == IdentifiableType.BUSBAR_SECTION) {
firstTraversedBbsId = terminal.getConnectable().getId();
return TraverseResult.TERMINATE_TRAVERSER;
}
return TraverseResult.CONTINUE;
}
@Override
public TraverseResult traverse(Switch aSwitch) {
if (onlyConnectedBbs && aSwitch.isOpen()) {
return TraverseResult.TERMINATE_PATH;
}
return TraverseResult.CONTINUE;
}
public String getFirstTraversedBbsId() {
return firstTraversedBbsId;
}
}
private static String getBusbarSectionId(Terminal terminal, TraversalType traversalType) {
BusbarSectionFinderTraverser connectedBusbarSectionFinder = new BusbarSectionFinderTraverser(terminal.isConnected());
terminal.traverse(connectedBusbarSectionFinder, traversalType);
return connectedBusbarSectionFinder.getFirstTraversedBbsId();
}
@Test
void testTraverseByDepthFirst() {
assertEquals("VL1_B1", getBusbarSectionId(network.getGenerator("G1").getTerminal(), TraversalType.DEPTH_FIRST));
assertEquals("VL1_B1", getBusbarSectionId(network.getGenerator("G2").getTerminal(), TraversalType.DEPTH_FIRST));
assertEquals("VL1_B2", getBusbarSectionId(network.getLine("L1").getTerminal("VL1"), TraversalType.DEPTH_FIRST));
assertEquals("VL2_B1", getBusbarSectionId(network.getLine("L1").getTerminal("VL2"), TraversalType.DEPTH_FIRST));
assertEquals("VL1_B2", getBusbarSectionId(network.getLine("L2").getTerminal("VL1"), TraversalType.DEPTH_FIRST));
assertEquals("VL3_B1", getBusbarSectionId(network.getLine("L2").getTerminal("VL3"), TraversalType.DEPTH_FIRST));
}
@Test
void testTraverseByBreadthFirst() {
assertEquals("VL1_B2", getBusbarSectionId(network.getGenerator("G1").getTerminal(), TraversalType.BREADTH_FIRST));
assertEquals("VL1_B2", getBusbarSectionId(network.getGenerator("G2").getTerminal(), TraversalType.BREADTH_FIRST));
assertEquals("VL1_B1", getBusbarSectionId(network.getLine("L1").getTerminal("VL1"), TraversalType.BREADTH_FIRST));
assertEquals("VL2_B1", getBusbarSectionId(network.getLine("L1").getTerminal("VL2"), TraversalType.BREADTH_FIRST));
assertEquals("VL1_B1", getBusbarSectionId(network.getLine("L2").getTerminal("VL1"), TraversalType.BREADTH_FIRST));
assertEquals("VL3_B1", getBusbarSectionId(network.getLine("L2").getTerminal("VL3"), TraversalType.BREADTH_FIRST));
}
}