LCOV - code coverage report
Current view: top level - src/base - MooseError.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: #32971 (54bef8) with base c6cf66 Lines: 49 58 84.5 %
Date: 2026-05-29 20:35:17 Functions: 5 7 71.4 %
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             : #include "MooseError.h"
      11             : #include "MooseUtils.h"
      12             : #include "MooseVariable.h"
      13             : #include "Registry.h"
      14             : 
      15             : #include "libmesh/string_to_enum.h"
      16             : 
      17             : using namespace libMesh;
      18             : 
      19             : namespace moose
      20             : {
      21             : 
      22             : namespace internal
      23             : {
      24             : 
      25             : std::string
      26           3 : incompatVarMsg(MooseVariableFEBase & var1, MooseVariableFEBase & var2)
      27             : {
      28           3 :   std::stringstream ss;
      29           3 :   ss << libMesh::Utility::enum_to_string<FEFamily>(var1.feType().family) << ",ORDER"
      30           3 :      << var1.feType().order
      31           6 :      << " != " << libMesh::Utility::enum_to_string<FEFamily>(var2.feType().family) << ",ORDER"
      32           3 :      << var2.feType().order;
      33           6 :   return ss.str();
      34           3 : }
      35             : 
      36             : std::string
      37       28342 : mooseMsgFmt(const std::string & msg, const std::string & title, const std::string & color)
      38             : {
      39       28342 :   std::ostringstream oss;
      40       28342 :   oss << "\n" << color << "\n" << title << "\n" << msg << COLOR_DEFAULT << "\n";
      41       56684 :   return oss.str();
      42       28342 : }
      43             : 
      44             : std::string
      45           0 : mooseMsgFmt(const std::string & msg, const std::string & color)
      46             : {
      47           0 :   std::ostringstream oss;
      48           0 :   oss << "\n" << color << "\n" << msg << COLOR_DEFAULT << "\n";
      49           0 :   return oss.str();
      50           0 : }
      51             : 
      52             : [[noreturn]] void
      53        4196 : mooseErrorRaw(std::string msg,
      54             :               const std::string & prefix /* = "" */,
      55             :               const hit::Node * node /* = nullptr */,
      56             :               const bool show_trace /* = true */)
      57             : {
      58        4196 :   if (Moose::_throw_on_error)
      59         799 :     throw MooseRuntimeError(msg, node);
      60             : 
      61             :   // Atomic that will be set as soon as any thread hits this method
      62             :   static std::atomic_flag aborting = ATOMIC_FLAG_INIT;
      63             : 
      64             :   // Per-thread bool that will avoid us getting stuck in pause() if one
      65             :   // thread hits this method twice.
      66             :   thread_local static bool this_thread_aborting = false;
      67             : 
      68             :   // This branch will be hit after another thread has already set the atomic.
      69             :   // MPI_Abort, despite its name, does not behave like std::abort but instead
      70             :   // calls exit handlers and destroys statics. So we don't want to touch
      71             :   // anything static at this point. We'll just wait until the winning thread
      72             :   // has incurred program exit
      73        3397 :   if (aborting.test_and_set(std::memory_order_acq_rel) && !this_thread_aborting)
      74             :   {
      75             :     // Waiting for the other thread(s), not burning CPU
      76             :     for (;;)
      77          14 :       pause();
      78             :   }
      79             :   // We're the first thread to hit this method (we set the atomic), so we're
      80             :   // responsible for dumping the error and trace(s) while the remaining
      81             :   // threads wait for us to exit (via libmesh_abort())
      82             :   else
      83             :   {
      84             :     // No, really, terminate. libmesh_abort() may throw an
      85             :     // exception, and if we catch that exception (or a bad_alloc, or
      86             :     // anything thrown) and mooseError because we didn't understand
      87             :     // it, we just want to continue up the stack.
      88        3383 :     if (this_thread_aborting)
      89           0 :       libmesh_abort();
      90             : 
      91        3383 :     this_thread_aborting = true;
      92             : 
      93             :     // Output the message if there is one, but flush it without the trace
      94             :     // as trace retrieval can be slow in some circumstances and we want to
      95             :     // get the error message out ASAP
      96        3383 :     if (!msg.empty())
      97             :     {
      98             :       // If we have a node available, add in the hit context (file location)
      99        3383 :       if (node)
     100        2317 :         msg = Moose::hitMessagePrefix(*node) + msg;
     101             : 
     102       10149 :       msg = mooseMsgFmt(msg, "*** ERROR ***", COLOR_RED) + "\n";
     103        3383 :       if (!prefix.empty()) // multiapp prefix
     104          30 :         MooseUtils::indentMessage(prefix, msg);
     105             : 
     106             :       {
     107        3383 :         Threads::spin_mutex::scoped_lock lock(moose_stream_lock);
     108        3383 :         Moose::err << msg << std::flush;
     109        3383 :       }
     110             :     }
     111             : 
     112             :     // Print the trace if enabled and on a single rank
     113        3383 :     if (show_trace && libMesh::global_n_processors() == 1)
     114             :     {
     115        2140 :       std::ostringstream oss;
     116        2140 :       print_trace(oss);
     117        2140 :       auto trace = oss.str();
     118        2140 :       if (!prefix.empty()) // multiapp prefix
     119          24 :         MooseUtils::indentMessage(prefix, trace);
     120             : 
     121             :       {
     122        2140 :         Threads::spin_mutex::scoped_lock lock(moose_stream_lock);
     123        2140 :         Moose::err << trace << std::flush;
     124        2140 :       }
     125        2140 :     }
     126             : 
     127             :     // In parallel with libMesh configured with --enable-tracefiles, this will
     128             :     // dump a trace for each rank to file
     129        3383 :     if (libMesh::global_n_processors() > 1)
     130           0 :       libMesh::write_traceout();
     131             : 
     132        3383 :     libmesh_abort();
     133             :   }
     134             : }
     135             : 
     136             : void
     137       27999 : mooseStreamAll(std::ostringstream &)
     138             : {
     139       27999 : }
     140             : 
     141             : std::string
     142           7 : formatMooseDocumentedError(const std::string & repo_name,
     143             :                            const unsigned int issue_num,
     144             :                            const std::string & msg)
     145             : {
     146           7 :   const auto & repo_url = Registry::getRepositoryURL(repo_name);
     147           7 :   std::stringstream oss;
     148           7 :   oss << msg << "\n\nThis error is documented at " << repo_url << "/issues/" << issue_num << ".";
     149          14 :   return oss.str();
     150           7 : }
     151             : 
     152             : } // namespace internal
     153             : 
     154             : void
     155           0 : translateMetaPhysicLError(const MetaPhysicL::LogicError &)
     156             : {
     157           0 :   mooseError(
     158             :       "We caught a MetaPhysicL error in while performing element or face loops. This is "
     159             :       "potentially due to AD not having a sufficiently large derivative container size. To "
     160             :       "increase the AD container size, you can run configure in the MOOSE root directory with the "
     161             :       "'--with-derivative-size=<n>' option and then recompile. Other causes of MetaPhysicL logic "
     162             :       "errors include evaluating functions where they are not defined or differentiable like sqrt "
     163             :       "(which gets called for vector norm functions) or log with arguments <= 0");
     164             : }
     165             : 
     166             : } // namespace moose

Generated by: LCOV version 1.14