Skip to content

Commit ab839de

Browse files
committed
added comments in Marmot
Signed-off-by: Philippe Edwards <philippe.edwards@rte-france.com>
1 parent cc1e122 commit ab839de

1 file changed

Lines changed: 37 additions & 17 deletions

File tree

  • ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/marmot

ra-optimisation/search-tree-rao/src/main/java/com/powsybl/openrao/searchtreerao/marmot/Marmot.java

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ public class Marmot implements InterTemporalRaoProvider {
6969

7070
@Override
7171
public CompletableFuture<TemporalData<RaoResult>> run(InterTemporalRaoInputWithNetworkPaths interTemporalRaoInputWithNetworkPaths, RaoParameters raoParameters) {
72-
// 1. Run independent RAOs to compute optimal preventive topological remedial actions
72+
// Run independent RAOs to compute optimal preventive topological remedial actions
7373
OpenRaoLoggerProvider.TECHNICAL_LOGS.info("[MARMOT] ----- Topological optimization [start]");
7474
TemporalData<Set<String>> consideredCnecs = new TemporalDataImpl<>();
7575
TemporalData<RaoResult> topologicalOptimizationResults = runTopologicalOptimization(interTemporalRaoInputWithNetworkPaths.getRaoInputs(), consideredCnecs, raoParameters);
@@ -82,8 +82,10 @@ public CompletableFuture<TemporalData<RaoResult>> run(InterTemporalRaoInputWithN
8282
return CompletableFuture.completedFuture(topologicalOptimizationResults);
8383
}
8484

85+
// Get the initial results from the various independent results to avoid recomputing them
8586
TemporalData<PrePerimeterResult> initialResults = buildInitialResults(topologicalOptimizationResults);
8687
TemporalData<RaoInput> raoInputsWithImportedNetworks = new TemporalDataImpl<>();
88+
// Import all the networks and create the InitialScenario variant
8789
interTemporalRaoInputWithNetworkPaths.getRaoInputs().getDataPerTimestamp().forEach((datetime, individualRaoInputWithNetworkPath) -> {
8890
Network network = Network.read(individualRaoInputWithNetworkPath.getPostIcsImportNetworkPath());
8991
RaoInput individualRaoInput = RaoInput
@@ -95,49 +97,59 @@ public CompletableFuture<TemporalData<RaoResult>> run(InterTemporalRaoInputWithN
9597
});
9698
InterTemporalRaoInput interTemporalRaoInput = new InterTemporalRaoInput(raoInputsWithImportedNetworks, interTemporalRaoInputWithNetworkPaths.getPowerGradients());
9799

98-
// 2. Apply preventive topological remedial actions
100+
// Apply preventive topological remedial actions
99101
OpenRaoLoggerProvider.TECHNICAL_LOGS.info("[MARMOT] Applying optimal topological actions on networks");
100102
applyPreventiveTopologicalActionsOnNetwork(interTemporalRaoInput.getRaoInputs(), topologicalOptimizationResults);
101103

104+
// Get the curative ations applied in the individual results to be able to apply them during sensitivity computations
102105
TemporalData<AppliedRemedialActions> curativeRemedialActions = MarmotUtils.getAppliedRemedialActionsInCurative(interTemporalRaoInput.getRaoInputs(), topologicalOptimizationResults);
106+
107+
// Create an objective function that takes into account ALL the cnecs
108+
ObjectiveFunction fullObjectiveFunction = buildGlobalObjectiveFunction(interTemporalRaoInput.getRaoInputs().map(RaoInput::getCrac), new GlobalFlowResult(initialResults), raoParameters);
109+
110+
// Create some variables that will be used in the MIP loops and will still be needed after the loop
103111
TemporalData<PrePerimeterResult> loadFlowResults;
104112
LinearOptimizationResult linearOptimizationResults;
105113
LinearOptimizationResult fullResults;
106-
ObjectiveFunction fullObjectiveFunction = buildGlobalObjectiveFunction(interTemporalRaoInput.getRaoInputs().map(RaoInput::getCrac), new GlobalFlowResult(initialResults), raoParameters);
107114
do {
115+
// Clone the PostTopoScenario variant to make sure we work on a clean variant every time
108116
interTemporalRaoInput.getRaoInputs().getDataPerTimestamp().values().forEach(raoInput -> {
109117
raoInput.getNetwork().getVariantManager().cloneVariant("PostTopoScenario", "PreMipScenario", true);
110118
raoInput.getNetwork().getVariantManager().setWorkingVariant("PreMipScenario");
111119
});
112120

113-
// 3. Run initial sensitivity analysis on all timestamps
121+
// 3. Run post topo sensitivity analysis on all timestamps ON CONSIDERED CNECS ONLY (which is why we do it every loop)
114122
OpenRaoLoggerProvider.TECHNICAL_LOGS.info("[MARMOT] Systematic inter-temporal sensitivity analysis [start]");
115-
TemporalData<PrePerimeterResult> prePerimeterResults = runAllInitialPrePerimeterSensitivityAnalysis(interTemporalRaoInput.getRaoInputs(), curativeRemedialActions, initialResults, consideredCnecs, raoParameters);
123+
TemporalData<PrePerimeterResult> postTopoResults = runAllInitialPrePerimeterSensitivityAnalysis(interTemporalRaoInput.getRaoInputs(), curativeRemedialActions, initialResults, consideredCnecs, raoParameters);
116124
OpenRaoLoggerProvider.TECHNICAL_LOGS.info("[MARMOT] Systematic inter-temporal sensitivity analysis [end]");
117125

118126

119-
// 4. Build objective function and initial result
127+
// Build objective function with ONLY THE CONSIDERED CNECS
120128
ObjectiveFunction filteredObjectiveFunction = buildGlobalObjectiveFunction(interTemporalRaoInput.getRaoInputs().map(RaoInput::getCrac), new GlobalFlowResult(initialResults), consideredCnecs, raoParameters);
121129
TemporalData<NetworkActionsResult> preventiveTopologicalActions = getPreventiveTopologicalActions(interTemporalRaoInput.getRaoInputs().map(RaoInput::getCrac), topologicalOptimizationResults);
122130
//LinearOptimizationResult initialLinearOptimizationResult = getInitialLinearOptimizationResult(prePerimeterResults, preventiveTopologicalActions, objectiveFunction);
123131

124-
// 5. Create and iteratively solve MIP to find optimal range actions' set-points
132+
// Create and iteratively solve MIP to find optimal range actions' set-points FOR THE CONSIDERED CNECS
125133
OpenRaoLoggerProvider.TECHNICAL_LOGS.info("[MARMOT] ----- Global range actions optimization [start]");
126-
linearOptimizationResults = optimizeLinearRemedialActions(interTemporalRaoInput, initialResults, prePerimeterResults, raoParameters, preventiveTopologicalActions, curativeRemedialActions, consideredCnecs, filteredObjectiveFunction);
134+
linearOptimizationResults = optimizeLinearRemedialActions(interTemporalRaoInput, initialResults, postTopoResults, raoParameters, preventiveTopologicalActions, curativeRemedialActions, consideredCnecs, filteredObjectiveFunction);
127135
OpenRaoLoggerProvider.TECHNICAL_LOGS.info("[MARMOT] ----- Global range actions optimization [end]");
128136

137+
// Compute the flows on ALL the cnecs to check if the worst cnecs have changed and were considered in the MIP or not
129138
loadFlowResults = applyActionsAndRunFullLoadflow(interTemporalRaoInput.getRaoInputs(), curativeRemedialActions, linearOptimizationResults, initialResults, raoParameters);
139+
140+
141+
// Create a global result with the flows on ALL cnecs and the actions applied during MIP
130142
TemporalData<RangeActionActivationResult> rangeActionActivationResultTemporalData = ((GlobalRangeActionActivationResult) linearOptimizationResults.getRangeActionActivationResult()).getRangeActionActivationPerTimestamp();
131-
fullResults = new GlobalLinearOptimizationResult(loadFlowResults, prePerimeterResults.map(PrePerimeterResult::getSensitivityResult), rangeActionActivationResultTemporalData, preventiveTopologicalActions, fullObjectiveFunction, LinearProblemStatus.OPTIMAL);
143+
fullResults = new GlobalLinearOptimizationResult(loadFlowResults, postTopoResults.map(PrePerimeterResult::getSensitivityResult), rangeActionActivationResultTemporalData, preventiveTopologicalActions, fullObjectiveFunction, LinearProblemStatus.OPTIMAL);
132144

133145
logCost("[MARMOT] next iteration of MIP: ", fullResults, raoParameters, 10);
134-
} while (!shouldStop(loadFlowResults, consideredCnecs));
146+
} while (!shouldStop(loadFlowResults, consideredCnecs)); // Stop if the worst element of each TS has been considered during MIP
135147

136-
// 6. Merge topological and linear result
148+
// Merge topological and linear result
137149
OpenRaoLoggerProvider.TECHNICAL_LOGS.info("[MARMOT] Merging topological and linear remedial action results");
138150
TemporalData<RaoResult> mergedRaoResults = mergeTopologicalAndLinearOptimizationResults(interTemporalRaoInput.getRaoInputs(), initialResults, linearOptimizationResults, topologicalOptimizationResults);
139151

140-
// 7. Log initial and final results
152+
// Log initial and final results
141153
//logCost("[MARMOT] Before global linear optimization: ", initialLinearOptimizationResult, raoParameters, 10);
142154
logCost("[MARMOT] After global linear optimization: ", linearOptimizationResults, raoParameters, 10);
143155

@@ -146,6 +158,9 @@ public CompletableFuture<TemporalData<RaoResult>> run(InterTemporalRaoInputWithN
146158

147159
private boolean shouldStop(TemporalData<PrePerimeterResult> loadFlowResults, TemporalData<Set<String>> consideredCnecs) {
148160
AtomicBoolean shouldStop = new AtomicBoolean(true);
161+
// For every TS, for all the virtual costs, go through all the costly cnecs in order.
162+
// If the cnec has already been considered, go to the next virtual cost
163+
// If not, add it to the considered cnecs, set shouldStop to false, and go to the next cnec
149164
loadFlowResults.getTimestamps().forEach(timestamp -> {
150165
PrePerimeterResult loadFlowResult = loadFlowResults.getData(timestamp).orElseThrow();
151166
Set<String> cnecs = consideredCnecs.getData(timestamp).orElseThrow();
@@ -181,6 +196,8 @@ private static TemporalData<RaoResult> runTopologicalOptimization(TemporalData<R
181196
OpenRaoLoggerProvider.TECHNICAL_LOGS.info(logMessage, "start");
182197
RaoResult raoResult = FastRao.launchFilteredRao(individualRaoInput, raoParameters, null, cnecs);
183198
OpenRaoLoggerProvider.TECHNICAL_LOGS.info(logMessage, "end");
199+
// generate a mock of the result to avoid storing unneeded information (memory reasons)
200+
// (initial results, activated network actions,
184201
individualResults.add(datetime, generateMockRaoResult(individualRaoInput, raoResult));
185202
consideredCnecs.add(datetime, cnecs);
186203
});
@@ -198,13 +215,16 @@ private static TemporalData<RaoResult> runTopologicalOptimization(TemporalData<R
198215
}
199216

200217
private static RaoResult generateMockRaoResult(RaoInput individualRaoInput, RaoResult raoResult) {
218+
//TODO: create a proper object (record?) for this instead of using Mockito
201219
FastRaoResultImpl mockedRaoResult = Mockito.mock(FastRaoResultImpl.class);
202220
Crac crac = individualRaoInput.getCrac();
203221
State preventiveState = crac.getPreventiveState();
204222
when(mockedRaoResult.getActivatedNetworkActionsDuringState(preventiveState)).thenReturn(raoResult.getActivatedNetworkActionsDuringState(preventiveState));
205223
when(mockedRaoResult.getInitialResult()).thenReturn(((FastRaoResultImpl) raoResult).getInitialResult());
206224

207225
for (State state : crac.getStates(crac.getLastInstant())) {
226+
// This is to get around the cases where the result is a OneStateOnlyRaoResultImpl in the cases where the FastRao filtered rao only optimized the preventive state
227+
// (If we catch an error with message "Trying to access perimeter result for the wrong state.", we know no actions were applied in curative)
208228
boolean errorCaught = false;
209229
try {
210230
raoResult.getActivatedNetworkActionsDuringState(state);
@@ -306,25 +326,25 @@ private static TemporalData<NetworkActionsResult> getPreventiveTopologicalAction
306326
private static LinearOptimizationResult optimizeLinearRemedialActions(
307327
InterTemporalRaoInput raoInput,
308328
TemporalData<PrePerimeterResult> initialResults,
309-
TemporalData<PrePerimeterResult> prePerimeterResults,
329+
TemporalData<PrePerimeterResult> postTopoResults,
310330
RaoParameters parameters,
311331
TemporalData<NetworkActionsResult> preventiveTopologicalActions,
312332
TemporalData<AppliedRemedialActions> curativeRemedialActions,
313333
TemporalData<Set<String>> consideredCnecs,
314334
ObjectiveFunction objectiveFunction) {
315335

316336
// -- Build IteratingLinearOptimizerInterTemporalInput
317-
TemporalData<OptimizationPerimeter> optimizationPerimeterPerTimestamp = computeOptimizationPerimetersPerTimestamp(raoInput.getRaoInputs().map(RaoInput::getCrac), prePerimeterResults, consideredCnecs);
337+
TemporalData<OptimizationPerimeter> optimizationPerimeterPerTimestamp = computeOptimizationPerimetersPerTimestamp(raoInput.getRaoInputs().map(RaoInput::getCrac), initialResults, consideredCnecs);
318338
// no objective function defined in individual IteratingLinearOptimizerInputs as it is global
319339
Map<OffsetDateTime, IteratingLinearOptimizerInput> linearOptimizerInputPerTimestamp = new HashMap<>();
320340
raoInput.getRaoInputs().getTimestamps().forEach(timestamp -> linearOptimizerInputPerTimestamp.put(timestamp, IteratingLinearOptimizerInput.create()
321341
.withNetwork(raoInput.getRaoInputs().getData(timestamp).orElseThrow().getNetwork())
322342
.withOptimizationPerimeter(optimizationPerimeterPerTimestamp.getData(timestamp).orElseThrow())
323343
.withInitialFlowResult(initialResults.getData(timestamp).orElseThrow())
324344
.withPrePerimeterFlowResult(initialResults.getData(timestamp).orElseThrow())
325-
.withPreOptimizationFlowResult(prePerimeterResults.getData(timestamp).orElseThrow())
326-
.withPrePerimeterSetpoints(prePerimeterResults.getData(timestamp).orElseThrow())
327-
.withPreOptimizationSensitivityResult(prePerimeterResults.getData(timestamp).orElseThrow())
345+
.withPreOptimizationFlowResult(postTopoResults.getData(timestamp).orElseThrow())
346+
.withPrePerimeterSetpoints(initialResults.getData(timestamp).orElseThrow())
347+
.withPreOptimizationSensitivityResult(postTopoResults.getData(timestamp).orElseThrow())
328348
.withPreOptimizationAppliedRemedialActions(curativeRemedialActions.getData(timestamp).orElseThrow())
329349
.withToolProvider(ToolProvider.buildFromRaoInputAndParameters(raoInput.getRaoInputs().getData(timestamp).orElseThrow(), parameters))
330350
.withOutageInstant(raoInput.getRaoInputs().getData(timestamp).orElseThrow().getCrac().getOutageInstant())

0 commit comments

Comments
 (0)