From 063574d5b9fdba0a6f9dbb6a41ca68ee3597b922 Mon Sep 17 00:00:00 2001 From: Peter Mitri Date: Fri, 30 Aug 2024 15:13:15 +0200 Subject: [PATCH] Backport CNE patch from PR #1115 Signed-off-by: Peter Mitri --- .../data/swecneexporter/SweCneUtil.java | 20 +++++ .../SweMonitoredSeriesCreator.java | 34 ++++--- .../data/swecneexporter/TieLineTest.java | 88 +++++++++++++++++++ .../SweTestCaseWith12NodesAndXnodes.uct | 42 +++++++++ 4 files changed, 173 insertions(+), 11 deletions(-) create mode 100644 data/result-exporter/swe-cne-exporter/src/test/java/com/powsybl/openrao/data/swecneexporter/TieLineTest.java create mode 100644 data/result-exporter/swe-cne-exporter/src/test/resources/SweTestCaseWith12NodesAndXnodes.uct diff --git a/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCneUtil.java b/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCneUtil.java index 59bfef5ab1..bad01c9725 100644 --- a/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCneUtil.java +++ b/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCneUtil.java @@ -7,6 +7,11 @@ package com.powsybl.openrao.data.swecneexporter; +import com.powsybl.iidm.network.Branch; +import com.powsybl.iidm.network.Country; +import com.powsybl.iidm.network.Substation; +import com.powsybl.iidm.network.TwoSides; +import com.powsybl.openrao.commons.OpenRaoException; import com.powsybl.openrao.data.swecneexporter.xsd.AreaIDString; import com.powsybl.openrao.data.swecneexporter.xsd.ESMPDateTimeInterval; import com.powsybl.openrao.data.swecneexporter.xsd.PartyIDString; @@ -76,4 +81,19 @@ public static AreaIDString createAreaIDString(String codingScheme, String value) areaIDString.setValue(cutString(value, 16)); return areaIDString; } + + public static Country getOperatorCountry(String operator) { + return switch (operator) { + case "RTE" -> Country.FR; + case "REE" -> Country.ES; + case "REN" -> Country.PT; + default -> throw new OpenRaoException(String.format("Unknown operator in SWE region: \"%s\"", operator)); + }; + } + + public static Country getBranchCountry(Branch branch, TwoSides side) { + return branch.getTerminal(side).getVoltageLevel().getSubstation() + .flatMap(Substation::getCountry) + .orElseThrow(() -> new OpenRaoException(String.format("Cannot figure out country of branch \"%s\" on side %s", branch.getId(), side))); + } } diff --git a/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweMonitoredSeriesCreator.java b/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweMonitoredSeriesCreator.java index 44c5f387a3..5eae563cc9 100644 --- a/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweMonitoredSeriesCreator.java +++ b/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweMonitoredSeriesCreator.java @@ -7,13 +7,13 @@ package com.powsybl.openrao.data.swecneexporter; +import com.powsybl.iidm.network.*; import com.powsybl.openrao.commons.OpenRaoException; import com.powsybl.openrao.commons.Unit; import com.powsybl.contingency.Contingency; import com.powsybl.openrao.data.cracapi.Crac; import com.powsybl.openrao.data.cracapi.Instant; import com.powsybl.openrao.data.cracapi.cnec.FlowCnec; -import com.powsybl.iidm.network.TwoSides; import com.powsybl.openrao.data.craccreation.creator.cim.craccreator.CimCracCreationContext; import com.powsybl.openrao.data.craccreation.creator.cim.craccreator.CnecCreationContext; import com.powsybl.openrao.data.craccreation.creator.cim.craccreator.MeasurementCreationContext; @@ -21,7 +21,6 @@ import com.powsybl.openrao.data.swecneexporter.xsd.Analog; import com.powsybl.openrao.data.swecneexporter.xsd.MonitoredRegisteredResource; import com.powsybl.openrao.data.swecneexporter.xsd.MonitoredSeries; -import com.powsybl.iidm.network.Branch; import java.util.*; @@ -68,10 +67,7 @@ private void prepareMap() { cnecCreationContextsMap.computeIfAbsent(contingency, c -> new TreeMap<>(Comparator.comparing(MonitoredSeriesCreationContext::getNativeId))); cnecCreationContextsMap.get(contingency).computeIfAbsent(monitoredSeriesCreationContext, cc -> new TreeSet<>(Comparator.comparing(CnecCreationContext::getCreatedCnecId))); cnecCreationContextsMap.get(contingency).get(monitoredSeriesCreationContext).add(cnecCreationContext); - } - ) - ) - ); + }))); } public List generateMonitoredSeries(Contingency contingency) { @@ -140,9 +136,7 @@ private MonitoredSeries generateMonitoredSeriesFromScratch(MonitoredSeriesCreati MonitoredRegisteredResource registeredResource = new MonitoredRegisteredResource(); registeredResource.setMRID(SweCneUtil.createResourceIDString(A02_CODING_SCHEME, monitoredSeriesCreationContext.getNativeResourceId())); registeredResource.setName(monitoredSeriesCreationContext.getNativeResourceName()); - Branch branch = sweCneHelper.getNetwork().getBranch(cnec.getNetworkElement().getId()); - registeredResource.setInAggregateNodeMRID(SweCneUtil.createResourceIDString(A02_CODING_SCHEME, branch.getTerminal1().getVoltageLevel().getId())); - registeredResource.setOutAggregateNodeMRID(SweCneUtil.createResourceIDString(A02_CODING_SCHEME, branch.getTerminal2().getVoltageLevel().getId())); + setInOutAggregateNodes(cnec.getNetworkElement().getId(), monitoredSeriesCreationContext.getNativeId(), registeredResource); if (includeMeasurements) { Analog flow = new Analog(); @@ -158,8 +152,8 @@ private MonitoredSeries generateMonitoredSeriesFromScratch(MonitoredSeriesCreati threshold.setUnitSymbol(AMP_UNIT_SYMBOL); TwoSides side = cnec.getMonitoredSides().contains(TwoSides.ONE) ? TwoSides.ONE : cnec.getMonitoredSides().iterator().next(); float roundedThreshold = Math.round(Math.min( - Math.abs(cnec.getLowerBound(side, Unit.AMPERE).orElse(Double.POSITIVE_INFINITY)), - Math.abs(cnec.getUpperBound(side, Unit.AMPERE).orElse(Double.NEGATIVE_INFINITY)))); + Math.abs(cnec.getLowerBound(side, Unit.AMPERE).orElse(Double.POSITIVE_INFINITY)), + Math.abs(cnec.getUpperBound(side, Unit.AMPERE).orElse(Double.NEGATIVE_INFINITY)))); threshold.setPositiveFlowIn(roundedFlow >= 0 ? DIRECT_POSITIVE_FLOW_IN : OPPOSITE_POSITIVE_FLOW_IN); threshold.setAnalogValuesValue(Math.abs(roundedThreshold)); registeredResource.getMeasurements().add(threshold); @@ -169,6 +163,24 @@ private MonitoredSeries generateMonitoredSeriesFromScratch(MonitoredSeriesCreati return monitoredSeries; } + void setInOutAggregateNodes(String networkElementId, String monitoredSeriesId, MonitoredRegisteredResource registeredResource) { + Branch branch = sweCneHelper.getNetwork().getBranch(networkElementId); + if (branch instanceof TieLine tieLine && tieLine.getDanglingLine1().hasProperty("CGMES.TopologicalNode_Boundary")) { + Country cnecOperatorCountry = SweCneUtil.getOperatorCountry(monitoredSeriesId.substring(0, 3)); + String xNodeMRId = tieLine.getDanglingLine1().getProperty("CGMES.TopologicalNode_Boundary"); + if (SweCneUtil.getBranchCountry(branch, TwoSides.ONE).equals(cnecOperatorCountry)) { + registeredResource.setInAggregateNodeMRID(SweCneUtil.createResourceIDString(A02_CODING_SCHEME, branch.getTerminal1().getVoltageLevel().getId())); + registeredResource.setOutAggregateNodeMRID(SweCneUtil.createResourceIDString(A02_CODING_SCHEME, xNodeMRId)); + } else { + registeredResource.setInAggregateNodeMRID(SweCneUtil.createResourceIDString(A02_CODING_SCHEME, xNodeMRId)); + registeredResource.setOutAggregateNodeMRID(SweCneUtil.createResourceIDString(A02_CODING_SCHEME, branch.getTerminal2().getVoltageLevel().getId())); + } + } else { + registeredResource.setInAggregateNodeMRID(SweCneUtil.createResourceIDString(A02_CODING_SCHEME, branch.getTerminal1().getVoltageLevel().getId())); + registeredResource.setOutAggregateNodeMRID(SweCneUtil.createResourceIDString(A02_CODING_SCHEME, branch.getTerminal2().getVoltageLevel().getId())); + } + } + private String getThresholdMeasurementType(FlowCnec cnec) { switch (cnec.getState().getInstant().getKind()) { case PREVENTIVE: diff --git a/data/result-exporter/swe-cne-exporter/src/test/java/com/powsybl/openrao/data/swecneexporter/TieLineTest.java b/data/result-exporter/swe-cne-exporter/src/test/java/com/powsybl/openrao/data/swecneexporter/TieLineTest.java new file mode 100644 index 0000000000..09836de622 --- /dev/null +++ b/data/result-exporter/swe-cne-exporter/src/test/java/com/powsybl/openrao/data/swecneexporter/TieLineTest.java @@ -0,0 +1,88 @@ +/* + * 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/. + */ + +package com.powsybl.openrao.data.swecneexporter; + +import com.powsybl.iidm.network.Network; +import com.powsybl.openrao.data.craccreation.creator.cim.craccreator.CimCracCreationContext; +import com.powsybl.openrao.data.swecneexporter.xsd.MonitoredRegisteredResource; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Tests for tie-line CNECs results handling + * @author Peter Mitri {@literal } + */ +public class TieLineTest { + private Network network; + private SweMonitoredSeriesCreator monitoredSeriesCreator; + + @BeforeEach + void setUp() { + network = Network.read("SweTestCaseWith12NodesAndXnodes.uct", getClass().getResourceAsStream("/SweTestCaseWith12NodesAndXnodes.uct")); + network.getDanglingLine("FFR2AA1 XES_FR11 1").setProperty("CGMES.TopologicalNode_Boundary", "XES_FR11_mRID"); + network.getDanglingLine("XES_FR11 EES3AA1 1").setProperty("CGMES.TopologicalNode_Boundary", "XES_FR11_mRID"); + network.getDanglingLine("EES2AA1 XES_PT11 1").setProperty("CGMES.TopologicalNode_Boundary", "XES_PT11_mRID"); + network.getDanglingLine("XES_PT11 PPT3AA1 1").setProperty("CGMES.TopologicalNode_Boundary", "XES_PT11_mRID"); + + SweCneHelper helper = Mockito.mock(SweCneHelper.class); + Mockito.when(helper.getNetwork()).thenReturn(network); + + monitoredSeriesCreator = new SweMonitoredSeriesCreator(helper, Mockito.mock(CimCracCreationContext.class)); + } + + @Test + void testSetInOutAggregateNodesFrEs() { + MonitoredRegisteredResource rr = new MonitoredRegisteredResource(); + + monitoredSeriesCreator.setInOutAggregateNodes("FFR2AA1 XES_FR11 1 + XES_FR11 EES3AA1 1", "RTE_blabla", rr); + assertEquals("FFR2AA1", rr.getInAggregateNodeMRID().getValue()); + assertEquals("XES_FR11_mRID", rr.getOutAggregateNodeMRID().getValue()); + + monitoredSeriesCreator.setInOutAggregateNodes("FFR2AA1 XES_FR11 1 + XES_FR11 EES3AA1 1", "REEejcnc", rr); + assertEquals("XES_FR11_mRID", rr.getInAggregateNodeMRID().getValue()); + assertEquals("EES3AA1", rr.getOutAggregateNodeMRID().getValue()); + } + + @Test + void testSetInOutAggregateNodesPtEs() { + MonitoredRegisteredResource rr = new MonitoredRegisteredResource(); + + monitoredSeriesCreator.setInOutAggregateNodes("EES2AA1 XES_PT11 1 + XES_PT11 PPT3AA1 1", "REN_blabla", rr); + assertEquals("XES_PT11_mRID", rr.getInAggregateNodeMRID().getValue()); + assertEquals("PPT3AA1", rr.getOutAggregateNodeMRID().getValue()); + + monitoredSeriesCreator.setInOutAggregateNodes("EES2AA1 XES_PT11 1 + XES_PT11 PPT3AA1 1", "REE", rr); + assertEquals("EES2AA1", rr.getInAggregateNodeMRID().getValue()); + assertEquals("XES_PT11_mRID", rr.getOutAggregateNodeMRID().getValue()); + } + + @Test + void testSetInOutAggregateNodesNoProperty() { + MonitoredRegisteredResource rr = new MonitoredRegisteredResource(); + network.getDanglingLine("EES2AA1 XES_PT11 1").removeProperty("CGMES.TopologicalNode_Boundary"); + + monitoredSeriesCreator.setInOutAggregateNodes("EES2AA1 XES_PT11 1 + XES_PT11 PPT3AA1 1", "REN_blabla", rr); + assertEquals("EES2AA1", rr.getInAggregateNodeMRID().getValue()); + assertEquals("PPT3AA1", rr.getOutAggregateNodeMRID().getValue()); + + monitoredSeriesCreator.setInOutAggregateNodes("EES2AA1 XES_PT11 1 + XES_PT11 PPT3AA1 1", "REE", rr); + assertEquals("EES2AA1", rr.getInAggregateNodeMRID().getValue()); + assertEquals("PPT3AA1", rr.getOutAggregateNodeMRID().getValue()); + } + + @Test + void testSetInOutAggregateNodesInternalLine() { + MonitoredRegisteredResource rr = new MonitoredRegisteredResource(); + monitoredSeriesCreator.setInOutAggregateNodes("EES1AA1 EES3AA1 1", "REN_blabla", rr); + assertEquals("EES1AA1", rr.getInAggregateNodeMRID().getValue()); + assertEquals("EES3AA1", rr.getOutAggregateNodeMRID().getValue()); + } +} diff --git a/data/result-exporter/swe-cne-exporter/src/test/resources/SweTestCaseWith12NodesAndXnodes.uct b/data/result-exporter/swe-cne-exporter/src/test/resources/SweTestCaseWith12NodesAndXnodes.uct new file mode 100644 index 0000000000..5b4facd339 --- /dev/null +++ b/data/result-exporter/swe-cne-exporter/src/test/resources/SweTestCaseWith12NodesAndXnodes.uct @@ -0,0 +1,42 @@ +##C 2007.05.01 +##N +##ZBE +BBE1AA1 BE1 0 2 400.00 2500.00 0.00000 -1500.0 0.00000 9000.00 -9000.0 9000.00 -9000.0 +BBE2AA1 BE2 0 2 400.00 1000.00 0.00000 -3000.0 0.00000 9000.00 -9000.0 9000.00 -9000.0 +BBE3AA1 BE3 0 2 400.00 1500.00 0.00000 -2500.0 0.00000 9000.00 -9000.0 9000.00 -9000.0 +##ZES +EES1AA1 ES1 0 2 400.00 3500.00 0.00000 -2500.0 0.00000 9000.00 -9000.0 9000.00 -9000.0 +EES2AA1 ES2 0 2 400.00 3000.00 0.00000 -2000.0 0.00000 9000.00 -9000.0 9000.00 -9000.0 +EES3AA1 ES3 0 2 400.00 2000.00 0.00000 -1500.0 0.00000 9000.00 -9000.0 9000.00 -9000.0 +##ZFR +FFR1AA1 FR1 0 2 400.00 1000.00 0.00000 -2000.0 0.00000 9000.00 -9000.0 9000.00 -9000.0 +FFR2AA1 FR2 0 2 400.00 3500.00 0.00000 -2000.0 0.00000 9000.00 -9000.0 9000.00 -9000.0 +FFR3AA1 FR3 0 2 400.00 1500.00 0.00000 -3000.0 0.00000 9000.00 -9000.0 9000.00 -9000.0 +##ZPT +PPT1AA1 PT1 0 2 400.00 1000.00 0.00000 -1500.0 0.00000 9000.00 -9000.0 9000.00 -9000.0 +PPT2AA1 PT2 0 2 400.00 1000.00 0.00000 -500.00 0.00000 9000.00 -9000.0 9000.00 -9000.0 +PPT3AA1 PT3 0 2 400.00 2500.00 0.00000 -2000.0 0.00000 9000.00 -9000.0 9000.00 -9000.0 +##ZXX +XES_PT11 0 0 0.00000 0.00000 0.00000 0.00000 +XES_FR11 0 0 0.00000 0.00000 0.00000 0.00000 +##L +BBE1AA1 BBE2AA1 1 0 0.0000 10.000 0.000000 5000 +BBE1AA1 BBE3AA1 1 0 0.0000 10.000 0.000000 5000 +FFR1AA1 FFR2AA1 1 0 0.0000 10.000 0.000000 5000 +FFR1AA1 FFR3AA1 1 0 0.0000 10.000 0.000000 5000 +FFR2AA1 FFR3AA1 1 0 0.0000 10.000 0.000000 5000 +EES1AA1 EES2AA1 1 0 0.0000 10.000 0.000000 5000 +EES1AA1 EES3AA1 1 0 0.0000 10.000 0.000000 5000 +EES2AA1 EES3AA1 1 0 0.0000 10.000 0.000000 5000 +PPT1AA1 PPT2AA1 1 0 0.0000 10.000 0.000000 5000 +PPT1AA1 PPT3AA1 1 0 0.0000 10.000 0.000000 5000 +PPT2AA1 PPT3AA1 1 0 0.0000 10.000 0.000000 5000 +FFR2AA1 XES_FR11 1 0 0.0000 10.000 0.000000 5000 +XES_FR11 EES3AA1 1 0 0.0000 10.000 0.000000 5000 +EES2AA1 XES_PT11 1 0 0.0000 10.000 0.000000 5000 +XES_PT11 PPT3AA1 1 0 0.0000 10.000 0.000000 5000 +BBE2AA1 FFR3AA1 1 0 0.0000 10.000 0.000000 5000 +##T +BBE2AA1 BBE3AA1 1 0 400.0 400.0 1000. 0.0000 10.000 0.000000 0.0 5000 PST +##R +BBE2AA1 BBE3AA1 1 -0.68 90.00 16 0 SYMM