MueLu  Version of the Day
Thyra_MueLuPreconditionerFactory_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 #ifndef THYRA_MUELU_PRECONDITIONER_FACTORY_DEF_HPP
47 #define THYRA_MUELU_PRECONDITIONER_FACTORY_DEF_HPP
48 
51 
52 #if defined(HAVE_MUELU_STRATIMIKOS) && defined(HAVE_MUELU_THYRA)
53 
54 // This is not as general as possible, but should be good enough for most builds.
55 #if (defined(HAVE_MUELU_TPETRA) && \
56  ((defined(HAVE_TPETRA_INST_DOUBLE) && defined(HAVE_TPETRA_INST_FLOAT) && !defined(HAVE_TPETRA_INST_COMPLEX_DOUBLE) && !defined(HAVE_TPETRA_INST_COMPLEX_FLOAT)) || \
57  (!defined(HAVE_TPETRA_INST_DOUBLE) && !defined(HAVE_TPETRA_INST_FLOAT) && defined(HAVE_TPETRA_INST_COMPLEX_DOUBLE) && defined(HAVE_TPETRA_INST_COMPLEX_FLOAT)) || \
58  (defined(HAVE_TPETRA_INST_DOUBLE) && defined(HAVE_TPETRA_INST_FLOAT) && defined(HAVE_TPETRA_INST_COMPLEX_DOUBLE) && defined(HAVE_TPETRA_INST_COMPLEX_FLOAT))))
59 # define MUELU_CAN_USE_MIXED_PRECISION
60 #endif
61 
62 namespace Thyra {
63 
64  using Teuchos::RCP;
65  using Teuchos::rcp;
66  using Teuchos::ParameterList;
67  using Teuchos::rcp_dynamic_cast;
68  using Teuchos::rcp_const_cast;
69 
70 
71  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
72  bool Converters<Scalar,LocalOrdinal,GlobalOrdinal,Node>::replaceWithXpetra(ParameterList& paramList, std::string parameterName) {
73  typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType Magnitude;
74  typedef Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> XpOp;
75  typedef Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpThyUtils;
76  // typedef Xpetra::CrsMatrixWrap<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpCrsMatWrap;
77  // typedef Xpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpCrsMat;
78  typedef Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpMat;
79  typedef Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpMultVec;
80  typedef Xpetra::MultiVector<Magnitude,LocalOrdinal,GlobalOrdinal,Node> XpMagMultVec;
81  typedef Xpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpVec;
82 
83  typedef Thyra::LinearOpBase<Scalar> ThyLinOpBase;
84  typedef Thyra::DiagonalLinearOpBase<Scalar> ThyDiagLinOpBase;
85  // typedef Thyra::XpetraLinearOp<Scalar, LocalOrdinal, GlobalOrdinal, Node> ThyXpOp;
86  // typedef Thyra::SpmdVectorSpaceBase<Scalar> ThyVSBase;
87 
88 #ifdef HAVE_MUELU_TPETRA
89  typedef Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpCrsMat;
90  typedef Tpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> tOp;
91  typedef Tpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node> tV;
92  typedef Thyra::TpetraVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> thyTpV;
93  typedef Tpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> tMV;
94  typedef Tpetra::MultiVector<Magnitude, LocalOrdinal, GlobalOrdinal, Node> tMagMV;
95 # if defined(MUELU_CAN_USE_MIXED_PRECISION)
96  typedef typename Teuchos::ScalarTraits<Magnitude>::halfPrecision HalfMagnitude;
97  typedef Tpetra::MultiVector<HalfMagnitude, LocalOrdinal, GlobalOrdinal, Node> tHalfMagMV;
98 # endif
99 #endif
100 
101  if (paramList.isParameter(parameterName)) {
102  if (paramList.isType<RCP<XpMat> >(parameterName))
103  return true;
104  else if (paramList.isType<RCP<const XpMat> >(parameterName)) {
105  RCP<const XpMat> constM = paramList.get<RCP<const XpMat> >(parameterName);
106  paramList.remove(parameterName);
107  RCP<XpMat> M = rcp_const_cast<XpMat>(constM);
108  paramList.set<RCP<XpMat> >(parameterName, M);
109  return true;
110  }
111  else if (paramList.isType<RCP<XpMultVec> >(parameterName))
112  return true;
113  else if (paramList.isType<RCP<const XpMultVec> >(parameterName)) {
114  RCP<const XpMultVec> constX = paramList.get<RCP<const XpMultVec> >(parameterName);
115  paramList.remove(parameterName);
116  RCP<XpMultVec> X = rcp_const_cast<XpMultVec>(constX);
117  paramList.set<RCP<XpMultVec> >(parameterName, X);
118  return true;
119  }
120  else if (paramList.isType<RCP<XpMagMultVec> >(parameterName))
121  return true;
122  else if (paramList.isType<RCP<const XpMagMultVec> >(parameterName)) {
123  RCP<const XpMagMultVec> constX = paramList.get<RCP<const XpMagMultVec> >(parameterName);
124  paramList.remove(parameterName);
125  RCP<XpMagMultVec> X = rcp_const_cast<XpMagMultVec>(constX);
126  paramList.set<RCP<XpMagMultVec> >(parameterName, X);
127  return true;
128  }
129 #ifdef HAVE_MUELU_TPETRA
130  else if (paramList.isType<RCP<TpCrsMat> >(parameterName)) {
131  RCP<TpCrsMat> tM = paramList.get<RCP<TpCrsMat> >(parameterName);
132  paramList.remove(parameterName);
133  RCP<XpMat> xM = MueLu::TpetraCrs_To_XpetraMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>(tM);
134  paramList.set<RCP<XpMat> >(parameterName, xM);
135  return true;
136  } else if (paramList.isType<RCP<tMV> >(parameterName)) {
137  RCP<tMV> tpetra_X = paramList.get<RCP<tMV> >(parameterName);
138  paramList.remove(parameterName);
139  RCP<XpMultVec> X = MueLu::TpetraMultiVector_To_XpetraMultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>(tpetra_X);
140  paramList.set<RCP<XpMultVec> >(parameterName, X);
141  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(X));
142  return true;
143  } else if (paramList.isType<RCP<tMagMV> >(parameterName)) {
144  RCP<tMagMV> tpetra_X = paramList.get<RCP<tMagMV> >(parameterName);
145  paramList.remove(parameterName);
146  RCP<XpMagMultVec> X = MueLu::TpetraMultiVector_To_XpetraMultiVector<Magnitude,LocalOrdinal,GlobalOrdinal,Node>(tpetra_X);
147  paramList.set<RCP<XpMagMultVec> >(parameterName, X);
148  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(X));
149  return true;
150  }
151 #if defined(MUELU_CAN_USE_MIXED_PRECISION)
152  else if (paramList.isType<RCP<tHalfMagMV> >(parameterName)) {
153  RCP<tHalfMagMV> tpetra_hX = paramList.get<RCP<tHalfMagMV> >(parameterName);
154  paramList.remove(parameterName);
155  RCP<tMagMV> tpetra_X = rcp(new tMagMV(tpetra_hX->getMap(),tpetra_hX->getNumVectors()));
156  Tpetra::deep_copy(*tpetra_X,*tpetra_hX);
157  RCP<XpMagMultVec> X = MueLu::TpetraMultiVector_To_XpetraMultiVector<Magnitude,LocalOrdinal,GlobalOrdinal,Node>(tpetra_X);
158  paramList.set<RCP<XpMagMultVec> >(parameterName, X);
159  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(X));
160  return true;
161  }
162 # endif
163 #endif
164  else if (paramList.isType<RCP<const ThyDiagLinOpBase> >(parameterName) ||
165  (paramList.isType<RCP<const ThyLinOpBase> >(parameterName) && !
166  rcp_dynamic_cast<const ThyDiagLinOpBase>(paramList.get<RCP<const ThyLinOpBase> >(parameterName)).is_null())) {
167  RCP<const ThyDiagLinOpBase> thyM;
168  if (paramList.isType<RCP<const ThyDiagLinOpBase> >(parameterName))
169  thyM = paramList.get<RCP<const ThyDiagLinOpBase> >(parameterName);
170  else
171  thyM = rcp_dynamic_cast<const ThyDiagLinOpBase>(paramList.get<RCP<const ThyLinOpBase> >(parameterName), true);
172  paramList.remove(parameterName);
173  RCP<const Thyra::VectorBase<Scalar> > diag = thyM->getDiag();
174 
175  RCP<const XpVec> xpDiag;
176 #ifdef HAVE_MUELU_TPETRA
177  if (!rcp_dynamic_cast<const thyTpV>(diag).is_null()) {
178  RCP<const tV> tDiag = Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getConstTpetraVector(diag);
179  if (!tDiag.is_null())
180  xpDiag = Xpetra::toXpetra(tDiag);
181  }
182 #endif
183  TEUCHOS_ASSERT(!xpDiag.is_null());
184  RCP<XpMat> M = Xpetra::MatrixFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(xpDiag);
185  paramList.set<RCP<XpMat> >(parameterName, M);
186  return true;
187  }
188  else if (paramList.isType<RCP<const ThyLinOpBase> >(parameterName)) {
189  RCP<const ThyLinOpBase> thyM = paramList.get<RCP<const ThyLinOpBase> >(parameterName);
190  paramList.remove(parameterName);
191  try {
192  RCP<XpMat> M = XpThyUtils::toXpetra(Teuchos::rcp_const_cast<ThyLinOpBase>(thyM));
193  paramList.set<RCP<XpMat> >(parameterName, M);
194  } catch (std::exception& e) {
195  RCP<XpOp> M = XpThyUtils::toXpetraOperator(Teuchos::rcp_const_cast<ThyLinOpBase>(thyM));
196  RCP<Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tpOp = rcp_dynamic_cast<Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(M, true);
197  RCP<tOp> tO = tpOp->getOperator();
198  RCP<tV> diag;
199  if (tO->hasDiagonal()) {
200  diag = rcp(new tV(tO->getRangeMap()));
201  tO->getLocalDiagCopy(*diag);
202  }
204  RCP<Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tpFOp = rcp(new Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node> (fTpRow));
205  auto op = rcp_dynamic_cast<XpOp>(tpFOp);
206  paramList.set<RCP<XpOp> >(parameterName, op);
207  }
208  return true;
209  }
210  else {
211  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "Parameter " << parameterName << " has wrong type.");
212  return false;
213  }
214  } else
215  return false;
216  }
217 
218 
219 #ifdef HAVE_MUELU_EPETRA
220  template <class GlobalOrdinal>
221  bool Converters<double, int, GlobalOrdinal, Kokkos::Compat::KokkosSerialWrapperNode>::replaceWithXpetra(ParameterList& paramList, std::string parameterName) {
222  typedef double Scalar;
223  typedef int LocalOrdinal;
224  typedef Kokkos::Compat::KokkosSerialWrapperNode Node;
225  typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType Magnitude;
226  typedef Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> XpOp;
227  typedef Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpThyUtils;
228  typedef Xpetra::CrsMatrixWrap<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpCrsMatWrap;
229  typedef Xpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpCrsMat;
230  typedef Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpMat;
231  typedef Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpMultVec;
232  typedef Xpetra::MultiVector<Magnitude,LocalOrdinal,GlobalOrdinal,Node> XpMagMultVec;
233  typedef Xpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpVec;
234 
235  typedef Thyra::LinearOpBase<Scalar> ThyLinOpBase;
236  typedef Thyra::DiagonalLinearOpBase<Scalar> ThyDiagLinOpBase;
237  typedef Thyra::SpmdVectorSpaceBase<Scalar> ThyVSBase;
238 
239 #ifdef HAVE_MUELU_TPETRA
240  typedef Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpCrsMat;
241  typedef Tpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> tOp;
242  typedef Tpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node> tV;
243  typedef Thyra::TpetraVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> thyTpV;
244  typedef Tpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> tMV;
245  typedef Tpetra::MultiVector<Magnitude, LocalOrdinal, GlobalOrdinal, Node> tMagMV;
246 #if defined(MUELU_CAN_USE_MIXED_PRECISION)
247  typedef typename Teuchos::ScalarTraits<Magnitude>::halfPrecision HalfMagnitude;
248  typedef Tpetra::MultiVector<HalfMagnitude, LocalOrdinal, GlobalOrdinal, Node> tHalfMagMV;
249 # endif
250 #endif
251 #if defined(HAVE_MUELU_EPETRA)
252  typedef Xpetra::EpetraCrsMatrixT<GlobalOrdinal,Node> XpEpCrsMat;
253 #endif
254 
255  if (paramList.isParameter(parameterName)) {
256  if (paramList.isType<RCP<XpMat> >(parameterName))
257  return true;
258  else if (paramList.isType<RCP<const XpMat> >(parameterName)) {
259  RCP<const XpMat> constM = paramList.get<RCP<const XpMat> >(parameterName);
260  paramList.remove(parameterName);
261  RCP<XpMat> M = rcp_const_cast<XpMat>(constM);
262  paramList.set<RCP<XpMat> >(parameterName, M);
263  return true;
264  }
265  else if (paramList.isType<RCP<XpMultVec> >(parameterName))
266  return true;
267  else if (paramList.isType<RCP<const XpMultVec> >(parameterName)) {
268  RCP<const XpMultVec> constX = paramList.get<RCP<const XpMultVec> >(parameterName);
269  paramList.remove(parameterName);
270  RCP<XpMultVec> X = rcp_const_cast<XpMultVec>(constX);
271  paramList.set<RCP<XpMultVec> >(parameterName, X);
272  return true;
273  }
274  else if (paramList.isType<RCP<XpMagMultVec> >(parameterName))
275  return true;
276  else if (paramList.isType<RCP<const XpMagMultVec> >(parameterName)) {
277  RCP<const XpMagMultVec> constX = paramList.get<RCP<const XpMagMultVec> >(parameterName);
278  paramList.remove(parameterName);
279  RCP<XpMagMultVec> X = rcp_const_cast<XpMagMultVec>(constX);
280  paramList.set<RCP<XpMagMultVec> >(parameterName, X);
281  return true;
282  }
283 #ifdef HAVE_MUELU_TPETRA
284  else if (paramList.isType<RCP<TpCrsMat> >(parameterName)) {
285  RCP<TpCrsMat> tM = paramList.get<RCP<TpCrsMat> >(parameterName);
286  paramList.remove(parameterName);
287  RCP<XpMat> xM = MueLu::TpetraCrs_To_XpetraMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>(tM);
288  paramList.set<RCP<XpMat> >(parameterName, xM);
289  return true;
290  } else if (paramList.isType<RCP<tMV> >(parameterName)) {
291  RCP<tMV> tpetra_X = paramList.get<RCP<tMV> >(parameterName);
292  paramList.remove(parameterName);
293  RCP<XpMultVec> X = MueLu::TpetraMultiVector_To_XpetraMultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>(tpetra_X);
294  paramList.set<RCP<XpMultVec> >(parameterName, X);
295  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(X));
296  return true;
297  } else if (paramList.isType<RCP<tMagMV> >(parameterName)) {
298  RCP<tMagMV> tpetra_X = paramList.get<RCP<tMagMV> >(parameterName);
299  paramList.remove(parameterName);
300  RCP<XpMagMultVec> X = MueLu::TpetraMultiVector_To_XpetraMultiVector<Magnitude,LocalOrdinal,GlobalOrdinal,Node>(tpetra_X);
301  paramList.set<RCP<XpMagMultVec> >(parameterName, X);
302  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(X));
303  return true;
304  }
305 #if defined(MUELU_CAN_USE_MIXED_PRECISION)
306  else if (paramList.isType<RCP<tHalfMagMV> >(parameterName)) {
307  RCP<tHalfMagMV> tpetra_hX = paramList.get<RCP<tHalfMagMV> >(parameterName);
308  paramList.remove(parameterName);
309  RCP<tMagMV> tpetra_X = rcp(new tMagMV(tpetra_hX->getMap(),tpetra_hX->getNumVectors()));
310  Tpetra::deep_copy(*tpetra_X,*tpetra_hX);
311  RCP<XpMagMultVec> X = MueLu::TpetraMultiVector_To_XpetraMultiVector<Magnitude,LocalOrdinal,GlobalOrdinal,Node>(tpetra_X);
312  paramList.set<RCP<XpMagMultVec> >(parameterName, X);
313  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(X));
314  return true;
315  }
316 # endif
317 #endif
318 #ifdef HAVE_MUELU_EPETRA
319  else if (paramList.isType<RCP<Epetra_CrsMatrix> >(parameterName)) {
320  RCP<Epetra_CrsMatrix> eM = paramList.get<RCP<Epetra_CrsMatrix> >(parameterName);
321  paramList.remove(parameterName);
322  RCP<XpEpCrsMat> xeM = rcp(new XpEpCrsMat(eM));
323  RCP<XpCrsMat> xCrsM = rcp_dynamic_cast<XpCrsMat>(xeM, true);
324  RCP<XpCrsMatWrap> xwM = rcp(new XpCrsMatWrap(xCrsM));
325  RCP<XpMat> xM = rcp_dynamic_cast<XpMat>(xwM);
326  paramList.set<RCP<XpMat> >(parameterName, xM);
327  return true;
328  } else if (paramList.isType<RCP<Epetra_MultiVector> >(parameterName)) {
329  RCP<Epetra_MultiVector> epetra_X = Teuchos::null;
330  epetra_X = paramList.get<RCP<Epetra_MultiVector> >(parameterName);
331  paramList.remove(parameterName);
332  RCP<Xpetra::EpetraMultiVectorT<int,Node> > xpEpX = rcp(new Xpetra::EpetraMultiVectorT<int,Node>(epetra_X));
333  RCP<Xpetra::MultiVector<Scalar,int,int,Node> > xpEpXMult = rcp_dynamic_cast<Xpetra::MultiVector<Scalar,int,int,Node> >(xpEpX, true);
334  RCP<XpMultVec> X = rcp_dynamic_cast<XpMultVec>(xpEpXMult, true);
335  paramList.set<RCP<XpMultVec> >(parameterName, X);
336  return true;
337  }
338 #endif
339  else if (paramList.isType<RCP<const ThyDiagLinOpBase> >(parameterName) ||
340  (paramList.isType<RCP<const ThyLinOpBase> >(parameterName) && !
341  rcp_dynamic_cast<const ThyDiagLinOpBase>(paramList.get<RCP<const ThyLinOpBase> >(parameterName)).is_null())) {
342  RCP<const ThyDiagLinOpBase> thyM;
343  if (paramList.isType<RCP<const ThyDiagLinOpBase> >(parameterName))
344  thyM = paramList.get<RCP<const ThyDiagLinOpBase> >(parameterName);
345  else
346  thyM = rcp_dynamic_cast<const ThyDiagLinOpBase>(paramList.get<RCP<const ThyLinOpBase> >(parameterName), true);
347  paramList.remove(parameterName);
348  RCP<const Thyra::VectorBase<Scalar> > diag = thyM->getDiag();
349 
350  RCP<const XpVec> xpDiag;
351 #ifdef HAVE_MUELU_TPETRA
352  if (!rcp_dynamic_cast<const thyTpV>(diag).is_null()) {
353  RCP<const tV> tDiag = Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getConstTpetraVector(diag);
354  if (!tDiag.is_null())
355  xpDiag = Xpetra::toXpetra(tDiag);
356  }
357 #endif
358 #ifdef HAVE_MUELU_EPETRA
359  if (xpDiag.is_null()) {
360  RCP<const Epetra_Comm> comm = Thyra::get_Epetra_Comm(*rcp_dynamic_cast<const ThyVSBase>(thyM->range())->getComm());
361  RCP<const Epetra_Map> map = Thyra::get_Epetra_Map(*(thyM->range()), comm);
362  if (!map.is_null()) {
363  RCP<const Epetra_Vector> eDiag = Thyra::get_Epetra_Vector(*map, diag);
364  RCP<Epetra_Vector> nceDiag = rcp_const_cast<Epetra_Vector>(eDiag);
365  RCP<Xpetra::EpetraVectorT<int,Node> > xpEpDiag = rcp(new Xpetra::EpetraVectorT<int,Node>(nceDiag));
366  xpDiag = rcp_dynamic_cast<XpVec>(xpEpDiag, true);
367  }
368  }
369 #endif
370  TEUCHOS_ASSERT(!xpDiag.is_null());
371  RCP<XpMat> M = Xpetra::MatrixFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(xpDiag);
372  paramList.set<RCP<XpMat> >(parameterName, M);
373  return true;
374  }
375  else if (paramList.isType<RCP<const ThyLinOpBase> >(parameterName)) {
376  RCP<const ThyLinOpBase> thyM = paramList.get<RCP<const ThyLinOpBase> >(parameterName);
377  paramList.remove(parameterName);
378  try {
379  RCP<XpMat> M = XpThyUtils::toXpetra(Teuchos::rcp_const_cast<ThyLinOpBase>(thyM));
380  paramList.set<RCP<XpMat> >(parameterName, M);
381  } catch (std::exception& e) {
382  RCP<XpOp> M = XpThyUtils::toXpetraOperator(Teuchos::rcp_const_cast<ThyLinOpBase>(thyM));
383  RCP<Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tpOp = rcp_dynamic_cast<Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(M, true);
384  RCP<tOp> tO = tpOp->getOperator();
385  RCP<tV> diag;
386  if (tO->hasDiagonal()) {
387  diag = rcp(new tV(tO->getRangeMap()));
388  tO->getLocalDiagCopy(*diag);
389  }
391  RCP<Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node> > tpFOp = rcp(new Xpetra::TpetraOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node> (fTpRow));
392  auto op = rcp_dynamic_cast<XpOp>(tpFOp);
393  paramList.set<RCP<XpOp> >(parameterName, op);
394  }
395  return true;
396  }
397  else {
398  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "Parameter " << parameterName << " has wrong type.");
399  return false;
400  }
401  } else
402  return false;
403  }
404 #endif
405 
406  // Constructors/initializers/accessors
407 
408  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
409  MueLuPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::MueLuPreconditionerFactory() :
410  paramList_(rcp(new ParameterList()))
411  {}
412 
413  // Overridden from PreconditionerFactoryBase
414 
415  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
416  bool MueLuPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::isCompatible(const LinearOpSourceBase<Scalar>& fwdOpSrc) const {
417  const RCP<const LinearOpBase<Scalar> > fwdOp = fwdOpSrc.getOp();
418 
419 #ifdef HAVE_MUELU_TPETRA
420  if (Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::isTpetra(fwdOp)) return true;
421 #endif
422 
423 #ifdef HAVE_MUELU_EPETRA
424  if (Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::isEpetra(fwdOp)) return true;
425 #endif
426 
427 
428  if (Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::isBlockedOperator(fwdOp)) return true;
429 
430  return false;
431  }
432 
433 
434  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
435  RCP<PreconditionerBase<Scalar> > MueLuPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::createPrec() const {
436  return Teuchos::rcp(new DefaultPreconditioner<Scalar>);
437  }
438 
439  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
440  void MueLuPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::
441  initializePrec(const RCP<const LinearOpSourceBase<Scalar> >& fwdOpSrc, PreconditionerBase<Scalar>* prec, const ESupportSolveUse supportSolveUse) const {
442  Teuchos::TimeMonitor tM(*Teuchos::TimeMonitor::getNewTimer(std::string("ThyraMueLu::initializePrec")));
443 
444  using Teuchos::rcp_dynamic_cast;
445 
446  // we are using typedefs here, since we are using objects from different packages (Xpetra, Thyra,...)
447  typedef Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> XpMap;
448  typedef Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node> XpOp;
450  typedef Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpThyUtils;
451  // typedef Xpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpCrsMat;
452  typedef Xpetra::BlockedCrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpBlockedCrsMat;
453  typedef Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpMat;
454  // typedef Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpMultVec;
455  // typedef Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::coordinateType,LocalOrdinal,GlobalOrdinal,Node> XpMultVecDouble;
456  typedef Thyra::LinearOpBase<Scalar> ThyLinOpBase;
458  typedef Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpMV;
459  typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType Magnitude;
460  typedef Xpetra::MultiVector<Magnitude,LocalOrdinal,GlobalOrdinal,Node > XpmMV;
461 #if defined(MUELU_CAN_USE_MIXED_PRECISION)
462  typedef Xpetra::TpetraHalfPrecisionOperator<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpHalfPrecOp;
463  typedef typename XpHalfPrecOp::HalfScalar HalfScalar;
464  typedef Xpetra::Operator<HalfScalar,LocalOrdinal,GlobalOrdinal,Node> XpHalfOp;
466  typedef typename Teuchos::ScalarTraits<Magnitude>::halfPrecision HalfMagnitude;
467  typedef Xpetra::MultiVector<HalfScalar,LocalOrdinal,GlobalOrdinal,Node> XphMV;
468  typedef Xpetra::MultiVector<HalfMagnitude,LocalOrdinal,GlobalOrdinal,Node > XphmMV;
469  typedef Xpetra::Matrix<HalfScalar,LocalOrdinal,GlobalOrdinal,Node> XphMat;
470 #endif
471 
472 
473  // Check precondition
474  TEUCHOS_ASSERT(Teuchos::nonnull(fwdOpSrc));
475  TEUCHOS_ASSERT(this->isCompatible(*fwdOpSrc));
476  TEUCHOS_ASSERT(prec);
477 
478  // Create a copy, as we may remove some things from the list
479  ParameterList paramList = *paramList_;
480 
481  // Retrieve wrapped concrete Xpetra matrix from FwdOp
482  const RCP<const ThyLinOpBase> fwdOp = fwdOpSrc->getOp();
483  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(fwdOp));
484 
485  // Check whether it is Epetra/Tpetra
486  bool bIsEpetra = XpThyUtils::isEpetra(fwdOp);
487  bool bIsTpetra = XpThyUtils::isTpetra(fwdOp);
488  bool bIsBlocked = XpThyUtils::isBlockedOperator(fwdOp);
489  TEUCHOS_TEST_FOR_EXCEPT((bIsEpetra == true && bIsTpetra == true));
490  TEUCHOS_TEST_FOR_EXCEPT((bIsEpetra == bIsTpetra) && bIsBlocked == false);
491  TEUCHOS_TEST_FOR_EXCEPT((bIsEpetra != bIsTpetra) && bIsBlocked == true);
492 
493  RCP<XpMat> A = Teuchos::null;
494  if(bIsBlocked) {
495  Teuchos::RCP<const Thyra::BlockedLinearOpBase<Scalar> > ThyBlockedOp =
496  Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(fwdOp);
497  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(ThyBlockedOp));
498 
499  TEUCHOS_TEST_FOR_EXCEPT(ThyBlockedOp->blockExists(0,0)==false);
500 
501  Teuchos::RCP<const LinearOpBase<Scalar> > b00 = ThyBlockedOp->getBlock(0,0);
502  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(b00));
503 
504  // wrap the forward operator as an Xpetra::Matrix that MueLu can work with
505  // MueLu needs a non-const object as input
506  RCP<XpMat> A00 = XpThyUtils::toXpetra(Teuchos::rcp_const_cast<LinearOpBase<Scalar> >(b00));
507  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(A00));
508 
509  RCP<const XpMap> rowmap00 = A00->getRowMap();
510  RCP< const Teuchos::Comm< int > > comm = rowmap00->getComm();
511 
512  // create a Xpetra::BlockedCrsMatrix which derives from Xpetra::Matrix that MueLu can work with
513  RCP<XpBlockedCrsMat> bMat = Teuchos::rcp(new XpBlockedCrsMat(ThyBlockedOp, comm));
514  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(bMat));
515 
516  // save blocked matrix
517  A = bMat;
518  } else {
519  // wrap the forward operator as an Xpetra::Matrix that MueLu can work with
520  // MueLu needs a non-const object as input
521  A = XpThyUtils::toXpetra(Teuchos::rcp_const_cast<ThyLinOpBase>(fwdOp));
522  }
523  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(A));
524 
525  // Retrieve concrete preconditioner object
526  const Teuchos::Ptr<DefaultPreconditioner<Scalar> > defaultPrec = Teuchos::ptr(dynamic_cast<DefaultPreconditioner<Scalar> *>(prec));
527  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(defaultPrec));
528 
529  // extract preconditioner operator
530  RCP<ThyLinOpBase> thyra_precOp = Teuchos::null;
531  thyra_precOp = rcp_dynamic_cast<Thyra::LinearOpBase<Scalar> >(defaultPrec->getNonconstUnspecifiedPrecOp(), true);
532 
533  // make a decision whether to (re)build the multigrid preconditioner or reuse the old one
534  // rebuild preconditioner if startingOver == true
535  // reuse preconditioner if startingOver == false
536  const bool startingOver = (thyra_precOp.is_null() || !paramList.isParameter("reuse: type") || paramList.get<std::string>("reuse: type") == "none");
537  bool useHalfPrecision = false;
538  if (paramList.isParameter("half precision"))
539  useHalfPrecision = paramList.get<bool>("half precision");
540  else if (paramList.isSublist("Hierarchy") && paramList.sublist("Hierarchy").isParameter("half precision"))
541  useHalfPrecision = paramList.sublist("Hierarchy").get<bool>("half precision");
542  if (useHalfPrecision)
543  TEUCHOS_TEST_FOR_EXCEPTION(!bIsTpetra, MueLu::Exceptions::RuntimeError, "The only scalar type Epetra knows is double, so a half precision preconditioner cannot be constructed.");
544 
545  RCP<XpOp> xpPrecOp;
546  if (startingOver == true) {
547  // Convert to Xpetra
548  std::list<std::string> convertXpetra = {"Coordinates", "Nullspace"};
549  for (auto it = convertXpetra.begin(); it != convertXpetra.end(); ++it)
550  Converters<Scalar,LocalOrdinal,GlobalOrdinal,Node>::replaceWithXpetra(paramList,*it);
551 
552  for (int lvlNo=0; lvlNo < 10; ++lvlNo) {
553  if (paramList.isSublist("level " + std::to_string(lvlNo) + " user data")) {
554  ParameterList& lvlList = paramList.sublist("level " + std::to_string(lvlNo) + " user data");
555  std::list<std::string> convertKeys;
556  for (auto it = lvlList.begin(); it != lvlList.end(); ++it)
557  convertKeys.push_back(lvlList.name(it));
558  for (auto it = convertKeys.begin(); it != convertKeys.end(); ++it)
559  Converters<Scalar,LocalOrdinal,GlobalOrdinal,Node>::replaceWithXpetra(lvlList,*it);
560  }
561  }
562 
563  if (useHalfPrecision) {
564 #if defined(MUELU_CAN_USE_MIXED_PRECISION)
565 
566  // CAG: There is nothing special about the combination double-float,
567  // except that I feel somewhat confident that Trilinos builds
568  // with both scalar types.
569 
570  // convert to half precision
571  RCP<XphMat> halfA = Xpetra::convertToHalfPrecision(A);
572  const std::string userName = "user data";
573  Teuchos::ParameterList& userParamList = paramList.sublist(userName);
574  if (userParamList.isType<RCP<XpmMV> >("Coordinates")) {
575  RCP<XpmMV> coords = userParamList.get<RCP<XpmMV> >("Coordinates");
576  userParamList.remove("Coordinates");
577  RCP<XphmMV> halfCoords = Xpetra::convertToHalfPrecision(coords);
578  userParamList.set("Coordinates",halfCoords);
579  }
580  if (userParamList.isType<RCP<XpMV> >("Nullspace")) {
581  RCP<XpMV> nullspace = userParamList.get<RCP<XpMV> >("Nullspace");
582  userParamList.remove("Nullspace");
583  RCP<XphMV> halfNullspace = Xpetra::convertToHalfPrecision(nullspace);
584  userParamList.set("Nullspace",halfNullspace);
585  }
586  if (paramList.isType<RCP<XpmMV> >("Coordinates")) {
587  RCP<XpmMV> coords = paramList.get<RCP<XpmMV> >("Coordinates");
588  paramList.remove("Coordinates");
589  RCP<XphmMV> halfCoords = Xpetra::convertToHalfPrecision(coords);
590  userParamList.set("Coordinates",halfCoords);
591  }
592  if (paramList.isType<RCP<XpMV> >("Nullspace")) {
593  RCP<XpMV> nullspace = paramList.get<RCP<XpMV> >("Nullspace");
594  paramList.remove("Nullspace");
595  RCP<XphMV> halfNullspace = Xpetra::convertToHalfPrecision(nullspace);
596  userParamList.set("Nullspace",halfNullspace);
597  }
598 
599 
600  // build a new half-precision MueLu preconditioner
601 
602  RCP<MueLu::Hierarchy<HalfScalar,LocalOrdinal,GlobalOrdinal,Node> > H = MueLu::CreateXpetraPreconditioner(halfA, paramList);
603  RCP<MueLuHalfXpOp> xpOp = rcp(new MueLuHalfXpOp(H));
604  xpPrecOp = rcp(new XpHalfPrecOp(xpOp));
605 #else
606  TEUCHOS_TEST_FOR_EXCEPT(true);
607 #endif
608  } else
609  {
610  const std::string userName = "user data";
611  Teuchos::ParameterList& userParamList = paramList.sublist(userName);
612  if (paramList.isType<RCP<XpmMV> >("Coordinates")) {
613  RCP<XpmMV> coords = paramList.get<RCP<XpmMV> >("Coordinates");
614  paramList.remove("Coordinates");
615  userParamList.set("Coordinates",coords);
616  }
617  if (paramList.isType<RCP<XpMV> >("Nullspace")) {
618  RCP<XpMV> nullspace = paramList.get<RCP<XpMV> >("Nullspace");
619  paramList.remove("Nullspace");
620  userParamList.set("Nullspace",nullspace);
621  }
622 
623  // build a new MueLu RefMaxwell preconditioner
624  RCP<MueLu::Hierarchy<Scalar,LocalOrdinal,GlobalOrdinal,Node> > H = MueLu::CreateXpetraPreconditioner(A, paramList);
625  xpPrecOp = rcp(new MueLuXpOp(H));
626  }
627  } else {
628  // reuse old MueLu hierarchy stored in MueLu Xpetra operator and put in new matrix
629  RCP<ThyXpOp> thyXpOp = rcp_dynamic_cast<ThyXpOp>(thyra_precOp, true);
630  xpPrecOp = rcp_dynamic_cast<XpOp>(thyXpOp->getXpetraOperator(), true);
631 #if defined(MUELU_CAN_USE_MIXED_PRECISION)
632  RCP<XpHalfPrecOp> xpHalfPrecOp = rcp_dynamic_cast<XpHalfPrecOp>(xpPrecOp);
633  if (!xpHalfPrecOp.is_null()) {
634  RCP<MueLu::Hierarchy<HalfScalar,LocalOrdinal,GlobalOrdinal,Node> > H = rcp_dynamic_cast<MueLuHalfXpOp>(xpHalfPrecOp->GetHalfPrecisionOperator(), true)->GetHierarchy();
635  RCP<XphMat> halfA = Xpetra::convertToHalfPrecision(A);
636 
637  TEUCHOS_TEST_FOR_EXCEPTION(!H->GetNumLevels(), MueLu::Exceptions::RuntimeError,
638  "Thyra::MueLuPreconditionerFactory: Hierarchy has no levels in it");
639  TEUCHOS_TEST_FOR_EXCEPTION(!H->GetLevel(0)->IsAvailable("A"), MueLu::Exceptions::RuntimeError,
640  "Thyra::MueLuPreconditionerFactory: Hierarchy has no fine level operator");
641  RCP<MueLu::Level> level0 = H->GetLevel(0);
642  RCP<XpHalfOp> O0 = level0->Get<RCP<XpHalfOp> >("A");
643  RCP<XphMat> A0 = rcp_dynamic_cast<XphMat>(O0, true);
644 
645  if (!A0.is_null()) {
646  // If a user provided a "number of equations" argument in a parameter list
647  // during the initial setup, we must honor that settings and reuse it for
648  // all consequent setups.
649  halfA->SetFixedBlockSize(A0->GetFixedBlockSize());
650  }
651 
652  // set new matrix
653  level0->Set("A", halfA);
654 
655  H->SetupRe();
656  } else
657 #endif
658  {
659  // get old MueLu hierarchy
660  RCP<MueLuXpOp> xpOp = rcp_dynamic_cast<MueLuXpOp>(thyXpOp->getXpetraOperator(), true);
661  RCP<MueLu::Hierarchy<Scalar,LocalOrdinal,GlobalOrdinal,Node> > H = xpOp->GetHierarchy();;
662 
663  TEUCHOS_TEST_FOR_EXCEPTION(!H->GetNumLevels(), MueLu::Exceptions::RuntimeError,
664  "Thyra::MueLuPreconditionerFactory: Hierarchy has no levels in it");
665  TEUCHOS_TEST_FOR_EXCEPTION(!H->GetLevel(0)->IsAvailable("A"), MueLu::Exceptions::RuntimeError,
666  "Thyra::MueLuPreconditionerFactory: Hierarchy has no fine level operator");
667  RCP<MueLu::Level> level0 = H->GetLevel(0);
668  RCP<XpOp> O0 = level0->Get<RCP<XpOp> >("A");
669  RCP<XpMat> A0 = rcp_dynamic_cast<XpMat>(O0);
670 
671  if (!A0.is_null()) {
672  // If a user provided a "number of equations" argument in a parameter list
673  // during the initial setup, we must honor that settings and reuse it for
674  // all consequent setups.
675  A->SetFixedBlockSize(A0->GetFixedBlockSize());
676  }
677 
678  // set new matrix
679  level0->Set("A", A);
680 
681  H->SetupRe();
682  }
683  }
684 
685  // wrap preconditioner in thyraPrecOp
686  RCP<const VectorSpaceBase<Scalar> > thyraRangeSpace = Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::toThyra(xpPrecOp->getRangeMap());
687  RCP<const VectorSpaceBase<Scalar> > thyraDomainSpace = Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::toThyra(xpPrecOp->getDomainMap());
688 
689  RCP<ThyLinOpBase > thyraPrecOp = Thyra::xpetraLinearOp<Scalar, LocalOrdinal, GlobalOrdinal, Node>(thyraRangeSpace, thyraDomainSpace, xpPrecOp);
690  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(thyraPrecOp));
691 
692  defaultPrec->initializeUnspecified(thyraPrecOp);
693 
694  }
695 
696  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
697  void MueLuPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::
698  uninitializePrec(PreconditionerBase<Scalar>* prec, RCP<const LinearOpSourceBase<Scalar> >* fwdOp, ESupportSolveUse* supportSolveUse) const {
699  TEUCHOS_ASSERT(prec);
700 
701  // Retrieve concrete preconditioner object
702  const Teuchos::Ptr<DefaultPreconditioner<Scalar> > defaultPrec = Teuchos::ptr(dynamic_cast<DefaultPreconditioner<Scalar> *>(prec));
703  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(defaultPrec));
704 
705  if (fwdOp) {
706  // TODO: Implement properly instead of returning default value
707  *fwdOp = Teuchos::null;
708  }
709 
710  if (supportSolveUse) {
711  // TODO: Implement properly instead of returning default value
712  *supportSolveUse = Thyra::SUPPORT_SOLVE_UNSPECIFIED;
713  }
714 
715  defaultPrec->uninitialize();
716  }
717 
718 
719  // Overridden from ParameterListAcceptor
720  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
721  void MueLuPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::setParameterList(RCP<ParameterList> const& paramList) {
722  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(paramList));
723  paramList_ = paramList;
724  }
725 
726  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
727  RCP<ParameterList> MueLuPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getNonconstParameterList() {
728  return paramList_;
729  }
730 
731  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
732  RCP<ParameterList> MueLuPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::unsetParameterList() {
733  RCP<ParameterList> savedParamList = paramList_;
734  paramList_ = Teuchos::null;
735  return savedParamList;
736  }
737 
738  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
739  RCP<const ParameterList> MueLuPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getParameterList() const {
740  return paramList_;
741  }
742 
743  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
744  RCP<const ParameterList> MueLuPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getValidParameters() const {
745  static RCP<const ParameterList> validPL;
746 
747  if (Teuchos::is_null(validPL))
748  validPL = rcp(new ParameterList());
749 
750  return validPL;
751  }
752 
753  // Public functions overridden from Teuchos::Describable
754  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
755  std::string MueLuPreconditionerFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::description() const {
756  return "Thyra::MueLuPreconditionerFactory";
757  }
758 } // namespace Thyra
759 
760 #endif // HAVE_MUELU_STRATIMIKOS
761 
762 #endif // ifdef THYRA_MUELU_PRECONDITIONER_FACTORY_DEF_HPP
MueLu::DefaultLocalOrdinal LocalOrdinal
MueLu::DefaultNode Node
MueLu::DefaultScalar Scalar
Concrete Thyra::LinearOpBase subclass for Xpetra::Operator.
Teuchos::RCP< MueLu::Hierarchy< Scalar, LocalOrdinal, GlobalOrdinal, Node > > CreateXpetraPreconditioner(Teuchos::RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > op, const Teuchos::ParameterList &inParamList)
Helper function to create a MueLu preconditioner that can be used by Xpetra.Given an Xpetra::Matrix...
Exception throws to report errors in the internal logical of the program.
Wraps an existing MueLu::Hierarchy as a Xpetra::Operator.