MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_AmesosSmoother.cpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // MueLu: A package for multigrid based preconditioning
4 //
5 // Copyright 2012 NTESS and the MueLu contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #include <algorithm>
11 
12 #include "MueLu_ConfigDefs.hpp"
13 
14 #if defined(HAVE_MUELU_EPETRA) && defined(HAVE_MUELU_AMESOS)
15 
16 #include <Epetra_LinearProblem.h>
17 
18 #include <Amesos_config.h>
19 #include <Amesos.h>
20 #include <Amesos_BaseSolver.h>
21 
22 #include "MueLu_AmesosSmoother.hpp"
23 
24 #include "MueLu_Level.hpp"
25 #include "MueLu_Utilities.hpp"
26 #include "MueLu_Monitor.hpp"
27 
28 namespace MueLu {
29 
30 template <class Node>
31 AmesosSmoother<Node>::AmesosSmoother(const std::string& type, const Teuchos::ParameterList& paramList)
32  : type_(type) {
33  this->SetParameterList(paramList);
34 
35  if (!type_.empty()) {
36  // Transform string to "Abcde" notation
37  std::transform(type_.begin(), type_.end(), type_.begin(), ::tolower);
38  std::transform(type_.begin(), ++type_.begin(), type_.begin(), ::toupper);
39  }
40  if (type_ == "Amesos_klu") type_ = "Klu";
41  if (type_ == "Klu2") type_ = "Klu";
42  if (type_ == "Amesos_umfpack") type_ = "Umfpack";
43  if (type_ == "Superlu_dist") type_ = "Superludist";
44  if (type_ == "Amesos_mumps") type_ = "Mumps";
45 
46  // Try to come up with something availble
47  // Order corresponds to our preference
48  // TODO: It would be great is Amesos provides directly this kind of logic for us
49  std::string oldtype = type_;
50  if (type_ == "" || Amesos().Query(type_) == false) {
51 #if defined(HAVE_AMESOS_SUPERLU)
52  type_ = "Superlu";
53 #elif defined(HAVE_AMESOS_KLU)
54  type_ = "Klu";
55 #elif defined(HAVE_AMESOS_SUPERLUDIST)
56  type_ = "Superludist";
57 #elif defined(HAVE_AMESOS_UMFPACK)
58  type_ = "Umfpack";
59 #else
60  this->declareConstructionOutcome(true, "Amesos has been compiled without SuperLU_DIST, SuperLU, Umfpack or Klu. By default, MueLu tries" +
61  "to use one of these libraries. Amesos must be compiled with one of these solvers, " +
62  "or a valid Amesos solver has to be specified explicitly.");
63  return;
64 #endif
65  if (oldtype != "")
66  this->GetOStream(Warnings0) << "MueLu::AmesosSmoother: \"" << oldtype << "\" is not available. Using \"" << type_ << "\" instead" << std::endl;
67  else
68  this->GetOStream(Runtime1) << "MueLu::AmesosSmoother: using \"" << type_ << "\"" << std::endl;
69  }
70  this->declareConstructionOutcome(false, "");
71 }
72 
73 template <class Node>
74 void AmesosSmoother<Node>::DeclareInput(Level& currentLevel) const {
75  this->Input(currentLevel, "A");
76 }
77 
78 template <class Node>
79 void AmesosSmoother<Node>::Setup(Level& currentLevel) {
80  FactoryMonitor m(*this, "Setup Smoother", currentLevel);
81 
82  if (SmootherPrototype::IsSetup() == true)
83  this->GetOStream(Warnings0) << "MueLu::AmesosSmoother::Setup(): Setup() has already been called" << std::endl;
84 
85  A_ = Factory::Get<RCP<Matrix> >(currentLevel, "A");
86 
88  linearProblem_ = rcp(new Epetra_LinearProblem());
89  linearProblem_->SetOperator(epA.get());
90 
91  Amesos factory;
92  prec_ = rcp(factory.Create(type_, *linearProblem_));
93  TEUCHOS_TEST_FOR_EXCEPTION(prec_ == Teuchos::null, Exceptions::RuntimeError, "MueLu::AmesosSmoother::Setup(): Solver '" + type_ + "' not supported by Amesos");
94 
95  // set Reindex flag, if A is distributed with non-contiguous maps
96  // unfortunately there is no reindex for Amesos2, yet. So, this only works for Epetra based problems
97  if (A_->getRowMap()->isDistributed() == true && A_->getRowMap()->isContiguous() == false)
98  const_cast<ParameterList&>(this->GetParameterList()).set("Reindex", true);
99 
100  const ParameterList& paramList = this->GetParameterList();
101  RCP<ParameterList> precList = this->RemoveFactoriesFromList(paramList);
102 
103  prec_->SetParameters(*precList);
104 
105  const_cast<ParameterList&>(paramList).setParameters(*precList);
106 
107  int r = prec_->NumericFactorization();
108  TEUCHOS_TEST_FOR_EXCEPTION(r != 0, Exceptions::RuntimeError, "MueLu::AmesosSmoother::Setup(): Amesos solver returns value of " + Teuchos::toString(r) + " during NumericFactorization()");
109 
111 }
112 
113 template <class Node>
114 void AmesosSmoother<Node>::Apply(MultiVector& X, const MultiVector& B, bool InitialGuessIsZero) const {
115  TEUCHOS_TEST_FOR_EXCEPTION(SmootherPrototype::IsSetup() == false, Exceptions::RuntimeError, "MueLu::AmesosSmoother::Apply(): Setup() has not been called");
116 
119  // Epetra_LinearProblem takes the right-hand side as a non-const pointer.
120  // I think this const_cast is safe because Amesos won't modify the rhs.
121  Epetra_MultiVector& nonconstB = const_cast<Epetra_MultiVector&>(epB);
122 
123  linearProblem_->SetLHS(&epX);
124  linearProblem_->SetRHS(&nonconstB);
125 
126  prec_->Solve();
127 
128  // Don't keep pointers to our vectors in the Epetra_LinearProblem.
129  linearProblem_->SetLHS(0);
130  linearProblem_->SetRHS(0);
131 }
132 
133 template <class Node>
135  return rcp(new AmesosSmoother<Node>(*this));
136 }
137 
138 template <class Node>
140  std::ostringstream out;
142  out << "{type = " << type_ << "}";
143  return out.str();
144 }
145 
146 // using MueLu::Describable::describe; // overloading, not hiding
147 template <class Node>
150 
151  if (verbLevel & Parameters0)
152  out0 << "Prec. type: " << type_ << std::endl;
153 
154  if (verbLevel & Parameters1) {
155  out0 << "Parameter list: " << std::endl;
156  Teuchos::OSTab tab2(out);
157  out << this->GetParameterList();
158  }
159 
160  if (verbLevel & External)
161  if (prec_ != Teuchos::null) {
162  prec_->PrintStatus();
163  prec_->PrintTiming();
164  }
165 
166  if (verbLevel & Debug) {
167  out0 << "IsSetup: " << Teuchos::toString(SmootherPrototype::IsSetup()) << std::endl
168  << "-" << std::endl
169  << "RCP<A_>: " << A_ << std::endl
170  << "RCP<linearProblem__>: " << linearProblem_ << std::endl
171  << "RCP<prec_>: " << prec_ << std::endl;
172  }
173 }
174 
175 template <class Node>
177  // FIXME: This is a placeholder
179 }
180 
181 } // namespace MueLu
182 
183 // The AmesosSmoother is only templated on the Node, since it is an Epetra only object
184 // Therefore we do not need the full ETI instantiations as we do for the other MueLu
185 // objects which are instantiated on all template parameters.
186 #if defined(HAVE_MUELU_EPETRA)
188 #endif
189 
190 #endif // HAVE_MUELU_EPETRA && HAVE_MUELU_AMESOS
Important warning messages (one line)
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
void Apply(MultiVector &X, const MultiVector &B, bool=false) const
Apply the direct solver.
Print external lib objects.
static RCP< Epetra_CrsMatrix > Op2NonConstEpetraCrs(RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> Op)
Timer to be used in factories. Similar to Monitor but with additional timers.
AmesosSmoother(const std::string &type="", const Teuchos::ParameterList &paramList=Teuchos::ParameterList())
Constructor.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
std::string description() const
Return a simple one-line description of this object.
Print additional debugging information.
std::string tolower(const std::string &str)
void Setup(Level &currentLevel)
Set up the direct solver. This creates the underlying Amesos solver object according to the parameter...
virtual void SetParameterList(const Teuchos::ParameterList &paramList)
Set parameters from a parameter list and return with default values.
std::string type_
amesos-specific key phrase that denote smoother type
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
static RCP< Epetra_MultiVector > MV2NonConstEpetraMV(RCP< Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node >> vec)
void declareConstructionOutcome(bool fail, std::string msg)
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:63
RCP< SmootherPrototype > Copy() const
bool IsSetup() const
Get the state of a smoother prototype.
#define MUELU_DESCRIBE
Helper macro for implementing Describable::describe() for BaseClass objects.
Print class parameters.
Amesos_BaseSolver * Create(const char *ClassType, const Epetra_LinearProblem &LinearProblem)
static RCP< const Epetra_MultiVector > MV2EpetraMV(RCP< Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node >> const vec)
Helper utility to pull out the underlying Epetra objects from an Xpetra object.
Print class parameters (more parameters, more verbose)
size_t getNodeSmootherComplexity() const
Get a rough estimate of cost per iteration.
Exception throws to report errors in the internal logical of the program.
Description of what is happening (more verbose)
void print(Teuchos::FancyOStream &out, const VerbLevel verbLevel=Default) const
Print the object with some verbosity level to an FancyOStream object.
virtual std::string description() const
Return a simple one-line description of this object.
std::string toString(const T &t)
bool Query(const char *ClassType)
void DeclareInput(Level &currentLevel) const
Input.
Class that encapsulates Amesos direct solvers.