unsigned long CSysSolve::Solve(CSysMatrix & Jacobian, CSysVector & LinSysRes, CSysVector & LinSysSol, CGeometry *geometry, CConfig *config) { su2double SolverTol = config->GetLinear_Solver_Error(), Residual; unsigned long MaxIter = config->GetLinear_Solver_Iter(); unsigned long IterLinSol = 0; CMatrixVectorProduct *mat_vec; bool TapeActive = NO; if (config->GetDiscrete_Adjoint()){ #ifdef CODI_REVERSE_TYPE /*--- Check whether the tape is active, i.e. if it is recording and store the status ---*/ TapeActive = AD::globalTape.isActive(); /*--- Stop the recording for the linear solver ---*/ AD::StopRecording(); #endif } /*--- Solve the linear system using a Krylov subspace method ---*/ if (config->GetKind_Linear_Solver() == BCGSTAB || config->GetKind_Linear_Solver() == FGMRES || config->GetKind_Linear_Solver() == RESTARTED_FGMRES) { mat_vec = new CSysMatrixVectorProduct(Jacobian, geometry, config); CPreconditioner* precond = NULL; switch (config->GetKind_Linear_Solver_Prec()) { case JACOBI: Jacobian.BuildJacobiPreconditioner(); precond = new CJacobiPreconditioner(Jacobian, geometry, config); break; case ILU: Jacobian.BuildILUPreconditioner(); precond = new CILUPreconditioner(Jacobian, geometry, config); break; case LU_SGS: precond = new CLU_SGSPreconditioner(Jacobian, geometry, config); break; case LINELET: Jacobian.BuildJacobiPreconditioner(); precond = new CLineletPreconditioner(Jacobian, geometry, config); break; default: Jacobian.BuildJacobiPreconditioner(); precond = new CJacobiPreconditioner(Jacobian, geometry, config); break; } switch (config->GetKind_Linear_Solver()) { case BCGSTAB: IterLinSol = BCGSTAB_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol, MaxIter, &Residual, false); break; case FGMRES: IterLinSol = FGMRES_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol, MaxIter, &Residual, false); break; case RESTARTED_FGMRES: IterLinSol = 0; while (IterLinSol < config->GetLinear_Solver_Iter()) { if (IterLinSol + config->GetLinear_Solver_Restart_Frequency() > config->GetLinear_Solver_Iter()) MaxIter = config->GetLinear_Solver_Iter() - IterLinSol; IterLinSol += FGMRES_LinSolver(LinSysRes, LinSysSol, *mat_vec, *precond, SolverTol, MaxIter, &Residual, false); if (LinSysRes.norm() < SolverTol) break; SolverTol = SolverTol*(1.0/LinSysRes.norm()); } break; } /*--- Dealocate memory of the Krylov subspace method ---*/ delete mat_vec; delete precond; } /*--- Smooth the linear system. ---*/ else { switch (config->GetKind_Linear_Solver()) { case SMOOTHER_LUSGS: mat_vec = new CSysMatrixVectorProduct(Jacobian, geometry, config); IterLinSol = Jacobian.LU_SGS_Smoother(LinSysRes, LinSysSol, *mat_vec, SolverTol, MaxIter, &Residual, false, geometry, config); delete mat_vec; break; case SMOOTHER_JACOBI: mat_vec = new CSysMatrixVectorProduct(Jacobian, geometry, config); Jacobian.BuildJacobiPreconditioner(); IterLinSol = Jacobian.Jacobi_Smoother(LinSysRes, LinSysSol, *mat_vec, SolverTol, MaxIter, &Residual, false, geometry, config); delete mat_vec; break; case SMOOTHER_ILU: mat_vec = new CSysMatrixVectorProduct(Jacobian, geometry, config); Jacobian.BuildILUPreconditioner(); IterLinSol = Jacobian.ILU0_Smoother(LinSysRes, LinSysSol, *mat_vec, SolverTol, MaxIter, &Residual, false, geometry, config); delete mat_vec; break; case SMOOTHER_LINELET: Jacobian.BuildJacobiPreconditioner(); Jacobian.ComputeLineletPreconditioner(LinSysRes, LinSysSol, geometry, config); IterLinSol = 1; break; } } if(TapeActive){ /*--- Prepare the externally differentiated linear solver ---*/ SetExternalSolve(Jacobian, LinSysRes, LinSysSol, geometry, config); /*--- Start recording if it was stopped for the linear solver ---*/ AD::StartRecording(); } return IterLinSol; }
unsigned long CSysSolve::Solve(CSysMatrix **Jacobian, CSysVector **LinSysRes, CSysVector **LinSysSol, CGeometry **geometry, CConfig *config, unsigned short iMesh) { double SolverTol = config->GetLinear_Solver_Error(); unsigned long MaxIter = config->GetLinear_Solver_Iter(); unsigned long IterLinSol = 0; /*--- Solve the linear system using a Krylov subspace method ---*/ if (config->GetKind_Linear_Solver() == BCGSTAB || config->GetKind_Linear_Solver() == FGMRES || config->GetKind_Linear_Solver() == RFGMRES) { CMatrixVectorProduct* mat_vec = new CSysMatrixVectorProduct(*Jacobian[iMesh], geometry[iMesh], config); CPreconditioner* precond = NULL; switch (config->GetKind_Linear_Solver_Prec()) { case JACOBI: Jacobian[iMesh]->BuildJacobiPreconditioner(); precond = new CJacobiPreconditioner(*Jacobian[iMesh], geometry[iMesh], config); break; case ILU: Jacobian[iMesh]->BuildILUPreconditioner(); precond = new CILUPreconditioner(*Jacobian[iMesh], geometry[iMesh], config); break; case LU_SGS: precond = new CLU_SGSPreconditioner(*Jacobian[iMesh], geometry[iMesh], config); break; case LINELET: Jacobian[iMesh]->BuildJacobiPreconditioner(); precond = new CLineletPreconditioner(*Jacobian[iMesh], geometry[iMesh], config); break; } switch (config->GetKind_Linear_Solver()) { case BCGSTAB: IterLinSol = BCGSTAB_LinSolver(*LinSysRes[iMesh], *LinSysSol[iMesh], *mat_vec, *precond, SolverTol, MaxIter, false); break; case FGMRES: IterLinSol = FGMRES_LinSolver(*LinSysRes[iMesh], *LinSysSol[iMesh], *mat_vec, *precond, SolverTol, MaxIter, false); break; case RFGMRES: IterLinSol = 0; while (IterLinSol < config->GetLinear_Solver_Iter()) { if (IterLinSol + config->GetLinear_Solver_Restart_Frequency() > config->GetLinear_Solver_Iter()) MaxIter = config->GetLinear_Solver_Iter() - IterLinSol; IterLinSol += FGMRES_LinSolver(*LinSysRes[iMesh], *LinSysSol[iMesh], *mat_vec, *precond, SolverTol, MaxIter, false); if (LinSysRes[iMesh]->norm() < SolverTol) break; SolverTol = SolverTol*(1.0/LinSysRes[iMesh]->norm()); } break; } /*--- Dealocate memory of the Krylov subspace method ---*/ delete mat_vec; delete precond; } /*--- Solve the linear system using a linear multigrid ---*/ else if (config->GetKind_Linear_Solver() == MULTIGRID) { CMatrixVectorProduct* mat_vec = new CSysMatrixVectorProduct(*Jacobian[iMesh], geometry[iMesh], config); MultiGrid_LinSolver(Jacobian, LinSysRes, LinSysSol, *mat_vec, geometry, config, iMesh, config->GetMGCycle(), SolverTol, MaxIter, true); delete mat_vec; } /*--- Smooth the linear system. ---*/ else if (config->GetKind_Linear_Solver() == SMOOTHER_LUSGS || config->GetKind_Linear_Solver() == SMOOTHER_JACOBI || config->GetKind_Linear_Solver() == SMOOTHER_ILU || config->GetKind_Linear_Solver() == SMOOTHER_LINELET) { switch (config->GetKind_Linear_Solver()) { case SMOOTHER_LUSGS: Jacobian[iMesh]->ComputeLU_SGSPreconditioner(*LinSysRes[iMesh], *LinSysSol[iMesh], geometry[iMesh], config); break; case SMOOTHER_JACOBI: Jacobian[iMesh]->BuildJacobiPreconditioner(); Jacobian[iMesh]->ComputeJacobiPreconditioner(*LinSysRes[iMesh], *LinSysSol[iMesh], geometry[iMesh], config); break; case SMOOTHER_ILU: Jacobian[iMesh]->BuildILUPreconditioner(); Jacobian[iMesh]->ComputeILUPreconditioner(*LinSysRes[iMesh], *LinSysSol[iMesh], geometry[iMesh], config); break; case SMOOTHER_LINELET: Jacobian[iMesh]->BuildJacobiPreconditioner(); Jacobian[iMesh]->ComputeLineletPreconditioner(*LinSysRes[iMesh], *LinSysSol[iMesh], geometry[iMesh], config); break; IterLinSol = 1; } } return IterLinSol; }