libmesh_common.h
Go to the documentation of this file.00001 // The libMesh Finite Element Library. 00002 // Copyright (C) 2002-2012 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner 00003 00004 // This library is free software; you can redistribute it and/or 00005 // modify it under the terms of the GNU Lesser General Public 00006 // License as published by the Free Software Foundation; either 00007 // version 2.1 of the License, or (at your option) any later version. 00008 00009 // This library is distributed in the hope that it will be useful, 00010 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 // Lesser General Public License for more details. 00013 00014 // You should have received a copy of the GNU Lesser General Public 00015 // License along with this library; if not, write to the Free Software 00016 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00017 00018 00019 00020 #ifndef LIBMESH_LIBMESH_COMMON_H 00021 #define LIBMESH_LIBMESH_COMMON_H 00022 00023 00024 // The library configuration options 00025 #include "libmesh/libmesh_config.h" 00026 00027 // Include the MPI definition 00028 #ifdef LIBMESH_HAVE_MPI 00029 # include "libmesh/ignore_warnings.h" 00030 # include <mpi.h> 00031 # include "libmesh/restore_warnings.h" 00032 #endif 00033 00034 // C/C++ includes everyone should know about 00035 #include <fstream> // needed for argument to print_trace() 00036 #include <unistd.h> // needed for getpid() 00037 #include <complex> 00038 // #include <cassert> // Use libmesh_assert() now 00039 #ifdef LIBMESH_HAVE_CSIGNAL 00040 # include <csignal> 00041 #endif 00042 #ifdef LIBMESH_HAVE_STDLIB_H 00043 # include <cstdlib> 00044 #endif 00045 #include <typeinfo> // std::bad_cast 00046 00047 // _basic_ library functionality 00048 #include "libmesh/libmesh_base.h" 00049 #include "libmesh/libmesh_exceptions.h" 00050 extern "C" { 00051 #include "libmesh/libmesh_C_isnan.h" 00052 } 00053 00054 // Proxy class for libMesh::out/err output 00055 #include "libmesh/ostream_proxy.h" 00056 #include "libmesh/print_trace.h" 00057 00058 // Here we add missing types to the standard namespace. For example, 00059 // std::max(double, float) etc... are well behaved but not defined 00060 // by the standard. This also includes workarounds for super-strict 00061 // implementations, for example Sun Studio and PGI C++. However, 00062 // this necessarily requires breaking the ISO-C++ standard, and is 00063 // really just a hack. As such, only do it if we are building the 00064 // libmesh library itself. Specifially, *DO NOT* export this to 00065 // user code or install this header. 00066 #ifdef LIBMESH_IS_COMPILING_ITSELF 00067 # include "libmesh/libmesh_augment_std_namespace.h" 00068 #endif 00069 00070 00071 namespace libMesh 00072 { 00073 00074 // Undefine any existing macros 00075 #ifdef Real 00076 # undef Real 00077 #endif 00078 00079 //#ifdef REAL 00080 //# undef REAL 00081 //#endif 00082 00083 #ifdef Complex 00084 # undef Complex 00085 #endif 00086 00087 #ifdef COMPLEX 00088 # undef COMPLEX 00089 #endif 00090 00091 #ifdef MPI_REAL 00092 # undef MPI_REAL 00093 #endif 00094 00095 // Check to see if TOLERANCE has been defined by another 00096 // package, if so we might want to change the name... 00097 #ifdef TOLERANCE 00098 DIE A HORRIBLE DEATH HERE... 00099 # undef TOLERANCE 00100 #endif 00101 00102 00103 00104 // Define the type to use for real numbers 00105 00106 typedef LIBMESH_DEFAULT_SCALAR_TYPE Real; 00107 00108 // Define a corresponding tolerance. This is what should be 00109 // considered "good enough" when doing floating point comparisons. 00110 // For example, v == 0 is changed to std::abs(v) < TOLERANCE. 00111 00112 #ifndef LIBMESH_DEFAULT_SINGLE_PRECISION 00113 #ifdef LIBMESH_DEFAULT_TRIPLE_PRECISION 00114 static const Real TOLERANCE = 1.e-8; 00115 # define MPI_REAL MPI_LONG_DOUBLE 00116 #else 00117 static const Real TOLERANCE = 1.e-6; 00118 # define MPI_REAL MPI_DOUBLE 00119 #endif 00120 #else 00121 static const Real TOLERANCE = 2.5e-3; 00122 # define MPI_REAL MPI_FLOAT 00123 #endif 00124 00125 // Define the type to use for complex numbers 00126 // Always use std::complex<double>, as required by Petsc? 00127 // If your version of Petsc doesn't support 00128 // std::complex<other_precision>, then you'd better just leave 00129 // Real==double 00130 typedef std::complex<Real> Complex; 00131 typedef std::complex<Real> COMPLEX; 00132 00133 00134 // Helper functions for complex/real numbers 00135 // to clean up #ifdef LIBMESH_USE_COMPLEX_NUMBERS elsewhere 00136 template<typename T> inline T libmesh_real(T a) { return a; } 00137 template<typename T> inline T libmesh_conj(T a) { return a; } 00138 00139 template<typename T> 00140 inline T libmesh_real(std::complex<T> a) { return std::real(a); } 00141 00142 template<typename T> 00143 inline std::complex<T> libmesh_conj(std::complex<T> a) { return std::conj(a); } 00144 00145 // isnan isn't actually C++ standard yet; in contexts where it's not defined in 00146 // cmath, libmesh_isnan will just end up returning false. 00147 inline bool libmesh_isnan(float a) { return libmesh_C_isnan_float(a); } 00148 inline bool libmesh_isnan(double a) { return libmesh_C_isnan_double(a); } 00149 inline bool libmesh_isnan(long double a) { return libmesh_C_isnan_longdouble(a); } 00150 00151 template <typename T> 00152 inline bool libmesh_isnan(std::complex<T> a) { return (libmesh_isnan(std::real(a)) || libmesh_isnan(std::imag(a))); } 00153 00154 00155 // Define the value type for unknowns in simulations. 00156 // This is either Real or Complex, depending on how 00157 // the library was configures 00158 #if defined (LIBMESH_USE_REAL_NUMBERS) 00159 typedef Real Number; 00160 #elif defined (LIBMESH_USE_COMPLEX_NUMBERS) 00161 typedef Complex Number; 00162 #else 00163 DIE A HORRIBLE DEATH HERE... 00164 #endif 00165 00166 00167 // Define the value type for error estimates. 00168 // Since AMR/C decisions don't have to be precise, 00169 // we default to float for memory efficiency. 00170 typedef float ErrorVectorReal; 00171 #define MPI_ERRORVECTORREAL MPI_FLOAT 00172 00173 00174 #ifdef LIBMESH_HAVE_MPI 00175 00178 extern MPI_Comm COMM_WORLD; 00179 #else 00180 00184 extern int COMM_WORLD; 00185 #endif 00186 00187 // Let's define a couple output streams - these will default 00188 // to cout/cerr, but LibMeshInit (or the user) can also set them to 00189 // something more sophisticated. 00190 // 00191 // We use a proxy class rather than references so they can be 00192 // reseated at runtime. 00193 00194 extern OStreamProxy out; 00195 extern OStreamProxy err; 00196 00197 // These are useful macros that behave like functions in the code. 00198 // If you want to make sure you are accessing a section of code just 00199 // stick a libmesh_here(); in it, for example 00200 00201 #define libmesh_here() do { libMesh::err << "[" << libMesh::processor_id() << "] " << __FILE__ << ", line " << __LINE__ << ", compiled " << __DATE__ << " at " << __TIME__ << std::endl; } while (0) 00202 00203 // the libmesh_stop() macro will stop the code until a SIGCONT signal 00204 // is recieved. This is useful, for example, when determining the 00205 // memory used by a given operation. A libmesh_stop() could be 00206 // instered before and after a questionable operation and the delta 00207 // memory can be obtained from a ps or top. This macro only works for 00208 // serial cases. 00209 #ifdef LIBMESH_HAVE_CSIGNAL 00210 # define libmesh_stop() do { if (libMesh::n_processors() == 1) { libmesh_here(); libMesh::out << "Stopping process " << getpid() << "..." << std::endl; std::raise(SIGSTOP); libMesh::out << "Continuing process " << getpid() << "..." << std::endl; } } while(0) 00211 #else 00212 # define libmesh_stop() do { if (libMesh::n_processors() == 1) { libmesh_here(); libMesh::out << "WARNING: libmesh_stop() does not work without the <csignal> header file!" << std::endl; } } while(0) 00213 #endif 00214 00215 // The libmesh_dbg_var() macro indicates that an argument to a function 00216 // is used only in debug mode (i.e., when NDEBUG is not defined). 00217 #ifndef NDEBUG 00218 #define libmesh_dbg_var(var) var 00219 #else 00220 #define libmesh_dbg_var(var) 00221 #endif 00222 00223 // The libmesh_dbg_var() macro indicates that an argument to a function 00224 // is used only in debug mode (i.e., when NDEBUG is not defined). 00225 #ifndef NDEBUG 00226 #define libmesh_dbg_var(var) var 00227 #else 00228 #define libmesh_dbg_var(var) 00229 #endif 00230 00231 // The libmesh_assert() macro acts like C's assert(), but throws a 00232 // libmesh_error() (including stack trace, etc) instead of just exiting 00233 #ifdef NDEBUG 00234 #define libmesh_assert(asserted) ((void) 0) 00235 #define libmesh_assert_msg(asserted, msg) ((void) 0) 00236 #define libmesh_assert_equal_to(expr1,expr2) ((void) 0) 00237 #define libmesh_assert_not_equal_to(expr1,expr2) ((void) 0) 00238 #define libmesh_assert_less(expr1,expr2) ((void) 0) 00239 #define libmesh_assert_greater(expr1,expr2) ((void) 0) 00240 #define libmesh_assert_less_equal(expr1,expr2) ((void) 0) 00241 #define libmesh_assert_greater_equal(expr1,expr2) ((void) 0) 00242 #else 00243 #define libmesh_assert(asserted) do { if (!(asserted)) { libMesh::err << "Assertion `" #asserted "' failed." << std::endl; libmesh_error(); } } while(0) 00244 #define libmesh_assert_msg(asserted, msg) do { if (!(asserted)) { libMesh::err << "Assertion `" #asserted "' failed." << std::endl; libmesh_error_msg(msg); } } while(0) 00245 #define libmesh_assert_equal_to(expr1,expr2) do { if (!(expr1 == expr2)) { libMesh::err << "Assertion `" #expr1 " == " #expr2 "' failed.\n" #expr1 " = " << (expr1) << "\n" #expr2 " = " << (expr2) << std::endl; libmesh_error(); } } while(0) 00246 #define libmesh_assert_not_equal_to(expr1,expr2) do { if (!(expr1 != expr2)) { libMesh::err << "Assertion `" #expr1 " != " #expr2 "' failed.\n" #expr1 " = " << (expr1) << "\n" #expr2 " = " << (expr2) << std::endl; libmesh_error(); } } while(0) 00247 #define libmesh_assert_less(expr1,expr2) do { if (!(expr1 < expr2)) { libMesh::err << "Assertion `" #expr1 " < " #expr2 "' failed.\n" #expr1 " = " << (expr1) << "\n" #expr2 " = " << (expr2) << std::endl; libmesh_error(); } } while(0) 00248 #define libmesh_assert_greater(expr1,expr2) do { if (!(expr1 > expr2)) { libMesh::err << "Assertion `" #expr1 " > " #expr2 "' failed.\n" #expr1 " = " << (expr1) << "\n" #expr2 " = " << (expr2) << std::endl; libmesh_error(); } } while(0) 00249 #define libmesh_assert_less_equal(expr1,expr2) do { if (!(expr1 <= expr2)) { libMesh::err << "Assertion `" #expr1 " <= " #expr2 "' failed.\n" #expr1 " = " << (expr1) << "\n" #expr2 " = " << (expr2) << std::endl; libmesh_error(); } } while(0) 00250 #define libmesh_assert_greater_equal(expr1,expr2) do { if (!(expr1 >= expr2)) { libMesh::err << "Assertion `" #expr1 " >= " #expr2 "' failed.\n" #expr1 " = " << (expr1) << "\n" #expr2 " = " << (expr2) << std::endl; libmesh_error(); } } while(0) 00251 #endif 00252 00253 // The libmesh_write_traceout() macro writes stack trace files, if 00254 // that feature has been configured. 00255 #ifdef LIBMESH_ENABLE_TRACEFILES 00256 #define libmesh_write_traceout() do { std::stringstream outname; outname << "traceout_" << libMesh::processor_id() << '_' << getpid() << ".txt"; std::ofstream traceout(outname.str().c_str()); libMesh::print_trace(traceout); } while(0) 00257 #else 00258 #define libmesh_write_traceout() do { } while (0) 00259 #endif 00260 00261 // The libmesh_error() macro prints a message and throws a LogicError 00262 // exception 00263 // 00264 // The libmesh_not_implemented() macro prints a message and throws a 00265 // NotImplemented exception 00266 // 00267 // The libmesh_file_error(const std::string& filename) macro prints a message 00268 // and throws a FileError exception 00269 // 00270 // The libmesh_convergence_failure() macro 00271 // throws a ConvergenceFailure exception 00272 // 00273 // These macros no longer write traceout files themselves, but if the 00274 // exceptions they throw are uncaught then the 00275 // libmesh_terminate_handler will write such files. 00276 #define libmesh_error() do { if (libMesh::n_processors() == 1) libMesh::print_trace(); libmesh_here(); LIBMESH_THROW(libMesh::LogicError()); } while(0) 00277 #define libmesh_error_msg(msg) do { if (libMesh::n_processors() == 1) libMesh::print_trace(); libmesh_here(); libMesh::err << msg << std::endl; LIBMESH_THROW(libMesh::LogicError()); } while(0) 00278 #define libmesh_not_implemented() do { if (libMesh::n_processors() == 1) libMesh::print_trace(); libmesh_here(); LIBMESH_THROW(libMesh::NotImplemented()); } while(0) 00279 #define libmesh_not_implemented_msg(msg) do { if (libMesh::n_processors() == 1) libMesh::print_trace(); libmesh_here(); libMesh::err << msg << std::endl; LIBMESH_THROW(libMesh::NotImplemented()); } while(0) 00280 #define libmesh_file_error(filename) do { if (libMesh::n_processors() == 1) libMesh::print_trace(); libmesh_here(); LIBMESH_THROW(libMesh::FileError(filename)); } while(0) 00281 #define libmesh_file_error_msg(filename, msg) do { if (libMesh::n_processors() == 1) libMesh::print_trace(); libmesh_here(); libMesh:err << msg << std::endl; LIBMESH_THROW(libMesh::FileError(filename)); } while(0) 00282 #define libmesh_convergence_failure() do { LIBMESH_THROW(libMesh::ConvergenceFailure()); } while(0) 00283 00284 // The libmesh_example_assert() macro prints a message and calls 00285 // "return 0;" if the assertion specified by the macro is not true. This 00286 // macro is used in the example executables, which should run when the 00287 // configure-time libMesh options support them but which should exit 00288 // without failure otherwise. 00289 // 00290 // This macro only works in main(), because we have no better way than 00291 // "return 0" from main to immediately exit successfully - std::exit(0) 00292 // gets seen by at least some MPI stacks as failure. 00293 00294 #define libmesh_example_assert(asserted, requirement) do { if (!(asserted)) { libMesh::out << "Assertion `" #asserted "' failed. Configuring libMesh with " requirement " may be required to run this code." << std::endl; return 0; } } while(0) 00295 00296 // libmesh_cast_ref and libmesh_cast_ptr do a dynamic cast and assert 00297 // the result, if we have RTTI enabled and we're in debug or 00298 // development modes, but they just do a faster static cast if we're 00299 // in optimized mode. 00300 // 00301 // Use these casts when you're certain that a cast will succeed in 00302 // correct code but you want to be able to double-check. 00303 template <typename Tnew, typename Told> 00304 inline Tnew libmesh_cast_ref(Told& oldvar) 00305 { 00306 #if !defined(NDEBUG) && defined(LIBMESH_HAVE_RTTI) 00307 try 00308 { 00309 Tnew newvar = dynamic_cast<Tnew>(oldvar); 00310 return newvar; 00311 } 00312 catch (std::bad_cast) 00313 { 00314 libMesh::err << "Failed to convert " << typeid(Told).name() 00315 << " reference to " << typeid(Tnew).name() 00316 << std::endl; 00317 libMesh::err << "The " << typeid(Told).name() 00318 << " appears to be a " 00319 << typeid(*(&oldvar)).name() << std::endl; 00320 libmesh_error(); 00321 } 00322 #else 00323 return(static_cast<Tnew>(oldvar)); 00324 #endif 00325 } 00326 00327 // We use two different function names to avoid an odd overloading 00328 // ambiguity bug with icc 10.1.008 00329 template <typename Tnew, typename Told> 00330 inline Tnew libmesh_cast_ptr (Told* oldvar) 00331 { 00332 #if !defined(NDEBUG) && defined(LIBMESH_HAVE_RTTI) 00333 Tnew newvar = dynamic_cast<Tnew>(oldvar); 00334 if (!newvar) 00335 { 00336 libMesh::err << "Failed to convert " << typeid(Told).name() 00337 << " pointer to " << typeid(Tnew).name() 00338 << std::endl; 00339 libMesh::err << "The " << typeid(Told).name() 00340 << " appears to be a " 00341 << typeid(*oldvar).name() << std::endl; 00342 libmesh_error(); 00343 } 00344 return newvar; 00345 #else 00346 return(static_cast<Tnew>(oldvar)); 00347 #endif 00348 } 00349 00350 00351 // libmesh_cast_int asserts that the value of the castee is within the 00352 // bounds which are exactly representable by the output type, if we're 00353 // in debug or development modes, but it just does a faster static 00354 // cast if we're in optimized mode. 00355 // 00356 // Use these casts when you're certain that a cast will succeed in 00357 // correct code but you want to be able to double-check. 00358 template <typename Tnew, typename Told> 00359 inline Tnew libmesh_cast_int (Told oldvar) 00360 { 00361 libmesh_assert_equal_to 00362 (oldvar, static_cast<Told>(static_cast<Tnew>(oldvar))); 00363 00364 return(static_cast<Tnew>(oldvar)); 00365 } 00366 00367 00368 // The libmesh_do_once macro helps us avoid redundant repeated 00369 // repetitions of the same warning messages 00370 #undef libmesh_do_once 00371 #define libmesh_do_once(do_this) do { static bool did_this_already = false; if (!did_this_already) { did_this_already = true; do_this; } } while (0) 00372 00373 00374 // The libmesh_experimental macro warns that you are using 00375 // bleeding-edge code 00376 #undef libmesh_experimental 00377 #define libmesh_experimental() libmesh_do_once(libMesh::out << "*** Warning, This code is untested, experimental, or likely to see future API changes: " << __FILE__ << ", line " << __LINE__ << ", compiled " << __DATE__ << " at " << __TIME__ << " ***" << std::endl;) 00378 00379 00380 // The libmesh_deprecated macro warns that you are using obsoleted code 00381 #undef libmesh_deprecated 00382 #define libmesh_deprecated() libmesh_do_once(libMesh::out << "*** Warning, This code is deprecated, and likely to be removed in future library versions! " << __FILE__ << ", line " << __LINE__ << ", compiled " << __DATE__ << " at " << __TIME__ << " ***" << std::endl;) 00383 00384 00385 00386 00387 // 3D spatial dimension unless otherwise specified 00388 #ifndef LIBMESH_DIM 00389 # define LIBMESH_DIM 3 00390 #endif 00391 00392 00393 // A function template for ignoring unused variables. This is a way 00394 // to shut up unused variable compiler warnings on a case by case 00395 // basis. 00396 template<class T> inline void libmesh_ignore( const T& ) { } 00397 00398 00399 // build a integer representation of version 00400 #define LIBMESH_VERSION_ID(major,minor,patch) (((major) << 16) | ((minor) << 8) | ((patch) & 0xFF)) 00401 00402 } // namespace libMesh 00403 00404 00405 #endif // LIBMESH_LIBMESH_COMMON_H
Site Created By: libMesh Developers
Last modified: February 05 2013 19:54:47 UTC
Hosted By: