MFEM v4.7.0
Finite element discretization library
Loading...
Searching...
No Matches
error.hpp
Go to the documentation of this file.
1// Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#ifndef MFEM_ERROR_HPP
13#define MFEM_ERROR_HPP
14
15#include "../config/config.hpp"
16#include <iomanip>
17#include <sstream>
18#ifdef MFEM_USE_HIP
19#include <hip/hip_runtime.h>
20#endif
21
22namespace mfem
23{
24
25/// Action to take when MFEM encounters an error.
27{
28 MFEM_ERROR_ABORT = 0, /**<
29 Abort execution using abort() or MPI_Abort(). This is the default error
30 action when the build option MFEM_USE_EXCEPTIONS is set to NO. */
32 Throw an ErrorException. Requires the build option MFEM_USE_EXCEPTIONS=YES
33 in which case it is also the default error action. */
34};
35
36/// Set the action MFEM takes when an error is encountered.
37void set_error_action(ErrorAction action);
38/// Get the action MFEM takes when an error is encountered.
40
41#ifdef MFEM_USE_EXCEPTIONS
42/** @brief Exception class thrown when MFEM encounters an error and the current
43 ErrorAction is set to MFEM_ERROR_THROW. */
44class ErrorException: public std::exception
45{
46private:
47 std::string msg;
48public:
49 explicit ErrorException(const std::string & in_msg) : msg(in_msg) { }
50 virtual ~ErrorException() throw() { }
51 virtual const char* what() const throw();
52};
53#endif
54
55void mfem_backtrace(int mode = 0, int depth = -1);
56
57/** @brief Function called when an error is encountered. Used by the macros
58 MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY. */
59#ifdef MFEM_USE_ENZYME
60__attribute__((enzyme_inactive, noreturn))
61#else
62[[noreturn]]
63#endif
64void mfem_error(const char *msg = NULL);
65
66/// Function called by the macro MFEM_WARNING.
67#ifdef MFEM_USE_ENZYME
68__attribute__((enzyme_inactive))
69#endif
70void mfem_warning(const char *msg = NULL);
71}
72
73#ifndef _MFEM_FUNC_NAME
74#ifndef _MSC_VER
75// This is nice because it shows the class and method name
76#define _MFEM_FUNC_NAME __PRETTY_FUNCTION__
77// This one is C99 standard.
78//#define _MFEM_FUNC_NAME __func__
79#else
80// for Visual Studio C++
81#define _MFEM_FUNC_NAME __FUNCSIG__
82#endif
83#endif
84
85#define MFEM_LOCATION \
86 "\n ... in function: " << _MFEM_FUNC_NAME << \
87 "\n ... in file: " << __FILE__ << ':' << __LINE__ << '\n'
88
89// Common error message and abort macro
90#define _MFEM_MESSAGE(msg, fn) \
91 { \
92 std::ostringstream mfemMsgStream; \
93 mfemMsgStream << std::setprecision(16); \
94 mfemMsgStream << std::setiosflags(std::ios_base::scientific); \
95 mfemMsgStream << msg << MFEM_LOCATION; \
96 mfem::fn(mfemMsgStream.str().c_str()); \
97 }
98
99// Outputs lots of useful information and aborts.
100// For all of these functions, "msg" is pushed to an ostream, so you can
101// write useful (if complicated) error messages instead of writing
102// out to the screen first, then calling abort. For example:
103// MFEM_ABORT( "Unknown geometry type: " << type );
104#define MFEM_ABORT(msg) _MFEM_MESSAGE("MFEM abort: " << msg, mfem_error)
105
106// Does a check, and then outputs lots of useful information if the test fails
107#define MFEM_VERIFY(x, msg) \
108 if (!(x)) \
109 { \
110 _MFEM_MESSAGE("Verification failed: (" \
111 << #x << ") is false:\n --> " << msg, mfem_error); \
112 }
113
114// Use this if the only place your variable is used is in ASSERTs
115// For example, this code snippet:
116// int err = MPI_Reduce(ldata, maxdata, 5, MPI_INT, MPI_MAX, 0, MyComm);
117// MFEM_CONTRACT_VAR(err);
118// MFEM_ASSERT( err == 0, "MPI_Reduce gave an error with length "
119// << ldata );
120#define MFEM_CONTRACT_VAR(x) (void)(x)
121
122// Now set up some optional checks, but only if the right flags are on
123#ifdef MFEM_DEBUG
124
125#define MFEM_ASSERT(x, msg) \
126 if (!(x)) \
127 { \
128 _MFEM_MESSAGE("Assertion failed: (" \
129 << #x << ") is false:\n --> " << msg, mfem_error); \
130 }
131
132// A macro that exposes its argument in debug mode only.
133#define MFEM_DEBUG_DO(x) x
134
135#else
136
137// Get rid of all this code, since we're not checking.
138#define MFEM_ASSERT(x, msg)
139
140// A macro that exposes its argument in debug mode only.
141#define MFEM_DEBUG_DO(x)
142
143#endif
144
145// Generate a warning message - always generated, regardless of MFEM_DEBUG.
146#define MFEM_WARNING(msg) _MFEM_MESSAGE("MFEM Warning: " << msg, mfem_warning)
147
148// Macro that checks (in MFEM_DEBUG mode) that i is in the range [imin,imax).
149#define MFEM_ASSERT_INDEX_IN_RANGE(i,imin,imax) \
150 MFEM_ASSERT((imin) <= (i) && (i) < (imax), \
151 "invalid index " #i << " = " << (i) << \
152 ", valid range is [" << (imin) << ',' << (imax) << ')')
153
154
155// Additional abort functions for HIP
156#if defined(MFEM_USE_HIP)
157#ifndef __HIP_DEVICE_COMPILE__
158template<typename T>
159__host__ void abort_msg(T & msg)
160{
161 MFEM_ABORT(msg);
162}
163#else
164template<typename T>
165__device__ void abort_msg(T & msg)
166{
167 abort();
168}
169#endif
170#endif
171
172// Abort inside a device kernel
173#if defined(__CUDA_ARCH__)
174#define MFEM_ABORT_KERNEL(...) \
175 { \
176 printf(__VA_ARGS__); \
177 asm("trap;"); \
178 }
179#elif defined(MFEM_USE_HIP)
180#define MFEM_ABORT_KERNEL(...) \
181 { \
182 printf(__VA_ARGS__); \
183 abort_msg(""); \
184 }
185#else
186#define MFEM_ABORT_KERNEL(...) \
187 { \
188 printf(__VA_ARGS__); \
189 MFEM_ABORT(""); \
190 }
191#endif
192
193// Verify inside a device kernel
194#define MFEM_VERIFY_KERNEL(x,...) \
195 if (!(x)) \
196 { \
197 MFEM_ABORT_KERNEL(__VA_ARGS__) \
198 }
199
200// Assert inside a device kernel
201#ifdef MFEM_DEBUG
202#define MFEM_ASSERT_KERNEL(x,...) \
203 if (!(x)) \
204 { \
205 MFEM_ABORT_KERNEL(__VA_ARGS__) \
206 }
207#else
208#define MFEM_ASSERT_KERNEL(x,...)
209#endif
210
211#endif
Exception class thrown when MFEM encounters an error and the current ErrorAction is set to MFEM_ERROR...
Definition error.hpp:45
virtual const char * what() const
Definition error.cpp:39
virtual ~ErrorException()
Definition error.hpp:50
ErrorException(const std::string &in_msg)
Definition error.hpp:49
__host__ void abort_msg(T &msg)
Definition error.hpp:159
void mfem_error(const char *msg)
Definition error.cpp:154
void mfem_warning(const char *msg)
Definition error.cpp:187
void mfem_backtrace(int mode, int depth)
Definition error.cpp:83
void set_error_action(ErrorAction action)
Set the action MFEM takes when an error is encountered.
Definition error.cpp:49
__attribute__((enzyme_inactive, noreturn)) void mfem_error(const char *msg
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT,...
ErrorAction
Action to take when MFEM encounters an error.
Definition error.hpp:27
@ MFEM_ERROR_ABORT
Definition error.hpp:28
@ MFEM_ERROR_THROW
Definition error.hpp:31
ErrorAction get_error_action()
Get the action MFEM takes when an error is encountered.
Definition error.cpp:72