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 #if defined (HAVE_AMESOS2_CHOLMOD) && defined (HAVE_AMESOS2_EXPERIMENTAL)
00114 #include "Amesos2_Cholmod.hpp"
00115 #endif
00116 
00117 namespace Amesos2 {
00118 
00119   template <class,class> class Solver;
00120 
00121   /*
00122    * Utility function to transform a string into all lowercase
00123    */
00124   std::string tolower(const std::string& s);
00125 
00126 
00141   template < class Matrix,
00142              class Vector >
00143   Solver<Matrix,Vector>*
00144   create(const Matrix* A, Vector* X, const Vector* B);
00145 
00146 
00161   template < class Matrix,
00162              class Vector >
00163   Teuchos::RCP<Solver<Matrix,Vector> >
00164   create(Teuchos::RCP<const Matrix> A,
00165          Teuchos::RCP<Vector>       X,
00166          Teuchos::RCP<const Vector> B);
00167 
00168 
00186   template < class Matrix,
00187              class Vector >
00188   Solver<Matrix,Vector>*
00189   create(const char* solverName, const Matrix* A, Vector* X, const Vector* B);
00190 
00191 
00208   template < class Matrix,
00209              class Vector >
00210   Teuchos::RCP<Solver<Matrix,Vector> >
00211   create(const char* solverName,
00212          const Teuchos::RCP<const Matrix> A,
00213          const Teuchos::RCP<Vector>       X,
00214          const Teuchos::RCP<const Vector> B);
00215 
00216 
00233   template < class Matrix,
00234              class Vector >
00235   Solver<Matrix,Vector>*
00236   create(const std::string solverName, const Matrix* A, Vector* X, const Vector* B);
00237 
00238 
00255   template < class Matrix,
00256              class Vector >
00257   Teuchos::RCP<Solver<Matrix,Vector> >
00258   create(const std::string solverName,
00259          const Teuchos::RCP<const Matrix> A,
00260          const Teuchos::RCP<Vector>       X,
00261          const Teuchos::RCP<const Vector> B);
00262 
00263 
00282   template < class Matrix,
00283              class Vector >
00284   Solver<Matrix,Vector>*
00285   create(const std::string solverName, const Matrix* A);
00286 
00287 
00306   template < class Matrix,
00307              class Vector >
00308   Teuchos::RCP<Solver<Matrix,Vector> >
00309   create(const std::string solverName,
00310          const Teuchos::RCP<const Matrix> A);
00311 
00312 
00314   // Meta-functions to help with creation of solvers //
00316 
00317   template < template <class,class> class ConcreteSolver,
00318              class Matrix,
00319              class Vector >
00320   struct create_solver_with_supported_type {
00321     static Teuchos::RCP<Solver<Matrix,Vector> > apply(Teuchos::RCP<const Matrix> A,
00322                                                       Teuchos::RCP<Vector>       X,
00323                                                       Teuchos::RCP<const Vector> B )
00324     {
00325       ctassert<
00326         Meta::is_same<
00327           typename MatrixTraits<Matrix>::scalar_t,
00328           typename MultiVecAdapter<Vector>::scalar_t
00329         >::value
00330       > same_scalar_assertion;
00331       (void)same_scalar_assertion; // This stops the compiler from warning about unused declared variables
00332 
00333       // If our assertion did not fail, then create and return a new solver
00334       return rcp( new ConcreteSolver<Matrix,Vector>(A, X, B) );
00335     }
00336   };
00337 
00346 template < template <class,class> class ConcreteSolver,
00347            class Matrix,
00348            class Vector >
00349 struct throw_no_scalar_support_exception {
00350   static Teuchos::RCP<Solver<Matrix,Vector> > apply(Teuchos::RCP<const Matrix> A,
00351                                                     Teuchos::RCP<Vector>       X,
00352                                                     Teuchos::RCP<const Vector> B )
00353   {
00354     // typedef ConcreteSolver<Matrix,Vector> concretesolver_matrix_vector;
00355     typedef typename MatrixTraits<Matrix>::scalar_t scalar_t;
00356     TEUCHOS_TEST_FOR_EXCEPTION( true,
00357                         std::invalid_argument,
00358                         "The requested Amesos2 "
00359                         // << concretesolver_matrix_vector::name <<
00360                         " solver interface does not support the " <<
00361                         Teuchos::ScalarTraits<scalar_t>::name() <<
00362                         " scalar type." );
00363   }
00364 };
00365 
00375   template < template <class,class> class ConcreteSolver,
00376              class Matrix,
00377              class Vector >
00378   struct handle_solver_type_support {
00379     static Teuchos::RCP<Solver<Matrix,Vector> > apply(Teuchos::RCP<const Matrix> A,
00380                                                       Teuchos::RCP<Vector>       X,
00381                                                       Teuchos::RCP<const Vector> B )
00382     {
00383       return Meta::if_then_else<
00384       solver_supports_scalar<ConcreteSolver, typename MatrixTraits<Matrix>::scalar_t>::value,
00385         create_solver_with_supported_type<ConcreteSolver,Matrix,Vector>,
00386         throw_no_scalar_support_exception<ConcreteSolver,Matrix,Vector> >::type::apply(A, X, B);
00387   }
00388     };
00389 
00390 
00392   // Query Functions //
00394 
00402   bool query(const char* solverName);
00403 
00404 
00412   bool query(const std::string solverName);
00413 
00414 
00416   // Definitions //
00418 
00419   template <class Matrix,
00420             class Vector >
00421   Solver<Matrix,Vector>*
00422   create(Matrix* A, Vector* X, Vector* B)
00423   {
00424     std::string solver = "Klu2";
00425     // Pass non-owning RCP objects to other factory method
00426     return( create(solver, rcp(A,false), rcp(X,false), rcp(B,false)).getRawPtr() );
00427   }
00428 
00429 
00430   template <class Matrix,
00431             class Vector >
00432   Teuchos::RCP<Solver<Matrix,Vector> >
00433   create(Teuchos::RCP<const Matrix> A,
00434          Teuchos::RCP<Vector>       X,
00435          Teuchos::RCP<const Vector> B)
00436   {
00437     std::string solver = "Klu2";
00438     return( create(solver, A, X, B) );
00439   }
00440 
00441 
00442   template <class Matrix,
00443             class Vector >
00444   Solver<Matrix,Vector>*
00445   create(const char* solverName, const Matrix* A, Vector* X, const Vector* B)
00446   {
00447     std::string solver = solverName;
00448     // Pass non-owning Teuchos::RCP objects to other factory method
00449     return( create(solver, rcp(A,false), rcp(X,false), rcp(B,false)).getRawPtr() );
00450   }
00451 
00452 
00453   template <class Matrix,
00454             class Vector >
00455   Teuchos::RCP<Solver<Matrix,Vector> >
00456   create(const char* solverName,
00457          const Teuchos::RCP<const Matrix> A,
00458          const Teuchos::RCP<Vector>       X,
00459          const Teuchos::RCP<const Vector> B)
00460   {
00461     std::string solver = solverName;
00462     return( create(solver, A, X, B) );
00463   }
00464 
00465 
00466   template <class Matrix,
00467             class Vector >
00468   Solver<Matrix,Vector>*
00469   create(const std::string solverName, const Matrix* A){
00470     return( create(solverName, rcp(A,false),
00471                    Teuchos::RCP<Vector>(),
00472                    Teuchos::RCP<const Vector>()).getRawPtr() );
00473   }
00474 
00475 
00476   template <class Matrix,
00477             class Vector >
00478   Teuchos::RCP<Solver<Matrix,Vector> >
00479   create(const std::string solverName, const Teuchos::RCP<const Matrix> A){
00480     return( create(solverName, A, Teuchos::RCP<Vector>(), Teuchos::RCP<const Vector>()) );
00481   }
00482 
00483 
00484   template <class Matrix,
00485             class Vector >
00486   Teuchos::RCP<Solver<Matrix,Vector> >
00487   create(const std::string solverName, const Matrix* A, Vector* X, const Vector* B)
00488   {
00489     // Pass non-owning Teuchos::RCP objects to other factory method
00490     return( create(solverName, rcp(A,false), rcp(X,false), rcp(B,false)) );
00491   }
00492 
00493 
00494   template <class Matrix,
00495             class Vector >
00496   Teuchos::RCP<Solver<Matrix,Vector> >
00497   create(const std::string solver_name,
00498          const Teuchos::RCP<const Matrix> A,
00499          const Teuchos::RCP<Vector>       X,
00500          const Teuchos::RCP<const Vector> B)
00501   {
00502     std::string solverName = tolower(solver_name); // for easy string checking
00503 
00504     // Check for our native solver first.  Treat KLU and KLU2 as equals.
00505     //
00506     // We use compiler guards in case a user does want to disable KLU2
00507 #ifdef HAVE_AMESOS2_KLU2
00508     if((solverName == "amesos2_klu2") || (solverName == "klu2") ||
00509        (solverName == "amesos2_klu")  || (solverName == "klu")){
00510       return handle_solver_type_support<Klu2,Matrix,Vector>::apply(A, X, B);
00511     }
00512 #endif
00513 
00514 #ifdef HAVE_AMESOS2_SUPERLUDIST
00515     if((solverName == "amesos2_superludist") ||
00516        (solverName == "superludist") ||
00517        (solverName == "amesos2_superlu_dist") ||
00518        (solverName == "superlu_dist")){
00519       return handle_solver_type_support<Superludist,Matrix,Vector>::apply(A, X, B);
00520     }
00521 #endif
00522 
00523 #ifdef HAVE_AMESOS2_SUPERLUMT
00524     if((solverName == "amesos2_superlumt") ||
00525        (solverName == "superlumt") ||
00526        (solverName == "amesos2_superlu_mt") ||
00527        (solverName == "superlu_mt")){
00528       return handle_solver_type_support<Superlumt,Matrix,Vector>::apply(A, X, B);
00529     }
00530 #endif
00531 
00532 #ifdef HAVE_AMESOS2_SUPERLU
00533     if((solverName == "amesos2_superlu") ||
00534        (solverName == "superlu")){
00535       return handle_solver_type_support<Superlu,Matrix,Vector>::apply(A, X, B);
00536     }
00537 #endif
00538 
00539 #ifdef HAVE_AMESOS2_PARDISO_MKL
00540     if((solverName == "amesos2_pardiso_mkl") ||
00541        (solverName == "pardiso_mkl") ||
00542        (solverName == "amesos2_pardisomkl")  ||
00543        (solverName == "pardisomkl")){
00544       return handle_solver_type_support<PardisoMKL,Matrix,Vector>::apply(A, X, B);
00545     }
00546 #endif
00547 
00548 #ifdef HAVE_AMESOS2_LAPACK
00549     if((solverName == "amesos2_lapack") ||
00550        (solverName == "lapack")){
00551       return handle_solver_type_support<Lapack,Matrix,Vector>::apply(A, X, B);
00552     }
00553 #endif
00554 
00555 #if defined (HAVE_AMESOS2_CHOLMOD) && defined (HAVE_AMESOS2_EXPERIMENTAL)
00556     if(solverName == "amesos2_cholmod")
00557       return handle_solver_type_support<Cholmod,Matrix,Vector>::apply(A, X, B);
00558 #endif
00559 
00560     /* If none of the above conditionals are satisfied, then the solver
00561      * requested is not yet supported.  We throw a runtime exception stating
00562      * this, and return null.
00563      */
00564     std::string err_msg = solver_name + " is not enabled or is not supported";
00565     TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, err_msg);
00566     return( Teuchos::null );
00567   }
00568 
00569 } // end namespace Amesos2
00570 
00571 #endif  // AMESOS2_FACTORY_HPP