1010import com .powsybl .openrao .commons .OpenRaoException ;
1111import com .powsybl .openrao .data .crac .api .Crac ;
1212import com .powsybl .openrao .data .crac .api .Instant ;
13- import com .powsybl .openrao .data .crac .api .InstantKind ;
1413import com .powsybl .openrao .data .crac .api .State ;
1514import com .powsybl .openrao .data .crac .api .cnec .FlowCnec ;
1615import com .powsybl .openrao .data .crac .api .networkaction .NetworkAction ;
4645import java .time .temporal .ChronoUnit ;
4746import java .util .*;
4847import java .util .concurrent .*;
48+ import java .util .stream .Collectors ;
4949
5050import static com .powsybl .openrao .commons .logs .OpenRaoLoggerProvider .*;
5151import static com .powsybl .openrao .searchtreerao .commons .HvdcUtils .getHvdcRangeActionsOnHvdcLineInAcEmulation ;
@@ -200,28 +200,34 @@ public CompletableFuture<RaoResult> run() {
200200 boolean logFinalResultsOutsideOfSecondPreventive = true ;
201201 // Run second preventive when necessary
202202 CastorSecondPreventive castorSecondPreventive = new CastorSecondPreventive (crac , raoParameters , network , stateTree , toolProvider , targetEndInstant );
203- PostPerimeterResult secondPreventiveResult = postPreventiveResult ;
203+
204+ // define variables to set with second preventive results only if it improves first
205+ PostPerimeterResult finalSecondPreventiveResult = postPreventiveResult ;
206+ PostPerimeterResult intermediateSecondPreventiveResult = postPreventiveResult ;
207+ Map <State , PostPerimeterResult > finalPostContingencyResults = new HashMap <>(postContingencyResults );
208+
204209 if (castorSecondPreventive .shouldRunSecondPreventiveRao (preventiveResult , postContingencyResults .values (), mergedRaoResults , preventiveRaoTime )) {
205210 CastorSecondPreventive .SecondPreventiveRaoResultsHolder secondPreventiveRaoResultsHolder = castorSecondPreventive .runSecondPreventiveAndAutoRao (castorContingencyScenarios , prePerimeterSensitivityAnalysis , initialOutput , postPreventiveResult , postContingencyResults );
206211 RaoResult secondPreventiveRaoResults ;
207212 if (secondPreventiveRaoResultsHolder .hasFailed ()) {
208213 secondPreventiveRaoResults = new FailedRaoResultImpl (secondPreventiveRaoResultsHolder .errorMessage ());
209214 } else {
210- secondPreventiveResult = new PostPerimeterResult (
215+ intermediateSecondPreventiveResult = new PostPerimeterResult (
211216 secondPreventiveRaoResultsHolder .secondPreventiveRaoResult ().perimeterResult (),
212217 secondPreventiveRaoResultsHolder .secondPreventiveRaoResult ().postPraSensitivityAnalysisOutput ()
213218 );
214219 secondPreventiveRaoResults = new PreventiveAndCurativesRaoResultImpl (
215220 stateTree ,
216221 initialOutput ,
217222 postPreventiveResult ,
218- secondPreventiveResult ,
223+ intermediateSecondPreventiveResult ,
219224 secondPreventiveRaoResultsHolder .postContingencyResults (),
220225 crac ,
221226 raoParameters );
222227 }
223228 if (secondPreventiveImprovesResults (secondPreventiveRaoResults , mergedRaoResults )) {
224- postContingencyResults = secondPreventiveRaoResultsHolder .postContingencyResults ();
229+ finalSecondPreventiveResult = intermediateSecondPreventiveResult ;
230+ finalPostContingencyResults = new HashMap <>(secondPreventiveRaoResultsHolder .postContingencyResults ());
225231 mergedRaoResults = secondPreventiveRaoResults ;
226232 mergedRaoResults .setExecutionDetails (OptimizationStepsExecuted .SECOND_PREVENTIVE_IMPROVED_FIRST );
227233 logFinalResultsOutsideOfSecondPreventive = false ;
@@ -232,8 +238,8 @@ public CompletableFuture<RaoResult> run() {
232238 // Log final results
233239 if (logFinalResultsOutsideOfSecondPreventive ) {
234240 BUSINESS_LOGS .info ("Merging preventive and post-contingency RAO results:" );
235- RaoLogger .logMostLimitingElementsResults (BUSINESS_LOGS , stateTree .getBasecaseScenario (), preventiveResult , stateTree .getContingencyScenarios (), postContingencyResults , raoParameters .getObjectiveFunctionParameters ().getType (), raoParameters .getObjectiveFunctionParameters ().getUnit (), NUMBER_LOGGED_ELEMENTS_END_RAO );
236- RaoLogger .checkIfMostLimitingElementIsFictional (BUSINESS_LOGS , stateTree .getBasecaseScenario (), preventiveResult , stateTree .getContingencyScenarios (), postContingencyResults , raoParameters .getObjectiveFunctionParameters ().getType (), raoParameters .getObjectiveFunctionParameters ().getUnit ());
241+ RaoLogger .logMostLimitingElementsResults (BUSINESS_LOGS , stateTree .getBasecaseScenario (), finalSecondPreventiveResult . optimizationResult () , stateTree .getContingencyScenarios (), finalPostContingencyResults , raoParameters .getObjectiveFunctionParameters ().getType (), raoParameters .getObjectiveFunctionParameters ().getUnit (), NUMBER_LOGGED_ELEMENTS_END_RAO );
242+ RaoLogger .checkIfMostLimitingElementIsFictional (BUSINESS_LOGS , stateTree .getBasecaseScenario (), finalSecondPreventiveResult . optimizationResult () , stateTree .getContingencyScenarios (), finalPostContingencyResults , raoParameters .getObjectiveFunctionParameters ().getType (), raoParameters .getObjectiveFunctionParameters ().getUnit ());
237243 }
238244
239245 CompletableFuture <RaoResult > raoResult = postCheckResults (mergedRaoResults , initialOutput , raoParameters .getObjectiveFunctionParameters (), true );
@@ -244,20 +250,21 @@ public CompletableFuture<RaoResult> run() {
244250 BUSINESS_LOGS .info ("----- PST regulation [start]" );
245251 network .getVariantManager ().cloneVariant (INITIAL_SCENARIO , PST_REGULATION );
246252 network .getVariantManager ().setWorkingVariant (PST_REGULATION );
247- Set <PstRegulationResult > pstRegulationResults = CastorPstRegulation .regulatePsts (pstsToRegulate , postContingencyResults , network , crac , raoParameters , raoResult . join () );
248- postContingencyResults = mergeRaoAndPstRegulationResults (pstRegulationResults , secondPreventiveResult , postContingencyResults , prePerimeterSensitivityAnalysis , initialOutput , toolProvider );
253+ Set <PstRegulationResult > pstRegulationResults = CastorPstRegulation .regulatePsts (pstsToRegulate , finalPostContingencyResults , network , crac , raoParameters , mergedRaoResults );
254+ Map < State , PostPerimeterResult > postRegulationResults = mergeRaoAndPstRegulationResults (pstRegulationResults , finalSecondPreventiveResult , finalPostContingencyResults , prePerimeterSensitivityAnalysis , initialOutput , toolProvider );
249255 RaoResult raoResultWithRegulation = new PreventiveAndCurativesRaoResultImpl (
250256 stateTree ,
251257 initialOutput ,
252258 postPreventiveResult ,
253- secondPreventiveResult ,
254- postContingencyResults ,
259+ finalSecondPreventiveResult ,
260+ postRegulationResults ,
255261 crac ,
256262 raoParameters );
263+ raoResultWithRegulation .setExecutionDetails (mergedRaoResults .getExecutionDetails ());
257264 BUSINESS_LOGS .info ("----- PST regulation [end]" );
258265 BUSINESS_LOGS .info ("Merging RAO and PST regulation results:" );
259- RaoLogger .logMostLimitingElementsResults (BUSINESS_LOGS , stateTree .getBasecaseScenario (), preventiveResult , stateTree .getContingencyScenarios (), postContingencyResults , raoParameters .getObjectiveFunctionParameters ().getType (), raoParameters .getObjectiveFunctionParameters ().getUnit (), NUMBER_LOGGED_ELEMENTS_END_RAO );
260- RaoLogger .checkIfMostLimitingElementIsFictional (BUSINESS_LOGS , stateTree .getBasecaseScenario (), preventiveResult , stateTree .getContingencyScenarios (), postContingencyResults , raoParameters .getObjectiveFunctionParameters ().getType (), raoParameters .getObjectiveFunctionParameters ().getUnit ());
266+ RaoLogger .logMostLimitingElementsResults (BUSINESS_LOGS , stateTree .getBasecaseScenario (), finalSecondPreventiveResult . optimizationResult () , stateTree .getContingencyScenarios (), postRegulationResults , raoParameters .getObjectiveFunctionParameters ().getType (), raoParameters .getObjectiveFunctionParameters ().getUnit (), NUMBER_LOGGED_ELEMENTS_END_RAO );
267+ RaoLogger .checkIfMostLimitingElementIsFictional (BUSINESS_LOGS , stateTree .getBasecaseScenario (), finalSecondPreventiveResult . optimizationResult () , stateTree .getContingencyScenarios (), postRegulationResults , raoParameters .getObjectiveFunctionParameters ().getType (), raoParameters .getObjectiveFunctionParameters ().getUnit ());
261268 return postCheckResults (raoResultWithRegulation , initialOutput , raoParameters .getObjectiveFunctionParameters (), false );
262269 }
263270
@@ -394,59 +401,46 @@ private Pair<OptimizationResult, Set<FlowCnec>> optimizePreventivePerimeter(Stat
394401 }
395402
396403 private Map <State , PostPerimeterResult > mergeRaoAndPstRegulationResults (Set <PstRegulationResult > pstRegulationResults , PostPerimeterResult postPraResult , Map <State , PostPerimeterResult > postContingencyResults , PrePerimeterSensitivityAnalysis prePerimeterSensitivityAnalysis , FlowResult initialFlowResult , ToolProvider toolProvider ) {
397- network .getVariantManager ().setWorkingVariant (PREVENTIVE_SCENARIO );
398- Map <State , PostPerimeterResult > postRegulationPostContingencyResults = new HashMap <>(postContingencyResults );
399- for (PstRegulationResult pstRegulationResult : pstRegulationResults ) {
400- State curativeState = crac .getState (pstRegulationResult .contingency ().getId (), crac .getLastInstant ());
401- if (!pstRegulationResult .regulatedTapPerPst ().isEmpty ()) {
402- String postRegulationVariantName = "PostPstRegulation_Contingency_%s" .formatted (pstRegulationResult .contingency ().getId ());
403- network .getVariantManager ().cloneVariant (PREVENTIVE_SCENARIO , postRegulationVariantName );
404- network .getVariantManager ().setWorkingVariant (postRegulationVariantName );
405-
406- AppliedRemedialActions appliedArasAndCras = new AppliedRemedialActions ();
407- Map <State , Set <NetworkAction >> appliedNetworkActions = new HashMap <>();
408- List <State > previousStates = new ArrayList <>();
409- if (crac .hasAutoInstant ()) {
410- State autoState = crac .getState (pstRegulationResult .contingency ().getId (), crac .getInstant (InstantKind .AUTO ));
411- if (autoState != null ) {
412- previousStates .add (autoState );
413- appliedArasAndCras .addAppliedNetworkActions (autoState , postContingencyResults .get (autoState ).optimizationResult ().getActivatedNetworkActions ());
414- appliedArasAndCras .addAppliedRangeActions (autoState , getAppliedRangeActionsAndSetPoint (autoState , postContingencyResults .get (autoState ).optimizationResult ()));
415- appliedNetworkActions .put (autoState , appliedArasAndCras .getAppliedNetworkActions (autoState ));
416- }
417- }
418- crac .getInstants (InstantKind .CURATIVE ).stream ().map (instant -> crac .getState (pstRegulationResult .contingency ().getId (), instant ))
419- .filter (Objects ::nonNull )
420- .forEach (cState -> {
421- previousStates .add (cState );
422- appliedArasAndCras .addAppliedNetworkActions (cState , postContingencyResults .get (cState ).optimizationResult ().getActivatedNetworkActions ());
423- appliedArasAndCras .addAppliedRangeActions (cState , getAppliedRangeActionsAndSetPoint (cState , postContingencyResults .get (cState ).optimizationResult ()));
424- appliedNetworkActions .put (cState , appliedArasAndCras .getAppliedNetworkActions (cState ));
425- });
426- pstRegulationResult .regulatedTapPerPst ().forEach ((pstRangeAction , regulatedTap ) -> appliedArasAndCras .addAppliedRangeAction (curativeState , pstRangeAction , pstRangeAction .convertTapToAngle (regulatedTap )));
427-
428- previousStates .forEach (s -> appliedArasAndCras .applyOnNetwork (s , network ));
429-
430- // retrieve pre-perimeter result before optimization and PST regulation of last curative state
431- PrePerimeterResult preLastCurativePerimeterResult = getPreLastCurativePerimeterResult (previousStates , postPraResult , postContingencyResults );
432- RangeActionActivationResultImpl postRegulationRangeActionActivationResult = new RangeActionActivationResultImpl (preLastCurativePerimeterResult .getRangeActionSetpointResult ());
433- appliedArasAndCras .getAppliedRangeActions (curativeState ).forEach ((rangeAction , setPoint ) -> postRegulationRangeActionActivationResult .putResult (rangeAction , curativeState , setPoint ));
434-
435- // compute pre-perimeter result including CRAs and PST regulation
436- PrePerimeterResult postCraSensitivityAnalysisOutput = prePerimeterSensitivityAnalysis .runBasedOnInitialResults (network , initialFlowResult , Collections .emptySet (), new AppliedRemedialActions ());
437- OptimizationResult optimizationResult = new OptimizationResultImpl (postCraSensitivityAnalysisOutput , postCraSensitivityAnalysisOutput , postCraSensitivityAnalysisOutput , new NetworkActionsResultImpl (appliedNetworkActions ), postRegulationRangeActionActivationResult );
438-
439- try {
440- PostPerimeterResult postRegulationResult = new PostPerimeterSensitivityAnalysis (crac , crac .getFlowCnecs (curativeState ), crac .getRangeActions (curativeState ), raoParameters , toolProvider )
441- .runBasedOnInitialPreviousAndOptimizationResults (network , initialFlowResult , CompletableFuture .completedFuture (preLastCurativePerimeterResult ), Collections .emptySet (), optimizationResult , null )
442- .get ();
443- postRegulationPostContingencyResults .put (curativeState , postRegulationResult );
444- } catch (InterruptedException | ExecutionException e ) {
445- Thread .currentThread ().interrupt ();
446- throw new OpenRaoException ("Exception during post PST regulation sensitivity analysis for state %s" .formatted (curativeState .getId ()), e );
447- }
448- }
404+ // create a new network variant from initial variant for performing the results merging
405+ String variantName = "PSTRegulationResultsMerging" ;
406+ network .getVariantManager ().setWorkingVariant (INITIAL_SCENARIO );
407+ network .getVariantManager ().cloneVariant (INITIAL_SCENARIO , variantName );
408+ network .getVariantManager ().setWorkingVariant (variantName );
409+
410+ // apply PRAs
411+ applyRemedialActions (network , postPraResult .optimizationResult (), crac .getPreventiveState ());
412+
413+ Set <State > regulatedStates = pstRegulationResults .stream ().map (pstRegulationResult -> crac .getState (pstRegulationResult .contingency ().getId (), crac .getLastInstant ())).collect (Collectors .toSet ());
414+ Map <State , Set <NetworkAction >> appliedNetworkActions = new HashMap <>();
415+
416+ // gather all applied ARAs and CRAs
417+ AppliedRemedialActions appliedRemedialActions = new AppliedRemedialActions ();
418+ postContingencyResults .forEach ((state , postPerimeterResult ) -> {
419+ appliedNetworkActions .put (state , postPerimeterResult .optimizationResult ().getActivatedNetworkActions ());
420+ appliedRemedialActions .addAppliedNetworkActions (state , postPerimeterResult .optimizationResult ().getActivatedNetworkActions ());
421+ appliedRemedialActions .addAppliedRangeActions (state , getAppliedRangeActionsAndSetPoint (state , postPraResult .optimizationResult ()));
422+ appliedRemedialActions .addAppliedRangeActions (state , getAppliedRangeActionsAndSetPoint (state , postPerimeterResult .optimizationResult ()));
423+ });
424+
425+ // overwrite PST range action results for regulated PSTs
426+ pstRegulationResults .forEach (pstRegulationResult -> pstRegulationResult .regulatedTapPerPst ().forEach ((pstRangeAction , regulatedTap ) -> appliedRemedialActions .addAppliedRangeAction (crac .getState (pstRegulationResult .contingency ().getId (), crac .getLastInstant ()), pstRangeAction , pstRangeAction .convertTapToAngle (regulatedTap ))));
427+
428+ PrePerimeterResult postCraSensitivityAnalysisOutput = prePerimeterSensitivityAnalysis .runBasedOnInitialResults (network , initialFlowResult , Collections .emptySet (), appliedRemedialActions );
429+
430+ Map <State , PostPerimeterResult > postRegulationPostContingencyResults = new HashMap <>();
431+
432+ // override optimization result
433+ RangeActionActivationResultImpl postRegulationRangeActionActivationResult = new RangeActionActivationResultImpl (postCraSensitivityAnalysisOutput );
434+ postContingencyResults .keySet ().forEach (state -> appliedRemedialActions .getAppliedRangeActions (state ).forEach ((rangeAction , setPoint ) -> postRegulationRangeActionActivationResult .putResult (rangeAction , state , setPoint )));
435+ OptimizationResult newOptimizationResult = new OptimizationResultImpl (postCraSensitivityAnalysisOutput , postCraSensitivityAnalysisOutput , postCraSensitivityAnalysisOutput , new NetworkActionsResultImpl (appliedNetworkActions ), postRegulationRangeActionActivationResult );
436+
437+ for (State state : postContingencyResults .keySet ()) {
438+ postRegulationPostContingencyResults .put (state , new PostPerimeterResult (
439+ regulatedStates .contains (state ) ? newOptimizationResult : postContingencyResults .get (state ).optimizationResult (),
440+ postCraSensitivityAnalysisOutput
441+ ));
449442 }
443+
450444 return postRegulationPostContingencyResults ;
451445 }
452446
@@ -455,16 +449,4 @@ private static Map<RangeAction<?>, Double> getAppliedRangeActionsAndSetPoint(Sta
455449 optimizationResult .getActivatedRangeActions (state ).forEach (rangeAction -> optimizedRangeActions .put (rangeAction , optimizationResult .getOptimizedSetpoint (rangeAction , state )));
456450 return optimizedRangeActions ;
457451 }
458-
459- /**
460- * Returns the PrePerimeterResult corresponding to the situation just before the optimization of the last instant of
461- * the CRAC. All the remedial actions from the previous states are thus applied.
462- *
463- * @param previousStates : sorted set containing all the post-outage optimized states that share a common contingency (the final element always is the last CRAC instant's state)
464- */
465- private static PrePerimeterResult getPreLastCurativePerimeterResult (List <State > previousStates , PostPerimeterResult postPraResult , Map <State , PostPerimeterResult > postContingencyResults ) {
466- // if previousStates is of size 1, then it only contains the final instant's state so the pre-perimeter result corresponds to the post-PRAs result
467- // otherwise, the penultimate pre-perimeter result must be retrieved
468- return previousStates .size () == 1 ? postPraResult .prePerimeterResultForAllFollowingStates () : postContingencyResults .get (previousStates .get (previousStates .size () - 2 )).prePerimeterResultForAllFollowingStates ();
469- }
470452}
0 commit comments