LCOV - code coverage report
Current view: top level - include/base - MooseError.h (source / functions) Hit Total Coverage
Test: idaholab/moose framework: fef103 Lines: 85 86 98.8 %
Date: 2025-09-03 20:01:23 Functions: 1203 2734 44.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #pragma once
      11             : 
      12             : #include "Moose.h"
      13             : #include "MooseException.h"
      14             : #include "libmesh/threads.h"
      15             : 
      16             : #include "libmesh/print_trace.h"
      17             : #include "libmesh/libmesh_common.h"
      18             : 
      19             : // C++ includes
      20             : #include <cstdlib>
      21             : #include <tuple>
      22             : #include <type_traits>
      23             : 
      24             : // Used in numerous downstream classes without 'libMesh::' prefix
      25             : using libMesh::demangle;
      26             : 
      27             : namespace MetaPhysicL
      28             : {
      29             : class LogicError;
      30             : }
      31             : 
      32             : namespace hit
      33             : {
      34             : class Node;
      35             : }
      36             : 
      37             : // this function allows streaming tuples to ostreams
      38             : template <size_t n, typename... T>
      39             : void
      40             : print_tuple(std::ostream & os, const std::tuple<T...> & tup)
      41             : {
      42             :   if constexpr (n < sizeof...(T))
      43             :   {
      44             :     if (n != 0)
      45             :       os << ", ";
      46             :     os << std::get<n>(tup);
      47             :     print_tuple<n + 1>(os, tup);
      48             :   }
      49             : }
      50             : template <typename... T>
      51             : std::ostream &
      52             : operator<<(std::ostream & os, const std::tuple<T...> & tup)
      53             : {
      54             :   os << "[";
      55             :   print_tuple<0>(os, tup);
      56             :   return os << "]";
      57             : }
      58             : 
      59             : /// Application abort macro. Uses MPI_Abort if available, std::abort otherwise
      60             : #if defined(LIBMESH_HAVE_MPI)
      61             : #define MOOSE_ABORT                                                                                \
      62             :   do                                                                                               \
      63             :   {                                                                                                \
      64             :     MPI_Abort(libMesh::GLOBAL_COMM_WORLD, 1);                                                      \
      65             :     std::abort();                                                                                  \
      66             :   } while (0)
      67             : #else
      68             : #define MOOSE_ABORT                                                                                \
      69             :   do                                                                                               \
      70             :   {                                                                                                \
      71             :     std::abort();                                                                                  \
      72             :   } while (0)
      73             : #endif
      74             : 
      75             : #define mooseDoOnce(do_this)                                                                       \
      76             :   do                                                                                               \
      77             :   {                                                                                                \
      78             :     static bool did_this_already = false;                                                          \
      79             :     if (Moose::show_multiple || !did_this_already)                                                 \
      80             :     {                                                                                              \
      81             :       did_this_already = true;                                                                     \
      82             :       do_this;                                                                                     \
      83             :     }                                                                                              \
      84             :   } while (0)
      85             : 
      86             : #define mooseCheckMPIErr(err)                                                                      \
      87             :   do                                                                                               \
      88             :   {                                                                                                \
      89             :     if (err != MPI_SUCCESS)                                                                        \
      90             :       moose::internal::mooseErrorRaw("");                                                          \
      91             :   } while (0)
      92             : 
      93             : #define mooseException(...)                                                                        \
      94             :   do                                                                                               \
      95             :   {                                                                                                \
      96             :     throw MooseException(__VA_ARGS__);                                                             \
      97             :   } while (0)
      98             : 
      99             : #ifdef NDEBUG
     100             : #define mooseAssert(asserted, msg) ((void)0)
     101             : #else
     102             : #define mooseAssert(asserted, msg)                                                                 \
     103             :   do                                                                                               \
     104             :   {                                                                                                \
     105             :     if (!(asserted))                                                                               \
     106             :     {                                                                                              \
     107             :       std::ostringstream _assert_oss_;                                                             \
     108             :       _assert_oss_ << COLOR_RED << "\n\nAssertion `" #asserted "' failed\n"                        \
     109             :                    << msg << "\nat " << __FILE__ << ", line " << __LINE__ << COLOR_DEFAULT         \
     110             :                    << std::endl;                                                                   \
     111             :       if (Moose::_throw_on_error)                                                                  \
     112             :         throw std::runtime_error(_assert_oss_.str());                                              \
     113             :       else                                                                                         \
     114             :       {                                                                                            \
     115             :         Moose::err << _assert_oss_.str() << std::flush;                                            \
     116             :         moose::internal::mooseErrorRaw("");                                                        \
     117             :       }                                                                                            \
     118             :     }                                                                                              \
     119             :   } while (0)
     120             : #endif
     121             : 
     122             : template <typename... Args>
     123             : [[noreturn]] void mooseError(Args &&... args);
     124             : 
     125             : /**
     126             :  * Exception to be thrown whenever we have _throw_on_error set and a
     127             :  * mooseError() is emitted.
     128             :  *
     129             :  * Enables adding the context of the hit node from the location in input
     130             :  * associated with the error, which can be used in the MooseServer to
     131             :  * produce diagnostics without parsing messages.
     132             :  */
     133             : class MooseRuntimeError : public std::runtime_error
     134             : {
     135             : public:
     136         243 :   MooseRuntimeError(const std::string & message, const hit::Node * const node)
     137         243 :     : runtime_error(message), _node(node)
     138             :   {
     139         243 :   }
     140             : 
     141             :   /// Get the associated hit node, if any
     142           1 :   const hit::Node * getNode() const { return _node; }
     143             : 
     144             : private:
     145             :   /// The associated hit node, if any
     146             :   const hit::Node * const _node;
     147             : };
     148             : 
     149             : class MooseVariableFieldBase;
     150             : 
     151             : namespace moose
     152             : {
     153             : 
     154             : namespace internal
     155             : {
     156             : inline libMesh::Threads::spin_mutex moose_stream_lock;
     157             : 
     158             : /// Builds and returns a string of the form:
     159             : ///
     160             : ///     [var1-elemtype],ORDER[var1-order] != [var2-elemtype],ORDER[var2-order]
     161             : ///
     162             : /// This is a convenience function to be used when error messages (especially with paramError)
     163             : /// need to report that variable types are incompatible (e.g. with residual save-in).
     164             : std::string incompatVarMsg(MooseVariableFieldBase & var1, MooseVariableFieldBase & var2);
     165             : 
     166             : /**
     167             :  * Format a message for output with a title
     168             :  * @param msg The message to print
     169             :  * @param title The title that will go on a line before the message
     170             :  * @param color The color to print the message in
     171             :  * @return The formatted message
     172             :  */
     173             : std::string
     174             : mooseMsgFmt(const std::string & msg, const std::string & title, const std::string & color);
     175             : 
     176             : /**
     177             :  * Format a message for output without a title
     178             :  * @param msg The message to print
     179             :  * @param color The color to print the message in
     180             :  * @return The formatted message
     181             :  */
     182             : std::string mooseMsgFmt(const std::string & msg, const std::string & color);
     183             : 
     184             : /**
     185             :  * Main callback for emitting a moose error.
     186             :  * @param msg The error message
     187             :  * @param prefix Optional prefix to add to every line of the error (for multiapp prefixes)
     188             :  * @param node Optional HIT node to associate with the error, adding file path context
     189             :  */
     190             : [[noreturn]] void
     191             : mooseErrorRaw(std::string msg, const std::string & prefix = "", const hit::Node * node = nullptr);
     192             : 
     193             : /**
     194             :  * All of the following are not meant to be called directly - they are called by the normal macros
     195             :  * (mooseError(), etc.) down below
     196             :  * @{
     197             :  */
     198             : void mooseStreamAll(std::ostringstream & ss);
     199             : 
     200             : template <typename T, typename... Args>
     201             : void
     202       74593 : mooseStreamAll(std::ostringstream & ss, T && val, Args &&... args)
     203             : {
     204       74593 :   ss << val;
     205       74593 :   mooseStreamAll(ss, std::forward<Args>(args)...);
     206       74593 : }
     207             : 
     208             : template <typename S, typename... Args>
     209             : void
     210        3769 : mooseWarningStream(S & oss, Args &&... args)
     211             : {
     212        3769 :   if (Moose::_warnings_are_errors)
     213         195 :     mooseError(std::forward<Args>(args)...);
     214             : 
     215        3574 :   std::ostringstream ss;
     216        3574 :   mooseStreamAll(ss, args...);
     217       10722 :   std::string msg = mooseMsgFmt(ss.str(), "*** Warning ***", COLOR_YELLOW);
     218        3574 :   if (Moose::_throw_on_warning)
     219           1 :     throw std::runtime_error(msg);
     220             : 
     221             :   {
     222        3573 :     libMesh::Threads::spin_mutex::scoped_lock lock(moose_stream_lock);
     223        3573 :     oss << msg << std::flush;
     224        3573 :   }
     225        3575 : }
     226             : 
     227             : template <typename S, typename... Args>
     228             : void
     229          51 : mooseUnusedStream(S & oss, Args &&... args)
     230             : {
     231          51 :   std::ostringstream ss;
     232          51 :   mooseStreamAll(ss, args...);
     233         153 :   std::string msg = mooseMsgFmt(ss.str(), "*** Warning ***", COLOR_YELLOW);
     234          51 :   if (Moose::_throw_on_warning)
     235           0 :     throw std::runtime_error(msg);
     236             : 
     237             :   {
     238          51 :     libMesh::Threads::spin_mutex::scoped_lock lock(moose_stream_lock);
     239          51 :     oss << msg << std::flush;
     240          51 :   }
     241          51 : }
     242             : 
     243             : template <typename S, typename... Args>
     244             : void
     245       21473 : mooseInfoStreamRepeated(S & oss, Args &&... args)
     246             : {
     247       21473 :   std::ostringstream ss;
     248       21473 :   mooseStreamAll(ss, args...);
     249       64419 :   std::string msg = mooseMsgFmt(ss.str(), "*** Info ***", COLOR_CYAN);
     250             :   {
     251       21473 :     libMesh::Threads::spin_mutex::scoped_lock lock(moose_stream_lock);
     252       21473 :     oss << msg << std::flush;
     253       21473 :   }
     254       21473 : }
     255             : 
     256             : template <typename S, typename... Args>
     257             : void
     258       11890 : mooseInfoStream(S & oss, Args &&... args)
     259             : {
     260       11890 :   mooseDoOnce(mooseInfoStreamRepeated(oss, args...););
     261       11890 : }
     262             : 
     263             : template <typename S, typename... Args>
     264             : void
     265       14665 : mooseDeprecatedStream(S & oss, const bool expired, const bool print_title, Args &&... args)
     266             : {
     267       14665 :   if (Moose::_deprecated_is_error)
     268          13 :     mooseError("\n\nDeprecated code:\n", std::forward<Args>(args)...);
     269             : 
     270       14652 :   std::ostringstream ss;
     271       14652 :   mooseStreamAll(ss, args...);
     272             : 
     273       14652 :   const auto color = expired ? COLOR_RED : COLOR_YELLOW;
     274       58608 :   std::string msg = print_title ? mooseMsgFmt(ss.str(), "*** Deprecation Warning ***", color)
     275             :                                 : mooseMsgFmt(ss.str(), color);
     276       14652 :   oss << msg;
     277       14652 :   ss.str("");
     278       14652 :   if (Moose::show_trace)
     279             :   {
     280       12118 :     if (libMesh::global_n_processors() == 1)
     281        6858 :       libMesh::print_trace(ss);
     282             :     else
     283        5260 :       libMesh::write_traceout();
     284             :     {
     285       12118 :       libMesh::Threads::spin_mutex::scoped_lock lock(moose_stream_lock);
     286       12118 :       oss << ss.str() << std::endl;
     287       12118 :     };
     288             :   };
     289       14652 : }
     290             : /**
     291             :  * @}
     292             :  */
     293             : 
     294             : /**
     295             :  * Formats a documented error. A documented error is an error that has
     296             :  * an issue associated with it.
     297             :  *
     298             :  * The repository name \p repo_name links a named repository to a URL
     299             :  * and should be registered at the application level with registerRepository().
     300             :  * See Moose.C for an example of the "moose" repository registration.
     301             :  *
     302             :  * @param repo_name The repository name where the issue resides
     303             :  * @param issue_num The number of the issue
     304             :  * @param msg The specific error message
     305             :  */
     306             : std::string formatMooseDocumentedError(const std::string & repo_name,
     307             :                                        const unsigned int issue_num,
     308             :                                        const std::string & msg);
     309             : } // namespace internal
     310             : 
     311             : /**
     312             :  * emit a relatively clear error message when we catch a MetaPhysicL logic error
     313             :  */
     314             : void translateMetaPhysicLError(const MetaPhysicL::LogicError &);
     315             : 
     316             : } // namespace moose
     317             : 
     318             : /// Emit an error message with the given stringified, concatenated args and
     319             : /// terminate the application.  Inside static functions, you will need to
     320             : /// explicitly scope your mooseError call - i.e. do "::mooseError(arg1, ...);".
     321             : template <typename... Args>
     322             : [[noreturn]] void
     323        1224 : mooseError(Args &&... args)
     324             : {
     325        1224 :   std::ostringstream oss;
     326        1224 :   moose::internal::mooseStreamAll(oss, std::forward<Args>(args)...);
     327        1602 :   moose::internal::mooseErrorRaw(oss.str());
     328         189 : }
     329             : 
     330             : /**
     331             :  * Emit a documented error message with the given stringified, concatenated args
     332             :  * and terminate the application.  Inside static functions, you will need to
     333             :  * explicitly scope your mooseError call - i.e. do "::mooseError(arg1, ...);".
     334             :  *
     335             :  * Here, a documented error message is one with an associated issue. See
     336             :  * formatMooseDocumentedError for more information.
     337             :  *
     338             :  * @param repo_name The repository name where the issue resides
     339             :  * @param issue_num The number of the issue
     340             :  * @param args The error message to stringify
     341             :  **/
     342             : template <typename... Args>
     343             : [[noreturn]] void
     344           1 : mooseDocumentedError(const std::string & repo_name, const unsigned int issue_num, Args &&... args)
     345             : {
     346           1 :   std::ostringstream oss;
     347           1 :   moose::internal::mooseStreamAll(oss, std::forward<Args>(args)...);
     348           4 :   moose::internal::mooseErrorRaw(
     349             :       moose::internal::formatMooseDocumentedError(repo_name, issue_num, oss.str()));
     350           1 : }
     351             : 
     352             : /// Emit a warning message with the given stringified, concatenated args.
     353             : /// Inside static functions, you will need to explicitly scope your
     354             : /// mooseWarning call - i.e. do "::mooseWarning(arg1, ...);".
     355             : template <typename... Args>
     356             : void
     357        1104 : mooseWarning(Args &&... args)
     358             : {
     359        1104 :   moose::internal::mooseWarningStream(Moose::out, std::forward<Args>(args)...);
     360        1081 : }
     361             : 
     362             : /// Warning message used to notify the users of unused parts of their input files
     363             : /// Really used internally by the parser and shouldn't really be called elsewhere
     364             : template <typename... Args>
     365             : void
     366          51 : mooseUnused(Args &&... args)
     367             : {
     368          51 :   moose::internal::mooseUnusedStream(Moose::out, std::forward<Args>(args)...);
     369          51 : }
     370             : 
     371             : /// Emit a deprecated code/feature message with the given stringified, concatenated args.
     372             : template <typename... Args>
     373             : void
     374       11204 : mooseDeprecated(Args &&... args)
     375             : {
     376       11204 :   moose::internal::mooseDeprecatedStream(Moose::out, false, true, std::forward<Args>(args)...);
     377       11204 : }
     378             : 
     379             : /// Emit a deprecated code/feature message with the given stringified, concatenated args.
     380             : template <typename... Args>
     381             : void
     382        1095 : mooseDeprecationExpired(Args &&... args)
     383             : {
     384        1095 :   moose::internal::mooseDeprecatedStream(Moose::out, true, true, std::forward<Args>(args)...);
     385        1091 : }
     386             : 
     387             : /// Emit an informational message with the given stringified, concatenated args.
     388             : template <typename... Args>
     389             : void
     390         617 : mooseInfo(Args &&... args)
     391             : {
     392         617 :   moose::internal::mooseInfoStream(Moose::out, std::forward<Args>(args)...);
     393         617 : }
     394             : 
     395             : /// Emit an informational message with the given stringified, concatenated args.
     396             : template <typename... Args>
     397             : void
     398       12115 : mooseInfoRepeated(Args &&... args)
     399             : {
     400       12115 :   moose::internal::mooseInfoStreamRepeated(Moose::out, std::forward<Args>(args)...);
     401       12115 : }

Generated by: LCOV version 1.14