Amesos2 - Direct Sparse Solver Interfaces  Version of the Day
Amesos2_Factory.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // Amesos2: Templated Direct Sparse Solver Package
4 //
5 // Copyright 2011 NTESS and the Amesos2 contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
48 #ifndef AMESOS2_FACTORY_HPP
49 #define AMESOS2_FACTORY_HPP
50 
51 #include "Amesos2_config.h"
52 
53 #include "Teuchos_CompilerCodeTweakMacros.hpp"
54 
55 #include "Amesos2_Solver.hpp"
56 #include "Amesos2_SolverTraits.hpp"
57 
58 #include "Teuchos_ScalarTraits.hpp"
60 #include "Amesos2_MatrixTraits.hpp"
61 #include "Amesos2_ctassert.hpp"
62 
63 #ifdef HAVE_AMESOS2_BASKER
64 #include "Amesos2_Basker.hpp"
65 #endif
66 
67 #ifdef HAVE_AMESOS2_SHYLU_NODEBASKER
68 #include "Amesos2_ShyLUBasker.hpp"
69 #endif
70 
71 #if defined(HAVE_AMESOS2_KLU2)
72 #include "Amesos2_KLU2.hpp"
73 #endif
74 
75 #ifdef HAVE_AMESOS2_SUPERLUDIST // Distributed-memory SuperLU
76 #include "Amesos2_Superludist.hpp"
77 #endif
78 
79 #ifdef HAVE_AMESOS2_SUPERLUMT // Multi-threaded SuperLU
80 #include "Amesos2_Superlumt.hpp"
81 #endif
82 
83 #ifdef HAVE_AMESOS2_UMFPACK // Umfpack
84 #include "Amesos2_Umfpack.hpp"
85 #endif
86 
87 #ifdef HAVE_AMESOS2_SHYLU_NODETACHO // Tacho
88 #include "Amesos2_Tacho.hpp"
89 #endif
90 
91 #ifdef HAVE_AMESOS2_SUPERLU // Sequential SuperLU
92 #include "Amesos2_Superlu.hpp"
93 #endif
94 
95 #ifdef HAVE_AMESOS2_PARDISO_MKL // MKL version of Pardiso
96 #include "Amesos2_PardisoMKL.hpp"
97 #endif
98 
99 #ifdef HAVE_AMESOS2_CSS_MKL // Cluster-Sparse solver from MKL
100 #include "Amesos2_CssMKL.hpp"
101 #endif
102 
103 #ifdef HAVE_AMESOS2_LAPACK
104 #include "Amesos2_Lapack.hpp"
105 #endif
106 
107 #if defined (HAVE_AMESOS2_CHOLMOD) && defined (HAVE_AMESOS2_EXPERIMENTAL)
108 #include "Amesos2_Cholmod.hpp"
109 #endif
110 
111 #if defined (HAVE_AMESOS2_CUSOLVER) && defined (HAVE_AMESOS2_CUSPARSE)
112 #include "Amesos2_cuSOLVER.hpp"
113 #endif
114 
115 #ifdef HAVE_AMESOS2_MUMPS
116 #include "Amesos2_MUMPS.hpp"
117 #endif
118 
119 #ifdef HAVE_AMESOS2_STRUMPACK
120 #include "Amesos2_STRUMPACK.hpp"
121 #endif
122 
123 
124 namespace Amesos2 {
125 
126  template <class,class> class Solver;
127 
128  /*
129  * Utility function to transform a string into all lowercase
130  */
131  std::string tolower(const std::string& s);
132 
133 
148  template < class Matrix,
149  class Vector >
150  Solver<Matrix,Vector>*
151  create(const Matrix* A, Vector* X, const Vector* B);
152 
153 
168  template < class Matrix,
169  class Vector >
170  Teuchos::RCP<Solver<Matrix,Vector> >
171  create(Teuchos::RCP<const Matrix> A,
172  Teuchos::RCP<Vector> X,
173  Teuchos::RCP<const Vector> B);
174 
175 
193  template < class Matrix,
194  class Vector >
195  Solver<Matrix,Vector>*
196  create(const char* solverName, const Matrix* A, Vector* X, const Vector* B);
197 
198 
215  template < class Matrix,
216  class Vector >
217  Teuchos::RCP<Solver<Matrix,Vector> >
218  create(const char* solverName,
219  const Teuchos::RCP<const Matrix> A,
220  const Teuchos::RCP<Vector> X,
221  const Teuchos::RCP<const Vector> B);
222 
223 
240  template < class Matrix,
241  class Vector >
242  Solver<Matrix,Vector>*
243  create(const std::string& solverName, const Matrix* A, Vector* X, const Vector* B);
244 
245 
262  template < class Matrix,
263  class Vector >
264  Teuchos::RCP<Solver<Matrix,Vector> >
265  create(const std::string& solverName,
266  const Teuchos::RCP<const Matrix> A,
267  const Teuchos::RCP<Vector> X,
268  const Teuchos::RCP<const Vector> B);
269 
270 
289  template < class Matrix,
290  class Vector >
291  Solver<Matrix,Vector>*
292  create(const std::string& solverName, const Matrix* A);
293 
294 
313  template < class Matrix,
314  class Vector >
315  Teuchos::RCP<Solver<Matrix,Vector> >
316  create(const std::string& solverName,
317  const Teuchos::RCP<const Matrix> A);
318 
319 
321  // Meta-functions to help with creation of solvers //
323 
324  template < template <class,class> class ConcreteSolver,
325  class Matrix,
326  class Vector >
327  struct create_solver_with_supported_type {
328  static Teuchos::RCP<Solver<Matrix,Vector> > apply(Teuchos::RCP<const Matrix> A,
329  Teuchos::RCP<Vector> X,
330  Teuchos::RCP<const Vector> B )
331  {
332  ctassert<
333  std::is_same_v<
334  typename MatrixTraits<Matrix>::scalar_t,
335  typename MultiVecAdapter<Vector>::scalar_t
336  >
337  > same_scalar_assertion;
338  (void)same_scalar_assertion; // This stops the compiler from warning about unused declared variables
339 
340  // If our assertion did not fail, then create and return a new solver
341  return rcp( new ConcreteSolver<Matrix,Vector>(A, X, B) );
342  }
343  };
344 
353 template < template <class,class> class ConcreteSolver,
354  class Matrix,
355  class Vector >
356 struct throw_no_scalar_support_exception {
357  static Teuchos::RCP<Solver<Matrix,Vector> > apply(Teuchos::RCP<const Matrix> A,
358  Teuchos::RCP<Vector> X,
359  Teuchos::RCP<const Vector> B )
360  {
361  // typedef ConcreteSolver<Matrix,Vector> concretesolver_matrix_vector;
362  typedef typename MatrixTraits<Matrix>::scalar_t scalar_t;
363  TEUCHOS_TEST_FOR_EXCEPTION( true,
364  std::invalid_argument,
365  "The requested Amesos2 "
366  // << concretesolver_matrix_vector::name <<
367  " solver interface does not support the " <<
368  Teuchos::ScalarTraits<scalar_t>::name() <<
369  " scalar type." );
370  }
371 };
372 
373 template < template <class,class> class ConcreteSolver,
374  class Matrix,
375  class Vector >
376 struct throw_no_matrix_support_exception {
377  static Teuchos::RCP<Solver<Matrix,Vector> > apply(Teuchos::RCP<const Matrix> A,
378  Teuchos::RCP<Vector> X,
379  Teuchos::RCP<const Vector> B )
380  {
381  TEUCHOS_TEST_FOR_EXCEPTION( true,
382  std::invalid_argument,
383  "This solver does not support the kokkos adapter." );
384  }
385 };
386 
396  template < template <class,class> class ConcreteSolver,
397  class Matrix,
398  class Vector >
399  struct handle_solver_scalar_type_support {
400  static Teuchos::RCP<Solver<Matrix,Vector> > apply(Teuchos::RCP<const Matrix> A,
401  Teuchos::RCP<Vector> X,
402  Teuchos::RCP<const Vector> B )
403  {
404  return std::conditional_t<
405  solver_supports_scalar<ConcreteSolver, typename MatrixTraits<Matrix>::scalar_t>::value,
406  create_solver_with_supported_type<ConcreteSolver,Matrix,Vector>,
407  throw_no_scalar_support_exception<ConcreteSolver,Matrix,Vector> >::apply(A, X, B);
408  }
409  };
410 
420  template < template <class,class> class ConcreteSolver,
421  class Matrix,
422  class Vector >
423  struct handle_solver_matrix_and_type_support {
424  static Teuchos::RCP<Solver<Matrix,Vector> > apply(Teuchos::RCP<const Matrix> A,
425  Teuchos::RCP<Vector> X,
426  Teuchos::RCP<const Vector> B )
427  {
428  return std::conditional_t<
429  solver_supports_matrix<ConcreteSolver, Matrix>::value,
430  handle_solver_scalar_type_support<ConcreteSolver,Matrix,Vector>,
431  throw_no_matrix_support_exception<ConcreteSolver,Matrix,Vector> >::apply(A, X, B);
432  }
433  };
434 
436  // Query Functions //
438 
446  bool query(const char* solverName);
447 
448 
456  bool query(const std::string& solverName);
457 
458 
460  // Definitions //
462 
463  template <class Matrix,
464  class Vector >
465  Solver<Matrix,Vector>*
466  create(Matrix* A, Vector* X, Vector* B)
467  {
468  std::string solver = "Klu2";
469  // Pass non-owning RCP objects to other factory method
470  return( create(solver, rcp(A,false), rcp(X,false), rcp(B,false)).getRawPtr() );
471  }
472 
473 
474  template <class Matrix,
475  class Vector >
476  Teuchos::RCP<Solver<Matrix,Vector> >
477  create(Teuchos::RCP<const Matrix> A,
478  Teuchos::RCP<Vector> X,
479  Teuchos::RCP<const Vector> B)
480  {
481  std::string solver = "Klu2";
482  return( create(solver, A, X, B) );
483  }
484 
485 
486  template <class Matrix,
487  class Vector >
488  Solver<Matrix,Vector>*
489  create(const char* solverName, const Matrix* A, Vector* X, const Vector* B)
490  {
491  std::string solver = solverName;
492  // Pass non-owning Teuchos::RCP objects to other factory method
493  return( create(solver, rcp(A,false), rcp(X,false), rcp(B,false)).getRawPtr() );
494  }
495 
496 
497  template <class Matrix,
498  class Vector >
499  Teuchos::RCP<Solver<Matrix,Vector> >
500  create(const char* solverName,
501  const Teuchos::RCP<const Matrix> A,
502  const Teuchos::RCP<Vector> X,
503  const Teuchos::RCP<const Vector> B)
504  {
505  std::string solver = solverName;
506  return( create(solver, A, X, B) );
507  }
508 
509 
510  template <class Matrix,
511  class Vector >
512  Solver<Matrix,Vector>*
513  create(const std::string& solverName, const Matrix* A){
514  return( create(solverName, rcp(A,false),
515  Teuchos::RCP<Vector>(),
516  Teuchos::RCP<const Vector>()).getRawPtr() );
517  }
518 
519 
520  template <class Matrix,
521  class Vector >
522  Teuchos::RCP<Solver<Matrix,Vector> >
523  create(const std::string& solverName, const Teuchos::RCP<const Matrix> A){
524  return( create(solverName, A, Teuchos::RCP<Vector>(), Teuchos::RCP<const Vector>()) );
525  }
526 
527 
528  template <class Matrix,
529  class Vector >
530  Teuchos::RCP<Solver<Matrix,Vector> >
531  create(const std::string& solverName, const Matrix* A, Vector* X, const Vector* B)
532  {
533  // Pass non-owning Teuchos::RCP objects to other factory method
534  return( create(solverName, rcp(A,false), rcp(X,false), rcp(B,false)) );
535  }
536 
537 
538  template <class Matrix,
539  class Vector >
540  Teuchos::RCP<Solver<Matrix,Vector> >
541  create(const std::string& solver_name,
542  const Teuchos::RCP<const Matrix> A,
543  const Teuchos::RCP<Vector> X,
544  const Teuchos::RCP<const Vector> B)
545  {
546  std::string solverName = tolower(solver_name); // for easy string checking
547 
548  // Check for our native solver first. Treat KLU and KLU2 as equals.
549  //
550  // We use compiler guards in case a user does want to disable KLU2
551 #ifdef HAVE_AMESOS2_SHYLU_NODEBASKER
552  if((solverName == "ShyLUBasker") || (solverName == "shylubasker") || (solverName == "amesos2_shylubasker"))
553  {
554  return handle_solver_matrix_and_type_support<ShyLUBasker, Matrix,Vector>::apply(A,X,B);
555  }
556 #endif
557 
558 #ifdef HAVE_AMESOS2_BASKER
559  if((solverName == "Basker") || (solverName == "basker") || (solverName == "amesos2_basker"))
560  {
561  return handle_solver_matrix_and_type_support<Basker, Matrix,Vector>::apply(A,X,B);
562  }
563 #endif
564 
565 
566 #ifdef HAVE_AMESOS2_KLU2
567  if((solverName == "amesos2_klu2") || (solverName == "klu2") ||
568  (solverName == "amesos2_klu") || (solverName == "klu")){
569  return handle_solver_matrix_and_type_support<KLU2,Matrix,Vector>::apply(A, X, B);
570  }
571 #endif
572 
573 #ifdef HAVE_AMESOS2_SUPERLUDIST
574  if((solverName == "amesos2_superludist") ||
575  (solverName == "superludist") ||
576  (solverName == "amesos2_superlu_dist") ||
577  (solverName == "superlu_dist")){
578  return handle_solver_matrix_and_type_support<Superludist,Matrix,Vector>::apply(A, X, B);
579  }
580 #endif
581 
582 #ifdef HAVE_AMESOS2_SUPERLUMT
583  if((solverName == "amesos2_superlumt") ||
584  (solverName == "superlumt") ||
585  (solverName == "amesos2_superlu_mt") ||
586  (solverName == "superlu_mt")){
587  return handle_solver_matrix_and_type_support<Superlumt,Matrix,Vector>::apply(A, X, B);
588  }
589 #endif
590 
591 #ifdef HAVE_AMESOS2_UMFPACK
592  if((solverName == "amesos2_umfpack") ||
593  (solverName == "umfpack")){
594  return handle_solver_matrix_and_type_support<Umfpack,Matrix,Vector>::apply(A, X, B);
595  }
596 #endif
597 
598 #ifdef HAVE_AMESOS2_SHYLU_NODETACHO
599  if((solverName == "amesos2_tacho") ||
600  (solverName == "tacho")){
601  return handle_solver_matrix_and_type_support<TachoSolver,Matrix,Vector>::apply(A, X, B);
602  }
603 
604 #endif
605 
606 #ifdef HAVE_AMESOS2_SUPERLU
607  if((solverName == "amesos2_superlu") ||
608  (solverName == "superlu")){
609  return handle_solver_matrix_and_type_support<Superlu,Matrix,Vector>::apply(A, X, B);
610  }
611 #endif
612 
613 #ifdef HAVE_AMESOS2_PARDISO_MKL
614  if((solverName == "amesos2_pardiso_mkl") ||
615  (solverName == "pardiso_mkl") ||
616  (solverName == "amesos2_pardisomkl") ||
617  (solverName == "pardisomkl")){
618  return handle_solver_matrix_and_type_support<PardisoMKL,Matrix,Vector>::apply(A, X, B);
619  }
620 #endif
621 #ifdef HAVE_AMESOS2_CSS_MKL
622  if((solverName == "amesos2_css_mkl") ||
623  (solverName == "css_mkl") ||
624  (solverName == "amesos2_cssmkl") ||
625  (solverName == "cssmkl")){
626  return handle_solver_matrix_and_type_support<CssMKL,Matrix,Vector>::apply(A, X, B);
627  }
628 #endif
629 
630 #ifdef HAVE_AMESOS2_LAPACK
631  if((solverName == "amesos2_lapack") ||
632  (solverName == "lapack")){
633  return handle_solver_matrix_and_type_support<Lapack,Matrix,Vector>::apply(A, X, B);
634  }
635 #endif
636 
637 
638 #ifdef HAVE_AMESOS2_MUMPS
639  if((solverName == "MUMPS") || (solverName == "mumps") ||
640  (solverName == "amesos2_MUMPS") || (solverName == "amesos2_mumps"))
641  {
642  return handle_solver_matrix_and_type_support<MUMPS,Matrix,Vector>::apply(A,X,B);
643  }
644 #endif
645 
646 #ifdef HAVE_AMESOS2_STRUMPACK
647  if((solverName == "STRUMPACK") || (solverName == "strumpack") ||
648  (solverName == "amesos2_STRUMPACK") || (solverName == "amesos2_strumpack"))
649  {
650  return handle_solver_matrix_and_type_support<STRUMPACK,Matrix,Vector>::apply(A,X,B);
651  }
652 #endif
653 
654 #if defined (HAVE_AMESOS2_CHOLMOD) && defined (HAVE_AMESOS2_EXPERIMENTAL)
655  if(solverName == "amesos2_cholmod" || solverName == "cholmod")
656  return handle_solver_matrix_and_type_support<Cholmod,Matrix,Vector>::apply(A, X, B);
657 #endif
658 
659 #if defined (HAVE_AMESOS2_CUSOLVER) && defined (HAVE_AMESOS2_CUSPARSE)
660  if(solverName == "amesos2_cusolver" || solverName == "cusolver")
661  return handle_solver_matrix_and_type_support<cuSOLVER,Matrix,Vector>::apply(A, X, B);
662 #endif
663 
664  /* If none of the above conditionals are satisfied, then the solver
665  * requested is not yet supported. We throw a runtime exception stating
666  * this, and return null.
667  */
668  std::string err_msg = solver_name + " is not enabled or is not supported";
669  TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument, err_msg);
670  //return( Teuchos::null ); // unreachable
671  TEUCHOS_UNREACHABLE_RETURN(Teuchos::null);
672  }
673 
674 } // end namespace Amesos2
675 
676 #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.