Teuchos Package Browser (Single Doxygen Collection) Version of the Day
Loading...
Searching...
No Matches
Trilinos_Details_LinearSolverFactory.hpp
Go to the documentation of this file.
1// @HEADER
2// ***********************************************************************
3//
4// Teuchos: Common Tools Package
5// Copyright (2004) Sandia Corporation
6//
7// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8// license for use of this work by or on behalf of the U.S. Government.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions are
12// met:
13//
14// 1. Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// 3. Neither the name of the Corporation nor the names of the
22// contributors may be used to endorse or promote products derived from
23// this software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36//
37// Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38//
39// ***********************************************************************
40// @HEADER
41
42#ifndef TRILINOS_DETAILS_LINEARSOLVER_FACTORY_HPP
43#define TRILINOS_DETAILS_LINEARSOLVER_FACTORY_HPP
44
81
82#include "Teuchos_RCP.hpp" // includes Teuchos_ConfigDefs.hpp
83#include "TeuchosRemainder_config.h"
84#include <map>
85#ifdef HAVE_TEUCHOSCORE_CXX11
86# include <memory> // std::shared_ptr
87#endif // HAVE_TEUCHOSCORE_CXX11
88#include <stdexcept>
89#include <sstream>
90#include <string>
91
92
93// Attempted fix for Bug 6392: declare all packages'
94// LinearSolverFactory registration functions here, with weak linkage.
95// This works whether or not the packages in question are actually
96// enabled. In createPackageNames() below, actually call these
97// functions if they are linked in. We only need to do this if
98// building with static libraries; if building with dynamic libraries,
99// each package takes care of this on its own.
100//
101// I wrote "attempted" because it DOESN'T WORK. It doesn't matter
102// whether these or their uses are in the .cpp or .hpp file, or
103// whether they are in a regular function that gets compiled or a
104// templated function that might not.
105#if ! defined(HAVE_TEUCHOS_DYNAMIC_LIBS) && defined(HAVE_TEUCHOS_CXX_ATTRIBUTE_WEAK)
106// FIXME (mfh 21 Aug 2015) NONE of the commented-out things work.
107
108// namespace Amesos2 {
109// namespace Details {
110// extern void __attribute__((weak)) registerLinearSolverFactory ();
111// } // namespace Details
112// } // namespace Amesos2
113
114// namespace Ifpack2 {
115// namespace Details {
116// // extern void __attribute__((weak)) registerLinearSolverFactory ();
117// // void __attribute__((weak)) registerLinearSolverFactory ();
118// // evoid __attribute__((weak)) registerLinearSolverFactory ();
119// } // namespace Details
120// } // namespace Ifpack2
121#endif // ! defined(HAVE_TEUCHOS_DYNAMIC_LIBS) && defined(HAVE_TEUCHOS_CXX_ATTRIBUTE_WEAK)
122
123
126namespace Trilinos {
127
134namespace Details {
135
136template<class MV, class OP, class NormType>
137class LinearSolver; // forward declaration
138
165template<class MV, class OP, class NormType>
167getLinearSolver (const std::string& packageName, const std::string& solverName);
168
234template<class MV, class OP, class NormType>
236public:
246 getLinearSolver (const std::string& solverName) = 0;
247};
248
326template<class MV, class OP, class NormType>
327void
328registerLinearSolverFactory (const std::string& packageName,
329#ifdef HAVE_TEUCHOSCORE_CXX11
330 const std::shared_ptr<LinearSolverFactory<MV, OP, NormType> >& factory);
331#else
333#endif // HAVE_TEUCHOSCORE_CXX11
334
335//
336// EVERYTHING BELOW THIS LINE IS AN IMPLEMENTATION DETAIL
337//
338
344namespace Impl {
345
356bool rememberRegisteredSomeLinearSolverFactory (const std::string& packageName);
357
363bool registeredSomeLinearSolverFactory (const std::string& packageName);
364
372
399template<class MV, class OP, class NormType>
401public:
407#ifdef HAVE_TEUCHOSCORE_CXX11
408 typedef std::shared_ptr<LinearSolverFactory<MV, OP, NormType> > factory_pointer_type;
409#else
411#endif // HAVE_TEUCHOSCORE_CXX11
412
420 typedef std::map<std::string, factory_pointer_type> map_type;
421
422public:
436 getFactory (const std::string& packageName)
437 {
439 typedef typename map_type::iterator iter_type;
440 iter_type it = factories_->find (packageName);
441 if (it == factories_->end ()) { // didn't find package name
442 return factory_pointer_type (); // null pointer
443 } else { // found package name
444 return it->second;
445 }
446 }
447
462 static void
463 registerLinearSolverFactory (const std::string& packageName,
464 const factory_pointer_type& factory)
465 {
467 (factory.get () == NULL, std::invalid_argument, "Trilinos::Details::"
468 "LinearSolverFactoryRepository::registerLinearSolverFactory: Input "
469 "'factory' is NULL!");
471 if (factories_->find (packageName) == factories_->end ()) {
472 factories_->insert (std::make_pair (packageName, factory));
473 }
474 }
475
476private:
488
492 static void createFactories () {
493 if (factories_ == NULL) {
494 factories_ = new map_type ();
495 // It _is_ possible for atexit() to fail (e.g., because it ran
496 // out of memory for storing callbacks). We could throw an
497 // exception here in that case, but I think it's better just
498 // to let the minor memory leak happen.
499 (void) atexit (freeFactories);
500 }
502 (factories_ == NULL, std::logic_error, "Trilinos::Details::"
503 "LinearSolverFactoryRepository::createFactories: "
504 "Should never get here! factories_ is NULL.");
505 }
506
515 static void freeFactories () {
516 if (factories_ != NULL) {
517 delete factories_;
518 factories_ = NULL;
519 }
520 }
521};
522
523// This is _not_ an explicit instantiation. C++ wants it, because
524// LinearSolverFactoryRepository is a templated class with a static
525// (class) member.
526template<class MV, class OP, class NormType>
529
530} // namespace Impl
531
532//
533// Definitions of nonmember functions
534//
535
536template<class MV, class OP, class NormType>
537void
538registerLinearSolverFactory (const std::string& packageName,
539#ifdef HAVE_TEUCHOSCORE_CXX11
540 const std::shared_ptr<LinearSolverFactory<MV, OP, NormType> >& factory)
541#else
543#endif // HAVE_TEUCHOSCORE_CXX11
544{
547}
548
549template<class MV, class OP, class NormType>
551getLinearSolver (const std::string& packageName, const std::string& solverName)
552{
553 using Teuchos::RCP;
556 typedef typename repo_type::factory_pointer_type factory_pointer_type;
557 typedef LinearSolver<MV, OP, NormType> solver_type;
558 const char prefix[] = "Trilinos::Details::getLinearSolver: ";
559
560 // FIXME (mfh 21 Aug 2015) Attempted fix for Bug 6392: DOES NOT WORK.
561 // (Compiles just fine, but test doesn't pass.)
562#if ! defined(HAVE_TEUCHOS_DYNAMIC_LIBS) && defined(HAVE_TEUCHOS_CXX_ATTRIBUTE_WEAK)
563 // if (Amesos2::Details::registerLinearSolverFactory == NULL) {
564 // std::cout << "-- Amesos2::Details::registerLinearSolverFactory is NULL" << std::endl;
565 // } else {
566 // Amesos2::Details::registerLinearSolverFactory ();
567 // }
568 // if (Ifpack2::Details::registerLinearSolverFactory == NULL) {
569 // std::cout << "-- Ifpack2::Details::registerLinearSolverFactory is NULL" << std::endl;
570 // } else {
571 // Ifpack2::Details::registerLinearSolverFactory ();
572 // }
573#endif // ! defined(HAVE_TEUCHOS_DYNAMIC_LIBS) && defined(HAVE_TEUCHOS_CXX_ATTRIBUTE_WEAK)
574
575 // Whether the CMake run-time registration option is ON. This
576 // doesn't actually say whether run-time registration has happened
577 // for the current combination of (MV, OP, NormType) template
578 // parameters.
579 const bool haveRunTimeReg =
581
582 const bool pkgExists = Impl::registeredSomeLinearSolverFactory (packageName);
584 (! pkgExists, std::invalid_argument, prefix << "Package \"" << packageName
585 << "\" never registered a LinearSolverFactory for _any_ combination of "
586 "template parameters MV, OP, and NormType. This means either that the "
587 "package name is invalid, or that the package is not enabled. "
588 "Trilinos_ENABLE_LINEAR_SOLVER_FACTORY_REGISTRATION = "
589 << (haveRunTimeReg ? "ON" : "OFF") << ".");
590
591 factory_pointer_type factory = repo_type::getFactory (packageName);
593 (factory.get () == NULL, std::invalid_argument, prefix << "Package \"" <<
594 packageName << "\" is valid, but it never registered a LinearSolverFactory"
595 " for template parameters "
596 "MV = " << TypeNameTraits<MV>::name () << ", "
597 "OP = " << TypeNameTraits<OP>::name () << ", "
598 "NormType = " << TypeNameTraits<NormType>::name () << ". "
599 "Trilinos_ENABLE_LINEAR_SOLVER_FACTORY_REGISTRATION = "
600 << (haveRunTimeReg ? "ON" : "OFF") << ".");
601
602 RCP<solver_type> solver = factory->getLinearSolver (solverName);
604 (solver.is_null (), std::invalid_argument, prefix << "Invalid solver name "
605 "\"" << solverName << "\". However, package \"" << packageName << "\" is "
606 "valid, and it did register a LinearSolverFactory for template parameters "
607 "MV = " << TypeNameTraits<MV>::name () << ", "
608 "OP = " << TypeNameTraits<OP>::name () << ", "
609 "NormType = " << TypeNameTraits<NormType>::name () << ". "
610 "Trilinos_ENABLE_LINEAR_SOLVER_FACTORY_REGISTRATION = "
611 << (haveRunTimeReg ? "ON" : "OFF") << ".");
612
613 return solver;
614}
615
616} // namespace Details
617} // namespace Trilinos
618
619#endif // TRILINOS_DETAILS_LINEARSOLVER_FACTORY_HPP
Reference-counted pointer class and non-member templated function implementations.
Smart reference counting pointer class for automatic garbage collection.
Concrete serial communicator subclass.
Default traits class that just returns typeid(T).name().
static map_type * factories_
Singleton where all packages' factories get stored.
Teuchos::RCP< LinearSolverFactory< MV, OP, NormType > > factory_pointer_type
Type of a reference-counted pointer to LinearSolverFactory.
static void createFactories()
Initialize factories_ if it hasn't been initialized.
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.
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.
Namespace of things generally useful to many Trilinos packages.