4242#include < iostream>
4343#include < limits>
4444#include < type_traits>
45+ #include < memory>
4546
4647/* !
4748 * \brief Epsilon used in CSysSolve depending on datatype to
@@ -1307,9 +1308,8 @@ unsigned long CSysSolve<ScalarType>::Solve(CSysMatrix<ScalarType>& Jacobian, con
13071308 break ;
13081309 }
13091310
1310- /* --- Normal mode
1311- * assumes that 'lin_sol_mode==LINEAR_SOLVER_MODE::STANDARD', but does not enforce it to avoid compiler warning.
1312- * ---*/
1311+ /* --- Normal mode assumes that 'lin_sol_mode==LINEAR_SOLVER_MODE::STANDARD',
1312+ * but does not enforce it to avoid compiler warning. ---*/
13131313 default : {
13141314 KindSolver = config->GetKind_Linear_Solver ();
13151315 KindPrecond = config->GetKind_Linear_Solver_Prec ();
@@ -1320,6 +1320,17 @@ unsigned long CSysSolve<ScalarType>::Solve(CSysMatrix<ScalarType>& Jacobian, con
13201320 }
13211321 }
13221322
1323+ const bool nested = (KindSolver == FGMRES || KindSolver == RESTARTED_FGMRES || KindSolver == SMOOTHER) &&
1324+ config->GetKind_Linear_Solver_Inner () != LINEAR_SOLVER_INNER::NONE;
1325+
1326+ if (nested && !inner_solver) {
1327+ BEGIN_SU2_OMP_SAFE_GLOBAL_ACCESS {
1328+ inner_solver = std::make_unique<CSysSolve<ScalarType>>(LINEAR_SOLVER_MODE::STANDARD);
1329+ inner_solver->SetxIsZero (true );
1330+ }
1331+ END_SU2_OMP_SAFE_GLOBAL_ACCESS
1332+ }
1333+
13231334 /* --- Stop the recording for the linear solver ---*/
13241335 bool TapeActive = NO;
13251336
@@ -1353,13 +1364,25 @@ unsigned long CSysSolve<ScalarType>::Solve(CSysMatrix<ScalarType>& Jacobian, con
13531364
13541365 auto mat_vec = CSysMatrixVectorProduct<ScalarType>(Jacobian, geometry, config);
13551366
1356- const auto kindPrec = static_cast <ENUM_LINEAR_SOLVER_PREC>(KindPrecond);
1357-
1358- auto precond = CPreconditioner<ScalarType>::Create (kindPrec, Jacobian, geometry, config);
1359-
13601367 /* --- Build preconditioner. ---*/
13611368
1362- precond->Build ();
1369+ const auto kindPrec = static_cast <ENUM_LINEAR_SOLVER_PREC>(KindPrecond);
1370+ auto * normal_prec = CPreconditioner<ScalarType>::Create (kindPrec, Jacobian, geometry, config);
1371+ normal_prec->Build ();
1372+
1373+ CPreconditioner<ScalarType>* nested_prec = nullptr ;
1374+ if (nested) {
1375+ nested_prec = new CAbstractPreconditioner<ScalarType>([&](const CSysVector<ScalarType>& u,
1376+ CSysVector<ScalarType>& v) {
1377+ /* --- Initialize to 0 to be safe. ---*/
1378+ v = ScalarType{};
1379+ ScalarType unused{};
1380+ /* --- Handle other types here if desired but do not call Solve because
1381+ * that will create issues with the AD external function. ---*/
1382+ (void )inner_solver->BCGSTAB_LinSolver (u, v, mat_vec, *normal_prec, SolverTol, MaxIter, unused, false , config);
1383+ });
1384+ }
1385+ const auto * precond = nested ? nested_prec : normal_prec;
13631386
13641387 /* --- Solve system. ---*/
13651388
@@ -1409,7 +1432,8 @@ unsigned long CSysSolve<ScalarType>::Solve(CSysMatrix<ScalarType>& Jacobian, con
14091432
14101433 HandleTemporariesOut (LinSysSol);
14111434
1412- delete precond;
1435+ delete normal_prec;
1436+ delete nested_prec;
14131437
14141438 if (TapeActive) {
14151439 /* --- To keep the behavior of SU2_DOT, but not strictly required since jacobian is symmetric(?). ---*/
@@ -1494,9 +1518,8 @@ unsigned long CSysSolve<ScalarType>::Solve_b(CSysMatrix<ScalarType>& Jacobian, c
14941518 break ;
14951519 }
14961520
1497- /* --- Normal mode
1498- * assumes that 'lin_sol_mode==LINEAR_SOLVER_MODE::STANDARD', but does not enforce it to avoid compiler warning.
1499- * ---*/
1521+ /* --- Normal mode assumes that 'lin_sol_mode==LINEAR_SOLVER_MODE::STANDARD',
1522+ * but does not enforce it to avoid compiler warning. ---*/
15001523 default : {
15011524 KindSolver = config->GetKind_Linear_Solver ();
15021525 KindPrecond = config->GetKind_Linear_Solver_Prec ();
@@ -1507,19 +1530,43 @@ unsigned long CSysSolve<ScalarType>::Solve_b(CSysMatrix<ScalarType>& Jacobian, c
15071530 }
15081531 }
15091532
1533+ const bool nested = (KindSolver == FGMRES || KindSolver == RESTARTED_FGMRES || KindSolver == SMOOTHER) &&
1534+ config->GetKind_Linear_Solver_Inner () != LINEAR_SOLVER_INNER::NONE;
1535+
1536+ if (nested && !inner_solver) {
1537+ BEGIN_SU2_OMP_SAFE_GLOBAL_ACCESS {
1538+ inner_solver = std::make_unique<CSysSolve<ScalarType>>(LINEAR_SOLVER_MODE::STANDARD);
1539+ inner_solver->SetxIsZero (true );
1540+ }
1541+ END_SU2_OMP_SAFE_GLOBAL_ACCESS
1542+ }
1543+
15101544 /* --- Set up preconditioner and matrix-vector product ---*/
15111545
1512- const auto kindPrec = static_cast <ENUM_LINEAR_SOLVER_PREC>(KindPrecond );
1546+ auto mat_vec = CSysMatrixVectorProduct<ScalarType>(Jacobian, geometry, config );
15131547
1514- auto precond = CPreconditioner<ScalarType>::Create (kindPrec, Jacobian, geometry, config);
1548+ const auto kindPrec = static_cast <ENUM_LINEAR_SOLVER_PREC>(KindPrecond);
1549+ auto * normal_prec = CPreconditioner<ScalarType>::Create (kindPrec, Jacobian, geometry, config);
15151550
15161551 /* --- If there was no call to solve first the preconditioner needs to be built here. ---*/
15171552 if (directCall) {
15181553 Jacobian.TransposeInPlace ();
1519- precond ->Build ();
1554+ normal_prec ->Build ();
15201555 }
15211556
1522- auto mat_vec = CSysMatrixVectorProduct<ScalarType>(Jacobian, geometry, config);
1557+ CPreconditioner<ScalarType>* nested_prec = nullptr ;
1558+ if (nested) {
1559+ nested_prec =
1560+ new CAbstractPreconditioner<ScalarType>([&](const CSysVector<ScalarType>& u, CSysVector<ScalarType>& v) {
1561+ /* --- Initialize to 0 to be safe. ---*/
1562+ v = ScalarType{};
1563+ ScalarType unused{};
1564+ /* --- Handle other types here if desired but do not call Solve because
1565+ * that will create issues with the AD external function. ---*/
1566+ (void )inner_solver->BCGSTAB_LinSolver (u, v, mat_vec, *normal_prec, SolverTol, MaxIter, unused, false , config);
1567+ });
1568+ }
1569+ const auto * precond = nested ? nested_prec : normal_prec;
15231570
15241571 /* --- Solve the system ---*/
15251572
@@ -1567,7 +1614,8 @@ unsigned long CSysSolve<ScalarType>::Solve_b(CSysMatrix<ScalarType>& Jacobian, c
15671614
15681615 HandleTemporariesOut (LinSysSol);
15691616
1570- delete precond;
1617+ delete normal_prec;
1618+ delete nested_prec;
15711619
15721620 SU2_OMP_MASTER {
15731621 Residual = residual;
0 commit comments