diff --git a/src/coreComponents/common/CMakeLists.txt b/src/coreComponents/common/CMakeLists.txt index 287b0ceee3d..907e09333a4 100644 --- a/src/coreComponents/common/CMakeLists.txt +++ b/src/coreComponents/common/CMakeLists.txt @@ -19,7 +19,6 @@ Also provides commonly used components for such as logging, formatting, memory a dependencies. #]] - # # Specify all headers # @@ -41,6 +40,7 @@ set( common_headers GeosxMacros.hpp MemoryInfos.hpp logger/Logger.hpp + logger/ErrorHandling.hpp MpiWrapper.hpp Path.hpp Span.hpp @@ -76,6 +76,7 @@ set( common_sources format/LogPart.cpp format/StringUtilities.cpp logger/Logger.cpp + logger/ErrorHandling.cpp BufferAllocator.cpp MemoryInfos.cpp MpiWrapper.cpp diff --git a/src/coreComponents/common/GeosxMacros.hpp b/src/coreComponents/common/GeosxMacros.hpp index bf3ab070948..f5de0d519ad 100644 --- a/src/coreComponents/common/GeosxMacros.hpp +++ b/src/coreComponents/common/GeosxMacros.hpp @@ -133,4 +133,71 @@ void i_g_n_o_r_e( ARGS const & ... ) {} #endif #endif +/** + * @name Parameters processing internal macros + * + * These internal macros allow to craft macros with multiple count of parameters. + */ +///@{ + +/// internal macro for GEOS_DETAIL_MORE_THAN_ONE_ARG +#define GEOS_DETAIL_MORE_THAN_ONE_ARG_VALUE( _00, _01, _02, _03, _04, _05, _06, _07, \ + _08, _09, _10, _11, _12, _13, _14, _15, \ + _INDEX, ... ) _INDEX + +/** + * @return 1 if variadic argument has more than 1 element, 0 otherwise. + * @note Undefined behaviour if variadic argument has more that 16 elements. + */ +#define GEOS_DETAIL_MORE_THAN_ONE_ARG( ... ) \ + GEOS_DETAIL_MORE_THAN_ONE_ARG_VALUE( __VA_ARGS__, \ + true, true, true, true, true, true, true, true, \ + true, true, true, true, true, true, true, false, false ) + +/// @cond DO_NOT_DOCUMENT + +/// internal macros for GEOS_DETAIL_FIRST_ARG +#define GEOS_DETAIL_FIRST_ARG_false( FIRST ) FIRST +#define GEOS_DETAIL_FIRST_ARG_true( FIRST, ... ) FIRST +#define GEOS_DETAIL_FIRST_ARG_FUNC( COND ) GEOS_DETAIL_FIRST_ARG_ ## COND +#define GEOS_DETAIL_FIRST_ARG_DISPATCH( COND, ... ) GEOS_DETAIL_FIRST_ARG_FUNC( COND )(__VA_ARGS__) + +/// internal macros for GEOS_DETAIL_LAST_ARG +#define GEOS_DETAIL_REST_ARGS_false( FIRST ) +#define GEOS_DETAIL_REST_ARGS_true( FIRST, ... ) __VA_ARGS__ +#define GEOS_DETAIL_REST_ARGS_FUNC( COND ) GEOS_DETAIL_REST_ARGS_ ## COND +#define GEOS_DETAIL_REST_ARGS_DISPATCH( COND, ... ) GEOS_DETAIL_REST_ARGS_FUNC( COND )(__VA_ARGS__) + +/// internal macros for GEOS_DETAIL_LAST_ARG_PREP +#define GEOS_DETAIL_REST_PREP_ARGS_false( FIRST ) +#define GEOS_DETAIL_REST_PREP_ARGS_true( FIRST, ... ) , __VA_ARGS__ +#define GEOS_DETAIL_REST_PREP_ARGS_FUNC( COND ) GEOS_DETAIL_REST_PREP_ARGS_ ## COND +#define GEOS_DETAIL_REST_PREP_ARGS_DISPATCH( COND, ... ) GEOS_DETAIL_REST_PREP_ARGS_FUNC( COND )(__VA_ARGS__) + +/// @endcond + +/** + * @return Return the first parameter of the variadic parameters (__VA_ARGS__). + * @note Undefined behaviour if variadic argument has more that 16 elements. + */ +#define GEOS_DETAIL_FIRST_ARG( ... ) GEOS_DETAIL_FIRST_ARG_DISPATCH( GEOS_DETAIL_MORE_THAN_ONE_ARG( __VA_ARGS__ ), \ + __VA_ARGS__ ) + +/** + * @return Return the parameters following the first of the variadic parameters (__VA_ARGS__). + * @note Undefined behaviour if variadic argument has more that 16 elements. + */ +#define GEOS_DETAIL_REST_ARGS( ... ) GEOS_DETAIL_REST_ARGS_DISPATCH( GEOS_DETAIL_MORE_THAN_ONE_ARG( __VA_ARGS__ ), \ + __VA_ARGS__ ) + +/** + * @return Return the parameters following the first of the variadic parameters (__VA_ARGS__), + * prepended with a comma when not empty. + * @note Undefined behaviour if variadic argument has more that 16 elements. + */ +#define GEOS_DETAIL_REST_PREP_ARGS( ... ) GEOS_DETAIL_REST_PREP_ARGS_DISPATCH( GEOS_DETAIL_MORE_THAN_ONE_ARG( __VA_ARGS__ ), \ + __VA_ARGS__ ) + +///@} + #endif // GEOS_COMMON_GEOSXMACROS_HPP_ diff --git a/src/coreComponents/common/logger/ErrorHandling.cpp b/src/coreComponents/common/logger/ErrorHandling.cpp new file mode 100644 index 00000000000..ef526f2b7bf --- /dev/null +++ b/src/coreComponents/common/logger/ErrorHandling.cpp @@ -0,0 +1,261 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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.cpp + */ + +#include "ErrorHandling.hpp" +#include "common/logger/Logger.hpp" +#include "common/format/StringUtilities.hpp" + +#include +#include +#include + +namespace geos +{ +static constexpr std::string_view g_level1Start = " - "; +static constexpr std::string_view g_level1Next = " "; +// static constexpr std::string_view g_level2Start = " - "; // unused for now +static constexpr std::string_view g_level2Next = " "; +static constexpr std::string_view g_level3Start = " - "; +static constexpr std::string_view g_level3Next = " "; + +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 ) +{ + switch( attribute ) + { + case ErrorLogger::ErrorContext::Attribute::InputFile: return "inputFile"; + case ErrorLogger::ErrorContext::Attribute::InputLine: return "inputLine"; + case ErrorLogger::ErrorContext::Attribute::DataPath: return "dataPath"; + default: return "Unknown"; + } +} + +ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addToMsg( std::exception const & e, bool toEnd ) +{ + if( toEnd ) + { + m_msg = m_msg + e.what(); + } + else + { + m_msg = e.what() + m_msg; + } + return *this; +} + +ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addToMsg( std::string_view errorMsg, bool toEnd ) +{ + if( toEnd ) + { + m_msg = m_msg + std::string( errorMsg ); + } + else + { + m_msg = std::string( errorMsg ) + m_msg; + } + return *this; +} + +ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::setCodeLocation( std::string_view msgFile, integer msgLine ) +{ + m_file = msgFile; + m_line = msgLine; + return *this; +} + +ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::setType( ErrorLogger::MsgType msgType ) +{ + m_type = msgType; + return *this; +} + +ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::setCause( std::string_view cause ) +{ + m_cause = cause; + return *this; +} + +void ErrorLogger::ErrorMsg::addContextInfoImpl( ErrorLogger::ErrorContext && ctxInfo ) +{ + m_contextsInfo.emplace_back( std::move( ctxInfo ) ); +} + +ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addRank( int rank ) +{ + m_ranksInfo.emplace( rank ); + return *this; +} + +ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addCallStackInfo( std::string_view ossStackTrace ) +{ + std::string str = std::string( ossStackTrace ); + std::istringstream iss( str ); + std::string stackLine; + std::size_t index; + + std::regex pattern( R"(Frame \d+: \S+)" ); + + while( std::getline( iss, stackLine ) ) + { + if( std::regex_search( stackLine, pattern )) + { + m_isValidStackTrace = true; + index = stackLine.find( ':' ); + m_sourceCallStack.push_back( stackLine.substr( index + 1 ) ); + } + } + + if( !m_isValidStackTrace ) + { + m_sourceCallStack.push_back( str ); + } + + return *this; +} + +std::string ErrorLogger::toString( ErrorLogger::MsgType type ) +{ + switch( type ) + { + case ErrorLogger::MsgType::Error: return "Error"; + case ErrorLogger::MsgType::Warning: return "Warning"; + case ErrorLogger::MsgType::Exception: return "Exception"; + default: return "Unknown"; + } +} + +void ErrorLogger::streamMultilineYamlAttribute( std::string_view msg, std::ofstream & yamlFile, + std::string_view indent ) +{ + std::size_t i = 0; + // Loop that runs through the string_view named msg + while( i < msg.size() ) + { + // Index of the next line break + std::size_t index = msg.find( "\n", i ); + // If there is no line break, the entire string is taken + if( index == std::string_view::npos ) + { + index = msg.size(); + } + // Writes the current line to the YAML file with the desired indentation + std::string_view msgLine = msg.substr( i, index - i ); + yamlFile << indent << msgLine << "\n"; + // Move to the next line + i = index + 1; + } +} + +void ErrorLogger::flushErrorMsg( ErrorLogger::ErrorMsg & errorMsg ) +{ + std::ofstream yamlFile( std::string( m_filename ), std::ios::app ); + if( yamlFile.is_open() && isOutputFileEnabled() ) + { + // 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 << "\n"; + + // Error message + yamlFile << g_level1Next << "message: >-\n"; + streamMultilineYamlAttribute( errorMsg.m_msg, yamlFile, g_level2Next ); + + // context information + if( !errorMsg.m_contextsInfo.empty() ) + { + // Sort contextual information by decreasing priority + std::sort( errorMsg.m_contextsInfo.begin(), errorMsg.m_contextsInfo.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 ) + { + yamlFile << g_level3Start << "priority: " << ctxInfo.m_priority << "\n"; + for( auto const & [key, value] : ctxInfo.m_attributes ) + { + yamlFile << g_level3Next << ErrorContext::attributeToString( key ) << ": " << value << "\n"; + } + } + } + + // error cause + if( !errorMsg.m_cause.empty() ) + { + yamlFile << g_level1Next << "cause: >-\n"; + streamMultilineYamlAttribute( errorMsg.m_cause, yamlFile, g_level2Next ); + } + + // Location of the error in the code + yamlFile << g_level1Next << "sourceLocation:\n"; + yamlFile << g_level2Next << "file: " << errorMsg.m_file << "\n"; + yamlFile << g_level2Next << "line: " << errorMsg.m_line << "\n"; + + // Information about the stack trace + if( !errorMsg.m_sourceCallStack.empty() ) + { + yamlFile << g_level1Next << "sourceCallStack:\n"; + for( size_t i = 0; i < errorMsg.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 << "\n"; + yamlFile.flush(); + errorMsg = ErrorMsg(); + GEOS_LOG_RANK( GEOS_FMT( "The error file {} was appended.", m_filename ) ); + } + else + { + GEOS_LOG_RANK( GEOS_FMT( "Unable to open error file for writing.\n- Error file: {}\n- Error file enabled = {}.\n", + m_filename, isOutputFileEnabled() ) ); + } +} + +} /* namespace geos */ diff --git a/src/coreComponents/common/logger/ErrorHandling.hpp b/src/coreComponents/common/logger/ErrorHandling.hpp new file mode 100644 index 00000000000..a1275433a14 --- /dev/null +++ b/src/coreComponents/common/logger/ErrorHandling.hpp @@ -0,0 +1,316 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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_ERROR_LOGGER_HPP +#define INITIALIZATION_ERROR_LOGGER_HPP + +#include "common/DataTypes.hpp" + +namespace geos +{ + +/** + * @class ErrorLogger + * @brief Class to format and write different error/warning information that occured during the initialization + */ +class ErrorLogger +{ + +public: + /** + * @enum MsgType + * Enum listing the different types of possible errors + */ + enum class MsgType + { + Error, + Warning, + Exception, + Undefined + }; + + /** + * @struct ErrorContext + * Store contextual information about the error that occurred and assign it a priority + * default is 0 + */ + struct ErrorContext + { + + /** + * @enum Attribute + * Enumeration used to secure potential map keys + */ + enum class Attribute + { + InputFile, + InputLine, + DataPath + }; + + /// The map contains contextual information about the error + /// It could be something like + /// "file" = "/path/to/file.xml" + /// "line" = "24" + /// or something like + /// "dataPath" = "/Functions/co2brine_philipsDensityTable + /// The key is a field of the Attribute enumeration and is converted to a string for writing in the YAML + map< Attribute, std::string > m_attributes; + + /** + * @brief Priority level assigned to an error context. + * @details Used to prioritize contextes (higher values = more relevant). Default is 0. + * + */ + integer m_priority = 0; + + /** + * @brief Set the priority value of the current error context information + * @param priority the new value to asign + * @return the reference to the corresponding error + */ + ErrorContext & setPriority( integer priority ) + { m_priority = priority; return *this; } + + /** + * @brief Convert a value from the Attribute enumeration to a string + * @param attribute the value of the enumeration to be converted + * @return a string representation of the enumeration value + */ + static std::string attributeToString( Attribute attribute ); + }; + + /** + * @brief Struct to construct the error/warning object + */ + struct ErrorMsg + { + /// the error type (Warning, Error or Exception) + MsgType m_type = ErrorLogger::MsgType::Undefined; + /// the error message that can be completed + std::string m_msg; + /// the cause of the error (erroneous condition, failed assertion...) if identified (optional) + std::string m_cause; + /// the rank(s) on which the error occured + std::set< int > m_ranksInfo; + /// the source location file corresponding to the error in the code + std::string m_file; + /// the source location line corresponding to the error in the code (default is 0) + integer m_line = 0; + /// Additional information about the error in the input file + std::vector< ErrorContext > m_contextsInfo; + /// the stack trace + std::vector< std::string > m_sourceCallStack; + + /** + * @brief Construct a default Error Message + */ + ErrorMsg() + {} + + /** + * @brief Construct a new Error Message from parameters + * @param msgType the type of the message (error or warning) + * @param msgContent the error/warning message content + * @param rank the rank where the error occcured + * @param msgFile the source file name where the error occcured + * @param msgLine the line where the error occured + */ + ErrorMsg( MsgType msgType, + std::string_view msgContent, + integer rank, + std::string_view msgFile, + integer msgLine ) + : m_type( msgType ), m_msg( msgContent ), m_ranksInfo( {rank} ), m_file( msgFile ), m_line( msgLine ) {} + + /** + * @brief Add text to the current error msg + * @param e The exception containing text to add + * @param toEnd Indicates whether to add the message at the beginning (true) or at the end (false) + * default is false + * @return Reference to the current instance for method chaining. + */ + ErrorMsg & addToMsg( std::exception const & e, bool toEnd = false ); + + /** + * @brief Add text to the current error msg + * @param msg The text to add + * @param toEnd Indicates whether to add the message at the beginning (true) or at the end (false) + * default is false + * @return Reference to the current instance for method chaining. + */ + ErrorMsg & addToMsg( std::string_view msg, bool toEnd = false ); + + /** + * @brief Set the source code location values (file and line where the error is detected) + * @param msgFile Name of the source file location to add + * @param msgLine Line of the source file location to add + * @return Reference to the current instance for method chaining. + */ + ErrorMsg & setCodeLocation( std::string_view msgFile, integer msgLine ); + + /** + * @brief Set the type of the error + * @param msgType The type can be error, warning or exception + * @return Reference to the current instance for method chaining. + */ + ErrorMsg & setType( MsgType msgType ); + + /** + * @brief Set the cause of the error + * @param cause See documentation of m_cause. + * @return Reference to the current instance for method chaining. + */ + ErrorMsg & setCause( std::string_view cause ); + + /** + * @brief Add a rank on which the error has been raised + * @param rank The value to add + * @return Reference to the current instance for method chaining. + */ + ErrorMsg & addRank( int rank ); + + /** + * @brief Add stack trace information about the error + * @param ossStackTrace stack trace information to add + * @return Reference to the current instance for method chaining. + */ + ErrorMsg & addCallStackInfo( std::string_view ossStackTrace ); + + /** + * @brief Adds one or more context elements to the error + * @tparam Args Variadic pack of compatible types (ErrorContext / DataContext) + * @param args List of context data structures. + * @return Reference to the current instance for method chaining. + */ + template< typename ... Args > + ErrorMsg & addContextInfo( Args && ... args ); + + /** + * @return true if the YAML file output is enabled + */ + bool isValidStackTrace() const + { return m_isValidStackTrace; } + +private: + /** + * @brief Add contextual information about the error/warning + * @param ctxInfo rvalue of the ErrorContext class + */ + void addContextInfoImpl( ErrorContext && ctxInfo ); + + bool m_isValidStackTrace = false; + }; + + /** + * @return Global instance of the ErrorLogger class used for error/warning reporting. + * @details This global instance is used across the codebase to log errors, warnings, and exceptions, + * and to write structured output of errors. It is used through the logging macros. + * @note - local instances are possible for more specialized logging. + * - currently not available on GPU, use GEOS_WARNING/ERROR/ASSERT macros for this usecase. + */ + 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 + */ + void enableFileOutput( bool value ) + { m_writeYaml = value; } + + /** + * @brief Set the name of the YAML file if specified by user + * default is "errors.yaml" + * @param filename the name of the YAML file + */ + void setOutputFilename( std::string_view filename ) + { m_filename = filename; } + + /** + * @return The file name of the output error file + */ + std::string_view getOutputFilename() + { return m_filename; } + + /** + * @brief Gives acces to the error message that is currently being constructed, + * potencially at various application layers + * Use flushErrorMsg() when the message is fully constructed and you want it to be output + * @return Reference to the current instance for method chaining. + */ + ErrorMsg & currentErrorMsg() + { return m_currentErrorMsg; } + + /** + * @brief Create the YAML file or overwrite the contents if a YAML file of the same name already exists + * And write its header when the command line option is enabled + */ + void createFile(); + + /** + * @brief Convert a MsgType into a string + * @param type the message type label + * @return the string representation of the message type + */ + static std::string toString( MsgType type ); + + /** + * @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 ); + +private: + /// The error constructed via exceptions + ErrorMsg m_currentErrorMsg; + /// 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"; + + /** + * @brief Write the error message in the YAML file regarding indentation and line break + * @param msg the message to write in the YAML + * For the exception type, this message can be added as needed + */ + void streamMultilineYamlAttribute( std::string_view msg, std::ofstream & yamlFile, + std::string_view indent ); +}; + +/// @cond DO_NOT_DOCUMENT + +template< typename ... Args > +ErrorLogger::ErrorMsg & ErrorLogger::ErrorMsg::addContextInfo( Args && ... args ) +{ + ( this->addContextInfoImpl( ErrorContext( args ) ), ... ); + return *this; +} + +/// @endcond + +} /* namespace geos */ + +#endif diff --git a/src/coreComponents/common/logger/Logger.cpp b/src/coreComponents/common/logger/Logger.cpp index 0ea4c47a7cb..ade2834cbb2 100644 --- a/src/coreComponents/common/logger/Logger.cpp +++ b/src/coreComponents/common/logger/Logger.cpp @@ -27,7 +27,7 @@ namespace geos /** * @brief Insert an exception message in another one. - * @param originalMsg original exception message (i.e. thrown from LVARRAY_THROW or GEOS_THROW) + * @param originalMsg original exception message (i.e. thrown from GEOS_THROW) * @param msgToInsert message to insert at the top of the originalMsg */ std::string insertExMsg( std::string const & originalMsg, std::string const & msgToInsert ) @@ -69,16 +69,10 @@ namespace logger namespace internal { -int rank = 0; -std::string rankString = "0"; - -int n_ranks = 1; - -std::ostream * rankStream = nullptr; - -#ifdef GEOS_USE_MPI -MPI_Comm comm; -#endif +int g_rank = 0; +int g_n_ranks = 1; +std::string g_rankString = "?"; +std::ostream * g_rankStream = nullptr; } // namespace internal @@ -86,26 +80,25 @@ MPI_Comm comm; void InitializeLogger( MPI_Comm mpi_comm, const std::string & rankOutputDir ) { - internal::comm = mpi_comm; - MPI_Comm_rank( mpi_comm, &internal::rank ); - MPI_Comm_size( mpi_comm, &internal::n_ranks ); + MPI_Comm_rank( mpi_comm, &internal::g_rank ); + MPI_Comm_size( mpi_comm, &internal::g_n_ranks ); - internal::rankString = std::to_string( internal::rank ); + internal::g_rankString = std::to_string( internal::g_rank ); if( rankOutputDir != "" ) { - if( internal::rank == 0 ) + if( internal::g_rank == 0 ) { makeDirsForPath( rankOutputDir ); } MPI_Barrier( mpi_comm ); - std::string outputFilePath = rankOutputDir + "/rank_" + internal::rankString + ".out"; - internal::rankStream = new std::ofstream( outputFilePath ); + std::string outputFilePath = rankOutputDir + "/rank_" + internal::g_rankString + ".out"; + internal::g_rankStream = new std::ofstream( outputFilePath ); } else { - internal::rankStream = &std::cout; + internal::g_rankStream = &std::cout; } } @@ -117,23 +110,23 @@ void InitializeLogger( const std::string & rankOutputDir ) { makeDirsForPath( rankOutputDir ); - std::string outputFilePath = rankOutputDir + "/rank_" + internal::rankString + ".out"; - internal::rankStream = new std::ofstream( outputFilePath ); + std::string outputFilePath = rankOutputDir + "/rank_" + internal::g_rankString + ".out"; + internal::g_rankStream = new std::ofstream( outputFilePath ); } else { - internal::rankStream = &std::cout; + internal::g_rankStream = &std::cout; } } void FinalizeLogger() { - if( internal::rankStream != &std::cout ) + if( internal::g_rankStream != &std::cout ) { - delete internal::rankStream; + delete internal::g_rankStream; } - internal::rankStream = nullptr; + internal::g_rankStream = nullptr; } } // namespace logger diff --git a/src/coreComponents/common/logger/Logger.hpp b/src/coreComponents/common/logger/Logger.hpp index b8f837a966d..e59cfa05256 100644 --- a/src/coreComponents/common/logger/Logger.hpp +++ b/src/coreComponents/common/logger/Logger.hpp @@ -25,6 +25,7 @@ #include "common/GeosxMacros.hpp" #include "common/format/Format.hpp" #include "LvArray/src/Macros.hpp" +#include "common/logger/ErrorHandling.hpp" // System includes #include @@ -71,7 +72,7 @@ */ #define GEOS_LOG_RANK_0_IF( EXP, msg ) \ do { \ - if( ::geos::logger::internal::rank == 0 && EXP ) \ + if( ::geos::logger::internal::g_rank == 0 && EXP ) \ { \ std::ostringstream oss; \ oss << msg; \ @@ -86,7 +87,7 @@ */ #define GEOS_LOG_RANK_0_IF_NLR( EXP, msg ) \ do { \ - if( ::geos::logger::internal::rank == 0 && EXP ) \ + if( ::geos::logger::internal::g_rank == 0 && EXP ) \ { \ std::ostringstream oss; \ oss << msg; \ @@ -113,8 +114,8 @@ if( EXP ) \ { \ std::ostringstream oss; \ - oss << "Rank " << ::geos::logger::internal::rankString << ": " << msg; \ - *logger::internal::rankStream << oss.str() << std::endl; \ + oss << "Rank " << ::geos::logger::internal::g_rankString << ": " << msg; \ + *logger::internal::g_rankStream << oss.str() << std::endl; \ } \ } while( false ) #endif @@ -131,63 +132,253 @@ */ #define GEOS_LOG_RANK_VAR( var ) GEOS_LOG_RANK( #var " = " << var ) +/** + * @brief Error logger instance to use in GEOS_ERROR*, GEOS_ASSERT*, GEOS_THROW*, GEOS_WARNING* macros. + * @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() +#endif + /** * @brief Conditionally raise a hard error and terminate the program. - * @param EXP an expression that will be evaluated as a predicate - * @param msg a message to log (any expression that can be stream inserted) + * Implementation of GEOS_ERROR_* and GEOS_ASSERT_* macros. + * @param COND A condition that causes the error if true. + * @param CAUSE_MESSAGE The condition that caused the error, in a readable text format for the user. + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#if defined(GEOS_DEVICE_COMPILE) -#define GEOS_ERROR_IF( EXP, msg ) LVARRAY_ERROR_IF( EXP, msg ) -#else -#define GEOS_ERROR_IF( EXP, msg ) LVARRAY_ERROR_IF( EXP, "***** Rank " << ::geos::logger::internal::rankString << ": " << msg ) +#if !defined(GEOS_DEVICE_COMPILE) +#define GEOS_ERROR_IF_CAUSE( COND, CAUSE_MESSAGE, ... ) \ + do \ + { \ + if( COND ) \ + { \ + 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 ); \ + } \ + LvArray::system::callErrorHandler(); \ + } \ + } while( false ) +#elif __CUDA_ARCH__ +#define GEOS_ERROR_IF_CAUSE( COND, CAUSE_MESSAGE, ... ) \ + do \ + { \ + if( COND ) \ + { \ + constexpr char const * formatString = "***** ERROR\n" \ + "***** LOCATION" LOCATION "\n" \ + "***** BLOCK: [%u, %u, %u]\n" \ + "***** THREAD: [%u, %u, %u]\n" \ + "***** " STRINGIZE( CAUSE_MESSAGE ) "\n" \ + "***** " STRINGIZE( GEOS_DETAIL_FIRST_ARG( __VA_ARGS__ ) ) "\n\n"; \ + printf( formatString, blockIdx.x, blockIdx.y, blockIdx.z, threadIdx.x, threadIdx.y, threadIdx.z ); \ + asm ( "trap;" ); \ + } \ + } while( false ) #endif /** - * @brief Conditionally throw an exception. - * @param EXP an expression that will be evaluated as a predicate - * @param msg a message to log (any expression that can be stream inserted) - * @param TYPE the type of exception to throw + * @brief Conditionally raise a hard error and terminate the program. + * @param COND A condition that causes the error if true. + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_THROW_IF( EXP, msg, TYPE ) LVARRAY_THROW_IF( EXP, "***** Rank " << ::geos::logger::internal::rankString << ": " << msg, TYPE ) +#define GEOS_ERROR_IF( COND, ... ) \ + GEOS_ERROR_IF_CAUSE( COND, "Error cause: " STRINGIZE( COND ), __VA_ARGS__ ) /** * @brief Raise a hard error and terminate the program. - * @param msg a message to log (any expression that can be stream inserted) + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_ERROR( msg ) GEOS_ERROR_IF( true, msg ) +#define GEOS_ERROR( ... ) GEOS_ERROR_IF_CAUSE( true, "", __VA_ARGS__ ) /** - * @brief Throw an exception. - * @param msg a message to log (any expression that can be stream inserted) - * @param TYPE the type of exception to throw + * @brief Conditionally throw an exception. + * @param COND an expression that will be evaluated as a predicate + * @param CAUSE_MESSAGE The condition that caused the error, in a readable text format for the user. + * @param MSG a message to log (any expression that can be stream inserted) + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the type of the exception to throw + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_THROW( msg, TYPE ) GEOS_THROW_IF( true, msg, TYPE ) +#if !defined(GEOS_DEVICE_COMPILE) +#define GEOS_THROW_IF_CAUSE( COND, CAUSE_MESSAGE, MSG, ... ) \ + do \ + { \ + if( COND ) \ + { \ + 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() ); \ + } \ + } while( false ) +#elif __CUDA_ARCH__ +#define GEOS_THROW_IF_CAUSE( COND, CAUSE_MESSAGE, MSG, ... ) \ + do \ + { \ + if( COND ) \ + { \ + static char const formatString[] = "***** ERROR\n" \ + "***** LOCATION" LOCATION "\n" \ + "***** BLOCK: [%u, %u, %u]\n" \ + "***** THREAD: [%u, %u, %u]\n" \ + "***** " STRINGIZE( CAUSE_MESSAGE ) "\n" \ + "***** " STRINGIZE( GEOS_DETAIL_FIRST_ARG( __VA_ARGS__ ) ) "\n\n"; \ + printf( formatString, blockIdx.x, blockIdx.y, blockIdx.z, threadIdx.x, threadIdx.y, threadIdx.z ); \ + asm ( "trap;" ); \ + } \ + } while( false ) +#endif /** - * @brief Assert a condition in debug builds. - * @param EXP an expression that will be evaluated as a predicate - * @param msg a message to log (any expression that can be stream inserted) + * @brief Conditionally raise a hard error and terminate the program. + * @param COND A condition that causes the error if true. + * @param MSG a message to log (any expression that can be stream inserted) + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the type of the exception to throw + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_ASSERT_MSG( EXP, msg ) LVARRAY_ASSERT_MSG( EXP, "***** Rank " << ::geos::logger::internal::rankString << ": " << msg ) +#define GEOS_THROW_IF( COND, MSG, ... ) \ + GEOS_THROW_IF_CAUSE( COND, "Error cause: " STRINGIZE( COND ), MSG, __VA_ARGS__ ) /** - * @brief Assert a condition in debug builds. - * @param EXP an expression that will be evaluated as a predicate + * @brief Conditionally raise a hard error and terminate the program. + * @param MSG a message to log (any expression that can be stream inserted) + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the type of the exception to throw + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_ASSERT( EXP ) GEOS_ASSERT_MSG( EXP, "" ) +#define GEOS_THROW( MSG, ... ) GEOS_THROW_IF_CAUSE( true, "", MSG, __VA_ARGS__ ) + +/** + * @brief Conditionally report a warning + * @param COND A condition that causes the error if true. + * @param CAUSE_MESSAGE The condition that caused the error, in a readable text format for the user. + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) + */ +#if !defined(GEOS_DEVICE_COMPILE) +#define GEOS_WARNING_IF_CAUSE( COND, CAUSE_MESSAGE, ... ) \ + do \ + { \ + if( COND ) \ + { \ + 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 ); \ + } \ + } \ + } while( false ) +#elif __CUDA_ARCH__ +#define GEOS_WARNING_IF_CAUSE( COND, CAUSE_MESSAGE, ... ) \ + do \ + { \ + if( COND ) \ + { \ + static char const formatString[] = "***** WARNING\n" \ + "***** LOCATION" LOCATION "\n" \ + "***** BLOCK: [%u, %u, %u]\n" \ + "***** THREAD: [%u, %u, %u]\n" \ + "***** " STRINGIZE( CAUSE_MESSAGE ) "\n" \ + "***** " STRINGIZE( GEOS_DETAIL_FIRST_ARG( __VA_ARGS__ ) ) "\n\n"; \ + printf( formatString, blockIdx.x, blockIdx.y, blockIdx.z, threadIdx.x, threadIdx.y, threadIdx.z ); \ + asm ( "trap;" ); \ + } \ + } while( false ) +#endif /** * @brief Conditionally report a warning. - * @param EXP an expression that will be evaluated as a predicate - * @param msg a message to log (any expression that can be stream inserted) + * @param COND an expression that will be evaluated as a predicate + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_WARNING_IF( EXP, msg ) LVARRAY_WARNING_IF( EXP, msg ) +#define GEOS_WARNING_IF( COND, ... ) \ + GEOS_WARNING_IF_CAUSE( COND, "Warning cause: " STRINGIZE( COND ), __VA_ARGS__ ) /** * @brief Report a warning. - * @param msg a message to log (any expression that can be stream inserted) + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_WARNING( msg ) LVARRAY_WARNING( msg ) +#define GEOS_WARNING( ... ) GEOS_WARNING_IF_CAUSE( true, "", __VA_ARGS__ ) /** * @brief Conditionally log an info message. @@ -203,21 +394,42 @@ #define GEOS_INFO( msg ) LVARRAY_INFO( msg ) /** - * @brief Raise a hard error if two values are equal. - * @param lhs expression to be evaluated and used as left-hand side in comparison - * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param msg a message to log (any expression that can be stream inserted) + * @brief Declares variables for "assertion" evaluation only on CPU; no-op on GPU to avoid device compilation errors. + * @param lhs The left side of the operation. + * @param rhs The right side of the operation. */ -#define GEOS_ERROR_IF_EQ_MSG( lhs, rhs, msg ) LVARRAY_ERROR_IF_EQ_MSG( lhs, rhs, "***** Rank " << ::geos::logger::internal::rankString << ": " << msg ) +#define GEOS_ERROR_LHS_RHS_DECLS( lhs, rhs ) \ + GEOS_MAYBE_UNUSED auto const lhsResult = (lhs); \ + GEOS_MAYBE_UNUSED auto const rhsResult = (rhs) + +/** + * @brief Abort execution if @p lhs @p OP @p rhs. + * @param lhs The left side of the operation. + * @param OP The operation to apply. + * @param NOP The operation that caused the error, used in the message (typically opposite of @p OP). + * @param rhs The right side of the operation. + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_ERROR_IF_OP_MSG( lhs, OP, NOP, rhs, ... ) \ + do { \ + GEOS_ERROR_LHS_RHS_DECLS( lhs, rhs ); \ + GEOS_ERROR_IF_CAUSE( lhsResult OP rhsResult, \ + "Expected: " #lhs " " #NOP " " #rhs "\n* " #lhs " = " << lhsResult << "\n* " #rhs " = " << rhsResult << "\n", \ + __VA_ARGS__ ); \ + } while(false) + /** * @brief Raise a hard error if two values are equal. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param msg a message to log (any expression that can be stream inserted) - * @param TYPE the type of exception to throw + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_THROW_IF_EQ_MSG( lhs, rhs, msg, TYPE ) LVARRAY_THROW_IF_EQ_MSG( lhs, rhs, "***** Rank " << ::geos::logger::internal::rankString << ": " << msg, TYPE ) +#define GEOS_ERROR_IF_EQ_MSG( lhs, rhs, ... ) GEOS_ERROR_IF_OP_MSG( lhs, ==, !=, rhs, __VA_ARGS__ ) /** * @brief Raise a hard error if two values are equal. @@ -227,180 +439,420 @@ #define GEOS_ERROR_IF_EQ( lhs, rhs ) GEOS_ERROR_IF_EQ_MSG( lhs, rhs, "" ) /** - * @brief Raise a hard error if two values are equal. + * @brief Raise a hard error if two values are not equal. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param TYPE the type of exception to throw + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_THROW_IF_EQ( lhs, rhs, TYPE ) GEOS_THROW_IF_EQ_MSG( lhs, rhs, "", TYPE ) +#define GEOS_ERROR_IF_NE_MSG( lhs, rhs, ... ) GEOS_ERROR_IF_OP_MSG( lhs, !=, ==, rhs, __VA_ARGS__ ) /** * @brief Raise a hard error if two values are not equal. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param msg a message to log (any expression that can be stream inserted) */ -#define GEOS_ERROR_IF_NE_MSG( lhs, rhs, msg ) LVARRAY_ERROR_IF_NE_MSG( lhs, rhs, "***** Rank " << ::geos::logger::internal::rankString << ": " << msg ) +#define GEOS_ERROR_IF_NE( lhs, rhs ) GEOS_ERROR_IF_NE_MSG( lhs, rhs, "" ) /** - * @brief Throw an exception if two values are not equal. + * @brief Raise a hard error if one value compares greater than the other. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param msg a message to log (any expression that can be stream inserted) - * @param TYPE the type of exception to throw + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_THROW_IF_NE_MSG( lhs, rhs, msg, TYPE ) LVARRAY_THROW_IF_NE_MSG( lhs, rhs, "***** Rank " << ::geos::logger::internal::rankString << ": " << msg, TYPE ) +#define GEOS_ERROR_IF_GT_MSG( lhs, rhs, ... ) GEOS_ERROR_IF_OP_MSG( lhs, >, <=, rhs, __VA_ARGS__ ) /** - * @brief Raise a hard error if two values are not equal. + * @brief Raise a hard error if one value compares greater than the other. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison */ -#define GEOS_ERROR_IF_NE( lhs, rhs ) GEOS_ERROR_IF_NE_MSG( lhs, rhs, "" ) +#define GEOS_ERROR_IF_GT( lhs, rhs ) GEOS_ERROR_IF_GT_MSG( lhs, rhs, "" ) /** - * @brief Throw an exception if two values are not equal. + * @brief Raise a hard error if one value compares greater than or equal to the other. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param TYPE the type of exception to throw + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_THROW_IF_NE( lhs, rhs, TYPE ) GEOS_THROW_IF_NE_MSG( lhs, rhs, "", TYPE ) +#define GEOS_ERROR_IF_GE_MSG( lhs, rhs, ... ) GEOS_ERROR_IF_OP_MSG( lhs, >=, <, rhs, __VA_ARGS__ ) /** - * @brief Raise a hard error if one value compares greater than the other. + * @brief Raise a hard error if one value compares greater than or equal to the other. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param msg a message to log (any expression that can be stream inserted) */ -#define GEOS_ERROR_IF_GT_MSG( lhs, rhs, msg ) LVARRAY_ERROR_IF_GT_MSG( lhs, rhs, "***** Rank " << ::geos::logger::internal::rankString << ": " << msg ) +#define GEOS_ERROR_IF_GE( lhs, rhs ) GEOS_ERROR_IF_GE_MSG( lhs, rhs, "" ) /** - * @brief Throw an exception if one value compares greater than the other. + * @brief Raise a hard error if one value compares less than the other. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param msg a message to log (any expression that can be stream inserted) - * @param TYPE the type of exception to throw + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_THROW_IF_GT_MSG( lhs, rhs, msg, TYPE ) LVARRAY_THROW_IF_GT_MSG( lhs, rhs, "***** Rank " << ::geos::logger::internal::rankString << ": " << msg, TYPE ) +#define GEOS_ERROR_IF_LT_MSG( lhs, rhs, ... ) GEOS_ERROR_IF_OP_MSG( lhs, <, >=, rhs, __VA_ARGS__ ) /** - * @brief Raise a hard error if one value compares greater than the other. + * @brief Raise a hard error if one value compares less than the other. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison */ -#define GEOS_ERROR_IF_GT( lhs, rhs ) GEOS_ERROR_IF_GT_MSG( lhs, rhs, "" ) +#define GEOS_ERROR_IF_LT( lhs, rhs ) GEOS_ERROR_IF_LT_MSG( lhs, rhs, "" ) /** - * @brief Throw an exception if one value compares greater than the other. + * @brief Raise a hard error if one value compares less than or equal to the other. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param TYPE the type of exception to throw + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_THROW_IF_GT( lhs, rhs, TYPE ) GEOS_ERROR_IF_GT_MSG( lhs, rhs, "", TYPE ) +#define GEOS_ERROR_IF_LE_MSG( lhs, rhs, ... ) GEOS_ERROR_IF_OP_MSG( lhs, <=, >, rhs, __VA_ARGS__ ) + /** - * @brief Raise a hard error if one value compares greater than or equal to the other. + * @brief Raise a hard error if one value compares less than or equal to the other. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param msg a message to log (any expression that can be stream inserted) */ -#define GEOS_ERROR_IF_GE_MSG( lhs, rhs, msg ) LVARRAY_ERROR_IF_GE_MSG( lhs, rhs, "***** Rank " << ::geos::logger::internal::rankString << ": " << msg ) +#define GEOS_ERROR_IF_LE( lhs, rhs ) GEOS_ERROR_IF_LE_MSG( lhs, rhs, "" ) /** - * @brief Throw an exception if one value compares greater than or equal to the other. + * @brief Log a warning if @p lhs @p OP @p rhs. + * @param lhs The left side of the operation. + * @param OP The operation to apply. + * @param NOP The operation that caused the error, used in the message (typically opposite of @p OP). + * @param rhs The right side of the operation. + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_WARNING_IF_OP_MSG( lhs, OP, NOP, rhs, ... ) \ + do { \ + GEOS_ERROR_LHS_RHS_DECLS( lhs, rhs ); \ + GEOS_WARNING_IF_CAUSE( lhsResult OP rhsResult, \ + "Expected: " #lhs " " #NOP " " #rhs "\n* " #lhs " = " << lhsResult << "\n* " #rhs " = " << rhsResult << "\n", \ + __VA_ARGS__ ); \ + } while(false) + + +/** + * @brief Log a warning if two values are equal. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param msg a message to log (any expression that can be stream inserted) - * @param TYPE the type of exception to throw + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_THROW_IF_GE_MSG( lhs, rhs, msg, TYPE ) LVARRAY_THROW_IF_GE_MSG( lhs, rhs, "***** Rank " << ::geos::logger::internal::rankString << ": " << msg, TYPE ) +#define GEOS_WARNING_IF_EQ_MSG( lhs, rhs, ... ) GEOS_WARNING_IF_OP_MSG( lhs, ==, !=, rhs, __VA_ARGS__ ) /** - * @brief Raise a hard error if one value compares greater than or equal to the other. + * @brief Log a warning if two values are equal. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison */ -#define GEOS_ERROR_IF_GE( lhs, rhs ) GEOS_ERROR_IF_GE_MSG( lhs, rhs, "" ) +#define GEOS_WARNING_IF_EQ( lhs, rhs ) GEOS_WARNING_IF_EQ_MSG( lhs, rhs, "" ) /** - * @brief Throw an exception if one value compares greater than or equal to the other. + * @brief Log a warning if two values are not equal. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param TYPE the type of exception to throw + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_THROW_IF_GE( lhs, rhs, TYPE ) GEOS_ERROR_IF_GE_MSG( lhs, rhs, "", TYPE ) +#define GEOS_WARNING_IF_NE_MSG( lhs, rhs, ... ) GEOS_WARNING_IF_OP_MSG( lhs, !=, ==, rhs, __VA_ARGS__ ) /** - * @brief Raise a hard error if one value compares less than the other. + * @brief Log a warning if two values are not equal. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param msg a message to log (any expression that can be stream inserted) */ -#define GEOS_ERROR_IF_LT_MSG( lhs, rhs, msg ) LVARRAY_ERROR_IF_LT_MSG( lhs, rhs, "***** Rank " << ::geos::logger::internal::rankString << ": " << msg ) +#define GEOS_WARNING_IF_NE( lhs, rhs ) GEOS_WARNING_IF_NE_MSG( lhs, rhs, "" ) /** - * @brief Throw an exception if one value compares less than the other. + * @brief Log a warning if one value compares greater than the other. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param msg a message to log (any expression that can be stream inserted) - * @param TYPE the type of exception to throw + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_THROW_IF_LT_MSG( lhs, rhs, msg, TYPE ) LVARRAY_THROW_IF_LT_MSG( lhs, rhs, "***** Rank " << ::geos::logger::internal::rankString << ": " << msg, TYPE ) +#define GEOS_WARNING_IF_GT_MSG( lhs, rhs, ... ) GEOS_WARNING_IF_OP_MSG( lhs, >, <=, rhs, __VA_ARGS__ ) /** - * @brief Raise a hard error if one value compares less than the other. + * @brief Log a warning if one value compares greater than the other. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison */ -#define GEOS_ERROR_IF_LT( lhs, rhs ) GEOS_ERROR_IF_LT_MSG( lhs, rhs, "" ) +#define GEOS_WARNING_IF_GT( lhs, rhs ) GEOS_WARNING_IF_GT_MSG( lhs, rhs, "" ) /** - * @brief Throw an exception if one value compares less than the other. + * @brief Log a warning if one value compares greater than or equal to the other. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param TYPE the type of exception to throw + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_THROW_IF_LT( lhs, rhs, TYPE ) GEOS_ERROR_IF_LT_MSG( lhs, rhs, "", TYPE ) +#define GEOS_WARNING_IF_GE_MSG( lhs, rhs, ... ) GEOS_WARNING_IF_OP_MSG( lhs, >=, <, rhs, __VA_ARGS__ ) /** - * @brief Raise a hard error if one value compares less than or equal to the other. + * @brief Log a warning if one value compares greater than or equal to the other. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param msg a message to log (any expression that can be stream inserted) */ -#define GEOS_ERROR_IF_LE_MSG( lhs, rhs, msg ) LVARRAY_ERROR_IF_LE_MSG( lhs, rhs, "***** Rank " << ::geos::logger::internal::rankString << ": " << msg ) +#define GEOS_WARNING_IF_GE( lhs, rhs ) GEOS_WARNING_IF_GE_MSG( lhs, rhs, "" ) /** - * @brief Throw an exception if one value compares less than or equal to the other. + * @brief Log a warning if one value compares less than the other. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param msg a message to log (any expression that can be stream inserted) - * @param TYPE the type of exception to throw + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_THROW_IF_LE_MSG( lhs, rhs, msg, TYPE ) LVARRAY_THROW_IF_LE_MSG( lhs, rhs, "***** Rank " << ::geos::logger::internal::rankString << ": " << msg, TYPE ) +#define GEOS_WARNING_IF_LT_MSG( lhs, rhs, ... ) GEOS_WARNING_IF_OP_MSG( lhs, <, >=, rhs, __VA_ARGS__ ) /** - * @brief Raise a hard error if one value compares less than or equal to the other. + * @brief Log a warning if one value compares less than the other. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison */ -#define GEOS_ERROR_IF_LE( lhs, rhs ) GEOS_ERROR_IF_LE_MSG( lhs, rhs, "" ) +#define GEOS_WARNING_IF_LT( lhs, rhs ) GEOS_WARNING_IF_LT_MSG( lhs, rhs, "" ) + +/** + * @brief Log a warning if one value compares less than or equal to the other. + * @param lhs expression to be evaluated and used as left-hand side in comparison + * @param rhs expression to be evaluated and used as right-hand side in comparison + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_WARNING_IF_LE_MSG( lhs, rhs, ... ) GEOS_WARNING_IF_OP_MSG( lhs, <=, >, rhs, __VA_ARGS__ ) + +/** + * @brief Log a warning if one value compares less than or equal to the other. + * @param lhs expression to be evaluated and used as left-hand side in comparison + * @param rhs expression to be evaluated and used as right-hand side in comparison + */ +#define GEOS_WARNING_IF_LE( lhs, rhs ) GEOS_WARNING_IF_LE_MSG( lhs, rhs, "" ) + +/** + * @brief Throw an exception if @p lhs @p OP @p rhs. + * @param lhs The left side of the operation. + * @param OP The operation to apply. + * @param NOP The operation that caused the error, used in the message (typically opposite of @p OP). + * @param rhs The right side of the operation. + * @param MSG a message to log (any expression that can be stream inserted) + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the type of the exception to throw + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_THROW_IF_OP_MSG( lhs, OP, NOP, rhs, MSG, ... ) \ + do { \ + GEOS_ERROR_LHS_RHS_DECLS( lhs, rhs ); \ + GEOS_THROW_IF_CAUSE( lhsResult OP rhsResult, \ + "Expected: " #lhs " " #NOP " " #rhs "\n* " #lhs " = " << lhsResult << "\n* " #rhs " = " << rhsResult << "\n", \ + MSG, __VA_ARGS__ ); \ + } while(false) + + + +/** + * @brief Raise a hard error if two values are equal. + * @param lhs expression to be evaluated and used as left-hand side in comparison + * @param rhs expression to be evaluated and used as right-hand side in comparison + * @param MSG a message to log (any expression that can be stream inserted) + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the type of the exception to throw + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_THROW_IF_EQ_MSG( lhs, rhs, MSG, ... ) GEOS_THROW_IF_OP_MSG( lhs, ==, !=, rhs, MSG, __VA_ARGS__ ) + +/** + * @brief Raise a hard error if two values are equal. + * @param lhs expression to be evaluated and used as left-hand side in comparison + * @param rhs expression to be evaluated and used as right-hand side in comparison + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the type of the exception to throw + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_THROW_IF_EQ( lhs, rhs, ... ) GEOS_THROW_IF_EQ_MSG( lhs, rhs, "", __VA_ARGS__ ) + +/** + * @brief Throw an exception if two values are not equal. + * @param lhs expression to be evaluated and used as left-hand side in comparison + * @param rhs expression to be evaluated and used as right-hand side in comparison + * @param MSG a message to log (any expression that can be stream inserted) + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the type of the exception to throw + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_THROW_IF_NE_MSG( lhs, rhs, MSG, ... ) GEOS_THROW_IF_OP_MSG( lhs, !=, ==, rhs, MSG, __VA_ARGS__ ) + +/** + * @brief Throw an exception if two values are not equal. + * @param lhs expression to be evaluated and used as left-hand side in comparison + * @param rhs expression to be evaluated and used as right-hand side in comparison + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the type of the exception to throw + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_THROW_IF_NE( lhs, rhs, ... ) GEOS_THROW_IF_NE_MSG( lhs, rhs, "", __VA_ARGS__ ) + +/** + * @brief Throw an exception if one value compares greater than the other. + * @param lhs expression to be evaluated and used as left-hand side in comparison + * @param rhs expression to be evaluated and used as right-hand side in comparison + * @param MSG a message to log (any expression that can be stream inserted) + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the type of the exception to throw + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_THROW_IF_GT_MSG( lhs, rhs, MSG, ... ) GEOS_THROW_IF_OP_MSG( lhs, >, <=, rhs, MSG, __VA_ARGS__ ) + +/** + * @brief Throw an exception if one value compares greater than the other. + * @param lhs expression to be evaluated and used as left-hand side in comparison + * @param rhs expression to be evaluated and used as right-hand side in comparison + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the type of the exception to throw + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_THROW_IF_GT( lhs, rhs, ... ) GEOS_THROW_IF_GT_MSG( lhs, rhs, "", __VA_ARGS__ ) + +/** + * @brief Throw an exception if one value compares greater than or equal to the other. + * @param lhs expression to be evaluated and used as left-hand side in comparison + * @param rhs expression to be evaluated and used as right-hand side in comparison + * @param MSG a message to log (any expression that can be stream inserted) + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the type of the exception to throw + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_THROW_IF_GE_MSG( lhs, rhs, MSG, ... ) GEOS_THROW_IF_OP_MSG( lhs, >=, <, rhs, MSG, __VA_ARGS__ ) + +/** + * @brief Throw an exception if one value compares greater than or equal to the other. + * @param lhs expression to be evaluated and used as left-hand side in comparison + * @param rhs expression to be evaluated and used as right-hand side in comparison + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the type of the exception to throw + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_THROW_IF_GE( lhs, rhs, ... ) GEOS_THROW_IF_GE_MSG( lhs, rhs, "", __VA_ARGS__ ) + +/** + * @brief Throw an exception if one value compares less than the other. + * @param lhs expression to be evaluated and used as left-hand side in comparison + * @param rhs expression to be evaluated and used as right-hand side in comparison + * @param MSG a message to log (any expression that can be stream inserted) + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the type of the exception to throw + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_THROW_IF_LT_MSG( lhs, rhs, MSG, ... ) GEOS_THROW_IF_OP_MSG( lhs, <, >=, rhs, MSG, __VA_ARGS__ ) + +/** + * @brief Throw an exception if one value compares less than the other. + * @param lhs expression to be evaluated and used as left-hand side in comparison + * @param rhs expression to be evaluated and used as right-hand side in comparison + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the type of the exception to throw + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_THROW_IF_LT( lhs, rhs, ... ) GEOS_THROW_IF_LT_MSG( lhs, rhs, "", __VA_ARGS__ ) + +/** + * @brief Throw an exception if one value compares less than or equal to the other. + * @param lhs expression to be evaluated and used as left-hand side in comparison + * @param rhs expression to be evaluated and used as right-hand side in comparison + * @param MSG a message to log (any expression that can be stream inserted) + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the type of the exception to throw + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_THROW_IF_LE_MSG( lhs, rhs, MSG, ... ) GEOS_THROW_IF_OP_MSG( lhs, <=, >, rhs, MSG, __VA_ARGS__ ) /** * @brief Throw an exception if one value compares less than or equal to the other. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param TYPE the type of exception to throw + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the type of the exception to throw + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_THROW_IF_LE( lhs, rhs, ... ) GEOS_THROW_IF_LE_MSG( lhs, rhs, "", __VA_ARGS__ ) + +#if !defined(NDEBUG) || defined(GEOS_ASSERT_ENABLED) + +/** + * @brief Enables assertion macros (GEOS_ASSERT*) when NDEBUG is not defined or previously explicitly enabled. */ -#define GEOS_THROW_IF_LE( lhs, rhs, TYPE ) GEOS_ERROR_IF_LE_MSG( lhs, rhs, "", TYPE ) +#define GEOS_ASSERT_ENABLED + +/** + * @brief Abort execution if @p COND is false but only when NDEBUG is not defined.. + * @param COND The condition to check, causes an error if false. + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) + * @note This macro can be used in both host and device code. + * @note Tries to provide as much information about the location of the error + * as possible. On host this should result in the file and line of the error + * and a stack trace along with the provided message. On device none of this is + * guaranteed. In fact it is only guaranteed to abort the current kernel. + */ +#define GEOS_ASSERT_MSG( COND, ... ) \ + GEOS_ERROR_IF_CAUSE( !( COND ), "Expected: " STRINGIZE( COND ), __VA_ARGS__ ) + +/** + * @brief Abort execution if @p lhs @p OP @p rhs is false. + * @param lhs The left side of the operation. + * @param OP The operation to apply. + * @param rhs The right side of the operation. + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_ASSERT_OP_MSG( lhs, OP, rhs, ... ) \ + { \ + GEOS_ERROR_LHS_RHS_DECLS( lhs, rhs ); \ + GEOS_ERROR_IF_CAUSE( !( lhsResult OP rhsResult ), \ + "Expected: " #lhs " " #OP " " #rhs "\n* " #lhs " = " << lhsResult << "\n* " #rhs " = " << rhsResult << "\n", \ + __VA_ARGS__ ); \ + } + +#else + +#define GEOS_ASSERT_MSG( ... ) ((void) 0) +#define GEOS_ASSERT_OP_MSG( ... ) ((void) 0) + +#endif + +/** + * @brief Assert a condition in debug builds. + * @param COND The condition to check, causes an error if false. + */ +#define GEOS_ASSERT( COND ) GEOS_ASSERT_MSG( COND, "" ) /** * @brief Assert that two values compare equal in debug builds. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param msg a message to log (any expression that can be stream inserted) + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_ASSERT_EQ_MSG( lhs, rhs, msg ) LVARRAY_ASSERT_EQ_MSG( lhs, rhs, "***** Rank " << ::geos::logger::internal::rankString << ": " << msg ) +#define GEOS_ASSERT_EQ_MSG( lhs, rhs, ... ) GEOS_ASSERT_OP_MSG( lhs, ==, rhs, __VA_ARGS__ ) /** * @brief Assert that two values compare equal in debug builds. @@ -413,24 +865,28 @@ * @brief Assert that two values compare not equal in debug builds. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param msg a message to log (any expression that can be stream inserted) + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_ASSERT_NE_MSG( lhs, rhs, msg ) LVARRAY_ASSERT_NE_MSG( lhs, rhs, msg ) +#define GEOS_ASSERT_NE_MSG( lhs, rhs, ... ) GEOS_ASSERT_OP_MSG( lhs, !=, rhs, __VA_ARGS__ ) /** * @brief Assert that two values compare not equal in debug builds. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison */ -#define GEOS_ASSERT_NE( lhs, rhs ) LVARRAY_ASSERT_NE( lhs, rhs ) +#define GEOS_ASSERT_NE( lhs, rhs ) GEOS_ASSERT_NE_MSG( lhs, rhs, "" ) /** * @brief Assert that one value compares greater than the other in debug builds. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param msg a message to log (any expression that can be stream inserted) + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_ASSERT_GT_MSG( lhs, rhs, msg ) LVARRAY_ASSERT_GT_MSG( lhs, rhs, "***** Rank " << ::geos::logger::internal::rankString << ": " << msg ) +#define GEOS_ASSERT_GT_MSG( lhs, rhs, ... ) GEOS_ASSERT_OP_MSG( lhs, >, rhs, __VA_ARGS__ ) /** * @brief Assert that one value compares greater than the other in debug builds. @@ -443,9 +899,11 @@ * @brief Assert that one value compares greater than or equal to the other in debug builds. * @param lhs expression to be evaluated and used as left-hand side in comparison * @param rhs expression to be evaluated and used as right-hand side in comparison - * @param msg a message to log (any expression that can be stream inserted) + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) */ -#define GEOS_ASSERT_GE_MSG( lhs, rhs, msg ) LVARRAY_ASSERT_GE_MSG( lhs, rhs, "***** Rank " << ::geos::logger::internal::rankString << ": " << msg ) +#define GEOS_ASSERT_GE_MSG( lhs, rhs, ... ) GEOS_ASSERT_OP_MSG( lhs, >=, rhs, __VA_ARGS__ ) /** * @brief Assert that one value compares greater than or equal to the other in debug builds. @@ -454,6 +912,40 @@ */ #define GEOS_ASSERT_GE( lhs, rhs ) GEOS_ASSERT_GE_MSG( lhs, rhs, "" ) +/** + * @brief Assert that one value compares greater than the other in debug builds. + * @param lhs expression to be evaluated and used as left-hand side in comparison + * @param rhs expression to be evaluated and used as right-hand side in comparison + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_ASSERT_LT_MSG( lhs, rhs, ... ) GEOS_ASSERT_OP_MSG( lhs, <, rhs, __VA_ARGS__ ) + +/** + * @brief Assert that one value compares greater than the other in debug builds. + * @param lhs expression to be evaluated and used as left-hand side in comparison + * @param rhs expression to be evaluated and used as right-hand side in comparison + */ +#define GEOS_ASSERT_LT( lhs, rhs ) GEOS_ASSERT_LT_MSG( lhs, rhs, "" ) + +/** + * @brief Assert that one value compares greater than or equal to the other in debug builds. + * @param lhs expression to be evaluated and used as left-hand side in comparison + * @param rhs expression to be evaluated and used as right-hand side in comparison + * @param ... Variable arguments with the following structure: + * - Mandatory first parameter, the message to log (must be streamable) + * - Optional following parameters, context information on the current error (DataContext) + */ +#define GEOS_ASSERT_LE_MSG( lhs, rhs, ... ) GEOS_ASSERT_OP_MSG( lhs, <=, rhs, __VA_ARGS__ ) + +/** + * @brief Assert that one value compares greater than or equal to the other in debug builds. + * @param lhs expression to be evaluated and used as left-hand side in comparison + * @param rhs expression to be evaluated and used as right-hand side in comparison + */ +#define GEOS_ASSERT_LE( lhs, rhs ) GEOS_ASSERT_LE_MSG( lhs, rhs, "" ) + namespace geos { @@ -545,17 +1037,12 @@ namespace logger namespace internal { -extern int rank; +extern int g_rank; -extern std::string rankString; +extern std::string g_rankString; -extern int n_ranks; +extern std::ostream * g_rankStream; -extern std::ostream * rankStream; - -#if defined(GEOS_USE_MPI) -extern MPI_Comm comm; -#endif } // namespace internal #if defined(GEOS_USE_MPI) @@ -578,7 +1065,7 @@ void InitializeLogger( const std::string & rank_output_dir="" ); */ void FinalizeLogger(); -} // namespace logger +} // namespace logger } // namespace geos diff --git a/src/coreComponents/common/unitTests/CMakeLists.txt b/src/coreComponents/common/unitTests/CMakeLists.txt index b0eb4ef72a1..2f6966bf487 100644 --- a/src/coreComponents/common/unitTests/CMakeLists.txt +++ b/src/coreComponents/common/unitTests/CMakeLists.txt @@ -2,6 +2,7 @@ set( gtest_geosx_tests testDataTypes.cpp testFixedSizeDeque.cpp + testMacros.cpp testMpiWrapper.cpp testTypeDispatch.cpp testLifoStorage.cpp diff --git a/src/coreComponents/common/unitTests/testLifoStorage.cpp b/src/coreComponents/common/unitTests/testLifoStorage.cpp index 54c5a864bc3..0a6ea4b410a 100644 --- a/src/coreComponents/common/unitTests/testLifoStorage.cpp +++ b/src/coreComponents/common/unitTests/testLifoStorage.cpp @@ -29,9 +29,9 @@ #define PORTABLE_EXPECT_NEAR( L, R, EPSILON ) EXPECT_LE( math::abs( ( L ) -( R ) ), EPSILON ) << \ STRINGIZE( L ) " = " << ( L ) << "\n" << STRINGIZE( R ) " = " << ( R ); #else -#define PORTABLE_EXPECT_EQ( L, R ) LVARRAY_ERROR_IF_NE( L, R ) -#define PORTABLE_EXPECT_NEAR( L, R, EPSILON ) LVARRAY_ERROR_IF_GE_MSG( math::abs( ( L ) -( R ) ), EPSILON, \ - STRINGIZE( L ) " = " << ( L ) << "\n" << STRINGIZE( R ) " = " << ( R ) ); +#define PORTABLE_EXPECT_EQ( L, R ) GEOS_ERROR_IF_NE( L, R ) +#define PORTABLE_EXPECT_NEAR( L, R, EPSILON ) GEOS_ERROR_IF_GE_MSG( math::abs( ( L ) -( R ) ), EPSILON, \ + STRINGIZE( L ) " = " << ( L ) << "\n" << STRINGIZE( R ) " = " << ( R ) ); #endif namespace geos diff --git a/src/coreComponents/common/unitTests/testMacros.cpp b/src/coreComponents/common/unitTests/testMacros.cpp new file mode 100644 index 00000000000..1059c7d5877 --- /dev/null +++ b/src/coreComponents/common/unitTests/testMacros.cpp @@ -0,0 +1,95 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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. + * ------------------------------------------------------------------------------------------------------------ + */ + +// Source includes +#include "common/GeosxMacros.hpp" +// TPL includes +#include +#include +// test dependancies +#include + +TEST( testMacros, testArgumentCount ) +{ + EXPECT_EQ( 0, int( GEOS_DETAIL_MORE_THAN_ONE_ARG( 'a' ) ) ); + EXPECT_EQ( 1, int( GEOS_DETAIL_MORE_THAN_ONE_ARG( 'a', 'b' ) ) ); + EXPECT_EQ( 1, int( GEOS_DETAIL_MORE_THAN_ONE_ARG( 'a', 'b', 'c' ) ) ); + + EXPECT_EQ( 1, int( GEOS_DETAIL_MORE_THAN_ONE_ARG( 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', + 'w', 'x', 'y', 'z' ) ) ); + + // Expected out of bound (>16 params): wrongly cast the last '!' to integer type + EXPECT_EQ( 33, int( GEOS_DETAIL_MORE_THAN_ONE_ARG( 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', + 'w', 'x', 'y', 'z', '!' ) ) ); +} + + +TEST( testMacros, testFirstArgument ) +{ + EXPECT_EQ( 'a', GEOS_DETAIL_FIRST_ARG( 'a' ) ); + EXPECT_EQ( 'a', GEOS_DETAIL_FIRST_ARG( 'a', 'b' ) ); + EXPECT_EQ( 'a', GEOS_DETAIL_FIRST_ARG( 'a', 'b', 'c' ) ); + + EXPECT_EQ( 'a', GEOS_DETAIL_FIRST_ARG( 'a', 'b', 'c', 'd', + 'e', 'f', 'g', 'h', + 'i', 'j', 'k', 'l', + 'w', 'x', 'y', 'z' ) ); + + // Out of bound (>16 params): Cannot compile here, not testable. + // EXPECT_EXIT( GEOS_DETAIL_FIRST_ARG( 'a', 'b', 'c', 'd', + // 'e', 'f', 'g', 'h', + // 'i', 'j', 'k', 'l', + // 'w', 'x', 'y', 'z', '!' ) ); +} + +TEST( testMacros, testRestArguments ) +{ + // no param after the first -> double(void) called -> 0.0 value + EXPECT_EQ( 0.0, double( GEOS_DETAIL_REST_ARGS( 1.0 ) ) ); + + EXPECT_EQ( 2.0, double( GEOS_DETAIL_REST_ARGS( 1.0, 2.0 ) ) ); + + { + auto const generatedArray = std::array< double, 3 >{ GEOS_DETAIL_REST_ARGS( 1.0, 2.0, 3.0, 4.0 ) }; + auto const expectedArray = std::array< double, 3 >{ 2.0, 3.0, 4.0 }; + EXPECT_EQ( generatedArray, expectedArray ); + } + + { + auto const generatedArray = std::array< double, 16 >{ GEOS_DETAIL_REST_ARGS( 01.0, 02.0, 03.0, 04.0, 05.0, 06.0, 07.0, 08.0, + 09.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 ) }; + auto const expectedArray = std::array< double, 16 >{ 02.0, 03.0, 04.0, 05.0, 06.0, 07.0, 08.0, 09.0, + 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0 }; + EXPECT_EQ( generatedArray, expectedArray ); + } + + // { // Out of bound (>16 params): Cannot compile here, not testable. + // auto const generatedArray = std::array< double, 3 >{ GEOS_DETAIL_REST_ARGS( 01.0, 02.0, 03.0, 04.0, 05.0, 06.0, 07.0, 08.0, + // 09.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0 ) }; + // auto const expectedArray = std::array< double, 3 >{ 02.0, 03.0, 04.0, 05.0, 06.0, 07.0, 08.0, + // 09.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0 }; + // EXPECT_EQ( generatedArray, expectedArray ); + // } +} + +int main( int argc, char * * argv ) +{ + testing::InitGoogleTest( &argc, argv ); + return RUN_ALL_TESTS(); +} diff --git a/src/coreComponents/constitutive/ConstitutiveManager.cpp b/src/coreComponents/constitutive/ConstitutiveManager.cpp index fd7a0ac1b82..b1f22721eb7 100644 --- a/src/coreComponents/constitutive/ConstitutiveManager.cpp +++ b/src/coreComponents/constitutive/ConstitutiveManager.cpp @@ -78,7 +78,8 @@ ConstitutiveManager::hangConstitutiveRelation( string const & constitutiveRelati GEOS_FMT( "Error! The constitutive relation {} has already been registered on the subRegion {}. " "Make sure that the same constitutive model is not listed as a material on a" " region both as a stand-alone one and as part of a compound constitutive model.", - constitutiveRelationInstanceName, parent->getDataContext().toString() ) ); + constitutiveRelationInstanceName, parent->getDataContext().toString() ), + parent->getDataContext() ); ConstitutiveBase const & constitutiveRelation = getConstitutiveRelation( constitutiveRelationInstanceName ); diff --git a/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp b/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp index 97072a8c9a8..f5fefec27a8 100644 --- a/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp +++ b/src/coreComponents/constitutive/capillaryPressure/JFunctionCapillaryPressure.cpp @@ -126,7 +126,7 @@ void JFunctionCapillaryPressure::postInputInitialization() GEOS_THROW_IF( numPhases != 2 && numPhases != 3, GEOS_FMT( "{}: the expected number of fluid phases is either two, or three", getFullName() ), - InputError ); + InputError, getDataContext() ); if( numPhases == 2 ) { @@ -134,12 +134,12 @@ void JFunctionCapillaryPressure::postInputInitialization() GEOS_FMT( "{}: for a two-phase flow simulation, we must use {} to specify the J-function table for the pair (wetting phase, non-wetting phase)", getFullName(), viewKeyStruct::wettingNonWettingJFuncTableNameString() ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( m_wettingNonWettingSurfaceTension <= 0, GEOS_FMT( "{}: for a two-phase flow simulation, we must use {} to specify the surface tension for the pair (wetting phase, non-wetting phase)", getFullName(), viewKeyStruct::wettingNonWettingSurfaceTensionString() ), - InputError ); + InputError, getDataContext() ); } else if( numPhases == 3 ) { @@ -150,7 +150,7 @@ void JFunctionCapillaryPressure::postInputInitialization() getFullName(), viewKeyStruct::wettingIntermediateJFuncTableNameString(), viewKeyStruct::nonWettingIntermediateJFuncTableNameString() ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( m_wettingIntermediateSurfaceTension <= 0 || m_nonWettingIntermediateSurfaceTension <= 0, GEOS_FMT( "{}: for a three-phase flow simulation, we must use {} to specify the surface tension" "for the pair (wetting phase, intermediate phase), " @@ -158,7 +158,7 @@ void JFunctionCapillaryPressure::postInputInitialization() getFullName(), viewKeyStruct::wettingIntermediateSurfaceTensionString(), viewKeyStruct::nonWettingIntermediateSurfaceTensionString() ), - InputError ); + InputError, getDataContext() ); } } @@ -175,7 +175,7 @@ void JFunctionCapillaryPressure::initializePreSubGroups() GEOS_FMT( "{}: the table function named {} could not be found", getFullName(), m_wettingNonWettingJFuncTableName ), - InputError ); + InputError, getDataContext() ); TableFunction const & jFuncTable = functionManager.getGroup< TableFunction >( m_wettingNonWettingJFuncTableName ); bool const jFuncMustBeIncreasing = ( m_phaseOrder[PhaseType::WATER] < 0 ) ? true // pc on the gas phase, function must be increasing @@ -188,7 +188,7 @@ void JFunctionCapillaryPressure::initializePreSubGroups() GEOS_FMT( "{}: the table function named {} could not be found", getFullName(), m_wettingIntermediateJFuncTableName ), - InputError ); + InputError, getDataContext() ); TableFunction const & jFuncTableWI = functionManager.getGroup< TableFunction >( m_wettingIntermediateJFuncTableName ); TableCapillaryPressureHelpers::validateCapillaryPressureTable( jFuncTableWI, getFullName(), false ); @@ -196,7 +196,7 @@ void JFunctionCapillaryPressure::initializePreSubGroups() GEOS_FMT( "{}: the table function named {} could not be found", getFullName(), m_nonWettingIntermediateJFuncTableName ), - InputError ); + InputError, getDataContext() ); TableFunction const & jFuncTableNWI = functionManager.getGroup< TableFunction >( m_nonWettingIntermediateJFuncTableName ); TableCapillaryPressureHelpers::validateCapillaryPressureTable( jFuncTableNWI, getFullName(), true ); } diff --git a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.cpp b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.cpp index 2304238b540..4f8ab264e05 100644 --- a/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.cpp +++ b/src/coreComponents/constitutive/capillaryPressure/TableCapillaryPressure.cpp @@ -76,7 +76,7 @@ void TableCapillaryPressure::postInputInitialization() GEOS_THROW_IF( numPhases != 2 && numPhases != 3, GEOS_FMT( "{}: the expected number of fluid phases is either two, or three", getFullName() ), - InputError ); + InputError, getDataContext() ); if( numPhases == 2 ) { @@ -84,7 +84,7 @@ void TableCapillaryPressure::postInputInitialization() GEOS_FMT( "{}: for a two-phase flow simulation, we must use {} to specify the capillary pressure table for the pair (wetting phase, non-wetting phase)", getFullName(), viewKeyStruct::wettingNonWettingCapPresTableNameString() ), - InputError ); + InputError, getDataContext() ); } else if( numPhases == 3 ) { @@ -95,7 +95,7 @@ void TableCapillaryPressure::postInputInitialization() getFullName(), viewKeyStruct::wettingIntermediateCapPresTableNameString(), viewKeyStruct::nonWettingIntermediateCapPresTableNameString() ), - InputError ); + InputError, getDataContext() ); } } @@ -125,7 +125,7 @@ void TableCapillaryPressure::initializePreSubGroups() GEOS_FMT( "{}: the table function named {} could not be found", getFullName(), m_wettingIntermediateCapPresTableName ), - InputError ); + InputError, getDataContext() ); TableFunction const & capPresTableWI = functionManager.getGroup< TableFunction >( m_wettingIntermediateCapPresTableName ); TableCapillaryPressureHelpers::validateCapillaryPressureTable( capPresTableWI, getFullName(), false ); @@ -133,7 +133,7 @@ void TableCapillaryPressure::initializePreSubGroups() GEOS_FMT( "{}: the table function named {} could not be found", getFullName(), m_nonWettingIntermediateCapPresTableName ), - InputError ); + InputError, getDataContext() ); TableFunction const & capPresTableNWI = functionManager.getGroup< TableFunction >( m_nonWettingIntermediateCapPresTableName ); TableCapillaryPressureHelpers::validateCapillaryPressureTable( capPresTableNWI, getFullName(), true ); } diff --git a/src/coreComponents/constitutive/contact/CoulombFriction.cpp b/src/coreComponents/constitutive/contact/CoulombFriction.cpp index 15b1abc1464..021c923e4ca 100644 --- a/src/coreComponents/constitutive/contact/CoulombFriction.cpp +++ b/src/coreComponents/constitutive/contact/CoulombFriction.cpp @@ -53,7 +53,7 @@ void CoulombFriction::postInputInitialization() { GEOS_THROW_IF( m_frictionCoefficient < 0.0, getFullName() << ": The provided friction coefficient is less than zero. Value: " << m_frictionCoefficient, - InputError ); + InputError, getDataContext() ); } diff --git a/src/coreComponents/constitutive/contact/HydraulicApertureTable.cpp b/src/coreComponents/constitutive/contact/HydraulicApertureTable.cpp index a798bc242a9..26a3260374a 100644 --- a/src/coreComponents/constitutive/contact/HydraulicApertureTable.cpp +++ b/src/coreComponents/constitutive/contact/HydraulicApertureTable.cpp @@ -53,13 +53,14 @@ HydraulicApertureTable::HydraulicApertureTable( string const & name, void HydraulicApertureTable::postInputInitialization() { GEOS_THROW_IF( m_apertureTableName.empty(), - getFullName() << ": the aperture table name " << m_apertureTableName << " is empty", InputError ); + getFullName() << ": the aperture table name " << m_apertureTableName << " is empty", + InputError, getDataContext() ); FunctionManager & functionManager = FunctionManager::getInstance(); GEOS_THROW_IF( !functionManager.hasGroup( m_apertureTableName ), getFullName() << ": the aperture table named " << m_apertureTableName << " could not be found", - InputError ); + InputError, getDataContext() ); } void HydraulicApertureTable::allocateConstitutiveData( dataRepository::Group & parent, @@ -123,25 +124,25 @@ void HydraulicApertureTable::validateApertureTable( TableFunction const & apertu GEOS_THROW_IF( coords.size() > 1, getFullName() << ": Aperture limiter table cannot be greater than a 1D table.", - InputError ); + InputError, getDataContext() ); arraySlice1d< real64 const > apertureValues = coords[0]; localIndex const size = apertureValues.size(); GEOS_THROW_IF( coords( 0, size-1 ) > 0.0 || coords( 0, size-1 ) < 0.0, getFullName() << ": Invalid aperture limiter table. Last coordinate must be zero!", - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( apertureValues.size() < 2, getFullName() << ": Invalid aperture limiter table. Must have more than two points specified", - InputError ); + InputError, getDataContext() ); localIndex const n = apertureValues.size()-1; real64 const slope = ( hydraulicApertureValues[n] - hydraulicApertureValues[n-1] ) / ( apertureValues[n] - apertureValues[n-1] ); GEOS_THROW_IF( slope >= 1.0, getFullName() << ": Invalid aperture table. The slope of the last two points >= 1 is invalid.", - InputError ); + InputError, getDataContext() ); } diff --git a/src/coreComponents/constitutive/diffusion/ConstantDiffusion.cpp b/src/coreComponents/constitutive/diffusion/ConstantDiffusion.cpp index 21dbdb4ca0e..523a2f38bfb 100644 --- a/src/coreComponents/constitutive/diffusion/ConstantDiffusion.cpp +++ b/src/coreComponents/constitutive/diffusion/ConstantDiffusion.cpp @@ -57,14 +57,14 @@ void ConstantDiffusion::postInputInitialization() GEOS_THROW_IF( m_diffusivityComponents.size() != 3, GEOS_FMT( "{}: the size of the diffusivity must be equal to 3", getFullName() ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( m_diffusivityComponents[0] < 0 || m_diffusivityComponents[1] < 0 || m_diffusivityComponents[2] < 0, GEOS_FMT( "{}: the components of the diffusivity tensor must be non-negative", getFullName() ), - InputError ); + InputError, getDataContext() ); } REGISTER_CATALOG_ENTRY( ConstitutiveBase, ConstantDiffusion, string const &, Group * const ) diff --git a/src/coreComponents/constitutive/diffusion/DiffusionBase.cpp b/src/coreComponents/constitutive/diffusion/DiffusionBase.cpp index c4a9fbd48b7..995233e9b36 100644 --- a/src/coreComponents/constitutive/diffusion/DiffusionBase.cpp +++ b/src/coreComponents/constitutive/diffusion/DiffusionBase.cpp @@ -60,7 +60,7 @@ void DiffusionBase::postInputInitialization() GEOS_THROW_IF( numPhases != m_defaultPhaseDiffusivityMultiplier.size(), GEOS_FMT( "{}: the arrays in `{}` and `{}` must have the same size", getFullName(), viewKeyStruct::phaseNamesString(), viewKeyStruct::defaultPhaseDiffusivityMultiplierString() ), - InputError ); + InputError, getDataContext() ); } void DiffusionBase::allocateConstitutiveData( Group & parent, localIndex const numPts ) diff --git a/src/coreComponents/constitutive/dispersion/LinearIsotropicDispersion.cpp b/src/coreComponents/constitutive/dispersion/LinearIsotropicDispersion.cpp index c01a6945059..65f919d2b12 100644 --- a/src/coreComponents/constitutive/dispersion/LinearIsotropicDispersion.cpp +++ b/src/coreComponents/constitutive/dispersion/LinearIsotropicDispersion.cpp @@ -41,7 +41,7 @@ void LinearIsotropicDispersion::postInputInitialization() GEOS_THROW_IF( m_longitudinalDispersivity < 0, GEOS_FMT( "{}: longitudinal dispersivity must be positive", getFullName() ), - InputError ); + InputError, getDataContext() ); } void LinearIsotropicDispersion::initializeVelocityState( arrayView2d< real64 const > const & initialVelocity ) const diff --git a/src/coreComponents/constitutive/fluid/multifluid/CO2Brine/CO2BrineFluid.cpp b/src/coreComponents/constitutive/fluid/multifluid/CO2Brine/CO2BrineFluid.cpp index 6915df28649..58322520aff 100644 --- a/src/coreComponents/constitutive/fluid/multifluid/CO2Brine/CO2BrineFluid.cpp +++ b/src/coreComponents/constitutive/fluid/multifluid/CO2Brine/CO2BrineFluid.cpp @@ -172,6 +172,9 @@ 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() + .addToMsg( errorMsg ) + .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); throw SimulationError( ex, errorMsg ); } @@ -184,6 +187,9 @@ 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() + .addToMsg( errorMsg ) + .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); throw SimulationError( ex, errorMsg ); } @@ -194,6 +200,9 @@ 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() + .addToMsg( errorMsg ) + .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); throw SimulationError( ex, errorMsg ); } } @@ -233,7 +242,7 @@ void CO2BrineFluid< PHASE1, PHASE2, FLASH >::postInputInitialization() GEOS_FMT( "{}: One and only one of {} or {} should be specified", getFullName(), viewKeyStruct::flashModelParaFileString(), viewKeyStruct::solubilityTablesString() ), - InputError ); + InputError, getDataContext() ); // NOTE: for now, the names of the phases are still hardcoded here // Later, we could read them from the XML file and we would then have a general class here @@ -269,7 +278,7 @@ void CO2BrineFluid< PHASE1, PHASE2, FLASH >::createPVTModels() { GEOS_THROW_IF( strs.size() < 2, GEOS_FMT( "{}: missing PVT model in line '{}'", getFullName(), str ), - InputError ); + InputError, getDataContext() ); if( strs[0] == "DensityFun" ) { @@ -316,26 +325,26 @@ void CO2BrineFluid< PHASE1, PHASE2, FLASH >::createPVTModels() // at this point, we have read the file and we check the consistency of non-thermal models GEOS_THROW_IF( phase1InputParams[PHASE1::InputParamOrder::DENSITY].empty(), GEOS_FMT( "{}: PVT model {} not found in input files", getFullName(), PHASE1::Density::catalogName() ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( phase2InputParams[PHASE2::InputParamOrder::DENSITY].empty(), GEOS_FMT( "{}: PVT model {} not found in input files", getFullName(), PHASE2::Density::catalogName() ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( phase1InputParams[PHASE1::InputParamOrder::VISCOSITY].empty(), GEOS_FMT( "{}: PVT model {} not found in input files", getFullName(), PHASE1::Viscosity::catalogName() ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( phase2InputParams[PHASE2::InputParamOrder::VISCOSITY].empty(), GEOS_FMT( "{}: PVT model {} not found in input files", getFullName(), PHASE2::Viscosity::catalogName() ), - InputError ); + InputError, getDataContext() ); // we also detect any inconsistency arising in the enthalpy models GEOS_THROW_IF( phase1InputParams[PHASE1::InputParamOrder::ENTHALPY].empty() && ( PHASE1::Enthalpy::catalogName() != PVTProps::NoOpPVTFunction::catalogName() ), GEOS_FMT( "{}: PVT model {} not found in input files", getFullName(), PHASE1::Enthalpy::catalogName() ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( phase2InputParams[PHASE2::InputParamOrder::ENTHALPY].empty() && ( PHASE2::Enthalpy::catalogName() != PVTProps::NoOpPVTFunction::catalogName() ), GEOS_FMT( "{}: PVT model {} not found in input files", getFullName(), PHASE2::Enthalpy::catalogName() ), - InputError ); + InputError, getDataContext() ); // then, we are ready to instantiate the phase models bool const isClone = this->isClone(); @@ -369,7 +378,7 @@ void CO2BrineFluid< PHASE1, PHASE2, FLASH >::createPVTModels() { GEOS_THROW_IF( strs.size() < 2, GEOS_FMT( "{}: missing flash model in line '{}'", getFullName(), str ), - InputError ); + InputError, getDataContext() ); if( strs[0] == "FlashModel" ) { @@ -396,7 +405,7 @@ void CO2BrineFluid< PHASE1, PHASE2, FLASH >::createPVTModels() // The user must provide 1 or 2 tables. GEOS_THROW_IF( m_solubilityTables.size() != 1 && m_solubilityTables.size() != 2, GEOS_FMT( "{}: The number of table names in {} must be 1 or 2", getFullName(), viewKeyStruct::solubilityTablesString() ), - InputError ); + InputError, getDataContext() ); // If 1 table is provided, it is the CO2 solubility table and water vapourisation is zero // If 2 tables are provided, they are the CO2 solubility and water vapourisation tables depending @@ -427,7 +436,7 @@ void CO2BrineFluid< PHASE1, PHASE2, FLASH >::createPVTModels() GEOS_THROW_IF( m_flash == nullptr, GEOS_FMT( "{}: flash model {} not found in input files", getFullName(), FLASH::catalogName() ), - InputError ); + InputError, getDataContext() ); } template< typename PHASE1, typename PHASE2, typename FLASH > diff --git a/src/coreComponents/constitutive/fluid/multifluid/blackOil/BlackOilFluid.cpp b/src/coreComponents/constitutive/fluid/multifluid/blackOil/BlackOilFluid.cpp index fe5bd5645b2..d99026ededc 100644 --- a/src/coreComponents/constitutive/fluid/multifluid/blackOil/BlackOilFluid.cpp +++ b/src/coreComponents/constitutive/fluid/multifluid/blackOil/BlackOilFluid.cpp @@ -57,7 +57,7 @@ void BlackOilFluid::readInputDataFromPVTFiles() { GEOS_THROW_IF( m_formationVolFactorTableNames.size() > 0.0 || m_viscosityTableNames.size() > 0.0, GEOS_FMT( "{}: input is redundant (both TableFunction names and pvt files)", getFullName() ), - InputError ); + InputError, getDataContext() ); using PT = BlackOilFluid::PhaseType; @@ -441,7 +441,7 @@ void BlackOilFluid::checkTableConsistency() const // check for the presence of one bubble point GEOS_THROW_IF( m_PVTO.undersaturatedPressure[m_PVTO.numSaturatedPoints - 1].size() <= 1, GEOS_FMT( "{}: at least one bubble pressure is required in {}", getFullName(), m_tableFiles[m_phaseOrder[PT::OIL]] ), - InputError ); + InputError, getDataContext() ); // check for saturated region for( integer i = 0; i < m_PVTO.numSaturatedPoints - 1; ++i ) @@ -449,16 +449,16 @@ void BlackOilFluid::checkTableConsistency() const // Rs must increase with Pb GEOS_THROW_IF( ( m_PVTO.Rs[i + 1] - m_PVTO.Rs[i] ) <= 0, GEOS_FMT( "{}: Rs must increase with Pb in {}", getFullName(), m_tableFiles[m_phaseOrder[PT::OIL]] ), - InputError ); + InputError, getDataContext() ); // Bo must increase with Pb GEOS_THROW_IF( ( m_PVTO.saturatedBo[i + 1] - m_PVTO.saturatedBo[i] ) <= 0, GEOS_FMT( "{}: Bo must increase with Pb in saturated region in {}", getFullName(), m_tableFiles[m_phaseOrder[PT::OIL]] ), - InputError ); + InputError, getDataContext() ); // Viscosity must decrease with Pb GEOS_THROW_IF( ( m_PVTO.saturatedViscosity[i + 1] - m_PVTO.saturatedViscosity[i] ) >= 0, GEOS_FMT( "{}: Viscosity must decrease with Pb in saturated region in {}", getFullName(), m_tableFiles[m_phaseOrder[PT::OIL]] ), - InputError ); + InputError, getDataContext() ); } // check for under-saturated branches @@ -469,15 +469,15 @@ void BlackOilFluid::checkTableConsistency() const // Pressure GEOS_THROW_IF( ( m_PVTO.undersaturatedPressure[i][j + 1] - m_PVTO.undersaturatedPressure[i][j] ) <= 0, GEOS_FMT( "{}: P must decrease in undersaturated region in {}", getFullName(), m_tableFiles[m_phaseOrder[PT::OIL]] ), - InputError ); + InputError, getDataContext() ); // Bo must decrease with P GEOS_THROW_IF( ( m_PVTO.undersaturatedBo[i][j + 1] - m_PVTO.undersaturatedBo[i][j] ) >= 0, GEOS_FMT( "{}: Bo must decrease with P in undersaturated region in {}", getFullName(), m_tableFiles[m_phaseOrder[PT::OIL]] ), - InputError ); + InputError, getDataContext() ); // Viscosity must increase with Pb GEOS_THROW_IF( ( m_PVTO.undersaturatedViscosity[i][j + 1] - m_PVTO.undersaturatedViscosity[i][j] ) < -1e-10, GEOS_FMT( "{}: viscosity must increase with P in undersaturated region in {}", getFullName(), m_tableFiles[m_phaseOrder[PT::OIL]] ), - InputError ); + InputError, getDataContext() ); } } } diff --git a/src/coreComponents/constitutive/fluid/multifluid/blackOil/BlackOilFluidBase.cpp b/src/coreComponents/constitutive/fluid/multifluid/blackOil/BlackOilFluidBase.cpp index e86cc168ac7..ecf77b94f40 100644 --- a/src/coreComponents/constitutive/fluid/multifluid/blackOil/BlackOilFluidBase.cpp +++ b/src/coreComponents/constitutive/fluid/multifluid/blackOil/BlackOilFluidBase.cpp @@ -15,6 +15,7 @@ #include "BlackOilFluidBase.hpp" +#include "common/logger/ErrorHandling.hpp" #include "constitutive/fluid/multifluid/MultiFluidUtils.hpp" #include "constitutive/fluid/multifluid/CO2Brine/functions/PVTFunctionHelpers.hpp" #include "functions/FunctionManager.hpp" @@ -105,7 +106,7 @@ void BlackOilFluidBase::fillWaterData( array1d< array1d< real64 > > const & tabl GEOS_THROW_IF( m_waterParams.referencePressure > 0.0 || m_waterParams.formationVolFactor > 0.0 || m_waterParams.compressibility > 0.0 || m_waterParams.viscosity > 0.0, getFullName() << ": input is redundant (user provided both water data and a water pvt file)", - InputError ); + InputError, getDataContext() ); m_waterParams.referencePressure = tableValues[0][0]; m_waterParams.formationVolFactor = tableValues[0][1]; @@ -255,8 +256,12 @@ void BlackOilFluidBase::checkTablesParameters( real64 const pressure, m_formationVolFactorTables[iph]->checkCoord( pressure, 0 ); } catch( SimulationError const & ex ) { - throw SimulationError( ex, GEOS_FMT( errorMsg, getCatalogName(), getDataContext(), - "formation volume factor", iph ) ); + string const msg = GEOS_FMT( errorMsg, getCatalogName(), getDataContext(), + "formation volume factor", iph ); + ErrorLogger::global().currentErrorMsg() + .addToMsg( msg ) + .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); + throw SimulationError( ex, msg ); } try @@ -264,8 +269,12 @@ void BlackOilFluidBase::checkTablesParameters( real64 const pressure, m_viscosityTables[iph]->checkCoord( pressure, 0 ); } catch( SimulationError const & ex ) { - throw SimulationError( ex, GEOS_FMT( errorMsg, getCatalogName(), getDataContext(), - "viscosity", iph ) ); + string const msg = GEOS_FMT( errorMsg, getCatalogName(), getDataContext(), + "viscosity", iph ); + ErrorLogger::global().currentErrorMsg() + .addToMsg( msg ) + .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); + throw SimulationError( ex, msg ); } } } @@ -274,7 +283,7 @@ void BlackOilFluidBase::createAllKernelWrappers() { GEOS_THROW_IF( m_hydrocarbonPhaseOrder.size() != 1 && m_hydrocarbonPhaseOrder.size() != 2, GEOS_FMT( "{}: the number of hydrocarbon phases must be 1 (oil) or 2 (oil+gas)", getFullName() ), - InputError ); + InputError, getDataContext() ); if( m_formationVolFactorTableKernels.empty() && m_viscosityTableKernels.empty() ) { @@ -305,7 +314,7 @@ void BlackOilFluidBase::validateTable( TableFunction const & table, { GEOS_THROW_IF( (property[i] - property[i-1]) * (property[i-1] - property[i-2]) < 0, GEOS_FMT( "{}: in table '{}', viscosity values must be monotone", getFullName(), table.getName() ), - InputError ); + InputError, getDataContext() ); } // we don't check the first value, as it may be used to specify surface conditions diff --git a/src/coreComponents/constitutive/fluid/multifluid/blackOil/DeadOilFluid.cpp b/src/coreComponents/constitutive/fluid/multifluid/blackOil/DeadOilFluid.cpp index f3e481f24ab..eb2db5ee9b2 100644 --- a/src/coreComponents/constitutive/fluid/multifluid/blackOil/DeadOilFluid.cpp +++ b/src/coreComponents/constitutive/fluid/multifluid/blackOil/DeadOilFluid.cpp @@ -40,7 +40,7 @@ void DeadOilFluid::postInputInitialization() integer const numComps = numFluidComponents(); GEOS_THROW_IF( numComps != 2 && numComps != 3, GEOS_FMT( "{}: this model only supports 2 or 3 components", getFullName() ), - InputError ); + InputError, getDataContext() ); } void DeadOilFluid::readInputDataFromPVTFiles() @@ -50,7 +50,7 @@ void DeadOilFluid::readInputDataFromPVTFiles() InputError ); GEOS_THROW_IF( m_formationVolFactorTableNames.size() > 0.0 || m_viscosityTableNames.size() > 0.0, GEOS_FMT( "{}: input is redundant (both TableFunction names and pvt files)", getFullName() ), - InputError ); + InputError, getDataContext() ); array1d< array1d< real64 > > tableValues; for( integer ip = 0; ip < numFluidPhases(); ++ip ) @@ -73,7 +73,7 @@ void DeadOilFluid::readInputDataFromTableFunctions() { GEOS_THROW_IF( !m_tableFiles.empty(), GEOS_FMT( "{}: input is redundant (both TableFunction names and pvt files)", getFullName() ), - InputError ); + InputError, getDataContext() ); integer const ipWater = m_phaseOrder[PhaseType::WATER]; integer const ipGas = m_phaseOrder[PhaseType::GAS]; @@ -116,10 +116,10 @@ void DeadOilFluid::readInputDataFromTableFunctions() { GEOS_THROW_IF( !functionManager.hasGroup( m_formationVolFactorTableNames[iph] ), GEOS_FMT( "{}: formation volume factor table '{}' not found", getFullName(), m_formationVolFactorTableNames[iph] ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( !functionManager.hasGroup( m_viscosityTableNames[iph] ), GEOS_FMT( "{}: viscosity table '{}' not found", getFullName(), m_viscosityTableNames[iph] ), - InputError ); + InputError, getDataContext() ); } } diff --git a/src/coreComponents/constitutive/fluid/multifluid/compositional/parameters/PressureTemperatureCoordinates.cpp b/src/coreComponents/constitutive/fluid/multifluid/compositional/parameters/PressureTemperatureCoordinates.cpp index 00d1d47ec8b..feed413b275 100644 --- a/src/coreComponents/constitutive/fluid/multifluid/compositional/parameters/PressureTemperatureCoordinates.cpp +++ b/src/coreComponents/constitutive/fluid/multifluid/compositional/parameters/PressureTemperatureCoordinates.cpp @@ -73,7 +73,7 @@ void PressureTemperatureCoordinates::postInputInitializationImpl( MultiFluidBase GEOS_THROW_IF( !isStrictlyIncreasing( m_pressureCoordinates.toSliceConst()), GEOS_FMT( "{}: invalid values of pressure coordinates provided in {}. " "Values must be strictly increasing.", fluid->getFullName(), viewKeyStruct::pressureCoordinatesString() ), - InputError ); + InputError, fluid->getDataContext() ); } if( !m_temperatureCoordinates.empty()) @@ -88,7 +88,7 @@ void PressureTemperatureCoordinates::postInputInitializationImpl( MultiFluidBase GEOS_THROW_IF( !isStrictlyIncreasing( m_temperatureCoordinates.toSliceConst()), GEOS_FMT( "{}: invalid values of temperature coordinates provided in {}. " "Values must be strictly increasing.", fluid->getFullName(), viewKeyStruct::temperatureCoordinatesString() ), - InputError ); + InputError, fluid->getDataContext() ); } } diff --git a/src/coreComponents/constitutive/fluid/multifluid/reactive/ReactiveBrineFluid.cpp b/src/coreComponents/constitutive/fluid/multifluid/reactive/ReactiveBrineFluid.cpp index 65214e56ab5..b400a5124f1 100644 --- a/src/coreComponents/constitutive/fluid/multifluid/reactive/ReactiveBrineFluid.cpp +++ b/src/coreComponents/constitutive/fluid/multifluid/reactive/ReactiveBrineFluid.cpp @@ -159,7 +159,7 @@ void ReactiveBrineFluid< PHASE > ::createPVTModels() { GEOS_THROW_IF( strs.size() < 2, GEOS_FMT( "{}: missing PVT model in line '{}'", getFullName(), str ), - InputError ); + InputError, getDataContext() ); if( strs[0] == "DensityFun" ) { @@ -194,15 +194,15 @@ void ReactiveBrineFluid< PHASE > ::createPVTModels() // at this point, we have read the file and we check the consistency of non-thermal models GEOS_THROW_IF( phase1InputParams[PHASE::InputParamOrder::DENSITY].empty(), GEOS_FMT( "{}: PVT model {} not found in input files", getFullName(), PHASE::Density::catalogName() ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( phase1InputParams[PHASE::InputParamOrder::VISCOSITY].empty(), GEOS_FMT( "{}: PVT model {} not found in input files", getFullName(), PHASE::Viscosity::catalogName() ), - InputError ); + InputError, getDataContext() ); // we also detect any inconsistency arising in the enthalpy models GEOS_THROW_IF( phase1InputParams[PHASE::InputParamOrder::ENTHALPY].empty() && ( PHASE::Enthalpy::catalogName() != PVTProps::NoOpPVTFunction::catalogName() ), GEOS_FMT( "{}: PVT model {} not found in input files", getFullName(), PHASE::Enthalpy::catalogName() ), - InputError ); + InputError, getDataContext() ); bool const isClone = this->isClone(); TableFunction::OutputOptions const pvtOutputOpts = { @@ -234,6 +234,9 @@ 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() + .addToMsg( errorMsg ) + .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); throw SimulationError( ex, errorMsg ); } } diff --git a/src/coreComponents/constitutive/fluid/singlefluid/ParticleFluid.cpp b/src/coreComponents/constitutive/fluid/singlefluid/ParticleFluid.cpp index e6f32fa932d..3a252f50c07 100644 --- a/src/coreComponents/constitutive/fluid/singlefluid/ParticleFluid.cpp +++ b/src/coreComponents/constitutive/fluid/singlefluid/ParticleFluid.cpp @@ -84,27 +84,33 @@ void ParticleFluid::postInputInitialization() GEOS_ERROR_IF( m_proppantDensity < 500.0, "Invalid proppantDensity in ParticleFluid " - << getDataContext() << ", which must >= 500.0 " ); + << getDataContext() << ", which must >= 500.0 ", + getDataContext() ); GEOS_ERROR_IF( m_proppantDiameter < 10e-6, "Invalid proppantDiameter in ParticleFluid " - << getDataContext() << ", which must >= 10e-6 " ); + << getDataContext() << ", which must >= 10e-6 ", + getDataContext() ); GEOS_ERROR_IF( m_hinderedSettlingCoefficient< 0.0 || m_hinderedSettlingCoefficient > 10.0, "Invalid hinderedSettlingCoefficient in ParticleFluid " - << getDataContext() << ", which must between 0 and 10 " ); + << getDataContext() << ", which must between 0 and 10 ", + getDataContext() ); GEOS_ERROR_IF( m_collisionAlpha < 1.0, "Invalid collisionAlpha in ParticleFluid " - << getDataContext() << ", which must >= 1 " ); + << getDataContext() << ", which must >= 1 ", + getDataContext() ); GEOS_ERROR_IF( m_collisionBeta < 0.0, "Invalid collisionBeta in ParticleFluid " - << getDataContext() << ", which must >= 0" ); + << getDataContext() << ", which must >= 0", + getDataContext() ); GEOS_ERROR_IF( m_slipConcentration > 0.3, "Invalid slipConcentration in ParticleFluid " - << getDataContext() << ", which must <= 0.3" ); + << getDataContext() << ", which must <= 0.3", + getDataContext() ); m_packPermeabilityCoef = pow( m_sphericity * m_proppantDiameter, 2.0 ) / 180.0; } diff --git a/src/coreComponents/constitutive/fluid/singlefluid/ThermalCompressibleSinglePhaseFluid.cpp b/src/coreComponents/constitutive/fluid/singlefluid/ThermalCompressibleSinglePhaseFluid.cpp index 2e51f625ed5..203cac5b95f 100644 --- a/src/coreComponents/constitutive/fluid/singlefluid/ThermalCompressibleSinglePhaseFluid.cpp +++ b/src/coreComponents/constitutive/fluid/singlefluid/ThermalCompressibleSinglePhaseFluid.cpp @@ -89,7 +89,7 @@ void ThermalCompressibleSinglePhaseFluid::postInputInitialization() GEOS_THROW_IF( value != expectedValue, GEOS_FMT( "{}: invalid model type in attribute '{}' (only {} currently supported)", getFullName(), attribute, EnumStrings< ExponentApproximationType >::toString( expectedValue ) ), - InputError ); + InputError, getDataContext() ); }; checkModelType( m_internalEnergyModelType, ExponentApproximationType::Linear, viewKeyStruct::internalEnergyModelTypeString() ); } diff --git a/src/coreComponents/constitutive/permeability/PressurePermeability.cpp b/src/coreComponents/constitutive/permeability/PressurePermeability.cpp index aaa8c86073c..ecffd7ccab0 100644 --- a/src/coreComponents/constitutive/permeability/PressurePermeability.cpp +++ b/src/coreComponents/constitutive/permeability/PressurePermeability.cpp @@ -65,7 +65,8 @@ void PressurePermeability::postInputInitialization() for( localIndex i=0; i < 3; i++ ) { GEOS_ERROR_IF( std::abs( m_pressureDependenceConstants[i] ) < 1e-15 && m_presModelType == PressureModelType::Hyperbolic, - getDataContext() << ": the pressure dependent constant at component " << i << " is too close to zero, which is not allowed for the hyperbolic model." ); + getDataContext() << ": the pressure dependent constant at component " << i << " is too close to zero, which is not allowed for the hyperbolic model.", + getDataContext() ); } } diff --git a/src/coreComponents/constitutive/relativePermeability/BrooksCoreyBakerRelativePermeability.cpp b/src/coreComponents/constitutive/relativePermeability/BrooksCoreyBakerRelativePermeability.cpp index bb8ad661a74..5893bc00d61 100644 --- a/src/coreComponents/constitutive/relativePermeability/BrooksCoreyBakerRelativePermeability.cpp +++ b/src/coreComponents/constitutive/relativePermeability/BrooksCoreyBakerRelativePermeability.cpp @@ -72,7 +72,7 @@ void BrooksCoreyBakerRelativePermeability::postInputInitialization() GEOS_THROW_IF( m_phaseOrder[PhaseType::OIL] < 0, GEOS_FMT( "{}: reference oil phase has not been defined and must be included in model", getFullName() ), - InputError ); + InputError, getDataContext() ); auto const checkInputSize = [&]( auto const & array, localIndex const expected, auto const & attribute ) { diff --git a/src/coreComponents/constitutive/relativePermeability/BrooksCoreyStone2RelativePermeability.cpp b/src/coreComponents/constitutive/relativePermeability/BrooksCoreyStone2RelativePermeability.cpp index 8eb25929ddb..564b3df38f1 100644 --- a/src/coreComponents/constitutive/relativePermeability/BrooksCoreyStone2RelativePermeability.cpp +++ b/src/coreComponents/constitutive/relativePermeability/BrooksCoreyStone2RelativePermeability.cpp @@ -72,7 +72,7 @@ void BrooksCoreyStone2RelativePermeability::postInputInitialization() GEOS_THROW_IF( m_phaseOrder[PhaseType::OIL] < 0, GEOS_FMT( "{}: reference oil phase has not been defined and must be included in model", getFullName() ), - InputError ); + InputError, getDataContext() ); auto const checkInputSize = [&]( auto const & array, localIndex const expected, auto const & attribute ) { diff --git a/src/coreComponents/constitutive/relativePermeability/TableRelativePermeability.cpp b/src/coreComponents/constitutive/relativePermeability/TableRelativePermeability.cpp index 08720cb48b8..ae8a530ab31 100644 --- a/src/coreComponents/constitutive/relativePermeability/TableRelativePermeability.cpp +++ b/src/coreComponents/constitutive/relativePermeability/TableRelativePermeability.cpp @@ -93,7 +93,7 @@ void TableRelativePermeability::postInputInitialization() GEOS_THROW_IF( numPhases != 2 && numPhases != 3, GEOS_FMT( "{}: the expected number of fluid phases is either two, or three", getFullName() ), - InputError ); + InputError, getDataContext() ); if( numPhases == 2 ) { @@ -101,14 +101,14 @@ void TableRelativePermeability::postInputInitialization() GEOS_FMT( "{}: for a two-phase flow simulation, we must use {} to specify the relative permeability tables for the pair (wetting phase, non-wetting phase)", getFullName(), viewKeyStruct::wettingNonWettingRelPermTableNamesString() ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( m_wettingNonWettingRelPermTableNames.size() != 2, GEOS_FMT( "{}: for a two-phase flow simulation, we must use {} to specify exactly two names: first the name of the wetting phase relperm table, second the name on the non-wetting phase relperm table", getFullName(), viewKeyStruct::wettingNonWettingRelPermTableNamesString() ), - InputError ); + InputError, getDataContext() ); } else if( numPhases == 3 ) @@ -119,21 +119,21 @@ void TableRelativePermeability::postInputInitialization() getFullName(), viewKeyStruct::wettingIntermediateRelPermTableNamesString(), viewKeyStruct::nonWettingIntermediateRelPermTableNamesString() ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( m_wettingIntermediateRelPermTableNames.size() != 2, GEOS_FMT( "{}: for a three-phase flow simulation, we must use {} to specify exactly two names: first the name of the wetting phase relperm table, second the name on the intermediate phase relperm table", getFullName(), viewKeyStruct::wettingIntermediateRelPermTableNamesString() ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( m_nonWettingIntermediateRelPermTableNames.size() != 2, GEOS_FMT( "{}: for a three-phase flow simulation, we must use {} to specify exactly two names: first the name of the non-wetting phase relperm table, second the name on the intermediate phase relperm table", getFullName(), viewKeyStruct::nonWettingIntermediateRelPermTableNamesString() ), - InputError ); + InputError, getDataContext() ); } } @@ -164,7 +164,7 @@ void TableRelativePermeability::initializePreSubGroups() GEOS_FMT( "{}: the table function named {} could not be found", getFullName(), m_wettingNonWettingRelPermTableNames[ip] ), - InputError ); + InputError, getDataContext() ); TableFunction const & relPermTable = functionManager.getGroup< TableFunction >( m_wettingNonWettingRelPermTableNames[ip] ); TableRelativePermeabilityHelpers:: validateRelativePermeabilityTable( relPermTable, // input @@ -193,7 +193,7 @@ void TableRelativePermeability::initializePreSubGroups() GEOS_FMT( "{}: the table function named {} could not be found", getFullName(), m_wettingIntermediateRelPermTableNames[ip] ), - InputError ); + InputError, getDataContext() ); TableFunction const & relPermTable = functionManager.getGroup< TableFunction >( m_wettingIntermediateRelPermTableNames[ip] ); TableRelativePermeabilityHelpers:: validateRelativePermeabilityTable( relPermTable, // input @@ -221,7 +221,7 @@ void TableRelativePermeability::initializePreSubGroups() GEOS_FMT( "{}: the table function named {} could not be found", getFullName(), m_nonWettingIntermediateRelPermTableNames[ip] ), - InputError ); + InputError, getDataContext() ); TableFunction const & relPermTable = functionManager.getGroup< TableFunction >( m_nonWettingIntermediateRelPermTableNames[ip] ); TableRelativePermeabilityHelpers:: validateRelativePermeabilityTable( relPermTable, // input diff --git a/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHelpers.cpp b/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHelpers.cpp index 4fe2ac70da1..965c9278fc1 100644 --- a/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHelpers.cpp +++ b/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHelpers.cpp @@ -61,14 +61,14 @@ TableRelativePermeabilityHelpers::validateRelativePermeabilityTable( TableFuncti GEOS_THROW_IF( !isZero( relPerm[0] ), GEOS_FMT( "{}: TableFunction '{}' first value must be equal to 0", fullConstitutiveName, relPermTable.getDataContext() ), - InputError ); + InputError, relPermTable.getDataContext() ); for( localIndex i = 1; i < coords.sizeOfArray( 0 ); ++i ) { // check phase volume fraction GEOS_THROW_IF( phaseVolFrac[i] < 0 || phaseVolFrac[i] > 1, GEOS_FMT( "{}: TableFunction '{}' values must be between 0 and 1", fullConstitutiveName, relPermTable.getDataContext() ), - InputError ); + InputError, relPermTable.getDataContext() ); // note that the TableFunction class has already checked that the coordinates are monotone @@ -76,7 +76,7 @@ TableRelativePermeabilityHelpers::validateRelativePermeabilityTable( TableFuncti GEOS_THROW_IF( !isZero( relPerm[i] ) && (relPerm[i] - relPerm[i-1]) < 1e-15, GEOS_FMT( "{}: TableFunction '{}' values must be strictly increasing (|Delta kr| > 1e-15 between two non-zero values)", fullConstitutiveName, relPermTable.getDataContext() ), - InputError ); + InputError, relPermTable.getDataContext() ); if( isZero( relPerm[i-1] ) && !isZero( relPerm[i] ) ) { diff --git a/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHysteresis.cpp b/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHysteresis.cpp index 0da9b4af093..910c42cce41 100644 --- a/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHysteresis.cpp +++ b/src/coreComponents/constitutive/relativePermeability/TableRelativePermeabilityHysteresis.cpp @@ -163,7 +163,7 @@ void TableRelativePermeabilityHysteresis::postInputInitialization() GEOS_THROW_IF( numPhases != 2 && numPhases != 3, GEOS_FMT( "{}: the expected number of fluid phases is either two, or three", getFullName() ), - InputError ); + InputError, getDataContext() ); m_phaseMinVolumeFraction.resize( numPhases ); m_phaseHasHysteresis.resize( numPhases ); @@ -178,14 +178,14 @@ void TableRelativePermeabilityHysteresis::postInputInitialization() "for the pair (wetting phase, non-wetting phase)", getFullName(), viewKeyStruct::drainageWettingNonWettingRelPermTableNamesString() ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( m_drainageWettingNonWettingRelPermTableNames.size() != 2, GEOS_FMT( "{}: for a two-phase flow simulation, we must use {} to specify exactly two names: " "first the name of the wetting phase relperm table, second the name on the non-wetting phase relperm table", getFullName(), viewKeyStruct::drainageWettingNonWettingRelPermTableNamesString() ), - InputError ); + InputError, getDataContext() ); m_phaseHasHysteresis[IPT::WETTING] = ( m_imbibitionWettingRelPermTableName.empty() || m_imbibitionWettingRelPermTableName == m_drainageWettingNonWettingRelPermTableNames[0] ) @@ -203,21 +203,21 @@ void TableRelativePermeabilityHysteresis::postInputInitialization() getFullName(), viewKeyStruct::drainageWettingIntermediateRelPermTableNamesString(), viewKeyStruct::drainageNonWettingIntermediateRelPermTableNamesString() ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( m_drainageWettingIntermediateRelPermTableNames.size() != 2, GEOS_FMT( "{}: for a three-phase flow simulation, we must use {} to specify exactly two names: " "first the name of the wetting phase relperm table, second the name on the intermediate phase relperm table", getFullName(), viewKeyStruct::drainageWettingIntermediateRelPermTableNamesString() ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( m_drainageNonWettingIntermediateRelPermTableNames.size() != 2, GEOS_FMT( "{}: for a three-phase flow simulation, we must use {} to specify exactly two names: " "first the name of the non-wetting phase relperm table, second the name on the intermediate phase relperm table", getFullName(), viewKeyStruct::drainageNonWettingIntermediateRelPermTableNamesString() ), - InputError ); + InputError, getDataContext() ); m_phaseHasHysteresis[IPT::WETTING] = ( m_imbibitionWettingRelPermTableName.empty() || m_imbibitionWettingRelPermTableName == m_drainageWettingIntermediateRelPermTableNames[0] ) @@ -232,7 +232,7 @@ void TableRelativePermeabilityHysteresis::postInputInitialization() getFullName(), viewKeyStruct::imbibitionWettingRelPermTableNameString(), viewKeyStruct::imbibitionNonWettingRelPermTableNameString() ), - InputError ); + InputError, getDataContext() ); //Killough section KilloughHysteresis::postProcessInput( m_jerauldParam_a, m_jerauldParam_b, m_killoughCurvatureParamRelPerm ); @@ -299,7 +299,7 @@ void TableRelativePermeabilityHysteresis::checkExistenceAndValidateWettingRelPer "whereas the imbibition critical wetting-phase volume fraction is {}", getFullName(), drainagePhaseMinVolFraction, imbibitionPhaseMinVolFraction ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( imbibitionPhaseMaxVolFraction > drainagePhaseMaxVolFraction, GEOS_FMT( "{}: the maximum wetting-phase volume fraction (saturation) must be smaller in imbibition (compared to the drainage value).\n" @@ -307,7 +307,7 @@ void TableRelativePermeabilityHysteresis::checkExistenceAndValidateWettingRelPer "whereas the imbibition maximum wetting-phase volume fraction is {}", getFullName(), drainagePhaseMaxVolFraction, imbibitionPhaseMaxVolFraction ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( imbibitionPhaseRelPermMaxEndPoint > drainagePhaseRelPermMaxEndPoint, GEOS_FMT( "{}: the maximum wetting-phase relperm must be smaller in imbibition (compared to the drainage value).\n" @@ -315,7 +315,7 @@ void TableRelativePermeabilityHysteresis::checkExistenceAndValidateWettingRelPer "whereas the imbibition maximum wetting-phase relperm is {}", getFullName(), drainagePhaseRelPermMaxEndPoint, imbibitionPhaseRelPermMaxEndPoint ), - InputError ); + InputError, getDataContext() ); } m_wettingCurve.setPoints( drainagePhaseMinVolFraction, drainagePhaseRelPermMinEndPoint, // same as imbibition min @@ -375,7 +375,7 @@ void TableRelativePermeabilityHysteresis::checkExistenceAndValidateNonWettingRel + string( "whereas the imbibition maximum wetting-phase volume fraction is {}" ), getFullName(), drainagePhaseMaxVolFraction, imbibitionPhaseMaxVolFraction ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( !isZero ( imbibitionPhaseRelPermMaxEndPoint - drainagePhaseRelPermMaxEndPoint ), GEOS_FMT( string( "{}: the non-wetting-phase relperm endpoint must be the same in drainage and imbibition.\n" ) @@ -383,7 +383,7 @@ void TableRelativePermeabilityHysteresis::checkExistenceAndValidateNonWettingRel + string( "whereas the imbibition endpoint wetting-phase relperm is {}" ), getFullName(), drainagePhaseRelPermMaxEndPoint, imbibitionPhaseRelPermMaxEndPoint ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( imbibitionPhaseMinVolFraction < drainagePhaseMinVolFraction, GEOS_FMT( string( "{}: the critical wetting-phase volume fraction (saturation) must be larger in imbibition (compared to the drainage value).\n" ) @@ -391,8 +391,7 @@ void TableRelativePermeabilityHysteresis::checkExistenceAndValidateNonWettingRel + string( "whereas the imbibition critical wetting-phase volume fraction is {}" ), getFullName(), drainagePhaseMinVolFraction, imbibitionPhaseMinVolFraction ), - InputError ); - + InputError, getDataContext() ); } @@ -450,7 +449,7 @@ void TableRelativePermeabilityHysteresis::checkExistenceAndValidateRelPermTable( GEOS_FMT( "{}: the table function named {} could not be found", getFullName(), relPermTableName ), - InputError ); + InputError, getDataContext() ); TableFunction const & relPermTable = functionManager.getGroup< TableFunction >( relPermTableName ); // read the table, check monotonicity, and return the min/max saturation and the endpoint diff --git a/src/coreComponents/constitutive/relativePermeability/VanGenuchtenBakerRelativePermeability.cpp b/src/coreComponents/constitutive/relativePermeability/VanGenuchtenBakerRelativePermeability.cpp index 12823c81163..065e1b4ebc8 100644 --- a/src/coreComponents/constitutive/relativePermeability/VanGenuchtenBakerRelativePermeability.cpp +++ b/src/coreComponents/constitutive/relativePermeability/VanGenuchtenBakerRelativePermeability.cpp @@ -74,7 +74,7 @@ void VanGenuchtenBakerRelativePermeability::postInputInitialization() GEOS_THROW_IF( m_phaseOrder[PhaseType::OIL] < 0, GEOS_FMT( "{}: reference oil phase has not been defined and must be included in model", getFullName() ), - InputError ); + InputError, getDataContext() ); auto const checkInputSize = [&]( auto const & array, localIndex const expected, auto const & attribute ) { diff --git a/src/coreComponents/constitutive/relativePermeability/VanGenuchtenStone2RelativePermeability.cpp b/src/coreComponents/constitutive/relativePermeability/VanGenuchtenStone2RelativePermeability.cpp index dbb0ee05f0e..f4e6a083775 100644 --- a/src/coreComponents/constitutive/relativePermeability/VanGenuchtenStone2RelativePermeability.cpp +++ b/src/coreComponents/constitutive/relativePermeability/VanGenuchtenStone2RelativePermeability.cpp @@ -74,7 +74,7 @@ void VanGenuchtenStone2RelativePermeability::postInputInitialization() GEOS_THROW_IF( m_phaseOrder[PhaseType::OIL] < 0, GEOS_FMT( "{}: reference oil phase has not been defined and must be included in model", getFullName() ), - InputError ); + InputError, getDataContext() ); auto const checkInputSize = [&]( auto const & array, localIndex const expected, auto const & attribute ) { diff --git a/src/coreComponents/constitutive/solid/Damage.cpp b/src/coreComponents/constitutive/solid/Damage.cpp index 4c0c6363c75..5272581c2ea 100644 --- a/src/coreComponents/constitutive/solid/Damage.cpp +++ b/src/coreComponents/constitutive/solid/Damage.cpp @@ -100,17 +100,21 @@ void Damage< BASE >::postInputInitialization() BASE::postInputInitialization(); GEOS_ERROR_IF( m_extDrivingForceFlag != 0 && m_extDrivingForceFlag!= 1, - BASE::getDataContext() << ": invalid external driving force flag option - must" - " be 0 or 1" ); + this->getDataContext() << ": invalid external driving force flag option - must" + " be 0 or 1", + this->getDataContext() ); GEOS_ERROR_IF( m_extDrivingForceFlag == 1 && m_defaultTensileStrength <= 0.0, - BASE::getDataContext() << ": tensile strength must be input and positive when the" - " external driving force flag is turned on" ); + this->getDataContext() << ": tensile strength must be input and positive when the" + " external driving force flag is turned on", + this->getDataContext() ); GEOS_ERROR_IF( m_extDrivingForceFlag == 1 && m_defaultCompressiveStrength <= 0.0, - BASE::getDataContext() << ": compressive strength must be input and positive when the" - " external driving force flag is turned on" ); + this->getDataContext() << ": compressive strength must be input and positive when the" + " external driving force flag is turned on", + this->getDataContext() ); GEOS_ERROR_IF( m_extDrivingForceFlag == 1 && m_defaultDeltaCoefficient < 0.0, - BASE::getDataContext() << ": delta coefficient must be input and non-negative when the" - " external driving force flag is turned on" ); + this->getDataContext() << ": delta coefficient must be input and non-negative when the" + " external driving force flag is turned on", + this->getDataContext() ); // set results as array default values this->template getField< fields::solid::criticalFractureEnergy >(). diff --git a/src/coreComponents/constitutive/solid/DelftEgg.cpp b/src/coreComponents/constitutive/solid/DelftEgg.cpp index 50c55ca8e16..a73adc31171 100644 --- a/src/coreComponents/constitutive/solid/DelftEgg.cpp +++ b/src/coreComponents/constitutive/solid/DelftEgg.cpp @@ -86,13 +86,17 @@ void DelftEgg::postInputInitialization() ElasticIsotropic::postInputInitialization(); GEOS_THROW_IF( m_defaultCslSlope <= 0, - getFullName() << ": Non-positive slope of critical state line detected", InputError ); + getFullName() << ": Non-positive slope of critical state line detected", + InputError, getDataContext() ); GEOS_THROW_IF( m_defaultShapeParameter < 1., - getFullName() << ": Shape parameter for yield surface must be greater than or equal to one", InputError ); + getFullName() << ": Shape parameter for yield surface must be greater than or equal to one", + InputError, getDataContext() ); GEOS_THROW_IF( m_defaultVirginCompressionIndex <= 0, - getFullName() << ": Non-positive virgin compression index detected", InputError ); + getFullName() << ": Non-positive virgin compression index detected", + InputError, getDataContext() ); GEOS_THROW_IF( m_defaultVirginCompressionIndex <= m_defaultRecompressionIndex, - getFullName() << ": Recompression index should exceed virgin recompression index", InputError ); + getFullName() << ": Recompression index should exceed virgin recompression index", + InputError, getDataContext() ); // set results as array default values diff --git a/src/coreComponents/constitutive/solid/DruckerPrager.cpp b/src/coreComponents/constitutive/solid/DruckerPrager.cpp index 6b06754b97e..b142889a24d 100644 --- a/src/coreComponents/constitutive/solid/DruckerPrager.cpp +++ b/src/coreComponents/constitutive/solid/DruckerPrager.cpp @@ -79,13 +79,17 @@ void DruckerPrager::postInputInitialization() ElasticIsotropic::postInputInitialization(); GEOS_THROW_IF( m_defaultCohesion < 0, - getFullName() << ": Negative cohesion value detected", InputError ); + getFullName() << ": Negative cohesion value detected", + InputError, getDataContext() ); GEOS_THROW_IF( m_defaultFrictionAngle < 0, - getFullName() << ": Negative friction angle detected", InputError ); + getFullName() << ": Negative friction angle detected", + InputError, getDataContext() ); GEOS_THROW_IF( m_defaultDilationAngle < 0, - getFullName() << ": Negative dilation angle detected", InputError ); + getFullName() << ": Negative dilation angle detected", + InputError, getDataContext() ); GEOS_THROW_IF( m_defaultFrictionAngle < m_defaultDilationAngle, - getFullName() << ": Dilation angle should not exceed friction angle", InputError ); + getFullName() << ": Dilation angle should not exceed friction angle", + InputError, getDataContext() ); // convert from Mohr-Coulomb constants to Drucker-Prager constants, assuming DP // passes through the triaxial compression corners of the MC surface. diff --git a/src/coreComponents/constitutive/solid/DruckerPragerExtended.cpp b/src/coreComponents/constitutive/solid/DruckerPragerExtended.cpp index 42f8671bded..6a07c27e1bc 100644 --- a/src/coreComponents/constitutive/solid/DruckerPragerExtended.cpp +++ b/src/coreComponents/constitutive/solid/DruckerPragerExtended.cpp @@ -88,17 +88,23 @@ void DruckerPragerExtended::postInputInitialization() ElasticIsotropic::postInputInitialization(); GEOS_THROW_IF( m_defaultCohesion < 0, - getFullName() << ": Negative cohesion value detected", InputError ); + getFullName() << ": Negative cohesion value detected", + InputError, getDataContext() ); GEOS_THROW_IF( m_defaultInitialFrictionAngle < 0, - getFullName() << ": Negative initial friction angle detected", InputError ); + getFullName() << ": Negative initial friction angle detected", + InputError, getDataContext() ); GEOS_THROW_IF( m_defaultResidualFrictionAngle < 0, - getFullName() << ": Negative residual friction angle detected", InputError ); + getFullName() << ": Negative residual friction angle detected", + InputError, getDataContext() ); GEOS_THROW_IF( m_defaultDilationRatio < 0, - getFullName() << ": Dilation ratio out of [0,1] range detected", InputError ); + getFullName() << ": Dilation ratio out of [0,1] range detected", + InputError, getDataContext() ); GEOS_THROW_IF( m_defaultDilationRatio > 1, - getFullName() << ": Dilation ratio out of [0,1] range detected", InputError ); + getFullName() << ": Dilation ratio out of [0,1] range detected", + InputError, getDataContext() ); GEOS_THROW_IF( m_defaultHardening < 0, - getFullName() << ": Negative hardening parameter detected", InputError ); + getFullName() << ": Negative hardening parameter detected", + InputError, getDataContext() ); // convert from Mohr-Coulomb constants to Drucker-Prager constants, assuming DP // passes through the triaxial tension corners of the MC surface. diff --git a/src/coreComponents/constitutive/solid/ElasticIsotropicPressureDependent.cpp b/src/coreComponents/constitutive/solid/ElasticIsotropicPressureDependent.cpp index 75357acc1a6..2872b738a75 100644 --- a/src/coreComponents/constitutive/solid/ElasticIsotropicPressureDependent.cpp +++ b/src/coreComponents/constitutive/solid/ElasticIsotropicPressureDependent.cpp @@ -97,12 +97,12 @@ void ElasticIsotropicPressureDependent::postInputInitialization() InputError ); GEOS_THROW_IF( m_defaultRecompressionIndex <= 0, GEOS_FMT( "{}: Non-positive recompression index detected {}", getFullName(), m_defaultRecompressionIndex ), - InputError ); + InputError, getDataContext() ); real64 poisson = conversions::bulkModAndShearMod::toPoissonRatio( -1 * m_defaultRefPressure / m_defaultRecompressionIndex, m_defaultShearModulus ); GEOS_THROW_IF( poisson < 0, GEOS_FMT( "{}: Elastic parameters lead to negative Poisson ratio at reference pressure", getFullName() ), - InputError ); + InputError, getDataContext() ); // set results as array default values diff --git a/src/coreComponents/constitutive/solid/ModifiedCamClay.cpp b/src/coreComponents/constitutive/solid/ModifiedCamClay.cpp index a5062f15904..c00a1a90f2c 100644 --- a/src/coreComponents/constitutive/solid/ModifiedCamClay.cpp +++ b/src/coreComponents/constitutive/solid/ModifiedCamClay.cpp @@ -72,16 +72,16 @@ void ModifiedCamClay::postInputInitialization() GEOS_THROW_IF( m_defaultCslSlope <= 0, GEOS_FMT( "{}: Non-positive slope of critical state line detected", getFullName() ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( m_defaultVirginCompressionIndex <= 0, GEOS_FMT( "{}: Non-positive virgin compression index detected", getFullName() ), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( m_defaultVirginCompressionIndex <= m_defaultRecompressionIndex, GEOS_FMT( "{}: Recompression index should exceed virgin recompression index", getFullName() ), InputError ); GEOS_THROW_IF( m_defaultPreConsolidationPressure >= 0, GEOS_FMT( "{}: Preconsolidation pressure must be negative", getFullName() ), - InputError ); + InputError, getDataContext() ); // set results as array default values diff --git a/src/coreComponents/constitutive/thermalConductivity/MultiPhaseConstantThermalConductivity.cpp b/src/coreComponents/constitutive/thermalConductivity/MultiPhaseConstantThermalConductivity.cpp index 2573679cc20..5e09a8762cb 100644 --- a/src/coreComponents/constitutive/thermalConductivity/MultiPhaseConstantThermalConductivity.cpp +++ b/src/coreComponents/constitutive/thermalConductivity/MultiPhaseConstantThermalConductivity.cpp @@ -59,7 +59,7 @@ void MultiPhaseConstantThermalConductivity::postInputInitialization() m_thermalConductivityComponents[2] < 0, GEOS_FMT( "{}: the components of the thermal conductivity tensor must be non-negative", getFullName() ), - InputError ); + InputError, getDataContext() ); } REGISTER_CATALOG_ENTRY( ConstitutiveBase, MultiPhaseConstantThermalConductivity, string const &, Group * const ) diff --git a/src/coreComponents/constitutive/thermalConductivity/MultiPhaseVolumeWeightedThermalConductivity.cpp b/src/coreComponents/constitutive/thermalConductivity/MultiPhaseVolumeWeightedThermalConductivity.cpp index efb1341d848..c7e309ceb4b 100644 --- a/src/coreComponents/constitutive/thermalConductivity/MultiPhaseVolumeWeightedThermalConductivity.cpp +++ b/src/coreComponents/constitutive/thermalConductivity/MultiPhaseVolumeWeightedThermalConductivity.cpp @@ -69,14 +69,14 @@ void MultiPhaseVolumeWeightedThermalConductivity::postInputInitialization() m_rockThermalConductivityComponents[2] <= 0, GEOS_FMT( "{}: the components of the rock thermal conductivity tensor must be strictly positive", getFullName() ), - InputError ); + InputError, getDataContext() ); for( integer ip = 0; ip < numFluidPhases(); ++ip ) { GEOS_THROW_IF( m_phaseThermalConductivity[ip] <= 0, GEOS_FMT( "{}: the phase thermal conductivity for phase {} must be strictly positive", getFullName(), ip ), - InputError ); + InputError, getDataContext() ); } } diff --git a/src/coreComponents/constitutive/thermalConductivity/SinglePhaseThermalConductivity.cpp b/src/coreComponents/constitutive/thermalConductivity/SinglePhaseThermalConductivity.cpp index fb5e2a410a2..00d77439387 100644 --- a/src/coreComponents/constitutive/thermalConductivity/SinglePhaseThermalConductivity.cpp +++ b/src/coreComponents/constitutive/thermalConductivity/SinglePhaseThermalConductivity.cpp @@ -110,7 +110,7 @@ void SinglePhaseThermalConductivity::postInputInitialization() m_defaultThermalConductivityComponents[2] <= 0, GEOS_FMT( "{}: the components of the default thermal conductivity tensor must be strictly positive", getFullName() ), - InputError ); + InputError, getDataContext() ); } diff --git a/src/coreComponents/constitutiveDrivers/fluid/multiFluid/PVTDriver.cpp b/src/coreComponents/constitutiveDrivers/fluid/multiFluid/PVTDriver.cpp index 49263cd1e07..db232e5c37d 100644 --- a/src/coreComponents/constitutiveDrivers/fluid/multiFluid/PVTDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/fluid/multiFluid/PVTDriver.cpp @@ -104,25 +104,30 @@ void PVTDriver::postInputInitialization() // Validate some inputs GEOS_ERROR_IF( m_outputMassDensity != 0 && m_outputMassDensity != 1, getWrapperDataContext( viewKeyStruct::outputMassDensityString() ) << - ": option can be either 0 (false) or 1 (true)" ); + ": option can be either 0 (false) or 1 (true)", + getWrapperDataContext( viewKeyStruct::outputMassDensityString() ) ); GEOS_ERROR_IF( m_outputCompressibility != 0 && m_outputCompressibility != 1, getWrapperDataContext( viewKeyStruct::outputCompressibilityString() ) << - ": option can be either 0 (false) or 1 (true)" ); + ": option can be either 0 (false) or 1 (true)", + getWrapperDataContext( viewKeyStruct::outputCompressibilityString() ) ); GEOS_ERROR_IF( m_outputPhaseComposition != 0 && m_outputPhaseComposition != 1, getWrapperDataContext( viewKeyStruct::outputPhaseCompositionString() ) << - ": option can be either 0 (false) or 1 (true)" ); + ": option can be either 0 (false) or 1 (true)", + getWrapperDataContext( viewKeyStruct::outputPhaseCompositionString() ) ); GEOS_WARNING_IF( m_precision < minPrecision, GEOS_FMT( "{}: option should be between {} and {}. A value of {} will be used.", getWrapperDataContext( viewKeyStruct::precisionString() ), - minPrecision, maxPrecision, minPrecision )); + minPrecision, maxPrecision, minPrecision ), + getWrapperDataContext( viewKeyStruct::precisionString() )); GEOS_WARNING_IF( maxPrecision < m_precision, GEOS_FMT( "{}: option should be between {} and {}. A value of {} will be used.", getWrapperDataContext( viewKeyStruct::precisionString() ), - minPrecision, maxPrecision, maxPrecision ) ); + minPrecision, maxPrecision, maxPrecision ), + getWrapperDataContext( viewKeyStruct::precisionString() ) ); // get number of phases and components diff --git a/src/coreComponents/constitutiveDrivers/solid/TriaxialDriver.cpp b/src/coreComponents/constitutiveDrivers/solid/TriaxialDriver.cpp index bfeb17f6217..73bea40106f 100644 --- a/src/coreComponents/constitutiveDrivers/solid/TriaxialDriver.cpp +++ b/src/coreComponents/constitutiveDrivers/solid/TriaxialDriver.cpp @@ -152,11 +152,11 @@ void TriaxialDriver::postInputInitialization() GEOS_THROW_IF( !isEqual( m_initialStress, m_table( 0, SIG0 ), 1e-6 ), getDataContext() << ": Initial stress values indicated by initialStress and axialFunction(time=0) appear inconsistent", - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( !isEqual( m_initialStress, m_table( 0, SIG1 ), 1e-6 ), getDataContext() << ": Initial stress values indicated by initialStress and radialFunction(time=0) appear inconsistent", - InputError ); + InputError, getDataContext() ); } diff --git a/src/coreComponents/dataRepository/DataContext.cpp b/src/coreComponents/dataRepository/DataContext.cpp index d34ab4b72c1..8e01140759f 100644 --- a/src/coreComponents/dataRepository/DataContext.cpp +++ b/src/coreComponents/dataRepository/DataContext.cpp @@ -108,10 +108,17 @@ string DataFileContext::toString() const } } +ErrorLogger::ErrorContext DataFileContext::getContextInfo() const +{ + ErrorLogger::ErrorContext ctxInfo{ + { { ErrorLogger::ErrorContext::Attribute::InputFile, m_filePath }, + { ErrorLogger::ErrorContext::Attribute::InputLine, std::to_string( m_line )} } // m_attributes + }; + return ctxInfo; +} + DataContext::ToStringInfo DataFileContext::getToStringInfo() const { return ToStringInfo( m_targetName, m_filePath, m_line ); } - - } /* namespace dataRepository */ } /* namespace geos */ diff --git a/src/coreComponents/dataRepository/DataContext.hpp b/src/coreComponents/dataRepository/DataContext.hpp index ee3abd0f1c1..63b855e24f2 100644 --- a/src/coreComponents/dataRepository/DataContext.hpp +++ b/src/coreComponents/dataRepository/DataContext.hpp @@ -24,6 +24,7 @@ #include "common/logger/Logger.hpp" #include "xmlWrapper.hpp" #include "common/format/Format.hpp" +#include "common/logger/ErrorHandling.hpp" namespace geos { @@ -60,6 +61,20 @@ class DataContext */ virtual string toString() const = 0; + /** + * @brief Returns contextual information, including the file name and the line number + * @return ErrorLogger::ErrorContext + */ + virtual ErrorLogger::ErrorContext getContextInfo() const = 0; + + /** + * @brief Conversion operator to ErrorLogger::ErrorContext + * @return ErrorLogger::ErrorContext + */ + explicit operator ErrorLogger::ErrorContext() const { + return getContextInfo(); + } + /** * @return Get the target object name */ @@ -155,6 +170,12 @@ class DataFileContext final : public DataContext */ string toString() const override; + /** + * @brief Return contextual information (file and line of the input file where the error occured) + * @return ErrorLogger::ErrorContext ErrorLogger instance updated with context information + */ + ErrorLogger::ErrorContext getContextInfo() const override; + /** * @return the type name in the source file (XML node tag name / attribute name). */ diff --git a/src/coreComponents/dataRepository/Group.cpp b/src/coreComponents/dataRepository/Group.cpp index 94a78c3e512..409fff42c61 100644 --- a/src/coreComponents/dataRepository/Group.cpp +++ b/src/coreComponents/dataRepository/Group.cpp @@ -77,7 +77,8 @@ WrapperBase & Group::registerWrapper( std::unique_ptr< WrapperBase > wrapper ) void Group::deregisterWrapper( string const & name ) { GEOS_ERROR_IF( !hasWrapper( name ), - "Wrapper " << name << " doesn't exist in Group" << getDataContext() << '.' ); + "Wrapper " << name << " doesn't exist in Group" << getDataContext() << '.', + getDataContext() ); m_wrappers.erase( name ); m_conduitNode.remove( name ); } @@ -251,7 +252,7 @@ void Group::processInputFile( xmlWrapper::xmlNode const & targetNode, "http://geosx-geosx.readthedocs-hosted.com/en/latest/docs/sphinx/userGuide/Index.html", getDataContext(), targetNode.path(), attributeName, dumpInputOptions() ), - InputError ); + InputError, getDataContext() ); } } } diff --git a/src/coreComponents/dataRepository/Group.hpp b/src/coreComponents/dataRepository/Group.hpp index 0aef2b787b8..bf185a656ef 100644 --- a/src/coreComponents/dataRepository/Group.hpp +++ b/src/coreComponents/dataRepository/Group.hpp @@ -321,12 +321,12 @@ class Group GEOS_THROW_IF( child == nullptr, "Group " << getDataContext() << " has no child named " << key << std::endl << dumpSubGroupsNames(), - std::domain_error ); + std::domain_error, getDataContext() ); T * const castedChild = dynamicCast< T * >( child ); GEOS_THROW_IF( castedChild == nullptr, GEOS_FMT( "{} was expected to be a '{}'.", child->getDataContext(), LvArray::system::demangleType< T >() ), - BadTypeError ); + BadTypeError, child->getDataContext() ); return *castedChild; } @@ -340,12 +340,12 @@ class Group GEOS_THROW_IF( child == nullptr, "Group " << getDataContext() << " has no child named " << key << std::endl << dumpSubGroupsNames(), - std::domain_error ); + std::domain_error, getDataContext() ); T const * const castedChild = dynamicCast< T const * >( child ); GEOS_THROW_IF( castedChild == nullptr, GEOS_FMT( "{} was expected to be a '{}'.", child->getDataContext(), LvArray::system::demangleType< T >() ), - BadTypeError ); + BadTypeError, child->getDataContext() ); return *castedChild; } @@ -1126,7 +1126,7 @@ class Group GEOS_THROW_IF( wrapper == nullptr, "Group " << getDataContext() << " has no wrapper named " << key << std::endl << dumpWrappersNames(), - std::domain_error ); + std::domain_error, 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 ); + std::domain_error, getDataContext() ); return *wrapper; } @@ -1363,7 +1363,9 @@ class Group */ Group & getParent() { - GEOS_THROW_IF( m_parent == nullptr, "Group at " << getDataContext() << " does not have a parent.", std::domain_error ); + GEOS_THROW_IF( m_parent == nullptr, + "Group at " << getDataContext() << " does not have a parent.", + std::domain_error, getDataContext() ); return *m_parent; } @@ -1372,7 +1374,9 @@ class Group */ Group const & getParent() const { - GEOS_THROW_IF( m_parent == nullptr, "Group at " << getDataContext() << " does not have a parent.", std::domain_error ); + GEOS_THROW_IF( m_parent == nullptr, + "Group at " << getDataContext() << " does not have a parent.", + std::domain_error, getDataContext() ); return *m_parent; } diff --git a/src/coreComponents/dataRepository/GroupContext.cpp b/src/coreComponents/dataRepository/GroupContext.cpp index ef07c03e6d1..f5085f51663 100644 --- a/src/coreComponents/dataRepository/GroupContext.cpp +++ b/src/coreComponents/dataRepository/GroupContext.cpp @@ -54,6 +54,14 @@ string GroupContext::toString() const return path.str(); } +ErrorLogger::ErrorContext GroupContext::getContextInfo() const +{ + ErrorLogger::ErrorContext ctxInfo{ + { { ErrorLogger::ErrorContext::Attribute::DataPath, toString() } } // m_attributes + }; + return ctxInfo; +} + DataContext::ToStringInfo GroupContext::getToStringInfo() const { return ToStringInfo( m_targetName ); } diff --git a/src/coreComponents/dataRepository/GroupContext.hpp b/src/coreComponents/dataRepository/GroupContext.hpp index 166543b883f..182245baa10 100644 --- a/src/coreComponents/dataRepository/GroupContext.hpp +++ b/src/coreComponents/dataRepository/GroupContext.hpp @@ -68,6 +68,13 @@ class GroupContext : public DataContext * @return the group path with the file & line of the first parent for which this information exists. */ string toString() const override; + + /** + * @brief Return contextual information here it is a data path + * @return ErrorLogger::ErrorContext ErrorLogger instance updated with context information + */ + ErrorLogger::ErrorContext getContextInfo() const override; + /** * @copydoc DataContext::getToStringInfo() */ diff --git a/src/coreComponents/dataRepository/WrapperContext.cpp b/src/coreComponents/dataRepository/WrapperContext.cpp index 92f52ba8708..50a37277e32 100644 --- a/src/coreComponents/dataRepository/WrapperContext.cpp +++ b/src/coreComponents/dataRepository/WrapperContext.cpp @@ -38,6 +38,13 @@ string WrapperContext::toString() const GEOS_FMT( "{}/{}", m_group.getDataContext().toString(), m_typeName ); } +ErrorLogger::ErrorContext WrapperContext::getContextInfo() const +{ + ErrorLogger::ErrorContext ctxInfo{ + { { ErrorLogger::ErrorContext::Attribute::DataPath, toString() } } // m_attributes + }; + return ctxInfo; +} } /* namespace dataRepository */ } /* namespace geos */ diff --git a/src/coreComponents/dataRepository/WrapperContext.hpp b/src/coreComponents/dataRepository/WrapperContext.hpp index 78fd48fb6f1..40f36b135a3 100644 --- a/src/coreComponents/dataRepository/WrapperContext.hpp +++ b/src/coreComponents/dataRepository/WrapperContext.hpp @@ -54,6 +54,11 @@ class WrapperContext final : public GroupContext */ string toString() const override; + /** + * @brief Return contextual information here it is a data path + * @return ErrorLogger::ErrorContext ErrorLogger instance updated with context information + */ + ErrorLogger::ErrorContext getContextInfo() const override; }; diff --git a/src/coreComponents/dataRepository/unitTests/CMakeLists.txt b/src/coreComponents/dataRepository/unitTests/CMakeLists.txt index 578071e570d..9e7c32e37e6 100644 --- a/src/coreComponents/dataRepository/unitTests/CMakeLists.txt +++ b/src/coreComponents/dataRepository/unitTests/CMakeLists.txt @@ -1,13 +1,14 @@ # Specify list of tests set( dataRepository_tests + testBufferOps.cpp testDefaultValue.cpp testDocumentationGeneration.cpp + testErrorHandling.cpp + testObjectCatalog.cpp testPacking.cpp + testWrapperHelpers.cpp testWrapper.cpp - testXmlWrapper.cpp - testBufferOps.cpp - testObjectCatalog.cpp - testWrapperHelpers.cpp ) + testXmlWrapper.cpp ) set( dependencyList mainInterface gtest ${parallelDeps} ) diff --git a/src/coreComponents/dataRepository/unitTests/testErrorHandling.cpp b/src/coreComponents/dataRepository/unitTests/testErrorHandling.cpp new file mode 100644 index 00000000000..39103cc5580 --- /dev/null +++ b/src/coreComponents/dataRepository/unitTests/testErrorHandling.cpp @@ -0,0 +1,316 @@ +/* + * ------------------------------------------------------------------------------------------------------------ + * 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. + * ------------------------------------------------------------------------------------------------------------ + */ + +// forcefully enable asserts macros for this unit test +#define GEOS_ASSERT_ENABLED +#include "common/logger/ErrorHandling.hpp" + +#include "common/logger/Logger.hpp" +#include "dataRepository/DataContext.hpp" +#include "common/initializeEnvironment.hpp" + +#include +#include + +using namespace geos; +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 + +// 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__ + +// various dummy test values and contexts +double testMinPrecision = 1e-6; +double testMaxPrecision = 1e-3; +int testValue = 5; +DataFileContext const context = DataFileContext( "Base Test Class", "/path/to/file.xml", 23 ); +DataFileContext const additionalContext = DataFileContext( "Additional Test Class", "/path/to/file.xml", 32 ); +DataFileContext const importantAdditionalContext = DataFileContext( "Important Additional Test Class", "/path/to/file.xml", 64 ); + +/** + * @brief begin a test with a local logger + * @param errorLogger local error logger instance + * @param filename output error filename + */ +void beginLocalLoggerTest( ErrorLogger & errorLogger, string_view filename ) +{ + errorLogger.enableFileOutput( true ); + errorLogger.setOutputFilename( filename ); + errorLogger.createFile(); +} + +/** + * @brief end the local logger test by reading the logger file output, comparing it to a reference, and removing it. + * @param errorLogger local error logger instance + * @param expectedFileBits reference file parts that must be in the logger file output + */ +void endLocalLoggerTest( ErrorLogger & errorLogger, + std::vector< string > expectedFileBits ) +{ + auto const readFile = [] ( string_view filename ) { + if( !fs::exists( filename )) + throw std::runtime_error( "File not found: " + std::string( filename ) ); + + std::ifstream file{ std::string( filename ) }; + if( !file.is_open()) + throw std::runtime_error( "Failed to open file: " + std::string( filename ) ); + + std::stringstream buffer; + std::string line; + while( std::getline( file, line )) + buffer << line << '\n'; + + return buffer.str(); + }; + + string_view filename = errorLogger.getOutputFilename(); + string fileContent = readFile( filename ); + bool testFailed = false; + for( size_t i = 0; i < expectedFileBits.size(); ++i ) + { + bool const foundFileBit = fileContent.find( expectedFileBits[i] ) != string::npos; + EXPECT_TRUE( foundFileBit ) << "Expected bit not found (no." << i << "):\n" + << "-----------------------\n" + << expectedFileBits[i] << '\n' + << "-----------------------\n"; + testFailed |= !foundFileBit; + } + EXPECT_FALSE( testFailed ) << "Generated error file content:\n" + << "-----------------------\n" + << fileContent << '\n' + << "-----------------------\n"; + + if( fs::exists( filename ) ) + fs::remove( filename ); +} + +TEST( ErrorHandling, testYamlFileWarningOutput ) +{ + ErrorLogger testErrorLogger; + + beginLocalLoggerTest( testErrorLogger, "warningTestOutput.yaml" ); + + GET_LINE( line1 ); GEOS_WARNING( "Conflicting pressure boundary conditions" ); + + GET_LINE( line2 ); GEOS_WARNING_IF_GT_MSG( testValue, testMaxPrecision, "Pressure value is too high." ); + + string const warningMsg = GEOS_FMT( "{}: option should be between {} and {}. A value of {} will be used.", + context.toString(), testMinPrecision, testMaxPrecision, testMinPrecision ); + GET_LINE( line3 ); GEOS_WARNING_IF( testValue == 5, warningMsg, context, additionalContext ); + + endLocalLoggerTest( testErrorLogger, { + R"(errors:)", + + GEOS_FMT( + R"(- type: Warning + rank: 0 + message: >- + Conflicting pressure boundary conditions + sourceLocation: + file: {} + line: {})", + __FILE__, line1 ), + + GEOS_FMT( + R"(- type: Warning + rank: 0 + message: >- + Pressure value is too high. + cause: >- + Expected: testValue <= testMaxPrecision + * testValue = 5 + * testMaxPrecision = 0.001 + sourceLocation: + file: {} + line: {})", + __FILE__, line2 ), + + GEOS_FMT( + R"(- type: Warning + rank: 0 + message: >- + Base Test Class (file.xml, l.23): option should be between 1e-06 and 0.001. A value of 1e-06 will be used. + contexts: + - priority: 0 + inputFile: /path/to/file.xml + inputLine: 23 + - priority: 0 + inputFile: /path/to/file.xml + inputLine: 32 + cause: >- + Warning cause: testValue == 5 + sourceLocation: + file: {} + line: {})", + __FILE__, line3 ), + } ); +} + +TEST( ErrorHandling, testYamlFileExceptionOutput ) +{ + ErrorLogger testErrorLogger; + + beginLocalLoggerTest( testErrorLogger, "exceptionTestOutput.yaml" ); + size_t line1; + + // Stacked exception test (contexts must appear sorted by priority) + try + { + line1 = __LINE__; GEOS_THROW_IF( testValue == 5, "Empty Group: " << context.toString(), std::domain_error, context ); + } + catch( std::domain_error const & ex ) + { + string const errorMsg = "Table input error.\n"; + testErrorLogger.currentErrorMsg() + .addToMsg( errorMsg ) + .addContextInfo( additionalContext.getContextInfo() ) + .addContextInfo( importantAdditionalContext.getContextInfo().setPriority( 2 ) ); + } + testErrorLogger.flushErrorMsg( testErrorLogger.currentErrorMsg() ); + + endLocalLoggerTest( testErrorLogger, { + R"(errors:)", + + GEOS_FMT( + R"(- type: Exception + rank: 0 + message: >- + Table input error. + Empty Group: Base Test Class (file.xml, l.23) + contexts: + - priority: 2 + inputFile: /path/to/file.xml + inputLine: 64 + - priority: 0 + inputFile: /path/to/file.xml + inputLine: 23 + - priority: 0 + inputFile: /path/to/file.xml + inputLine: 32 + cause: >- + Error cause: testValue == 5 + sourceLocation: + file: {} + line: {} + sourceCallStack:)", + __FILE__, line1 ), + "- frame0: ", + "- frame1: ", + "- frame2: " + } ); +} + +TEST( ErrorHandling, testYamlFileErrorOutput ) +{ + ErrorLogger testErrorLogger; + + beginLocalLoggerTest( testErrorLogger, "errorTestOutput.yaml" ); + + EXPECT_EXIT( GEOS_ERROR_IF_GT_MSG( testValue, testMaxPrecision, + GEOS_FMT( "{}: option should be lower than {}.", + context.toString(), testMaxPrecision ), + context, + additionalContext, + importantAdditionalContext.getContextInfo().setPriority( 2 ) ), + ::testing::ExitedWithCode( 1 ), + ".*" ); + + endLocalLoggerTest( testErrorLogger, { + R"(errors:)", + + // we won't test the line index for this test as it cannot be a one-liner. + R"(- type: Error + rank: 0 + message: >- + Base Test Class (file.xml, l.23): option should be lower than 0.001. + contexts: + - priority: 2 + inputFile: /path/to/file.xml + inputLine: 64 + - priority: 0 + inputFile: /path/to/file.xml + inputLine: 23 + - priority: 0 + inputFile: /path/to/file.xml + inputLine: 32 + cause: >- + Expected: testValue <= testMaxPrecision + * testValue = 5 + * testMaxPrecision = 0.001 + sourceLocation:)", + " file: ", + " line: ", + "sourceCallStack:", + "- frame0: ", + "- frame1: ", + "- frame2: " + } ); +} + +TEST( ErrorHandling, testYamlFileAssertOutput ) +{ + ErrorLogger testErrorLogger; + + beginLocalLoggerTest( testErrorLogger, "assertTestOutput.yaml" ); + + EXPECT_EXIT( GEOS_ASSERT_MSG( testValue > testMinPrecision && testValue < testMaxPrecision, + GEOS_FMT( "{}: value should be between {} and {}, but is {}.", + context.toString(), testMinPrecision, testMaxPrecision, testValue ), + context, + additionalContext ), + ::testing::ExitedWithCode( 1 ), + ".*" ); + + endLocalLoggerTest( testErrorLogger, { + R"(errors:)", + + // we won't test the line index for this test as it cannot be a one-liner. + R"(- type: Error + rank: 0 + message: >- + Base Test Class (file.xml, l.23): value should be between 1e-06 and 0.001, but is 5. + contexts: + - priority: 0 + inputFile: /path/to/file.xml + inputLine: 23 + - priority: 0 + inputFile: /path/to/file.xml + inputLine: 32 + cause: >- + Expected: testValue > testMinPrecision && testValue < testMaxPrecision + sourceLocation:)", + " file: ", + " line: ", + "sourceCallStack:", + "- frame0: ", + "- frame1: ", + "- frame2: " + } ); +} + +int main( int ac, char * av[] ) +{ + ::testing::GTEST_FLAG( death_test_style ) = "threadsafe"; + ::testing::InitGoogleTest( &ac, av ); + geos::setupEnvironment( ac, av ); + int const result = RUN_ALL_TESTS(); + geos::cleanupEnvironment( ); + return result; +} diff --git a/src/coreComponents/denseLinearAlgebra/unitTests/testUtils.hpp b/src/coreComponents/denseLinearAlgebra/unitTests/testUtils.hpp index 17f093a569b..44c83edc9f1 100644 --- a/src/coreComponents/denseLinearAlgebra/unitTests/testUtils.hpp +++ b/src/coreComponents/denseLinearAlgebra/unitTests/testUtils.hpp @@ -15,8 +15,8 @@ namespace testing #if defined(GEOS_DEVICE_COMPILE) #define PORTABLE_EXPECT_EQ( L, R ) GEOS_ERROR_IF_NE( L, R ) -#define PORTABLE_EXPECT_NEAR( L, R, EPSILON ) LVARRAY_ERROR_IF_GE_MSG( LvArray::math::abs( ( L ) -( R ) ), EPSILON, \ - STRINGIZE( L ) " = " << ( L ) << "\n" << STRINGIZE( R ) " = " << ( R ) ); +#define PORTABLE_EXPECT_NEAR( L, R, EPSILON ) GEOS_ERROR_IF_GE_MSG( LvArray::math::abs( ( L ) -( R ) ), EPSILON, \ + STRINGIZE( L ) " = " << ( L ) << "\n" << STRINGIZE( R ) " = " << ( R ) ); #define PORTABLE_EXPECT_TRUE( value ) GEOS_ERROR_IF( !value, "should be true" ) #define PORTABLE_EXPECT_FALSE( value ) GEOS_ERROR_IF( value, "should be false" ) #else diff --git a/src/coreComponents/events/EventBase.cpp b/src/coreComponents/events/EventBase.cpp index 00aed4b5d15..1984ec59fbc 100644 --- a/src/coreComponents/events/EventBase.cpp +++ b/src/coreComponents/events/EventBase.cpp @@ -19,7 +19,6 @@ #include "EventBase.hpp" #include - #include "events/LogLevelsInfo.hpp" #include "common/DataTypes.hpp" @@ -152,8 +151,13 @@ void EventBase::getTargetReferences() } catch( std::exception const & e ) { - throw InputError( e, GEOS_FMT( "Error while reading {}:\n", - getWrapperDataContext( viewKeyStruct::eventTargetString() ) ) ); + string const errorMsg = GEOS_FMT( "Error while reading {}:\n", + getWrapperDataContext( viewKeyStruct::eventTargetString() ) ); + ErrorLogger::global().currentErrorMsg() + .addToMsg( errorMsg ) + .addContextInfo( getWrapperDataContext( viewKeyStruct::eventTargetString() ).getContextInfo() + .setPriority( 1 ) ); + throw InputError( e, errorMsg ); } } diff --git a/src/coreComponents/events/PeriodicEvent.cpp b/src/coreComponents/events/PeriodicEvent.cpp index e26ea889137..4a5a1c64db5 100644 --- a/src/coreComponents/events/PeriodicEvent.cpp +++ b/src/coreComponents/events/PeriodicEvent.cpp @@ -267,22 +267,22 @@ void PeriodicEvent::validate() const return; } - GEOS_THROW_IF( m_timeFrequency > 0 && - target->getTimesteppingBehavior() == ExecutableGroup::TimesteppingBehavior::DeterminesTimeStepSize, + constexpr auto determinesTimeStepSize = ExecutableGroup::TimesteppingBehavior::DeterminesTimeStepSize; + + GEOS_THROW_IF( m_timeFrequency > 0 && target->getTimesteppingBehavior() == determinesTimeStepSize, GEOS_FMT( "`{}`: This event targets an object that automatically selects the time " "step size. Therefore, `{}` cannot be used here. However, forcing a " "constant time step size can still be achived with `{}`.", getDataContext(), viewKeyStruct::timeFrequencyString(), EventBase::viewKeyStruct::forceDtString() ), - InputError ); - GEOS_THROW_IF( m_cycleFrequency != 1 && - target->getTimesteppingBehavior() == ExecutableGroup::TimesteppingBehavior::DeterminesTimeStepSize, + InputError, getDataContext() ); + GEOS_THROW_IF( m_cycleFrequency != 1 && target->getTimesteppingBehavior() == determinesTimeStepSize, GEOS_FMT( "`{}`: This event targets an object that automatically selects the time " "step size. Therefore, `{}` cannot be used here. However, forcing a " "constant time step size can still be achived with `{}`.", getDataContext(), viewKeyStruct::cycleFrequencyString(), EventBase::viewKeyStruct::forceDtString() ), - InputError ); + InputError, getDataContext() ); } REGISTER_CATALOG_ENTRY( EventBase, PeriodicEvent, string const &, Group * const ) diff --git a/src/coreComponents/fieldSpecification/AquiferBoundaryCondition.cpp b/src/coreComponents/fieldSpecification/AquiferBoundaryCondition.cpp index 325be2e2fe7..667e2ecc682 100644 --- a/src/coreComponents/fieldSpecification/AquiferBoundaryCondition.cpp +++ b/src/coreComponents/fieldSpecification/AquiferBoundaryCondition.cpp @@ -129,7 +129,7 @@ void AquiferBoundaryCondition::postInputInitialization() GEOS_THROW_IF( !functionManager.hasGroup( m_pressureInfluenceFunctionName ), getCatalogName() << " " << getDataContext() << ": the pressure influence table " << m_pressureInfluenceFunctionName << " could not be found", - InputError ); + InputError, getDataContext() ); TableFunction const & pressureInfluenceFunction = functionManager.getGroup< TableFunction >( m_pressureInfluenceFunctionName ); GEOS_THROW_IF( pressureInfluenceFunction.getInterpolationMethod() != TableFunction::InterpolationType::Linear, @@ -137,7 +137,7 @@ void AquiferBoundaryCondition::postInputInitialization() ": The interpolation method for the pressure influence function table " << pressureInfluenceFunction.getDataContext() << " should be TableFunction::InterpolationType::Linear", - InputError ); + InputError, getDataContext() ); } computeTimeConstant(); diff --git a/src/coreComponents/fieldSpecification/EquilibriumInitialCondition.cpp b/src/coreComponents/fieldSpecification/EquilibriumInitialCondition.cpp index 30a41770e9d..8316c3beacd 100644 --- a/src/coreComponents/fieldSpecification/EquilibriumInitialCondition.cpp +++ b/src/coreComponents/fieldSpecification/EquilibriumInitialCondition.cpp @@ -100,16 +100,16 @@ void EquilibriumInitialCondition::postInputInitialization() GEOS_THROW_IF( m_componentFractionVsElevationTableNames.size() <= 1, getCatalogName() << " " << getDataContext() << ": at least two component names must be specified in " << viewKeyStruct::componentNamesString(), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( m_componentFractionVsElevationTableNames.size() != m_componentNames.size(), getCatalogName() << " " << getDataContext() << ": mismatch between the size of " << viewKeyStruct::componentNamesString() << " and " << viewKeyStruct::componentFractionVsElevationTableNamesString(), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( m_componentNames.size() >= 2 && m_initPhaseName.empty(), getCatalogName() << " " << getDataContext() << ": for now, the keyword: " << viewKeyStruct::initPhaseNameString() << " must be filled for a multiphase simulation", - InputError ); + InputError, getDataContext() ); array1d< localIndex > tableSizes( m_componentNames.size() ); for( size_t ic = 0; ic < m_componentNames.size(); ++ic ) @@ -117,20 +117,20 @@ void EquilibriumInitialCondition::postInputInitialization() GEOS_THROW_IF( m_componentFractionVsElevationTableNames[ic].empty(), getCatalogName() << " " << getDataContext() << ": the component fraction vs elevation table name is missing for component " << ic, - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( !m_componentFractionVsElevationTableNames[ic].empty() && !functionManager.hasGroup( m_componentFractionVsElevationTableNames[ic] ), getCatalogName() << " " << getDataContext() << ": the component fraction vs elevation table " << m_componentFractionVsElevationTableNames[ic] << " could not be found" << " for component " << ic, - InputError ); + InputError, getDataContext() ); TableFunction const & compFracTable = functionManager.getGroup< TableFunction >( m_componentFractionVsElevationTableNames[ic] ); GEOS_THROW_IF( compFracTable.getInterpolationMethod() != TableFunction::InterpolationType::Linear, getCatalogName() << " " << getDataContext() << ": the interpolation method for the component fraction vs elevation table " << compFracTable.getName() << " should be TableFunction::InterpolationType::Linear", - InputError ); + InputError, getDataContext() ); } } @@ -141,14 +141,14 @@ void EquilibriumInitialCondition::postInputInitialization() GEOS_THROW_IF( !functionManager.hasGroup( m_temperatureVsElevationTableName ), getCatalogName() << " " << getDataContext() << ": the temperature vs elevation table " << m_temperatureVsElevationTableName << " could not be found", - InputError ); + InputError, getDataContext() ); TableFunction const & tempTable = functionManager.getGroup< TableFunction >( m_temperatureVsElevationTableName ); GEOS_THROW_IF( tempTable.getInterpolationMethod() != TableFunction::InterpolationType::Linear, getCatalogName() << " " << getDataContext() << ": The interpolation method for the temperature vs elevation table " << tempTable.getName() << " should be TableFunction::InterpolationType::Linear", - InputError ); + InputError, getDataContext() ); } } @@ -169,7 +169,7 @@ void EquilibriumInitialCondition::initializePreSubGroups() getCatalogName() << " " << getDataContext() << ": the component fraction vs elevation table " << compFracTable.getName() << " must contain at least two values", - InputError ); + InputError, getDataContext() ); tableSizes[ic] = compFracValues.size(); if( ic >= 1 ) @@ -177,7 +177,7 @@ void EquilibriumInitialCondition::initializePreSubGroups() GEOS_THROW_IF( tableSizes[ic] != tableSizes[ic-1], getCatalogName() << " " << getDataContext() << ": all the component fraction vs elevation tables must contain the same number of values", - InputError ); + InputError, getDataContext() ); } } @@ -199,7 +199,7 @@ void EquilibriumInitialCondition::initializePreSubGroups() GEOS_THROW_IF( !isZero( elevation[ic][i] - elevation[ic-1][i] ), getCatalogName() << " " << getDataContext() << ": the elevation values must be the same in all the component vs elevation tables", - InputError ); + InputError, getDataContext() ); } if( ic == m_componentNames.size() - 1 ) @@ -207,7 +207,7 @@ void EquilibriumInitialCondition::initializePreSubGroups() GEOS_THROW_IF( !isZero( sumCompFrac[i] - 1 ), getCatalogName() << " " << getDataContext() << ": at a given elevation, the component fraction sum must be equal to one", - InputError ); + InputError, getDataContext() ); } } } diff --git a/src/coreComponents/fieldSpecification/FieldSpecificationBase.cpp b/src/coreComponents/fieldSpecification/FieldSpecificationBase.cpp index 5a07d93d689..841ec1abcc0 100644 --- a/src/coreComponents/fieldSpecification/FieldSpecificationBase.cpp +++ b/src/coreComponents/fieldSpecification/FieldSpecificationBase.cpp @@ -115,6 +115,11 @@ void FieldSpecificationBase::setMeshObjectPath( Group const & meshBodies ) } catch( std::exception const & e ) { + ErrorLogger::global().currentErrorMsg() + .addToMsg( getWrapperDataContext( viewKeyStruct::objectPathString() ).toString() + + " is a wrong objectPath: " + m_objectPath + "\n" ) + .addContextInfo( getWrapperDataContext( viewKeyStruct::objectPathString() ).getContextInfo() + .setPriority( 2 ) ); throw InputError( e, getWrapperDataContext( viewKeyStruct::objectPathString() ).toString() + " is a wrong objectPath: " + m_objectPath + "\n" ); } diff --git a/src/coreComponents/fieldSpecification/FieldSpecificationBase.hpp b/src/coreComponents/fieldSpecification/FieldSpecificationBase.hpp index 62aa6a00626..2880b4811a6 100644 --- a/src/coreComponents/fieldSpecification/FieldSpecificationBase.hpp +++ b/src/coreComponents/fieldSpecification/FieldSpecificationBase.hpp @@ -636,8 +636,13 @@ void FieldSpecificationBase::applyFieldValueKernel( ArrayView< T, N, USD > const } catch( std::exception const & e ) { - throw InputError( e, GEOS_FMT( "Error while reading {}:\n", - getWrapperDataContext( viewKeyStruct::functionNameString() ) ) ); + string const errorMsg = GEOS_FMT( "Error while reading {}:\n", + getWrapperDataContext( viewKeyStruct::functionNameString() ) ); + ErrorLogger::global().currentErrorMsg() + .addToMsg( errorMsg ) + .addContextInfo( getWrapperDataContext( viewKeyStruct::functionNameString() ).getContextInfo() + .setPriority( 1 ) ); + throw InputError( e, errorMsg ); } }(); diff --git a/src/coreComponents/fieldSpecification/PerfectlyMatchedLayer.cpp b/src/coreComponents/fieldSpecification/PerfectlyMatchedLayer.cpp index c2d7317cec0..11f1b683b04 100644 --- a/src/coreComponents/fieldSpecification/PerfectlyMatchedLayer.cpp +++ b/src/coreComponents/fieldSpecification/PerfectlyMatchedLayer.cpp @@ -83,13 +83,13 @@ void PerfectlyMatchedLayer::postInputInitialization() << viewKeyStruct::xMinString() << " must be smaller than " << viewKeyStruct::xMaxString(), - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( (m_reflectivity<=0 || m_reflectivity>1), getCatalogName() << " " << getDataContext() << " " << viewKeyStruct::reflectivityString() << " must satisfy 0 < reflectivity <= 1", - InputError ); + InputError, getDataContext() ); GEOS_LOG_RANK_0_IF( (m_xMin[0]( getDirection() ) < 1e-20, getDataContext() << ": " << viewKeyStruct::directionString() << " is required for " << viewKeyStruct::tractionTypeString() << " = " << TractionType::vector << - ", but appears to be unspecified" ); + ", but appears to be unspecified", + getDataContext() ); } else { @@ -99,7 +100,8 @@ void TractionBoundaryCondition::postInputInitialization() GEOS_ERROR_IF( !inputStressRead && m_tractionType == TractionType::stress, getDataContext() << ": " << viewKeyStruct::tractionTypeString() << " = " << TractionType::stress << - ", but " << viewKeyStruct::inputStressString() << " is not specified." ); + ", but " << viewKeyStruct::inputStressString() << " is not specified.", + getDataContext() ); // localIndex const numStressFunctionsNames = m_stressFunctionNames.size(); diff --git a/src/coreComponents/fileIO/Outputs/SiloOutput.cpp b/src/coreComponents/fileIO/Outputs/SiloOutput.cpp index 0adac80f5c8..7d93495048f 100644 --- a/src/coreComponents/fileIO/Outputs/SiloOutput.cpp +++ b/src/coreComponents/fileIO/Outputs/SiloOutput.cpp @@ -100,7 +100,7 @@ void SiloOutput::postInputInitialization() GEOS_FMT( "{} `{}`: the flag `{}` is different from zero, but `{}` is empty, which is inconsistent", catalogName(), getDataContext(), onlyPlotSpecifiedFieldNamesString, fieldNamesString ), - InputError ); + InputError, getDataContext() ); GEOS_LOG_RANK_0_IF( !m_fieldNames.empty() && ( m_onlyPlotSpecifiedFieldNames != 0 ), GEOS_FMT( diff --git a/src/coreComponents/fileIO/Outputs/TimeHistoryOutput.cpp b/src/coreComponents/fileIO/Outputs/TimeHistoryOutput.cpp index 0c66a3bf3bd..ed84a72833b 100644 --- a/src/coreComponents/fileIO/Outputs/TimeHistoryOutput.cpp +++ b/src/coreComponents/fileIO/Outputs/TimeHistoryOutput.cpp @@ -143,8 +143,13 @@ void TimeHistoryOutput::initializePostInitialConditionsPostSubGroups() } catch( std::exception const & e ) { - throw InputError( e, GEOS_FMT( "Error while reading {}:\n", - getWrapperDataContext( viewKeys::timeHistoryOutputTargetString() ) ) ); + string const errorMsg = GEOS_FMT( "Error while reading {}:\n", + getWrapperDataContext( viewKeys::timeHistoryOutputTargetString() ) ); + ErrorLogger::global().currentErrorMsg() + .addToMsg( errorMsg ) + .addContextInfo( getWrapperDataContext( viewKeys::timeHistoryOutputTargetString() ).getContextInfo() + .setPriority( 1 ) ); + throw InputError( e, errorMsg ); } } } diff --git a/src/coreComponents/fileIO/Outputs/VTKOutput.cpp b/src/coreComponents/fileIO/Outputs/VTKOutput.cpp index 9403f0ed9c5..5f617298ad5 100644 --- a/src/coreComponents/fileIO/Outputs/VTKOutput.cpp +++ b/src/coreComponents/fileIO/Outputs/VTKOutput.cpp @@ -123,7 +123,7 @@ void VTKOutput::postInputInitialization() GEOS_FMT( "{} `{}`: the flag `{}` is different from zero, but `{}` is empty, which is inconsistent", catalogName(), getDataContext(), onlyPlotSpecifiedFieldNamesString, fieldNamesString ), - InputError ); + InputError, getDataContext() ); GEOS_LOG_RANK_0_IF( !m_fieldNames.empty() && ( m_onlyPlotSpecifiedFieldNames != 0 ), GEOS_FMT( @@ -137,8 +137,10 @@ void VTKOutput::postInputInitialization() catalogName(), getDataContext(), std::to_string( m_fieldNames.size() ), fieldNamesString, m_plotLevel ) ); - GEOS_ERROR_IF( m_writeFaceElementsAs3D, GEOS_FMT( "{} `{}`: 3D vtk plot of faceElements is not yet supported.", - catalogName(), getDataContext() ) ); + GEOS_ERROR_IF( m_writeFaceElementsAs3D, + GEOS_FMT( "{} `{}`: 3D vtk plot of faceElements is not yet supported.", + catalogName(), getDataContext() ), + getDataContext() ); } diff --git a/src/coreComponents/fileIO/timeHistory/HistoryCollectionBase.cpp b/src/coreComponents/fileIO/timeHistory/HistoryCollectionBase.cpp index 4fe9b535e4c..cbfa1e1b303 100644 --- a/src/coreComponents/fileIO/timeHistory/HistoryCollectionBase.cpp +++ b/src/coreComponents/fileIO/timeHistory/HistoryCollectionBase.cpp @@ -200,6 +200,9 @@ dataRepository::Group const * HistoryCollectionBase::getTargetObject( DomainPart } catch( std::exception const & e ) { + ErrorLogger::global().currentErrorMsg() + .addToMsg( getDataContext().toString() + " has a wrong objectPath: " + objectPath + "\n" ) + .addContextInfo( getDataContext().getContextInfo().setPriority( 2 ) ); 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 db8492f10f4..ff9b229cec1 100644 --- a/src/coreComponents/fileIO/timeHistory/PackCollection.cpp +++ b/src/coreComponents/fileIO/timeHistory/PackCollection.cpp @@ -153,6 +153,11 @@ void PackCollection::updateSetsIndices( DomainPartition const & domain ) } catch( std::exception const & e ) { + ErrorLogger::global().currentErrorMsg() + .addToMsg( getWrapperDataContext( viewKeysStruct::fieldNameString() ).toString() + + ": Target not found !\n" ) + .addContextInfo( getWrapperDataContext( viewKeysStruct::fieldNameString() ).getContextInfo() + .setPriority( 1 ) ); throw InputError( e, getWrapperDataContext( viewKeysStruct::fieldNameString() ).toString() + ": Target not found !\n" ); } diff --git a/src/coreComponents/finiteElement/FiniteElementDiscretization.cpp b/src/coreComponents/finiteElement/FiniteElementDiscretization.cpp index 30a5010e70f..be6a5716b43 100644 --- a/src/coreComponents/finiteElement/FiniteElementDiscretization.cpp +++ b/src/coreComponents/finiteElement/FiniteElementDiscretization.cpp @@ -63,7 +63,8 @@ FiniteElementDiscretization::~FiniteElementDiscretization() void FiniteElementDiscretization::postInputInitialization() { GEOS_ERROR_IF( m_useVem < 0 || m_useVem > 1, - getDataContext() << ": The flag useVirtualElements can be either 0 or 1" ); + getDataContext() << ": The flag useVirtualElements can be either 0 or 1", + getDataContext() ); } std::unique_ptr< FiniteElementBase > @@ -206,7 +207,8 @@ FiniteElementDiscretization::factory( ElementType const parentElementShape ) con case ElementType::Hexahedron: GEOS_ERROR_IF( m_formulation != Formulation::SEM, getDataContext() << ": Element type Hexahedron with order 2 available" << - " only when using the Spectral Element Method" ); + " only when using the Spectral Element Method", + getDataContext() ); return std::make_unique< Q2_Hexahedron_Lagrange_GaussLobatto >(); #else GEOS_ERROR( "Cannot compile this with HIP active." ); @@ -233,7 +235,8 @@ FiniteElementDiscretization::factory( ElementType const parentElementShape ) con case ElementType::Hexahedron: GEOS_ERROR_IF( m_formulation != Formulation::SEM, getDataContext() << ": Element type Hexahedron with order 3 available" << - " only when using the Spectral Element Method" ); + " only when using the Spectral Element Method", + getDataContext() ); return std::make_unique< Q3_Hexahedron_Lagrange_GaussLobatto >(); #else GEOS_ERROR( "Cannot compile this with HIP active." ); @@ -260,7 +263,8 @@ FiniteElementDiscretization::factory( ElementType const parentElementShape ) con case ElementType::Hexahedron: GEOS_ERROR_IF( m_formulation != Formulation::SEM, getDataContext() << ": Element type Hexahedron with order 4 available only" << - " when using the Spectral Element Method" ); + " when using the Spectral Element Method", + getDataContext() ); return std::make_unique< Q4_Hexahedron_Lagrange_GaussLobatto >(); #else GEOS_ERROR( "Cannot compile this with HIP active." ); @@ -287,7 +291,8 @@ FiniteElementDiscretization::factory( ElementType const parentElementShape ) con case ElementType::Hexahedron: GEOS_ERROR_IF( m_formulation != Formulation::SEM, getDataContext() << ": Element type Hexahedron with order 5 available only" << - " when using the Spectral Element Method" ); + " when using the Spectral Element Method", + getDataContext() ); return std::make_unique< Q5_Hexahedron_Lagrange_GaussLobatto >(); #else GEOS_ERROR( "Cannot compile this with HIP active." ); diff --git a/src/coreComponents/functions/MultivariableTableFunction.cpp b/src/coreComponents/functions/MultivariableTableFunction.cpp index 4f8db1244bb..cd7eca72b66 100644 --- a/src/coreComponents/functions/MultivariableTableFunction.cpp +++ b/src/coreComponents/functions/MultivariableTableFunction.cpp @@ -35,7 +35,8 @@ MultivariableTableFunction::MultivariableTableFunction( const string & name, void MultivariableTableFunction::initializeFunctionFromFile( string const & filename ) { std::ifstream file( filename.c_str() ); - GEOS_THROW_IF( !file, catalogName() << " " << getDataContext() << ": could not read input file " << filename, InputError ); + GEOS_THROW_IF( !file, catalogName() << " " << getDataContext() << ": could not read input file " << filename, + InputError, getDataContext() ); integer numDims, numOps; globalIndex numPointsTotal = 1; @@ -67,12 +68,15 @@ void MultivariableTableFunction::initializeFunctionFromFile( string const & file for( integer i = 0; i < numDims; i++ ) { file >> axisPoints[i]; - GEOS_THROW_IF( !file, catalogName() << " " << getDataContext() << ": can`t read the number of points for axis " + std::to_string( i ), InputError ); + GEOS_THROW_IF( !file, catalogName() << " " << getDataContext() << ": can`t read the number of points for axis " + std::to_string( i ), + InputError, getDataContext() ); GEOS_THROW_IF_LE_MSG( axisPoints[i], 1, catalogName() << " " << getDataContext() << ": minimum 2 discretization point per axis are expected", InputError ); file >> axisMinimums[i]; - GEOS_THROW_IF( !file, catalogName() << " " << getDataContext() << ": can`t read minimum value for axis " + std::to_string( i ), InputError ); + GEOS_THROW_IF( !file, catalogName() << " " << getDataContext() << ": can`t read minimum value for axis " + std::to_string( i ), + InputError, getDataContext() ); file >> axisMaximums[i]; - GEOS_THROW_IF( !file, catalogName() << " " << getDataContext() << ": can`t read maximum value for axis " + std::to_string( i ), InputError ); + GEOS_THROW_IF( !file, catalogName() << " " << getDataContext() << ": can`t read maximum value for axis " + std::to_string( i ), + InputError, getDataContext() ); GEOS_THROW_IF_LT_MSG( axisMaximums[i], axisMinimums[i], catalogName() << " " << getDataContext() << ": maximum axis value is expected to be larger than minimum", InputError ); numPointsTotal *= axisPoints[i]; @@ -95,13 +99,15 @@ void MultivariableTableFunction::initializeFunctionFromFile( string const & file for( auto j = 0; j < numOps; j++ ) { file >> m_pointData[i * numOps + j]; - GEOS_THROW_IF( !file, catalogName() << " " << getDataContext() << ": table file is shorter than expected", InputError ); + GEOS_THROW_IF( !file, catalogName() << " " << getDataContext() << ": table file is shorter than expected", + InputError, getDataContext() ); } } real64 value; file >> value; - GEOS_THROW_IF( file, catalogName() << " " << getDataContext() << ": table file is longer than expected", InputError ); + GEOS_THROW_IF( file, catalogName() << " " << getDataContext() << ": table file is longer than expected", + InputError, getDataContext() ); file.close(); diff --git a/src/coreComponents/functions/TableFunction.cpp b/src/coreComponents/functions/TableFunction.cpp index 1bb752fbebe..7ee6c4a3490 100644 --- a/src/coreComponents/functions/TableFunction.cpp +++ b/src/coreComponents/functions/TableFunction.cpp @@ -105,7 +105,7 @@ void TableFunction::setTableCoordinates( array1d< real64_array > const & coordin GEOS_THROW_IF( coordinates[i][j] - coordinates[i][j-1] <= 0, GEOS_FMT( "{} {}: coordinates must be strictly increasing, but axis {} is not", catalogName(), getDataContext(), i ), - InputError ); + InputError, getDataContext() ); } m_coordinates.appendArray( coordinates[i].begin(), coordinates[i].end() ); } @@ -167,7 +167,7 @@ void TableFunction::reInitializeFunction() GEOS_THROW_IF( m_coordinates[ii][j] - m_coordinates[ii][j-1] <= 0, GEOS_FMT( "{} {}: coordinates must be strictly increasing, but axis {} is not", catalogName(), getDataContext(), ii ), - InputError ); + InputError, getDataContext() ); } } if( m_coordinates.size() > 0 && !m_values.empty() ) // coordinates and values have been set @@ -187,7 +187,7 @@ void TableFunction::checkCoord( real64 const coord, localIndex const dim ) const GEOS_THROW_IF( dim >= m_coordinates.size() || dim < 0, GEOS_FMT( "{}: The {} dimension ( no. {} ) doesn't exist in the table.", getDataContext(), units::getDescription( getDimUnit( dim ) ), dim ), - SimulationError ); + SimulationError, getDataContext() ); real64 const lowerBound = m_coordinates[dim][0]; real64 const upperBound = m_coordinates[dim][m_coordinates.sizeOfArray( dim ) - 1]; GEOS_THROW_IF( coord > upperBound || coord < lowerBound, @@ -196,7 +196,7 @@ void TableFunction::checkCoord( real64 const coord, localIndex const dim ) const units::formatValue( coord, getDimUnit( dim ) ), units::formatValue( lowerBound, getDimUnit( dim ) ), units::formatValue( upperBound, getDimUnit( dim ) ) ), - SimulationError ); + SimulationError, getDataContext() ); } TableFunction::KernelWrapper TableFunction::createKernelWrapper() const diff --git a/src/coreComponents/integrationTests/dataRepositoryTests/testGroupPath.cpp b/src/coreComponents/integrationTests/dataRepositoryTests/testGroupPath.cpp index 0872e7087d3..3927a3812b4 100644 --- a/src/coreComponents/integrationTests/dataRepositoryTests/testGroupPath.cpp +++ b/src/coreComponents/integrationTests/dataRepositoryTests/testGroupPath.cpp @@ -106,7 +106,7 @@ TEST( testGroupPath, testGlobalPaths ) } catch( const std::domain_error & e ) { - static constexpr auto expectedMsg = "***** Controlling expression (should be false): child == nullptr\n" + static constexpr auto expectedMsg = "***** Error cause: child == nullptr\n" "***** Rank 0: 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 diff --git a/src/coreComponents/linearAlgebra/multiscale/msrsb/MsrsbLevelBuilderCoupled.cpp b/src/coreComponents/linearAlgebra/multiscale/msrsb/MsrsbLevelBuilderCoupled.cpp index 545df9b7e9b..dc268a33e17 100644 --- a/src/coreComponents/linearAlgebra/multiscale/msrsb/MsrsbLevelBuilderCoupled.cpp +++ b/src/coreComponents/linearAlgebra/multiscale/msrsb/MsrsbLevelBuilderCoupled.cpp @@ -147,11 +147,11 @@ void MsrsbLevelBuilderCoupled< LAI >::buildProlongationStructure( DofManager con GEOS_ASSERT_EQ( m_prolongationBlocks.size(), m_dofManager.numFields() ); array1d< localIndex > rowLength( fineDofManager.numLocalDofs() ); - for( std::size_t blockIdx = 0; blockIdx < m_prolongationBlocks.size(); ++blockIdx ) + for( std::size_t blockId = 0; blockId < m_prolongationBlocks.size(); ++blockId ) { - localIndex const rowOffset = fineDofManager.localOffset( m_fields[blockIdx] ); - forAll< parallelHostPolicy >( m_prolongationBlocks[blockIdx].numRows(), - [block = m_prolongationBlocks[blockIdx].toViewConst(), + localIndex const rowOffset = fineDofManager.localOffset( m_fields[blockId] ); + forAll< parallelHostPolicy >( m_prolongationBlocks[blockId].numRows(), + [block = m_prolongationBlocks[blockId].toViewConst(), rowLength = rowLength.toView(), rowOffset]( localIndex const localRow ) { @@ -163,10 +163,10 @@ void MsrsbLevelBuilderCoupled< LAI >::buildProlongationStructure( DofManager con m_dofManager.numGlobalDofs(), rowLength.data() ); - for( std::size_t blockIdx = 0; blockIdx < m_prolongationBlocks.size(); ++blockIdx ) + for( std::size_t blockId = 0; blockId < m_prolongationBlocks.size(); ++blockId ) { - DofManager const & dofManager = m_builders[blockIdx]->dofManager(); - string const & fieldName = m_fields[blockIdx]; + DofManager const & dofManager = m_builders[blockId]->dofManager(); + string const & fieldName = m_fields[blockId]; globalIndex const minLocalDof = dofManager.rankOffset(); globalIndex const maxLocalDof = minLocalDof + dofManager.numLocalDofs(); @@ -177,7 +177,7 @@ void MsrsbLevelBuilderCoupled< LAI >::buildProlongationStructure( DofManager con integer const numComp = m_dofManager.numComponents( fieldName ); std::unordered_map< globalIndex, globalIndex > const ghostDofMap = - makeGhostDofMap( m_builders[blockIdx]->manager(), dofManager.key( fieldName ), m_dofManager.key( fieldName ) ); + makeGhostDofMap( m_builders[blockId]->manager(), dofManager.key( fieldName ), m_dofManager.key( fieldName ) ); auto const mapGhostCol = [numComp, &ghostDofMap]( globalIndex const col ) { @@ -194,8 +194,8 @@ void MsrsbLevelBuilderCoupled< LAI >::buildProlongationStructure( DofManager con return ( minLocalDof <= col && col < maxLocalDof ) ? colOffset + col : mapGhostCol( col ); }; - forAll< parallelHostPolicy >( m_prolongationBlocks[blockIdx].numRows(), - [block = m_prolongationBlocks[blockIdx].toViewConst(), + forAll< parallelHostPolicy >( m_prolongationBlocks[blockId].numRows(), + [block = m_prolongationBlocks[blockId].toViewConst(), prolongation = m_localProlongation.toView(), rowOffset, mapColumn]( localIndex const localRow ) { @@ -217,12 +217,12 @@ void MsrsbLevelBuilderCoupled< LAI >::initializeCoarseLevel( LevelBuilderBase< L GEOS_ASSERT( fine.m_builders.size() == m_builders.size() ); m_fineLevel = &fine; - for( size_t blockIdx = 0; blockIdx < m_builders.size(); ++blockIdx ) + for( size_t blockId = 0; blockId < m_builders.size(); ++blockId ) { Matrix fineBlock; - fineMatrix.multiplyPtAP( fine.m_selectors[blockIdx], fineBlock ); - m_builders[blockIdx]->initializeCoarseLevel( *fine.m_builders[blockIdx], fineBlock ); - m_prolongationBlocks[blockIdx] = m_builders[blockIdx]->prolongation().extract(); + fineMatrix.multiplyPtAP( fine.m_selectors[blockId], fineBlock ); + m_builders[blockId]->initializeCoarseLevel( *fine.m_builders[blockId], fineBlock ); + m_prolongationBlocks[blockId] = m_builders[blockId]->prolongation().extract(); } initializeCommon( fine.dofManager().domain(), fineMatrix.comm() ); @@ -240,22 +240,22 @@ bool MsrsbLevelBuilderCoupled< LAI >::updateProlongation( Matrix const & fineMat // Extract diagonal blocks, update and extract sub-block prolongations bool update = false; localIndex rowOffset = 0; - for( size_t blockIdx = 0; blockIdx < m_builders.size(); ++blockIdx ) + for( size_t blockId = 0; blockId < m_builders.size(); ++blockId ) { Matrix fineBlock; { GEOS_MARK_SCOPE( extract blocks ); auto const & fine = dynamicCast< MsrsbLevelBuilderCoupled< LAI > const & >( *m_fineLevel ); - fineMatrix.multiplyPtAP( fine.m_selectors[blockIdx], fineBlock ); + fineMatrix.multiplyPtAP( fine.m_selectors[blockId], fineBlock ); } - bool const updateBlock = m_builders[blockIdx]->updateProlongation( fineBlock ); - CRSMatrixView< real64, globalIndex const > const block = m_prolongationBlocks[blockIdx].toViewConstSizes(); + bool const updateBlock = m_builders[blockId]->updateProlongation( fineBlock ); + CRSMatrixView< real64, globalIndex const > const block = m_prolongationBlocks[blockId].toViewConstSizes(); if( updateBlock ) { GEOS_MARK_SCOPE( merge blocks ); - m_builders[blockIdx]->prolongation().extract( block ); + m_builders[blockId]->prolongation().extract( block ); forAll< parallelHostPolicy >( block.numRows(), [block = block.toViewConst(), prolongation = m_localProlongation.toViewConstSizes(), diff --git a/src/coreComponents/mainInterface/ProblemManager.cpp b/src/coreComponents/mainInterface/ProblemManager.cpp index decbae981ef..ed85797f2c2 100644 --- a/src/coreComponents/mainInterface/ProblemManager.cpp +++ b/src/coreComponents/mainInterface/ProblemManager.cpp @@ -498,8 +498,12 @@ void ProblemManager::parseXMLDocument( xmlWrapper::xmlDocument & xmlDocument ) } catch( InputError const & e ) { - throw InputError( e, GEOS_FMT( "Error while parsing region {} ({}):\n", - regionName, regionNodePos.toString() ) ); + string const errorMsg = GEOS_FMT( "Error while parsing region {} ({}):\n", + regionName, regionNodePos.toString() ); + ErrorLogger::global().currentErrorMsg() + .addToMsg( errorMsg ) + .addContextInfo( getDataContext().getContextInfo().setPriority( -1 ) ); + throw InputError( e, errorMsg ); } } }; diff --git a/src/coreComponents/mainInterface/initialization.cpp b/src/coreComponents/mainInterface/initialization.cpp index 814ad76e5f8..39367cbb263 100644 --- a/src/coreComponents/mainInterface/initialization.cpp +++ b/src/coreComponents/mainInterface/initialization.cpp @@ -105,6 +105,7 @@ std::unique_ptr< CommandLineOptions > parseCommandLineOptions( int argc, char * TRACE_DATA_MIGRATION, MEMORY_USAGE, PAUSE_FOR, + ERRORSOUTPUT, }; const option::Descriptor usage[] = @@ -128,6 +129,7 @@ std::unique_ptr< CommandLineOptions > parseCommandLineOptions( int argc, char * { TRACE_DATA_MIGRATION, 0, "", "trace-data-migration", Arg::None, "\t--trace-data-migration, \t Trace host-device data migration" }, { MEMORY_USAGE, 0, "m", "memory-usage", Arg::nonEmpty, "\t-m, --memory-usage, \t Minimum threshold for printing out memory allocations in a member of the data repository." }, { PAUSE_FOR, 0, "", "pause-for", Arg::numeric, "\t--pause-for, \t Pause geosx for a given number of seconds before starting execution" }, + { ERRORSOUTPUT, 0, "e", "errorsOutput", Arg::nonEmpty, "\t-e, --errors-output, \t Output path for the errors file (\".yaml\" supported)" }, { 0, 0, nullptr, nullptr, nullptr, nullptr } }; @@ -253,6 +255,17 @@ std::unique_ptr< CommandLineOptions > parseCommandLineOptions( int argc, char * std::this_thread::sleep_for( std::chrono::seconds( duration ) ); } break; + case ERRORSOUTPUT: + { + ErrorLogger::global().enableFileOutput( true ); + if( options[ERRORSOUTPUT].arg != nullptr ) + { + std::string_view filename = options[ERRORSOUTPUT].arg; + ErrorLogger::global().setOutputFilename( filename ); + } + ErrorLogger::global().createFile(); + } + break; } } diff --git a/src/coreComponents/mesh/CellElementRegion.cpp b/src/coreComponents/mesh/CellElementRegion.cpp index 4251a8679b3..fe669ed1864 100644 --- a/src/coreComponents/mesh/CellElementRegion.cpp +++ b/src/coreComponents/mesh/CellElementRegion.cpp @@ -52,7 +52,7 @@ void CellElementRegion::generateMesh( Group const & cellBlocks ) GEOS_THROW_IF( m_cellBlockNames.empty(), GEOS_FMT( "{}: No cellBlock selected in this region.", getDataContext() ), - InputError ); + InputError, getDataContext() ); Group & subRegions = this->getGroup( viewKeyStruct::elementSubRegions() ); for( string const & cbName : m_cellBlockNames ) { @@ -60,7 +60,7 @@ void CellElementRegion::generateMesh( Group const & cellBlocks ) GEOS_THROW_IF( cellBlock == nullptr, GEOS_FMT( "{}: No cellBlock named '{}' found.\nAvailable cellBlock list: {{ {} }}\nNo CellElementRegionSelector has been used to verify the cellBlock selection.", getDataContext(), cbName, stringutilities::join( m_cellBlockNames, ", " ) ), - InputError ); + InputError, getDataContext() ); // subRegion name must be the same as the cell-block (so we can match them and reference them in errors). CellElementSubRegion & subRegion = subRegions.registerGroup< CellElementSubRegion >( cbName ); diff --git a/src/coreComponents/mesh/CellElementRegionSelector.cpp b/src/coreComponents/mesh/CellElementRegionSelector.cpp index 6121006ba66..de70294a1ef 100644 --- a/src/coreComponents/mesh/CellElementRegionSelector.cpp +++ b/src/coreComponents/mesh/CellElementRegionSelector.cpp @@ -71,7 +71,7 @@ CellElementRegionSelector::getMatchingCellblocks( CellElementRegion const & regi []( auto pair ) { return pair->first; } ), stringutilities::joinLambda( m_cellBlocksOwners, ", ", []( auto pair ) { return pair->first; } ) ), - InputError ); + InputError, region.getWrapperDataContext( ViewKeys::sourceCellBlockNamesString() ) ); return matchedCellBlocks; } @@ -88,7 +88,7 @@ CellElementRegionSelector::verifyRequestedCellBlocks( CellElementRegion const & requestedCellBlockName, stringutilities::joinLambda( m_cellBlocksOwners, ", ", []( auto pair ) { return pair->first; } ) ), - InputError ); + InputError, region.getWrapperDataContext( ViewKeys::sourceCellBlockNamesString() ) ); } } diff --git a/src/coreComponents/mesh/ElementRegionManager.cpp b/src/coreComponents/mesh/ElementRegionManager.cpp index 0ba6bfc2b84..367d0bb2662 100644 --- a/src/coreComponents/mesh/ElementRegionManager.cpp +++ b/src/coreComponents/mesh/ElementRegionManager.cpp @@ -81,7 +81,8 @@ Group * ElementRegionManager::createChild( string const & childKey, string const { GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); GEOS_ERROR_IF( getUserAvailableKeys().count( childKey ) == 0, - CatalogInterface::unknownTypeError( childKey, getDataContext(), getUserAvailableKeys() ) ); + CatalogInterface::unknownTypeError( childKey, getDataContext(), getUserAvailableKeys() ), + getDataContext() ); Group & elementRegions = this->getGroup( ElementRegionManager::groupKeyStruct::elementRegionsGroup() ); return &elementRegions.registerGroup( childName, CatalogInterface::factory( childKey, getDataContext(), @@ -222,7 +223,8 @@ void ElementRegionManager::generateWells( CellBlockManagerABC const & cellBlockM GEOS_ERROR_IF( numWellElemsGlobal != lineBlock.numElements(), "Invalid partitioning in well " << lineBlock.getDataContext() << - ", subregion " << subRegion.getDataContext() ); + ", subregion " << subRegion.getDataContext(), + getDataContext() ); } ); @@ -783,10 +785,12 @@ ElementRegionManager::getCellBlockToSubRegionMap( CellBlockManagerABC const & ce localIndex const blockIndex = cellBlocks.getIndex( subRegion.getName() ); GEOS_ERROR_IF( blockIndex == Group::subGroupMap::KeyIndex::invalid_index, GEOS_FMT( "{}, subregion {}: Cell block not found at index {}.", - region.getDataContext().toString(), subRegion.getName(), blockIndex ) ); + region.getDataContext().toString(), subRegion.getName(), blockIndex ), + region.getDataContext() ); GEOS_ERROR_IF( blockMap( blockIndex, 1 ) != -1, GEOS_FMT( "{}, subregion {}: Cell block at index {} is mapped to more than one subregion.", - region.getDataContext().toString(), subRegion.getName(), blockIndex ) ); + region.getDataContext().toString(), subRegion.getName(), blockIndex ), + region.getDataContext() ); blockMap( blockIndex, 0 ) = er; blockMap( blockIndex, 1 ) = esr; diff --git a/src/coreComponents/mesh/ElementRegionManager.hpp b/src/coreComponents/mesh/ElementRegionManager.hpp index 26c705438dc..0058e862f63 100644 --- a/src/coreComponents/mesh/ElementRegionManager.hpp +++ b/src/coreComponents/mesh/ElementRegionManager.hpp @@ -1513,7 +1513,8 @@ ElementRegionManager::constructMaterialViewAccessor( string const & viewName, GEOS_ERROR_IF( !allowMissingViews, subRegion.getDataContext() << ": Material " << constitutiveRelation.getDataContext() << - " does not contain " << viewName ); + " does not contain " << viewName, + subRegion.getDataContext(), constitutiveRelation.getDataContext() ); } } ); } @@ -1561,7 +1562,8 @@ ElementRegionManager::constructMaterialViewAccessor( string const & viewName, else { GEOS_ERROR_IF( !allowMissingViews, region.getDataContext() << ": Material " << materialName - << " does not contain " << viewName ); + << " does not contain " << viewName, + region.getDataContext(), subRegion.getDataContext() ); } } ); } diff --git a/src/coreComponents/mesh/FaceManager.cpp b/src/coreComponents/mesh/FaceManager.cpp index 7584d082ea5..1cf388d34f4 100644 --- a/src/coreComponents/mesh/FaceManager.cpp +++ b/src/coreComponents/mesh/FaceManager.cpp @@ -298,6 +298,9 @@ void FaceManager::sortAllFaceNodes( NodeManager const & nodeManager, sortFaceNodes( X, elemCenter[er][esr][ei], facesToNodes[faceIndex] ); } catch( std::runtime_error const & e ) { + ErrorLogger::global().currentErrorMsg() + .addToMsg( getDataContext().toString() + ": " + e.what() ) + .addContextInfo( getDataContext().getContextInfo().setPriority( 1 ) ); throw std::runtime_error( getDataContext().toString() + ": " + e.what() ); } } ); @@ -308,7 +311,10 @@ void FaceManager::sortFaceNodes( arrayView2d< real64 const, nodes::REFERENCE_POS Span< localIndex > const faceNodes ) { localIndex const numFaceNodes = LvArray::integerConversion< localIndex >( faceNodes.size() ); - GEOS_THROW_IF_GT_MSG( numFaceNodes, MAX_FACE_NODES, "The number of maximum nodes allocated per cell face has been reached.", std::runtime_error ); + 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 ); localIndex const firstNodeIndex = faceNodes[0]; diff --git a/src/coreComponents/mesh/MeshObjectPath.cpp b/src/coreComponents/mesh/MeshObjectPath.cpp index 7d5da2c4f63..e5482d68ec5 100644 --- a/src/coreComponents/mesh/MeshObjectPath.cpp +++ b/src/coreComponents/mesh/MeshObjectPath.cpp @@ -213,7 +213,7 @@ void processTokenRecursive( dataRepository::Group const & parentGroup, GEOS_THROW_IF( namesInRepository.empty(), GEOS_FMT( "{0} has no children.", parentGroup.getDataContext().toString()), - InputError ); + InputError, parentGroup.getDataContext() ); for( string const & inputEntry : stringutilities::tokenize( pathToken, " " ) ) { @@ -238,7 +238,7 @@ void processTokenRecursive( dataRepository::Group const & parentGroup, parentGroup.getDataContext().toString(), inputEntry, stringutilities::join( namesInRepository, ", " ) ), - InputError ); + InputError, parentGroup.getDataContext() ); } } diff --git a/src/coreComponents/mesh/Perforation.cpp b/src/coreComponents/mesh/Perforation.cpp index ce2335ea766..f271a31ed47 100644 --- a/src/coreComponents/mesh/Perforation.cpp +++ b/src/coreComponents/mesh/Perforation.cpp @@ -75,7 +75,8 @@ void Perforation::postInputInitialization() { GEOS_ERROR_IF( m_distanceFromHead <= 0, getWrapperDataContext( viewKeyStruct::distanceFromHeadString() ) << - ": distance from well head to perforation cannot be negative." ); + ": distance from well head to perforation cannot be negative.", + getWrapperDataContext( viewKeyStruct::distanceFromHeadString() ) ); // Setup perforation status function FunctionManager & functionManager = FunctionManager::getInstance(); diff --git a/src/coreComponents/mesh/SurfaceElementRegion.hpp b/src/coreComponents/mesh/SurfaceElementRegion.hpp index 2958bd44280..313c983dc7d 100644 --- a/src/coreComponents/mesh/SurfaceElementRegion.hpp +++ b/src/coreComponents/mesh/SurfaceElementRegion.hpp @@ -212,7 +212,8 @@ class SurfaceElementRegion : public ElementRegionBase } ); GEOS_ERROR_IF( subRegionNames.size() != 1, "Surface region \"" << getDataContext() << - "\" should have one unique sub region (" << subRegionNames.size() << " found)." ); + "\" should have one unique sub region (" << subRegionNames.size() << " found).", + getDataContext() ); return subRegionNames.front(); } diff --git a/src/coreComponents/mesh/WellElementSubRegion.cpp b/src/coreComponents/mesh/WellElementSubRegion.cpp index 1b61cc7c507..b58343bdd12 100644 --- a/src/coreComponents/mesh/WellElementSubRegion.cpp +++ b/src/coreComponents/mesh/WellElementSubRegion.cpp @@ -511,7 +511,7 @@ void WellElementSubRegion::generate( MeshLevel & mesh, // TODO: split the well elements that contain multiple perforations, so that no element is shared GEOS_THROW_IF( sharedElems.size() > 0, "Well " << lineBlock.getDataContext() << " contains shared well elements", - InputError ); + InputError, lineBlock.getDataContext() ); // In Steps 1 and 2 we determine the local objects on this rank (elems and nodes) // Once this is done, in Steps 3, 4, and 5, we update the nodeManager and wellElementSubRegion (size, maps) @@ -664,7 +664,7 @@ void WellElementSubRegion::checkPartitioningValidity( LineBlockABC const & lineB " The main reason for this error is that there may be no perforation" << " in the bottom well element of the well, which is required to have" << " a well-posed problem.", - InputError ); + InputError, lineBlock.getDataContext() ); if( elemStatusGlobal[prevGlobal] == WellElemParallelStatus::LOCAL ) { diff --git a/src/coreComponents/mesh/generators/CellBlockManager.cpp b/src/coreComponents/mesh/generators/CellBlockManager.cpp index 2c7be094170..7506e96b77e 100644 --- a/src/coreComponents/mesh/generators/CellBlockManager.cpp +++ b/src/coreComponents/mesh/generators/CellBlockManager.cpp @@ -211,11 +211,11 @@ struct NodesAndElementOfFace { NodesAndElementOfFace( localIndex const duplicateFaceNodesIdx, localIndex const cellIdx, - localIndex const blockIdx, + localIndex const blockId, localIndex const faceNum ): duplicateFaceNodesIndex( duplicateFaceNodesIdx ), cellIndex( cellIdx ), - blockIndex( blockIdx ), + blockIndex( blockId ), faceNumber( faceNum ) {} diff --git a/src/coreComponents/mesh/generators/ExternalMeshGeneratorBase.cpp b/src/coreComponents/mesh/generators/ExternalMeshGeneratorBase.cpp index 89bfc6cbc83..cb6c351cf7e 100644 --- a/src/coreComponents/mesh/generators/ExternalMeshGeneratorBase.cpp +++ b/src/coreComponents/mesh/generators/ExternalMeshGeneratorBase.cpp @@ -82,7 +82,7 @@ void ExternalMeshGeneratorBase::postInputInitialization() GEOS_THROW_IF( hasDuplicates, getWrapperDataContext( key ) << ": '" << stringutilities::join( v, ", " ) << "' already present in list of fields to import.", - InputError ); + InputError, getWrapperDataContext( key ) ); }; checkDuplicates( m_volumicFieldsInGEOS, viewKeyStruct::volumicFieldsInGEOSString() ); checkDuplicates( m_surfacicFieldsInGEOS, viewKeyStruct::surfacicFieldsInGEOSString() ); diff --git a/src/coreComponents/mesh/generators/InternalMeshGenerator.cpp b/src/coreComponents/mesh/generators/InternalMeshGenerator.cpp index 5070d7d33c5..0eac2831c21 100644 --- a/src/coreComponents/mesh/generators/InternalMeshGenerator.cpp +++ b/src/coreComponents/mesh/generators/InternalMeshGenerator.cpp @@ -183,8 +183,12 @@ void InternalMeshGenerator::postInputInitialization() } catch( InputError const & e ) { WrapperBase const & wrapper = getWrapperBase( viewKeyStruct::elementTypesString() ); - throw InputError( e, "InternalMesh " + wrapper.getDataContext().toString() + - ", element index = " + std::to_string( i ) + ": " ); + std::string const msg = GEOS_FMT( "InternalMesh {}, element index = {}: ", + wrapper.getDataContext().toString(), std::to_string( i ) ); + ErrorLogger::global().currentErrorMsg() + .addToMsg( msg ) + .addContextInfo( wrapper.getDataContext().getContextInfo().setPriority( 2 ) ); + throw InputError( e, msg ); } } diff --git a/src/coreComponents/mesh/generators/InternalMeshGenerator.hpp b/src/coreComponents/mesh/generators/InternalMeshGenerator.hpp index bf7d893160f..7b38c4d3ed7 100644 --- a/src/coreComponents/mesh/generators/InternalMeshGenerator.hpp +++ b/src/coreComponents/mesh/generators/InternalMeshGenerator.hpp @@ -346,11 +346,14 @@ class InternalMeshGenerator : public MeshGeneratorBase // Verify that the bias is non-zero and applied to more than one block: if( ( !isZero( m_nElemBias[i][block] ) ) && (m_nElems[i][block]>1)) { + dataRepository::DataContext const & wrapperContext = + getWrapperDataContext( i == 0 ? viewKeyStruct::xBiasString() : + i == 1 ? viewKeyStruct::yBiasString() : + viewKeyStruct::zBiasString() ); GEOS_ERROR_IF( fabs( m_nElemBias[i][block] ) >= 1, - getWrapperDataContext( i == 0 ? viewKeyStruct::xBiasString() : - i == 1 ? viewKeyStruct::yBiasString() : - viewKeyStruct::zBiasString() ) << - ", block index = " << block << " : Mesh bias must between -1 and 1!" ); + wrapperContext << + ", block index = " << block << " : Mesh bias must between -1 and 1!", + wrapperContext ); real64 len = max - min; real64 xmean = len / m_nElems[i][block]; diff --git a/src/coreComponents/mesh/generators/InternalWellGenerator.cpp b/src/coreComponents/mesh/generators/InternalWellGenerator.cpp index 88a36aebeff..f219d359e9a 100644 --- a/src/coreComponents/mesh/generators/InternalWellGenerator.cpp +++ b/src/coreComponents/mesh/generators/InternalWellGenerator.cpp @@ -43,17 +43,17 @@ void InternalWellGenerator::postInputInitialization() GEOS_THROW_IF( m_polyNodeCoords.size( 1 ) != m_nDims, "InternalWell " << getWrapperDataContext( viewKeyStruct::polylineNodeCoordsString() ) << ": Invalid number of physical coordinates.", - InputError ); + InputError, getWrapperDataContext( viewKeyStruct::polylineNodeCoordsString() ) ); GEOS_THROW_IF( m_segmentToPolyNodeMap.size( 1 ) != 2, "InternalWell " << getWrapperDataContext( viewKeyStruct::polylineSegmentConnString() ) << ": Invalid size.", - InputError ); + InputError, getWrapperDataContext( viewKeyStruct::polylineSegmentConnString() ) ); GEOS_THROW_IF( m_polyNodeCoords.size( 0 )-1 != m_segmentToPolyNodeMap.size( 0 ), "Incompatible sizes of " << getWrapperDataContext( viewKeyStruct::polylineNodeCoordsString() ) << " and " << getWrapperDataContext( viewKeyStruct::polylineSegmentConnString() ), - InputError ); + InputError, getWrapperDataContext( viewKeyStruct::polylineSegmentConnString() ) ); // TODO: add more checks here // TODO: check that the connectivity of the well is valid diff --git a/src/coreComponents/mesh/generators/InternalWellboreGenerator.cpp b/src/coreComponents/mesh/generators/InternalWellboreGenerator.cpp index c48385b9de7..e14a593c018 100644 --- a/src/coreComponents/mesh/generators/InternalWellboreGenerator.cpp +++ b/src/coreComponents/mesh/generators/InternalWellboreGenerator.cpp @@ -117,18 +117,21 @@ void InternalWellboreGenerator::postInputInitialization() GEOS_ERROR_IF( m_nElems[1].size() > 1, getWrapperDataContext( viewKeyStruct::yElemsString() ) << - ": Only one block in the theta direction is currently supported. " ); + ": Only one block in the theta direction is currently supported. ", + getWrapperDataContext( viewKeyStruct::yElemsString() ) ); GEOS_ERROR_IF( m_nElems[2].size() > 1, getWrapperDataContext( viewKeyStruct::yElemsString() ) << - ": Only one block in the z direction is currently supported. " ); + ": Only one block in the z direction is currently supported. ", + getWrapperDataContext( viewKeyStruct::yElemsString() ) ); GEOS_ERROR_IF( m_trajectory.size( 0 ) != 2 || m_trajectory.size( 1 ) != 3, getWrapperDataContext( viewKeyStruct::trajectoryString() ) << ": Input for trajectory should be specified in the form of " - "{ { xbottom, ybottom, zbottom }, { xtop, ytop, ztop } }." ); + "{ { xbottom, ybottom, zbottom }, { xtop, ytop, ztop } }.", + getWrapperDataContext( viewKeyStruct::trajectoryString() ) ); // Project trajectory to bottom and top of the wellbore real64 trajectoryVector[3] = {0}; diff --git a/src/coreComponents/mesh/generators/VTKMeshGenerator.cpp b/src/coreComponents/mesh/generators/VTKMeshGenerator.cpp index db8c899cd91..8f1d434ad45 100644 --- a/src/coreComponents/mesh/generators/VTKMeshGenerator.cpp +++ b/src/coreComponents/mesh/generators/VTKMeshGenerator.cpp @@ -102,13 +102,15 @@ void VTKMeshGenerator::postInputInitialization() ExternalMeshGeneratorBase::postInputInitialization(); GEOS_ERROR_IF( m_filePath.empty() && m_dataSourceName.empty(), - GEOS_FMT( "{}: Either {} or {} must be specified.", - getDataContext(), viewKeyStruct::filePathString(), viewKeyStruct::dataSourceString() ) ); + GEOS_FMT( "Either {} or {} must be specified.", + viewKeyStruct::filePathString(), viewKeyStruct::dataSourceString() ), + getDataContext() ); GEOS_ERROR_IF( !m_filePath.empty() && !m_dataSourceName.empty(), - GEOS_FMT( "{}: Access to the mesh via file and data source are mutually exclusive. " + GEOS_FMT( "Access to the mesh via file and data source are mutually exclusive. " "You can't set both {} and {} at the same time.", - getDataContext(), viewKeyStruct::filePathString(), viewKeyStruct::dataSourceString() ) ); + viewKeyStruct::filePathString(), viewKeyStruct::dataSourceString() ), + getDataContext() ); if( !m_dataSourceName.empty()) { @@ -118,7 +120,7 @@ void VTKMeshGenerator::postInputInitialization() GEOS_THROW_IF( m_dataSource == nullptr, getDataContext() << ": VTK Data Object Source not found: " << m_dataSourceName, - InputError ); + InputError, getDataContext() ); m_dataSource->open(); } diff --git a/src/coreComponents/mesh/generators/VTKUtilities.cpp b/src/coreComponents/mesh/generators/VTKUtilities.cpp index b49e30e857a..92f96d34a3c 100644 --- a/src/coreComponents/mesh/generators/VTKUtilities.cpp +++ b/src/coreComponents/mesh/generators/VTKUtilities.cpp @@ -75,6 +75,7 @@ #endif #include +#include namespace geos @@ -928,8 +929,11 @@ redistributeByAreaGraphAndLayer( AllMeshes & input, minA = idxLimits[0].first]( localIndex const i ) { auto const aidx = index.Get( i, 0 ); - GEOS_ASSERT_GE( aidx, 0 ); + GEOS_ASSERT_GT( std::numeric_limits< int32_t >::max(), dst[i] ); + if constexpr ( std::is_signed_v< decltype(aidx) > ) + GEOS_ASSERT_GE( aidx, 0 ); + dst[i] |= static_cast< int64_t >( aidx - minA ) << 32; } ); } ); diff --git a/src/coreComponents/mesh/generators/WellGeneratorBase.cpp b/src/coreComponents/mesh/generators/WellGeneratorBase.cpp index c92967ed8dc..f55ba78049d 100644 --- a/src/coreComponents/mesh/generators/WellGeneratorBase.cpp +++ b/src/coreComponents/mesh/generators/WellGeneratorBase.cpp @@ -80,7 +80,8 @@ Group * WellGeneratorBase::createChild( string const & childKey, string const & GEOS_LOG_RANK_0( GEOS_FMT( "{}: adding {} {}", getName(), childKey, childName ) ); const auto childTypes = { viewKeyStruct::perforationString() }; GEOS_ERROR_IF( childKey != viewKeyStruct::perforationString(), - CatalogInterface::unknownTypeError( childKey, getDataContext(), childTypes ) ); + CatalogInterface::unknownTypeError( childKey, getDataContext(), childTypes ), + getDataContext() ); ++m_numPerforations; m_perforationList.emplace_back( childName ); diff --git a/src/coreComponents/mesh/simpleGeometricObjects/Box.cpp b/src/coreComponents/mesh/simpleGeometricObjects/Box.cpp index 4bcc6918245..172f529ed59 100644 --- a/src/coreComponents/mesh/simpleGeometricObjects/Box.cpp +++ b/src/coreComponents/mesh/simpleGeometricObjects/Box.cpp @@ -78,7 +78,8 @@ void Box::postInputInitialization() { GEOS_ERROR_IF( (m_max[0]-m_min[0]) < (m_max[1]-m_min[1]), getDataContext() << ": When a strike angle is specified, the box is supposed to" << - " represent a plane normal to the y direction. This box seems to be too thick." ); + " represent a plane normal to the y direction. This box seems to be too thick.", + getDataContext() ); m_cosStrike = std::cos( m_strikeAngle / 180 *M_PI ); m_sinStrike = std::sin( m_strikeAngle / 180 *M_PI ); diff --git a/src/coreComponents/mesh/simpleGeometricObjects/ThickPlane.cpp b/src/coreComponents/mesh/simpleGeometricObjects/ThickPlane.cpp index 251e0e09477..4b04b18fd61 100644 --- a/src/coreComponents/mesh/simpleGeometricObjects/ThickPlane.cpp +++ b/src/coreComponents/mesh/simpleGeometricObjects/ThickPlane.cpp @@ -50,11 +50,13 @@ void ThickPlane::postInputInitialization() m_thickness *= 0.5; // actually store the half-thickness GEOS_ERROR_IF( m_thickness <= 0, - getDataContext() << ": The plane appears to have zero or negative thickness" ); + getDataContext() << ": The plane appears to have zero or negative thickness", + getDataContext() ); LvArray::tensorOps::normalize< 3 >( m_normal ); GEOS_ERROR_IF( std::fabs( LvArray::tensorOps::l2Norm< 3 >( m_normal ) - 1.0 ) > 1e-15, - getDataContext() << ": Could not properly normalize input normal." ); + getDataContext() << ": Could not properly normalize input normal.", + getDataContext() ); } diff --git a/src/coreComponents/physicsSolvers/FieldStatisticsBase.hpp b/src/coreComponents/physicsSolvers/FieldStatisticsBase.hpp index c67eed1c217..af9efb7fefa 100644 --- a/src/coreComponents/physicsSolvers/FieldStatisticsBase.hpp +++ b/src/coreComponents/physicsSolvers/FieldStatisticsBase.hpp @@ -90,7 +90,7 @@ class FieldStatisticsBase : public TaskBase GEOS_FMT( "{}: Could not find solver '{}' of type {}", getDataContext(), m_solverName, LvArray::system::demangleType< SOLVER >() ), - InputError ); + InputError, getDataContext() ); // create dir for output if( m_writeCSV > 0 ) diff --git a/src/coreComponents/physicsSolvers/LinearSolverParameters.cpp b/src/coreComponents/physicsSolvers/LinearSolverParameters.cpp index 1c8157ef574..cca018cabe3 100644 --- a/src/coreComponents/physicsSolvers/LinearSolverParameters.cpp +++ b/src/coreComponents/physicsSolvers/LinearSolverParameters.cpp @@ -817,22 +817,28 @@ void LinearSolverParametersInput::postInputInitialization() GEOS_ERROR_IF( binaryOptions.count( m_parameters.stopIfError ) == 0, getWrapperDataContext( viewKeyStruct::stopIfErrorString() ) << - ": option can be either 0 (false) or 1 (true)" ); + ": option can be either 0 (false) or 1 (true)", + getWrapperDataContext( viewKeyStruct::stopIfErrorString() ) ); GEOS_ERROR_IF( binaryOptions.count( m_parameters.direct.checkResidual ) == 0, getWrapperDataContext( viewKeyStruct::directCheckResidualString() ) << - ": option can be either 0 (false) or 1 (true)" ); + ": option can be either 0 (false) or 1 (true)", + getWrapperDataContext( viewKeyStruct::directCheckResidualString() ) ); GEOS_ERROR_IF( binaryOptions.count( m_parameters.direct.equilibrate ) == 0, getWrapperDataContext( viewKeyStruct::directEquilString() ) << - ": option can be either 0 (false) or 1 (true)" ); + ": option can be either 0 (false) or 1 (true)", + getWrapperDataContext( viewKeyStruct::directEquilString() ) ); GEOS_ERROR_IF( binaryOptions.count( m_parameters.direct.replaceTinyPivot ) == 0, getWrapperDataContext( viewKeyStruct::directReplTinyPivotString() ) << - ": option can be either 0 (false) or 1 (true)" ); + ": option can be either 0 (false) or 1 (true)", + getWrapperDataContext( viewKeyStruct::directReplTinyPivotString() ) ); GEOS_ERROR_IF( binaryOptions.count( m_parameters.direct.iterativeRefine ) == 0, getWrapperDataContext( viewKeyStruct::directIterRefString() ) << - ": option can be either 0 (false) or 1 (true)" ); + ": option can be either 0 (false) or 1 (true)", + getWrapperDataContext( viewKeyStruct::directIterRefString() ) ); GEOS_ERROR_IF( binaryOptions.count( m_parameters.direct.parallel ) == 0, getWrapperDataContext( viewKeyStruct::directParallelString() ) << - ": option can be either 0 (false) or 1 (true)" ); + ": option can be either 0 (false) or 1 (true)", + getWrapperDataContext( viewKeyStruct::directParallelString() ) ); GEOS_ERROR_IF_LT_MSG( m_parameters.krylov.maxIterations, 0, getWrapperDataContext( viewKeyStruct::krylovMaxIterString() ) << diff --git a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp index 7448c5ec46d..8d301476cc5 100644 --- a/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/PhysicsSolverBase.cpp @@ -16,6 +16,7 @@ #include "PhysicsSolverBase.hpp" #include "PhysicsSolverManager.hpp" +#include "common/MpiWrapper.hpp" #include "codingUtilities/RTTypes.hpp" #include "common/format/EnumStrings.hpp" #include "dataRepository/Group.hpp" @@ -166,7 +167,8 @@ void PhysicsSolverBase::generateMeshTargetsFromTargetRegions( Group const & mesh { GEOS_ERROR_IF( meshBodies.numSubGroups() != 1, getDataContext() << ": No MeshBody information is specified in" << - " PhysicsSolverBase::meshTargets, but there are multiple MeshBody objects" ); + " PhysicsSolverBase::meshTargets, but there are multiple MeshBody objects", + getDataContext() ); MeshBody const & meshBody = meshBodies.getGroup< MeshBody >( 0 ); string const meshBodyName = meshBody.getName(); @@ -181,7 +183,8 @@ void PhysicsSolverBase::generateMeshTargetsFromTargetRegions( Group const & mesh string const meshBodyName = targetTokens[0]; GEOS_ERROR_IF( !meshBodies.hasGroup( meshBodyName ), getWrapperDataContext( viewKeyStruct::targetRegionsString() ) << ": MeshBody (" << - meshBodyName << ") is specified in targetRegions, but does not exist." ); + meshBodyName << ") is specified in targetRegions, but does not exist.", + getWrapperDataContext( viewKeyStruct::targetRegionsString() ) ); string const meshLevelName = m_discretizationName; @@ -239,7 +242,7 @@ localIndex PhysicsSolverBase::targetRegionIndex( string const & regionName ) con auto const pos = std::find( m_targetRegionNames.begin(), m_targetRegionNames.end(), regionName ); GEOS_ERROR_IF( pos == m_targetRegionNames.end(), GEOS_FMT( "{}: Region {} is not a target of the solver.", - getDataContext(), regionName ) ); + getDataContext(), regionName ), getDataContext() ); return std::distance( m_targetRegionNames.begin(), pos ); } @@ -356,8 +359,10 @@ bool PhysicsSolverBase::execute( real64 const time_n, getName(), subStep, dtAccepted, nextDt, dtRemaining ) ); } } - GEOS_ERROR_IF( dtRemaining > 0.0, getDataContext() << ": Maximum allowed number of sub-steps" - " reached. Consider increasing maxSubSteps." ); + GEOS_ERROR_IF( dtRemaining > 0.0, + getDataContext() << ": Maximum allowed number of sub-steps" + " reached. Consider increasing maxSubSteps.", + getDataContext() ); // Decide what to do with the next Dt for the event running the solver. m_nextDt = setNextDt( time_n + dt, nextDt, domain ); @@ -764,7 +769,7 @@ bool PhysicsSolverBase::lineSearchWithParabolicInterpolation( real64 const & tim applyBoundaryConditions( time_n, dt, domain, dofManager, localMatrix, localRhs ); rhs.close(); - if( logger::internal::rank==0 ) + if( MpiWrapper::commRank()==0 ) { GEOS_LOG_LEVEL_RANK_0( logInfo::LineSearch, GEOS_FMT( " Line search @ {:0.3f}: ", cumulativeScale ) ); @@ -1447,11 +1452,15 @@ void PhysicsSolverBase::solveLinearSystem( DofManager const & dofManager, if( params.stopIfError ) { - GEOS_ERROR_IF( m_linearSolverResult.breakdown(), getDataContext() << ": Linear solution breakdown -> simulation STOP" ); + GEOS_ERROR_IF( m_linearSolverResult.breakdown(), + getDataContext() << ": Linear solution breakdown -> simulation STOP", + getDataContext() ); } else { - GEOS_WARNING_IF( !m_linearSolverResult.success(), getDataContext() << ": Linear solution failed" ); + GEOS_WARNING_IF( !m_linearSolverResult.success(), + getDataContext() << ": Linear solution failed", + getDataContext() ); } // Unscale the solution vector if physics-based scaling was applied diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp index efd4c0e39fa..8089089777f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseBase.cpp @@ -614,11 +614,11 @@ void CompositionalMultiphaseBase::validateConstitutiveModels( DomainPartition co GEOS_THROW_IF( m_isThermal && !isFluidModelThermal, GEOS_FMT( "CompositionalMultiphaseBase {}: the thermal option is enabled in the solver, but the fluid model {} is incompatible with the thermal option", getDataContext(), fluid.getDataContext() ), - InputError ); + InputError, getDataContext(), fluid.getDataContext() ); GEOS_THROW_IF( !m_isThermal && isFluidModelThermal, GEOS_FMT( "CompositionalMultiphaseBase {}: the thermal option is enabled in fluid model {}, but the solver options are incompatible with the thermal option", getDataContext(), fluid.getDataContext() ), - InputError ); + InputError, getDataContext(), fluid.getDataContext() ); string const & relpermName = subRegion.getReference< string >( viewKeyStruct::relPermNamesString() ); RelativePermeabilityBase const & relPerm = getConstitutiveModel< RelativePermeabilityBase >( subRegion, relpermName ); @@ -1111,7 +1111,7 @@ void CompositionalMultiphaseBase::computeHydrostaticEquilibrium( DomainPartition "used in this simulation. To proceed, you can either: \n" << " - Use a gravityVector aligned with the z-axis, such as (0.0,0.0,-9.81)\n" << " - Remove the hydrostatic equilibrium initial condition from the XML file", - InputError ); + InputError, getDataContext(), bc.getDataContext() ); // ensure that the temperature and composition tables are defined GEOS_THROW_IF( bc.getTemperatureVsElevationTableName().empty(), @@ -1224,13 +1224,13 @@ void CompositionalMultiphaseBase::computeHydrostaticEquilibrium( DomainPartition GEOS_THROW_IF( fluid.componentNames().size() != componentNames.size(), "Mismatch in number of components between constitutive model " << fluid.getDataContext() << " and the Equilibrium initial condition " << fs.getDataContext(), - InputError ); + InputError, fluid.getDataContext(), fs.getDataContext() ); for( integer ic = 0; ic < fluid.numFluidComponents(); ++ic ) { GEOS_THROW_IF( fluid.componentNames()[ic] != componentNames[ic], "Mismatch in component names between constitutive model " << fluid.getDataContext() << " and the Equilibrium initial condition " << fs.getDataContext(), - InputError ); + InputError, fluid.getDataContext(), fs.getDataContext() ); } // Note: for now, we assume that the reservoir is in a single-phase state at initialization @@ -1239,7 +1239,7 @@ void CompositionalMultiphaseBase::computeHydrostaticEquilibrium( DomainPartition GEOS_THROW_IF( itPhaseNames == std::end( phaseNames ), getCatalogName() << " " << getDataContext() << ": phase name " << initPhaseName << " not found in the phases of " << fluid.getDataContext(), - InputError ); + InputError, getDataContext(), fluid.getDataContext() ); integer const ipInit = std::distance( std::begin( phaseNames ), itPhaseNames ); // Step 3.4: compute the hydrostatic pressure values @@ -1275,7 +1275,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 ); + std::runtime_error, getDataContext() ); GEOS_LOG_RANK_0_IF( returnValue == isothermalCompositionalMultiphaseBaseKernels::HydrostaticPressureKernel::ReturnType::DETECTED_MULTIPHASE_FLOW, getCatalogName() << " " << getDataContext() << @@ -1335,7 +1335,8 @@ void CompositionalMultiphaseBase::computeHydrostaticEquilibrium( DomainPartition GEOS_ERROR_IF( minPressure.get() < 0.0, GEOS_FMT( "{}: A negative pressure of {} Pa was found during hydrostatic initialization in region/subRegion {}/{}", - getDataContext(), minPressure.get(), region.getName(), subRegion.getName() ) ); + getDataContext(), minPressure.get(), region.getName(), subRegion.getName() ), + getDataContext() ); } ); } ); } @@ -1848,7 +1849,9 @@ void CompositionalMultiphaseBase::applyDirichletBC( real64 const time_n, if( m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) { bool const bcConsistent = validateDirichletBC( domain, time_n + dt ); - GEOS_ERROR_IF( !bcConsistent, GEOS_FMT( "CompositionalMultiphaseBase {}: inconsistent boundary conditions", getDataContext() ) ); + GEOS_ERROR_IF( !bcConsistent, + GEOS_FMT( "CompositionalMultiphaseBase {}: inconsistent boundary conditions", getDataContext() ), + getDataContext() ); } FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.cpp index 4f2f9fe43c1..f4a8d3c3ffd 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseFVM.cpp @@ -206,7 +206,9 @@ void CompositionalMultiphaseFVM::initializePreSubGroups() FluxApproximationBase const & fluxApprox = fvManager.getFluxApproximation( m_discretizationName ); GEOS_ERROR_IF( fluxApprox.upwindingParams().upwindingScheme == UpwindingScheme::HU2PH && m_numPhases != 2, GEOS_FMT( "{}: upwinding scheme {} only supports 2-phase flow", - getName(), EnumStrings< UpwindingScheme >::toString( UpwindingScheme::HU2PH ))); + getDataContext(), + EnumStrings< UpwindingScheme >::toString( UpwindingScheme::HU2PH )), + getDataContext() ); } void CompositionalMultiphaseFVM::setupDofs( DomainPartition const & domain, @@ -1264,7 +1266,9 @@ void CompositionalMultiphaseFVM::applyFaceDirichletBC( real64 const time_n, if( m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) { bool const bcConsistent = validateFaceDirichletBC( domain, time_n + dt ); - GEOS_ERROR_IF( !bcConsistent, GEOS_FMT( "{}: inconsistent boundary conditions", getDataContext() ) ); + GEOS_ERROR_IF( !bcConsistent, + GEOS_FMT( "{}: inconsistent boundary conditions", getDataContext() ), + getDataContext() ); } using namespace isothermalCompositionalMultiphaseFVMKernels; diff --git a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp index 11b4fead408..a022ad76443 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/CompositionalMultiphaseHybridFVM.cpp @@ -89,12 +89,12 @@ void CompositionalMultiphaseHybridFVM::initializePreSubGroups() GEOS_THROW_IF( !fvManager.hasGroup< HybridMimeticDiscretization >( m_discretizationName ), getCatalogName() << " " << getDataContext() << ": the HybridMimeticDiscretization must be selected with CompositionalMultiphaseHybridFVM", - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( m_hasCapPressure, getCatalogName() << " " << getDataContext() << ": capillary pressure is not yet supported by CompositionalMultiphaseHybridFVM", - InputError ); + InputError, getDataContext() ); } void CompositionalMultiphaseHybridFVM::initializePostInitialConditionsPreSubGroups() @@ -147,7 +147,7 @@ void CompositionalMultiphaseHybridFVM::initializePostInitialConditionsPreSubGrou GEOS_THROW_IF( minVal.get() <= 0.0, getCatalogName() << " " << getDataContext() << ": the transmissibility multipliers used in SinglePhaseHybridFVM must strictly larger than 0.0", - std::runtime_error ); + std::runtime_error, getDataContext() ); FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); fsManager.forSubGroups< AquiferBoundaryCondition >( [&] ( AquiferBoundaryCondition const & bc ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/ReactiveCompositionalMultiphaseOBL.cpp b/src/coreComponents/physicsSolvers/fluidFlow/ReactiveCompositionalMultiphaseOBL.cpp index 345fe31f8fa..48f6b85b6af 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/ReactiveCompositionalMultiphaseOBL.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/ReactiveCompositionalMultiphaseOBL.cpp @@ -1068,7 +1068,9 @@ void ReactiveCompositionalMultiphaseOBL::applyDirichletBC( real64 const time, if( m_nonlinearSolverParameters.m_numNewtonIterations == 0 ) { bool const bcConsistent = validateDirichletBC( domain, time + dt ); - GEOS_ERROR_IF( !bcConsistent, GEOS_FMT( "CompositionalMultiphaseBase {}: inconsistent boundary conditions", getDataContext() ) ); + GEOS_ERROR_IF( !bcConsistent, + GEOS_FMT( "CompositionalMultiphaseBase {}: inconsistent boundary conditions", getDataContext() ), + getDataContext() ); } FieldSpecificationManager & fsManager = FieldSpecificationManager::getInstance(); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseBase.cpp index d57772ffe81..6fca54281ae 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseBase.cpp @@ -165,11 +165,11 @@ void SinglePhaseBase::validateConstitutiveModels( DomainPartition & domain ) con GEOS_THROW_IF( m_isThermal && (fluidModelName != "ThermalCompressibleSinglePhaseFluid"), GEOS_FMT( "SingleFluidBase {}: the thermal option is enabled in the solver, but the fluid model {} is not for thermal fluid", getDataContext(), fluid.getDataContext() ), - InputError ); + InputError, getDataContext(), fluid.getDataContext() ); GEOS_THROW_IF( !m_isThermal && (fluidModelName == "ThermalCompressibleSinglePhaseFluid"), GEOS_FMT( "SingleFluidBase {}: the fluid model is for thermal fluid {}, but the solver option is incompatible with the fluid model", getDataContext(), fluid.getDataContext() ), - InputError ); + InputError, getDataContext(), fluid.getDataContext() ); } ); } ); } ); @@ -421,27 +421,27 @@ void SinglePhaseBase::computeHydrostaticEquilibrium( DomainPartition & domain ) "used in this simulation. To proceed, you can either: \n" << " - Use a gravityVector aligned with the z-axis, such as (0.0,0.0,-9.81)\n" << " - Remove the hydrostatic equilibrium initial condition from the XML file", - InputError ); + InputError, getDataContext(), bc.getDataContext() ); // ensure that the temperature tables are defined for thermal simulations GEOS_THROW_IF( m_isThermal && bc.getTemperatureVsElevationTableName().empty(), getCatalogName() << " " << bc.getDataContext() << ": " << EquilibriumInitialCondition::viewKeyStruct::temperatureVsElevationTableNameString() << " must be provided for a thermal simulation", - InputError ); + InputError, getDataContext(), bc.getDataContext() ); //ensure that compositions are empty GEOS_THROW_IF( !bc.getComponentFractionVsElevationTableNames().empty(), getCatalogName() << " " << bc.getDataContext() << ": " << EquilibriumInitialCondition::viewKeyStruct::componentFractionVsElevationTableNamesString() << " must not be provided for a single phase simulation.", - InputError ); + InputError, getDataContext(), bc.getDataContext() ); GEOS_THROW_IF( !bc.getComponentNames().empty(), getCatalogName() << " " << bc.getDataContext() << ": " << EquilibriumInitialCondition::viewKeyStruct::componentNamesString() << " must not be provided for a single phase simulation.", - InputError ); + InputError, getDataContext(), bc.getDataContext() ); } ); if( equilCounter == 0 ) @@ -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 ); + std::runtime_error, 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 4b28b4a2780..5ae213a31b2 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseHybridFVM.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/SinglePhaseHybridFVM.cpp @@ -96,7 +96,7 @@ void SinglePhaseHybridFVM::initializePreSubGroups() GEOS_THROW_IF( m_isThermal, GEOS_FMT( "{} {}: The thermal option is not supported by SinglePhaseHybridFVM", getCatalogName(), getDataContext().toString() ), - InputError ); + InputError, getDataContext() ); DomainPartition & domain = this->getGroupByPath< DomainPartition >( "/Problem/domain" ); NumericalMethodsManager const & numericalMethodManager = domain.getNumericalMethodManager(); @@ -105,7 +105,7 @@ void SinglePhaseHybridFVM::initializePreSubGroups() GEOS_THROW_IF( !fvManager.hasGroup< HybridMimeticDiscretization >( m_discretizationName ), getCatalogName() << " " << getDataContext() << ": the HybridMimeticDiscretization must be selected with SinglePhaseHybridFVM", - InputError ); + InputError, getDataContext() ); } void SinglePhaseHybridFVM::initializePostInitialConditionsPreSubGroups() diff --git a/src/coreComponents/physicsSolvers/fluidFlow/SourceFluxStatistics.cpp b/src/coreComponents/physicsSolvers/fluidFlow/SourceFluxStatistics.cpp index 1391b40e51f..e454f54030d 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/SourceFluxStatistics.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/SourceFluxStatistics.cpp @@ -60,7 +60,8 @@ void SourceFluxStatsAggregator::postInputInitialization() GEOS_WARNING_IF( m_fluxNames.empty(), GEOS_FMT( "{}: No {} was found in {}.", getDataContext(), SourceFluxBoundaryCondition::catalogName(), - fsManager.getDataContext() ) ); + fsManager.getDataContext() ), + getDataContext(), fsManager.getDataContext() ); } else { @@ -69,7 +70,7 @@ void SourceFluxStatsAggregator::postInputInitialization() GEOS_ERROR_IF( !fsManager.hasGroup< SourceFluxBoundaryCondition >( fluxName ), GEOS_FMT( "{}: No {} named {} was found in {}.", getDataContext(), SourceFluxBoundaryCondition::catalogName(), - fluxName, fsManager.getDataContext() ) ); + fluxName, fsManager.getDataContext() ), getDataContext() ); } } @@ -146,7 +147,7 @@ void SourceFluxStatsAggregator::gatherStatsForLog( bool logLevelActive, TableData & tableData, WrappedStats const & wrappedStats ) { - if( logLevelActive && logger::internal::rank == 0 ) + if( logLevelActive && MpiWrapper::commRank() == 0 ) { if( wrappedStats.stats().m_producedMass.size() == 1 ) { @@ -199,7 +200,7 @@ void SourceFluxStatsAggregator::outputStatsToLog( bool logLevelActive, string_view fluxesStr, TableData const & statsData ) { - if( logLevelActive && logger::internal::rank == 0 ) + if( logLevelActive && MpiWrapper::commRank() == 0 ) { string const title = GEOS_FMT( "{}, flux statistics for: {}", getName(), fluxesStr ); @@ -211,7 +212,7 @@ void SourceFluxStatsAggregator::outputStatsToLog( bool logLevelActive, } void SourceFluxStatsAggregator::outputStatsToCSV( TableData & csvData ) { - if( m_writeCSV > 0 && logger::internal::rank == 0 ) + if( m_writeCSV > 0 && MpiWrapper::commRank() == 0 ) { std::ofstream outputFile( m_csvFilename ); TableCSVFormatter const tableStatFormatter( m_csvLayout ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/StencilDataCollection.cpp b/src/coreComponents/physicsSolvers/fluidFlow/StencilDataCollection.cpp index 8f49e849e7e..5accd9a0def 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/StencilDataCollection.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/StencilDataCollection.cpp @@ -72,7 +72,7 @@ void StencilDataCollection::postInputInitialization() GEOS_FMT( "{}: Could not find flow solver named '{}'.", getDataContext(), m_solverName ), - InputError ); + InputError, getDataContext() ); } { // find mesh & discretization @@ -114,9 +114,11 @@ void StencilDataCollection::initializePostInitialConditionsPostSubGroups() ++supportedStencilCount; } ); GEOS_ERROR_IF( supportedStencilCount == 0, - GEOS_FMT( "{}: No compatible discretization was found.", getDataContext() ) ); + GEOS_FMT( "{}: No compatible discretization was found.", getDataContext() ), + getDataContext() ); GEOS_ERROR_IF( supportedStencilCount > 1, - GEOS_FMT( "{}: Multiple discretization was found.", getDataContext() ) ); + GEOS_FMT( "{}: Multiple discretization was found.", getDataContext() ), + getDataContext() ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/proppantTransport/ProppantTransport.cpp b/src/coreComponents/physicsSolvers/fluidFlow/proppantTransport/ProppantTransport.cpp index e44833d58aa..98f54f20a2f 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/proppantTransport/ProppantTransport.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/proppantTransport/ProppantTransport.cpp @@ -701,7 +701,8 @@ void ProppantTransport::applyBoundaryConditions( real64 const time_n, string const & subRegionName = subRegion.getName(); GEOS_ERROR_IF( bcStatusMap[subRegionName].count( setName ) > 0, - getDataContext() << ": Conflicting proppant boundary conditions on set " << setName ); + getDataContext() << ": Conflicting proppant boundary conditions on set " << setName, + getDataContext() ); bcStatusMap[subRegionName][setName].resize( m_numComponents ); bcStatusMap[subRegionName][setName].setValues< serialPolicy >( false ); @@ -721,9 +722,11 @@ void ProppantTransport::applyBoundaryConditions( real64 const time_n, localIndex const comp = fs.getComponent(); GEOS_ERROR_IF( bcStatusMap[subRegionName].count( setName ) == 0, - getDataContext() << ": Proppant boundary condition not prescribed on set '" << setName << "'" ); + getDataContext() << ": Proppant boundary condition not prescribed on set '" << setName << "'", + getDataContext() ); GEOS_ERROR_IF( bcStatusMap[subRegionName][setName][comp], - getDataContext() << ": Conflicting composition[" << comp << "] boundary conditions on set '" << setName << "'" ); + getDataContext() << ": Conflicting composition[" << comp << "] boundary conditions on set '" << setName << "'", + getDataContext() ); bcStatusMap[subRegionName][setName][comp] = true; fs.applyFieldValue< FieldSpecificationEqual >( targetSet, @@ -744,7 +747,7 @@ void ProppantTransport::applyBoundaryConditions( real64 const time_n, GEOS_WARNING_IF( !bcConsistent, getDataContext() << ": Composition boundary condition not applied to component " << ic << " on region '" << bcStatusEntryOuter.first << "'," << - " set '" << bcStatusEntryInner.first << "'" ); + " set '" << bcStatusEntryInner.first << "'", getDataContext() ); } } } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp index 14537f0d999..3b8184a1a38 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/CompositionalMultiphaseWell.cpp @@ -353,6 +353,9 @@ void CompositionalMultiphaseWell::validateWellControlsForFluid( WellControls con } catch( SimulationError const & ex ) { string const errorMsg = GEOS_FMT( "{}: wrong surface pressure / temperature.\n", getDataContext() ); + ErrorLogger::global().currentErrorMsg() + .addToMsg( errorMsg ) + .addContextInfo( getDataContext().getContextInfo().setPriority( 1 ) ); throw SimulationError( ex, errorMsg ); } } @@ -414,14 +417,14 @@ void CompositionalMultiphaseWell::validateInjectionStreams( WellElementSubRegion GEOS_THROW_IF( ( compFrac < 0.0 ) || ( compFrac > 1.0 ), "WellControls " << wellControls.getDataContext() << ": Invalid injection stream for well " << subRegion.getName(), - InputError ); + InputError, wellControls.getDataContext() ); compFracSum += compFrac; } GEOS_THROW_IF( ( compFracSum < 1.0 - std::numeric_limits< real64 >::epsilon() ) || ( compFracSum > 1.0 + std::numeric_limits< real64 >::epsilon() ), "WellControls " << wellControls.getDataContext() << ": Invalid injection stream for well " << subRegion.getName(), - InputError ); + InputError, wellControls.getDataContext() ); } } @@ -477,42 +480,42 @@ void CompositionalMultiphaseWell::validateWellConstraints( real64 const & time_n GEOS_THROW_IF( wellControls.isInjector() && currentControl == WellControls::Control::PHASEVOLRATE, "WellControls " << wellControls.getDataContext() << ": Phase rate control is not available for injectors", - InputError ); + InputError, wellControls.getDataContext() ); GEOS_THROW_IF( wellControls.isProducer() && currentControl == WellControls::Control::TOTALVOLRATE, "WellControls " << wellControls.getDataContext() << ": Total rate control is not available for producers", - InputError ); + InputError, wellControls.getDataContext() ); GEOS_THROW_IF( wellControls.isInjector() && targetTotalRate < 0.0, "WellControls " << wellControls.getDataContext() << ": Target total rate cannot be negative for injectors", - InputError ); + InputError, wellControls.getDataContext() ); GEOS_THROW_IF( wellControls.isInjector() && !isZero( targetPhaseRate ), "WellControls " << wellControls.getDataContext() << ": Target phase rate cannot be used for injectors", - InputError ); + InputError, wellControls.getDataContext() ); GEOS_THROW_IF( wellControls.isProducer() && !isZero( targetTotalRate ), "WellControls " << wellControls.getDataContext() << ": Target total rate cannot be used for producers", - InputError ); + InputError, wellControls.getDataContext() ); GEOS_THROW_IF( wellControls.isProducer() && !isZero( targetMassRate ), "WellControls " << wellControls.getDataContext() << ": Target mass rate cannot be used for producers", - InputError ); + InputError, wellControls.getDataContext() ); GEOS_THROW_IF( !m_useMass && !isZero( targetMassRate ), "WellControls " << wellControls.getDataContext() << ": Target mass rate cannot with useMass=0", - InputError ); + InputError, wellControls.getDataContext() ); // The user always provides positive rates, but these rates are later multiplied by -1 internally for producers GEOS_THROW_IF( wellControls.isProducer() && targetPhaseRate > 0.0, "WellControls " << wellControls.getDataContext() << ": Target phase rate cannot be negative for producers", - InputError ); + InputError, wellControls.getDataContext() ); GEOS_THROW_IF( wellControls.isProducer() && !isZero( targetTotalRate ), "WellControls " << wellControls.getDataContext() << ": Target total rate cannot be used for producers", - InputError ); + InputError, wellControls.getDataContext() ); // Find target phase index for phase rate constraint for( integer ip = 0; ip < fluid.numFluidPhases(); ++ip ) @@ -525,7 +528,7 @@ void CompositionalMultiphaseWell::validateWellConstraints( real64 const & time_n GEOS_THROW_IF( wellControls.isProducer() && m_targetPhaseIndex == -1, "WellControls " << wellControls.getDataContext() << ": Phase " << wellControls.getTargetPhaseName() << " not found for well control " << wellControls.getName(), - InputError ); + InputError, wellControls.getDataContext() ); } void CompositionalMultiphaseWell::initializePostSubGroups() diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp index 4d49a5062e4..ce588ad3d5c 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/SinglePhaseWell.cpp @@ -182,17 +182,17 @@ void SinglePhaseWell::validateWellConstraints( real64 const & time_n, GEOS_THROW_IF( currentControl == WellControls::Control::PHASEVOLRATE, "WellControls " << wellControls.getDataContext() << ": Phase rate control is not available for SinglePhaseWell", - InputError ); + InputError, wellControls.getDataContext() ); // The user always provides positive rates, but these rates are later multiplied by -1 internally for producers GEOS_THROW_IF( ( ( wellControls.isInjector() && targetTotalRate < 0.0 ) || ( wellControls.isProducer() && targetTotalRate > 0.0) ), "WellControls " << wellControls.getDataContext() << ": Target total rate cannot be negative", - InputError ); + InputError, wellControls.getDataContext() ); GEOS_THROW_IF( !isZero( targetPhaseRate ), "WellControls " << wellControls.getDataContext() << ": Target phase rate cannot be used for SinglePhaseWell", - InputError ); + InputError, wellControls.getDataContext() ); } void SinglePhaseWell::updateBHPForConstraint( WellElementSubRegion & subRegion ) diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp index 15914dfb8a1..098d80beac0 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellControls.cpp @@ -242,7 +242,7 @@ void WellControls::postInputInitialization() GEOS_THROW_IF( m_inputControl == Control::UNINITIALIZED, getWrapperDataContext( viewKeyStruct::inputControlString() ) << ": Input well control cannot be uninitialized", - InputError ); + InputError, getWrapperDataContext( viewKeyStruct::inputControlString() ) ); if( m_currentControl == Control::UNINITIALIZED ) { @@ -253,27 +253,27 @@ void WellControls::postInputInitialization() GEOS_THROW_IF( m_targetBHP < 0, getWrapperDataContext( viewKeyStruct::targetBHPString() ) << ": Target bottom-hole pressure is negative", - InputError ); + InputError, getWrapperDataContext( viewKeyStruct::targetBHPString() ) ); // 1.b) check target rates GEOS_THROW_IF( m_targetTotalRate < 0, getWrapperDataContext( viewKeyStruct::targetTotalRateString() ) << ": Target rate is negative", - InputError ); + InputError, getWrapperDataContext( viewKeyStruct::targetTotalRateString() ) ); GEOS_THROW_IF( m_targetPhaseRate < 0, getWrapperDataContext( viewKeyStruct::targetPhaseRateString() ) << ": Target oil rate is negative", - InputError ); + InputError, getWrapperDataContext( viewKeyStruct::targetPhaseRateString() ) ); GEOS_THROW_IF( m_targetMassRate < 0, getWrapperDataContext( viewKeyStruct::targetMassRateString() ) << ": Target mass rate is negative", - InputError ); + InputError, getWrapperDataContext( viewKeyStruct::targetMassRateString() ) ); GEOS_THROW_IF( (m_injectionStream.empty() && m_injectionTemperature >= 0) || (!m_injectionStream.empty() && m_injectionTemperature < 0), "WellControls " << getDataContext() << ": Both " << viewKeyStruct::injectionStreamString() << " and " << viewKeyStruct::injectionTemperatureString() << " must be specified for multiphase simulations", - InputError ); + InputError, getDataContext() ); // 1.c) Set the multiplier for the rates if( isProducer() ) @@ -292,18 +292,19 @@ void WellControls::postInputInitialization() for( localIndex ic = 0; ic < m_injectionStream.size(); ++ic ) { GEOS_ERROR_IF( m_injectionStream[ic] < 0.0 || m_injectionStream[ic] > 1.0, - getWrapperDataContext( viewKeyStruct::injectionStreamString() ) << ": Invalid injection stream" ); + getWrapperDataContext( viewKeyStruct::injectionStreamString() ) << ": Invalid injection stream", + getWrapperDataContext( viewKeyStruct::injectionStreamString() ) ); sum += m_injectionStream[ic]; } GEOS_THROW_IF( LvArray::math::abs( 1.0 - sum ) > std::numeric_limits< real64 >::epsilon(), getWrapperDataContext( viewKeyStruct::injectionStreamString() ) << ": Invalid injection stream", - InputError ); + InputError, getWrapperDataContext( viewKeyStruct::injectionStreamString() ) ); } // 3) check the flag for surface / reservoir conditions GEOS_THROW_IF( m_useSurfaceConditions != 0 && m_useSurfaceConditions != 1, getWrapperDataContext( viewKeyStruct::useSurfaceConditionsString() ) << ": The flag to select surface/reservoir conditions must be equal to 0 or 1", - InputError ); + InputError, getWrapperDataContext( viewKeyStruct::useSurfaceConditionsString() ) ); // 4) check that at least one rate constraint has been defined GEOS_THROW_IF( ((m_targetPhaseRate <= 0.0 && m_targetPhaseRateTableName.empty()) && @@ -319,32 +320,32 @@ void WellControls::postInputInitialization() "The mass rate constraint can be specified using " << "either " << viewKeyStruct::targetMassRateString() << " or " << viewKeyStruct::targetMassRateTableNameString(), - InputError ); + InputError, getDataContext() ); // 5) check whether redundant information has been provided GEOS_THROW_IF( ((m_targetPhaseRate > 0.0 && !m_targetPhaseRateTableName.empty())), "WellControls " << getDataContext() << ": You have provided redundant information for well phase rate." << " The keywords " << viewKeyStruct::targetPhaseRateString() << " and " << viewKeyStruct::targetPhaseRateTableNameString() << " cannot be specified together", - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( ((m_targetTotalRate > 0.0 && !m_targetTotalRateTableName.empty())), "WellControls " << getDataContext() << ": You have provided redundant information for well total rate." << " The keywords " << viewKeyStruct::targetTotalRateString() << " and " << viewKeyStruct::targetTotalRateTableNameString() << " cannot be specified together", - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( ((m_targetBHP > 0.0 && !m_targetBHPTableName.empty())), "WellControls " << getDataContext() << ": You have provided redundant information for well BHP." << " The keywords " << viewKeyStruct::targetBHPString() << " and " << viewKeyStruct::targetBHPTableNameString() << " cannot be specified together", - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( ((m_targetMassRate > 0.0 && !m_targetMassRateTableName.empty())), "WellControls " << getDataContext() << ": You have provided redundant information for well mass rate." << " The keywords " << viewKeyStruct::targetMassRateString() << " and " << viewKeyStruct::targetMassRateTableNameString() << " cannot be specified together", - InputError ); + InputError, getDataContext() ); GEOS_THROW_IF( ((m_targetMassRate > 0.0 && m_useSurfaceConditions==0)), "WellControls " << getDataContext() << ": Option only valid if useSurfaceConditions set to 1", - InputError ); + InputError, getDataContext() ); // 6.1) If the well is under BHP control then the BHP must be specified. // Otherwise the BHP will be set to a default value. @@ -353,7 +354,7 @@ void WellControls::postInputInitialization() GEOS_THROW_IF( ((m_targetBHP <= 0.0 && m_targetBHPTableName.empty())), "WellControls " << getDataContext() << ": You have to provide well BHP by specifying either " << viewKeyStruct::targetBHPString() << " or " << viewKeyStruct::targetBHPTableNameString(), - InputError ); + InputError, getDataContext() ); } else if( m_targetBHP <= 0.0 && m_targetBHPTableName.empty() ) { @@ -368,19 +369,19 @@ void WellControls::postInputInitialization() GEOS_THROW_IF( (isInjector() && (m_inputControl == Control::PHASEVOLRATE)), "WellControls " << getDataContext() << ": You have to control an injector with " << EnumStrings< Control >::toString( Control::TOTALVOLRATE ), - InputError ); + InputError, getDataContext() ); // An injector must be controlled by TotalVolRate GEOS_THROW_IF( (isProducer() && (m_inputControl == Control::MASSRATE)), "WellControls " << getDataContext() << ": You have to control an injector with " << EnumStrings< Control >::toString( Control::MASSRATE ), - InputError ); + InputError, getDataContext() ); // 8) Make sure that the initial pressure coefficient is positive GEOS_THROW_IF( m_initialPressureCoefficient < 0, getWrapperDataContext( viewKeyStruct::initialPressureCoefficientString() ) << ": This tuning coefficient is negative", - InputError ); + InputError, getWrapperDataContext( viewKeyStruct::initialPressureCoefficientString() ) ); // 9) Create time-dependent BHP table @@ -397,7 +398,7 @@ void WellControls::postInputInitialization() GEOS_THROW_IF( m_targetBHPTable->getInterpolationMethod() != TableFunction::InterpolationType::Lower, "WellControls " << getDataContext() << ": The interpolation method for the time-dependent BHP table " << m_targetBHPTable->getName() << " should be TableFunction::InterpolationType::Lower", - InputError ); + InputError, getDataContext() ); } // 10) Create time-dependent total rate table @@ -414,7 +415,7 @@ void WellControls::postInputInitialization() GEOS_THROW_IF( m_targetTotalRateTable->getInterpolationMethod() != TableFunction::InterpolationType::Lower, "WellControls " << getDataContext() << ": The interpolation method for the time-dependent total rate table " << m_targetTotalRateTable->getName() << " should be TableFunction::InterpolationType::Lower", - InputError ); + InputError, getDataContext() ); } // 11) Create time-dependent phase rate table @@ -431,7 +432,7 @@ void WellControls::postInputInitialization() GEOS_THROW_IF( m_targetPhaseRateTable->getInterpolationMethod() != TableFunction::InterpolationType::Lower, "WellControls " << getDataContext() << ": The interpolation method for the time-dependent phase rate table " << m_targetPhaseRateTable->getName() << " should be TableFunction::InterpolationType::Lower", - InputError ); + InputError, getDataContext() ); } // Create time-dependent mass rate table if( m_targetMassRateTableName.empty() ) @@ -447,7 +448,7 @@ void WellControls::postInputInitialization() GEOS_THROW_IF( m_targetMassRateTable->getInterpolationMethod() != TableFunction::InterpolationType::Lower, "WellControls " << getDataContext() << ": The interpolation method for the time-dependent mass rate table " << m_targetMassRateTable->getName() << " should be TableFunction::InterpolationType::Lower", - InputError ); + InputError, getDataContext() ); } // 12) Create the time-dependent well status table if( m_statusTableName.empty()) @@ -469,7 +470,7 @@ void WellControls::postInputInitialization() GEOS_THROW_IF( m_statusTable->getInterpolationMethod() != TableFunction::InterpolationType::Lower, "WellControls " << getDataContext() << ": The interpolation method for the time-dependent status table " << m_statusTable->getName() << " should be TableFunction::InterpolationType::Lower", - InputError ); + InputError, getDataContext() ); } } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp index e470984d7cd..daeeffef3c1 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/WellSolverBase.cpp @@ -74,7 +74,8 @@ Group * WellSolverBase::createChild( string const & childKey, string const & chi PhysicsSolverBase::groupKeyStruct::nonlinearSolverParametersString(), }; GEOS_ERROR_IF( childTypes.count( childKey ) == 0, - CatalogInterface::unknownTypeError( childKey, getDataContext(), childTypes ) ); + CatalogInterface::unknownTypeError( childKey, getDataContext(), childTypes ), + getDataContext() ); if( childKey == keys::wellControls ) { return ®isterGroup< WellControls >( childName ); diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp index 039ae5c1813..ee04ffa8c73 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/CompositionalMultiphaseWellKernels.cpp @@ -681,13 +681,13 @@ PresTempCompFracInitializationKernel:: GEOS_THROW_IF( foundNegativePres.get() == 1, wellControls.getDataContext() << "Invalid well initialization, negative pressure was found.", - InputError ); + InputError, wellControls.getDataContext() ); GEOS_THROW_IF( foundNegativeTemp.get() == 1, wellControls.getDataContext() << "Invalid well initialization, negative temperature was found.", - InputError ); + InputError, wellControls.getDataContext() ); GEOS_THROW_IF( foundInconsistentCompFrac.get() == 1, wellControls.getDataContext() << "Invalid well initialization, inconsistent component fractions were found.", - InputError ); + InputError, wellControls.getDataContext() ); } diff --git a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.cpp b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.cpp index b0e87ffbc63..ddd707cf9b1 100644 --- a/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.cpp +++ b/src/coreComponents/physicsSolvers/fluidFlow/wells/kernels/SinglePhaseWellKernels.cpp @@ -580,12 +580,12 @@ PresTempInitializationKernel:: GEOS_THROW_IF( foundNegativePressure.get() == 1, wellControls.getDataContext() << ": Invalid well initialization, negative pressure was found.", - InputError ); + InputError, wellControls.getDataContext() ); if( isThermal ) // tjb change temp in isothermal cases shouldnt be an issue (also what if temp in fluid prop calcs like compo) { GEOS_THROW_IF( foundNegativeTemp.get() == 1, wellControls.getDataContext() << "Invalid well initialization, negative temperature was found.", - InputError ); + InputError, wellControls.getDataContext() ); } } diff --git a/src/coreComponents/physicsSolvers/inducedSeismicity/SpringSlider.cpp b/src/coreComponents/physicsSolvers/inducedSeismicity/SpringSlider.cpp index 801fb1afb6b..345a118ed74 100644 --- a/src/coreComponents/physicsSolvers/inducedSeismicity/SpringSlider.cpp +++ b/src/coreComponents/physicsSolvers/inducedSeismicity/SpringSlider.cpp @@ -89,8 +89,10 @@ void SpringSlider< RSSOLVER_TYPE >::registerDataOnMesh( Group & meshBodies ) string & frictionLawName = subRegion.getReference< string >( viewKeyStruct::frictionLawNameString() ); frictionLawName = PhysicsSolverBase::getConstitutiveName< FrictionBase >( subRegion ); - GEOS_ERROR_IF( frictionLawName.empty(), GEOS_FMT( "{}: FrictionBase model not found on subregion {}", - this->getDataContext(), subRegion.getDataContext() ) ); + GEOS_ERROR_IF( frictionLawName.empty(), + GEOS_FMT( "{}: FrictionBase model not found on subregion {}", + this->getDataContext(), subRegion.getDataContext() ), + this->getDataContext() ); } ); } ); } diff --git a/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp b/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp index b95f3493187..425bccfa72c 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp +++ b/src/coreComponents/physicsSolvers/multiphysics/CompositionalMultiphaseReservoirAndWells.cpp @@ -154,7 +154,7 @@ initializePreSubGroups() GEOS_FMT( "{}: the input flag {} must be the same in the flow and well solvers, respectively '{}' and '{}'", this->getDataContext(), CompositionalMultiphaseBase::viewKeyStruct::useMassFlagString(), Base::reservoirSolver()->getDataContext(), Base::wellSolver()->getDataContext() ), - InputError ); + InputError, this->getDataContext(), Base::reservoirSolver()->getDataContext(), Base::wellSolver()->getDataContext() ); bool const isThermalFlow = flowSolver->getReference< integer >( CompositionalMultiphaseBase::viewKeyStruct::isThermalString() ); bool const isThermalWell = Base::wellSolver()->template getReference< integer >( CompositionalMultiphaseWell::viewKeyStruct::isThermalString() ); @@ -162,7 +162,7 @@ initializePreSubGroups() GEOS_FMT( "{}: the input flag {} must be the same in the flow and well solvers, respectively '{}' and '{}'", this->getDataContext(), CompositionalMultiphaseBase::viewKeyStruct::isThermalString(), Base::reservoirSolver()->getDataContext(), Base::wellSolver()->getDataContext() ), - InputError ); + InputError, this->getDataContext(), Base::reservoirSolver()->getDataContext(), Base::wellSolver()->getDataContext() ); } template< typename RESERVOIR_SOLVER > diff --git a/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellsBase.cpp b/src/coreComponents/physicsSolvers/multiphysics/CoupledReservoirAndWellsBase.cpp index 0c01d00945c..fbb8e7fb935 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 ); + std::runtime_error, wellSolver->getDataContext() ); return hasBadPerforations == 0; } diff --git a/src/coreComponents/physicsSolvers/multiphysics/CoupledSolver.hpp b/src/coreComponents/physicsSolvers/multiphysics/CoupledSolver.hpp index bb485b2fade..c6da8277ae7 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/CoupledSolver.hpp +++ b/src/coreComponents/physicsSolvers/multiphysics/CoupledSolver.hpp @@ -734,7 +734,7 @@ class CoupledSolver : public PhysicsSolverBase EnumStrings< NonlinearSolverParameters::CouplingType >::toString( NonlinearSolverParameters::CouplingType::Sequential ), NonlinearSolverParameters::viewKeysStruct::lineSearchActionString(), EnumStrings< NonlinearSolverParameters::LineSearchAction >::toString( NonlinearSolverParameters::LineSearchAction::None ) ), - InputError ); + InputError, getNonlinearSolverParameters().getWrapperDataContext( NonlinearSolverParameters::viewKeysStruct::couplingTypeString() ) ); if( m_nonlinearSolverParameters.m_nonlinearAccelerationType != NonlinearSolverParameters::NonlinearAccelerationType::None ) { diff --git a/src/coreComponents/physicsSolvers/multiphysics/PoromechanicsInitialization.cpp b/src/coreComponents/physicsSolvers/multiphysics/PoromechanicsInitialization.cpp index 40c6db48c03..4dcb4638c50 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/PoromechanicsInitialization.cpp +++ b/src/coreComponents/physicsSolvers/multiphysics/PoromechanicsInitialization.cpp @@ -76,7 +76,7 @@ postInputInitialization() getWrapperDataContext( viewKeyStruct::poromechanicsSolverNameString() ), POROMECHANICS_SOLVER::catalogName(), m_poromechanicsSolverName ), - InputError ); + InputError, getWrapperDataContext( viewKeyStruct::poromechanicsSolverNameString() ) ); m_poromechanicsSolver = &physicsSolverManager.getGroup< POROMECHANICS_SOLVER >( m_poromechanicsSolverName ); @@ -89,7 +89,7 @@ postInputInitialization() getWrapperDataContext( viewKeyStruct::solidMechanicsStatisticsNameString() ), SolidMechanicsStatistics::catalogName(), m_solidMechanicsStatisticsName ), - InputError ); + InputError, getWrapperDataContext( viewKeyStruct::solidMechanicsStatisticsNameString() ) ); m_solidMechanicsStatistics = &tasksManager.getGroup< SolidMechanicsStatistics >( m_solidMechanicsStatisticsName ); } diff --git a/src/coreComponents/physicsSolvers/multiphysics/PoromechanicsSolver.hpp b/src/coreComponents/physicsSolvers/multiphysics/PoromechanicsSolver.hpp index f553759e327..0e5db5c376c 100644 --- a/src/coreComponents/physicsSolvers/multiphysics/PoromechanicsSolver.hpp +++ b/src/coreComponents/physicsSolvers/multiphysics/PoromechanicsSolver.hpp @@ -155,7 +155,7 @@ class PoromechanicsSolver : public CoupledSolver< FLOW_SOLVER, MECHANICS_SOLVER GEOS_THROW_IF( m_stabilizationType == stabilization::StabilizationType::Local, this->getWrapperDataContext( viewKeyStruct::stabilizationTypeString() ) << ": Local stabilization has been temporarily disabled", - InputError ); + InputError, this->getWrapperDataContext( viewKeyStruct::stabilizationTypeString() ) ); DomainPartition & domain = this->template getGroupByPath< DomainPartition >( "/Problem/domain" ); diff --git a/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsLagrangianFEM.cpp b/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsLagrangianFEM.cpp index 40b56bb749c..18e7714e97d 100644 --- a/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsLagrangianFEM.cpp +++ b/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsLagrangianFEM.cpp @@ -714,13 +714,13 @@ void SolidMechanicsLagrangianFEM::applyDisplacementBCImplicit( real64 const time "The problem may be ill-posed.\n"; GEOS_WARNING_IF( isDisplacementBCAppliedGlobal[0] == 0, // target set is empty GEOS_FMT( bcLogMessage, - getCatalogName(), getDataContext(), 'x' ) ); + getCatalogName(), getDataContext(), 'x' ), getDataContext() ); GEOS_WARNING_IF( isDisplacementBCAppliedGlobal[1] == 0, // target set is empty GEOS_FMT( bcLogMessage, - getCatalogName(), getDataContext(), 'y' ) ); + getCatalogName(), getDataContext(), 'y' ), getDataContext() ); GEOS_WARNING_IF( isDisplacementBCAppliedGlobal[2] == 0, // target set is empty GEOS_FMT( bcLogMessage, - getCatalogName(), getDataContext(), 'z' ) ); + getCatalogName(), getDataContext(), 'z' ), getDataContext() ); } } diff --git a/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsStateReset.cpp b/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsStateReset.cpp index 45f5a282840..b8fe2dd7c96 100644 --- a/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsStateReset.cpp +++ b/src/coreComponents/physicsSolvers/solidMechanics/SolidMechanicsStateReset.cpp @@ -67,7 +67,7 @@ void SolidMechanicsStateReset::postInputInitialization() GEOS_THROW_IF( !physicsSolverManager.hasGroup( m_solidSolverName ), GEOS_FMT( "Task {}: physics solver named {} not found", getDataContext(), m_solidSolverName ), - InputError ); + InputError, getDataContext() ); m_solidSolver = &physicsSolverManager.getGroup< SolidMechanicsLagrangianFEM >( m_solidSolverName ); } diff --git a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsLagrangeContact.cpp b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsLagrangeContact.cpp index 5b67c829b29..855864cb1e3 100644 --- a/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsLagrangeContact.cpp +++ b/src/coreComponents/physicsSolvers/solidMechanics/contact/SolidMechanicsLagrangeContact.cpp @@ -1830,7 +1830,8 @@ void SolidMechanicsLagrangeContact::assembleStabilization( MeshLevel const & mes } } GEOS_ERROR_IF( realNodes != 2, - getDataContext() << ": An edge shared by two fracture elements must have 2 nodes." ); + getDataContext() << ": An edge shared by two fracture elements must have 2 nodes.", + getDataContext() ); edge.resize( realNodes ); // Compute nodal area factor diff --git a/src/coreComponents/physicsSolvers/surfaceGeneration/SurfaceGenerator.cpp b/src/coreComponents/physicsSolvers/surfaceGeneration/SurfaceGenerator.cpp index 886aa6b1658..76a9fd032c4 100644 --- a/src/coreComponents/physicsSolvers/surfaceGeneration/SurfaceGenerator.cpp +++ b/src/coreComponents/physicsSolvers/surfaceGeneration/SurfaceGenerator.cpp @@ -194,15 +194,18 @@ void SurfaceGenerator::postInputInitialization() GEOS_ERROR_IF( binaryOptions.count( m_isPoroelastic ) == 0, getWrapperDataContext( viewKeyStruct::isPoroelasticString() ) << - ": option can be either 0 (false) or 1 (true)" ); + ": option can be either 0 (false) or 1 (true)", + getWrapperDataContext( viewKeyStruct::isPoroelasticString() ) ); GEOS_ERROR_IF( binaryOptions.count( m_nodeBasedSIF ) == 0, getWrapperDataContext( viewKeyStruct::nodeBasedSIFString() ) << - ": option can be either 0 (false) or 1 (true)" ); + ": option can be either 0 (false) or 1 (true)", + getWrapperDataContext( viewKeyStruct::nodeBasedSIFString() ) ); GEOS_ERROR_IF( binaryOptions.count( m_mpiCommOrder ) == 0, getWrapperDataContext( viewKeyStruct::mpiCommOrderString() ) << - ": option can be either 0 (false) or 1 (true)" ); + ": option can be either 0 (false) or 1 (true)", + getWrapperDataContext( viewKeyStruct::mpiCommOrderString() ) ); } SurfaceGenerator::~SurfaceGenerator() @@ -950,7 +953,9 @@ void SurfaceGenerator::synchronizeTipSets ( FaceManager & faceManager, { localIndex const parentNodeIndex = parentNodeIndices[nodeIndex]; - GEOS_ERROR_IF( parentNodeIndex == -1, getDataContext() << ": parentNodeIndex should not be -1" ); + GEOS_ERROR_IF( parentNodeIndex == -1, + getDataContext() << ": parentNodeIndex should not be -1", + getDataContext() ); m_tipNodes.remove( parentNodeIndex ); } @@ -975,7 +980,9 @@ void SurfaceGenerator::synchronizeTipSets ( FaceManager & faceManager, { localIndex const parentEdgeIndex = parentEdgeIndices[edgeIndex]; - GEOS_ERROR_IF( parentEdgeIndex == -1, getDataContext() << ": parentEdgeIndex should not be -1" ); + GEOS_ERROR_IF( parentEdgeIndex == -1, + getDataContext() << ": parentEdgeIndex should not be -1", + getDataContext() ); m_tipEdges.remove( parentEdgeIndex ); for( localIndex const faceIndex : edgeToFaceMap[ parentEdgeIndex ] ) @@ -1008,7 +1015,9 @@ void SurfaceGenerator::synchronizeTipSets ( FaceManager & faceManager, for( localIndex const faceIndex : receivedObjects.newFaces ) { localIndex const parentFaceIndex = parentFaceIndices[faceIndex]; - GEOS_ERROR_IF( parentFaceIndex == -1, getDataContext() << ": parentFaceIndex should not be -1" ); + GEOS_ERROR_IF( parentFaceIndex == -1, + getDataContext() << ": parentFaceIndex should not be -1", + getDataContext() ); m_trailingFaces.insert( parentFaceIndex ); m_tipFaces.remove( parentFaceIndex ); diff --git a/src/coreComponents/physicsSolvers/wavePropagation/sem/acoustic/firstOrderEqn/isotropic/AcousticFirstOrderWaveEquationSEM.cpp b/src/coreComponents/physicsSolvers/wavePropagation/sem/acoustic/firstOrderEqn/isotropic/AcousticFirstOrderWaveEquationSEM.cpp index cc7ad520a73..35446a74147 100644 --- a/src/coreComponents/physicsSolvers/wavePropagation/sem/acoustic/firstOrderEqn/isotropic/AcousticFirstOrderWaveEquationSEM.cpp +++ b/src/coreComponents/physicsSolvers/wavePropagation/sem/acoustic/firstOrderEqn/isotropic/AcousticFirstOrderWaveEquationSEM.cpp @@ -213,7 +213,7 @@ void AcousticFirstOrderWaveEquationSEM::precomputeSourceAndReceiverTerm( MeshLev { GEOS_THROW_IF( elementSubRegion.getElementType() != ElementType::Hexahedron, getDataContext() << ": Invalid type of element, the acoustic solver is designed for hexahedral meshes only (C3D8) ", - InputError ); + InputError, getDataContext() ); arrayView2d< localIndex const > const elemsToFaces = elementSubRegion.faceList(); arrayView2d< localIndex const, cells::NODE_MAP_USD > const & elemsToNodes = elementSubRegion.nodeList(); 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 238c8af4d75..6190586dded 100644 --- a/src/coreComponents/physicsSolvers/wavePropagation/sem/acoustic/secondOrderEqn/isotropic/AcousticWaveEquationSEM.cpp +++ b/src/coreComponents/physicsSolvers/wavePropagation/sem/acoustic/secondOrderEqn/isotropic/AcousticWaveEquationSEM.cpp @@ -222,7 +222,7 @@ void AcousticWaveEquationSEM::precomputeSourceAndReceiverTerm( MeshLevel & baseM { GEOS_THROW_IF( elementSubRegion.getElementType() != ElementType::Hexahedron, getDataContext() << ": Invalid type of element, the acoustic solver is designed for hexahedral meshes only (C3D8), using the SEM formulation", - InputError ); + InputError, getDataContext() ); arrayView2d< localIndex const > const elemsToFaces = elementSubRegion.faceList(); arrayView2d< localIndex const, cells::NODE_MAP_USD > const & elemsToNodes = elementSubRegion.nodeList(); @@ -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 ); + std::runtime_error, getDataContext() ); forAll< EXEC_POLICY >( sourceConstants.size( 0 ), [=] GEOS_HOST_DEVICE ( localIndex const isrc ) { if( sourceIsAccessible[isrc] == 1 ) @@ -1040,12 +1040,12 @@ real64 AcousticWaveEquationSEM::explicitStepForward( real64 const & time_n, std::ofstream wf( fileName, std::ios::out | std::ios::binary ); GEOS_THROW_IF( !wf, getDataContext() << ": Could not open file "<< fileName << " for writing", - InputError ); + InputError, getDataContext() ); wf.write( (char *)&p_n[0], p_n.size()*sizeof( real32 ) ); wf.close( ); GEOS_THROW_IF( !wf.good(), getDataContext() << ": An error occured while writing "<< fileName, - InputError ); + InputError, getDataContext() ); } } @@ -1108,7 +1108,7 @@ real64 AcousticWaveEquationSEM::explicitStepBackward( real64 const & time_n, std::ifstream wf( fileName, std::ios::in | std::ios::binary ); GEOS_THROW_IF( !wf, getDataContext() << ": Could not open file "<< fileName << " for reading", - InputError ); + InputError, getDataContext() ); p_forward.move( LvArray::MemorySpace::host, true ); wf.read( (char *)&p_forward[0], p_forward.size()*sizeof( real32 ) ); diff --git a/src/coreComponents/physicsSolvers/wavePropagation/sem/elastic/firstOrderEqn/isotropic/ElasticFirstOrderWaveEquationSEM.cpp b/src/coreComponents/physicsSolvers/wavePropagation/sem/elastic/firstOrderEqn/isotropic/ElasticFirstOrderWaveEquationSEM.cpp index f3f8bbc0270..0434b2f71f9 100644 --- a/src/coreComponents/physicsSolvers/wavePropagation/sem/elastic/firstOrderEqn/isotropic/ElasticFirstOrderWaveEquationSEM.cpp +++ b/src/coreComponents/physicsSolvers/wavePropagation/sem/elastic/firstOrderEqn/isotropic/ElasticFirstOrderWaveEquationSEM.cpp @@ -263,7 +263,8 @@ void ElasticFirstOrderWaveEquationSEM::precomputeSourceAndReceiverTerm( MeshLeve GEOS_THROW_IF( elementSubRegion.getElementType() != ElementType::Hexahedron, getDataContext() << ": Invalid type of element, the elastic solver is designed for hexahedral meshes only (C3D8) ", - InputError ); + InputError, getDataContext(), + elementSubRegion.getDataContext().getContextInfo().setPriority( -1 ) ); arrayView2d< localIndex const > const elemsToFaces = elementSubRegion.faceList(); arrayView2d< localIndex const, cells::NODE_MAP_USD > const & elemsToNodes = elementSubRegion.nodeList(); 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 5c271dd8b2d..2c16780151b 100644 --- a/src/coreComponents/physicsSolvers/wavePropagation/sem/elastic/secondOrderEqn/isotropic/ElasticWaveEquationSEM.cpp +++ b/src/coreComponents/physicsSolvers/wavePropagation/sem/elastic/secondOrderEqn/isotropic/ElasticWaveEquationSEM.cpp @@ -298,7 +298,8 @@ void ElasticWaveEquationSEM::precomputeSourceAndReceiverTerm( MeshLevel & baseMe GEOS_THROW_IF( elementSubRegion.getElementType() != ElementType::Hexahedron, getDataContext() << ": Invalid type of element, the elastic solver is designed for hexahedral meshes only (C3D8) ", - InputError ); + InputError, getDataContext(), + elementSubRegion.getDataContext().getContextInfo().setPriority( -1 ) ); arrayView2d< localIndex const > const elemsToFaces = elementSubRegion.faceList(); arrayView2d< localIndex const, cells::NODE_MAP_USD > const & elemsToNodes = elementSubRegion.nodeList(); diff --git a/src/coreComponents/physicsSolvers/wavePropagation/shared/WaveSolverBase.cpp b/src/coreComponents/physicsSolvers/wavePropagation/shared/WaveSolverBase.cpp index 49fdfdca68f..bd0561bc9b5 100644 --- a/src/coreComponents/physicsSolvers/wavePropagation/shared/WaveSolverBase.cpp +++ b/src/coreComponents/physicsSolvers/wavePropagation/shared/WaveSolverBase.cpp @@ -338,7 +338,7 @@ void WaveSolverBase::postInputInitialization() } ); GEOS_THROW_IF( counter > 1, getDataContext() << ": One single PML field specification is allowed", - InputError ); + InputError, getDataContext() ); m_usePML = counter; @@ -462,7 +462,7 @@ localIndex WaveSolverBase::getNumNodesPerElem() feDiscretization = feDiscretizationManager.getGroupPointer< FiniteElementDiscretization >( m_discretizationName ); GEOS_THROW_IF( feDiscretization == nullptr, getDataContext() << ": FE discretization not found: " << m_discretizationName, - InputError ); + InputError, getDataContext() ); localIndex numNodesPerElem = 0; forDiscretizationOnMeshTargets( domain.getMeshBodies(), diff --git a/src/coreComponents/schema/schema.xsd.other b/src/coreComponents/schema/schema.xsd.other index 380d963e2ef..33a2ec00f2c 100644 --- a/src/coreComponents/schema/schema.xsd.other +++ b/src/coreComponents/schema/schema.xsd.other @@ -516,7 +516,7 @@ - + @@ -1516,7 +1516,7 @@ - + diff --git a/src/main/main.cpp b/src/main/main.cpp index 4673f2e228a..14750a4d4a1 100644 --- a/src/main/main.cpp +++ b/src/main/main.cpp @@ -49,7 +49,7 @@ int main( int argc, char *argv[] ) { state.applyInitialConditions(); state.run(); - LVARRAY_WARNING_IF( state.getState() != State::COMPLETED, "Simulation exited early." ); + GEOS_WARNING_IF( state.getState() != State::COMPLETED, "Simulation exited early." ); } initTime = state.getInitTime(); @@ -77,6 +77,10 @@ int main( int argc, char *argv[] ) catch( std::exception const & e ) { GEOS_LOG( e.what() ); + if( ErrorLogger::global().isOutputFileEnabled() ) + { + ErrorLogger::global().flushErrorMsg( ErrorLogger::global().currentErrorMsg() ); + } LvArray::system::callErrorHandler(); basicCleanup(); std::abort();