Skip to content

Commit

Permalink
Fix fork disconnection (#3245)
Browse files Browse the repository at this point in the history
Signed-off-by: Nicolas Rol <[email protected]>
(cherry picked from commit f0482f1)
  • Loading branch information
rolnico authored and olperr1 committed Dec 11, 2024
1 parent 3cd8ba6 commit 91b7b42
Show file tree
Hide file tree
Showing 3 changed files with 265 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1285,8 +1285,8 @@ boolean getDisconnectingSwitches(Terminal terminal, Predicate<? super SwitchImpl
checkTopologyKind(terminal);

int node = ((NodeTerminal) terminal).getNode();
// find all paths starting from the current terminal to a busbar section that does not contain an open switch
List<TIntArrayList> paths = graph.findAllPaths(node, NodeBreakerTopologyModel::isBusbarSection, SwitchPredicates.IS_OPEN);
// find all paths starting from the current terminal to a terminal that does not contain an open switch
List<TIntArrayList> paths = graph.findAllPaths(node, Objects::nonNull, SwitchPredicates.IS_OPEN);
if (paths.isEmpty()) {
return false;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* Copyright (c) 2024, 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.tck;

import com.powsybl.iidm.network.tck.AbstractForkConnectDisconnectTest;

/**
* @author Nicolas Rol {@literal <nicolas.rol at rte-france.com>}
*/
class ForkConnectDisconnectTest extends AbstractForkConnectDisconnectTest {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
/*
* Copyright (c) 2024, 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.tck;

import com.powsybl.iidm.network.*;
import com.powsybl.iidm.network.extensions.BusbarSectionPositionAdder;
import com.powsybl.iidm.network.util.SwitchPredicates;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.assertFalse;

/**
* @author Nicolas Rol {@literal <nicolas.rol at rte-france.com>}
*/
public abstract class AbstractForkConnectDisconnectTest {

public Network createNetwork() {
Network network = Network.create("test", "test");
// Substations
Substation s1 = network.newSubstation()
.setId("S1")
.setCountry(Country.FR)
.add();
VoltageLevel vl1 = s1.newVoltageLevel()
.setId("VL1")
.setNominalV(1.0)
.setTopologyKind(TopologyKind.NODE_BREAKER)
.add();
VoltageLevel vl2 = s1.newVoltageLevel()
.setId("VL2")
.setNominalV(1.0)
.setTopologyKind(TopologyKind.NODE_BREAKER)
.add();

// Busbar sections
BusbarSection bbs1 = vl1.getNodeBreakerView()
.newBusbarSection()
.setId("BBS11")
.setNode(0)
.add();
bbs1.newExtension(BusbarSectionPositionAdder.class)
.withBusbarIndex(1)
.withSectionIndex(1)
.add();
BusbarSection bbs2A = vl2.getNodeBreakerView()
.newBusbarSection()
.setId("BBS2A")
.setNode(0)
.add();
bbs2A.newExtension(BusbarSectionPositionAdder.class)
.withBusbarIndex(1)
.withSectionIndex(1)
.add();
BusbarSection bbs2B = vl2.getNodeBreakerView()
.newBusbarSection()
.setId("BBS2B")
.setNode(1)
.add();
bbs2B.newExtension(BusbarSectionPositionAdder.class)
.withBusbarIndex(2)
.withSectionIndex(1)
.add();

// Lines
network.newLine()
.setId("L1")
.setName("LINE1")
.setR(1.0)
.setX(2.0)
.setG1(3.0)
.setG2(3.5)
.setB1(4.0)
.setB2(4.5)
.setVoltageLevel1("VL1")
.setVoltageLevel2("VL2")
.setNode1(4)
.setNode2(3)
.add();

// Add a second line
network.newLine()
.setId("L2")
.setName("LINE2")
.setR(1.0)
.setX(2.0)
.setG1(3.0)
.setG2(3.5)
.setB1(4.0)
.setB2(4.5)
.setVoltageLevel1("VL1")
.setVoltageLevel2("VL2")
.setNode1(5)
.setNode2(5)
.add();

// VL1 - Breakers and disconnectors for L1 and L2
vl1.getNodeBreakerView().newDisconnector()
.setId("D_L1")
.setNode1(4)
.setNode2(6)
.setOpen(false)
.add();
vl1.getNodeBreakerView().newDisconnector()
.setId("D_L2")
.setNode1(5)
.setNode2(6)
.setOpen(false)
.add();
vl1.getNodeBreakerView().newBreaker()
.setId("B_L1_L2")
.setNode1(6)
.setNode2(7)
.setOpen(false)
.setFictitious(false)
.add();
vl1.getNodeBreakerView().newDisconnector()
.setId("D0")
.setNode1(7)
.setNode2(0)
.setOpen(false)
.add();

// VL2 - Breakers and disconnectors for L1 and L2
vl2.getNodeBreakerView().newBreaker()
.setId("B_L1_VL2")
.setNode1(3)
.setNode2(2)
.setOpen(false)
.setFictitious(false)
.add();
vl2.getNodeBreakerView().newDisconnector()
.setId("D_L1_BBS2A")
.setNode1(2)
.setNode2(0)
.setOpen(false)
.add();
vl2.getNodeBreakerView().newDisconnector()
.setId("D_L1_BBS2B")
.setNode1(2)
.setNode2(1)
.setOpen(true)
.add();
vl2.getNodeBreakerView().newBreaker()
.setId("B_L2_VL2")
.setNode1(5)
.setNode2(4)
.setOpen(false)
.setFictitious(false)
.add();
vl2.getNodeBreakerView().newDisconnector()
.setId("D_L2_BBS2A")
.setNode1(4)
.setNode2(0)
.setOpen(true)
.add();
vl2.getNodeBreakerView().newDisconnector()
.setId("D_L2_BBS2B")
.setNode1(4)
.setNode2(1)
.setOpen(false)
.add();
return network;
}

@Test
public void fullyClosedTest() {
Network network = createNetwork();

// Useful elements
VoltageLevel.NodeBreakerView topo = network.getVoltageLevel("VL1").getNodeBreakerView();
Line line1 = network.getLine("L1");
Line line2 = network.getLine("L2");
Switch disconnector = network.getSwitch("D_L1");

// L1 and L2 are fully connected
assertTrue(topo.getOptionalTerminal(4).isPresent());
assertTerminalsStatus(line1.getTerminals(), true);
assertTrue(topo.getOptionalTerminal(5).isPresent());
assertTerminalsStatus(line2.getTerminals(), true);

// Disconnect L1
line1.disconnect(SwitchPredicates.IS_NON_NULL);

// check that L1 is disconnected while L2 is still connected
assertTrue(topo.getOptionalTerminal(4).isPresent());
assertTerminalsStatus(line1.getTerminals(), false);
assertTrue(topo.getOptionalTerminal(5).isPresent());
assertTerminalsStatus(line2.getTerminals(), true);

// D_L1 should be open
assertTrue(disconnector.isOpen());
}

@Test
public void forkDisconnectedTest() {
Network network = createNetwork();

// Useful elements
VoltageLevel.NodeBreakerView topo = network.getVoltageLevel("VL1").getNodeBreakerView();
Line line1 = network.getLine("L1");
Line line2 = network.getLine("L2");
Switch disconnectorL1 = network.getSwitch("D_L1");
Switch disconnectorL2 = network.getSwitch("D_L2");
Switch breaker = network.getSwitch("B_L1_L2");

// In this case, B_L1_L2 is open
breaker.setOpen(true);

// L1 and L2 are fully connected
assertTrue(topo.getOptionalTerminal(4).isPresent());
assertTerminalsStatus(line1.getTerminals(), true);
assertTrue(topo.getOptionalTerminal(5).isPresent());
assertTerminalsStatus(line2.getTerminals(), true);

// Disconnect L1
line1.disconnect(SwitchPredicates.IS_NON_NULL);

// check that L1 and L2 are disconnected
assertTrue(topo.getOptionalTerminal(4).isPresent());
assertTerminalsStatus(line1.getTerminals(), false);
assertTrue(topo.getOptionalTerminal(5).isPresent());
assertTerminalsStatus(List.of(line2.getTerminal1()), false);
assertTerminalsStatus(List.of(line2.getTerminal2()), true);

// D_L1 should be open but not D_L2
assertTrue(disconnectorL1.isOpen());
assertFalse(disconnectorL2.isOpen());
}

private void assertTerminalsStatus(List<? extends Terminal> terminals, boolean terminalsShouldBeConnected) {
if (terminalsShouldBeConnected) {
terminals.forEach(terminal -> assertNotNull(terminal.getBusView().getBus()));
terminals.forEach(terminal -> assertTrue(terminal.isConnected()));
} else {
terminals.forEach(terminal -> assertNull(terminal.getBusView().getBus()));
terminals.forEach(terminal -> assertFalse(terminal.isConnected()));
}
}
}

0 comments on commit 91b7b42

Please sign in to comment.