LCOV - code coverage report
Current view: top level - src/base - libmesh.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4229 (6a9aeb) with base 727f46 Lines: 190 307 61.9 %
Date: 2025-08-19 19:27:09 Functions: 20 57 35.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2025 Benjamin S. Kirk, John W. Peterson, Roy H. Stogner
       3             : 
       4             : // This library is free software; you can redistribute it and/or
       5             : // modify it under the terms of the GNU Lesser General Public
       6             : // License as published by the Free Software Foundation; either
       7             : // version 2.1 of the License, or (at your option) any later version.
       8             : 
       9             : // This library is distributed in the hope that it will be useful,
      10             : // but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      12             : // Lesser General Public License for more details.
      13             : 
      14             : // You should have received a copy of the GNU Lesser General Public
      15             : // License along with this library; if not, write to the Free Software
      16             : // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      17             : 
      18             : 
      19             : // Local includes
      20             : #include "libmesh/libmesh.h"
      21             : 
      22             : // libMesh includes
      23             : #include "libmesh/getpot.h"
      24             : #include "libmesh/reference_counter.h"
      25             : #include "libmesh/libmesh_singleton.h"
      26             : #include "libmesh/remote_elem.h"
      27             : #include "libmesh/threads.h"
      28             : #include "libmesh/parallel_only.h"
      29             : #include "libmesh/print_trace.h"
      30             : #include "libmesh/enum_solver_package.h"
      31             : #include "libmesh/perf_log.h"
      32             : 
      33             : // TIMPI includes
      34             : #include "timpi/communicator.h"
      35             : #include "timpi/timpi_init.h"
      36             : 
      37             : // C/C++ includes
      38             : #include <cstdlib>
      39             : #include <iostream>
      40             : #include <fstream>
      41             : 
      42             : #ifdef LIBMESH_ENABLE_EXCEPTIONS
      43             : #include <exception>
      44             : #endif
      45             : 
      46             : #ifdef LIBMESH_HAVE_OPENMP
      47             : #include <omp.h>
      48             : #endif
      49             : 
      50             : #include "stdlib.h" // C, not C++ - we need setenv() from POSIX
      51             : #include "signal.h"
      52             : 
      53             : 
      54             : // floating-point exceptions
      55             : #ifdef LIBMESH_HAVE_FENV_H
      56             : #  include <fenv.h>
      57             : #endif
      58             : #ifdef LIBMESH_HAVE_XMMINTRIN_H
      59             : #  include <xmmintrin.h>
      60             : #endif
      61             : 
      62             : 
      63             : #if defined(LIBMESH_HAVE_MPI)
      64             : # include "libmesh/ignore_warnings.h"
      65             : # include <mpi.h>
      66             : # include "libmesh/restore_warnings.h"
      67             : #endif // #if defined(LIBMESH_HAVE_MPI)
      68             : 
      69             : #if defined(LIBMESH_HAVE_PETSC)
      70             : # include "libmesh/petsc_solver_exception.h"
      71             : # include <petsc.h>
      72             : # include <petscerror.h>
      73             : # include "libmesh/petscdmlibmesh.h"
      74             : # if defined(LIBMESH_HAVE_SLEPC)
      75             : // Ignore unused variable warnings from SLEPc
      76             : #  include "libmesh/ignore_warnings.h"
      77             : #  include "libmesh/slepc_macro.h"
      78             : #  include <slepc.h>
      79             : #  include "libmesh/restore_warnings.h"
      80             : # endif // #if defined(LIBMESH_HAVE_SLEPC)
      81             : #endif // #if defined(LIBMESH_HAVE_PETSC)
      82             : 
      83             : #ifdef LIBMESH_HAVE_NETGEN
      84             : // We need the nglib namespace, because it's used everywhere in nglib
      85             : // and we don't get binary compatibility without it.
      86             : //
      87             : // We need the nglib namespace *here*, because somehow nobody ever
      88             : // figured out to just put it in nglib.h?
      89             : namespace nglib {
      90             : #include "netgen/nglib/nglib.h"
      91             : }
      92             : #endif
      93             : 
      94             : // If we're using MPI and VTK has been detected, we need to do some
      95             : // MPI initialize/finalize stuff for VTK.
      96             : #if defined(LIBMESH_HAVE_MPI) && defined(LIBMESH_HAVE_VTK)
      97             : #include "libmesh/ignore_warnings.h"
      98             : # include "vtkMPIController.h"
      99             : #include "libmesh/restore_warnings.h"
     100             : #endif
     101             : 
     102             : #include <mutex>
     103             : 
     104             : // --------------------------------------------------------
     105             : // Local anonymous namespace to hold miscellaneous bits
     106             : namespace {
     107             : 
     108             : std::unique_ptr<GetPot> command_line;
     109             : 
     110             : std::set<std::string> command_line_name_set;
     111             : 
     112             : std::unique_ptr<std::ofstream> _ofstream;
     113             : // If std::cout and std::cerr are redirected, we need to
     114             : // be a little careful and save the original streambuf objects,
     115             : // replacing them in the destructor before program termination.
     116             : std::streambuf * out_buf (nullptr);
     117             : std::streambuf * err_buf (nullptr);
     118             : 
     119             : std::unique_ptr<libMesh::Threads::task_scheduler_init> task_scheduler;
     120             : #if defined(LIBMESH_HAVE_PETSC)
     121             : bool libmesh_initialized_petsc = false;
     122             : #endif
     123             : #if defined(LIBMESH_HAVE_SLEPC)
     124             : bool libmesh_initialized_slepc = false;
     125             : #endif
     126             : 
     127             : 
     128             : 
     129             : /**
     130             :  * Floating point exception handler -- courtesy of Cody Permann & MOOSE team
     131             :  */
     132             : #if LIBMESH_HAVE_DECL_SIGACTION
     133           0 : void libmesh_handleFPE(int /*signo*/, siginfo_t * info, void * /*context*/)
     134             : {
     135           0 :   libMesh::err << std::endl;
     136           0 :   libMesh::err << "Floating point exception signaled (";
     137           0 :   switch (info->si_code)
     138             :     {
     139           0 :     case FPE_INTDIV: libMesh::err << "integer divide by zero"; break;
     140           0 :     case FPE_INTOVF: libMesh::err << "integer overflow"; break;
     141           0 :     case FPE_FLTDIV: libMesh::err << "floating point divide by zero"; break;
     142           0 :     case FPE_FLTOVF: libMesh::err << "floating point overflow"; break;
     143           0 :     case FPE_FLTUND: libMesh::err << "floating point underflow"; break;
     144           0 :     case FPE_FLTRES: libMesh::err << "floating point inexact result"; break;
     145           0 :     case FPE_FLTINV: libMesh::err << "invalid floating point operation"; break;
     146           0 :     case FPE_FLTSUB: libMesh::err << "subscript out of range"; break;
     147           0 :     default:         libMesh::err << "unrecognized"; break;
     148             :     }
     149           0 :   libMesh::err << ")!" << std::endl;
     150             : 
     151           0 :   libmesh_error_msg("\nTo track this down, compile in debug mode, then in gdb do:\n" \
     152             :                     << "  break libmesh_handleFPE\n"                    \
     153             :                     << "  run ...\n"                                    \
     154             :                     << "  bt");
     155             : }
     156             : 
     157             : 
     158           0 : void libmesh_handleSEGV(int /*signo*/, siginfo_t * info, void * /*context*/)
     159             : {
     160           0 :   libMesh::err << std::endl;
     161           0 :   libMesh::err << "Segmentation fault exception signaled (";
     162           0 :   switch (info->si_code)
     163             :     {
     164           0 :     case SEGV_MAPERR: libMesh::err << "Address not mapped"; break;
     165           0 :     case SEGV_ACCERR: libMesh::err << "Invalid permissions"; break;
     166           0 :     default:         libMesh::err << "unrecognized"; break;
     167             :     }
     168           0 :   libMesh::err << ")!" << std::endl;
     169             : 
     170           0 :   libmesh_error_msg("\nTo track this down, compile in debug mode, then in gdb do:\n" \
     171             :                     << "  break libmesh_handleSEGV\n"                    \
     172             :                     << "  run ...\n"                                    \
     173             :                     << "  bt");
     174             : }
     175             : #endif
     176             : }
     177             : 
     178             : 
     179             : 
     180             : #ifdef LIBMESH_HAVE_MPI
     181           0 : void libMesh_MPI_Handler (MPI_Comm *, int *, ...)
     182             : {
     183           0 :   libmesh_not_implemented();
     184             : }
     185             : #endif
     186             : 
     187             : 
     188             : namespace libMesh
     189             : {
     190             : 
     191             : /**
     192             :  * Namespaces don't provide private data,
     193             :  * so let's take the data we would like
     194             :  * private and put it in an obnoxious
     195             :  * namespace.  At least that way it is a
     196             :  * pain to use, thus discouraging errors.
     197             :  */
     198             : namespace libMeshPrivateData {
     199             : 
     200             : /**
     201             :  * Flag that tells if \p init() has been called.
     202             :  */
     203             : extern bool _is_initialized;
     204             : 
     205             : /**
     206             :  * The default solver package to use.
     207             :  */
     208             : extern SolverPackage _solver_package;
     209             : }
     210             : 
     211             : 
     212             : // ------------------------------------------------------------
     213             : // libMesh data initialization
     214             : #ifdef LIBMESH_HAVE_MPI
     215             : MPI_Comm           GLOBAL_COMM_WORLD = MPI_COMM_NULL;
     216             : #else
     217             : int                GLOBAL_COMM_WORLD = 0;
     218             : #endif
     219             : 
     220             : OStreamProxy out(std::cout);
     221             : OStreamProxy err(std::cerr);
     222             : 
     223             : bool warned_about_auto_ptr(false);
     224             : 
     225             : PerfLog            perflog ("libMesh",
     226             : #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING
     227             :                             true
     228             : #else
     229             :                             false
     230             : #endif
     231             :                             );
     232             : 
     233             : 
     234             : #ifdef LIBMESH_USE_COMPLEX_NUMBERS
     235             : const Number       imaginary (0., 1.);
     236             : // const Number       zero      (0., 0.);
     237             : #else
     238             : // const Number       zero = 0.;
     239             : #endif
     240             : 
     241             : // This is now a static constant in the header; no reason not to let
     242             : // the compiler inline it.
     243             : 
     244             : // const unsigned int invalid_uint = static_cast<unsigned int>(-1);
     245             : 
     246             : 
     247             : 
     248             : // ------------------------------------------------------------
     249             : // libMesh::libMeshPrivateData data initialization
     250             : #ifdef LIBMESH_HAVE_MPI
     251             : MPI_Errhandler libmesh_errhandler;
     252             : 
     253             : processor_id_type libMesh::libMeshPrivateData::_n_processors = 1;
     254             : processor_id_type libMesh::libMeshPrivateData::_processor_id = 0;
     255             : #endif
     256             : int           libMesh::libMeshPrivateData::_n_threads = 1; /* Threads::task_scheduler_init::automatic; */
     257             : bool          libMesh::libMeshPrivateData::_is_initialized = false;
     258             : SolverPackage libMesh::libMeshPrivateData::_solver_package =
     259             : #if   defined(LIBMESH_HAVE_PETSC)    // PETSc is the default
     260             :   PETSC_SOLVERS;
     261             : #elif defined(LIBMESH_TRILINOS_HAVE_AZTECOO) // Use Trilinos if PETSc isn't there
     262             : TRILINOS_SOLVERS;
     263             : #elif defined(LIBMESH_HAVE_EIGEN)    // Use Eigen if neither are there
     264             : EIGEN_SOLVERS;
     265             : #elif defined(LIBMESH_HAVE_LASPACK)  // Use LASPACK as a last resort
     266             : LASPACK_SOLVERS;
     267             : #else                        // No valid linear solver package at compile time
     268             : INVALID_SOLVER_PACKAGE;
     269             : #endif
     270             : 
     271             : 
     272             : 
     273             : // ------------------------------------------------------------
     274             : // libMesh functions
     275             : 
     276       76122 : bool initialized()
     277             : {
     278       76122 :   return libMeshPrivateData::_is_initialized;
     279             : }
     280             : 
     281             : 
     282             : 
     283       26802 : bool closed()
     284             : {
     285       26802 :   return !libMeshPrivateData::_is_initialized;
     286             : }
     287             : 
     288             : 
     289             : #ifdef LIBMESH_ENABLE_EXCEPTIONS
     290             : std::terminate_handler old_terminate_handler;
     291             : #endif
     292             : 
     293           0 : void libmesh_terminate_handler()
     294             : {
     295             : #ifdef LIBMESH_ENABLE_EXCEPTIONS
     296             :   // If we have an active exception, it may have an error message that
     297             :   // we should print.
     298           0 :   libMesh::err << "libMesh terminating";
     299           0 :   std::exception_ptr ex = std::current_exception();
     300           0 :   if (ex)
     301             :     {
     302             :       try
     303             :         {
     304           0 :           std::rethrow_exception(ex);
     305             :         }
     306           0 :       catch (const std::exception & std_ex)
     307             :         {
     308           0 :           libMesh::err << ":\n" << std_ex.what();
     309           0 :         }
     310             :     }
     311           0 :   libMesh::err << std::endl;
     312             : #endif
     313             : 
     314             :   // If this got called then we're probably crashing; let's print a
     315             :   // stack trace.  The trace files that are ultimately written depend on:
     316             :   // 1.) Who throws the exception.
     317             :   // 2.) Whether the C++ runtime unwinds the stack before the
     318             :   //     terminate_handler is called (this is implementation defined).
     319             :   //
     320             :   // The various cases are summarized in the table below:
     321             :   //
     322             :   //                        | libmesh exception | other exception
     323             :   //                        -------------------------------------
     324             :   // stack unwinds          |        A          |       B
     325             :   // stack does not unwind  |        C          |       D
     326             :   //
     327             :   // Case A: There will be two stack traces in the file: one "useful"
     328             :   //         one, and one nearly empty one due to stack unwinding.
     329             :   // Case B: You will get one nearly empty stack trace (not great, Bob!)
     330             :   // Case C: You will get two nearly identical stack traces, ignore one of them.
     331             :   // Case D: You will get one useful stack trace.
     332             :   //
     333             :   // Cases A and B (where the stack unwinds when an exception leaves
     334             :   // main) appear to be non-existent in practice.  I don't have a
     335             :   // definitive list, but the stack does not unwind for GCC on either
     336             :   // Mac or Linux.  I think there's good reasons for this behavior too:
     337             :   // it's much easier to get a stack trace when the stack doesn't
     338             :   // unwind, for example.
     339           0 :   libMesh::write_traceout();
     340             : 
     341             :   // We may care about performance data pre-crash; it would be sad to
     342             :   // throw that away.
     343           0 :   libMesh::perflog.print_log();
     344           0 :   libMesh::perflog.clear();
     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           0 :   MPI_Initialized (&mpi_initialized);
     352             : 
     353           0 :   if (mpi_initialized)
     354           0 :     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.
     360           0 :   old_terminate_handler();
     361             : #endif
     362             : 
     363             :   // The last attempt to die if nothing else has killed us
     364           0 :   std::abort();
     365             : }
     366             : 
     367             : 
     368             : 
     369       16381 : LibMeshInit::LibMeshInit (int argc, const char * const * argv,
     370       16381 :                           TIMPI::communicator COMM_WORLD_IN, int n_threads)
     371             : {
     372             :   // should _not_ be initialized already.
     373         462 :   libmesh_assert (!libMesh::initialized());
     374             : 
     375             :   // Build a command-line parser.
     376       31838 :   command_line = std::make_unique<GetPot>(argc, argv);
     377             : 
     378             :   // Disable performance logging upon request
     379             :   {
     380       32300 :     if (libMesh::on_command_line ("--disable-perflog"))
     381           0 :       libMesh::perflog.disable_logging();
     382             :   }
     383             : 
     384       46831 :   auto check_empty_command_line_value = [](auto & cl, const std::string & option) {
     385       46831 :     libmesh_error_msg_if(cl.search(option),
     386             :                          "Detected option " << option << " with no value.  Did you forget '='?");
     387       46831 :   };
     388             : 
     389             :   // Build a task scheduler
     390             :   {
     391             :     // Get the requested number of threads, defaults to 1 to avoid MPI and
     392             :     // multithreading competition.  If you would like to use MPI and multithreading
     393             :     // at the same time then (n_mpi_processes_per_node)x(n_threads) should be the
     394             :     //  number of processing cores per node.
     395       16843 :     std::vector<std::string> n_threads_opt(2);
     396         924 :     n_threads_opt[0] = "--n_threads";
     397         924 :     n_threads_opt[1] = "--n-threads";
     398       16381 :     libMesh::libMeshPrivateData::_n_threads =
     399       16381 :       libMesh::command_line_value(n_threads_opt, n_threads);
     400             : 
     401       16381 :     if (libMesh::libMeshPrivateData::_n_threads == -1)
     402             :       {
     403       45675 :         for (auto & option : n_threads_opt)
     404       30450 :           check_empty_command_line_value(*command_line, option);
     405             : 
     406       15225 :         libMesh::libMeshPrivateData::_n_threads = 1;
     407             :       }
     408             : 
     409             :     // If there's no threading model active, force _n_threads==1
     410             : #if !LIBMESH_USING_THREADS
     411             :     if (libMesh::libMeshPrivateData::_n_threads != 1)
     412             :       {
     413             :         libMesh::libMeshPrivateData::_n_threads = 1;
     414             :         libmesh_warning("Warning: You requested --n-threads>1 but no threading model is active!\n"
     415             :                         << "Forcing --n-threads==1 instead!");
     416             :       }
     417             : #endif
     418             : 
     419             :     // Set the number of OpenMP threads to the same as the number of threads libMesh is going to use
     420             : #ifdef LIBMESH_HAVE_OPENMP
     421       16381 :     omp_set_num_threads(libMesh::libMeshPrivateData::_n_threads);
     422             : #endif
     423             : 
     424       15919 :     task_scheduler = std::make_unique<Threads::task_scheduler_init>(libMesh::n_threads());
     425       15457 :   }
     426             : 
     427             :   // Construct singletons who may be at risk of the
     428             :   // "static initialization order fiasco"
     429       16381 :   Singleton::setup();
     430             : 
     431             :   // Make sure the construction worked
     432         462 :   libmesh_assert(remote_elem);
     433             : 
     434       16381 :   const bool using_threads = libMesh::n_threads() > 1;
     435         462 :   const bool handle_mpi_errors = false; // libMesh does this
     436             : 
     437             : #if defined(LIBMESH_HAVE_MPI)
     438             : 
     439             :   // Allow the user to bypass MPI initialization
     440       32300 :   if (!libMesh::on_command_line ("--disable-mpi"))
     441             :     {
     442       16381 :       int mpi_thread_request = using_threads;
     443       33224 :       const auto mpi_thread_type = libMesh::command_line_value("--mpi-thread-type", std::string(""));
     444       16381 :       if (mpi_thread_type.empty())
     445             :         {
     446       32300 :           check_empty_command_line_value(*command_line, "--mpi-thread-type");
     447             : #if defined(PETSC_HAVE_STRUMPACK) && defined(PETSC_HAVE_SLATE)
     448             :           // For GPU computations, the solver strumpack uses slate which always requests
     449             :           // MPI_THREAD_MULTIPLE. The solution here is not perfect because the run may never be
     450             :           // using strumpack, but we believe it's better to force the MPI library to use locks
     451             :           // whenever it accesses the message queue, that is, when processing any sends and receive,
     452             :           // than it is to require users to pre-announce/signal what solvers they are using through
     453             :           // --mpi-thread-type
     454             :           mpi_thread_request = 3;
     455             : #endif
     456             :         }
     457             :       else
     458             :         {
     459           0 :           if (mpi_thread_type == "single")
     460             :             {
     461           0 :               if (using_threads)
     462           0 :                 libmesh_error_msg("We are using threads, so we require more mpi thread support "
     463             :                                   "than '--mpi-thread-type=single'");
     464           0 :               mpi_thread_request = 0;
     465             :             }
     466           0 :           else if (mpi_thread_type == "funneled")
     467           0 :             mpi_thread_request = 1;
     468           0 :           else if (mpi_thread_type == "serialized")
     469           0 :             mpi_thread_request = 2;
     470           0 :           else if (mpi_thread_type == "multiple")
     471           0 :             mpi_thread_request = 3;
     472             :           else
     473           0 :             libmesh_error_msg(
     474             :                 "Unsupported mpi thread type '"
     475             :                 << mpi_thread_type
     476             :                 << "'. Allowed options are 'single', 'funneled', 'serialized', and 'multiple'");
     477             :         }
     478             : 
     479       16381 :       this->_timpi_init =
     480             :         new TIMPI::TIMPIInit(argc, argv, mpi_thread_request,
     481       16381 :                              handle_mpi_errors, COMM_WORLD_IN);
     482       16381 :       _comm = new Parallel::Communicator(this->_timpi_init->comm().get());
     483             : 
     484             :       const std::string timpi_sync =
     485       33224 :         libMesh::command_line_value("--timpi-sync", std::string("nbx"));
     486       16381 :       _comm->sync_type(timpi_sync);
     487             : 
     488       16381 :       libMesh::GLOBAL_COMM_WORLD = COMM_WORLD_IN;
     489             : 
     490             :       //MPI_Comm_set_name not supported in at least SGI MPT's MPI implementation
     491             :       //MPI_Comm_set_name (libMesh::COMM_WORLD, "libMesh::COMM_WORLD");
     492             : 
     493       16381 :       libMeshPrivateData::_processor_id =
     494         924 :         cast_int<processor_id_type>(this->comm().rank());
     495       16381 :       libMeshPrivateData::_n_processors =
     496         924 :         cast_int<processor_id_type>(this->comm().size());
     497             : 
     498             :       // Set up an MPI error handler if requested.  This helps us get
     499             :       // into a debugger with a proper stack when an MPI error occurs.
     500       32300 :       if (libMesh::on_command_line ("--handle-mpi-errors"))
     501             :         {
     502           0 :           timpi_call_mpi
     503             :             (MPI_Comm_create_errhandler(libMesh_MPI_Handler, &libmesh_errhandler));
     504           0 :           timpi_call_mpi
     505             :             (MPI_Comm_set_errhandler(libMesh::GLOBAL_COMM_WORLD, libmesh_errhandler));
     506           0 :           timpi_call_mpi
     507             :             (MPI_Comm_set_errhandler(MPI_COMM_WORLD, libmesh_errhandler));
     508             :         }
     509             :     }
     510             : 
     511             :   // Could we have gotten bad values from the above calls?
     512         462 :   libmesh_assert_greater (libMeshPrivateData::_n_processors, 0);
     513             : 
     514             :   // The cast_int already tested _processor_id>=0
     515             :   // libmesh_assert_greater_equal (libMeshPrivateData::_processor_id, 0);
     516             : 
     517             :   // Let's be sure we properly initialize on every processor at once:
     518         462 :   libmesh_parallel_only(this->comm());
     519             : 
     520             : #else
     521             :   libmesh_ignore(COMM_WORLD_IN);
     522             :   this->_timpi_init =
     523             :     new TIMPI::TIMPIInit(argc, argv, using_threads,
     524             :                          handle_mpi_errors);
     525             :   _comm = new Parallel::Communicator(this->_timpi_init->comm().get());
     526             : #endif
     527             : 
     528             : #if defined(LIBMESH_HAVE_PETSC)
     529             : 
     530             :   // Allow the user to bypass PETSc initialization
     531       32340 :   if (!libMesh::on_command_line ("--disable-petsc")
     532             : 
     533             : #if defined(LIBMESH_HAVE_MPI)
     534             :       // If the user bypassed MPI, we'd better be safe and assume that
     535             :       // PETSc was built to require it; otherwise PETSc initialization
     536             :       // dies.
     537       32340 :       && !libMesh::on_command_line ("--disable-mpi")
     538             : #endif
     539             :       )
     540             :     {
     541             : #ifdef LIBMESH_HAVE_MPI
     542       16170 :       PETSC_COMM_WORLD = libMesh::GLOBAL_COMM_WORLD;
     543             : #else
     544             :       // PETSc --with-mpi=0 doesn't like our default "communicator" 0
     545             :       this->_comm->get() = PETSC_COMM_SELF;
     546             : #endif
     547             : 
     548             :       // Check whether the calling program has already initialized
     549             :       // PETSc, and avoid duplicate Initialize/Finalize
     550             :       PetscBool petsc_already_initialized;
     551       16170 :       LibmeshPetscCallA(libMesh::GLOBAL_COMM_WORLD, PetscInitialized(&petsc_already_initialized));
     552       16170 :       if (petsc_already_initialized != PETSC_TRUE)
     553       16170 :         libmesh_initialized_petsc = true;
     554             : # if defined(LIBMESH_HAVE_SLEPC)
     555             : 
     556             :       // If SLEPc allows us to check whether the calling program
     557             :       // has already initialized it, we do that, and avoid
     558             :       // duplicate Initialize/Finalize.
     559             :       // We assume that SLEPc will handle PETSc appropriately,
     560             :       // which it does in the versions we've checked.
     561       16170 :       if (!SlepcInitializeCalled)
     562             :         {
     563       16170 :           LibmeshPetscCallA(libMesh::GLOBAL_COMM_WORLD, SlepcInitialize  (&argc, const_cast<char ***>(&argv), nullptr, nullptr));
     564       16170 :           libmesh_initialized_slepc = true;
     565             :         }
     566             : # else
     567             :       if (libmesh_initialized_petsc)
     568             :         LibmeshPetscCallA(libMesh::GLOBAL_COMM_WORLD, PetscInitialize (&argc, const_cast<char ***>(&argv), nullptr, nullptr));
     569             : # endif
     570             :       // Register the reference implementation of DMlibMesh
     571       16170 :       LibmeshPetscCallA(libMesh::GLOBAL_COMM_WORLD, DMRegister(DMLIBMESH, DMCreate_libMesh));
     572             :     }
     573             : #endif
     574             : 
     575             : #ifdef LIBMESH_HAVE_NETGEN
     576       16381 :   nglib::Ng_Init();
     577             : #endif
     578             : 
     579             : #if defined(LIBMESH_HAVE_MPI) && defined(LIBMESH_HAVE_VTK)
     580             :   // Do MPI initialization for VTK.
     581             :   _vtk_mpi_controller = vtkMPIController::New();
     582             :   _vtk_mpi_controller->Initialize(&argc, const_cast<char ***>(&argv), /*initialized_externally=*/1);
     583             :   _vtk_mpi_controller->SetGlobalController(_vtk_mpi_controller);
     584             : #endif
     585             : 
     586             :   // Re-parse the command-line arguments.  Note that PETSc and MPI
     587             :   // initialization above may have removed command line arguments
     588             :   // that are not relevant to this application in the above calls.
     589             :   // We don't want a false-positive by detecting those arguments.
     590             :   //
     591             :   // Note: this seems overly paranoid/like it should be unnecessary,
     592             :   // plus we were doing it wrong for many years and not clearing the
     593             :   // existing GetPot object before re-parsing the command line, so all
     594             :   // the command line arguments appeared twice in the GetPot object...
     595       31838 :   command_line = std::make_unique<GetPot>(argc, argv);
     596             : 
     597             :   // The following line is an optimization when simultaneous
     598             :   // C and C++ style access to output streams is not required.
     599             :   // The amount of benefit which occurs is probably implementation
     600             :   // defined, and may be nothing.  On the other hand, I have seen
     601             :   // some IO tests where IO performance improves by a factor of two.
     602       32300 :   if (!libMesh::on_command_line ("--sync-with-stdio"))
     603       16381 :     std::ios::sync_with_stdio(false);
     604             : 
     605             :   // Honor the --separate-libmeshout command-line option.
     606             :   // When this is specified, the library uses an independent ostream
     607             :   // for libMesh::out/libMesh::err messages, and
     608             :   // std::cout and std::cerr are untouched by any other options
     609       32300 :   if (libMesh::on_command_line ("--separate-libmeshout"))
     610             :     {
     611             :       // Redirect.  We'll share streambufs with cout/cerr for now, but
     612             :       // presumably anyone using this option will want to replace the
     613             :       // bufs later.
     614           0 :       std::ostream * newout = new std::ostream(std::cout.rdbuf());
     615           0 :       libMesh::out = *newout;
     616           0 :       std::ostream * newerr = new std::ostream(std::cerr.rdbuf());
     617           0 :       libMesh::err = *newerr;
     618             :     }
     619             : 
     620             :   // Process command line arguments for redirecting stdout/stderr.
     621             :   bool
     622       16381 :     cmdline_has_redirect_stdout = libMesh::on_command_line ("--redirect-stdout"),
     623       16381 :     cmdline_has_redirect_output = libMesh::on_command_line ("--redirect-output");
     624             : 
     625             :   // The --redirect-stdout command-line option has been deprecated in
     626             :   // favor of "--redirect-output basename".
     627             :   if (cmdline_has_redirect_stdout)
     628             :     libmesh_warning("The --redirect-stdout command line option has been deprecated. "
     629             :                     "Use '--redirect-output basename' instead.");
     630             : 
     631             :   // Honor the "--redirect-stdout" and "--redirect-output basename"
     632             :   // command-line options.  When one of these is specified, each
     633             :   // processor sends libMesh::out/libMesh::err messages to
     634             :   // stdout.processor.#### (default) or basename.processor.####.
     635       16381 :   if (cmdline_has_redirect_stdout || cmdline_has_redirect_output)
     636             :     {
     637           0 :       std::string basename = "stdout";
     638             : 
     639             :       // Look for following argument if using new API
     640           0 :       if (cmdline_has_redirect_output)
     641             :         {
     642             :           // Set the cursor to the correct location in the list of command line arguments.
     643           0 :           command_line->search(1, "--redirect-output");
     644             : 
     645             :           // Get the next option on the command line as a string.
     646           0 :           std::string next_string = "";
     647           0 :           next_string = command_line->next(next_string);
     648             : 
     649             :           // If the next string starts with a dash, we assume it's
     650             :           // another flag and not a file basename requested by the
     651             :           // user.
     652           0 :           if (next_string.size() > 0 && next_string.find_first_of("-") != 0)
     653           0 :             basename = next_string;
     654             :         }
     655             : 
     656           0 :       std::ostringstream filename;
     657           0 :       filename << basename << ".processor." << libMesh::global_processor_id();
     658           0 :       _ofstream = std::make_unique<std::ofstream>(filename.str().c_str());
     659             : 
     660             :       // Redirect, saving the original streambufs!
     661           0 :       out_buf = libMesh::out.rdbuf (_ofstream->rdbuf());
     662           0 :       err_buf = libMesh::err.rdbuf (_ofstream->rdbuf());
     663           0 :     }
     664             : 
     665             :   // redirect libMesh::out to nothing on all
     666             :   // other processors unless explicitly told
     667             :   // not to via the --keep-cout command-line argument.
     668       32300 :   if (!libMesh::on_command_line ("--keep-cout"))
     669       16381 :     if (libMesh::global_processor_id() != 0)
     670       13629 :       libMesh::out.rdbuf (nullptr);
     671             : 
     672             :   // Similarly, the user can request to drop cerr on all non-0 ranks.
     673             :   // By default, errors are printed on all ranks, but this can lead to
     674             :   // interleaved/unpredictable outputs when doing parallel regression
     675             :   // testing, which this option is designed to support.
     676       32300 :   if (libMesh::on_command_line ("--drop-cerr"))
     677           0 :     if (libMesh::global_processor_id() != 0)
     678           0 :       libMesh::err.rdbuf (nullptr);
     679             : 
     680             :   // Check command line to override printing
     681             :   // of reference count information.
     682       32300 :   if (libMesh::on_command_line("--disable-refcount-printing"))
     683           0 :     ReferenceCounter::disable_print_counter_info();
     684             : 
     685             : #ifdef LIBMESH_ENABLE_EXCEPTIONS
     686             :   // Set our terminate handler to write stack traces in the event of a
     687             :   // crash
     688       16381 :   old_terminate_handler = std::set_terminate(libmesh_terminate_handler);
     689             : #endif
     690             : 
     691             : 
     692       32300 :   if (libMesh::on_command_line("--enable-fpe"))
     693           0 :     libMesh::enableFPE(true);
     694             : 
     695       32300 :   if (libMesh::on_command_line("--enable-segv"))
     696           0 :     libMesh::enableSEGV(true);
     697             : 
     698             : #if defined(LIBMESH_HAVE_HDF5) && !defined(_MSC_VER)
     699             :   // We may be running with ExodusII configured not to use HDF5 (in
     700             :   // which case user code which wants to lock files has to do flock()
     701             :   // itself) or with ExodusII configured to use HDF5 (which will
     702             :   // helpfully try to get an exclusive flock() itself, and then scream
     703             :   // and die if user code has already locked the file.  To get
     704             :   // consistent behavior, we need to disable file locking.  The only
     705             :   // reliable way I can see to do this is via an HDF5 environment
     706             :   // variable.
     707             :   //
     708             :   // If the user set this environment variable then we'll trust that
     709             :   // they know what they're doing.  If not then we'll set FALSE,
     710             :   // because that's a better default for us than the unset default.
     711         462 :   setenv("HDF5_USE_FILE_LOCKING", "FALSE", /*overwrite=false*/0);
     712             : #endif // LIBMESH_HAVE_HDF5
     713             : 
     714             :   // The library is now ready for use
     715       16381 :   libMeshPrivateData::_is_initialized = true;
     716             : 
     717             : 
     718             :   // Make sure these work.  Library methods
     719             :   // depend on these being implemented properly,
     720             :   // so this is a good time to test them!
     721         462 :   libmesh_assert (libMesh::initialized());
     722         462 :   libmesh_assert (!libMesh::closed());
     723       16381 : }
     724             : 
     725             : 
     726             : 
     727       17305 : LibMeshInit::~LibMeshInit()
     728             : {
     729             :   // Every processor had better be ready to exit at the same time.
     730             :   // This would be a libmesh_parallel_only() function, except that
     731             :   // libmesh_parallel_only() uses libmesh_assert() which throws an
     732             :   // exception() which causes compilers to scream about exceptions
     733             :   // inside destructors.
     734             : 
     735             :   // Even if we're not doing parallel_only debugging, we don't want
     736             :   // one processor to try to exit until all others are done working.
     737       16381 :   this->comm().barrier();
     738             : 
     739             :   // We can't delete, finalize, etc. more than once without
     740             :   // reinitializing in between
     741         462 :   libmesh_exceptionless_assert(!libMesh::closed());
     742             : 
     743             :   // Delete reference counted singleton(s)
     744       16381 :   Singleton::cleanup();
     745             : 
     746             :   // Clear the thread task manager we started
     747         462 :   task_scheduler.reset();
     748             : 
     749             :   // Force the \p ReferenceCounter to print
     750             :   // its reference count information.  This allows
     751             :   // us to find memory leaks.  By default the
     752             :   // \p ReferenceCounter only prints its information
     753             :   // when the last created object has been destroyed.
     754             :   // That does no good if we are leaking memory!
     755       16381 :   ReferenceCounter::print_info ();
     756             : 
     757             : 
     758             :   // Print an informative message if we detect a memory leak
     759       16381 :   if (ReferenceCounter::n_objects() != 0)
     760             :     {
     761           0 :       libMesh::err << "Memory leak detected!"
     762           0 :                    << std::endl;
     763             : 
     764             : #if !defined(LIBMESH_ENABLE_REFERENCE_COUNTING) || defined(NDEBUG)
     765             : 
     766             :       libMesh::err << "Compile in DEBUG mode with --enable-reference-counting"
     767             :                    << std::endl
     768             :                    << "for more information"
     769             :                    << std::endl;
     770             : #endif
     771             : 
     772             :     }
     773             : 
     774             :   //  print the perflog to individual processor's file.
     775       16381 :   libMesh::perflog.print_log();
     776             : 
     777             :   // Now clear the logging object, we don't want it to print
     778             :   // a second time during the PerfLog destructor.
     779       16381 :   libMesh::perflog.clear();
     780             : 
     781             :   // Reconnect the output streams
     782             :   // (don't do this, or we will get messages from objects
     783             :   //  that go out of scope after the following return)
     784             :   //std::cout.rdbuf(std::cerr.rdbuf());
     785             : 
     786             : 
     787             :   // Set the initialized() flag to false
     788       16381 :   libMeshPrivateData::_is_initialized = false;
     789             : 
     790       33686 :   if (libMesh::on_command_line ("--redirect-stdout") ||
     791       33224 :       libMesh::on_command_line ("--redirect-output"))
     792             :     {
     793             :       // If stdout/stderr were redirected to files, reset them now.
     794           0 :       libMesh::out.rdbuf (out_buf);
     795           0 :       libMesh::err.rdbuf (err_buf);
     796             :     }
     797             : 
     798             :   // If we built our own output streams, we want to clean them up.
     799       32300 :   if (libMesh::on_command_line ("--separate-libmeshout"))
     800             :     {
     801           0 :       delete libMesh::out.get();
     802           0 :       delete libMesh::err.get();
     803             : 
     804           0 :       libMesh::out.reset(std::cout);
     805           0 :       libMesh::err.reset(std::cerr);
     806             :     }
     807             : 
     808             : #ifdef LIBMESH_ENABLE_EXCEPTIONS
     809             :   // Reset the old terminate handler; maybe the user code wants to
     810             :   // keep doing C++ stuff after closing libMesh stuff.
     811       16381 :   std::set_terminate(old_terminate_handler);
     812             : #endif
     813             : 
     814             : #ifdef LIBMESH_HAVE_NETGEN
     815       16381 :   nglib::Ng_Exit();
     816             : #endif
     817             : 
     818       32300 :   if (libMesh::on_command_line("--enable-fpe"))
     819           0 :     libMesh::enableFPE(false);
     820             : 
     821             : #if defined(LIBMESH_HAVE_PETSC)
     822             :   // Let PETSc know about all the command line objects that we
     823             :   // consumed without asking them, so we don't get unused option
     824             :   // warnings about those.
     825       17094 :   std::vector<std::string> cli_names = command_line_names();
     826      505204 :   for (const auto & name : cli_names)
     827      489034 :     if (!name.empty() && name[0] == '-')
     828             :       {
     829             :         // Newer PETSc can give me a double-free I'm having trouble
     830             :         // replicating; let's protect against trying to clear
     831             :         // already-used values
     832      476434 :         PetscBool used = PETSC_FALSE;
     833      476434 :         auto ierr = PetscOptionsUsed(NULL, name.c_str(), &used);
     834      476434 :         CHKERRABORT(libMesh::GLOBAL_COMM_WORLD, ierr);
     835      476434 :         if (used == PETSC_FALSE)
     836             :           {
     837      476434 :             ierr = PetscOptionsClearValue(NULL, name.c_str());
     838      476434 :             CHKERRABORT(libMesh::GLOBAL_COMM_WORLD, ierr);
     839             :           }
     840             :       }
     841             : 
     842             :   // Allow the user to bypass PETSc finalization
     843       32340 :   if (!libMesh::on_command_line ("--disable-petsc")
     844             : #if defined(LIBMESH_HAVE_MPI)
     845       32340 :       && !libMesh::on_command_line ("--disable-mpi")
     846             : #endif
     847             :       )
     848             :     {
     849         462 :       PetscErrorCode ierr = LIBMESH_PETSC_SUCCESS;
     850             : # if defined(LIBMESH_HAVE_SLEPC)
     851       16170 :       if (libmesh_initialized_slepc)
     852       16170 :         ierr = SlepcFinalize();
     853             : # else
     854             :       if (libmesh_initialized_petsc)
     855             :         ierr = PetscFinalize();
     856             : # endif
     857       16170 :       CHKERRABORT(libMesh::GLOBAL_COMM_WORLD, ierr);
     858             :     }
     859             : #endif
     860             : 
     861             : #if defined(LIBMESH_HAVE_MPI) && defined(LIBMESH_HAVE_VTK)
     862             :   _vtk_mpi_controller->Finalize(/*finalized_externally=*/1);
     863             :   _vtk_mpi_controller->Delete();
     864             : #endif
     865             : 
     866       32300 :   delete this->_comm;
     867             : 
     868             : #if defined(LIBMESH_HAVE_MPI)
     869             :   // Allow the user to bypass MPI finalization
     870       32300 :   if (!libMesh::on_command_line ("--disable-mpi"))
     871             :     {
     872       16381 :       delete this->_timpi_init;
     873             :     }
     874             : #else
     875             :   delete this->_timpi_init;
     876             : #endif
     877       16381 : }
     878             : 
     879             : 
     880             : 
     881             : /**
     882             :  * Toggle floating point exceptions -- courtesy of Cody Permann & MOOSE team
     883             :  */
     884           0 : void enableFPE(bool on)
     885             : {
     886             : #if !defined(LIBMESH_HAVE_FEENABLEEXCEPT) && defined(LIBMESH_HAVE_XMMINTRIN_H)
     887             :   static int flags = 0;
     888             : #endif
     889             : 
     890           0 :   if (on)
     891             :     {
     892             : #ifdef LIBMESH_HAVE_FEENABLEEXCEPT
     893           0 :       feenableexcept(FE_DIVBYZERO | FE_INVALID);
     894             : #elif  LIBMESH_HAVE_XMMINTRIN_H
     895             :       flags = _MM_GET_EXCEPTION_MASK();           // store the flags
     896             :       _MM_SET_EXCEPTION_MASK(flags & ~_MM_MASK_INVALID);
     897             : #endif
     898             : 
     899             : #if LIBMESH_HAVE_DECL_SIGACTION
     900             :       struct sigaction new_action, old_action;
     901             : 
     902             :       // Set up the structure to specify the new action.
     903           0 :       new_action.sa_sigaction = libmesh_handleFPE;
     904           0 :       sigemptyset (&new_action.sa_mask);
     905           0 :       new_action.sa_flags = SA_SIGINFO;
     906             : 
     907           0 :       sigaction (SIGFPE, nullptr, &old_action);
     908           0 :       if (old_action.sa_handler != SIG_IGN)
     909           0 :         sigaction (SIGFPE, &new_action, nullptr);
     910             : #endif
     911             :     }
     912             :   else
     913             :     {
     914             : #ifdef LIBMESH_HAVE_FEDISABLEEXCEPT
     915           0 :       fedisableexcept(FE_DIVBYZERO | FE_INVALID);
     916             : #elif  LIBMESH_HAVE_XMMINTRIN_H
     917             :       _MM_SET_EXCEPTION_MASK(flags);
     918             : #endif
     919           0 :       signal(SIGFPE, SIG_DFL);
     920             :     }
     921           0 : }
     922             : 
     923             : 
     924             : // Enable handling of SIGSEGV by libMesh
     925             : // (potentially instead of PETSc)
     926           0 : void enableSEGV(bool on)
     927             : {
     928             : #if LIBMESH_HAVE_DECL_SIGACTION
     929             :   static struct sigaction old_action;
     930             :   static bool was_on = false;
     931             : 
     932           0 :   if (on)
     933             :     {
     934             :       struct sigaction new_action;
     935           0 :       was_on = true;
     936             : 
     937             :       // Set up the structure to specify the new action.
     938           0 :       new_action.sa_sigaction = libmesh_handleSEGV;
     939           0 :       sigemptyset (&new_action.sa_mask);
     940           0 :       new_action.sa_flags = SA_SIGINFO;
     941             : 
     942           0 :       sigaction (SIGSEGV, &new_action, &old_action);
     943             :     }
     944           0 :   else if (was_on)
     945             :     {
     946           0 :       was_on = false;
     947           0 :       sigaction (SIGSEGV, &old_action, nullptr);
     948             :     }
     949             : #else
     950             :   libmesh_error_msg("System call sigaction not supported.");
     951             : #endif
     952           0 : }
     953             : 
     954             : 
     955             : 
     956     4350476 : void add_command_line_name(const std::string & name)
     957             : {
     958             :   // Users had better not be asking about an empty string
     959      115082 :   libmesh_assert(!name.empty());
     960             : 
     961             :   static std::mutex command_line_names_mutex;
     962      230164 :   std::scoped_lock lock(command_line_names_mutex);
     963             : 
     964     4235402 :   command_line_name_set.insert(name);
     965     4350476 : }
     966             : 
     967             : 
     968             : 
     969          71 : void add_command_line_names(const GetPot & getpot)
     970             : {
     971         213 :   for (auto & getter : {&GetPot::get_requested_arguments,
     972             :                         &GetPot::get_requested_variables,
     973         284 :                         &GetPot::get_requested_sections})
     974       10591 :     for (const std::string & name : (getpot.*getter)())
     975       10372 :       add_command_line_name(name);
     976          71 : }
     977             : 
     978             : 
     979       16170 : std::vector<std::string> command_line_names()
     980             : {
     981             :   return std::vector<std::string>(command_line_name_set.begin(),
     982       16170 :                                   command_line_name_set.end());
     983             : }
     984             : 
     985             : 
     986             : 
     987     4289269 : bool on_command_line (std::string arg)
     988             : {
     989             :   // Make sure the command line parser is ready for use.  If it's not,
     990             :   // then we'll have to treat the command line as empty, for maximum
     991             :   // compatibility with programs that don't use LibMeshInit but
     992             :   // indirectly (e.g. via error handling code) query the command line.
     993     4289269 :   if (!command_line.get())
     994           0 :     return false;
     995             : 
     996             :   // Keep track of runtime queries, for later
     997     4289269 :   add_command_line_name(arg);
     998             : 
     999      113152 :   bool found_it = command_line->search(arg);
    1000             : 
    1001     4289269 :   if (!found_it)
    1002             :     {
    1003             :       // Try with all dashes instead of underscores
    1004      112720 :       std::replace(arg.begin(), arg.end(), '_', '-');
    1005      112720 :       found_it = command_line->search(arg);
    1006             :     }
    1007             : 
    1008     4278809 :   if (!found_it)
    1009             :     {
    1010             :       // OK, try with all underscores instead of dashes
    1011      112718 :       auto name_begin = arg.begin();
    1012    12826010 :       while (*name_begin == '-')
    1013      225124 :         ++name_begin;
    1014      112718 :       std::replace(name_begin, arg.end(), '-', '_');
    1015      112718 :       found_it = command_line->search(arg);
    1016             :     }
    1017             : 
    1018      113152 :   return found_it;
    1019             : }
    1020             : 
    1021             : 
    1022             : 
    1023             : template <typename T>
    1024      339739 : T command_line_value (const std::string & name, T value)
    1025             : {
    1026             :   // Make sure the command line parser is ready for use
    1027        9880 :   libmesh_assert(command_line.get());
    1028             : 
    1029             :   // only if the variable exists in the file
    1030        9880 :   if (command_line->have_variable(name))
    1031             :     {
    1032        2652 :       value = (*command_line)(name, value);
    1033             : 
    1034             :       // Keep track of runtime queries, for later.  GetPot splits
    1035             :       // foo=bar into a separate name=value, so we can query for the
    1036             :       // name, but as far as PETSc is concerned that's one CLI
    1037             :       // argument.  We'll store it that way.
    1038         124 :       const std::string stringvalue =
    1039        2111 :         (*command_line)(name, std::string());
    1040        4284 :       add_command_line_name(name+"="+stringvalue);
    1041             :     }
    1042             : 
    1043      339739 :   return value;
    1044             : }
    1045             : 
    1046             : template <typename T>
    1047       16381 : T command_line_value (const std::vector<std::string> & names, T value)
    1048             : {
    1049             :   // Make sure the command line parser is ready for use
    1050         462 :   libmesh_assert(command_line.get());
    1051             : 
    1052             :   // Keep track of runtime queries, for later
    1053       49143 :   for (const auto & entry : names)
    1054             :     {
    1055             :       // Keep track of runtime queries, for later.  GetPot splits
    1056             :       // foo=bar into a separate name=value, so we can query for the
    1057             :       // name, but as far as PETSc is concerned that's one CLI
    1058             :       // argument.  We'll store it that way.
    1059        1848 :       const std::string stringvalue =
    1060       31838 :         (*command_line)(entry, std::string());
    1061       64600 :       add_command_line_name(entry+"="+stringvalue);
    1062             :     }
    1063             : 
    1064             :   // Check for multiple options (return the first that matches)
    1065       46831 :   for (const auto & entry : names)
    1066         582 :     if (command_line->have_variable(entry))
    1067             :       {
    1068        1156 :         value = (*command_line)(entry, value);
    1069        1156 :         break;
    1070             :       }
    1071             : 
    1072       16381 :   return value;
    1073             : }
    1074             : 
    1075             : 
    1076             : 
    1077             : template <typename T>
    1078       15620 : T command_line_next (std::string name, T value)
    1079             : {
    1080             :   // Make sure the command line parser is ready for use
    1081         642 :   libmesh_assert(command_line.get());
    1082             : 
    1083             :   // Keep track of runtime queries, for later
    1084       15620 :   add_command_line_name(name);
    1085             : 
    1086             :   // on_command_line also puts the command_line cursor in the spot we
    1087             :   // need
    1088       30598 :   if (on_command_line(name))
    1089        8790 :     return command_line->next(value);
    1090             : 
    1091        6720 :   return value;
    1092             : }
    1093             : 
    1094             : 
    1095             : 
    1096             : template <typename T>
    1097         280 : void command_line_vector (const std::string & name, std::vector<T> & vec)
    1098             : {
    1099             :   // Make sure the command line parser is ready for use
    1100           8 :   libmesh_assert(command_line.get());
    1101             : 
    1102             :   // Keep track of runtime queries, for later
    1103         280 :   add_command_line_name(name);
    1104             : 
    1105             :   // only if the variable exists on the command line
    1106           8 :   if (command_line->have_variable(name))
    1107             :     {
    1108           8 :       unsigned size = command_line->vector_variable_size(name);
    1109         280 :       vec.resize(size);
    1110             : 
    1111         560 :       for (unsigned i=0; i<size; ++i)
    1112         280 :         vec[i] = (*command_line)(name, vec[i], i);
    1113             :     }
    1114         280 : }
    1115             : 
    1116             : 
    1117     1934237 : SolverPackage default_solver_package ()
    1118             : {
    1119       56824 :   libmesh_assert (libMesh::initialized());
    1120             : 
    1121             :   static bool called = false;
    1122             : 
    1123             :   // Check the command line.  Since the command line is
    1124             :   // unchanging it is sufficient to do this only once.
    1125     1934237 :   if (!called)
    1126             :     {
    1127       14902 :       called = true;
    1128             : 
    1129             : #ifdef LIBMESH_HAVE_PETSC
    1130       28988 :       if (libMesh::on_command_line ("--use-petsc"))
    1131           0 :         libMeshPrivateData::_solver_package = PETSC_SOLVERS;
    1132             : #endif
    1133             : 
    1134             : #ifdef LIBMESH_TRILINOS_HAVE_AZTECOO
    1135             :       if (libMesh::on_command_line ("--use-trilinos") ||
    1136             :           libMesh::on_command_line ("--disable-petsc"))
    1137             :         libMeshPrivateData::_solver_package = TRILINOS_SOLVERS;
    1138             : #endif
    1139             : 
    1140             : #ifdef LIBMESH_HAVE_EIGEN
    1141       44284 :       if (libMesh::on_command_line ("--use-eigen"  ) ||
    1142             : #if defined(LIBMESH_HAVE_MPI)
    1143             :           // If the user bypassed MPI, we disable PETSc and Trilinos
    1144             :           // too
    1145       31070 :           libMesh::on_command_line ("--disable-mpi") ||
    1146             : #endif
    1147       30226 :           libMesh::on_command_line ("--disable-petsc"))
    1148           0 :         libMeshPrivateData::_solver_package = EIGEN_SOLVERS;
    1149             : #endif
    1150             : 
    1151             : #ifdef LIBMESH_HAVE_LASPACK
    1152        2110 :       if (libMesh::on_command_line ("--use-laspack"  ) ||
    1153             : #if defined(LIBMESH_HAVE_MPI)
    1154             :           // If the user bypassed MPI, we disable PETSc and Trilinos
    1155             :           // too
    1156        2954 :           libMesh::on_command_line ("--disable-mpi") ||
    1157             : #endif
    1158        2110 :           libMesh::on_command_line ("--disable-petsc"))
    1159           0 :         libMeshPrivateData::_solver_package = LASPACK_SOLVERS;
    1160             : #endif
    1161             : 
    1162       29804 :       if (libMesh::on_command_line ("--disable-laspack") &&
    1163       14902 :           libMesh::on_command_line ("--disable-trilinos") &&
    1164       30226 :           libMesh::on_command_line ("--disable-eigen") &&
    1165             :           (
    1166             : #if defined(LIBMESH_HAVE_MPI)
    1167             :            // If the user bypassed MPI, we disable PETSc too
    1168       14902 :            libMesh::on_command_line ("--disable-mpi") ||
    1169             : #endif
    1170       14902 :            libMesh::on_command_line ("--disable-petsc")))
    1171           0 :         libMeshPrivateData::_solver_package = INVALID_SOLVER_PACKAGE;
    1172             :     }
    1173             : 
    1174             : 
    1175     1934237 :   return libMeshPrivateData::_solver_package;
    1176             : }
    1177             : 
    1178             : 
    1179             : 
    1180             : //-------------------------------------------------------------------------------
    1181             : template LIBMESH_EXPORT unsigned char  command_line_value<unsigned char>  (const std::string &, unsigned char);
    1182             : template LIBMESH_EXPORT unsigned short command_line_value<unsigned short> (const std::string &, unsigned short);
    1183             : template LIBMESH_EXPORT unsigned int   command_line_value<unsigned int>   (const std::string &, unsigned int);
    1184             : template LIBMESH_EXPORT char           command_line_value<char>           (const std::string &, char);
    1185             : template LIBMESH_EXPORT short          command_line_value<short>          (const std::string &, short);
    1186             : template LIBMESH_EXPORT int            command_line_value<int>            (const std::string &, int);
    1187             : template LIBMESH_EXPORT float          command_line_value<float>          (const std::string &, float);
    1188             : template LIBMESH_EXPORT double         command_line_value<double>         (const std::string &, double);
    1189             : template LIBMESH_EXPORT long double    command_line_value<long double>    (const std::string &, long double);
    1190             : template LIBMESH_EXPORT std::string    command_line_value<std::string>    (const std::string &, std::string);
    1191             : 
    1192             : template LIBMESH_EXPORT unsigned char  command_line_value<unsigned char>  (const std::vector<std::string> &, unsigned char);
    1193             : template LIBMESH_EXPORT unsigned short command_line_value<unsigned short> (const std::vector<std::string> &, unsigned short);
    1194             : template LIBMESH_EXPORT unsigned int   command_line_value<unsigned int>   (const std::vector<std::string> &, unsigned int);
    1195             : template LIBMESH_EXPORT char           command_line_value<char>           (const std::vector<std::string> &, char);
    1196             : template LIBMESH_EXPORT short          command_line_value<short>          (const std::vector<std::string> &, short);
    1197             : template LIBMESH_EXPORT int            command_line_value<int>            (const std::vector<std::string> &, int);
    1198             : template LIBMESH_EXPORT float          command_line_value<float>          (const std::vector<std::string> &, float);
    1199             : template LIBMESH_EXPORT double         command_line_value<double>         (const std::vector<std::string> &, double);
    1200             : template LIBMESH_EXPORT long double    command_line_value<long double>    (const std::vector<std::string> &, long double);
    1201             : template LIBMESH_EXPORT std::string    command_line_value<std::string>    (const std::vector<std::string> &, std::string);
    1202             : 
    1203             : template LIBMESH_EXPORT unsigned char  command_line_next<unsigned char>   (std::string, unsigned char);
    1204             : template LIBMESH_EXPORT unsigned short command_line_next<unsigned short>  (std::string, unsigned short);
    1205             : template LIBMESH_EXPORT unsigned int   command_line_next<unsigned int>    (std::string, unsigned int);
    1206             : template LIBMESH_EXPORT char           command_line_next<char>            (std::string, char);
    1207             : template LIBMESH_EXPORT short          command_line_next<short>           (std::string, short);
    1208             : template LIBMESH_EXPORT int            command_line_next<int>             (std::string, int);
    1209             : template LIBMESH_EXPORT float          command_line_next<float>           (std::string, float);
    1210             : template LIBMESH_EXPORT double         command_line_next<double>          (std::string, double);
    1211             : template LIBMESH_EXPORT long double    command_line_next<long double>     (std::string, long double);
    1212             : template LIBMESH_EXPORT std::string    command_line_next<std::string>     (std::string, std::string);
    1213             : 
    1214             : template LIBMESH_EXPORT void           command_line_vector<unsigned char> (const std::string &, std::vector<unsigned char> &);
    1215             : template LIBMESH_EXPORT void           command_line_vector<unsigned short>(const std::string &, std::vector<unsigned short> &);
    1216             : template LIBMESH_EXPORT void           command_line_vector<unsigned int>  (const std::string &, std::vector<unsigned int> &);
    1217             : template LIBMESH_EXPORT void           command_line_vector<char>          (const std::string &, std::vector<char> &);
    1218             : template LIBMESH_EXPORT void           command_line_vector<short>         (const std::string &, std::vector<short> &);
    1219             : template LIBMESH_EXPORT void           command_line_vector<int>           (const std::string &, std::vector<int> &);
    1220             : template LIBMESH_EXPORT void           command_line_vector<float>         (const std::string &, std::vector<float> &);
    1221             : template LIBMESH_EXPORT void           command_line_vector<double>        (const std::string &, std::vector<double> &);
    1222             : template LIBMESH_EXPORT void           command_line_vector<long double>   (const std::string &, std::vector<long double> &);
    1223             : 
    1224             : #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
    1225             : template LIBMESH_EXPORT Real           command_line_value<Real>           (const std::string &, Real);
    1226             : template LIBMESH_EXPORT Real           command_line_value<Real>           (const std::vector<std::string> &, Real);
    1227             : template LIBMESH_EXPORT Real           command_line_next<Real>            (std::string, Real);
    1228             : template LIBMESH_EXPORT void           command_line_vector<Real>          (const std::string &, std::vector<Real> &);
    1229             : #endif
    1230             : 
    1231             : } // namespace libMesh

Generated by: LCOV version 1.14