libMesh
petsc_solver_exception.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 
9 // This library 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 GNU
12 // Lesser General Public License for more details.
13 
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 
18 #ifndef LIBMESH_PETSC_SOLVER_EXCEPTION_H
19 #define LIBMESH_PETSC_SOLVER_EXCEPTION_H
20 
21 #include "libmesh/libmesh_common.h"
22 
23 #ifdef LIBMESH_HAVE_PETSC
24 
25 #include "libmesh/libmesh_exceptions.h"
26 #include "libmesh/petsc_macro.h"
27 #include "timpi/communicator.h"
28 
29 #ifdef I
30 # define LIBMESH_SAW_I
31 #endif
32 
33 #include "libmesh/ignore_warnings.h"
34 #include <petscsys.h>
35 #include "libmesh/restore_warnings.h"
36 
37 #ifndef LIBMESH_SAW_I
38 # undef I // Avoid complex.h contamination
39 #endif
40 
41 namespace libMesh
42 {
43 
44 // The SolverException class is only defined when exceptions are enabled.
45 #ifdef LIBMESH_ENABLE_EXCEPTIONS
46 
51 {
52 public:
53  PetscSolverException(int error_code_in) :
54  SolverException(error_code_in)
55  {
56  const char * text;
57 #if PETSC_VERSION_LESS_THAN(3,25,0)
58  char * specific;
59 #else
60  const char * specific;
61 #endif
62  auto ierr = PetscErrorMessage(cast_int<PetscErrorCode>(error_code), &text, &specific);
63  // This is one scenario where we ignore the error code
64  // returned by a PETSc function :)
65  libmesh_ignore(ierr);
66 
67  // Usually the "specific" error message string is more useful than
68  // the generic text corresponding to the error_code, since many
69  // SETERRQ calls just use error_code == 1
70  if (specific)
71  what_message = std::string(specific);
72  else if (text)
73  what_message = std::string(text);
74  }
75 };
76 
77 
78 
79 // Macro which we call in functions returning a datatype convertible
80 // to PetscErrorCode after every PETSc function that returns an error code.
81 #define LIBMESH_CHKERRQ(ierr) \
82  do { \
83  if (ierr != 0) \
84  throw libMesh::PetscSolverException(ierr); \
85  } while (0)
86 
87 // Two-argument CHKERR macro that takes both a comm and an error
88 // code. When exceptions are enabled, the comm is not used for
89 // anything, so we libmesh_ignore() it.
90 #define LIBMESH_CHKERRA(comm, ierr) \
91  do { \
92  libmesh_ignore(comm); \
93  LIBMESH_CHKERRQ(ierr); \
94  } while (0)
95 
96 #else
97 
98 // If we don't have exceptions enabled, just fall back on calling
99 // PETSc's CHKERRQ or CHKERRABORT macros.
100 #define LIBMESH_CHKERRQ(ierr) CHKERRQ(ierr);
101 #define LIBMESH_CHKERRA(comm, ierr) CHKERRABORT(comm, ierr);
102 
103 #endif
104 
105 #define PETSC_BEGIN_END(Function) \
106  template<class ...Args> \
107  inline \
108  void Function ## BeginEnd(const Parallel::Communicator & comm, const Args&... args) \
109  { \
110  PetscErrorCode ierr = LIBMESH_PETSC_SUCCESS; \
111  ierr = Function ## Begin(args...); \
112  LIBMESH_CHKERRA(comm.get(), ierr); \
113  ierr = Function ## End(args...); \
114  LIBMESH_CHKERRA(comm.get(), ierr); \
115  }
116 
117 PETSC_BEGIN_END(VecScatter) // VecScatterBeginEnd
118 PETSC_BEGIN_END(MatAssembly) // MatAssemblyBeginEnd
119 PETSC_BEGIN_END(VecAssembly) // VecAssemblyBeginEnd
120 PETSC_BEGIN_END(VecGhostUpdate) // VecGhostUpdateBeginEnd
121 
122 // To use instead of PETSc idioms that'd call CHKERRQ or PetscCall().
123 #define LibmeshPetscCallQ(...) \
124  do \
125  { \
126  PetscErrorCode libmesh_petsc_call_ierr; \
127  libmesh_petsc_call_ierr = __VA_ARGS__; \
128  LIBMESH_CHKERRQ(libmesh_petsc_call_ierr); \
129  } while (0)
130 
131 // To use instead of PETSc idioms that'd call CHKERRABORT or PetscCallAbort().
132 #define LibmeshPetscCallA(comm, ...) \
133  do \
134  { \
135  PetscErrorCode libmesh_petsc_call_ierr; \
136  libmesh_petsc_call_ierr = __VA_ARGS__; \
137  LIBMESH_CHKERRA(comm, libmesh_petsc_call_ierr); \
138  } while (0)
139 
140 // Shortcut for LibmeshPetscCallA for use within a ParallelObject, i.e. when
141 // we can rely on the communicator being available from the "this" pointer.
142 #define LibmeshPetscCall(...) \
143  LibmeshPetscCallA(this->comm().get(), __VA_ARGS__)
144 
145 // Shortcut for LibmeshPetscCallA for use when we have a Parallel::Communicator
146 // available instead of just a bare MPI communicator.
147 #define LibmeshPetscCall2(comm, ...) \
148  LibmeshPetscCallA(comm.get(), __VA_ARGS__)
149 
150 #ifdef LIBMESH_ENABLE_EXCEPTIONS
151 #define LibmeshPetscCallExternal(func, ...) \
152  do { \
153  const auto libmesh_petsc_call_external_ierr = cast_int<int>(func(__VA_ARGS__)); \
154  if (libmesh_petsc_call_external_ierr != 0) \
155  throw PetscSolverException(libmesh_petsc_call_external_ierr); \
156  } while (0)
157 #else
158 #define LibmeshPetscCallExternal(func, ...) \
159  do { \
160  const auto libmesh_petsc_call_external_ierr = cast_int<int>(func(__VA_ARGS__)); \
161  if (libmesh_petsc_call_external_ierr != 0) \
162  libmesh_terminate_handler(); \
163  } while (0)
164 #endif
165 
166 
167 } // namespace libMesh
168 
169 #endif // LIBMESH_HAVE_PETSC
170 #endif // LIBMESH_PETSC_SOLVER_EXCEPTION_H
int error_code
The error code generated by the solver.
The libMesh namespace provides an interface to certain functionality in the library.
std::string what_message
string which holds the message built in the constructor.
A class representing an exception during a solve.
A specialization of the SolverException class for PETSc.
void libmesh_ignore(const Args &...)