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