6
6
*/
7
7
package org .gridsuite .network .map .dto .definition .extension ;
8
8
9
- import com .powsybl .iidm .network .IdentifiableType ;
10
- import com .powsybl .iidm .network .SwitchKind ;
11
- import com .powsybl .iidm .network .Terminal ;
12
- import com .powsybl .iidm .network .VoltageLevel ;
9
+ import com .powsybl .iidm .network .*;
13
10
14
11
import java .util .*;
15
12
16
13
/**
17
14
* @author Slimane Amar <slimane.amar at rte-france.com>
18
15
*/
16
+ // TODO : to remove when this class is available in network-store
19
17
public final class BusbarSectionFinderTraverser {
20
18
21
19
/**
@@ -32,10 +30,10 @@ private BusbarSectionFinderTraverser() {
32
30
* @param terminal the starting terminal
33
31
* @return the best busbar result according to selection criteria, or null if none found
34
32
*/
35
- public static BusbarResult findBestBusbar (Terminal terminal ) {
33
+ public static BusbarSectionResult findBestBusbar (Terminal terminal ) {
36
34
VoltageLevel .NodeBreakerView view = terminal .getVoltageLevel ().getNodeBreakerView ();
37
35
int startNode = terminal .getNodeBreakerView ().getNode ();
38
- List <BusbarResult > allResults = searchAllBusbars (view , startNode );
36
+ List <BusbarSectionResult > allResults = searchAllBusbars (view , startNode );
39
37
if (allResults .isEmpty ()) {
40
38
return null ;
41
39
}
@@ -51,27 +49,23 @@ public static BusbarResult findBestBusbar(Terminal terminal) {
51
49
* @param results list of all found busbar results
52
50
* @return the best busbar according to selection criteria
53
51
*/
54
- private static BusbarResult selectBestBusbar (List <BusbarResult > results ) {
52
+ private static BusbarSectionResult selectBestBusbar (List <BusbarSectionResult > results ) {
55
53
// Priority 1: Search for busbar with closed last switch
56
- List <BusbarResult > withClosedSwitch = results .stream ().filter (r -> r .lastSwitch () != null && !r .lastSwitch ().isOpen ()).toList ();
54
+ List <BusbarSectionResult > withClosedSwitch = results .stream ().filter (r -> r .lastSwitch () != null && !r .lastSwitch ().isOpen ()).toList ();
57
55
if (!withClosedSwitch .isEmpty ()) {
58
- return withClosedSwitch .stream ().min (Comparator .comparingInt (BusbarResult ::depth )
59
- .thenComparingInt (BusbarResult ::switchesBeforeLast ))
60
- .get ();
56
+ return withClosedSwitch .stream ().min (Comparator .comparingInt (BusbarSectionResult ::depth ).thenComparingInt (BusbarSectionResult ::switchesBeforeLast )).orElse (null );
61
57
}
62
58
63
59
// Priority 2: Search for busbar with open last switch
64
- List <BusbarResult > withOpenSwitch = results .stream ().filter (r -> r .lastSwitch () != null && r .lastSwitch ().isOpen ()).toList ();
60
+ List <BusbarSectionResult > withOpenSwitch = results .stream ().filter (r -> r .lastSwitch () != null && r .lastSwitch ().isOpen ()).toList ();
65
61
if (!withOpenSwitch .isEmpty ()) {
66
- return withOpenSwitch .stream ().min (Comparator .comparingInt (BusbarResult ::depth )
67
- .thenComparingInt (BusbarResult ::switchesBeforeLast ))
68
- .get ();
62
+ return withOpenSwitch .stream ().min (Comparator .comparingInt (BusbarSectionResult ::depth ).thenComparingInt (BusbarSectionResult ::switchesBeforeLast )).orElse (null );
69
63
}
70
64
71
- // Priority 3: Busbars without switch ( direct connection)
72
- List <BusbarResult > withoutSwitch = results .stream ().filter (r -> r .lastSwitch () == null ).toList ();
65
+ // Priority 3: Busbars without switch direct connection
66
+ List <BusbarSectionResult > withoutSwitch = results .stream ().filter (r -> r .lastSwitch () == null ).toList ();
73
67
if (!withoutSwitch .isEmpty ()) {
74
- return withoutSwitch .stream ().min (Comparator .comparingInt (BusbarResult ::depth )).get ( );
68
+ return withoutSwitch .stream ().min (Comparator .comparingInt (BusbarSectionResult ::depth )).orElse ( null );
75
69
}
76
70
77
71
// Fallback: select first busbar
@@ -86,50 +80,77 @@ private static BusbarResult selectBestBusbar(List<BusbarResult> results) {
86
80
* @param startNode the starting node index
87
81
* @return list of all busbar results found
88
82
*/
89
- private static List <BusbarResult > searchAllBusbars (VoltageLevel .NodeBreakerView view , int startNode ) {
90
- List <BusbarResult > results = new ArrayList <>();
83
+ private static List <BusbarSectionResult > searchAllBusbars (VoltageLevel .NodeBreakerView view , int startNode ) {
84
+ List <BusbarSectionResult > results = new ArrayList <>();
91
85
Set <Integer > visited = new HashSet <>();
92
86
Queue <NodePath > queue = new LinkedList <>();
93
87
queue .offer (new NodePath (startNode , new ArrayList <>(), null ));
94
88
while (!queue .isEmpty ()) {
95
- NodePath current = queue .poll ();
96
- if (visited . contains ( current .node ())) {
89
+ NodePath currentNodePath = queue .poll ();
90
+ if (! hasNotBeenVisited ( currentNodePath .node (), visited )) {
97
91
continue ;
98
92
}
99
- visited .add (current .node ());
100
- // Check if current node is a busbar section
101
- Optional <Terminal > nodeTerminal = view .getOptionalTerminal (current .node ());
102
- if (nodeTerminal .isPresent ()) {
103
- Terminal term = nodeTerminal .get ();
104
- if (term .getConnectable ().getType () == IdentifiableType .BUSBAR_SECTION ) {
105
- String busbarId = term .getConnectable ().getId ();
106
- int depth = current .pathSwitches ().size ();
107
- SwitchInfo lastSwitch = current .lastSwitch ();
108
- // Calculate number of switches BEFORE the last one
109
- int switchesBeforeLast = lastSwitch != null ? (depth - 1 ) : 0 ;
110
- results .add (new BusbarResult (busbarId , depth , switchesBeforeLast , lastSwitch ));
111
- continue ; // Don't explore beyond busbar
112
- }
93
+ visited .add (currentNodePath .node ());
94
+ Optional <BusbarSectionResult > busbarSectionResult = tryCreateBusbarResult (view , currentNodePath );
95
+ if (busbarSectionResult .isPresent ()) {
96
+ results .add (busbarSectionResult .get ());
97
+ } else {
98
+ exploreAdjacentNodes (view , currentNodePath , visited , queue );
113
99
}
114
-
115
- // Explore adjacent nodes through switches
116
- view .getSwitchStream ().forEach (sw -> {
117
- int node1 = view .getNode1 (sw .getId ());
118
- int node2 = view .getNode2 (sw .getId ());
119
- if (node1 == current .node () || node2 == current .node ()) {
120
- int nextNode = (node1 == current .node ()) ? node2 : node1 ;
121
- if (!visited .contains (nextNode )) {
122
- List <SwitchInfo > newPathSwitches = new ArrayList <>(current .pathSwitches ());
123
- SwitchInfo switchInfo = new SwitchInfo (sw .getId (), sw .getKind (), sw .isOpen (), node1 , node2 );
124
- newPathSwitches .add (switchInfo );
125
- queue .offer (new NodePath (nextNode , newPathSwitches , switchInfo ));
126
- }
127
- }
128
- });
129
100
}
130
101
return results ;
131
102
}
132
103
104
+ private static boolean hasNotBeenVisited (int node , Set <Integer > visited ) {
105
+ return !visited .contains (node );
106
+ }
107
+
108
+ private static Optional <BusbarSectionResult > tryCreateBusbarResult (VoltageLevel .NodeBreakerView view , NodePath currentNodePath ) {
109
+ Optional <Terminal > nodeTerminal = view .getOptionalTerminal (currentNodePath .node ());
110
+ if (nodeTerminal .isEmpty ()) {
111
+ return Optional .empty ();
112
+ }
113
+ Terminal term = nodeTerminal .get ();
114
+ // Check if current node is a busbar section
115
+ if (term .getConnectable ().getType () == IdentifiableType .BUSBAR_SECTION ) {
116
+ String busbarSectionId = term .getConnectable ().getId ();
117
+ int depth = currentNodePath .pathSwitches ().size ();
118
+ SwitchInfo lastSwitch = currentNodePath .lastSwitch ();
119
+ int switchesBeforeLast = lastSwitch != null ? (depth - 1 ) : 0 ;
120
+ return Optional .of (new BusbarSectionResult (busbarSectionId , depth , switchesBeforeLast , lastSwitch ));
121
+ }
122
+ return Optional .empty ();
123
+ }
124
+
125
+ private static void exploreAdjacentNodes (VoltageLevel .NodeBreakerView view , NodePath currentNodePath , Set <Integer > visited , Queue <NodePath > queue ) {
126
+ view .getSwitchStream ().forEach (sw -> {
127
+ int node1 = view .getNode1 (sw .getId ());
128
+ int node2 = view .getNode2 (sw .getId ());
129
+ Optional <Integer > nextNode = getNextNodeIfAdjacent (currentNodePath .node (), node1 , node2 );
130
+ if (nextNode .isPresent () && !visited .contains (nextNode .get ())) {
131
+ NodePath newPath = createNodePath (currentNodePath , sw , node1 , node2 , nextNode .get ());
132
+ queue .offer (newPath );
133
+ }
134
+ });
135
+ }
136
+
137
+ private static Optional <Integer > getNextNodeIfAdjacent (int currentNode , int node1 , int node2 ) {
138
+ if (node1 == currentNode ) {
139
+ return Optional .of (node2 );
140
+ }
141
+ if (node2 == currentNode ) {
142
+ return Optional .of (node1 );
143
+ }
144
+ return Optional .empty ();
145
+ }
146
+
147
+ private static NodePath createNodePath (NodePath currentNodePath , Switch sw , int node1 , int node2 , int nextNode ) {
148
+ List <SwitchInfo > newPathSwitches = new ArrayList <>(currentNodePath .pathSwitches ());
149
+ SwitchInfo switchInfo = new SwitchInfo (sw .getId (), sw .getKind (), sw .isOpen (), node1 , node2 );
150
+ newPathSwitches .add (switchInfo );
151
+ return new NodePath (nextNode , newPathSwitches , switchInfo );
152
+ }
153
+
133
154
/**
134
155
* Internal record to track the path during graph traversal.
135
156
*/
@@ -143,16 +164,16 @@ public record SwitchInfo(String id, SwitchKind kind, boolean isOpen, int node1,
143
164
/**
144
165
* Record containing the result of a busbar search with selection metadata.
145
166
*/
146
- public record BusbarResult (String busbarId , int depth , int switchesBeforeLast , SwitchInfo lastSwitch ) { }
167
+ public record BusbarSectionResult (String busbarSectionId , int depth , int switchesBeforeLast , SwitchInfo lastSwitch ) { }
147
168
148
169
/**
149
170
* Convenience method to get only the busbar ID.
150
171
*
151
172
* @param terminal the starting terminal
152
173
* @return the busbar ID or null if none found
153
174
*/
154
- public static String findBusbarId (Terminal terminal ) {
155
- BusbarResult result = findBestBusbar (terminal );
156
- return result != null ? result .busbarId () : null ;
175
+ public static String findBusbarSectionId (Terminal terminal ) {
176
+ BusbarSectionResult result = findBestBusbar (terminal );
177
+ return result != null ? result .busbarSectionId () : null ;
157
178
}
158
179
}
0 commit comments