Skip to content

Commit b48cd79

Browse files
authored
Implement MoveVoltageLevelFeederBays modification (#87)
Signed-off-by: Rehili Ghazwa <[email protected]> Co-authored-by: Etienne LESOT <[email protected]>
1 parent 5da4279 commit b48cd79

14 files changed

+580
-12
lines changed

src/main/java/org/gridsuite/modification/ModificationType.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ public enum ModificationType {
6262
CREATE_COUPLING_DEVICE(PreloadingStrategy.NONE),
6363
CREATE_VOLTAGE_LEVEL_TOPOLOGY(PreloadingStrategy.NONE),
6464
LIMIT_SETS_TABULAR_MODIFICATION(PreloadingStrategy.COLLECTION),
65-
CREATE_VOLTAGE_LEVEL_SECTION(PreloadingStrategy.NONE);
65+
CREATE_VOLTAGE_LEVEL_SECTION(PreloadingStrategy.NONE),
66+
MOVE_VOLTAGE_LEVEL_FEEDER_BAYS(PreloadingStrategy.NONE);
6667

6768
private final PreloadingStrategy strategy;
6869

src/main/java/org/gridsuite/modification/NetworkModificationException.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,8 @@ public enum Type {
133133
MODIFY_VOLTAGE_LEVEL_TOPOLOGY_ERROR(HttpStatus.INTERNAL_SERVER_ERROR),
134134
CREATE_COUPLING_DEVICE_ERROR(HttpStatus.INTERNAL_SERVER_ERROR),
135135
CREATE_VOLTAGE_LEVEL_TOPOLOGY_ERROR(HttpStatus.INTERNAL_SERVER_ERROR),
136-
CREATE_VOLTAGE_LEVEL_SECTION_ERROR(HttpStatus.INTERNAL_SERVER_ERROR);
136+
CREATE_VOLTAGE_LEVEL_SECTION_ERROR(HttpStatus.INTERNAL_SERVER_ERROR),
137+
MOVE_VOLTAGE_LEVEL_FEEDER_BAYS_ERROR(HttpStatus.INTERNAL_SERVER_ERROR),;
137138

138139
public final HttpStatus status;
139140
private final String message;

src/main/java/org/gridsuite/modification/dto/ModificationInfos.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@
8383
@JsonSubTypes.Type(value = CreateVoltageLevelTopologyInfos.class),
8484
@JsonSubTypes.Type(value = LimitSetsTabularModificationInfos.class),
8585
@JsonSubTypes.Type(value = CreateVoltageLevelSectionInfos.class),
86+
@JsonSubTypes.Type(value = MoveVoltageLevelFeederBaysInfos.class),
8687
})
8788
@SuperBuilder
8889
@NoArgsConstructor
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
package org.gridsuite.modification.dto;
8+
9+
import com.powsybl.iidm.network.extensions.ConnectablePosition;
10+
import io.swagger.v3.oas.annotations.media.Schema;
11+
import lombok.Getter;
12+
import lombok.NoArgsConstructor;
13+
import lombok.ToString;
14+
import lombok.experimental.SuperBuilder;
15+
16+
/**
17+
* @author Etienne Lesot <etienne.lesot at rte-france.com>
18+
*/
19+
@SuperBuilder
20+
@NoArgsConstructor
21+
@Getter
22+
@ToString(callSuper = true)
23+
@Schema(description = "Move feeder bay")
24+
public class MoveFeederBayInfos {
25+
@Schema(description = "Equipment id")
26+
private String equipmentId;
27+
28+
@Schema(description = "busbar section id")
29+
private String busbarSectionId;
30+
31+
@Schema(description = "connection side")
32+
private String connectionSide;
33+
34+
@Schema(description = "connection position")
35+
private Integer connectionPosition;
36+
37+
@Schema(description = "connection name")
38+
private String connectionName;
39+
40+
@Schema(description = "connection direction")
41+
private ConnectablePosition.Direction connectionDirection;
42+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
package org.gridsuite.modification.dto;
8+
9+
import com.fasterxml.jackson.annotation.JsonTypeName;
10+
import com.powsybl.commons.report.ReportNode;
11+
import io.swagger.v3.oas.annotations.media.Schema;
12+
import lombok.Getter;
13+
import lombok.NoArgsConstructor;
14+
import lombok.Setter;
15+
import lombok.experimental.SuperBuilder;
16+
import org.gridsuite.modification.dto.annotation.ModificationErrorTypeName;
17+
import org.gridsuite.modification.modifications.AbstractModification;
18+
import org.gridsuite.modification.modifications.MoveVoltageLevelFeederBays;
19+
20+
import java.util.List;
21+
import java.util.Map;
22+
23+
/**
24+
* @author Etienne Lesot <etienne.lesot at rte-france.com>
25+
*/
26+
@SuperBuilder
27+
@NoArgsConstructor
28+
@Getter
29+
@Setter
30+
@Schema(description = "Move voltage level feeder bays")
31+
@JsonTypeName("MOVE_VOLTAGE_LEVEL_FEEDER_BAYS")
32+
@ModificationErrorTypeName("MOVE_VOLTAGE_LEVEL_FEEDER_BAYS_ERROR")
33+
public class MoveVoltageLevelFeederBaysInfos extends ModificationInfos {
34+
35+
@Schema(description = "Voltage level id")
36+
private String voltageLevelId;
37+
38+
@Schema(description = "Feeder bays list")
39+
private List<MoveFeederBayInfos> feederBays;
40+
41+
@Override
42+
public AbstractModification toModification() {
43+
return new MoveVoltageLevelFeederBays(this);
44+
}
45+
46+
@Override
47+
public ReportNode createSubReportNode(ReportNode reportNode) {
48+
return reportNode.newReportNode()
49+
.withMessageTemplate("network.modification.MOVE_VOLTAGE_LEVEL_FEEDER_BAYS")
50+
.withUntypedValue("voltageLevelId", getVoltageLevelId())
51+
.add();
52+
}
53+
54+
@Override
55+
public Map<String, String> getMapMessageValues() {
56+
return Map.of("voltageLevelId", getVoltageLevelId());
57+
}
58+
}

src/main/java/org/gridsuite/modification/modifications/AbstractBranchModification.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ private ReportNode modifyBranchConnectivityAttributes(BranchModificationInfos br
595595

596596
private void modifyBranchVoltageLevelBusOrBusBarSectionAttributesSide1(BranchModificationInfos modificationInfos,
597597
Branch<?> branch, ReportNode subReportNode) {
598-
ModificationUtils.getInstance().modifyVoltageLevelBusOrBusBarSectionAttributes(
598+
ModificationUtils.getInstance().moveFeederBay(
599599
(Connectable<?>) branch, branch.getTerminal1(),
600600
modificationInfos.getVoltageLevelId1(),
601601
modificationInfos.getBusOrBusbarSectionId1(),
@@ -605,7 +605,7 @@ private void modifyBranchVoltageLevelBusOrBusBarSectionAttributesSide1(BranchMod
605605

606606
private void modifyBranchVoltageLevelBusOrBusBarSectionAttributesSide2(BranchModificationInfos modificationInfos,
607607
Branch<?> branch, ReportNode subReportNode) {
608-
ModificationUtils.getInstance().modifyVoltageLevelBusOrBusBarSectionAttributes(
608+
ModificationUtils.getInstance().moveFeederBay(
609609
(Connectable<?>) branch, branch.getTerminal2(),
610610
modificationInfos.getVoltageLevelId2(),
611611
modificationInfos.getBusOrBusbarSectionId2(),

src/main/java/org/gridsuite/modification/modifications/BatteryModification.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public static void modifyBatterySetpointsAttributes(AttributeModification<Double
125125

126126
private void modifyBatteryVoltageLevelBusOrBusBarSectionAttributes(BatteryModificationInfos modificationInfos,
127127
Battery battery, ReportNode subReportNode) {
128-
ModificationUtils.getInstance().modifyVoltageLevelBusOrBusBarSectionAttributes(
128+
ModificationUtils.getInstance().moveFeederBay(
129129
battery, battery.getTerminal(),
130130
modificationInfos.getVoltageLevelId(),
131131
modificationInfos.getBusOrBusbarSectionId(),

src/main/java/org/gridsuite/modification/modifications/GeneratorModification.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ private void modifyGeneratorLimitsAttributes(GeneratorModificationInfos modifica
504504

505505
private void modifyGeneratorVoltageLevelBusOrBusBarSectionAttributes(GeneratorModificationInfos modificationInfos,
506506
Generator generator, ReportNode subReportNode) {
507-
ModificationUtils.getInstance().modifyVoltageLevelBusOrBusBarSectionAttributes(
507+
ModificationUtils.getInstance().moveFeederBay(
508508
generator, generator.getTerminal(),
509509
modificationInfos.getVoltageLevelId(),
510510
modificationInfos.getBusOrBusbarSectionId(),

src/main/java/org/gridsuite/modification/modifications/LoadModification.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ public static void modifyP0(Load load, AttributeModification<Double> p0, ReportN
8282

8383
private void modifyLoadVoltageLevelBusOrBusBarSectionAttributes(LoadModificationInfos modificationInfos,
8484
Load load, ReportNode subReportNode) {
85-
ModificationUtils.getInstance().modifyVoltageLevelBusOrBusBarSectionAttributes(
85+
ModificationUtils.getInstance().moveFeederBay(
8686
load, load.getTerminal(),
8787
modificationInfos.getVoltageLevelId(),
8888
modificationInfos.getBusOrBusbarSectionId(),
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
/**
2+
* Copyright (c) 2025, RTE (http://www.rte-france.com)
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
6+
*/
7+
package org.gridsuite.modification.modifications;
8+
9+
import com.powsybl.commons.report.ReportNode;
10+
import com.powsybl.iidm.network.*;
11+
import com.powsybl.iidm.network.extensions.ConnectablePosition;
12+
import com.powsybl.iidm.network.extensions.ConnectablePositionAdder;
13+
import org.gridsuite.modification.ModificationType;
14+
import org.gridsuite.modification.NetworkModificationException;
15+
import org.gridsuite.modification.dto.*;
16+
import org.gridsuite.modification.utils.ModificationUtils;
17+
18+
import static org.gridsuite.modification.NetworkModificationException.Type.MOVE_VOLTAGE_LEVEL_FEEDER_BAYS_ERROR;
19+
20+
/**
21+
* @author Etienne Lesot <etienne.lesot at rte-france.com>
22+
*/
23+
public class MoveVoltageLevelFeederBays extends AbstractModification {
24+
private static final String VOLTAGE_LEVEL_NOT_FOUND = "Voltage level %s is not found";
25+
private static final String CONNECTABLE_NOT_FOUND = "Connectable %s not found";
26+
private static final String BUSBAR_NOT_FOUND = "Bus or busbar section %s where connectable %s is supposed to be is not found in voltage level %s";
27+
private static final String UNSUPPORTED_CONNECTABLE = "MoveVoltageLevelFeederBays is not implemented for %s";
28+
private static final String INVALID_CONNECTION_SIDE = "Invalid connection side: %s for branch %s";
29+
30+
private final MoveVoltageLevelFeederBaysInfos modificationInfos;
31+
32+
public MoveVoltageLevelFeederBays(MoveVoltageLevelFeederBaysInfos modificationInfos) {
33+
this.modificationInfos = modificationInfos;
34+
}
35+
36+
@Override
37+
public void check(Network network) throws NetworkModificationException {
38+
VoltageLevel voltageLevel = getVoltageLevelOrThrow(network, modificationInfos.getVoltageLevelId());
39+
for (MoveFeederBayInfos info : modificationInfos.getFeederBays()) {
40+
checkBusOrBusbarSectionExist(voltageLevel, info);
41+
checkConnectable(network, info);
42+
}
43+
}
44+
45+
private VoltageLevel getVoltageLevelOrThrow(Network network, String voltageLevelId) {
46+
VoltageLevel voltageLevel = network.getVoltageLevel(voltageLevelId);
47+
if (voltageLevel == null) {
48+
throw new NetworkModificationException(MOVE_VOLTAGE_LEVEL_FEEDER_BAYS_ERROR, String.format(VOLTAGE_LEVEL_NOT_FOUND, voltageLevelId));
49+
}
50+
return voltageLevel;
51+
}
52+
53+
private void checkBusOrBusbarSectionExist(VoltageLevel voltageLevel, MoveFeederBayInfos info) {
54+
boolean busOrBusbarSectionExists = voltageLevel.getTopologyKind().equals(TopologyKind.NODE_BREAKER)
55+
? voltageLevel.getNodeBreakerView().getBusbarSection(info.getBusbarSectionId()) != null
56+
: voltageLevel.getBusBreakerView().getBus(info.getBusbarSectionId()) != null;
57+
if (!busOrBusbarSectionExists) {
58+
throw new NetworkModificationException(MOVE_VOLTAGE_LEVEL_FEEDER_BAYS_ERROR, String.format(BUSBAR_NOT_FOUND,
59+
info.getBusbarSectionId(), info.getEquipmentId(), modificationInfos.getVoltageLevelId()));
60+
}
61+
}
62+
63+
private void checkConnectable(Network network, MoveFeederBayInfos info) {
64+
Connectable<?> connectable = network.getConnectable(info.getEquipmentId());
65+
if (connectable == null) {
66+
throw new NetworkModificationException(MOVE_VOLTAGE_LEVEL_FEEDER_BAYS_ERROR, String.format(CONNECTABLE_NOT_FOUND, info.getEquipmentId()));
67+
}
68+
if (connectable instanceof BusbarSection || connectable instanceof ThreeWindingsTransformer) {
69+
throw new NetworkModificationException(MOVE_VOLTAGE_LEVEL_FEEDER_BAYS_ERROR, String.format(UNSUPPORTED_CONNECTABLE, connectable.getClass()));
70+
}
71+
}
72+
73+
@Override
74+
public void apply(Network network, ReportNode subReportNode) {
75+
for (MoveFeederBayInfos info : modificationInfos.getFeederBays()) {
76+
Connectable<?> connectable = network.getConnectable(info.getEquipmentId());
77+
modifyConnectablePosition(network, connectable, info, subReportNode);
78+
}
79+
}
80+
81+
@Override
82+
public String getName() {
83+
return ModificationType.MOVE_VOLTAGE_LEVEL_FEEDER_BAYS.name();
84+
}
85+
86+
private void modifyConnectablePosition(Network network, Connectable<?> connectable, MoveFeederBayInfos newConnectablePositionInfos, ReportNode subReportNode) {
87+
ConnectablePosition<?> oldConnectablePosition = (ConnectablePosition<?>) connectable.getExtension(ConnectablePosition.class);
88+
ConnectablePositionAdder<?> connectablePositionAdder = connectable.newExtension(ConnectablePositionAdder.class);
89+
90+
switch (connectable) {
91+
case Injection<?> injection -> {
92+
InjectionModificationInfos injectionModificationInfos = buildInjectionModificationInfos(newConnectablePositionInfos);
93+
ModificationUtils.getInstance().modifyInjectionConnectivityAttributes(oldConnectablePosition, connectablePositionAdder, injection, injectionModificationInfos, subReportNode);
94+
}
95+
case Branch<?> branch -> {
96+
BranchModificationInfos branchModificationInfos = buildBranchModificationInfos(newConnectablePositionInfos);
97+
ModificationUtils.getInstance().modifyBranchConnectivityAttributes(oldConnectablePosition, connectablePositionAdder, branch, branchModificationInfos, subReportNode);
98+
}
99+
default -> throw new NetworkModificationException(MOVE_VOLTAGE_LEVEL_FEEDER_BAYS_ERROR, String.format(UNSUPPORTED_CONNECTABLE, connectable.getClass()));
100+
}
101+
moveFeederBay(network, connectable, newConnectablePositionInfos, subReportNode);
102+
}
103+
104+
private InjectionModificationInfos buildInjectionModificationInfos(MoveFeederBayInfos newConnectablePositionInfos) {
105+
InjectionModificationInfos injectionInfos = new InjectionModificationInfos();
106+
injectionInfos.setEquipmentId(newConnectablePositionInfos.getEquipmentId());
107+
setConnectionAttributes(injectionInfos::setConnectionPosition,
108+
injectionInfos::setConnectionName,
109+
injectionInfos::setConnectionDirection,
110+
newConnectablePositionInfos);
111+
return injectionInfos;
112+
}
113+
114+
private BranchModificationInfos buildBranchModificationInfos(MoveFeederBayInfos info) {
115+
BranchModificationInfos branchInfos = new BranchModificationInfos();
116+
branchInfos.setEquipmentId(info.getEquipmentId());
117+
ThreeSides connectionSide = ThreeSides.valueOf(info.getConnectionSide());
118+
switch (connectionSide) {
119+
case ONE -> setConnectionAttributes(branchInfos::setConnectionPosition1,
120+
branchInfos::setConnectionName1,
121+
branchInfos::setConnectionDirection1,
122+
info);
123+
case TWO -> setConnectionAttributes(branchInfos::setConnectionPosition2,
124+
branchInfos::setConnectionName2,
125+
branchInfos::setConnectionDirection2,
126+
info);
127+
default -> throw new NetworkModificationException(MOVE_VOLTAGE_LEVEL_FEEDER_BAYS_ERROR, String.format(INVALID_CONNECTION_SIDE, info.getConnectionSide(), branchInfos.getEquipmentId()));
128+
}
129+
return branchInfos;
130+
}
131+
132+
private void setConnectionAttributes(java.util.function.Consumer<AttributeModification<Integer>> setPosition,
133+
java.util.function.Consumer<AttributeModification<String>> setName,
134+
java.util.function.Consumer<AttributeModification<ConnectablePosition.Direction>> setDirection,
135+
MoveFeederBayInfos info) {
136+
setPosition.accept(new AttributeModification<>(info.getConnectionPosition(), OperationType.SET));
137+
setName.accept(new AttributeModification<>(info.getConnectionName(), OperationType.SET));
138+
setDirection.accept(new AttributeModification<>(info.getConnectionDirection(), OperationType.SET));
139+
}
140+
141+
private void moveFeederBay(Network network, Connectable<?> connectable, MoveFeederBayInfos info, ReportNode subReportNode) {
142+
Terminal terminal = getTerminal(network, info);
143+
String currentBusbarId = ModificationUtils.getInstance().getBusOrBusbarSection(terminal);
144+
String targetBusbarId = info.getBusbarSectionId();
145+
if (!currentBusbarId.equals(targetBusbarId)) {
146+
ModificationUtils.getInstance().moveFeederBay(
147+
connectable, terminal,
148+
new AttributeModification<>(modificationInfos.getVoltageLevelId(), OperationType.SET),
149+
new AttributeModification<>(targetBusbarId, OperationType.SET),
150+
subReportNode);
151+
}
152+
}
153+
154+
public Terminal getTerminal(Network network, MoveFeederBayInfos info) {
155+
Connectable<?> connectable = network.getConnectable(info.getEquipmentId());
156+
return switch (connectable) {
157+
case Injection<?> injection -> injection.getTerminal();
158+
case Branch<?> branch -> {
159+
try {
160+
TwoSides side = TwoSides.valueOf(info.getConnectionSide());
161+
yield branch.getTerminal(side);
162+
} catch (IllegalArgumentException e) {
163+
throw new NetworkModificationException(MOVE_VOLTAGE_LEVEL_FEEDER_BAYS_ERROR,
164+
String.format(INVALID_CONNECTION_SIDE, info.getConnectionSide(), branch.getId()));
165+
}
166+
}
167+
default -> throw new NetworkModificationException(MOVE_VOLTAGE_LEVEL_FEEDER_BAYS_ERROR, String.format(UNSUPPORTED_CONNECTABLE, connectable.getClass()));
168+
};
169+
}
170+
}

0 commit comments

Comments
 (0)