Line data Source code
1 : // The libMesh Finite Element Library.
2 : // Copyright (C) 2002-2026 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
3 :
4 : // This library is free software; you can redistribute it and/or
5 : // modify it under the terms of the GNU Lesser General Public
6 : // License as published by the Free Software Foundation; either
7 : // version 2.1 of the License, or (at your option) any later version.
8 :
9 : // This library is distributed in the hope that it will be useful,
10 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 : // Lesser General Public License for more details.
13 :
14 : // You should have received a copy of the GNU Lesser General Public
15 : // License along with this library; if not, write to the Free Software
16 : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 :
18 :
19 :
20 : #ifndef LIBMESH_LIBMESH_COMMON_H
21 : #define LIBMESH_LIBMESH_COMMON_H
22 :
23 : // These flags should never be used together. -DDEBUG means "turn on
24 : // all the ridiculously expensive error checking"; -DNDEBUG means
25 : // "turn off all the somewhat affordable error checking"
26 : #if defined(DEBUG) && defined(NDEBUG)
27 : # error DEBUG and NDEBUG should never be defined simultaneously
28 : #endif
29 :
30 : // The library configuration options
31 : #include "libmesh/libmesh_config.h"
32 :
33 : // Use actual timestamps or constant dummies (to aid ccache)
34 : #ifdef LIBMESH_ENABLE_TIMESTAMPS
35 : # define LIBMESH_TIME __TIME__
36 : # define LIBMESH_DATE __DATE__
37 : #else
38 : # define LIBMESH_TIME "notime"
39 : # define LIBMESH_DATE "nodate"
40 : #endif
41 :
42 : // C/C++ includes everyone should know about
43 : #include <cstdlib>
44 : #ifdef __PGI
45 : // BSK, Thu Feb 20 08:32:06 CST 2014 - For some reason, unless PGI gets
46 : // <cmath> early this nonsense shows up:
47 : // "/software/x86_64/pgi/12.9/linux86-64/12.9/include/CC/cmath", line 57: error:
48 : // the global scope has no "abs"
49 : // using _STLP_VENDOR_CSTD::abs;
50 : // So include <cmath> as early as possible under the PGI compilers.
51 : # include <cmath>
52 : #endif
53 : #include <complex>
54 : #include <typeinfo> // std::bad_cast
55 : #include <type_traits> // std::decay
56 : #include <functional> // std::less, etc
57 : #include <string>
58 :
59 : // Include the MPI definition
60 : #ifdef LIBMESH_HAVE_MPI
61 : # include "libmesh/ignore_warnings.h"
62 : # include <mpi.h>
63 : # include "libmesh/restore_warnings.h"
64 : #endif
65 :
66 : // Quad precision if we need it
67 : #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
68 : #include "libmesh/float128_shims.h"
69 : #endif
70 :
71 : // _basic_ library functionality
72 : #include "libmesh/libmesh_base.h"
73 : #include "libmesh/libmesh_exceptions.h"
74 :
75 : // Proxy class for libMesh::out/err output
76 : #include "libmesh/ostream_proxy.h"
77 :
78 : // Make sure the libmesh_nullptr define is available for backwards
79 : // compatibility, although we no longer use it in the library.
80 : #include "libmesh/libmesh_nullptr.h"
81 :
82 : // C++ headers
83 : #include <iomanip> // setprecision, in assertion macros
84 :
85 : namespace libMesh
86 : {
87 : namespace Threads
88 : {
89 : // For thread-safe error-messaging. Definitions in threads.h
90 : void lock_singleton_spin_mutex();
91 : void unlock_singleton_spin_mutex();
92 : }
93 :
94 : // Let's define a couple output streams - these will default
95 : // to cout/cerr, but LibMeshInit (or the user) can also set them to
96 : // something more sophisticated.
97 : //
98 : // We use a proxy class rather than references so they can be
99 : // reseated at runtime.
100 :
101 : extern OStreamProxy out;
102 : extern OStreamProxy err;
103 :
104 : // A namespace for functions used in the bodies of the macros below.
105 : // The macros generally call these functions with __FILE__, __LINE__,
106 : // __DATE__, and __TIME__ in the appropriate order. These should not
107 : // be called by users directly! The implementations can be found in
108 : // libmesh_common.C.
109 : namespace MacroFunctions
110 : {
111 : void here(const char * file, int line, const char * date, const char * time, std::ostream & os = libMesh::err);
112 : void stop(const char * file, int line, const char * date, const char * time);
113 : void report_error(const char * file, int line, const char * date, const char * time, std::ostream & os = libMesh::err);
114 : }
115 :
116 : // Undefine any existing macros
117 : #ifdef Real
118 : # undef Real
119 : #endif
120 :
121 : //#ifdef REAL
122 : //# undef REAL
123 : //#endif
124 :
125 : #ifdef Complex
126 : # undef Complex
127 : #endif
128 :
129 : #ifdef COMPLEX
130 : # undef COMPLEX
131 : #endif
132 :
133 : // Check to see if TOLERANCE has been defined by another
134 : // package, if so we might want to change the name...
135 : #ifdef TOLERANCE
136 : DIE A HORRIBLE DEATH HERE...
137 : # undef TOLERANCE
138 : #endif
139 :
140 :
141 :
142 : // Define the type to use for real numbers
143 :
144 : typedef LIBMESH_DEFAULT_SCALAR_TYPE Real;
145 :
146 : // Define a corresponding tolerance. This is what should be
147 : // considered "good enough" when doing floating point comparisons.
148 : // For example, v == 0 is changed to std::abs(v) < TOLERANCE.
149 :
150 : #ifdef LIBMESH_DEFAULT_SINGLE_PRECISION
151 : static constexpr Real TOLERANCE = 2.5e-3;
152 : # if defined (LIBMESH_DEFAULT_TRIPLE_PRECISION) || \
153 : defined (LIBMESH_DEFAULT_QUADRUPLE_PRECISION)
154 : # error Cannot define multiple precision levels
155 : # endif
156 : #endif
157 :
158 : #ifdef LIBMESH_DEFAULT_TRIPLE_PRECISION
159 : static constexpr Real TOLERANCE = 1.e-8;
160 : # if defined (LIBMESH_DEFAULT_QUADRUPLE_PRECISION)
161 : # error Cannot define multiple precision levels
162 : # endif
163 : #endif
164 :
165 : #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
166 : static constexpr Real TOLERANCE = 1.e-11;
167 : #endif
168 :
169 : #if !defined (LIBMESH_DEFAULT_SINGLE_PRECISION) && \
170 : !defined (LIBMESH_DEFAULT_TRIPLE_PRECISION) && \
171 : !defined (LIBMESH_DEFAULT_QUADRUPLE_PRECISION)
172 : static constexpr Real TOLERANCE = 1.e-6;
173 : #endif
174 :
175 : // Define the type to use for complex numbers
176 : // Always use std::complex<double>, as required by Petsc?
177 : // If your version of Petsc doesn't support
178 : // std::complex<other_precision>, then you'd better just leave
179 : // Real==double
180 : typedef std::complex<Real> Complex;
181 : typedef std::complex<Real> COMPLEX;
182 :
183 :
184 : // Helper functions for complex/real number components, to clean up
185 : // #ifdef LIBMESH_USE_COMPLEX_NUMBERS elsewhere
186 : //
187 : // Some of these are just backwards compatibility shims for old code
188 : // that predated C++11
189 20240710 : template<typename T> inline T libmesh_real(T a) { return a; }
190 : template<typename T> inline T libmesh_imag(T /*a*/) { return 0; }
191 36672082 : template<typename T> inline T libmesh_conj(T a) { return a; }
192 :
193 : template<typename T>
194 0 : inline T libmesh_real(std::complex<T> a) { return std::real(a); }
195 :
196 : template<typename T>
197 : inline T libmesh_imag(std::complex<T> a) { return std::imag(a); }
198 :
199 : template<typename T>
200 : inline std::complex<T> libmesh_conj(std::complex<T> a) { return std::conj(a); }
201 :
202 : // Helper functions for complex/real number classification, because
203 : // for some reason std:: never added isfinite/isinf/isnan overloads
204 : // for std::complex.
205 :
206 : template <typename T>
207 656 : inline bool libmesh_isinf(T x) { using std::isinf; return isinf(x); }
208 :
209 : template <typename T>
210 203273 : inline bool libmesh_isnan(T x) { using std::isnan; return isnan(x); }
211 :
212 : // You'd think we'd treat inf,NaN pairs as NaN rather than infinite,
213 : // but that's not what the C/C++ standards recommend (ever since C99
214 : // Annex G), so we'll follow their lead.
215 : //
216 : // Anyone who doesn't care about these subtle NaN/inf distinctions
217 : // should just test isfinite() in their code, and can also probably
218 : // speed up their arithmetic greatly by using -fcx-limited-range
219 : // and/or -fcx-fortran-rules
220 : template <typename T>
221 : inline bool libmesh_isinf(std::complex<T> a)
222 : { return (std::isinf(std::real(a)) || std::isinf(std::imag(a))); }
223 :
224 : // Treats inf,NaN pairs as infinite rather than NaN
225 : template <typename T>
226 42964 : inline bool libmesh_isnan(std::complex<T> a)
227 42964 : { return ((std::isnan(std::real(a)) || std::isnan(std::imag(a))) &&
228 42964 : !std::isinf(std::real(a)) && !std::isinf(std::imag(a))); }
229 :
230 : template <typename T>
231 : inline bool isfinite(std::complex<T> a)
232 : {
233 : return (std::isfinite(std::real(a)) && std::isfinite(std::imag(a)));
234 : }
235 :
236 : template <typename T>
237 : inline bool isinf(std::complex<T> a)
238 : {
239 : return (std::isinf(std::real(a)) || std::isinf(std::imag(a)));
240 : }
241 :
242 : template <typename T>
243 : inline bool isnan(std::complex<T> a)
244 : {
245 : { return ((std::isnan(std::real(a)) || std::isnan(std::imag(a))) &&
246 : !std::isinf(std::real(a)) && !std::isinf(std::imag(a))); }
247 : }
248 :
249 : // Define the value type for unknowns in simulations.
250 : // This is either Real or Complex, depending on how
251 : // the library was configures
252 : #if defined (LIBMESH_USE_REAL_NUMBERS)
253 : typedef Real Number;
254 : #elif defined (LIBMESH_USE_COMPLEX_NUMBERS)
255 : typedef Complex Number;
256 : #else
257 : DIE A HORRIBLE DEATH HERE...
258 : #endif
259 :
260 :
261 : // Define the value type for error estimates.
262 : // Since AMR/C decisions don't have to be precise,
263 : // we default to float for memory efficiency.
264 : typedef float ErrorVectorReal;
265 : #define MPI_ERRORVECTORREAL MPI_FLOAT
266 :
267 :
268 : #ifdef LIBMESH_HAVE_MPI
269 :
270 : /**
271 : * MPI Communicator used to initialize libMesh.
272 : */
273 : extern MPI_Comm GLOBAL_COMM_WORLD;
274 : #else
275 :
276 : /**
277 : * Something to use with CHKERRABORT if we're just using PETSc's MPI
278 : * "uni" stub.
279 : */
280 : extern int GLOBAL_COMM_WORLD;
281 : #endif
282 :
283 : // This global variable is to help us deprecate AutoPtr. We can't
284 : // just use libmesh_deprecated() because then you get one print out
285 : // per template instantiation, instead of one total print out.
286 : extern bool warned_about_auto_ptr;
287 :
288 : // These are useful macros that behave like functions in the code.
289 : // If you want to make sure you are accessing a section of code just
290 : // stick a libmesh_here(); in it, for example
291 : #define libmesh_here() \
292 : do { \
293 : libMesh::MacroFunctions::here(__FILE__, __LINE__, LIBMESH_DATE, LIBMESH_TIME); \
294 : } while (0)
295 :
296 : // the libmesh_stop() macro will stop the code until a SIGCONT signal
297 : // is received. This is useful, for example, when determining the
298 : // memory used by a given operation. A libmesh_stop() could be
299 : // inserted before and after a questionable operation and the delta
300 : // memory can be obtained from a ps or top. This macro only works for
301 : // serial cases.
302 : #define libmesh_stop() \
303 : do { \
304 : libMesh::MacroFunctions::stop(__FILE__, __LINE__, LIBMESH_DATE, LIBMESH_TIME); \
305 : } while (0)
306 :
307 : // The libmesh_dbg_var() macro indicates that an argument to a function
308 : // is used only in debug and devel modes (i.e., when NDEBUG is not defined).
309 : #ifndef NDEBUG
310 : #define libmesh_dbg_var(var) var
311 : #else
312 : #define libmesh_dbg_var(var)
313 : #endif
314 :
315 : // The libmesh_inf_var() macro indicates that an argument to a function
316 : // is used only when infinite elements are enabled
317 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
318 : #define libmesh_inf_var(var) var
319 : #else
320 : #define libmesh_inf_var(var)
321 : #endif
322 :
323 : // The libmesh_assert() macro acts like C's assert(), but throws a
324 : // libmesh_error() (including stack trace, etc) instead of just exiting
325 : #ifdef NDEBUG
326 :
327 : #define libmesh_assert_msg(asserted, msg) ((void) 0)
328 : #define libmesh_exceptionless_assert_msg(asserted, msg) ((void) 0)
329 : #define libmesh_assert_equal_to_msg(expr1,expr2, msg) ((void) 0)
330 : #define libmesh_assert_not_equal_to_msg(expr1,expr2, msg) ((void) 0)
331 : #define libmesh_assert_less_msg(expr1,expr2, msg) ((void) 0)
332 : #define libmesh_assert_greater_msg(expr1,expr2, msg) ((void) 0)
333 : #define libmesh_assert_less_equal_msg(expr1,expr2, msg) ((void) 0)
334 : #define libmesh_assert_greater_equal_msg(expr1,expr2, msg) ((void) 0)
335 :
336 : #else
337 :
338 : #define libmesh_assertion_types(expr1,expr2) \
339 : typedef typename std::decay<decltype(expr1)>::type libmesh_type1; \
340 : typedef typename std::decay<decltype(expr2)>::type libmesh_type2
341 :
342 : #define libmesh_assert_msg(asserted, msg) \
343 : do { \
344 : if (!(asserted)) { \
345 : libmesh_error_msg("Assertion `" #asserted "' failed.\n" << msg); \
346 : } } while (0)
347 :
348 : #define libmesh_exceptionless_assert_msg(asserted, msg) \
349 : do { \
350 : if (!(asserted)) { \
351 : libMesh::Threads::lock_singleton_spin_mutex(); \
352 : libMesh::err << "Assertion `" #asserted "' failed." << std::endl; \
353 : libMesh::Threads::unlock_singleton_spin_mutex(); \
354 : libmesh_exceptionless_error(); \
355 : } } while (0)
356 :
357 : #define libmesh_assert_equal_to_msg(expr1,expr2, msg) \
358 : do { \
359 : if (!((expr1) == (expr2))) { \
360 : libmesh_error_msg(std::setprecision(17) << "Assertion `" #expr1 " == " #expr2 "' failed.\n" #expr1 " = " << (expr1) << "\n" #expr2 " = " << (expr2) << '\n' << msg << std::endl); \
361 : } } while (0)
362 :
363 : #define libmesh_assert_not_equal_to_msg(expr1,expr2, msg) \
364 : do { \
365 : if (!((expr1) != (expr2))) { \
366 : libmesh_error_msg(std::setprecision(17) << "Assertion `" #expr1 " != " #expr2 "' failed.\n" #expr1 " = " << (expr1) << "\n" #expr2 " = " << (expr2) << '\n' << msg << std::endl); \
367 : } } while (0)
368 :
369 : template <template <class> class Comp>
370 : struct casting_compare {
371 :
372 : template <typename T1, typename T2>
373 1023531364 : bool operator()(const T1 & e1, const T2 & e2) const
374 : {
375 : typedef typename std::decay<T1>::type DT1;
376 : typedef typename std::decay<T2>::type DT2;
377 2047062728 : return (Comp<DT2>()(static_cast<DT2>(e1), e2) &&
378 2047062728 : Comp<DT1>()(e1, static_cast<DT1>(e2)));
379 : }
380 :
381 : template <typename T1>
382 185868095 : bool operator()(const T1 & e1, const T1 & e2) const
383 : {
384 185868095 : return Comp<T1>()(e1, e2);
385 : }
386 : };
387 :
388 : #define libmesh_assert_less_msg(expr1,expr2, msg) \
389 : do { \
390 : if (!libMesh::casting_compare<std::less>()(expr1, expr2)) { \
391 : libmesh_error_msg(std::setprecision(17) << "Assertion `" #expr1 " < " #expr2 "' failed.\n" #expr1 " = " << (expr1) << "\n" #expr2 " = " << (expr2) << '\n' << msg << std::endl); \
392 : } } while (0)
393 :
394 : #define libmesh_assert_greater_msg(expr1,expr2, msg) \
395 : do { \
396 : if (!libMesh::casting_compare<std::greater>()(expr1, expr2)) { \
397 : libmesh_error_msg(std::setprecision(17) << "Assertion `" #expr1 " > " #expr2 "' failed.\n" #expr1 " = " << (expr1) << "\n" #expr2 " = " << (expr2) << '\n' << msg << std::endl); \
398 : } } while (0)
399 :
400 : #define libmesh_assert_less_equal_msg(expr1,expr2, msg) \
401 : do { \
402 : if (!libMesh::casting_compare<std::less_equal>()(expr1, expr2)) { \
403 : libmesh_error_msg(std::setprecision(17) << "Assertion `" #expr1 " <= " #expr2 "' failed.\n" #expr1 " = " << (expr1) << "\n" #expr2 " = " << (expr2) << '\n' << msg << std::endl); \
404 : } } while (0)
405 :
406 : #define libmesh_assert_greater_equal_msg(expr1,expr2, msg) \
407 : do { \
408 : if (!libMesh::casting_compare<std::greater_equal>()(expr1, expr2)) { \
409 : libmesh_error_msg(std::setprecision(17) << "Assertion `" #expr1 " >= " #expr2 "' failed.\n" #expr1 " = " << (expr1) << "\n" #expr2 " = " << (expr2) << '\n' << msg << std::endl); \
410 : } } while (0)
411 :
412 : #endif
413 :
414 :
415 : #define libmesh_assert(asserted) libmesh_assert_msg(asserted, "")
416 : #define libmesh_exceptionless_assert(asserted) libmesh_exceptionless_assert_msg(asserted, "")
417 : #define libmesh_assert_equal_to(expr1,expr2) libmesh_assert_equal_to_msg(expr1,expr2, "")
418 : #define libmesh_assert_not_equal_to(expr1,expr2) libmesh_assert_not_equal_to_msg(expr1,expr2, "")
419 : #define libmesh_assert_less(expr1,expr2) libmesh_assert_less_msg(expr1,expr2, "")
420 : #define libmesh_assert_greater(expr1,expr2) libmesh_assert_greater_msg(expr1,expr2, "")
421 : #define libmesh_assert_less_equal(expr1,expr2) libmesh_assert_less_equal_msg(expr1,expr2, "")
422 : #define libmesh_assert_greater_equal(expr1,expr2) libmesh_assert_greater_equal_msg(expr1,expr2, "")
423 :
424 : // The libmesh_error() macro prints a message and throws a LogicError
425 : // exception
426 : //
427 : // The libmesh_not_implemented() macro prints a message and throws a
428 : // NotImplemented exception
429 : //
430 : // The libmesh_file_error(const std::string & filename) macro prints a message
431 : // and throws a FileError exception
432 : //
433 : // The libmesh_convergence_failure() macro
434 : // throws a ConvergenceFailure exception
435 : //
436 : // The libmesh_degenerate_mapping() macro prints a message into and
437 : // throws a DegenerateMap exception
438 : //
439 : // The libmesh_terminate() macro prints a message and throws a
440 : // TerminationException exception
441 : #define libmesh_error_msg(msg) \
442 : do { \
443 : std::stringstream message_stream; \
444 : message_stream << msg << '\n'; \
445 : libMesh::MacroFunctions::report_error(__FILE__, __LINE__, LIBMESH_DATE, LIBMESH_TIME, message_stream); \
446 : LIBMESH_THROW(libMesh::LogicError(message_stream.str())); \
447 : } while (0)
448 :
449 : #define libmesh_error() libmesh_error_msg("")
450 :
451 : #define libmesh_error_msg_if(cond, msg) \
452 : do { \
453 : if (cond) \
454 : libmesh_error_msg(msg); \
455 : } while (0)
456 :
457 : #define libmesh_exceptionless_error_msg(msg) \
458 : do { \
459 : libMesh::Threads::lock_singleton_spin_mutex(); \
460 : libMesh::err << msg << '\n'; \
461 : libMesh::Threads::unlock_singleton_spin_mutex(); \
462 : libmesh_try { libMesh::MacroFunctions::report_error(__FILE__, __LINE__, LIBMESH_DATE, LIBMESH_TIME); } \
463 : libmesh_catch (...) {} \
464 : std::terminate(); \
465 : } while (0)
466 :
467 : #define libmesh_exceptionless_error() libmesh_exceptionless_error_msg("")
468 :
469 : #define libmesh_not_implemented_msg(msg) \
470 : do { \
471 : std::stringstream message_stream; \
472 : message_stream << msg << '\n'; \
473 : libMesh::MacroFunctions::report_error(__FILE__, __LINE__, LIBMESH_DATE, LIBMESH_TIME, message_stream); \
474 : LIBMESH_THROW(libMesh::NotImplemented(message_stream.str())); \
475 : } while (0)
476 :
477 : #define libmesh_not_implemented() libmesh_not_implemented_msg("")
478 :
479 : #define libmesh_file_error_msg(filename, msg) \
480 : do { \
481 : std::stringstream message_stream; \
482 : message_stream << msg << '\n'; \
483 : libMesh::MacroFunctions::report_error(__FILE__, __LINE__, LIBMESH_DATE, LIBMESH_TIME, message_stream); \
484 : LIBMESH_THROW(libMesh::FileError(filename, message_stream.str())); \
485 : } while (0)
486 :
487 : #define libmesh_file_error(filename) libmesh_file_error_msg(filename,"")
488 :
489 : #define libmesh_convergence_failure() \
490 : do { \
491 : LIBMESH_THROW(libMesh::ConvergenceFailure()); \
492 : } while (0)
493 :
494 : #define libmesh_degenerate_mapping_msg(msg) \
495 : do { \
496 : std::stringstream message_stream; \
497 : message_stream << msg << '\n'; \
498 : LIBMESH_THROW(libMesh::DegenerateMap(message_stream.str())); \
499 : } while (0)
500 :
501 : #define libmesh_degenerate_mapping(filename) libmesh_degenerate_mapping_msg("")
502 :
503 : #define libmesh_terminate() \
504 : do { \
505 : LIBMESH_THROW(libMesh::TerminationException()); \
506 : } while (0)
507 :
508 : // The libmesh_example_requires() macro prints a message and calls
509 : // "return 77;" if the condition specified by the macro is not true. This
510 : // macro is used in the example executables, which should run when the
511 : // configure-time libMesh options support them but which should exit
512 : // without failure otherwise.
513 : //
514 : // This macro only works in main(), because we have no better way than
515 : // "return" from main to immediately exit successfully - std::exit()
516 : // gets seen by at least some MPI stacks as failure.
517 : //
518 : // 77 is the automake code for a skipped test.
519 :
520 : #define libmesh_example_requires(condition, option) \
521 : do { \
522 : if (!(condition)) { \
523 : libMesh::out << "Configuring libMesh with " << option << " is required to run this example." << std::endl; \
524 : return 77; \
525 : } } while (0)
526 :
527 : // The libmesh_do_once macro helps us avoid redundant repeated
528 : // repetitions of the same warning messages
529 : #undef libmesh_do_once
530 : #define libmesh_do_once(do_this) \
531 : do { \
532 : static bool did_this_already = false; \
533 : if (!did_this_already) { \
534 : did_this_already = true; \
535 : do_this; \
536 : } } while (0)
537 :
538 :
539 : // The libmesh_warning macro outputs a file/line/time stamped warning
540 : // message, if warnings are enabled.
541 : #ifdef LIBMESH_ENABLE_WARNINGS
542 : #define libmesh_warning(message) \
543 : libmesh_do_once(libMesh::out << message \
544 : << __FILE__ << ", line " << __LINE__ << ", compiled " << LIBMESH_DATE << " at " << LIBMESH_TIME << " ***" << std::endl;)
545 : #else
546 : #define libmesh_warning(message) ((void) 0)
547 : #endif
548 :
549 : // The libmesh_experimental macro warns that you are using
550 : // bleeding-edge code
551 : #undef libmesh_experimental
552 : #define libmesh_experimental() \
553 : libmesh_warning("*** Warning, This code is untested, experimental, or likely to see future API changes: ");
554 :
555 :
556 : // The libmesh_deprecated macro warns that you are using obsoleted code
557 : #undef libmesh_deprecated
558 : #ifndef LIBMESH_ENABLE_DEPRECATED
559 : #define libmesh_deprecated() \
560 : libmesh_error_msg("*** Error, This code is deprecated, and likely to be removed in future library versions! ");
561 : #else
562 : #define libmesh_deprecated() \
563 : libmesh_warning("*** Warning, This code is deprecated, and likely to be removed in future library versions! ");
564 : #endif
565 :
566 : // A function template for ignoring unused variables. This is a way
567 : // to shut up unused variable compiler warnings on a case by case
568 : // basis.
569 329304392 : template<class ...Args> inline void libmesh_ignore( const Args&... ) { }
570 :
571 :
572 : // Workaround for incomplete C++17 support in some compilers/libs
573 :
574 : #ifdef LIBMESH_HAVE_CXX17_SPLICING
575 : template <typename T>
576 50184 : void libmesh_merge_move(T & target, T & source)
577 : {
578 50184 : target.merge(std::move(source));
579 1495998 : }
580 : #else
581 : template <typename T>
582 : void libmesh_merge_move(T & target, T & source)
583 : {
584 : target.insert(source.begin(), source.end());
585 : source.clear(); // Avoid forwards-incompatibility
586 : }
587 : #endif // LIBMESH_HAVE_CXX17_SPLICING
588 :
589 : /**
590 : * Mostly system independent demangler
591 : */
592 : std::string demangle(const char * name);
593 :
594 : // cast_ref and cast_ptr do a dynamic cast and assert
595 : // the result, if we have RTTI enabled and we're in debug or
596 : // development modes, but they just do a faster static cast if we're
597 : // in optimized mode.
598 : //
599 : // Use these casts when you're certain that a cast will succeed in
600 : // correct code but you want to be able to double-check.
601 : template <typename Tnew, typename Told>
602 8605846 : inline Tnew cast_ref(Told & oldvar)
603 : {
604 : #if !defined(NDEBUG) && defined(LIBMESH_HAVE_RTTI) && defined(LIBMESH_ENABLE_EXCEPTIONS)
605 : try
606 : {
607 8605846 : Tnew newvar = dynamic_cast<Tnew>(oldvar);
608 8605846 : return newvar;
609 : }
610 0 : catch (std::bad_cast &)
611 : {
612 0 : libMesh::err << "Failed to convert " << demangle(typeid(Told).name())
613 0 : << " reference to " << demangle(typeid(Tnew).name())
614 0 : << std::endl;
615 0 : libMesh::err << "The " << demangle(typeid(Told).name())
616 0 : << " appears to be a "
617 0 : << demangle(typeid(*(&oldvar)).name()) << std::endl;
618 0 : libmesh_error();
619 : }
620 : #else
621 : return(static_cast<Tnew>(oldvar));
622 : #endif
623 : }
624 :
625 : // We use two different function names to avoid an odd overloading
626 : // ambiguity bug with icc 10.1.008
627 : template <typename Tnew, typename Told>
628 741194664 : inline Tnew cast_ptr (Told * oldvar)
629 : {
630 : #if !defined(NDEBUG) && defined(LIBMESH_HAVE_RTTI)
631 741194664 : Tnew newvar = dynamic_cast<Tnew>(oldvar);
632 741194664 : if (!newvar)
633 : {
634 0 : libMesh::err << "Failed to convert " << demangle(typeid(Told).name())
635 0 : << " pointer to " << demangle(typeid(Tnew).name())
636 0 : << std::endl;
637 0 : libMesh::err << "The " << demangle(typeid(Told).name())
638 0 : << " appears to be a "
639 0 : << demangle(typeid(*oldvar).name()) << std::endl;
640 0 : libmesh_error();
641 : }
642 741194664 : return newvar;
643 : #else
644 : return(static_cast<Tnew>(oldvar));
645 : #endif
646 : }
647 :
648 :
649 : #ifdef LIBMESH_ENABLE_DEPRECATED
650 : template <typename Tnew, typename Told>
651 : inline Tnew libmesh_cast_ptr (Told * oldvar)
652 : {
653 : libmesh_deprecated();
654 :
655 : // we use the less redundantly named libMesh::cast_ptr now
656 : return cast_ptr<Tnew>(oldvar);
657 : }
658 : #endif // LIBMESH_ENABLE_DEPRECATED
659 :
660 :
661 : // cast_int asserts that the value of the castee is within the
662 : // bounds which are exactly representable by the output type, if we're
663 : // in debug or development modes, but it just does a faster static
664 : // cast if we're in optimized mode.
665 : //
666 : // Use these casts when you're certain that a cast will succeed in
667 : // correct code but you want to be able to double-check.
668 : template <typename Tnew, typename Told>
669 9028431405 : inline Tnew cast_int (Told oldvar)
670 : {
671 130403078 : libmesh_assert_equal_to
672 : (oldvar, static_cast<Told>(static_cast<Tnew>(oldvar)));
673 :
674 21631493882 : return(static_cast<Tnew>(oldvar));
675 : }
676 :
677 :
678 : template <typename Tnew, typename Told>
679 : inline Tnew libmesh_cast_int (Told oldvar)
680 : {
681 : // we use the less redundantly named libMesh::cast_int now
682 : return cast_int<Tnew>(oldvar);
683 : }
684 :
685 :
686 : /**
687 : * restrict_int checks that the value of the castee is within the
688 : * bounds which are exactly representable by the output type, even in
689 : * optimized modes.
690 : *
691 : * Use this cast when you suspect that the input may not succeed in
692 : * correct code (e.g. when an input file is being read from a format
693 : * that may allow wider integer types than the current libMesh
694 : * configuration).
695 : */
696 : template <typename Tnew, typename Told>
697 733940 : inline Tnew restrict_int (Told oldvar)
698 : {
699 : if constexpr (!std::is_same_v<Tnew, Told>)
700 : {
701 733940 : const Tnew returnval = static_cast<Tnew>(oldvar);
702 :
703 733940 : libmesh_error_msg_if (oldvar != static_cast<Told>(returnval),
704 : "restrict_int failed: " << oldvar << " does not fit in type " << typeid(returnval).name());
705 : }
706 :
707 733940 : return oldvar;
708 : }
709 :
710 :
711 : /**
712 : * This is a helper variable template for cases when we want to use a default compile-time
713 : * error with constexpr-based if conditions. The templating delays the triggering
714 : * of the static assertion until the template is instantiated.
715 : */
716 : template <class T>
717 : constexpr std::false_type always_false{};
718 :
719 : static constexpr std::size_t libmesh_dim = LIBMESH_DIM;
720 :
721 : // build a integer representation of version
722 : #define LIBMESH_VERSION_ID(major,minor,patch) (((major) << 16) | ((minor) << 8) | ((patch) & 0xFF))
723 :
724 :
725 : // libmesh_override is simply a synonym for override as we now require
726 : // a C++11 compiler that supports this keyword.
727 : #define libmesh_override override
728 :
729 : // libmesh_delete is simply a synonym for '=delete' as we now require
730 : // a C++11 compiler that supports this keyword.
731 : #define libmesh_delete =delete
732 :
733 : // libmesh_final is simply a synonym for 'final' as we now require
734 : // a C++11 compiler that supports this keyword.
735 : #define libmesh_final final
736 :
737 : // Define backwards-compatible fallthrough attribute. We could
738 : // eventually also add support for other compiler-specific fallthrough
739 : // attributes.
740 : #ifdef LIBMESH_HAVE_CXX17_FALLTHROUGH_ATTRIBUTE
741 : #define libmesh_fallthrough() [[fallthrough]]
742 : #elif defined(LIBMESH_HAVE_DOUBLE_UNDERSCORE_ATTRIBUTE_FALLTHROUGH)
743 : #define libmesh_fallthrough() __attribute__((fallthrough))
744 : #else
745 : #define libmesh_fallthrough() ((void) 0)
746 : #endif
747 :
748 : template <typename T>
749 : class PassKey
750 : {
751 : friend T;
752 : constexpr PassKey() = default;
753 : };
754 : } // namespace libMesh
755 :
756 :
757 : // Backwards compatibility
758 : namespace libMeshEnums
759 : {
760 : using namespace libMesh;
761 : }
762 :
763 : // Backwards compatibility with pre-TIMPI reference
764 : namespace TIMPI {}
765 :
766 : namespace libMesh {
767 : namespace Parallel {
768 : using namespace TIMPI;
769 : }
770 : }
771 :
772 :
773 : // Here we add missing types to the standard namespace. For example,
774 : // std::max(double, float) etc... are well behaved but not defined
775 : // by the standard. This also includes workarounds for super-strict
776 : // implementations, for example Sun Studio and PGI C++. However,
777 : // this necessarily requires breaking the ISO-C++ standard, and is
778 : // really just a hack. As such, only do it if we are building the
779 : // libmesh library itself. Specifically, *DO NOT* export this to
780 : // user code or install this header.
781 : //
782 : // We put this at the end of libmesh_common.h so we can make use of
783 : // any exotic definitions of Real above.
784 : #ifdef LIBMESH_IS_COMPILING_ITSELF
785 : # include "libmesh/libmesh_augment_std_namespace.h"
786 : #endif
787 :
788 :
789 : #ifdef _MSC_VER
790 : #define LIBMESH_EXPORT __declspec(dllexport)
791 : #else
792 : #define LIBMESH_EXPORT
793 : #endif
794 :
795 :
796 : #endif // LIBMESH_LIBMESH_COMMON_H
|