From ec14273ddfd68f918f6139526cbbe354f49a4cb3 Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Tue, 27 Feb 2024 14:59:23 +0100 Subject: [PATCH 01/13] Check parameters Signed-off-by: Thomas Bouquet --- .../openrao/data/raoresultimpl/RaoResultImpl.java | 8 +++++++- .../anglemonitoring/RaoResultWithAngleMonitoring.java | 3 +++ .../RaoResultWithVoltageMonitoring.java | 3 +++ .../result/impl/OneStateOnlyRaoResultImpl.java | 11 ++++++++++- .../impl/PreventiveAndCurativesRaoResultImpl.java | 11 ++++++++++- 5 files changed, 33 insertions(+), 3 deletions(-) diff --git a/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java b/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java index e0da0a9d9d..f1f4b0abe1 100644 --- a/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java +++ b/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java @@ -344,7 +344,12 @@ private boolean instantHasNoNegativeMargin(Instant optimizedInstant, PhysicalPar for (PhysicalParameter physicalParameter : Set.of(u)) { switch (physicalParameter) { case ANGLE -> { - if (angleCnecResults.keySet().stream() + // TODO: check that all CNECs have a result for the given optimized instant? + if (!crac.getAngleCnecs().stream().allMatch(angleCnecResults::containsKey)) { + throw new OpenRaoException("RaoResult does not contain angle values for all AngleCNECs, security status for physical parameter ANGLE is unknown"); + } + // TODO: lancer cucumber + if (crac.getAngleCnecs().stream() .mapToDouble(cnec -> getMargin(optimizedInstant, cnec, Unit.DEGREE)) .filter(margin -> !Double.isNaN(margin)) .anyMatch(margin -> margin < 0)) { @@ -357,6 +362,7 @@ private boolean instantHasNoNegativeMargin(Instant optimizedInstant, PhysicalPar } } case VOLTAGE -> { + // TODO: check that all CNECs have a result for the given optimized instant? if (voltageCnecResults.keySet().stream() .mapToDouble(cnec -> getMargin(optimizedInstant, cnec, Unit.KILOVOLT)) .filter(margin -> !Double.isNaN(margin)) diff --git a/monitoring/angle-monitoring/src/main/java/com/powsybl/openrao/monitoring/anglemonitoring/RaoResultWithAngleMonitoring.java b/monitoring/angle-monitoring/src/main/java/com/powsybl/openrao/monitoring/anglemonitoring/RaoResultWithAngleMonitoring.java index a5e8f57e3d..0cf1e9f6c9 100644 --- a/monitoring/angle-monitoring/src/main/java/com/powsybl/openrao/monitoring/anglemonitoring/RaoResultWithAngleMonitoring.java +++ b/monitoring/angle-monitoring/src/main/java/com/powsybl/openrao/monitoring/anglemonitoring/RaoResultWithAngleMonitoring.java @@ -18,6 +18,7 @@ import com.powsybl.openrao.data.raoresultapi.RaoResult; import com.powsybl.openrao.data.raoresultapi.RaoResultClone; +import java.util.Arrays; import java.util.HashSet; import java.util.Set; @@ -84,6 +85,7 @@ public boolean isActivatedDuringState(State state, NetworkAction networkAction) @Override public boolean isSecure(Instant instant, PhysicalParameter... u) { + // TODO: remove ANGLE from u if (Set.of(u).contains(PhysicalParameter.ANGLE)) { return raoResult.isSecure(instant, u) && angleMonitoringResult.isSecure(); } else { @@ -93,6 +95,7 @@ public boolean isSecure(Instant instant, PhysicalParameter... u) { @Override public boolean isSecure(PhysicalParameter... u) { + // TODO: remove ANGLE from u if (Set.of(u).contains(PhysicalParameter.ANGLE)) { return raoResult.isSecure(u) && angleMonitoringResult.isSecure(); } else { diff --git a/monitoring/voltage-monitoring/src/main/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoring.java b/monitoring/voltage-monitoring/src/main/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoring.java index 1ac1f190ba..49d7f48ada 100644 --- a/monitoring/voltage-monitoring/src/main/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoring.java +++ b/monitoring/voltage-monitoring/src/main/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoring.java @@ -18,6 +18,7 @@ import com.powsybl.openrao.data.raoresultapi.RaoResult; import com.powsybl.openrao.data.raoresultapi.RaoResultClone; +import java.util.Arrays; import java.util.HashSet; import java.util.Set; @@ -92,6 +93,7 @@ public boolean isActivatedDuringState(State state, NetworkAction networkAction) @Override public boolean isSecure(Instant instant, PhysicalParameter... u) { + // TODO: remove VOLTAGE from u if (Set.of(u).contains(PhysicalParameter.VOLTAGE)) { return raoResult.isSecure(instant, u) && voltageMonitoringResult.isSecure(); } else { @@ -101,6 +103,7 @@ public boolean isSecure(Instant instant, PhysicalParameter... u) { @Override public boolean isSecure(PhysicalParameter... u) { + // TODO: remove VOLTAGE from u if (Set.of(u).contains(PhysicalParameter.VOLTAGE)) { return raoResult.isSecure(u) && voltageMonitoringResult.isSecure(); } else { diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImpl.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImpl.java index 6d17a81f92..f3d52fe962 100644 --- a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImpl.java +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImpl.java @@ -302,7 +302,16 @@ public boolean isSecure(Instant optimizedInstant, PhysicalParameter... u) { if (ComputationStatus.FAILURE.equals(getComputationStatus())) { return false; } - return getFunctionalCost(optimizedInstant) < 0; + if (Arrays.stream(u).noneMatch(PhysicalParameter.FLOW::equals)) { + throw new OpenRaoException("This is a flow RaoResult, isSecure is available for FLOW physical parameter"); + } + if (getFunctionalCost(optimizedInstant) >= 0) { + return false; + } + if (Arrays.stream(u).anyMatch(physicalParameter -> !PhysicalParameter.FLOW.equals(physicalParameter))) { + throw new OpenRaoException("This is a flow RaoResult, flows are secure but other physical parameters' security status is unknown"); + } + return true; } @Override diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/PreventiveAndCurativesRaoResultImpl.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/PreventiveAndCurativesRaoResultImpl.java index 1e674d9b44..d12b80fa18 100644 --- a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/PreventiveAndCurativesRaoResultImpl.java +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/PreventiveAndCurativesRaoResultImpl.java @@ -619,7 +619,16 @@ public boolean isSecure(Instant optimizedInstant, PhysicalParameter... u) { if (ComputationStatus.FAILURE.equals(getComputationStatus())) { return false; } - return getFunctionalCost(optimizedInstant) < 0; + if (Arrays.stream(u).noneMatch(PhysicalParameter.FLOW::equals)) { + throw new OpenRaoException("This is a flow RaoResult, isSecure is available for FLOW physical parameter"); + } + if (getFunctionalCost(optimizedInstant) >= 0) { + return false; + } + if (Arrays.stream(u).anyMatch(physicalParameter -> !PhysicalParameter.FLOW.equals(physicalParameter))) { + throw new OpenRaoException("This is a flow RaoResult, flows are secure but other physical parameters' security status is unknown"); + } + return true; } @Override From 2994c8239a0d0c9616d60691513043dcb630cc60 Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Wed, 28 Feb 2024 10:55:38 +0100 Subject: [PATCH 02/13] Check physical parameters in isSecure Signed-off-by: Thomas Bouquet --- .../powsybl/openrao/data/cracapi/Instant.java | 8 +++++++ .../data/raoresultimpl/RaoResultImpl.java | 13 +++++++--- .../data/raoresultimpl/RaoResultImplTest.java | 8 +++++++ .../RaoResultWithAngleMonitoring.java | 22 +++++++++-------- .../RaoResultWithAngleMonitoringTest.java | 8 +++---- .../RaoResultWithVoltageMonitoring.java | 24 ++++++++++--------- .../RaoResultWithVoltageMonitoringTest.java | 8 +++---- 7 files changed, 59 insertions(+), 32 deletions(-) diff --git a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/Instant.java b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/Instant.java index f982797a61..6ec442cb47 100644 --- a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/Instant.java +++ b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/Instant.java @@ -36,4 +36,12 @@ public interface Instant extends Identifiable, Comparable { boolean isAuto(); boolean isCurative(); + + // TODO: test this + static Instant min(Instant instant1, Instant instant2) { + if (instant1 == null || instant2 == null) { + return null; + } + return instant1.comesBefore(instant2) ? instant1 : instant2; + } } diff --git a/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java b/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java index f1f4b0abe1..d39a4419c9 100644 --- a/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java +++ b/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java @@ -344,7 +344,12 @@ private boolean instantHasNoNegativeMargin(Instant optimizedInstant, PhysicalPar for (PhysicalParameter physicalParameter : Set.of(u)) { switch (physicalParameter) { case ANGLE -> { - // TODO: check that all CNECs have a result for the given optimized instant? + // TODO: check instant + // TODO: test without min and if it does not work add min + // TODO: create JSON RaoResult with anlgeCNECs prev + cur (prev -> prev / cur -> prev + cur) + // if (crac.getAngleCnecs().stream() + // .mapToDouble(cnec -> getMargin(Instant.min(optimizedInstant, cnec.getState().getInstant()), cnec, Unit.DEGREE)) + // .anyMatch(Double::isNaN)) { } if (!crac.getAngleCnecs().stream().allMatch(angleCnecResults::containsKey)) { throw new OpenRaoException("RaoResult does not contain angle values for all AngleCNECs, security status for physical parameter ANGLE is unknown"); } @@ -362,8 +367,10 @@ private boolean instantHasNoNegativeMargin(Instant optimizedInstant, PhysicalPar } } case VOLTAGE -> { - // TODO: check that all CNECs have a result for the given optimized instant? - if (voltageCnecResults.keySet().stream() + if (!crac.getVoltageCnecs().stream().allMatch(voltageCnecResults::containsKey)) { + throw new OpenRaoException("RaoResult does not contain voltage values for all VoltageCNECs, security status for physical parameter VOLTAGE is unknown"); + } + if (crac.getVoltageCnecs().stream() .mapToDouble(cnec -> getMargin(optimizedInstant, cnec, Unit.KILOVOLT)) .filter(margin -> !Double.isNaN(margin)) .anyMatch(margin -> margin < 0)) { diff --git a/data/rao-result/rao-result-impl/src/test/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImplTest.java b/data/rao-result/rao-result-impl/src/test/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImplTest.java index 548d9e021e..8241da653f 100644 --- a/data/rao-result/rao-result-impl/src/test/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImplTest.java +++ b/data/rao-result/rao-result-impl/src/test/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImplTest.java @@ -332,4 +332,12 @@ void testIsSecureDependsOnOptimizationState() { assertTrue(raoResult.isSecure(curativeInstant, PhysicalParameter.FLOW, PhysicalParameter.ANGLE, PhysicalParameter.VOLTAGE)); assertTrue(raoResult.isSecure()); } + + @Test + void comprehensiveRaoResultWithAllThreeTypesOfCnecs() { + // TODO: crac with FlowCNECs, VoltageCNECs, AngleCNECs x3 (prev, out, cur) + // TODO: raoResult with all instants + // TODO: results after PRAs? + // TODO: check throw if instant does not exist + } } diff --git a/monitoring/angle-monitoring/src/main/java/com/powsybl/openrao/monitoring/anglemonitoring/RaoResultWithAngleMonitoring.java b/monitoring/angle-monitoring/src/main/java/com/powsybl/openrao/monitoring/anglemonitoring/RaoResultWithAngleMonitoring.java index 0cf1e9f6c9..144fe2c630 100644 --- a/monitoring/angle-monitoring/src/main/java/com/powsybl/openrao/monitoring/anglemonitoring/RaoResultWithAngleMonitoring.java +++ b/monitoring/angle-monitoring/src/main/java/com/powsybl/openrao/monitoring/anglemonitoring/RaoResultWithAngleMonitoring.java @@ -18,9 +18,11 @@ import com.powsybl.openrao.data.raoresultapi.RaoResult; import com.powsybl.openrao.data.raoresultapi.RaoResultClone; -import java.util.Arrays; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; +import java.util.stream.Stream; /** * class that enhances rao result with angle monitoring results @@ -54,7 +56,7 @@ public double getAngle(Instant optimizationInstant, AngleCnec angleCnec, Unit un if (!unit.equals(Unit.DEGREE)) { throw new OpenRaoException("Unexpected unit for angle monitoring result : " + unit); } - if (!optimizationInstant.isCurative()) { + if (optimizationInstant == null || !optimizationInstant.isCurative()) { throw new OpenRaoException("Unexpected optimization instant for angle monitoring result (only curative instant is supported currently) : " + optimizationInstant); } return angleMonitoringResult.getAngle(angleCnec, unit); @@ -85,21 +87,21 @@ public boolean isActivatedDuringState(State state, NetworkAction networkAction) @Override public boolean isSecure(Instant instant, PhysicalParameter... u) { - // TODO: remove ANGLE from u - if (Set.of(u).contains(PhysicalParameter.ANGLE)) { - return raoResult.isSecure(instant, u) && angleMonitoringResult.isSecure(); + List physicalParameters = new ArrayList<>(Stream.of(u).sorted().toList()); + if (physicalParameters.remove(PhysicalParameter.ANGLE)) { + return raoResult.isSecure(instant, physicalParameters.toArray(new PhysicalParameter[0])) && angleMonitoringResult.isSecure(); } else { - return raoResult.isSecure(instant, u); + return raoResult.isSecure(instant, physicalParameters.toArray(new PhysicalParameter[0])); } } @Override public boolean isSecure(PhysicalParameter... u) { - // TODO: remove ANGLE from u - if (Set.of(u).contains(PhysicalParameter.ANGLE)) { - return raoResult.isSecure(u) && angleMonitoringResult.isSecure(); + List physicalParameters = new ArrayList<>(Stream.of(u).sorted().toList()); + if (physicalParameters.remove(PhysicalParameter.ANGLE)) { + return raoResult.isSecure(physicalParameters.toArray(new PhysicalParameter[0])) && angleMonitoringResult.isSecure(); } else { - return raoResult.isSecure(u); + return raoResult.isSecure(physicalParameters.toArray(new PhysicalParameter[0])); } } diff --git a/monitoring/angle-monitoring/src/test/java/com/powsybl/openrao/monitoring/anglemonitoring/RaoResultWithAngleMonitoringTest.java b/monitoring/angle-monitoring/src/test/java/com/powsybl/openrao/monitoring/anglemonitoring/RaoResultWithAngleMonitoringTest.java index 04ab00d0e3..d8054a9ce8 100644 --- a/monitoring/angle-monitoring/src/test/java/com/powsybl/openrao/monitoring/anglemonitoring/RaoResultWithAngleMonitoringTest.java +++ b/monitoring/angle-monitoring/src/test/java/com/powsybl/openrao/monitoring/anglemonitoring/RaoResultWithAngleMonitoringTest.java @@ -74,8 +74,8 @@ void testIsSecureWhenRaoResultAndAngleMonitoringIsSecure() { RaoResult raoResultWithVoltageMonitoring = new RaoResultWithAngleMonitoring(raoResult, angleMonitoringResult); Mockito.when(raoResult.isSecure()).thenReturn(true); Mockito.when(angleMonitoringResult.isSecure()).thenReturn(true); - Mockito.when(raoResult.isSecure(PhysicalParameter.FLOW, PhysicalParameter.ANGLE)).thenReturn(true); - Mockito.when(raoResult.isSecure(Mockito.any(Instant.class), Mockito.eq(PhysicalParameter.FLOW), Mockito.eq(PhysicalParameter.ANGLE))).thenReturn(true); + Mockito.when(raoResult.isSecure(PhysicalParameter.FLOW)).thenReturn(true); + Mockito.when(raoResult.isSecure(Mockito.any(Instant.class), Mockito.eq(PhysicalParameter.FLOW))).thenReturn(true); assertTrue(raoResultWithVoltageMonitoring.isSecure()); assertTrue(raoResultWithVoltageMonitoring.isSecure(PhysicalParameter.FLOW, PhysicalParameter.ANGLE)); @@ -89,9 +89,9 @@ void testIsSecureWhenRaoResultAndAngleMonitoringUnsecureIfAngleNotChecked() { RaoResult raoResultWithVoltageMonitoring = new RaoResultWithAngleMonitoring(raoResult, angleMonitoringResult); Mockito.when(raoResult.isSecure()).thenReturn(true); Mockito.when(angleMonitoringResult.isSecure()).thenReturn(false); - Mockito.when(raoResult.isSecure(PhysicalParameter.FLOW, PhysicalParameter.ANGLE)).thenReturn(true); + Mockito.when(raoResult.isSecure(PhysicalParameter.FLOW)).thenReturn(true); Mockito.when(raoResult.isSecure(PhysicalParameter.FLOW, PhysicalParameter.VOLTAGE)).thenReturn(true); - Mockito.when(raoResult.isSecure(Mockito.any(Instant.class), Mockito.eq(PhysicalParameter.FLOW), Mockito.eq(PhysicalParameter.ANGLE))).thenReturn(true); + Mockito.when(raoResult.isSecure(Mockito.any(Instant.class), Mockito.eq(PhysicalParameter.FLOW))).thenReturn(true); Mockito.when(raoResult.isSecure(Mockito.any(Instant.class), Mockito.eq(PhysicalParameter.FLOW), Mockito.eq(PhysicalParameter.VOLTAGE))).thenReturn(true); assertFalse(raoResultWithVoltageMonitoring.isSecure()); diff --git a/monitoring/voltage-monitoring/src/main/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoring.java b/monitoring/voltage-monitoring/src/main/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoring.java index 49d7f48ada..982a2ad7ad 100644 --- a/monitoring/voltage-monitoring/src/main/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoring.java +++ b/monitoring/voltage-monitoring/src/main/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoring.java @@ -18,9 +18,11 @@ import com.powsybl.openrao.data.raoresultapi.RaoResult; import com.powsybl.openrao.data.raoresultapi.RaoResultClone; -import java.util.Arrays; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; +import java.util.stream.Stream; /** * class that enhances rao result with voltage monitoring results @@ -51,7 +53,7 @@ public double getVoltage(Instant optimizationInstant, VoltageCnec voltageCnec, U if (!unit.equals(Unit.KILOVOLT)) { throw new OpenRaoException("Unexpected unit for voltage monitoring result : " + unit); } - if (!optimizationInstant.isCurative()) { + if (optimizationInstant == null || !optimizationInstant.isCurative()) { throw new OpenRaoException("Unexpected optimization instant for voltage monitoring result (only curative instant is supported currently) : " + optimizationInstant); } double upperBound = voltageCnec.getUpperBound(unit).orElse(Double.MAX_VALUE); @@ -67,7 +69,7 @@ public double getVoltage(Instant optimizationInstant, VoltageCnec voltageCnec, U @Override public double getMargin(Instant optimizationInstant, VoltageCnec voltageCnec, Unit unit) { - if (!optimizationInstant.isCurative()) { + if (optimizationInstant == null || !optimizationInstant.isCurative()) { throw new OpenRaoException("Unexpected optimization instant for voltage monitoring result (only curative instant is supported currently): " + optimizationInstant); } return Math.min(voltageCnec.getUpperBound(unit).orElse(Double.MAX_VALUE) - voltageMonitoringResult.getMaxVoltage(voltageCnec), @@ -93,21 +95,21 @@ public boolean isActivatedDuringState(State state, NetworkAction networkAction) @Override public boolean isSecure(Instant instant, PhysicalParameter... u) { - // TODO: remove VOLTAGE from u - if (Set.of(u).contains(PhysicalParameter.VOLTAGE)) { - return raoResult.isSecure(instant, u) && voltageMonitoringResult.isSecure(); + List physicalParameters = new ArrayList<>(Stream.of(u).sorted().toList()); + if (physicalParameters.remove(PhysicalParameter.VOLTAGE)) { + return raoResult.isSecure(instant, physicalParameters.toArray(new PhysicalParameter[0])) && voltageMonitoringResult.isSecure(); } else { - return raoResult.isSecure(instant, u); + return raoResult.isSecure(instant, physicalParameters.toArray(new PhysicalParameter[0])); } } @Override public boolean isSecure(PhysicalParameter... u) { - // TODO: remove VOLTAGE from u - if (Set.of(u).contains(PhysicalParameter.VOLTAGE)) { - return raoResult.isSecure(u) && voltageMonitoringResult.isSecure(); + List physicalParameters = new ArrayList<>(Stream.of(u).sorted().toList()); + if (physicalParameters.remove(PhysicalParameter.VOLTAGE)) { + return raoResult.isSecure(physicalParameters.toArray(new PhysicalParameter[0])) && voltageMonitoringResult.isSecure(); } else { - return raoResult.isSecure(u); + return raoResult.isSecure(physicalParameters.toArray(new PhysicalParameter[0])); } } diff --git a/monitoring/voltage-monitoring/src/test/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoringTest.java b/monitoring/voltage-monitoring/src/test/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoringTest.java index bd1e93514a..90dc3566d2 100644 --- a/monitoring/voltage-monitoring/src/test/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoringTest.java +++ b/monitoring/voltage-monitoring/src/test/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoringTest.java @@ -64,8 +64,8 @@ void testIsSecureWhenRaoResultAndVoltageMonitoringIsSecure() { RaoResult raoResultWithVoltageMonitoring = new RaoResultWithVoltageMonitoring(raoResult, voltageMonitoringResult); Mockito.when(raoResult.isSecure()).thenReturn(true); Mockito.when(voltageMonitoringResult.isSecure()).thenReturn(true); - Mockito.when(raoResult.isSecure(PhysicalParameter.FLOW, PhysicalParameter.VOLTAGE)).thenReturn(true); - Mockito.when(raoResult.isSecure(Mockito.any(Instant.class), Mockito.eq(PhysicalParameter.FLOW), Mockito.eq(PhysicalParameter.VOLTAGE))).thenReturn(true); + Mockito.when(raoResult.isSecure(PhysicalParameter.FLOW)).thenReturn(true); + Mockito.when(raoResult.isSecure(Mockito.any(Instant.class), Mockito.eq(PhysicalParameter.FLOW))).thenReturn(true); assertTrue(raoResultWithVoltageMonitoring.isSecure()); assertTrue(raoResultWithVoltageMonitoring.isSecure(PhysicalParameter.FLOW, PhysicalParameter.VOLTAGE)); @@ -79,9 +79,9 @@ void testIsSecureWhenRaoResultAndVoltageMonitoringUnsecureIfVoltageNotChecked() RaoResult raoResultWithVoltageMonitoring = new RaoResultWithVoltageMonitoring(raoResult, voltageMonitoringResult); Mockito.when(raoResult.isSecure()).thenReturn(true); Mockito.when(voltageMonitoringResult.isSecure()).thenReturn(false); - Mockito.when(raoResult.isSecure(PhysicalParameter.FLOW, PhysicalParameter.VOLTAGE)).thenReturn(true); + Mockito.when(raoResult.isSecure(PhysicalParameter.FLOW)).thenReturn(true); Mockito.when(raoResult.isSecure(PhysicalParameter.FLOW, PhysicalParameter.ANGLE)).thenReturn(true); - Mockito.when(raoResult.isSecure(Mockito.any(Instant.class), Mockito.eq(PhysicalParameter.FLOW), Mockito.eq(PhysicalParameter.VOLTAGE))).thenReturn(true); + Mockito.when(raoResult.isSecure(Mockito.any(Instant.class), Mockito.eq(PhysicalParameter.FLOW))).thenReturn(true); Mockito.when(raoResult.isSecure(Mockito.any(Instant.class), Mockito.eq(PhysicalParameter.FLOW), Mockito.eq(PhysicalParameter.ANGLE))).thenReturn(true); assertFalse(raoResultWithVoltageMonitoring.isSecure()); From 5423aa5d499bf879234a983dd07cf47487046e30 Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Fri, 22 Mar 2024 14:02:04 +0100 Subject: [PATCH 03/13] Test Instant.min Signed-off-by: Thomas Bouquet --- .../java/com/powsybl/openrao/data/cracapi/Instant.java | 6 +++++- .../com/powsybl/openrao/data/cracimpl/InstantImpl.java | 5 ----- .../powsybl/openrao/data/cracimpl/InstantImplTest.java | 10 ++++++++++ .../RaoResultWithVoltageMonitoring.java | 1 + 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/Instant.java b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/Instant.java index 6ec442cb47..106d9877cf 100644 --- a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/Instant.java +++ b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/Instant.java @@ -37,7 +37,11 @@ public interface Instant extends Identifiable, Comparable { boolean isCurative(); - // TODO: test this + @Override + default int compareTo(Instant otherInstant) { + return Integer.compare(getOrder(), otherInstant.getOrder()); + } + static Instant min(Instant instant1, Instant instant2) { if (instant1 == null || instant2 == null) { return null; diff --git a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/InstantImpl.java b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/InstantImpl.java index 6a2873c1d4..3b98a28a9f 100644 --- a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/InstantImpl.java +++ b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/InstantImpl.java @@ -106,9 +106,4 @@ public int hashCode() { Instant getInstantBefore() { return previous; } - - @Override - public int compareTo(Instant otherInstant) { - return Integer.compare(getOrder(), otherInstant.getOrder()); - } } diff --git a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/InstantImplTest.java b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/InstantImplTest.java index 433e976c10..31e5b9f423 100644 --- a/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/InstantImplTest.java +++ b/data/crac/crac-impl/src/test/java/com/powsybl/openrao/data/cracimpl/InstantImplTest.java @@ -162,4 +162,14 @@ void testInstantBeforeAfter() { assertFalse(preventiveInstant.comesAfter(preventiveInstant)); } + + @Test + void testMin() { + InstantImpl instant1 = new InstantImpl("instant1", InstantKind.PREVENTIVE, null); + InstantImpl instant2 = new InstantImpl("instant2", InstantKind.CURATIVE, instant1); + assertEquals(instant1, Instant.min(instant1, instant2)); + assertNull(Instant.min(instant1, null)); + assertNull(Instant.min(null, instant2)); + assertNull(Instant.min(null, null)); + } } diff --git a/monitoring/voltage-monitoring/src/main/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoring.java b/monitoring/voltage-monitoring/src/main/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoring.java index 25b3d98a0e..2385c3602d 100644 --- a/monitoring/voltage-monitoring/src/main/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoring.java +++ b/monitoring/voltage-monitoring/src/main/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoring.java @@ -18,6 +18,7 @@ import com.powsybl.openrao.data.raoresultapi.RaoResult; import com.powsybl.openrao.data.raoresultapi.RaoResultClone; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; From 18ab9f225df080c2e5548efd0a3abb9622ed7245 Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Fri, 22 Mar 2024 15:25:31 +0100 Subject: [PATCH 04/13] Exhaustive tests with all 2 types of CNECs Signed-off-by: Thomas Bouquet --- .../data/raoresultimpl/RaoResultImpl.java | 17 +- .../data/raoresultimpl/RaoResultImplTest.java | 161 +++++++++++++++++- .../impl/OneStateOnlyRaoResultImplTest.java | 9 +- 3 files changed, 177 insertions(+), 10 deletions(-) diff --git a/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java b/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java index d39a4419c9..cb721dbb2b 100644 --- a/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java +++ b/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java @@ -347,12 +347,14 @@ private boolean instantHasNoNegativeMargin(Instant optimizedInstant, PhysicalPar // TODO: check instant // TODO: test without min and if it does not work add min // TODO: create JSON RaoResult with anlgeCNECs prev + cur (prev -> prev / cur -> prev + cur) - // if (crac.getAngleCnecs().stream() - // .mapToDouble(cnec -> getMargin(Instant.min(optimizedInstant, cnec.getState().getInstant()), cnec, Unit.DEGREE)) - // .anyMatch(Double::isNaN)) { } - if (!crac.getAngleCnecs().stream().allMatch(angleCnecResults::containsKey)) { + if (crac.getAngleCnecs().stream() + .mapToDouble(cnec -> getMargin(Instant.min(optimizedInstant, cnec.getState().getInstant()), cnec, Unit.DEGREE)) + .anyMatch(Double::isNaN)) { throw new OpenRaoException("RaoResult does not contain angle values for all AngleCNECs, security status for physical parameter ANGLE is unknown"); } + // if (!crac.getAngleCnecs().stream().allMatch(angleCnecResults::containsKey)) { + // throw new OpenRaoException("RaoResult does not contain angle values for all AngleCNECs, security status for physical parameter ANGLE is unknown"); + // } // TODO: lancer cucumber if (crac.getAngleCnecs().stream() .mapToDouble(cnec -> getMargin(optimizedInstant, cnec, Unit.DEGREE)) @@ -367,7 +369,12 @@ private boolean instantHasNoNegativeMargin(Instant optimizedInstant, PhysicalPar } } case VOLTAGE -> { - if (!crac.getVoltageCnecs().stream().allMatch(voltageCnecResults::containsKey)) { + // if (!crac.getVoltageCnecs().stream().allMatch(voltageCnecResults::containsKey)) { + // throw new OpenRaoException("RaoResult does not contain voltage values for all VoltageCNECs, security status for physical parameter VOLTAGE is unknown"); + // } + if (crac.getVoltageCnecs().stream() + .mapToDouble(cnec -> getMargin(Instant.min(optimizedInstant, cnec.getState().getInstant()), cnec, Unit.KILOVOLT)) + .anyMatch(Double::isNaN)) { throw new OpenRaoException("RaoResult does not contain voltage values for all VoltageCNECs, security status for physical parameter VOLTAGE is unknown"); } if (crac.getVoltageCnecs().stream() diff --git a/data/rao-result/rao-result-impl/src/test/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImplTest.java b/data/rao-result/rao-result-impl/src/test/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImplTest.java index 8241da653f..2529bebf41 100644 --- a/data/rao-result/rao-result-impl/src/test/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImplTest.java +++ b/data/rao-result/rao-result-impl/src/test/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImplTest.java @@ -8,6 +8,7 @@ import com.powsybl.openrao.commons.OpenRaoException; import com.powsybl.openrao.commons.PhysicalParameter; +import com.powsybl.openrao.commons.Unit; import com.powsybl.openrao.data.cracapi.Crac; import com.powsybl.openrao.data.cracapi.Instant; import com.powsybl.openrao.data.cracapi.State; @@ -37,6 +38,7 @@ class RaoResultImplTest { private static final double DOUBLE_TOLERANCE = 1e-6; private static final String PREVENTIVE_INSTANT_ID = "preventive"; + private static final String OUTAGE_INSTANT_ID = "outage"; private static final String AUTO_INSTANT_ID = "auto"; private static final String CURATIVE_INSTANT_ID = "curative"; @@ -46,12 +48,14 @@ class RaoResultImplTest { private PstRangeAction pst; private NetworkAction na; private Instant preventiveInstant; + private Instant outageInstant; private Instant autoInstant; private Instant curativeInstant; private void setUp() { crac = CommonCracCreation.createWithPreventiveAndCurativePstRange(); preventiveInstant = crac.getInstant(PREVENTIVE_INSTANT_ID); + outageInstant = crac.getInstant(OUTAGE_INSTANT_ID); autoInstant = crac.getInstant(AUTO_INSTANT_ID); curativeInstant = crac.getInstant(CURATIVE_INSTANT_ID); cnec = crac.getFlowCnec("cnec1basecase"); @@ -335,9 +339,158 @@ void testIsSecureDependsOnOptimizationState() { @Test void comprehensiveRaoResultWithAllThreeTypesOfCnecs() { - // TODO: crac with FlowCNECs, VoltageCNECs, AngleCNECs x3 (prev, out, cur) - // TODO: raoResult with all instants - // TODO: results after PRAs? - // TODO: check throw if instant does not exist + setUp(); + addOutageFlowCnec(); + addAngleCnecs(); + addVoltageCnecs(); + + AngleCnecResult angleResult1 = raoResult.getAndCreateIfAbsentAngleCnecResult(crac.getAngleCnec("angleCnecPreventive")); + ElementaryAngleCnecResult elementaryAngleCnecResult1 = angleResult1.getAndCreateIfAbsentResultForOptimizationState(preventiveInstant); + elementaryAngleCnecResult1.setAngle(50., DEGREE); + elementaryAngleCnecResult1.setMargin(10., DEGREE); + + AngleCnecResult angleResult2 = raoResult.getAndCreateIfAbsentAngleCnecResult(crac.getAngleCnec("angleCnecStateOutageContingency1")); + ElementaryAngleCnecResult elementaryAngleCnecResult2 = angleResult2.getAndCreateIfAbsentResultForOptimizationState(preventiveInstant); + elementaryAngleCnecResult2.setAngle(90., DEGREE); + elementaryAngleCnecResult2.setMargin(30., DEGREE); + + AngleCnecResult angleResult3 = raoResult.getAndCreateIfAbsentAngleCnecResult(crac.getAngleCnec("angleCnecStateCurativeContingency1")); + ElementaryAngleCnecResult elementaryAngleCnecResult3 = angleResult3.getAndCreateIfAbsentResultForOptimizationState(preventiveInstant); + elementaryAngleCnecResult3.setAngle(35., DEGREE); + elementaryAngleCnecResult3.setMargin(-.5, DEGREE); + + VoltageCnecResult voltageResult1 = raoResult.getAndCreateIfAbsentVoltageCnecResult(crac.getVoltageCnec("voltageCnecPreventive")); + ElementaryVoltageCnecResult elementaryVoltageCnecResult1 = voltageResult1.getAndCreateIfAbsentResultForOptimizationState(preventiveInstant); + elementaryVoltageCnecResult1.setVoltage(400., KILOVOLT); + elementaryVoltageCnecResult1.setMargin(40., KILOVOLT); + + VoltageCnecResult voltageResult2 = raoResult.getAndCreateIfAbsentVoltageCnecResult(crac.getVoltageCnec("voltageCnecStateOutageContingency1")); + ElementaryVoltageCnecResult elementaryVoltageCnecResult2 = voltageResult2.getAndCreateIfAbsentResultForOptimizationState(preventiveInstant); + elementaryVoltageCnecResult2.setVoltage(415., KILOVOLT); + elementaryVoltageCnecResult2.setMargin(5., KILOVOLT); + + VoltageCnecResult voltageResult3 = raoResult.getAndCreateIfAbsentVoltageCnecResult(crac.getVoltageCnec("voltageCnecStateCurativeContingency1")); + ElementaryVoltageCnecResult elementaryVoltageCnecResult3 = voltageResult3.getAndCreateIfAbsentResultForOptimizationState(preventiveInstant); + elementaryVoltageCnecResult3.setVoltage(400., KILOVOLT); + elementaryVoltageCnecResult3.setMargin(40., KILOVOLT); + + assertFalse(raoResult.isSecure(preventiveInstant, PhysicalParameter.FLOW, PhysicalParameter.ANGLE, PhysicalParameter.VOLTAGE)); + assertTrue(raoResult.isSecure(preventiveInstant, PhysicalParameter.FLOW, PhysicalParameter.VOLTAGE)); + + assertEquals("RaoResult does not contain angle values for all AngleCNECs, security status for physical parameter ANGLE is unknown", assertThrows(OpenRaoException.class, () -> raoResult.isSecure(outageInstant, PhysicalParameter.FLOW, PhysicalParameter.ANGLE)).getMessage()); + assertEquals("RaoResult does not contain angle values for all AngleCNECs, security status for physical parameter ANGLE is unknown", assertThrows(OpenRaoException.class, () -> raoResult.isSecure(curativeInstant, PhysicalParameter.FLOW, PhysicalParameter.ANGLE)).getMessage()); + assertEquals("RaoResult does not contain voltage values for all VoltageCNECs, security status for physical parameter VOLTAGE is unknown", assertThrows(OpenRaoException.class, () -> raoResult.isSecure(outageInstant, PhysicalParameter.FLOW, PhysicalParameter.VOLTAGE)).getMessage()); + assertEquals("RaoResult does not contain voltage values for all VoltageCNECs, security status for physical parameter VOLTAGE is unknown", assertThrows(OpenRaoException.class, () -> raoResult.isSecure(curativeInstant, PhysicalParameter.FLOW, PhysicalParameter.VOLTAGE)).getMessage()); + } + + private void addVoltageCnecs() { + crac.newVoltageCnec() + .withId("voltageCnecPreventive") + .withNetworkElement("BBE2AA1 ") + .withInstant(PREVENTIVE_INSTANT_ID) + .withMonitored(true) + .withOperator("operator1") + .newThreshold() + .withUnit(KILOVOLT) + .withMax(440.) + .add() + .add(); + + crac.newVoltageCnec() + .withId("voltageCnecStateOutageContingency1") + .withNetworkElement("BBE2AA1 ") + .withInstant(OUTAGE_INSTANT_ID) + .withContingency("Contingency FR1 FR3") + .withMonitored(true) + .withOperator("operator1") + .newThreshold() + .withUnit(KILOVOLT) + .withMax(420.) + .add() + .add(); + + crac.newVoltageCnec() + .withId("voltageCnecStateCurativeContingency1") + .withNetworkElement("BBE2AA1 ") + .withInstant(CURATIVE_INSTANT_ID) + .withContingency("Contingency FR1 FR3") + .withMonitored(true) + .withOperator("operator1") + .newThreshold() + .withUnit(KILOVOLT) + .withMax(440.) + .add() + .add(); + } + + private void addAngleCnecs() { + crac.newAngleCnec() + .withId("angleCnecPreventive") + .withExportingNetworkElement("BBE2AA1 ") + .withImportingNetworkElement("FFR3AA1 ") + .withInstant(PREVENTIVE_INSTANT_ID) + .withOperator("operator1") + .withMonitored(true) + .newThreshold() + .withUnit(DEGREE) + .withMin(-60.) + .withMax(60.) + .add() + .add(); + + crac.newAngleCnec() + .withId("angleCnecStateOutageContingency1") + .withExportingNetworkElement("BBE2AA1 ") + .withImportingNetworkElement("FFR3AA1 ") + .withInstant(OUTAGE_INSTANT_ID) + .withContingency("Contingency FR1 FR3") + .withMonitored(true) + .withOperator("operator1") + .newThreshold() + .withUnit(DEGREE) + .withMin(-120.) + .withMax(120.) + .add() + .add(); + + crac.newAngleCnec() + .withId("angleCnecStateCurativeContingency1") + .withExportingNetworkElement("BBE2AA1 ") + .withImportingNetworkElement("FFR3AA1 ") + .withInstant(CURATIVE_INSTANT_ID) + .withContingency("Contingency FR1 FR3") + .withMonitored(true) + .withOperator("operator1") + .newThreshold() + .withUnit(DEGREE) + .withMin(-30.) + .withMax(30.) + .add() + .add(); + } + + private void addOutageFlowCnec() { + crac.newFlowCnec() + .withId("cnec1stateOutageContingency1") + .withNetworkElement("BBE2AA1 FFR3AA1 1") + .withInstant(OUTAGE_INSTANT_ID) + .withContingency("Contingency FR1 FR3") + .withOptimized(true) + .withOperator("operator1") + .withNominalVoltage(380.) + .withIMax(5000.) + .newThreshold() + .withUnit(Unit.MEGAWATT) + .withSide(Side.LEFT) + .withMin(-2000.) + .withMax(2000.) + .add() + .newThreshold() + .withUnit(Unit.MEGAWATT) + .withSide(Side.RIGHT) + .withMin(-2000.) + .withMax(2000.) + .add() + .add(); } } diff --git a/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImplTest.java b/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImplTest.java index 258fc6c4bd..d3fbdc296e 100644 --- a/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImplTest.java +++ b/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImplTest.java @@ -8,6 +8,7 @@ package com.powsybl.openrao.searchtreerao.result.impl; import com.powsybl.openrao.commons.OpenRaoException; +import com.powsybl.openrao.commons.PhysicalParameter; import com.powsybl.openrao.commons.Unit; import com.powsybl.openrao.data.cracapi.*; import com.powsybl.openrao.data.cracapi.cnec.AngleCnec; @@ -466,7 +467,13 @@ void testAngleAndVoltageCnec() { void testIsSecureOnSecureCase() { when(optimizedState.getInstant()).thenReturn(curativeInstant); when(output.getFunctionalCost(curativeInstant)).thenReturn(-10.); - assertTrue(output.isSecure()); + assertTrue(output.isSecure(PhysicalParameter.FLOW)); + + String expectedErrorMessage = "This is a flow RaoResult, flows are secure but other physical parameters' security status is unknown"; + OpenRaoException angleException = assertThrows(OpenRaoException.class, () -> output.isSecure(PhysicalParameter.FLOW, PhysicalParameter.ANGLE)); + assertEquals(expectedErrorMessage, angleException.getMessage()); + OpenRaoException voltageException = assertThrows(OpenRaoException.class, () -> output.isSecure(PhysicalParameter.FLOW, PhysicalParameter.VOLTAGE)); + assertEquals(expectedErrorMessage, voltageException.getMessage()); } @Test From c528edf6e3911aa34617319ce264516d14c54084 Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Fri, 22 Mar 2024 15:34:18 +0100 Subject: [PATCH 05/13] Remove comments Signed-off-by: Thomas Bouquet --- .../openrao/data/raoresultimpl/RaoResultImpl.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java b/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java index cb721dbb2b..951a9e5af8 100644 --- a/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java +++ b/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java @@ -344,18 +344,11 @@ private boolean instantHasNoNegativeMargin(Instant optimizedInstant, PhysicalPar for (PhysicalParameter physicalParameter : Set.of(u)) { switch (physicalParameter) { case ANGLE -> { - // TODO: check instant - // TODO: test without min and if it does not work add min - // TODO: create JSON RaoResult with anlgeCNECs prev + cur (prev -> prev / cur -> prev + cur) if (crac.getAngleCnecs().stream() .mapToDouble(cnec -> getMargin(Instant.min(optimizedInstant, cnec.getState().getInstant()), cnec, Unit.DEGREE)) .anyMatch(Double::isNaN)) { throw new OpenRaoException("RaoResult does not contain angle values for all AngleCNECs, security status for physical parameter ANGLE is unknown"); } - // if (!crac.getAngleCnecs().stream().allMatch(angleCnecResults::containsKey)) { - // throw new OpenRaoException("RaoResult does not contain angle values for all AngleCNECs, security status for physical parameter ANGLE is unknown"); - // } - // TODO: lancer cucumber if (crac.getAngleCnecs().stream() .mapToDouble(cnec -> getMargin(optimizedInstant, cnec, Unit.DEGREE)) .filter(margin -> !Double.isNaN(margin)) @@ -369,9 +362,6 @@ private boolean instantHasNoNegativeMargin(Instant optimizedInstant, PhysicalPar } } case VOLTAGE -> { - // if (!crac.getVoltageCnecs().stream().allMatch(voltageCnecResults::containsKey)) { - // throw new OpenRaoException("RaoResult does not contain voltage values for all VoltageCNECs, security status for physical parameter VOLTAGE is unknown"); - // } if (crac.getVoltageCnecs().stream() .mapToDouble(cnec -> getMargin(Instant.min(optimizedInstant, cnec.getState().getInstant()), cnec, Unit.KILOVOLT)) .anyMatch(Double::isNaN)) { From 032152e637e5f432080678c0f3ca0343861c8471 Mon Sep 17 00:00:00 2001 From: Peter Mitri Date: Fri, 12 Apr 2024 09:33:04 +0200 Subject: [PATCH 06/13] Change test 12.15.6 Signed-off-by: Peter Mitri --- .../epic12_export_improvement/US12_15.feature | 8 +- .../files/cne/epic12/ExpectedCNE_12_15_6.xml | 141 ++++++++++++++++++ .../raoresults/epic12/RaoResult_12_15_6.json | 135 +++++++++++++++++ 3 files changed, 280 insertions(+), 4 deletions(-) create mode 100644 tests/src/test/resources/files/cne/epic12/ExpectedCNE_12_15_6.xml create mode 100644 tests/src/test/resources/files/raoresults/epic12/RaoResult_12_15_6.json diff --git a/tests/src/test/resources/features/epic12_export_improvement/US12_15.feature b/tests/src/test/resources/features/epic12_export_improvement/US12_15.feature index 36c9286d80..ed51827411 100644 --- a/tests/src/test/resources/features/epic12_export_improvement/US12_15.feature +++ b/tests/src/test/resources/features/epic12_export_improvement/US12_15.feature @@ -291,13 +291,13 @@ Feature: US 12.15: export different reason per perimeter in SWE CNE @fast @cne-export @mock Scenario: US 12.15.6: CNE export with angles, no angle results - # Copy of 12.15.4 with extra angle CNEC but no angle values in RAO result - # Should not fail. Should instead skip angle CNECs, thus expected CNE is the same as 12.5.4 + # Copy of 12.15.4 with extra angle CNEC but no angle values in RAO result and a secure RAO + # Should not fail. Should instead skip angle CNECs, thus expected CNE is the same as 12.5.4 (but secure) Given network file is "epic12/nordic32.xiidm" Given crac file is "epic12/CIM_12_15_5.xml" Given crac creation parameters file is "epic12/CimCracCreationParameters_MonitorLeftSide.json" Given configuration file is "epic12/raoParametersSweIDCC_minObjectiveDisabled2P.json" - Given RaoResult file is "epic12/RaoResult_12_15_4.json" + Given RaoResult file is "epic12/RaoResult_12_15_6.json" When I import data at "2021-04-02 05:00" And I export SWE CNE - Then the exported CNE file is the same as "epic12/ExpectedCNE_12_15_4.xml" + Then the exported CNE file is the same as "epic12/ExpectedCNE_12_15_6.xml" diff --git a/tests/src/test/resources/files/cne/epic12/ExpectedCNE_12_15_6.xml b/tests/src/test/resources/files/cne/epic12/ExpectedCNE_12_15_6.xml new file mode 100644 index 0000000000..f5fe09df7f --- /dev/null +++ b/tests/src/test/resources/files/cne/epic12/ExpectedCNE_12_15_6.xml @@ -0,0 +1,141 @@ + + + documentId + 3 + B06 + A48 + senderId + A44 + receiverId + A36 + 2023-01-30T15:58:09Z + + 2019-04-01T13:09Z + 2019-04-01T14:09Z + + + CNE_RAO_CASTOR-TimeSeries-1 + B54 + A01 + + + 2021-04-02T03:00Z + 2021-04-02T04:00Z + + PT60M + + 1 + + 1ddcfad-29bb-4ef1-828f-ed7065fd8928 + B56 + + + db4a7e0-dde6-4cc3-9ca5-4816d6f26491 + B56 + + CO_N1012_N1014 + CO_N1012_N1014 + + + + b893392-32ed-4569-8bcf-f022fb4c5933 + B56 + + CO_N1012_N4012 + CO_N1012_N4012 + + + + ab18126-3240-4a1d-808a-2884cd09875f + B57 + + CNE_N1011_N1013 + CNE_N1011_N1013 + + N1011___-N1013___-1_AC + N1011_N1013 + N1011____VL + N1013____VL + + A01 + AMP + A02 + 1076 + + + A02 + AMP + A02 + 1000 + + + + + + e1fc140-be92-4ed1-bf9a-befe09ab1553 + B57 + + CO_N1012_N1014 + CO_N1012_N1014 + + + CNE_N1013_N1014 + CNE_N1013_N1014 + + N1013___-N1014___-1_AC + N1013_N1014 + N1013____VL + N1014____VL + + A01 + AMP + A02 + 700 + + + A13 + AMP + A02 + 500 + + + + + + 5ac608b-32a2-46da-b497-5eb07774e9cd + B57 + + CO_N1012_N4012 + CO_N1012_N4012 + + + CNE_N1013_N1014 + CNE_N1013_N1014 + + N1013___-N1014___-1_AC + N1013_N1014 + N1013____VL + N1014____VL + + A01 + AMP + A02 + 1919 + + + A13 + AMP + A02 + 500 + + + + + + Z13 + Network is secure + + + + + diff --git a/tests/src/test/resources/files/raoresults/epic12/RaoResult_12_15_6.json b/tests/src/test/resources/files/raoresults/epic12/RaoResult_12_15_6.json new file mode 100644 index 0000000000..ec7b520e64 --- /dev/null +++ b/tests/src/test/resources/files/raoresults/epic12/RaoResult_12_15_6.json @@ -0,0 +1,135 @@ +{ + "type" : "RAO_RESULT", + "version" : "1.3", + "info" : "Generated by FARAO http://farao-community.github.io", + "computationStatus" : "default", + "costResults" : { + "initial" : { + "functionalCost" : 1419.4 + }, + "afterPRA" : { + "functionalCost" : 1419.4, + "virtualCost" : { + "sensitivity-fallback-cost" : 0.0, + "sensitivity-failure-cost" : 0.0 + } + }, + "afterARA" : { + "functionalCost" : 1419.4, + "virtualCost" : { + "sensitivity-fallback-cost" : 0.0, + "sensitivity-failure-cost" : 0.0 + } + }, + "afterCRA" : { + "functionalCost" : -1419.4, + "virtualCost" : { + "sensitivity-fallback-cost" : 0.0, + "sensitivity-failure-cost" : 0.0 + } + } + }, + "computationStatusMap" : [ { + "computationStatus" : "DEFAULT", + "instant" : "preventive" + }, { + "computationStatus" : "DEFAULT", + "instant" : "curative", + "contingency" : "CO_N1012_N1014" + }, { + "computationStatus" : "DEFAULT", + "instant" : "curative", + "contingency" : "CO_N1012_N4012" + } ], + "flowCnecResults" : [ { + "flowCnecId" : "N1011_N1013 - preventive", + "initial" : { + "ampere" : { + "margin" : -75.64, + "leftSide" : { + "flow" : -1075.64 + } + } + }, + "afterPRA" : { + "ampere" : { + "margin" : -75.64, + "leftSide" : { + "flow" : -1075.64 + } + } + } + }, { + "flowCnecId" : "N1013_N1014 - CO_N1012_N1014 - curative", + "initial" : { + "ampere" : { + "margin" : -199.95, + "leftSide" : { + "flow" : -699.95 + } + } + }, + "afterPRA" : { + "ampere" : { + "margin" : -199.95, + "leftSide" : { + "flow" : -699.95 + } + } + }, + "afterARA" : { + "ampere" : { + "margin" : -199.95, + "leftSide" : { + "flow" : -699.95 + } + } + }, + "afterCRA" : { + "ampere" : { + "margin" : -199.95, + "leftSide" : { + "flow" : -699.95 + } + } + } + }, { + "flowCnecId" : "N1013_N1014 - CO_N1012_N4012 - curative", + "initial" : { + "ampere" : { + "margin" : -1419.4, + "leftSide" : { + "flow" : -1919.4 + } + } + }, + "afterPRA" : { + "ampere" : { + "margin" : -1419.4, + "leftSide" : { + "flow" : -1919.4 + } + } + }, + "afterARA" : { + "ampere" : { + "margin" : -1419.4, + "leftSide" : { + "flow" : -1919.4 + } + } + }, + "afterCRA" : { + "ampere" : { + "margin" : 1419.4, + "leftSide" : { + "flow" : -1919.4 + } + } + } + } ], + "angleCnecResults" : [ ], + "voltageCnecResults" : [ ], + "networkActionResults" : [ ], + "rangeActionResults" : [ ] +} \ No newline at end of file From 9b1540a9fe17f895c1c144fe6efe230aa09bec90 Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Fri, 12 Apr 2024 09:45:18 +0200 Subject: [PATCH 07/13] Rollb Signed-off-by: Thomas Bouquet --- .../anglemonitoring/RaoResultWithAngleMonitoring.java | 4 ++-- .../voltagemonitoring/RaoResultWithVoltageMonitoring.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/monitoring/angle-monitoring/src/main/java/com/powsybl/openrao/monitoring/anglemonitoring/RaoResultWithAngleMonitoring.java b/monitoring/angle-monitoring/src/main/java/com/powsybl/openrao/monitoring/anglemonitoring/RaoResultWithAngleMonitoring.java index 2b969a6fdb..0af049ef45 100644 --- a/monitoring/angle-monitoring/src/main/java/com/powsybl/openrao/monitoring/anglemonitoring/RaoResultWithAngleMonitoring.java +++ b/monitoring/angle-monitoring/src/main/java/com/powsybl/openrao/monitoring/anglemonitoring/RaoResultWithAngleMonitoring.java @@ -94,7 +94,7 @@ public boolean isSecure(Instant instant, PhysicalParameter... u) { if (physicalParameters.remove(PhysicalParameter.ANGLE)) { return raoResult.isSecure(instant, physicalParameters.toArray(new PhysicalParameter[0])) && angleMonitoringResult.isSecure(); } else { - return raoResult.isSecure(instant, physicalParameters.toArray(new PhysicalParameter[0])); + return raoResult.isSecure(instant, u); } } @@ -104,7 +104,7 @@ public boolean isSecure(PhysicalParameter... u) { if (physicalParameters.remove(PhysicalParameter.ANGLE)) { return raoResult.isSecure(physicalParameters.toArray(new PhysicalParameter[0])) && angleMonitoringResult.isSecure(); } else { - return raoResult.isSecure(physicalParameters.toArray(new PhysicalParameter[0])); + return raoResult.isSecure(u); } } diff --git a/monitoring/voltage-monitoring/src/main/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoring.java b/monitoring/voltage-monitoring/src/main/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoring.java index 2385c3602d..5f4f5017c7 100644 --- a/monitoring/voltage-monitoring/src/main/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoring.java +++ b/monitoring/voltage-monitoring/src/main/java/com/powsybl/openrao/monitoring/voltagemonitoring/RaoResultWithVoltageMonitoring.java @@ -102,7 +102,7 @@ public boolean isSecure(Instant instant, PhysicalParameter... u) { if (physicalParameters.remove(PhysicalParameter.VOLTAGE)) { return raoResult.isSecure(instant, physicalParameters.toArray(new PhysicalParameter[0])) && voltageMonitoringResult.isSecure(); } else { - return raoResult.isSecure(instant, physicalParameters.toArray(new PhysicalParameter[0])); + return raoResult.isSecure(instant, u); } } @@ -112,7 +112,7 @@ public boolean isSecure(PhysicalParameter... u) { if (physicalParameters.remove(PhysicalParameter.VOLTAGE)) { return raoResult.isSecure(physicalParameters.toArray(new PhysicalParameter[0])) && voltageMonitoringResult.isSecure(); } else { - return raoResult.isSecure(physicalParameters.toArray(new PhysicalParameter[0])); + return raoResult.isSecure(u); } } From 88a0a2c073a3a3f5df5b7753440e0f18a0132b33 Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Mon, 17 Jun 2024 17:02:52 +0200 Subject: [PATCH 08/13] Fix test 12.15.6 + remove dupliacted code (now default RaoResul method) Signed-off-by: Thomas Bouquet --- .../openrao/data/raoresultapi/RaoResult.java | 112 ++++++++++-------- .../data/raoresultimpl/RaoResultImpl.java | 11 -- .../openrao/data/swecneexporter/SweCne.java | 11 +- .../impl/OneStateOnlyRaoResultImpl.java | 11 -- .../PreventiveAndCurativesRaoResultImpl.java | 11 -- .../result/impl/UnoptimizedRaoResultImpl.java | 12 -- 6 files changed, 70 insertions(+), 98 deletions(-) diff --git a/data/rao-result/rao-result-api/src/main/java/com/powsybl/openrao/data/raoresultapi/RaoResult.java b/data/rao-result/rao-result-api/src/main/java/com/powsybl/openrao/data/raoresultapi/RaoResult.java index 12de57764e..ace16b11c6 100644 --- a/data/rao-result/rao-result-api/src/main/java/com/powsybl/openrao/data/raoresultapi/RaoResult.java +++ b/data/rao-result/rao-result-api/src/main/java/com/powsybl/openrao/data/raoresultapi/RaoResult.java @@ -50,9 +50,9 @@ public interface RaoResult { * given {@link Unit}. * * @param optimizedInstant: The optimized instant to be studied (set to null to access initial results) - * @param flowCnec: The branch to be studied. - * @param side: The side of the branch to be queried. - * @param unit: The unit in which the flow is queried. Only accepted values are MEGAWATT or AMPERE. + * @param flowCnec: The branch to be studied. + * @param side: The side of the branch to be queried. + * @param unit: The unit in which the flow is queried. Only accepted values are MEGAWATT or AMPERE. * @return The flow on the branch at the optimization state in the given unit. */ double getFlow(Instant optimizedInstant, FlowCnec flowCnec, Side side, Unit unit); @@ -62,8 +62,8 @@ public interface RaoResult { * given {@link Unit}. * * @param optimizedInstant: The optimized instant to be studied (set to null to access initial results) - * @param angleCnec: The angle cnec to be studied. - * @param unit: The unit in which the flow is queried. Only accepted value for now is DEGREE. + * @param angleCnec: The angle cnec to be studied. + * @param unit: The unit in which the flow is queried. Only accepted value for now is DEGREE. * @return The angle on the cnec at the optimization state in the given unit. */ default double getAngle(Instant optimizedInstant, AngleCnec angleCnec, Unit unit) { @@ -75,8 +75,8 @@ default double getAngle(Instant optimizedInstant, AngleCnec angleCnec, Unit unit * given {@link Unit}. * * @param optimizedInstant: The optimized instant to be studied (set to null to access initial results) - * @param voltageCnec: The voltage cnec to be studied. - * @param unit: The unit in which the flow is queried. Only accepted value for now is KILOVOLT. + * @param voltageCnec: The voltage cnec to be studied. + * @param unit: The unit in which the flow is queried. Only accepted value for now is KILOVOLT. * @return The voltage on the cnec at the optimization state in the given unit. */ default double getVoltage(Instant optimizedInstant, VoltageCnec voltageCnec, Unit unit) { @@ -89,8 +89,8 @@ default double getVoltage(Instant optimizedInstant, VoltageCnec voltageCnec, Uni * flow direction of the given branch. If it is negative the branch is under constraint. * * @param optimizedInstant: The optimized instant to be studied (set to null to access initial results) - * @param flowCnec: The branch to be studied. - * @param unit: The unit in which the margin is queried. Only accepted values are MEGAWATT or AMPERE. + * @param flowCnec: The branch to be studied. + * @param unit: The unit in which the margin is queried. Only accepted values are MEGAWATT or AMPERE. * @return The margin on the branch at the optimization state in the given unit. */ double getMargin(Instant optimizedInstant, FlowCnec flowCnec, Unit unit); @@ -101,8 +101,8 @@ default double getVoltage(Instant optimizedInstant, VoltageCnec voltageCnec, Uni * angle direction of the given branch. If it is negative the cnec is under constraint. * * @param optimizedInstant: The optimized instant to be studied (set to null to access initial results) - * @param angleCnec: The angle cnec to be studied. - * @param unit: The unit in which the margin is queried. Only accepted for now is DEGREE. + * @param angleCnec: The angle cnec to be studied. + * @param unit: The unit in which the margin is queried. Only accepted for now is DEGREE. * @return The margin on the angle cnec at the optimization state in the given unit. */ default double getMargin(Instant optimizedInstant, AngleCnec angleCnec, Unit unit) { @@ -115,8 +115,8 @@ default double getMargin(Instant optimizedInstant, AngleCnec angleCnec, Unit uni * of the given voltage level. If it is negative the cnec is under constraint. * * @param optimizedInstant: The optimized instant to be studied (set to null to access initial results) - * @param voltageCnec: The voltage cnec to be studied. - * @param unit: The unit in which the margin is queried. Only accepted for now is KILOVOLT. + * @param voltageCnec: The voltage cnec to be studied. + * @param unit: The unit in which the margin is queried. Only accepted for now is KILOVOLT. * @return The margin on the voltage cnec at the optimization state in the given unit. */ default double getMargin(Instant optimizedInstant, VoltageCnec voltageCnec, Unit unit) { @@ -132,8 +132,8 @@ default double getMargin(Instant optimizedInstant, VoltageCnec voltageCnec, Unit * computation or the sum of them is null, this method could return {@code Double.NaN} values. * * @param optimizedInstant: The optimized instant to be studied (set to null to access initial results) - * @param flowCnec: The branch to be studied. - * @param unit: The unit in which the relative margin is queried. Only accepted values are MEGAWATT or AMPERE. + * @param flowCnec: The branch to be studied. + * @param unit: The unit in which the relative margin is queried. Only accepted values are MEGAWATT or AMPERE. * @return The relative margin on the branch at the optimization state in the given unit. */ double getRelativeMargin(Instant optimizedInstant, FlowCnec flowCnec, Unit unit); @@ -144,8 +144,8 @@ default double getMargin(Instant optimizedInstant, VoltageCnec voltageCnec, Unit * loop flows are monitored, this method could return {@code Double.NaN} values. * * @param optimizedInstant: The optimized instant to be studied (set to null to access initial results) - * @param flowCnec: The branch to be studied. - * @param unit: The unit in which the commercial flow is queried. Only accepted values are MEGAWATT or AMPERE. + * @param flowCnec: The branch to be studied. + * @param unit: The unit in which the commercial flow is queried. Only accepted values are MEGAWATT or AMPERE. * @return The commercial flow on the branch at the optimization state in the given unit. */ double getCommercialFlow(Instant optimizedInstant, FlowCnec flowCnec, Side side, Unit unit); @@ -156,8 +156,8 @@ default double getMargin(Instant optimizedInstant, VoltageCnec voltageCnec, Unit * loop flows are monitored, this method could return {@code Double.NaN} values. * * @param optimizedInstant: The optimized instant to be studied (set to null to access initial results) - * @param flowCnec: The branch to be studied. - * @param unit: The unit in which the loop flow is queried. Only accepted values are MEGAWATT or AMPERE. + * @param flowCnec: The branch to be studied. + * @param unit: The unit in which the loop flow is queried. Only accepted values are MEGAWATT or AMPERE. * @return The loop flow on the branch at the optimization state in the given unit. */ double getLoopFlow(Instant optimizedInstant, FlowCnec flowCnec, Side side, Unit unit); @@ -168,7 +168,7 @@ default double getMargin(Instant optimizedInstant, VoltageCnec voltageCnec, Unit * not define any list of considered areas, this method could return {@code Double.NaN} values. * * @param optimizedInstant: The optimized instant to be studied (set to null to access initial results) - * @param flowCnec: The branch to be studied. + * @param flowCnec: The branch to be studied. * @return The sum of the computation areas' zonal PTDFs on the branch at the optimization state. */ double getPtdfZonalSum(Instant optimizedInstant, FlowCnec flowCnec, Side side); @@ -217,7 +217,7 @@ default double getCost(Instant optimizedInstant) { * objective function, this method could return {@code Double.NaN} values. * * @param optimizedInstant: The optimized instant to be studied (set to null to access initial results) - * @param virtualCostName: The name of the virtual cost. + * @param virtualCostName: The name of the virtual cost. * @return The specific virtual cost of the situation state. */ double getVirtualCost(Instant optimizedInstant, String virtualCostName); @@ -225,18 +225,26 @@ default double getCost(Instant optimizedInstant) { /** * It states if the {@link RemedialAction} is activated on a specific {@link State}. * - * @param state: The state of the state tree to be studied. + * @param state: The state of the state tree to be studied. * @param remedialAction: The remedial action to be studied. * @return True if the remedial action is chosen by the optimizer during the specified state. */ - boolean isActivatedDuringState(State state, RemedialAction remedialAction); + default boolean isActivatedDuringState(State state, RemedialAction remedialAction) { + if (remedialAction instanceof NetworkAction networkAction) { + return isActivatedDuringState(state, networkAction); + } else if (remedialAction instanceof RangeAction rangeAction) { + return isActivatedDuringState(state, rangeAction); + } else { + throw new OpenRaoException("Unrecognized remedial action type"); + } + } /** * It states if the {@link NetworkAction} was already activated when a specific {@link State} is studied. Meaning * the network action has not been chosen by the optimizer on this state, but this action is already effective in * the network due to previous optimizations. * - * @param state: The state of the state tree to be studied. + * @param state: The state of the state tree to be studied. * @param networkAction: The network action to be studied. * @return True if the network action is already active but has not been activated during the specified state. */ @@ -245,7 +253,7 @@ default double getCost(Instant optimizedInstant) { /** * It states if the {@link NetworkAction} is activated on a specific {@link State}. * - * @param state: The state of the state tree to be studied. + * @param state: The state of the state tree to be studied. * @param networkAction: The network action to be studied. * @return True if the network action is chosen by the optimizer during the specified state. */ @@ -254,7 +262,7 @@ default double getCost(Instant optimizedInstant) { /** * It states if the {@link NetworkAction} is or was activated when a specific {@link State} is studied. * - * @param state: The state of the state tree to be studied. + * @param state: The state of the state tree to be studied. * @param networkAction: The network action to be studied. * @return True if the network action is active during the specified state. */ @@ -275,7 +283,7 @@ default boolean isActivated(State state, NetworkAction networkAction) { * point of the range action is different in the specified state compared to the previous state. The previous * "state" is the initial situation in the case of the preventive state. * - * @param state: The state of the state tree to be studied. + * @param state: The state of the state tree to be studied. * @param rangeAction: The range action to be studied. * @return True if the set point of the range action has been changed during the specified state. */ @@ -286,18 +294,18 @@ default boolean isActivated(State state, NetworkAction networkAction) { * on the specified {@link State}. So, in the specific case of a PST range action that would be defined several * times for the same PST (but available on different states), the final result would always be the situation of * the PST on the state before its optimization. For example, if two PST range actions are defined : - * - RA1 : on "pst-element" only available in preventive state - * - RA2 : on "pst-element" only available on curative state after contingency "co-example" - * + * - RA1 : on "pst-element" only available in preventive state + * - RA2 : on "pst-element" only available on curative state after contingency "co-example" + *

* Let's say tap of "pst-element" is initially at 0 in the network. During preventive optimization RA1 is activated * and the PST tap goes to 5. During curative optimization RA2 is activated and the PST tap goes to 10. So when the * method is called, we would get the following results : - * - getPreOptimizationTapOnState(preventiveState, RA1) = getPreOptimizationTapOnState(preventiveState, RA2) = 0 - * - getPreOptimizationTapOnState(curativeState, RA1) = getPreOptimizationTapOnState(curativeState, RA2) = 5 + * - getPreOptimizationTapOnState(preventiveState, RA1) = getPreOptimizationTapOnState(preventiveState, RA2) = 0 + * - getPreOptimizationTapOnState(curativeState, RA1) = getPreOptimizationTapOnState(curativeState, RA2) = 5 * So we will still get 0 in preventive even if RA2 has not been activated during preventive optimization. And we * will still get 5 in curative even if RA1 has not been activated during curative optimization. * - * @param state: The state of the state tree to be studied. + * @param state: The state of the state tree to be studied. * @param pstRangeAction: The PST range action to be studied. * @return The tap of the PST defined in the PST range action at the specified state before its optimization. */ @@ -308,18 +316,18 @@ default boolean isActivated(State state, NetworkAction networkAction) { * on the specified {@link State}. So, in the specific case of a PST range action that would be defined several * times for the same PST (but available on different states), the final result would always be the optimized * situation of the PST on the state. For example, if two range actions are defined : - * - RA1 : on "pst-element" only available in preventive state - * - RA2 : on "pst-element" only available on curative state after contingency "co-example" - * + * - RA1 : on "pst-element" only available in preventive state + * - RA2 : on "pst-element" only available on curative state after contingency "co-example" + *

* Let's say tap of "pst-element" is initially at 0 in the network. During preventive optimization RA1 is activated * and the PST tap goes to 5. During curative optimization RA2 is activated and the PST tap goes to 10. So when the * method is called, we would get the following results : - * - getOptimizedTapOnState(preventiveState, RA1) = getOptimizedTapOnState(preventiveState, RA2) = 5 - * - getOptimizedTapOnState(curativeState, RA1) = getOptimizedTapOnState(curativeState, RA2) = 10 + * - getOptimizedTapOnState(preventiveState, RA1) = getOptimizedTapOnState(preventiveState, RA2) = 5 + * - getOptimizedTapOnState(curativeState, RA1) = getOptimizedTapOnState(curativeState, RA2) = 10 * So we will still get 5 in preventive even if RA2 has not been activated during preventive optimization. And we * will still get 10 in curative even if RA1 has not been activated during curative optimization. * - * @param state: The state of the state tree to be studied. + * @param state: The state of the state tree to be studied. * @param pstRangeAction: The PST range action to be studied. * @return The tap of the PST defined in the PST range action at the specified state after its optimization. */ @@ -331,18 +339,18 @@ default boolean isActivated(State state, NetworkAction networkAction) { * times for the same network element (but available on different states), the final result would always be the * set point of the network element on the state before its optimization. For example, if two range actions are * defined : - * - RA1 : on "pst-element" only available in preventive state - * - RA2 : on "pst-element" only available on curative state after contingency "co-example" - * + * - RA1 : on "pst-element" only available in preventive state + * - RA2 : on "pst-element" only available on curative state after contingency "co-example" + *

* Let's say the set point of "pst-element" is initially at 0. in the network. During preventive optimization RA1 * is activated and the PST set point goes to 3.2. During curative optimization RA2 is activated and the PST tap * goes to 5.6. So when the method is called, we would get the following results : - * - getOptimizedSetPointOnState(preventiveState, RA1) = getOptimizedSetPointOnState(preventiveState, RA2) = 0. - * - getOptimizedSetPointOnState(curativeState, RA1) = getOptimizedSetPointOnState(curativeState, RA2) = 3.2 + * - getOptimizedSetPointOnState(preventiveState, RA1) = getOptimizedSetPointOnState(preventiveState, RA2) = 0. + * - getOptimizedSetPointOnState(curativeState, RA1) = getOptimizedSetPointOnState(curativeState, RA2) = 3.2 * So we will still get 0. in preventive even if RA2 has not been activated during preventive optimization. And we * will still get 3.2 in curative even if RA1 has not been activated during curative optimization. * - * @param state: The state of the state tree to be studied. + * @param state: The state of the state tree to be studied. * @param rangeAction: The range action to be studied. * @return The set point of the network element defined in the range action at the specified state before its * optimization. @@ -354,18 +362,18 @@ default boolean isActivated(State state, NetworkAction networkAction) { * on the specified {@link State}. So, in the specific case of a range action that would be defined several * times for the same network element (but available on different states), the final result would always be the * optimized situation of the network element on the state. For example, if two PST range actions are defined : - * - RA1 : on "pst-element" only available in preventive state - * - RA2 : on "pst-element" only available on curative state after contingency "co-example" - * + * - RA1 : on "pst-element" only available in preventive state + * - RA2 : on "pst-element" only available on curative state after contingency "co-example" + *

* Let's say the set point of "pst-element" is initially at 0. in the network. During preventive optimization RA1 * is activated and the PST set point goes to 3.2. During curative optimization RA2 is activated and the PST tap * goes to 5.6. So when the method is called, we would get the following results : - * - getOptimizedSetPointOnState(preventiveState, RA1) = getOptimizedSetPointOnState(preventiveState, RA2) = 3.2 - * - getOptimizedSetPointOnState(curativeState, RA1) = getOptimizedSetPointOnState(curativeState, RA2) = 5.6 + * - getOptimizedSetPointOnState(preventiveState, RA1) = getOptimizedSetPointOnState(preventiveState, RA2) = 3.2 + * - getOptimizedSetPointOnState(curativeState, RA1) = getOptimizedSetPointOnState(curativeState, RA2) = 5.6 * So we will still get 3.2 in preventive even if RA2 has not been activated during preventive optimization. And we * will still get 5.6 in curative even if RA1 has not been activated during curative optimization. * - * @param state: The state of the state tree to be studied. + * @param state: The state of the state tree to be studied. * @param rangeAction: The range action to be studied. * @return The set point of the network element defined in the range action at the specified state after its * optimization. @@ -409,7 +417,7 @@ default boolean isActivated(State state, NetworkAction networkAction) { * Indicates whether the all the CNECs of a given type at a given instant are secure. * * @param optimizedInstant: The instant to assess - * @param u: The types of CNECs to check (FLOW -> FlowCNECs, ANGLE -> AngleCNECs, VOLTAGE -> VoltageCNECs). 1 to 3 arguments can be provided. + * @param u: The types of CNECs to check (FLOW -> FlowCNECs, ANGLE -> AngleCNECs, VOLTAGE -> VoltageCNECs). 1 to 3 arguments can be provided. * @return whether all the CNECs of the given type(s) are secure at the optimized instant. */ boolean isSecure(Instant optimizedInstant, PhysicalParameter... u); diff --git a/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java b/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java index 951a9e5af8..5d44e027fb 100644 --- a/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java +++ b/data/rao-result/rao-result-impl/src/main/java/com/powsybl/openrao/data/raoresultimpl/RaoResultImpl.java @@ -189,17 +189,6 @@ private static String getIdFromNullableInstant(Instant optimizedInstant) { return optimizedInstant == null ? INITIAL_INSTANT_ID : optimizedInstant.getId(); } - @Override - public boolean isActivatedDuringState(State state, RemedialAction remedialAction) { - if (remedialAction instanceof NetworkAction networkAction) { - return isActivatedDuringState(state, networkAction); - } else if (remedialAction instanceof RangeAction rangeAction) { - return isActivatedDuringState(state, rangeAction); - } else { - throw new OpenRaoException("Unrecognized remedial action type"); - } - } - public NetworkActionResult getAndCreateIfAbsentNetworkActionResult(NetworkAction networkAction) { networkActionResults.putIfAbsent(networkAction, new NetworkActionResult()); return networkActionResults.get(networkAction); diff --git a/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCne.java b/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCne.java index e6f9fc0a1d..133bb1eb82 100644 --- a/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCne.java +++ b/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCne.java @@ -109,7 +109,16 @@ private void addReason(Point point) { Reason reason = new Reason(); RaoResult raoResult = sweCneHelper.getRaoResult(); boolean isDivergent = sweCneHelper.isAnyContingencyInFailure() || raoResult.getComputationStatus() == ComputationStatus.FAILURE; - boolean isUnsecure = !raoResult.isSecure(PhysicalParameter.FLOW, PhysicalParameter.ANGLE); + boolean isUnsecure; + try { + isUnsecure = !raoResult.isSecure(PhysicalParameter.FLOW, PhysicalParameter.ANGLE); + } catch (OpenRaoException e) { + if ("RaoResult does not contain angle values for all AngleCNECs, security status for physical parameter ANGLE is unknown".equals(e.getMessage())) { + isUnsecure = false; // simply ignore AngleCNECs + } else { + throw e; // unexpected error + } + } if (isDivergent) { reason.setCode(DIVERGENCE_CODE); reason.setText(DIVERGENCE_TEXT); diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImpl.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImpl.java index fc8e054007..a8e8ccc8ca 100644 --- a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImpl.java +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImpl.java @@ -189,17 +189,6 @@ public List getCostlyElements(Instant optimizedInstant, String virtual } } - @Override - public boolean isActivatedDuringState(State state, RemedialAction remedialAction) { - if (remedialAction instanceof NetworkAction networkAction) { - return isActivatedDuringState(state, networkAction); - } else if (remedialAction instanceof RangeAction rangeAction) { - return isActivatedDuringState(state, rangeAction); - } else { - throw new OpenRaoException("Unrecognized remedial action type"); - } - } - @Override public boolean wasActivatedBeforeState(State state, NetworkAction networkAction) { if (!state.equals(optimizedState)) { diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/PreventiveAndCurativesRaoResultImpl.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/PreventiveAndCurativesRaoResultImpl.java index c319c38fc2..c15f4cd473 100644 --- a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/PreventiveAndCurativesRaoResultImpl.java +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/PreventiveAndCurativesRaoResultImpl.java @@ -442,17 +442,6 @@ public List getCostlyElements(Instant optimizedInstant, String virtual } } - @Override - public boolean isActivatedDuringState(State state, RemedialAction remedialAction) { - if (remedialAction instanceof NetworkAction networkAction) { - return isActivatedDuringState(state, networkAction); - } else if (remedialAction instanceof RangeAction rangeAction) { - return isActivatedDuringState(state, rangeAction); - } else { - throw new OpenRaoException("Unrecognized remedial action type"); - } - } - @Override public boolean wasActivatedBeforeState(State state, NetworkAction networkAction) { if (state.getInstant().isPreventive()) { diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/UnoptimizedRaoResultImpl.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/UnoptimizedRaoResultImpl.java index 54d10cdc24..4d99e08d99 100644 --- a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/UnoptimizedRaoResultImpl.java +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/UnoptimizedRaoResultImpl.java @@ -11,7 +11,6 @@ import com.powsybl.openrao.commons.PhysicalParameter; import com.powsybl.openrao.commons.Unit; import com.powsybl.openrao.data.cracapi.Instant; -import com.powsybl.openrao.data.cracapi.RemedialAction; import com.powsybl.openrao.data.cracapi.State; import com.powsybl.openrao.data.cracapi.cnec.FlowCnec; import com.powsybl.openrao.data.cracapi.cnec.Side; @@ -106,17 +105,6 @@ public double getVirtualCost(Instant optimizedInstant, String virtualCostName) { return initialResult.getVirtualCost(virtualCostName); } - @Override - public boolean isActivatedDuringState(State state, RemedialAction remedialAction) { - if (remedialAction instanceof NetworkAction networkAction) { - return isActivatedDuringState(state, networkAction); - } else if (remedialAction instanceof RangeAction rangeAction) { - return isActivatedDuringState(state, rangeAction); - } else { - throw new OpenRaoException("Unrecognized remedial action type"); - } - } - @Override public boolean wasActivatedBeforeState(State state, NetworkAction networkAction) { return false; From 30c682d3f083d0d02bec482dd782d84b047470af Mon Sep 17 00:00:00 2001 From: Thomas Bouquet <63302082+bqth29@users.noreply.github.com> Date: Fri, 21 Jun 2024 10:44:02 +0200 Subject: [PATCH 09/13] Update data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCne.java Co-authored-by: Peter Mitri Signed-off-by: Thomas Bouquet <63302082+bqth29@users.noreply.github.com> --- .../com/powsybl/openrao/data/swecneexporter/SweCne.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCne.java b/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCne.java index 133bb1eb82..65a66b253b 100644 --- a/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCne.java +++ b/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCne.java @@ -113,11 +113,8 @@ private void addReason(Point point) { try { isUnsecure = !raoResult.isSecure(PhysicalParameter.FLOW, PhysicalParameter.ANGLE); } catch (OpenRaoException e) { - if ("RaoResult does not contain angle values for all AngleCNECs, security status for physical parameter ANGLE is unknown".equals(e.getMessage())) { - isUnsecure = false; // simply ignore AngleCNECs - } else { - throw e; // unexpected error - } + // Sometimes we run this method before without running angle monitoring. In that case, simply ignore AngleCnecs + isUnsecure = !raoResult.isSecure(PhysicalParameter.FLOW); } if (isDivergent) { reason.setCode(DIVERGENCE_CODE); From cdc19688d936f918af68d5d10b087e7b94d52163 Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Fri, 21 Jun 2024 11:05:50 +0200 Subject: [PATCH 10/13] Fix tests and remove duplicated code Signed-off-by: Thomas Bouquet --- .../openrao/data/swecneexporter/SweCne.java | 2 +- .../result/impl/FlowRaoResult.java | 38 +++++++++++++++++++ .../impl/OneStateOnlyRaoResultImpl.java | 20 +--------- .../PreventiveAndCurativesRaoResultImpl.java | 20 +--------- 4 files changed, 41 insertions(+), 39 deletions(-) create mode 100644 ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/FlowRaoResult.java diff --git a/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCne.java b/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCne.java index 65a66b253b..91f59c476a 100644 --- a/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCne.java +++ b/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCne.java @@ -114,7 +114,7 @@ private void addReason(Point point) { isUnsecure = !raoResult.isSecure(PhysicalParameter.FLOW, PhysicalParameter.ANGLE); } catch (OpenRaoException e) { // Sometimes we run this method before without running angle monitoring. In that case, simply ignore AngleCnecs - isUnsecure = !raoResult.isSecure(PhysicalParameter.FLOW); + isUnsecure = !raoResult.isSecure(PhysicalParameter.FLOW); } if (isDivergent) { reason.setCode(DIVERGENCE_CODE); diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/FlowRaoResult.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/FlowRaoResult.java new file mode 100644 index 0000000000..9c2b5bcf60 --- /dev/null +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/FlowRaoResult.java @@ -0,0 +1,38 @@ +/* + * 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.searchtreerao.result.impl; + +import com.powsybl.openrao.commons.OpenRaoException; +import com.powsybl.openrao.commons.PhysicalParameter; +import com.powsybl.openrao.data.cracapi.Instant; +import com.powsybl.openrao.data.raoresultapi.ComputationStatus; +import com.powsybl.openrao.data.raoresultapi.RaoResult; + +import java.util.Arrays; + +/** + * @author Thomas Bouquet {@literal } + */ +public interface FlowRaoResult extends RaoResult { + @Override + default boolean isSecure(Instant optimizedInstant, PhysicalParameter... u) { + if (ComputationStatus.FAILURE.equals(getComputationStatus())) { + return false; + } + if (Arrays.stream(u).noneMatch(PhysicalParameter.FLOW::equals)) { + throw new OpenRaoException("This is a flow RaoResult, isSecure is available for FLOW physical parameter"); + } + if (getFunctionalCost(optimizedInstant) >= 0) { + return false; + } + if (Arrays.stream(u).anyMatch(physicalParameter -> !PhysicalParameter.FLOW.equals(physicalParameter))) { + throw new OpenRaoException("This is a flow RaoResult, flows are secure but other physical parameters' security status is unknown"); + } + return true; + } +} diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImpl.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImpl.java index a8e8ccc8ca..00a8b92d2d 100644 --- a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImpl.java +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImpl.java @@ -19,7 +19,6 @@ import com.powsybl.openrao.data.cracapi.rangeaction.RangeAction; import com.powsybl.openrao.data.raoresultapi.ComputationStatus; import com.powsybl.openrao.data.raoresultapi.OptimizationStepsExecuted; -import com.powsybl.openrao.data.raoresultapi.RaoResult; import com.powsybl.openrao.searchtreerao.result.api.*; import java.util.*; @@ -28,7 +27,7 @@ /** * @author Joris Mancini {@literal } */ -public class OneStateOnlyRaoResultImpl implements RaoResult { +public class OneStateOnlyRaoResultImpl implements FlowRaoResult { public static final String WRONG_STATE = "Trying to access perimeter result for the wrong state."; private final State optimizedState; private final PrePerimeterResult initialResult; @@ -287,23 +286,6 @@ public void setOptimizationStepsExecuted(OptimizationStepsExecuted optimizationS } } - @Override - public boolean isSecure(Instant optimizedInstant, PhysicalParameter... u) { - if (ComputationStatus.FAILURE.equals(getComputationStatus())) { - return false; - } - if (Arrays.stream(u).noneMatch(PhysicalParameter.FLOW::equals)) { - throw new OpenRaoException("This is a flow RaoResult, isSecure is available for FLOW physical parameter"); - } - if (getFunctionalCost(optimizedInstant) >= 0) { - return false; - } - if (Arrays.stream(u).anyMatch(physicalParameter -> !PhysicalParameter.FLOW.equals(physicalParameter))) { - throw new OpenRaoException("This is a flow RaoResult, flows are secure but other physical parameters' security status is unknown"); - } - return true; - } - @Override public boolean isSecure(PhysicalParameter... u) { return isSecure(optimizedState.getInstant(), u); diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/PreventiveAndCurativesRaoResultImpl.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/PreventiveAndCurativesRaoResultImpl.java index c15f4cd473..627e4049df 100644 --- a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/PreventiveAndCurativesRaoResultImpl.java +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/PreventiveAndCurativesRaoResultImpl.java @@ -19,7 +19,6 @@ import com.powsybl.openrao.data.cracapi.rangeaction.RangeAction; import com.powsybl.openrao.data.raoresultapi.ComputationStatus; import com.powsybl.openrao.data.raoresultapi.OptimizationStepsExecuted; -import com.powsybl.openrao.data.raoresultapi.RaoResult; import com.powsybl.openrao.searchtreerao.castor.algorithm.Perimeter; import com.powsybl.openrao.searchtreerao.result.api.*; import com.powsybl.openrao.searchtreerao.castor.algorithm.StateTree; @@ -32,7 +31,7 @@ /** * @author Joris Mancini {@literal } */ -public class PreventiveAndCurativesRaoResultImpl implements RaoResult { +public class PreventiveAndCurativesRaoResultImpl implements FlowRaoResult { private final State preventiveState; private final PrePerimeterResult initialResult; private final PerimeterResult firstPreventivePerimeterResult; @@ -604,23 +603,6 @@ public void setOptimizationStepsExecuted(OptimizationStepsExecuted optimizationS } } - @Override - public boolean isSecure(Instant optimizedInstant, PhysicalParameter... u) { - if (ComputationStatus.FAILURE.equals(getComputationStatus())) { - return false; - } - if (Arrays.stream(u).noneMatch(PhysicalParameter.FLOW::equals)) { - throw new OpenRaoException("This is a flow RaoResult, isSecure is available for FLOW physical parameter"); - } - if (getFunctionalCost(optimizedInstant) >= 0) { - return false; - } - if (Arrays.stream(u).anyMatch(physicalParameter -> !PhysicalParameter.FLOW.equals(physicalParameter))) { - throw new OpenRaoException("This is a flow RaoResult, flows are secure but other physical parameters' security status is unknown"); - } - return true; - } - @Override public boolean isSecure(PhysicalParameter... u) { return isSecure(crac.getLastInstant(), u); From d6f4a565afc2d6ac6d93dcd5589d7f2c46b8fd34 Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Fri, 21 Jun 2024 11:29:46 +0200 Subject: [PATCH 11/13] Promote default methods to Instant interface Signed-off-by: Thomas Bouquet --- .../powsybl/openrao/data/cracapi/Instant.java | 24 ++- .../openrao/data/cracapi/InstantTest.java | 160 ++++++++++++++++++ .../openrao/data/cracimpl/InstantImpl.java | 28 --- 3 files changed, 178 insertions(+), 34 deletions(-) create mode 100644 data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/InstantTest.java diff --git a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/Instant.java b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/Instant.java index 106d9877cf..f9edd1e341 100644 --- a/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/Instant.java +++ b/data/crac/crac-api/src/main/java/com/powsybl/openrao/data/cracapi/Instant.java @@ -25,17 +25,29 @@ public interface Instant extends Identifiable, Comparable { @Override String toString(); - boolean comesBefore(Instant otherInstant); + default boolean comesBefore(Instant otherInstant) { + return getOrder() < otherInstant.getOrder(); + } - boolean comesAfter(Instant otherInstant); + default boolean comesAfter(Instant otherInstant) { + return getOrder() > otherInstant.getOrder(); + } - boolean isPreventive(); + default boolean isPreventive() { + return InstantKind.PREVENTIVE.equals(getKind()); + } - boolean isOutage(); + default boolean isOutage() { + return InstantKind.OUTAGE.equals(getKind()); + } - boolean isAuto(); + default boolean isAuto() { + return InstantKind.AUTO.equals(getKind()); + } - boolean isCurative(); + default boolean isCurative() { + return InstantKind.CURATIVE.equals(getKind()); + } @Override default int compareTo(Instant otherInstant) { diff --git a/data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/InstantTest.java b/data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/InstantTest.java new file mode 100644 index 0000000000..f6b1bfa65b --- /dev/null +++ b/data/crac/crac-api/src/test/java/com/powsybl/openrao/data/cracapi/InstantTest.java @@ -0,0 +1,160 @@ +/* + * 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.cracapi; + +import com.powsybl.commons.extensions.Extension; +import org.junit.jupiter.api.Test; + +import java.util.Collection; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +/** + * @author Thomas Bouquet {@literal } + */ +class InstantTest { + static class InstantImplTest implements Instant { + + private final int order; + private final InstantKind instantKind; + + public InstantImplTest(int order, InstantKind instantKind) { + this.order = order; + this.instantKind = instantKind; + } + + @Override + public String getId() { + return null; + } + + @Override + public String getName() { + return null; + } + + @Override + public int getOrder() { + return order; + } + + @Override + public InstantKind getKind() { + return instantKind; + } + + @Override + public > void addExtension(Class aClass, E e) { + + } + + @Override + public > E getExtension(Class aClass) { + return null; + } + + @Override + public > E getExtensionByName(String s) { + return null; + } + + @Override + public > boolean removeExtension(Class aClass) { + return false; + } + + @Override + public > Collection getExtensions() { + return null; + } + } + + private final Instant preventiveInstant = new InstantImplTest(1, InstantKind.PREVENTIVE); + private final Instant outageInstant = new InstantImplTest(2, InstantKind.OUTAGE); + private final Instant autoInstant = new InstantImplTest(3, InstantKind.AUTO); + private final Instant curativeInstant = new InstantImplTest(4, InstantKind.CURATIVE); + + @Test + void testIsPreventive() { + assertTrue(preventiveInstant.isPreventive()); + assertFalse(outageInstant.isPreventive()); + assertFalse(autoInstant.isPreventive()); + assertFalse(curativeInstant.isPreventive()); + } + + @Test + void testIsOutage() { + assertFalse(preventiveInstant.isOutage()); + assertTrue(outageInstant.isOutage()); + assertFalse(autoInstant.isOutage()); + assertFalse(curativeInstant.isOutage()); + } + + @Test + void testIsAuto() { + assertFalse(preventiveInstant.isAuto()); + assertFalse(outageInstant.isAuto()); + assertTrue(autoInstant.isAuto()); + assertFalse(curativeInstant.isAuto()); + } + + @Test + void testIsCurative() { + assertFalse(preventiveInstant.isCurative()); + assertFalse(outageInstant.isCurative()); + assertFalse(autoInstant.isCurative()); + assertTrue(curativeInstant.isCurative()); + } + + @Test + void testComesBefore() { + assertFalse(preventiveInstant.comesBefore(preventiveInstant)); + assertTrue(preventiveInstant.comesBefore(outageInstant)); + assertTrue(preventiveInstant.comesBefore(autoInstant)); + assertTrue(preventiveInstant.comesBefore(curativeInstant)); + assertFalse(outageInstant.comesBefore(outageInstant)); + assertTrue(outageInstant.comesBefore(autoInstant)); + assertTrue(outageInstant.comesBefore(curativeInstant)); + assertFalse(autoInstant.comesBefore(autoInstant)); + assertTrue(autoInstant.comesBefore(curativeInstant)); + assertFalse(curativeInstant.comesBefore(curativeInstant)); + } + + @Test + void testComesAfter() { + assertFalse(curativeInstant.comesAfter(curativeInstant)); + assertTrue(curativeInstant.comesAfter(autoInstant)); + assertTrue(curativeInstant.comesAfter(outageInstant)); + assertTrue(curativeInstant.comesAfter(preventiveInstant)); + assertFalse(autoInstant.comesAfter(autoInstant)); + assertTrue(autoInstant.comesAfter(outageInstant)); + assertTrue(autoInstant.comesAfter(preventiveInstant)); + assertFalse(outageInstant.comesAfter(outageInstant)); + assertTrue(outageInstant.comesAfter(preventiveInstant)); + assertFalse(preventiveInstant.comesAfter(preventiveInstant)); + } + + @Test + void testCompareInstants() { + assertEquals(0, preventiveInstant.compareTo(preventiveInstant)); + assertEquals(0, curativeInstant.compareTo(curativeInstant)); + assertEquals(-1, preventiveInstant.compareTo(curativeInstant)); + assertEquals(1, curativeInstant.compareTo(preventiveInstant)); + } + + @Test + void testMin() { + assertNull(Instant.min(null, null)); + assertNull(Instant.min(preventiveInstant, null)); + assertNull(Instant.min(null, curativeInstant)); + assertEquals(preventiveInstant, Instant.min(preventiveInstant, curativeInstant)); + } +} diff --git a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/InstantImpl.java b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/InstantImpl.java index 3b98a28a9f..99fdbd5751 100644 --- a/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/InstantImpl.java +++ b/data/crac/crac-impl/src/main/java/com/powsybl/openrao/data/cracimpl/InstantImpl.java @@ -55,34 +55,6 @@ public String toString() { return name; } - public boolean comesBefore(Instant otherInstant) { - return this.order < otherInstant.getOrder(); - } - - public boolean comesAfter(Instant otherInstant) { - return this.order > otherInstant.getOrder(); - } - - @Override - public boolean isPreventive() { - return instantKind == InstantKind.PREVENTIVE; - } - - @Override - public boolean isOutage() { - return instantKind == InstantKind.OUTAGE; - } - - @Override - public boolean isAuto() { - return instantKind == InstantKind.AUTO; - } - - @Override - public boolean isCurative() { - return instantKind == InstantKind.CURATIVE; - } - @Override public boolean equals(Object o) { if (this == o) { From 93b0b352a89af6cd859d642111b0d8875b83ee58 Mon Sep 17 00:00:00 2001 From: Thomas Bouquet <63302082+bqth29@users.noreply.github.com> Date: Mon, 24 Jun 2024 17:01:14 +0200 Subject: [PATCH 12/13] Update data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCne.java Co-authored-by: Peter Mitri Signed-off-by: Thomas Bouquet <63302082+bqth29@users.noreply.github.com> --- .../java/com/powsybl/openrao/data/swecneexporter/SweCne.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCne.java b/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCne.java index 91f59c476a..482f97720e 100644 --- a/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCne.java +++ b/data/result-exporter/swe-cne-exporter/src/main/java/com/powsybl/openrao/data/swecneexporter/SweCne.java @@ -113,7 +113,7 @@ private void addReason(Point point) { try { isUnsecure = !raoResult.isSecure(PhysicalParameter.FLOW, PhysicalParameter.ANGLE); } catch (OpenRaoException e) { - // Sometimes we run this method before without running angle monitoring. In that case, simply ignore AngleCnecs + // Sometimes we run this method without running angle monitoring. In that case, simply ignore AngleCnecs isUnsecure = !raoResult.isSecure(PhysicalParameter.FLOW); } if (isDivergent) { From d3607c8c0ab196bfce277583a6a995b10b3dd92a Mon Sep 17 00:00:00 2001 From: Thomas Bouquet Date: Mon, 24 Jun 2024 17:04:38 +0200 Subject: [PATCH 13/13] Fix after comments Signed-off-by: Thomas Bouquet --- .../impl/{FlowRaoResult.java => AbstractFlowRaoResult.java} | 4 ++-- .../searchtreerao/result/impl/OneStateOnlyRaoResultImpl.java | 2 +- .../result/impl/PreventiveAndCurativesRaoResultImpl.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/{FlowRaoResult.java => AbstractFlowRaoResult.java} (90%) diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/FlowRaoResult.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/AbstractFlowRaoResult.java similarity index 90% rename from ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/FlowRaoResult.java rename to ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/AbstractFlowRaoResult.java index 9c2b5bcf60..3246f5231d 100644 --- a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/FlowRaoResult.java +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/AbstractFlowRaoResult.java @@ -18,9 +18,9 @@ /** * @author Thomas Bouquet {@literal } */ -public interface FlowRaoResult extends RaoResult { +public abstract class AbstractFlowRaoResult implements RaoResult { @Override - default boolean isSecure(Instant optimizedInstant, PhysicalParameter... u) { + public boolean isSecure(Instant optimizedInstant, PhysicalParameter... u) { if (ComputationStatus.FAILURE.equals(getComputationStatus())) { return false; } diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImpl.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImpl.java index 00a8b92d2d..c4945b090e 100644 --- a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImpl.java +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/OneStateOnlyRaoResultImpl.java @@ -27,7 +27,7 @@ /** * @author Joris Mancini {@literal } */ -public class OneStateOnlyRaoResultImpl implements FlowRaoResult { +public class OneStateOnlyRaoResultImpl extends AbstractFlowRaoResult { public static final String WRONG_STATE = "Trying to access perimeter result for the wrong state."; private final State optimizedState; private final PrePerimeterResult initialResult; diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/PreventiveAndCurativesRaoResultImpl.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/PreventiveAndCurativesRaoResultImpl.java index 627e4049df..c11e7a0a00 100644 --- a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/PreventiveAndCurativesRaoResultImpl.java +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/result/impl/PreventiveAndCurativesRaoResultImpl.java @@ -31,7 +31,7 @@ /** * @author Joris Mancini {@literal } */ -public class PreventiveAndCurativesRaoResultImpl implements FlowRaoResult { +public class PreventiveAndCurativesRaoResultImpl extends AbstractFlowRaoResult { private final State preventiveState; private final PrePerimeterResult initialResult; private final PerimeterResult firstPreventivePerimeterResult;