Skip to content

Commit e2a9a68

Browse files
bqth29Godelaine
andauthored
fix(PST regulation): Objective function reevaluation after PST regulation (#1561)
* do not regulate skipped perimeters * add log when no PST regulated * fix bug on reported cost Signed-off-by: Thomas Bouquet <thomas.bouquet@rte-france.com> Co-authored-by: Godelaine <godelaine.demontmorillon@rte-france.com>
1 parent 284ada8 commit e2a9a68

4 files changed

Lines changed: 70 additions & 79 deletions

File tree

ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/castor/algorithm/CastorFullOptimization.java

Lines changed: 59 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import com.powsybl.openrao.commons.OpenRaoException;
1111
import com.powsybl.openrao.data.crac.api.Crac;
1212
import com.powsybl.openrao.data.crac.api.Instant;
13-
import com.powsybl.openrao.data.crac.api.InstantKind;
1413
import com.powsybl.openrao.data.crac.api.State;
1514
import com.powsybl.openrao.data.crac.api.cnec.FlowCnec;
1615
import com.powsybl.openrao.data.crac.api.networkaction.NetworkAction;
@@ -46,6 +45,7 @@
4645
import java.time.temporal.ChronoUnit;
4746
import java.util.*;
4847
import java.util.concurrent.*;
48+
import java.util.stream.Collectors;
4949

5050
import static com.powsybl.openrao.commons.logs.OpenRaoLoggerProvider.*;
5151
import 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

Comments
 (0)