@@ -2028,17 +2028,33 @@ void CSolver::AdaptCFLNumber(CGeometry **geometry,
20282028 }
20292029
20302030 /* Stagnation guard: if over a recent window there is essentially no improvement,
2031- lower CFL to escape the stall. */
2031+ lower CFL to escape the stall. Only trigger if we're truly stalled (near zero or
2032+ positive change) and not conflicting with other indicators showing good progress. */
20322033 const unsigned long STALL_WINDOW = min (100ul , Res_Count);
20332034 if (config->GetInnerIter () >= STALL_WINDOW) {
20342035 su2double stallChange = 0.0 ;
20352036 for (unsigned long i = 0 ; i < STALL_WINDOW; i++) {
20362037 unsigned long idx = (NonLinRes_Counter + Res_Count - 1 - i) % Res_Count;
20372038 stallChange += NonLinRes_Series[idx];
20382039 }
2039- /* If cumulative change is greater than a small negative tolerance, we are stalled. */
2040- const su2double STALL_TOL = -0.1 ; /* about 0.1 log10 improvement threshold over window */
2041- if (stallChange > STALL_TOL) {
2040+ /* Only flag as stalled if change is very small or positive, AND we're not already
2041+ seeing good convergence indicators (canIncrease means linear solver is doing well).
2042+ Tightened threshold from -0.1 to -0.01 to avoid false positives on slow but steady convergence. */
2043+ const su2double STALL_TOL = -0.01 ; /* about 0.01 log10 improvement threshold over window */
2044+ bool isStalled = (stallChange > STALL_TOL);
2045+
2046+ if (rank == MASTER_NODE && currIter % 50 == 0 ) {
2047+ cout << " Stagnation Debug - Iter " << currIter << " : stallChange=" << stallChange
2048+ << " STALL_TOL=" << STALL_TOL << " isStalled=" << isStalled
2049+ << " canIncrease=" << canIncrease << " will_reduce="
2050+ << ((isStalled && !canIncrease) || (stallChange > 0.0 )) << endl;
2051+ }
2052+
2053+ /* Don't override canIncrease unless truly stalled (near zero or positive trend) */
2054+ if (isStalled && !canIncrease) {
2055+ reduceCFL = true ;
2056+ } else if (stallChange > 0.0 ) {
2057+ /* Only force reduction if residuals actually increased */
20422058 reduceCFL = true ;
20432059 }
20442060 }
@@ -2100,35 +2116,23 @@ void CSolver::AdaptCFLNumber(CGeometry **geometry,
21002116 << " reduceCFL=" << reduceCFL << " canIncrease=" << canIncrease << endl;
21012117 }
21022118
2103- /* Check if we are hitting the min or max and adjust. */
2104-
2105- if (CFL*CFLFactor <= CFLMin) {
2106- CFL = CFLMin;
2107- // nijso says: we might need to add this back in again when we have more complex
2108- // cfl scaling for multigrid (happening in CMultiGridGeometry.cpp)
2109- // CFLFactor = MGFactor[iMesh];
2110- } else if (CFL*CFLFactor >= CFLMax) {
2111- CFL = CFLMax;
2112- // CFLFactor = MGFactor[iMesh];
2113- }
2114-
2115- /* Debug output for min/max capping */
2116- if (iPoint == 0 && config->GetInnerIter () % 50 == 0 && rank == MASTER_NODE) {
2117- cout << " After min/max check - CFL=" << CFL << " (min=" << CFLMin << " , max=" << CFLMax
2118- << " , wanted=" << (CFL*CFLFactor) << " )" << endl;
2119- }
2120-
21212119 /* If we detect a stalled nonlinear residual, then force the CFL
21222120 for all points to the minimum temporarily to restart the ramp. */
21232121
21242122 if (resetCFL) {
2125- CFL = CFLMin;
2126- // CFLFactor = MGFactor[iMesh];
2127- }
2123+ CFL = CFLMin;
2124+ } else {
2125+ /* Apply the adjustment to the CFL first. */
2126+ CFL *= CFLFactor;
21282127
2129- /* Apply the adjustment to the CFL and store local values. */
2128+ /* Then clamp to min/max limits. */
2129+ CFL = max (CFLMin, min (CFLMax, CFL));
2130+ }
21302131
2131- CFL *= CFLFactor;
2132+ /* Debug output for min/max capping */
2133+ if (iPoint == 0 && config->GetInnerIter () % 50 == 0 && rank == MASTER_NODE) {
2134+ cout << " After adjustment - CFL=" << CFL << " (min=" << CFLMin << " , max=" << CFLMax << " )" << endl;
2135+ }
21322136
21332137 // cout << "CFL = " << CFL << " Factor = " << CFLFactor << endl;
21342138
0 commit comments