Skip to content

Commit 405f1fe

Browse files
author
Denis Bonnand
committed
Add DC Switches in topology traverser. Fix Subnetwork issue
Signed-off-by: Denis Bonnand <[email protected]>
1 parent f34158d commit 405f1fe

File tree

12 files changed

+145
-50
lines changed

12 files changed

+145
-50
lines changed

iidm/iidm-api/src/main/java/com/powsybl/iidm/network/DcTerminal.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,15 @@ interface TopologyTraverser {
104104
* to stop the current traversal path, {@link TraverseResult#TERMINATE_TRAVERSER} to stop all the traversal paths
105105
*/
106106
TraverseResult traverse(DcTerminal terminal, boolean connected);
107+
108+
/**
109+
* Called when a DC switch is encountered
110+
*
111+
* @param aSwitch the encountered switch
112+
* @return {@link TraverseResult#CONTINUE} to continue traversal, {@link TraverseResult#TERMINATE_PATH}
113+
* to stop the current traversal path, {@link TraverseResult#TERMINATE_TRAVERSER} to stop all the traversal paths
114+
*/
115+
TraverseResult traverse(DcSwitch aSwitch);
107116
}
108117

109118
boolean traverse(TopologyTraverser traverser, Set<DcTerminal> visitedDcTerminals);

iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/DcTerminalImpl.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,15 @@ NetworkImpl getNetwork() {
186186
throw new IllegalStateException("Unexpected dcConnectable type: " + dcConnectable.getClass().getName());
187187
}
188188

189+
Network getParentNetwork() {
190+
if (dcConnectable instanceof AbstractDcConnectable<?> abstractDcConnectable) {
191+
return abstractDcConnectable.getParentNetwork();
192+
} else if (dcConnectable instanceof AbstractAcDcConverter<?> abstractDcConverter) {
193+
return abstractDcConverter.getParentNetwork();
194+
}
195+
throw new IllegalStateException("Unexpected dcConnectable type: " + dcConnectable.getClass().getName());
196+
}
197+
189198
String getAttributeSideOrNumberSuffix() {
190199
return "" + (side != null ? side.getNum() : "") + (terminalNumber != null ? terminalNumber.getNum() : "");
191200
}
@@ -207,7 +216,12 @@ public boolean traverse(TopologyTraverser traverser, Set<DcTerminal> visitedDcTe
207216
}
208217

209218
private DcTopologyModel getTopologyModel() {
210-
return this.getNetwork().getDcTopologyModel();
219+
Network parent = this.getParentNetwork();
220+
if (parent instanceof SubnetworkImpl subnetwork) {
221+
return subnetwork.getDcTopologyModel();
222+
} else {
223+
return ((NetworkImpl) parent).getDcTopologyModel();
224+
}
211225
}
212226

213227
@Override

iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/DcTopologyModel.java

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,9 @@ boolean traverse(DcTerminal terminal, DcTerminal.TopologyTraverser traverser, Se
400400
List<DcTerminal> nextDcTerminals = new ArrayList<>();
401401
addNextDcTerminals(terminal, nextDcTerminals);
402402

403-
// then check we can traverse terminals connected to same dc node
404-
DcNode dcNode = terminal.getDcNode();
403+
// then check we can traverse terminals connected to same DC node
404+
int v = getVertex(terminal.getDcNode().getId());
405+
DcNode dcNode = graph.getVertexObject(v);
405406
for (DcTerminal t : dcNode.getDcTerminals()) {
406407
TraverseResult tTraverseResult = getTraverserResult(visitedDcTerminals, t, traverser);
407408
if (tTraverseResult == TraverseResult.TERMINATE_TRAVERSER) {
@@ -411,15 +412,40 @@ boolean traverse(DcTerminal terminal, DcTerminal.TopologyTraverser traverser, Se
411412
}
412413
}
413414

415+
// then go through other connected DC nodes
416+
boolean traversalTerminated = traverseOtherDcNodes(v, nextDcTerminals, traverser, visitedDcTerminals);
417+
if (traversalTerminated) {
418+
return false;
419+
}
420+
414421
for (DcTerminal t : nextDcTerminals) {
415422
if (!t.traverse(traverser, visitedDcTerminals)) {
416423
return false;
417424
}
418425
}
419426
}
427+
420428
return true;
421429
}
422430

431+
private boolean traverseOtherDcNodes(int v, List<DcTerminal> nextDcTerminals,
432+
DcTerminal.TopologyTraverser traverser, Set<DcTerminal> visitedDcTerminals) {
433+
return !graph.traverse(v, TraversalType.DEPTH_FIRST, (v1, e, v2) -> {
434+
DcSwitchImpl aSwitch = graph.getEdgeObject(e);
435+
List<DcTerminal> otherBusDcTerminals = graph.getVertexObject(v2).getDcTerminals();
436+
TraverseResult switchTraverseResult = traverser.traverse(aSwitch);
437+
if (switchTraverseResult == TraverseResult.CONTINUE && !otherBusDcTerminals.isEmpty()) {
438+
DcTerminal otherDcTerminal = otherBusDcTerminals.get(0);
439+
TraverseResult otherTermTraverseResult = getTraverserResult(visitedDcTerminals, otherDcTerminal, traverser);
440+
if (otherTermTraverseResult == TraverseResult.CONTINUE) {
441+
addNextDcTerminals(otherDcTerminal, nextDcTerminals);
442+
}
443+
return otherTermTraverseResult;
444+
}
445+
return switchTraverseResult;
446+
});
447+
}
448+
423449
boolean disconnect(DcTerminal terminal) {
424450
// already disconnected?
425451
if (!terminal.isConnected()) {

iidm/iidm-impl/src/test/java/com/powsybl/iidm/network/impl/DcTopologyTraverseTest.java

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,25 @@
77
*/
88
package com.powsybl.iidm.network.impl;
99

10-
import com.powsybl.iidm.network.DcTerminal;
11-
import com.powsybl.iidm.network.IdentifiableType;
12-
import com.powsybl.iidm.network.Network;
10+
import com.powsybl.iidm.network.*;
1311
import com.powsybl.iidm.network.test.DcDetailedNetworkFactory;
1412
import com.powsybl.math.graph.TraverseResult;
1513
import org.junit.jupiter.api.Test;
1614

1715
import static org.junit.jupiter.api.Assertions.assertEquals;
18-
import static org.junit.jupiter.api.Assertions.assertNull;
1916

2017
/**
2118
* @author Denis Bonnand {@literal <denis.bonnand at supergrid-institute.com>}
2219
*/
2320
class DcTopologyTraverseTest {
2421
private static final class ConverterTraverser implements DcTerminal.TopologyTraverser {
22+
private final boolean onlyConnectedDcNode;
2523
private String firstTraversedConverterId;
2624

25+
public ConverterTraverser(boolean onlyConnectedDcNode) {
26+
this.onlyConnectedDcNode = onlyConnectedDcNode;
27+
}
28+
2729
@Override
2830
public TraverseResult traverse(DcTerminal terminal, boolean connected) {
2931
if (terminal.getDcConnectable().getType() == IdentifiableType.VOLTAGE_SOURCE_CONVERTER) {
@@ -33,20 +35,33 @@ public TraverseResult traverse(DcTerminal terminal, boolean connected) {
3335
return TraverseResult.CONTINUE;
3436
}
3537

38+
@Override
39+
public TraverseResult traverse(DcSwitch aSwitch) {
40+
if (onlyConnectedDcNode && aSwitch.isOpen()) {
41+
return TraverseResult.TERMINATE_PATH;
42+
}
43+
return TraverseResult.CONTINUE;
44+
}
45+
3646
public String getFirstTraversedConverterId() {
3747
return firstTraversedConverterId;
3848
}
3949
}
4050

4151
private static String getConverterSectionId(DcTerminal terminal) {
42-
ConverterTraverser connectedConverter = new ConverterTraverser();
52+
ConverterTraverser connectedConverter = new ConverterTraverser(terminal.isConnected());
4353
terminal.traverse(connectedConverter);
4454
return connectedConverter.getFirstTraversedConverterId();
4555
}
4656

4757
private static final class DcLineTraverser implements DcTerminal.TopologyTraverser {
58+
private final boolean onlyConnectedDcNode;
4859
private String firstTraversedDcLineId;
4960

61+
public DcLineTraverser(boolean onlyConnectedDcNode) {
62+
this.onlyConnectedDcNode = onlyConnectedDcNode;
63+
}
64+
5065
@Override
5166
public TraverseResult traverse(DcTerminal terminal, boolean connected) {
5267
if (terminal.getDcConnectable().getType() == IdentifiableType.DC_LINE) {
@@ -56,21 +71,28 @@ public TraverseResult traverse(DcTerminal terminal, boolean connected) {
5671
return TraverseResult.CONTINUE;
5772
}
5873

74+
@Override
75+
public TraverseResult traverse(DcSwitch aSwitch) {
76+
if (onlyConnectedDcNode && aSwitch.isOpen()) {
77+
return TraverseResult.TERMINATE_PATH;
78+
}
79+
return TraverseResult.CONTINUE;
80+
}
81+
5982
public String getFirstTraversedDcLineId() {
6083
return firstTraversedDcLineId;
6184
}
6285
}
6386

6487
private static String getDcLineSectionId(DcTerminal terminal) {
65-
DcLineTraverser connectedDcLine = new DcLineTraverser();
88+
DcLineTraverser connectedDcLine = new DcLineTraverser(terminal.isConnected());
6689
terminal.traverse(connectedDcLine);
6790
return connectedDcLine.getFirstTraversedDcLineId();
6891
}
6992

7093
@Test
7194
void testVscSymmetricalMonopole() {
7295
Network network = DcDetailedNetworkFactory.createVscSymmetricalMonopole();
73-
7496
assertEquals("VscGb", getConverterSectionId(network.getDcNode("dcNodeGbNeg").getDcTerminals().getFirst()));
7597
assertEquals("VscGb", getConverterSectionId(network.getDcNode("dcNodeGbPos").getDcTerminals().getFirst()));
7698
assertEquals("VscFr", getConverterSectionId(network.getDcNode("dcNodeFrNeg").getDcTerminals().getFirst()));
@@ -98,6 +120,9 @@ void testVscSymmetricalMonopole() {
98120
void testLccBipoleGroundReturn() {
99121
Network network = DcDetailedNetworkFactory.createLccBipoleGroundReturn();
100122

123+
network.getDcSwitch("dcSwitchGbPosBypass").setOpen(false);
124+
network.getDcSwitch("dcSwitchFrPosBypass").setOpen(false);
125+
101126
assertEquals("dcLine2", getDcLineSectionId(network.getDcNode("dcNodeGbNeg").getDcTerminals().getFirst()));
102127
assertEquals("dcLine1", getDcLineSectionId(network.getDcNode("dcNodeGbPos").getDcTerminals().getFirst()));
103128
assertEquals("dcLine2", getDcLineSectionId(network.getDcNode("dcNodeFrNeg").getDcTerminals().getFirst()));
@@ -106,7 +131,7 @@ void testLccBipoleGroundReturn() {
106131
assertEquals("dcLine1", getDcLineSectionId(network.getDcLine("dcLine1").getDcTerminal2()));
107132
assertEquals("dcLine2", getDcLineSectionId(network.getDcLine("dcLine2").getDcTerminal1()));
108133
assertEquals("dcLine2", getDcLineSectionId(network.getDcLine("dcLine2").getDcTerminal2()));
109-
assertNull(getDcLineSectionId(network.getDcNode("dcNodeFrMid").getDcTerminals().getFirst()));
110-
assertNull(getDcLineSectionId(network.getDcNode("dcNodeGbMid").getDcTerminals().getFirst()));
134+
assertEquals("dcLine1", getDcLineSectionId(network.getDcNode("dcNodeGbMid").getDcTerminals().getFirst()));
135+
assertEquals("dcLine1", getDcLineSectionId(network.getDcNode("dcNodeFrMid").getDcTerminals().getFirst()));
111136
}
112137
}

iidm/iidm-modification/src/main/java/com/powsybl/iidm/modification/tripping/AbstractTripping.java

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,7 @@
1313
import com.powsybl.iidm.modification.AbstractNetworkModification;
1414
import com.powsybl.iidm.modification.NetworkModificationImpact;
1515
import com.powsybl.iidm.modification.topology.NamingStrategy;
16-
import com.powsybl.iidm.network.DcTerminal;
17-
import com.powsybl.iidm.network.Network;
18-
import com.powsybl.iidm.network.Switch;
19-
import com.powsybl.iidm.network.Terminal;
16+
import com.powsybl.iidm.network.*;
2017

2118
import java.util.HashSet;
2219
import java.util.Objects;
@@ -44,13 +41,15 @@ public void apply(Network network, NamingStrategy namingStrategy, boolean throwE
4441
ReportNode reportNode) {
4542
Set<Switch> switchesToOpen = new HashSet<>();
4643
Set<Terminal> terminalsToDisconnect = new HashSet<>();
44+
Set<DcSwitch> dcSwitchesToOpen = new HashSet<>();
4745
Set<DcTerminal> dcTerminalsToDisconnect = new HashSet<>();
4846

4947
try {
5048
traverse(network, switchesToOpen, terminalsToDisconnect);
51-
traverseDc(network, dcTerminalsToDisconnect);
49+
traverseDc(network, dcSwitchesToOpen, dcTerminalsToDisconnect);
5250
switchesToOpen.forEach(s -> s.setOpen(true));
5351
terminalsToDisconnect.forEach(Terminal::disconnect);
52+
dcSwitchesToOpen.forEach(s -> s.setOpen(true));
5453
dcTerminalsToDisconnect.forEach(DcTerminal::disconnect);
5554
} catch (PowsyblException powsyblException) {
5655
logOrThrow(throwException, powsyblException.getMessage());
@@ -65,10 +64,11 @@ public NetworkModificationImpact hasImpactOnNetwork(Network network) {
6564
} else {
6665
Set<Switch> switchesToOpen = new HashSet<>();
6766
Set<Terminal> terminalsToDisconnect = new HashSet<>();
67+
Set<DcSwitch> dcSwitchesToOpen = new HashSet<>();
6868
Set<DcTerminal> dcTerminalsToDisconnect = new HashSet<>();
6969

7070
traverse(network, switchesToOpen, terminalsToDisconnect);
71-
traverseDc(network, dcTerminalsToDisconnect);
71+
traverseDc(network, dcSwitchesToOpen, dcTerminalsToDisconnect);
7272
if (switchesToOpen.isEmpty() && terminalsToDisconnect.isEmpty() && dcTerminalsToDisconnect.isEmpty()) {
7373
impact = NetworkModificationImpact.NO_IMPACT_ON_NETWORK;
7474
}
@@ -91,18 +91,18 @@ public void traverseDoubleSidedEquipment(String voltageLevelId, Terminal termina
9191
}
9292
}
9393

94-
public void traverseDoubleSidedEquipment(String dcNodeId, DcTerminal terminal1, DcTerminal terminal2, Set<DcTerminal> terminalsToDisconnect, Set<DcTerminal> traversedTerminals, String equipmentType) {
94+
public void traverseDoubleSidedEquipment(String dcNodeId, DcTerminal terminal1, DcTerminal terminal2, Set<DcSwitch> dcSwitchesToOpen, Set<DcTerminal> dcTerminalsToDisconnect, Set<DcTerminal> traversedDcTerminals, String equipmentType) {
9595
if (dcNodeId != null) {
9696
if (dcNodeId.equals(terminal1.getDcNode().getId())) {
97-
TrippingTopologyTraverser.traverse(terminal1, terminalsToDisconnect, traversedTerminals);
97+
TrippingTopologyTraverser.traverse(terminal1, dcSwitchesToOpen, dcTerminalsToDisconnect, traversedDcTerminals);
9898
} else if (dcNodeId.equals(terminal2.getDcNode().getId())) {
99-
TrippingTopologyTraverser.traverse(terminal2, terminalsToDisconnect, traversedTerminals);
99+
TrippingTopologyTraverser.traverse(terminal2, dcSwitchesToOpen, dcTerminalsToDisconnect, traversedDcTerminals);
100100
} else {
101101
throw new PowsyblException("DcNode '" + dcNodeId + "' not connected to " + equipmentType + " '" + id + "'");
102102
}
103103
} else {
104-
TrippingTopologyTraverser.traverse(terminal1, terminalsToDisconnect, traversedTerminals);
105-
TrippingTopologyTraverser.traverse(terminal2, terminalsToDisconnect, traversedTerminals);
104+
TrippingTopologyTraverser.traverse(terminal1, dcSwitchesToOpen, dcTerminalsToDisconnect, traversedDcTerminals);
105+
TrippingTopologyTraverser.traverse(terminal2, dcSwitchesToOpen, dcTerminalsToDisconnect, traversedDcTerminals);
106106
}
107107
}
108108
}

iidm/iidm-modification/src/main/java/com/powsybl/iidm/modification/tripping/DcGroundTripping.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ public String getName() {
2828
}
2929

3030
@Override
31-
public void traverseDc(Network network, Set<DcTerminal> terminalsToDisconnect, Set<DcTerminal> traversedDcTerminals) {
31+
public void traverseDc(Network network, Set<DcSwitch> dcSwitchesToOpen, Set<DcTerminal> dcTerminalsToDisconnect, Set<DcTerminal> traversedDcTerminals) {
3232
Objects.requireNonNull(network);
3333
DcGround dcGround = network.getDcGround(id);
3434
if (dcGround == null) {
3535
throw new PowsyblException("DcGround '" + id + "' not found");
3636
}
3737

3838
for (DcTerminal t : dcGround.getDcTerminals()) {
39-
TrippingTopologyTraverser.traverse(t, terminalsToDisconnect, traversedDcTerminals);
39+
TrippingTopologyTraverser.traverse(t, dcSwitchesToOpen, dcTerminalsToDisconnect, traversedDcTerminals);
4040
}
4141
}
4242
}

iidm/iidm-modification/src/main/java/com/powsybl/iidm/modification/tripping/DcLineTripping.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,12 @@ protected String getDcNodeId() {
4747
}
4848

4949
@Override
50-
public void traverseDc(Network network, Set<DcTerminal> terminalsToDisconnect, Set<DcTerminal> traversedTerminals) {
50+
public void traverseDc(Network network, Set<DcSwitch> dcSwitchesToOpen, Set<DcTerminal> dcTerminalsToDisconnect, Set<DcTerminal> traversedTerminals) {
5151
Objects.requireNonNull(network);
5252
DcLine dcLine = supplier.apply(network, id);
5353
if (dcLine == null) {
5454
throw new PowsyblException("DcLine '" + id + "' not found");
5555
}
56-
traverseDoubleSidedEquipment(dcNodeId, dcLine.getDcTerminal1(), dcLine.getDcTerminal2(), terminalsToDisconnect, traversedTerminals, dcLine.getType().name());
56+
traverseDoubleSidedEquipment(dcNodeId, dcLine.getDcTerminal1(), dcLine.getDcTerminal2(), dcSwitchesToOpen, dcTerminalsToDisconnect, traversedTerminals, dcLine.getType().name());
5757
}
5858
}

iidm/iidm-modification/src/main/java/com/powsybl/iidm/modification/tripping/DcNodeTripping.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
import com.powsybl.commons.PowsyblException;
1111
import com.powsybl.iidm.network.DcNode;
12+
import com.powsybl.iidm.network.DcSwitch;
1213
import com.powsybl.iidm.network.DcTerminal;
1314
import com.powsybl.iidm.network.Network;
1415

@@ -30,15 +31,15 @@ public String getName() {
3031
}
3132

3233
@Override
33-
public void traverseDc(Network network, Set<DcTerminal> terminalsToDisconnect, Set<DcTerminal> traversedDcTerminals) {
34+
public void traverseDc(Network network, Set<DcSwitch> dcSwitchesToOpen, Set<DcTerminal> dcTerminalsToDisconnect, Set<DcTerminal> traversedDcTerminals) {
3435
Objects.requireNonNull(network);
3536
DcNode dcNode = network.getDcNode(id);
3637
if (dcNode == null) {
3738
throw new PowsyblException("DcNode '" + id + "' not found");
3839
}
3940

4041
for (DcTerminal t : dcNode.getDcTerminals()) {
41-
TrippingTopologyTraverser.traverse(t, terminalsToDisconnect, traversedDcTerminals);
42+
TrippingTopologyTraverser.traverse(t, dcSwitchesToOpen, dcTerminalsToDisconnect, traversedDcTerminals);
4243
}
4344
}
4445
}

iidm/iidm-modification/src/main/java/com/powsybl/iidm/modification/tripping/Tripping.java

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@
88
package com.powsybl.iidm.modification.tripping;
99

1010
import com.powsybl.iidm.modification.NetworkModification;
11-
import com.powsybl.iidm.network.DcTerminal;
12-
import com.powsybl.iidm.network.Network;
13-
import com.powsybl.iidm.network.Switch;
14-
import com.powsybl.iidm.network.Terminal;
11+
import com.powsybl.iidm.network.*;
1512

1613
import java.util.Set;
1714

@@ -27,10 +24,10 @@ default void traverse(Network network, Set<Switch> switchesToOpen, Set<Terminal>
2724
traverse(network, switchesToOpen, terminalsToDisconnect, null);
2825
}
2926

30-
default void traverseDc(Network network, Set<DcTerminal> terminalsToDisconnect, Set<DcTerminal> traversedDcTerminals) {
27+
default void traverseDc(Network network, Set<DcSwitch> dcSwitchesToOpen, Set<DcTerminal> dcTerminalsToDisconnect, Set<DcTerminal> traversedDcTerminals) {
3128
}
3229

33-
default void traverseDc(Network network, Set<DcTerminal> terminalsToDisconnect) {
34-
traverseDc(network, terminalsToDisconnect, null);
30+
default void traverseDc(Network network, Set<DcSwitch> dcSwitchesToOpen, Set<DcTerminal> dcTerminalsToDisconnect) {
31+
traverseDc(network, dcSwitchesToOpen, dcTerminalsToDisconnect, null);
3532
}
3633
}

0 commit comments

Comments
 (0)