OGS
PETScLinearSolver.cpp
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Copyright (c) OpenGeoSys Community (opengeosys.org)
2// SPDX-License-Identifier: BSD-3-Clause
3
4#include "PETScLinearSolver.h"
5
6#include "BaseLib/RunTime.h"
7
8namespace MathLib
9{
10PETScLinearSolver::PETScLinearSolver(std::string const& prefix,
11 std::string const& petsc_options)
12{
13#if PETSC_VERSION_LT(3, 7, 0)
14 PetscOptionsInsertString(petsc_options.c_str());
15#else
16 PetscOptionsInsertString(nullptr, petsc_options.c_str());
17#endif
18
19 PetscCallAbort(PETSC_COMM_WORLD, KSPCreate(PETSC_COMM_WORLD, &solver_));
20
21 PetscCallAbort(PETSC_COMM_WORLD, KSPGetPC(solver_, &pc_));
22
23 if (!prefix.empty())
24 {
25 PetscCallAbort(PETSC_COMM_WORLD,
26 KSPSetOptionsPrefix(solver_, prefix.c_str()));
27 }
28
29 PetscCallAbort(PETSC_COMM_WORLD,
30 KSPSetInitialGuessNonzero(solver_, PETSC_TRUE));
31 PetscCallAbort(PETSC_COMM_WORLD,
32 KSPSetFromOptions(solver_)); // set run-time options
33
34 KSPType ksp_type;
35 PetscCallAbort(PETSC_COMM_WORLD, KSPGetType(solver_, &ksp_type));
37}
38
40{
41 BaseLib::RunTime wtimer;
42 wtimer.start();
43
44// define TEST_MEM_PETSC
45#ifdef TEST_MEM_PETSC
46 PetscLogDouble mem1, mem2;
47 PetscMemoryGetCurrentUsage(&mem1);
48#endif
49
50 KSPNormType norm_type;
51 PetscCallAbort(PETSC_COMM_WORLD, KSPGetNormType(solver_, &norm_type));
52 const char* ksp_type;
53 const char* pc_type;
54 PetscCallAbort(PETSC_COMM_WORLD, KSPGetType(solver_, &ksp_type));
55 PetscCallAbort(PETSC_COMM_WORLD, PCGetType(pc_, &pc_type));
56
57 PetscPrintf(PETSC_COMM_WORLD,
58 "\n================================================");
59 PetscPrintf(PETSC_COMM_WORLD,
60 "\nLinear solver %s with %s preconditioner using %s", ksp_type,
61 pc_type, KSPNormTypes[norm_type]);
62
63 PetscCallAbort(PETSC_COMM_WORLD, KSPSetOperators(solver_, A.getRawMatrix(),
64 A.getRawMatrix()));
65
66 PetscCallAbort(PETSC_COMM_WORLD,
67 KSPSolve(solver_, b.getRawVector(), x.getRawVector()));
68
69 KSPConvergedReason reason;
70 PetscCallAbort(PETSC_COMM_WORLD, KSPGetConvergedReason(solver_, &reason));
71
72 bool converged = true;
73 if (reason > 0)
74 {
75 PetscInt its;
76 PetscCallAbort(PETSC_COMM_WORLD, KSPGetIterationNumber(solver_, &its));
77 PetscPrintf(PETSC_COMM_WORLD, "\nconverged in %d iterations", its);
78 switch (reason)
79 {
80 case KSP_CONVERGED_RTOL:
81 PetscPrintf(PETSC_COMM_WORLD,
82 " (relative convergence criterion fulfilled).");
83 break;
84 case KSP_CONVERGED_ATOL:
85 PetscPrintf(PETSC_COMM_WORLD,
86 " (absolute convergence criterion fulfilled).");
87 break;
88 default:
89 PetscPrintf(PETSC_COMM_WORLD, ".");
90 }
91
92 PetscPrintf(PETSC_COMM_WORLD,
93 "\n================================================\n");
94 }
95 else if (reason == KSP_DIVERGED_ITS)
96 {
97 PetscPrintf(PETSC_COMM_WORLD,
98 "\nWarning: maximum number of iterations reached.\n");
99 }
100 else
101 {
102 converged = false;
103 if (reason == KSP_DIVERGED_INDEFINITE_PC)
104 {
105 PetscPrintf(PETSC_COMM_WORLD,
106 "\nDivergence because of indefinite preconditioner,");
107 PetscPrintf(PETSC_COMM_WORLD,
108 "\nTry to run again with "
109 "-pc_factor_shift_positive_definite option.\n");
110 }
111 else if (reason == KSP_DIVERGED_BREAKDOWN_BICG)
112 {
113 PetscPrintf(PETSC_COMM_WORLD,
114 "\nKSPBICG method was detected so the method could not "
115 "continue to enlarge the Krylov space.");
116 PetscPrintf(PETSC_COMM_WORLD,
117 "\nTry to run again with another solver.\n");
118 }
119 else if (reason == KSP_DIVERGED_NONSYMMETRIC)
120 {
121 PetscPrintf(PETSC_COMM_WORLD,
122 "\nMatrix or preconditioner is unsymmetric but KSP "
123 "requires symmetric.\n");
124 }
125 else
126 {
127 PetscPrintf(PETSC_COMM_WORLD,
128 "\nDivergence detected, use command option "
129 "-ksp_monitor or -log_summary to check the details.\n");
130 }
131 }
132
133#ifdef TEST_MEM_PETSC
134 PetscMemoryGetCurrentUsage(&mem2);
135 PetscPrintf(
136 PETSC_COMM_WORLD,
137 "###Memory usage by solver. Before: %f After: %f Increase: %d\n", mem1,
138 mem2, (int)(mem2 - mem1));
139#endif
140
141 elapsed_ctime_ += wtimer.elapsed();
142
143 return converged;
144}
145
146} // namespace MathLib
Count the running time.
Definition RunTime.h:18
double elapsed() const
Get the elapsed time in seconds.
Definition RunTime.h:31
void start()
Start the timer.
Definition RunTime.h:21
double elapsed_ctime_
Clock time.
PETScLinearSolver(std::string const &prefix, std::string const &petsc_options)
PC pc_
Preconditioner type.
bool solve(PETScMatrix &A, PETScVector &b, PETScVector &x)
bool canSolverHandleRectangular(std::string_view ksp_type)
Wrapper class for PETSc matrix routines for matrix.
Definition PETScMatrix.h:21
Mat & getRawMatrix()
Get matrix reference.
Definition PETScMatrix.h:75
Wrapper class for PETSc vector.
Definition PETScVector.h:28
PETSc_Vec & getRawVector()
Exposes the underlying PETSc vector.