Skip to content

Commit

Permalink
add disconnection of connectable at the other end of paths
Browse files Browse the repository at this point in the history
Signed-off-by: Nicolas Rol <[email protected]>
  • Loading branch information
rolnico committed Dec 9, 2024
1 parent 5e15d64 commit 56559a9
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@

import com.powsybl.commons.report.ReportNode;
import com.powsybl.commons.report.TypedValue;
import com.powsybl.iidm.network.Identifiable;
import com.powsybl.iidm.network.Switch;
import com.powsybl.iidm.network.Terminal;
import com.powsybl.iidm.network.*;

import java.util.HashSet;
import java.util.List;
Expand Down Expand Up @@ -114,6 +112,9 @@ static boolean disconnectAllTerminals(Identifiable<?> identifiable, List<? exten
// Initialisation of a list to open in case some terminals are in node-breaker view
Set<SwitchImpl> switchForDisconnection = new HashSet<>();

// Set of terminals at the other end of paths - used to disconnect their connectable if needed
Set<NodeTerminal> endOfPathTerminals = new HashSet<>();

// We try to disconnect each terminal
for (Terminal terminal : terminals) {
// Check if the terminal is already disconnected
Expand All @@ -131,7 +132,7 @@ static boolean disconnectAllTerminals(Identifiable<?> identifiable, List<? exten
// If it's a node-breaker terminal, the switches to disconnect are added to a set
if (terminal.getVoltageLevel().getTopologyKind() == NODE_BREAKER) {
NodeBreakerTopologyModel topologyModel = (NodeBreakerTopologyModel) ((VoltageLevelImpl) terminal.getVoltageLevel()).getTopologyModel();
if (!topologyModel.getDisconnectingSwitches(terminal, isSwitchOpenable, switchForDisconnection)) {
if (!topologyModel.getDisconnectingSwitches(terminal, isSwitchOpenable, switchForDisconnection, endOfPathTerminals)) {
// Exit if the terminal cannot be disconnected
return false;
}
Expand All @@ -154,6 +155,42 @@ static boolean disconnectAllTerminals(Identifiable<?> identifiable, List<? exten
}
// Disconnect all switches on node-breaker terminals
switchForDisconnection.forEach(sw -> sw.setOpen(true));

// Completely disconnect if needed the elements (other than busbar sections at the end of the paths)
disconnectEndOfPathTerminals(endOfPathTerminals, isSwitchOpenable);
return isNowDisconnected;
}

private static void disconnectEndOfPathTerminals(Set<NodeTerminal> endOfPathTerminals, Predicate<Switch> isSwitchOpenable) {
for (Terminal terminal : endOfPathTerminals) {
if (!terminal.isConnected()) {
// If one side is disconnected, the connectable has to be fully disconnected
switch (terminal.getConnectable().getType()) {
case LINE -> {
Line line = (Line) terminal.getConnectable();
line.disconnect(isSwitchOpenable);
}
case TWO_WINDINGS_TRANSFORMER -> {
TwoWindingsTransformer twt = (TwoWindingsTransformer) terminal.getConnectable();
twt.disconnect(isSwitchOpenable);
}
case THREE_WINDINGS_TRANSFORMER -> {
ThreeWindingsTransformer twt = (ThreeWindingsTransformer) terminal.getConnectable();
twt.disconnect(isSwitchOpenable);
}
case HVDC_CONVERTER_STATION ->
((HvdcConverterStation<?>) terminal.getConnectable()).getHvdcLine().disconnectConverterStations(isSwitchOpenable);
case DANGLING_LINE -> {
DanglingLine danglingLine = (DanglingLine) terminal.getConnectable();
if (danglingLine.getTieLine().isPresent()) {
danglingLine.getTieLine().get().disconnectDanglingLines(isSwitchOpenable);
}
}
default -> {
// Nothing to do
}
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1285,6 +1285,11 @@ public boolean disconnect(TerminalExt terminal, Predicate<? super SwitchImpl> is
}

boolean getDisconnectingSwitches(Terminal terminal, Predicate<? super SwitchImpl> isSwitchOpenable, Set<SwitchImpl> switchForDisconnection) {
return getDisconnectingSwitches(terminal, isSwitchOpenable, switchForDisconnection, new HashSet<>());
}

boolean getDisconnectingSwitches(Terminal terminal, Predicate<? super SwitchImpl> isSwitchOpenable, Set<SwitchImpl> switchForDisconnection,
Set<NodeTerminal> endOfPathTerminals) {
// Check the topology kind
checkTopologyKind(terminal);

Expand All @@ -1303,6 +1308,9 @@ boolean getDisconnectingSwitches(Terminal terminal, Predicate<? super SwitchImpl
return false;
}
}

// Identify the terminal at the end of the paths
graph.identifyEndOfPathVerticesObjects(paths, endOfPathTerminals, NodeBreakerTopologyModel::isTerminal);
return true;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.iidm.network.impl;
package com.powsybl.iidm.network.impl.tck;

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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,36 @@ public Network createNetwork() {
VoltageLevel vl2 = s1.newVoltageLevel()
.setId("VL2")
.setNominalV(1.0)
.setTopologyKind(TopologyKind.BUS_BREAKER)
.setTopologyKind(TopologyKind.NODE_BREAKER)
.add();

// Busbar sections
BusbarSection bbs11 = vl1.getNodeBreakerView()
BusbarSection bbs1 = vl1.getNodeBreakerView()
.newBusbarSection()
.setId("BBS11")
.setNode(0)
.add();
bbs11.newExtension(BusbarSectionPositionAdder.class)
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();
vl2.getBusBreakerView()
.newBus()
.setId("bus2A")
BusbarSection bbs2B = vl2.getNodeBreakerView()
.newBusbarSection()
.setId("BBS2B")
.setNode(1)
.add();
vl2.getBusBreakerView()
.newBus()
.setId("bus2B")
bbs2B.newExtension(BusbarSectionPositionAdder.class)
.withBusbarIndex(2)
.withSectionIndex(1)
.add();

// Lines
Expand All @@ -70,8 +80,7 @@ public Network createNetwork() {
.setVoltageLevel1("VL1")
.setVoltageLevel2("VL2")
.setNode1(4)
.setBus2("bus2A")
.setConnectableBus2("bus2A")
.setNode2(3)
.add();
network.newLine()
.setId("L2")
Expand All @@ -85,11 +94,10 @@ public Network createNetwork() {
.setVoltageLevel1("VL1")
.setVoltageLevel2("VL2")
.setNode1(5)
.setBus2("bus2B")
.setConnectableBus2("bus2B")
.setNode2(5)
.add();

// Breakers and disconnectors for L1 and L2
// VL1 - Breakers and disconnectors for L1 and L2
vl1.getNodeBreakerView().newDisconnector()
.setId("D_L1")
.setNode1(4)
Expand All @@ -115,6 +123,46 @@ public Network createNetwork() {
.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;
}

Expand Down Expand Up @@ -184,7 +232,6 @@ public void forkDisconnectedTest() {
assertTrue(topo.getOptionalTerminal(5).isPresent());
line2.getTerminals().forEach(terminal -> assertNull(terminal.getBusView().getBus()));
line2.getTerminals().forEach(terminal -> assertFalse(terminal.isConnected()));
// TODO: Warning - L2 is half connected!

// D_L1 should be open but not D_L2
assertTrue(disconnectorL1.isOpen());
Expand Down
20 changes: 20 additions & 0 deletions math/src/main/java/com/powsybl/math/graph/UndirectedGraphImpl.java
Original file line number Diff line number Diff line change
Expand Up @@ -706,6 +706,26 @@ private void findAllPaths(int v, Predicate<V> pathComplete, Predicate<? super E>
}
}

public void identifyEndOfPathVerticesObjects(List<TIntArrayList> paths, Set<V> endOfPathVerticesObjects,
Predicate<V> pathComplete) {
for (TIntArrayList path : paths) {
// We get the last edge of the path
int e = path.get(path.size() - 1);
Edge<E> edge = edges.get(e);

// The last vertice can be at either side of the edge
V object1 = vertices.get(edge.getV1()).getObject();
V object2 = vertices.get(edge.getV2()).getObject();

// Only one side can validate the predicate
if (Boolean.TRUE.equals(pathComplete.test(object1))) {
endOfPathVerticesObjects.add(object1);
} else {
endOfPathVerticesObjects.add(object2);
}
}
}

@Override
public void addListener(UndirectedGraphListener<V, E> l) {
listeners.add(l);
Expand Down

0 comments on commit 56559a9

Please sign in to comment.