opm-common
ErrorMacros.hpp
1 /*
2  Copyright 2013 Andreas Lauser
3  Copyright 2009, 2010 SINTEF ICT, Applied Mathematics.
4  Copyright 2009, 2010 Statoil ASA.
5 
6  This file is part of the Open Porous Media project (OPM).
7 
8  OPM is free software: you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation, either version 3 of the License, or
11  (at your option) any later version.
12 
13  OPM is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with OPM. If not, see <http://www.gnu.org/licenses/>.
20 */
21 #ifndef OPM_ERRORMACROS_HPP
22 #define OPM_ERRORMACROS_HPP
23 
24 #include <opm/common/OpmLog/OpmLog.hpp>
25 #include <opm/common/utility/gpuDecorators.hpp>
26 
27 #include <string>
28 #include <exception>
29 #include <stdexcept>
30 #include <cassert>
31 
32 #if OPM_IS_COMPILING_WITH_GPU_COMPILER
33 #include <stdlib.h> // for abort()
34 #endif
35 
36 // macros for reporting to stderr
37 #ifdef OPM_VERBOSE // Verbose mode
38 # include <iostream>
39 # define OPM_REPORT do { std::cerr << "[" << __FILE__ << ":" << __LINE__ << "] " } while (false)
40 # define OPM_MESSAGE(x) do { OPM_REPORT; std::cerr << x << "\n"; } while (false)
41 # define OPM_MESSAGE_IF(cond, m) do {if(cond) OPM_MESSAGE(m);} while (false)
42 #else // non-verbose mode (default)
43 # define OPM_REPORT do {} while (false)
44 # define OPM_MESSAGE(x) do {} while (false)
45 # define OPM_MESSAGE_IF(cond, m) do {} while (false)
46 #endif
47 
48 #if OPM_IS_INSIDE_HOST_FUNCTION
49 // Macro to throw an exception that counts as an error in PRT file.
50 // NOTE: For this macro to work, the
51 // exception class must exhibit a constructor with the signature
52 // (const std::string &message). Since this condition is not fulfilled
53 // for the std::exception, you should use this macro with some
54 // exception class derived from either std::logic_error or
55 // std::runtime_error.
56 //
57 // Usage: OPM_THROW(ExceptionClass, "Error message");
58 #define OPM_THROW(Exception, message) \
59  do { \
60  std::string oss_ = std::string{"["} + __FILE__ + ":" + \
61  std::to_string(__LINE__) + "] " + \
62  message; \
63  ::Opm::OpmLog::error(oss_); \
64  throw Exception(oss_); \
65  } while (false)
66 
67 // Macro to throw an exception that only counts as a problem in PRT file.
68 // NOTE: For this macro to work, the
69 // exception class must exhibit a constructor with the signature
70 // (const std::string &message). Since this condition is not fulfilled
71 // for the std::exception, you should use this macro with some
72 // exception class derived from either std::logic_error or
73 // std::runtime_error.
74 //
75 // Usage: OPM_THROW_PROBLEM(ExceptionClass, "Error message");
76 #define OPM_THROW_PROBLEM(Exception, message) \
77  do { \
78  std::string oss_ = std::string{"["} + __FILE__ + ":" + \
79  std::to_string(__LINE__) + "] " + \
80  message; \
81  ::Opm::OpmLog::problem(oss_); \
82  throw Exception(oss_); \
83  } while (false)
84 
85 // Same as OPM_THROW, except for not making an OpmLog::error() call.
86 //
87 // Usage: OPM_THROW_NOLOG(ExceptionClass, "Error message");
88 #define OPM_THROW_NOLOG(Exception, message) \
89  do { \
90  std::string oss_ = std::string{"["} + __FILE__ + ":" + \
91  std::to_string(__LINE__) + "] " + \
92  message; \
93  throw Exception(oss_); \
94  } while (false)
95 
96 // throw an exception if a condition is true
97 #define OPM_ERROR_IF(condition, message) do {if(condition){ OPM_THROW(std::logic_error, message);}} while(false)
98 
99 #else // On GPU
100 // On the GPU, we cannot throw exceptions, so we use abort() instead.
101 // This will allow us to keep the same code for both CPU and GPU when using
102 // the macros. The abort() will only cause the CUDA kernel to terminate,
103 // but it will not throw an exception. However, it will terminate the execution of the
104 // program, at least on ROCm.
105 //
106 // Notice however, that once we abort() in a CUDA kernel, the CUDA context
107 // is broken for the rest of the process, see
108 // https://forums.developer.nvidia.com/t/how-to-clear-cuda-errors/296393/5
109 
113 #define OPM_THROW(Exception, message) \
114  abort()
115 
119 #define OPM_THROW_PROBLEM(Exception, message) \
120  abort()
121 
125 #define OPM_THROW_NOLOG(Exception, message) \
126  abort()
127 
131 #define OPM_ERROR_IF(condition, message) \
132  do {if(condition){abort();}} while(false)
133 #endif // GPU
134 #endif // OPM_ERRORMACROS_HPP