AbstractDcLineTest.java
/**
* Copyright (c) 2025, Coreso SA (https://www.coreso.eu/) and TSCNET Services GmbH (https://www.tscnet.eu/)
* 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 org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author Damien Jeandemange {@literal <damien.jeandemange at artelys.com>}
*/
public abstract class AbstractDcLineTest {
private Network network;
private DcNode dcNode1;
private DcNode dcNode2;
@BeforeEach
void setup() {
network = Network.create("test", "test");
dcNode1 = network.newDcNode().setId("dcNode1").setNominalV(500.).add();
dcNode2 = network.newDcNode().setId("dcNode2").setNominalV(500.).add();
}
@Test
public void testBase() {
String dcLine1Id = "dcLine1";
DcLine dcLine1 = network.newDcLine()
.setId(dcLine1Id)
.setDcNode1(dcNode1.getId())
.setConnected1(true)
.setDcNode2(dcNode2.getId())
.setConnected2(true)
.setR(1.1)
.add();
assertSame(IdentifiableType.DC_LINE, dcLine1.getType());
assertEquals(dcLine1Id, dcLine1.getId());
assertTrue(dcLine1.getDcTerminal1().isConnected());
assertTrue(dcLine1.getDcTerminal2().isConnected());
assertEquals(2, dcLine1.getDcTerminals().size());
assertSame(dcLine1.getDcTerminals().get(0), dcLine1.getDcTerminal1());
assertSame(dcLine1.getDcTerminals().get(1), dcLine1.getDcTerminal2());
assertSame(dcNode1, dcLine1.getDcTerminal1().getDcNode());
assertSame(dcNode2, dcLine1.getDcTerminal2().getDcNode());
assertSame(dcLine1, dcLine1.getDcTerminal1().getDcConnectable());
assertSame(dcLine1, dcLine1.getDcTerminal2().getDcConnectable());
assertEquals(1, network.getDcLineCount());
assertEquals(1.1, dcLine1.getR());
String dcLine2Id = "dcLine2";
DcLine dcLine2 = network.newDcLine()
.setId(dcLine2Id)
.setDcNode1(dcNode1.getId())
.setConnected1(false)
.setDcNode2(dcNode2.getId())
.setConnected2(false)
.setR(1.2)
.add();
assertEquals(dcLine2Id, dcLine2.getId());
assertFalse(dcLine2.getDcTerminal1().isConnected());
assertFalse(dcLine2.getDcTerminal2().isConnected());
assertSame(dcNode1, dcLine2.getDcTerminal1().getDcNode());
assertSame(dcNode2, dcLine2.getDcTerminal2().getDcNode());
assertEquals(1.2, dcLine2.getR());
List<DcLine> dcLineList = List.of(dcLine1, dcLine2);
assertEquals(2, ((Collection<?>) network.getDcLines()).size());
network.getDcLines().forEach(dcLine -> assertTrue(dcLineList.contains(dcLine)));
network.getDcLineStream().forEach(dcLine -> assertTrue(dcLineList.contains(dcLine)));
assertEquals(2, network.getIdentifiableStream(IdentifiableType.DC_LINE).count());
network.getIdentifiableStream(IdentifiableType.DC_LINE).forEach(dcLine -> assertTrue(dcLineList.contains((DcLine) dcLine)));
assertEquals(2, network.getDcLineCount());
}
@Test
public void testGetterSetter() {
DcLine dcLine = network.newDcLine()
.setId("dcLine")
.setDcNode1(dcNode1.getId())
.setConnected1(true)
.setDcNode2(dcNode2.getId())
.setConnected2(true)
.setR(1.1)
.add();
assertSame(TwoSides.ONE, dcLine.getDcTerminal1().getSide());
assertSame(TwoSides.TWO, dcLine.getDcTerminal2().getSide());
assertSame(TwoSides.ONE, dcLine.getSide(dcLine.getDcTerminal1()));
assertSame(TwoSides.TWO, dcLine.getSide(dcLine.getDcTerminal2()));
assertSame(dcLine.getDcTerminal1(), dcLine.getDcTerminal(TwoSides.ONE));
assertSame(dcLine.getDcTerminal2(), dcLine.getDcTerminal(TwoSides.TWO));
assertEquals(1.1, dcLine.getR());
dcLine.setR(1.2);
assertEquals(1.2, dcLine.getR());
dcLine.setR(0.0);
assertEquals(0.0, dcLine.getR());
PowsyblException e1 = assertThrows(PowsyblException.class, () -> dcLine.setR(Double.NaN));
assertEquals("DC Line 'dcLine': r is invalid", e1.getMessage());
PowsyblException e2 = assertThrows(PowsyblException.class, () -> dcLine.setR(-1.0));
assertEquals("DC Line 'dcLine': r is invalid", e2.getMessage());
}
@Test
public void testCreateDuplicate() {
network.newDcLine()
.setId("dcLine1")
.setDcNode1(dcNode1.getId())
.setConnected1(true)
.setDcNode2(dcNode2.getId())
.setConnected2(true)
.setR(1.1)
.add();
DcLineAdder dcLineDuplicateAdder = network.newDcLine()
.setId("dcLine1")
.setDcNode1(dcNode1.getId())
.setConnected1(false)
.setDcNode2(dcNode2.getId())
.setConnected2(false)
.setR(1.2);
PowsyblException exception = assertThrows(PowsyblException.class, dcLineDuplicateAdder::add);
assertTrue(Pattern.compile("The network test already contains an object '(\\w+)' with the id 'dcLine1'").matcher(exception.getMessage()).find());
}
@Test
public void testRemove() {
String dcLine1Id = "dcLine1";
DcLine dcLine1 = network.newDcLine()
.setId(dcLine1Id)
.setDcNode1(dcNode1.getId())
.setDcNode2(dcNode2.getId())
.setR(1.1)
.add();
DcTerminal t1 = dcLine1.getDcTerminal1();
DcTerminal t2 = dcLine1.getDcTerminal2();
String dcLine2Id = "dcLine2";
DcLine dcLine2 = network.newDcLine()
.setId(dcLine2Id)
.setDcNode1(dcNode1.getId())
.setDcNode2(dcNode2.getId())
.setR(1.2)
.add();
assertEquals(2, network.getDcLineCount());
dcLine1.remove();
assertNull(network.getDcLine(dcLine1Id));
assertEquals(1, network.getDcLineCount());
dcLine2.remove();
assertNull(network.getDcLine(dcLine2Id));
assertEquals(0, network.getDcLineCount());
PowsyblException e1 = assertThrows(PowsyblException.class, () -> dcLine1.setR(2.));
assertEquals("Cannot modify r of removed equipment dcLine1", e1.getMessage());
PowsyblException e2 = assertThrows(PowsyblException.class, dcLine1::getR);
assertEquals("Cannot access r of removed equipment dcLine1", e2.getMessage());
PowsyblException e3 = assertThrows(PowsyblException.class, t1::isConnected);
assertEquals("Cannot access removed equipment dcLine1", e3.getMessage());
PowsyblException e4 = assertThrows(PowsyblException.class, () -> t2.setConnected(false));
assertEquals("Cannot modify removed equipment dcLine1", e4.getMessage());
}
@Test
public void testCreationError() {
DcLineAdder adder = network.newDcLine();
PowsyblException e1 = assertThrows(PowsyblException.class, adder::add);
assertEquals("DC Line id is not set", e1.getMessage());
adder.setId("dcLine");
PowsyblException e2 = assertThrows(PowsyblException.class, adder::add);
assertEquals("DC Line 'dcLine': dcNode1 is not set", e2.getMessage());
adder.setDcNode1("notExists");
PowsyblException e3 = assertThrows(PowsyblException.class, adder::add);
assertEquals("DC Line 'dcLine': DcNode 'notExists' not found", e3.getMessage());
adder.setDcNode1(dcNode1.getId());
PowsyblException e4 = assertThrows(PowsyblException.class, adder::add);
assertEquals("DC Line 'dcLine': dcNode2 is not set", e4.getMessage());
adder.setDcNode2("notExists");
PowsyblException e5 = assertThrows(PowsyblException.class, adder::add);
assertEquals("DC Line 'dcLine': DcNode 'notExists' not found", e5.getMessage());
adder.setDcNode2(dcNode2.getId());
PowsyblException e6 = assertThrows(PowsyblException.class, adder::add);
assertEquals("DC Line 'dcLine': r is invalid", e6.getMessage());
adder.setR(Double.NaN);
PowsyblException e7 = assertThrows(PowsyblException.class, adder::add);
assertEquals("DC Line 'dcLine': r is invalid", e7.getMessage());
adder.setR(-1.0);
PowsyblException e8 = assertThrows(PowsyblException.class, adder::add);
assertEquals("DC Line 'dcLine': r is invalid", e8.getMessage());
}
@Test
public void testOnSubnetwork() {
Network netWithSubnet = Network.create("test", "test");
Network subnetwork1 = netWithSubnet.createSubnetwork("subnetwork1", "subnetwork1", "format1");
Network subnetwork2 = netWithSubnet.createSubnetwork("subnetwork2", "subnetwork2", "format2");
DcNode dcNode1Subnet1 = subnetwork1.newDcNode().setId("dcNode1Subnetwork1").setNominalV(500.).add();
DcNode dcNode2Subnet1 = subnetwork1.newDcNode().setId("dcNode2Subnetwork1").setNominalV(500.).add();
DcNode dcNode1Subnet2 = subnetwork2.newDcNode().setId("dcNode1Subnetwork2").setNominalV(500.).add();
DcNode dcNode2Subnet2 = subnetwork2.newDcNode().setId("dcNode2Subnetwork2").setNominalV(500.).add();
DcLine dcLine1Subnet1 = subnetwork1.newDcLine().setId("dcLine1Subnetwork1")
.setDcNode1(dcNode1Subnet1.getId())
.setDcNode2(dcNode2Subnet1.getId())
.setR(1.0)
.add();
DcLine dcLine2Subnet1 = subnetwork1.newDcLine().setId("dcLine2Subnetwork1")
.setDcNode1(dcNode1Subnet1.getId())
.setDcNode2(dcNode2Subnet1.getId())
.setR(1.0)
.add();
DcLine dcLine1Subnet2 = subnetwork2.newDcLine().setId("dcLine1Subnetwork2")
.setDcNode1(dcNode1Subnet2.getId())
.setDcNode2(dcNode2Subnet2.getId())
.setR(1.0)
.add();
List<DcLine> dcLineList = List.of(dcLine1Subnet1, dcLine2Subnet1, dcLine1Subnet2);
// network content
assertEquals(3, ((Collection<?>) netWithSubnet.getDcLines()).size());
netWithSubnet.getDcLines().forEach(dcLine -> assertTrue(dcLineList.contains(dcLine)));
netWithSubnet.getDcLineStream().forEach(dcLine -> assertTrue(dcLineList.contains(dcLine)));
assertEquals(3, netWithSubnet.getIdentifiableStream(IdentifiableType.DC_LINE).count());
netWithSubnet.getIdentifiableStream(IdentifiableType.DC_LINE).forEach(dcLine -> assertTrue(dcLineList.contains((DcLine) dcLine)));
assertEquals(3, netWithSubnet.getDcLineCount());
assertSame(dcLine1Subnet1, netWithSubnet.getDcLine(dcLine1Subnet1.getId()));
assertSame(dcLine2Subnet1, netWithSubnet.getDcLine(dcLine2Subnet1.getId()));
assertSame(dcLine1Subnet2, netWithSubnet.getDcLine(dcLine1Subnet2.getId()));
// subnetwork1 content
List<DcLine> dcLineListSubnet1 = List.of(dcLine1Subnet1, dcLine2Subnet1);
assertEquals(2, ((Collection<?>) subnetwork1.getDcLines()).size());
subnetwork1.getDcLines().forEach(dcLine -> assertTrue(dcLineListSubnet1.contains(dcLine)));
subnetwork1.getDcLineStream().forEach(dcLine -> assertTrue(dcLineListSubnet1.contains(dcLine)));
assertEquals(2, subnetwork1.getIdentifiableStream(IdentifiableType.DC_LINE).count());
subnetwork1.getIdentifiableStream(IdentifiableType.DC_LINE).forEach(dcNode -> assertTrue(dcLineListSubnet1.contains((DcLine) dcNode)));
assertEquals(2, subnetwork1.getDcLineCount());
assertSame(dcLine1Subnet1, subnetwork1.getDcLine(dcLine1Subnet1.getId()));
assertSame(dcLine2Subnet1, subnetwork1.getDcLine(dcLine2Subnet1.getId()));
assertNull(subnetwork1.getDcLine(dcLine1Subnet2.getId()));
// subnetwork2 content
List<DcLine> dcLineListSubnet2 = List.of(dcLine1Subnet2);
assertEquals(1, ((Collection<?>) subnetwork2.getDcLines()).size());
subnetwork2.getDcLines().forEach(dcLine -> assertTrue(dcLineListSubnet2.contains(dcLine)));
subnetwork2.getDcLineStream().forEach(dcLine -> assertTrue(dcLineListSubnet2.contains(dcLine)));
assertEquals(1, subnetwork2.getIdentifiableStream(IdentifiableType.DC_LINE).count());
subnetwork2.getIdentifiableStream(IdentifiableType.DC_LINE).forEach(dcLine -> assertTrue(dcLineListSubnet2.contains((DcLine) dcLine)));
assertEquals(1, subnetwork2.getDcLineCount());
assertNull(subnetwork2.getDcLine(dcLine1Subnet1.getId()));
assertNull(subnetwork2.getDcLine(dcLine2Subnet1.getId()));
assertSame(dcLine1Subnet2, subnetwork2.getDcLine(dcLine1Subnet2.getId()));
}
@Test
public void testNotAcrossNetworkSubnetworks() {
Network netWithSubnet = Network.create("test", "test");
Network subnetwork1 = netWithSubnet.createSubnetwork("subnetwork1", "subnetwork1", "format1");
Network subnetwork2 = netWithSubnet.createSubnetwork("subnetwork2", "subnetwork2", "format2");
DcNode dcNode1Subnet1 = subnetwork1.newDcNode().setId("dcNode1Subnetwork1").setNominalV(500.).add();
DcNode dcNode2Subnet1 = subnetwork1.newDcNode().setId("dcNode2Subnetwork1").setNominalV(500.).add();
DcNode dcNode1Subnet2 = subnetwork2.newDcNode().setId("dcNode1Subnetwork2").setNominalV(500.).add();
DcNode dcNodeRootNetwork = netWithSubnet.newDcNode().setId("dcNodeRootNetwork").setNominalV(500.).add();
// test cannot create DcLine across subnetwork1 & subnetwork2
DcLineAdder adder = netWithSubnet.newDcLine().setId("dcLineAcrossSubnets")
.setDcNode1(dcNode1Subnet1.getId())
.setDcNode2(dcNode1Subnet2.getId())
.setR(1.0);
PowsyblException e1 = assertThrows(PowsyblException.class, adder::add);
assertEquals("DC Line 'dcLineAcrossSubnets': DC Nodes 'dcNode1Subnetwork1' and 'dcNode1Subnetwork2' are in different networks 'subnetwork1' and 'subnetwork2'", e1.getMessage());
// test cannot create DcLine in netWithSubnet referencing nodes of subnetwork1
adder.setDcNode1(dcNode1Subnet1.getId()).setDcNode2(dcNode2Subnet1.getId());
PowsyblException e2 = assertThrows(PowsyblException.class, adder::add);
assertEquals("DC Line 'dcLineAcrossSubnets': DC Nodes 'dcNode1Subnetwork1' and 'dcNode2Subnetwork1' are in network 'subnetwork1' but DC Equipment is in 'test'", e2.getMessage());
// test cannot create DcLine across subnetwork1 & netWithSubnet
adder.setDcNode2(dcNodeRootNetwork.getId());
PowsyblException e3 = assertThrows(PowsyblException.class, adder::add);
assertEquals("DC Line 'dcLineAcrossSubnets': DC Nodes 'dcNode1Subnetwork1' and 'dcNodeRootNetwork' are in different networks 'subnetwork1' and 'test'", e3.getMessage());
}
}