diff --git a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingTerminalMapper.java b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingTerminalMapper.java index dc94ce656de..5cd28bb4f9b 100644 --- a/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingTerminalMapper.java +++ b/cgmes/cgmes-conversion/src/main/java/com/powsybl/cgmes/conversion/RegulatingTerminalMapper.java @@ -42,9 +42,11 @@ public static Optional mapForVoltageControl(String cgmesTerminalId, Co .or(() -> new EquivalentTerminalFinderVoltageControl(cgmesTerminalId, context).find()) // As a last resource, rely on the "find" method of terminal mapping: // Bus/branch models may define remote voltage controls that point to busbar sections - // Busbar sections are not mapped to IIDM + // Since busbar sections are not mapped to IIDM, we look for an equivalent IIDM terminal + // is connected to the busbar section via switches .or(() -> Optional.ofNullable(context.terminalMapping() - .findFromTopologicalNode(context.terminalMapping().getTopologicalNode(cgmesTerminalId)))); + .findFromTopologicalNode(context.terminalMapping().getTopologicalNode(cgmesTerminalId))) + .or(() -> findEquivalentTerminalForVoltageRegulatingTerminalDefinedAtBusbarSection(cgmesTerminalId, context))); } public static Optional mapForFlowControl(String cgmesTerminalId, Context context) { @@ -337,7 +339,7 @@ private Optional findNodeBreaker() { private Optional findBusBranch() { Bus end1 = vl.getBusBreakerView().getBus1(sw.getId()); - List terminals = findTerminalsBusBranch(end1); + List terminals = findTerminalsBusBranch(vl, end1); return best(terminals); } @@ -346,7 +348,7 @@ protected List findTerminalsNodeBreaker(int node) { return allTerminals(vl, nodes, t -> t.getNodeBreakerView().getNode()); } - private List findTerminalsBusBranch(Bus end) { + private static List findTerminalsBusBranch(VoltageLevel vl, Bus end) { Set buses = allBusesReachableBySwitches(vl, end); return allTerminals(vl, buses, RegulatingTerminalMapper::getTerminalBus); } @@ -399,6 +401,17 @@ private Optional findBusBranch() { } } + static Optional findEquivalentTerminalForVoltageRegulatingTerminalDefinedAtBusbarSection(String cgmesTerminalId, Context context) { + CgmesTerminal busbarSectionCgmesTerminal = context.cgmes().terminal(cgmesTerminalId); + if (busbarSectionCgmesTerminal == null) { + return Optional.empty(); + } + Bus busInBusBreakerView = context.network().getBusBreakerView().getBus(busbarSectionCgmesTerminal.topologicalNode()); + return busInBusBreakerView != null + ? EquivalentTerminalFinderVoltageControl.best(EquivalentTerminalFinderVoltageControl.findTerminalsBusBranch(busInBusBreakerView.getVoltageLevel(), busInBusBreakerView)) + : Optional.empty(); + } + private static Bus getTerminalBus(Terminal terminal) { return terminal.getBusBreakerView().getBus() != null ? terminal.getBusBreakerView().getBus() : terminal.getBusBreakerView().getConnectableBus(); diff --git a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/RegulatingTerminalConversionTest.java b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/RegulatingTerminalConversionTest.java index e6ce84fd240..fdff12e658c 100644 --- a/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/RegulatingTerminalConversionTest.java +++ b/cgmes/cgmes-conversion/src/test/java/com/powsybl/cgmes/conversion/test/RegulatingTerminalConversionTest.java @@ -10,13 +10,16 @@ import com.powsybl.cgmes.conformity.Cgmes3ModifiedCatalog; import com.powsybl.cgmes.conformity.CgmesConformity1ModifiedCatalog; +import com.powsybl.cgmes.conversion.CgmesImport; import com.powsybl.cgmes.conversion.Conversion; import com.powsybl.cgmes.model.GridModelReference; import com.powsybl.iidm.network.*; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; +import java.util.Properties; + +import static com.powsybl.cgmes.conversion.test.ConversionUtil.readCgmesResources; +import static org.junit.jupiter.api.Assertions.*; /** * @author Luma ZamarreƱo {@literal } @@ -86,6 +89,38 @@ void microGridBaseBECaseRegulatingTerminalsDefinedOnSwitches() { assertEquals(21.987, regulationValue, 0.0); } + @Test + void voltageRegulatingTerminalAtBusbarSectionNodeBreakerTest() { + Network network = readCgmesResources("/issues/voltage-regulating-terminal-at-busbar-section", + "issue_3560_CGMES_EQ.xml", + "issue_3560_CGMES_SSH.xml", + "issue_3560_CGMES_SV.xml", + "issue_3560_CGMES_TP.xml"); + + Generator generator = network.getGenerator("GEN"); + assertNotNull(generator); + assertEquals("VL2_400_BBS1", generator.getRegulatingTerminal().getConnectable().getId()); + assertSame(IdentifiableType.BUSBAR_SECTION, generator.getRegulatingTerminal().getConnectable().getType()); + } + + @Test + void voltageRegulatingTerminalAtBusbarSectionBusBreakerTest() { + Properties importParams = new Properties(); + importParams.put(CgmesImport.IMPORT_NODE_BREAKER_AS_BUS_BREAKER, "true"); + + Network network = readCgmesResources(importParams, + "/issues/voltage-regulating-terminal-at-busbar-section", + "issue_3560_CGMES_EQ.xml", + "issue_3560_CGMES_SSH.xml", + "issue_3560_CGMES_SV.xml", + "issue_3560_CGMES_TP.xml"); + + Generator generator = network.getGenerator("GEN"); + assertNotNull(generator); + assertEquals("LOAD", generator.getRegulatingTerminal().getConnectable().getId()); + assertSame(IdentifiableType.LOAD, generator.getRegulatingTerminal().getConnectable().getType()); + } + private Network networkModel(GridModelReference testGridModel, Conversion.Config config) { config.setConvertSvInjections(true); return ConversionUtil.networkModel(testGridModel, config); diff --git a/cgmes/cgmes-conversion/src/test/resources/issues/voltage-regulating-terminal-at-busbar-section/issue_3560_CGMES_EQ.xml b/cgmes/cgmes-conversion/src/test/resources/issues/voltage-regulating-terminal-at-busbar-section/issue_3560_CGMES_EQ.xml new file mode 100644 index 00000000000..2c07d47c1ea --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/issues/voltage-regulating-terminal-at-busbar-section/issue_3560_CGMES_EQ.xml @@ -0,0 +1,355 @@ + + + + 2025-11-25T12:06:35Z + 2025-11-25T12:06:36Z + EQ Model + 1 + http://entsoe.eu/CIM/EquipmentCore/3/1 + http://entsoe.eu/CIM/EquipmentOperation/3/1 + powsybl.org + + + 0 + + + + 0 + + + + 0 + + + + 1 + + + + 6 + + + + 7 + + + + 8 + + + + 9 + + + + 10 + + + + VL1_400_BBS + + + 1 + + + LOAD + + + 1 + + + line + + + 1 + + + line + + + 2 + + + VL1_15_BBS + + + 1 + + + 2WT + + + 1 + + + 2WT + + + 2 + + + GEN + + + 1 + + + VL2_400_BBS3 + + + 1 + + + VL2_400_BBS1 + + + 1 + + + VL2_400_BBS2 + + + 1 + + + VL2_400_COUPLER_BBS2_BBS3 + + + 1 + + + VL2_400_COUPLER_BBS2_BBS3 + + + 2 + + + VL2_400_DISCONNECTOR_23a + + + 1 + + + VL2_400_DISCONNECTOR_23a + + + 2 + + + VL2_400_DISCONNECTOR_23b + + + 1 + + + VL2_400_DISCONNECTOR_23b + + + 2 + + + VL2_400_COUPLER_BBS1_BBS3 + + + 1 + + + VL2_400_COUPLER_BBS1_BBS3 + + + 2 + + + VL2_400_DISCONNECTOR_13a + + + 1 + + + VL2_400_DISCONNECTOR_13a + + + 2 + + + VL2_400_DISCONNECTOR_13b + + + 1 + + + VL2_400_DISCONNECTOR_13b + + + 2 + + + VL2_400_COUPLER_BBS2_BBS3 + + false + true + + + VL2_400_DISCONNECTOR_23a + + false + false + + + VL2_400_DISCONNECTOR_23b + + false + false + + + VL2_400_COUPLER_BBS1_BBS3 + + false + true + + + VL2_400_DISCONNECTOR_13a + + false + false + + + VL2_400_DISCONNECTOR_13b + + false + false + + + default region + + + default region + + + + S1 + + + + S2 + + + + 400 + 400 + + + VL1_400 + + + + + 15 + 15 + + + VL1_15 + + + + + VL2_400 + + + + + VL1_400_BBS + + + + + VL1_15_BBS + + + + + VL2_400_BBS1 + + + + + VL2_400_BBS2 + + + + + VL2_400_BBS3 + + + + + LOAD + + + + test Load Area + + + test SubLoad Area + + + + RC_GEN + + + + + GEN + + + + -3.402823E38 + 3.402823E38 + 179769313486231570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 + + + + GU_GEN + 0 + 500 + 100 + + + + line + 0.1 + 1 + 0.000002 + + + + 2WT + + + + 2WT_1 + 1 + 0.00140625 + 0.028125 + 0.00071111111111 + 0.00071111111111 + 100 + 15 + + + + + + 2WT_2 + 2 + 0 + 0 + 0 + 0 + 100 + 400 + + + + + diff --git a/cgmes/cgmes-conversion/src/test/resources/issues/voltage-regulating-terminal-at-busbar-section/issue_3560_CGMES_SSH.xml b/cgmes/cgmes-conversion/src/test/resources/issues/voltage-regulating-terminal-at-busbar-section/issue_3560_CGMES_SSH.xml new file mode 100644 index 00000000000..ed3d3867840 --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/issues/voltage-regulating-terminal-at-busbar-section/issue_3560_CGMES_SSH.xml @@ -0,0 +1,117 @@ + + + + 2025-11-25T12:06:35Z + 2025-11-25T12:06:36Z + SSH Model + 1 + + http://entsoe.eu/CIM/SteadyStateHypothesis/1/1 + powsybl.org + + + 100 + 10 + + + true + -100 + 0 + 0 + + + + false + true + 0 + 400 + + + + false + + + false + + + false + + + false + + + false + + + false + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + + true + + diff --git a/cgmes/cgmes-conversion/src/test/resources/issues/voltage-regulating-terminal-at-busbar-section/issue_3560_CGMES_SV.xml b/cgmes/cgmes-conversion/src/test/resources/issues/voltage-regulating-terminal-at-busbar-section/issue_3560_CGMES_SV.xml new file mode 100644 index 00000000000..e1818336028 --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/issues/voltage-regulating-terminal-at-busbar-section/issue_3560_CGMES_SV.xml @@ -0,0 +1,174 @@ + + + + 2025-11-25T12:06:35Z + 2025-11-25T12:06:36Z + SV Model + 1 + + + http://entsoe.eu/CIM/StateVariables/4/1 + powsybl.org + + + 0_TI + + converged + + + + + + + + 0.71122754359187 + 15.03066126293102 + + + + -0.03545309244288 + 400 + + + + 0 + 400.0496765855606 + + + + -0.03545309244288 + 400 + + + + -0.03545309244288 + 400 + + + + 100 + 10 + + + + -100.22978382656605 + -10.84411096204798 + + + + 100.22978435978061 + 10.84411096204798 + + + + -100.00604440346368 + -9.7430621205252 + + + + 100.00631051598157 + 9.74306541624976 + + + + -100.00000000000284 + -10.00000000001364 + + + + -0.00000000000284 + -0.00000000001364 + + + + 0.00000000000284 + 0.00000000001364 + + + + 0.00000000000284 + 0.00000000001364 + + + + -0.00000000000284 + -0.00000000001364 + + + + -0.00000000000284 + -0.00000000001364 + + + + 0.00000000000284 + 0.00000000001364 + + + + -0.00000000000284 + -0.00000000001364 + + + + 0.00000000000284 + 0.00000000001364 + + + + -0.00000000000284 + -0.00000000001364 + + + + 0.00000000000284 + 0.00000000001364 + + + + -0.00000000000284 + -0.00000000001364 + + + + 0.00000000000284 + 0.00000000001364 + + + + true + + + + true + + + + true + + + + true + + + + true + + + + true + + + + true + + + + true + + + + true + + + diff --git a/cgmes/cgmes-conversion/src/test/resources/issues/voltage-regulating-terminal-at-busbar-section/issue_3560_CGMES_TP.xml b/cgmes/cgmes-conversion/src/test/resources/issues/voltage-regulating-terminal-at-busbar-section/issue_3560_CGMES_TP.xml new file mode 100644 index 00000000000..8e137eaef7c --- /dev/null +++ b/cgmes/cgmes-conversion/src/test/resources/issues/voltage-regulating-terminal-at-busbar-section/issue_3560_CGMES_TP.xml @@ -0,0 +1,106 @@ + + + + 2025-11-25T12:06:35Z + 2025-11-25T12:06:36Z + TP Model + 1 + + http://entsoe.eu/CIM/Topology/4/1 + powsybl.org + + + VL1_400_0 + + + + + VL1_15_0 + + + + + VL2_400_0 + + + + + VL2_400_1 + + + + + VL2_400_7 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +