MueLu  Version of the Day
MueLu_BlockedJacobiSmoother_def.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
6 // Copyright 2012 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
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 
47 #ifndef MUELU_BLOCKEDJACOBISMOOTHER_DEF_HPP_
48 #define MUELU_BLOCKEDJACOBISMOOTHER_DEF_HPP_
49 
50 #include "Teuchos_ArrayViewDecl.hpp"
51 #include "Teuchos_ScalarTraits.hpp"
52 
53 #include "MueLu_ConfigDefs.hpp"
54 
55 #include <Xpetra_BlockReorderManager.hpp>
56 #include <Xpetra_Matrix.hpp>
57 #include <Xpetra_BlockedCrsMatrix.hpp>
58 #include <Xpetra_ReorderedBlockedCrsMatrix.hpp>
59 #include <Xpetra_ReorderedBlockedMultiVector.hpp>
60 #include <Xpetra_MultiVectorFactory.hpp>
61 
63 #include "MueLu_Level.hpp"
64 #include "MueLu_Utilities.hpp"
65 #include "MueLu_Monitor.hpp"
66 #include "MueLu_HierarchyUtils.hpp"
67 #include "MueLu_SmootherBase.hpp"
68 
69 namespace MueLu {
70 
71  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
73  : type_("blocked Jacobi"), A_(Teuchos::null)
74  {
75  FactManager_.reserve(10); // TODO fix me!
76  }
77 
78  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
80 
81  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
83  RCP<ParameterList> validParamList = rcp(new ParameterList());
84 
85  validParamList->set<RCP<const FactoryBase> >("A", Teuchos::null, "Generating factory of the matrix A");
86  validParamList->set<Scalar>("Damping factor", 1.0, "Damping/Scaling factor in Jacobi");
87  validParamList->set<LocalOrdinal>("Sweeps", 1, "Number of sweeps (default = 1)");
88 
89  return validParamList;
90  }
91 
92  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
93  void BlockedJacobiSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::AddFactoryManager(RCP<const FactoryManagerBase> FactManager, int pos) {
94  TEUCHOS_TEST_FOR_EXCEPTION(pos < 0, Exceptions::RuntimeError, "MueLu::BlockedJacobiSmoother::AddFactoryManager: parameter \'pos\' must not be negative! error.");
95 
96  size_t myPos = Teuchos::as<size_t>(pos);
97 
98  if (myPos < FactManager_.size()) {
99  // replace existing entris in FactManager_ vector
100  FactManager_.at(myPos) = FactManager;
101  } else if( myPos == FactManager_.size()) {
102  // add new Factory manager in the end of the vector
103  FactManager_.push_back(FactManager);
104  } else { // if(myPos > FactManager_.size())
105  RCP<Teuchos::FancyOStream> out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
106  *out << "Warning: cannot add new FactoryManager at proper position " << pos << ". The FactoryManager is just appended to the end. Check this!" << std::endl;
107 
108  // add new Factory manager in the end of the vector
109  FactManager_.push_back(FactManager);
110  }
111  }
112 
113  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
115  //this->Input(currentLevel, "A");
116  // TODO: check me: why is this->Input not freeing properly A in release mode?
117  currentLevel.DeclareInput("A",this->GetFactory("A").get());
118 
119  // loop over all factory managers for the subblocks of blocked operator A
120  std::vector<Teuchos::RCP<const FactoryManagerBase> >::const_iterator it;
121  for(it = FactManager_.begin(); it!=FactManager_.end(); ++it) {
122  SetFactoryManager currentSFM (rcpFromRef(currentLevel), *it);
123 
124  // request "Smoother" for current subblock row.
125  currentLevel.DeclareInput("PreSmoother",(*it)->GetFactory("Smoother").get());
126 
127  // request "A" for current subblock row (only needed for Thyra mode)
128  currentLevel.DeclareInput("A",(*it)->GetFactory("A").get());
129  }
130  }
131 
132  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
134 
135  RCP<Teuchos::FancyOStream> out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout));
136 
137  FactoryMonitor m(*this, "Setup blocked Jacobi Smoother", currentLevel);
138  if (SmootherPrototype::IsSetup() == true) this->GetOStream(Warnings0) << "MueLu::BlockedJacobiSmoother::Setup(): Setup() has already been called";
139 
140  // extract blocked operator A from current level
141  A_ = Factory::Get< RCP<Matrix> >(currentLevel, "A"); // A needed for extracting map extractors
142  RCP<BlockedCrsMatrix> bA = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A_);
143  TEUCHOS_TEST_FOR_EXCEPTION(bA==Teuchos::null, Exceptions::BadCast, "MueLu::BlockedPFactory::Build: input matrix A is not of type BlockedCrsMatrix! error.");
144 
145  // plausibility check
146  TEUCHOS_TEST_FOR_EXCEPTION(bA->Rows() != FactManager_.size(), Exceptions::RuntimeError, "MueLu::BlockedJacobiSmoother::Setup: number of block rows of A is " << bA->Rows() << " and does not match number of SubFactoryManagers " << FactManager_.size() << ". error.");
147  TEUCHOS_TEST_FOR_EXCEPTION(bA->Cols() != FactManager_.size(), Exceptions::RuntimeError, "MueLu::BlockedJacobiSmoother::Setup: number of block cols of A is " << bA->Cols() << " and does not match number of SubFactoryManagers " << FactManager_.size() << ". error.");
148 
149  // store map extractors
150  rangeMapExtractor_ = bA->getRangeMapExtractor();
151  domainMapExtractor_ = bA->getDomainMapExtractor();
152 
153  // loop over all factory managers for the subblocks of blocked operator A
154  std::vector<Teuchos::RCP<const FactoryManagerBase> >::const_iterator it;
155  for(it = FactManager_.begin(); it!=FactManager_.end(); ++it) {
156  SetFactoryManager currentSFM (rcpFromRef(currentLevel), *it);
157 
158  // extract Smoother for current block row
159  RCP<const SmootherBase> Smoo = currentLevel.Get< RCP<SmootherBase> >("PreSmoother",(*it)->GetFactory("Smoother").get());
160  Inverse_.push_back(Smoo);
161 
162  // store whether subblock matrix is blocked or not!
163  RCP<Matrix> Aii = currentLevel.Get< RCP<Matrix> >("A",(*it)->GetFactory("A").get());
164  bIsBlockedOperator_.push_back(Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Aii)!=Teuchos::null);
165  }
166 
168  }
169 
170  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
171  void BlockedJacobiSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Apply(MultiVector &X, const MultiVector& B, bool InitialGuessIsZero) const
172  {
173  TEUCHOS_TEST_FOR_EXCEPTION(SmootherPrototype::IsSetup() == false, Exceptions::RuntimeError, "MueLu::BlockedJacobiSmoother::Apply(): Setup() has not been called");
174 
175 #if 0 // def HAVE_MUELU_DEBUG
176  // TODO simplify this debug check
177  RCP<MultiVector> rcpDebugX = Teuchos::rcpFromRef(X);
178  RCP<const MultiVector> rcpDebugB = Teuchos::rcpFromRef(B);
179  RCP<BlockedMultiVector> rcpBDebugX = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(rcpDebugX);
180  RCP<const BlockedMultiVector> rcpBDebugB = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpDebugB);
181  //RCP<BlockedCrsMatrix> bA = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A_);
182  if(rcpBDebugB.is_null() == false) {
183  //this->GetOStream(Runtime1) << "BlockedJacobi: B is a BlockedMultiVector of size " << B.getMap()->getGlobalNumElements() << " with " << rcpBDebugB->getBlockedMap()->getNumMaps() << " blocks." << std::endl;
184  //TEUCHOS_TEST_FOR_EXCEPTION(A_->getRangeMap()->isSameAs(*(B.getMap())) == false, Exceptions::RuntimeError, "MueLu::BlockedJacobiSmoother::Apply(): The map of RHS vector B is not the same as range map of the blocked operator A. Please check the map of B and A.");
185  } else {
186  //this->GetOStream(Runtime1) << "BlockedJacobi: B is a MultiVector of size " << B.getMap()->getGlobalNumElements() << std::endl;
187  //TEUCHOS_TEST_FOR_EXCEPTION(bA->getFullRangeMap()->isSameAs(*(B.getMap())) == false, Exceptions::RuntimeError, "MueLu::BlockedJacobiSmoother::Apply(): The map of RHS vector B is not the same as range map of the blocked operator A. Please check the map of B and A.");
188  }
189  if(rcpBDebugX.is_null() == false) {
190  //this->GetOStream(Runtime1) << "BlockedJacobi: X is a BlockedMultiVector of size " << X.getMap()->getGlobalNumElements() << " with " << rcpBDebugX->getBlockedMap()->getNumMaps() << " blocks." << std::endl;
191  //TEUCHOS_TEST_FOR_EXCEPTION(A_->getDomainMap()->isSameAs(*(X.getMap())) == false, Exceptions::RuntimeError, "MueLu::BlockedJacobiSmoother::Apply(): The map of the solution vector X is not the same as domain map of the blocked operator A. Please check the map of X and A.");
192  } else {
193  //this->GetOStream(Runtime1) << "BlockedJacobi: X is a MultiVector of size " << X.getMap()->getGlobalNumElements() << std::endl;
194  //TEUCHOS_TEST_FOR_EXCEPTION(bA->getFullDomainMap()->isSameAs(*(X.getMap())) == false, Exceptions::RuntimeError, "MueLu::BlockedJacobiSmoother::Apply(): The map of the solution vector X is not the same as domain map of the blocked operator A. Please check the map of X and A.");
195  }
196 
197 
198 #endif
199  SC zero = Teuchos::ScalarTraits<SC>::zero(), one = Teuchos::ScalarTraits<SC>::one();
200 
201  // Input variables used for the rest of the algorithm
202  RCP<MultiVector> rcpX = Teuchos::rcpFromRef(X);
203  RCP<const MultiVector> rcpB = Teuchos::rcpFromRef(B);
204 
205  // make sure that both rcpX and rcpB are BlockedMultiVector objects
206  bool bCopyResultX = false;
207  RCP<BlockedCrsMatrix> bA = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A_);
208  MUELU_TEST_FOR_EXCEPTION(bA.is_null() == true, Exceptions::RuntimeError, "MueLu::BlockedJacobiSmoother::Apply(): A_ must be a BlockedCrsMatrix");
209  RCP<BlockedMultiVector> bX = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(rcpX);
210  RCP<const BlockedMultiVector> bB = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpB);
211 
212  if(bX.is_null() == true) {
213  RCP<MultiVector> test = Teuchos::rcp(new BlockedMultiVector(bA->getBlockedDomainMap(),rcpX));
214  rcpX.swap(test);
215  bCopyResultX = true;
216  }
217 
218  if(bB.is_null() == true) {
219  RCP<const MultiVector> test = Teuchos::rcp(new BlockedMultiVector(bA->getBlockedRangeMap(),rcpB));
220  rcpB.swap(test);
221  }
222 
223  // we now can guarantee that X and B are blocked multi vectors
224  bX = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(rcpX);
225  bB = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpB);
226 
227  // check the type of operator
228  RCP<Xpetra::ReorderedBlockedCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > rbA = Teuchos::rcp_dynamic_cast<Xpetra::ReorderedBlockedCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(bA);
229  if(rbA.is_null() == false) {
230  // A is a ReorderedBlockedCrsMatrix
231  Teuchos::RCP<const Xpetra::BlockReorderManager > brm = rbA->getBlockReorderManager();
232 
233  // check type of X vector
234  if(bX->getBlockedMap()->getNumMaps() != bA->getDomainMapExtractor()->NumMaps()) {
235  // X is a blocked multi vector but incompatible to the reordered blocked operator A
236  Teuchos::RCP<MultiVector> test =
237  buildReorderedBlockedMultiVector(brm, bX);
238  rcpX.swap(test);
239  }
240  if(bB->getBlockedMap()->getNumMaps() != bA->getRangeMapExtractor()->NumMaps()) {
241  // B is a blocked multi vector but incompatible to the reordered blocked operator A
242  Teuchos::RCP<const MultiVector> test =
243  buildReorderedBlockedMultiVector(brm, bB);
244  rcpB.swap(test);
245  }
246  }
247 
248 
249  // check the type of operator
250  /*RCP<BlockedCrsMatrix> bA = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A_);
251  MUELU_TEST_FOR_EXCEPTION(bA.is_null() == true, Exceptions::RuntimeError, "MueLu::BlockedJacobiSmoother::Apply(): A_ must be a BlockedCrsMatrix");
252  RCP<Xpetra::ReorderedBlockedCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > rbA = Teuchos::rcp_dynamic_cast<Xpetra::ReorderedBlockedCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(bA);
253  if(rbA.is_null() == false) {
254  // A is a ReorderedBlockedCrsMatrix
255  Teuchos::RCP<const Xpetra::BlockReorderManager > brm = rbA->getBlockReorderManager();
256 
257  // check type of vectors
258  RCP<BlockedMultiVector> bX = Teuchos::rcp_dynamic_cast<BlockedMultiVector>(rcpX);
259  RCP<const BlockedMultiVector> bB = Teuchos::rcp_dynamic_cast<const BlockedMultiVector>(rcpB);
260 
261  // check type of X vector
262  if(bX.is_null() == false && bX->getBlockedMap()->getNumMaps() != bA->getDomainMapExtractor()->NumMaps()) {
263  RCP<ReorderedBlockedMultiVector> rbX = Teuchos::rcp_dynamic_cast<ReorderedBlockedMultiVector>(bX);
264  if(rbX.is_null() == true) {
265  // X is a blocked multi vector but not reordered
266  // However, A is a reordered blocked operator
267  // We have to make sure, that A and X use compatible maps
268  Teuchos::RCP<MultiVector> test =
269  buildReorderedBlockedMultiVector(brm, bX);
270  rcpX.swap(test);
271  }
272  }
273  if(bB.is_null() == false && bB->getBlockedMap()->getNumMaps() != bA->getRangeMapExtractor()->NumMaps()) {
274  RCP<const ReorderedBlockedMultiVector> rbB = Teuchos::rcp_dynamic_cast<const ReorderedBlockedMultiVector>(bB);
275  if(rbB.is_null() == true) {
276  // B is a blocked multi vector but not reordered
277  // However, A is a reordered blocked operator
278  // We have to make sure, that A and X use compatible maps
279  Teuchos::RCP<const MultiVector> test =
280  buildReorderedBlockedMultiVector(brm, bB);
281  rcpB.swap(test);
282  }
283  }
284  }*/
285 
286  // Throughout the rest of the algorithm rcpX and rcpB are used for solution vector and RHS
287 
288  RCP<MultiVector> residual = MultiVectorFactory::Build(rcpB->getMap(), rcpB->getNumVectors());
289  RCP<MultiVector> tempres = MultiVectorFactory::Build(rcpB->getMap(), rcpB->getNumVectors());
290 
291  // extract parameters from internal parameter list
292  const ParameterList & pL = Factory::GetParameterList();
293  LocalOrdinal nSweeps = pL.get<LocalOrdinal>("Sweeps");
294  Scalar omega = pL.get<Scalar>("Damping factor");
295 
296  // outer Richardson loop
297  for (LocalOrdinal run = 0; run < nSweeps; ++run) {
298  // one sweep of Jacobi: loop over all block rows
299  for(size_t i = 0; i<Inverse_.size(); i++) {
300 
301  // calculate block residual r = B-A*X
302  // note: A_ is the full blocked operator
303  residual->update(1.0,*rcpB,0.0); // r = B
304  if(InitialGuessIsZero == false || i > 0 || run > 0)
305  bA->bgs_apply(*rcpX, *residual, i, Teuchos::NO_TRANS, -1.0, 1.0);
306 
307  // extract corresponding subvectors from X and residual
308  bool bRangeThyraMode = rangeMapExtractor_->getThyraMode();
309  bool bDomainThyraMode = domainMapExtractor_->getThyraMode();
310  Teuchos::RCP<MultiVector> Xi = domainMapExtractor_->ExtractVector(rcpX, i, bDomainThyraMode);
311  Teuchos::RCP<MultiVector> ri = rangeMapExtractor_->ExtractVector(residual, i, bRangeThyraMode);
312  Teuchos::RCP<MultiVector> tXi = domainMapExtractor_->getVector(i, X.getNumVectors(), bDomainThyraMode);
313 
314  // apply solver/smoother
315  Inverse_.at(i)->Apply(*tXi, *ri, false);
316 
317  // update vector
318  Xi->update(omega,*tXi,1.0); // X_{i+1} = X_i + omega \Delta X_i
319 
320  }
321  }
322 
323  if (bCopyResultX == true) {
324  RCP<MultiVector> Xmerged = bX->Merge();
325  X.update(one, *Xmerged, zero);
326  }
327  }
328 
329  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
330  RCP<MueLu::SmootherPrototype<Scalar, LocalOrdinal, GlobalOrdinal, Node> > BlockedJacobiSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Copy() const {
331  return rcp( new BlockedJacobiSmoother(*this) );
332  }
333 
334  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
336  std::ostringstream out;
338  out << "{type = " << type_ << "}";
339  return out.str();
340  }
341 
342  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
343  void BlockedJacobiSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::print(Teuchos::FancyOStream &out, const VerbLevel verbLevel) const {
345 
346  // extract parameters from internal parameter list
347  const ParameterList & pL = Factory::GetParameterList();
348  LocalOrdinal nSweeps = pL.get<LocalOrdinal>("Sweeps");
349  Scalar omega = pL.get<Scalar>("Damping factor");
350 
351  if (verbLevel & Parameters0) {
352  out0 << "Prec. type: " << type_ << " Sweeps: " << nSweeps << " damping: " << omega << std::endl;
353  }
354 
355  if (verbLevel & Debug) {
356  out0 << "IsSetup: " << Teuchos::toString(SmootherPrototype::IsSetup()) << std::endl;
357  }
358  }
359 
360  template <class Scalar,class LocalOrdinal, class GlobalOrdinal, class Node>
362  // FIXME: This is a placeholder
363  return Teuchos::OrdinalTraits<size_t>::invalid();
364  }
365 
366 } // namespace MueLu
367 
368 #endif /* MUELU_BLOCKEDJACOBISMOOTHER_DEF_HPP_ */
#define MUELU_DESCRIBE
Helper macro for implementing Describable::describe() for BaseClass objects.
#define MUELU_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
MueLu::DefaultLocalOrdinal LocalOrdinal
MueLu::DefaultScalar Scalar
block Jacobi method for blocked matrices
void Apply(MultiVector &X, const MultiVector &B, bool InitialGuessIsZero=false) const
Apply the direct solver.
RCP< const ParameterList > GetValidParameterList() const
Input.
void Setup(Level &currentLevel)
Setup routine In the Setup method the Inverse_ vector is filled with the corresponding SmootherBase o...
std::string description() const
Return a simple one-line description of this object.
void DeclareInput(Level &currentLevel) const
Input.
RCP< SmootherPrototype > Copy() const
std::vector< Teuchos::RCP< const FactoryManagerBase > > FactManager_
vector of factory managers
void AddFactoryManager(RCP< const FactoryManagerBase > FactManager, int pos)
Add a factory manager.
void print(Teuchos::FancyOStream &out, const VerbLevel verbLevel=Default) const
Print the object with some verbosity level to an FancyOStream object.
size_t getNodeSmootherComplexity() const
Get a rough estimate of cost per iteration.
virtual std::string description() const
Return a simple one-line description of this object.
Exception indicating invalid cast attempted.
Exception throws to report errors in the internal logical of the program.
Timer to be used in factories. Similar to Monitor but with additional timers.
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:99
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access)....
virtual const Teuchos::ParameterList & GetParameterList() const
An exception safe way to call the method 'Level::SetFactoryManager()'.
bool IsSetup() const
Get the state of a smoother prototype.
Namespace for MueLu classes and methods.
@ Warnings0
Important warning messages (one line)
@ Debug
Print additional debugging information.
@ Parameters0
Print class parameters.
std::string toString(const T &what)
Little helper function to convert non-string types to strings.