$extrastylesheet
libmesh.C
Go to the documentation of this file.
00001 // The libMesh Finite Element Library.
00002 // Copyright (C) 2002-2014 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 // Local includes
00020 #include "libmesh/libmesh.h"
00021 #include "libmesh/auto_ptr.h"
00022 #include "libmesh/getpot.h"
00023 #include "libmesh/parallel.h"
00024 #include "libmesh/reference_counter.h"
00025 #include "libmesh/libmesh_singleton.h"
00026 #include "libmesh/remote_elem.h"
00027 #include "libmesh/threads.h"
00028 #include "libmesh/print_trace.h"
00029 
00030 
00031 // C/C++ includes
00032 #include <iostream>
00033 #include <fstream>
00034 
00035 #ifdef LIBMESH_ENABLE_EXCEPTIONS
00036 #include <exception>
00037 #endif
00038 
00039 #ifdef LIBMESH_HAVE_OPENMP
00040 #include <omp.h>
00041 #endif
00042 
00043 #include "signal.h"
00044 
00045 
00046 // floating-point exceptions
00047 #ifdef LIBMESH_HAVE_FENV_H
00048 #  include <fenv.h>
00049 #endif
00050 #ifdef LIBMESH_HAVE_XMMINTRIN_H
00051 #  include <xmmintrin.h>
00052 #endif
00053 
00054 
00055 #if defined(LIBMESH_HAVE_MPI)
00056 # include "libmesh/ignore_warnings.h"
00057 # include <mpi.h>
00058 # include "libmesh/restore_warnings.h"
00059 #endif // #if defined(LIBMESH_HAVE_MPI)
00060 
00061 #if defined(LIBMESH_HAVE_PETSC)
00062 # include "libmesh/petsc_macro.h"
00063 EXTERN_C_FOR_PETSC_BEGIN
00064 # include <petsc.h>
00065 # include <petscerror.h>
00066 #if !PETSC_RELEASE_LESS_THAN(3,3,0)
00067 #include "libmesh/petscdmlibmesh.h"
00068 #endif
00069 EXTERN_C_FOR_PETSC_END
00070 # if defined(LIBMESH_HAVE_SLEPC)
00071 #  include "libmesh/slepc_macro.h"
00072 EXTERN_C_FOR_PETSC_BEGIN
00073 #  include <slepc.h>
00074 EXTERN_C_FOR_PETSC_END
00075 # endif // #if defined(LIBMESH_HAVE_SLEPC)
00076 #endif // #if defined(LIBMESH_HAVE_PETSC)
00077 
00078 // --------------------------------------------------------
00079 // Local anonymous namespace to hold miscelaneous bits
00080 namespace {
00081 
00082 UniquePtr<GetPot> command_line;
00083 UniquePtr<std::ofstream> _ofstream;
00084 // If std::cout and std::cerr are redirected, we need to
00085 // be a little careful and save the original streambuf objects,
00086 // replacing them in the destructor before program termination.
00087 std::streambuf* out_buf (NULL);
00088 std::streambuf* err_buf (NULL);
00089 
00090 UniquePtr<libMesh::Threads::task_scheduler_init> task_scheduler;
00091 #if defined(LIBMESH_HAVE_MPI)
00092 bool libmesh_initialized_mpi = false;
00093 #endif
00094 #if defined(LIBMESH_HAVE_PETSC)
00095 bool libmesh_initialized_petsc = false;
00096 #endif
00097 #if defined(LIBMESH_HAVE_SLEPC)
00098 bool libmesh_initialized_slepc = false;
00099 #endif
00100 
00101 
00102 
00106 void libmesh_handleFPE(int /*signo*/, siginfo_t *info, void * /*context*/)
00107 {
00108   libMesh::err << std::endl;
00109   libMesh::err << "Floating point exception signaled (";
00110   switch (info->si_code)
00111     {
00112     case FPE_INTDIV: libMesh::err << "integer divide by zero"; break;
00113     case FPE_INTOVF: libMesh::err << "integer overflow"; break;
00114     case FPE_FLTDIV: libMesh::err << "floating point divide by zero"; break;
00115     case FPE_FLTOVF: libMesh::err << "floating point overflow"; break;
00116     case FPE_FLTUND: libMesh::err << "floating point underflow"; break;
00117     case FPE_FLTRES: libMesh::err << "floating point inexact result"; break;
00118     case FPE_FLTINV: libMesh::err << "invalid floating point operation"; break;
00119     case FPE_FLTSUB: libMesh::err << "subscript out of range"; break;
00120     default:         libMesh::err << "unrecognized"; break;
00121     }
00122   libMesh::err << ")!" << std::endl;
00123 
00124   libmesh_error_msg("\nTo track this down, compile in debug mode, then in gdb do:\n" \
00125                     << "  break libmesh_handleFPE\n"                    \
00126                     << "  run ...\n"                                    \
00127                     << "  bt");
00128 }
00129 
00130 
00131 void libmesh_handleSEGV(int /*signo*/, siginfo_t *info, void * /*context*/)
00132 {
00133   libMesh::err << std::endl;
00134   libMesh::err << "Segmentation fault exception signaled (";
00135   switch (info->si_code)
00136     {
00137     case SEGV_MAPERR: libMesh::err << "Address not mapped"; break;
00138     case SEGV_ACCERR: libMesh::err << "Invalid permissions"; break;
00139     default:         libMesh::err << "unrecognized"; break;
00140     }
00141   libMesh::err << ")!" << std::endl;
00142 
00143   libmesh_error_msg("\nTo track this down, compile in debug mode, then in gdb do:\n" \
00144                     << "  break libmesh_handleSEGV\n"                    \
00145                     << "  run ...\n"                                    \
00146                     << "  bt");
00147 }
00148 }
00149 
00150 
00151 
00152 #ifdef LIBMESH_HAVE_MPI
00153 void libMesh_MPI_Handler (MPI_Comm *, int *, ...)
00154 {
00155   libmesh_not_implemented();
00156 }
00157 #endif
00158 
00159 
00160 namespace libMesh
00161 {
00162 
00170 namespace libMeshPrivateData {
00171 
00175 extern bool _is_initialized;
00176 
00180 extern SolverPackage _solver_package;
00181 }
00182 
00183 
00184 // ------------------------------------------------------------
00185 // libMeshdata initialization
00186 #ifdef LIBMESH_HAVE_MPI
00187 #ifndef LIBMESH_DISABLE_COMMWORLD
00188 MPI_Comm           COMM_WORLD = MPI_COMM_NULL;
00189 #endif
00190 MPI_Comm           GLOBAL_COMM_WORLD = MPI_COMM_NULL;
00191 #else
00192 #ifndef LIBMESH_DISABLE_COMMWORLD
00193 int                COMM_WORLD = 0;
00194 #endif
00195 int                GLOBAL_COMM_WORLD = 0;
00196 #endif
00197 
00198 #ifdef LIBMESH_DISABLE_COMMWORLD
00199 Parallel::FakeCommunicator CommWorld;
00200 Parallel::FakeCommunicator& Parallel::Communicator_World = CommWorld;
00201 #else
00202 Parallel::Communicator CommWorld;
00203 Parallel::Communicator& Parallel::Communicator_World = CommWorld;
00204 #endif
00205 
00206 
00207 OStreamProxy out(std::cout);
00208 OStreamProxy err(std::cerr);
00209 
00210 bool warned_about_auto_ptr(false);
00211 
00212 PerfLog            perflog ("libMesh",
00213 #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING
00214                             true
00215 #else
00216                             false
00217 #endif
00218                             );
00219 
00220 
00221 // const Real         pi = 3.1415926535897932384626433832795029L;
00222 
00223 #ifdef LIBMESH_USE_COMPLEX_NUMBERS
00224 const Number       imaginary (0., 1.);
00225 // const Number       zero      (0., 0.);
00226 #else
00227 // const Number       zero = 0.;
00228 #endif
00229 
00230 // This is now a static constant in the header; no reason not to let
00231 // the compiler inline it.
00232 
00233 // const unsigned int invalid_uint = static_cast<unsigned int>(-1);
00234 
00235 
00236 
00237 // ------------------------------------------------------------
00238 // libMesh::libMeshPrivateData data initialization
00239 #ifdef LIBMESH_HAVE_MPI
00240 MPI_Errhandler libmesh_errhandler;
00241 
00242 processor_id_type libMesh::libMeshPrivateData::_n_processors = 1;
00243 processor_id_type libMesh::libMeshPrivateData::_processor_id = 0;
00244 #endif
00245 int           libMesh::libMeshPrivateData::_n_threads = 1; /* Threads::task_scheduler_init::automatic; */
00246 bool          libMesh::libMeshPrivateData::_is_initialized = false;
00247 SolverPackage libMesh::libMeshPrivateData::_solver_package =
00248 #if   defined(LIBMESH_HAVE_PETSC)    // PETSc is the default
00249   PETSC_SOLVERS;
00250 #elif defined(LIBMESH_HAVE_TRILINOS) // Use Trilinos if PETSc isn't there
00251 TRILINOS_SOLVERS;
00252 #elif defined(LIBMESH_HAVE_EIGEN)    // Use Eigen if neither are there
00253 EIGEN_SOLVERS;
00254 #elif defined(LIBMESH_HAVE_LASPACK)  // Use LASPACK as a last resort
00255 LASPACK_SOLVERS;
00256 #else                        // No valid linear solver package at compile time
00257 INVALID_SOLVER_PACKAGE;
00258 #endif
00259 
00260 
00261 
00262 // ------------------------------------------------------------
00263 // libMesh functions
00264 
00265 bool initialized()
00266 {
00267   return libMeshPrivateData::_is_initialized;
00268 }
00269 
00270 
00271 
00272 bool closed()
00273 {
00274   return !libMeshPrivateData::_is_initialized;
00275 }
00276 
00277 
00278 #ifdef LIBMESH_ENABLE_EXCEPTIONS
00279 std::terminate_handler old_terminate_handler;
00280 
00281 void libmesh_terminate_handler()
00282 {
00283   // If this got called then we're probably crashing; let's print a
00284   // stack trace.  The trace files that are ultimately written depend on:
00285   // 1.) Who throws the exception.
00286   // 2.) Whether the C++ runtime unwinds the stack before the
00287   //     terminate_handler is called (this is implementation defined).
00288   //
00289   // The various cases are summarized in the table below:
00290   //
00291   //                        | libmesh exception | other exception
00292   //                        -------------------------------------
00293   // stack unwinds          |        A          |       B
00294   // stack does not unwind  |        C          |       D
00295   //
00296   // Case A: There will be two stack traces in the file: one "useful"
00297   //         one, and one nearly empty one due to stack unwinding.
00298   // Case B: You will get one nearly empty stack trace (not great, Bob!)
00299   // Case C: You will get two nearly identical stack traces, ignore one of them.
00300   // Case D: You will get one useful stack trace.
00301   //
00302   // Cases A and B (where the stack unwinds when an exception leaves
00303   // main) appear to be non-existent in practice.  I don't have a
00304   // definitive list, but the stack does not unwind for GCC on either
00305   // Mac or Linux.  I think there's good reasons for this behavior too:
00306   // it's much easier to get a stack trace when the stack doesn't
00307   // unwind, for example.
00308   libMesh::write_traceout();
00309 
00310   // We may care about performance data pre-crash; it would be sad to
00311   // throw that away.
00312   libMesh::perflog.print_log();
00313   libMesh::perflog.clear();
00314 
00315   // If we have MPI and it has been initialized, we need to be sure
00316   // and call MPI_Abort instead of std::abort, so that the parallel
00317   // job can die nicely.
00318 #if defined(LIBMESH_HAVE_MPI)
00319   int mpi_initialized;
00320   MPI_Initialized (&mpi_initialized);
00321 
00322   if (mpi_initialized)
00323     MPI_Abort(libMesh::GLOBAL_COMM_WORLD, 1);
00324   else
00325 #endif
00326     // The system terminate_handler may do useful things like printing
00327     // uncaught exception information, or the user may have created
00328     // their own terminate handler that we want to call.
00329     old_terminate_handler();
00330 }
00331 #endif
00332 
00333 
00334 
00335 #ifndef LIBMESH_HAVE_MPI
00336 LibMeshInit::LibMeshInit (int argc, const char* const* argv)
00337 #else
00338 LibMeshInit::LibMeshInit (int argc, const char* const* argv,
00339                           MPI_Comm COMM_WORLD_IN)
00340 #endif
00341 {
00342   // should _not_ be initialized already.
00343   libmesh_assert (!libMesh::initialized());
00344 
00345   // Build a command-line parser.
00346   command_line.reset (new GetPot (argc, argv));
00347 
00348   // Disable performance logging upon request
00349   {
00350     if (libMesh::on_command_line ("--disable-perflog"))
00351       libMesh::perflog.disable_logging();
00352   }
00353 
00354   // Build a task scheduler
00355   {
00356     // Get the requested number of threads, defaults to 1 to avoid MPI and
00357     // multithreading competition.  If you would like to use MPI and multithreading
00358     // at the same time then (n_mpi_processes_per_node)x(n_threads) should be the
00359     //  number of processing cores per node.
00360     std::vector<std::string> n_threads(2);
00361     n_threads[0] = "--n_threads";
00362     n_threads[1] = "--n-threads";
00363     libMesh::libMeshPrivateData::_n_threads =
00364       libMesh::command_line_value (n_threads, 1);
00365 
00366     // Set the number of OpenMP threads to the same as the number of threads libMesh is going to use
00367 #ifdef LIBMESH_HAVE_OPENMP
00368     omp_set_num_threads(libMesh::libMeshPrivateData::_n_threads);
00369 #endif
00370 
00371     task_scheduler.reset (new Threads::task_scheduler_init(libMesh::n_threads()));
00372   }
00373 
00374   // Construct singletons who may be at risk of the
00375   // "static initialization order fiasco"
00376   Singleton::setup();
00377 
00378   // Make sure the construction worked
00379   libmesh_assert(remote_elem);
00380 
00381 #if defined(LIBMESH_HAVE_MPI)
00382 
00383   // Allow the user to bypass MPI initialization
00384   if (!libMesh::on_command_line ("--disable-mpi"))
00385     {
00386       // Check whether the calling program has already initialized
00387       // MPI, and avoid duplicate Init/Finalize
00388       int flag;
00389       MPI_Initialized (&flag);
00390 
00391       if (!flag)
00392         {
00393 #if MPI_VERSION > 1
00394           int mpi_thread_provided;
00395           const int mpi_thread_requested = libMesh::n_threads() > 1 ?
00396             MPI_THREAD_FUNNELED :
00397             MPI_THREAD_SINGLE;
00398 
00399           MPI_Init_thread (&argc, const_cast<char***>(&argv),
00400                            mpi_thread_requested, &mpi_thread_provided);
00401 
00402           if ((libMesh::n_threads() > 1) &&
00403               (mpi_thread_provided < MPI_THREAD_FUNNELED))
00404             {
00405               libmesh_warning("Warning: MPI failed to guarantee MPI_THREAD_FUNNELED\n"
00406                               << "for a threaded run.\n"
00407                               << "Be sure your library is funneled-thread-safe..."
00408                               << std::endl);
00409 
00410               // Ideally, if an MPI stack tells us it's unsafe for us
00411               // to use threads, we shouldn't use threads.
00412               // In practice, we've encountered one MPI stack (an
00413               // mvapich2 configuration) that returned
00414               // MPI_THREAD_SINGLE as a proper warning, two stacks
00415               // that handle MPI_THREAD_FUNNELED properly, and two
00416               // current stacks plus a couple old stacks that return
00417               // MPI_THREAD_SINGLE but support libMesh threaded runs
00418               // anyway.
00419 
00420               // libMesh::libMeshPrivateData::_n_threads = 1;
00421               // task_scheduler.reset (new Threads::task_scheduler_init(libMesh::n_threads()));
00422             }
00423 #else
00424           if (libMesh::libMeshPrivateData::_n_threads > 1)
00425             {
00426               libmesh_warning("Warning: using MPI1 for threaded code.\n" <<
00427                               "Be sure your library is funneled-thread-safe..." <<
00428                               std::endl);
00429             }
00430 
00431           MPI_Init (&argc, const_cast<char***>(&argv));
00432 #endif
00433           libmesh_initialized_mpi = true;
00434         }
00435 
00436       // Duplicate the input communicator for internal use
00437       // And get a Parallel::Communicator copy too, to use
00438       // as a default for that API
00439       this->_comm = COMM_WORLD_IN;
00440 
00441       libMesh::GLOBAL_COMM_WORLD = COMM_WORLD_IN;
00442 
00443 #ifndef LIBMESH_DISABLE_COMMWORLD
00444       libMesh::COMM_WORLD = COMM_WORLD_IN;
00445       Parallel::Communicator_World = COMM_WORLD_IN;
00446 #endif
00447 
00448       //MPI_Comm_set_name not supported in at least SGI MPT's MPI implementation
00449       //MPI_Comm_set_name (libMesh::COMM_WORLD, "libMesh::COMM_WORLD");
00450 
00451       libMeshPrivateData::_processor_id =
00452         cast_int<processor_id_type>(this->comm().rank());
00453       libMeshPrivateData::_n_processors =
00454         cast_int<processor_id_type>(this->comm().size());
00455 
00456       // Set up an MPI error handler if requested.  This helps us get
00457       // into a debugger with a proper stack when an MPI error occurs.
00458       if (libMesh::on_command_line ("--handle-mpi-errors"))
00459         {
00460 #if MPI_VERSION > 1
00461           MPI_Comm_create_errhandler(libMesh_MPI_Handler, &libmesh_errhandler);
00462           MPI_Comm_set_errhandler(libMesh::GLOBAL_COMM_WORLD, libmesh_errhandler);
00463           MPI_Comm_set_errhandler(MPI_COMM_WORLD, libmesh_errhandler);
00464 #else
00465           MPI_Errhandler_create(libMesh_MPI_Handler, &libmesh_errhandler);
00466           MPI_Errhandler_set(libMesh::GLOBAL_COMM_WORLD, libmesh_errhandler);
00467           MPI_Errhandler_set(MPI_COMM_WORLD, libmesh_errhandler);
00468 #endif // #if MPI_VERSION > 1
00469         }
00470     }
00471 
00472   // Could we have gotten bad values from the above calls?
00473   libmesh_assert_greater (libMeshPrivateData::_n_processors, 0);
00474 
00475   // The cast_int already tested _processor_id>=0
00476   // libmesh_assert_greater_equal (libMeshPrivateData::_processor_id, 0);
00477 
00478   // Let's be sure we properly initialize on every processor at once:
00479   libmesh_parallel_only(this->comm());
00480 
00481 #endif
00482 
00483 #if defined(LIBMESH_HAVE_PETSC)
00484 
00485   // Allow the user to bypass PETSc initialization
00486   if (!libMesh::on_command_line ("--disable-petsc")
00487 
00488 #if defined(LIBMESH_HAVE_MPI)
00489       // If the user bypassed MPI, we'd better be safe and assume that
00490       // PETSc was built to require it; otherwise PETSc initialization
00491       // dies.
00492       && !libMesh::on_command_line ("--disable-mpi")
00493 #endif
00494       )
00495     {
00496       int ierr=0;
00497 
00498       PETSC_COMM_WORLD = libMesh::GLOBAL_COMM_WORLD;
00499 
00500       // Check whether the calling program has already initialized
00501       // PETSc, and avoid duplicate Initialize/Finalize
00502       PetscBool petsc_already_initialized;
00503       ierr = PetscInitialized(&petsc_already_initialized);
00504       CHKERRABORT(libMesh::GLOBAL_COMM_WORLD,ierr);
00505       if (petsc_already_initialized != PETSC_TRUE)
00506         libmesh_initialized_petsc = true;
00507 # if defined(LIBMESH_HAVE_SLEPC)
00508 
00509       // If SLEPc allows us to check whether the calling program
00510       // has already initialized it, we do that, and avoid
00511       // duplicate Initialize/Finalize.
00512       // We assume that SLEPc will handle PETSc appropriately,
00513       // which it does in the versions we've checked.
00514 #  if !SLEPC_VERSION_LESS_THAN(2,3,3)
00515       if (!SlepcInitializeCalled)
00516 #  endif
00517         {
00518           ierr = SlepcInitialize  (&argc, const_cast<char***>(&argv), NULL, NULL);
00519           CHKERRABORT(libMesh::GLOBAL_COMM_WORLD,ierr);
00520           libmesh_initialized_slepc = true;
00521         }
00522 # else
00523       if (libmesh_initialized_petsc)
00524         {
00525           ierr = PetscInitialize (&argc, const_cast<char***>(&argv), NULL, NULL);
00526           CHKERRABORT(libMesh::GLOBAL_COMM_WORLD,ierr);
00527         }
00528 # endif
00529 #if !PETSC_RELEASE_LESS_THAN(3,3,0)
00530       // Register the reference implementation of DMlibMesh
00531 #if PETSC_RELEASE_LESS_THAN(3,4,0)
00532   ierr = DMRegister(DMLIBMESH, PETSC_NULL, "DMCreate_libMesh", DMCreate_libMesh); CHKERRABORT(libMesh::GLOBAL_COMM_WORLD,ierr);
00533 #else
00534   ierr = DMRegister(DMLIBMESH, DMCreate_libMesh); CHKERRABORT(libMesh::GLOBAL_COMM_WORLD,ierr);
00535 #endif
00536 
00537 #endif
00538     }
00539 #endif
00540 
00541   // Re-parse the command-line arguments.  Note that PETSc and MPI
00542   // initialization above may have removed command line arguments
00543   // that are not relevant to this application in the above calls.
00544   // We don't want a false-positive by detecting those arguments.
00545   command_line->parse_command_line (argc, argv);
00546 
00547   // The following line is an optimization when simultaneous
00548   // C and C++ style access to output streams is not required.
00549   // The amount of benefit which occurs is probably implementation
00550   // defined, and may be nothing.  On the other hand, I have seen
00551   // some IO tests where IO peformance improves by a factor of two.
00552   if (!libMesh::on_command_line ("--sync-with-stdio"))
00553     std::ios::sync_with_stdio(false);
00554 
00555   // Honor the --separate-libmeshout command-line option.
00556   // When this is specified, the library uses an independent ostream
00557   // for libMesh::out/libMesh::err messages, and
00558   // std::cout and std::cerr are untouched by any other options
00559   if (libMesh::on_command_line ("--separate-libmeshout"))
00560     {
00561       // Redirect.  We'll share streambufs with cout/cerr for now, but
00562       // presumably anyone using this option will want to replace the
00563       // bufs later.
00564       std::ostream* newout = new std::ostream(std::cout.rdbuf());
00565       libMesh::out = *newout;
00566       std::ostream* newerr = new std::ostream(std::cerr.rdbuf());
00567       libMesh::err = *newerr;
00568     }
00569 
00570   // Honor the --redirect-stdout command-line option.
00571   // When this is specified each processor sends
00572   // libMesh::out/libMesh::err messages to
00573   // stdout.processor.####
00574   if (libMesh::on_command_line ("--redirect-stdout"))
00575     {
00576       std::ostringstream filename;
00577       filename << "stdout.processor." << libMesh::global_processor_id();
00578       _ofstream.reset (new std::ofstream (filename.str().c_str()));
00579       // Redirect, saving the original streambufs!
00580       out_buf = libMesh::out.rdbuf (_ofstream->rdbuf());
00581       err_buf = libMesh::err.rdbuf (_ofstream->rdbuf());
00582     }
00583 
00584   // redirect libMesh::out to nothing on all
00585   // other processors unless explicitly told
00586   // not to via the --keep-cout command-line argument.
00587   if (libMesh::global_processor_id() != 0)
00588     if (!libMesh::on_command_line ("--keep-cout"))
00589       libMesh::out.rdbuf (NULL);
00590 
00591   // Check command line to override printing
00592   // of reference count information.
00593   if(libMesh::on_command_line("--disable-refcount-printing") )
00594     ReferenceCounter::disable_print_counter_info();
00595 
00596 #ifdef LIBMESH_ENABLE_EXCEPTIONS
00597   // Set our terminate handler to write stack traces in the event of a
00598   // crash
00599   old_terminate_handler = std::set_terminate(libmesh_terminate_handler);
00600 #endif
00601 
00602 
00603   if (libMesh::on_command_line("--enable-fpe"))
00604     libMesh::enableFPE(true);
00605 
00606   if (libMesh::on_command_line("--enable-segv"))
00607     libMesh::enableSEGV(true);
00608 
00609   // The library is now ready for use
00610   libMeshPrivateData::_is_initialized = true;
00611 
00612 
00613   // Make sure these work.  Library methods
00614   // depend on these being implemented properly,
00615   // so this is a good time to test them!
00616   libmesh_assert (libMesh::initialized());
00617   libmesh_assert (!libMesh::closed());
00618 }
00619 
00620 
00621 
00622 LibMeshInit::~LibMeshInit()
00623 {
00624   // We can't delete, finalize, etc. more than once without
00625   // reinitializing in between
00626   libmesh_exceptionless_assert(!libMesh::closed());
00627 
00628   // Delete reference counted singleton(s)
00629   Singleton::cleanup();
00630 
00631   // Clear the thread task manager we started
00632   task_scheduler.reset();
00633 
00634   // Let's be sure we properly close on every processor at once:
00635   libmesh_parallel_only(this->comm());
00636 
00637 
00638   // Force the \p ReferenceCounter to print
00639   // its reference count information.  This allows
00640   // us to find memory leaks.  By default the
00641   // \p ReferenceCounter only prints its information
00642   // when the last created object has been destroyed.
00643   // That does no good if we are leaking memory!
00644   ReferenceCounter::print_info ();
00645 
00646 
00647   // Print an informative message if we detect a memory leak
00648   if (ReferenceCounter::n_objects() != 0)
00649     {
00650       libMesh::err << "Memory leak detected!"
00651                    << std::endl;
00652 
00653 #if !defined(LIBMESH_ENABLE_REFERENCE_COUNTING) || defined(NDEBUG)
00654 
00655       libMesh::err << "Compile in DEBUG mode with --enable-reference-counting"
00656                    << std::endl
00657                    << "for more information"
00658                    << std::endl;
00659 #endif
00660 
00661     }
00662 
00663   //  print the perflog to individual processor's file.
00664   libMesh::perflog.print_log();
00665 
00666   // Now clear the logging object, we don't want it to print
00667   // a second time during the PerfLog destructor.
00668   libMesh::perflog.clear();
00669 
00670   // Reconnect the output streams
00671   // (don't do this, or we will get messages from objects
00672   //  that go out of scope after the following return)
00673   //std::cout.rdbuf(std::cerr.rdbuf());
00674 
00675 
00676   // Set the initialized() flag to false
00677   libMeshPrivateData::_is_initialized = false;
00678 
00679   if (libMesh::on_command_line ("--redirect-stdout"))
00680     {
00681       // If stdout/stderr were redirected to files, reset them now.
00682       libMesh::out.rdbuf (out_buf);
00683       libMesh::err.rdbuf (err_buf);
00684     }
00685 
00686   // If we built our own output streams, we want to clean them up.
00687   if (libMesh::on_command_line ("--separate-libmeshout"))
00688     {
00689       delete libMesh::out.get();
00690       delete libMesh::err.get();
00691 
00692       libMesh::out.reset(std::cout);
00693       libMesh::err.reset(std::cerr);
00694     }
00695 
00696 #ifdef LIBMESH_ENABLE_EXCEPTIONS
00697   // Reset the old terminate handler; maybe the user code wants to
00698   // keep doing C++ stuff after closing libMesh stuff.
00699   std::set_terminate(old_terminate_handler);
00700 #endif
00701 
00702 
00703   if (libMesh::on_command_line("--enable-fpe"))
00704     libMesh::enableFPE(false);
00705 
00706 #if defined(LIBMESH_HAVE_PETSC)
00707   // Allow the user to bypass PETSc finalization
00708   if (!libMesh::on_command_line ("--disable-petsc")
00709 #if defined(LIBMESH_HAVE_MPI)
00710       && !libMesh::on_command_line ("--disable-mpi")
00711 #endif
00712       )
00713     {
00714 # if defined(LIBMESH_HAVE_SLEPC)
00715       if (libmesh_initialized_slepc)
00716         SlepcFinalize();
00717 # else
00718       if (libmesh_initialized_petsc)
00719         PetscFinalize();
00720 # endif
00721     }
00722 #endif
00723 
00724 
00725 #if defined(LIBMESH_HAVE_MPI)
00726   // Allow the user to bypass MPI finalization
00727   if (!libMesh::on_command_line ("--disable-mpi"))
00728     {
00729       this->_comm.clear();
00730 #ifndef LIBMESH_DISABLE_COMMWORLD
00731       Parallel::Communicator_World.clear();
00732 #endif
00733 
00734       if (libmesh_initialized_mpi)
00735         MPI_Finalize();
00736     }
00737 #endif
00738 }
00739 
00740 
00741 
00745 void enableFPE(bool on)
00746 {
00747 #if !defined(LIBMESH_HAVE_FEENABLEEXCEPT) && defined(LIBMESH_HAVE_XMMINTRIN_H) && !defined(__SUNPRO_CC)
00748   static int flags = 0;
00749 #endif
00750 
00751   if (on)
00752     {
00753       struct sigaction new_action, old_action;
00754 
00755 #ifdef LIBMESH_HAVE_FEENABLEEXCEPT
00756       feenableexcept(FE_DIVBYZERO | FE_INVALID);
00757 #elif  LIBMESH_HAVE_XMMINTRIN_H
00758 #  ifndef __SUNPRO_CC
00759       flags = _MM_GET_EXCEPTION_MASK();           // store the flags
00760       _MM_SET_EXCEPTION_MASK(flags & ~_MM_MASK_INVALID);
00761 #  endif
00762 #endif
00763 
00764 
00765       // Set up the structure to specify the new action.
00766       new_action.sa_sigaction = libmesh_handleFPE;
00767       sigemptyset (&new_action.sa_mask);
00768       new_action.sa_flags = SA_SIGINFO;
00769 
00770       sigaction (SIGFPE, NULL, &old_action);
00771       if (old_action.sa_handler != SIG_IGN)
00772         sigaction (SIGFPE, &new_action, NULL);
00773     }
00774   else
00775     {
00776 #ifdef LIBMESH_HAVE_FEDISABLEEXCEPT
00777       fedisableexcept(FE_DIVBYZERO | FE_INVALID);
00778 #elif  LIBMESH_HAVE_XMMINTRIN_H
00779 #  ifndef __SUNPRO_CC
00780       _MM_SET_EXCEPTION_MASK(flags);
00781 #  endif
00782 #endif
00783       signal(SIGFPE, SIG_DFL);
00784     }
00785 }
00786 
00787 
00788 // Enable handling of SIGSEGV by libMesh
00789 // (potentially instead of PETSc)
00790 void enableSEGV(bool on)
00791 {
00792   static struct sigaction old_action;
00793   static bool was_on = false;
00794 
00795   if (on)
00796     {
00797       struct sigaction new_action;
00798       was_on = true;
00799 
00800       // Set up the structure to specify the new action.
00801       new_action.sa_sigaction = libmesh_handleSEGV;
00802       sigemptyset (&new_action.sa_mask);
00803       new_action.sa_flags = SA_SIGINFO;
00804 
00805       sigaction (SIGSEGV, &new_action, &old_action);
00806     }
00807   else if (was_on)
00808     {
00809       was_on = false;
00810       sigaction (SIGSEGV, &old_action, NULL);
00811     }
00812 }
00813 
00814 
00815 
00816 bool on_command_line (const std::string& arg)
00817 {
00818   // Make sure the command line parser is ready for use
00819   libmesh_assert(command_line.get());
00820 
00821   return command_line->search (arg);
00822 }
00823 
00824 
00825 
00826 template <typename T>
00827 T command_line_value (const std::string &name, T value)
00828 {
00829   // Make sure the command line parser is ready for use
00830   libmesh_assert(command_line.get());
00831 
00832   // only if the variable exists in the file
00833   if (command_line->have_variable(name.c_str()))
00834     value = (*command_line)(name.c_str(), value);
00835 
00836   return value;
00837 }
00838 
00839 template <typename T>
00840 T command_line_value (const std::vector<std::string> &name, T value)
00841 {
00842   // Make sure the command line parser is ready for use
00843   libmesh_assert(command_line.get());
00844 
00845   // Check for multiple options (return the first that matches)
00846   for (std::vector<std::string>::const_iterator i=name.begin(); i != name.end(); ++i)
00847     if (command_line->have_variable(i->c_str()))
00848       {
00849         value = (*command_line)(i->c_str(), value);
00850         break;
00851       }
00852 
00853   return value;
00854 }
00855 
00856 
00857 
00858 template <typename T>
00859 T command_line_next (const std::string &name, T value)
00860 {
00861   // Make sure the command line parser is ready for use
00862   libmesh_assert(command_line.get());
00863 
00864   if (command_line->search(1, name.c_str()))
00865     value = command_line->next(value);
00866 
00867   return value;
00868 }
00869 
00870 
00871 
00872 template <typename T>
00873 void command_line_vector (const std::string &name, std::vector<T>& vec)
00874 {
00875   // Make sure the command line parser is ready for use
00876   libmesh_assert(command_line.get());
00877 
00878   // only if the variable exists on the command line
00879   if (command_line->have_variable(name.c_str()))
00880     {
00881       unsigned size = command_line->vector_variable_size(name.c_str());
00882       vec.resize(size);
00883 
00884       for (unsigned i=0; i<size; ++i)
00885         vec[i] = (*command_line)(name.c_str(), vec[i], i);
00886     }
00887 }
00888 
00889 
00890 SolverPackage default_solver_package ()
00891 {
00892   libmesh_assert (libMesh::initialized());
00893 
00894   static bool called = false;
00895 
00896   // Check the command line.  Since the command line is
00897   // unchanging it is sufficient to do this only once.
00898   if (!called)
00899     {
00900       called = true;
00901 
00902 #ifdef LIBMESH_HAVE_PETSC
00903       if (libMesh::on_command_line ("--use-petsc"))
00904         libMeshPrivateData::_solver_package = PETSC_SOLVERS;
00905 #endif
00906 
00907 #ifdef LIBMESH_HAVE_TRILINOS
00908       if (libMesh::on_command_line ("--use-trilinos") ||
00909           libMesh::on_command_line ("--disable-petsc"))
00910         libMeshPrivateData::_solver_package = TRILINOS_SOLVERS;
00911 #endif
00912 
00913 #ifdef LIBMESH_HAVE_EIGEN
00914       if (libMesh::on_command_line ("--use-eigen"  ) ||
00915 #if defined(LIBMESH_HAVE_MPI)
00916           // If the user bypassed MPI, we disable PETSc and Trilinos
00917           // too
00918           libMesh::on_command_line ("--disable-mpi") ||
00919 #endif
00920           libMesh::on_command_line ("--disable-petsc"))
00921         libMeshPrivateData::_solver_package = EIGEN_SOLVERS;
00922 #endif
00923 
00924 #ifdef LIBMESH_HAVE_LASPACK
00925       if (libMesh::on_command_line ("--use-laspack"  ) ||
00926 #if defined(LIBMESH_HAVE_MPI)
00927           // If the user bypassed MPI, we disable PETSc and Trilinos
00928           // too
00929           libMesh::on_command_line ("--disable-mpi") ||
00930 #endif
00931           libMesh::on_command_line ("--disable-petsc"))
00932         libMeshPrivateData::_solver_package = LASPACK_SOLVERS;
00933 #endif
00934 
00935       if (libMesh::on_command_line ("--disable-laspack") &&
00936           libMesh::on_command_line ("--disable-trilinos") &&
00937           libMesh::on_command_line ("--disable-eigen") &&
00938           (
00939 #if defined(LIBMESH_HAVE_MPI)
00940            // If the user bypassed MPI, we disable PETSc too
00941            libMesh::on_command_line ("--disable-mpi") ||
00942 #endif
00943            libMesh::on_command_line ("--disable-petsc")))
00944         libMeshPrivateData::_solver_package = INVALID_SOLVER_PACKAGE;
00945     }
00946 
00947 
00948   return libMeshPrivateData::_solver_package;
00949 }
00950 
00951 
00952 
00953 //-------------------------------------------------------------------------------
00954 template int          command_line_value<int>         (const std::string&, int);
00955 template float        command_line_value<float>       (const std::string&, float);
00956 template double       command_line_value<double>      (const std::string&, double);
00957 template long double  command_line_value<long double> (const std::string&, long double);
00958 template std::string  command_line_value<std::string> (const std::string&, std::string);
00959 
00960 template int          command_line_next<int>         (const std::string&, int);
00961 template float        command_line_next<float>       (const std::string&, float);
00962 template double       command_line_next<double>      (const std::string&, double);
00963 template long double  command_line_next<long double> (const std::string&, long double);
00964 template std::string  command_line_next<std::string> (const std::string&, std::string);
00965 
00966 template void         command_line_vector<int>         (const std::string&, std::vector<int>&);
00967 template void         command_line_vector<float>       (const std::string&, std::vector<float>&);
00968 template void         command_line_vector<double>      (const std::string&, std::vector<double>&);
00969 template void         command_line_vector<long double> (const std::string&, std::vector<long double>&);
00970 
00971 } // namespace libMesh