libMesh
Loading...
Searching...
No Matches
libmesh_common.h
Go to the documentation of this file.
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
85namespace libMesh
86{
87namespace Threads
88{
89// For thread-safe error-messaging. Definitions in threads.h
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
101extern OStreamProxy out;
102extern 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.
109namespace MacroFunctions
110{
111void here(const char * file, int line, const char * date, const char * time, std::ostream & os = libMesh::err);
112void stop(const char * file, int line, const char * date, const char * time);
113void 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
136DIE A HORRIBLE DEATH HERE...
137# undef TOLERANCE
138#endif
139
140
141
142// Define the type to use for real numbers
143
144typedef 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
151static 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
159static 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
166static 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)
172static 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
180typedef std::complex<Real> Complex;
181typedef 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
189template<typename T> inline T libmesh_real(T a) { return a; }
190template<typename T> inline T libmesh_imag(T /*a*/) { return 0; }
191template<typename T> inline T libmesh_conj(T a) { return a; }
192
193template<typename T>
194inline T libmesh_real(std::complex<T> a) { return std::real(a); }
195
196template<typename T>
197inline T libmesh_imag(std::complex<T> a) { return std::imag(a); }
198
199template<typename T>
200inline 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
206template <typename T>
207inline bool libmesh_isinf(T x) { using std::isinf; return isinf(x); }
208
209template <typename T>
210inline 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
220template <typename T>
221inline 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
225template <typename T>
226inline bool libmesh_isnan(std::complex<T> a)
227{ return ((std::isnan(std::real(a)) || std::isnan(std::imag(a))) &&
228 !std::isinf(std::real(a)) && !std::isinf(std::imag(a))); }
229
230template <typename T>
231inline bool isfinite(std::complex<T> a)
232{
233 return (std::isfinite(std::real(a)) && std::isfinite(std::imag(a)));
234}
235
236template <typename T>
237inline bool isinf(std::complex<T> a)
238{
239 return (std::isinf(std::real(a)) || std::isinf(std::imag(a)));
240}
241
242template <typename T>
243inline 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)
253typedef Real Number;
254#elif defined (LIBMESH_USE_COMPLEX_NUMBERS)
255typedef Complex Number;
256#else
257DIE 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.
264typedef float ErrorVectorReal;
265#define MPI_ERRORVECTORREAL MPI_FLOAT
266
267
268#ifdef LIBMESH_HAVE_MPI
269
273extern MPI_Comm GLOBAL_COMM_WORLD;
274#else
275
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.
286extern 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
369template <template <class> class Comp>
371
372 template <typename T1, typename T2>
373 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 return (Comp<DT2>()(static_cast<DT2>(e1), e2) &&
378 Comp<DT1>()(e1, static_cast<DT1>(e2)));
379 }
380
381 template <typename T1>
382 bool operator()(const T1 & e1, const T1 & e2) const
383 {
384 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.
569template<class ...Args> inline void libmesh_ignore( const Args&... ) { }
570
571
572// A workaround for the lack of C++17 merge() support in some
573// compilers
574
575#ifdef LIBMESH_HAVE_CXX17_SPLICING
576template <typename T>
577void libmesh_merge_move(T & target, T & source)
578{
579 target.merge(std::move(source));
580}
581#else
582template <typename T>
583void libmesh_merge_move(T & target, T & source)
584{
585 target.insert(source.begin(), source.end());
586 source.clear(); // Avoid forwards-incompatibility
587}
588#endif // LIBMESH_HAVE_CXX17_SPLICING
589
593 std::string demangle(const char * name);
594
595// cast_ref and cast_ptr do a dynamic cast and assert
596// the result, if we have RTTI enabled and we're in debug or
597// development modes, but they just do a faster static cast if we're
598// in optimized mode.
599//
600// Use these casts when you're certain that a cast will succeed in
601// correct code but you want to be able to double-check.
602template <typename Tnew, typename Told>
603inline Tnew cast_ref(Told & oldvar)
604{
605#if !defined(NDEBUG) && defined(LIBMESH_HAVE_RTTI) && defined(LIBMESH_ENABLE_EXCEPTIONS)
606 try
607 {
608 Tnew newvar = dynamic_cast<Tnew>(oldvar);
609 return newvar;
610 }
611 catch (std::bad_cast &)
612 {
613 libMesh::err << "Failed to convert " << demangle(typeid(Told).name())
614 << " reference to " << demangle(typeid(Tnew).name())
615 << std::endl;
616 libMesh::err << "The " << demangle(typeid(Told).name())
617 << " appears to be a "
618 << demangle(typeid(*(&oldvar)).name()) << std::endl;
619 libmesh_error();
620 }
621#else
622 return(static_cast<Tnew>(oldvar));
623#endif
624}
625
626// We use two different function names to avoid an odd overloading
627// ambiguity bug with icc 10.1.008
628template <typename Tnew, typename Told>
629inline Tnew cast_ptr (Told * oldvar)
630{
631#if !defined(NDEBUG) && defined(LIBMESH_HAVE_RTTI)
632 Tnew newvar = dynamic_cast<Tnew>(oldvar);
633 if (!newvar)
634 {
635 libMesh::err << "Failed to convert " << demangle(typeid(Told).name())
636 << " pointer to " << demangle(typeid(Tnew).name())
637 << std::endl;
638 libMesh::err << "The " << demangle(typeid(Told).name())
639 << " appears to be a "
640 << demangle(typeid(*oldvar).name()) << std::endl;
641 libmesh_error();
642 }
643 return newvar;
644#else
645 return(static_cast<Tnew>(oldvar));
646#endif
647}
648
649
650#ifdef LIBMESH_ENABLE_DEPRECATED
651template <typename Tnew, typename Told>
652inline Tnew libmesh_cast_ptr (Told * oldvar)
653{
654 libmesh_deprecated();
655
656 // we use the less redundantly named libMesh::cast_ptr now
657 return cast_ptr<Tnew>(oldvar);
658}
659#endif // LIBMESH_ENABLE_DEPRECATED
660
661
662// cast_int asserts that the value of the castee is within the
663// bounds which are exactly representable by the output type, if we're
664// in debug or development modes, but it just does a faster static
665// cast if we're in optimized mode.
666//
667// Use these casts when you're certain that a cast will succeed in
668// correct code but you want to be able to double-check.
669template <typename Tnew, typename Told>
670inline Tnew cast_int (Told oldvar)
671{
672 libmesh_assert_equal_to
673 (oldvar, static_cast<Told>(static_cast<Tnew>(oldvar)));
674
675 return(static_cast<Tnew>(oldvar));
676}
677
678
679template <typename Tnew, typename Told>
680inline Tnew libmesh_cast_int (Told oldvar)
681{
682 // we use the less redundantly named libMesh::cast_int now
683 return cast_int<Tnew>(oldvar);
684}
685
686
697template <typename Tnew, typename Told>
698inline Tnew restrict_int (Told oldvar)
699{
700 if constexpr (!std::is_same_v<Tnew, Told>)
701 {
702 const Tnew returnval = static_cast<Tnew>(oldvar);
703
704 libmesh_error_msg_if (oldvar != static_cast<Told>(returnval),
705 "restrict_int failed: " << oldvar << " does not fit in type " << typeid(returnval).name());
706 }
707
708 return oldvar;
709}
710
711
717template <class T>
718constexpr std::false_type always_false{};
719
720static constexpr std::size_t libmesh_dim = LIBMESH_DIM;
721
722// build a integer representation of version
723#define LIBMESH_VERSION_ID(major,minor,patch) (((major) << 16) | ((minor) << 8) | ((patch) & 0xFF))
724
725
726// libmesh_override is simply a synonym for override as we now require
727// a C++11 compiler that supports this keyword.
728#define libmesh_override override
729
730// libmesh_delete is simply a synonym for '=delete' as we now require
731// a C++11 compiler that supports this keyword.
732#define libmesh_delete =delete
733
734// libmesh_final is simply a synonym for 'final' as we now require
735// a C++11 compiler that supports this keyword.
736#define libmesh_final final
737
738// Define backwards-compatible fallthrough attribute. We could
739// eventually also add support for other compiler-specific fallthrough
740// attributes.
741#ifdef LIBMESH_HAVE_CXX17_FALLTHROUGH_ATTRIBUTE
742#define libmesh_fallthrough() [[fallthrough]]
743#elif defined(LIBMESH_HAVE_DOUBLE_UNDERSCORE_ATTRIBUTE_FALLTHROUGH)
744#define libmesh_fallthrough() __attribute__((fallthrough))
745#else
746#define libmesh_fallthrough() ((void) 0)
747#endif
748
749template <typename T>
751{
752 friend T;
753 constexpr PassKey() = default;
754};
755} // namespace libMesh
756
757
758// Backwards compatibility
760{
761using namespace libMesh;
762}
763
764// Backwards compatibility with pre-TIMPI reference
765namespace TIMPI {}
766
767namespace libMesh {
768 namespace Parallel {
769 using namespace TIMPI;
770 }
771}
772
773
774// Here we add missing types to the standard namespace. For example,
775// std::max(double, float) etc... are well behaved but not defined
776// by the standard. This also includes workarounds for super-strict
777// implementations, for example Sun Studio and PGI C++. However,
778// this necessarily requires breaking the ISO-C++ standard, and is
779// really just a hack. As such, only do it if we are building the
780// libmesh library itself. Specifically, *DO NOT* export this to
781// user code or install this header.
782//
783// We put this at the end of libmesh_common.h so we can make use of
784// any exotic definitions of Real above.
785#ifdef LIBMESH_IS_COMPILING_ITSELF
786# include "libmesh/libmesh_augment_std_namespace.h"
787#endif
788
789
790#ifdef _MSC_VER
791#define LIBMESH_EXPORT __declspec(dllexport)
792#else
793#define LIBMESH_EXPORT
794#endif
795
796
797#endif // LIBMESH_LIBMESH_COMMON_H
This class is intended to be reseatable like a pointer-to-ostream for flexibility,...
constexpr PassKey()=default
void here(const char *file, int line, const char *date, const char *time, std::ostream &os=libMesh::err)
void stop(const char *file, int line, const char *date, const char *time)
void report_error(const char *file, int line, const char *date, const char *time, std::ostream &os=libMesh::err)
void lock_singleton_spin_mutex()
Definition threads.C:35
void unlock_singleton_spin_mutex()
Definition threads.C:36
The libMesh namespace provides an interface to certain functionality in the library.
std::complex< Real > COMPLEX
OStreamProxy err
bool libmesh_isinf(T x)
static constexpr std::size_t libmesh_dim
DIE A HORRIBLE DEATH HERE typedef float ErrorVectorReal
bool warned_about_auto_ptr
Tnew restrict_int(Told oldvar)
restrict_int checks that the value of the castee is within the bounds which are exactly representable...
Tnew cast_ref(Told &oldvar)
std::string demangle(const char *name)
Mostly system independent demangler.
std::complex< Real > Complex
void libmesh_ignore(const Args &...)
T libmesh_real(T a)
bool isfinite(std::complex< T > a)
bool isnan(std::complex< T > a)
OStreamProxy out
T libmesh_imag(T)
Tnew libmesh_cast_int(Told oldvar)
void libmesh_merge_move(T &target, T &source)
static constexpr Real TOLERANCE
bool isinf(std::complex< T > a)
bool libmesh_isnan(T x)
MPI_Comm GLOBAL_COMM_WORLD
MPI Communicator used to initialize libMesh.
Tnew cast_ptr(Told *oldvar)
T libmesh_conj(T a)
constexpr std::false_type always_false
This is a helper variable template for cases when we want to use a default compile-time error with co...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Tnew libmesh_cast_ptr(Told *oldvar)
boost::multiprecision::float128 real(const boost::multiprecision::float128 in)
boost::multiprecision::float128 imag(const boost::multiprecision::float128)
bool operator()(const T1 &e1, const T2 &e2) const
bool operator()(const T1 &e1, const T1 &e2) const