2019-02-07 07:43:17 -06:00
|
|
|
/*
|
|
|
|
Copyright 2019 SINTEF Digital, Mathematics and Cybernetics.
|
|
|
|
|
|
|
|
This file is part of the Open Porous Media project (OPM).
|
|
|
|
|
|
|
|
OPM is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
OPM is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with OPM. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef OPM_DEFERREDLOGGINGERRORHELPERS_HPP
|
|
|
|
#define OPM_DEFERREDLOGGINGERRORHELPERS_HPP
|
|
|
|
|
2022-12-13 05:54:27 -06:00
|
|
|
#include <opm/common/Exceptions.hpp>
|
|
|
|
|
2019-05-07 06:06:02 -05:00
|
|
|
#include <opm/simulators/utils/DeferredLogger.hpp>
|
2021-05-25 05:57:11 -05:00
|
|
|
#include <opm/simulators/utils/gatherDeferredLogger.hpp>
|
2019-02-07 07:43:17 -06:00
|
|
|
|
2021-10-05 01:25:54 -05:00
|
|
|
#include <opm/simulators/utils/ParallelCommunication.hpp>
|
2019-02-07 07:43:17 -06:00
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <exception>
|
|
|
|
#include <stdexcept>
|
|
|
|
|
|
|
|
// Macro to throw an exception.
|
|
|
|
// Inspired by ErrorMacros.hpp in opm-common.
|
|
|
|
// NOTE: For this macro to work, the
|
|
|
|
// exception class must exhibit a constructor with the signature
|
|
|
|
// (const std::string &message). Since this condition is not fulfilled
|
|
|
|
// for the std::exception, you should use this macro with some
|
|
|
|
// exception class derived from either std::logic_error or
|
|
|
|
// std::runtime_error.
|
|
|
|
//
|
2022-12-20 05:50:28 -06:00
|
|
|
// Usage: OPM_DEFLOG_THROW(ExceptionClass, "Error message", DeferredLogger);
|
2023-01-03 09:34:49 -06:00
|
|
|
#define OPM_DEFLOG_THROW(Exception, message, deferred_logger) \
|
|
|
|
do { \
|
|
|
|
std::string oss_ = std::string{"["} + __FILE__ + ":" + \
|
|
|
|
std::to_string(__LINE__) + "] " + \
|
|
|
|
message; \
|
|
|
|
deferred_logger.error(oss_); \
|
|
|
|
throw Exception(oss_); \
|
2019-02-07 07:43:17 -06:00
|
|
|
} while (false)
|
|
|
|
|
2021-03-18 02:29:23 -05:00
|
|
|
namespace {
|
|
|
|
|
2021-05-25 05:57:11 -05:00
|
|
|
void _throw(Opm::ExceptionType::ExcEnum exc_type,
|
|
|
|
const std::string& message,
|
|
|
|
Opm::Parallel::Communication comm)
|
|
|
|
{
|
|
|
|
auto global_exc = comm.max(exc_type);
|
2021-03-18 02:29:23 -05:00
|
|
|
|
|
|
|
switch (global_exc) {
|
|
|
|
case Opm::ExceptionType::NONE:
|
|
|
|
break;
|
|
|
|
case Opm::ExceptionType::RUNTIME_ERROR:
|
2019-05-22 03:08:55 -05:00
|
|
|
throw std::runtime_error(message);
|
2021-03-18 02:29:23 -05:00
|
|
|
break;
|
|
|
|
case Opm::ExceptionType::INVALID_ARGUMENT:
|
|
|
|
throw std::invalid_argument(message);
|
|
|
|
break;
|
2021-09-15 13:06:26 -05:00
|
|
|
case Opm::ExceptionType::NUMERICAL_ISSUE:
|
2022-12-13 05:54:27 -06:00
|
|
|
throw Opm::NumericalProblem(message);
|
2021-09-15 13:06:26 -05:00
|
|
|
break;
|
2021-03-18 02:29:23 -05:00
|
|
|
case Opm::ExceptionType::DEFAULT:
|
|
|
|
case Opm::ExceptionType::LOGIC_ERROR:
|
|
|
|
throw std::logic_error(message);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
throw std::logic_error(message);
|
2019-02-07 07:43:17 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-25 05:57:11 -05:00
|
|
|
} // anonymous namespace
|
2021-03-18 02:29:23 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
2021-05-25 05:57:11 -05:00
|
|
|
inline void checkForExceptionsAndThrow(Opm::ExceptionType::ExcEnum exc_type,
|
|
|
|
const std::string& message,
|
|
|
|
Opm::Parallel::Communication comm)
|
2021-03-18 02:29:23 -05:00
|
|
|
{
|
2021-05-25 05:57:11 -05:00
|
|
|
_throw(exc_type, message, comm);
|
2021-03-18 02:29:23 -05:00
|
|
|
}
|
|
|
|
|
2021-05-25 05:57:11 -05:00
|
|
|
inline void logAndCheckForExceptionsAndThrow(Opm::DeferredLogger& deferred_logger,
|
|
|
|
Opm::ExceptionType::ExcEnum exc_type,
|
|
|
|
const std::string& message,
|
|
|
|
const bool terminal_output,
|
|
|
|
Opm::Parallel::Communication comm)
|
2019-02-07 07:43:17 -06:00
|
|
|
{
|
2021-05-25 05:57:11 -05:00
|
|
|
Opm::DeferredLogger global_deferredLogger = gatherDeferredLogger(deferred_logger, comm);
|
|
|
|
|
2019-02-07 07:43:17 -06:00
|
|
|
if (terminal_output) {
|
|
|
|
global_deferredLogger.logMessages();
|
|
|
|
}
|
2019-04-30 05:24:31 -05:00
|
|
|
// Now that all messages have been logged, they are automatically
|
|
|
|
// cleared from the global logger, but we must also clear them
|
|
|
|
// from the local logger.
|
|
|
|
deferred_logger.clearMessages();
|
2021-05-25 05:57:11 -05:00
|
|
|
_throw(exc_type, message, comm);
|
2019-02-07 07:43:17 -06:00
|
|
|
}
|
|
|
|
|
2021-09-20 03:56:11 -05:00
|
|
|
|
|
|
|
/// \brief Macro to setup the try of a parallel try-catch
|
|
|
|
///
|
|
|
|
/// Use OPM_END_PARALLEL_TRY_CATCH or OPM_END_PARALLEL_TRY_CATCH_LOG
|
|
|
|
/// fot the catch part.
|
|
|
|
#define OPM_BEGIN_PARALLEL_TRY_CATCH() \
|
|
|
|
std::string obptc_exc_msg; \
|
|
|
|
auto obptc_exc_type = Opm::ExceptionType::NONE; \
|
|
|
|
try {
|
|
|
|
|
|
|
|
/// \brief Inserts catch classes for the parallel try-catch
|
|
|
|
///
|
|
|
|
/// There is a clause that will catch anything
|
|
|
|
#define OPM_PARALLEL_CATCH_CLAUSE(obptc_exc_type, \
|
|
|
|
obptc_exc_msg) \
|
2022-12-13 05:54:27 -06:00
|
|
|
catch (const Opm::NumericalProblem& e){ \
|
2021-09-20 03:56:11 -05:00
|
|
|
obptc_exc_type = Opm::ExceptionType::NUMERICAL_ISSUE; \
|
|
|
|
obptc_exc_msg = e.what(); \
|
|
|
|
} catch (const std::runtime_error& e) { \
|
|
|
|
obptc_exc_type = Opm::ExceptionType::RUNTIME_ERROR; \
|
|
|
|
obptc_exc_msg = e.what(); \
|
|
|
|
} catch (const std::invalid_argument& e) { \
|
|
|
|
obptc_exc_type = Opm::ExceptionType::INVALID_ARGUMENT; \
|
|
|
|
obptc_exc_msg = e.what(); \
|
|
|
|
} catch (const std::logic_error& e) { \
|
|
|
|
obptc_exc_type = Opm::ExceptionType::LOGIC_ERROR; \
|
|
|
|
obptc_exc_msg = e.what(); \
|
|
|
|
} catch (const std::exception& e) { \
|
|
|
|
obptc_exc_type = Opm::ExceptionType::DEFAULT; \
|
|
|
|
obptc_exc_msg = e.what(); \
|
|
|
|
} catch (...) { \
|
|
|
|
obptc_exc_type = Opm::ExceptionType::DEFAULT; \
|
|
|
|
obptc_exc_msg = "Unknown exception was thrown"; \
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Catch exception and throw in a parallel try-catch clause
|
|
|
|
///
|
|
|
|
/// Assumes that OPM_BEGIN_PARALLEL_TRY_CATCH() was called to initiate
|
|
|
|
/// the try-catch clause
|
2021-05-25 05:57:11 -05:00
|
|
|
#define OPM_END_PARALLEL_TRY_CATCH(prefix, comm) \
|
2021-09-20 03:56:11 -05:00
|
|
|
} \
|
|
|
|
OPM_PARALLEL_CATCH_CLAUSE(obptc_exc_type, obptc_exc_msg);\
|
|
|
|
checkForExceptionsAndThrow(obptc_exc_type, \
|
2021-05-25 05:57:11 -05:00
|
|
|
prefix + obptc_exc_msg, comm);
|
2021-09-20 03:56:11 -05:00
|
|
|
|
|
|
|
/// \brief Catch exception, log, and throw in a parallel try-catch clause
|
|
|
|
///
|
|
|
|
/// Assumes that OPM_BEGIN_PARALLEL_TRY_CATCH() was called to initiate
|
|
|
|
/// the try-catch clause
|
2021-05-25 05:57:11 -05:00
|
|
|
#define OPM_END_PARALLEL_TRY_CATCH_LOG(obptc_logger, obptc_prefix, obptc_output, comm)\
|
2021-09-20 03:56:11 -05:00
|
|
|
} \
|
|
|
|
OPM_PARALLEL_CATCH_CLAUSE(obptc_exc_type, obptc_exc_msg); \
|
|
|
|
logAndCheckForExceptionsAndThrow(obptc_logger, obptc_exc_type, \
|
2021-05-25 05:57:11 -05:00
|
|
|
obptc_prefix + obptc_exc_msg, obptc_output, comm);
|
2019-02-07 07:43:17 -06:00
|
|
|
#endif // OPM_DEFERREDLOGGINGERRORHELPERS_HPP
|