LCOV - code coverage report
Current view: top level - src/base - libmesh.C (source / functions) Hit Total Coverage
Test: libMesh/libmesh: #4475 (55045b) with base a68cc6 Lines: 227 294 77.2 %
Date: 2026-06-03 14:29:06 Functions: 24 58 41.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // The libMesh Finite Element Library.
       2             : // Copyright (C) 2002-2026 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             : #include "libmesh/thread_buffered_syncbuf.h"
      33             : 
      34             : // TIMPI includes
      35             : #include "timpi/communicator.h"
      36             : #include "timpi/timpi_init.h"
      37             : 
      38             : // C/C++ includes
      39             : #include <cstdlib>
      40             : #include <iostream>
      41             : #include <fstream>
      42             : 
      43             : #ifdef LIBMESH_ENABLE_EXCEPTIONS
      44             : #include <exception>
      45             : #include <optional>
      46             : #endif
      47             : 
      48             : #ifdef LIBMESH_HAVE_OPENMP
      49             : #include <omp.h>
      50             : #endif
      51             : 
      52             : #include "stdlib.h" // C, not C++ - we need setenv() from POSIX
      53             : 
      54             : 
      55             : #if defined(LIBMESH_HAVE_MPI)
      56             : # include "libmesh/ignore_warnings.h"
      57             : # include <mpi.h>
      58             : # include "libmesh/restore_warnings.h"
      59             : #endif // #if defined(LIBMESH_HAVE_MPI)
      60             : 
      61             : #if defined(LIBMESH_HAVE_PETSC)
      62             : # include "libmesh/petsc_solver_exception.h"
      63             : # include <petsc.h>
      64             : # include <petscerror.h>
      65             : # include "libmesh/petscdmlibmesh.h"
      66             : # if defined(LIBMESH_HAVE_SLEPC)
      67             : // Ignore unused variable warnings from SLEPc
      68             : #  include "libmesh/ignore_warnings.h"
      69             : #  include "libmesh/slepc_macro.h"
      70             : #  include <slepc.h>
      71             : #  include "libmesh/restore_warnings.h"
      72             : # endif // #if defined(LIBMESH_HAVE_SLEPC)
      73             : #endif // #if defined(LIBMESH_HAVE_PETSC)
      74             : 
      75             : #ifdef LIBMESH_HAVE_NETGEN
      76             : // We need the nglib namespace, because it's used everywhere in nglib
      77             : // and we don't get binary compatibility without it.
      78             : //
      79             : // We need the nglib namespace *here*, because somehow nobody ever
      80             : // figured out to just put it in nglib.h?
      81             : namespace nglib {
      82             : #include "netgen/nglib/nglib.h"
      83             : }
      84             : #endif
      85             : 
      86             : // If we're using MPI and VTK has been detected, we need to do some
      87             : // MPI initialize/finalize stuff for VTK.
      88             : #if defined(LIBMESH_HAVE_MPI) && defined(LIBMESH_HAVE_VTK)
      89             : #include "libmesh/ignore_warnings.h"
      90             : # include "vtkMPIController.h"
      91             : #include "libmesh/restore_warnings.h"
      92             : #endif
      93             : 
      94             : #ifdef PETSC_HAVE_UMPIRE
      95             : #include "umpire/util/io.hpp"
      96             : #endif
      97             : 
      98             : #include <mutex>
      99             : 
     100             : // --------------------------------------------------------
     101             : // Local anonymous namespace to hold miscellaneous bits
     102             : namespace {
     103             : 
     104             : std::unique_ptr<GetPot> command_line;
     105             : 
     106             : std::set<std::string> command_line_name_set;
     107             : 
     108             : std::unique_ptr<std::ofstream> _ofstream;
     109             : // If std::cout and std::cerr are redirected, we need to
     110             : // be a little careful and save the original streambuf objects,
     111             : // replacing them in the destructor before program termination.
     112             : std::streambuf * out_buf (nullptr);
     113             : std::streambuf * err_buf (nullptr);
     114             : 
     115             : std::unique_ptr<libMesh::Threads::task_scheduler_init> task_scheduler;
     116             : #if defined(LIBMESH_HAVE_PETSC)
     117             : bool libmesh_initialized_petsc = false;
     118             : #endif
     119             : #if defined(LIBMESH_HAVE_SLEPC)
     120             : bool libmesh_initialized_slepc = false;
     121             : #endif
     122             : 
     123             : } // anonymous namespace
     124             : 
     125             : 
     126             : 
     127             : #ifdef LIBMESH_HAVE_MPI
     128           0 : void libMesh_MPI_Handler (MPI_Comm *, int *, ...)
     129             : {
     130           0 :   libmesh_not_implemented();
     131             : }
     132             : #endif
     133             : 
     134             : 
     135             : namespace libMesh
     136             : {
     137             : 
     138             : /**
     139             :  * Namespaces don't provide private data,
     140             :  * so let's take the data we would like
     141             :  * private and put it in an obnoxious
     142             :  * namespace.  At least that way it is a
     143             :  * pain to use, thus discouraging errors.
     144             :  */
     145             : namespace libMeshPrivateData {
     146             : 
     147             : /**
     148             :  * Flag that tells if \p init() has been called.
     149             :  */
     150             : extern bool _is_initialized;
     151             : 
     152             : /**
     153             :  * The default solver package to use.
     154             :  */
     155             : extern SolverPackage _solver_package;
     156             : }
     157             : 
     158             : 
     159             : // ------------------------------------------------------------
     160             : // libMesh data initialization
     161             : #ifdef LIBMESH_HAVE_MPI
     162             : MPI_Comm           GLOBAL_COMM_WORLD = MPI_COMM_NULL;
     163             : #else
     164             : int                GLOBAL_COMM_WORLD = 0;
     165             : #endif
     166             : 
     167             : #ifdef LIBMESH_ENABLE_EXCEPTIONS
     168             : std::terminate_handler LibMeshInit::_old_terminate_handler;
     169             : #endif
     170             : 
     171             : OStreamProxy out(std::cout);
     172             : OStreamProxy err(std::cerr);
     173             : 
     174             : // Our thread-safe wrappers and the “pre-wrap” sink pointers
     175             : std::unique_ptr<ThreadBufferedSyncbuf> _out_syncd_thread_buffer;
     176             : std::unique_ptr<ThreadBufferedSyncbuf> _err_syncd_thread_buffer;
     177             : std::streambuf * _out_prewrap_buf = nullptr;
     178             : std::streambuf * _err_prewrap_buf = nullptr;
     179             : 
     180             : // Install after redirection/drop decisions
     181       16600 : void install_thread_buffered_sync()
     182             : {
     183         702 :   auto check_stored_buffer = [](const auto * const libmesh_dbg_var(stored_buffer)) {
     184         702 :     libmesh_assert_msg(!stored_buffer,
     185             :                        "Oops, we've already stored a prewrapped buffer. We must be calling this "
     186             :                        "function a second time in which case we're going to lose the already "
     187             :                        "stored prewrapped buffer forever");
     188         702 :   };
     189             : 
     190             :   // libMesh::out
     191       17068 :   if (auto * ob = libMesh::out.rdbuf(); ob)
     192             :     {
     193         234 :       check_stored_buffer(_out_prewrap_buf);
     194        2794 :       _out_prewrap_buf = ob;
     195             :       _out_syncd_thread_buffer =
     196        5354 :           std::make_unique<ThreadBufferedSyncbuf>(*ob, /*flush_on_newline=*/true);
     197        2794 :       libMesh::out.rdbuf(_out_syncd_thread_buffer.get());
     198             :     }
     199             : 
     200             :   // libMesh::err
     201       17068 :   if (auto * eb = libMesh::err.rdbuf(); eb)
     202             :     {
     203         468 :       check_stored_buffer(_err_prewrap_buf);
     204       16600 :       _err_prewrap_buf = eb;
     205             :       _err_syncd_thread_buffer =
     206       32732 :           std::make_unique<ThreadBufferedSyncbuf>(*eb, /*flush_on_newline=*/true);
     207       16600 :       libMesh::err.rdbuf(_err_syncd_thread_buffer.get());
     208             :     }
     209       16600 : }
     210             : 
     211             : // Uninstall before restoring/redirection teardown
     212       16600 : void uninstall_thread_buffered_sync()
     213             : {
     214       16600 :   if (_out_syncd_thread_buffer)
     215             :     {
     216             :       // flush any thread-local leftovers on this thread
     217         234 :       libMesh::out << std::flush;
     218        2794 :       libMesh::out.rdbuf(_out_prewrap_buf);
     219         234 :       _out_syncd_thread_buffer.reset();
     220        2794 :       _out_prewrap_buf = nullptr;
     221             :     }
     222       16600 :   if (_err_syncd_thread_buffer)
     223             :     {
     224         468 :       libMesh::err << std::flush;
     225       16600 :       libMesh::err.rdbuf(_err_prewrap_buf);
     226             : #ifdef PETSC_HAVE_UMPIRE
     227             :       // Our libMesh::out and libMesh::err stream proxies are very thin wrappers around,
     228             :       // by default, std::cout and std::cerr. So when other libraries or users access the
     229             :       // rdbuf of those streams, then they directly access our thread sync'd custom stream
     230             :       // buffer. Umpire doesn't use the rdbuf of std::cout, but they *do* use the rdbuf of
     231             :       // std::cerr, which means they're using our thread sync'd stream buffer. Consequently,
     232             :       // we must release umpire's reference to our buffer before we destroy it
     233             :       umpire::util::finalize_io();
     234             : #endif
     235         468 :       _err_syncd_thread_buffer.reset();
     236       16600 :       _err_prewrap_buf = nullptr;
     237             :     }
     238       16600 : }
     239             : 
     240             : 
     241             : /**
     242             :  * Helper to do cleanup from both destructor and terminate
     243             :  */
     244       16600 : void cleanup_stream_buffers()
     245             : {
     246             :   // Before resetting the stream buffers, let's remove our thread wrappers
     247       32732 :   if (!libMesh::on_command_line ("--disable-thread-safe-output"))
     248       16600 :     uninstall_thread_buffered_sync();
     249             : 
     250       34136 :   if (libMesh::on_command_line ("--redirect-stdout") ||
     251       33668 :       libMesh::on_command_line ("--redirect-output"))
     252             :     {
     253             :       // If stdout/stderr were redirected to files, reset them now.
     254           0 :       libMesh::out.rdbuf (out_buf);
     255           0 :       libMesh::err.rdbuf (err_buf);
     256             :     }
     257             : 
     258             :   // If we built our own output streams, we want to clean them up.
     259       32732 :   if (libMesh::on_command_line ("--separate-libmeshout"))
     260             :     {
     261           0 :       delete libMesh::out.get();
     262           0 :       delete libMesh::err.get();
     263             : 
     264           0 :       libMesh::out.reset(std::cout);
     265           0 :       libMesh::err.reset(std::cerr);
     266             :     }
     267       16600 : }
     268             : 
     269             : 
     270             : bool warned_about_auto_ptr(false);
     271             : 
     272             : PerfLog            perflog ("libMesh",
     273             : #ifdef LIBMESH_ENABLE_PERFORMANCE_LOGGING
     274             :                             true
     275             : #else
     276             :                             false
     277             : #endif
     278             :                             );
     279             : 
     280             : 
     281             : #ifdef LIBMESH_USE_COMPLEX_NUMBERS
     282             : const Number       imaginary (0., 1.);
     283             : // const Number       zero      (0., 0.);
     284             : #else
     285             : // const Number       zero = 0.;
     286             : #endif
     287             : 
     288             : // This is now a static constant in the header; no reason not to let
     289             : // the compiler inline it.
     290             : 
     291             : // const unsigned int invalid_uint = static_cast<unsigned int>(-1);
     292             : 
     293             : 
     294             : 
     295             : // ------------------------------------------------------------
     296             : // libMesh::libMeshPrivateData data initialization
     297             : #ifdef LIBMESH_HAVE_MPI
     298             : MPI_Errhandler libmesh_errhandler;
     299             : 
     300             : processor_id_type libMesh::libMeshPrivateData::_n_processors = 1;
     301             : processor_id_type libMesh::libMeshPrivateData::_processor_id = 0;
     302             : #endif
     303             : int           libMesh::libMeshPrivateData::_n_threads = 1; /* Threads::task_scheduler_init::automatic; */
     304             : bool          libMesh::libMeshPrivateData::_is_initialized = false;
     305             : SolverPackage libMesh::libMeshPrivateData::_solver_package =
     306             : #if   defined(LIBMESH_HAVE_PETSC)    // PETSc is the default
     307             :   PETSC_SOLVERS;
     308             : #elif defined(LIBMESH_TRILINOS_HAVE_AZTECOO) // Use Trilinos if PETSc isn't there
     309             : TRILINOS_SOLVERS;
     310             : #elif defined(LIBMESH_HAVE_EIGEN)    // Use Eigen if neither are there
     311             : EIGEN_SOLVERS;
     312             : #elif defined(LIBMESH_HAVE_LASPACK)  // Use LASPACK as a last resort
     313             : LASPACK_SOLVERS;
     314             : #else                        // No valid linear solver package at compile time
     315             : INVALID_SOLVER_PACKAGE;
     316             : #endif
     317             : 
     318             : 
     319             : 
     320             : // ------------------------------------------------------------
     321             : // libMesh functions
     322             : 
     323       79692 : bool initialized()
     324             : {
     325       79692 :   return libMeshPrivateData::_is_initialized;
     326             : }
     327             : 
     328             : 
     329             : 
     330       28740 : bool closed()
     331             : {
     332       28740 :   return !libMeshPrivateData::_is_initialized;
     333             : }
     334             : 
     335             : 
     336             : 
     337           0 : void libmesh_abort()
     338             : {
     339           0 :   libMesh::perflog.clear();
     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
     344           0 :   cleanup_stream_buffers();
     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 :   LibMeshInit::_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       16600 : LibMeshInit::LibMeshInit (int argc, const char * const * argv,
     370       16600 :                           TIMPI::communicator COMM_WORLD_IN, int n_threads)
     371             : {
     372             :   // should _not_ be initialized already.
     373         468 :   libmesh_assert (!libMesh::initialized());
     374             : 
     375             :   // Build a command-line parser.
     376       32264 :   command_line = std::make_unique<GetPot>(argc, argv);
     377             : 
     378             :   // Disable performance logging upon request
     379             :   {
     380       32732 :     if (libMesh::on_command_line ("--disable-perflog"))
     381           0 :       libMesh::perflog.disable_logging();
     382             :   }
     383             : 
     384       47488 :   auto check_empty_command_line_value = [](auto & cl, const std::string & option) {
     385       47488 :     libmesh_error_msg_if(cl.search(option),
     386             :                          "Detected option " << option << " with no value.  Did you forget '='?");
     387       47488 :   };
     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       17068 :     std::vector<std::string> n_threads_opt(2);
     396         936 :     n_threads_opt[0] = "--n_threads";
     397         936 :     n_threads_opt[1] = "--n-threads";
     398       16600 :     libMesh::libMeshPrivateData::_n_threads =
     399       16600 :       libMesh::command_line_value(n_threads_opt, n_threads);
     400             : 
     401       16600 :     if (libMesh::libMeshPrivateData::_n_threads == -1)
     402             :       {
     403       46332 :         for (auto & option : n_threads_opt)
     404       30888 :           check_empty_command_line_value(*command_line, option);
     405             : 
     406       15444 :         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       16600 :     omp_set_num_threads(libMesh::libMeshPrivateData::_n_threads);
     422             : #endif
     423             : 
     424       16132 :     task_scheduler = std::make_unique<Threads::task_scheduler_init>(libMesh::n_threads());
     425       15664 :   }
     426             : 
     427             :   // Construct singletons who may be at risk of the
     428             :   // "static initialization order fiasco"
     429       16600 :   Singleton::setup();
     430             : 
     431             :   // Make sure the construction worked
     432         468 :   libmesh_assert(remote_elem);
     433             : 
     434       16600 :   const bool using_threads = libMesh::n_threads() > 1;
     435         468 :   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       32732 :   if (!libMesh::on_command_line ("--disable-mpi"))
     441             :     {
     442       16600 :       int mpi_thread_request = using_threads;
     443       33668 :       const auto mpi_thread_type = libMesh::command_line_value("--mpi-thread-type", std::string(""));
     444       16600 :       if (mpi_thread_type.empty())
     445             :         {
     446       32732 :           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       16600 :       this->_timpi_init =
     480             :         new TIMPI::TIMPIInit(argc, argv, mpi_thread_request,
     481       16600 :                              handle_mpi_errors, COMM_WORLD_IN);
     482       16600 :       _comm = new Parallel::Communicator(this->_timpi_init->comm().get());
     483             : 
     484             :       const std::string timpi_sync =
     485       33668 :         libMesh::command_line_value("--timpi-sync", std::string("nbx"));
     486       16600 :       _comm->sync_type(timpi_sync);
     487             : 
     488       16600 :       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       16600 :       libMeshPrivateData::_processor_id =
     494         936 :         cast_int<processor_id_type>(this->comm().rank());
     495       16600 :       libMeshPrivateData::_n_processors =
     496         936 :         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       32732 :       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         468 :   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         468 :   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       32760 :   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       32760 :       && !libMesh::on_command_line ("--disable-mpi")
     538             : #endif
     539             :       )
     540             :     {
     541             : #ifdef LIBMESH_HAVE_MPI
     542       16380 :       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       16380 :       LibmeshPetscCallA(libMesh::GLOBAL_COMM_WORLD, PetscInitialized(&petsc_already_initialized));
     552       16380 :       if (petsc_already_initialized != PETSC_TRUE)
     553       16380 :         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       16380 :       if (!SlepcInitializeCalled)
     562             :         {
     563       16380 :           LibmeshPetscCallA(libMesh::GLOBAL_COMM_WORLD, SlepcInitialize  (&argc, const_cast<char ***>(&argv), nullptr, nullptr));
     564       16380 :           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       16380 :       LibmeshPetscCallA(libMesh::GLOBAL_COMM_WORLD, DMRegister(DMLIBMESH, DMCreate_libMesh));
     572             :     }
     573             : #endif
     574             : 
     575             : #ifdef LIBMESH_HAVE_NETGEN
     576       16600 :   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       32264 :   command_line = std::make_unique<GetPot>(argc, argv);
     596             : 
     597             :   // Not syncing with stdio 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             :   // However, not syncing the streams means thread safety is no longer
     603             :   // guaranteed and we have indeed seen thread sanitizer warnings
     604             :   // during concurrent writes to std::cout when toggling this boolean
     605             :   // to true. We default to preferring safety and correctness instead
     606             :   // of performance
     607       32732 :   if (libMesh::on_command_line ("--dont-sync-with-stdio"))
     608           0 :     std::ios::sync_with_stdio(false);
     609             : 
     610             :   // Honor the --separate-libmeshout command-line option.
     611             :   // When this is specified, the library uses an independent ostream
     612             :   // for libMesh::out/libMesh::err messages, and
     613             :   // std::cout and std::cerr are untouched by any other options
     614       32732 :   if (libMesh::on_command_line ("--separate-libmeshout"))
     615             :     {
     616             :       // Redirect.  We'll share streambufs with cout/cerr for now, but
     617             :       // presumably anyone using this option will want to replace the
     618             :       // bufs later.
     619           0 :       std::ostream * newout = new std::ostream(std::cout.rdbuf());
     620           0 :       libMesh::out = *newout;
     621           0 :       std::ostream * newerr = new std::ostream(std::cerr.rdbuf());
     622           0 :       libMesh::err = *newerr;
     623             :     }
     624             : 
     625             :   // Process command line arguments for redirecting stdout/stderr.
     626             :   bool
     627       16600 :     cmdline_has_redirect_stdout = libMesh::on_command_line ("--redirect-stdout"),
     628       16600 :     cmdline_has_redirect_output = libMesh::on_command_line ("--redirect-output");
     629             : 
     630             :   // The --redirect-stdout command-line option has been deprecated in
     631             :   // favor of "--redirect-output basename".
     632             :   if (cmdline_has_redirect_stdout)
     633             :     libmesh_warning("The --redirect-stdout command line option has been deprecated. "
     634             :                     "Use '--redirect-output basename' instead.");
     635             : 
     636             :   // Honor the "--redirect-stdout" and "--redirect-output basename"
     637             :   // command-line options.  When one of these is specified, each
     638             :   // processor sends libMesh::out/libMesh::err messages to
     639             :   // stdout.processor.#### (default) or basename.processor.####.
     640       16600 :   if (cmdline_has_redirect_stdout || cmdline_has_redirect_output)
     641             :     {
     642           0 :       std::string basename = "stdout";
     643             : 
     644             :       // Look for following argument if using new API
     645           0 :       if (cmdline_has_redirect_output)
     646             :         {
     647             :           // Set the cursor to the correct location in the list of command line arguments.
     648           0 :           command_line->search(1, "--redirect-output");
     649             : 
     650             :           // Get the next option on the command line as a string.
     651           0 :           std::string next_string = "";
     652           0 :           next_string = command_line->next(next_string);
     653             : 
     654             :           // If the next string starts with a dash, we assume it's
     655             :           // another flag and not a file basename requested by the
     656             :           // user.
     657           0 :           if (next_string.size() > 0 && next_string.find_first_of("-") != 0)
     658           0 :             basename = next_string;
     659             :         }
     660             : 
     661           0 :       std::ostringstream filename;
     662           0 :       filename << basename << ".processor." << libMesh::global_processor_id();
     663           0 :       _ofstream = std::make_unique<std::ofstream>(filename.str().c_str());
     664             : 
     665             :       // Redirect, saving the original streambufs!
     666           0 :       out_buf = libMesh::out.rdbuf (_ofstream->rdbuf());
     667           0 :       err_buf = libMesh::err.rdbuf (_ofstream->rdbuf());
     668           0 :     }
     669             : 
     670             :   // redirect libMesh::out to nothing on all
     671             :   // other processors unless explicitly told
     672             :   // not to via the --keep-cout command-line argument.
     673       32732 :   if (!libMesh::on_command_line ("--keep-cout"))
     674       16600 :     if (libMesh::global_processor_id() != 0)
     675       13806 :       libMesh::out.rdbuf (nullptr);
     676             : 
     677             :   // Similarly, the user can request to drop cerr on all non-0 ranks.
     678             :   // By default, errors are printed on all ranks, but this can lead to
     679             :   // interleaved/unpredictable outputs when doing parallel regression
     680             :   // testing, which this option is designed to support.
     681       32732 :   if (libMesh::on_command_line ("--drop-cerr"))
     682           0 :     if (libMesh::global_processor_id() != 0)
     683           0 :       libMesh::err.rdbuf (nullptr);
     684             : 
     685             :   // Now that we've finished setting our stream buffers, let's wrap them (if they're non-null) in our thread-safe wrapper
     686       32732 :   if (!libMesh::on_command_line ("--disable-thread-safe-output"))
     687       16600 :     install_thread_buffered_sync();
     688             : 
     689             :   // Check command line to override printing
     690             :   // of reference count information.
     691       32732 :   if (libMesh::on_command_line("--disable-refcount-printing"))
     692           0 :     ReferenceCounter::disable_print_counter_info();
     693             : 
     694             : #ifdef LIBMESH_ENABLE_EXCEPTIONS
     695             :   // Set our terminate handler to write stack traces in the event of a
     696             :   // crash
     697       16600 :   _old_terminate_handler = std::set_terminate(libmesh_terminate_handler);
     698             : #endif
     699             : 
     700             : 
     701       32732 :   if (libMesh::on_command_line("--enable-fpe"))
     702           0 :     libMesh::enableFPE(true);
     703             : 
     704       32732 :   if (libMesh::on_command_line("--enable-segv"))
     705           0 :     libMesh::enableSEGV(true);
     706             : 
     707       32732 :   if (libMesh::on_command_line("--enable-sigint"))
     708           0 :     libMesh::enableSIGINT(true);
     709             : 
     710             : #if defined(LIBMESH_HAVE_HDF5) && !defined(_MSC_VER)
     711             :   // We may be running with ExodusII configured not to use HDF5 (in
     712             :   // which case user code which wants to lock files has to do flock()
     713             :   // itself) or with ExodusII configured to use HDF5 (which will
     714             :   // helpfully try to get an exclusive flock() itself, and then scream
     715             :   // and die if user code has already locked the file.  To get
     716             :   // consistent behavior, we need to disable file locking.  The only
     717             :   // reliable way I can see to do this is via an HDF5 environment
     718             :   // variable.
     719             :   //
     720             :   // If the user set this environment variable then we'll trust that
     721             :   // they know what they're doing.  If not then we'll set FALSE,
     722             :   // because that's a better default for us than the unset default.
     723         468 :   setenv("HDF5_USE_FILE_LOCKING", "FALSE", /*overwrite=false*/0);
     724             : #endif // LIBMESH_HAVE_HDF5
     725             : 
     726             :   // The library is now ready for use
     727       16600 :   libMeshPrivateData::_is_initialized = true;
     728             : 
     729             : 
     730             :   // Make sure these work.  Library methods
     731             :   // depend on these being implemented properly,
     732             :   // so this is a good time to test them!
     733         468 :   libmesh_assert (libMesh::initialized());
     734         468 :   libmesh_assert (!libMesh::closed());
     735       16600 : }
     736             : 
     737             : 
     738             : 
     739       17536 : LibMeshInit::~LibMeshInit()
     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       16600 :   if (!std::uncaught_exceptions())
     755             : #endif
     756       16600 :     this->comm().barrier();
     757             : 
     758             :   // We can't delete, finalize, etc. more than once without
     759             :   // reinitializing in between
     760         468 :   libmesh_exceptionless_assert(!libMesh::closed());
     761             : 
     762             :   // Delete reference counted singleton(s)
     763       16600 :   Singleton::cleanup();
     764             : 
     765             :   // Clear the thread task manager we started
     766         468 :   task_scheduler.reset();
     767             : 
     768             :   // If we have a memory leak, we want the details printed.
     769       16600 :   if (ReferenceCounter::n_objects() != 0)
     770           0 :     ReferenceCounter::enable_print_counter_info();
     771             : 
     772             :   // Ask the \p ReferenceCounter to print its reference count
     773             :   // information, if printing is enabled.  This allows us to find
     774             :   // memory leaks.
     775             :   //
     776             :   // If we don't have any leaks, we'll print to cout, only if we've
     777             :   // been told to.  If we do, we'll print to cerr, to make sure the
     778             :   // user doesn't miss a leak that's only on a processor other than 0.
     779       16600 :   if (ReferenceCounter::n_objects() == 0)
     780       16600 :     ReferenceCounter::print_info ();
     781             : 
     782             :   // Scream specifically if we detect a memory leak
     783       16600 :   if (ReferenceCounter::n_objects() != 0)
     784             :     {
     785           0 :       ReferenceCounter::print_info (libMesh::err);
     786             : 
     787           0 :       libMesh::err << "Memory leak detected!"
     788           0 :                    << std::endl;
     789             : 
     790             : #if !defined(LIBMESH_ENABLE_REFERENCE_COUNTING) || defined(NDEBUG)
     791             : 
     792             :       libMesh::err << "Compile in DEBUG mode with --enable-reference-counting"
     793             :                    << std::endl
     794             :                    << "for more information"
     795             :                    << std::endl;
     796             : #endif
     797             :     }
     798             : 
     799             :   //  print the perflog to individual processor's file.
     800       16600 :   libMesh::perflog.print_log();
     801             : 
     802             :   // Now clear the logging object, we don't want it to print
     803             :   // a second time during the PerfLog destructor.
     804       16600 :   libMesh::perflog.clear();
     805             : 
     806             :   // Reconnect the output streams
     807             :   // (don't do this, or we will get messages from objects
     808             :   //  that go out of scope after the following return)
     809             :   //std::cout.rdbuf(std::cerr.rdbuf());
     810             : 
     811             : 
     812             :   // Set the initialized() flag to false
     813       16600 :   libMeshPrivateData::_is_initialized = false;
     814             : 
     815       16600 :   cleanup_stream_buffers();
     816             : 
     817             : #ifdef LIBMESH_ENABLE_EXCEPTIONS
     818             :   // Reset the old terminate handler; maybe the user code wants to
     819             :   // keep doing C++ stuff after closing libMesh stuff.
     820       16600 :   std::set_terminate(_old_terminate_handler);
     821             : #endif
     822             : 
     823             : #ifdef LIBMESH_HAVE_NETGEN
     824       16600 :   nglib::Ng_Exit();
     825             : #endif
     826             : 
     827       32732 :   if (libMesh::on_command_line("--enable-fpe"))
     828           0 :     libMesh::enableFPE(false);
     829             : 
     830             : #if defined(LIBMESH_HAVE_PETSC)
     831             :   // Let PETSc know about all the command line objects that we
     832             :   // consumed without asking them, so we don't get unused option
     833             :   // warnings about those.
     834       17316 :   std::vector<std::string> cli_names = command_line_names();
     835      546244 :   for (const auto & name : cli_names)
     836      529864 :     if (!name.empty() && name[0] == '-')
     837             :       {
     838             :         // Newer PETSc can give me a double-free I'm having trouble
     839             :         // replicating; let's protect against trying to clear
     840             :         // already-used values
     841      517202 :         PetscBool used = PETSC_FALSE;
     842      517202 :         auto ierr = PetscOptionsUsed(NULL, name.c_str(), &used);
     843      517202 :         CHKERRABORT(libMesh::GLOBAL_COMM_WORLD, ierr);
     844      517202 :         if (used == PETSC_FALSE)
     845             :           {
     846      517202 :             ierr = PetscOptionsClearValue(NULL, name.c_str());
     847      517202 :             CHKERRABORT(libMesh::GLOBAL_COMM_WORLD, ierr);
     848             :           }
     849             :       }
     850             : 
     851             :   // Allow the user to bypass PETSc finalization
     852       32760 :   if (!libMesh::on_command_line ("--disable-petsc")
     853             : #if defined(LIBMESH_HAVE_MPI)
     854       32760 :       && !libMesh::on_command_line ("--disable-mpi")
     855             : #endif
     856             :       )
     857             :     {
     858         468 :       PetscErrorCode ierr = LIBMESH_PETSC_SUCCESS;
     859             : # if defined(LIBMESH_HAVE_SLEPC)
     860       16380 :       if (libmesh_initialized_slepc)
     861       16380 :         ierr = SlepcFinalize();
     862             : # else
     863             :       if (libmesh_initialized_petsc)
     864             :         ierr = PetscFinalize();
     865             : # endif
     866       16380 :       CHKERRABORT(libMesh::GLOBAL_COMM_WORLD, ierr);
     867             :     }
     868             : #endif
     869             : 
     870             : #if defined(LIBMESH_HAVE_MPI) && defined(LIBMESH_HAVE_VTK)
     871             :   _vtk_mpi_controller->Finalize(/*finalized_externally=*/1);
     872             :   _vtk_mpi_controller->Delete();
     873             : #endif
     874             : 
     875       32732 :   delete this->_comm;
     876             : 
     877             : #if defined(LIBMESH_HAVE_MPI)
     878             :   // Allow the user to bypass MPI finalization
     879       32732 :   if (!libMesh::on_command_line ("--disable-mpi"))
     880             :     {
     881       16600 :       delete this->_timpi_init;
     882             :     }
     883             : #else
     884             :   delete this->_timpi_init;
     885             : #endif
     886       16600 : }
     887             : 
     888             : 
     889           0 : PerfLog & LibMeshInit::perf_log()
     890             : {
     891           0 :   return libMesh::perflog;
     892             : }
     893             : 
     894             : 
     895             : 
     896     4747621 : void add_command_line_name(const std::string & name)
     897             : {
     898             :   // Users had better not be asking about an empty string
     899      123930 :   libmesh_assert(!name.empty());
     900             : 
     901             :   static std::mutex command_line_names_mutex;
     902      247860 :   std::scoped_lock lock(command_line_names_mutex);
     903             : 
     904     4623731 :   command_line_name_set.insert(name);
     905     4747621 : }
     906             : 
     907             : 
     908             : 
     909          71 : void add_command_line_names(const GetPot & getpot)
     910             : {
     911         213 :   for (auto & getter : {&GetPot::get_requested_arguments,
     912             :                         &GetPot::get_requested_variables,
     913         284 :                         &GetPot::get_requested_sections})
     914       10591 :     for (const std::string & name : (getpot.*getter)())
     915       10372 :       add_command_line_name(name);
     916          71 : }
     917             : 
     918             : 
     919       16380 : std::vector<std::string> command_line_names()
     920             : {
     921             :   return std::vector<std::string>(command_line_name_set.begin(),
     922       16380 :                                   command_line_name_set.end());
     923             : }
     924             : 
     925             : 
     926             : 
     927     4681220 : bool on_command_line (std::string arg)
     928             : {
     929             :   // Make sure the command line parser is ready for use.  If it's not,
     930             :   // then we'll have to treat the command line as empty, for maximum
     931             :   // compatibility with programs that don't use LibMeshInit but
     932             :   // indirectly (e.g. via error handling code) query the command line.
     933     4681220 :   if (!command_line.get())
     934           0 :     return false;
     935             : 
     936             :   // Keep track of runtime queries, for later
     937     4681220 :   add_command_line_name(arg);
     938             : 
     939      121856 :   bool found_it = command_line->search(arg);
     940             : 
     941     4681220 :   if (!found_it)
     942             :     {
     943             :       // Try with all dashes instead of underscores
     944      121298 :       std::replace(arg.begin(), arg.end(), '_', '-');
     945      121298 :       found_it = command_line->search(arg);
     946             :     }
     947             : 
     948     4666602 :   if (!found_it)
     949             :     {
     950             :       // OK, try with all underscores instead of dashes
     951      121296 :       auto name_begin = arg.begin();
     952    13988822 :       while (*name_begin == '-')
     953      242262 :         ++name_begin;
     954      121296 :       std::replace(name_begin, arg.end(), '-', '_');
     955      121296 :       found_it = command_line->search(arg);
     956             :     }
     957             : 
     958      121856 :   return found_it;
     959             : }
     960             : 
     961             : 
     962             : 
     963             : template <typename T>
     964      370497 : T command_line_value (const std::string & name, T value)
     965             : {
     966             :   // Make sure the command line parser is ready for use
     967       10722 :   libmesh_assert(command_line.get());
     968             : 
     969             :   // only if the variable exists in the file
     970       10722 :   if (command_line->have_variable(name))
     971             :     {
     972        2776 :       value = (*command_line)(name, value);
     973             : 
     974             :       // Keep track of runtime queries, for later.  GetPot splits
     975             :       // foo=bar into a separate name=value, so we can query for the
     976             :       // name, but as far as PETSc is concerned that's one CLI
     977             :       // argument.  We'll store it that way.
     978         120 :       const std::string stringvalue =
     979        2174 :         (*command_line)(name, std::string());
     980        4408 :       add_command_line_name(name+"="+stringvalue);
     981             :     }
     982             : 
     983      370497 :   return value;
     984             : }
     985             : 
     986             : template <typename T>
     987       16600 : T command_line_value (const std::vector<std::string> & names, T value)
     988             : {
     989             :   // Make sure the command line parser is ready for use
     990         468 :   libmesh_assert(command_line.get());
     991             : 
     992             :   // Keep track of runtime queries, for later
     993       49800 :   for (const auto & entry : names)
     994             :     {
     995             :       // Keep track of runtime queries, for later.  GetPot splits
     996             :       // foo=bar into a separate name=value, so we can query for the
     997             :       // name, but as far as PETSc is concerned that's one CLI
     998             :       // argument.  We'll store it that way.
     999        1872 :       const std::string stringvalue =
    1000       32264 :         (*command_line)(entry, std::string());
    1001       65464 :       add_command_line_name(entry+"="+stringvalue);
    1002             :     }
    1003             : 
    1004             :   // Check for multiple options (return the first that matches)
    1005       47488 :   for (const auto & entry : names)
    1006         594 :     if (command_line->have_variable(entry))
    1007             :       {
    1008        1156 :         value = (*command_line)(entry, value);
    1009        1156 :         break;
    1010             :       }
    1011             : 
    1012       16600 :   return value;
    1013             : }
    1014             : 
    1015             : 
    1016             : 
    1017             : template <typename T>
    1018       20315 : T command_line_next (std::string name, T value)
    1019             : {
    1020             :   // Make sure the command line parser is ready for use
    1021         776 :   libmesh_assert(command_line.get());
    1022             : 
    1023             :   // Keep track of runtime queries, for later
    1024       20315 :   add_command_line_name(name);
    1025             : 
    1026             :   // on_command_line also puts the command_line cursor in the spot we
    1027             :   // need
    1028       39854 :   if (on_command_line(name))
    1029       12920 :     return command_line->next(value);
    1030             : 
    1031        7285 :   return value;
    1032             : }
    1033             : 
    1034             : 
    1035             : 
    1036             : template <typename T>
    1037         280 : void command_line_vector (const std::string & name, std::vector<T> & vec)
    1038             : {
    1039             :   // Make sure the command line parser is ready for use
    1040           8 :   libmesh_assert(command_line.get());
    1041             : 
    1042             :   // Keep track of runtime queries, for later
    1043         280 :   add_command_line_name(name);
    1044             : 
    1045             :   // only if the variable exists on the command line
    1046           8 :   if (command_line->have_variable(name))
    1047             :     {
    1048           8 :       unsigned size = command_line->vector_variable_size(name);
    1049         280 :       vec.resize(size);
    1050             : 
    1051         560 :       for (unsigned i=0; i<size; ++i)
    1052         280 :         vec[i] = (*command_line)(name, vec[i], i);
    1053             :     }
    1054         280 : }
    1055             : 
    1056             : 
    1057     2005787 : SolverPackage default_solver_package ()
    1058             : {
    1059       58644 :   libmesh_assert (libMesh::initialized());
    1060             : 
    1061             :   static bool called = false;
    1062             : 
    1063             :   // Check the command line.  Since the command line is
    1064             :   // unchanging it is sufficient to do this only once.
    1065     2005787 :   if (!called)
    1066             :     {
    1067       15121 :       called = true;
    1068             : 
    1069             : #ifdef LIBMESH_HAVE_PETSC
    1070       29402 :       if (libMesh::on_command_line ("--use-petsc"))
    1071           0 :         libMeshPrivateData::_solver_package = PETSC_SOLVERS;
    1072             : #endif
    1073             : 
    1074             : #ifdef LIBMESH_TRILINOS_HAVE_AZTECOO
    1075             :       if (libMesh::on_command_line ("--use-trilinos") ||
    1076             :           libMesh::on_command_line ("--disable-petsc"))
    1077             :         libMeshPrivateData::_solver_package = TRILINOS_SOLVERS;
    1078             : #endif
    1079             : 
    1080             : #ifdef LIBMESH_HAVE_EIGEN
    1081       44935 :       if (libMesh::on_command_line ("--use-eigen"  ) ||
    1082             : #if defined(LIBMESH_HAVE_MPI)
    1083             :           // If the user bypassed MPI, we disable PETSc and Trilinos
    1084             :           // too
    1085       31526 :           libMesh::on_command_line ("--disable-mpi") ||
    1086             : #endif
    1087       30670 :           libMesh::on_command_line ("--disable-petsc"))
    1088           0 :         libMeshPrivateData::_solver_package = EIGEN_SOLVERS;
    1089             : #endif
    1090             : 
    1091             : #ifdef LIBMESH_HAVE_LASPACK
    1092        2140 :       if (libMesh::on_command_line ("--use-laspack"  ) ||
    1093             : #if defined(LIBMESH_HAVE_MPI)
    1094             :           // If the user bypassed MPI, we disable PETSc and Trilinos
    1095             :           // too
    1096        2996 :           libMesh::on_command_line ("--disable-mpi") ||
    1097             : #endif
    1098        2140 :           libMesh::on_command_line ("--disable-petsc"))
    1099           0 :         libMeshPrivateData::_solver_package = LASPACK_SOLVERS;
    1100             : #endif
    1101             : 
    1102       30242 :       if (libMesh::on_command_line ("--disable-laspack") &&
    1103       15121 :           libMesh::on_command_line ("--disable-trilinos") &&
    1104       30670 :           libMesh::on_command_line ("--disable-eigen") &&
    1105             :           (
    1106             : #if defined(LIBMESH_HAVE_MPI)
    1107             :            // If the user bypassed MPI, we disable PETSc too
    1108       15121 :            libMesh::on_command_line ("--disable-mpi") ||
    1109             : #endif
    1110       15121 :            libMesh::on_command_line ("--disable-petsc")))
    1111           0 :         libMeshPrivateData::_solver_package = INVALID_SOLVER_PACKAGE;
    1112             :     }
    1113             : 
    1114             : 
    1115     2005787 :   return libMeshPrivateData::_solver_package;
    1116             : }
    1117             : 
    1118             : 
    1119             : 
    1120             : //-------------------------------------------------------------------------------
    1121             : template LIBMESH_EXPORT unsigned char  command_line_value<unsigned char>  (const std::string &, unsigned char);
    1122             : template LIBMESH_EXPORT unsigned short command_line_value<unsigned short> (const std::string &, unsigned short);
    1123             : template LIBMESH_EXPORT unsigned int   command_line_value<unsigned int>   (const std::string &, unsigned int);
    1124             : template LIBMESH_EXPORT char           command_line_value<char>           (const std::string &, char);
    1125             : template LIBMESH_EXPORT short          command_line_value<short>          (const std::string &, short);
    1126             : template LIBMESH_EXPORT int            command_line_value<int>            (const std::string &, int);
    1127             : template LIBMESH_EXPORT float          command_line_value<float>          (const std::string &, float);
    1128             : template LIBMESH_EXPORT double         command_line_value<double>         (const std::string &, double);
    1129             : template LIBMESH_EXPORT long double    command_line_value<long double>    (const std::string &, long double);
    1130             : template LIBMESH_EXPORT std::string    command_line_value<std::string>    (const std::string &, std::string);
    1131             : 
    1132             : template LIBMESH_EXPORT unsigned char  command_line_value<unsigned char>  (const std::vector<std::string> &, unsigned char);
    1133             : template LIBMESH_EXPORT unsigned short command_line_value<unsigned short> (const std::vector<std::string> &, unsigned short);
    1134             : template LIBMESH_EXPORT unsigned int   command_line_value<unsigned int>   (const std::vector<std::string> &, unsigned int);
    1135             : template LIBMESH_EXPORT char           command_line_value<char>           (const std::vector<std::string> &, char);
    1136             : template LIBMESH_EXPORT short          command_line_value<short>          (const std::vector<std::string> &, short);
    1137             : template LIBMESH_EXPORT int            command_line_value<int>            (const std::vector<std::string> &, int);
    1138             : template LIBMESH_EXPORT float          command_line_value<float>          (const std::vector<std::string> &, float);
    1139             : template LIBMESH_EXPORT double         command_line_value<double>         (const std::vector<std::string> &, double);
    1140             : template LIBMESH_EXPORT long double    command_line_value<long double>    (const std::vector<std::string> &, long double);
    1141             : template LIBMESH_EXPORT std::string    command_line_value<std::string>    (const std::vector<std::string> &, std::string);
    1142             : 
    1143             : template LIBMESH_EXPORT unsigned char  command_line_next<unsigned char>   (std::string, unsigned char);
    1144             : template LIBMESH_EXPORT unsigned short command_line_next<unsigned short>  (std::string, unsigned short);
    1145             : template LIBMESH_EXPORT unsigned int   command_line_next<unsigned int>    (std::string, unsigned int);
    1146             : template LIBMESH_EXPORT char           command_line_next<char>            (std::string, char);
    1147             : template LIBMESH_EXPORT short          command_line_next<short>           (std::string, short);
    1148             : template LIBMESH_EXPORT int            command_line_next<int>             (std::string, int);
    1149             : template LIBMESH_EXPORT float          command_line_next<float>           (std::string, float);
    1150             : template LIBMESH_EXPORT double         command_line_next<double>          (std::string, double);
    1151             : template LIBMESH_EXPORT long double    command_line_next<long double>     (std::string, long double);
    1152             : template LIBMESH_EXPORT std::string    command_line_next<std::string>     (std::string, std::string);
    1153             : 
    1154             : template LIBMESH_EXPORT void           command_line_vector<unsigned char> (const std::string &, std::vector<unsigned char> &);
    1155             : template LIBMESH_EXPORT void           command_line_vector<unsigned short>(const std::string &, std::vector<unsigned short> &);
    1156             : template LIBMESH_EXPORT void           command_line_vector<unsigned int>  (const std::string &, std::vector<unsigned int> &);
    1157             : template LIBMESH_EXPORT void           command_line_vector<char>          (const std::string &, std::vector<char> &);
    1158             : template LIBMESH_EXPORT void           command_line_vector<short>         (const std::string &, std::vector<short> &);
    1159             : template LIBMESH_EXPORT void           command_line_vector<int>           (const std::string &, std::vector<int> &);
    1160             : template LIBMESH_EXPORT void           command_line_vector<float>         (const std::string &, std::vector<float> &);
    1161             : template LIBMESH_EXPORT void           command_line_vector<double>        (const std::string &, std::vector<double> &);
    1162             : template LIBMESH_EXPORT void           command_line_vector<long double>   (const std::string &, std::vector<long double> &);
    1163             : 
    1164             : #ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
    1165             : template LIBMESH_EXPORT Real           command_line_value<Real>           (const std::string &, Real);
    1166             : template LIBMESH_EXPORT Real           command_line_value<Real>           (const std::vector<std::string> &, Real);
    1167             : template LIBMESH_EXPORT Real           command_line_next<Real>            (std::string, Real);
    1168             : template LIBMESH_EXPORT void           command_line_vector<Real>          (const std::string &, std::vector<Real> &);
    1169             : #endif
    1170             : 
    1171             : } // namespace libMesh

Generated by: LCOV version 1.14