@@ -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