Teuchos - Trilinos Tools Package Version of the Day
Loading...
Searching...
No Matches
Trilinos_Details_LinearSolverFactory.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Teuchos: Common Tools Package
4//
5// Copyright 2004 NTESS and the Teuchos contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef TRILINOS_DETAILS_LINEARSOLVER_FACTORY_HPP
11#define TRILINOS_DETAILS_LINEARSOLVER_FACTORY_HPP
12
49
50#include "Teuchos_RCP.hpp" // includes Teuchos_ConfigDefs.hpp
51#include "TeuchosRemainder_config.h"
52#include <map>
53#ifdef HAVE_TEUCHOSCORE_CXX11
54# include <memory> // std::shared_ptr
55#endif // HAVE_TEUCHOSCORE_CXX11
56#include <stdexcept>
57#include <sstream>
58#include <string>
59
60
61// Attempted fix for Bug 6392: declare all packages'
62// LinearSolverFactory registration functions here, with weak linkage.
63// This works whether or not the packages in question are actually
64// enabled. In createPackageNames() below, actually call these
65// functions if they are linked in. We only need to do this if
66// building with static libraries; if building with dynamic libraries,
67// each package takes care of this on its own.
68//
69// I wrote "attempted" because it DOESN'T WORK. It doesn't matter
70// whether these or their uses are in the .cpp or .hpp file, or
71// whether they are in a regular function that gets compiled or a
72// templated function that might not.
73#if ! defined(HAVE_TEUCHOS_DYNAMIC_LIBS) && defined(HAVE_TEUCHOS_CXX_ATTRIBUTE_WEAK)
74// FIXME (mfh 21 Aug 2015) NONE of the commented-out things work.
75
76// namespace Amesos2 {
77// namespace Details {
78// extern void __attribute__((weak)) registerLinearSolverFactory ();
79// } // namespace Details
80// } // namespace Amesos2
81
82// namespace Ifpack2 {
83// namespace Details {
84// // extern void __attribute__((weak)) registerLinearSolverFactory ();
85// // void __attribute__((weak)) registerLinearSolverFactory ();
86// // evoid __attribute__((weak)) registerLinearSolverFactory ();
87// } // namespace Details
88// } // namespace Ifpack2
89#endif // ! defined(HAVE_TEUCHOS_DYNAMIC_LIBS) && defined(HAVE_TEUCHOS_CXX_ATTRIBUTE_WEAK)
90
91
94namespace Trilinos {
95
102namespace Details {
103
104template<class MV, class OP, class NormType>
105class LinearSolver; // forward declaration
106
133template<class MV, class OP, class NormType>
135getLinearSolver (const std::string& packageName, const std::string& solverName);
136
202template<class MV, class OP, class NormType>
204public:
205 virtual ~LinearSolverFactory() {}
214 getLinearSolver (const std::string& solverName) = 0;
215};
216
294template<class MV, class OP, class NormType>
295void
296registerLinearSolverFactory (const std::string& packageName,
297#ifdef HAVE_TEUCHOSCORE_CXX11
298 const std::shared_ptr<LinearSolverFactory<MV, OP, NormType> >& factory);
299#else
301#endif // HAVE_TEUCHOSCORE_CXX11
302
303//
304// EVERYTHING BELOW THIS LINE IS AN IMPLEMENTATION DETAIL
305//
306
312namespace Impl {
313
324bool rememberRegisteredSomeLinearSolverFactory (const std::string& packageName);
325
331bool registeredSomeLinearSolverFactory (const std::string& packageName);
332
340
367template<class MV, class OP, class NormType>
369public:
375#ifdef HAVE_TEUCHOSCORE_CXX11
376 typedef std::shared_ptr<LinearSolverFactory<MV, OP, NormType> > factory_pointer_type;
377#else
379#endif // HAVE_TEUCHOSCORE_CXX11
380
388 typedef std::map<std::string, factory_pointer_type> map_type;
389
390public:
404 getFactory (const std::string& packageName)
405 {
406 createFactories ();
407 typedef typename map_type::iterator iter_type;
408 iter_type it = factories_->find (packageName);
409 if (it == factories_->end ()) { // didn't find package name
410 return factory_pointer_type (); // null pointer
411 } else { // found package name
412 return it->second;
413 }
414 }
415
430 static void
431 registerLinearSolverFactory (const std::string& packageName,
432 const factory_pointer_type& factory)
433 {
435 (factory.get () == NULL, std::invalid_argument, "Trilinos::Details::"
436 "LinearSolverFactoryRepository::registerLinearSolverFactory: Input "
437 "'factory' is NULL!");
438 createFactories ();
439 if (factories_->find (packageName) == factories_->end ()) {
440 factories_->insert (std::make_pair (packageName, factory));
441 }
442 }
443
444private:
455 static map_type* factories_;
456
460 static void createFactories () {
461 if (factories_ == NULL) {
462 factories_ = new map_type ();
463 // It _is_ possible for atexit() to fail (e.g., because it ran
464 // out of memory for storing callbacks). We could throw an
465 // exception here in that case, but I think it's better just
466 // to let the minor memory leak happen.
467 (void) atexit (freeFactories);
468 }
470 (factories_ == NULL, std::logic_error, "Trilinos::Details::"
471 "LinearSolverFactoryRepository::createFactories: "
472 "Should never get here! factories_ is NULL.");
473 }
474
483 static void freeFactories () {
484 if (factories_ != NULL) {
485 delete factories_;
486 factories_ = NULL;
487 }
488 }
489};
490
491// This is _not_ an explicit instantiation. C++ wants it, because
492// LinearSolverFactoryRepository is a templated class with a static
493// (class) member.
494template<class MV, class OP, class NormType>
496LinearSolverFactoryRepository<MV, OP, NormType>::factories_ = NULL;
497
498} // namespace Impl
499
500//
501// Definitions of nonmember functions
502//
503
504template<class MV, class OP, class NormType>
505void
506registerLinearSolverFactory (const std::string& packageName,
507#ifdef HAVE_TEUCHOSCORE_CXX11
508 const std::shared_ptr<LinearSolverFactory<MV, OP, NormType> >& factory)
509#else
511#endif // HAVE_TEUCHOSCORE_CXX11
512{
515}
516
517template<class MV, class OP, class NormType>
519getLinearSolver (const std::string& packageName, const std::string& solverName)
520{
521 using Teuchos::RCP;
524 typedef typename repo_type::factory_pointer_type factory_pointer_type;
525 typedef LinearSolver<MV, OP, NormType> solver_type;
526 const char prefix[] = "Trilinos::Details::getLinearSolver: ";
527
528 // FIXME (mfh 21 Aug 2015) Attempted fix for Bug 6392: DOES NOT WORK.
529 // (Compiles just fine, but test doesn't pass.)
530#if ! defined(HAVE_TEUCHOS_DYNAMIC_LIBS) && defined(HAVE_TEUCHOS_CXX_ATTRIBUTE_WEAK)
531 // if (Amesos2::Details::registerLinearSolverFactory == NULL) {
532 // std::cout << "-- Amesos2::Details::registerLinearSolverFactory is NULL" << std::endl;
533 // } else {
534 // Amesos2::Details::registerLinearSolverFactory ();
535 // }
536 // if (Ifpack2::Details::registerLinearSolverFactory == NULL) {
537 // std::cout << "-- Ifpack2::Details::registerLinearSolverFactory is NULL" << std::endl;
538 // } else {
539 // Ifpack2::Details::registerLinearSolverFactory ();
540 // }
541#endif // ! defined(HAVE_TEUCHOS_DYNAMIC_LIBS) && defined(HAVE_TEUCHOS_CXX_ATTRIBUTE_WEAK)
542
543 // Whether the CMake run-time registration option is ON. This
544 // doesn't actually say whether run-time registration has happened
545 // for the current combination of (MV, OP, NormType) template
546 // parameters.
547 const bool haveRunTimeReg =
549
550 const bool pkgExists = Impl::registeredSomeLinearSolverFactory (packageName);
552 (! pkgExists, std::invalid_argument, prefix << "Package \"" << packageName
553 << "\" never registered a LinearSolverFactory for _any_ combination of "
554 "template parameters MV, OP, and NormType. This means either that the "
555 "package name is invalid, or that the package is not enabled. "
556 "Trilinos_ENABLE_LINEAR_SOLVER_FACTORY_REGISTRATION = "
557 << (haveRunTimeReg ? "ON" : "OFF") << ".");
558
559 factory_pointer_type factory = repo_type::getFactory (packageName);
561 (factory.get () == NULL, std::invalid_argument, prefix << "Package \"" <<
562 packageName << "\" is valid, but it never registered a LinearSolverFactory"
563 " for template parameters "
564 "MV = " << TypeNameTraits<MV>::name () << ", "
565 "OP = " << TypeNameTraits<OP>::name () << ", "
566 "NormType = " << TypeNameTraits<NormType>::name () << ". "
567 "Trilinos_ENABLE_LINEAR_SOLVER_FACTORY_REGISTRATION = "
568 << (haveRunTimeReg ? "ON" : "OFF") << ".");
569
570 RCP<solver_type> solver = factory->getLinearSolver (solverName);
572 (solver.is_null (), std::invalid_argument, prefix << "Invalid solver name "
573 "\"" << solverName << "\". However, package \"" << packageName << "\" is "
574 "valid, and it did register a LinearSolverFactory for template parameters "
575 "MV = " << TypeNameTraits<MV>::name () << ", "
576 "OP = " << TypeNameTraits<OP>::name () << ", "
577 "NormType = " << TypeNameTraits<NormType>::name () << ". "
578 "Trilinos_ENABLE_LINEAR_SOLVER_FACTORY_REGISTRATION = "
579 << (haveRunTimeReg ? "ON" : "OFF") << ".");
580
581 return solver;
582}
583
584} // namespace Details
585} // namespace Trilinos
586
587#endif // TRILINOS_DETAILS_LINEARSOLVER_FACTORY_HPP
Reference-counted pointer class and non-member templated function implementations.
void registerLinearSolverFactory(const std::string &packageName, const Teuchos::RCP< LinearSolverFactory< MV, OP, NormType > > &factory)
Called by a package to register its LinearSolverFactory.
Teuchos::RCP< LinearSolver< MV, OP, NormType > > getLinearSolver(const std::string &packageName, const std::string &solverName)
Get a LinearSolver instance.
Smart reference counting pointer class for automatic garbage collection.
T * get() const
Get the raw C++ pointer to the underlying object.
Default traits class that just returns typeid(T).name().
Teuchos::RCP< LinearSolverFactory< MV, OP, NormType > > factory_pointer_type
Type of a reference-counted pointer to LinearSolverFactory.
static factory_pointer_type getFactory(const std::string &packageName)
Get a LinearSolverFactory from the given package.
std::map< std::string, factory_pointer_type > map_type
Type of a data structure that looks up a LinearSolverFactory corresponding to a given package name.
static void registerLinearSolverFactory(const std::string &packageName, const factory_pointer_type &factory)
Register the given factory from a package.
Interface for a "factory" that creates solvers.
virtual Teuchos::RCP< LinearSolver< MV, OP, NormType > > getLinearSolver(const std::string &solverName)=0
Get an instance of a solver from a particular package.
Interface for a method for solving linear system(s) AX=B.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
Namespace of implementation details.
bool registeredSomeLinearSolverFactory(const std::string &packageName)
Did the package with the given name register at least one LinearSolverFactory, with any template para...
bool rememberRegisteredSomeLinearSolverFactory(const std::string &packageName)
Remember which packages registered at least one LinearSolverFactory, with any template parameters.
bool haveLinearSolverFactoryRunTimeRegistration()
Whether the CMake run-time registration option is ON.
Namespace of things generally useful to many Trilinos packages.