Skip to content

Commit

Permalink
Fix remove voltage level (#3280)
Browse files Browse the repository at this point in the history
* Add failing unit test
* Remove branches (except TieLines) before connectables
* Fix RemoveFeederBay
* Handle tielines

Signed-off-by: Florian Dupuy <[email protected]>
  • Loading branch information
flo-dup authored Jan 22, 2025
1 parent 62a1afc commit 2e3edfa
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,11 @@ private void searchConnectables(VoltageLevel.NodeBreakerView nbv, Graph<Integer,
*/
private void removeAllSwitchesAndInternalConnections(VoltageLevel.NodeBreakerView nbv, Graph<Integer, Object> graph,
int originNode, Object edge, ReportNode reportNode) {
// in case of loops inside the traversed bay, the edge might have been already removed
if (!graph.containsEdge(edge)) {
return;
}

Integer oppositeNode = getOppositeNode(graph, originNode, edge);
removeSwitchOrInternalConnection(nbv, graph, edge, reportNode);
if (!isBusbarSection(nbv, oppositeNode)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@
import org.slf4j.LoggerFactory;

import java.util.Objects;
import java.util.function.Consumer;

import static com.powsybl.iidm.modification.util.ModificationReports.*;

/**
* Removes a voltage level and the feeder bays connected to that voltage level. Note that dangling lines connected to
* this voltage level (hence paired) are not removed but unpaired.
* @author Etienne Homer {@literal <etienne.homer at rte-france.com>}
*/
public class RemoveVoltageLevel extends AbstractNetworkModification {
Expand Down Expand Up @@ -55,15 +58,27 @@ public void apply(Network network, NamingStrategy namingStrategy, boolean throwE
}
});

voltageLevel.getDanglingLines().forEach(dl ->
dl.getTieLine().ifPresent(tieLine -> {
String tlId = tieLine.getId();
String pairingKey = tieLine.getPairingKey();
tieLine.remove();
removedTieLineReport(reportNode, tlId, pairingKey);
LOGGER.info("Tie line {} removed", tlId);
})
);

Consumer<String> removeConnectableFeederBay = id -> new RemoveFeederBayBuilder().withConnectableId(id).build()
.apply(network, throwException, computationManager, reportNode);
voltageLevel.getLines().forEach(line -> removeConnectableFeederBay.accept(line.getId()));
voltageLevel.getTwoWindingsTransformers().forEach(transformer -> removeConnectableFeederBay.accept(transformer.getId()));
voltageLevel.getThreeWindingsTransformers().forEach(transformer -> removeConnectableFeederBay.accept(transformer.getId()));

voltageLevel.getConnectables().forEach(connectable -> {
if (connectable instanceof Injection) {
String connectableId = connectable.getId();
connectable.remove();
removedConnectableReport(reportNode, connectableId);
LOGGER.info("Connectable {} removed", connectableId);
} else {
new RemoveFeederBayBuilder().withConnectableId(connectable.getId()).build().apply(network, throwException, computationManager, reportNode);
}
String connectableId = connectable.getId();
connectable.remove();
removedConnectableReport(reportNode, connectableId);
LOGGER.info("Connectable {} removed", connectableId);
});

voltageLevel.remove();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public final class ModificationReports {
private static final String THREE_WINDINGS_TRANSFORMER_ID = "threeWindingsTransformerId";
private static final String EXTENSIONS = "extensions";
public static final String POSITION_ORDER = "positionOrder";
public static final String TIE_LINE_ID = "tieLineId";

// INFO
public static void createdConnectable(ReportNode reportNode, Connectable<?> connectable) {
Expand Down Expand Up @@ -62,10 +63,19 @@ public static void removedLineReport(ReportNode reportNode, String lineId) {
.add();
}

public static void removedTieLineReport(ReportNode reportNode, String tieLineId, String pairingKey) {
reportNode.newReportNode()
.withMessageTemplate("removedTieLine", "Removed tie line ${tieLineId} with pairing key ${pairingKey}")
.withTypedValue(TIE_LINE_ID, tieLineId, TypedValue.ID)
.withUntypedValue("pairingKey", pairingKey == null ? "" : pairingKey)
.withSeverity(TypedValue.INFO_SEVERITY)
.add();
}

public static void removedTieLineAndAssociatedDanglingLines(ReportNode reportNode, String tieLineId, String danglingLineId1, String danglingLineId2, String pairingKey) {
reportNode.newReportNode()
.withMessageTemplate("removedTieLineAndAssociatedDanglingLines", "Removed tie line ${tieLineId} and associated dangling lines ${danglingLineId1} and ${danglingLineId2} with pairing key ${pairingKey}")
.withUntypedValue("tieLineId", tieLineId)
.withTypedValue(TIE_LINE_ID, tieLineId, TypedValue.ID)
.withUntypedValue("danglingLineId1", danglingLineId1)
.withUntypedValue("danglingLineId2", danglingLineId2)
.withUntypedValue("pairingKey", pairingKey == null ? "" : pairingKey)
Expand Down Expand Up @@ -355,7 +365,7 @@ public static void lostTieLineExtensions(ReportNode reportNode, String extension
reportNode.newReportNode()
.withMessageTemplate("lostTieLineExtensions", "Extension [${extensions}] of tie line ${tieLineId} will be lost")
.withUntypedValue(EXTENSIONS, extensions)
.withUntypedValue("tieLineId", tieLineId)
.withTypedValue(TIE_LINE_ID, tieLineId, TypedValue.ID)
.withSeverity(TypedValue.WARN_SEVERITY)
.add();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@
import com.powsybl.iidm.modification.AbstractNetworkModification;
import com.powsybl.iidm.modification.NetworkModification;
import com.powsybl.iidm.modification.NetworkModificationImpact;
import com.powsybl.iidm.network.DefaultNetworkListener;
import com.powsybl.iidm.network.Identifiable;
import com.powsybl.iidm.network.Network;
import com.powsybl.iidm.network.*;
import com.powsybl.iidm.network.test.FourSubstationsNodeBreakerFactory;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -54,6 +52,44 @@ public void afterRemoval(String id) {
});
}

@Test
void testLoops() {
Network network = Network.create("test", "test");
var s = network.newSubstation().setId("s").add();

// First voltage level (which will be removed):
// two busbars linked with a coupler, two lines, one diamond-shaped cell (two breakers in parallel)
var vl1 = s.newVoltageLevel().setId("vl1").setTopologyKind(TopologyKind.NODE_BREAKER).setNominalV(225).add();
vl1.getNodeBreakerView().newBusbarSection().setId("bbs1").setNode(0).add();
vl1.getNodeBreakerView().newBusbarSection().setId("bbs2").setNode(1).add();
vl1.getNodeBreakerView().newSwitch().setId("Coupler").setNode1(0).setNode2(1).setKind(SwitchKind.BREAKER).add();
vl1.getNodeBreakerView().newSwitch().setId("d_l1_bbs1").setNode1(0).setNode2(2).setKind(SwitchKind.DISCONNECTOR).add();
vl1.getNodeBreakerView().newSwitch().setId("d_l1_bbs2").setNode1(1).setNode2(2).setKind(SwitchKind.DISCONNECTOR).add();
vl1.getNodeBreakerView().newSwitch().setId("d_l2_bbs1").setNode1(0).setNode2(3).setKind(SwitchKind.DISCONNECTOR).add();
vl1.getNodeBreakerView().newSwitch().setId("d_l2_bbs2").setNode1(1).setNode2(3).setKind(SwitchKind.DISCONNECTOR).add();
vl1.getNodeBreakerView().newSwitch().setId("b_l2_bbs2_A").setNode1(3).setNode2(4).setKind(SwitchKind.BREAKER).setOpen(true).add();
vl1.getNodeBreakerView().newSwitch().setId("b_l2_bbs2_B").setNode1(3).setNode2(4).setKind(SwitchKind.BREAKER).setOpen(false).add();

// Second voltage level, only there to host the lines
var vl2 = s.newVoltageLevel().setId("vl2").setTopologyKind(TopologyKind.NODE_BREAKER).setNominalV(225).add();
vl2.getNodeBreakerView().newBusbarSection().setId("bbs").setNode(0).add();
vl2.getNodeBreakerView().newInternalConnection().setNode1(0).setNode2(1).add();
vl2.getNodeBreakerView().newInternalConnection().setNode1(0).setNode2(2).add();

// "Parallel lines" between voltage levels: a tie line and a line
DanglingLine dl1 = vl1.newDanglingLine().setId("DL1").setNode(2).setP0(0.0).setQ0(0.0).setR(1.5).setX(13.0).setG(0.0).setB(1e-6).add();
DanglingLine dl2 = vl2.newDanglingLine().setId("DL2").setNode(1).setP0(0.0).setQ0(0.0).setR(1.5).setX(13.0).setG(0.0).setB(1e-6).add();
network.newTieLine().setId("TL").setDanglingLine1(dl1.getId()).setDanglingLine2(dl2.getId()).add();
network.newLine().setId("line").setVoltageLevel1(vl1.getId()).setVoltageLevel2(vl2.getId()).setNode1(4).setNode2(2)
.setR(0.01).setX(20.0).setG1(0.0).setB1(0.0).setG2(0.0).setB2(0.0).add();
addListener(network);

new RemoveVoltageLevelBuilder().withVoltageLevelId(vl1.getId()).build().apply(network);

assertEquals(Set.of("bbs1", "bbs2", "Coupler", "b_l2_bbs2_B", "b_l2_bbs2_A", "d_l2_bbs2", "vl1", "d_l2_bbs1", "d_l1_bbs2", "line", "TL", "DL1", "d_l1_bbs1"), removedObjects);
assertNull(network.getVoltageLevel("TL"));
}

@Test
void testRemoveVoltageLevel() {
Network network = FourSubstationsNodeBreakerFactory.create();
Expand Down

0 comments on commit 2e3edfa

Please sign in to comment.