2828#include " ../../include/integration/CMultiGridIntegration.hpp"
2929#include " ../../../Common/include/parallelization/omp_structure.hpp"
3030
31+ #include " ComputeLinSysResRMS.hpp"
32+
3133
3234CMultiGridIntegration::CMultiGridIntegration () : CIntegration() { }
3335
@@ -217,7 +219,7 @@ void CMultiGridIntegration::MultiGrid_Cycle(CGeometry ****geometry,
217219 /* --- Compute prolongated solution, and smooth the correction $u^(new)_k = u_k + Smooth(I^k_(k+1)(u_(k+1)-I^(k+1)_k u_k))$ ---*/
218220
219221 GetProlongated_Correction (RunTime_EqSystem, solver_fine, solver_coarse, geometry_fine, geometry_coarse, config);
220- SmoothProlongated_Correction (RunTime_EqSystem, solver_fine, geometry_fine, config->GetMG_CorrecSmooth (iMesh), 1.25 , config);
222+ SmoothProlongated_Correction (RunTime_EqSystem, solver_fine, geometry_fine, config->GetMG_CorrecSmooth (iMesh), config-> GetMG_Smooth_Coeff () , config, iMesh );
221223 SetProlongated_Correction (solver_fine, geometry_fine, config, iMesh);
222224
223225
@@ -245,43 +247,52 @@ unsigned short iRKLimit) {
245247 const unsigned short nPreSmooth = config->GetMG_PreSmooth (iMesh);
246248 const unsigned long timeIter = config->GetTimeIter ();
247249
250+ // Early exit settings from config
251+ const bool early_exit_enabled = config->GetMG_Smooth_EarlyExit ();
252+ const su2double early_exit_threshold = config->GetMG_Smooth_Res_Threshold ();
253+ const bool output_enabled = config->GetMG_Smooth_Output ();
254+
255+ su2double initial_rms = 0.0 ;
256+ if (early_exit_enabled || output_enabled) {
257+ initial_rms = ComputeLinSysResRMS (solver_fine, geometry_fine);
258+ if (output_enabled) {
259+ cout << " MG Pre-Smoothing Level " << iMesh << " Initial RMS: " << initial_rms << endl;
260+ }
261+ }
262+
248263 /* --- Do a presmoothing on the grid iMesh to be restricted to the grid iMesh+1 ---*/
249264 for (unsigned short iPreSmooth = 0 ; iPreSmooth < nPreSmooth; iPreSmooth++) {
250-
251265 /* --- Time and space integration ---*/
252266 for (unsigned short iRKStep = 0 ; iRKStep < iRKLimit; iRKStep++) {
253-
254267 /* --- Send-Receive boundary conditions, and preprocessing ---*/
255268 solver_fine->Preprocessing (geometry_fine, solver_container_fine, config, iMesh, iRKStep, RunTime_EqSystem, false );
256-
257269 if (iRKStep == 0 ) {
258-
259270 /* --- Set the old solution ---*/
260271 solver_fine->Set_OldSolution ();
261-
262272 if (classical_rk4) solver_fine->Set_NewSolution ();
263- // nijso asks: only call when classical_rk4?
264- // this copies solution to old solution, which we already did above.
265- // solver_fine->Set_OldSolution();
266-
267- /* --- Compute time step, max eigenvalue, and integration scheme (steady and unsteady problems) ---*/
268273 solver_fine->SetTime_Step (geometry_fine, solver_container_fine, config, iMesh, timeIter);
269-
270- /* --- Restrict the solution and gradient for the adjoint problem ---*/
271- // nijso asks: why do we call this here but not in the post-smoothing?
272274 Adjoint_Setup (geometry, solver_container, config_container, RunTime_EqSystem, timeIter, iZone);
273-
274275 }
275- // cout << "pre-smoothing mesh " << iMesh << " rkstep " << iRKStep << endl;
276276 /* --- Space integration ---*/
277277 Space_Integration (geometry_fine, solver_container_fine, numerics_fine, config, iMesh, iRKStep, RunTime_EqSystem);
278-
279278 /* --- Time integration, update solution using the old solution plus the solution increment ---*/
280279 Time_Integration (geometry_fine, solver_container_fine, config, iRKStep, RunTime_EqSystem);
281-
282280 /* --- Send-Receive boundary conditions, and postprocessing ---*/
283281 solver_fine->Postprocessing (geometry_fine, solver_container_fine, config, iMesh);
282+ }
284283
284+ // Early exit check and output
285+ if (early_exit_enabled || output_enabled) {
286+ su2double current_rms = ComputeLinSysResRMS (solver_fine, geometry_fine);
287+ if (output_enabled) {
288+ cout << " MG Pre-Smoothing Level " << iMesh << " Iteration " << iPreSmooth + 1 << " /" << nPreSmooth << " RMS: " << current_rms << endl;
289+ }
290+ if (early_exit_enabled && current_rms < early_exit_threshold * initial_rms) {
291+ if (output_enabled) {
292+ cout << " MG Pre-Smoothing Level " << iMesh << " Early exit at iteration " << iPreSmooth + 1 << endl;
293+ }
294+ break ;
295+ }
285296 }
286297 }
287298}
@@ -293,32 +304,49 @@ void CMultiGridIntegration::PostSmoothing(unsigned short RunTime_EqSystem, CSolv
293304 const unsigned short nPostSmooth = config->GetMG_PostSmooth (iMesh);
294305 const unsigned long timeIter = config->GetTimeIter ();
295306
307+ // Early exit settings from config
308+ const bool early_exit_enabled = config->GetMG_Smooth_EarlyExit ();
309+ const su2double early_exit_threshold = config->GetMG_Smooth_Res_Threshold ();
310+ const bool output_enabled = config->GetMG_Smooth_Output ();
311+
312+ su2double initial_rms = 0.0 ;
313+ if (early_exit_enabled || output_enabled) {
314+ initial_rms = ComputeLinSysResRMS (solver_fine, geometry_fine);
315+ if (output_enabled) {
316+ cout << " MG Post-Smoothing Level " << iMesh << " Initial RMS: " << initial_rms << endl;
317+ }
318+ }
319+
296320 /* --- Do a postsmoothing on the grid iMesh after prolongation from the grid iMesh+1 ---*/
297321 for (unsigned short iPostSmooth = 0 ; iPostSmooth < nPostSmooth; iPostSmooth++) {
298-
299322 for (unsigned short iRKStep = 0 ; iRKStep < iRKLimit; iRKStep++) {
300-
301323 solver_fine->Preprocessing (geometry_fine, solver_container_fine, config, iMesh, iRKStep, RunTime_EqSystem, false );
302-
303324 if (iRKStep == 0 ) {
304-
305325 /* --- Set the old solution ---*/
306326 solver_fine->Set_OldSolution ();
307-
308327 if (classical_rk4) solver_fine->Set_NewSolution ();
309- solver_fine->SetTime_Step (geometry_fine, solver_container_fine, config, iMesh, timeIter);
310-
328+ solver_fine->SetTime_Step (geometry_fine, solver_container_fine, config, iMesh, timeIter);
311329 }
312-
313330 /* --- Space integration ---*/
314331 Space_Integration (geometry_fine, solver_container_fine, numerics_fine, config, iMesh, iRKStep, RunTime_EqSystem);
315- // cout << "post-smoothing mesh " << iMesh << " rkstep " << iRKStep << endl;
316332 /* --- Time integration, update solution using the old solution plus the solution increment ---*/
317333 Time_Integration (geometry_fine, solver_container_fine, config, iRKStep, RunTime_EqSystem);
318-
319334 /* --- Send-Receive boundary conditions, and postprocessing ---*/
320335 solver_fine->Postprocessing (geometry_fine, solver_container_fine, config, iMesh);
336+ }
321337
338+ // Early exit check and output
339+ if (early_exit_enabled || output_enabled) {
340+ su2double current_rms = ComputeLinSysResRMS (solver_fine, geometry_fine);
341+ if (output_enabled) {
342+ cout << " MG Post-Smoothing Level " << iMesh << " Iteration " << iPostSmooth + 1 << " /" << nPostSmooth << " RMS: " << current_rms << endl;
343+ }
344+ if (early_exit_enabled && current_rms < early_exit_threshold * initial_rms) {
345+ if (output_enabled) {
346+ cout << " MG Post-Smoothing Level " << iMesh << " Early exit at iteration " << iPostSmooth + 1 << endl;
347+ }
348+ break ;
349+ }
322350 }
323351 }
324352}
@@ -400,7 +428,7 @@ void CMultiGridIntegration::GetProlongated_Correction(unsigned short RunTime_EqS
400428}
401429
402430void CMultiGridIntegration::SmoothProlongated_Correction (unsigned short RunTime_EqSystem, CSolver *solver, CGeometry *geometry,
403- unsigned short val_nSmooth, su2double val_smooth_coeff, CConfig *config) {
431+ unsigned short val_nSmooth, su2double val_smooth_coeff, CConfig *config, unsigned short iMesh ) {
404432
405433 /* --- Check if there is work to do. ---*/
406434 if (val_nSmooth == 0 ) return ;
@@ -418,7 +446,19 @@ void CMultiGridIntegration::SmoothProlongated_Correction(unsigned short RunTime_
418446 }
419447 END_SU2_OMP_FOR
420448
421- /* --- Jacobi iterations. ---*/
449+ /* --- Compute initial RMS for adaptive smoothing ---*/
450+ su2double initial_rms = 0.0 ;
451+ if (config->GetMG_Smooth_EarlyExit ()) {
452+ initial_rms = ComputeLinSysResRMS (solver, geometry);
453+ }
454+
455+ /* --- Output initial RMS if enabled ---*/
456+ if (config->GetMG_Smooth_Output ()) {
457+ cout << " MG Correction-Smoothing Level " << iMesh << " Initial RMS: " << initial_rms << endl;
458+ }
459+
460+ /* --- Jacobi iterations with adaptive early exit ---*/
461+ unsigned short actual_iterations = val_nSmooth;
422462
423463 for (iSmooth = 0 ; iSmooth < val_nSmooth; iSmooth++) {
424464
@@ -470,6 +510,35 @@ void CMultiGridIntegration::SmoothProlongated_Correction(unsigned short RunTime_
470510 }
471511 }
472512
513+ /* --- Output RMS residual if enabled ---*/
514+ if (config->GetMG_Smooth_Output ()) {
515+ const su2double RMS_Res = ComputeLinSysResRMS (solver, geometry);
516+ cout << " MG Correction-Smoothing Level " << iMesh << " Iteration " << iSmooth+1 << " /" << val_nSmooth << " RMS: " << RMS_Res << endl;
517+ }
518+
519+ /* --- Adaptive early exit check after first iteration ---*/
520+ if (config->GetMG_Smooth_EarlyExit () && iSmooth == 0 && val_nSmooth > 1 ) {
521+ su2double current_rms = ComputeLinSysResRMS (solver, geometry);
522+ su2double reduction_ratio = current_rms / initial_rms;
523+
524+ // If RMS reduction is sufficient (ratio <= threshold), additional iterations may not be necessary
525+ if (reduction_ratio <= config->GetMG_Smooth_Res_Threshold ()) {
526+ if (config->GetMG_Smooth_Output ()) {
527+ cout << " MG Correction-Smoothing Level " << iMesh << " Early exit: sufficient RMS reduction ("
528+ << reduction_ratio << " <= " << config->GetMG_Smooth_Res_Threshold () << " )" << endl;
529+ }
530+ actual_iterations = 1 ; // Only do this one iteration
531+ break ;
532+ }
533+ // If reduction is insufficient (ratio > threshold), continue with remaining iterations
534+ }
535+
536+ }
537+
538+ /* --- Log if iterations were skipped ---*/
539+ if (config->GetMG_Smooth_Output () && actual_iterations < val_nSmooth) {
540+ cout << " MG Correction-Smoothing Level " << iMesh << " completed " << actual_iterations
541+ << " /" << val_nSmooth << " iterations (adaptive early exit)" << endl;
473542 }
474543
475544}
0 commit comments