@@ -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
@@ -1032,8 +1032,8 @@ unsigned long CSysSolve<ScalarType>::BCGSTAB_LinSolver(const CSysVector<ScalarTy
10321032 /* --- Only compute the residuals in full communication mode. ---*/
10331033
10341034 if (config->GetComm_Level () == COMM_FULL) {
1035- norm_r = r.norm ();
10361035 norm0 = b.norm ();
1036+ norm_r = xIsZero ? norm0 : r.norm ();
10371037
10381038 /* --- Set the norm to the initial initial residual value ---*/
10391039
@@ -1205,8 +1205,8 @@ unsigned long CSysSolve<ScalarType>::Smoother_LinSolver(const CSysVector<ScalarT
12051205 /* --- Only compute the residuals in full communication mode. ---*/
12061206
12071207 if (config->GetComm_Level () == COMM_FULL) {
1208- norm_r = r.norm ();
12091208 norm0 = b.norm ();
1209+ norm_r = xIsZero ? norm0 : r.norm ();
12101210
12111211 /* --- Set the norm to the initial initial residual value ---*/
12121212
@@ -1246,15 +1246,19 @@ unsigned long CSysSolve<ScalarType>::Smoother_LinSolver(const CSysVector<ScalarT
12461246 current residual, the system is linear so this saves some computation
12471247 compared to re-evaluating r = b-A*x. ---*/
12481248
1249- mat_vec (z, A_x);
1249+ if (!fix_iter_mode || i != m - 1 ) {
1250+ mat_vec (z, A_x);
1251+ }
12501252
12511253 /* --- Update solution and residual with relaxation omega. Mathematically this
12521254 is a modified Richardson iteration for the left-preconditioned system
12531255 M^{-1}(b-A*x) which converges if ||I-w*M^{-1}*A|| < 1. Combining this method
12541256 with a Gauss-Seidel preconditioner and w>1 is NOT equivalent to SOR. ---*/
12551257
12561258 x += omega * z;
1257- r -= omega * A_x;
1259+ if (!fix_iter_mode || i != m - 1 ) {
1260+ r -= omega * A_x;
1261+ }
12581262
12591263 /* --- Only compute the residuals in full communication mode. ---*/
12601264 /* --- Check if solution has converged, else output the relative residual if necessary. ---*/
@@ -1282,6 +1286,33 @@ unsigned long CSysSolve<ScalarType>::Smoother_LinSolver(const CSysVector<ScalarT
12821286 return i;
12831287}
12841288
1289+ template <class ScalarType >
1290+ bool CSysSolve<ScalarType>::SetupInnerSolver(unsigned short kind_solver, const CConfig* config) {
1291+ bool flexible = false ;
1292+ switch (kind_solver) {
1293+ case FGMRES:
1294+ case FGCRODR:
1295+ case RESTARTED_FGMRES:
1296+ case SMOOTHER:
1297+ flexible = true ;
1298+ break ;
1299+ default :
1300+ flexible = false ;
1301+ }
1302+ const bool is_linear = config->GetKind_Linear_Solver_Inner () == LINEAR_SOLVER_INNER::SMOOTHER;
1303+
1304+ if (config->GetKind_Linear_Solver_Inner () != LINEAR_SOLVER_INNER::NONE && (flexible || is_linear)) {
1305+ BEGIN_SU2_OMP_SAFE_GLOBAL_ACCESS
1306+ if (!inner_solver) {
1307+ inner_solver = std::make_unique<CSysSolve<ScalarType>>(LINEAR_SOLVER_MODE::STANDARD);
1308+ inner_solver->SetxIsZero (true );
1309+ }
1310+ END_SU2_OMP_SAFE_GLOBAL_ACCESS
1311+ return true ;
1312+ }
1313+ return false ;
1314+ }
1315+
12851316template <class ScalarType >
12861317unsigned long CSysSolve<ScalarType>::Solve(CSysMatrix<ScalarType>& Jacobian, const CSysVector<su2double>& LinSysRes,
12871318 CSysVector<su2double>& LinSysSol, CGeometry* geometry,
@@ -1334,16 +1365,7 @@ unsigned long CSysSolve<ScalarType>::Solve(CSysMatrix<ScalarType>& Jacobian, con
13341365 }
13351366 }
13361367
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- }
1368+ const bool nested = SetupInnerSolver (KindSolver, config);
13471369
13481370 /* --- Stop the recording for the linear solver ---*/
13491371 bool TapeActive = NO;
@@ -1389,11 +1411,15 @@ unsigned long CSysSolve<ScalarType>::Solve(CSysMatrix<ScalarType>& Jacobian, con
13891411 auto f = [&](const CSysVector<ScalarType>& u, CSysVector<ScalarType>& v) {
13901412 /* --- Initialize to 0 to be safe. ---*/
13911413 v = ScalarType{};
1392- ScalarType unused {};
1414+ ScalarType res {};
13931415 /* --- Handle other types here if desired but do not call Solve because
13941416 * 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);
1417+ if (config->GetKind_Linear_Solver_Inner () == LINEAR_SOLVER_INNER::BCGSTAB) {
1418+ inner_solver->BCGSTAB_LinSolver (u, v, mat_vec, *normal_prec, sqrt (SolverTol), MaxIter, res, false , config);
1419+ } else {
1420+ const auto smooth_iter = static_cast <unsigned long >(std::round (fmax (2 , sqrt (MaxIter))));
1421+ inner_solver->Smoother_LinSolver (u, v, mat_vec, *normal_prec, 0 , smooth_iter, res, false , config);
1422+ }
13971423 };
13981424 nested_prec = new CAbstractPreconditioner<ScalarType>(f);
13991425 }
@@ -1545,16 +1571,7 @@ unsigned long CSysSolve<ScalarType>::Solve_b(CSysMatrix<ScalarType>& Jacobian, c
15451571 }
15461572 }
15471573
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- }
1574+ const bool nested = SetupInnerSolver (KindSolver, config);
15581575
15591576 /* --- Set up preconditioner and matrix-vector product ---*/
15601577
@@ -1572,13 +1589,15 @@ unsigned long CSysSolve<ScalarType>::Solve_b(CSysMatrix<ScalarType>& Jacobian, c
15721589 CPreconditioner<ScalarType>* nested_prec = nullptr ;
15731590 if (nested) {
15741591 auto f = [&](const CSysVector<ScalarType>& u, CSysVector<ScalarType>& v) {
1575- /* --- Initialize to 0 to be safe . ---*/
1592+ /* --- See "Solve" . ---*/
15761593 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);
1594+ ScalarType res{};
1595+ if (config->GetKind_Linear_Solver_Inner () == LINEAR_SOLVER_INNER::BCGSTAB) {
1596+ inner_solver->BCGSTAB_LinSolver (u, v, mat_vec, *normal_prec, sqrt (SolverTol), MaxIter, res, false , config);
1597+ } else {
1598+ const auto smooth_iter = static_cast <unsigned long >(std::round (fmax (2 , sqrt (MaxIter))));
1599+ inner_solver->Smoother_LinSolver (u, v, mat_vec, *normal_prec, 0 , smooth_iter, res, false , config);
1600+ }
15821601 };
15831602 nested_prec = new CAbstractPreconditioner<ScalarType>(f);
15841603 }
0 commit comments