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 : #define mooseDoOnce(do_this) \
60 : do \
61 : { \
62 : static bool did_this_already = false; \
63 : if (Moose::show_multiple || !did_this_already) \
64 : { \
65 : did_this_already = true; \
66 : do_this; \
67 : } \
68 : } while (0)
69 :
70 : #define mooseCheckMPIErr(err) \
71 : do \
72 : { \
73 : if (err != MPI_SUCCESS) \
74 : moose::internal::mooseErrorRaw(""); \
75 : } while (0)
76 :
77 : #define mooseException(...) \
78 : do \
79 : { \
80 : throw MooseException(__VA_ARGS__); \
81 : } while (0)
82 :
83 : #ifdef NDEBUG
84 : #define mooseAssert(asserted, msg) ((void)0)
85 : #else
86 : #define mooseAssert(asserted, msg) \
87 : do \
88 : { \
89 : if (!(asserted)) \
90 : { \
91 : std::ostringstream _assert_oss_; \
92 : _assert_oss_ << COLOR_RED << "\n\nAssertion `" #asserted "' failed\n" \
93 : << msg << "\nat " << __FILE__ << ", line " << __LINE__ << COLOR_DEFAULT \
94 : << std::endl; \
95 : if (Moose::_throw_on_error) \
96 : throw std::runtime_error(_assert_oss_.str()); \
97 : else \
98 : { \
99 : Moose::err << _assert_oss_.str() << std::flush; \
100 : moose::internal::mooseErrorRaw(""); \
101 : } \
102 : } \
103 : } while (0)
104 : #endif
105 :
106 : template <typename... Args>
107 : [[noreturn]] void mooseError(Args &&... args);
108 :
109 : /**
110 : * Exception to be thrown whenever we have _throw_on_error set and a
111 : * mooseError() is emitted.
112 : *
113 : * Enables adding the context of the hit node from the location in input
114 : * associated with the error, which can be used in the MooseServer to
115 : * produce diagnostics without parsing messages.
116 : */
117 : class MooseRuntimeError : public std::runtime_error
118 : {
119 : public:
120 825 : MooseRuntimeError(const std::string & message, const hit::Node * const node)
121 825 : : runtime_error(message), _node(node)
122 : {
123 825 : }
124 :
125 : /// Get the associated hit node, if any
126 10 : const hit::Node * getNode() const { return _node; }
127 :
128 : private:
129 : /// The associated hit node, if any
130 : const hit::Node * const _node;
131 : };
132 :
133 : class MooseVariableFieldBase;
134 :
135 : namespace moose
136 : {
137 :
138 : namespace internal
139 : {
140 : inline libMesh::Threads::spin_mutex moose_stream_lock;
141 :
142 : /// Builds and returns a string of the form:
143 : ///
144 : /// [var1-elemtype],ORDER[var1-order] != [var2-elemtype],ORDER[var2-order]
145 : ///
146 : /// This is a convenience function to be used when error messages (especially with paramError)
147 : /// need to report that variable types are incompatible (e.g. with residual save-in).
148 : std::string incompatVarMsg(MooseVariableFieldBase & var1, MooseVariableFieldBase & var2);
149 :
150 : /**
151 : * Format a message for output with a title
152 : * @param msg The message to print
153 : * @param title The title that will go on a line before the message
154 : * @param color The color to print the message in
155 : * @return The formatted message
156 : */
157 : std::string
158 : mooseMsgFmt(const std::string & msg, const std::string & title, const std::string & color);
159 :
160 : /**
161 : * Format a message for output without a title
162 : * @param msg The message to print
163 : * @param color The color to print the message in
164 : * @return The formatted message
165 : */
166 : std::string mooseMsgFmt(const std::string & msg, const std::string & color);
167 :
168 : /**
169 : * Main callback for emitting a moose error.
170 : * @param msg The error message
171 : * @param prefix Optional prefix to add to every line of the error (for multiapp prefixes)
172 : * @param node Optional HIT node to associate with the error, adding file path context
173 : * @param show_trace Whether or not to show a stack trace, defaults to true
174 : */
175 : [[noreturn]] void mooseErrorRaw(std::string msg,
176 : const std::string & prefix = "",
177 : const hit::Node * node = nullptr,
178 : const bool show_trace = true);
179 :
180 : /**
181 : * All of the following are not meant to be called directly - they are called by the normal macros
182 : * (mooseError(), etc.) down below
183 : * @{
184 : */
185 : void mooseStreamAll(std::ostringstream & ss);
186 :
187 : template <typename T, typename... Args>
188 : void
189 60779 : mooseStreamAll(std::ostringstream & ss, T && val, Args &&... args)
190 : {
191 60779 : ss << val;
192 60779 : mooseStreamAll(ss, std::forward<Args>(args)...);
193 60779 : }
194 :
195 : template <typename S, typename... Args>
196 : void
197 3650 : mooseWarningStream(S & oss, Args &&... args)
198 : {
199 3650 : if (Moose::_warnings_are_errors)
200 151 : mooseError(std::forward<Args>(args)...);
201 :
202 3499 : std::ostringstream ss;
203 3499 : mooseStreamAll(ss, args...);
204 10497 : std::string msg = mooseMsgFmt(ss.str(), "*** Warning ***", COLOR_YELLOW);
205 3499 : if (Moose::_throw_on_warning)
206 20 : throw std::runtime_error(msg);
207 :
208 : {
209 3479 : libMesh::Threads::spin_mutex::scoped_lock lock(moose_stream_lock);
210 3479 : oss << msg << std::flush;
211 3479 : }
212 3519 : }
213 :
214 : template <typename S, typename... Args>
215 : void
216 51 : mooseUnusedStream(S & oss, Args &&... args)
217 : {
218 51 : std::ostringstream ss;
219 51 : mooseStreamAll(ss, args...);
220 153 : std::string msg = mooseMsgFmt(ss.str(), "*** Warning ***", COLOR_YELLOW);
221 51 : if (Moose::_throw_on_warning)
222 0 : throw std::runtime_error(msg);
223 :
224 : {
225 51 : libMesh::Threads::spin_mutex::scoped_lock lock(moose_stream_lock);
226 51 : oss << msg << std::flush;
227 51 : }
228 51 : }
229 :
230 : template <typename S, typename... Args>
231 : void
232 13767 : mooseInfoStreamRepeated(S & oss, Args &&... args)
233 : {
234 13767 : if (Moose::_suppress_info)
235 54 : return;
236 :
237 13713 : std::ostringstream ss;
238 13713 : mooseStreamAll(ss, args...);
239 41139 : std::string msg = mooseMsgFmt(ss.str(), "*** Info ***", COLOR_CYAN);
240 : {
241 13713 : libMesh::Threads::spin_mutex::scoped_lock lock(moose_stream_lock);
242 13713 : oss << msg << std::flush;
243 13713 : }
244 13713 : }
245 :
246 : template <typename S, typename... Args>
247 : void
248 12436 : mooseInfoStream(S & oss, Args &&... args)
249 : {
250 12436 : if (Moose::_suppress_info)
251 0 : return;
252 :
253 12436 : mooseDoOnce(mooseInfoStreamRepeated(oss, args...););
254 : }
255 :
256 : template <typename S, typename... Args>
257 : void
258 7826 : mooseDeprecatedStream(
259 : S & oss, const bool expired, const bool print_title, const bool show_trace, Args &&... args)
260 : {
261 7826 : if (Moose::_deprecated_is_error)
262 13 : mooseError("\n\nDeprecated code:\n", std::forward<Args>(args)...);
263 :
264 7813 : std::ostringstream ss;
265 7813 : mooseStreamAll(ss, args...);
266 :
267 7813 : const auto color = expired ? COLOR_RED : COLOR_YELLOW;
268 31252 : std::string msg = print_title ? mooseMsgFmt(ss.str(), "*** Deprecation Warning ***", color)
269 : : mooseMsgFmt(ss.str(), color);
270 7813 : oss << msg;
271 7813 : ss.str("");
272 7813 : if (show_trace)
273 : {
274 5047 : if (libMesh::global_n_processors() == 1)
275 3009 : libMesh::print_trace(ss);
276 : else
277 2038 : libMesh::write_traceout();
278 : {
279 5047 : libMesh::Threads::spin_mutex::scoped_lock lock(moose_stream_lock);
280 5047 : oss << ss.str() << std::endl;
281 5047 : };
282 : };
283 7813 : }
284 : /**
285 : * @}
286 : */
287 :
288 : /**
289 : * Formats a documented error. A documented error is an error that has
290 : * an issue associated with it.
291 : *
292 : * The repository name \p repo_name links a named repository to a URL
293 : * and should be registered at the application level with registerRepository().
294 : * See Moose.C for an example of the "moose" repository registration.
295 : *
296 : * @param repo_name The repository name where the issue resides
297 : * @param issue_num The number of the issue
298 : * @param msg The specific error message
299 : */
300 : std::string formatMooseDocumentedError(const std::string & repo_name,
301 : const unsigned int issue_num,
302 : const std::string & msg);
303 : } // namespace internal
304 :
305 : /**
306 : * emit a relatively clear error message when we catch a MetaPhysicL logic error
307 : */
308 : void translateMetaPhysicLError(const MetaPhysicL::LogicError &);
309 :
310 : } // namespace moose
311 :
312 : /// Emit an error message with the given stringified, concatenated args and
313 : /// terminate the application. Inside static functions, you will need to
314 : /// explicitly scope your mooseError call - i.e. do "::mooseError(arg1, ...);".
315 : template <typename... Args>
316 : [[noreturn]] void
317 1492 : mooseError(Args &&... args)
318 : {
319 1492 : std::ostringstream oss;
320 1492 : moose::internal::mooseStreamAll(oss, std::forward<Args>(args)...);
321 2834 : moose::internal::mooseErrorRaw(oss.str());
322 671 : }
323 :
324 : /**
325 : * Emit a documented error message with the given stringified, concatenated args
326 : * and terminate the application. Inside static functions, you will need to
327 : * explicitly scope your mooseError call - i.e. do "::mooseError(arg1, ...);".
328 : *
329 : * Here, a documented error message is one with an associated issue. See
330 : * formatMooseDocumentedError for more information.
331 : *
332 : * @param repo_name The repository name where the issue resides
333 : * @param issue_num The number of the issue
334 : * @param args The error message to stringify
335 : **/
336 : template <typename... Args>
337 : [[noreturn]] void
338 2 : mooseDocumentedError(const std::string & repo_name, const unsigned int issue_num, Args &&... args)
339 : {
340 2 : std::ostringstream oss;
341 2 : moose::internal::mooseStreamAll(oss, std::forward<Args>(args)...);
342 8 : moose::internal::mooseErrorRaw(
343 : moose::internal::formatMooseDocumentedError(repo_name, issue_num, oss.str()));
344 2 : }
345 :
346 : /// Emit a warning message with the given stringified, concatenated args.
347 : /// Inside static functions, you will need to explicitly scope your
348 : /// mooseWarning call - i.e. do "::mooseWarning(arg1, ...);".
349 : template <typename... Args>
350 : void
351 1077 : mooseWarning(Args &&... args)
352 : {
353 1077 : moose::internal::mooseWarningStream(Moose::out, std::forward<Args>(args)...);
354 1044 : }
355 :
356 : /// Warning message used to notify the users of unused parts of their input files
357 : /// Really used internally by the parser and shouldn't really be called elsewhere
358 : template <typename... Args>
359 : void
360 51 : mooseUnused(Args &&... args)
361 : {
362 51 : moose::internal::mooseUnusedStream(Moose::out, std::forward<Args>(args)...);
363 51 : }
364 :
365 : /// Emit a deprecated code/feature message with the given stringified, concatenated args.
366 : /// Will include a stack trace; use mooseDeprecatedNoTrace to exclude the trace.
367 : template <typename... Args>
368 : void
369 3689 : mooseDeprecated(Args &&... args)
370 : {
371 3689 : moose::internal::mooseDeprecatedStream(
372 : Moose::out, false, true, true, std::forward<Args>(args)...);
373 3687 : }
374 :
375 : /// Emit a deprecated code/feature message with the given stringified, concatenated args.
376 : /// Will not include a stack trace; use mooseDeprecated to include the trace.
377 : template <typename... Args>
378 : void
379 550 : mooseDeprecatedNoTrace(Args &&... args)
380 : {
381 550 : moose::internal::mooseDeprecatedStream(
382 : Moose::out, false, true, false, std::forward<Args>(args)...);
383 550 : }
384 :
385 : /// Emit a deprecated code/feature message with the given stringified, concatenated args.
386 : /// Will include a stack trace; use mooseDeprecationExpiredNoTrace to exclude the trace.
387 : template <typename... Args>
388 : void
389 : mooseDeprecationExpired(Args &&... args)
390 : {
391 : moose::internal::mooseDeprecatedStream(Moose::out, true, true, true, std::forward<Args>(args)...);
392 : }
393 :
394 : /// Emit a deprecated code/feature message with the given stringified, concatenated args.
395 : /// Will not include a stack trace; use mooseDeprecationExpired to include the trace.
396 : template <typename... Args>
397 : void
398 1476 : mooseDeprecationExpiredNoTrace(Args &&... args)
399 : {
400 1476 : moose::internal::mooseDeprecatedStream(
401 : Moose::out, true, true, false, std::forward<Args>(args)...);
402 1473 : }
403 :
404 : /// Emit an informational message with the given stringified, concatenated args.
405 : template <typename... Args>
406 : void
407 224 : mooseInfo(Args &&... args)
408 : {
409 224 : moose::internal::mooseInfoStream(Moose::out, std::forward<Args>(args)...);
410 224 : }
411 :
412 : /// Emit an informational message with the given stringified, concatenated args.
413 : template <typename... Args>
414 : void
415 3861 : mooseInfoRepeated(Args &&... args)
416 : {
417 3861 : moose::internal::mooseInfoStreamRepeated(Moose::out, std::forward<Args>(args)...);
418 3861 : }
|