libMesh
Loading...
Searching...
No Matches
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
41namespace libMesh
42{
43
44// The SolverException class is only defined when exceptions are enabled.
45#ifdef LIBMESH_ENABLE_EXCEPTIONS
46
51{
52public:
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
117PETSC_BEGIN_END(VecScatter) // VecScatterBeginEnd
118PETSC_BEGIN_END(MatAssembly) // MatAssemblyBeginEnd
119PETSC_BEGIN_END(VecAssembly) // VecAssemblyBeginEnd
120PETSC_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
A specialization of the SolverException class for PETSc.
A class representing an exception during a solve.
int error_code
The error code generated by the solver.
std::string what_message
string which holds the message built in the constructor.
The libMesh namespace provides an interface to certain functionality in the library.
void libmesh_ignore(const Args &...)