3535#include " ../../include/linear_algebra/CPreconditioner.hpp"
3636
3737#include < limits>
38+ #include < memory>
3839
3940/* !
4041 * \brief Epsilon used in CSysSolve depending on datatype to
@@ -110,7 +111,7 @@ void CSysSolve<ScalarType>::SolveReduced(int n, const su2matrix<ScalarType>& Hsb
110111
111112template <class ScalarType >
112113void CSysSolve<ScalarType>::ModGramSchmidt(bool shared_hsbg, int i, su2matrix<ScalarType>& Hsbg,
113- vector<CSysVector<ScalarType> >& w) const {
114+ vector<CSysVector<ScalarType>>& w) const {
114115 const auto thread = omp_get_thread_num ();
115116
116117 /* --- If Hsbg is shared by multiple threads calling this function, only one
@@ -902,9 +903,8 @@ unsigned long CSysSolve<ScalarType>::Solve(CSysMatrix<ScalarType>& Jacobian, con
902903 break ;
903904 }
904905
905- /* --- Normal mode
906- * assumes that 'lin_sol_mode==LINEAR_SOLVER_MODE::STANDARD', but does not enforce it to avoid compiler warning.
907- * ---*/
906+ /* --- Normal mode assumes that 'lin_sol_mode==LINEAR_SOLVER_MODE::STANDARD',
907+ * but does not enforce it to avoid compiler warning. ---*/
908908 default : {
909909 KindSolver = config->GetKind_Linear_Solver ();
910910 KindPrecond = config->GetKind_Linear_Solver_Prec ();
@@ -915,6 +915,17 @@ unsigned long CSysSolve<ScalarType>::Solve(CSysMatrix<ScalarType>& Jacobian, con
915915 }
916916 }
917917
918+ const bool nested = (KindSolver == FGMRES || KindSolver == RESTARTED_FGMRES || KindSolver == SMOOTHER) &&
919+ config->GetKind_Linear_Solver_Inner () != LINEAR_SOLVER_INNER::NONE;
920+
921+ if (nested && !inner_solver) {
922+ BEGIN_SU2_OMP_SAFE_GLOBAL_ACCESS {
923+ inner_solver = std::make_unique<CSysSolve<ScalarType>>(LINEAR_SOLVER_MODE::STANDARD);
924+ inner_solver->SetxIsZero (true );
925+ }
926+ END_SU2_OMP_SAFE_GLOBAL_ACCESS
927+ }
928+
918929 /* --- Stop the recording for the linear solver ---*/
919930 bool TapeActive = NO;
920931
@@ -948,13 +959,25 @@ unsigned long CSysSolve<ScalarType>::Solve(CSysMatrix<ScalarType>& Jacobian, con
948959
949960 auto mat_vec = CSysMatrixVectorProduct<ScalarType>(Jacobian, geometry, config);
950961
951- const auto kindPrec = static_cast <ENUM_LINEAR_SOLVER_PREC>(KindPrecond);
952-
953- auto precond = CPreconditioner<ScalarType>::Create (kindPrec, Jacobian, geometry, config);
954-
955962 /* --- Build preconditioner. ---*/
956963
957- precond->Build ();
964+ const auto kindPrec = static_cast <ENUM_LINEAR_SOLVER_PREC>(KindPrecond);
965+ auto * normal_prec = CPreconditioner<ScalarType>::Create (kindPrec, Jacobian, geometry, config);
966+ normal_prec->Build ();
967+
968+ CPreconditioner<ScalarType>* nested_prec = nullptr ;
969+ if (nested) {
970+ nested_prec = new CAbstractPreconditioner<ScalarType>([&](const CSysVector<ScalarType>& u,
971+ CSysVector<ScalarType>& v) {
972+ /* --- Initialize to 0 to be safe. ---*/
973+ v = ScalarType{};
974+ ScalarType unused{};
975+ /* --- Handle other types here if desired but do not call Solve because
976+ * that will create issues with the AD external function. ---*/
977+ (void )inner_solver->BCGSTAB_LinSolver (u, v, mat_vec, *normal_prec, SolverTol, MaxIter, unused, false , config);
978+ });
979+ }
980+ const auto * precond = nested ? nested_prec : normal_prec;
958981
959982 /* --- Solve system. ---*/
960983
@@ -1000,7 +1023,8 @@ unsigned long CSysSolve<ScalarType>::Solve(CSysMatrix<ScalarType>& Jacobian, con
10001023
10011024 HandleTemporariesOut (LinSysSol);
10021025
1003- delete precond;
1026+ delete normal_prec;
1027+ delete nested_prec;
10041028
10051029 if (TapeActive) {
10061030 /* --- To keep the behavior of SU2_DOT, but not strictly required since jacobian is symmetric(?). ---*/
@@ -1085,9 +1109,8 @@ unsigned long CSysSolve<ScalarType>::Solve_b(CSysMatrix<ScalarType>& Jacobian, c
10851109 break ;
10861110 }
10871111
1088- /* --- Normal mode
1089- * assumes that 'lin_sol_mode==LINEAR_SOLVER_MODE::STANDARD', but does not enforce it to avoid compiler warning.
1090- * ---*/
1112+ /* --- Normal mode assumes that 'lin_sol_mode==LINEAR_SOLVER_MODE::STANDARD',
1113+ * but does not enforce it to avoid compiler warning. ---*/
10911114 default : {
10921115 KindSolver = config->GetKind_Linear_Solver ();
10931116 KindPrecond = config->GetKind_Linear_Solver_Prec ();
@@ -1098,19 +1121,43 @@ unsigned long CSysSolve<ScalarType>::Solve_b(CSysMatrix<ScalarType>& Jacobian, c
10981121 }
10991122 }
11001123
1124+ const bool nested = (KindSolver == FGMRES || KindSolver == RESTARTED_FGMRES || KindSolver == SMOOTHER) &&
1125+ config->GetKind_Linear_Solver_Inner () != LINEAR_SOLVER_INNER::NONE;
1126+
1127+ if (nested && !inner_solver) {
1128+ BEGIN_SU2_OMP_SAFE_GLOBAL_ACCESS {
1129+ inner_solver = std::make_unique<CSysSolve<ScalarType>>(LINEAR_SOLVER_MODE::STANDARD);
1130+ inner_solver->SetxIsZero (true );
1131+ }
1132+ END_SU2_OMP_SAFE_GLOBAL_ACCESS
1133+ }
1134+
11011135 /* --- Set up preconditioner and matrix-vector product ---*/
11021136
1103- const auto kindPrec = static_cast <ENUM_LINEAR_SOLVER_PREC>(KindPrecond );
1137+ auto mat_vec = CSysMatrixVectorProduct<ScalarType>(Jacobian, geometry, config );
11041138
1105- auto precond = CPreconditioner<ScalarType>::Create (kindPrec, Jacobian, geometry, config);
1139+ const auto kindPrec = static_cast <ENUM_LINEAR_SOLVER_PREC>(KindPrecond);
1140+ auto * normal_prec = CPreconditioner<ScalarType>::Create (kindPrec, Jacobian, geometry, config);
11061141
11071142 /* --- If there was no call to solve first the preconditioner needs to be built here. ---*/
11081143 if (directCall) {
11091144 Jacobian.TransposeInPlace ();
1110- precond ->Build ();
1145+ normal_prec ->Build ();
11111146 }
11121147
1113- auto mat_vec = CSysMatrixVectorProduct<ScalarType>(Jacobian, geometry, config);
1148+ CPreconditioner<ScalarType>* nested_prec = nullptr ;
1149+ if (nested) {
1150+ nested_prec =
1151+ new CAbstractPreconditioner<ScalarType>([&](const CSysVector<ScalarType>& u, CSysVector<ScalarType>& v) {
1152+ /* --- Initialize to 0 to be safe. ---*/
1153+ v = ScalarType{};
1154+ ScalarType unused{};
1155+ /* --- Handle other types here if desired but do not call Solve because
1156+ * that will create issues with the AD external function. ---*/
1157+ (void )inner_solver->BCGSTAB_LinSolver (u, v, mat_vec, *normal_prec, SolverTol, MaxIter, unused, false , config);
1158+ });
1159+ }
1160+ const auto * precond = nested ? nested_prec : normal_prec;
11141161
11151162 /* --- Solve the system ---*/
11161163
@@ -1154,7 +1201,8 @@ unsigned long CSysSolve<ScalarType>::Solve_b(CSysMatrix<ScalarType>& Jacobian, c
11541201
11551202 HandleTemporariesOut (LinSysSol);
11561203
1157- delete precond;
1204+ delete normal_prec;
1205+ delete nested_prec;
11581206
11591207 SU2_OMP_MASTER {
11601208 Residual = residual;
0 commit comments