diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/castor/algorithm/CastorContingencyScenarios.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/castor/algorithm/CastorContingencyScenarios.java index f92d494662..d17289a890 100644 --- a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/castor/algorithm/CastorContingencyScenarios.java +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/castor/algorithm/CastorContingencyScenarios.java @@ -120,11 +120,10 @@ private Object runScenario(PrePerimeterResult prePerimeterSensitivityOutput, boo boolean autoStateSensiFailed = false; if (automatonState.isPresent()) { AutomatonPerimeterResultImpl automatonResult = automatonSimulator.simulateAutomatonState(automatonState.get(), curativeStates, networkClone, stateTree, automatonTreeParameters); + contingencyScenarioResults.put(automatonState.get(), automatonResult); if (automatonResult.getComputationStatus() == ComputationStatus.FAILURE) { autoStateSensiFailed = true; - contingencyScenarioResults.put(automatonState.get(), new SkippedOptimizationResultImpl(automatonState.get(), automatonResult.getActivatedNetworkActions(), automatonResult.getActivatedRangeActions(automatonState.get()), ComputationStatus.FAILURE, sensitivityFailureOvercost)); } else { - contingencyScenarioResults.put(automatonState.get(), automatonResult); preCurativeResult = automatonResult.getPostAutomatonSensitivityAnalysisOutput(); } } diff --git a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/commons/RaoUtil.java b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/commons/RaoUtil.java index 1305c9c265..64d1ff8e08 100644 --- a/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/commons/RaoUtil.java +++ b/ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/commons/RaoUtil.java @@ -189,15 +189,15 @@ public static Pair, State> getLastAvailableRangeActionOnSameNetwo } else if (state.getInstant().isCurative()) { // look if a preventive range action acts on the same network elements - State preventiveState = optimizationContext.getMainOptimizationState(); + State previousUsageState = optimizationContext.getMainOptimizationState(); - if (preventiveState.isPreventive()) { - Optional> correspondingRa = optimizationContext.getRangeActionsPerState().get(preventiveState).stream() + if (previousUsageState.getInstant().comesBefore(state.getInstant())) { + Optional> correspondingRa = optimizationContext.getRangeActionsPerState().get(previousUsageState).stream() .filter(ra -> ra.getId().equals(rangeAction.getId()) || ra.getNetworkElements().equals(rangeAction.getNetworkElements())) .findAny(); if (correspondingRa.isPresent()) { - return Pair.of(correspondingRa.get(), preventiveState); + return Pair.of(correspondingRa.get(), previousUsageState); } } return null; diff --git a/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/commons/RaoUtilTest.java b/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/commons/RaoUtilTest.java index 20d48a9a68..bed7e86f1b 100644 --- a/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/commons/RaoUtilTest.java +++ b/ra-optimisation/search-tree-rao/src/test/java/com/powsybl/openrao/searchtreerao/commons/RaoUtilTest.java @@ -7,16 +7,20 @@ package com.powsybl.openrao.searchtreerao.commons; +import com.powsybl.contingency.Contingency; import com.powsybl.openrao.commons.OpenRaoException; import com.powsybl.openrao.commons.Unit; import com.powsybl.openrao.data.crac.api.Crac; import com.powsybl.openrao.data.crac.api.Instant; +import com.powsybl.openrao.data.crac.api.InstantKind; +import com.powsybl.openrao.data.crac.api.NetworkElement; import com.powsybl.openrao.data.crac.api.RemedialAction; import com.powsybl.openrao.data.crac.api.State; import com.powsybl.openrao.data.crac.api.cnec.FlowCnec; import com.powsybl.iidm.network.TwoSides; import com.powsybl.openrao.data.crac.api.networkaction.ActionType; import com.powsybl.openrao.data.crac.api.networkaction.NetworkAction; +import com.powsybl.openrao.data.crac.api.rangeaction.RangeAction; import com.powsybl.openrao.data.crac.api.usagerule.OnConstraint; import com.powsybl.openrao.data.crac.api.usagerule.OnInstant; import com.powsybl.openrao.data.crac.api.usagerule.UsageMethod; @@ -25,9 +29,10 @@ import com.powsybl.openrao.raoapi.RaoInput; import com.powsybl.openrao.raoapi.parameters.ObjectiveFunctionParameters; import com.powsybl.openrao.raoapi.parameters.RaoParameters; +import com.powsybl.openrao.raoapi.parameters.RelativeMarginsParameters; import com.powsybl.openrao.raoapi.parameters.extensions.OpenRaoSearchTreeParameters; import com.powsybl.openrao.raoapi.parameters.extensions.SearchTreeRaoRangeActionsOptimizationParameters; -import com.powsybl.openrao.raoapi.parameters.RelativeMarginsParameters; +import com.powsybl.openrao.searchtreerao.commons.optimizationperimeters.OptimizationPerimeter; import com.powsybl.openrao.searchtreerao.result.api.FlowResult; import com.powsybl.openrao.searchtreerao.result.api.PrePerimeterResult; import com.powsybl.glsk.commons.ZonalData; @@ -35,6 +40,7 @@ import com.powsybl.iidm.network.Country; import com.powsybl.iidm.network.Network; import com.powsybl.sensitivity.SensitivityVariableSet; +import org.apache.commons.lang3.tuple.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mockito; @@ -357,4 +363,54 @@ void testElementaryActionsLimitWithNonDiscretePsts() { OpenRaoException exception = assertThrows(OpenRaoException.class, () -> RaoUtil.checkParameters(raoParameters, raoInput)); assertEquals("The PSTs must be approximated as integers to use the limitations of elementary actions as a constraint in the RAO.", exception.getMessage()); } + + @Test + void testGetLastAvailableRangeActionOnSameNetworkElementWithOutageState() { + OptimizationPerimeter optimizationContext = Mockito.mock(OptimizationPerimeter.class); + Mockito.when(optimizationContext.getMainOptimizationState()).thenReturn(crac.getPreventiveState()); + State outageState = Mockito.mock(State.class); + Mockito.when(outageState.getContingency()).thenReturn(Optional.of(crac.getContingency("Contingency FR1 FR3"))); + Mockito.when(outageState.getInstant()).thenReturn(crac.getInstant(InstantKind.OUTAGE)); + OpenRaoException exception = assertThrows(OpenRaoException.class, () -> RaoUtil.getLastAvailableRangeActionOnSameNetworkElement(optimizationContext, crac.getRangeActions().iterator().next(), outageState)); + assertEquals("Linear optimization does not handle range actions which are neither PREVENTIVE nor CURATIVE.", exception.getMessage()); + } + + @Test + void testGetLastAvailableRangeActionOnSameNetworkElementMultiCurative() { + Contingency contingency = crac.getContingency("Contingency FR1 FR3"); + + Instant curative1Instant = Mockito.mock(Instant.class); + Mockito.when(curative1Instant.getKind()).thenReturn(InstantKind.CURATIVE); + + State curativeState1 = Mockito.mock(State.class); + Mockito.when(curativeState1.getInstant()).thenReturn(curative1Instant); + Mockito.when(curativeState1.getContingency()).thenReturn(Optional.of(contingency)); + + Instant curative3Instant = Mockito.mock(Instant.class); + Mockito.when(curative3Instant.getKind()).thenReturn(InstantKind.CURATIVE); + Mockito.when(curative3Instant.isCurative()).thenReturn(true); + + State curativeState3 = Mockito.mock(State.class); + Mockito.when(curativeState3.getInstant()).thenReturn(curative3Instant); + Mockito.when(curativeState3.getContingency()).thenReturn(Optional.of(contingency)); + + Mockito.when(curative1Instant.comesBefore(curative3Instant)).thenReturn(true); + + NetworkElement pst = Mockito.mock(NetworkElement.class); + Mockito.when(pst.getId()).thenReturn("pst"); + + RangeAction rangeAction1 = Mockito.mock(RangeAction.class); + Mockito.when(rangeAction1.getNetworkElements()).thenReturn(Set.of(pst)); + Mockito.when(rangeAction1.getId()).thenReturn("range-action-1"); + + RangeAction rangeAction2 = Mockito.mock(RangeAction.class); + Mockito.when(rangeAction2.getNetworkElements()).thenReturn(Set.of(pst)); + Mockito.when(rangeAction2.getId()).thenReturn("range-action-2"); + + OptimizationPerimeter optimizationContext = Mockito.mock(OptimizationPerimeter.class); + Mockito.when(optimizationContext.getMainOptimizationState()).thenReturn(curativeState1); + Mockito.when(optimizationContext.getRangeActionsPerState()).thenReturn(Map.of(curativeState1, Set.of(rangeAction1))); + + assertEquals(Pair.of(rangeAction1, curativeState1), RaoUtil.getLastAvailableRangeActionOnSameNetworkElement(optimizationContext, rangeAction2, curativeState3)); + } } diff --git a/sensitivity-analysis/src/main/java/com/powsybl/openrao/sensitivityanalysis/SystematicSensitivityAdapter.java b/sensitivity-analysis/src/main/java/com/powsybl/openrao/sensitivityanalysis/SystematicSensitivityAdapter.java index 43c89430b9..d37c5fe16b 100644 --- a/sensitivity-analysis/src/main/java/com/powsybl/openrao/sensitivityanalysis/SystematicSensitivityAdapter.java +++ b/sensitivity-analysis/src/main/java/com/powsybl/openrao/sensitivityanalysis/SystematicSensitivityAdapter.java @@ -131,7 +131,12 @@ static SystematicSensitivityResult runSensitivity(Network network, sensitivityComputationParameters), state.getInstant().getOrder()); } catch (Exception e) { TECHNICAL_LOGS.error(String.format("Systematic sensitivity analysis failed for state %s : %s", state.getId(), e.getMessage())); - result.completeDataWithFailingPerimeter(state.getInstant().getOrder(), optContingency.get().getId()); + SensitivityAnalysisResult failedResult = new SensitivityAnalysisResult( + cnecSensitivityProvider.getContingencyFactors(network, contingencyList), + List.of(new SensitivityAnalysisResult.SensitivityContingencyStatus(optContingency.get().getId(), SensitivityAnalysisResult.Status.FAILURE)), + List.of() + ); + result.completeData(failedResult, state.getInstant().getOrder()); } counterForLogs++; } diff --git a/sensitivity-analysis/src/main/java/com/powsybl/openrao/sensitivityanalysis/SystematicSensitivityResult.java b/sensitivity-analysis/src/main/java/com/powsybl/openrao/sensitivityanalysis/SystematicSensitivityResult.java index 6e6a940537..3d70e6cae3 100644 --- a/sensitivity-analysis/src/main/java/com/powsybl/openrao/sensitivityanalysis/SystematicSensitivityResult.java +++ b/sensitivity-analysis/src/main/java/com/powsybl/openrao/sensitivityanalysis/SystematicSensitivityResult.java @@ -29,7 +29,7 @@ public class SystematicSensitivityResult { private static class StateResult { - private SensitivityComputationStatus status; + private SensitivityComputationStatus status = SensitivityComputationStatus.SUCCESS; private final Map> referenceFlows = new HashMap<>(); private final Map> referenceIntensities = new HashMap<>(); private final Map>> flowSensitivities = new HashMap<>(); @@ -54,6 +54,10 @@ private Map>> getFlowSensitivities() { private Map>> getIntensitySensitivities() { return intensitySensitivities; } + + private boolean isEmpty() { + return referenceFlows.isEmpty() && referenceIntensities.isEmpty() && flowSensitivities.isEmpty() && intensitySensitivities.isEmpty(); + } } public enum SensitivityComputationStatus { @@ -98,24 +102,15 @@ public SystematicSensitivityResult completeData(SensitivityAnalysisResult result ); postContingencyResults.get(instantOrder).put(contingencyStatus.getContingencyId(), contingencyStateResult); } - - nStateResult.status = this.status; - - if (nStateResult.status != SensitivityComputationStatus.FAILURE && anyContingencyFailure) { + if (!results.getPreContingencyValues().isEmpty()) { + nStateResult.status = this.status; + } + if (nStateResult.status != SensitivityComputationStatus.FAILURE && anyContingencyFailure && !nStateResult.isEmpty()) { this.status = SensitivityComputationStatus.PARTIAL_FAILURE; } return this; } - public SystematicSensitivityResult completeDataWithFailingPerimeter(int instantOrder, String contingencyId) { - this.status = SensitivityComputationStatus.PARTIAL_FAILURE; - StateResult contingencyStateResult = new StateResult(); - contingencyStateResult.status = SensitivityComputationStatus.FAILURE; - postContingencyResults.putIfAbsent(instantOrder, new HashMap<>()); - postContingencyResults.get(instantOrder).put(contingencyId, contingencyStateResult); - return this; - } - public SystematicSensitivityResult postTreatIntensities() { postTreatIntensitiesOnState(nStateResult); postContingencyResults.values().forEach(map -> map.values().forEach(this::postTreatIntensitiesOnState)); diff --git a/sensitivity-analysis/src/test/java/com/powsybl/openrao/sensitivityanalysis/SystematicSensitivityResultTest.java b/sensitivity-analysis/src/test/java/com/powsybl/openrao/sensitivityanalysis/SystematicSensitivityResultTest.java index e520c4a85a..f649ab0aad 100644 --- a/sensitivity-analysis/src/test/java/com/powsybl/openrao/sensitivityanalysis/SystematicSensitivityResultTest.java +++ b/sensitivity-analysis/src/test/java/com/powsybl/openrao/sensitivityanalysis/SystematicSensitivityResultTest.java @@ -254,6 +254,7 @@ void testPostTreatHvdcInvert() { } @Test + // Test case where N succeeds and all N-1 fail void testPartialContingencyFailures() { setUpWith12Nodes(); @@ -373,20 +374,70 @@ void testCurativeResultAtOutageInstant() { } @Test - void testCompleteDataWithFailingPerimeter() { + void testCompleteDataWithFailingPerimeterIn2P() { + setUpWith12Nodes(); - // When + + // A first call to complete data with a sensitivity analysis N and N-1 succeed. + // Simulate the first call to completeData of the sensi computation pre 2P. SensitivityAnalysisResult sensitivityAnalysisResult = SensitivityAnalysis.find().run(network, rangeActionSensitivityProvider.getAllFactors(network), rangeActionSensitivityProvider.getContingencies(network), new ArrayList<>(), SensitivityAnalysisParameters.load()); + SystematicSensitivityResult result = new SystematicSensitivityResult().completeData(sensitivityAnalysisResult, outageInstantOrder); assertEquals(SystematicSensitivityResult.SensitivityComputationStatus.SUCCESS, result.getStatus()); - result.completeDataWithFailingPerimeter(outageInstantOrder, "Contingency FR1 FR3"); - // after computation failure on contingency + // Simulate a second call to completeData during sensitivity computation pre 2P on a state with RAs that failed (a N-1 state fails). + Contingency contingency = new Contingency("contingency", new BranchContingency("branch")); + + SensitivityFactor sensitivityFactor1 = new SensitivityFactor( + SensitivityFunctionType.BRANCH_ACTIVE_POWER_1, + "BBE2AA1 FFR3AA1 1", + SensitivityVariableType.TRANSFORMER_PHASE, + "BBE2AA1 BBE3AA1 1", + false, + new ContingencyContext(contingency.getId(), ContingencyContextType.SPECIFIC) + ); + + sensitivityAnalysisResult = new SensitivityAnalysisResult( + List.of(sensitivityFactor1), + List.of(new SensitivityAnalysisResult.SensitivityContingencyStatus(contingency.getId(), SensitivityAnalysisResult.Status.FAILURE)), + List.of() + ); + + result.completeData(sensitivityAnalysisResult, outageInstantOrder); + + // success in n and a n-1 fails -> PARTIAL_FAILURE assertEquals(SystematicSensitivityResult.SensitivityComputationStatus.PARTIAL_FAILURE, result.getStatus()); } + @Test + void testFailingCurativePerimeter() { + setUpWith12Nodes(); + // Simulate a second call to completeData during sensitivity computation pre 2P on a state with RAs that failed (a N-1 state fails). + Contingency contingency = new Contingency("contingency", new BranchContingency("branch")); + + SensitivityFactor sensitivityFactor1 = new SensitivityFactor( + SensitivityFunctionType.BRANCH_ACTIVE_POWER_1, + "BBE2AA1 FFR3AA1 1", + SensitivityVariableType.TRANSFORMER_PHASE, + "BBE2AA1 BBE3AA1 1", + false, + new ContingencyContext(contingency.getId(), ContingencyContextType.SPECIFIC) + ); + + SensitivityAnalysisResult sensitivityAnalysisResult = new SensitivityAnalysisResult( + List.of(sensitivityFactor1), + List.of(new SensitivityAnalysisResult.SensitivityContingencyStatus(contingency.getId(), SensitivityAnalysisResult.Status.FAILURE)), + List.of() + ); + + SystematicSensitivityResult result = new SystematicSensitivityResult(); + result.completeData(sensitivityAnalysisResult, outageInstantOrder); + + assertEquals(SystematicSensitivityResult.SensitivityComputationStatus.FAILURE, result.getStatus()); + } + } diff --git a/tests/src/test/java/com/powsybl/openrao/tests/steps/SearchTreeRaoSteps.java b/tests/src/test/java/com/powsybl/openrao/tests/steps/SearchTreeRaoSteps.java index a38542769d..85e8fb6dfc 100644 --- a/tests/src/test/java/com/powsybl/openrao/tests/steps/SearchTreeRaoSteps.java +++ b/tests/src/test/java/com/powsybl/openrao/tests/steps/SearchTreeRaoSteps.java @@ -172,7 +172,7 @@ public void objectiveFunctionValueAfterAraShouldBe(double expectedValue) { @Then("the value of the objective function after CRA should be {double}") public void objectiveFunctionValueAfterCraShouldBe(double expectedValue) { - assertEquals(expectedValue, raoResult.getCost(crac.getInstant(InstantKind.CURATIVE)), flowAmpereTolerance(expectedValue)); + assertEquals(expectedValue, raoResult.getCost(crac.getLastInstant()), flowAmpereTolerance(expectedValue)); } @Then("the value of the objective function before optimisation should be {double}") diff --git a/tests/src/test/resources/com/powsybl/openrao/tests/features/epic12_export_improvement/US12_15.feature b/tests/src/test/resources/com/powsybl/openrao/tests/features/epic12_export_improvement/US12_15.feature index f58d9e2bc4..6917ee9152 100644 --- a/tests/src/test/resources/com/powsybl/openrao/tests/features/epic12_export_improvement/US12_15.feature +++ b/tests/src/test/resources/com/powsybl/openrao/tests/features/epic12_export_improvement/US12_15.feature @@ -87,7 +87,7 @@ Feature: US 12.15: export different reason per perimeter in SWE CNE And the worst margin is -1419.4 A @fast @rao @mock @ac @contingency-scenarios @second-preventive - # sensi pre 2P fails + # sensi pre 2P partially fails Scenario: US 12.15.2.2: one contingency failing during 1st ARAO, with 2P Given network file is "epic12/nordic32.xiidm" Given crac file is "epic12/CIM_12_15_2.xml" @@ -99,7 +99,7 @@ Feature: US 12.15: export different reason per perimeter in SWE CNE And the worst margin is -1419.4 A @fast @rao @mock @ac @contingency-scenarios @second-preventive - # sensi pre 2P fails + # sensi pre 2P partially fails Scenario: US 12.15.2.3: one contingency failing during 1st ARAO, with global 2P Given network file is "epic12/nordic32.xiidm" Given crac file is "epic12/CIM_12_15_2.xml" diff --git a/tests/src/test/resources/com/powsybl/openrao/tests/features/epic92_costly_rao/US92_2.feature b/tests/src/test/resources/com/powsybl/openrao/tests/features/epic92_costly_rao/US92_2.feature index 29de68b40f..77b0e8bef2 100644 --- a/tests/src/test/resources/com/powsybl/openrao/tests/features/epic92_costly_rao/US92_2.feature +++ b/tests/src/test/resources/com/powsybl/openrao/tests/features/epic92_costly_rao/US92_2.feature @@ -87,4 +87,51 @@ Feature: US 92.2: Costly range actions optimization - APPROXIMATED_INTEGERS PSTs # Activation of pstBeFr3 (20) + 9 taps moved (9 * 7.5) And the value of the objective function after PRA should be 87.5 And 0 remedial actions are used after "coBeFr2" at "curative" - And the value of the objective function after CRA should be 87.5 \ No newline at end of file + And the value of the objective function after CRA should be 87.5 + + @fast @costly @rao + Scenario: US 92.2.6: Multi-curative costly optimization + The same PST is moved in preventive optimization and at all curative states + Given network file is "epic92/2Nodes3ParallelLinesPST.uct" + Given crac file is "epic92/crac-92-2-6.json" + Given configuration file is "epic92/RaoParameters_dc_minObjective_discretePst.json" + When I launch search_tree_rao + Then the worst margin is 32.13 MW + And the value of the objective function initially should be 4500000.0 + And 1 remedial actions are used in preventive + And the remedial action "pstBeFr3" is used in preventive + And the tap of PstRangeAction "pstBeFr3" should be -2 in preventive + # Activation of pstBeFr3 (20) + 2 taps moved (2 * 5.0) + And the value of the objective function after PRA should be 3518125.13 + And 1 remedial actions are used after "coBeFr2" at "curative-1" + And the remedial action "pstBeFr3" is used after "coBeFr2" at "curative-1" + And the tap of PstRangeAction "pstBeFr3" should be -7 after "coBeFr2" at "curative-1" + And 1 remedial actions are used after "coBeFr2" at "curative-2" + And the remedial action "pstBeFr3" is used after "coBeFr2" at "curative-2" + And the tap of PstRangeAction "pstBeFr3" should be -9 after "coBeFr2" at "curative-2" + And 1 remedial actions are used after "coBeFr2" at "curative-3" + And the remedial action "pstBeFr3" is used after "coBeFr2" at "curative-3" + And the tap of PstRangeAction "pstBeFr3" should be -10 after "coBeFr2" at "curative-3" + # Activation of pstBeFr3 4 times (4 * 20) + 10 taps moved (10 * 5.0) + And the value of the objective function after CRA should be 130.0 + + @fast @costly @rao @second-preventive + Scenario: US 92.2.6: Multi-curative costly optimization with 2P + Same case as US 92.2.6 but with second preventive optimization. + The PST is moved to tap -10 straight from preventive optimization to cut activation expenses. + Given network file is "epic92/2Nodes3ParallelLinesPST.uct" + Given crac file is "epic92/crac-92-2-6.json" + Given configuration file is "epic92/RaoParameters_dc_minObjective_discretePst_2P.json" + When I launch search_tree_rao + Then the worst margin is 40.77 MW + And the value of the objective function initially should be 4500000.0 + And 1 remedial actions are used in preventive + And the remedial action "pstBeFr3" is used in preventive + And the tap of PstRangeAction "pstBeFr3" should be -10 in preventive + # Activation of pstBeFr3 (20) + 10 taps moved (10 * 5.0) + And the value of the objective function after PRA should be 70.0 + And 0 remedial actions are used after "coBeFr2" at "curative-1" + And 0 remedial actions are used after "coBeFr2" at "curative-2" + And 0 remedial actions are used after "coBeFr2" at "curative-3" + # Activation of pstBeFr3 (20) + 10 taps moved (10 * 5.0) + And the value of the objective function after CRA should be 70.0 \ No newline at end of file diff --git a/tests/src/test/resources/files/crac/epic92/crac-92-2-6.json b/tests/src/test/resources/files/crac/epic92/crac-92-2-6.json new file mode 100644 index 0000000000..f3c194233c --- /dev/null +++ b/tests/src/test/resources/files/crac/epic92/crac-92-2-6.json @@ -0,0 +1,234 @@ +{ + "type": "CRAC", + "version": "2.6", + "info": "Generated by PowSyBl OpenRAO https://powsybl.readthedocs.io/projects/openrao/", + "id": "crac-92.2.6", + "name": "crac-92.2.6", + "instants": [ + { + "id": "preventive", + "kind": "PREVENTIVE" + }, + { + "id": "outage", + "kind": "OUTAGE" + }, + { + "id": "curative-1", + "kind": "CURATIVE" + }, + { + "id": "curative-2", + "kind": "CURATIVE" + }, + { + "id": "curative-3", + "kind": "CURATIVE" + } + ], + "networkElementsNamePerId": {}, + "contingencies": [ + { + "id": "coBeFr2", + "networkElementsIds": [ + "BBE1AA1 FFR1AA1 2" + ] + } + ], + "flowCnecs": [ + { + "id": "cnecBeFrPreventive", + "name": "cnecBeFrPreventive", + "networkElementId": "BBE1AA1 FFR1AA1 1", + "operator": "FR", + "instant": "preventive", + "contingencyId": null, + "optimized": true, + "monitored": false, + "iMax": [ + NaN + ], + "nominalV": [ + 400.0 + ], + "thresholds": [ + { + "unit": "megawatt", + "min": -300.0, + "max": 300.0, + "side": 1 + }, + { + "unit": "megawatt", + "min": -300.0, + "max": 300.0, + "side": 2 + } + ] + }, + { + "id": "cnecBeFrCurative1", + "name": "cnecBeFrCurative1", + "networkElementId": "BBE1AA1 FFR1AA1 1", + "operator": "FR", + "instant": "curative-1", + "contingencyId": "coBeFr2", + "optimized": true, + "monitored": false, + "iMax": [ + NaN + ], + "nominalV": [ + 400.0 + ], + "thresholds": [ + { + "unit": "megawatt", + "min": -200.0, + "max": 200.0, + "side": 1 + }, + { + "unit": "megawatt", + "min": -200.0, + "max": 200.0, + "side": 2 + } + ] + }, + { + "id": "cnecBeFrCurative2", + "name": "cnecBeFrCurative2", + "networkElementId": "BBE1AA1 FFR1AA1 1", + "operator": "FR", + "instant": "curative-2", + "contingencyId": "coBeFr2", + "optimized": true, + "monitored": false, + "iMax": [ + NaN + ], + "nominalV": [ + 400.0 + ], + "thresholds": [ + { + "unit": "megawatt", + "min": -100.0, + "max": 100.0, + "side": 1 + }, + { + "unit": "megawatt", + "min": -100.0, + "max": 100.0, + "side": 2 + } + ] + }, + { + "id": "cnecBeFrCurative3", + "name": "cnecBeFrCurative3", + "networkElementId": "BBE1AA1 FFR1AA1 1", + "operator": "FR", + "instant": "curative-3", + "contingencyId": "coBeFr2", + "optimized": true, + "monitored": false, + "iMax": [ + NaN + ], + "nominalV": [ + 400.0 + ], + "thresholds": [ + { + "unit": "megawatt", + "min": -50.0, + "max": 50.0, + "side": 1 + }, + { + "unit": "megawatt", + "min": -50.0, + "max": 50.0, + "side": 2 + } + ] + } + ], + "pstRangeActions": [ + { + "id": "pstBeFr3", + "name": "pstBeFr3", + "operator": "BE", + "activationCost": 20.0, + "variationCosts": { + "up": 5.0, + "down": 5.0 + }, + "onInstantUsageRules": [ + { + "instant": "preventive", + "usageMethod": "available" + }, + { + "instant": "curative-1", + "usageMethod": "available" + }, + { + "instant": "curative-2", + "usageMethod": "available" + }, + { + "instant": "curative-3", + "usageMethod": "available" + } + ], + "networkElementId": "BBE1AA1 FFR1AA1 3", + "initialTap": 0, + "tapToAngleConversionMap": { + "-1": -0.3896097993971608, + "0": 0.0, + "-2": -0.7792105912934298, + "1": 0.3896097993971608, + "-3": -1.1687933694373345, + "2": 0.7792105912934298, + "-4": -1.5583491300758083, + "3": 1.1687933694373345, + "-5": -1.9478688732023104, + "4": 1.5583491300758083, + "-6": -2.337343603803646, + "5": 1.9478688732023104, + "-7": -2.7267643331050597, + "6": 2.337343603803646, + "-8": -3.1161220798131644, + "7": 2.7267643331050597, + "-9": -3.505407871356285, + "8": 3.1161220798131644, + "-10": -3.894612745121778, + "9": 3.505407871356285, + "-11": -4.283727749689918, + "10": 3.894612745121778, + "-12": -4.672743946063913, + "11": 4.283727749689918, + "-13": -5.061652408895631, + "12": 4.672743946063913, + "-14": -5.4504442277066305, + "13": 5.061652408895631, + "-15": -5.839110508104064, + "14": 5.4504442277066305, + "-16": -6.2276423729910535, + "15": 5.839110508104064, + "16": 6.2276423729910535 + }, + "ranges": [ + { + "min": -16, + "max": 16, + "rangeType": "absolute" + } + ] + } + ] +} \ No newline at end of file