libMesh
Loading...
Searching...
No Matches
libmesh.C
Go to the documentation of this file.
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?
81namespace 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
102namespace {
103
104std::unique_ptr<GetPot> command_line;
105
106std::set<std::string> command_line_name_set;
107
108std::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.
112std::streambuf * out_buf (nullptr);
113std::streambuf * err_buf (nullptr);
114
115std::unique_ptr<libMesh::Threads::task_scheduler_init> task_scheduler;
116#if defined(LIBMESH_HAVE_PETSC)
117bool libmesh_initialized_petsc = false;
118#endif
119#if defined(LIBMESH_HAVE_SLEPC)
120bool libmesh_initialized_slepc = false;
121#endif
122
123} // anonymous namespace
124
125
126
127#ifdef LIBMESH_HAVE_MPI
128void libMesh_MPI_Handler (MPI_Comm *, int *, ...)
129{
130 libmesh_not_implemented();
131}
132#endif
133
134
135namespace libMesh
136{
137
145namespace libMeshPrivateData {
146
150extern bool _is_initialized;
151
156}
157
158
159// ------------------------------------------------------------
160// libMesh data initialization
161#ifdef LIBMESH_HAVE_MPI
162MPI_Comm GLOBAL_COMM_WORLD = MPI_COMM_NULL;
163#else
164int GLOBAL_COMM_WORLD = 0;
165#endif
166
167#ifdef LIBMESH_ENABLE_EXCEPTIONS
168std::terminate_handler LibMeshInit::_old_terminate_handler;
169#endif
170
171OStreamProxy out(std::cout);
172OStreamProxy err(std::cerr);
173
174// Our thread-safe wrappers and the “pre-wrap” sink pointers
175std::unique_ptr<ThreadBufferedSyncbuf> _out_syncd_thread_buffer;
176std::unique_ptr<ThreadBufferedSyncbuf> _err_syncd_thread_buffer;
177std::streambuf * _out_prewrap_buf = nullptr;
178std::streambuf * _err_prewrap_buf = nullptr;
179
180// Install after redirection/drop decisions
182{
183 auto check_stored_buffer = [](const auto * const libmesh_dbg_var(stored_buffer)) {
184 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 };
189
190 // libMesh::out
191 if (auto * ob = libMesh::out.rdbuf(); ob)
192 {
193 check_stored_buffer(_out_prewrap_buf);
194 _out_prewrap_buf = ob;
196 std::make_unique<ThreadBufferedSyncbuf>(*ob, /*flush_on_newline=*/true);
198 }
199
200 // libMesh::err
201 if (auto * eb = libMesh::err.rdbuf(); eb)
202 {
203 check_stored_buffer(_err_prewrap_buf);
204 _err_prewrap_buf = eb;
206 std::make_unique<ThreadBufferedSyncbuf>(*eb, /*flush_on_newline=*/true);
208 }
209}
210
211// Uninstall before restoring/redirection teardown
213{
215 {
216 // flush any thread-local leftovers on this thread
217 libMesh::out << std::flush;
220 _out_prewrap_buf = nullptr;
221 }
223 {
224 libMesh::err << std::flush;
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
236 _err_prewrap_buf = nullptr;
237 }
238}
239
240
245{
246 // Before resetting the stream buffers, let's remove our thread wrappers
247 if (!libMesh::on_command_line ("--disable-thread-safe-output"))
249
250 if (libMesh::on_command_line ("--redirect-stdout") ||
251 libMesh::on_command_line ("--redirect-output"))
252 {
253 // If stdout/stderr were redirected to files, reset them now.
254 libMesh::out.rdbuf (out_buf);
255 libMesh::err.rdbuf (err_buf);
256 }
257
258 // If we built our own output streams, we want to clean them up.
259 if (libMesh::on_command_line ("--separate-libmeshout"))
260 {
261 delete libMesh::out.get();
262 delete libMesh::err.get();
263
264 libMesh::out.reset(std::cout);
265 libMesh::err.reset(std::cerr);
266 }
267}
268
269
271
272PerfLog 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
282const 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
298MPI_Errhandler libmesh_errhandler;
299
302#endif
303int libMesh::libMeshPrivateData::_n_threads = 1; /* Threads::task_scheduler_init::automatic; */
307#if defined(LIBMESH_HAVE_PETSC) // PETSc is the default
309#elif defined(LIBMESH_TRILINOS_HAVE_AZTECOO) // Use Trilinos if PETSc isn't there
311#elif defined(LIBMESH_HAVE_EIGEN) // Use Eigen if neither are there
313#elif defined(LIBMESH_HAVE_LASPACK) // Use LASPACK as a last resort
315#else // No valid linear solver package at compile time
317#endif
318
319
320
321// ------------------------------------------------------------
322// libMesh functions
323
328
329
330
331bool closed()
332{
334}
335
336
337
339{
341
342 // Now that we're done with output we should clean up our stream
343 // buffers; if we fail to uninstall_thread_buffered_sync() when
344 // needed we can end up seeing a segfault in iostreams destructors
346
347 // If we have MPI and it has been initialized, we need to be sure
348 // and call MPI_Abort instead of std::abort, so that the parallel
349 // job can die nicely.
350#if defined(LIBMESH_HAVE_MPI)
351 int mpi_initialized;
352 MPI_Initialized (&mpi_initialized);
353
354 if (mpi_initialized)
355 MPI_Abort(libMesh::GLOBAL_COMM_WORLD, 1);
356#endif
357
358#ifdef LIBMESH_ENABLE_EXCEPTIONS
359 // The system terminate_handler may do useful things, or the user
360 // may have set their own terminate handler that we want to call.
362#endif
363
364 // The last attempt to die if nothing else has killed us
365 std::abort();
366}
367
368
369
370LibMeshInit::LibMeshInit (int argc, const char * const * argv,
371 TIMPI::communicator COMM_WORLD_IN, int n_threads)
372{
373 // should _not_ be initialized already.
375
376 // Build a command-line parser.
377 command_line = std::make_unique<GetPot>(argc, argv);
378
379 // Disable performance logging upon request
380 {
381 if (libMesh::on_command_line ("--disable-perflog"))
383 }
384
385 auto check_empty_command_line_value = [](auto & cl, const std::string & option) {
386 libmesh_error_msg_if(cl.search(option),
387 "Detected option " << option << " with no value. Did you forget '='?");
388 };
389
390 // Build a task scheduler
391 {
392 // Get the requested number of threads, defaults to 1 to avoid MPI and
393 // multithreading competition. If you would like to use MPI and multithreading
394 // at the same time then (n_mpi_processes_per_node)x(n_threads) should be the
395 // number of processing cores per node.
396 std::vector<std::string> n_threads_opt(2);
397 n_threads_opt[0] = "--n_threads";
398 n_threads_opt[1] = "--n-threads";
401
403 {
404 for (auto & option : n_threads_opt)
405 check_empty_command_line_value(*command_line, option);
406
408 }
409
410 // If there's no threading model active, force _n_threads==1
411#if !LIBMESH_USING_THREADS
413 {
415 libmesh_warning("Warning: You requested --n-threads>1 but no threading model is active!\n"
416 << "Forcing --n-threads==1 instead!");
417 }
418#endif
419
420 // Set the number of OpenMP threads to the same as the number of threads libMesh is going to use
421#ifdef LIBMESH_HAVE_OPENMP
422 omp_set_num_threads(libMesh::libMeshPrivateData::_n_threads);
423#endif
424
425 task_scheduler = std::make_unique<Threads::task_scheduler_init>(libMesh::n_threads());
426 }
427
428 // The optimal minimum chunk size for threading is probably fairly
429 // system-dependent.
431 libMesh::command_line_value("--default-grainsize",
433
434 // Construct singletons who may be at risk of the
435 // "static initialization order fiasco"
437
438 // Make sure the construction worked
440
441 const bool using_threads = libMesh::n_threads() > 1;
442 const bool handle_mpi_errors = false; // libMesh does this
443
444#if defined(LIBMESH_HAVE_MPI)
445
446 // Allow the user to bypass MPI initialization
447 if (!libMesh::on_command_line ("--disable-mpi"))
448 {
449 int mpi_thread_request = using_threads;
450 const auto mpi_thread_type = libMesh::command_line_value("--mpi-thread-type", std::string(""));
451 if (mpi_thread_type.empty())
452 {
453 check_empty_command_line_value(*command_line, "--mpi-thread-type");
454#if defined(PETSC_HAVE_STRUMPACK) && defined(PETSC_HAVE_SLATE)
455 // For GPU computations, the solver strumpack uses slate which always requests
456 // MPI_THREAD_MULTIPLE. The solution here is not perfect because the run may never be
457 // using strumpack, but we believe it's better to force the MPI library to use locks
458 // whenever it accesses the message queue, that is, when processing any sends and receive,
459 // than it is to require users to pre-announce/signal what solvers they are using through
460 // --mpi-thread-type
461 mpi_thread_request = 3;
462#endif
463 }
464 else
465 {
466 if (mpi_thread_type == "single")
467 {
468 if (using_threads)
469 libmesh_error_msg("We are using threads, so we require more mpi thread support "
470 "than '--mpi-thread-type=single'");
471 mpi_thread_request = 0;
472 }
473 else if (mpi_thread_type == "funneled")
474 mpi_thread_request = 1;
475 else if (mpi_thread_type == "serialized")
476 mpi_thread_request = 2;
477 else if (mpi_thread_type == "multiple")
478 mpi_thread_request = 3;
479 else
480 libmesh_error_msg(
481 "Unsupported mpi thread type '"
482 << mpi_thread_type
483 << "'. Allowed options are 'single', 'funneled', 'serialized', and 'multiple'");
484 }
485
486 this->_timpi_init =
487 new TIMPI::TIMPIInit(argc, argv, mpi_thread_request,
488 handle_mpi_errors, COMM_WORLD_IN);
489 _comm = new Parallel::Communicator(this->_timpi_init->comm().get());
490
491 const std::string timpi_sync =
492 libMesh::command_line_value("--timpi-sync", std::string("nbx"));
493 _comm->sync_type(timpi_sync);
494
495 libMesh::GLOBAL_COMM_WORLD = COMM_WORLD_IN;
496
497 //MPI_Comm_set_name not supported in at least SGI MPT's MPI implementation
498 //MPI_Comm_set_name (libMesh::COMM_WORLD, "libMesh::COMM_WORLD");
499
501 cast_int<processor_id_type>(this->comm().rank());
503 cast_int<processor_id_type>(this->comm().size());
504
505 // Set up an MPI error handler if requested. This helps us get
506 // into a debugger with a proper stack when an MPI error occurs.
507 if (libMesh::on_command_line ("--handle-mpi-errors"))
508 {
509 timpi_call_mpi
510 (MPI_Comm_create_errhandler(libMesh_MPI_Handler, &libmesh_errhandler));
511 timpi_call_mpi
512 (MPI_Comm_set_errhandler(libMesh::GLOBAL_COMM_WORLD, libmesh_errhandler));
513 timpi_call_mpi
514 (MPI_Comm_set_errhandler(MPI_COMM_WORLD, libmesh_errhandler));
515 }
516 }
517
518 // Could we have gotten bad values from the above calls?
519 libmesh_assert_greater (libMeshPrivateData::_n_processors, 0);
520
521 // The cast_int already tested _processor_id>=0
522 // libmesh_assert_greater_equal (libMeshPrivateData::_processor_id, 0);
523
524 // Let's be sure we properly initialize on every processor at once:
525 libmesh_parallel_only(this->comm());
526
527#else
528 libmesh_ignore(COMM_WORLD_IN);
529 this->_timpi_init =
530 new TIMPI::TIMPIInit(argc, argv, using_threads,
531 handle_mpi_errors);
532 _comm = new Parallel::Communicator(this->_timpi_init->comm().get());
533#endif
534
535#if defined(LIBMESH_HAVE_PETSC)
536
537 // Allow the user to bypass PETSc initialization
538 if (!libMesh::on_command_line ("--disable-petsc")
539
540#if defined(LIBMESH_HAVE_MPI)
541 // If the user bypassed MPI, we'd better be safe and assume that
542 // PETSc was built to require it; otherwise PETSc initialization
543 // dies.
544 && !libMesh::on_command_line ("--disable-mpi")
545#endif
546 )
547 {
548#ifdef LIBMESH_HAVE_MPI
549 PETSC_COMM_WORLD = libMesh::GLOBAL_COMM_WORLD;
550#else
551 // PETSc --with-mpi=0 doesn't like our default "communicator" 0
552 this->_comm->get() = PETSC_COMM_SELF;
553#endif
554
555 // Check whether the calling program has already initialized
556 // PETSc, and avoid duplicate Initialize/Finalize
557 PetscBool petsc_already_initialized;
558 LibmeshPetscCallA(libMesh::GLOBAL_COMM_WORLD, PetscInitialized(&petsc_already_initialized));
559 if (petsc_already_initialized != PETSC_TRUE)
560 libmesh_initialized_petsc = true;
561# if defined(LIBMESH_HAVE_SLEPC)
562
563 // If SLEPc allows us to check whether the calling program
564 // has already initialized it, we do that, and avoid
565 // duplicate Initialize/Finalize.
566 // We assume that SLEPc will handle PETSc appropriately,
567 // which it does in the versions we've checked.
568 if (!SlepcInitializeCalled)
569 {
570 LibmeshPetscCallA(libMesh::GLOBAL_COMM_WORLD, SlepcInitialize (&argc, const_cast<char ***>(&argv), nullptr, nullptr));
571 libmesh_initialized_slepc = true;
572 }
573# else
574 if (libmesh_initialized_petsc)
575 LibmeshPetscCallA(libMesh::GLOBAL_COMM_WORLD, PetscInitialize (&argc, const_cast<char ***>(&argv), nullptr, nullptr));
576# endif
577 // Register the reference implementation of DMlibMesh
578 LibmeshPetscCallA(libMesh::GLOBAL_COMM_WORLD, DMRegister(DMLIBMESH, DMCreate_libMesh));
579 }
580#endif
581
582#ifdef LIBMESH_HAVE_NETGEN
583 nglib::Ng_Init();
584#endif
585
586#if defined(LIBMESH_HAVE_MPI) && defined(LIBMESH_HAVE_VTK)
587 // Do MPI initialization for VTK.
588 _vtk_mpi_controller = vtkMPIController::New();
589 _vtk_mpi_controller->Initialize(&argc, const_cast<char ***>(&argv), /*initialized_externally=*/1);
590 _vtk_mpi_controller->SetGlobalController(_vtk_mpi_controller);
591#endif
592
593 // Re-parse the command-line arguments. Note that PETSc and MPI
594 // initialization above may have removed command line arguments
595 // that are not relevant to this application in the above calls.
596 // We don't want a false-positive by detecting those arguments.
597 //
598 // Note: this seems overly paranoid/like it should be unnecessary,
599 // plus we were doing it wrong for many years and not clearing the
600 // existing GetPot object before re-parsing the command line, so all
601 // the command line arguments appeared twice in the GetPot object...
602 command_line = std::make_unique<GetPot>(argc, argv);
603
604 // Not syncing with stdio is an optimization when simultaneous
605 // C and C++ style access to output streams is not required.
606 // The amount of benefit which occurs is probably implementation
607 // defined, and may be nothing. On the other hand, I have seen
608 // some IO tests where IO performance improves by a factor of two.
609 // However, not syncing the streams means thread safety is no longer
610 // guaranteed and we have indeed seen thread sanitizer warnings
611 // during concurrent writes to std::cout when toggling this boolean
612 // to true. We default to preferring safety and correctness instead
613 // of performance
614 if (libMesh::on_command_line ("--dont-sync-with-stdio"))
615 std::ios::sync_with_stdio(false);
616
617 // Honor the --separate-libmeshout command-line option.
618 // When this is specified, the library uses an independent ostream
619 // for libMesh::out/libMesh::err messages, and
620 // std::cout and std::cerr are untouched by any other options
621 if (libMesh::on_command_line ("--separate-libmeshout"))
622 {
623 // Redirect. We'll share streambufs with cout/cerr for now, but
624 // presumably anyone using this option will want to replace the
625 // bufs later.
626 std::ostream * newout = new std::ostream(std::cout.rdbuf());
627 libMesh::out = *newout;
628 std::ostream * newerr = new std::ostream(std::cerr.rdbuf());
629 libMesh::err = *newerr;
630 }
631
632 // Process command line arguments for redirecting stdout/stderr.
633 bool
634 cmdline_has_redirect_stdout = libMesh::on_command_line ("--redirect-stdout"),
635 cmdline_has_redirect_output = libMesh::on_command_line ("--redirect-output");
636
637 // The --redirect-stdout command-line option has been deprecated in
638 // favor of "--redirect-output basename".
639 if (cmdline_has_redirect_stdout)
640 libmesh_warning("The --redirect-stdout command line option has been deprecated. "
641 "Use '--redirect-output basename' instead.");
642
643 // Honor the "--redirect-stdout" and "--redirect-output basename"
644 // command-line options. When one of these is specified, each
645 // processor sends libMesh::out/libMesh::err messages to
646 // stdout.processor.#### (default) or basename.processor.####.
647 if (cmdline_has_redirect_stdout || cmdline_has_redirect_output)
648 {
649 std::string basename = "stdout";
650
651 // Look for following argument if using new API
652 if (cmdline_has_redirect_output)
653 {
654 // Set the cursor to the correct location in the list of command line arguments.
655 command_line->search(1, "--redirect-output");
656
657 // Get the next option on the command line as a string.
658 std::string next_string = "";
659 next_string = command_line->next(next_string);
660
661 // If the next string starts with a dash, we assume it's
662 // another flag and not a file basename requested by the
663 // user.
664 if (next_string.size() > 0 && next_string.find_first_of("-") != 0)
665 basename = next_string;
666 }
667
668 std::ostringstream filename;
669 filename << basename << ".processor." << libMesh::global_processor_id();
670 _ofstream = std::make_unique<std::ofstream>(filename.str().c_str());
671
672 // Redirect, saving the original streambufs!
673 out_buf = libMesh::out.rdbuf (_ofstream->rdbuf());
674 err_buf = libMesh::err.rdbuf (_ofstream->rdbuf());
675 }
676
677 // redirect libMesh::out to nothing on all
678 // other processors unless explicitly told
679 // not to via the --keep-cout command-line argument.
680 if (!libMesh::on_command_line ("--keep-cout"))
682 libMesh::out.rdbuf (nullptr);
683
684 // Similarly, the user can request to drop cerr on all non-0 ranks.
685 // By default, errors are printed on all ranks, but this can lead to
686 // interleaved/unpredictable outputs when doing parallel regression
687 // testing, which this option is designed to support.
688 if (libMesh::on_command_line ("--drop-cerr"))
690 libMesh::err.rdbuf (nullptr);
691
692 // Now that we've finished setting our stream buffers, let's wrap them (if they're non-null) in our thread-safe wrapper
693 if (!libMesh::on_command_line ("--disable-thread-safe-output"))
695
696 // Check command line to override printing
697 // of reference count information.
698 if (libMesh::on_command_line("--disable-refcount-printing"))
700
701#ifdef LIBMESH_ENABLE_EXCEPTIONS
702 // Set our terminate handler to write stack traces in the event of a
703 // crash
705#endif
706
707
708 if (libMesh::on_command_line("--enable-fpe"))
709 libMesh::enableFPE(true);
710
711 if (libMesh::on_command_line("--enable-segv"))
713
714 if (libMesh::on_command_line("--enable-sigint"))
716
717#if defined(LIBMESH_HAVE_HDF5) && !defined(_MSC_VER)
718 // We may be running with ExodusII configured not to use HDF5 (in
719 // which case user code which wants to lock files has to do flock()
720 // itself) or with ExodusII configured to use HDF5 (which will
721 // helpfully try to get an exclusive flock() itself, and then scream
722 // and die if user code has already locked the file. To get
723 // consistent behavior, we need to disable file locking. The only
724 // reliable way I can see to do this is via an HDF5 environment
725 // variable.
726 //
727 // If the user set this environment variable then we'll trust that
728 // they know what they're doing. If not then we'll set FALSE,
729 // because that's a better default for us than the unset default.
730 setenv("HDF5_USE_FILE_LOCKING", "FALSE", /*overwrite=false*/0);
731#endif // LIBMESH_HAVE_HDF5
732
733 // The library is now ready for use
735
736
737 // Make sure these work. Library methods
738 // depend on these being implemented properly,
739 // so this is a good time to test them!
742}
743
744
745
747{
748 // Every processor had better be ready to exit at the same time.
749 // Even if we're not doing parallel_only debugging, we don't want
750 // one processor to try to exit until all others are done working.
751
752 // We could be destructing here because we're unwinding the stack
753 // due to a thrown exception, though. It's possible that an
754 // application is catching exceptions outside of the LibMeshInit
755 // scope, or that we're using a C++ compiler that does unwinding
756 // for uncaught exceptions (the standard says whether to go straight
757 // to terminate() or unwind first is "implementation-defined"). If
758 // *that* is the case then we can't safely communicate with other
759 // processors that might not all be unwinding too.
760#ifdef LIBMESH_ENABLE_EXCEPTIONS
761 if (!std::uncaught_exceptions())
762#endif
763 this->comm().barrier();
764
765 // We can't delete, finalize, etc. more than once without
766 // reinitializing in between
767 libmesh_exceptionless_assert(!libMesh::closed());
768
769 // Delete reference counted singleton(s)
771
772 // Clear the thread task manager we started
773 task_scheduler.reset();
774
775 // If we have a memory leak, we want the details printed.
778
779 // Ask the \p ReferenceCounter to print its reference count
780 // information, if printing is enabled. This allows us to find
781 // memory leaks.
782 //
783 // If we don't have any leaks, we'll print to cout, only if we've
784 // been told to. If we do, we'll print to cerr, to make sure the
785 // user doesn't miss a leak that's only on a processor other than 0.
788
789 // Scream specifically if we detect a memory leak
791 {
793
794 libMesh::err << "Memory leak detected!"
795 << std::endl;
796
797#if !defined(LIBMESH_ENABLE_REFERENCE_COUNTING) || defined(NDEBUG)
798
799 libMesh::err << "Compile in DEBUG mode with --enable-reference-counting"
800 << std::endl
801 << "for more information"
802 << std::endl;
803#endif
804 }
805
806 // print the perflog to individual processor's file.
808
809 // Now clear the logging object, we don't want it to print
810 // a second time during the PerfLog destructor.
812
813 // Reconnect the output streams
814 // (don't do this, or we will get messages from objects
815 // that go out of scope after the following return)
816 //std::cout.rdbuf(std::cerr.rdbuf());
817
818
819 // Set the initialized() flag to false
821
823
824#ifdef LIBMESH_ENABLE_EXCEPTIONS
825 // Reset the old terminate handler; maybe the user code wants to
826 // keep doing C++ stuff after closing libMesh stuff.
827 std::set_terminate(_old_terminate_handler);
828#endif
829
830#ifdef LIBMESH_HAVE_NETGEN
831 nglib::Ng_Exit();
832#endif
833
834 if (libMesh::on_command_line("--enable-fpe"))
835 libMesh::enableFPE(false);
836
837#if defined(LIBMESH_HAVE_PETSC)
838 // Let PETSc know about all the command line objects that we
839 // consumed without asking them, so we don't get unused option
840 // warnings about those.
841 std::vector<std::string> cli_names = command_line_names();
842 for (const auto & name : cli_names)
843 if (!name.empty() && name[0] == '-')
844 {
845 // Newer PETSc can give me a double-free I'm having trouble
846 // replicating; let's protect against trying to clear
847 // already-used values
848 PetscBool used = PETSC_FALSE;
849 auto ierr = PetscOptionsUsed(NULL, name.c_str(), &used);
850 CHKERRABORT(libMesh::GLOBAL_COMM_WORLD, ierr);
851 if (used == PETSC_FALSE)
852 {
853 ierr = PetscOptionsClearValue(NULL, name.c_str());
854 CHKERRABORT(libMesh::GLOBAL_COMM_WORLD, ierr);
855 }
856 }
857
858 // Allow the user to bypass PETSc finalization
859 if (!libMesh::on_command_line ("--disable-petsc")
860#if defined(LIBMESH_HAVE_MPI)
861 && !libMesh::on_command_line ("--disable-mpi")
862#endif
863 )
864 {
865 PetscErrorCode ierr = LIBMESH_PETSC_SUCCESS;
866# if defined(LIBMESH_HAVE_SLEPC)
867 if (libmesh_initialized_slepc)
868 ierr = SlepcFinalize();
869# else
870 if (libmesh_initialized_petsc)
871 ierr = PetscFinalize();
872# endif
873 CHKERRABORT(libMesh::GLOBAL_COMM_WORLD, ierr);
874 }
875#endif
876
877#if defined(LIBMESH_HAVE_MPI) && defined(LIBMESH_HAVE_VTK)
878 _vtk_mpi_controller->Finalize(/*finalized_externally=*/1);
879 _vtk_mpi_controller->Delete();
880#endif
881
882 delete this->_comm;
883
884#if defined(LIBMESH_HAVE_MPI)
885 // Allow the user to bypass MPI finalization
886 if (!libMesh::on_command_line ("--disable-mpi"))
887 {
888 delete this->_timpi_init;
889 }
890#else
891 delete this->_timpi_init;
892#endif
893}
894
895
900
901
902
903void add_command_line_name(const std::string & name)
904{
905 // Users had better not be asking about an empty string
906 libmesh_assert(!name.empty());
907
908 static std::mutex command_line_names_mutex;
909 std::scoped_lock lock(command_line_names_mutex);
910
911 command_line_name_set.insert(name);
912}
913
914
915
916void add_command_line_names(const GetPot & getpot)
917{
918 for (auto & getter : {&GetPot::get_requested_arguments,
919 &GetPot::get_requested_variables,
920 &GetPot::get_requested_sections})
921 for (const std::string & name : (getpot.*getter)())
923}
924
925
926std::vector<std::string> command_line_names()
927{
928 return std::vector<std::string>(command_line_name_set.begin(),
929 command_line_name_set.end());
930}
931
932
933
934bool on_command_line (std::string arg)
935{
936 // Make sure the command line parser is ready for use. If it's not,
937 // then we'll have to treat the command line as empty, for maximum
938 // compatibility with programs that don't use LibMeshInit but
939 // indirectly (e.g. via error handling code) query the command line.
940 if (!command_line.get())
941 return false;
942
943 // Keep track of runtime queries, for later
945
946 bool found_it = command_line->search(arg);
947
948 if (!found_it)
949 {
950 // Try with all dashes instead of underscores
951 std::replace(arg.begin(), arg.end(), '_', '-');
952 found_it = command_line->search(arg);
953 }
954
955 if (!found_it)
956 {
957 // OK, try with all underscores instead of dashes
958 auto name_begin = arg.begin();
959 while (*name_begin == '-')
960 ++name_begin;
961 std::replace(name_begin, arg.end(), '-', '_');
962 found_it = command_line->search(arg);
963 }
964
965 return found_it;
966}
967
968
969
970template <typename T>
971T command_line_value (const std::string & name, T value)
972{
973 // Make sure the command line parser is ready for use
974 libmesh_assert(command_line.get());
975
976 // only if the variable exists in the file
977 if (command_line->have_variable(name))
978 {
979 value = (*command_line)(name, value);
980
981 // Keep track of runtime queries, for later. GetPot splits
982 // foo=bar into a separate name=value, so we can query for the
983 // name, but as far as PETSc is concerned that's one CLI
984 // argument. We'll store it that way.
985 const std::string stringvalue =
986 (*command_line)(name, std::string());
987 add_command_line_name(name+"="+stringvalue);
988 }
989
990 return value;
991}
992
993template <typename T>
994T command_line_value (const std::vector<std::string> & names, T value)
995{
996 // Make sure the command line parser is ready for use
997 libmesh_assert(command_line.get());
998
999 // Keep track of runtime queries, for later
1000 for (const auto & entry : names)
1001 {
1002 // Keep track of runtime queries, for later. GetPot splits
1003 // foo=bar into a separate name=value, so we can query for the
1004 // name, but as far as PETSc is concerned that's one CLI
1005 // argument. We'll store it that way.
1006 const std::string stringvalue =
1007 (*command_line)(entry, std::string());
1008 add_command_line_name(entry+"="+stringvalue);
1009 }
1010
1011 // Check for multiple options (return the first that matches)
1012 for (const auto & entry : names)
1013 if (command_line->have_variable(entry))
1014 {
1015 value = (*command_line)(entry, value);
1016 break;
1017 }
1018
1019 return value;
1020}
1021
1022
1023
1024template <typename T>
1025T command_line_next (std::string name, T value)
1026{
1027 // Make sure the command line parser is ready for use
1028 libmesh_assert(command_line.get());
1029
1030 // Keep track of runtime queries, for later
1032
1033 // on_command_line also puts the command_line cursor in the spot we
1034 // need
1035 if (on_command_line(name))
1036 return command_line->next(value);
1037
1038 return value;
1039}
1040
1041
1042
1043template <typename T>
1044void command_line_vector (const std::string & name, std::vector<T> & vec)
1045{
1046 // Make sure the command line parser is ready for use
1047 libmesh_assert(command_line.get());
1048
1049 // Keep track of runtime queries, for later
1051
1052 // only if the variable exists on the command line
1053 if (command_line->have_variable(name))
1054 {
1055 unsigned size = command_line->vector_variable_size(name);
1056 vec.resize(size);
1057
1058 for (unsigned i=0; i<size; ++i)
1059 vec[i] = (*command_line)(name, vec[i], i);
1060 }
1061}
1062
1063
1065{
1067
1068 static bool called = false;
1069
1070 // Check the command line. Since the command line is
1071 // unchanging it is sufficient to do this only once.
1072 if (!called)
1073 {
1074 called = true;
1075
1076#ifdef LIBMESH_HAVE_PETSC
1077 if (libMesh::on_command_line ("--use-petsc"))
1079#endif
1080
1081#ifdef LIBMESH_TRILINOS_HAVE_AZTECOO
1082 if (libMesh::on_command_line ("--use-trilinos") ||
1083 libMesh::on_command_line ("--disable-petsc"))
1085#endif
1086
1087#ifdef LIBMESH_HAVE_EIGEN
1088 if (libMesh::on_command_line ("--use-eigen" ) ||
1089#if defined(LIBMESH_HAVE_MPI)
1090 // If the user bypassed MPI, we disable PETSc and Trilinos
1091 // too
1092 libMesh::on_command_line ("--disable-mpi") ||
1093#endif
1094 libMesh::on_command_line ("--disable-petsc"))
1096#endif
1097
1098#ifdef LIBMESH_HAVE_LASPACK
1099 if (libMesh::on_command_line ("--use-laspack" ) ||
1100#if defined(LIBMESH_HAVE_MPI)
1101 // If the user bypassed MPI, we disable PETSc and Trilinos
1102 // too
1103 libMesh::on_command_line ("--disable-mpi") ||
1104#endif
1105 libMesh::on_command_line ("--disable-petsc"))
1107#endif
1108
1109 if (libMesh::on_command_line ("--disable-laspack") &&
1110 libMesh::on_command_line ("--disable-trilinos") &&
1111 libMesh::on_command_line ("--disable-eigen") &&
1112 (
1113#if defined(LIBMESH_HAVE_MPI)
1114 // If the user bypassed MPI, we disable PETSc too
1115 libMesh::on_command_line ("--disable-mpi") ||
1116#endif
1117 libMesh::on_command_line ("--disable-petsc")))
1119 }
1120
1121
1123}
1124
1125
1126
1127//-------------------------------------------------------------------------------
1128template LIBMESH_EXPORT unsigned char command_line_value<unsigned char> (const std::string &, unsigned char);
1129template LIBMESH_EXPORT unsigned short command_line_value<unsigned short> (const std::string &, unsigned short);
1130template LIBMESH_EXPORT unsigned int command_line_value<unsigned int> (const std::string &, unsigned int);
1131template LIBMESH_EXPORT char command_line_value<char> (const std::string &, char);
1132template LIBMESH_EXPORT short command_line_value<short> (const std::string &, short);
1133template LIBMESH_EXPORT int command_line_value<int> (const std::string &, int);
1134template LIBMESH_EXPORT float command_line_value<float> (const std::string &, float);
1135template LIBMESH_EXPORT double command_line_value<double> (const std::string &, double);
1136template LIBMESH_EXPORT long double command_line_value<long double> (const std::string &, long double);
1137template LIBMESH_EXPORT std::string command_line_value<std::string> (const std::string &, std::string);
1138
1139template LIBMESH_EXPORT unsigned char command_line_value<unsigned char> (const std::vector<std::string> &, unsigned char);
1140template LIBMESH_EXPORT unsigned short command_line_value<unsigned short> (const std::vector<std::string> &, unsigned short);
1141template LIBMESH_EXPORT unsigned int command_line_value<unsigned int> (const std::vector<std::string> &, unsigned int);
1142template LIBMESH_EXPORT char command_line_value<char> (const std::vector<std::string> &, char);
1143template LIBMESH_EXPORT short command_line_value<short> (const std::vector<std::string> &, short);
1144template LIBMESH_EXPORT int command_line_value<int> (const std::vector<std::string> &, int);
1145template LIBMESH_EXPORT float command_line_value<float> (const std::vector<std::string> &, float);
1146template LIBMESH_EXPORT double command_line_value<double> (const std::vector<std::string> &, double);
1147template LIBMESH_EXPORT long double command_line_value<long double> (const std::vector<std::string> &, long double);
1148template LIBMESH_EXPORT std::string command_line_value<std::string> (const std::vector<std::string> &, std::string);
1149
1150template LIBMESH_EXPORT unsigned char command_line_next<unsigned char> (std::string, unsigned char);
1151template LIBMESH_EXPORT unsigned short command_line_next<unsigned short> (std::string, unsigned short);
1152template LIBMESH_EXPORT unsigned int command_line_next<unsigned int> (std::string, unsigned int);
1153template LIBMESH_EXPORT char command_line_next<char> (std::string, char);
1154template LIBMESH_EXPORT short command_line_next<short> (std::string, short);
1155template LIBMESH_EXPORT int command_line_next<int> (std::string, int);
1156template LIBMESH_EXPORT float command_line_next<float> (std::string, float);
1157template LIBMESH_EXPORT double command_line_next<double> (std::string, double);
1158template LIBMESH_EXPORT long double command_line_next<long double> (std::string, long double);
1159template LIBMESH_EXPORT std::string command_line_next<std::string> (std::string, std::string);
1160
1161template LIBMESH_EXPORT void command_line_vector<unsigned char> (const std::string &, std::vector<unsigned char> &);
1162template LIBMESH_EXPORT void command_line_vector<unsigned short>(const std::string &, std::vector<unsigned short> &);
1163template LIBMESH_EXPORT void command_line_vector<unsigned int> (const std::string &, std::vector<unsigned int> &);
1164template LIBMESH_EXPORT void command_line_vector<char> (const std::string &, std::vector<char> &);
1165template LIBMESH_EXPORT void command_line_vector<short> (const std::string &, std::vector<short> &);
1166template LIBMESH_EXPORT void command_line_vector<int> (const std::string &, std::vector<int> &);
1167template LIBMESH_EXPORT void command_line_vector<float> (const std::string &, std::vector<float> &);
1168template LIBMESH_EXPORT void command_line_vector<double> (const std::string &, std::vector<double> &);
1169template LIBMESH_EXPORT void command_line_vector<long double> (const std::string &, std::vector<long double> &);
1170
1171#ifdef LIBMESH_DEFAULT_QUADRUPLE_PRECISION
1172template LIBMESH_EXPORT Real command_line_value<Real> (const std::string &, Real);
1173template LIBMESH_EXPORT Real command_line_value<Real> (const std::vector<std::string> &, Real);
1174template LIBMESH_EXPORT Real command_line_next<Real> (std::string, Real);
1175template LIBMESH_EXPORT void command_line_vector<Real> (const std::string &, std::vector<Real> &);
1176#endif
1177
1178} // namespace libMesh
void sync_type(const SyncType st)
communicator & get()
const Communicator & comm() const
This class is intended to be reseatable like a pointer-to-ostream for flexibility,...
streambufT * rdbuf() const
Get the associated stream buffer.
streamT * get()
Rather than implement every ostream/ios/ios_base function, we'll be lazy and make esoteric uses go th...
void reset(streamT &target)
Reset the proxy to point to a different target.
Parallel::Communicator * _comm
Definition libmesh.h:143
LibMeshInit(int argc, const char *const *argv, MPI_Comm COMM_WORLD_IN=MPI_COMM_WORLD, int n_threads=-1)
Initialize the library for use, with the command line options provided.
static std::terminate_handler _old_terminate_handler
Definition libmesh.h:153
const Parallel::Communicator & comm() const
Returns a Communicator created from the TIMPIInit object we hold, which will be a compatibility shim ...
Definition libmesh.h:129
vtkMPIController * _vtk_mpi_controller
Definition libmesh.h:149
TIMPI::TIMPIInit * _timpi_init
Definition libmesh.h:136
static PerfLog & perf_log()
Definition libmesh.C:896
virtual ~LibMeshInit()
Destructor.
Definition libmesh.C:746
friend void libmesh_terminate_handler()
A terminate handler.
The PerfLog class allows monitoring of specific events.
Definition perf_log.h:154
void print_log() const
Print the log.
Definition perf_log.C:714
void disable_logging()
Disables performance logging for an active object.
Definition perf_log.h:184
void clear()
Clears all the internal data and restores the data structures to a pristine state.
Definition perf_log.C:78
static void print_info(std::ostream &out_stream=libMesh::out)
Prints the reference information, by default to libMesh::out.
static unsigned int n_objects()
Prints the number of outstanding (created, but not yet destroyed) objects.
static void disable_print_counter_info()
static void enable_print_counter_info()
Methods to enable/disable the reference counter output from print_info().
static void cleanup()
Cleanup function.
static void setup()
Setup function.
void libMesh_MPI_Handler(MPI_Comm *, int *,...)
Definition libmesh.C:128
DIE A HORRIBLE DEATH HERE typedef MPI_Comm communicator
processor_id_type _n_processors
Total number of processors used.
Definition libmesh.C:300
unsigned int _default_grainsize
Minimum number of elements/nodes/indices per thread above which we can split work onto more threads.
Definition libmesh.C:304
processor_id_type _processor_id
The local processor id.
Definition libmesh.C:301
SolverPackage _solver_package
The default solver package to use.
Definition libmesh.C:306
bool _is_initialized
Flag that tells if init() has been called.
Definition libmesh.C:305
int _n_threads
Total number of threads possible.
Definition libmesh.C:303
The libMesh namespace provides an interface to certain functionality in the library.
template LIBMESH_EXPORT void command_line_vector< int >(const std::string &, std::vector< int > &)
OStreamProxy err
template LIBMESH_EXPORT char command_line_value< char >(const std::string &, char)
template LIBMESH_EXPORT void command_line_vector< unsigned int >(const std::string &, std::vector< unsigned int > &)
template LIBMESH_EXPORT void command_line_vector< unsigned short >(const std::string &, std::vector< unsigned short > &)
template LIBMESH_EXPORT int command_line_value< int >(const std::string &, int)
template LIBMESH_EXPORT void command_line_vector< short >(const std::string &, std::vector< short > &)
processor_id_type global_processor_id()
void enableSIGINT(bool on)
Toggle libMesh handling of SIGINT (Ctrl+C) interrupts.
bool warned_about_auto_ptr
template LIBMESH_EXPORT double command_line_value< double >(const std::string &, double)
template LIBMESH_EXPORT short command_line_next< short >(std::string, short)
std::streambuf * _out_prewrap_buf
Definition libmesh.C:177
template LIBMESH_EXPORT unsigned int command_line_next< unsigned int >(std::string, unsigned int)
template LIBMESH_EXPORT std::string command_line_next< std::string >(std::string, std::string)
bool closed()
Checks that the library has been closed.
Definition libmesh.C:331
void command_line_vector(const std::string &, std::vector< T > &)
Definition libmesh.C:1044
void libmesh_ignore(const Args &...)
SolverPackage default_solver_package()
Definition libmesh.C:1064
template LIBMESH_EXPORT float command_line_next< float >(std::string, float)
MPI_Errhandler libmesh_errhandler
Definition libmesh.C:298
libmesh_assert(ctx)
void uninstall_thread_buffered_sync()
Definition libmesh.C:212
OStreamProxy out
template LIBMESH_EXPORT short command_line_value< short >(const std::string &, short)
template LIBMESH_EXPORT long double command_line_value< long double >(const std::string &, long double)
void add_command_line_names(const GetPot &getpot)
Merge a GetPot object's requested names into the set of queried command-line names.
Definition libmesh.C:916
PerfLog perflog
A PerfLog object to log performance.
template LIBMESH_EXPORT void command_line_vector< unsigned char >(const std::string &, std::vector< unsigned char > &)
template LIBMESH_EXPORT float command_line_value< float >(const std::string &, float)
T command_line_next(std::string name, T default_value)
Use GetPot's search()/next() functions to get following arguments from the command line.
Definition libmesh.C:1025
SolverPackage
Defines an enum for various linear solver packages.
template LIBMESH_EXPORT void command_line_vector< double >(const std::string &, std::vector< double > &)
void enableFPE(bool on)
Toggle hardware trap floating point exceptions.
void add_command_line_name(const std::string &name)
Add a name to the set of queried command-line names.
Definition libmesh.C:903
std::streambuf * _err_prewrap_buf
Definition libmesh.C:178
template LIBMESH_EXPORT long double command_line_next< long double >(std::string, long double)
const RemoteElem * remote_elem
Definition remote_elem.C:57
template LIBMESH_EXPORT Real command_line_next< Real >(std::string, Real)
T command_line_value(const std::string &, T)
Definition libmesh.C:971
const Number imaginary
The imaginary unit, .
template LIBMESH_EXPORT void command_line_vector< long double >(const std::string &, std::vector< long double > &)
void install_thread_buffered_sync()
Definition libmesh.C:181
bool initialized()
Checks that library initialization has been done.
Definition libmesh.C:324
template LIBMESH_EXPORT std::string command_line_value< std::string >(const std::string &, std::string)
std::vector< std::string > command_line_names()
Definition libmesh.C:926
template LIBMESH_EXPORT char command_line_next< char >(std::string, char)
std::unique_ptr< ThreadBufferedSyncbuf > _err_syncd_thread_buffer
Definition libmesh.C:176
void libmesh_abort()
Abort as soon as possible.
Definition libmesh.C:338
template LIBMESH_EXPORT unsigned char command_line_next< unsigned char >(std::string, unsigned char)
template LIBMESH_EXPORT Real command_line_value< Real >(const std::string &, Real)
template LIBMESH_EXPORT void command_line_vector< Real >(const std::string &, std::vector< Real > &)
template LIBMESH_EXPORT unsigned int command_line_value< unsigned int >(const std::string &, unsigned int)
MPI_Comm GLOBAL_COMM_WORLD
MPI Communicator used to initialize libMesh.
template LIBMESH_EXPORT int command_line_next< int >(std::string, int)
bool on_command_line(std::string arg)
Definition libmesh.C:934
template LIBMESH_EXPORT void command_line_vector< char >(const std::string &, std::vector< char > &)
template LIBMESH_EXPORT double command_line_next< double >(std::string, double)
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
uint8_t processor_id_type
Definition id_types.h:104
std::unique_ptr< ThreadBufferedSyncbuf > _out_syncd_thread_buffer
Definition libmesh.C:175
template LIBMESH_EXPORT unsigned short command_line_value< unsigned short >(const std::string &, unsigned short)
void enableSEGV(bool on)
Toggle libMesh reporting of segmentation faults.
template LIBMESH_EXPORT unsigned short command_line_next< unsigned short >(std::string, unsigned short)
template LIBMESH_EXPORT void command_line_vector< float >(const std::string &, std::vector< float > &)
void cleanup_stream_buffers()
Helper to do cleanup from both destructor and terminate.
Definition libmesh.C:244
unsigned int n_threads()
template LIBMESH_EXPORT unsigned char command_line_value< unsigned char >(const std::string &, unsigned char)
EXTERN_C_BEGIN PETSC_EXTERN PetscErrorCode DMCreate_libMesh(DM)
static const bool value
Definition xdr_io.C:55