$extrastylesheet
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