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