6 #include <amdis/Initfile.hpp> 7 #include <amdis/linearalgebra/LinearSolverInterface.hpp> 8 #include <amdis/linearalgebra/petsc/Interface.hpp> 11 #define KSPDGGMRES "dggmres" 42 template <
class Matrix,
class VectorX,
class VectorY = VectorX>
44 :
public LinearSolverInterface<Matrix,VectorX,VectorY>
46 using Vector = VectorX;
70 void init(Matrix
const& A)
override 76 KSPCreate(PETSC_COMM_SELF, &ksp_);
79 PETSc::KSPSetOperators(ksp_, A.matrix(), A.matrix());
80 initKSP(ksp_, prefix_);
93 void apply(Vector& x, Vector
const& b, Dune::InverseOperatorResult& stat)
override 95 KSPSolve(ksp_, b.vector(), x.vector());
98 PETSc::KSPConvergedReasonView(ksp_, PETSC_VIEWER_STDOUT_WORLD);
100 KSPConvergedReason reason;
101 KSPGetConvergedReason(ksp_, &reason);
103 stat.converged = (reason > 0);
106 KSP ksp() {
return ksp_; }
110 virtual void initKSP(KSP ksp, std::string prefix)
const 113 auto kspType = Parameters::get<std::string>(prefix +
"->ksp");
114 std::string kspTypeStr = kspType.value_or(
"default");
119 if (kspTypeStr ==
"direct")
120 initDirectSolver(ksp, prefix);
121 else if (kspTypeStr !=
"default") {
122 KSPSetType(ksp, kspTypeStr.c_str());
125 initKSPParameters(ksp, kspTypeStr.c_str(), prefix);
128 if (kspTypeStr !=
"preonly")
129 KSPSetInitialGuessNonzero(ksp, PETSC_TRUE);
136 KSPMonitorSet(ksp, PETSc::KSPMonitorCyclic,
nullptr,
nullptr);
137 }
else if (info > 1) {
138 KSPMonitorSet(ksp, PETSc::KSPMonitorNoisy,
nullptr,
nullptr);
142 auto maxIt = Parameters::get<PetscInt>(prefix +
"->max it");
143 auto rTol = Parameters::get<PetscReal>(prefix +
"->rtol");
144 auto aTol = Parameters::get<PetscReal>(prefix +
"->atol");
145 auto dTol = Parameters::get<PetscReal>(prefix +
"->divtol");
146 if (maxIt || rTol || aTol || dTol)
147 KSPSetTolerances(ksp,
148 rTol.value_or(PETSC_DEFAULT), aTol.value_or(PETSC_DEFAULT),
149 dTol.value_or(PETSC_DEFAULT), maxIt.value_or(PETSC_DEFAULT));
151 auto kspPrefixParam = Parameters::get<std::string>(prefix +
"->prefix");
152 if (kspPrefixParam) {
153 std::string kspPrefix = kspPrefixParam.value() +
"_";
154 KSPSetOptionsPrefix(ksp, kspPrefix.c_str());
155 KSPSetFromOptions(ksp);
160 initPC(pc, prefix +
"->pc");
164 KSPView(ksp, PETSC_VIEWER_STDOUT_WORLD);
170 virtual void initDirectSolver(KSP ksp, std::string prefix)
const 172 KSPSetInitialGuessNonzero(ksp, PETSC_TRUE);
173 KSPSetType(ksp, KSPRICHARDSON);
178 auto matSolverType = Parameters::get<std::string>(prefix +
"->mat solver");
180 PETSc::PCFactorSetMatSolverType(pc, matSolverType.value().c_str());
183 KSPGetOperators(ksp, &Amat, &Pmat);
185 MatGetType(Pmat, &type);
186 if (std::strcmp(type, MATSEQAIJ) == 0)
187 PETSc::PCFactorSetMatSolverType(pc, MATSOLVERUMFPACK);
188 else if (std::strcmp(type, MATAIJ) == 0)
189 PETSc::PCFactorSetMatSolverType(pc, MATSOLVERMUMPS);
195 virtual void initPC(PC pc, std::string prefix)
const 198 auto pcType = Parameters::get<std::string>(prefix);
199 std::string pcTypeStr =
"default";
201 pcTypeStr = pcType.value();
202 PCSetType(pc, pcTypeStr.c_str());
205 if (pcTypeStr ==
"lu") {
208 auto matSolverType = Parameters::get<std::string>(prefix +
"->mat solver");
210 PETSc::PCFactorSetMatSolverType(pc, matSolverType.value().c_str());
211 }
else if (pcTypeStr ==
"bjacobi") {
213 PetscInt n_local, first;
216 PCBJacobiGetSubKSP(pc, &n_local, &first, &ksps);
217 for (PetscInt i = 0; i < n_local; ++i)
218 initKSP(ksps[i], prefix +
"->sub ksp");
219 }
else if (pcTypeStr ==
"ksp") {
223 PCKSPGetKSP(pc, &ksp);
224 initKSP(ksp, prefix +
"->ksp");
227 auto pcPrefixParam = Parameters::get<std::string>(prefix +
"->prefix");
229 std::string pcPrefix = pcPrefixParam.value() +
"_";
230 PCSetOptionsPrefix(pc, pcPrefix.c_str());
231 PCSetFromOptions(pc);
237 virtual void initKSPParameters(KSP ksp,
char const* ksptype, std::string prefix)
const 240 if (std::strcmp(ksptype, KSPRICHARDSON) == 0)
242 auto scale = Parameters::get<PetscReal>(prefix +
"->scale");
244 KSPRichardsonSetScale(ksp, scale.value());
247 else if (std::strcmp(ksptype, KSPGMRES) == 0 ||
248 std::strcmp(ksptype, KSPFGMRES) == 0 ||
249 std::strcmp(ksptype, KSPLGMRES) == 0 ||
250 std::strcmp(ksptype, KSPDGGMRES) == 0 ||
251 std::strcmp(ksptype, KSPPGMRES) == 0)
253 auto restart = Parameters::get<PetscInt>(prefix +
"->restart");
255 KSPGMRESSetRestart(ksp, restart.value());
257 auto gramschmidt = Parameters::get<std::string>(prefix +
"->gramschmidt");
259 if (gramschmidt.value() ==
"classical") {
260 KSPGMRESSetOrthogonalization(ksp, KSPGMRESClassicalGramSchmidtOrthogonalization);
261 auto refinementType = Parameters::get<std::string>(prefix +
"->refinement type");
262 if (refinementType) {
263 if (refinementType.value() ==
"never")
264 KSPGMRESSetCGSRefinementType(ksp, KSP_GMRES_CGS_REFINE_NEVER);
265 else if (refinementType.value() ==
"ifneeded")
266 KSPGMRESSetCGSRefinementType(ksp, KSP_GMRES_CGS_REFINE_IFNEEDED);
267 else if (refinementType.value() ==
"always")
268 KSPGMRESSetCGSRefinementType(ksp, KSP_GMRES_CGS_REFINE_ALWAYS);
270 }
else if (gramschmidt.value() ==
"modified") {
271 KSPGMRESSetOrthogonalization(ksp, KSPGMRESModifiedGramSchmidtOrthogonalization);
276 else if (std::strcmp(ksptype, KSPBCGSL) == 0)
278 auto ell = Parameters::get<PetscInt>(prefix +
"->ell");
280 KSPBCGSLSetEll(ksp, ell.value());
283 else if (std::strcmp(ksptype, KSPGCR) == 0)
285 auto restart = Parameters::get<PetscInt>(prefix +
"->restart");
287 KSPGCRSetRestart(ksp, restart.value());
296 bool initialized_ =
false;
void init(Matrix const &A) override
Implements LinearSolverInterface::init()
Definition: LinearSolver.hpp:70
Definition: AdaptBase.hpp:6
void apply(Vector &x, Vector const &b, Dune::InverseOperatorResult &stat) override
Implements LinearSolverInterface::apply()
Definition: LinearSolver.hpp:93
static std::optional< T > get(std::string const &key)
Get parameter-values from parameter-tree.
Definition: Initfile.hpp:25
LinearSolver(std::string const &, std::string const &prefix)
Constructor.
Definition: LinearSolver.hpp:58
Implementation of LinearSolverInterface for EIGEN solvers.
Definition: LinearSolver.hpp:14
void finish() override
Implements LinearSolverInterface::finish()
Definition: LinearSolver.hpp:35
static Dune::MPIHelper::MPICommunicator comm()
Return the MPI_Comm object (or a fake communicator)
Definition: Environment.hpp:86