libMesh
petsc_solver_exception.h
Go to the documentation of this file.
1 // The libMesh Finite Element Library.
2 // Copyright (C) 2002-2025 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  char * specific;
58  auto ierr = PetscErrorMessage(cast_int<PetscErrorCode>(error_code), &text, &specific);
59  // This is one scenario where we ignore the error code
60  // returned by a PETSc function :)
61  libmesh_ignore(ierr);
62 
63  // Usually the "specific" error message string is more useful than
64  // the generic text corresponding to the error_code, since many
65  // SETERRQ calls just use error_code == 1
66  if (specific)
67  what_message = std::string(specific);
68  else if (text)
69  what_message = std::string(text);
70  }
71 };
72 
73 
74 
75 // Macro which we call in functions returning a datatype convertible
76 // to PetscErrorCode after every PETSc function that returns an error code.
77 #define LIBMESH_CHKERRQ(ierr) \
78  do { \
79  if (ierr != 0) \
80  throw libMesh::PetscSolverException(ierr); \
81  } while (0)
82 
83 // Two-argument CHKERR macro that takes both a comm and an error
84 // code. When exceptions are enabled, the comm is not used for
85 // anything, so we libmesh_ignore() it.
86 #define LIBMESH_CHKERRA(comm, ierr) \
87  do { \
88  libmesh_ignore(comm); \
89  LIBMESH_CHKERRQ(ierr); \
90  } while (0)
91 
92 #else
93 
94 // If we don't have exceptions enabled, just fall back on calling
95 // PETSc's CHKERRQ or CHKERRABORT macros.
96 #define LIBMESH_CHKERRQ(ierr) CHKERRQ(ierr);
97 #define LIBMESH_CHKERRA(comm, ierr) CHKERRABORT(comm, ierr);
98 
99 #endif
100 
101 #define PETSC_BEGIN_END(Function) \
102  template<class ...Args> \
103  inline \
104  void Function ## BeginEnd(const Parallel::Communicator & comm, const Args&... args) \
105  { \
106  PetscErrorCode ierr = LIBMESH_PETSC_SUCCESS; \
107  ierr = Function ## Begin(args...); \
108  LIBMESH_CHKERRA(comm.get(), ierr); \
109  ierr = Function ## End(args...); \
110  LIBMESH_CHKERRA(comm.get(), ierr); \
111  }
112 
113 PETSC_BEGIN_END(VecScatter) // VecScatterBeginEnd
114 PETSC_BEGIN_END(MatAssembly) // MatAssemblyBeginEnd
115 PETSC_BEGIN_END(VecAssembly) // VecAssemblyBeginEnd
116 PETSC_BEGIN_END(VecGhostUpdate) // VecGhostUpdateBeginEnd
117 
118 // To use instead of PETSc idioms that'd call CHKERRQ or PetscCall().
119 #define LibmeshPetscCallQ(...) \
120  do \
121  { \
122  PetscErrorCode libmesh_petsc_call_ierr; \
123  libmesh_petsc_call_ierr = __VA_ARGS__; \
124  LIBMESH_CHKERRQ(libmesh_petsc_call_ierr); \
125  } while (0)
126 
127 // To use instead of PETSc idioms that'd call CHKERRABORT or PetscCallAbort().
128 #define LibmeshPetscCallA(comm, ...) \
129  do \
130  { \
131  PetscErrorCode libmesh_petsc_call_ierr; \
132  libmesh_petsc_call_ierr = __VA_ARGS__; \
133  LIBMESH_CHKERRA(comm, libmesh_petsc_call_ierr); \
134  } while (0)
135 
136 // Shortcut for LibmeshPetscCallA for use within a ParallelObject, i.e. when
137 // we can rely on the communicator being available from the "this" pointer.
138 #define LibmeshPetscCall(...) \
139  LibmeshPetscCallA(this->comm().get(), __VA_ARGS__)
140 
141 // Shortcut for LibmeshPetscCallA for use when we have a Parallel::Communicator
142 // available instead of just a bare MPI communicator.
143 #define LibmeshPetscCall2(comm, ...) \
144  LibmeshPetscCallA(comm.get(), __VA_ARGS__)
145 
146 #ifdef LIBMESH_ENABLE_EXCEPTIONS
147 #define LibmeshPetscCallExternal(func, ...) \
148  do { \
149  const auto libmesh_petsc_call_external_ierr = cast_int<int>(func(__VA_ARGS__)); \
150  if (libmesh_petsc_call_external_ierr != 0) \
151  throw PetscSolverException(libmesh_petsc_call_external_ierr); \
152  } while (0)
153 #else
154 #define LibmeshPetscCallExternal(func, ...) \
155  do { \
156  const auto libmesh_petsc_call_external_ierr = cast_int<int>(func(__VA_ARGS__)); \
157  if (libmesh_petsc_call_external_ierr != 0) \
158  libmesh_terminate_handler(); \
159  } while (0)
160 #endif
161 
162 
163 } // namespace libMesh
164 
165 #endif // LIBMESH_HAVE_PETSC
166 #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 &...)