Amesos2 - Direct Sparse Solver Interfaces Version of the Day
Amesos2_Factory.hpp
Go to the documentation of this file.
00001 // @HEADER
00002 //
00003 // ***********************************************************************
00004 //
00005 //           Amesos2: Templated Direct Sparse Solver Package
00006 //                  Copyright 2011 Sandia Corporation
00007 //
00008 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00009 // the U.S. Government retains certain rights in this software.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00039 //
00040 // ***********************************************************************
00041 //
00042 // @HEADER
00043 
00082 #ifndef AMESOS2_FACTORY_HPP
00083 #define AMESOS2_FACTORY_HPP
00084 
00085 #include "Amesos2_config.h"
00086 
00087 #include "Amesos2_Solver.hpp"
00088 #include "Amesos2_SolverTraits.hpp"
00089 
00090 #include "Teuchos_ScalarTraits.hpp"
00091 #include "Amesos2_MultiVecAdapter.hpp"
00092 #include "Amesos2_MatrixTraits.hpp"
00093 #include "Amesos2_ctassert.hpp"
00094 
00095 #ifdef HAVE_AMESOS2_KLU2
00096 #include "Amesos2_Klu2.hpp"
00097 #endif
00098 #ifdef HAVE_AMESOS2_SUPERLUDIST // Distributed-memory SuperLU
00099 #include "Amesos2_Superludist.hpp"
00100 #endif
00101 #ifdef HAVE_AMESOS2_SUPERLUMT   // Multi-threaded SuperLU
00102 #include "Amesos2_Superlumt.hpp"
00103 #endif
00104 #ifdef HAVE_AMESOS2_SUPERLU     // Sequential SuperLU
00105 #include "Amesos2_Superlu.hpp"
00106 #endif
00107 #ifdef HAVE_AMESOS2_PARDISO_MKL // MKL version of Pardiso
00108 #include "Amesos2_PardisoMKL.hpp"
00109 #endif
00110 #ifdef HAVE_AMESOS2_LAPACK
00111 #include "Amesos2_Lapack.hpp"
00112 #endif
00113 
00114 namespace Amesos2 {
00115 
00116   template <class,class> class Solver;
00117 
00118   /*
00119    * Utility function to transform a string into all lowercase
00120    */
00121   std::string tolower(const std::string& s);
00122 
00123 
00138   template < class Matrix,
00139              class Vector >
00140   Solver<Matrix,Vector>*
00141   create(const Matrix* A, Vector* X, const Vector* B);
00142 
00143 
00158   template < class Matrix,
00159              class Vector >
00160   Teuchos::RCP<Solver<Matrix,Vector> >
00161   create(Teuchos::RCP<const Matrix> A,
00162          Teuchos::RCP<Vector>       X,
00163          Teuchos::RCP<const Vector> B);
00164 
00165 
00183   template < class Matrix,
00184              class Vector >
00185   Solver<Matrix,Vector>*
00186   create(const char* solverName, const Matrix* A, Vector* X, const Vector* B);
00187 
00188 
00205   template < class Matrix,
00206              class Vector >
00207   Teuchos::RCP<Solver<Matrix,Vector> >
00208   create(const char* solverName,
00209          const Teuchos::RCP<const Matrix> A,
00210          const Teuchos::RCP<Vector>       X,
00211          const Teuchos::RCP<const Vector> B);
00212 
00213 
00230   template < class Matrix,
00231              class Vector >
00232   Solver<Matrix,Vector>*
00233   create(const std::string solverName, const Matrix* A, Vector* X, const Vector* B);
00234 
00235 
00252   template < class Matrix,
00253              class Vector >
00254   Teuchos::RCP<Solver<Matrix,Vector> >
00255   create(const std::string solverName,
00256          const Teuchos::RCP<const Matrix> A,
00257          const Teuchos::RCP<Vector>       X,
00258          const Teuchos::RCP<const Vector> B);
00259 
00260 
00279   template < class Matrix,
00280              class Vector >
00281   Solver<Matrix,Vector>*
00282   create(const std::string solverName, const Matrix* A);
00283 
00284 
00303   template < class Matrix,
00304              class Vector >
00305   Teuchos::RCP<Solver<Matrix,Vector> >
00306   create(const std::string solverName,
00307          const Teuchos::RCP<const Matrix> A);
00308 
00309 
00311   // Meta-functions to help with creation of solvers //
00313 
00314   template < template <class,class> class ConcreteSolver,
00315              class Matrix,
00316              class Vector >
00317   struct create_solver_with_supported_type {
00318     static Teuchos::RCP<Solver<Matrix,Vector> > apply(Teuchos::RCP<const Matrix> A,
00319                                                       Teuchos::RCP<Vector>       X,
00320                                                       Teuchos::RCP<const Vector> B )
00321     {
00322       ctassert<
00323         Meta::is_same<
00324           typename MatrixTraits<Matrix>::scalar_t,
00325           typename MultiVecAdapter<Vector>::scalar_t
00326         >::value
00327       > same_scalar_assertion;
00328       (void)same_scalar_assertion; // This stops the compiler from warning about unused declared variables
00329 
00330       // If our assertion did not fail, then create and return a new solver
00331       return rcp( new ConcreteSolver<Matrix,Vector>(A, X, B) );
00332     }
00333   };
00334 
00343 template < template <class,class> class ConcreteSolver,
00344            class Matrix,
00345            class Vector >
00346 struct throw_no_scalar_support_exception {
00347   static Teuchos::RCP<Solver<Matrix,Vector> > apply(Teuchos::RCP<const Matrix> A,
00348                                                     Teuchos::RCP<Vector>       X,
00349                                                     Teuchos::RCP<const Vector> B )
00350   {
00351     // typedef ConcreteSolver<Matrix,Vector> concretesolver_matrix_vector;
00352     typedef typename MatrixTraits<Matrix>::scalar_t scalar_t;
00353     TEUCHOS_TEST_FOR_EXCEPTION( true,
00354                         std::invalid_argument,
00355                         "The requested Amesos2 "
00356                         // << concretesolver_matrix_vector::name <<
00357                         " solver interface does not support the " <<
00358                         Teuchos::ScalarTraits<scalar_t>::name() <<
00359                         " scalar type." );
00360   }
00361 };
00362 
00372   template < template <class,class> class ConcreteSolver,
00373              class Matrix,
00374              class Vector >
00375   struct handle_solver_type_support {
00376     static Teuchos::RCP<Solver<Matrix,Vector> > apply(Teuchos::RCP<const Matrix> A,
00377                                                       Teuchos::RCP<Vector>       X,
00378                                                       Teuchos::RCP<const Vector> B )
00379     {
00380       return Meta::if_then_else<
00381       solver_supports_scalar<ConcreteSolver, typename MatrixTraits<Matrix>::scalar_t>::value,
00382         create_solver_with_supported_type<ConcreteSolver,Matrix,Vector>,
00383         throw_no_scalar_support_exception<ConcreteSolver,Matrix,Vector> >::type::apply(A, X, B);
00384   }
00385     };
00386 
00387 
00389   // Query Functions //
00391 
00399   bool query(const char* solverName);
00400 
00401 
00409   bool query(const std::string solverName);
00410 
00411 
00413   // Definitions //
00415 
00416   template <class Matrix,
00417             class Vector >
00418   Solver<Matrix,Vector>*
00419   create(Matrix* A, Vector* X, Vector* B)
00420   {
00421     std::string solver = "Klu2";
00422     // Pass non-owning RCP objects to other factory method
00423     return( create(solver, rcp(A,false), rcp(X,false), rcp(B,false)).getRawPtr() );
00424   }
00425 
00426 
00427   template <class Matrix,
00428             class Vector >
00429   Teuchos::RCP<Solver<Matrix,Vector> >
00430   create(Teuchos::RCP<const Matrix> A,
00431          Teuchos::RCP<Vector>       X,
00432          Teuchos::RCP<const Vector> B)
00433   {
00434     std::string solver = "Klu2";
00435     return( create(solver, A, X, B) );
00436   }
00437 
00438 
00439   template <class Matrix,
00440             class Vector >
00441   Solver<Matrix,Vector>*
00442   create(const char* solverName, const Matrix* A, Vector* X, const Vector* B)
00443   {
00444     std::string solver = solverName;
00445     // Pass non-owning Teuchos::RCP objects to other factory method
00446     return( create(solver, rcp(A,false), rcp(X,false), rcp(B,false)).getRawPtr() );
00447   }
00448 
00449 
00450   template <class Matrix,
00451             class Vector >
00452   Teuchos::RCP<Solver<Matrix,Vector> >
00453   create(const char* solverName,
00454          const Teuchos::RCP<const Matrix> A,
00455          const Teuchos::RCP<Vector>       X,
00456          const Teuchos::RCP<const Vector> B)
00457   {
00458     std::string solver = solverName;
00459     return( create(solver, A, X, B) );
00460   }
00461 
00462 
00463   template <class Matrix,
00464             class Vector >
00465   Solver<Matrix,Vector>*
00466   create(const std::string solverName, const Matrix* A){
00467     return( create(solverName, rcp(A,false),
00468                    Teuchos::RCP<Vector>(),
00469                    Teuchos::RCP<const Vector>()).getRawPtr() );
00470   }
00471 
00472 
00473   template <class Matrix,
00474             class Vector >
00475   Teuchos::RCP<Solver<Matrix,Vector> >
00476   create(const std::string solverName, const Teuchos::RCP<const Matrix> A){
00477     return( create(solverName, A, Teuchos::RCP<Vector>(), Teuchos::RCP<const Vector>()) );
00478   }
00479 
00480 
00481   template <class Matrix,
00482             class Vector >
00483   Teuchos::RCP<Solver<Matrix,Vector> >
00484   create(const std::string solverName, const Matrix* A, Vector* X, const Vector* B)
00485   {
00486     // Pass non-owning Teuchos::RCP objects to other factory method
00487     return( create(solverName, rcp(A,false), rcp(X,false), rcp(B,false)) );
00488   }
00489 
00490 
00491   template <class Matrix,
00492             class Vector >
00493   Teuchos::RCP<Solver<Matrix,Vector> >
00494   create(const std::string solver_name,
00495          const Teuchos::RCP<const Matrix> A,
00496          const Teuchos::RCP<Vector>       X,
00497          const Teuchos::RCP<const Vector> B)
00498   {
00499     std::string solverName = tolower(solver_name); // for easy string checking
00500 
00501     // Check for our native solver first.  Treat KLU and KLU2 as equals.
00502     //
00503     // We use compiler guards in case a user does want to disable KLU2
00504 #ifdef HAVE_AMESOS2_KLU2
00505     if((solverName == "amesos2_klu2") || (solverName == "klu2") ||
00506        (solverName == "amesos2_klu")  || (solverName == "klu")){
00507       return handle_solver_type_support<Klu2,Matrix,Vector>::apply(A, X, B);
00508     }
00509 #endif
00510 
00511 #ifdef HAVE_AMESOS2_SUPERLUDIST
00512     if((solverName == "amesos2_superludist") ||
00513        (solverName == "superludist") ||
00514        (solverName == "amesos2_superlu_dist") ||
00515        (solverName == "superlu_dist")){
00516       return handle_solver_type_support<Superludist,Matrix,Vector>::apply(A, X, B);
00517     }
00518 #endif
00519 
00520 #ifdef HAVE_AMESOS2_SUPERLUMT
00521     if((solverName == "amesos2_superlumt") ||
00522        (solverName == "superlumt") ||
00523        (solverName == "amesos2_superlu_mt") ||
00524        (solverName == "superlu_mt")){
00525       return handle_solver_type_support<Superlumt,Matrix,Vector>::apply(A, X, B);
00526     }
00527 #endif
00528 
00529 #ifdef HAVE_AMESOS2_SUPERLU
00530     if((solverName == "amesos2_superlu") ||
00531        (solverName == "superlu")){
00532       return handle_solver_type_support<Superlu,Matrix,Vector>::apply(A, X, B);
00533     }
00534 #endif
00535 
00536 #ifdef HAVE_AMESOS2_PARDISO_MKL
00537     if((solverName == "amesos2_pardiso_mkl") ||
00538        (solverName == "pardiso_mkl") ||
00539        (solverName == "amesos2_pardisomkl")  ||
00540        (solverName == "pardisomkl")){
00541       return handle_solver_type_support<PardisoMKL,Matrix,Vector>::apply(A, X, B);
00542     }
00543 #endif
00544 
00545 #ifdef HAVE_AMESOS2_LAPACK
00546     if((solverName == "amesos2_lapack") ||
00547        (solverName == "lapack")){
00548       return handle_solver_type_support<Lapack,Matrix,Vector>::apply(A, X, B);
00549     }
00550 #endif
00551 
00552     /* If none of the above conditionals are satisfied, then the solver
00553      * requested is not yet supported.  We throw a runtime exception stating
00554      * this, and return null.
00555      */
00556     std::string err_msg = solver_name + " is not enabled or is not supported";
00557     TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, err_msg);
00558     return( Teuchos::null );
00559   }
00560 
00561 } // end namespace Amesos2
00562 
00563 #endif  // AMESOS2_FACTORY_HPP