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 number components, to clean up
189 : // #ifdef LIBMESH_USE_COMPLEX_NUMBERS elsewhere
190 : //
191 : // Some of these are just backwards compatibility shims for old code
192 : // that predated C++11
193 20240710 : template<typename T> LIBMESH_DEVICE_INLINE T libmesh_real(T a) { return a; }
194 : template<typename T> LIBMESH_DEVICE_INLINE T libmesh_imag(T /*a*/) { return 0; }
195 372978733 : template<typename T> LIBMESH_DEVICE_INLINE T libmesh_conj(T a) { return a; }
196 :
197 : template<typename T>
198 0 : LIBMESH_DEVICE_INLINE T libmesh_real(std::complex<T> a) { return std::real(a); }
199 :
200 : template<typename T>
201 : LIBMESH_DEVICE_INLINE T libmesh_imag(std::complex<T> a) { return std::imag(a); }
202 :
203 : template<typename T>
204 : LIBMESH_DEVICE_INLINE std::complex<T> libmesh_conj(std::complex<T> a) { return std::conj(a); }
205 :
206 : // Helper functions for complex/real number classification, because
207 : // for some reason std:: never added isfinite/isinf/isnan overloads
208 : // for std::complex.
209 :
210 : template <typename T>
211 660 : LIBMESH_DEVICE_INLINE bool libmesh_isinf(T x) { using std::isinf; return isinf(x); }
212 :
213 : template <typename T>
214 203273 : LIBMESH_DEVICE_INLINE bool libmesh_isnan(T x) { using std::isnan; return isnan(x); }
215 :
216 : // You'd think we'd treat inf,NaN pairs as NaN rather than infinite,
217 : // but that's not what the C/C++ standards recommend (ever since C99
218 : // Annex G), so we'll follow their lead.
219 : //
220 : // Anyone who doesn't care about these subtle NaN/inf distinctions
221 : // should just test isfinite() in their code, and can also probably
222 : // speed up their arithmetic greatly by using -fcx-limited-range
223 : // and/or -fcx-fortran-rules
224 : template <typename T>
225 : LIBMESH_DEVICE_INLINE bool libmesh_isinf(std::complex<T> a)
226 : { return (std::isinf(std::real(a)) || std::isinf(std::imag(a))); }
227 :
228 : // Treats inf,NaN pairs as infinite rather than NaN
229 : template <typename T>
230 42964 : LIBMESH_DEVICE_INLINE bool libmesh_isnan(std::complex<T> a)
231 42964 : { return ((std::isnan(std::real(a)) || std::isnan(std::imag(a))) &&
232 42964 : !std::isinf(std::real(a)) && !std::isinf(std::imag(a))); }
233 :
234 : template <typename T>
235 : LIBMESH_DEVICE_INLINE bool isfinite(std::complex<T> a)
236 : {
237 : return (std::isfinite(std::real(a)) && std::isfinite(std::imag(a)));
238 : }
239 :
240 : template <typename T>
241 : LIBMESH_DEVICE_INLINE bool isinf(std::complex<T> a)
242 : {
243 : return (std::isinf(std::real(a)) || std::isinf(std::imag(a)));
244 : }
245 :
246 : template <typename T>
247 : LIBMESH_DEVICE_INLINE bool isnan(std::complex<T> a)
248 : {
249 : { return ((std::isnan(std::real(a)) || std::isnan(std::imag(a))) &&
250 : !std::isinf(std::real(a)) && !std::isinf(std::imag(a))); }
251 : }
252 :
253 : // Define the value type for unknowns in simulations.
254 : // This is either Real or Complex, depending on how
255 : // the library was configures
256 : #if defined (LIBMESH_USE_REAL_NUMBERS)
257 : typedef Real Number;
258 : #elif defined (LIBMESH_USE_COMPLEX_NUMBERS)
259 : typedef Complex Number;
260 : #else
261 : DIE A HORRIBLE DEATH HERE...
262 : #endif
263 :
264 :
265 : // Define the value type for error estimates.
266 : // Since AMR/C decisions don't have to be precise,
267 : // we default to float for memory efficiency.
268 : typedef float ErrorVectorReal;
269 : #define MPI_ERRORVECTORREAL MPI_FLOAT
270 :
271 :
272 : #ifdef LIBMESH_HAVE_MPI
273 :
274 : /**
275 : * MPI Communicator used to initialize libMesh.
276 : */
277 : extern MPI_Comm GLOBAL_COMM_WORLD;
278 : #else
279 :
280 : /**
281 : * Something to use with CHKERRABORT if we're just using PETSc's MPI
282 : * "uni" stub.
283 : */
284 : extern int GLOBAL_COMM_WORLD;
285 : #endif
286 :
287 : // This global variable is to help us deprecate AutoPtr. We can't
288 : // just use libmesh_deprecated() because then you get one print out
289 : // per template instantiation, instead of one total print out.
290 : extern bool warned_about_auto_ptr;
291 :
292 : // These are useful macros that behave like functions in the code.
293 : // If you want to make sure you are accessing a section of code just
294 : // stick a libmesh_here(); in it, for example
295 : #define libmesh_here() \
296 : do { \
297 : libMesh::MacroFunctions::here(__FILE__, __LINE__, LIBMESH_DATE, LIBMESH_TIME); \
298 : } while (0)
299 :
300 : // the libmesh_stop() macro will stop the code until a SIGCONT signal
301 : // is received. This is useful, for example, when determining the
302 : // memory used by a given operation. A libmesh_stop() could be
303 : // inserted before and after a questionable operation and the delta
304 : // memory can be obtained from a ps or top. This macro only works for
305 : // serial cases.
306 : #define libmesh_stop() \
307 : do { \
308 : libMesh::MacroFunctions::stop(__FILE__, __LINE__, LIBMESH_DATE, LIBMESH_TIME); \
309 : } while (0)
310 :
311 : // The libmesh_dbg_var() macro indicates that an argument to a function
312 : // is used only in debug and devel modes (i.e., when NDEBUG is not defined).
313 : #ifndef NDEBUG
314 : #define libmesh_dbg_var(var) var
315 : #else
316 : #define libmesh_dbg_var(var)
317 : #endif
318 :
319 : // The libmesh_inf_var() macro indicates that an argument to a function
320 : // is used only when infinite elements are enabled
321 : #ifdef LIBMESH_ENABLE_INFINITE_ELEMENTS
322 : #define libmesh_inf_var(var) var
323 : #else
324 : #define libmesh_inf_var(var)
325 : #endif
326 :
327 : // The libmesh_assert() macro acts like C's assert(), but throws a
328 : // libmesh_error() (including stack trace, etc) instead of just exiting.
329 : //
330 : // In .K translation units (ACSM_KOKKOS_COMPILATION defined),
331 : // LIBMESH_DEVICE_ASSERT is provided by libmesh_device.h using
332 : // printf + Kokkos::abort() — device-safe across CUDA/HIP/SYCL.
333 : // The assert macros delegate to it so that both host and device
334 : // code in the same file get assertion checking.
335 : #ifdef NDEBUG
336 :
337 : #define libmesh_assert_msg(asserted, msg) ((void) 0)
338 : #define libmesh_exceptionless_assert_msg(asserted, msg) ((void) 0)
339 : #define libmesh_assert_equal_to_msg(expr1,expr2, msg) ((void) 0)
340 : #define libmesh_assert_not_equal_to_msg(expr1,expr2, msg) ((void) 0)
341 : #define libmesh_assert_less_msg(expr1,expr2, msg) ((void) 0)
342 : #define libmesh_assert_greater_msg(expr1,expr2, msg) ((void) 0)
343 : #define libmesh_assert_less_equal_msg(expr1,expr2, msg) ((void) 0)
344 : #define libmesh_assert_greater_equal_msg(expr1,expr2, msg) ((void) 0)
345 :
346 : #elif defined(ACSM_KOKKOS_COMPILATION)
347 :
348 : // Kokkos compilation: use the device-safe assert from libmesh_device.h.
349 : #define libmesh_assert_msg(asserted, msg) LIBMESH_DEVICE_ASSERT(asserted)
350 : #define libmesh_exceptionless_assert_msg(asserted, msg) LIBMESH_DEVICE_ASSERT(asserted)
351 : #define libmesh_assert_equal_to_msg(expr1,expr2, msg) LIBMESH_DEVICE_ASSERT((expr1) == (expr2))
352 : #define libmesh_assert_not_equal_to_msg(expr1,expr2, msg) LIBMESH_DEVICE_ASSERT((expr1) != (expr2))
353 : #define libmesh_assert_less_msg(expr1,expr2, msg) LIBMESH_DEVICE_ASSERT((expr1) < (expr2))
354 : #define libmesh_assert_greater_msg(expr1,expr2, msg) LIBMESH_DEVICE_ASSERT((expr1) > (expr2))
355 : #define libmesh_assert_less_equal_msg(expr1,expr2, msg) LIBMESH_DEVICE_ASSERT((expr1) <= (expr2))
356 : #define libmesh_assert_greater_equal_msg(expr1,expr2, msg) LIBMESH_DEVICE_ASSERT((expr1) >= (expr2))
357 :
358 : #else
359 :
360 : #define libmesh_assertion_types(expr1,expr2) \
361 : typedef typename std::decay<decltype(expr1)>::type libmesh_type1; \
362 : typedef typename std::decay<decltype(expr2)>::type libmesh_type2
363 :
364 : #define libmesh_assert_msg(asserted, msg) \
365 : do { \
366 : if (!(asserted)) { \
367 : libmesh_error_msg("Assertion `" #asserted "' failed.\n" << msg); \
368 : } } while (0)
369 :
370 : #define libmesh_exceptionless_assert_msg(asserted, msg) \
371 : do { \
372 : if (!(asserted)) { \
373 : libMesh::Threads::lock_singleton_spin_mutex(); \
374 : libMesh::err << "Assertion `" #asserted "' failed." << std::endl; \
375 : libMesh::Threads::unlock_singleton_spin_mutex(); \
376 : libmesh_exceptionless_error(); \
377 : } } while (0)
378 :
379 : #define libmesh_assert_equal_to_msg(expr1,expr2, msg) \
380 : do { \
381 : if (!((expr1) == (expr2))) { \
382 : libmesh_error_msg(std::setprecision(17) << "Assertion `" #expr1 " == " #expr2 "' failed.\n" #expr1 " = " << (expr1) << "\n" #expr2 " = " << (expr2) << '\n' << msg << std::endl); \
383 : } } while (0)
384 :
385 : #define libmesh_assert_not_equal_to_msg(expr1,expr2, msg) \
386 : do { \
387 : if (!((expr1) != (expr2))) { \
388 : libmesh_error_msg(std::setprecision(17) << "Assertion `" #expr1 " != " #expr2 "' failed.\n" #expr1 " = " << (expr1) << "\n" #expr2 " = " << (expr2) << '\n' << msg << std::endl); \
389 : } } while (0)
390 :
391 : template <template <class> class Comp>
392 : struct casting_compare {
393 :
394 : template <typename T1, typename T2>
395 1023538963 : bool operator()(const T1 & e1, const T2 & e2) const
396 : {
397 : typedef typename std::decay<T1>::type DT1;
398 : typedef typename std::decay<T2>::type DT2;
399 2047077926 : return (Comp<DT2>()(static_cast<DT2>(e1), e2) &&
400 2047077926 : Comp<DT1>()(e1, static_cast<DT1>(e2)));
401 : }
402 :
403 : template <typename T1>
404 185868134 : bool operator()(const T1 & e1, const T1 & e2) const
405 : {
406 185868134 : return Comp<T1>()(e1, e2);
407 : }
408 : };
409 :
410 : #define libmesh_assert_less_msg(expr1,expr2, msg) \
411 : do { \
412 : if (!libMesh::casting_compare<std::less>()(expr1, expr2)) { \
413 : libmesh_error_msg(std::setprecision(17) << "Assertion `" #expr1 " < " #expr2 "' failed.\n" #expr1 " = " << (expr1) << "\n" #expr2 " = " << (expr2) << '\n' << msg << std::endl); \
414 : } } while (0)
415 :
416 : #define libmesh_assert_greater_msg(expr1,expr2, msg) \
417 : do { \
418 : if (!libMesh::casting_compare<std::greater>()(expr1, expr2)) { \
419 : libmesh_error_msg(std::setprecision(17) << "Assertion `" #expr1 " > " #expr2 "' failed.\n" #expr1 " = " << (expr1) << "\n" #expr2 " = " << (expr2) << '\n' << msg << std::endl); \
420 : } } while (0)
421 :
422 : #define libmesh_assert_less_equal_msg(expr1,expr2, msg) \
423 : do { \
424 : if (!libMesh::casting_compare<std::less_equal>()(expr1, expr2)) { \
425 : libmesh_error_msg(std::setprecision(17) << "Assertion `" #expr1 " <= " #expr2 "' failed.\n" #expr1 " = " << (expr1) << "\n" #expr2 " = " << (expr2) << '\n' << msg << std::endl); \
426 : } } while (0)
427 :
428 : #define libmesh_assert_greater_equal_msg(expr1,expr2, msg) \
429 : do { \
430 : if (!libMesh::casting_compare<std::greater_equal>()(expr1, expr2)) { \
431 : libmesh_error_msg(std::setprecision(17) << "Assertion `" #expr1 " >= " #expr2 "' failed.\n" #expr1 " = " << (expr1) << "\n" #expr2 " = " << (expr2) << '\n' << msg << std::endl); \
432 : } } while (0)
433 :
434 : #endif
435 :
436 :
437 : #define libmesh_assert(asserted) libmesh_assert_msg(asserted, "")
438 : #define libmesh_exceptionless_assert(asserted) libmesh_exceptionless_assert_msg(asserted, "")
439 : #define libmesh_assert_equal_to(expr1,expr2) libmesh_assert_equal_to_msg(expr1,expr2, "")
440 : #define libmesh_assert_not_equal_to(expr1,expr2) libmesh_assert_not_equal_to_msg(expr1,expr2, "")
441 : #define libmesh_assert_less(expr1,expr2) libmesh_assert_less_msg(expr1,expr2, "")
442 : #define libmesh_assert_greater(expr1,expr2) libmesh_assert_greater_msg(expr1,expr2, "")
443 : #define libmesh_assert_less_equal(expr1,expr2) libmesh_assert_less_equal_msg(expr1,expr2, "")
444 : #define libmesh_assert_greater_equal(expr1,expr2) libmesh_assert_greater_equal_msg(expr1,expr2, "")
445 :
446 : // The libmesh_error() macro prints a message and throws a LogicError
447 : // exception
448 : //
449 : // The libmesh_not_implemented() macro prints a message and throws a
450 : // NotImplemented exception
451 : //
452 : // The libmesh_file_error(const std::string & filename) macro prints a message
453 : // and throws a FileError exception
454 : //
455 : // The libmesh_convergence_failure() macro
456 : // throws a ConvergenceFailure exception
457 : //
458 : // The libmesh_degenerate_mapping() macro prints a message into and
459 : // throws a DegenerateMap exception
460 : //
461 : // The libmesh_terminate() macro prints a message and throws a
462 : // TerminationException exception
463 : #if LIBMESH_IN_DEVICE_CODE
464 : #define libmesh_error_msg(msg) \
465 : do { \
466 : LIBMESH_DEVICE_ERROR_MSG(msg); \
467 : } while (0)
468 : #else
469 : #define libmesh_error_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::LogicError(message_stream.str())); \
475 : } while (0)
476 : #endif
477 :
478 : #define libmesh_error() libmesh_error_msg("")
479 :
480 : #define libmesh_error_msg_if(cond, msg) \
481 : do { \
482 : if (cond) \
483 : libmesh_error_msg(msg); \
484 : } while (0)
485 :
486 : #define libmesh_exceptionless_error_msg(msg) \
487 : do { \
488 : libMesh::Threads::lock_singleton_spin_mutex(); \
489 : libMesh::err << msg << '\n'; \
490 : libMesh::Threads::unlock_singleton_spin_mutex(); \
491 : libmesh_try { libMesh::MacroFunctions::report_error(__FILE__, __LINE__, LIBMESH_DATE, LIBMESH_TIME); } \
492 : libmesh_catch (...) {} \
493 : std::terminate(); \
494 : } while (0)
495 :
496 : #define libmesh_exceptionless_error() libmesh_exceptionless_error_msg("")
497 :
498 : #define libmesh_not_implemented_msg(msg) \
499 : do { \
500 : std::stringstream message_stream; \
501 : message_stream << msg << '\n'; \
502 : libMesh::MacroFunctions::report_error(__FILE__, __LINE__, LIBMESH_DATE, LIBMESH_TIME, message_stream); \
503 : LIBMESH_THROW(libMesh::NotImplemented(message_stream.str())); \
504 : } while (0)
505 :
506 : #define libmesh_not_implemented() libmesh_not_implemented_msg("")
507 :
508 : #define libmesh_file_error_msg(filename, msg) \
509 : do { \
510 : std::stringstream message_stream; \
511 : message_stream << msg << '\n'; \
512 : libMesh::MacroFunctions::report_error(__FILE__, __LINE__, LIBMESH_DATE, LIBMESH_TIME, message_stream); \
513 : LIBMESH_THROW(libMesh::FileError(filename, message_stream.str())); \
514 : } while (0)
515 :
516 : #define libmesh_file_error(filename) libmesh_file_error_msg(filename,"")
517 :
518 : #define libmesh_convergence_failure() \
519 : do { \
520 : LIBMESH_THROW(libMesh::ConvergenceFailure()); \
521 : } while (0)
522 :
523 : #define libmesh_degenerate_mapping_msg(msg) \
524 : do { \
525 : std::stringstream message_stream; \
526 : message_stream << msg << '\n'; \
527 : LIBMESH_THROW(libMesh::DegenerateMap(message_stream.str())); \
528 : } while (0)
529 :
530 : #define libmesh_degenerate_mapping(filename) libmesh_degenerate_mapping_msg("")
531 :
532 : #define libmesh_terminate() \
533 : do { \
534 : LIBMESH_THROW(libMesh::TerminationException()); \
535 : } while (0)
536 :
537 : // The libmesh_example_requires() macro prints a message and calls
538 : // "return 77;" if the condition specified by the macro is not true. This
539 : // macro is used in the example executables, which should run when the
540 : // configure-time libMesh options support them but which should exit
541 : // without failure otherwise.
542 : //
543 : // This macro only works in main(), because we have no better way than
544 : // "return" from main to immediately exit successfully - std::exit()
545 : // gets seen by at least some MPI stacks as failure.
546 : //
547 : // 77 is the automake code for a skipped test.
548 :
549 : #define libmesh_example_requires(condition, option) \
550 : do { \
551 : if (!(condition)) { \
552 : libMesh::out << "Configuring libMesh with " << option << " is required to run this example." << std::endl; \
553 : return 77; \
554 : } } while (0)
555 :
556 : // The libmesh_do_once macro helps us avoid redundant repeated
557 : // repetitions of the same warning messages
558 : #undef libmesh_do_once
559 : #define libmesh_do_once(do_this) \
560 : do { \
561 : static bool did_this_already = false; \
562 : if (!did_this_already) { \
563 : did_this_already = true; \
564 : do_this; \
565 : } } while (0)
566 :
567 :
568 : // The libmesh_warning macro outputs a file/line/time stamped warning
569 : // message, if warnings are enabled.
570 : #ifdef LIBMESH_ENABLE_WARNINGS
571 : #define libmesh_warning(message) \
572 : libmesh_do_once(libMesh::out << message \
573 : << __FILE__ << ", line " << __LINE__ << ", compiled " << LIBMESH_DATE << " at " << LIBMESH_TIME << " ***" << std::endl;)
574 : #else
575 : #define libmesh_warning(message) ((void) 0)
576 : #endif
577 :
578 : // The libmesh_experimental macro warns that you are using
579 : // bleeding-edge code
580 : #undef libmesh_experimental
581 : #define libmesh_experimental() \
582 : libmesh_warning("*** Warning, This code is untested, experimental, or likely to see future API changes: ");
583 :
584 :
585 : // The libmesh_deprecated macro warns that you are using obsoleted code
586 : #undef libmesh_deprecated
587 : #ifndef LIBMESH_ENABLE_DEPRECATED
588 : #define libmesh_deprecated() \
589 : libmesh_error_msg("*** Error, This code is deprecated, and likely to be removed in future library versions! ");
590 : #else
591 : #define libmesh_deprecated() \
592 : libmesh_warning("*** Warning, This code is deprecated, and likely to be removed in future library versions! ");
593 : #endif
594 :
595 : // A function template for ignoring unused variables. This is a way
596 : // to shut up unused variable compiler warnings on a case by case
597 : // basis.
598 329306913 : template<class ...Args> inline void libmesh_ignore( const Args&... ) { }
599 :
600 :
601 : // Workaround for incomplete C++17 support in some compilers/libs
602 :
603 : #ifdef LIBMESH_HAVE_CXX17_SPLICING
604 : template <typename T>
605 50184 : void libmesh_merge_move(T & target, T & source)
606 : {
607 50184 : target.merge(std::move(source));
608 1495998 : }
609 : #else
610 : template <typename T>
611 : void libmesh_merge_move(T & target, T & source)
612 : {
613 : target.insert(source.begin(), source.end());
614 : source.clear(); // Avoid forwards-incompatibility
615 : }
616 : #endif // LIBMESH_HAVE_CXX17_SPLICING
617 :
618 : /**
619 : * Mostly system independent demangler
620 : */
621 : std::string demangle(const char * name);
622 :
623 : // cast_ref and cast_ptr do a dynamic cast and assert
624 : // the result, if we have RTTI enabled and we're in debug or
625 : // development modes, but they just do a faster static cast if we're
626 : // in optimized mode.
627 : //
628 : // Use these casts when you're certain that a cast will succeed in
629 : // correct code but you want to be able to double-check.
630 : template <typename Tnew, typename Told>
631 8605818 : inline Tnew cast_ref(Told & oldvar)
632 : {
633 : #if !defined(NDEBUG) && defined(LIBMESH_HAVE_RTTI) && defined(LIBMESH_ENABLE_EXCEPTIONS)
634 : try
635 : {
636 8605818 : Tnew newvar = dynamic_cast<Tnew>(oldvar);
637 8605818 : return newvar;
638 : }
639 0 : catch (std::bad_cast &)
640 : {
641 0 : libMesh::err << "Failed to convert " << demangle(typeid(Told).name())
642 0 : << " reference to " << demangle(typeid(Tnew).name())
643 0 : << std::endl;
644 0 : libMesh::err << "The " << demangle(typeid(Told).name())
645 0 : << " appears to be a "
646 0 : << demangle(typeid(*(&oldvar)).name()) << std::endl;
647 0 : libmesh_error();
648 : }
649 : #else
650 : return(static_cast<Tnew>(oldvar));
651 : #endif
652 : }
653 :
654 : // We use two different function names to avoid an odd overloading
655 : // ambiguity bug with icc 10.1.008
656 : template <typename Tnew, typename Told>
657 741159762 : inline Tnew cast_ptr (Told * oldvar)
658 : {
659 : #if !defined(NDEBUG) && defined(LIBMESH_HAVE_RTTI)
660 741159762 : Tnew newvar = dynamic_cast<Tnew>(oldvar);
661 741159762 : if (!newvar)
662 : {
663 0 : libMesh::err << "Failed to convert " << demangle(typeid(Told).name())
664 0 : << " pointer to " << demangle(typeid(Tnew).name())
665 0 : << std::endl;
666 0 : libMesh::err << "The " << demangle(typeid(Told).name())
667 0 : << " appears to be a "
668 0 : << demangle(typeid(*oldvar).name()) << std::endl;
669 0 : libmesh_error();
670 : }
671 741159762 : return newvar;
672 : #else
673 : return(static_cast<Tnew>(oldvar));
674 : #endif
675 : }
676 :
677 :
678 : #ifdef LIBMESH_ENABLE_DEPRECATED
679 : template <typename Tnew, typename Told>
680 : inline Tnew libmesh_cast_ptr (Told * oldvar)
681 : {
682 : libmesh_deprecated();
683 :
684 : // we use the less redundantly named libMesh::cast_ptr now
685 : return cast_ptr<Tnew>(oldvar);
686 : }
687 : #endif // LIBMESH_ENABLE_DEPRECATED
688 :
689 :
690 : // cast_int asserts that the value of the castee is within the
691 : // bounds which are exactly representable by the output type, if we're
692 : // in debug or development modes, but it just does a faster static
693 : // cast if we're in optimized mode.
694 : //
695 : // Use these casts when you're certain that a cast will succeed in
696 : // correct code but you want to be able to double-check.
697 : template <typename Tnew, typename Told>
698 9028584836 : inline Tnew cast_int (Told oldvar)
699 : {
700 130404702 : libmesh_assert_equal_to
701 : (oldvar, static_cast<Told>(static_cast<Tnew>(oldvar)));
702 :
703 21632752117 : return(static_cast<Tnew>(oldvar));
704 : }
705 :
706 :
707 : template <typename Tnew, typename Told>
708 : inline Tnew libmesh_cast_int (Told oldvar)
709 : {
710 : // we use the less redundantly named libMesh::cast_int now
711 : return cast_int<Tnew>(oldvar);
712 : }
713 :
714 :
715 : /**
716 : * restrict_int checks that the value of the castee is within the
717 : * bounds which are exactly representable by the output type, even in
718 : * optimized modes.
719 : *
720 : * Use this cast when you suspect that the input may not succeed in
721 : * correct code (e.g. when an input file is being read from a format
722 : * that may allow wider integer types than the current libMesh
723 : * configuration).
724 : */
725 : template <typename Tnew, typename Told>
726 733940 : inline Tnew restrict_int (Told oldvar)
727 : {
728 : if constexpr (!std::is_same_v<Tnew, Told>)
729 : {
730 733940 : const Tnew returnval = static_cast<Tnew>(oldvar);
731 :
732 733940 : libmesh_error_msg_if (oldvar != static_cast<Told>(returnval),
733 : "restrict_int failed: " << oldvar << " does not fit in type " << typeid(returnval).name());
734 : }
735 :
736 733940 : return oldvar;
737 : }
738 :
739 : /**
740 : * This is a helper variable template for cases when we want to use a default compile-time
741 : * error with constexpr-based if conditions. The templating delays the triggering
742 : * of the static assertion until the template is instantiated.
743 : */
744 : template <class T>
745 : constexpr std::false_type always_false{};
746 :
747 : static constexpr std::size_t libmesh_dim = LIBMESH_DIM;
748 :
749 : // build a integer representation of version
750 : #define LIBMESH_VERSION_ID(major,minor,patch) (((major) << 16) | ((minor) << 8) | ((patch) & 0xFF))
751 :
752 :
753 : // libmesh_override is simply a synonym for override as we now require
754 : // a C++11 compiler that supports this keyword.
755 : #define libmesh_override override
756 :
757 : // libmesh_delete is simply a synonym for '=delete' as we now require
758 : // a C++11 compiler that supports this keyword.
759 : #define libmesh_delete =delete
760 :
761 : // libmesh_final is simply a synonym for 'final' as we now require
762 : // a C++11 compiler that supports this keyword.
763 : #define libmesh_final final
764 :
765 : // Define backwards-compatible fallthrough attribute. We could
766 : // eventually also add support for other compiler-specific fallthrough
767 : // attributes.
768 : #ifdef LIBMESH_HAVE_CXX17_FALLTHROUGH_ATTRIBUTE
769 : #define libmesh_fallthrough() [[fallthrough]]
770 : #elif defined(LIBMESH_HAVE_DOUBLE_UNDERSCORE_ATTRIBUTE_FALLTHROUGH)
771 : #define libmesh_fallthrough() __attribute__((fallthrough))
772 : #else
773 : #define libmesh_fallthrough() ((void) 0)
774 : #endif
775 :
776 : template <typename T>
777 : class PassKey
778 : {
779 : friend T;
780 : constexpr PassKey() = default;
781 : };
782 : } // namespace libMesh
783 :
784 :
785 : // Backwards compatibility
786 : namespace libMeshEnums
787 : {
788 : using namespace libMesh;
789 : }
790 :
791 : // Backwards compatibility with pre-TIMPI reference
792 : namespace TIMPI {}
793 :
794 : namespace libMesh {
795 : namespace Parallel {
796 : using namespace TIMPI;
797 : }
798 : }
799 :
800 :
801 : // Here we add missing types to the standard namespace. For example,
802 : // std::max(double, float) etc... are well behaved but not defined
803 : // by the standard. This also includes workarounds for super-strict
804 : // implementations, for example Sun Studio and PGI C++. However,
805 : // this necessarily requires breaking the ISO-C++ standard, and is
806 : // really just a hack. As such, only do it if we are building the
807 : // libmesh library itself. Specifically, *DO NOT* export this to
808 : // user code or install this header.
809 : //
810 : // We put this at the end of libmesh_common.h so we can make use of
811 : // any exotic definitions of Real above.
812 : #ifdef LIBMESH_IS_COMPILING_ITSELF
813 : # include "libmesh/libmesh_augment_std_namespace.h"
814 : #endif
815 :
816 :
817 : #ifdef _MSC_VER
818 : #define LIBMESH_EXPORT __declspec(dllexport)
819 : #else
820 : #define LIBMESH_EXPORT
821 : #endif
822 :
823 :
824 : #endif // LIBMESH_LIBMESH_COMMON_H
|