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 : // this function allows streaming tuples to ostreams
33 : template <size_t n, typename... T>
34 : void
35 : print_tuple(std::ostream & os, const std::tuple<T...> & tup)
36 : {
37 : if constexpr (n < sizeof...(T))
38 : {
39 : if (n != 0)
40 : os << ", ";
41 : os << std::get<n>(tup);
42 : print_tuple<n + 1>(os, tup);
43 : }
44 : }
45 : template <typename... T>
46 : std::ostream &
47 : operator<<(std::ostream & os, const std::tuple<T...> & tup)
48 : {
49 : os << "[";
50 : print_tuple<0>(os, tup);
51 : return os << "]";
52 : }
53 :
54 : /// Application abort macro. Uses MPI_Abort if available, std::abort otherwise
55 : #if defined(LIBMESH_HAVE_MPI)
56 : #define MOOSE_ABORT \
57 : do \
58 : { \
59 : MPI_Abort(libMesh::GLOBAL_COMM_WORLD, 1); \
60 : std::abort(); \
61 : } while (0)
62 : #else
63 : #define MOOSE_ABORT \
64 : do \
65 : { \
66 : std::abort(); \
67 : } while (0)
68 : #endif
69 :
70 : #define mooseDoOnce(do_this) \
71 : do \
72 : { \
73 : static bool did_this_already = false; \
74 : if (Moose::show_multiple || !did_this_already) \
75 : { \
76 : did_this_already = true; \
77 : do_this; \
78 : } \
79 : } while (0)
80 :
81 : #define mooseCheckMPIErr(err) \
82 : do \
83 : { \
84 : if (err != MPI_SUCCESS) \
85 : { \
86 : if (libMesh::global_n_processors() == 1) \
87 : libMesh::print_trace(); \
88 : libmesh_here(); \
89 : MOOSE_ABORT; \
90 : } \
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 : if (libMesh::global_n_processors() == 1) \
117 : libMesh::print_trace(); \
118 : else \
119 : libMesh::write_traceout(); \
120 : libmesh_here(); \
121 : MOOSE_ABORT; \
122 : } \
123 : } \
124 : } while (0)
125 : #endif
126 :
127 : template <typename... Args>
128 : [[noreturn]] void mooseError(Args &&... args);
129 :
130 : class MooseVariableFieldBase;
131 :
132 : namespace moose
133 : {
134 :
135 : namespace internal
136 : {
137 : inline libMesh::Threads::spin_mutex moose_stream_lock;
138 :
139 : /// Builds and returns a string of the form:
140 : ///
141 : /// [var1-elemtype],ORDER[var1-order] != [var2-elemtype],ORDER[var2-order]
142 : ///
143 : /// This is a convenience function to be used when error messages (especially with paramError)
144 : /// need to report that variable types are incompatible (e.g. with residual save-in).
145 : std::string incompatVarMsg(MooseVariableFieldBase & var1, MooseVariableFieldBase & var2);
146 :
147 : /**
148 : * Format a message for output with a title
149 : * @param msg The message to print
150 : * @param title The title that will go on a line before the message
151 : * @param color The color to print the message in
152 : * @return The formatted message
153 : */
154 : std::string
155 : mooseMsgFmt(const std::string & msg, const std::string & title, const std::string & color);
156 :
157 : /**
158 : * Format a message for output without a title
159 : * @param msg The message to print
160 : * @param color The color to print the message in
161 : * @return The formatted message
162 : */
163 : std::string mooseMsgFmt(const std::string & msg, const std::string & color);
164 :
165 : [[noreturn]] void mooseErrorRaw(std::string msg, const std::string prefix = "");
166 :
167 : /**
168 : * All of the following are not meant to be called directly - they are called by the normal macros
169 : * (mooseError(), etc.) down below
170 : * @{
171 : */
172 : void mooseStreamAll(std::ostringstream & ss);
173 :
174 : template <typename T, typename... Args>
175 : void
176 66387 : mooseStreamAll(std::ostringstream & ss, T && val, Args &&... args)
177 : {
178 66387 : ss << val;
179 66387 : mooseStreamAll(ss, std::forward<Args>(args)...);
180 66387 : }
181 :
182 : template <typename S, typename... Args>
183 : void
184 3520 : mooseWarningStream(S & oss, Args &&... args)
185 : {
186 3520 : if (Moose::_warnings_are_errors)
187 194 : mooseError(std::forward<Args>(args)...);
188 :
189 3326 : std::ostringstream ss;
190 3326 : mooseStreamAll(ss, args...);
191 3326 : std::string msg = mooseMsgFmt(ss.str(), "*** Warning ***", COLOR_YELLOW);
192 3326 : if (Moose::_throw_on_warning)
193 4 : throw std::runtime_error(msg);
194 :
195 : {
196 3322 : libMesh::Threads::spin_mutex::scoped_lock lock(moose_stream_lock);
197 3322 : oss << msg << std::flush;
198 3322 : }
199 3330 : }
200 :
201 : template <typename S, typename... Args>
202 : void
203 49 : mooseUnusedStream(S & oss, Args &&... args)
204 : {
205 49 : std::ostringstream ss;
206 49 : mooseStreamAll(ss, args...);
207 49 : std::string msg = mooseMsgFmt(ss.str(), "*** Warning ***", COLOR_YELLOW);
208 49 : if (Moose::_throw_on_warning)
209 0 : throw std::runtime_error(msg);
210 :
211 : {
212 49 : libMesh::Threads::spin_mutex::scoped_lock lock(moose_stream_lock);
213 49 : oss << msg << std::flush;
214 49 : }
215 49 : }
216 :
217 : template <typename S, typename... Args>
218 : void
219 15817 : mooseInfoStreamRepeated(S & oss, Args &&... args)
220 : {
221 15817 : std::ostringstream ss;
222 15817 : mooseStreamAll(ss, args...);
223 15817 : std::string msg = mooseMsgFmt(ss.str(), "*** Info ***", COLOR_CYAN);
224 : {
225 15817 : libMesh::Threads::spin_mutex::scoped_lock lock(moose_stream_lock);
226 15817 : oss << msg << std::flush;
227 15817 : }
228 15817 : }
229 :
230 : template <typename S, typename... Args>
231 : void
232 7099 : mooseInfoStream(S & oss, Args &&... args)
233 : {
234 7099 : mooseDoOnce(mooseInfoStreamRepeated(oss, args...););
235 7099 : }
236 :
237 : template <typename S, typename... Args>
238 : void
239 14061 : mooseDeprecatedStream(S & oss, const bool expired, const bool print_title, Args &&... args)
240 : {
241 14061 : if (Moose::_deprecated_is_error)
242 13 : mooseError("\n\nDeprecated code:\n", std::forward<Args>(args)...);
243 :
244 14048 : std::ostringstream ss;
245 14048 : mooseStreamAll(ss, args...);
246 :
247 14048 : const auto color = expired ? COLOR_RED : COLOR_YELLOW;
248 14048 : std::string msg =
249 : print_title
250 14048 : ? mooseMsgFmt(
251 : ss.str(),
252 : "*** Warning, This code is deprecated and will be removed in future versions:",
253 : color)
254 : : mooseMsgFmt(ss.str(), color);
255 14048 : oss << msg;
256 14048 : ss.str("");
257 14048 : if (Moose::show_trace)
258 : {
259 11469 : if (libMesh::global_n_processors() == 1)
260 6391 : libMesh::print_trace(ss);
261 : else
262 5078 : libMesh::write_traceout();
263 : {
264 11469 : libMesh::Threads::spin_mutex::scoped_lock lock(moose_stream_lock);
265 11469 : oss << ss.str() << std::endl;
266 11469 : };
267 : };
268 14048 : }
269 : /**
270 : * @}
271 : */
272 :
273 : /**
274 : * Formats a documented error. A documented error is an error that has
275 : * an issue associated with it.
276 : *
277 : * The repository name \p repo_name links a named repository to a URL
278 : * and should be registered at the application level with registerRepository().
279 : * See Moose.C for an example of the "moose" repository registration.
280 : *
281 : * @param repo_name The repository name where the issue resides
282 : * @param issue_num The number of the issue
283 : * @param msg The specific error message
284 : */
285 : std::string formatMooseDocumentedError(const std::string & repo_name,
286 : const unsigned int issue_num,
287 : const std::string & msg);
288 : } // namespace internal
289 :
290 : /**
291 : * emit a relatively clear error message when we catch a MetaPhysicL logic error
292 : */
293 : void translateMetaPhysicLError(const MetaPhysicL::LogicError &);
294 :
295 : } // namespace moose
296 :
297 : /// Emit an error message with the given stringified, concatenated args and
298 : /// terminate the application. Inside static functions, you will need to
299 : /// explicitly scope your mooseError call - i.e. do "::mooseError(arg1, ...);".
300 : template <typename... Args>
301 : [[noreturn]] void
302 1406 : mooseError(Args &&... args)
303 : {
304 1406 : std::ostringstream oss;
305 1406 : moose::internal::mooseStreamAll(oss, std::forward<Args>(args)...);
306 2048 : moose::internal::mooseErrorRaw(oss.str());
307 214 : }
308 :
309 : /**
310 : * Emit a documented error message with the given stringified, concatenated args
311 : * and terminate the application. Inside static functions, you will need to
312 : * explicitly scope your mooseError call - i.e. do "::mooseError(arg1, ...);".
313 : *
314 : * Here, a documented error message is one with an associated issue. See
315 : * formatMooseDocumentedError for more information.
316 : *
317 : * @param repo_name The repository name where the issue resides
318 : * @param issue_num The number of the issue
319 : * @param args The error message to stringify
320 : **/
321 : template <typename... Args>
322 : [[noreturn]] void
323 1 : mooseDocumentedError(const std::string & repo_name, const unsigned int issue_num, Args &&... args)
324 : {
325 1 : std::ostringstream oss;
326 1 : moose::internal::mooseStreamAll(oss, std::forward<Args>(args)...);
327 5 : moose::internal::mooseErrorRaw(
328 : moose::internal::formatMooseDocumentedError(repo_name, issue_num, oss.str()));
329 1 : }
330 :
331 : /// Emit a warning message with the given stringified, concatenated args.
332 : /// Inside static functions, you will need to explicitly scope your
333 : /// mooseWarning call - i.e. do "::mooseWarning(arg1, ...);".
334 : template <typename... Args>
335 : void
336 1138 : mooseWarning(Args &&... args)
337 : {
338 1138 : moose::internal::mooseWarningStream(Moose::out, std::forward<Args>(args)...);
339 1099 : }
340 :
341 : /// Warning message used to notify the users of unused parts of their input files
342 : /// Really used internally by the parser and shouldn't really be called elsewhere
343 : template <typename... Args>
344 : void
345 49 : mooseUnused(Args &&... args)
346 : {
347 49 : moose::internal::mooseUnusedStream(Moose::out, std::forward<Args>(args)...);
348 49 : }
349 :
350 : /// Emit a deprecated code/feature message with the given stringified, concatenated args.
351 : template <typename... Args>
352 : void
353 10475 : mooseDeprecated(Args &&... args)
354 : {
355 10475 : moose::internal::mooseDeprecatedStream(Moose::out, false, true, std::forward<Args>(args)...);
356 10474 : }
357 :
358 : /// Emit a deprecated code/feature message with the given stringified, concatenated args.
359 : template <typename... Args>
360 : void
361 1018 : mooseDeprecationExpired(Args &&... args)
362 : {
363 1018 : moose::internal::mooseDeprecatedStream(Moose::out, true, true, std::forward<Args>(args)...);
364 1014 : }
365 :
366 : /// Emit an informational message with the given stringified, concatenated args.
367 : template <typename... Args>
368 : void
369 703 : mooseInfo(Args &&... args)
370 : {
371 703 : moose::internal::mooseInfoStream(Moose::out, std::forward<Args>(args)...);
372 703 : }
373 :
374 : /// Emit an informational message with the given stringified, concatenated args.
375 : template <typename... Args>
376 : void
377 11104 : mooseInfoRepeated(Args &&... args)
378 : {
379 11104 : moose::internal::mooseInfoStreamRepeated(Moose::out, std::forward<Args>(args)...);
380 11104 : }
|