AbstractNodeBreakerTest.java
/**
* Copyright (c) 2016-2018, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
* SPDX-License-Identifier: MPL-2.0
*/
package com.powsybl.iidm.network.tck;
import com.powsybl.commons.PowsyblException;
import com.powsybl.iidm.network.*;
import com.powsybl.iidm.network.extensions.BusbarSectionPositionAdder;
import com.powsybl.iidm.network.test.FourSubstationsNodeBreakerFactory;
import com.powsybl.iidm.network.test.NetworkTest1Factory;
import com.powsybl.iidm.network.util.SwitchPredicates;
import org.junit.jupiter.api.Test;
import java.util.regex.Pattern;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author Geoffroy Jamgotchian {@literal <geoffroy.jamgotchian at rte-france.com>}
*/
public abstract class AbstractNodeBreakerTest {
protected Network createNetwork() {
Network network = Network.create("test", "test");
Substation s1 = network.newSubstation()
.setId("S1")
.setCountry(Country.FR)
.add();
VoltageLevel vl = s1.newVoltageLevel()
.setId("VL1")
.setNominalV(1.0)
.setTopologyKind(TopologyKind.NODE_BREAKER)
.add();
// Busbar sections
BusbarSection bbs11 = vl.getNodeBreakerView()
.newBusbarSection()
.setId("BBS11")
.setNode(0)
.add();
bbs11.newExtension(BusbarSectionPositionAdder.class)
.withBusbarIndex(1)
.withSectionIndex(1)
.add();
BusbarSection bbs21 = vl.getNodeBreakerView()
.newBusbarSection()
.setId("BBS21")
.setNode(1)
.add();
bbs21.newExtension(BusbarSectionPositionAdder.class)
.withBusbarIndex(2)
.withSectionIndex(1)
.add();
BusbarSection bbs12 = vl.getNodeBreakerView()
.newBusbarSection()
.setId("BBS12")
.setNode(2)
.add();
bbs12.newExtension(BusbarSectionPositionAdder.class)
.withBusbarIndex(1)
.withSectionIndex(2)
.add();
BusbarSection bbs22 = vl.getNodeBreakerView()
.newBusbarSection()
.setId("BBS22")
.setNode(3)
.add();
bbs22.newExtension(BusbarSectionPositionAdder.class)
.withBusbarIndex(2)
.withSectionIndex(2)
.add();
// Disconnectors for coupling
vl.getNodeBreakerView().newDisconnector()
.setId("D_BBS11_BBS12")
.setNode1(0)
.setNode2(2)
.setOpen(true)
.add();
vl.getNodeBreakerView().newDisconnector()
.setId("D_BBS21_BBS22")
.setNode1(1)
.setNode2(3)
.setOpen(false)
.add();
// Generators and loads
vl.newLoad()
.setId("L1")
.setNode(4)
.setP0(1)
.setQ0(1)
.add();
vl.newGenerator()
.setId("G1")
.setNode(5)
.setMaxP(100)
.setMinP(50)
.setTargetP(100)
.setTargetV(400)
.setVoltageRegulatorOn(true)
.add();
vl.newGenerator()
.setId("G2")
.setNode(6)
.setMaxP(100)
.setMinP(50)
.setTargetP(100)
.setTargetV(400)
.setVoltageRegulatorOn(true)
.add();
// Breakers
vl.getNodeBreakerView().newBreaker()
.setId("B_L1_1")
.setNode1(4)
.setNode2(7)
.setOpen(false)
.setFictitious(true)
.add();
vl.getNodeBreakerView().newBreaker()
.setId("B_L1_2")
.setNode1(4)
.setNode2(7)
.setOpen(false)
.add();
vl.getNodeBreakerView().newBreaker()
.setId("B_G1")
.setNode1(5)
.setNode2(8)
.setOpen(true)
.add();
vl.getNodeBreakerView().newBreaker()
.setId("B_G2")
.setNode1(6)
.setNode2(9)
.setOpen(false)
.setFictitious(true)
.add();
vl.getNodeBreakerView().newBreaker()
.setId("B0")
.setNode1(7)
.setNode2(17)
.setOpen(false)
.add();
vl.getNodeBreakerView().newBreaker()
.setId("B1")
.setNode1(8)
.setNode2(11)
.setOpen(true)
.add();
vl.getNodeBreakerView().newBreaker()
.setId("B2")
.setNode1(9)
.setNode2(12)
.setOpen(false)
.setFictitious(true)
.add();
vl.getNodeBreakerView().newBreaker()
.setId("B3")
.setNode1(7)
.setNode2(8)
.setOpen(false)
.add();
vl.getNodeBreakerView().newBreaker()
.setId("B4")
.setNode1(8)
.setNode2(9)
.setOpen(false)
.add();
vl.getNodeBreakerView().newBreaker()
.setId("B5")
.setNode1(17)
.setNode2(10)
.setOpen(false)
.add();
// Disconnectors
vl.getNodeBreakerView().newDisconnector()
.setId("D0")
.setNode1(0)
.setNode2(10)
.setOpen(true)
.add();
vl.getNodeBreakerView().newDisconnector()
.setId("D1")
.setNode1(1)
.setNode2(10)
.setOpen(false)
.add();
vl.getNodeBreakerView().newDisconnector()
.setId("D2")
.setNode1(0)
.setNode2(11)
.setOpen(false)
.add();
vl.getNodeBreakerView().newDisconnector()
.setId("D3")
.setNode1(1)
.setNode2(11)
.setOpen(true)
.add();
vl.getNodeBreakerView().newDisconnector()
.setId("D4")
.setNode1(2)
.setNode2(12)
.setOpen(false)
.add();
vl.getNodeBreakerView().newDisconnector()
.setId("D5")
.setNode1(3)
.setNode2(12)
.setOpen(true)
.add();
return network;
}
private static Network createIsolatedLoadNetwork() {
Network network = Network.create("test", "test");
Substation s1 = network.newSubstation().setId("S").add();
VoltageLevel vl1 = s1.newVoltageLevel().setId("VL").setNominalV(1f)
.setTopologyKind(TopologyKind.NODE_BREAKER)
.add();
VoltageLevel vl2 = s1.newVoltageLevel().setId("VL2").setNominalV(1f)
.setTopologyKind(TopologyKind.NODE_BREAKER)
.add();
vl1.getNodeBreakerView()
.newBusbarSection()
.setId("B0")
.setNode(0)
.add();
vl1.getNodeBreakerView()
.newBusbarSection()
.setId("B1")
.setNode(1)
.add();
vl1.getNodeBreakerView()
.newBusbarSection()
.setId("B2")
.setNode(2)
.add();
vl1.newLoad()
.setId("L0")
.setNode(6)
.setP0(0)
.setQ0(0)
.add();
vl1.newLoad()
.setId("L1")
.setNode(3)
.setP0(0)
.setQ0(0)
.add();
vl1.newLoad()
.setId("L2")
.setNode(4)
.setP0(0)
.setQ0(0)
.add();
vl1.newLoad()
.setId("L3")
.setNode(5)
.setP0(0)
.setQ0(0)
.add();
vl1.getNodeBreakerView().newBreaker()
.setId("L0-node")
.setOpen(false)
.setNode1(0)
.setNode2(6)
.add();
vl1.getNodeBreakerView().newBreaker()
.setId("L1-node")
.setOpen(true)
.setNode1(4)
.setNode2(10)
.add();
vl1.getNodeBreakerView().newBreaker()
.setId("L0-B0")
.setOpen(false)
.setNode1(3)
.setNode2(1)
.add();
vl1.getNodeBreakerView().newBreaker()
.setId("B0-node")
.setOpen(true)
.setNode1(1)
.setNode2(10)
.setRetained(true)
.add();
vl1.getNodeBreakerView().newBreaker()
.setId("node-B1")
.setOpen(false)
.setNode1(10)
.setNode2(2)
.setRetained(true)
.add();
vl2.newLoad()
.setId("L4")
.setNode(0)
.setP0(0)
.setQ0(0)
.add();
return network;
}
/**
* <pre>
* load
* |
* ___|___
* | |
* fd1 x x fd2
* bbs1 _________|__ |
* | |
* c |
* bbs2 __|____________|__
* </pre>
*/
private static Network createNetworkWithLoop() {
Network network = Network.create("test", "test");
Substation substation = network.newSubstation().setId("s").add();
VoltageLevel vl = substation.newVoltageLevel().setId("vl").setNominalV(400).setTopologyKind(TopologyKind.NODE_BREAKER).add();
VoltageLevel.NodeBreakerView topology = vl.getNodeBreakerView();
topology.newBusbarSection().setId("bbs1").setNode(0).add();
topology.newBusbarSection().setId("bbs2").setNode(1).add();
topology.newDisconnector().setId("fd1").setNode1(0).setNode2(2).add();
topology.newDisconnector().setId("fd2").setNode1(1).setNode2(2).add();
topology.newBreaker().setId("c").setNode1(0).setNode2(1).add();
vl.newLoad().setId("load").setNode(2).setP0(10).setQ0(3).add();
return network;
}
@Test
public void connectDisconnectRemove() {
Network network = createNetwork();
VoltageLevel.NodeBreakerView topo = network.getVoltageLevel("VL1").getNodeBreakerView();
Load l1 = network.getLoad("L1");
Generator g1 = network.getGenerator("G1");
Generator g2 = network.getGenerator("G2");
// generator 1 is disconnected, load and generator 2 are connected
assertTrue(topo.getOptionalTerminal(4).isPresent());
assertTrue(topo.getOptionalTerminal(5).isPresent());
assertTrue(topo.getOptionalTerminal(6).isPresent());
assertNotNull(l1.getTerminal().getBusView().getBus());
assertNull(g1.getTerminal().getBusView().getBus());
assertNotNull(g2.getTerminal().getBusView().getBus());
assertTrue(l1.getTerminal().isConnected());
assertFalse(g1.getTerminal().isConnected());
assertTrue(g2.getTerminal().isConnected());
// connect the generator 1
assertTrue(g1.getTerminal().connect());
// check generator 1 is connected
assertTrue(topo.getOptionalTerminal(5).isPresent());
assertNotNull(g1.getTerminal().getBusView().getBus());
assertTrue(g1.getTerminal().isConnected());
// disconnect the load
l1.getTerminal().disconnect();
// check load is disconnected
assertTrue(topo.getOptionalTerminal(4).isPresent());
assertNull(l1.getTerminal().getBusView().getBus());
assertFalse(l1.getTerminal().isConnected());
// remove load
l1.remove();
topo.removeSwitch("B_L1_1");
topo.removeSwitch("B_L1_2");
// check load is removed
assertFalse(topo.getOptionalTerminal(4).isPresent());
// disconnect and reconnect the generator 1
g1.getTerminal().disconnect();
network.getSwitch("B_G1").setFictitious(true);
network.getSwitch("B1").setFictitious(true);
assertFalse(g1.getTerminal().connect(SwitchPredicates.IS_NONFICTIONAL_BREAKER));
}
@Test
public void errorDisconnectOnRemoved() {
Network network = createNetwork();
VoltageLevel.NodeBreakerView topo = network.getVoltageLevel("VL1").getNodeBreakerView();
Load l1 = network.getLoad("L1");
// disconnect the load
l1.getTerminal().disconnect(SwitchPredicates.IS_CLOSED_BREAKER);
// remove load
l1.remove();
topo.removeSwitch("B_L1_1");
topo.removeSwitch("B_L1_2");
// Load terminal (used to have only one possible runtime exception)
Terminal loadTerminal = l1.getTerminal();
// disconnect the load again
PowsyblException exception = assertThrows(PowsyblException.class, () -> loadTerminal.disconnect(SwitchPredicates.IS_CLOSED_BREAKER));
assertTrue(Pattern.compile("Cannot modify removed equipment(?: L1)?$").matcher(exception.getMessage()).find());
}
@Test
public void errorConnectOnRemoved() {
Network network = createNetwork();
VoltageLevel.NodeBreakerView topo = network.getVoltageLevel("VL1").getNodeBreakerView();
Load l1 = network.getLoad("L1");
// disconnect the load
l1.getTerminal().disconnect(SwitchPredicates.IS_CLOSED_BREAKER);
// remove load
l1.remove();
topo.removeSwitch("B_L1_1");
topo.removeSwitch("B_L1_2");
// Load terminal (used to have only one possible runtime exception)
Terminal loadTerminal = l1.getTerminal();
// disconnect the load again
PowsyblException exception = assertThrows(PowsyblException.class, loadTerminal::connect);
assertTrue(Pattern.compile("Cannot modify removed equipment(?: L1)?$").matcher(exception.getMessage()).find());
}
@Test
public void failToDisconnectWhenAlreadyDisconnected() {
Network network = createNetwork();
Generator g1 = network.getGenerator("G1");
// disconnect the generator
assertFalse(g1.getTerminal().disconnect(SwitchPredicates.IS_CLOSED_BREAKER));
}
@Test
public void failToDisconnectDueToPredicate() {
Network network = createNetwork();
Generator g2 = network.getGenerator("G2");
// disconnect the generator
assertFalse(g2.getTerminal().disconnect(SwitchPredicates.IS_NONFICTIONAL_CLOSED_BREAKER));
}
private static Bus getBusInBusBreakerView(Injection<?> i) {
return i.getTerminal().getBusBreakerView().getBus();
}
private static Bus getBusInBusView(Injection<?> i) {
return i.getTerminal().getBusView().getBus();
}
private static Bus getConnectableBusInBusBreakerView(Injection<?> i) {
return i.getTerminal().getBusBreakerView().getConnectableBus();
}
private static Bus getConnectableBusInBusView(Injection<?> i) {
return i.getTerminal().getBusView().getConnectableBus();
}
@Test
public void replaceLoad() {
Network network = NetworkTest1Factory.create();
VoltageLevel vl = network.getVoltageLevel("voltageLevel1");
Load l1 = network.getLoad("load1");
int n = l1.getTerminal().getNodeBreakerView().getNode();
LoadAdder newLoad = vl.newLoad()
.setId("load2")
.setP0(10)
.setQ0(2)
.setNode(n);
// The new load cannot be connected since the old load is still connected to the node.
try {
newLoad.add();
fail("Should have thrown a validation exception");
} catch (ValidationException ignored) {
// ignore
}
l1.remove();
// Now the load may be attached.
Load l2 = newLoad.add();
assertNull(network.getLoad("load1"));
assertNotNull(network.getLoad("load2"));
assertEquals(n, l2.getTerminal().getNodeBreakerView().getNode());
// Check thew load is connected to the correct bus bar.
BusbarSection bb = vl.getNodeBreakerView().getBusbarSection("voltageLevel1BusbarSection1");
assertEquals(getBusInBusView(bb), getBusInBusView(l2));
}
@Test
public void testIsolatedLoadBusBranch() {
Network network = createIsolatedLoadNetwork();
assertEquals(2, network.getBusView().getBusStream().count());
// load "L0" is connected to bus "VL_0"
Load l0 = network.getLoad("L0");
assertNotNull(getBusInBusBreakerView(l0));
assertEquals("VL_0", getConnectableBusInBusBreakerView(l0).getId());
assertNotNull(getBusInBusView(l0));
assertEquals("VL_0", getConnectableBusInBusView(l0).getId());
// load "L1" is connected to bus "VL_1"
Load l1 = network.getLoad("L1");
assertNotNull(getBusInBusBreakerView(l1));
assertEquals("VL_1", getConnectableBusInBusBreakerView(l1).getId());
assertNotNull(getBusInBusView(l1));
assertEquals("VL_1", getConnectableBusInBusView(l1).getId());
// load "L2" is not connected but is connectable to bus "VL_1"
Load l2 = network.getLoad("L2");
assertNotNull(getBusInBusBreakerView(l2));
assertEquals("VL_4", getConnectableBusInBusBreakerView(l2).getId());
assertNull(getBusInBusView(l2));
assertEquals("VL_1", getConnectableBusInBusView(l2).getId());
// load "L3" is not connected and has no connectable bus (the first bus is taken as connectable bus in this case)
Load l3 = network.getLoad("L3");
assertNotNull(getBusInBusBreakerView(l3));
assertEquals("VL_5", getConnectableBusInBusBreakerView(l3).getId());
assertNull(getBusInBusView(l3));
assertEquals("VL_0", getConnectableBusInBusView(l3).getId());
// load "L4" is not connected, has no connectable bus and is in a disconnected voltage level
Load l4 = network.getLoad("L4");
assertNotNull(getBusInBusBreakerView(l4));
assertEquals("VL2_0", getConnectableBusInBusBreakerView(l4).getId());
assertNull(getBusInBusView(l4));
assertNull(getConnectableBusInBusView(l4));
}
@Test
public void testCalculatedBus() {
Network network = createIsolatedLoadNetwork();
Bus busL0 = network.getLoad("L0").getTerminal().getBusBreakerView().getBus();
assertNotNull(busL0);
assertEquals("VL", busL0.getVoltageLevel().getId());
assertEquals("VL_0", busL0.getId());
assertNull(network.getBusBreakerView().getBus("unknownBus"));
network.getVoltageLevel("VL").getNodeBreakerView().newBusbarSection().setId("VL_0").setNode(10).add();
busL0 = network.getLoad("L0").getTerminal().getBusBreakerView().getBus();
assertEquals("VL_0#0", busL0.getId());
}
@Test
public void testRemove() {
Network network = FourSubstationsNodeBreakerFactory.create();
Substation sub = network.getSubstation("S1");
// Disconnect the substation from the network
network.getHvdcLine("HVDC1").remove();
network.getHvdcLine("HVDC2").remove();
sub.getVoltageLevelStream()
.flatMap(VoltageLevel::getVscConverterStationStream)
.forEach(Connectable::remove);
// Remove 1 switch
VoltageLevel vl1 = network.getVoltageLevel("S1VL1");
vl1.getNodeBreakerView().removeSwitch("S1VL1_LD1_BREAKER");
assertNull(vl1.getNodeBreakerView().getSwitch("S1VL1_LD1_BREAKER"));
// Remove substation
sub.remove();
assertNull(network.getSubstation("S1"));
}
@Test
public void testCalculatedBusTopologyWithLoop() {
Network n = createNetworkWithLoop();
Bus busBbv = n.getBusBreakerView().getBus("vl_0");
assertNotNull(busBbv);
assertEquals(1, n.getBusBreakerView().getBusCount());
assertEquals(3, busBbv.getConnectedTerminalCount());
Bus busBv = n.getBusView().getBus("vl_0");
assertNotNull(busBv);
assertEquals(1, n.getBusView().getBusStream().count());
assertEquals(3, busBv.getConnectedTerminalCount());
}
}