Amesos2 - Direct Sparse Solver Interfaces  Version of the Day
Amesos2_Factory.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // Amesos2: Templated Direct Sparse Solver Package
6 // Copyright 2011 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
39 //
40 // ***********************************************************************
41 //
42 // @HEADER
43 
82 #ifndef AMESOS2_FACTORY_HPP
83 #define AMESOS2_FACTORY_HPP
84 
85 #include "Amesos2_config.h"
86 
87 #include "Amesos2_Solver.hpp"
88 #include "Amesos2_SolverTraits.hpp"
89 
90 #include "Teuchos_ScalarTraits.hpp"
92 #include "Amesos2_MatrixTraits.hpp"
93 #include "Amesos2_ctassert.hpp"
94 
95 #ifdef HAVE_AMESOS2_BASKER
96 #include "Amesos2_Basker.hpp"
97 #endif
98 
99 #ifdef HAVE_AMESOS2_SHYLU_NODEBASKER
100 #include "Amesos2_ShyLUBasker.hpp"
101 #endif
102 
103 #if defined(HAVE_AMESOS2_KLU2)
104 #include "Amesos2_KLU2.hpp"
105 #endif
106 
107 #ifdef HAVE_AMESOS2_SUPERLUDIST // Distributed-memory SuperLU
108 #include "Amesos2_Superludist.hpp"
109 #endif
110 
111 #ifdef HAVE_AMESOS2_SUPERLUMT // Multi-threaded SuperLU
112 #include "Amesos2_Superlumt.hpp"
113 #endif
114 
115 #ifdef HAVE_AMESOS2_UMFPACK // Umfpack
116 #include "Amesos2_Umfpack.hpp"
117 #endif
118 
119 #ifdef HAVE_AMESOS2_SHYLU_NODETACHO // Tacho
120 #include "Amesos2_Tacho.hpp"
121 #endif
122 
123 #ifdef HAVE_AMESOS2_SUPERLU // Sequential SuperLU
124 #include "Amesos2_Superlu.hpp"
125 #endif
126 
127 #ifdef HAVE_AMESOS2_PARDISO_MKL // MKL version of Pardiso
128 #include "Amesos2_PardisoMKL.hpp"
129 #endif
130 
131 #ifdef HAVE_AMESOS2_LAPACK
132 #include "Amesos2_Lapack.hpp"
133 #endif
134 
135 #if defined (HAVE_AMESOS2_CHOLMOD) && defined (HAVE_AMESOS2_EXPERIMENTAL)
136 #include "Amesos2_Cholmod.hpp"
137 #endif
138 
139 #if defined (HAVE_AMESOS2_CUSOLVER) && defined (HAVE_AMESOS2_CUSPARSE)
140 #include "Amesos2_cuSOLVER.hpp"
141 #endif
142 
143 #ifdef HAVE_AMESOS2_MUMPS
144 #include "Amesos2_MUMPS.hpp"
145 #endif
146 
147 #ifdef HAVE_AMESOS2_STRUMPACK
148 #include "Amesos2_STRUMPACK.hpp"
149 #endif
150 
151 
152 namespace Amesos2 {
153 
154  template <class,class> class Solver;
155 
156  /*
157  * Utility function to transform a string into all lowercase
158  */
159  std::string tolower(const std::string& s);
160 
161 
176  template < class Matrix,
177  class Vector >
178  Solver<Matrix,Vector>*
179  create(const Matrix* A, Vector* X, const Vector* B);
180 
181 
196  template < class Matrix,
197  class Vector >
198  Teuchos::RCP<Solver<Matrix,Vector> >
199  create(Teuchos::RCP<const Matrix> A,
200  Teuchos::RCP<Vector> X,
201  Teuchos::RCP<const Vector> B);
202 
203 
221  template < class Matrix,
222  class Vector >
223  Solver<Matrix,Vector>*
224  create(const char* solverName, const Matrix* A, Vector* X, const Vector* B);
225 
226 
243  template < class Matrix,
244  class Vector >
245  Teuchos::RCP<Solver<Matrix,Vector> >
246  create(const char* solverName,
247  const Teuchos::RCP<const Matrix> A,
248  const Teuchos::RCP<Vector> X,
249  const Teuchos::RCP<const Vector> B);
250 
251 
268  template < class Matrix,
269  class Vector >
270  Solver<Matrix,Vector>*
271  create(const std::string& solverName, const Matrix* A, Vector* X, const Vector* B);
272 
273 
290  template < class Matrix,
291  class Vector >
292  Teuchos::RCP<Solver<Matrix,Vector> >
293  create(const std::string& solverName,
294  const Teuchos::RCP<const Matrix> A,
295  const Teuchos::RCP<Vector> X,
296  const Teuchos::RCP<const Vector> B);
297 
298 
317  template < class Matrix,
318  class Vector >
319  Solver<Matrix,Vector>*
320  create(const std::string& solverName, const Matrix* A);
321 
322 
341  template < class Matrix,
342  class Vector >
343  Teuchos::RCP<Solver<Matrix,Vector> >
344  create(const std::string& solverName,
345  const Teuchos::RCP<const Matrix> A);
346 
347 
349  // Meta-functions to help with creation of solvers //
351 
352  template < template <class,class> class ConcreteSolver,
353  class Matrix,
354  class Vector >
355  struct create_solver_with_supported_type {
356  static Teuchos::RCP<Solver<Matrix,Vector> > apply(Teuchos::RCP<const Matrix> A,
357  Teuchos::RCP<Vector> X,
358  Teuchos::RCP<const Vector> B )
359  {
360  ctassert<
361  std::is_same_v<
362  typename MatrixTraits<Matrix>::scalar_t,
363  typename MultiVecAdapter<Vector>::scalar_t
364  >
365  > same_scalar_assertion;
366  (void)same_scalar_assertion; // This stops the compiler from warning about unused declared variables
367 
368  // If our assertion did not fail, then create and return a new solver
369  return rcp( new ConcreteSolver<Matrix,Vector>(A, X, B) );
370  }
371  };
372 
381 template < template <class,class> class ConcreteSolver,
382  class Matrix,
383  class Vector >
384 struct throw_no_scalar_support_exception {
385  static Teuchos::RCP<Solver<Matrix,Vector> > apply(Teuchos::RCP<const Matrix> A,
386  Teuchos::RCP<Vector> X,
387  Teuchos::RCP<const Vector> B )
388  {
389  // typedef ConcreteSolver<Matrix,Vector> concretesolver_matrix_vector;
390  typedef typename MatrixTraits<Matrix>::scalar_t scalar_t;
391  TEUCHOS_TEST_FOR_EXCEPTION( true,
392  std::invalid_argument,
393  "The requested Amesos2 "
394  // << concretesolver_matrix_vector::name <<
395  " solver interface does not support the " <<
396  Teuchos::ScalarTraits<scalar_t>::name() <<
397  " scalar type." );
398  }
399 };
400 
401 template < template <class,class> class ConcreteSolver,
402  class Matrix,
403  class Vector >
404 struct throw_no_matrix_support_exception {
405  static Teuchos::RCP<Solver<Matrix,Vector> > apply(Teuchos::RCP<const Matrix> A,
406  Teuchos::RCP<Vector> X,
407  Teuchos::RCP<const Vector> B )
408  {
409  TEUCHOS_TEST_FOR_EXCEPTION( true,
410  std::invalid_argument,
411  "This solver does not support the kokkos adapter." );
412  }
413 };
414 
424  template < template <class,class> class ConcreteSolver,
425  class Matrix,
426  class Vector >
427  struct handle_solver_scalar_type_support {
428  static Teuchos::RCP<Solver<Matrix,Vector> > apply(Teuchos::RCP<const Matrix> A,
429  Teuchos::RCP<Vector> X,
430  Teuchos::RCP<const Vector> B )
431  {
432  return std::conditional_t<
433  solver_supports_scalar<ConcreteSolver, typename MatrixTraits<Matrix>::scalar_t>::value,
434  create_solver_with_supported_type<ConcreteSolver,Matrix,Vector>,
435  throw_no_scalar_support_exception<ConcreteSolver,Matrix,Vector> >::apply(A, X, B);
436  }
437  };
438 
448  template < template <class,class> class ConcreteSolver,
449  class Matrix,
450  class Vector >
451  struct handle_solver_matrix_and_type_support {
452  static Teuchos::RCP<Solver<Matrix,Vector> > apply(Teuchos::RCP<const Matrix> A,
453  Teuchos::RCP<Vector> X,
454  Teuchos::RCP<const Vector> B )
455  {
456  return std::conditional_t<
457  solver_supports_matrix<ConcreteSolver, Matrix>::value,
458  handle_solver_scalar_type_support<ConcreteSolver,Matrix,Vector>,
459  throw_no_matrix_support_exception<ConcreteSolver,Matrix,Vector> >::apply(A, X, B);
460  }
461  };
462 
464  // Query Functions //
466 
474  bool query(const char* solverName);
475 
476 
484  bool query(const std::string& solverName);
485 
486 
488  // Definitions //
490 
491  template <class Matrix,
492  class Vector >
493  Solver<Matrix,Vector>*
494  create(Matrix* A, Vector* X, Vector* B)
495  {
496  std::string solver = "Klu2";
497  // Pass non-owning RCP objects to other factory method
498  return( create(solver, rcp(A,false), rcp(X,false), rcp(B,false)).getRawPtr() );
499  }
500 
501 
502  template <class Matrix,
503  class Vector >
504  Teuchos::RCP<Solver<Matrix,Vector> >
505  create(Teuchos::RCP<const Matrix> A,
506  Teuchos::RCP<Vector> X,
507  Teuchos::RCP<const Vector> B)
508  {
509  std::string solver = "Klu2";
510  return( create(solver, A, X, B) );
511  }
512 
513 
514  template <class Matrix,
515  class Vector >
516  Solver<Matrix,Vector>*
517  create(const char* solverName, const Matrix* A, Vector* X, const Vector* B)
518  {
519  std::string solver = solverName;
520  // Pass non-owning Teuchos::RCP objects to other factory method
521  return( create(solver, rcp(A,false), rcp(X,false), rcp(B,false)).getRawPtr() );
522  }
523 
524 
525  template <class Matrix,
526  class Vector >
527  Teuchos::RCP<Solver<Matrix,Vector> >
528  create(const char* solverName,
529  const Teuchos::RCP<const Matrix> A,
530  const Teuchos::RCP<Vector> X,
531  const Teuchos::RCP<const Vector> B)
532  {
533  std::string solver = solverName;
534  return( create(solver, A, X, B) );
535  }
536 
537 
538  template <class Matrix,
539  class Vector >
540  Solver<Matrix,Vector>*
541  create(const std::string& solverName, const Matrix* A){
542  return( create(solverName, rcp(A,false),
543  Teuchos::RCP<Vector>(),
544  Teuchos::RCP<const Vector>()).getRawPtr() );
545  }
546 
547 
548  template <class Matrix,
549  class Vector >
550  Teuchos::RCP<Solver<Matrix,Vector> >
551  create(const std::string& solverName, const Teuchos::RCP<const Matrix> A){
552  return( create(solverName, A, Teuchos::RCP<Vector>(), Teuchos::RCP<const Vector>()) );
553  }
554 
555 
556  template <class Matrix,
557  class Vector >
558  Teuchos::RCP<Solver<Matrix,Vector> >
559  create(const std::string& solverName, const Matrix* A, Vector* X, const Vector* B)
560  {
561  // Pass non-owning Teuchos::RCP objects to other factory method
562  return( create(solverName, rcp(A,false), rcp(X,false), rcp(B,false)) );
563  }
564 
565 
566  template <class Matrix,
567  class Vector >
568  Teuchos::RCP<Solver<Matrix,Vector> >
569  create(const std::string& solver_name,
570  const Teuchos::RCP<const Matrix> A,
571  const Teuchos::RCP<Vector> X,
572  const Teuchos::RCP<const Vector> B)
573  {
574  std::string solverName = tolower(solver_name); // for easy string checking
575 
576  // Check for our native solver first. Treat KLU and KLU2 as equals.
577  //
578  // We use compiler guards in case a user does want to disable KLU2
579 #ifdef HAVE_AMESOS2_SHYLU_NODEBASKER
580  if((solverName == "ShyLUBasker") || (solverName == "shylubasker") || (solverName == "amesos2_shylubasker"))
581  {
582  return handle_solver_matrix_and_type_support<ShyLUBasker, Matrix,Vector>::apply(A,X,B);
583  }
584 #endif
585 
586 #ifdef HAVE_AMESOS2_BASKER
587  if((solverName == "Basker") || (solverName == "basker") || (solverName == "amesos2_basker"))
588  {
589  return handle_solver_matrix_and_type_support<Basker, Matrix,Vector>::apply(A,X,B);
590  }
591 #endif
592 
593 
594 #ifdef HAVE_AMESOS2_KLU2
595  if((solverName == "amesos2_klu2") || (solverName == "klu2") ||
596  (solverName == "amesos2_klu") || (solverName == "klu")){
597  return handle_solver_matrix_and_type_support<KLU2,Matrix,Vector>::apply(A, X, B);
598  }
599 #endif
600 
601 #ifdef HAVE_AMESOS2_SUPERLUDIST
602  if((solverName == "amesos2_superludist") ||
603  (solverName == "superludist") ||
604  (solverName == "amesos2_superlu_dist") ||
605  (solverName == "superlu_dist")){
606  return handle_solver_matrix_and_type_support<Superludist,Matrix,Vector>::apply(A, X, B);
607  }
608 #endif
609 
610 #ifdef HAVE_AMESOS2_SUPERLUMT
611  if((solverName == "amesos2_superlumt") ||
612  (solverName == "superlumt") ||
613  (solverName == "amesos2_superlu_mt") ||
614  (solverName == "superlu_mt")){
615  return handle_solver_matrix_and_type_support<Superlumt,Matrix,Vector>::apply(A, X, B);
616  }
617 #endif
618 
619 #ifdef HAVE_AMESOS2_UMFPACK
620  if((solverName == "amesos2_umfpack") ||
621  (solverName == "umfpack")){
622  return handle_solver_matrix_and_type_support<Umfpack,Matrix,Vector>::apply(A, X, B);
623  }
624 #endif
625 
626 #ifdef HAVE_AMESOS2_SHYLU_NODETACHO
627  if((solverName == "amesos2_tacho") ||
628  (solverName == "tacho")){
629  return handle_solver_matrix_and_type_support<TachoSolver,Matrix,Vector>::apply(A, X, B);
630  }
631 
632 #endif
633 
634 #ifdef HAVE_AMESOS2_SUPERLU
635  if((solverName == "amesos2_superlu") ||
636  (solverName == "superlu")){
637  return handle_solver_matrix_and_type_support<Superlu,Matrix,Vector>::apply(A, X, B);
638  }
639 #endif
640 
641 #ifdef HAVE_AMESOS2_PARDISO_MKL
642  if((solverName == "amesos2_pardiso_mkl") ||
643  (solverName == "pardiso_mkl") ||
644  (solverName == "amesos2_pardisomkl") ||
645  (solverName == "pardisomkl")){
646  return handle_solver_matrix_and_type_support<PardisoMKL,Matrix,Vector>::apply(A, X, B);
647  }
648 #endif
649 
650 #ifdef HAVE_AMESOS2_LAPACK
651  if((solverName == "amesos2_lapack") ||
652  (solverName == "lapack")){
653  return handle_solver_matrix_and_type_support<Lapack,Matrix,Vector>::apply(A, X, B);
654  }
655 #endif
656 
657 
658 #ifdef HAVE_AMESOS2_MUMPS
659  if((solverName == "MUMPS") || (solverName == "mumps") ||
660  (solverName == "amesos2_MUMPS") || (solverName == "amesos2_mumps"))
661  {
662  return handle_solver_matrix_and_type_support<MUMPS,Matrix,Vector>::apply(A,X,B);
663  }
664 #endif
665 
666 #ifdef HAVE_AMESOS2_STRUMPACK
667  if((solverName == "STRUMPACK") || (solverName == "strumpack") ||
668  (solverName == "amesos2_STRUMPACK") || (solverName == "amesos2_strumpack"))
669  {
670  return handle_solver_matrix_and_type_support<STRUMPACK,Matrix,Vector>::apply(A,X,B);
671  }
672 #endif
673 
674 #if defined (HAVE_AMESOS2_CHOLMOD) && defined (HAVE_AMESOS2_EXPERIMENTAL)
675  if(solverName == "amesos2_cholmod" || solverName == "cholmod")
676  return handle_solver_matrix_and_type_support<Cholmod,Matrix,Vector>::apply(A, X, B);
677 #endif
678 
679 #if defined (HAVE_AMESOS2_CUSOLVER) && defined (HAVE_AMESOS2_CUSPARSE)
680  if(solverName == "amesos2_cusolver" || solverName == "cusolver")
681  return handle_solver_matrix_and_type_support<cuSOLVER,Matrix,Vector>::apply(A, X, B);
682 #endif
683 
684  /* If none of the above conditionals are satisfied, then the solver
685  * requested is not yet supported. We throw a runtime exception stating
686  * this, and return null.
687  */
688  std::string err_msg = solver_name + " is not enabled or is not supported";
689  TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, err_msg);
690  //return( Teuchos::null ); // unreachable
691  }
692 
693 } // end namespace Amesos2
694 
695 #endif // AMESOS2_FACTORY_HPP
A templated adapter/wrapper class for Trilinos Multivector type classes. Provides the functions neces...
Simple compile-time assertion class.
Provides access to interesting solver traits.