diff --git a/src/coreComponents/codingUtilities/Parsing.hpp b/src/coreComponents/codingUtilities/Parsing.hpp index 3badd24f056..7acd766cfb5 100644 --- a/src/coreComponents/codingUtilities/Parsing.hpp +++ b/src/coreComponents/codingUtilities/Parsing.hpp @@ -91,7 +91,7 @@ char const * parseBuffer( char const * first, * @param issep function that returns true if given character is a value separator * @return @p last if the entire buffer has been processed, or pointer to * the start of the unprocessed part if a parsing error occurred - * @throws std::runtime_error if file IO or parsing error occurred + * @throws geos::RuntimeError if file IO or parsing error occurred */ template< typename CONTAINER, typename SEPFUNC > void parseFile( string const & filename, @@ -134,13 +134,13 @@ void parseFile( string const & filename, GEOS_THROW( GEOS_FMT( "Unable to parse value in file {} at position {}: {}...", filename, static_cast< std::streamoff >( inputStream.tellg() ) - left, string( ptr, std::min( left, std::ptrdiff_t{32} ) ) ), - std::runtime_error ); + geos::RuntimeError ); } } GEOS_THROW_IF( inputStream.fail() && !inputStream.eof(), GEOS_FMT( "Error while reading file {}: {}", filename, std::strerror( errno ) ), - std::runtime_error ); + geos::RuntimeError ); } } // namespace geos diff --git a/src/coreComponents/codingUtilities/tests/testParsing.cpp b/src/coreComponents/codingUtilities/tests/testParsing.cpp index 6d9e7b3ae04..e045979730a 100644 --- a/src/coreComponents/codingUtilities/tests/testParsing.cpp +++ b/src/coreComponents/codingUtilities/tests/testParsing.cpp @@ -140,7 +140,7 @@ class ParsingTest : public ::testing::TestWithParam< T > geos::stdVector< T > vec; auto const issep_invalid = []( char const c ){ return c == '|'; }; - EXPECT_THROW( geos::parseFile( fname, vec, issep_invalid ), std::runtime_error ); + EXPECT_THROW( geos::parseFile( fname, vec, issep_invalid ), geos::RuntimeError ); std::remove( fname.c_str() ); } diff --git a/src/coreComponents/common/CMakeLists.txt b/src/coreComponents/common/CMakeLists.txt index 2b094d68ad2..38d684c29bd 100644 --- a/src/coreComponents/common/CMakeLists.txt +++ b/src/coreComponents/common/CMakeLists.txt @@ -38,6 +38,7 @@ set( common_headers GEOS_RAJA_Interface.hpp GeosxMacros.hpp MemoryInfos.hpp + logger/GeosExceptions.hpp logger/Logger.hpp logger/ErrorHandling.hpp logger/ExternalErrorHandler.hpp diff --git a/src/coreComponents/common/Path.cpp b/src/coreComponents/common/Path.cpp index b376b1580b2..11ac6e3d679 100644 --- a/src/coreComponents/common/Path.cpp +++ b/src/coreComponents/common/Path.cpp @@ -140,7 +140,7 @@ void makeDirectory( std::string const & path ) { constexpr mode_t mode = 0770; // user and group rwx permissions int const err = mkdir( path.c_str(), mode ); - GEOS_THROW_IF( err && ( errno != EEXIST ), "Failed to create directory: " << path, std::runtime_error ); + GEOS_THROW_IF( err && ( errno != EEXIST ), "Failed to create directory: " << path, geos::RuntimeError ); } void makeDirsForPath( std::string const & path ) diff --git a/src/coreComponents/common/format/table/TableLayout.hpp b/src/coreComponents/common/format/table/TableLayout.hpp index b166f65b198..4ef156ad760 100644 --- a/src/coreComponents/common/format/table/TableLayout.hpp +++ b/src/coreComponents/common/format/table/TableLayout.hpp @@ -20,10 +20,8 @@ #ifndef GEOS_COMMON_FORMAT_TABLE_TABLELAYOUT_HPP #define GEOS_COMMON_FORMAT_TABLE_TABLELAYOUT_HPP -#include "common/DataTypes.hpp" #include "TableTypes.hpp" #include -#include "common/logger/Logger.hpp" namespace geos diff --git a/src/coreComponents/common/format/table/TableTypes.hpp b/src/coreComponents/common/format/table/TableTypes.hpp index 4565ad92ff8..59826ddde6a 100644 --- a/src/coreComponents/common/format/table/TableTypes.hpp +++ b/src/coreComponents/common/format/table/TableTypes.hpp @@ -23,6 +23,8 @@ #ifndef GEOS_COMMON_FORMAT_TABLETYPES_HPP #define GEOS_COMMON_FORMAT_TABLETYPES_HPP +#include "common/DataTypes.hpp" + namespace geos { diff --git a/src/coreComponents/common/initializeEnvironment.cpp b/src/coreComponents/common/initializeEnvironment.cpp index 6eeae2eaee3..96238758318 100644 --- a/src/coreComponents/common/initializeEnvironment.cpp +++ b/src/coreComponents/common/initializeEnvironment.cpp @@ -70,7 +70,6 @@ void setupLogger() #endif { // setup error handling (using LvArray helper system functions) - using ErrorContext = ErrorLogger::ErrorContext; ///// set Post-Handled Error behaviour ///// LvArray::system::setErrorHandler( []() @@ -102,22 +101,16 @@ void setupLogger() std::string const stackHistory = LvArray::system::stackTrace( true ); - GEOS_LOG( GEOS_FMT( "***** ERROR\n" - "***** LOCATION: (external error, detected {})\n" - "{}\n{}", - detectionLocation, errorMsg, stackHistory ) ); - if( ErrorLogger::global().isOutputFileEnabled() ) - { - ErrorLogger::ErrorMsg error; - error.setType( ErrorLogger::MsgType::Error ); - error.addToMsg( errorMsg ); - error.addRank( ::geos::logger::internal::g_rank ); - error.addCallStackInfo( stackHistory ); - error.addContextInfo( - ErrorContext{ { { ErrorContext::Attribute::DetectionLoc, string( detectionLocation ) } } } ); - - ErrorLogger::global().flushErrorMsg( error ); - } + ErrorLogger::global().flushErrorMsg( DiagnosticMsgBuilder::init() + .setType( MsgType::Error ) + .addToMsg( errorMsg ) + .addRank( ::geos::logger::internal::g_rank ) + .addCallStackInfo( stackHistory ) + .addContextInfo( + ErrorContext{ string( detectionLocation ), + { { ErrorContext::Attribute::DetectionLoc, + string( detectionLocation ) } }, + } ).get() ); // we do not terminate the program as 1. the error could be non-fatal, 2. there may be more messages to output. } ); @@ -134,26 +127,17 @@ void setupLogger() // error message output std::string const stackHistory = LvArray::system::stackTrace( true ); - ErrorLogger::ErrorMsg error; - error.addSignalToMsg( signal ); - - GEOS_LOG( GEOS_FMT( "***** ERROR\n" - "***** SIGNAL: {}\n" - "***** LOCATION: (external error, captured by signal handler)\n" - "{}\n{}", - signal, error.m_msg, stackHistory ) ); - if( ErrorLogger::global().isOutputFileEnabled() ) - { - error.setType( ErrorLogger::MsgType::Error ); - error.addRank( ::geos::logger::internal::g_rank ); - error.addCallStackInfo( stackHistory ); - error.addContextInfo( - ErrorContext{ { { ErrorContext::Attribute::Signal, std::to_string( signal ) } }, 1 }, - ErrorContext{ { { ErrorContext::Attribute::DetectionLoc, string( "signal handler" ) } }, 0 } ); - - ErrorLogger::global().flushErrorMsg( error ); - } + ErrorLogger::global().flushErrorMsg( DiagnosticMsgBuilder::init() + .addSignalToMsg( signal ) + .setType( MsgType::Error ) + .addRank( ::geos::logger::internal::g_rank ) + .addCallStackInfo( stackHistory ) + .addContextInfo( + ErrorContext{ { { ErrorContext::Attribute::Signal, + std::to_string( signal ) } }, 1 }, + ErrorContext{ { { ErrorContext::Attribute::DetectionLoc, + string( "signal handler" ) } }, 0 } ).get() ); // call program termination LvArray::system::callErrorHandler(); diff --git a/src/coreComponents/common/logger/ErrorHandling.cpp b/src/coreComponents/common/logger/ErrorHandling.cpp index 5bec5c6754c..514d6aab5e1 100644 --- a/src/coreComponents/common/logger/ErrorHandling.cpp +++ b/src/coreComponents/common/logger/ErrorHandling.cpp @@ -44,68 +44,61 @@ ErrorLogger g_errorLogger{}; ErrorLogger & ErrorLogger::global() { return g_errorLogger; } -void ErrorLogger::createFile() -{ - if( stringutilities::endsWith( m_filename, ".yaml" ) ) - { - std::ofstream yamlFile( std::string( m_filename ), std::ios::out ); - if( yamlFile.is_open() ) - { - yamlFile << "errors: \n\n"; - yamlFile.close(); - } - else - { - GEOS_LOG_RANK( GEOS_FMT( "Unable to open error file for writing: {}", m_filename ) ); - } - } - else - { - enableFileOutput( false ); - GEOS_LOG_RANK( GEOS_FMT( "{} is a bad file name argument. The file must be in yaml format.", m_filename ) ); - } -} -std::string ErrorLogger::ErrorContext::attributeToString( ErrorLogger::ErrorContext::Attribute attribute ) +std::string ErrorContext::attributeToString( ErrorContext::Attribute attribute ) { switch( attribute ) { - case ErrorLogger::ErrorContext::Attribute::InputFile: return "inputFile"; - case ErrorLogger::ErrorContext::Attribute::InputLine: return "inputLine"; - case ErrorLogger::ErrorContext::Attribute::DataPath: return "dataPath"; - case ErrorLogger::ErrorContext::Attribute::DetectionLoc: return "detectionLocation"; - case ErrorLogger::ErrorContext::Attribute::Signal: return "signal"; + case ErrorContext::Attribute::InputFile: return "inputFile"; + case ErrorContext::Attribute::InputLine: return "inputLine"; + case ErrorContext::Attribute::DataPath: return "dataPath"; + case ErrorContext::Attribute::DetectionLoc: return "detectionLocation"; + case ErrorContext::Attribute::Signal: return "signal"; default: return "unknown"; } } -ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addToMsg( std::exception const & e, bool toEnd ) +DiagnosticMsgBuilder DiagnosticMsgBuilder::modify( DiagnosticMsg & errorMsg ) +{ + DiagnosticMsgBuilder builder; + builder.m_errorMsg = errorMsg; + builder.m_targetErrorMsg = &errorMsg; + return builder; +} + +DiagnosticMsgBuilder & DiagnosticMsgBuilder::addContextInfoImpl( ErrorContext && ctxInfo ) +{ + m_errorMsg.m_contextsInfo.emplace_back( std::move( ctxInfo ) ); + return *this; +} + + +DiagnosticMsgBuilder & DiagnosticMsgBuilder::addToMsg( std::exception const & e, bool const toEnd ) { if( toEnd ) { - m_msg = m_msg + e.what(); + m_errorMsg.m_msg = m_errorMsg.m_msg + e.what(); } else { - m_msg = e.what() + m_msg; + m_errorMsg.m_msg = e.what() + m_errorMsg.m_msg; } return *this; } - -ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addToMsg( std::string_view errorMsg, bool toEnd ) +DiagnosticMsgBuilder & DiagnosticMsgBuilder::addToMsg( std::string_view errorMsg, bool toEnd ) { if( toEnd ) { - m_msg = m_msg + std::string( errorMsg ); + m_errorMsg.m_msg = m_errorMsg.m_msg + std::string( errorMsg ); } else { - m_msg = std::string( errorMsg ) + m_msg; + m_errorMsg.m_msg = std::string( errorMsg ) + m_errorMsg.m_msg; } return *this; } -ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addSignalToMsg( int sig, bool toEnd ) +DiagnosticMsgBuilder & DiagnosticMsgBuilder::addSignalToMsg( integer const sig, bool const toEnd ) { if( sig == SIGFPE ) { @@ -114,9 +107,6 @@ ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addSignalToMsg( int sig, bool toE if( std::fetestexcept( FE_DIVBYZERO ) ) errorMsg += "- Division by zero operation.\n"; - if( std::fetestexcept( FE_INEXACT ) ) - errorMsg += "- Inexact result.\n"; - if( std::fetestexcept( FE_INVALID ) ) errorMsg += "- Domain error occurred in an earlier floating-point operation.\n"; @@ -126,6 +116,9 @@ ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addSignalToMsg( int sig, bool toE if( std::fetestexcept( FE_UNDERFLOW ) ) errorMsg += "- The result of the earlier floating-point operation was subnormal with a loss of precision.\n"; + if( std::fetestexcept( FE_INEXACT ) ) + errorMsg += "- Inexact result.\n"; + return addToMsg( errorMsg, toEnd ); } @@ -136,39 +129,36 @@ ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addSignalToMsg( int sig, bool toE sig, ::strsignal( sig ) ), toEnd ); } -} - -ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::setCodeLocation( std::string_view msgFile, integer msgLine ) -{ - m_file = msgFile; - m_line = msgLine; return *this; } -ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::setType( ErrorLogger::MsgType msgType ) +DiagnosticMsgBuilder & DiagnosticMsgBuilder::setCodeLocation( std::string_view msgFile, + integer const msgLine ) { - m_type = msgType; + m_errorMsg.m_file = msgFile; + m_errorMsg.m_line = msgLine; return *this; } -ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::setCause( std::string_view cause ) +DiagnosticMsgBuilder & DiagnosticMsgBuilder::setType( MsgType const msgType ) { - m_cause = cause; + m_errorMsg.m_type = msgType; return *this; } -void ErrorLogger::ErrorMsg::addContextInfoImpl( ErrorLogger::ErrorContext && ctxInfo ) +DiagnosticMsgBuilder & DiagnosticMsgBuilder::setCause( std::string_view cause ) { - m_contextsInfo.emplace_back( std::move( ctxInfo ) ); + m_errorMsg.m_cause = cause; + return *this; } -ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addRank( int rank ) +DiagnosticMsgBuilder & DiagnosticMsgBuilder::addRank( integer const rank ) { - m_ranksInfo.emplace( rank ); + m_errorMsg.m_ranksInfo.emplace( rank ); return *this; } -ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addCallStackInfo( std::string_view ossStackTrace ) +DiagnosticMsgBuilder & DiagnosticMsgBuilder::addCallStackInfo( std::string_view ossStackTrace ) { std::string str = std::string( ossStackTrace ); std::istringstream iss( str ); @@ -181,29 +171,27 @@ ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addCallStackInfo( std::string_vie { if( std::regex_search( stackLine, pattern )) { - m_isValidStackTrace = true; + m_errorMsg.m_isValidStackTrace = true; index = stackLine.find( ':' ); - m_sourceCallStack.push_back( stackLine.substr( index + 1 ) ); + m_errorMsg.m_sourceCallStack.push_back( stackLine.substr( index + 1 ) ); } } - if( !m_isValidStackTrace ) + if( !m_errorMsg.m_isValidStackTrace ) { - m_sourceCallStack.push_back( str ); + m_errorMsg.m_sourceCallStack.push_back( str ); } return *this; } -std::string ErrorLogger::toString( ErrorLogger::MsgType type ) +DiagnosticMsg & DiagnosticMsgBuilder::get() { - switch( type ) + if( m_targetErrorMsg != nullptr ) { - case ErrorLogger::MsgType::Error: return "Error"; - case ErrorLogger::MsgType::Warning: return "Warning"; - case ErrorLogger::MsgType::Exception: return "Exception"; - default: return "Unknown"; + *m_targetErrorMsg = m_errorMsg; } + return m_errorMsg; } void ErrorLogger::streamMultilineYamlAttribute( std::string_view msg, std::ofstream & yamlFile, @@ -228,33 +216,126 @@ void ErrorLogger::streamMultilineYamlAttribute( std::string_view msg, std::ofstr } } -void ErrorLogger::flushErrorMsg( ErrorLogger::ErrorMsg & errorMsg ) +void ErrorLogger::createFile() +{ + if( stringutilities::endsWith( m_filename, ".yaml" ) ) + { + std::ofstream yamlFile( std::string( m_filename ), std::ios::out ); + if( yamlFile.is_open() ) + { + yamlFile << "errors: \n\n"; + yamlFile.close(); + } + else + { + GEOS_LOG_RANK( GEOS_FMT( "Unable to open error file for writing: {}", m_filename ) ); + } + } + else + { + enableFileOutput( false ); + GEOS_LOG_RANK( GEOS_FMT( "{} is a bad file name argument. The file must be in yaml format.", m_filename ) ); + } +} + +std::string ErrorLogger::toString( MsgType const type ) +{ + switch( type ) + { + case MsgType::Error: return "Error"; + case MsgType::Warning: return "Warning"; + case MsgType::Exception: return "Exception"; + default: return "Unknown"; + } +} + +/** + * @brief Retrieve all informations from the ErrorMsg and format and write into a stream. + * @param errMsg Class containing all the error/warning information + * @param oss The output stream to write the content to. + */ +void ErrorLogger::writeToAscii( DiagnosticMsg const & errMsg, std::ostream & oss ) +{ + static constexpr string_view PREFIX = "***** "; + // --- HEADER --- + oss << PREFIX << ErrorLogger::toString( errMsg.m_type ) << "\n"; + if( !errMsg.m_file.empty()) + { + oss << PREFIX<< "LOCATION: " << errMsg.m_file; + if( errMsg.m_line > 0 ) + { + oss << ":" << errMsg.m_line; + } + oss << "\n"; + } + if( !errMsg.m_cause.empty()) + { + oss << PREFIX << errMsg.m_cause << "\n"; + } + oss << PREFIX << "Rank " << stringutilities::join( errMsg.m_ranksInfo, ", " ) << "\n"; + // --- ERROR CONTEXT & MESSAGE --- + std::vector< ErrorContext > const & contexts = errMsg.m_contextsInfo; + if( contexts.empty()) + { + oss << PREFIX << "Message :\n"; + } + else + { + oss << PREFIX << "Message from " << contexts.front().m_formattedContext << ":\n"; + } + oss << errMsg.m_msg << "\n"; + + if( contexts.size() > 1 ) + { + oss << PREFIX << "Additional contexts:\n"; + for( size_t i = 1; i < contexts.size(); ++i ) + { + oss << PREFIX << "- " << contexts[i].m_formattedContext << "\n"; + } + } + // --- STACKTRACE --- + if( !errMsg.m_sourceCallStack.empty() ) + { + oss << "\n** StackTrace of "<< errMsg.m_sourceCallStack.size() << " frames **\n"; + for( size_t i = 0; i < errMsg.m_sourceCallStack.size(); i++ ) + { + oss << GEOS_FMT( "Frame {}: {}\n", i, errMsg.m_sourceCallStack[i] ); + } + oss << "=====\n"; + } +} + +void ErrorLogger::writeToYaml( DiagnosticMsg & errMsg ) { std::ofstream yamlFile( std::string( m_filename ), std::ios::app ); - if( yamlFile.is_open() && isOutputFileEnabled() ) + if( yamlFile.is_open() ) { // General errors info (type, rank on which the error occured) - yamlFile << g_level1Start << "type: " << ErrorLogger::toString( errorMsg.m_type ) << "\n"; - yamlFile << g_level1Next << "rank: " << stringutilities::join( errorMsg.m_ranksInfo, "," ); + yamlFile << g_level1Start << "type: " << ErrorLogger::toString( errMsg.m_type ) << "\n"; + yamlFile << g_level1Next << "rank: " << stringutilities::join( errMsg.m_ranksInfo, "," ); yamlFile << "\n"; // Error message yamlFile << g_level1Next << "message: >-\n"; - streamMultilineYamlAttribute( errorMsg.m_msg, yamlFile, g_level2Next ); - + streamMultilineYamlAttribute( errMsg.m_msg, yamlFile, g_level2Next ); // context information - if( !errorMsg.m_contextsInfo.empty() ) + if( !errMsg.m_contextsInfo.empty() ) { + std::vector< ErrorContext > contextInfo = errMsg.m_contextsInfo; // Sort contextual information by decreasing priority - std::sort( errorMsg.m_contextsInfo.begin(), errorMsg.m_contextsInfo.end(), - []( const ErrorLogger::ErrorContext & a, const ErrorLogger::ErrorContext & b ) { + std::sort( contextInfo.begin(), contextInfo.end(), + []( const ErrorContext & a, const ErrorContext & b ) { return a.m_priority > b.m_priority; } ); // Additional informations about the context of the error and priority information of each context yamlFile << g_level1Next << "contexts:\n"; - for( ErrorContext const & ctxInfo : errorMsg.m_contextsInfo ) + for( ErrorContext const & ctxInfo : contextInfo ) { yamlFile << g_level3Start << "priority: " << ctxInfo.m_priority << "\n"; + if( !ctxInfo.m_formattedContext.empty()) + { + yamlFile << g_level3Next << "description: " << ctxInfo.m_formattedContext << "\n"; + } for( auto const & [key, value] : ctxInfo.m_attributes ) { yamlFile << g_level3Next << ErrorContext::attributeToString( key ) << ": " << value << "\n"; @@ -263,40 +344,59 @@ void ErrorLogger::flushErrorMsg( ErrorLogger::ErrorMsg & errorMsg ) } // error cause - if( !errorMsg.m_cause.empty() ) + if( !errMsg.m_cause.empty() ) { yamlFile << g_level1Next << "cause: >-\n"; - streamMultilineYamlAttribute( errorMsg.m_cause, yamlFile, g_level2Next ); + streamMultilineYamlAttribute( errMsg.m_cause, yamlFile, g_level2Next ); } // Location of the error in the code - if( !errorMsg.m_file.empty() ) + if( !errMsg.m_file.empty() ) { yamlFile << g_level1Next << "sourceLocation:\n"; - yamlFile << g_level2Next << "file: " << errorMsg.m_file << "\n"; - yamlFile << g_level2Next << "line: " << errorMsg.m_line << "\n"; + yamlFile << g_level2Next << "file: " << errMsg.m_file << "\n"; + if( errMsg.m_line > 0 ) + { + yamlFile << g_level2Next << "line: " << errMsg.m_line << "\n"; + } } // Information about the stack trace - if( !errorMsg.m_sourceCallStack.empty() ) + if( !errMsg.m_sourceCallStack.empty() ) { yamlFile << g_level1Next << "sourceCallStack:\n"; - for( size_t i = 0; i < errorMsg.m_sourceCallStack.size(); i++ ) + for( size_t i = 0; i < errMsg.m_sourceCallStack.size(); i++ ) { - yamlFile << ( errorMsg.isValidStackTrace() ? - GEOS_FMT( "{}frame{}: {}\n", g_level3Start, i, errorMsg.m_sourceCallStack[i] ) : - GEOS_FMT( "{}{}\n", g_level3Start, errorMsg.m_sourceCallStack[i] ) ); + yamlFile << ( errMsg.m_isValidStackTrace ? + GEOS_FMT( "{}frame{}: {}\n", g_level3Start, i, errMsg.m_sourceCallStack[i] ) : + GEOS_FMT( "{}{}\n", g_level3Start, errMsg.m_sourceCallStack[i] ) ); } } yamlFile << "\n"; yamlFile.flush(); - errorMsg = ErrorMsg(); - GEOS_LOG_RANK( GEOS_FMT( "The error file {} has been appended.\n", m_filename ) ); + errMsg = DiagnosticMsg(); } else { - GEOS_LOG_RANK( GEOS_FMT( "Unable to open error file for writing.\n- Error file: {}\n- Error file enabled = {}.\n", - m_filename, isOutputFileEnabled() ) ); + GEOS_LOG_RANK( GEOS_FMT( "Unable to open error file for writing.\n- Error file: {}\n", m_filename ) ); + } +} + +void ErrorLogger::flushErrorMsg( DiagnosticMsg & errMsg ) +{ + writeToAscii( errMsg, m_stream ); + if( isOutputFileEnabled() ) + { + writeToYaml( errMsg ); + } +} + +void ErrorLogger::flushCurrentExceptionMessage() +{ + writeToAscii( m_getCurrentExceptionMsg, m_stream ); + if( isOutputFileEnabled() ) + { + writeToYaml( m_getCurrentExceptionMsg ); } } diff --git a/src/coreComponents/common/logger/ErrorHandling.hpp b/src/coreComponents/common/logger/ErrorHandling.hpp index 62e3db66df6..fede949ce36 100644 --- a/src/coreComponents/common/logger/ErrorHandling.hpp +++ b/src/coreComponents/common/logger/ErrorHandling.hpp @@ -21,214 +21,228 @@ #define INITIALIZATION_ERROR_LOGGER_HPP #include "common/DataTypes.hpp" +#include "common/format/Format.hpp" +#include "common/format/StringUtilities.hpp" namespace geos { /** - * @class ErrorLogger - * @brief Class to format and write different error/warning information that occured during the initialization + * @struct ErrorContext + * Store contextual information about the error that occurred and assign it a priority + * default is 0 */ -class ErrorLogger +struct ErrorContext { -public: /** - * @enum MsgType - * Enum listing the different types of possible errors + * @enum Attribute + * Enumeration used to secure potential map keys */ - enum class MsgType + enum class Attribute { - Error, - Warning, - Exception, - Undefined + InputFile, + InputLine, + DataPath, + DetectionLoc, + Signal, }; /** - * @struct ErrorContext - * Store contextual information about the error that occurred and assign it a priority - * default is 0 + * @brief Construct to initialize ErrorContext given a string containing the context and his attribute + * @param formattedContext String containing the target object name followed by the the file and line declaring it. + * @param attributes Map containing contextual information about the error */ - struct ErrorContext - { + ErrorContext( string formattedContext, map< Attribute, std::string > attributes ): + m_formattedContext( formattedContext ), + m_attributes( attributes ) {}; - /** - * @enum Attribute - * Enumeration used to secure potential map keys - */ - enum class Attribute - { - InputFile, - InputLine, - DataPath, - DetectionLoc, - Signal, - }; - - /// The map contains contextual information about the error - /// It could be something like - /// "file" = "/path/to/file.xml" - /// "line" = "24" - /// or something like - /// "dataPath" = "/Functions/co2brine_philipsDensityTable - /// The key is a field of the Attribute enumeration and is converted to a string for writing in the YAML - map< Attribute, std::string > m_attributes; - - /** - * @brief Priority level assigned to an error context. - * @details Used to prioritize contextes (higher values = more relevant). Default is 0. - * - */ - integer m_priority = 0; - - /** - * @brief Set the priority value of the current error context information - * @param priority the new value to asign - * @return the reference to the corresponding error - */ - ErrorContext & setPriority( integer priority ) - { m_priority = priority; return *this; } - - /** - * @brief Convert a value from the Attribute enumeration to a string - * @param attribute the value of the enumeration to be converted - * @return a string representation of the enumeration value - */ - static std::string attributeToString( Attribute attribute ); - }; + /** + * @brief Construct to initialize ErrorContext given a string containing the context and his priority + * @param attributes Map containing contextual information about the error + * @param priority Priority level assigned to an error context. + */ + ErrorContext( map< Attribute, std::string > attributes, integer priority ): + m_formattedContext( "" ), + m_attributes( attributes ), + m_priority( priority ) {}; + + /** + * @brief Set the priority value of the current error context information + * @param priority the new value to asign + * @return the reference to the corresponding error + */ + ErrorContext & setPriority( integer priority ) + { m_priority = priority; return *this; } + + /** + * @brief Convert a value from the Attribute enumeration to a string + * @param attribute the value of the enumeration to be converted + * @return a string representation of the enumeration value + */ + static std::string attributeToString( Attribute attribute ); + + /// String containing the target object name followed by the the file and line declaring it. + string m_formattedContext; + + /// The map contains contextual information about the error + /// It could be something like + /// "file" = "/path/to/file.xml" + /// "line" = "24" + /// or something like + /// "dataPath" = "/Functions/co2brine_philipsDensityTable + /// The key is a field of the Attribute enumeration and is converted to a string for writing in the YAML + map< Attribute, std::string > m_attributes; + + /** + * @brief Priority level assigned to an error context. + * @details Used to prioritize contextes (higher values = more relevant). Default is 0. + * + */ + integer m_priority = 0; +}; + +/** + * @enum MsgType + * Enum listing the different types of possible errors + */ +enum class MsgType +{ + Error, + ExternalError, + Warning, + Exception, + Undefined +}; + +/** + * @brief Struct to construct the diagnostic message object + */ +struct DiagnosticMsg +{ + /// Type of diagnostic (Warning, Error or Exception) + MsgType m_type = MsgType::Undefined; + /// the message that can be completed + std::string m_msg; + /// the cause of the error (erroneous condition, failed assertion...) if identified (optional) + std::string m_cause; + /// the rank(s) on which the diagnostic occured + std::set< int > m_ranksInfo; + /// the source location file + std::string m_file; + /// the source location line (default is 0) + integer m_line = 0; + /// Additional information about the diagnostic in the input file + std::vector< ErrorContext > m_contextsInfo; + /// the stack trace + std::vector< std::string > m_sourceCallStack; + /// Indicates whether the stored call stack trace is valid and usable. + bool m_isValidStackTrace = false; +}; + +/** + * @brief Builder class for constructing DiagnosticMsg objects + */ +class DiagnosticMsgBuilder +{ +public: + static DiagnosticMsgBuilder init() + { return DiagnosticMsgBuilder();} + + static DiagnosticMsgBuilder modify( DiagnosticMsg & errorMsg ); /** - * @brief Struct to construct the error/warning object + * @brief Append exception text to the message + * @param e The exception containing text to add + * @param toEnd If true, append at end; otherwise prepend + * @return Reference to the current instance for method chaining. */ - struct ErrorMsg + DiagnosticMsgBuilder & addToMsg( std::exception const & e, bool toEnd = false ); + + /** + * @brief Append text to the message + * @param msg The text to add + * @param toEnd If true, append at end; otherwise prepend + * @return Reference to the current instance for method chaining. + */ + DiagnosticMsgBuilder & addToMsg( std::string_view msg, bool toEnd = false ); + /** + * @brief Adds one or more context elements to the error + * @tparam Args Variadic pack of compatible types (ErrorContext / DataContext) + * @param args List of context data structures. + * @return Reference to the current instance for method chaining. + */ + template< typename ... Args > + DiagnosticMsgBuilder & addContextInfo( Args && ... args ) { - /// the error type (Warning, Error or Exception) - MsgType m_type = ErrorLogger::MsgType::Undefined; - /// the error message that can be completed - std::string m_msg; - /// the cause of the error (erroneous condition, failed assertion...) if identified (optional) - std::string m_cause; - /// the rank(s) on which the error occured - std::set< int > m_ranksInfo; - /// the source location file corresponding to the error in the code - std::string m_file; - /// the source location line corresponding to the error in the code (default is 0) - integer m_line = 0; - /// Additional information about the error in the input file - std::vector< ErrorContext > m_contextsInfo; - /// the stack trace - std::vector< std::string > m_sourceCallStack; - - /** - * @brief Construct a default Error Message - */ - ErrorMsg() - {} - - /** - * @brief Construct a new Error Message from parameters - * @param msgType the type of the message (error or warning) - * @param msgContent the error/warning message content - * @param rank the rank where the error occcured - * @param msgFile the source file name where the error occcured - * @param msgLine the line where the error occured - */ - ErrorMsg( MsgType msgType, - std::string_view msgContent, - integer rank, - std::string_view msgFile, - integer msgLine ) - : m_type( msgType ), m_msg( msgContent ), m_ranksInfo( {rank} ), m_file( msgFile ), m_line( msgLine ) {} - - /** - * @brief Add text to the current error msg - * @param e The exception containing text to add - * @param toEnd Indicates whether to add the message at the beginning (true) or at the end (false) - * default is false - * @return Reference to the current instance for method chaining. - */ - ErrorMsg & addToMsg( std::exception const & e, bool toEnd = false ); - - /** - * @brief Add text to the current error msg - * @param msg The text to add - * @param toEnd Indicates whether to add the message at the beginning (true) or at the end (false) - * default is false - * @return Reference to the current instance for method chaining. - */ - ErrorMsg & addToMsg( std::string_view msg, bool toEnd = false ); - - /** - * @brief Add text to the error msg that occured according to the specified signal. - * - the signal can be one of the main error signals. - * - if the signal is SIGFPE, the nature of floating point error will be interpreted. - * @param signal The signal, from ISO C99 or POSIX standard. - * @param toEnd adds the message to the end if true, at the start otherwise. - * @return The instance, for builder pattern. - */ - ErrorMsg & addSignalToMsg( int signal, bool toEnd = false ); - - /** - * @brief Set the source code location values (file and line where the error is detected) - * @param msgFile Name of the source file location to add - * @param msgLine Line of the source file location to add - * @return Reference to the current instance for method chaining. - */ - ErrorMsg & setCodeLocation( std::string_view msgFile, integer msgLine ); - - /** - * @brief Set the type of the error - * @param msgType The type can be error, warning or exception - * @return Reference to the current instance for method chaining. - */ - ErrorMsg & setType( MsgType msgType ); - - /** - * @brief Set the cause of the error - * @param cause See documentation of m_cause. - * @return Reference to the current instance for method chaining. - */ - ErrorMsg & setCause( std::string_view cause ); - - /** - * @brief Add a rank on which the error has been raised - * @param rank The value to add - * @return Reference to the current instance for method chaining. - */ - ErrorMsg & addRank( int rank ); - - /** - * @brief Add stack trace information about the error - * @param ossStackTrace stack trace information to add - * @return Reference to the current instance for method chaining. - */ - ErrorMsg & addCallStackInfo( std::string_view ossStackTrace ); - - /** - * @brief Adds one or more context elements to the error - * @tparam Args Variadic pack of compatible types (ErrorContext / DataContext) - * @param args List of context data structures. - * @return Reference to the current instance for method chaining. - */ - template< typename ... Args > - ErrorMsg & addContextInfo( Args && ... args ); - - /** - * @return true if the YAML file output is enabled - */ - bool isValidStackTrace() const - { return m_isValidStackTrace; } + ( this->addContextInfoImpl( ErrorContext( args ) ), ... ); + return *this; + } + /** + * @brief Add text to the error msg that occured according to the specified signal. + * - the signal can be one of the main error signals. + * - if the signal is SIGFPE, the nature of floating point error will be interpreted. + * @param signal The signal, from ISO C99 or POSIX standard. + * @param toEnd adds the message to the end if true, at the start otherwise. + * @return The instance, for builder pattern. + */ + DiagnosticMsgBuilder & addSignalToMsg( integer sig, bool toEnd = false ); + /** + * @brief Set the source code location values (file and line where the error is detected) + * @param msgFile Name of the source file location to add + * @param msgLine Line of the source file location to add + * @return Reference to the current instance for method chaining. + */ + DiagnosticMsgBuilder & setCodeLocation( std::string_view msgFile, integer msgLine ); + /** + * @brief Set the type of the error + * @param msgType The type can be error, warning or exception + * @return Reference to the current instance for method chaining. + */ + DiagnosticMsgBuilder & setType( MsgType msgType ); + /** + * @brief Set the cause of the error + * @param cause See documentation of m_cause. + * @return Reference to the current instance for method chaining. + */ + DiagnosticMsgBuilder & setCause( std::string_view cause ); + /** + * @brief Add a rank on which the error has been raised + * @param rank The value to add + * @return Reference to the current instance for method chaining. + */ + DiagnosticMsgBuilder & addRank( integer rank ); + /** + * @brief Add stack trace information about the error + * @param ossStackTrace stack trace information to add + * @return Reference to the current instance for method chaining. + */ + DiagnosticMsgBuilder & addCallStackInfo( std::string_view ossStackTrace ); + + /** + * @return The constructed diagnostic message + */ + DiagnosticMsg & get(); private: - /** - * @brief Add contextual information about the error/warning - * @param ctxInfo rvalue of the ErrorContext class - */ - void addContextInfoImpl( ErrorContext && ctxInfo ); + /** + * @brief Add contextual information about the error/warning + * @param ctxInfo rvalue of the ErrorContext class + */ + DiagnosticMsgBuilder & addContextInfoImpl( ErrorContext && ctxInfo ); + /// The diagnosticMsg being constructed + DiagnosticMsg m_errorMsg; + /// The target diagnosticMsg + DiagnosticMsg * m_targetErrorMsg = nullptr; +}; - bool m_isValidStackTrace = false; - }; +/** + * @brief Logger for formatting and outputting diagnostics + */ +class ErrorLogger +{ + +public: /** * @return Global instance of the ErrorLogger class used for error/warning reporting. @@ -240,10 +254,10 @@ class ErrorLogger GEOS_HOST static ErrorLogger & global(); /** - * @return true if the YAML file output is enabled + * @brief Create the YAML file or overwrite the contents if a YAML file of the same name already exists + * And write its header when the command line option is enabled */ - bool isOutputFileEnabled() const - { return m_writeYaml; } + void createFile(); /** * @brief Enable the YAML file output, which is false by default @@ -252,6 +266,12 @@ class ErrorLogger void enableFileOutput( bool value ) { m_writeYaml = value; } + /** + * @return true if the YAML file output is enabled + */ + bool isOutputFileEnabled() const + { return m_writeYaml; } + /** * @brief Set the name of the YAML file if specified by user * default is "errors.yaml" @@ -267,41 +287,75 @@ class ErrorLogger { return m_filename; } /** - * @brief Gives acces to the error message that is currently being constructed, - * potencially at various application layers - * Use flushErrorMsg() when the message is fully constructed and you want it to be output - * @return Reference to the current instance for method chaining. + * @brief Convert a MsgType into a string + * @param type the message type label + * @return the string representation of the message type */ - ErrorMsg & currentErrorMsg() - { return m_currentErrorMsg; } + static std::string toString( MsgType type ); /** - * @brief Create the YAML file or overwrite the contents if a YAML file of the same name already exists - * And write its header when the command line option is enabled + * @return Return the const general log stream */ - void createFile(); + std::ostream const & getErrorStream() const + { return m_stream; } + + DiagnosticMsg const & getCurrentExceptionMsg() const + { return m_getCurrentExceptionMsg;} /** - * @brief Convert a MsgType into a string - * @param type the message type label - * @return the string representation of the message type + * @brief Start building a new exception message + * @return Builder for the exception + * @note One exception can exist at a time */ - static std::string toString( MsgType type ); + DiagnosticMsgBuilder initCurrentExceptionMessage() + { + m_getCurrentExceptionMsg = DiagnosticMsg(); + return DiagnosticMsgBuilder::modify( m_getCurrentExceptionMsg ); + } /** - * @brief Write all the information retrieved about the error/warning message into the YAML file - * and reset the errorMsg instance to its initial state - * @param errorMsg a constant reference to the error + * @brief Modify/Continue building the current exception message + * @return Builder for the exception */ - void flushErrorMsg( ErrorMsg & errorMsg ); + DiagnosticMsgBuilder modifyCurrentExceptionMessage() + { return DiagnosticMsgBuilder::modify( m_getCurrentExceptionMsg ); } + + /** + * @brief Write all the information retrieved about the current exception message into the instance + * outputs (stream specified + optional yaml file) + */ + void flushCurrentExceptionMessage(); + + /** + * @brief Write all the information retrieved about the diagnostic message into the instance + * outputs (stream specified + optional yaml file) + * @param errorMsg a reference to the ErrorMsg to output, and will be re-initialized + * @note Used for warnings and non-exception errors + */ + void flushErrorMsg( DiagnosticMsg & errMsg ); + + /** + * @brief Format all information in ErrorMsg and write it to the specified output stream + * @param errMsg The struct containing the error/warning object + * @param oss The output stream + */ + static void writeToAscii( DiagnosticMsg const & errMsg, std::ostream & oss ); private: /// The error constructed via exceptions - ErrorMsg m_currentErrorMsg; + DiagnosticMsg m_getCurrentExceptionMsg; /// Indicate whether the write to YAML command line option is enabled bool m_writeYaml = false; /// YAML file name std::string_view m_filename = "errors.yaml"; + /// The stream used for the log output. By default used std::cout + std::ostream & m_stream = std::cout; + + /** + * @brief Write all the information retrieved about the error/warning message into the YAML file + * @param errorMsg a constant reference to the error + */ + void writeToYaml( DiagnosticMsg & errMsg ); /** * @brief Write the error message in the YAML file regarding indentation and line break @@ -312,16 +366,7 @@ class ErrorLogger std::string_view indent ); }; -/// @cond DO_NOT_DOCUMENT - -template< typename ... Args > -ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addContextInfo( Args && ... args ) -{ - ( this->addContextInfoImpl( ErrorContext( args ) ), ... ); - return *this; -} -/// @endcond } /* namespace geos */ diff --git a/src/coreComponents/common/logger/GeosExceptions.hpp b/src/coreComponents/common/logger/GeosExceptions.hpp new file mode 100644 index 00000000000..675756c040c --- /dev/null +++ b/src/coreComponents/common/logger/GeosExceptions.hpp @@ -0,0 +1,250 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * SPDX-License-Identifier: LGPL-2.1-only + * + * Copyright (c) 2016-2024 Lawrence Livermore National Security LLC + * Copyright (c) 2018-2024 TotalEnergies + * Copyright (c) 2018-2024 The Board of Trustees of the Leland Stanford Junior University + * Copyright (c) 2023-2024 Chevron + * Copyright (c) 2019- GEOS/GEOSX Contributors + * All rights reserved + * + * See top level LICENSE, COPYRIGHT, CONTRIBUTORS, NOTICE, and ACKNOWLEDGEMENTS files for details. + * ------------------------------------------------------------------------------------------------------------ + */ + +/** + * @file Logger.hpp + */ + + +#include "common/logger/ErrorHandling.hpp" + +namespace geos +{ + +/** + * @brief Geos Exception used in GEOS_THROW + */ +struct Exception : public std::exception +{ +public: + Exception() = default; + + /** + * @brief Constructor + * @param what The error message describing the exception + */ + Exception( std::string const & what ): + std::exception( ) + { + m_errorMsg.m_msg = what; + } + + /** + * @return Reference to the ErrorMsg object + */ + DiagnosticMsg & getErrorMsg() + { return m_errorMsg; } + + /** + * @brief System fallback to get description content if error system does not achieve to output the ErrorMsg + can also provide exception information to debuggers + * @return Returns The exception message + * @note We does not allow to override what(), it's the GEOS_THROW responsability to write-in the exception message + */ + virtual char const * what() const noexcept override final + { + return m_cachedWhat.c_str(); + } + + /** + * @brief Prepare and cache the formatted exception message + * @param msg The main error message + * @param cause The cause of the exception + * @param file The source file where the exception occurred + * @param line The line number where the exception occurred + * @param rank The MPI rank + * @param stackTrace The stack trace at the point of exception + */ + void prepareWhat( std::string const & msg, + std::string const & cause, + char const * file, + int line, + int rank, + string_view stackTrace ) noexcept + { + try + { + std::ostringstream oss; + oss << "***** GEOS Exception\n"; + oss << "***** LOCATION: " << file << ":" << line << "\n"; + oss << "***** " << cause << "\n"; + oss << "***** Rank " << rank << ": "<< msg <<"\n\n"; + oss << stackTrace; + m_cachedWhat = oss.str(); + } catch( ... ) + { + m_cachedWhat = "GEOS Exception (formatting failed)"; + } + + } + +private: + /// Formatted exception message for what() method + string m_cachedWhat; + /// Error message logger for structured error reporting + DiagnosticMsg m_errorMsg; +}; + +/** + * @brief Exception class used to report errors in user input. + */ +struct RuntimeError : public geos::Exception +{ + /** + * @brief Constructor + * @param what the error message + */ + RuntimeError( std::string const & what ): + geos::Exception( what ) + {} + + RuntimeError(): geos::Exception(){} +}; + +/** + * @brief Exception class used to report bad GEOS state + */ +struct LogicError : public geos::Exception +{ + /** + * @brief Constructor + * @param what the error message + */ + LogicError( std::string const & what ): + geos::Exception( what ) + {} + + /** + * @brief Default constructor + */ + LogicError(): geos::Exception(){} +}; + +/** + * @brief Exception class used to report errors in user input. + */ +struct DomainError : public geos::Exception +{ + /** + * @brief Constructor + * @param what the error message + */ + DomainError( std::string const & what ): + geos::Exception( what ) + {} + + /** + * @brief Default constructor + */ + DomainError(): geos::Exception(){} +}; +/** + * @brief Exception class used to report errors in user input. + */ +struct InputError : public geos::Exception +{ + /** + * @brief Constructor + * @param what the error message + */ + InputError( std::string const & what ): + geos::Exception( what ) + {} + + /** + * @brief Default constructor + */ + InputError(): geos::Exception(){} + + /** + * @brief Constructor + * @param what the error message + */ + InputError( char const * const what ): + geos::Exception( what ) + {} + + /** + * @brief Constructs an InputError from an underlying exception. + * @param subException The exception on which the created one is based. + * @param msgToInsert The error message that will be inserted in the subException error message. + */ + InputError( std::exception const & subException, std::string const & msgToInsert ); +}; + +/** + * @brief Exception class used to report errors in user input. + */ +struct SimulationError : public geos::Exception +{ + /** + * @brief Constructor + * @param what the error message + */ + SimulationError( std::string const & what ): + geos::Exception( what ) + {} + + /** + * @brief Default constructor + */ + SimulationError(): geos::Exception(){} + + /** + * @brief Constructor + * @param what the error message + */ + SimulationError( char const * const what ): + geos::Exception( what ) + {} + + /** + * @brief Construct a SimulationError from an underlying exception. + * @param subException An exception to base this new one on. + * @param msgToInsert The error message. + * It will be inserted before the error message inside of subException. + */ + SimulationError( std::exception const & subException, std::string const & msgToInsert ); +}; + +/** + * @brief Exception class used to report errors from type conversion + * @todo (ErrorManager EPIC #2940) Consider adding a way to precise custom exception parameters, to add + * expected & encountered typeid for this one (in order to manage the exception output more precisely). + * We could also manage this by having: BadTypeErrorABC <|--- BadTypeError< T > /!\ compilation time + */ +struct BadTypeError : public geos::Exception +{ + /** + * @brief Constructor + * @param what the error message + */ + BadTypeError( std::string const & what ): + geos::Exception( what ) + {} + + /** + * @brief Default constructor + */ + BadTypeError(): geos::Exception(){} +}; + +/** + * @brief Exception class used for special control flow. + */ +class NotAnError : public geos::Exception +{}; + +} diff --git a/src/coreComponents/common/logger/Logger.cpp b/src/coreComponents/common/logger/Logger.cpp index ade2834cbb2..ba1877eb4c9 100644 --- a/src/coreComponents/common/logger/Logger.cpp +++ b/src/coreComponents/common/logger/Logger.cpp @@ -20,7 +20,6 @@ // Source includes #include "Logger.hpp" #include "common/Path.hpp" -#include "common/format/StringUtilities.hpp" namespace geos { @@ -56,11 +55,11 @@ std::string insertExMsg( std::string const & originalMsg, std::string const & ms } InputError::InputError( std::exception const & subException, std::string const & msgToInsert ): - std::runtime_error( insertExMsg( subException.what(), msgToInsert ) ) + geos::Exception( insertExMsg( subException.what(), msgToInsert ) ) {} SimulationError::SimulationError( std::exception const & subException, std::string const & msgToInsert ): - std::runtime_error( insertExMsg( subException.what(), msgToInsert ) ) + geos::Exception( insertExMsg( subException.what(), msgToInsert ) ) {} namespace logger diff --git a/src/coreComponents/common/logger/Logger.hpp b/src/coreComponents/common/logger/Logger.hpp index e59cfa05256..92a0a06f722 100644 --- a/src/coreComponents/common/logger/Logger.hpp +++ b/src/coreComponents/common/logger/Logger.hpp @@ -20,12 +20,9 @@ #ifndef GEOS_COMMON_LOGGER_HPP #define GEOS_COMMON_LOGGER_HPP -// Source incldes -#include "common/GeosxConfig.hpp" -#include "common/GeosxMacros.hpp" -#include "common/format/Format.hpp" +// Source includes #include "LvArray/src/Macros.hpp" -#include "common/logger/ErrorHandling.hpp" +#include "common/logger/GeosExceptions.hpp" // System includes #include @@ -137,8 +134,8 @@ * @note - Currently not available on GPU. * - Possible to pre-define it in any source file (e.g. for unit tests) */ -#if !defined(GEOS_DEVICE_COMPILE) && !defined(GEOS_ERROR_LOGGER_INSTANCE) -#define GEOS_ERROR_LOGGER_INSTANCE ErrorLogger::global() +#if !defined(GEOS_DEVICE_COMPILE) && !defined(GEOS_GLOBAL_LOGGER) +#define GEOS_GLOBAL_LOGGER ErrorLogger::global() #endif /** @@ -158,34 +155,21 @@ { \ std::ostringstream __msgoss; \ __msgoss << GEOS_DETAIL_FIRST_ARG( __VA_ARGS__ ); \ - std::string __message = __msgoss.str(); \ - __msgoss = std::ostringstream(); \ - __msgoss << CAUSE_MESSAGE; \ - std::string __cause = __msgoss.str(); \ - std::ostringstream __oss; \ - __oss << "***** ERROR\n"; \ - __oss << "***** LOCATION: " LOCATION "\n"; \ - __oss << "***** " << __cause << "\n"; \ - __oss << "***** Rank " << ::geos::logger::internal::g_rankString << ": " << __message << "\n"; \ - std::string stackHistory = LvArray::system::stackTrace( true ); \ - __oss << stackHistory; \ - std::cout << __oss.str() << std::endl; \ - if( GEOS_ERROR_LOGGER_INSTANCE.isOutputFileEnabled() ) \ - { \ - ErrorLogger::ErrorMsg msgStruct( ErrorLogger::MsgType::Error, \ - __message, \ - ::geos::logger::internal::g_rank, \ - __FILE__, \ - __LINE__ ); \ - msgStruct.setCause( __cause ); \ - msgStruct.addCallStackInfo( stackHistory ); \ - msgStruct.addContextInfo( GEOS_DETAIL_REST_ARGS( __VA_ARGS__ ) ); \ - GEOS_ERROR_LOGGER_INSTANCE.flushErrorMsg( msgStruct ); \ - } \ + std::ostringstream __causemsgsoss; \ + __causemsgsoss << CAUSE_MESSAGE; \ + GEOS_GLOBAL_LOGGER.initCurrentExceptionMessage() \ + .setType( MsgType::Error ) \ + .setCodeLocation( __FILE__, __LINE__ ) \ + .setCause( __causemsgsoss.str() ) \ + .addRank( ::geos::logger::internal::g_rank ) \ + .addCallStackInfo( LvArray::system::stackTrace( true ) ) \ + .addToMsg( __msgoss.str() ) \ + .addContextInfo( GEOS_DETAIL_REST_ARGS( __VA_ARGS__ )).get(); \ + GEOS_GLOBAL_LOGGER.flushCurrentExceptionMessage(); \ LvArray::system::callErrorHandler(); \ } \ - } while( false ) -#elif __CUDA_ARCH__ + }while( false ) + #elif __CUDA_ARCH__ #define GEOS_ERROR_IF_CAUSE( COND, CAUSE_MESSAGE, ... ) \ do \ { \ @@ -230,7 +214,7 @@ * - Mandatory first parameter, the type of the exception to throw * - Optional following parameters, context information on the current error (DataContext) */ -#if !defined(GEOS_DEVICE_COMPILE) + #if !defined(GEOS_DEVICE_COMPILE) #define GEOS_THROW_IF_CAUSE( COND, CAUSE_MESSAGE, MSG, ... ) \ do \ { \ @@ -238,36 +222,24 @@ { \ std::ostringstream __msgoss; \ __msgoss << MSG; \ - std::string __message = __msgoss.str(); \ - __msgoss = std::ostringstream(); \ - __msgoss << CAUSE_MESSAGE; \ - std::string __cause = __msgoss.str(); \ - std::ostringstream __oss; \ - __oss << "***** EXCEPTION\n"; \ - __oss << "***** LOCATION: " LOCATION "\n"; \ - __oss << "***** " << __cause << "\n"; \ - __oss << "***** Rank " << ::geos::logger::internal::g_rankString << ": " << __message << "\n"; \ - std::string stackHistory = LvArray::system::stackTrace( true ); \ - __oss << stackHistory; \ - if( GEOS_ERROR_LOGGER_INSTANCE.isOutputFileEnabled() ) \ - { \ - if( GEOS_ERROR_LOGGER_INSTANCE.currentErrorMsg().m_type == ErrorLogger::MsgType::Undefined ) \ - { /* first throw site, we initialize the error message completly */ \ - GEOS_ERROR_LOGGER_INSTANCE.currentErrorMsg() \ - .setType( ErrorLogger::MsgType::Exception ) \ - .setCodeLocation( __FILE__, __LINE__ ) \ - .setCause( __cause ) \ - .addRank( ::geos::logger::internal::g_rank ) \ - .addCallStackInfo( stackHistory ); \ - } \ - GEOS_ERROR_LOGGER_INSTANCE.currentErrorMsg() \ - .addToMsg( __message ) \ - .addContextInfo( GEOS_DETAIL_REST_ARGS( __VA_ARGS__ ) ); \ - } \ - throw GEOS_DETAIL_FIRST_ARG( __VA_ARGS__ )( __oss.str() ); \ + std::ostringstream __causemsgsoss; \ + __causemsgsoss << CAUSE_MESSAGE; \ + GEOS_GLOBAL_LOGGER.initCurrentExceptionMessage() \ + .setType( MsgType::Exception ) \ + .setCodeLocation( __FILE__, __LINE__ ) \ + .setCause( __causemsgsoss.str() ) \ + .addRank( ::geos::logger::internal::g_rank ) \ + .addCallStackInfo( LvArray::system::stackTrace( true ) ) \ + .addToMsg( __msgoss.str() ) \ + .addContextInfo( GEOS_DETAIL_REST_ARGS( __VA_ARGS__ )).get(); \ + auto ex = GEOS_DETAIL_FIRST_ARG( __VA_ARGS__ )(); \ + ex.prepareWhat( __msgoss.str(), __causemsgsoss.str(), \ + __FILE__, __LINE__, \ + ::geos::logger::internal::g_rank, LvArray::system::stackTrace( true ) ); \ + throw ex; \ } \ - } while( false ) -#elif __CUDA_ARCH__ + }while( false ) + #elif __CUDA_ARCH__ #define GEOS_THROW_IF_CAUSE( COND, CAUSE_MESSAGE, MSG, ... ) \ do \ { \ @@ -321,29 +293,18 @@ { \ std::ostringstream __msgoss; \ __msgoss << GEOS_DETAIL_FIRST_ARG( __VA_ARGS__ ); \ - std::string __message = __msgoss.str(); \ - __msgoss = std::ostringstream(); \ - __msgoss << CAUSE_MESSAGE; \ - std::string __cause = __msgoss.str(); \ - std::ostringstream __oss; \ - __oss << "***** WARNING\n"; \ - __oss << "***** LOCATION: " LOCATION "\n"; \ - __oss << "***** " << __cause << "\n"; \ - __oss << "***** Rank " << ::geos::logger::internal::g_rankString << ": " << __message << "\n"; \ - std::cout << __oss.str() << std::endl; \ - if( GEOS_ERROR_LOGGER_INSTANCE.isOutputFileEnabled() ) \ - { \ - ErrorLogger::ErrorMsg msgStruct( ErrorLogger::MsgType::Warning, \ - __message, \ - ::geos::logger::internal::g_rank, \ - __FILE__, \ - __LINE__ ); \ - msgStruct.setCause( __cause ); \ - msgStruct.addContextInfo( GEOS_DETAIL_REST_ARGS( __VA_ARGS__ ) ); \ - GEOS_ERROR_LOGGER_INSTANCE.flushErrorMsg( msgStruct ); \ - } \ + std::ostringstream __causemsgsoss; \ + __causemsgsoss << CAUSE_MESSAGE; \ + GEOS_GLOBAL_LOGGER.flushErrorMsg( DiagnosticMsgBuilder::init() \ + .setType( MsgType::Warning ) \ + .setCodeLocation( __FILE__, __LINE__ ) \ + .setCause( __causemsgsoss.str() ) \ + .addRank( ::geos::logger::internal::g_rank ) \ + .addCallStackInfo( LvArray::system::stackTrace( true ) ) \ + .addToMsg( __msgoss.str() ) \ + .addContextInfo( GEOS_DETAIL_REST_ARGS( __VA_ARGS__ )).get() ); \ } \ - } while( false ) + }while( false ) #elif __CUDA_ARCH__ #define GEOS_WARNING_IF_CAUSE( COND, CAUSE_MESSAGE, ... ) \ do \ @@ -949,88 +910,6 @@ namespace geos { -/** - * @brief Exception class used to report errors in user input. - */ -struct InputError : public std::runtime_error -{ - /** - * @brief Constructor - * @param what the error message - */ - InputError( std::string const & what ): - std::runtime_error( what ) - {} - - /** - * @brief Constructor - * @param what the error message - */ - InputError( char const * const what ): - std::runtime_error( what ) - {} - - /** - * @brief Constructs an InputError from an underlying exception. - * @param subException The exception on which the created one is based. - * @param msgToInsert The error message that will be inserted in the subException error message. - */ - InputError( std::exception const & subException, std::string const & msgToInsert ); -}; - -/** - * @brief Exception class used to report errors in user input. - */ -struct SimulationError : public std::runtime_error -{ - /** - * @brief Constructor - * @param what the error message - */ - SimulationError( std::string const & what ): - std::runtime_error( what ) - {} - - /** - * @brief Constructor - * @param what the error message - */ - SimulationError( char const * const what ): - std::runtime_error( what ) - {} - - /** - * @brief Construct a SimulationError from an underlying exception. - * @param subException An exception to base this new one on. - * @param msgToInsert The error message. - * It will be inserted before the error message inside of subException. - */ - SimulationError( std::exception const & subException, std::string const & msgToInsert ); -}; - -/** - * @brief Exception class used to report errors from type conversion - * @todo (ErrorManager EPIC #2940) Consider adding a way to precise custom exception parameters, to add - * expected & encountered typeid for this one (in order to manage the exception output more precisely). - * We could also manage this by having: BadTypeErrorABC <|--- BadTypeError< T > /!\ compilation time - */ -struct BadTypeError : public std::runtime_error -{ - /** - * @brief Constructor - * @param what the error message - */ - BadTypeError( std::string const & what ): - std::runtime_error( what ) - {} -}; - -/** - * @brief Exception class used for special control flow. - */ -class NotAnError : public std::exception -{}; - namespace logger { @@ -1043,7 +922,7 @@ extern std::string g_rankString; extern std::ostream * g_rankStream; -} // namespace internal +} // namespace internal #if defined(GEOS_USE_MPI) /** @@ -1065,8 +944,8 @@ void InitializeLogger( const std::string & rank_output_dir="" ); */ void FinalizeLogger(); -} // namespace logger +} // namespace logger -} // namespace geos +} // namespace geos #endif /* GEOS_COMMON_LOGGER_HPP */ diff --git a/src/coreComponents/common/unitTests/testDataTypes.cpp b/src/coreComponents/common/unitTests/testDataTypes.cpp index 5c2daf1655a..58ebc681cae 100644 --- a/src/coreComponents/common/unitTests/testDataTypes.cpp +++ b/src/coreComponents/common/unitTests/testDataTypes.cpp @@ -58,8 +58,6 @@ TEST( testDataTypes, testBoundChecking ) } }, std::out_of_range ); - // std::cout <<" sdsfs "<< mapBoundsChecking.get_inserted(0)<< std::endl; - // std::cout << mapBoundsChecking.get_inserted(1); internal::StdMapWrapper< std::unordered_map< integer, integer >, true > unorderedMapBoundsChecking{{0, 1}}; EXPECT_THROW( { diff --git a/src/coreComponents/common/unitTests/testUnits.cpp b/src/coreComponents/common/unitTests/testUnits.cpp index 9dc1685632d..2fdd6823f83 100644 --- a/src/coreComponents/common/unitTests/testUnits.cpp +++ b/src/coreComponents/common/unitTests/testUnits.cpp @@ -155,3 +155,11 @@ TEST( Units, SystemDurationFormatTest ) } } } + + +int main( int ac, char * av[] ) +{ + ::testing::InitGoogleTest( &ac, av ); + int const result = RUN_ALL_TESTS(); + return result; +} diff --git a/src/coreComponents/constitutive/fluid/multifluid/CO2Brine/CO2BrineFluid.cpp b/src/coreComponents/constitutive/fluid/multifluid/CO2Brine/CO2BrineFluid.cpp index 470cc72f920..3558bd9035a 100644 --- a/src/coreComponents/constitutive/fluid/multifluid/CO2Brine/CO2BrineFluid.cpp +++ b/src/coreComponents/constitutive/fluid/multifluid/CO2Brine/CO2BrineFluid.cpp @@ -172,7 +172,7 @@ void CO2BrineFluid< PHASE1, PHASE2, FLASH >::checkTablesParameters( real64 const { string const errorMsg = GEOS_FMT( "Table input error for {} phase (in table from \"{}\").\n", m_phaseNames[m_p1Index], m_phasePVTParaFiles[m_p1Index] ); - ErrorLogger::global().currentErrorMsg() + ErrorLogger::global().modifyCurrentExceptionMessage() .addToMsg( errorMsg ) .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); throw SimulationError( ex, errorMsg ); @@ -187,7 +187,7 @@ void CO2BrineFluid< PHASE1, PHASE2, FLASH >::checkTablesParameters( real64 const { string const errorMsg = GEOS_FMT( "Table input error for {} phase (in table from \"{}\").\n", m_phaseNames[m_p2Index], m_phasePVTParaFiles[m_p2Index] ); - ErrorLogger::global().currentErrorMsg() + ErrorLogger::global().modifyCurrentExceptionMessage() .addToMsg( errorMsg ) .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); throw SimulationError( ex, errorMsg ); @@ -200,7 +200,7 @@ void CO2BrineFluid< PHASE1, PHASE2, FLASH >::checkTablesParameters( real64 const { string const errorMsg = GEOS_FMT( "Table input error for flash phase (in table from \"{}\").\n", m_flashModelParaFile ); - ErrorLogger::global().currentErrorMsg() + ErrorLogger::global().modifyCurrentExceptionMessage() .addToMsg( errorMsg ) .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); throw SimulationError( ex, errorMsg ); diff --git a/src/coreComponents/constitutive/fluid/multifluid/blackOil/BlackOilFluidBase.cpp b/src/coreComponents/constitutive/fluid/multifluid/blackOil/BlackOilFluidBase.cpp index ecf77b94f40..22c652aefb6 100644 --- a/src/coreComponents/constitutive/fluid/multifluid/blackOil/BlackOilFluidBase.cpp +++ b/src/coreComponents/constitutive/fluid/multifluid/blackOil/BlackOilFluidBase.cpp @@ -256,12 +256,12 @@ void BlackOilFluidBase::checkTablesParameters( real64 const pressure, m_formationVolFactorTables[iph]->checkCoord( pressure, 0 ); } catch( SimulationError const & ex ) { - string const msg = GEOS_FMT( errorMsg, getCatalogName(), getDataContext(), - "formation volume factor", iph ); - ErrorLogger::global().currentErrorMsg() - .addToMsg( msg ) - .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); - throw SimulationError( ex, msg ); + string const exceptionMsg = GEOS_FMT( errorMsg, getCatalogName(), getDataContext(), + "formation volume factor", iph ); + ErrorLogger::global().modifyCurrentExceptionMessage() + .addToMsg( exceptionMsg ) + .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ).get(); + throw SimulationError( ex, exceptionMsg ); } try @@ -269,12 +269,13 @@ void BlackOilFluidBase::checkTablesParameters( real64 const pressure, m_viscosityTables[iph]->checkCoord( pressure, 0 ); } catch( SimulationError const & ex ) { - string const msg = GEOS_FMT( errorMsg, getCatalogName(), getDataContext(), - "viscosity", iph ); - ErrorLogger::global().currentErrorMsg() - .addToMsg( msg ) - .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); - throw SimulationError( ex, msg ); + string const exceptionMsg = GEOS_FMT( errorMsg, getCatalogName(), getDataContext(), + "viscosity", iph ); + + ErrorLogger::global().modifyCurrentExceptionMessage() + .addToMsg( exceptionMsg ) + .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ).get(); + throw SimulationError( ex, exceptionMsg ); } } } diff --git a/src/coreComponents/constitutive/fluid/multifluid/reactive/ReactiveBrineFluid.cpp b/src/coreComponents/constitutive/fluid/multifluid/reactive/ReactiveBrineFluid.cpp index 7371e60d080..b5e50660291 100644 --- a/src/coreComponents/constitutive/fluid/multifluid/reactive/ReactiveBrineFluid.cpp +++ b/src/coreComponents/constitutive/fluid/multifluid/reactive/ReactiveBrineFluid.cpp @@ -235,9 +235,10 @@ void ReactiveBrineFluid< PHASE >::checkTablesParameters( real64 const pressure, { string const errorMsg = GEOS_FMT( "Table input error (in table from {}).\n", stringutilities::join( m_phasePVTParaFiles ) ); - ErrorLogger::global().currentErrorMsg() + ErrorLogger::global().modifyCurrentExceptionMessage() .addToMsg( errorMsg ) - .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); + .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ) + .get(); throw SimulationError( ex, errorMsg ); } } diff --git a/src/coreComponents/constitutiveDrivers/fluid/multiFluid/PVTDriver.cpp b/src/coreComponents/constitutiveDrivers/fluid/multiFluid/PVTDriver.cpp index db232e5c37d..d6469615055 100644 --- a/src/coreComponents/constitutiveDrivers/fluid/multiFluid/PVTDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/fluid/multiFluid/PVTDriver.cpp @@ -207,7 +207,7 @@ bool PVTDriver::execute( real64 const GEOS_UNUSED_PARAM( time_n ), { // this code only makes sense in serial - GEOS_THROW_IF( MpiWrapper::commRank() > 0, "PVTDriver should only be run in serial", std::runtime_error ); + GEOS_THROW_IF( MpiWrapper::commRank() > 0, "PVTDriver should only be run in serial", geos::RuntimeError ); // get the fluid out of the constitutive manager. // for the moment it is of type MultiFluidBase. @@ -372,21 +372,21 @@ void PVTDriver::compareWithBaseline() { for( integer col=0; col < m_table.size( 1 ); ++col ) { - GEOS_THROW_IF( file.eof(), "Baseline file appears shorter than internal results", std::runtime_error ); + GEOS_THROW_IF( file.eof(), "Baseline file appears shorter than internal results", geos::RuntimeError ); file >> value; real64 const error = fabs( m_table[row][col]-value ) / ( fabs( value )+1 ); GEOS_THROW_IF( error > MultiFluidConstants::baselineTolerance, GEOS_FMT( "Results do not match baseline ({} vs {}) at data row {} (row {} with header) and column {}", m_table[row][col], value, row+1, row+headerRows, col+1 ), - std::runtime_error ); + geos::RuntimeError ); } } // check we actually reached the end of the baseline file file >> value; - GEOS_THROW_IF( !file.eof(), "Baseline file appears longer than internal results", std::runtime_error ); + GEOS_THROW_IF( !file.eof(), "Baseline file appears longer than internal results", geos::RuntimeError ); // success diff --git a/src/coreComponents/constitutiveDrivers/fluid/multiFluid/reactive/ReactiveFluidDriver.cpp b/src/coreComponents/constitutiveDrivers/fluid/multiFluid/reactive/ReactiveFluidDriver.cpp index 8bf8db3077d..24afcd65d15 100644 --- a/src/coreComponents/constitutiveDrivers/fluid/multiFluid/reactive/ReactiveFluidDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/fluid/multiFluid/reactive/ReactiveFluidDriver.cpp @@ -127,7 +127,7 @@ bool ReactiveFluidDriver::execute( real64 const GEOS_UNUSED_PARAM( time_n ), { // this code only makes sense in serial - GEOS_THROW_IF( MpiWrapper::commRank() > 0, "ReactiveFluidDriver should only be run in serial", std::runtime_error ); + GEOS_THROW_IF( MpiWrapper::commRank() > 0, "ReactiveFluidDriver should only be run in serial", geos::RuntimeError ); // get the fluid out of the constitutive manager. // for the moment it is of type MultiFluidBase. @@ -324,20 +324,20 @@ void ReactiveFluidDriver::compareWithBaseline() { for( integer col=0; col < m_table.size( 1 ); ++col ) { - GEOS_THROW_IF( file.eof(), "Baseline file appears shorter than internal results", std::runtime_error ); + GEOS_THROW_IF( file.eof(), "Baseline file appears shorter than internal results", geos::RuntimeError ); file >> value; error = fabs( m_table[row][col]-value ) / ( fabs( value )+1 ); GEOS_THROW_IF( error > m_baselineTol, "Results do not match baseline at data row " << row+1 << " (row " << row+m_numColumns << " with header)" - << " and column " << col+1, std::runtime_error ); + << " and column " << col+1, geos::RuntimeError ); } } // check we actually reached the end of the baseline file file >> value; - GEOS_THROW_IF( !file.eof(), "Baseline file appears longer than internal results", std::runtime_error ); + GEOS_THROW_IF( !file.eof(), "Baseline file appears longer than internal results", geos::RuntimeError ); // success diff --git a/src/coreComponents/constitutiveDrivers/relativePermeability/RelpermDriver.cpp b/src/coreComponents/constitutiveDrivers/relativePermeability/RelpermDriver.cpp index 49dca10b482..a46e6927baa 100644 --- a/src/coreComponents/constitutiveDrivers/relativePermeability/RelpermDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/relativePermeability/RelpermDriver.cpp @@ -110,7 +110,7 @@ bool RelpermDriver::execute( const geos::real64 GEOS_UNUSED_PARAM( time_n ), { // this code only makes sense in serial - GEOS_THROW_IF( MpiWrapper::commRank() > 0, "RelpermDriver should only be run in serial", std::runtime_error ); + GEOS_THROW_IF( MpiWrapper::commRank() > 0, "RelpermDriver should only be run in serial", geos::RuntimeError ); ConstitutiveManager @@ -301,7 +301,7 @@ void RelpermDriver::compareWithBaseline() { for( integer col = 0; col < m_table.size( 1 ); ++col ) { - GEOS_THROW_IF( file.eof(), "Baseline file appears shorter than internal results", std::runtime_error ); + GEOS_THROW_IF( file.eof(), "Baseline file appears shorter than internal results", geos::RuntimeError ); file >> value; real64 const error = fabs( m_table[row][col] - value ) / ( fabs( value ) + 1 ); @@ -310,14 +310,14 @@ void RelpermDriver::compareWithBaseline() << row + m_numColumns << " with header)" << " and column " << col + 1, - std::runtime_error ); + geos::RuntimeError ); } } // check we actually reached the end of the baseline file file >> value; - GEOS_THROW_IF( !file.eof(), "Baseline file appears longer than internal results", std::runtime_error ); + GEOS_THROW_IF( !file.eof(), "Baseline file appears longer than internal results", geos::RuntimeError ); // success diff --git a/src/coreComponents/constitutiveDrivers/solid/TriaxialDriver.cpp b/src/coreComponents/constitutiveDrivers/solid/TriaxialDriver.cpp index 73bea40106f..0dd8ad22c75 100644 --- a/src/coreComponents/constitutiveDrivers/solid/TriaxialDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/solid/TriaxialDriver.cpp @@ -394,7 +394,7 @@ bool TriaxialDriver::execute( real64 const GEOS_UNUSED_PARAM( time_n ), { // this code only makes sense in serial - GEOS_THROW_IF( MpiWrapper::commRank() > 0, "Triaxial Driver should only be run in serial", std::runtime_error ); + GEOS_THROW_IF( MpiWrapper::commRank() > 0, "Triaxial Driver should only be run in serial", geos::RuntimeError ); // get the solid out of the constitutive manager. // for the moment it is of type SolidBase. @@ -560,7 +560,7 @@ void TriaxialDriver::compareWithBaseline() { for( integer col=0; col < m_table.size( 1 ); ++col ) { - GEOS_THROW_IF( file.eof(), "Baseline file appears shorter than internal results", std::runtime_error ); + GEOS_THROW_IF( file.eof(), "Baseline file appears shorter than internal results", geos::RuntimeError ); file >> value; if( col < ITER ) // only compare "real" data columns @@ -568,7 +568,7 @@ void TriaxialDriver::compareWithBaseline() error = fabs( m_table[row][col]-value ) / ( fabs( value )+1 ); GEOS_THROW_IF( error > m_baselineTol, "Results do not match baseline at data row " << row+1 << " (row " << row+10 << " with header)" - << " and column " << col+1, std::runtime_error ); + << " and column " << col+1, geos::RuntimeError ); } } } @@ -576,7 +576,7 @@ void TriaxialDriver::compareWithBaseline() // check we actually reached the end of the baseline file file >> value; - GEOS_THROW_IF( !file.eof(), "Baseline file appears longer than internal results", std::runtime_error ); + GEOS_THROW_IF( !file.eof(), "Baseline file appears longer than internal results", geos::RuntimeError ); // success diff --git a/src/coreComponents/dataRepository/DataContext.cpp b/src/coreComponents/dataRepository/DataContext.cpp index 8e01140759f..8ce7f1c7b55 100644 --- a/src/coreComponents/dataRepository/DataContext.cpp +++ b/src/coreComponents/dataRepository/DataContext.cpp @@ -108,11 +108,12 @@ string DataFileContext::toString() const } } -ErrorLogger::ErrorContext DataFileContext::getContextInfo() const +ErrorContext DataFileContext::getContextInfo() const { - ErrorLogger::ErrorContext ctxInfo{ - { { ErrorLogger::ErrorContext::Attribute::InputFile, m_filePath }, - { ErrorLogger::ErrorContext::Attribute::InputLine, std::to_string( m_line )} } // m_attributes + ErrorContext ctxInfo{ + toString(), + { { ErrorContext::Attribute::InputFile, m_filePath }, + { ErrorContext::Attribute::InputLine, std::to_string( m_line )} } }; return ctxInfo; } diff --git a/src/coreComponents/dataRepository/DataContext.hpp b/src/coreComponents/dataRepository/DataContext.hpp index 63b855e24f2..8a43381b438 100644 --- a/src/coreComponents/dataRepository/DataContext.hpp +++ b/src/coreComponents/dataRepository/DataContext.hpp @@ -63,15 +63,15 @@ class DataContext /** * @brief Returns contextual information, including the file name and the line number - * @return ErrorLogger::ErrorContext + * @return ErrorContext */ - virtual ErrorLogger::ErrorContext getContextInfo() const = 0; + virtual ErrorContext getContextInfo() const = 0; /** - * @brief Conversion operator to ErrorLogger::ErrorContext - * @return ErrorLogger::ErrorContext + * @brief Conversion operator to ErrorContext + * @return ErrorContext */ - explicit operator ErrorLogger::ErrorContext() const { + explicit operator ErrorContext() const { return getContextInfo(); } @@ -172,9 +172,9 @@ class DataFileContext final : public DataContext /** * @brief Return contextual information (file and line of the input file where the error occured) - * @return ErrorLogger::ErrorContext ErrorLogger instance updated with context information + * @return ErrorContext ErrorLogger instance updated with context information */ - ErrorLogger::ErrorContext getContextInfo() const override; + ErrorContext getContextInfo() const override; /** * @return the type name in the source file (XML node tag name / attribute name). diff --git a/src/coreComponents/dataRepository/Group.cpp b/src/coreComponents/dataRepository/Group.cpp index 409fff42c61..b9ece9eb301 100644 --- a/src/coreComponents/dataRepository/Group.cpp +++ b/src/coreComponents/dataRepository/Group.cpp @@ -695,7 +695,7 @@ Group const & Group::getBaseGroupByPath( string const & path ) const GEOS_THROW_IF( !foundTarget, "Could not find the specified path start.\n"<< "Specified path is " << path, - std::domain_error ); + geos::DomainError ); } string::size_type currentPosition; diff --git a/src/coreComponents/dataRepository/Group.hpp b/src/coreComponents/dataRepository/Group.hpp index bf185a656ef..86ff2215e42 100644 --- a/src/coreComponents/dataRepository/Group.hpp +++ b/src/coreComponents/dataRepository/Group.hpp @@ -312,7 +312,7 @@ class Group * @tparam KEY The type of the lookup. * @param key The key used to perform the lookup. * @return A reference to @p T that refers to the sub-group. - * @throw std::domain_error If the Group does not exist is thrown. + * @throw geos::DomainError If the Group does not exist is thrown. */ template< typename T = Group, typename KEY = void > T & getGroup( KEY const & key ) @@ -321,7 +321,7 @@ class Group GEOS_THROW_IF( child == nullptr, "Group " << getDataContext() << " has no child named " << key << std::endl << dumpSubGroupsNames(), - std::domain_error, getDataContext() ); + geos::DomainError, getDataContext() ); T * const castedChild = dynamicCast< T * >( child ); GEOS_THROW_IF( castedChild == nullptr, GEOS_FMT( "{} was expected to be a '{}'.", @@ -340,7 +340,7 @@ class Group GEOS_THROW_IF( child == nullptr, "Group " << getDataContext() << " has no child named " << key << std::endl << dumpSubGroupsNames(), - std::domain_error, getDataContext() ); + geos::DomainError, getDataContext() ); T const * const castedChild = dynamicCast< T const * >( child ); GEOS_THROW_IF( castedChild == nullptr, GEOS_FMT( "{} was expected to be a '{}'.", @@ -356,7 +356,7 @@ class Group * to lookup the Group to return. Absolute paths search * from the tree root, while relative - from current group. * @return A reference to @p T that refers to the sub-group. - * @throw std::domain_error If the Group doesn't exist. + * @throw geos::DomainError If the Group doesn't exist. */ template< typename T = Group > T & getGroupByPath( string const & path ) @@ -1117,7 +1117,7 @@ class Group * @tparam KEY The lookup type. * @param key The value used to lookup the wrapper. * @return A reference to the WrapperBase that resulted from the lookup. - * @throw std::domain_error if the wrapper doesn't exist. + * @throw geos::DomainError if the wrapper doesn't exist. */ template< typename KEY > WrapperBase const & getWrapperBase( KEY const & key ) const @@ -1126,7 +1126,7 @@ class Group GEOS_THROW_IF( wrapper == nullptr, "Group " << getDataContext() << " has no wrapper named " << key << std::endl << dumpWrappersNames(), - std::domain_error, getDataContext() ); + geos::DomainError, getDataContext() ); return *wrapper; } @@ -1141,7 +1141,7 @@ class Group GEOS_THROW_IF( wrapper == nullptr, "Group " << getDataContext() << " has no wrapper named " << key << std::endl << dumpWrappersNames(), - std::domain_error, getDataContext() ); + geos::DomainError, getDataContext() ); return *wrapper; } @@ -1210,7 +1210,7 @@ class Group * @tparam LOOKUP_TYPE the type of key used to perform the lookup * @param[in] index a lookup value used to search the collection of wrappers * @return A reference to the Wrapper that resulted from the lookup. - * @throw std::domain_error if the Wrapper doesn't exist. + * @throw geos::DomainError if the Wrapper doesn't exist. */ template< typename T, typename LOOKUP_TYPE > Wrapper< T > const & getWrapper( LOOKUP_TYPE const & index ) const @@ -1268,7 +1268,7 @@ class Group * @tparam LOOKUP_TYPE type of value used for wrapper lookup * @param lookup value for wrapper lookup * @return reference to @p T - * @throw A std::domain_error if the Wrapper does not exist. + * @throw A geos::DomainError if the Wrapper does not exist. */ template< typename T, typename LOOKUP_TYPE > GEOS_DECLTYPE_AUTO_RETURN @@ -1350,7 +1350,7 @@ class Group * this group that can be used in output messages. * @tparam KEY The lookup type. * @param key The value used to lookup the wrapper. - * @throw std::domain_error if the wrapper doesn't exist. + * @throw geos::DomainError if the wrapper doesn't exist. */ template< typename KEY > DataContext const & getWrapperDataContext( KEY key ) const @@ -1359,13 +1359,13 @@ class Group /** * @brief Access the group's parent. * @return reference to parent Group - * @throw std::domain_error if the Group doesn't have a parent. + * @throw geos::DomainError if the Group doesn't have a parent. */ Group & getParent() { GEOS_THROW_IF( m_parent == nullptr, "Group at " << getDataContext() << " does not have a parent.", - std::domain_error, getDataContext() ); + geos::DomainError, getDataContext() ); return *m_parent; } @@ -1376,7 +1376,7 @@ class Group { GEOS_THROW_IF( m_parent == nullptr, "Group at " << getDataContext() << " does not have a parent.", - std::domain_error, getDataContext() ); + geos::DomainError, getDataContext() ); return *m_parent; } diff --git a/src/coreComponents/dataRepository/GroupContext.cpp b/src/coreComponents/dataRepository/GroupContext.cpp index f5085f51663..04e1fa1f2a3 100644 --- a/src/coreComponents/dataRepository/GroupContext.cpp +++ b/src/coreComponents/dataRepository/GroupContext.cpp @@ -54,10 +54,11 @@ string GroupContext::toString() const return path.str(); } -ErrorLogger::ErrorContext GroupContext::getContextInfo() const +ErrorContext GroupContext::getContextInfo() const { - ErrorLogger::ErrorContext ctxInfo{ - { { ErrorLogger::ErrorContext::Attribute::DataPath, toString() } } // m_attributes + ErrorContext ctxInfo{ + toString(), + { { ErrorContext::Attribute::DataPath, GEOS_FMT( "{}/{}", m_group.getPath(), m_targetName )} } }; return ctxInfo; } diff --git a/src/coreComponents/dataRepository/GroupContext.hpp b/src/coreComponents/dataRepository/GroupContext.hpp index 182245baa10..abdc1199e7d 100644 --- a/src/coreComponents/dataRepository/GroupContext.hpp +++ b/src/coreComponents/dataRepository/GroupContext.hpp @@ -71,9 +71,9 @@ class GroupContext : public DataContext /** * @brief Return contextual information here it is a data path - * @return ErrorLogger::ErrorContext ErrorLogger instance updated with context information + * @return ErrorContext ErrorLogger instance updated with context information */ - ErrorLogger::ErrorContext getContextInfo() const override; + ErrorContext getContextInfo() const override; /** * @copydoc DataContext::getToStringInfo() diff --git a/src/coreComponents/dataRepository/WrapperContext.cpp b/src/coreComponents/dataRepository/WrapperContext.cpp index 50a37277e32..3d689ade254 100644 --- a/src/coreComponents/dataRepository/WrapperContext.cpp +++ b/src/coreComponents/dataRepository/WrapperContext.cpp @@ -38,10 +38,11 @@ string WrapperContext::toString() const GEOS_FMT( "{}/{}", m_group.getDataContext().toString(), m_typeName ); } -ErrorLogger::ErrorContext WrapperContext::getContextInfo() const +ErrorContext WrapperContext::getContextInfo() const { - ErrorLogger::ErrorContext ctxInfo{ - { { ErrorLogger::ErrorContext::Attribute::DataPath, toString() } } // m_attributes + ErrorContext ctxInfo{ + toString(), + {{ ErrorContext::Attribute::DataPath, GEOS_FMT( "{}/{}", m_group.getPath(), m_typeName ) } }, }; return ctxInfo; } diff --git a/src/coreComponents/dataRepository/WrapperContext.hpp b/src/coreComponents/dataRepository/WrapperContext.hpp index 40f36b135a3..b136a66862c 100644 --- a/src/coreComponents/dataRepository/WrapperContext.hpp +++ b/src/coreComponents/dataRepository/WrapperContext.hpp @@ -56,9 +56,9 @@ class WrapperContext final : public GroupContext /** * @brief Return contextual information here it is a data path - * @return ErrorLogger::ErrorContext ErrorLogger instance updated with context information + * @return ErrorContext ErrorLogger instance updated with context information */ - ErrorLogger::ErrorContext getContextInfo() const override; + ErrorContext getContextInfo() const override; }; diff --git a/src/coreComponents/dataRepository/python/PyGroup.cpp b/src/coreComponents/dataRepository/python/PyGroup.cpp index 9fa25b2db3c..db16370b826 100644 --- a/src/coreComponents/dataRepository/python/PyGroup.cpp +++ b/src/coreComponents/dataRepository/python/PyGroup.cpp @@ -194,8 +194,8 @@ static PyObject * PyGroup_getGroup( PyGroup * const self, PyObject * const args { return createNewPyGroup( self->group->getGroupByPath( path ) ); } - // If the path isn't valid then getGroupByPath will throw a std::domain_error - catch( std::domain_error const & e ) + // If the path isn't valid then getGroupByPath will throw a geos::DomainError + catch( geos::DomainError const & e ) { // If no default return value was specified then this results in a Python exception. if( defaultReturnValue == nullptr ) @@ -259,8 +259,8 @@ static PyObject * PyGroup_getWrapper( PyGroup * const self, PyObject * const arg dataRepository::WrapperBase & wrapper = group.getWrapperBase( wrapperName ); return createNewPyWrapper( wrapper ); } - // If the path isn't valid then either getGroupByPath or getWrapperBase will throw a std::domain_error - catch( std::domain_error const & e ) + // If the path isn't valid then either getGroupByPath or getWrapperBase will throw a geos::DomainError + catch( geos::DomainError const & e ) { // If no default return value was specified then this results in a Python exception. if( defaultReturnValue == nullptr ) diff --git a/src/coreComponents/dataRepository/unitTests/testErrorHandling.cpp b/src/coreComponents/dataRepository/unitTests/testErrorHandling.cpp index 39103cc5580..ce69c14998c 100644 --- a/src/coreComponents/dataRepository/unitTests/testErrorHandling.cpp +++ b/src/coreComponents/dataRepository/unitTests/testErrorHandling.cpp @@ -30,8 +30,8 @@ using namespace dataRepository; namespace fs = std::filesystem; // redeging logger instance to test macros with a local instance (to prevent any side effect) -#undef GEOS_ERROR_LOGGER_INSTANCE -#define GEOS_ERROR_LOGGER_INSTANCE testErrorLogger +#undef GEOS_GLOBAL_LOGGER +#define GEOS_GLOBAL_LOGGER testErrorLogger // declare a constant which value is the source file line (to predict the error file output). #define GET_LINE( lineVar ) static size_t constexpr lineVar = __LINE__ @@ -114,7 +114,6 @@ TEST( ErrorHandling, testYamlFileWarningOutput ) string const warningMsg = GEOS_FMT( "{}: option should be between {} and {}. A value of {} will be used.", context.toString(), testMinPrecision, testMaxPrecision, testMinPrecision ); GET_LINE( line3 ); GEOS_WARNING_IF( testValue == 5, warningMsg, context, additionalContext ); - endLocalLoggerTest( testErrorLogger, { R"(errors:)", @@ -149,9 +148,11 @@ TEST( ErrorHandling, testYamlFileWarningOutput ) Base Test Class (file.xml, l.23): option should be between 1e-06 and 0.001. A value of 1e-06 will be used. contexts: - priority: 0 + description: Base Test Class (file.xml, l.23) inputFile: /path/to/file.xml inputLine: 23 - priority: 0 + description: Additional Test Class (file.xml, l.32) inputFile: /path/to/file.xml inputLine: 32 cause: >- @@ -166,42 +167,54 @@ TEST( ErrorHandling, testYamlFileWarningOutput ) TEST( ErrorHandling, testYamlFileExceptionOutput ) { ErrorLogger testErrorLogger; - - beginLocalLoggerTest( testErrorLogger, "exceptionTestOutput.yaml" ); + string const file = "exceptionTestOutput.yaml"; + beginLocalLoggerTest( testErrorLogger, file ); size_t line1; // Stacked exception test (contexts must appear sorted by priority) try { - line1 = __LINE__; GEOS_THROW_IF( testValue == 5, "Empty Group: " << context.toString(), std::domain_error, context ); + line1 = __LINE__; GEOS_THROW_IF( testValue == 5, "Empty Group", geos::DomainError, context.getContextInfo() ); } - catch( std::domain_error const & ex ) + catch( geos::DomainError const & ex ) { string const errorMsg = "Table input error.\n"; - testErrorLogger.currentErrorMsg() + testErrorLogger.modifyCurrentExceptionMessage() .addToMsg( errorMsg ) .addContextInfo( additionalContext.getContextInfo() ) - .addContextInfo( importantAdditionalContext.getContextInfo().setPriority( 2 ) ); + .addContextInfo( importantAdditionalContext.getContextInfo().setPriority( 2 ) ).get(); + string const whatExpected = GEOS_FMT( "***** GEOS Exception\n" + "***** LOCATION: {}:{}\n" + "***** Error cause: testValue == 5\n" + "***** Rank 0: Empty Group", + testErrorLogger.getCurrentExceptionMsg().m_file, line1 ); + + GEOS_ERROR_IF_EQ_MSG( string( ex.what()).find( whatExpected ), string::npos, + "The error message was not containing the expected sequence.\n" << + " Error message :\n" << ex.what() << + " expected sequence :\n" << whatExpected ); } - testErrorLogger.flushErrorMsg( testErrorLogger.currentErrorMsg() ); + testErrorLogger.flushCurrentExceptionMessage(); endLocalLoggerTest( testErrorLogger, { R"(errors:)", - GEOS_FMT( R"(- type: Exception rank: 0 message: >- Table input error. - Empty Group: Base Test Class (file.xml, l.23) + Empty Group contexts: - priority: 2 + description: Important Additional Test Class (file.xml, l.64) inputFile: /path/to/file.xml inputLine: 64 - priority: 0 + description: Base Test Class (file.xml, l.23) inputFile: /path/to/file.xml inputLine: 23 - priority: 0 + description: Additional Test Class (file.xml, l.32) inputFile: /path/to/file.xml inputLine: 32 cause: >- @@ -242,12 +255,15 @@ TEST( ErrorHandling, testYamlFileErrorOutput ) Base Test Class (file.xml, l.23): option should be lower than 0.001. contexts: - priority: 2 + description: Important Additional Test Class (file.xml, l.64) inputFile: /path/to/file.xml inputLine: 64 - priority: 0 + description: Base Test Class (file.xml, l.23) inputFile: /path/to/file.xml inputLine: 23 - priority: 0 + description: Additional Test Class (file.xml, l.32) inputFile: /path/to/file.xml inputLine: 32 cause: >- @@ -264,6 +280,85 @@ TEST( ErrorHandling, testYamlFileErrorOutput ) } ); } + +TEST( ErrorHandling, testLogFileExceptionOutput ) +{ + ErrorLogger testErrorLogger; + + size_t line1; + + try + { + line1 = __LINE__; GEOS_THROW_IF( testValue == 5, "Empty Group", geos::DomainError, context ); + } + catch( geos::DomainError const & ex ) + { + string const errorMsg = "Table input error.\n"; + testErrorLogger.modifyCurrentExceptionMessage() + .addToMsg( errorMsg ) + .addContextInfo( additionalContext.getContextInfo() ) + .addContextInfo( importantAdditionalContext.getContextInfo().setPriority( 2 )).get(); + string const streamExpected = GEOS_FMT( + "***** Exception\n" + "***** LOCATION: {}:{}\n" + "***** {}\n" + "***** Rank 0\n" + "***** Message from {}:\n" + "{}\n" + "***** Additional contexts:\n" + "***** - {}\n" + "***** - {}\n", + testErrorLogger.getCurrentExceptionMsg().m_file, line1, + testErrorLogger.getCurrentExceptionMsg().m_cause, + context.toString(), + testErrorLogger.getCurrentExceptionMsg().m_msg, + additionalContext.toString(), + importantAdditionalContext.toString(), testErrorLogger.getCurrentExceptionMsg().m_sourceCallStack ); + std::ostringstream oss; + ErrorLogger::writeToAscii( testErrorLogger.getCurrentExceptionMsg(), oss ); + GEOS_ERROR_IF_EQ_MSG( oss.str().find( streamExpected ), string::npos, + "The error message was not containing the expected sequence.\n" << + "The error message was not containing the expected sequence.\n" << + " Error message :\n" <- diff --git a/src/coreComponents/events/EventBase.cpp b/src/coreComponents/events/EventBase.cpp index 1984ec59fbc..ebb10b1e47c 100644 --- a/src/coreComponents/events/EventBase.cpp +++ b/src/coreComponents/events/EventBase.cpp @@ -153,10 +153,12 @@ void EventBase::getTargetReferences() { string const errorMsg = GEOS_FMT( "Error while reading {}:\n", getWrapperDataContext( viewKeyStruct::eventTargetString() ) ); - ErrorLogger::global().currentErrorMsg() + + ErrorLogger::global().modifyCurrentExceptionMessage() .addToMsg( errorMsg ) .addContextInfo( getWrapperDataContext( viewKeyStruct::eventTargetString() ).getContextInfo() - .setPriority( 1 ) ); + .setPriority( 1 )) + .get(); throw InputError( e, errorMsg ); } } diff --git a/src/coreComponents/fieldSpecification/FieldSpecificationBase.cpp b/src/coreComponents/fieldSpecification/FieldSpecificationBase.cpp index 47209289471..a3697cc69ef 100644 --- a/src/coreComponents/fieldSpecification/FieldSpecificationBase.cpp +++ b/src/coreComponents/fieldSpecification/FieldSpecificationBase.cpp @@ -119,11 +119,12 @@ void FieldSpecificationBase::setMeshObjectPath( Group const & meshBodies ) } catch( std::exception const & e ) { - ErrorLogger::global().currentErrorMsg() + ErrorLogger::global().modifyCurrentExceptionMessage() .addToMsg( getWrapperDataContext( viewKeyStruct::objectPathString() ).toString() + " is a wrong objectPath: " + m_objectPath + "\n" ) .addContextInfo( getWrapperDataContext( viewKeyStruct::objectPathString() ).getContextInfo() - .setPriority( 2 ) ); + .setPriority( 2 ) ) + .get(); throw InputError( e, getWrapperDataContext( viewKeyStruct::objectPathString() ).toString() + " is a wrong objectPath: " + m_objectPath + "\n" ); } diff --git a/src/coreComponents/fieldSpecification/FieldSpecificationBase.hpp b/src/coreComponents/fieldSpecification/FieldSpecificationBase.hpp index 2880b4811a6..f139552702b 100644 --- a/src/coreComponents/fieldSpecification/FieldSpecificationBase.hpp +++ b/src/coreComponents/fieldSpecification/FieldSpecificationBase.hpp @@ -638,10 +638,11 @@ void FieldSpecificationBase::applyFieldValueKernel( ArrayView< T, N, USD > const { string const errorMsg = GEOS_FMT( "Error while reading {}:\n", getWrapperDataContext( viewKeyStruct::functionNameString() ) ); - ErrorLogger::global().currentErrorMsg() + ErrorLogger::global().modifyCurrentExceptionMessage() .addToMsg( errorMsg ) .addContextInfo( getWrapperDataContext( viewKeyStruct::functionNameString() ).getContextInfo() - .setPriority( 1 ) ); + .setPriority( 1 ) ) + .get(); throw InputError( e, errorMsg ); } }(); diff --git a/src/coreComponents/fileIO/Outputs/TimeHistoryOutput.cpp b/src/coreComponents/fileIO/Outputs/TimeHistoryOutput.cpp index ed84a72833b..a198963203c 100644 --- a/src/coreComponents/fileIO/Outputs/TimeHistoryOutput.cpp +++ b/src/coreComponents/fileIO/Outputs/TimeHistoryOutput.cpp @@ -145,10 +145,11 @@ void TimeHistoryOutput::initializePostInitialConditionsPostSubGroups() { string const errorMsg = GEOS_FMT( "Error while reading {}:\n", getWrapperDataContext( viewKeys::timeHistoryOutputTargetString() ) ); - ErrorLogger::global().currentErrorMsg() + ErrorLogger::global().modifyCurrentExceptionMessage() .addToMsg( errorMsg ) .addContextInfo( getWrapperDataContext( viewKeys::timeHistoryOutputTargetString() ).getContextInfo() - .setPriority( 1 ) ); + .setPriority( 1 ) ) + .get(); throw InputError( e, errorMsg ); } } diff --git a/src/coreComponents/fileIO/timeHistory/HistoryCollectionBase.cpp b/src/coreComponents/fileIO/timeHistory/HistoryCollectionBase.cpp index dc17c782fe3..519e71acf4b 100644 --- a/src/coreComponents/fileIO/timeHistory/HistoryCollectionBase.cpp +++ b/src/coreComponents/fileIO/timeHistory/HistoryCollectionBase.cpp @@ -128,7 +128,7 @@ dataRepository::Group const * HistoryCollectionBase::getTargetObject( DomainPart GEOS_THROW_IF( !bodyFound, GEOS_FMT( "MeshBody ({}) is specified, but not found.", targetTokens[0] ), - std::domain_error ); + geos::DomainError ); } string const meshBodyName = targetTokens[0]; @@ -158,7 +158,7 @@ dataRepository::Group const * HistoryCollectionBase::getTargetObject( DomainPart GEOS_THROW_IF( !levelFound, GEOS_FMT( "MeshLevel ({}) is specified, but not found.", targetTokens[1] ), - std::domain_error ); + geos::DomainError ); } } else if( !meshBody.getMeshLevels().hasGroup< MeshLevel >( targetTokens[1] ) ) @@ -179,7 +179,7 @@ dataRepository::Group const * HistoryCollectionBase::getTargetObject( DomainPart GEOS_THROW_IF( targetTokens.size() <= 4, GEOS_FMT( " Object Path '{}' does not target any element sub region", objectPath ), - std::runtime_error ); + geos::RuntimeError ); ElementRegionManager const & elemRegionManager = meshLevel.getElemManager(); string const elemRegionName = targetTokens[3]; ElementRegionBase const & elemRegion = elemRegionManager.getRegion( elemRegionName ); @@ -200,7 +200,7 @@ dataRepository::Group const * HistoryCollectionBase::getTargetObject( DomainPart { GEOS_THROW( targetTokens[pathLevel] << " not found in path " << objectPath << std::endl << targetGroup->dumpSubGroupsNames(), - std::domain_error ); + geos::DomainError ); } } } @@ -209,9 +209,10 @@ dataRepository::Group const * HistoryCollectionBase::getTargetObject( DomainPart } catch( std::exception const & e ) { - ErrorLogger::global().currentErrorMsg() + ErrorLogger::global().modifyCurrentExceptionMessage() .addToMsg( getDataContext().toString() + " has a wrong objectPath: " + objectPath + "\n" ) - .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); + .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ) + .get(); throw InputError( e, getDataContext().toString() + " has a wrong objectPath: " + objectPath + "\n" ); } } diff --git a/src/coreComponents/fileIO/timeHistory/PackCollection.cpp b/src/coreComponents/fileIO/timeHistory/PackCollection.cpp index ff9b229cec1..5f0cc9319a6 100644 --- a/src/coreComponents/fileIO/timeHistory/PackCollection.cpp +++ b/src/coreComponents/fileIO/timeHistory/PackCollection.cpp @@ -153,11 +153,12 @@ void PackCollection::updateSetsIndices( DomainPartition const & domain ) } catch( std::exception const & e ) { - ErrorLogger::global().currentErrorMsg() + ErrorLogger::global().modifyCurrentExceptionMessage() .addToMsg( getWrapperDataContext( viewKeysStruct::fieldNameString() ).toString() + ": Target not found !\n" ) .addContextInfo( getWrapperDataContext( viewKeysStruct::fieldNameString() ).getContextInfo() - .setPriority( 1 ) ); + .setPriority( 1 ) ) + .get(); throw InputError( e, getWrapperDataContext( viewKeysStruct::fieldNameString() ).toString() + ": Target not found !\n" ); } diff --git a/src/coreComponents/functions/TableFunction.cpp b/src/coreComponents/functions/TableFunction.cpp index 7ee6c4a3490..4446d2be72b 100644 --- a/src/coreComponents/functions/TableFunction.cpp +++ b/src/coreComponents/functions/TableFunction.cpp @@ -81,7 +81,7 @@ void TableFunction::readFile( string const & filename, array1d< real64 > & targe { parseFile( filename, target, skipped ); } - catch( std::runtime_error const & e ) + catch( geos::RuntimeError const & e ) { GEOS_THROW( GEOS_FMT( "{} {}: {}", catalogName(), getDataContext(), e.what() ), InputError ); } diff --git a/src/coreComponents/integrationTests/dataRepositoryTests/testGroupPath.cpp b/src/coreComponents/integrationTests/dataRepositoryTests/testGroupPath.cpp index 3927a3812b4..ab53f2b4f89 100644 --- a/src/coreComponents/integrationTests/dataRepositoryTests/testGroupPath.cpp +++ b/src/coreComponents/integrationTests/dataRepositoryTests/testGroupPath.cpp @@ -14,6 +14,7 @@ */ // Source includes +#include "common/logger/ErrorHandling.hpp" #include "mainInterface/ProblemManager.hpp" #include "mainInterface/initialization.hpp" #include "mainInterface/GeosxState.hpp" @@ -104,13 +105,17 @@ TEST( testGroupPath, testGlobalPaths ) { problem.getGroupByPath( "/Mesh/mesh2" ); } - catch( const std::domain_error & e ) + catch( geos::Exception & e ) { static constexpr auto expectedMsg = "***** Error cause: child == nullptr\n" - "***** Rank 0: Group Mesh (CodeIncludedXML0, l.10) has no child named mesh2\n" + "***** Rank 0\n" + "***** Message from Mesh (CodeIncludedXML0, l.10):\n" + "Group Mesh (CodeIncludedXML0, l.10) has no child named mesh2\n" "The children of Mesh are: { mesh1 }"; // checks if the exception contains the expected message - GEOS_ERROR_IF_EQ_MSG( string( e.what() ).find( expectedMsg ), string::npos, + std::ostringstream stream; + geos::ErrorLogger::writeToAscii( ErrorLogger::global().getCurrentExceptionMsg(), stream ); + GEOS_ERROR_IF_EQ_MSG( string( stream.str() ).find( expectedMsg ), string::npos, "The error message was not containing the expected sequence.\n" << " Error message :\n" << e.what() << " expected sequence :\n" << expectedMsg ); diff --git a/src/coreComponents/linearAlgebra/multiscale/mesh/coarsening/MetisInterface.cpp b/src/coreComponents/linearAlgebra/multiscale/mesh/coarsening/MetisInterface.cpp index 7fdfcb333b4..df30b457b45 100644 --- a/src/coreComponents/linearAlgebra/multiscale/mesh/coarsening/MetisInterface.cpp +++ b/src/coreComponents/linearAlgebra/multiscale/mesh/coarsening/MetisInterface.cpp @@ -87,7 +87,7 @@ void partition( CRSMatrixView< int64_t const, int64_t const, int64_t const > con options, // options &objval, // edgecut partition.data() ); // part - GEOS_THROW_IF_NE_MSG( result, METIS_OK, "METIS call failed", std::runtime_error ); + GEOS_THROW_IF_NE_MSG( result, METIS_OK, "METIS call failed", geos::RuntimeError ); } } // namespace metis diff --git a/src/coreComponents/linearAlgebra/multiscale/mesh/coarsening/PartitionerBase.cpp b/src/coreComponents/linearAlgebra/multiscale/mesh/coarsening/PartitionerBase.cpp index ea0d251b4c7..14a1d37d325 100644 --- a/src/coreComponents/linearAlgebra/multiscale/mesh/coarsening/PartitionerBase.cpp +++ b/src/coreComponents/linearAlgebra/multiscale/mesh/coarsening/PartitionerBase.cpp @@ -38,7 +38,7 @@ PartitionerBase::create( LinearSolverParameters::Multiscale::Coarsening params ) case PartitionType::semistructured: return std::make_unique< SemistructuredPartitioner >( std::move( params ) ); default: { - GEOS_THROW( "Multiscale partitioning not supported yet: " << params.partitionType, std::runtime_error ); + GEOS_THROW( "Multiscale partitioning not supported yet: " << params.partitionType, geos::RuntimeError ); } } } diff --git a/src/coreComponents/mainInterface/GeosxState.cpp b/src/coreComponents/mainInterface/GeosxState.cpp index 5929b2c99d3..42ec604d228 100644 --- a/src/coreComponents/mainInterface/GeosxState.cpp +++ b/src/coreComponents/mainInterface/GeosxState.cpp @@ -126,7 +126,7 @@ bool GeosxState::initializeDataRepository() GEOS_MARK_FUNCTION; Timer timer( m_initTime ); - GEOS_THROW_IF_NE( m_state, State::UNINITIALIZED, std::logic_error ); + GEOS_THROW_IF_NE( m_state, State::UNINITIALIZED, geos::LogicError ); getProblemManager().parseCommandLineInput(); @@ -156,7 +156,7 @@ void GeosxState::applyInitialConditions() GEOS_MARK_FUNCTION; Timer timer( m_initTime ); - GEOS_THROW_IF_NE( m_state, State::INITIALIZED, std::logic_error ); + GEOS_THROW_IF_NE( m_state, State::INITIALIZED, geos::LogicError ); getProblemManager().applyInitialConditions(); @@ -175,7 +175,7 @@ void GeosxState::run() GEOS_MARK_FUNCTION; Timer timer( m_runTime ); - GEOS_THROW_IF_NE( m_state, State::READY_TO_RUN, std::logic_error ); + GEOS_THROW_IF_NE( m_state, State::READY_TO_RUN, geos::LogicError ); if( getCommandLineOptions().onlyValidateInput ) { diff --git a/src/coreComponents/mainInterface/ProblemManager.cpp b/src/coreComponents/mainInterface/ProblemManager.cpp index ed85797f2c2..8723a833532 100644 --- a/src/coreComponents/mainInterface/ProblemManager.cpp +++ b/src/coreComponents/mainInterface/ProblemManager.cpp @@ -500,9 +500,10 @@ void ProblemManager::parseXMLDocument( xmlWrapper::xmlDocument & xmlDocument ) { string const errorMsg = GEOS_FMT( "Error while parsing region {} ({}):\n", regionName, regionNodePos.toString() ); - ErrorLogger::global().currentErrorMsg() + ErrorLogger::global().modifyCurrentExceptionMessage() .addToMsg( errorMsg ) - .addContextInfo( getDataContext().getContextInfo().setPriority( -1 ) ); + .addContextInfo( getDataContext().getContextInfo().setPriority( -1 ) ) + .get(); throw InputError( e, errorMsg ); } } diff --git a/src/coreComponents/mesh/FaceManager.cpp b/src/coreComponents/mesh/FaceManager.cpp index 1cf388d34f4..8d2ea35103b 100644 --- a/src/coreComponents/mesh/FaceManager.cpp +++ b/src/coreComponents/mesh/FaceManager.cpp @@ -298,9 +298,10 @@ void FaceManager::sortAllFaceNodes( NodeManager const & nodeManager, sortFaceNodes( X, elemCenter[er][esr][ei], facesToNodes[faceIndex] ); } catch( std::runtime_error const & e ) { - ErrorLogger::global().currentErrorMsg() + ErrorLogger::global().modifyCurrentExceptionMessage() .addToMsg( getDataContext().toString() + ": " + e.what() ) - .addContextInfo( getDataContext().getContextInfo().setPriority( 1 ) ); + .addContextInfo( getDataContext().getContextInfo().setPriority( 1 ) ) + .get(); throw std::runtime_error( getDataContext().toString() + ": " + e.what() ); } } ); @@ -314,7 +315,7 @@ void FaceManager::sortFaceNodes( arrayView2d< real64 const, nodes::REFERENCE_POS GEOS_THROW_IF_GT_MSG( numFaceNodes, MAX_FACE_NODES, GEOS_FMT( "The number of maximum nodes allocated per cell face has been reached " "at position {}.", elementCenter ), - std::runtime_error ); + geos::RuntimeError ); localIndex const firstNodeIndex = faceNodes[0]; diff --git a/src/coreComponents/mesh/generators/InternalMeshGenerator.cpp b/src/coreComponents/mesh/generators/InternalMeshGenerator.cpp index 0eac2831c21..2c4943f5b92 100644 --- a/src/coreComponents/mesh/generators/InternalMeshGenerator.cpp +++ b/src/coreComponents/mesh/generators/InternalMeshGenerator.cpp @@ -183,12 +183,13 @@ void InternalMeshGenerator::postInputInitialization() } catch( InputError const & e ) { WrapperBase const & wrapper = getWrapperBase( viewKeyStruct::elementTypesString() ); - std::string const msg = GEOS_FMT( "InternalMesh {}, element index = {}: ", - wrapper.getDataContext().toString(), std::to_string( i ) ); - ErrorLogger::global().currentErrorMsg() - .addToMsg( msg ) - .addContextInfo( wrapper.getDataContext().getContextInfo().setPriority( 2 ) ); - throw InputError( e, msg ); + std::string const exceptionMsg = GEOS_FMT( "InternalMesh {}, element index = {}: ", + wrapper.getDataContext().toString(), std::to_string( i ) ); + ErrorLogger::global().modifyCurrentExceptionMessage() + .addToMsg( exceptionMsg ) + .addContextInfo( wrapper.getDataContext().getContextInfo().setPriority( 2 ) ) + .get(); + throw InputError( e, exceptionMsg ); } } diff --git a/src/coreComponents/mesh/generators/VTKUtilities.cpp b/src/coreComponents/mesh/generators/VTKUtilities.cpp index 1f21a300d52..bdda87aff30 100644 --- a/src/coreComponents/mesh/generators/VTKUtilities.cpp +++ b/src/coreComponents/mesh/generators/VTKUtilities.cpp @@ -1170,7 +1170,7 @@ ensureNoEmptyRank( vtkSmartPointer< vtkDataSet > mesh, localIndex const lastRecipientPosition = firstRecipientPosition + numElems - 1; GEOS_THROW_IF( isLastDonor && ( lastRecipientPosition < recipientRanks.size() ), "The current implementation is unable to guarantee that all ranks have at least one element", - std::runtime_error ); + geos::RuntimeError ); for( localIndex iElem = 1; iElem < numElems; ++iElem ) // I only keep my first element { diff --git a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp index 8d301476cc5..2c40697121a 100644 --- a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp @@ -1174,7 +1174,7 @@ real64 PhysicsSolverBase::explicitStep( real64 const & GEOS_UNUSED_PARAM( time_n integer const GEOS_UNUSED_PARAM( cycleNumber ), DomainPartition & GEOS_UNUSED_PARAM( domain ) ) { - GEOS_THROW( "PhysicsSolverBase::ExplicitStep called!. Should be overridden.", std::runtime_error ); + GEOS_THROW( "PhysicsSolverBase::ExplicitStep called!. Should be overridden.", geos::RuntimeError ); return 0; } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp index ec8268e0079..82973f52e61 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp @@ -1396,7 +1396,7 @@ void CompositionalMultiphaseBase::computeHydrostaticEquilibrium( DomainPartition ": hydrostatic pressure initialization failed to converge in region " << region.getName() << "! \n" << "Try to loosen the equilibration tolerance, or increase the number of equilibration iterations. \n" << "If nothing works, something may be wrong in the fluid model, see ", - std::runtime_error, getDataContext() ); + geos::RuntimeError, getDataContext() ); if( singlePhaseInitialisation ) { diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 7f1998b66a1..2a624108899 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -182,7 +182,7 @@ void CompositionalMultiphaseHybridFVM::initializePostInitialConditionsPreSubGrou GEOS_THROW_IF( minVal.get() <= 0.0, getCatalogName() << " " << getDataContext() << ": the transmissibility multipliers used in SinglePhaseHybridFVM must be strictly larger than 0.0", - std::runtime_error ); + geos::RuntimeError ); // Initialize face-based constitutive property arrays to zero to prevent uninitialized memory usage on GPU arrayView2d< real64, compflow::USD_PHASE > facePhaseMob = faceManager.getField< flow::facePhaseMobility >(); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseBase.cpp index 6fca54281ae..5dc05b9fc56 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseBase.cpp @@ -579,7 +579,7 @@ void SinglePhaseBase::computeHydrostaticEquilibrium( DomainPartition & domain ) GEOS_THROW_IF( !equilHasConverged, getCatalogName() << " " << getDataContext() << ": hydrostatic pressure initialization failed to converge in region " << region.getName() << "!", - std::runtime_error, getDataContext() ); + geos::RuntimeError, getDataContext() ); } ); // Step 3.4: create hydrostatic pressure table diff --git a/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseHybridFVM.cpp index 5ae213a31b2..b31b42dcb35 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseHybridFVM.cpp @@ -141,7 +141,7 @@ void SinglePhaseHybridFVM::initializePostInitialConditionsPreSubGroups() GEOS_THROW_IF_LE_MSG( minVal.get(), 0.0, getCatalogName() << " " << getDataContext() << "The transmissibility multipliers used in SinglePhaseHybridFVM must strictly larger than 0.0", - std::runtime_error ); + geos::RuntimeError ); FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); fsManager.forSubGroups< AquiferBoundaryCondition >( [&] ( AquiferBoundaryCondition const & bc ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 28def34e770..b214b6ff0e0 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -353,9 +353,10 @@ void CompositionalMultiphaseWell::validateWellControlsForFluid( WellControls con } catch( SimulationError const & ex ) { string const errorMsg = GEOS_FMT( "{}: wrong surface pressure / temperature.\n", getDataContext() ); - ErrorLogger::global().currentErrorMsg() + ErrorLogger::global().modifyCurrentExceptionMessage() .addToMsg( errorMsg ) - .addContextInfo( getDataContext().getContextInfo().setPriority( 1 ) ); + .addContextInfo( getDataContext().getContextInfo().setPriority( 1 ) ) + .get(); throw SimulationError( ex, errorMsg ); } } diff --git a/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp b/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp index 425bccfa72c..00e98cfcdcd 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp +++ b/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp @@ -291,7 +291,7 @@ assembleCouplingTerms( real64 const time_n, GEOS_THROW_IF( !Base::m_isWellTransmissibilityComputed, GEOS_FMT( "{} {}: The well transmissibility has not been computed yet", this->getCatalogName(), this->getName() ), - std::runtime_error ); + geos::RuntimeError ); BitFlags< isothermalCompositionalMultiphaseBaseKernels::KernelFlags > kernelFlags; if( Base::wellSolver()->useTotalMassEquation() ) diff --git a/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellsBase.cpp b/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellsBase.cpp index fbb8e7fb935..26355f4b610 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellsBase.cpp +++ b/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellsBase.cpp @@ -157,7 +157,7 @@ bool validateWellPerforations( PhysicsSolverBase const * const reservoirSolver, GEOS_THROW_IF( !badPerforation.first.empty(), GEOS_FMT( "{}: The well {} has a connection to the region {} which is not targeted by the flow solver", wellSolver->getDataContext(), badPerforation.first, badPerforation.second ), - std::runtime_error, wellSolver->getDataContext() ); + geos::RuntimeError, wellSolver->getDataContext() ); return hasBadPerforations == 0; } diff --git a/src/coreComponents/physicsSolvers/multiphysics/SinglePhaseReservoirAndWells.cpp b/src/coreComponents/physicsSolvers/multiphysics/SinglePhaseReservoirAndWells.cpp index 46cf3257088..acdc445d705 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/SinglePhaseReservoirAndWells.cpp +++ b/src/coreComponents/physicsSolvers/multiphysics/SinglePhaseReservoirAndWells.cpp @@ -249,7 +249,7 @@ assembleCouplingTerms( real64 const time_n, GEOS_THROW_IF( !Base::m_isWellTransmissibilityComputed, GEOS_FMT( "{} {}: The well transmissibility has not been computed yet", this->getCatalogName(), this->getName() ), - std::runtime_error ); + geos::RuntimeError ); this->template forDiscretizationOnMeshTargets<>( domain.getMeshBodies(), [&] ( string const &, MeshLevel const & mesh, diff --git a/src/coreComponents/physicsSolvers/wavePropagation/sem/acoustic/secondOrderEqn/isotropic/AcousticWaveEquationSEM.cpp b/src/coreComponents/physicsSolvers/wavePropagation/sem/acoustic/secondOrderEqn/isotropic/AcousticWaveEquationSEM.cpp index 6190586dded..95cd1f636f0 100644 --- a/src/coreComponents/physicsSolvers/wavePropagation/sem/acoustic/secondOrderEqn/isotropic/AcousticWaveEquationSEM.cpp +++ b/src/coreComponents/physicsSolvers/wavePropagation/sem/acoustic/secondOrderEqn/isotropic/AcousticWaveEquationSEM.cpp @@ -293,7 +293,7 @@ void AcousticWaveEquationSEM::addSourceToRightHandSide( integer const cycleNumbe GEOS_THROW_IF( cycleNumber > sourceValue.size( 0 ), getDataContext() << ": Too many steps compared to array size", - std::runtime_error, getDataContext() ); + geos::RuntimeError, getDataContext() ); forAll< EXEC_POLICY >( sourceConstants.size( 0 ), [=] GEOS_HOST_DEVICE ( localIndex const isrc ) { if( sourceIsAccessible[isrc] == 1 ) @@ -555,7 +555,7 @@ real64 AcousticWaveEquationSEM::computeTimeStep( real64 & dtOut ) } while (counter < 10 && numberIter < nIterMax); - GEOS_THROW_IF( numberIter> nIterMax, "Power Iteration algorithm does not converge", std::runtime_error ); + GEOS_THROW_IF( numberIter> nIterMax, "Power Iteration algorithm does not converge", geos::RuntimeError ); // We use 1.99 instead of 2 to have a 5% margin error real64 dt = 1.99/sqrt( LvArray::math::abs( lambdaNew )); diff --git a/src/coreComponents/physicsSolvers/wavePropagation/sem/acoustoelastic/secondOrderEqn/isotropic/AcousticElasticWaveEquationSEM.cpp b/src/coreComponents/physicsSolvers/wavePropagation/sem/acoustoelastic/secondOrderEqn/isotropic/AcousticElasticWaveEquationSEM.cpp index 9059a3f8a27..b543c6643d5 100644 --- a/src/coreComponents/physicsSolvers/wavePropagation/sem/acoustoelastic/secondOrderEqn/isotropic/AcousticElasticWaveEquationSEM.cpp +++ b/src/coreComponents/physicsSolvers/wavePropagation/sem/acoustoelastic/secondOrderEqn/isotropic/AcousticElasticWaveEquationSEM.cpp @@ -61,7 +61,7 @@ void AcousticElasticWaveEquationSEM::initializePostInitialConditionsPreSubGroups m_interfaceNodesSet.insert( val ); } localIndex const numInterfaceNodes = MpiWrapper::sum( m_interfaceNodesSet.size() ); - GEOS_THROW_IF( numInterfaceNodes == 0, "Failed to compute interface: check xml input (solver order)", std::runtime_error ); + GEOS_THROW_IF( numInterfaceNodes == 0, "Failed to compute interface: check xml input (solver order)", geos::RuntimeError ); m_acousRegions = &(acousSolver->getReference< string_array >( PhysicsSolverBase::viewKeyStruct::targetRegionsString() )); m_elasRegions = &(elasSolver->getReference< string_array >( PhysicsSolverBase::viewKeyStruct::targetRegionsString() )); diff --git a/src/coreComponents/physicsSolvers/wavePropagation/sem/elastic/secondOrderEqn/anisotropic/ElasticVTIWaveEquationSEMKernel.hpp b/src/coreComponents/physicsSolvers/wavePropagation/sem/elastic/secondOrderEqn/anisotropic/ElasticVTIWaveEquationSEMKernel.hpp index dce27fada16..3b70241a7ec 100644 --- a/src/coreComponents/physicsSolvers/wavePropagation/sem/elastic/secondOrderEqn/anisotropic/ElasticVTIWaveEquationSEMKernel.hpp +++ b/src/coreComponents/physicsSolvers/wavePropagation/sem/elastic/secondOrderEqn/anisotropic/ElasticVTIWaveEquationSEMKernel.hpp @@ -308,7 +308,7 @@ struct ComputeTimeStep } while (counter < 10 && numberIter < nIterMax); - GEOS_THROW_IF( numberIter> nIterMax, "Power Iteration algorithm does not converge", std::runtime_error ); + GEOS_THROW_IF( numberIter> nIterMax, "Power Iteration algorithm does not converge", RuntimeError ); real64 dt = 1.99/sqrt( LvArray::math::abs( lambdaNew )); diff --git a/src/coreComponents/physicsSolvers/wavePropagation/sem/elastic/secondOrderEqn/isotropic/ElasticWaveEquationSEM.cpp b/src/coreComponents/physicsSolvers/wavePropagation/sem/elastic/secondOrderEqn/isotropic/ElasticWaveEquationSEM.cpp index 2c16780151b..2b5e34323c7 100644 --- a/src/coreComponents/physicsSolvers/wavePropagation/sem/elastic/secondOrderEqn/isotropic/ElasticWaveEquationSEM.cpp +++ b/src/coreComponents/physicsSolvers/wavePropagation/sem/elastic/secondOrderEqn/isotropic/ElasticWaveEquationSEM.cpp @@ -680,7 +680,7 @@ real64 ElasticWaveEquationSEM::computeTimeStep( real64 & dtOut ) } while (counter < 10 && numberIter < nIterMax); - GEOS_THROW_IF( numberIter> nIterMax, "Power Iteration algorithm does not converge", std::runtime_error ); + GEOS_THROW_IF( numberIter> nIterMax, "Power Iteration algorithm does not converge", geos::RuntimeError ); //We use 1.99 instead of 2 to have a 5% margin error real64 dt = 1.99/sqrt( LvArray::math::abs( lambdaNew )); diff --git a/src/coreComponents/schema/schema.xsd b/src/coreComponents/schema/schema.xsd index 98b399613cb..80750753fcd 100644 --- a/src/coreComponents/schema/schema.xsd +++ b/src/coreComponents/schema/schema.xsd @@ -3655,8 +3655,9 @@ Information output from lower logLevels is added with the desired log level +Frequency of pressure update is set in SinglePhase/CompositionalMultiphaseStatistics definition. +Setting cycleFrequency='1' will update the pressure every timestep, note that is a lagged property in constraint propertiesNote the event associated with the statists task must be entered before the solver event. +--> @@ -8403,7 +8404,7 @@ The expected format is "{ waterMax, oilMax }", in that order--> - + diff --git a/src/main/main.cpp b/src/main/main.cpp index 14750a4d4a1..1b229d56964 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -14,8 +14,7 @@ */ // Source includes -#include "common/DataTypes.hpp" -#include "common/format/Format.hpp" +#include "common/logger/Logger.hpp" #include "common/TimingMacros.hpp" #include "common/Units.hpp" #include "mainInterface/initialization.hpp" @@ -74,16 +73,24 @@ int main( int argc, char *argv[] ) basicCleanup(); return 0; } - catch( std::exception const & e ) - { - GEOS_LOG( e.what() ); - if( ErrorLogger::global().isOutputFileEnabled() ) - { - ErrorLogger::global().flushErrorMsg( ErrorLogger::global().currentErrorMsg() ); - } + catch( geos::Exception & e ) + { // GEOS generated exceptions management + ErrorLogger::global().flushCurrentExceptionMessage(); + basicCleanup(); + // lvarray error handler is just program termination LvArray::system::callErrorHandler(); + } + catch( std::exception const & e ) + { // native exceptions management + ErrorLogger::global().flushErrorMsg( DiagnosticMsgBuilder::init() + .setType( MsgType::Exception ) + .addToMsg( e.what() ) + .addRank( ::geos::logger::internal::g_rank ) + .addCallStackInfo( LvArray::system::stackTrace( true ) ) + .get()); basicCleanup(); - std::abort(); + // lvarray error handler is just program termination + LvArray::system::callErrorHandler(); } return 0; } diff --git a/src/pygeosx/pygeosx.cpp b/src/pygeosx/pygeosx.cpp index fff9d7aea9c..3941c74668a 100644 --- a/src/pygeosx/pygeosx.cpp +++ b/src/pygeosx/pygeosx.cpp @@ -119,7 +119,7 @@ static constexpr char const * initializeDocString = "--\n\n" "Initialize GEOSX, this must be the first module call.\n\n" "Should only be called once. All calls after the first will\n" - "raise a `RuntimeError`. To reinitialize GEOSX for a new problem,\n" + "raise a `geos::RuntimeError`. To reinitialize GEOSX for a new problem,\n" "use the `reinit` function.\n" "\n" "Parameters\n"