CEPS  24.01
Cardiac ElectroPhysiology Simulator
PETScKSP.cpp
Go to the documentation of this file.
1 /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2  This file is part of CEPS.
3 
4  CEPS is free software: you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation, either version 3 of the License, or
7  (at your option) any later version.
8 
9  CEPS is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You should have received a copy of the GNU General Public License
15  along with CEPS (see file LICENSE at root of project).
16  If not, see <https://www.gnu.org/licenses/>.
17 
18 
19  Copyright 2019-2024 Inria, Universite de Bordeaux
20 
21  Authors, in alphabetical order:
22 
23  Pierre-Elliott BECUE, Florian CARO, Yves COUDIERE(*), Andjela DAVIDOVIC,
24  Charlie DOUANLA-LONTSI, Marc FUENTES, Mehdi JUHOOR, Michael LEGUEBE(*),
25  Pauline MIGERDITICHAN, Valentin PANNETIER(*), Nejib ZEMZEMI.
26  * : currently active authors
27 
28 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
31 
33 {
34  this->initialize();
35 }
36 
38 {
39  this->initialize();
40 
41  if (ceps::isValidPtr(params))
42  setupWithParameters(params);
43 }
44 
46 {
47  if (ceps::isProfiling())
48  ceps::profilingLog() << "# Average number of CG iterations: " << m_avIterNb/(1.*m_nSolv) << std::endl;
49 
50  KSPDestroy(&m_solver);
51 }
52 
53 void
55 {
56  if (!m_isSetUp)
57  setUp();
58 
59  CEPS_ABORT_IF(not x, "Provided solution vector is nullptr");
60  CEPS_ABORT_IF(not m_rhsVector, "right-hand side vector has not been set.");
61 
62  // Global size
63  CepsIndex rhsSize, xSize;
64  m_rhsVector->getSize(&rhsSize);
65  x->getSize(&xSize);
66  CEPS_ABORT_IF(rhsSize != xSize,
67  "right hand side and solution vectors " << std::endl
68  << "have incompatible sizes. RHS has global size " << rhsSize << "\n"
69  << "while solution has size " << xSize
70  );
71  // Local range
72  CepsIndex rhsLo, rhsHi, xLo, xHi;
73  m_rhsVector->getLocalRange(&rhsLo, &rhsHi);
74  x->getLocalRange(&xLo, &xHi);
75  CEPS_ABORT_IF(rhsLo != xLo or rhsHi != xHi,
76  "right hand side and solution vectors" << std::endl
77  << "have incompatible rangees. RHS has local range (" << rhsLo << "," << rhsHi << ")\n"
78  << "while solution has range (" << xLo << "," << xHi << ")"
79  );
80 
81  if (ceps::isProfiling ())
82  getProfiler()->start("LSsolve", "solving linear system(s)");
83 
84  // solve system
85  KSPSolve (m_solver,m_rhsVector->getVector(),x->getVector());
86 
87  if (ceps::isProfiling())
88  getProfiler()->stop("LSsolve");
89 
90  CepsInt nbIterations;
91  KSPGetIterationNumber(m_solver, &nbIterations);
92 
93  m_avIterNb += nbIterations;
94  m_nSolv++;
95 
96  // check if converged
97  KSPConvergedReason reason;
98  KSPGetConvergedReason (m_solver, &reason);
99  // PetscViewer viewer;
100  // PetscViewerCreate(PETSC_COMM_WORLD,&viewer);
101  // KSPConvergedReasonView(m_solver,viewer);
102 
103  static constexpr const char* description[] = {
104  "",
105  "",
106  "KSP_DIVERGED_NULL: breakdown when solving the Hessenberg system within GMRES",
107  "KSP_DIVERGED_ITS: requested number of iterations",
108  "KSP_DIVERGED_DTOL: large increase in the residual norm",
109  "KSP_DIVERGED_BREAKDOWN: breakdown in the Krylov method",
110  "KSP_DIVERGED_BREAKDOWN_BICG: breakdown in the KSPBGCS Krylov method",
111  "KSP_DIVERGED_NONSYMMETRIC: the operator or preconditioner was not symmetric for a KSPType that requires symmetry",
112  "KSP_DIVERGED_INDEFINITE_PC: the preconditioner was indefinite for a KSPType that requires it be definite",
113  "KSP_DIVERGED_NANORINF: a not a number of infinity was detected in a vector during the computation",
114  "KSP_DIVERGED_INDEFINITE_MAT: the operator was indefinite for a KSPType that requires it be definite",
115  "KSP_DIVERGED_PC_FAILED: the action of the preconditioner failed for some reason"};
116  CEPS_ABORT_IF(reason<=-1,
117  "KSP diverged: " << description[-reason]
118  // << "Please refer to the KSPConvergedReason page of PETSc\n"
119  // << "documentation for more explanations"
120  );
121 }
122 
124 setLhsMatrix (DMatPtr lhs)
125 {
126  CEPS_ABORT_IF(not lhs,"nullptr passed as lhs matrix");
127  m_lhsMatrix = lhs;
128  // forces call of setOperators function
129  m_isSetUp = false;
130 }
131 
132 void
134 {
135  // nullptr matrix can be given: LHS matrix will be used when solving
136  m_precondMatrix = precond;
137  m_isSetUp = false;
138 }
139 
140 void
142 {
143  CEPS_ABORT_IF(not rhs,"nullptr passed as rhs vector");
144  m_rhsVector = rhs;
145  return;
146 }
147 
148 void
150 {
151  CepsString S = ceps::toUpper(stype);
152  if (S == "CG" or S == "CONJUGATE GRADIENT")
153  {
154  PC pc;
155  KSPGetPC (m_solver, &pc);
156  PCSetType (pc, PCBJACOBI);
157  KSPSetType (m_solver, KSPCG);
158  }
159  else if (S == "BICGSTAB")
160  {
161  PC pc;
162  KSPGetPC (m_solver, &pc);
163  PCSetType (pc, PCBJACOBI);
164  KSPSetType (m_solver, KSPBCGS);
165  }
166  else if (S == "GMRES")
167  {
168  PC pc;
169  KSPGetPC (m_solver, &pc);
170  PCSetType (pc, PCBJACOBI);
171  KSPSetType (m_solver, KSPGMRES);
172  }
173  else if (S == "LU")
174  {
175  CEPS_ABORT_IF(ceps::isParallel(),"Impossible to use a direct solver in parallel.");
176  PC pc;
177  KSPGetPC (m_solver, &pc);
178  PCSetType (pc, PCLU);
179  }
180  else
181  {
182  // unsupported solverType
183  CEPS_WARNS (
184  "unsupported solver type. Will use default value GMRES.\n" <<
185  " Valid types are CG, BICGSTAB, GMRES, and LU (LU for sequential runs only)"
186  );
187  }
188 }
189 
190 void
192 {
193  // check correct lhs
194  CEPS_ABORT_IF(not m_lhsMatrix,"no LHS matrix was provided to the solver");
195 
196  // if precond is nullptr, default is to give LHS matrix as preconditioning matrix
197  if (not m_precondMatrix)
199 
200  KSPSetOperators (m_solver, m_lhsMatrix->getMatrix (), m_precondMatrix->getMatrix ());
201  KSPSetUp (m_solver);
202  m_isSetUp = true;
203 }
204 
205 void
207 {
208  m_relativeTolerance = rTol;
209  m_absoluteTolerance = aTol;
210  m_divergenceTolerance = dTol;
211  m_maxIterations = iter;
212  KSPSetTolerances (m_solver, rTol, aTol, dTol, iter);
213 }
214 
215 void
217 {
218  m_maxIterations = maxIterations;
219  CepsReal rtol, abstol, dtol;
220 
221  // get the previous tolerances, since PETSc API does not
222  // have a function that changes only the number of iterations
223  KSPGetTolerances (m_solver, &rtol, &abstol, &dtol, nullptr);
224  KSPSetTolerances (m_solver, rtol, abstol, dtol, maxIterations);
225 }
226 
227 void
229 {
230  m_relativeTolerance = rTol;
231  CepsReal absTol, dTol;
232  CepsInt iter;
233  KSPGetTolerances (m_solver, nullptr, &absTol, &dTol, &iter);
234  KSPSetTolerances (m_solver, rTol, absTol, dTol, iter);
235 }
236 
237 void
239 {
240  m_absoluteTolerance = aTol;
241  CepsReal relTol, dtol;
242  CepsInt iter;
243  KSPGetTolerances(m_solver, &relTol, nullptr, &dtol, &iter);
244  KSPSetTolerances(m_solver, relTol, aTol, dtol, iter);
245 }
246 
247 void
249 {
250  m_divergenceTolerance = dTol;
251  CepsReal absTol, relTol;
252  CepsInt iter;
253  KSPGetTolerances (m_solver, &relTol, &absTol, nullptr, &iter);
254  KSPSetTolerances (m_solver, relTol, absTol, dTol, iter);
255 }
256 
257 CepsUInt
259 {
260  return m_maxIterations;
261 }
262 
263 void
265 {
266  KSPCreate(PETSC_COMM_WORLD, &m_solver);
267  m_isSetUp = false;
268  m_lhsMatrix = nullptr;
269  m_rhsVector = nullptr;
270  m_precondMatrix = nullptr;
271 
272  // default solver is GMRES
273  setType("GMRES");
274 
275  // Get PetscDefaults for tolerances
276  CepsReal rTol, aTol, dTol;
277  CepsInt iter;
278  KSPGetTolerances(m_solver, &rTol, &aTol, &dTol, &iter);
279  m_relativeTolerance = rTol;
280  m_absoluteTolerance = aTol;
281  m_divergenceTolerance = dTol;
282  m_maxIterations = iter;
283 
284  // Initialize iteration counters
285  m_nSolv = 0;
286  m_avIterNb = 0;
287 }
#define CEPS_ABORT_IF(condition, message)
Stops the execution with a message if condition is true. If testing is enabled, only throws a runtime...
#define CEPS_WARNS(message)
Writes a warning in the debug log and in the terminal (stderr).
std::basic_string< CepsChar > CepsString
C++ format string.
Definition: CepsTypes.hpp:128
std::make_unsigned_t< CepsInt > CepsUInt
Unsigned version on CepsInt.
Definition: CepsTypes.hpp:109
float CepsReal
Need single precision floating point.
Definition: CepsTypes.hpp:100
int32_t CepsInt
Need 32 bit integer.
Definition: CepsTypes.hpp:106
CepsInt CepsIndex
Index rowid etc.
Definition: CepsTypes.hpp:111
std::shared_ptr< DistributedMatrix > DMatPtr
Short typedef for pointer on dist matrix.
std::shared_ptr< DistributedVector > DVecPtr
Short typedef for pointer on distributed vector.
Profiler * getProfiler() const
Access to profiler.
Definition: CepsObject.cpp:46
Reads and stores simulation configuration.
CepsReal m_relativeTolerance
Stopping criterion for iterative methods (rel diff between iterations)
void setLhsMatrix(DMatPtr lhs)
Set the left-hand side matrix of the system.
Definition: PETScKSP.cpp:124
void setTolerances(CepsReal rTol, CepsReal aTol, CepsReal dTol, CepsUInt iter)
Sets all stopping criteria of iterative methods at once.
Definition: PETScKSP.cpp:206
~LinearSystem() override
Destructor.
Definition: PETScKSP.cpp:45
CepsUInt m_avIterNb
average number of iterations
void setMaxNbIterations(CepsUInt nbIterations)
Stopping criterion for iterative solvers.
Definition: PETScKSP.cpp:216
LinearSystem()
Default constructor.
Definition: PETScKSP.cpp:32
void setupWithParameters(InputParameters *params)
Sets the options from text parameters.
void setDivergenceTolerance(CepsReal dTol)
Stopping criterion for iterative solvers: increase in norm of residuals.
Definition: PETScKSP.cpp:248
DVecPtr m_rhsVector
Right Hand Side (B)
DMatPtr m_lhsMatrix
Left Hand Side (A)
void setAbsoluteTolerance(CepsReal aTol)
Stopping criterion for iterative solvers: absolute norm of residuals.
Definition: PETScKSP.cpp:238
void setPreconditioningMatrix(DMatPtr preconditioningMatrix)
Sets the preconditioning matrix. If nullptr (default) LHS is used as preconditionner.
Definition: PETScKSP.cpp:133
CepsUInt m_nSolv
number of calls of the solvers
DMatPtr m_precondMatrix
Preconditioning matrix.
CepsReal m_divergenceTolerance
Stopping criterion for iterative methods (too large diff between iterations)
CepsBool m_isSetUp
Is the solver ready to solve ?
void initialize()
Sets the defaults values.
Definition: PETScKSP.cpp:264
virtual void solve(DVecPtr solution)
Solve current linear system. Calls the solver's method.
Definition: PETScKSP.cpp:54
CepsUInt m_maxIterations
Maximum of iterations for iterative methods.
void setUp()
Calls methods of Linear Algebra library in order to prepare the solver.
Definition: PETScKSP.cpp:191
CepsUInt getMaxNbIterations() const
Stopping criterion for iterative solvers.
Definition: PETScKSP.cpp:258
void setRelativeTolerance(CepsReal rTol)
Stopping criterion for iterative solvers: relative norm of residuals.
Definition: PETScKSP.cpp:228
CepsReal m_absoluteTolerance
Stopping criterion for iterative methods (abs diff between iterations)
void setRhsVector(DVecPtr rhs)
Set the right hand side.
Definition: PETScKSP.cpp:141
CepsSolver m_solver
Underlying solver.
void setType(const CepsString &type)
Set solver type which can be CG, GMRES or LU. (LU for sequential runs only)
Definition: PETScKSP.cpp:149
void stop(CepsString lbl)
Stops the measure of a labeled chronometer.
void start(CepsString lbl, CepsString dspl="")
Creates or continue a labeled chronometer.
CepsBool isValidPtr(_Type *ptr)
Tells if pointer is not null.
Definition: CepsMemory.hpp:61
CepsBool isParallel()
Is there more than 1 process currently working ?
CepsString toUpper(const CepsString &s)
Switches all characters to upper case.
Definition: CepsString.cpp:124
std::ofstream & profilingLog()
Get the ProfilingLog used in Ceps.
Definition: CepsFlags.cpp:251
CepsBool isProfiling()
Check if we are currently profiling on the master proc (always false on slave procs).
Definition: CepsFlags.cpp:257