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 739 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::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().

740 {
741  // Every processor had better be ready to exit at the same time.
742  // Even if we're not doing parallel_only debugging, we don't want
743  // one processor to try to exit until all others are done working.
744 
745  // We could be destructing here because we're unwinding the stack
746  // due to a thrown exception, though. It's possible that an
747  // application is catching exceptions outside of the LibMeshInit
748  // scope, or that we're using a C++ compiler that does unwinding
749  // for uncaught exceptions (the standard says whether to go straight
750  // to terminate() or unwind first is "implementation-defined"). If
751  // *that* is the case then we can't safely communicate with other
752  // processors that might not all be unwinding too.
753 #ifdef LIBMESH_ENABLE_EXCEPTIONS
754  if (!std::uncaught_exceptions())
755 #endif
756  this->comm().barrier();
757 
758  // We can't delete, finalize, etc. more than once without
759  // reinitializing in between
760  libmesh_exceptionless_assert(!libMesh::closed());
761 
762  // Delete reference counted singleton(s)
764 
765  // Clear the thread task manager we started
766  task_scheduler.reset();
767 
768  // Force the \p ReferenceCounter to print
769  // its reference count information. This allows
770  // us to find memory leaks. By default the
771  // \p ReferenceCounter only prints its information
772  // when the last created object has been destroyed.
773  // That does no good if we are leaking memory!
775 
776 
777  // Print an informative message if we detect a memory leak
778  if (ReferenceCounter::n_objects() != 0)
779  {
780  libMesh::err << "Memory leak detected!"
781  << std::endl;
782 
783 #if !defined(LIBMESH_ENABLE_REFERENCE_COUNTING) || defined(NDEBUG)
784 
785  libMesh::err << "Compile in DEBUG mode with --enable-reference-counting"
786  << std::endl
787  << "for more information"
788  << std::endl;
789 #endif
790 
791  }
792 
793  // print the perflog to individual processor's file.
795 
796  // Now clear the logging object, we don't want it to print
797  // a second time during the PerfLog destructor.
799 
800  // Reconnect the output streams
801  // (don't do this, or we will get messages from objects
802  // that go out of scope after the following return)
803  //std::cout.rdbuf(std::cerr.rdbuf());
804 
805 
806  // Set the initialized() flag to false
808 
810 
811 #ifdef LIBMESH_ENABLE_EXCEPTIONS
812  // Reset the old terminate handler; maybe the user code wants to
813  // keep doing C++ stuff after closing libMesh stuff.
814  std::set_terminate(_old_terminate_handler);
815 #endif
816 
817 #ifdef LIBMESH_HAVE_NETGEN
818  nglib::Ng_Exit();
819 #endif
820 
821  if (libMesh::on_command_line("--enable-fpe"))
822  libMesh::enableFPE(false);
823 
824 #if defined(LIBMESH_HAVE_PETSC)
825  // Let PETSc know about all the command line objects that we
826  // consumed without asking them, so we don't get unused option
827  // warnings about those.
828  std::vector<std::string> cli_names = command_line_names();
829  for (const auto & name : cli_names)
830  if (!name.empty() && name[0] == '-')
831  {
832  // Newer PETSc can give me a double-free I'm having trouble
833  // replicating; let's protect against trying to clear
834  // already-used values
835  PetscBool used = PETSC_FALSE;
836  auto ierr = PetscOptionsUsed(NULL, name.c_str(), &used);
837  CHKERRABORT(libMesh::GLOBAL_COMM_WORLD, ierr);
838  if (used == PETSC_FALSE)
839  {
840  ierr = PetscOptionsClearValue(NULL, name.c_str());
841  CHKERRABORT(libMesh::GLOBAL_COMM_WORLD, ierr);
842  }
843  }
844 
845  // Allow the user to bypass PETSc finalization
846  if (!libMesh::on_command_line ("--disable-petsc")
847 #if defined(LIBMESH_HAVE_MPI)
848  && !libMesh::on_command_line ("--disable-mpi")
849 #endif
850  )
851  {
852  PetscErrorCode ierr = LIBMESH_PETSC_SUCCESS;
853 # if defined(LIBMESH_HAVE_SLEPC)
854  if (libmesh_initialized_slepc)
855  ierr = SlepcFinalize();
856 # else
857  if (libmesh_initialized_petsc)
858  ierr = PetscFinalize();
859 # endif
860  CHKERRABORT(libMesh::GLOBAL_COMM_WORLD, ierr);
861  }
862 #endif
863 
864 #if defined(LIBMESH_HAVE_MPI) && defined(LIBMESH_HAVE_VTK)
865  _vtk_mpi_controller->Finalize(/*finalized_externally=*/1);
866  _vtk_mpi_controller->Delete();
867 #endif
868 
869  delete this->_comm;
870 
871 #if defined(LIBMESH_HAVE_MPI)
872  // Allow the user to bypass MPI finalization
873  if (!libMesh::on_command_line ("--disable-mpi"))
874  {
875  delete this->_timpi_init;
876  }
877 #else
878  delete this->_timpi_init;
879 #endif
880 }
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:330
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
bool _is_initialized
Flag that tells if init() has been called.
Definition: libmesh.C:304
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:913
void print_log() const
Print the log.
Definition: perf_log.C:697
static void cleanup()
Cleanup function.
bool on_command_line(std::string arg)
Definition: libmesh.C:921
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 883 of file libmesh.C.

References libMesh::perflog.

Referenced by libMesh::libmesh_terminate_handler().

884 {
885  return libMesh::perflog;
886 }
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 337 of file libmesh.C.

338 {
340 
341  // Now that we're done with output we should clean up our stream
342  // buffers; if we fail to uninstall_thread_buffered_sync() when
343  // needed we can end up seeing a segfault in iostreams destructors
345 
346  // If we have MPI and it has been initialized, we need to be sure
347  // and call MPI_Abort instead of std::abort, so that the parallel
348  // job can die nicely.
349 #if defined(LIBMESH_HAVE_MPI)
350  int mpi_initialized;
351  MPI_Initialized (&mpi_initialized);
352 
353  if (mpi_initialized)
354  MPI_Abort(libMesh::GLOBAL_COMM_WORLD, 1);
355 #endif
356 
357 #ifdef LIBMESH_ENABLE_EXCEPTIONS
358  // The system terminate_handler may do useful things, or the user
359  // may have set their own terminate handler that we want to call.
361 #endif
362 
363  // The last attempt to die if nothing else has killed us
364  std::abort();
365 }
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:337
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:883
void print_log() const
Print the log.
Definition: perf_log.C:697

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: