NodeContainerMappingTest.java
/**
* Copyright (c) 2024, 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.cgmes.conversion.test;
import com.powsybl.cgmes.conversion.CgmesImport;
import com.powsybl.commons.test.AbstractSerDeTest;
import com.powsybl.iidm.network.*;
import org.junit.jupiter.api.Test;
import java.util.Properties;
import java.util.Set;
import java.util.stream.Collectors;
import static com.powsybl.cgmes.conversion.test.ConversionUtil.readCgmesResources;
import static org.junit.jupiter.api.Assertions.*;
/**
* @author Romain Courtier {@literal <romain.courtier at rte-france.com>}
*/
class NodeContainerMappingTest extends AbstractSerDeTest {
private static final String DIR = "/issues/node-containers/";
@Test
void nodeContainersConnectedBySwitchesTest() {
// CGMES network:
// Switch SW_AB connects nodes in VoltageLevels VL_1A, VL_1B of the same Substation ST_1.
// Switch SW_12 connects nodes in VoltageLevels VL_1B, VL_2 of Substations ST_1, ST_2.
// Switch SW_23 connects node in VoltageLevel VL_2 of Substation ST_2 with node in Substation ST_3.
// Switch SW_3L connects node in Substation ST_3 with node in Line LN_L.
// There is a BusbarSection attached to the node in VL_2 and a Load attached to the node in ST_3
// IIDM network:
// Ends of switches must be in the same VoltageLevel. So none of the situation above is allowed.
// In such cases, a representative Substation and VoltageLevel are determined and gather all the elements.
Network network = readCgmesResources(DIR, "containers_connected_by_switches.xml");
assertNotNull(network);
// All Substations and VoltageLevels are adjacent. Only 1 of each is kept.
assertEquals(1, network.getSubstationCount());
assertEquals(1, network.getVoltageLevelCount());
// Representatives are ST_1 and VL_1A (min in alphabetical order).
assertNotNull(network.getSubstation("ST_1"));
assertNotNull(network.getVoltageLevel("VL_1A"));
// Merged Substations and VoltageLevels are saved in aliases.
assertEquals(Set.of("ST_2", "ST_3"), network.getSubstation("ST_1").getAliases());
assertEquals(Set.of("VL_1B", "VL_2", "CN_3_VL", "CN_L_VL"), network.getVoltageLevel("VL_1A").getAliases());
// Verify that the Load has been imported and has a Bus
assertNotNull(network.getLoad("LD"));
assertNotNull(network.getLoad("LD").getTerminal().getBusView().getBus());
}
@Test
void nodeOfTJunctionInLineContainerTest() {
// CGMES network:
// 3 VoltageLevels VL_1, VL_2, VL_3 are connected together through line segments in a T-junction.
// ACLineSegments ACL_1A, ACL_2A are in Line LN_A, but ACL_3A has no EquipmentContainer.
// Node CN_A of T-junction is directly in Line Container LN_A.
// IIDM network:
// Nodes must be within a VoltageLevel.
// If that is not the case and no real representative can be found, a fictitious one is created.
Network network = readCgmesResources(DIR, "line_with_t-junction.xml");
assertNotNull(network);
// There is no real representative VoltageLevel for node CN_A, so a fictitious one has been created.
VoltageLevel innerVL = network.getVoltageLevel("CN_A_VL");
assertNotNull(innerVL);
assertNull(innerVL.getNullableSubstation());
assertEquals("LN_A", innerVL.getProperty("CGMES.LineContainerId"));
// All line segments have been imported (even if not associated to an EquipmentContainer) and connected together
assertEquals(3, network.getLineCount());
assertEquals(3, innerVL.getBusBreakerView().getBuses().iterator().next().getConnectedTerminalCount());
}
@Test
void chainedLineSegmentsTest() {
// CGMES network:
// 2 Substations ST_1, ST_2 connected by 3 ACLineSegments in a row: ACL_1A, ACL_AB, ACL_B2.
// The 3 ACLineSegments are in the Line container LN_12.
// Extremity nodes CN_A and CN_B of ACL_AB are in LN_12, nodes CN_1, CN_2 are in VL_1, VL_2 of ST_1, ST_2.
// IIDM network:
// Nodes must be within a VoltageLevel. In case of multiple nodes in the same non-VoltageLevel container,
// a parameter allows to create a fictitious VoltageLevel for every node or for that container
Properties importParams = new Properties();
importParams.put(CgmesImport.CREATE_FICTITIOUS_VOLTAGE_LEVEL_FOR_EVERY_NODE, "false");
Network network = readCgmesResources(importParams, DIR, "chained_line_segments.xml");
assertNotNull(network);
assertEquals(Set.of("VL_1", "VL_2", "LN_12_VL"),
network.getVoltageLevelStream().map(Identifiable::getId).collect(Collectors.toSet()));
assertTrue(network.getVoltageLevel("LN_12_VL").isFictitious());
importParams.put(CgmesImport.CREATE_FICTITIOUS_VOLTAGE_LEVEL_FOR_EVERY_NODE, "true");
network = readCgmesResources(importParams, DIR, "chained_line_segments.xml");
assertNotNull(network);
assertEquals(Set.of("VL_1", "VL_2", "CN_A_VL", "CN_B_VL"),
network.getVoltageLevelStream().map(Identifiable::getId).collect(Collectors.toSet()));
assertTrue(network.getVoltageLevel("CN_A_VL").isFictitious());
assertTrue(network.getVoltageLevel("CN_B_VL").isFictitious());
}
@Test
void substationsConnectedByTransformerTest() {
// CGMES network:
// 3-winding transformer connects nodes in VoltageLevels VL_1, VL_2, VL_3 of Substations ST_1, ST_2, ST_3.
// IIDM network:
// Ends of transformers need to be in the same Substation. So the situation above is not allowed.
// In such a case, a representative Substation is determined and gathers all the elements.
Network network = readCgmesResources(DIR, "substations_connected_by_transformer.xml");
assertNotNull(network);
// All Substations are adjacent, only 1 is kept.
assertEquals(1, network.getSubstationCount());
// Representative is ST_1 (min in alphabetical order).
assertNotNull(network.getSubstation("ST_1"));
// Merged Substations are saved in aliases.
assertEquals(Set.of("ST_2", "ST_3"), network.getSubstation("ST_1").getAliases());
}
@Test
void voltageLevelsConnectedByOpenSwitchTest() {
// CGMES network:
// VoltageLevel VL_1 and VL_2 in Substation ST are connected by Switch SW_12 which is open in SSH.
// IIDM network:
// Ends of switches must be in the same VoltageLevel regardless the switch status in SSH.
Network network = readCgmesResources(DIR,
"voltage_levels_connected_by_open_switch_EQ.xml", "voltage_levels_connected_by_open_switch_SSH.xml");
assertNotNull(network);
// The Switch is indeed open.
assertTrue(network.getSwitch("SW_12").isOpen());
// Still there is only one VoltageLevel.
assertEquals(1, network.getVoltageLevelCount());
assertNotNull(network.getVoltageLevel("VL_1"));
}
@Test
void voltageLevelWithoutName() {
// CGMES network:
// Voltage level of ID "VoltageLevel1" has no name
// IIDM network:
// The voltage level imported without name, and can be retrieved via its id
Network network = readCgmesResources(DIR, "vl_without_name.xml");
assertNotNull(network);
assertEquals(2, network.getVoltageLevelCount());
assertNotNull(network.getVoltageLevel("VoltageLevel"));
}
}