libMesh
Public Member Functions | Static Private Member Functions | Private Attributes | Static Private Attributes | Friends | List of all members
libMesh::LibMeshInit Class Reference

The LibMeshInit class, when constructed, initializes the dependent libraries (e.g. More...

#include <libmesh.h>

Public Member Functions

 LibMeshInit (int argc, const char *const *argv, MPI_Comm COMM_WORLD_IN=MPI_COMM_WORLD, int n_threads=-1)
 Initialize the library for use, with the command line options provided. More...
 
 LibMeshInit (int argc, const char *const *argv, int COMM_WORLD_IN=0, int n_threads=-1)
 
virtual ~LibMeshInit ()
 Destructor. More...
 
const Parallel::Communicatorcomm () const
 Returns a Communicator created from the TIMPIInit object we hold, which will be a compatibility shim if MPI is not enabled. More...
 
Parallel::Communicatorcomm ()
 

Static Private Member Functions

static PerfLogperf_log ()
 

Private Attributes

TIMPI::TIMPIInit_timpi_init
 
Parallel::Communicator_comm
 
vtkMPIController * _vtk_mpi_controller
 

Static Private Attributes

static std::terminate_handler _old_terminate_handler
 

Friends

void libmesh_abort ()
 Abort as soon as possible. More...
 
void libmesh_terminate_handler ()
 A terminate handler. More...
 

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 91 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,
int  n_threads = -1 
)

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,
int  COMM_WORLD_IN = 0,
int  n_threads = -1 
)

◆ ~LibMeshInit()

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.

Definition at line 746 of file libmesh.C.

References _comm, libMesh::libMeshPrivateData::_is_initialized, _old_terminate_handler, _timpi_init, _vtk_mpi_controller, TIMPI::Communicator::barrier(), libMesh::Singleton::cleanup(), libMesh::cleanup_stream_buffers(), libMesh::PerfLog::clear(), libMesh::closed(), comm(), libMesh::command_line_names(), libMesh::ReferenceCounter::enable_print_counter_info(), libMesh::enableFPE(), libMesh::err, libMesh::GLOBAL_COMM_WORLD, libMesh::ReferenceCounter::n_objects(), libMesh::Quality::name(), libMesh::on_command_line(), libMesh::perflog, libMesh::ReferenceCounter::print_info(), and libMesh::PerfLog::print_log().

747 {
748  // Every processor had better be ready to exit at the same time.
749  // Even if we're not doing parallel_only debugging, we don't want
750  // one processor to try to exit until all others are done working.
751 
752  // We could be destructing here because we're unwinding the stack
753  // due to a thrown exception, though. It's possible that an
754  // application is catching exceptions outside of the LibMeshInit
755  // scope, or that we're using a C++ compiler that does unwinding
756  // for uncaught exceptions (the standard says whether to go straight
757  // to terminate() or unwind first is "implementation-defined"). If
758  // *that* is the case then we can't safely communicate with other
759  // processors that might not all be unwinding too.
760 #ifdef LIBMESH_ENABLE_EXCEPTIONS
761  if (!std::uncaught_exceptions())
762 #endif
763  this->comm().barrier();
764 
765  // We can't delete, finalize, etc. more than once without
766  // reinitializing in between
767  libmesh_exceptionless_assert(!libMesh::closed());
768 
769  // Delete reference counted singleton(s)
771 
772  // Clear the thread task manager we started
773  task_scheduler.reset();
774 
775  // If we have a memory leak, we want the details printed.
776  if (ReferenceCounter::n_objects() != 0)
778 
779  // Ask the \p ReferenceCounter to print its reference count
780  // information, if printing is enabled. This allows us to find
781  // memory leaks.
782  //
783  // If we don't have any leaks, we'll print to cout, only if we've
784  // been told to. If we do, we'll print to cerr, to make sure the
785  // user doesn't miss a leak that's only on a processor other than 0.
786  if (ReferenceCounter::n_objects() == 0)
788 
789  // Scream specifically if we detect a memory leak
790  if (ReferenceCounter::n_objects() != 0)
791  {
793 
794  libMesh::err << "Memory leak detected!"
795  << std::endl;
796 
797 #if !defined(LIBMESH_ENABLE_REFERENCE_COUNTING) || defined(NDEBUG)
798 
799  libMesh::err << "Compile in DEBUG mode with --enable-reference-counting"
800  << std::endl
801  << "for more information"
802  << std::endl;
803 #endif
804  }
805 
806  // print the perflog to individual processor's file.
808 
809  // Now clear the logging object, we don't want it to print
810  // a second time during the PerfLog destructor.
812 
813  // Reconnect the output streams
814  // (don't do this, or we will get messages from objects
815  // that go out of scope after the following return)
816  //std::cout.rdbuf(std::cerr.rdbuf());
817 
818 
819  // Set the initialized() flag to false
821 
823 
824 #ifdef LIBMESH_ENABLE_EXCEPTIONS
825  // Reset the old terminate handler; maybe the user code wants to
826  // keep doing C++ stuff after closing libMesh stuff.
827  std::set_terminate(_old_terminate_handler);
828 #endif
829 
830 #ifdef LIBMESH_HAVE_NETGEN
831  nglib::Ng_Exit();
832 #endif
833 
834  if (libMesh::on_command_line("--enable-fpe"))
835  libMesh::enableFPE(false);
836 
837 #if defined(LIBMESH_HAVE_PETSC)
838  // Let PETSc know about all the command line objects that we
839  // consumed without asking them, so we don't get unused option
840  // warnings about those.
841  std::vector<std::string> cli_names = command_line_names();
842  for (const auto & name : cli_names)
843  if (!name.empty() && name[0] == '-')
844  {
845  // Newer PETSc can give me a double-free I'm having trouble
846  // replicating; let's protect against trying to clear
847  // already-used values
848  PetscBool used = PETSC_FALSE;
849  auto ierr = PetscOptionsUsed(NULL, name.c_str(), &used);
850  CHKERRABORT(libMesh::GLOBAL_COMM_WORLD, ierr);
851  if (used == PETSC_FALSE)
852  {
853  ierr = PetscOptionsClearValue(NULL, name.c_str());
854  CHKERRABORT(libMesh::GLOBAL_COMM_WORLD, ierr);
855  }
856  }
857 
858  // Allow the user to bypass PETSc finalization
859  if (!libMesh::on_command_line ("--disable-petsc")
860 #if defined(LIBMESH_HAVE_MPI)
861  && !libMesh::on_command_line ("--disable-mpi")
862 #endif
863  )
864  {
865  PetscErrorCode ierr = LIBMESH_PETSC_SUCCESS;
866 # if defined(LIBMESH_HAVE_SLEPC)
867  if (libmesh_initialized_slepc)
868  ierr = SlepcFinalize();
869 # else
870  if (libmesh_initialized_petsc)
871  ierr = PetscFinalize();
872 # endif
873  CHKERRABORT(libMesh::GLOBAL_COMM_WORLD, ierr);
874  }
875 #endif
876 
877 #if defined(LIBMESH_HAVE_MPI) && defined(LIBMESH_HAVE_VTK)
878  _vtk_mpi_controller->Finalize(/*finalized_externally=*/1);
879  _vtk_mpi_controller->Delete();
880 #endif
881 
882  delete this->_comm;
883 
884 #if defined(LIBMESH_HAVE_MPI)
885  // Allow the user to bypass MPI finalization
886  if (!libMesh::on_command_line ("--disable-mpi"))
887  {
888  delete this->_timpi_init;
889  }
890 #else
891  delete this->_timpi_init;
892 #endif
893 }
std::string name(const ElemQuality q)
This function returns a string containing some name for q.
Definition: elem_quality.C:42
OStreamProxy err
bool closed()
Checks that the library has been closed.
Definition: libmesh.C:331
static unsigned int n_objects()
Prints the number of outstanding (created, but not yet destroyed) objects.
void barrier() const
PerfLog perflog
A PerfLog object to log performance.
static void print_info(std::ostream &out_stream=libMesh::out)
Prints the reference information, by default to libMesh::out.
MPI_Comm GLOBAL_COMM_WORLD
MPI Communicator used to initialize libMesh.
vtkMPIController * _vtk_mpi_controller
Definition: libmesh.h:149
const Parallel::Communicator & comm() const
Returns a Communicator created from the TIMPIInit object we hold, which will be a compatibility shim ...
Definition: libmesh.h:129
static void enable_print_counter_info()
Methods to enable/disable the reference counter output from print_info().
bool _is_initialized
Flag that tells if init() has been called.
Definition: libmesh.C:305
void cleanup_stream_buffers()
Helper to do cleanup from both destructor and terminate.
Definition: libmesh.C:244
TIMPI::TIMPIInit * _timpi_init
Definition: libmesh.h:136
void clear()
Clears all the internal data and restores the data structures to a pristine state.
Definition: perf_log.C:78
void enableFPE(bool on)
Toggle hardware trap floating point exceptions.
std::vector< std::string > command_line_names()
Definition: libmesh.C:926
void print_log() const
Print the log.
Definition: perf_log.C:714
static void cleanup()
Cleanup function.
bool on_command_line(std::string arg)
Definition: libmesh.C:934
static std::terminate_handler _old_terminate_handler
Definition: libmesh.h:153
Parallel::Communicator * _comm
Definition: libmesh.h:143

Member Function Documentation

◆ comm() [1/2]

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

Returns a Communicator created from the TIMPIInit object we hold, which will be a compatibility shim if MPI is not enabled.

Definition at line 129 of file libmesh.h.

References _comm.

Referenced by ~LibMeshInit().

129 { return *_comm; }
Parallel::Communicator * _comm
Definition: libmesh.h:143

◆ comm() [2/2]

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

Definition at line 131 of file libmesh.h.

References _comm.

131 { return *_comm; }
Parallel::Communicator * _comm
Definition: libmesh.h:143

◆ perf_log()

PerfLog & libMesh::LibMeshInit::perf_log ( )
staticprivate

Definition at line 896 of file libmesh.C.

References libMesh::perflog.

Referenced by libMesh::libmesh_terminate_handler().

897 {
898  return libMesh::perflog;
899 }
PerfLog perflog
A PerfLog object to log performance.

Friends And Related Function Documentation

◆ libmesh_abort

void libmesh_abort ( )
friend

Abort as soon as possible.

This cleans up stream buffers, aborts with MPI_Abort (if MPI is initialized), and falls back on std::abort afterward.

Definition at line 338 of file libmesh.C.

339 {
341 
342  // Now that we're done with output we should clean up our stream
343  // buffers; if we fail to uninstall_thread_buffered_sync() when
344  // needed we can end up seeing a segfault in iostreams destructors
346 
347  // If we have MPI and it has been initialized, we need to be sure
348  // and call MPI_Abort instead of std::abort, so that the parallel
349  // job can die nicely.
350 #if defined(LIBMESH_HAVE_MPI)
351  int mpi_initialized;
352  MPI_Initialized (&mpi_initialized);
353 
354  if (mpi_initialized)
355  MPI_Abort(libMesh::GLOBAL_COMM_WORLD, 1);
356 #endif
357 
358 #ifdef LIBMESH_ENABLE_EXCEPTIONS
359  // The system terminate_handler may do useful things, or the user
360  // may have set their own terminate handler that we want to call.
362 #endif
363 
364  // The last attempt to die if nothing else has killed us
365  std::abort();
366 }
PerfLog perflog
A PerfLog object to log performance.
MPI_Comm GLOBAL_COMM_WORLD
MPI Communicator used to initialize libMesh.
void cleanup_stream_buffers()
Helper to do cleanup from both destructor and terminate.
Definition: libmesh.C:244
void clear()
Clears all the internal data and restores the data structures to a pristine state.
Definition: perf_log.C:78
static std::terminate_handler _old_terminate_handler
Definition: libmesh.h:153

◆ libmesh_terminate_handler

void libmesh_terminate_handler ( )
friend

A terminate handler.

libMesh sets this to handle uncaught exceptions; it can also be called manually to cleanup, print any diagnostics, do cleanup, and abort.

If an uncaught exception is a TerminationException, as thrown by libmesh_terminate(), the handler avoids any diagnostic output.

If an uncaught exception is a std::exception, its message is printed, followed by stack trace and performance log output.

Definition at line 110 of file libmesh_exceptions.C.

111 {
112  bool quiet = false;
113 
114 #ifdef LIBMESH_ENABLE_EXCEPTIONS
115  // If we have an active exception, it may have an error message that
116  // we should print, or it may have a type that tells us not to print
117  // anything.
118  std::optional<std::string> exception_message;
119  std::exception_ptr ex = std::current_exception();
120  if (ex)
121  {
122  try
123  {
124  std::rethrow_exception(ex);
125  }
126  // Capture the exception message to be used later.
127  catch (const std::exception & std_ex)
128  {
129  exception_message = std_ex.what();
130  }
131  // We arrived here via TerminationException (likely from
132  // libmesh_terminate()), which implies that a useful
133  // error message has already been emitted.
134  catch (const TerminationException &)
135  {
136  quiet = true;
137  }
138  // We're just trying to detect exception types here, not
139  // actually rethrow
140  catch (...)
141  {
142  }
143  }
144 #endif
145 
146  if (!quiet)
147  {
148  libMesh::err << "libMesh terminating";
149 #ifdef LIBMESH_ENABLE_EXCEPTIONS
150  if (exception_message)
151  libMesh::err << ":\n" << *exception_message;
152 #endif
153  libMesh::err << std::endl;
154 
155  // If this got called then we're probably crashing; let's print a
156  // stack trace. The trace files that are ultimately written depend on:
157  // 1.) Who throws the exception.
158  // 2.) Whether the C++ runtime unwinds the stack before the
159  // terminate_handler is called (this is implementation defined).
160  //
161  // The various cases are summarized in the table below:
162  //
163  // | libmesh exception | other exception
164  // -------------------------------------
165  // stack unwinds | A | B
166  // stack does not unwind | C | D
167  //
168  // Case A: There will be two stack traces in the file: one "useful"
169  // one, and one nearly empty one due to stack unwinding.
170  // Case B: You will get one nearly empty stack trace (not great, Bob!)
171  // Case C: You will get two nearly identical stack traces, ignore one of them.
172  // Case D: You will get one useful stack trace.
173  //
174  // Cases A and B (where the stack unwinds when an exception leaves
175  // main) appear to be non-existent in practice. I don't have a
176  // definitive list, but the stack does not unwind for GCC on either
177  // Mac or Linux. I think there's good reasons for this behavior too:
178  // it's much easier to get a stack trace when the stack doesn't
179  // unwind, for example.
181 
182  // We may care about performance data pre-crash; it would be sad to
183  // throw that away.
185  }
186 
187  libmesh_abort();
188 }
friend void libmesh_abort()
Abort as soon as possible.
Definition: libmesh.C:338
OStreamProxy err
void write_traceout()
Writes a stack trace to a uniquely named file if –enable-tracefiles has been set by configure...
Definition: print_trace.C:240
static PerfLog & perf_log()
Definition: libmesh.C:896
void print_log() const
Print the log.
Definition: perf_log.C:714

Member Data Documentation

◆ _comm

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

Definition at line 143 of file libmesh.h.

Referenced by comm(), and ~LibMeshInit().

◆ _old_terminate_handler

std::terminate_handler libMesh::LibMeshInit::_old_terminate_handler
staticprivate

Definition at line 153 of file libmesh.h.

Referenced by libMesh::libmesh_abort(), and ~LibMeshInit().

◆ _timpi_init

TIMPI::TIMPIInit* libMesh::LibMeshInit::_timpi_init
private

Definition at line 136 of file libmesh.h.

Referenced by ~LibMeshInit().

◆ _vtk_mpi_controller

vtkMPIController* libMesh::LibMeshInit::_vtk_mpi_controller
private

Definition at line 149 of file libmesh.h.

Referenced by ~LibMeshInit().


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