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