libMesh::LibMeshInit Class Reference

#include <libmesh.h>

Public Member Functions

 LibMeshInit (int argc, const char *const *argv, MPI_Comm COMM_WORLD_IN=MPI_COMM_WORLD)
 
 LibMeshInit (int argc, const char *const *argv)
 
virtual ~LibMeshInit ()
 
const Parallel::Communicatorcomm () const
 
Parallel::Communicatorcomm ()
 

Private Attributes

Parallel::Communicator _comm
 
vtkMPIController * _vtk_mpi_controller
 

Detailed Description

The LibMeshInit class, when constructed, initializes the dependent libraries (e.g. MPI or PETSC) and does the command line parsing needed by libMesh. The LibMeshInit destructor closes those libraries properly.

For most users, a single LibMeshInit object should be created at the start of your main() function.

All libMesh functionality should be used only when a LibMeshInit object exists. Dependent library functionality, likewise, except in codes which manually initialize those libraries before LibMeshInit creation and finalize them after LibMeshInit destruction.

Since "it is best not to perform much more than a return rc after calling MPI_Finalize", applications which want to do anything after LibMeshInit destruction should manage MPI initialization and finalization manually.

Definition at line 79 of file libmesh.h.

Constructor & Destructor Documentation

◆ LibMeshInit() [1/2]

libMesh::LibMeshInit::LibMeshInit ( int  argc,
const char *const *  argv,
MPI_Comm  COMM_WORLD_IN = MPI_COMM_WORLD 
)

Initialize the library for use, with the command line options provided. This will e.g. call MPI_Init if MPI is available and enabled and has not already been initialized; similar initialization may take place for Petsc, Slepc, multithreading support, libMesh Singleton objects, the libMesh::out/err IO streams, and any libMesh handlers for floating-point exceptions, signals, and/or C++ aborts.

You must create a LibMeshInit object before using any of the library functionality. This method may take an optional parameter to use a user-specified MPI communicator.

◆ LibMeshInit() [2/2]

libMesh::LibMeshInit::LibMeshInit ( int  argc,
const char *const *  argv 
)

Definition at line 329 of file libmesh.C.

References libMesh::libMeshPrivateData::_is_initialized, libMesh::libMeshPrivateData::_n_processors, libMesh::libMeshPrivateData::_n_threads, libMesh::libMeshPrivateData::_processor_id, libMesh::closed(), libMesh::command_line_value(), libMesh::PerfLog::disable_logging(), libMesh::ReferenceCounter::disable_print_counter_info(), DMCreate_libMesh(), libMesh::enableFPE(), libMesh::enableSEGV(), libMesh::err, libMesh::GLOBAL_COMM_WORLD, libMesh::global_processor_id(), ierr, libMesh::initialized(), libMesh::libmesh_errhandler, libMesh_MPI_Handler(), libMesh::libmesh_terminate_handler(), libMesh::n_threads(), libMesh::old_terminate_handler, libMesh::on_command_line(), libMesh::out, libMesh::perflog, libMesh::BasicOStreamProxy< charT, traits >::rdbuf(), libMesh::remote_elem, and libMesh::Singleton::setup().

334 {
335  // should _not_ be initialized already.
336  libmesh_assert (!libMesh::initialized());
337 
338  // Build a command-line parser.
339  command_line.reset (new GetPot (argc, argv));
340 
341  // Disable performance logging upon request
342  {
343  if (libMesh::on_command_line ("--disable-perflog"))
345  }
346 
347  // Build a task scheduler
348  {
349  // Get the requested number of threads, defaults to 1 to avoid MPI and
350  // multithreading competition. If you would like to use MPI and multithreading
351  // at the same time then (n_mpi_processes_per_node)x(n_threads) should be the
352  // number of processing cores per node.
353  std::vector<std::string> n_threads(2);
354  n_threads[0] = "--n_threads";
355  n_threads[1] = "--n-threads";
358 
359  // If there's no threading model active, force _n_threads==1
360 #if !LIBMESH_USING_THREADS
362  {
364  libmesh_warning("Warning: You requested --n-threads>1 but no threading model is active!\n"
365  << "Forcing --n-threads==1 instead!");
366  }
367 #endif
368 
369  // Set the number of OpenMP threads to the same as the number of threads libMesh is going to use
370 #ifdef LIBMESH_HAVE_OPENMP
371  omp_set_num_threads(libMesh::libMeshPrivateData::_n_threads);
372 #endif
373 
374  task_scheduler.reset (new Threads::task_scheduler_init(libMesh::n_threads()));
375  }
376 
377  // Construct singletons who may be at risk of the
378  // "static initialization order fiasco"
380 
381  // Make sure the construction worked
382  libmesh_assert(remote_elem);
383 
384 #if defined(LIBMESH_HAVE_MPI)
385 
386  // Allow the user to bypass MPI initialization
387  if (!libMesh::on_command_line ("--disable-mpi"))
388  {
389  // Check whether the calling program has already initialized
390  // MPI, and avoid duplicate Init/Finalize
391  int flag;
392  libmesh_call_mpi(MPI_Initialized (&flag));
393 
394  if (!flag)
395  {
396  int mpi_thread_provided;
397  const int mpi_thread_requested = libMesh::n_threads() > 1 ?
398  MPI_THREAD_FUNNELED :
399  MPI_THREAD_SINGLE;
400 
401  libmesh_call_mpi
402  (MPI_Init_thread (&argc, const_cast<char ***>(&argv),
403  mpi_thread_requested, &mpi_thread_provided));
404 
405  if ((libMesh::n_threads() > 1) &&
406  (mpi_thread_provided < MPI_THREAD_FUNNELED))
407  {
408  libmesh_warning("Warning: MPI failed to guarantee MPI_THREAD_FUNNELED\n"
409  << "for a threaded run.\n"
410  << "Be sure your library is funneled-thread-safe..."
411  << std::endl);
412 
413  // Ideally, if an MPI stack tells us it's unsafe for us
414  // to use threads, we shouldn't use threads.
415  // In practice, we've encountered one MPI stack (an
416  // mvapich2 configuration) that returned
417  // MPI_THREAD_SINGLE as a proper warning, two stacks
418  // that handle MPI_THREAD_FUNNELED properly, and two
419  // current stacks plus a couple old stacks that return
420  // MPI_THREAD_SINGLE but support libMesh threaded runs
421  // anyway.
422 
423  // libMesh::libMeshPrivateData::_n_threads = 1;
424  // task_scheduler.reset (new Threads::task_scheduler_init(libMesh::n_threads()));
425  }
426  libmesh_initialized_mpi = true;
427  }
428 
429  // Duplicate the input communicator for internal use
430  // And get a Parallel::Communicator copy too, to use
431  // as a default for that API
432  this->_comm = COMM_WORLD_IN;
433 
434  libMesh::GLOBAL_COMM_WORLD = COMM_WORLD_IN;
435 
436  //MPI_Comm_set_name not supported in at least SGI MPT's MPI implementation
437  //MPI_Comm_set_name (libMesh::COMM_WORLD, "libMesh::COMM_WORLD");
438 
440  cast_int<processor_id_type>(this->comm().rank());
442  cast_int<processor_id_type>(this->comm().size());
443 
444  // Set up an MPI error handler if requested. This helps us get
445  // into a debugger with a proper stack when an MPI error occurs.
446  if (libMesh::on_command_line ("--handle-mpi-errors"))
447  {
448  libmesh_call_mpi
449  (MPI_Comm_create_errhandler(libMesh_MPI_Handler, &libmesh_errhandler));
450  libmesh_call_mpi
451  (MPI_Comm_set_errhandler(libMesh::GLOBAL_COMM_WORLD, libmesh_errhandler));
452  libmesh_call_mpi
453  (MPI_Comm_set_errhandler(MPI_COMM_WORLD, libmesh_errhandler));
454  }
455  }
456 
457  // Could we have gotten bad values from the above calls?
458  libmesh_assert_greater (libMeshPrivateData::_n_processors, 0);
459 
460  // The cast_int already tested _processor_id>=0
461  // libmesh_assert_greater_equal (libMeshPrivateData::_processor_id, 0);
462 
463  // Let's be sure we properly initialize on every processor at once:
464  libmesh_parallel_only(this->comm());
465 
466 #endif
467 
468 #if defined(LIBMESH_HAVE_PETSC)
469 
470  // Allow the user to bypass PETSc initialization
471  if (!libMesh::on_command_line ("--disable-petsc")
472 
473 #if defined(LIBMESH_HAVE_MPI)
474  // If the user bypassed MPI, we'd better be safe and assume that
475  // PETSc was built to require it; otherwise PETSc initialization
476  // dies.
477  && !libMesh::on_command_line ("--disable-mpi")
478 #endif
479  )
480  {
481  int ierr=0;
482 
483  PETSC_COMM_WORLD = libMesh::GLOBAL_COMM_WORLD;
484 
485  // Check whether the calling program has already initialized
486  // PETSc, and avoid duplicate Initialize/Finalize
487  PetscBool petsc_already_initialized;
488  ierr = PetscInitialized(&petsc_already_initialized);
489  CHKERRABORT(libMesh::GLOBAL_COMM_WORLD,ierr);
490  if (petsc_already_initialized != PETSC_TRUE)
491  libmesh_initialized_petsc = true;
492 # if defined(LIBMESH_HAVE_SLEPC)
493 
494  // If SLEPc allows us to check whether the calling program
495  // has already initialized it, we do that, and avoid
496  // duplicate Initialize/Finalize.
497  // We assume that SLEPc will handle PETSc appropriately,
498  // which it does in the versions we've checked.
499  if (!SlepcInitializeCalled)
500  {
501  ierr = SlepcInitialize (&argc, const_cast<char ***>(&argv), nullptr, nullptr);
502  CHKERRABORT(libMesh::GLOBAL_COMM_WORLD,ierr);
503  libmesh_initialized_slepc = true;
504  }
505 # else
506  if (libmesh_initialized_petsc)
507  {
508  ierr = PetscInitialize (&argc, const_cast<char ***>(&argv), nullptr, nullptr);
509  CHKERRABORT(libMesh::GLOBAL_COMM_WORLD,ierr);
510  }
511 # endif
512 #if !PETSC_RELEASE_LESS_THAN(3,3,0)
513  // Register the reference implementation of DMlibMesh
514 #if PETSC_RELEASE_LESS_THAN(3,4,0)
515  ierr = DMRegister(DMLIBMESH, PETSC_NULL, "DMCreate_libMesh", DMCreate_libMesh); CHKERRABORT(libMesh::GLOBAL_COMM_WORLD,ierr);
516 #else
517  ierr = DMRegister(DMLIBMESH, DMCreate_libMesh); CHKERRABORT(libMesh::GLOBAL_COMM_WORLD,ierr);
518 #endif
519 
520 #endif
521  }
522 #endif
523 
524 #if defined(LIBMESH_HAVE_MPI) && defined(LIBMESH_HAVE_VTK)
525  // Do MPI initialization for VTK.
526  _vtk_mpi_controller = vtkMPIController::New();
527  _vtk_mpi_controller->Initialize(&argc, const_cast<char ***>(&argv), /*initialized_externally=*/1);
528  _vtk_mpi_controller->SetGlobalController(_vtk_mpi_controller);
529 #endif
530 
531  // Re-parse the command-line arguments. Note that PETSc and MPI
532  // initialization above may have removed command line arguments
533  // that are not relevant to this application in the above calls.
534  // We don't want a false-positive by detecting those arguments.
535  //
536  // Note: this seems overly paranoid/like it should be unnecessary,
537  // plus we were doing it wrong for many years and not clearing the
538  // existing GetPot object before re-parsing the command line, so all
539  // the command line arguments appeared twice in the GetPot object...
540  command_line.reset (new GetPot (argc, argv));
541 
542  // The following line is an optimization when simultaneous
543  // C and C++ style access to output streams is not required.
544  // The amount of benefit which occurs is probably implementation
545  // defined, and may be nothing. On the other hand, I have seen
546  // some IO tests where IO performance improves by a factor of two.
547  if (!libMesh::on_command_line ("--sync-with-stdio"))
548  std::ios::sync_with_stdio(false);
549 
550  // Honor the --separate-libmeshout command-line option.
551  // When this is specified, the library uses an independent ostream
552  // for libMesh::out/libMesh::err messages, and
553  // std::cout and std::cerr are untouched by any other options
554  if (libMesh::on_command_line ("--separate-libmeshout"))
555  {
556  // Redirect. We'll share streambufs with cout/cerr for now, but
557  // presumably anyone using this option will want to replace the
558  // bufs later.
559  std::ostream * newout = new std::ostream(std::cout.rdbuf());
560  libMesh::out = *newout;
561  std::ostream * newerr = new std::ostream(std::cerr.rdbuf());
562  libMesh::err = *newerr;
563  }
564 
565  // Process command line arguments for redirecting stdout/stderr.
566  bool
567  cmdline_has_redirect_stdout = libMesh::on_command_line ("--redirect-stdout"),
568  cmdline_has_redirect_output = libMesh::on_command_line ("--redirect-output");
569 
570  // The --redirect-stdout command-line option has been deprecated in
571  // favor of "--redirect-output basename".
572  if (cmdline_has_redirect_stdout)
573  libmesh_warning("The --redirect-stdout command line option has been deprecated. "
574  "Use '--redirect-output basename' instead.");
575 
576  // Honor the "--redirect-stdout" and "--redirect-output basename"
577  // command-line options. When one of these is specified, each
578  // processor sends libMesh::out/libMesh::err messages to
579  // stdout.processor.#### (default) or basename.processor.####.
580  if (cmdline_has_redirect_stdout || cmdline_has_redirect_output)
581  {
582  std::string basename = "stdout";
583 
584  // Look for following argument if using new API
585  if (cmdline_has_redirect_output)
586  {
587  // Set the cursor to the correct location in the list of command line arguments.
588  command_line->search(1, "--redirect-output");
589 
590  // Get the next option on the command line as a string.
591  std::string next_string = "";
592  next_string = command_line->next(next_string);
593 
594  // If the next string starts with a dash, we assume it's
595  // another flag and not a file basename requested by the
596  // user.
597  if (next_string.size() > 0 && next_string.find_first_of("-") != 0)
598  basename = next_string;
599  }
600 
601  std::ostringstream filename;
602  filename << basename << ".processor." << libMesh::global_processor_id();
603  _ofstream.reset (new std::ofstream (filename.str().c_str()));
604 
605  // Redirect, saving the original streambufs!
606  out_buf = libMesh::out.rdbuf (_ofstream->rdbuf());
607  err_buf = libMesh::err.rdbuf (_ofstream->rdbuf());
608  }
609 
610  // redirect libMesh::out to nothing on all
611  // other processors unless explicitly told
612  // not to via the --keep-cout command-line argument.
613  if (libMesh::global_processor_id() != 0)
614  if (!libMesh::on_command_line ("--keep-cout"))
615  libMesh::out.rdbuf (nullptr);
616 
617  // Similarly, the user can request to drop cerr on all non-0 ranks.
618  // By default, errors are printed on all ranks, but this can lead to
619  // interleaved/unpredictable outputs when doing parallel regression
620  // testing, which this option is designed to support.
621  if (libMesh::global_processor_id() != 0)
622  if (libMesh::on_command_line ("--drop-cerr"))
623  libMesh::err.rdbuf (nullptr);
624 
625  // Check command line to override printing
626  // of reference count information.
627  if (libMesh::on_command_line("--disable-refcount-printing"))
629 
630 #ifdef LIBMESH_ENABLE_EXCEPTIONS
631  // Set our terminate handler to write stack traces in the event of a
632  // crash
633  old_terminate_handler = std::set_terminate(libmesh_terminate_handler);
634 #endif
635 
636 
637  if (libMesh::on_command_line("--enable-fpe"))
638  libMesh::enableFPE(true);
639 
640  if (libMesh::on_command_line("--enable-segv"))
641  libMesh::enableSEGV(true);
642 
643  // The library is now ready for use
645 
646 
647  // Make sure these work. Library methods
648  // depend on these being implemented properly,
649  // so this is a good time to test them!
650  libmesh_assert (libMesh::initialized());
651  libmesh_assert (!libMesh::closed());
652 }
653 
654 
655 
657 {
658  // Every processor had better be ready to exit at the same time.
659  // This would be a libmesh_parallel_only() function, except that
660  // libmesh_parallel_only() uses libmesh_assert() which throws an
661  // exception() which causes compilers to scream about exceptions
662  // inside destructors.
663 
664  // Even if we're not doing parallel_only debugging, we don't want
665  // one processor to try to exit until all others are done working.
666  this->comm().barrier();
667 
668  // We can't delete, finalize, etc. more than once without
669  // reinitializing in between
670  libmesh_exceptionless_assert(!libMesh::closed());
671 
672  // Delete reference counted singleton(s)
674 
675  // Clear the thread task manager we started
676  task_scheduler.reset();
677 
678  // Force the \p ReferenceCounter to print
679  // its reference count information. This allows
680  // us to find memory leaks. By default the
681  // \p ReferenceCounter only prints its information
682  // when the last created object has been destroyed.
683  // That does no good if we are leaking memory!
685 
686 
687  // Print an informative message if we detect a memory leak
688  if (ReferenceCounter::n_objects() != 0)
689  {
690  libMesh::err << "Memory leak detected!"
691  << std::endl;
692 
693 #if !defined(LIBMESH_ENABLE_REFERENCE_COUNTING) || defined(NDEBUG)
694 
695  libMesh::err << "Compile in DEBUG mode with --enable-reference-counting"
696  << std::endl
697  << "for more information"
698  << std::endl;
699 #endif
700 
701  }
702 
703  // print the perflog to individual processor's file.
705 
706  // Now clear the logging object, we don't want it to print
707  // a second time during the PerfLog destructor.
709 
710  // Reconnect the output streams
711  // (don't do this, or we will get messages from objects
712  // that go out of scope after the following return)
713  //std::cout.rdbuf(std::cerr.rdbuf());
714 
715 
716  // Set the initialized() flag to false
718 
719  if (libMesh::on_command_line ("--redirect-stdout") ||
720  libMesh::on_command_line ("--redirect-output"))
721  {
722  // If stdout/stderr were redirected to files, reset them now.
723  libMesh::out.rdbuf (out_buf);
724  libMesh::err.rdbuf (err_buf);
725  }
726 
727  // If we built our own output streams, we want to clean them up.
728  if (libMesh::on_command_line ("--separate-libmeshout"))
729  {
730  delete libMesh::out.get();
731  delete libMesh::err.get();
732 
733  libMesh::out.reset(std::cout);
734  libMesh::err.reset(std::cerr);
735  }
736 
737 #ifdef LIBMESH_ENABLE_EXCEPTIONS
738  // Reset the old terminate handler; maybe the user code wants to
739  // keep doing C++ stuff after closing libMesh stuff.
740  std::set_terminate(old_terminate_handler);
741 #endif
742 
743 
744  if (libMesh::on_command_line("--enable-fpe"))
745  libMesh::enableFPE(false);
746 
747 #if defined(LIBMESH_HAVE_PETSC)
748  // Allow the user to bypass PETSc finalization
749  if (!libMesh::on_command_line ("--disable-petsc")
750 #if defined(LIBMESH_HAVE_MPI)
751  && !libMesh::on_command_line ("--disable-mpi")
752 #endif
753  )
754  {
755 # if defined(LIBMESH_HAVE_SLEPC)
756  if (libmesh_initialized_slepc)
757  SlepcFinalize();
758 # else
759  if (libmesh_initialized_petsc)
760  PetscFinalize();
761 # endif
762  }
763 #endif
764 
765 #if defined(LIBMESH_HAVE_MPI) && defined(LIBMESH_HAVE_VTK)
766  _vtk_mpi_controller->Finalize(/*finalized_externally=*/1);
767  _vtk_mpi_controller->Delete();
768 #endif
769 
770 #if defined(LIBMESH_HAVE_MPI)
771  // Allow the user to bypass MPI finalization
772  if (!libMesh::on_command_line ("--disable-mpi"))
773  {
774  this->_comm.clear();
775 
776  if (libmesh_initialized_mpi)
777  {
778  // We can't just libmesh_assert here because destructor,
779  // but we ought to report any errors
780  unsigned int error_code = MPI_Finalize();
781  if (error_code != MPI_SUCCESS)
782  {
783  char error_string[MPI_MAX_ERROR_STRING+1];
784  int error_string_len;
785  MPI_Error_string(error_code, error_string,
786  &error_string_len);
787  std::cerr << "Failure from MPI_Finalize():\n"
788  << error_string << std::endl;
789  }
790  }
791  }
792 #endif
793 }
bool closed()
Definition: libmesh.C:265
static unsigned int n_objects()
unsigned int n_threads()
Definition: libmesh_base.h:96
processor_id_type size() const
Definition: communicator.h:175
void enableSEGV(bool on)
Definition: libmesh.C:846
processor_id_type _n_processors
Definition: libmesh.C:235
Parallel::Communicator _comm
Definition: libmesh.h:123
MPI_Comm GLOBAL_COMM_WORLD
Definition: libmesh.C:195
void reset(streamT &target)
vtkMPIController * _vtk_mpi_controller
Definition: libmesh.h:129
PerfLog perflog("libMesh", #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING true #else false #endif)
const Parallel::Communicator & comm() const
Definition: libmesh.h:118
PetscErrorCode DMCreate_libMesh(DM dm)
tbb::task_scheduler_init task_scheduler_init
Definition: threads_tbb.h:73
processor_id_type rank() const
Definition: communicator.h:173
std::terminate_handler old_terminate_handler
Definition: libmesh.C:272
processor_id_type _processor_id
Definition: libmesh.C:236
OStreamProxy err(std::cerr)
static void print_info(std::ostream &out=libMesh::out)
streambufT * rdbuf() const
MPI_Errhandler libmesh_errhandler
Definition: libmesh.C:233
void clear()
Definition: perf_log.C:77
void enableFPE(bool on)
Definition: libmesh.C:800
PetscTruth PetscBool
Definition: petsc_macro.h:67
PetscErrorCode ierr
processor_id_type global_processor_id()
Definition: libmesh_base.h:85
void print_log() const
Definition: perf_log.C:684
bool initialized()
Definition: libmesh.C:258
void libMesh_MPI_Handler(MPI_Comm *, int *,...)
Definition: libmesh.C:161
static void cleanup()
bool on_command_line(std::string arg)
Definition: libmesh.C:876
T command_line_value(const std::string &name, T value)
Definition: libmesh.C:909
static void disable_print_counter_info()
OStreamProxy out(std::cout)
void disable_logging()
Definition: perf_log.h:156
void libmesh_terminate_handler()
Definition: libmesh.C:274
const RemoteElem * remote_elem
Definition: remote_elem.C:57

◆ ~LibMeshInit()

virtual libMesh::LibMeshInit::~LibMeshInit ( )
virtual

Destructor. Cleans up libMesh Singleton objects, and thread manager if threading is in use. Prints reference count and performance logging information if enabled. Restores pre-LibMeshInit terminate handler and floating-point-exception handling. Finalizes any of Slepc, Petsc, and MPI which were initialized by LibMeshInit.

Member Function Documentation

◆ comm() [1/2]

const Parallel::Communicator& libMesh::LibMeshInit::comm ( ) const
inline

Returns the Communicator created by this libMesh object, which will be a compatibility shim if MPI is not enabled, or a wrapper for the user-input MPI_Comm if we were constructed with one, or a wrapper for MPI_COMM_WORLD by default.

Definition at line 118 of file libmesh.h.

References _comm.

118 { return _comm; }
Parallel::Communicator _comm
Definition: libmesh.h:123

◆ comm() [2/2]

Parallel::Communicator& libMesh::LibMeshInit::comm ( )
inline

Definition at line 120 of file libmesh.h.

References _comm.

120 { return _comm; }
Parallel::Communicator _comm
Definition: libmesh.h:123

Member Data Documentation

◆ _comm

Parallel::Communicator libMesh::LibMeshInit::_comm
private

Definition at line 123 of file libmesh.h.

Referenced by comm().

◆ _vtk_mpi_controller

vtkMPIController* libMesh::LibMeshInit::_vtk_mpi_controller
private

Definition at line 129 of file libmesh.h.


The documentation for this class was generated from the following files: