@@ -312,8 +312,8 @@ unsigned long CSysSolve<ScalarType>::CG_LinSolver(const CSysVector<ScalarType>&
312312 /* --- Only compute the residuals in full communication mode. ---*/
313313
314314 if (config->GetComm_Level () == COMM_FULL) {
315- norm_r = r.norm ();
316315 norm0 = b.norm ();
316+ norm_r = xIsZero ? norm0 : r.norm ();
317317
318318 /* --- Set the norm to the initial initial residual value ---*/
319319
@@ -626,14 +626,15 @@ unsigned long CSysSolve<ScalarType>::RFGMRES_LinSolver(const CSysVector<ScalarTy
626626 }
627627 END_SU2_OMP_SAFE_GLOBAL_ACCESS
628628
629- for (auto totalIter = 0ul ; totalIter < MaxIter;) {
629+ auto totalIter = 0ul ;
630+ while (totalIter < MaxIter) {
630631 /* --- Enforce a hard limit on total number of iterations ---*/
631632 auto iterLimit = min (restartIter, MaxIter - totalIter);
632633 auto iter = FGMRES_LinSolver (b, x, mat_vec, precond, tol, iterLimit, residual, monitoring, config);
633634 totalIter += iter;
634- if (residual <= tol || iter < iterLimit) return totalIter ;
635+ if (residual <= tol || iter < iterLimit) break ;
635636 }
636- return 0 ;
637+ return totalIter ;
637638}
638639
639640template <class ScalarType >
@@ -1032,8 +1033,8 @@ unsigned long CSysSolve<ScalarType>::BCGSTAB_LinSolver(const CSysVector<ScalarTy
10321033 /* --- Only compute the residuals in full communication mode. ---*/
10331034
10341035 if (config->GetComm_Level () == COMM_FULL) {
1035- norm_r = r.norm ();
10361036 norm0 = b.norm ();
1037+ norm_r = xIsZero ? norm0 : r.norm ();
10371038
10381039 /* --- Set the norm to the initial initial residual value ---*/
10391040
@@ -1205,8 +1206,8 @@ unsigned long CSysSolve<ScalarType>::Smoother_LinSolver(const CSysVector<ScalarT
12051206 /* --- Only compute the residuals in full communication mode. ---*/
12061207
12071208 if (config->GetComm_Level () == COMM_FULL) {
1208- norm_r = r.norm ();
12091209 norm0 = b.norm ();
1210+ norm_r = xIsZero ? norm0 : r.norm ();
12101211
12111212 /* --- Set the norm to the initial initial residual value ---*/
12121213
@@ -1246,15 +1247,19 @@ unsigned long CSysSolve<ScalarType>::Smoother_LinSolver(const CSysVector<ScalarT
12461247 current residual, the system is linear so this saves some computation
12471248 compared to re-evaluating r = b-A*x. ---*/
12481249
1249- mat_vec (z, A_x);
1250+ if (!fix_iter_mode || i != m - 1 ) {
1251+ mat_vec (z, A_x);
1252+ }
12501253
12511254 /* --- Update solution and residual with relaxation omega. Mathematically this
12521255 is a modified Richardson iteration for the left-preconditioned system
12531256 M^{-1}(b-A*x) which converges if ||I-w*M^{-1}*A|| < 1. Combining this method
12541257 with a Gauss-Seidel preconditioner and w>1 is NOT equivalent to SOR. ---*/
12551258
12561259 x += omega * z;
1257- r -= omega * A_x;
1260+ if (!fix_iter_mode || i != m - 1 ) {
1261+ r -= omega * A_x;
1262+ }
12581263
12591264 /* --- Only compute the residuals in full communication mode. ---*/
12601265 /* --- Check if solution has converged, else output the relative residual if necessary. ---*/
@@ -1282,6 +1287,33 @@ unsigned long CSysSolve<ScalarType>::Smoother_LinSolver(const CSysVector<ScalarT
12821287 return i;
12831288}
12841289
1290+ template <class ScalarType >
1291+ bool CSysSolve<ScalarType>::SetupInnerSolver(unsigned short kind_solver, const CConfig* config) {
1292+ bool flexible = false ;
1293+ switch (kind_solver) {
1294+ case FGMRES:
1295+ case FGCRODR:
1296+ case RESTARTED_FGMRES:
1297+ case SMOOTHER:
1298+ flexible = true ;
1299+ break ;
1300+ default :
1301+ flexible = false ;
1302+ }
1303+ const bool is_linear = config->GetKind_Linear_Solver_Inner () == LINEAR_SOLVER_INNER::SMOOTHER;
1304+
1305+ if (config->GetKind_Linear_Solver_Inner () != LINEAR_SOLVER_INNER::NONE && (flexible || is_linear)) {
1306+ BEGIN_SU2_OMP_SAFE_GLOBAL_ACCESS
1307+ if (!inner_solver) {
1308+ inner_solver = std::make_unique<CSysSolve<ScalarType>>(LINEAR_SOLVER_MODE::STANDARD);
1309+ inner_solver->SetxIsZero (true );
1310+ }
1311+ END_SU2_OMP_SAFE_GLOBAL_ACCESS
1312+ return true ;
1313+ }
1314+ return false ;
1315+ }
1316+
12851317template <class ScalarType >
12861318unsigned long CSysSolve<ScalarType>::Solve(CSysMatrix<ScalarType>& Jacobian, const CSysVector<su2double>& LinSysRes,
12871319 CSysVector<su2double>& LinSysSol, CGeometry* geometry,
@@ -1334,16 +1366,7 @@ unsigned long CSysSolve<ScalarType>::Solve(CSysMatrix<ScalarType>& Jacobian, con
13341366 }
13351367 }
13361368
1337- const bool nested = (KindSolver == FGMRES || KindSolver == RESTARTED_FGMRES || KindSolver == SMOOTHER) &&
1338- config->GetKind_Linear_Solver_Inner () != LINEAR_SOLVER_INNER::NONE;
1339-
1340- if (nested && !inner_solver) {
1341- BEGIN_SU2_OMP_SAFE_GLOBAL_ACCESS {
1342- inner_solver = std::make_unique<CSysSolve<ScalarType>>(LINEAR_SOLVER_MODE::STANDARD);
1343- inner_solver->SetxIsZero (true );
1344- }
1345- END_SU2_OMP_SAFE_GLOBAL_ACCESS
1346- }
1369+ const bool nested = SetupInnerSolver (KindSolver, config);
13471370
13481371 /* --- Stop the recording for the linear solver ---*/
13491372 bool TapeActive = NO;
@@ -1389,11 +1412,15 @@ unsigned long CSysSolve<ScalarType>::Solve(CSysMatrix<ScalarType>& Jacobian, con
13891412 auto f = [&](const CSysVector<ScalarType>& u, CSysVector<ScalarType>& v) {
13901413 /* --- Initialize to 0 to be safe. ---*/
13911414 v = ScalarType{};
1392- ScalarType unused {};
1415+ ScalarType res {};
13931416 /* --- Handle other types here if desired but do not call Solve because
13941417 * that will create issues with the AD external function. ---*/
1395- (void )inner_solver->BCGSTAB_LinSolver (u, v, mat_vec, *normal_prec, sqrt (SolverTol), MaxIter, unused, false ,
1396- config);
1418+ if (config->GetKind_Linear_Solver_Inner () == LINEAR_SOLVER_INNER::BCGSTAB) {
1419+ inner_solver->BCGSTAB_LinSolver (u, v, mat_vec, *normal_prec, sqrt (SolverTol), MaxIter, res, false , config);
1420+ } else {
1421+ const auto smooth_iter = static_cast <unsigned long >(std::round (fmax (2 , sqrt (MaxIter))));
1422+ inner_solver->Smoother_LinSolver (u, v, mat_vec, *normal_prec, 0 , smooth_iter, res, false , config);
1423+ }
13971424 };
13981425 nested_prec = new CAbstractPreconditioner<ScalarType>(f);
13991426 }
@@ -1545,16 +1572,7 @@ unsigned long CSysSolve<ScalarType>::Solve_b(CSysMatrix<ScalarType>& Jacobian, c
15451572 }
15461573 }
15471574
1548- const bool nested = (KindSolver == FGMRES || KindSolver == RESTARTED_FGMRES || KindSolver == SMOOTHER) &&
1549- config->GetKind_Linear_Solver_Inner () != LINEAR_SOLVER_INNER::NONE;
1550-
1551- if (nested && !inner_solver) {
1552- BEGIN_SU2_OMP_SAFE_GLOBAL_ACCESS {
1553- inner_solver = std::make_unique<CSysSolve<ScalarType>>(LINEAR_SOLVER_MODE::STANDARD);
1554- inner_solver->SetxIsZero (true );
1555- }
1556- END_SU2_OMP_SAFE_GLOBAL_ACCESS
1557- }
1575+ const bool nested = SetupInnerSolver (KindSolver, config);
15581576
15591577 /* --- Set up preconditioner and matrix-vector product ---*/
15601578
@@ -1572,13 +1590,15 @@ unsigned long CSysSolve<ScalarType>::Solve_b(CSysMatrix<ScalarType>& Jacobian, c
15721590 CPreconditioner<ScalarType>* nested_prec = nullptr ;
15731591 if (nested) {
15741592 auto f = [&](const CSysVector<ScalarType>& u, CSysVector<ScalarType>& v) {
1575- /* --- Initialize to 0 to be safe . ---*/
1593+ /* --- See "Solve" . ---*/
15761594 v = ScalarType{};
1577- ScalarType unused{};
1578- /* --- Handle other types here if desired but do not call Solve because
1579- * that will create issues with the AD external function. ---*/
1580- (void )inner_solver->BCGSTAB_LinSolver (u, v, mat_vec, *normal_prec, sqrt (SolverTol), MaxIter, unused, false ,
1581- config);
1595+ ScalarType res{};
1596+ if (config->GetKind_Linear_Solver_Inner () == LINEAR_SOLVER_INNER::BCGSTAB) {
1597+ inner_solver->BCGSTAB_LinSolver (u, v, mat_vec, *normal_prec, sqrt (SolverTol), MaxIter, res, false , config);
1598+ } else {
1599+ const auto smooth_iter = static_cast <unsigned long >(std::round (fmax (2 , sqrt (MaxIter))));
1600+ inner_solver->Smoother_LinSolver (u, v, mat_vec, *normal_prec, 0 , smooth_iter, res, false , config);
1601+ }
15821602 };
15831603 nested_prec = new CAbstractPreconditioner<ScalarType>(f);
15841604 }
0 commit comments