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..0497ec04c9e 100644 --- a/src/coreComponents/common/CMakeLists.txt +++ b/src/coreComponents/common/CMakeLists.txt @@ -28,6 +28,7 @@ set( common_headers format/table/TableFormatter.hpp format/table/TableData.hpp format/EnumStrings.hpp + format/EnumStringsCore.hpp format/LogPart.hpp format/Format.hpp format/StringUtilities.hpp @@ -38,9 +39,12 @@ set( common_headers GEOS_RAJA_Interface.hpp GeosxMacros.hpp MemoryInfos.hpp + logger/GeosExceptions.hpp logger/Logger.hpp logger/ErrorHandling.hpp logger/ExternalErrorHandler.hpp + logger/LoggerMsgReportData.hpp + logger/MsgType.hpp MpiWrapper.hpp Path.hpp Span.hpp @@ -78,6 +82,7 @@ set( common_sources logger/Logger.cpp logger/ErrorHandling.cpp logger/ExternalErrorHandler.cpp + logger/LoggerMsgReportData.cpp BufferAllocator.cpp MemoryInfos.cpp MpiWrapper.cpp 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/EnumStrings.hpp b/src/coreComponents/common/format/EnumStrings.hpp index f5b37de1df1..75776276ea4 100644 --- a/src/coreComponents/common/format/EnumStrings.hpp +++ b/src/coreComponents/common/format/EnumStrings.hpp @@ -25,6 +25,7 @@ #ifndef GEOS_COMMON_FORMAT_ENUMSTRINGS_HPP #define GEOS_COMMON_FORMAT_ENUMSTRINGS_HPP +#include "EnumStringsCore.hpp" #include "common/format/StringUtilities.hpp" // #include "codingUtilities/RTTypes.hpp" #include "common/DataTypes.hpp" @@ -38,43 +39,11 @@ namespace geos { -namespace internal -{ -/** - * @brief Simple compile-time variadic function that counts its arguments. - * @tparam ARGS variadic pack of argument types - * @return the number of arguments passed - */ -template< typename ... ARGS > -constexpr int countArgs( ARGS ... ) -{ - return sizeof...( ARGS ); -} -} - /** * @brief Associate a list of string names with enumeration values. * @param ENUM the enumeration type * @param ... list of names (C-string literals) * - * Conditions (not enforced but won't work correctly if violated): - * - the macro must be called in the same namespace the enumeration type is defined in - * - the number and order of string arguments passed must match the enum values - * - enumeration constants must not have custom values assigned - * - * After the macro has been called, template instantiation EnumStrings - * may be used to get access to strings at runtime. While not strictly necessary, - * it is recommended that macro call immediately follows the enum definition - * (or the class definition, if enum is defined inside a class). - * - * enum struct VTKOutputMode - * { - * BINARY, - * ASCII - * }; - * ENUM_STRINGS( VTKOutputMode, - * "binary", - * "ascii" ); */ #define ENUM_STRINGS( ENUM, ... ) \ inline auto const & getEnumStrings( ENUM const ) \ @@ -113,22 +82,10 @@ constexpr int countArgs( ARGS ... ) * @tparam ENUM the enumeration type */ template< typename ENUM > -struct EnumStrings +struct EnumStrings : public EnumStringsCore< ENUM > { - /// Alias for the enumeration type - using enum_type = ENUM; - - /// Alias for enum's underlying fundamental type - using base_type = std::underlying_type_t< ENUM >; - - /** - * @brief @return An array of strings associated with enumeration. - */ - static auto const & get() - { - return getEnumStrings( enum_type{} ); // invoke ADL - } + using Base = EnumStringsCore; /** * @brief Get a list of valid options as a delimited string. * @param delim delimiter (defaults to single space) @@ -136,7 +93,7 @@ struct EnumStrings */ static string concat( string const & delim = " " ) { - auto const & strings = get(); + auto const & strings = Base::get(); return stringutilities::join( std::begin( strings ), std::end( strings ), delim ); } @@ -147,13 +104,13 @@ struct EnumStrings * * An error is raised if enum's numerical value is greater of equal than the number of strings. */ - static string toString( enum_type const & e ) + static string toString( typename Base::enum_type const & e ) { - auto const & strings = get(); + auto const & strings = Base::get(); std::size_t size = std::distance( std::begin( strings ), std::end( strings ) ); - base_type const index = static_cast< base_type >( e ); - GEOS_THROW_IF( index >= LvArray::integerConversion< base_type >( size ), - "Invalid value " << index << " of type " << getEnumTypeNameString( enum_type{} ) << ". Valid range is 0.." << size - 1, + typename Base::base_type const index = static_cast< typename Base::base_type >( e ); + GEOS_THROW_IF( index >= LvArray::integerConversion< typename Base::base_type >( size ), + "Invalid value " << index << " of type " << getEnumTypeNameString( typename Base::enum_type{} ) << ". Valid range is 0.." << size - 1, InputError ); return strings[ index ]; } @@ -163,14 +120,14 @@ struct EnumStrings * @param s the string to convert * @return the corresponding enum value */ - static enum_type fromString( string const & s ) + static typename Base::enum_type fromString( string const & s ) { - auto const & strings = get(); + auto const & strings = Base::get(); auto const it = std::find( std::begin( strings ), std::end( strings ), s ); GEOS_THROW_IF( it == std::end( strings ), - "Invalid value '" << s << "' of type " << getEnumTypeNameString( enum_type{} ) << ". Valid options are: " << concat( ", " ), + "Invalid value '" << s << "' of type " << getEnumTypeNameString( typename Base::enum_type{} ) << ". Valid options are: " << concat( ", " ), InputError ); - enum_type const e = static_cast< enum_type >( LvArray::integerConversion< base_type >( std::distance( std::begin( strings ), it ) ) ); + typename Base::enum_type const e = static_cast< typename Base::enum_type >( LvArray::integerConversion< typename Base::base_type >( std::distance( std::begin( strings ), it ) ) ); return e; } }; diff --git a/src/coreComponents/common/format/EnumStringsCore.hpp b/src/coreComponents/common/format/EnumStringsCore.hpp new file mode 100644 index 00000000000..0708f765e63 --- /dev/null +++ b/src/coreComponents/common/format/EnumStringsCore.hpp @@ -0,0 +1,110 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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 EnumStrings.hpp + * + * Collection of utilities to facilitate I/O of enumeration types. + * Provides a macro definition that allows associating string names + * with enumeration constants and a set of functions that make use + * of these strings, like stream insertion/extraction operators. + */ + +#ifndef GEOS_COMMON_FORMAT_ENUMSTRINGSCORE_HPP +#define GEOS_COMMON_FORMAT_ENUMSTRINGSCORE_HPP + +#include +#include +namespace geos +{ + +namespace internal +{ +/** + * @brief Simple compile-time variadic function that counts its arguments. + * @tparam ARGS variadic pack of argument types + * @return the number of arguments passed + */ +template< typename ... ARGS > +constexpr int countArgs( ARGS ... ) +{ + return sizeof...( ARGS ); +} +} + +/** + * @brief Associate a list of string names with enumeration values. + * @param ENUM the enumeration type + * @param ... list of names (C-string literals) + * + * Conditions (not enforced but won't work correctly if violated): + * - the macro must be called in the same namespace the enumeration type is defined in + * - the number and order of string arguments passed must match the enum values + * - enumeration constants must not have custom values assigned + * + * After the macro has been called, template instantiation EnumStrings + * may be used to get access to strings at runtime. While not strictly necessary, + * it is recommended that macro call immediately follows the enum definition + * (or the class definition, if enum is defined inside a class). + * + * enum struct VTKOutputMode + * { + * BINARY, + * ASCII + * }; + * ENUM_STRINGS( VTKOutputMode, + * "binary", + * "ascii" ); + */ +#define ENUM_STRINGS_CORE( ENUM, ... ) \ + inline auto const & getEnumStrings( ENUM const ) \ + { \ + static constexpr char const * ss[] { __VA_ARGS__ }; \ + return ss; \ + } \ + \ + inline auto const & getEnumTypeNameString( ENUM const ) \ + { \ + return #ENUM; \ + } \ + inline std::ostream & operator<<( std::ostream & os, ENUM const e ) \ + { \ + os << EnumStringsCore< ENUM >::toRawString( e ); \ + return os; \ + } \ + inline std::string toString( ENUM const e ) \ + { \ + return EnumStringsCore< ENUM >::toRawString( e ); \ + } \ + +template< typename ENUM > +struct EnumStringsCore +{ + using enum_type = ENUM; + using base_type = std::underlying_type_t< ENUM >; + + static auto const & get() + { + return getEnumStrings( enum_type{} ); + } + + static const char * toRawString( enum_type const e ) + { + auto const & strings = get(); + return strings[static_cast< base_type >(e)]; + } +}; +} +#endif //GEOS_COMMON_FORMAT_ENUMSTRINGSCORE_HPP diff --git a/src/coreComponents/common/format/LogPart.cpp b/src/coreComponents/common/format/LogPart.cpp index a9ce3c69da6..f0dfda636fc 100644 --- a/src/coreComponents/common/format/LogPart.cpp +++ b/src/coreComponents/common/format/LogPart.cpp @@ -18,6 +18,7 @@ #include "LogPart.hpp" #include "common/format/StringUtilities.hpp" +#include "common/logger/ErrorHandling.hpp" #include using namespace geos::stringutilities; @@ -30,6 +31,8 @@ LogPart::LogPart( string_view logPartTitle, bool enableOutput ) m_formattedEndDescription.m_title = GEOS_FMT( "{}{}", m_prefixEndTitle, logPartTitle ); m_enableOutput = enableOutput; + + ErrorLogger::global().setCurrentLogPart( string( logPartTitle )); } void LogPart::addDescription( string_view description ) 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..9df6bbc1813 100644 --- a/src/coreComponents/common/initializeEnvironment.cpp +++ b/src/coreComponents/common/initializeEnvironment.cpp @@ -20,8 +20,11 @@ #include "LvArray/src/system.hpp" #include "common/LifoStorageCommon.hpp" #include "common/MemoryInfos.hpp" +#include "common/logger/Logger.hpp" +#include "common/logger/LoggerMsgReportData.hpp" #include "logger/ErrorHandling.hpp" #include "logger/ExternalErrorHandler.hpp" +#include #include // TPL includes #include @@ -102,22 +105,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().beginLogger() + .setType( MsgType::Error ) + .addToMsg( errorMsg ) + .addRank( ::geos::logger::internal::g_rank ) + .addCallStackInfo( stackHistory ) + .addContextInfo( + ErrorContext{ string( detectionLocation ), + { { ErrorContext::Attribute::DetectionLoc, string( detectionLocation ) } }, + } ) + .flush(); // we do not terminate the program as 1. the error could be non-fatal, 2. there may be more messages to output. } ); @@ -134,26 +131,16 @@ 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().beginLogger() + .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 } ) + .flush(); // call program termination LvArray::system::callErrorHandler(); @@ -355,6 +342,8 @@ void setupEnvironment( int argc, char * argv[] ) void cleanupEnvironment() { MemoryLogging::getInstance().memoryStatsReport(); + TableTextFormatter truc; + GEOS_LOG_RANK_0( truc.toString< LoggerMsgReportData >( GEOS_GLOBAL_LOGGER.getLoggerReportData())); LvArray::system::resetSignalHandling(); finalizeLogger(); finalizeCaliper(); diff --git a/src/coreComponents/common/logger/ErrorHandling.cpp b/src/coreComponents/common/logger/ErrorHandling.cpp index 5bec5c6754c..ca6b627a40e 100644 --- a/src/coreComponents/common/logger/ErrorHandling.cpp +++ b/src/coreComponents/common/logger/ErrorHandling.cpp @@ -44,27 +44,6 @@ 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 ) { @@ -138,14 +117,14 @@ ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addSignalToMsg( int sig, bool toE } } -ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::setCodeLocation( std::string_view msgFile, integer msgLine ) +ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::setCodeLocation( std::string_view msgFile, integer const msgLine ) { m_file = msgFile; m_line = msgLine; return *this; } -ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::setType( ErrorLogger::MsgType msgType ) +ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::setType( MsgType const msgType ) { m_type = msgType; return *this; @@ -162,7 +141,7 @@ void ErrorLogger::ErrorMsg::addContextInfoImpl( ErrorLogger::ErrorContext && ctx m_contextsInfo.emplace_back( std::move( ctxInfo ) ); } -ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addRank( int rank ) +ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addRank( integer const rank ) { m_ranksInfo.emplace( rank ); return *this; @@ -195,15 +174,67 @@ ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addCallStackInfo( std::string_vie return *this; } -std::string ErrorLogger::toString( ErrorLogger::MsgType type ) +ErrorLogger::ErrorMsgBuilder & ErrorLogger::ErrorMsgBuilder::addToMsg( std::exception const & e, bool const toEnd ) { - switch( type ) + m_errorContext.m_currentErrorMsg.addToMsg( e, toEnd ); + return *this; +} +ErrorLogger::ErrorMsgBuilder & ErrorLogger::ErrorMsgBuilder::addToMsg( std::string_view msg, bool toEnd ) +{ + m_errorContext.m_currentErrorMsg.addToMsg( msg, toEnd ); + return *this; +} + +ErrorLogger::ErrorMsgBuilder & ErrorLogger::ErrorMsgBuilder::addSignalToMsg( integer const sig, bool const toEnd ) +{ + m_errorContext.m_currentErrorMsg.addSignalToMsg( sig, toEnd ); + return *this; +} + +ErrorLogger::ErrorMsgBuilder & ErrorLogger::ErrorMsgBuilder::setCodeLocation( std::string_view msgFile, + integer const msgLine ) +{ + if( !m_errorContext.m_currentErrorMsg.isCommited() ) { - case ErrorLogger::MsgType::Error: return "Error"; - case ErrorLogger::MsgType::Warning: return "Warning"; - case ErrorLogger::MsgType::Exception: return "Exception"; - default: return "Unknown"; + m_errorContext.m_currentErrorMsg.setCodeLocation( msgFile, msgLine ); } + return *this; +} + +ErrorLogger::ErrorMsgBuilder & ErrorLogger::ErrorMsgBuilder::setType( MsgType const msgType ) +{ + if( !m_errorContext.m_currentErrorMsg.isCommited() ) + { + m_errorContext.m_currentErrorMsg.setType( msgType ); + } + return *this; +} + +ErrorLogger::ErrorMsgBuilder & ErrorLogger::ErrorMsgBuilder::setCause( std::string_view cause ) +{ + if( !m_errorContext.m_currentErrorMsg.isCommited() ) + { + m_errorContext.m_currentErrorMsg.setCause( cause ); + } + return *this; +} + +ErrorLogger::ErrorMsgBuilder & ErrorLogger::ErrorMsgBuilder::addRank( integer const rank ) +{ + if( !m_errorContext.m_currentErrorMsg.isCommited() ) + { + m_errorContext.m_currentErrorMsg.addRank( rank ); + } + return *this; +} + +ErrorLogger::ErrorMsgBuilder & ErrorLogger::ErrorMsgBuilder::addCallStackInfo( std::string_view ossStackTrace ) +{ + if( !m_errorContext.m_currentErrorMsg.isCommited() ) + { + m_errorContext.m_currentErrorMsg.addCallStackInfo( ossStackTrace ); + } + return *this; } void ErrorLogger::streamMultilineYamlAttribute( std::string_view msg, std::ofstream & yamlFile, @@ -228,31 +259,121 @@ 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( ErrorLogger::ErrorMsg 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 << " l." << 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< ErrorLogger::ErrorContext > const & contexts = errMsg.m_contextsInfo; + if( contexts.empty()) + { + oss << PREFIX << "Message :\n"; + } + else + { + oss << PREFIX << "Message from " << contexts.front().m_dataDisplayString << ":\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_dataDisplayString << "\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() { 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( m_currentErrorMsg.m_type ) << "\n"; + yamlFile << g_level1Next << "rank: " << stringutilities::join( m_currentErrorMsg.m_ranksInfo, "," ); yamlFile << "\n"; // Error message yamlFile << g_level1Next << "message: >-\n"; - streamMultilineYamlAttribute( errorMsg.m_msg, yamlFile, g_level2Next ); + streamMultilineYamlAttribute( m_currentErrorMsg.m_msg, yamlFile, g_level2Next ); // context information - if( !errorMsg.m_contextsInfo.empty() ) + if( !m_currentErrorMsg.m_contextsInfo.empty() ) { + std::vector< ErrorContext > contextInfo = m_currentErrorMsg.m_contextsInfo; // Sort contextual information by decreasing priority - std::sort( errorMsg.m_contextsInfo.begin(), errorMsg.m_contextsInfo.end(), + std::sort( contextInfo.begin(), contextInfo.end(), []( const ErrorLogger::ErrorContext & a, const ErrorLogger::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"; for( auto const & [key, value] : ctxInfo.m_attributes ) @@ -263,40 +384,47 @@ void ErrorLogger::flushErrorMsg( ErrorLogger::ErrorMsg & errorMsg ) } // error cause - if( !errorMsg.m_cause.empty() ) + if( !m_currentErrorMsg.m_cause.empty() ) { yamlFile << g_level1Next << "cause: >-\n"; - streamMultilineYamlAttribute( errorMsg.m_cause, yamlFile, g_level2Next ); + streamMultilineYamlAttribute( m_currentErrorMsg.m_cause, yamlFile, g_level2Next ); } // Location of the error in the code - if( !errorMsg.m_file.empty() ) + if( !m_currentErrorMsg.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: " << m_currentErrorMsg.m_file << "\n"; + yamlFile << g_level2Next << "line: " << m_currentErrorMsg.m_line << "\n"; } // Information about the stack trace - if( !errorMsg.m_sourceCallStack.empty() ) + if( !m_currentErrorMsg.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 < m_currentErrorMsg.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 << ( m_currentErrorMsg.isValidStackTrace() ? + GEOS_FMT( "{}frame{}: {}\n", g_level3Start, i, m_currentErrorMsg.m_sourceCallStack[i] ) : + GEOS_FMT( "{}{}\n", g_level3Start, m_currentErrorMsg.m_sourceCallStack[i] ) ); } } yamlFile << "\n"; yamlFile.flush(); - errorMsg = ErrorMsg(); - GEOS_LOG_RANK( GEOS_FMT( "The error file {} has been appended.\n", m_filename ) ); + m_currentErrorMsg = ErrorMsg(); } 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() +{ + writeToAscii( m_currentErrorMsg, m_stream ); + if( isOutputFileEnabled() ) + { + writeToYaml(); } } diff --git a/src/coreComponents/common/logger/ErrorHandling.hpp b/src/coreComponents/common/logger/ErrorHandling.hpp index 62e3db66df6..0d785489a43 100644 --- a/src/coreComponents/common/logger/ErrorHandling.hpp +++ b/src/coreComponents/common/logger/ErrorHandling.hpp @@ -21,6 +21,8 @@ #define INITIALIZATION_ERROR_LOGGER_HPP #include "common/DataTypes.hpp" +#include "common/logger/LoggerMsgReportData.hpp" +#include "common/logger/MsgType.hpp" namespace geos { @@ -33,17 +35,6 @@ class ErrorLogger { public: - /** - * @enum MsgType - * Enum listing the different types of possible errors - */ - enum class MsgType - { - Error, - Warning, - Exception, - Undefined - }; /** * @struct ErrorContext @@ -66,21 +57,24 @@ class ErrorLogger 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 Construct to initialize ErrorContext given a string containing the context and his attribute + * @param dataDisplayString String containing the target object name followed by the the file and line declaring it. + * @param attributes Map containing contextual information about the error + */ + ErrorContext( string dataDisplayString, map< Attribute, std::string > attributes ): + m_dataDisplayString( dataDisplayString ), + m_attributes( attributes ) {}; /** - * @brief Priority level assigned to an error context. - * @details Used to prioritize contextes (higher values = more relevant). Default is 0. - * + * @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. */ - integer m_priority = 0; + ErrorContext( map< Attribute, std::string > attributes, integer priority ): + m_dataDisplayString( "" ), + m_attributes( attributes ), + m_priority( priority ) {}; /** * @brief Set the priority value of the current error context information @@ -96,6 +90,25 @@ class ErrorLogger * @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_dataDisplayString; + + /// 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; }; /** @@ -104,7 +117,7 @@ class ErrorLogger struct ErrorMsg { /// the error type (Warning, Error or Exception) - MsgType m_type = ErrorLogger::MsgType::Undefined; + MsgType m_type = 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) @@ -139,7 +152,13 @@ class ErrorLogger integer rank, std::string_view msgFile, integer msgLine ) - : m_type( msgType ), m_msg( msgContent ), m_ranksInfo( {rank} ), m_file( msgFile ), m_line( msgLine ) {} + : + m_type( msgType ), + m_msg( msgContent ), + m_ranksInfo( {rank} ), + m_file( msgFile ), + m_line( msgLine ), + m_commit( false ) {} /** * @brief Add text to the current error msg @@ -148,7 +167,7 @@ class ErrorLogger * default is false * @return Reference to the current instance for method chaining. */ - ErrorMsg & addToMsg( std::exception const & e, bool toEnd = false ); + ErrorMsg & addToMsg( std::exception const & e, bool const toEnd = false ); /** * @brief Add text to the current error msg @@ -157,7 +176,7 @@ class ErrorLogger * default is false * @return Reference to the current instance for method chaining. */ - ErrorMsg & addToMsg( std::string_view msg, bool toEnd = false ); + ErrorMsg & addToMsg( std::string_view msg, bool const toEnd = false ); /** * @brief Add text to the error msg that occured according to the specified signal. @@ -167,7 +186,7 @@ class ErrorLogger * @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 ); + ErrorMsg & addSignalToMsg( integer const signal, bool const toEnd = false ); /** * @brief Set the source code location values (file and line where the error is detected) @@ -175,14 +194,14 @@ class ErrorLogger * @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 ); + ErrorMsg & setCodeLocation( std::string_view msgFile, integer const 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 ); + ErrorMsg & setType( MsgType const msgType ); /** * @brief Set the cause of the error @@ -196,7 +215,7 @@ class ErrorLogger * @param rank The value to add * @return Reference to the current instance for method chaining. */ - ErrorMsg & addRank( int rank ); + ErrorMsg & addRank( integer const rank ); /** * @brief Add stack trace information about the error @@ -220,15 +239,111 @@ class ErrorLogger bool isValidStackTrace() const { return m_isValidStackTrace; } + /** + * @return whether the error message has been finalized and committed. + */ + bool isCommited() const + { return m_commit; } + + /** + * @brief Marks the error message as committed (finalized). + */ + void commitErrorMsg() + { m_commit = true; } + private: /** * @brief Add contextual information about the error/warning * @param ctxInfo rvalue of the ErrorContext class */ void addContextInfoImpl( ErrorContext && ctxInfo ); - + /// Indicates whether the stored call stack trace is valid and usable. + /// Indicates whether the stored call stack trace is valid and usable. bool m_isValidStackTrace = false; + /// Indicates whether the error message has been fully constructed and finalized. + bool m_commit = false; + }; + + /** + * @brief Builder class for constructing ErrorMsg objects + */ + class ErrorMsgBuilder + { +public: + ErrorMsgBuilder( ErrorLogger & errorContext ): m_errorContext( errorContext ){}; + /** + * @copydoc ErrorLogger:ErrorMsg::addToMsg( std::exception const & e, bool toEnd = false ) + */ + ErrorMsgBuilder & addToMsg( std::exception const & e, bool toEnd = false ); + /** + * @copydoc ErrorLogger:ErrorMsg::addToMsg( std::string_view msg, bool toEnd = false ) + */ + ErrorMsgBuilder & addToMsg( std::string_view msg, bool const toEnd = false ); + /** + * @copydoc ErrorLogger:ErrorMsg::addContextInfo( Args && ... args ) + */ + template< typename ... Args > + ErrorMsgBuilder & addContextInfo( Args && ... args ) + { + ( m_errorContext.m_currentErrorMsg.addContextInfo( ErrorContext( args ) ), ... ); + return *this; + } + /** + * @copydoc ErrorLogger:ErrorMsg::addSignalToMsg( int sig, bool toEnd = false ); + */ + ErrorMsgBuilder & addSignalToMsg( integer const sig, bool toEnd = false ); + /** + * @copydoc ErrorLogger:ErrorMsg::setCodeLocation( std::string_view msgFile, integer msgLine ) + */ + ErrorMsgBuilder & setCodeLocation( std::string_view msgFile, integer const msgLine ); + /** + * @copydoc ErrorLogger:ErrorMsg::setType( MsgType msgType ) + */ + ErrorMsgBuilder & setType( MsgType const msgType ); + /** + * @copydoc ErrorLogger:ErrorMsg::setCause( std::string_view cause ) + */ + ErrorMsgBuilder & setCause( std::string_view cause ); + /** + * @copydoc ErrorLogger:ErrorMsg::addRank( int rank ); + */ + ErrorMsgBuilder & addRank( integer const rank ); + /** + * @copydoc ErrorLogger:ErrorMsg::addCallStackInfo( std::string_view ossStackTrace ) + */ + ErrorMsgBuilder & addCallStackInfo( std::string_view ossStackTrace ); + /** + * @brief Finalizes the error message construction + * @note Calling commit() does not flush/output the error; + */ + void commit() + { + m_errorContext.loggerMsgReportData.increment( m_errorContext.getCurrentLogPart(), + m_errorContext.m_currentErrorMsg.m_type ); + m_errorContext.m_currentErrorMsg.commitErrorMsg(); + } + /** + * @copydoc ErrorLogger::flushErrorMsg() + */ + void flush() + { + m_errorContext.loggerMsgReportData.increment( m_errorContext.getCurrentLogPart(), + m_errorContext.m_currentErrorMsg.m_type ); + m_errorContext.flushErrorMsg(); + } + +private: + ///@copydoc ErrorLogger::m_errorContext + ErrorLogger & m_errorContext; }; + /** + * @brief Creates and returns a new ErrorMsgBuilder to begin constructing an error message. + * @return A new ErrorMsgBuilder instance + */ + ErrorMsgBuilder beginLogger() + { + return ErrorMsgBuilder( *this ); + } /** * @return Global instance of the ErrorLogger class used for error/warning reporting. @@ -239,12 +354,6 @@ class ErrorLogger */ GEOS_HOST static ErrorLogger & global(); - /** - * @return true if the YAML file output is enabled - */ - bool isOutputFileEnabled() const - { return m_writeYaml; } - /** * @brief Enable the YAML file output, which is false by default * @param value A value of true enable the file writing @@ -252,6 +361,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" @@ -268,11 +383,10 @@ class ErrorLogger /** * @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. + * potencially at various application layers (Typically for exceptions) + * @return Reference to the current error message instance; */ - ErrorMsg & currentErrorMsg() + ErrorMsg const & currentErrorMsg() const { return m_currentErrorMsg; } /** @@ -288,20 +402,68 @@ class ErrorLogger */ static std::string toString( MsgType type ); + /** + * @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( ErrorLogger::ErrorMsg const & errMsg, std::ostream & oss ); + /** * @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 */ - void flushErrorMsg( ErrorMsg & errorMsg ); + void writeToYaml(); + + /** + * @brief Write all the information retrieved about the error/warning message into the output stream specified and + * optionnaly into a yaml file + * @param errorMsg a constant reference to the ErrorMsg + */ + void flushErrorMsg(); + + /** + * @return Return the const general log stream + */ + std::ostream const & getErrorStream() const + { return m_stream; } + + /** + * @brief Gets the current log part. + * @return The current log part as a string. + */ + string const & getCurrentLogPart() const + {return m_currentLogPart;} + +/** + * @brief Sets the current log part. + * @param logPart The new log part to set. + */ + void setCurrentLogPart( string const & logPart ) + { m_currentLogPart = logPart; } + + /** + * @brief Gets the current logger report data. + * @return The current log part as a string. + */ + LoggerMsgReportData const & getLoggerReportData() const + {return loggerMsgReportData;} private: /// The error constructed via exceptions ErrorMsg m_currentErrorMsg; + + LoggerMsgReportData loggerMsgReportData = {}; + /// 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; + + string m_currentLogPart; /** * @brief Write the error message in the YAML file regarding indentation and line break diff --git a/src/coreComponents/common/logger/GeosExceptions.hpp b/src/coreComponents/common/logger/GeosExceptions.hpp new file mode 100644 index 00000000000..1adf819077d --- /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( ) + { + errorMsg.addToMsg( what ); + } + + /** + * @return Reference to the ErrorMsg object + */ + ErrorLogger::ErrorMsg & getErrorMsg() + { return 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 << " l." << 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 + ErrorLogger::ErrorMsg 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..4d0ea161a58 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.beginLogger() \ + .setType( MsgType::Error ) \ + .setCodeLocation( __FILE__, __LINE__ ) \ + .setCause( __causemsgsoss.str() ) \ + .addRank( ::geos::logger::internal::g_rank ) \ + .addToMsg( __msgoss.str() ) \ + .addContextInfo( GEOS_DETAIL_REST_ARGS( __VA_ARGS__ ) ) \ + .addCallStackInfo( LvArray::system::stackTrace( true ) ) \ + .flush(); \ 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,25 @@ { \ 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.beginLogger() \ + .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__ ) ) \ + .commit(); \ + 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,27 +294,16 @@ { \ 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.beginLogger() \ + .setType( MsgType::Warning ) \ + .setCodeLocation( __FILE__, __LINE__ ) \ + .setCause( __causemsgsoss.str() ) \ + .addRank( ::geos::logger::internal::g_rank ) \ + .addToMsg( __msgoss.str() ) \ + .addContextInfo( GEOS_DETAIL_REST_ARGS( __VA_ARGS__ ) ) \ + .flush(); \ } \ } while( false ) #elif __CUDA_ARCH__ @@ -949,88 +911,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 { diff --git a/src/coreComponents/common/logger/LoggerMsgReportData.cpp b/src/coreComponents/common/logger/LoggerMsgReportData.cpp new file mode 100644 index 00000000000..ea3f984fece --- /dev/null +++ b/src/coreComponents/common/logger/LoggerMsgReportData.cpp @@ -0,0 +1,65 @@ +#include "LoggerMsgReportData.hpp" +#include "common/format/EnumStringsCore.hpp" +#include "common/format/table/TableData.hpp" +#include "common/format/table/TableFormatter.hpp" +#include "common/format/table/TableLayout.hpp" +#include "common/format/table/TableTypes.hpp" +#include "common/logger/MsgType.hpp" +#include + +namespace geos +{ + +void LoggerMsgReportData::increment( string const & logPartName, MsgType msgType ) +{ + if( numMsgByPart.count( logPartName ) ==0 ) + { + NumMsg numMsg{ { {msgType, 1}}, {{msgType, 1} }}; + numMsgByPart[logPartName] = numMsg; + } + else + { + NumMsg & numMsg = numMsgByPart.at( logPartName ); + numMsg.numMsg[msgType]++; + numMsg.numMsgLoc[msgType]++; + } +} + +template<> +string TableTextFormatter::toString< LoggerMsgReportData >( LoggerMsgReportData const & report ) const +{ + TableLayout tableLayoutPerSection; + TableData dataPerSection; + + std::ostringstream oss; + tableLayoutPerSection.addColumn( " Types " ); + + for( auto const & [ logPartName, numMsg ] : report.numMsgByPart ) + { + tableLayoutPerSection.addColumn( logPartName ); + } + + + for( size_t i = (size_t) MsgType::Error; i != (size_t)MsgType::Undefined; i++ ) + { + MsgType const currentType = (MsgType) i; + stdVector< TableData::CellData > row; + + row.push_back( {CellType::Value, EnumStringsCore< MsgType >::toRawString( (MsgType) i ) } ); + for( auto const & [ _, msgTypes ] : report.numMsgByPart ) + { + auto it = msgTypes.numMsg.find( currentType ); + int const count = ( it != msgTypes.numMsg.end() ) ? it->second : 0; + row.push_back( {CellType::Value, std::to_string( count )} ); + + } + dataPerSection.addRow( row ); + } + + TableTextFormatter textFormatter( tableLayoutPerSection ); + oss << textFormatter.toString( dataPerSection ) << "\n"; + + return oss.str(); +} + +}; diff --git a/src/coreComponents/common/logger/LoggerMsgReportData.hpp b/src/coreComponents/common/logger/LoggerMsgReportData.hpp new file mode 100644 index 00000000000..e50f1a7f54a --- /dev/null +++ b/src/coreComponents/common/logger/LoggerMsgReportData.hpp @@ -0,0 +1,49 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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 LoggerMsgReportData.hpp + */ + +#ifndef GEOS_COMMON_LOGGER_MSG_REPORT_DATA_HPP +#define GEOS_COMMON_LOGGER_MSG_REPORT_DATA_HPP + +#include "common/format/table/TableFormatter.hpp" +#include "MsgType.hpp" + +namespace geos +{ + +struct NumMsg; + +struct LoggerMsgReportData +{ + stdMap< std::string, NumMsg > numMsgByPart; + + void increment( string const & logPartName, MsgType ); +}; + +struct NumMsg +{ + stdMap< MsgType, int > numMsg; + stdMap< MsgType, int > numMsgLoc; +}; + +template<> +string TableTextFormatter::toString(LoggerMsgReportData const &) const; + +} + +#endif diff --git a/src/coreComponents/common/logger/MsgType.hpp b/src/coreComponents/common/logger/MsgType.hpp new file mode 100644 index 00000000000..b62e2b9dffa --- /dev/null +++ b/src/coreComponents/common/logger/MsgType.hpp @@ -0,0 +1,50 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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 ErrorHandling.hpp + */ + +#ifndef INITIALIZATION_MSG_TYPE_HPP +#define INITIALIZATION_MSG_TYPE_HPP + +#include "common/format/EnumStringsCore.hpp" + +namespace geos +{ + +/** + * @enum MsgType + * Enum listing the different types of possible errors + */ +enum class MsgType +{ + Error, + ExternalError, + Warning, + Exception, + Undefined +}; + +ENUM_STRINGS_CORE( MsgType, + "Error", + "ExternalError", + "Warning", + "Exception", + "Undefined" ); + +}; + +#endif 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..635f6a9348a 100644 --- a/src/coreComponents/constitutive/fluid/multifluid/CO2Brine/CO2BrineFluid.cpp +++ b/src/coreComponents/constitutive/fluid/multifluid/CO2Brine/CO2BrineFluid.cpp @@ -172,9 +172,10 @@ 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().beginLogger() .addToMsg( errorMsg ) - .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); + .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ) + .commit(); throw SimulationError( ex, errorMsg ); } @@ -187,9 +188,10 @@ 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().beginLogger() .addToMsg( errorMsg ) - .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); + .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ) + .commit(); throw SimulationError( ex, errorMsg ); } @@ -200,9 +202,10 @@ 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().beginLogger() .addToMsg( errorMsg ) - .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); + .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ) + .commit(); 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..b87019f6fa6 100644 --- a/src/coreComponents/constitutive/fluid/multifluid/blackOil/BlackOilFluidBase.cpp +++ b/src/coreComponents/constitutive/fluid/multifluid/blackOil/BlackOilFluidBase.cpp @@ -258,9 +258,10 @@ void BlackOilFluidBase::checkTablesParameters( real64 const pressure, { string const msg = GEOS_FMT( errorMsg, getCatalogName(), getDataContext(), "formation volume factor", iph ); - ErrorLogger::global().currentErrorMsg() + ErrorLogger::global().beginLogger() .addToMsg( msg ) - .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); + .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ) + .commit(); throw SimulationError( ex, msg ); } @@ -271,9 +272,10 @@ void BlackOilFluidBase::checkTablesParameters( real64 const pressure, { string const msg = GEOS_FMT( errorMsg, getCatalogName(), getDataContext(), "viscosity", iph ); - ErrorLogger::global().currentErrorMsg() + ErrorLogger::global().beginLogger() .addToMsg( msg ) - .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); + .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ) + .commit(); throw SimulationError( ex, msg ); } } diff --git a/src/coreComponents/constitutive/fluid/multifluid/reactive/ReactiveBrineFluid.cpp b/src/coreComponents/constitutive/fluid/multifluid/reactive/ReactiveBrineFluid.cpp index 7371e60d080..ece03e2c60b 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().beginLogger() .addToMsg( errorMsg ) - .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); + .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ) + .commit(); 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..02e5b098d97 100644 --- a/src/coreComponents/dataRepository/DataContext.cpp +++ b/src/coreComponents/dataRepository/DataContext.cpp @@ -111,8 +111,9 @@ string DataFileContext::toString() const ErrorLogger::ErrorContext DataFileContext::getContextInfo() const { ErrorLogger::ErrorContext ctxInfo{ + toString(), { { ErrorLogger::ErrorContext::Attribute::InputFile, m_filePath }, - { ErrorLogger::ErrorContext::Attribute::InputLine, std::to_string( m_line )} } // m_attributes + { ErrorLogger::ErrorContext::Attribute::InputLine, std::to_string( m_line )} } }; return ctxInfo; } 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..6384c4f43cd 100644 --- a/src/coreComponents/dataRepository/GroupContext.cpp +++ b/src/coreComponents/dataRepository/GroupContext.cpp @@ -57,7 +57,8 @@ string GroupContext::toString() const ErrorLogger::ErrorContext GroupContext::getContextInfo() const { ErrorLogger::ErrorContext ctxInfo{ - { { ErrorLogger::ErrorContext::Attribute::DataPath, toString() } } // m_attributes + toString(), + { { ErrorLogger::ErrorContext::Attribute::DataPath, GEOS_FMT( "{}/{}", m_group.getPath(), m_targetName )} } }; return ctxInfo; } diff --git a/src/coreComponents/dataRepository/WrapperContext.cpp b/src/coreComponents/dataRepository/WrapperContext.cpp index 50a37277e32..f5220e3fdee 100644 --- a/src/coreComponents/dataRepository/WrapperContext.cpp +++ b/src/coreComponents/dataRepository/WrapperContext.cpp @@ -41,7 +41,8 @@ string WrapperContext::toString() const ErrorLogger::ErrorContext WrapperContext::getContextInfo() const { ErrorLogger::ErrorContext ctxInfo{ - { { ErrorLogger::ErrorContext::Attribute::DataPath, toString() } } // m_attributes + toString(), + {{ ErrorLogger::ErrorContext::Attribute::DataPath, GEOS_FMT( "{}/{}", m_group.getPath(), m_typeName ) } }, }; return ctxInfo; } 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..e76adf1f509 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__ @@ -173,17 +173,28 @@ TEST( ErrorHandling, testYamlFileExceptionOutput ) // 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 ); } - catch( std::domain_error const & ex ) + catch( geos::DomainError const & ex ) { string const errorMsg = "Table input error.\n"; - testErrorLogger.currentErrorMsg() + testErrorLogger.beginLogger() .addToMsg( errorMsg ) .addContextInfo( additionalContext.getContextInfo() ) .addContextInfo( importantAdditionalContext.getContextInfo().setPriority( 2 ) ); + + string const whatExpected = GEOS_FMT( "***** GEOS Exception\n" + "***** LOCATION: {} l.{}\n" + "***** Error cause: testValue == 5\n" + "***** Rank 0: Empty Group", + testErrorLogger.currentErrorMsg().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.flushErrorMsg(); endLocalLoggerTest( testErrorLogger, { R"(errors:)", @@ -193,7 +204,7 @@ TEST( ErrorHandling, testYamlFileExceptionOutput ) rank: 0 message: >- Table input error. - Empty Group: Base Test Class (file.xml, l.23) + Empty Group contexts: - priority: 2 inputFile: /path/to/file.xml @@ -264,6 +275,84 @@ 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.beginLogger() + .addToMsg( errorMsg ) + .addContextInfo( additionalContext.getContextInfo() ) + .addContextInfo( importantAdditionalContext.getContextInfo().setPriority( 2 ) ); + + string const streamExpected = GEOS_FMT( + "***** Exception\n" + "***** LOCATION: {} l.{}\n" + "***** {}\n" + "***** Rank 0\n" + "***** Message from {}:\n" + "{}\n" + "***** Additional contexts:\n" + "***** - {}\n" + "***** - {}\n", + testErrorLogger.currentErrorMsg().m_file, line1, + testErrorLogger.currentErrorMsg().m_cause, + context.toString(), + testErrorLogger.currentErrorMsg().m_msg, + additionalContext.toString(), + importantAdditionalContext.toString(), testErrorLogger.currentErrorMsg().m_sourceCallStack ); + std::ostringstream oss; + ErrorLogger::writeToAscii( testErrorLogger.currentErrorMsg(), 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" < const { string const errorMsg = GEOS_FMT( "Error while reading {}:\n", getWrapperDataContext( viewKeyStruct::functionNameString() ) ); - ErrorLogger::global().currentErrorMsg() + ErrorLogger::global().beginLogger() .addToMsg( errorMsg ) .addContextInfo( getWrapperDataContext( viewKeyStruct::functionNameString() ).getContextInfo() - .setPriority( 1 ) ); + .setPriority( 1 ) ) + .commit(); throw InputError( e, errorMsg ); } }(); diff --git a/src/coreComponents/fileIO/Outputs/TimeHistoryOutput.cpp b/src/coreComponents/fileIO/Outputs/TimeHistoryOutput.cpp index ed84a72833b..4a84a2888d7 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().beginLogger() .addToMsg( errorMsg ) .addContextInfo( getWrapperDataContext( viewKeys::timeHistoryOutputTargetString() ).getContextInfo() - .setPriority( 1 ) ); + .setPriority( 1 ) ) + .commit(); throw InputError( e, errorMsg ); } } diff --git a/src/coreComponents/fileIO/timeHistory/HistoryCollectionBase.cpp b/src/coreComponents/fileIO/timeHistory/HistoryCollectionBase.cpp index dc17c782fe3..48715ad68dd 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().beginLogger() .addToMsg( getDataContext().toString() + " has a wrong objectPath: " + objectPath + "\n" ) - .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); + .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ) + .commit(); 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..72b1d331bc1 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().beginLogger() .addToMsg( getWrapperDataContext( viewKeysStruct::fieldNameString() ).toString() + ": Target not found !\n" ) .addContextInfo( getWrapperDataContext( viewKeysStruct::fieldNameString() ).getContextInfo() - .setPriority( 1 ) ); + .setPriority( 1 ) ) + .commit(); 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..8174481d720 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().currentErrorMsg(), 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..e442abed212 100644 --- a/src/coreComponents/mainInterface/ProblemManager.cpp +++ b/src/coreComponents/mainInterface/ProblemManager.cpp @@ -174,6 +174,9 @@ void ProblemManager::problemSetup() LogPart meshGenerationLog( "Mesh generation", MpiWrapper::commRank() == 0 ); meshGenerationLog.begin(); + GEOS_WARNING("plouf"); + GEOS_WARNING("plouf"); + GEOS_WARNING("plouf"); generateMesh(); meshGenerationLog.end(); @@ -181,6 +184,11 @@ void ProblemManager::problemSetup() LogPart numericalMethodLog( "Numerical Methods", MpiWrapper::commRank() == 0 ); numericalMethodLog.begin(); applyNumericalMethods(); + GEOS_WARNING("plouf"); + GEOS_WARNING("plouf"); + GEOS_WARNING("plouf"); + GEOS_WARNING("plouf"); + GEOS_WARNING("plouf"); numericalMethodLog.end(); registerDataOnMeshRecursive( getDomainPartition().getMeshBodies() ); @@ -189,6 +197,11 @@ void ProblemManager::problemSetup() LogPart importFieldsLog( "Import fields", MpiWrapper::commRank() == 0 ); importFieldsLog.begin(); + GEOS_WARNING("plouf"); + GEOS_WARNING("plouf"); + GEOS_WARNING("plouf"); + GEOS_WARNING("plouf"); + GEOS_WARNING("plouf"); importFields(); importFieldsLog.end(); } @@ -500,9 +513,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().beginLogger() .addToMsg( errorMsg ) - .addContextInfo( getDataContext().getContextInfo().setPriority( -1 ) ); + .addContextInfo( getDataContext().getContextInfo().setPriority( -1 ) ) + .commit(); throw InputError( e, errorMsg ); } } diff --git a/src/coreComponents/mesh/FaceManager.cpp b/src/coreComponents/mesh/FaceManager.cpp index 1cf388d34f4..ae9c3cee3df 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().beginLogger() .addToMsg( getDataContext().toString() + ": " + e.what() ) - .addContextInfo( getDataContext().getContextInfo().setPriority( 1 ) ); + .addContextInfo( getDataContext().getContextInfo().setPriority( 1 ) ) + .commit(); 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..4fc02dc879e 100644 --- a/src/coreComponents/mesh/generators/InternalMeshGenerator.cpp +++ b/src/coreComponents/mesh/generators/InternalMeshGenerator.cpp @@ -185,9 +185,10 @@ void InternalMeshGenerator::postInputInitialization() 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() + ErrorLogger::global().beginLogger() .addToMsg( msg ) - .addContextInfo( wrapper.getDataContext().getContextInfo().setPriority( 2 ) ); + .addContextInfo( wrapper.getDataContext().getContextInfo().setPriority( 2 ) ) + .commit(); throw InputError( e, msg ); } } 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..5bac5cc9d95 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().beginLogger() .addToMsg( errorMsg ) - .addContextInfo( getDataContext().getContextInfo().setPriority( 1 ) ); + .addContextInfo( getDataContext().getContextInfo().setPriority( 1 ) ) + .commit(); 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..23a623e7ee1 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().flushErrorMsg(); + basicCleanup(); + // lvarray error handler is just program termination LvArray::system::callErrorHandler(); + } + catch( std::exception const & e ) + { // native exceptions management + ErrorLogger::global().beginLogger() + .setType( MsgType::Exception ) + .addToMsg( e.what() ) + .addRank( ::geos::logger::internal::g_rank ) + .addCallStackInfo( LvArray::system::stackTrace( true ) ) + .flush(); 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"