DeferredLoggingErrorHelpers.hpp
Go to the documentation of this file.
1/*
2 Copyright 2019 SINTEF Digital, Mathematics and Cybernetics.
3
4 This file is part of the Open Porous Media project (OPM).
5
6 OPM is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 OPM is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with OPM. If not, see <http://www.gnu.org/licenses/>.
18
19*/
20
21#ifndef OPM_DEFERREDLOGGINGERRORHELPERS_HPP
22#define OPM_DEFERREDLOGGINGERRORHELPERS_HPP
23
24#include <dune/istl/istlexception.hh>
25
26#include <opm/common/Exceptions.hpp>
27
30
32
33#include <string>
34#include <exception>
35#include <stdexcept>
36
37// Macro to log an error and throw an exception.
38// Inspired by ErrorMacros.hpp in opm-common.
39// NOTE: For this macro to work, the
40// exception class must exhibit a constructor with the signature
41// (const std::string &message). Since this condition is not fulfilled
42// for the std::exception, you should use this macro with some
43// exception class derived from either std::logic_error or
44// std::runtime_error.
45//
46// Usage: OPM_DEFLOG_THROW(ExceptionClass, "Error message", DeferredLogger);
47#define OPM_DEFLOG_THROW(Exception, message, deferred_logger) \
48 do { \
49 std::string oss_ = std::string{"["} + __FILE__ + ":" + \
50 std::to_string(__LINE__) + "] " + \
51 message; \
52 deferred_logger.error(oss_); \
53 throw Exception(oss_); \
54 } while (false)
55
56// Macro to log a problem and throw an exception.
57// Idenitical to OPM_DEFLOG_THROW() except for using
58// the "problem" category instead of "error" for the
59// log message. The Exception argument will typically
60// be NumericalProblem.
61//
62// Usage: OPM_DEFLOG_PROBLEM(ExceptionClass, "Error message", DeferredLogger);
63#define OPM_DEFLOG_PROBLEM(Exception, message, deferred_logger) \
64 do { \
65 std::string oss_ = std::string{"["} + __FILE__ + ":" + \
66 std::to_string(__LINE__) + "] " + \
67 message; \
68 deferred_logger.problem(oss_); \
69 throw Exception(oss_); \
70 } while (false)
71
72
73namespace {
74
75void _throw(Opm::ExceptionType::ExcEnum exc_type,
76 const std::string& message,
78{
79 auto global_exc = comm.max(exc_type);
80
81 switch (global_exc) {
83 break;
85 throw std::runtime_error(message);
86 break;
88 throw std::invalid_argument(message);
89 break;
91 throw Opm::NumericalProblem(message);
92 break;
95 throw std::logic_error(message);
96 break;
97 default:
98 throw std::logic_error(message);
99 }
100}
101
102} // anonymous namespace
103
104
105
107 const std::string& message,
109{
110 _throw(exc_type, message, comm);
111}
112
115 const std::string& message,
116 const bool terminal_output,
118{
119 // add exception message to logger in order to display message from all ranks
120 if (exc_type != Opm::ExceptionType::NONE && comm.size() > 1) {
121 deferred_logger.error("[Exception on rank " + std::to_string(comm.rank()) + "]: " + message);
122 }
123 Opm::DeferredLogger global_deferredLogger = gatherDeferredLogger(deferred_logger, comm);
124
125 if (terminal_output) {
126 global_deferredLogger.logMessages();
127 }
128 // Now that all messages have been logged, they are automatically
129 // cleared from the global logger, but we must also clear them
130 // from the local logger.
131 deferred_logger.clearMessages();
132 _throw(exc_type, message, comm);
133}
134
137 const std::string& message,
138 const bool terminal_output,
140{
141 // add exception message to logger in order to display message from all ranks
142 if (exc_type != Opm::ExceptionType::NONE && comm.size() > 1) {
143 deferred_logger.problem("[Exception on rank " + std::to_string(comm.rank()) + "]: " + message);
144 }
145 Opm::DeferredLogger global_deferredLogger = gatherDeferredLogger(deferred_logger, comm);
146
147 if (terminal_output) {
148 global_deferredLogger.logMessages();
149 }
150 // Now that all messages have been logged, they are automatically
151 // cleared from the global logger, but we must also clear them
152 // from the local logger.
153 deferred_logger.clearMessages();
154 _throw(exc_type, message, comm);
155}
160#define OPM_BEGIN_PARALLEL_TRY_CATCH() \
161std::string obptc_exc_msg; \
162auto obptc_exc_type = Opm::ExceptionType::NONE; \
163try {
164
168#define OPM_PARALLEL_CATCH_CLAUSE(obptc_exc_type, \
169 obptc_exc_msg) \
170catch (const Opm::NumericalProblem& e){ \
171 obptc_exc_type = Opm::ExceptionType::NUMERICAL_ISSUE; \
172 obptc_exc_msg = e.what(); \
173} catch (const Dune::MatrixBlockError& e) { \
174 obptc_exc_type = Opm::ExceptionType::NUMERICAL_ISSUE; \
175 obptc_exc_msg = e.what(); \
176} catch (const std::runtime_error& e) { \
177 obptc_exc_type = Opm::ExceptionType::RUNTIME_ERROR; \
178 obptc_exc_msg = e.what(); \
179} catch (const std::invalid_argument& e) { \
180 obptc_exc_type = Opm::ExceptionType::INVALID_ARGUMENT; \
181 obptc_exc_msg = e.what(); \
182} catch (const std::logic_error& e) { \
183 obptc_exc_type = Opm::ExceptionType::LOGIC_ERROR; \
184 obptc_exc_msg = e.what(); \
185} catch (const std::exception& e) { \
186 obptc_exc_type = Opm::ExceptionType::DEFAULT; \
187 obptc_exc_msg = e.what(); \
188} catch (...) { \
189 obptc_exc_type = Opm::ExceptionType::DEFAULT; \
190 obptc_exc_msg = "Unknown exception was thrown"; \
191}
192
197#define OPM_END_PARALLEL_TRY_CATCH(prefix, comm) \
198} \
199OPM_PARALLEL_CATCH_CLAUSE(obptc_exc_type, obptc_exc_msg);\
200checkForExceptionsAndThrow(obptc_exc_type, \
201 prefix + obptc_exc_msg, comm);
202
207#define OPM_END_PARALLEL_TRY_CATCH_LOG(obptc_logger, obptc_prefix, obptc_output, comm)\
208} \
209OPM_PARALLEL_CATCH_CLAUSE(obptc_exc_type, obptc_exc_msg); \
210logAndCheckForExceptionsAndThrow(obptc_logger, obptc_exc_type, \
211 obptc_prefix + obptc_exc_msg, obptc_output, comm);
212#endif // OPM_DEFERREDLOGGINGERRORHELPERS_HPP
void logAndCheckForProblemsAndThrow(Opm::DeferredLogger &deferred_logger, Opm::ExceptionType::ExcEnum exc_type, const std::string &message, const bool terminal_output, Opm::Parallel::Communication comm)
Definition: DeferredLoggingErrorHelpers.hpp:135
void logAndCheckForExceptionsAndThrow(Opm::DeferredLogger &deferred_logger, Opm::ExceptionType::ExcEnum exc_type, const std::string &message, const bool terminal_output, Opm::Parallel::Communication comm)
Definition: DeferredLoggingErrorHelpers.hpp:113
void checkForExceptionsAndThrow(Opm::ExceptionType::ExcEnum exc_type, const std::string &message, Opm::Parallel::Communication comm)
Definition: DeferredLoggingErrorHelpers.hpp:106
Definition: DeferredLogger.hpp:57
void problem(const std::string &tag, const std::string &message)
void clearMessages()
Clear the message container without logging them.
void error(const std::string &tag, const std::string &message)
ExcEnum
Definition: DeferredLogger.hpp:45
@ NONE
Definition: DeferredLogger.hpp:46
@ INVALID_ARGUMENT
Definition: DeferredLogger.hpp:48
@ RUNTIME_ERROR
Definition: DeferredLogger.hpp:47
@ LOGIC_ERROR
Definition: DeferredLogger.hpp:49
@ DEFAULT
Definition: DeferredLogger.hpp:50
@ NUMERICAL_ISSUE
Definition: DeferredLogger.hpp:51
Dune::Communication< MPIComm > Communication
Definition: ParallelCommunication.hpp:30
Opm::DeferredLogger gatherDeferredLogger(const Opm::DeferredLogger &local_deferredlogger, Parallel::Communication communicator)
Create a global log combining local logs.
std::string to_string(const ConvergenceReport::ReservoirFailure::Type t)