MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Thyra_MueLuRefMaxwellPreconditionerFactory_decl.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 // Tobias Wiesner (tawiesn@sandia.gov)
43 //
44 // ***********************************************************************
45 //
46 // @HEADER
47 #ifndef THYRA_MUELU_REFMAXWELL_PRECONDITIONER_FACTORY_DECL_HPP
48 #define THYRA_MUELU_REFMAXWELL_PRECONDITIONER_FACTORY_DECL_HPP
49 
50 #include <MueLu_ConfigDefs.hpp>
51 
52 #ifdef HAVE_MUELU_STRATIMIKOS
53 
54 // Stratimikos needs Thyra, so we don't need special guards for Thyra here
55 #include "Thyra_DefaultPreconditioner.hpp"
56 #include "Thyra_BlockedLinearOpBase.hpp"
57 #include "Thyra_DiagonalLinearOpBase.hpp"
58 #include "Thyra_XpetraLinearOp.hpp"
59 #ifdef HAVE_MUELU_TPETRA
60 #include "Thyra_TpetraLinearOp.hpp"
61 #include "Thyra_TpetraThyraWrappers.hpp"
62 #endif
63 #ifdef HAVE_MUELU_EPETRA
64 #include "Thyra_EpetraLinearOp.hpp"
65 #include "Thyra_EpetraThyraWrappers.hpp"
66 #endif
67 
68 #include "Teuchos_Ptr.hpp"
70 #include "Teuchos_Assert.hpp"
71 #include "Teuchos_Time.hpp"
72 
73 #include <Xpetra_CrsMatrixWrap.hpp>
74 #include <Xpetra_CrsMatrix.hpp>
75 #include <Xpetra_Matrix.hpp>
76 #include <Xpetra_ThyraUtils.hpp>
77 
78 #include <MueLu_Hierarchy.hpp>
80 #include <MueLu_HierarchyUtils.hpp>
81 #include <MueLu_Utilities.hpp>
82 #include <MueLu_ParameterListInterpreter.hpp>
83 #include <MueLu_MLParameterListInterpreter.hpp>
84 #include <MueLu_MasterList.hpp>
85 #include <MueLu_XpetraOperator_decl.hpp> // todo fix me
86 #include <MueLu_RefMaxwell.hpp>
87 #ifdef HAVE_MUELU_TPETRA
88 #include <MueLu_TpetraOperator.hpp>
89 #endif
90 #ifdef HAVE_MUELU_EPETRA
91 #include <MueLu_EpetraOperator.hpp>
93 #endif
94 
95 #include "Thyra_PreconditionerFactoryBase.hpp"
96 
97 #include "Kokkos_DefaultNode.hpp"
98 
99 
100 namespace Thyra {
101 
110  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node = KokkosClassic::DefaultNode::DefaultNodeType>
111  class MueLuRefMaxwellPreconditionerFactory : public PreconditionerFactoryBase<Scalar> {
112  public:
113 
116 
120 
123 
125  bool isCompatible(const LinearOpSourceBase<Scalar>& fwdOp) const;
129  void initializePrec(const Teuchos::RCP<const LinearOpSourceBase<Scalar> >& fwdOp,
130  PreconditionerBase<Scalar>* prec,
131  const ESupportSolveUse supportSolveUse
132  ) const;
134  void uninitializePrec(PreconditionerBase<Scalar>* prec,
135  Teuchos::RCP<const LinearOpSourceBase<Scalar> >* fwdOp,
136  ESupportSolveUse* supportSolveUse
137  ) const;
138 
140 
143 
155 
158 
160  std::string description() const;
161 
162  // ToDo: Add an override of describe(...) to give more detail!
163 
165 
166  private:
167 
169 
170  };
171 
172 #ifdef HAVE_MUELU_EPETRA
173 
180  template <>
181  class MueLuRefMaxwellPreconditionerFactory<double,int,int,Xpetra::EpetraNode> : public PreconditionerFactoryBase<double> {
182  public:
183  typedef double Scalar;
184  typedef int LocalOrdinal;
185  typedef int GlobalOrdinal;
187 
190 
193 
195 
198 
200  bool isCompatible(const LinearOpSourceBase<Scalar>& fwdOpSrc) const {
201  const RCP<const LinearOpBase<Scalar> > fwdOp = fwdOpSrc.getOp();
202 
203 #ifdef HAVE_MUELU_TPETRA
204  if (Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::isTpetra(fwdOp)) return true;
205 #endif
206 
207 #ifdef HAVE_MUELU_EPETRA
208  if (Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::isEpetra(fwdOp)) return true;
209 #endif
210 
211  if (Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::isBlockedOperator(fwdOp)) return true;
212 
213  return false;
214  }
215 
218  return Teuchos::rcp(new DefaultPreconditioner<Scalar>);
219  }
220 
222  void initializePrec(const Teuchos::RCP<const LinearOpSourceBase<Scalar> >& fwdOpSrc,
223  PreconditionerBase<Scalar>* prec,
224  const ESupportSolveUse /* supportSolveUse */
225  ) const {
226  using Teuchos::rcp_dynamic_cast;
227 
228  // we are using typedefs here, since we are using objects from different packages (Xpetra, Thyra,...)
231  typedef Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node> XpThyUtils;
238  typedef Thyra::LinearOpBase<Scalar> ThyLinOpBase;
239  typedef Thyra::DiagonalLinearOpBase<Scalar> ThyDiagLinOpBase;
240 #ifdef HAVE_MUELU_TPETRA
241  // TAW 1/26/2016: We deal with Tpetra objects
242 #if ((defined(EPETRA_HAVE_OMP) && (defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT))) || \
243  (!defined(EPETRA_HAVE_OMP) && (defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT))))
244  typedef Thyra::TpetraLinearOp<Scalar,LocalOrdinal,GlobalOrdinal,Node> ThyTpLinOp;
245 #endif
246 #endif
247 #if defined(HAVE_MUELU_EPETRA)
248  typedef Thyra::EpetraLinearOp ThyEpLinOp;
250 #endif
251 
252  //std::cout << "-======---------------------------------" << std::endl;
253  //std::cout << *paramList_ << std::endl;
254  //std::cout << "-======---------------------------------" << std::endl;
255 
256  // Check precondition
257  TEUCHOS_ASSERT(Teuchos::nonnull(fwdOpSrc));
258  TEUCHOS_ASSERT(this->isCompatible(*fwdOpSrc));
259  TEUCHOS_ASSERT(prec);
260 
261  // Create a copy, as we may remove some things from the list
262  ParameterList paramList = *paramList_;
263 
264  // Retrieve wrapped concrete Xpetra matrix from FwdOp
265  const RCP<const ThyLinOpBase> fwdOp = fwdOpSrc->getOp();
267 
268  // Check whether it is Epetra/Tpetra
269  bool bIsEpetra = XpThyUtils::isEpetra(fwdOp);
270  bool bIsTpetra = XpThyUtils::isTpetra(fwdOp);
271  bool bIsBlocked = XpThyUtils::isBlockedOperator(fwdOp);
272  TEUCHOS_TEST_FOR_EXCEPT((bIsEpetra == true && bIsTpetra == true));
273  TEUCHOS_TEST_FOR_EXCEPT((bIsEpetra == bIsTpetra) && bIsBlocked == false);
274  TEUCHOS_TEST_FOR_EXCEPT((bIsEpetra != bIsTpetra) && bIsBlocked == true);
275 
276  RCP<XpMat> A = Teuchos::null;
277  if(bIsBlocked) {
279  Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<Scalar> >(fwdOp);
281 
282  TEUCHOS_TEST_FOR_EXCEPT(ThyBlockedOp->blockExists(0,0)==false);
283 
284  Teuchos::RCP<const LinearOpBase<Scalar> > b00 = ThyBlockedOp->getBlock(0,0);
285  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(b00));
286 
287  RCP<const XpCrsMat > xpetraFwdCrsMat00 = XpThyUtils::toXpetra(b00);
288  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(xpetraFwdCrsMat00));
289 
290  // MueLu needs a non-const object as input
291  RCP<XpCrsMat> xpetraFwdCrsMatNonConst00 = Teuchos::rcp_const_cast<XpCrsMat>(xpetraFwdCrsMat00);
292  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(xpetraFwdCrsMatNonConst00));
293 
294  // wrap the forward operator as an Xpetra::Matrix that MueLu can work with
296  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(A00));
297 
298  RCP<const XpMap> rowmap00 = A00->getRowMap();
299  RCP< const Teuchos::Comm< int > > comm = rowmap00->getComm();
300 
301  // create a Xpetra::BlockedCrsMatrix which derives from Xpetra::Matrix that MueLu can work with
302  RCP<XpBlockedCrsMat> bMat = Teuchos::rcp(new XpBlockedCrsMat(ThyBlockedOp, comm));
303  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(bMat));
304 
305  // save blocked matrix
306  A = bMat;
307  } else {
308  RCP<const XpCrsMat > xpetraFwdCrsMat = XpThyUtils::toXpetra(fwdOp);
309  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(xpetraFwdCrsMat));
310 
311  // MueLu needs a non-const object as input
312  RCP<XpCrsMat> xpetraFwdCrsMatNonConst = Teuchos::rcp_const_cast<XpCrsMat>(xpetraFwdCrsMat);
313  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(xpetraFwdCrsMatNonConst));
314 
315  // wrap the forward operator as an Xpetra::Matrix that MueLu can work with
316  A = rcp(new Xpetra::CrsMatrixWrap<Scalar,LocalOrdinal,GlobalOrdinal,Node>(xpetraFwdCrsMatNonConst));
317  }
319 
320  // Retrieve concrete preconditioner object
321  const Teuchos::Ptr<DefaultPreconditioner<Scalar> > defaultPrec = Teuchos::ptr(dynamic_cast<DefaultPreconditioner<Scalar> *>(prec));
323 
324  // extract preconditioner operator
325  RCP<ThyLinOpBase> thyra_precOp = Teuchos::null;
326  thyra_precOp = rcp_dynamic_cast<Thyra::LinearOpBase<Scalar> >(defaultPrec->getNonconstUnspecifiedPrecOp(), true);
327 
328  // Variable for RefMaxwell preconditioner: either build a new one or reuse the existing preconditioner
329  RCP<MueLu::RefMaxwell<Scalar,LocalOrdinal,GlobalOrdinal,Node> > preconditioner = Teuchos::null;
330 
331  // make a decision whether to (re)build the multigrid preconditioner or reuse the old one
332  // rebuild preconditioner if startingOver == true
333  // reuse preconditioner if startingOver == false
334  const bool startingOver = (thyra_precOp.is_null() || !paramList.isParameter("reuse: type") || paramList.get<std::string>("reuse: type") == "none");
335 
336  if (startingOver == true) {
337  // extract coordinates from parameter list
338  Teuchos::RCP<XpMultVecDouble> coordinates = Teuchos::null;
340  paramList.set<RCP<XpMultVecDouble> >("Coordinates", coordinates);
341 
342  // TODO check for Xpetra or Thyra vectors?
343 #ifdef HAVE_MUELU_TPETRA
344  if (bIsTpetra) {
345 #if ((defined(EPETRA_HAVE_OMP) && (defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT))) || \
346  (!defined(EPETRA_HAVE_OMP) && (defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT))))
347  typedef Tpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node> tV;
348  typedef Tpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> tMV;
349  typedef Tpetra::CrsMatrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> TpCrsMat;
350  if (paramList.isType<Teuchos::RCP<tMV> >("Nullspace")) {
351  RCP<tMV> tpetra_nullspace = paramList.get<RCP<tMV> >("Nullspace");
352  paramList.remove("Nullspace");
353  RCP<XpMultVec> nullspace = MueLu::TpetraMultiVector_To_XpetraMultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>(tpetra_nullspace);
354  paramList.set<RCP<XpMultVec> >("Nullspace", nullspace);
356  }
357 
358  if (paramList.isParameter("M1")) {
359  if (paramList.isType<Teuchos::RCP<TpCrsMat> >("M1")) {
360  RCP<TpCrsMat> tM1 = paramList.get<RCP<TpCrsMat> >("M1");
361  paramList.remove("M1");
362  RCP<XpCrsMat> xM1 = rcp_dynamic_cast<XpCrsMat>(tM1, true);
363  paramList.set<RCP<XpCrsMat> >("M1", xM1);
364  } else if (paramList.isType<Teuchos::RCP<const ThyLinOpBase> >("M1")) {
365  RCP<const ThyLinOpBase> thyM1 = paramList.get<RCP<const ThyLinOpBase> >("M1");
366  paramList.remove("M1");
367  RCP<const XpCrsMat> crsM1 = XpThyUtils::toXpetra(thyM1);
369  // MueLu needs a non-const object as input
370  RCP<XpCrsMat> crsM1NonConst = Teuchos::rcp_const_cast<XpCrsMat>(crsM1);
372  // wrap as an Xpetra::Matrix that MueLu can work with
374  paramList.set<RCP<XpMat> >("M1", M1);
375  } else if (paramList.isType<Teuchos::RCP<XpMat> >("M1")) {
376  // do nothing
377  } else
378  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "Parameter M1 has wrong type.");
379  } else
380  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "Need to specify matrix M1.");
381 
382  if (paramList.isParameter("D0")) {
383  if(paramList.isType<Teuchos::RCP<TpCrsMat> >("D0")) {
384  RCP<TpCrsMat> tD0 = paramList.get<RCP<TpCrsMat> >("D0");
385  paramList.remove("D0");
386  RCP<XpCrsMat> xD0 = rcp_dynamic_cast<XpCrsMat>(tD0, true);
387  paramList.set<RCP<XpCrsMat> >("D0", xD0);
388  } else if (paramList.isType<Teuchos::RCP<const ThyLinOpBase> >("D0")) {
389  RCP<const ThyLinOpBase> thyD0 = paramList.get<RCP<const ThyLinOpBase> >("D0");
390  paramList.remove("D0");
391  RCP<const XpCrsMat> crsD0 = XpThyUtils::toXpetra(thyD0);
393  // MueLu needs a non-const object as input
394  RCP<XpCrsMat> crsD0NonConst = Teuchos::rcp_const_cast<XpCrsMat>(crsD0);
396  // wrap as an Xpetra::Matrix that MueLu can work with
398  paramList.set<RCP<XpMat> >("D0", D0);
399  } else if (paramList.isType<Teuchos::RCP<XpMat> >("D0")) {
400  // do nothing
401  } else
402  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "Parameter D0 has wrong type.");
403  } else
404  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "Need to specify matrix D0.");
405 
406  if (paramList.isParameter("M0inv")) {
407  if (paramList.isType<Teuchos::RCP<TpCrsMat> >("M0inv")) {
408  RCP<TpCrsMat> tM0inv = paramList.get<RCP<TpCrsMat> >("M0inv");
409  paramList.remove("M0inv");
410  RCP<XpCrsMat> xM0inv = rcp_dynamic_cast<XpCrsMat>(tM0inv, true);
411  paramList.set<RCP<XpCrsMat> >("M0inv", xM0inv);
412  } else if (paramList.isType<Teuchos::RCP<const ThyDiagLinOpBase> >("M0inv")) {
413  RCP<const ThyDiagLinOpBase> thyM0inv = paramList.get<RCP<const ThyDiagLinOpBase> >("M0inv");
414  paramList.remove("M0inv");
415  RCP<const Thyra::VectorBase<Scalar> > diag = thyM0inv->getDiag();
416  RCP<const Thyra::TpetraVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > ttDiag = rcp_dynamic_cast<const Thyra::TpetraVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(diag);
417  RCP<const tV> tDiag = Thyra::TpetraOperatorVectorExtraction<Scalar,LocalOrdinal,GlobalOrdinal,Node>::getConstTpetraVector(diag);
419  paramList.set<RCP<XpMat> >("M0inv", M0inv);
420  } else if (paramList.isType<Teuchos::RCP<const ThyLinOpBase> >("M0inv")) {
421  RCP<const ThyLinOpBase> thyM0inv = paramList.get<RCP<const ThyLinOpBase> >("M0inv");
422  paramList.remove("M0inv");
423  RCP<const XpCrsMat> crsM0inv = XpThyUtils::toXpetra(thyM0inv);
425  // MueLu needs a non-const object as input
426  RCP<XpCrsMat> crsM0invNonConst = Teuchos::rcp_const_cast<XpCrsMat>(crsM0inv);
427  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(crsM0invNonConst));
428  // wrap as an Xpetra::Matrix that MueLu can work with
430  paramList.set<RCP<XpMat> >("M0inv", M0inv);
431  } else if (paramList.isType<Teuchos::RCP<XpMat> >("M0inv")) {
432  // do nothing
433  } else
434  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "Parameter M0inv has wrong type.");
435  } else
436  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "Need to specify matrix M0inv.");
437 #else
439  "Thyra::MueLuRefMaxwellPreconditionerFactory: Tpetra does not support GO=int and or EpetraNode.");
440 #endif
441  }
442 #endif
443 #ifdef HAVE_MUELU_EPETRA
444  if (bIsEpetra) {
445  if (paramList.isType<RCP<Epetra_MultiVector> >("Nullspace")) {
446  RCP<Epetra_MultiVector> epetra_nullspace = Teuchos::null;
447  epetra_nullspace = paramList.get<RCP<Epetra_MultiVector> >("Nullspace");
448  paramList.remove("Nullspace");
450  RCP<Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType,int,int,Node> > xpEpNullspaceMult = rcp_dynamic_cast<Xpetra::MultiVector<typename Teuchos::ScalarTraits<Scalar>::magnitudeType,int,int,Node> >(xpEpNullspace, true);
451  RCP<XpMultVec> nullspace = rcp_dynamic_cast<XpMultVec>(xpEpNullspaceMult, true);
452  paramList.set<RCP<XpMultVec> >("Nullspace", nullspace);
453  }
454 
455  if (paramList.isParameter("M1")) {
456  if (paramList.isType<Teuchos::RCP<Epetra_CrsMatrix> >("M1")) {
457  RCP<Epetra_CrsMatrix> eM1 = paramList.get<RCP<Epetra_CrsMatrix> >("M1");
458  paramList.remove("M1");
459  RCP<XpEpCrsMat> xeM1 = Teuchos::rcp(new XpEpCrsMat(eM1));
460  RCP<XpCrsMat> xCrsM1 = rcp_dynamic_cast<XpCrsMat>(xeM1, true);
461  RCP<XpCrsMatWrap> xwM1 = Teuchos::rcp(new XpCrsMatWrap(xCrsM1));
462  RCP<XpMat> xM1 = rcp_dynamic_cast<XpMat>(xwM1);
463  paramList.set<RCP<XpMat> >("M1", xM1);
464  }
465  else if (paramList.isType<Teuchos::RCP<const ThyLinOpBase> >("M1")) {
466  RCP<const ThyLinOpBase> thyM1 = paramList.get<RCP<const ThyLinOpBase> >("M1");
467  paramList.remove("M1");
468  RCP<const XpCrsMat> crsM1 = XpThyUtils::toXpetra(thyM1);
470  // MueLu needs a non-const object as input
471  RCP<XpCrsMat> crsM1NonConst = Teuchos::rcp_const_cast<XpCrsMat>(crsM1);
473  // wrap as an Xpetra::Matrix that MueLu can work with
475  paramList.set<RCP<XpMat> >("M1", M1);
476  } else if (paramList.isType<Teuchos::RCP<XpMat> >("M1")) {
477  // do nothing
478  } else
479  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "Parameter M1 has wrong type.");
480  } else
481  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "Need to specify matrix M1.");
482 
483  if (paramList.isParameter("D0")) {
484  if (paramList.isType<Teuchos::RCP<Epetra_CrsMatrix> >("D0")) {
485  RCP<Epetra_CrsMatrix> eD0 = paramList.get<RCP<Epetra_CrsMatrix> >("D0");
486  paramList.remove("D0");
487  RCP<XpEpCrsMat> xeD0 = Teuchos::rcp(new XpEpCrsMat(eD0));
488  RCP<XpCrsMat> xCrsD0 = rcp_dynamic_cast<XpCrsMat>(xeD0, true);
489  RCP<XpCrsMatWrap> xwD0 = Teuchos::rcp(new XpCrsMatWrap(xCrsD0));
490  RCP<XpMat> xD0 = rcp_dynamic_cast<XpMat>(xwD0);
491  paramList.set<RCP<XpMat> >("D0", xD0);
492  }
493  else if (paramList.isType<Teuchos::RCP<const ThyLinOpBase> >("D0")) {
494  RCP<const ThyLinOpBase> thyD0 = paramList.get<RCP<const ThyLinOpBase> >("D0");
495  paramList.remove("D0");
496  RCP<const XpCrsMat> crsD0 = XpThyUtils::toXpetra(thyD0);
498  // MueLu needs a non-const object as input
499  RCP<XpCrsMat> crsD0NonConst = Teuchos::rcp_const_cast<XpCrsMat>(crsD0);
501  // wrap as an Xpetra::Matrix that MueLu can work with
503  paramList.set<RCP<XpMat> >("D0", D0);
504  } else if (paramList.isType<Teuchos::RCP<XpMat> >("D0")) {
505  // do nothing
506  } else
507  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "Parameter D0 has wrong type.");
508  } else
509  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "Need to specify matrix D0.");
510 
511  if (paramList.isParameter("M0inv")) {
512  if (paramList.isType<Teuchos::RCP<Epetra_CrsMatrix> >("M0inv")) {
513  RCP<Epetra_CrsMatrix> eM0inv = paramList.get<RCP<Epetra_CrsMatrix> >("M0inv");
514  paramList.remove("M0inv");
515  RCP<XpEpCrsMat> xeM0inv = Teuchos::rcp(new XpEpCrsMat(eM0inv));
516  RCP<XpCrsMat> xCrsM0inv = rcp_dynamic_cast<XpCrsMat>(xeM0inv, true);
517  RCP<XpCrsMatWrap> xwM0inv = Teuchos::rcp(new XpCrsMatWrap(xCrsM0inv));
518  RCP<XpMat> xM0inv = rcp_dynamic_cast<XpMat>(xwM0inv);
519  paramList.set<RCP<XpMat> >("M0inv", xM0inv);
520  }
521  else if (paramList.isType<Teuchos::RCP<const ThyDiagLinOpBase> >("M0inv")) {
522  RCP<const ThyDiagLinOpBase> thyM0inv = paramList.get<RCP<const ThyDiagLinOpBase> >("M0inv");
523  paramList.remove("M0inv");
524 
525  RCP<const Teuchos::Comm<int> > comm = A->getDomainMap()->getComm();
526  RCP<const Epetra_Map> map = Thyra::get_Epetra_Map(*(thyM0inv->range()), Xpetra::toEpetra(comm));
527  // RCP<XpMap> map = XpThyUtils::toXpetra(thyM0inv->range(), comm);
528  RCP<const Thyra::VectorBase<double> > diag = thyM0inv->getDiag();
529  RCP<const Epetra_Vector> eDiag = Thyra::get_Epetra_Vector(*map, diag);
530  RCP<Epetra_Vector> nceDiag = Teuchos::rcp_const_cast<Epetra_Vector>(eDiag);
534  paramList.set<RCP<XpMat> >("M0inv", M0inv);
535  } else if (paramList.isType<Teuchos::RCP<const ThyLinOpBase> >("M0inv")) {
536  RCP<const ThyLinOpBase> thyM0inv = paramList.get<RCP<const ThyLinOpBase> >("M0inv");
537  paramList.remove("M0inv");
538  RCP<const XpCrsMat> crsM0inv = XpThyUtils::toXpetra(thyM0inv);
540  // MueLu needs a non-const object as input
541  RCP<XpCrsMat> crsM0invNonConst = Teuchos::rcp_const_cast<XpCrsMat>(crsM0inv);
542  TEUCHOS_TEST_FOR_EXCEPT(Teuchos::is_null(crsM0invNonConst));
543  // wrap as an Xpetra::Matrix that MueLu can work with
545  paramList.set<RCP<XpMat> >("M0inv", M0inv);
546  } else if (paramList.isType<Teuchos::RCP<XpMat> >("M0inv")) {
547  // do nothing
548  } else
549  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "Parameter M0inv has wrong type.");
550  } else
551  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "Need to specify matrix M0inv.");
552  }
553 #endif
554  // build a new MueLu RefMaxwell preconditioner
555  paramList.set<bool>("refmaxwell: use as preconditioner", true);
556  preconditioner = rcp(new MueLu::RefMaxwell<Scalar,LocalOrdinal,GlobalOrdinal,Node>(A, paramList, true));
557 
558  } else {
559  // reuse old MueLu preconditioner stored in MueLu Xpetra operator and put in new matrix
560 
561  // get old MueLu preconditioner
562 #if defined(HAVE_MUELU_TPETRA)
563  if (bIsTpetra) {
564 #if ((defined(EPETRA_HAVE_OMP) && (defined(HAVE_TPETRA_INST_OPENMP) && defined(HAVE_TPETRA_INST_INT_INT))) || \
565  (!defined(EPETRA_HAVE_OMP) && (defined(HAVE_TPETRA_INST_SERIAL) && defined(HAVE_TPETRA_INST_INT_INT))))
566  RCP<ThyTpLinOp> tpetr_precOp = rcp_dynamic_cast<ThyTpLinOp>(thyra_precOp);
567  preconditioner = rcp_dynamic_cast<MueLu::RefMaxwell<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(tpetr_precOp->getTpetraOperator(),true);
568 #else
570  "Thyra::MueLuRefMaxwellPreconditionerFactory: Tpetra does not support GO=int and or EpetraNode.");
571 #endif
572  }
573 #endif
574 #if defined(HAVE_MUELU_EPETRA)// && defined(HAVE_MUELU_SERIAL)
575  if (bIsEpetra) {
576  RCP<ThyEpLinOp> epetr_precOp = rcp_dynamic_cast<ThyEpLinOp>(thyra_precOp);
577  preconditioner = rcp_dynamic_cast<MueLu::RefMaxwell<Scalar,LocalOrdinal,GlobalOrdinal,Node> >(epetr_precOp->epetra_op(),true);
578  }
579 #endif
580  // TODO add the blocked matrix case here...
581 
582  }
583 
584  // wrap preconditioner in thyraPrecOp
585  RCP<ThyLinOpBase > thyraPrecOp = Teuchos::null;
586  RCP<const VectorSpaceBase<Scalar> > thyraRangeSpace = Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::toThyra(preconditioner->getRangeMap());
587  RCP<const VectorSpaceBase<Scalar> > thyraDomainSpace = Xpetra::ThyraUtils<Scalar,LocalOrdinal,GlobalOrdinal,Node>::toThyra(preconditioner->getDomainMap());
588 
589  RCP<XpOp> xpOp = Teuchos::rcp_dynamic_cast<XpOp>(preconditioner);
590  thyraPrecOp = Thyra::xpetraLinearOp<Scalar, LocalOrdinal, GlobalOrdinal, Node>(thyraRangeSpace, thyraDomainSpace,xpOp);
591 
593 
594  defaultPrec->initializeUnspecified(thyraPrecOp);
595  }
596 
598  void uninitializePrec(PreconditionerBase<Scalar>* prec,
599  Teuchos::RCP<const LinearOpSourceBase<Scalar> >* fwdOp,
600  ESupportSolveUse* supportSolveUse
601  ) const {
602  TEUCHOS_ASSERT(prec);
603 
604  // Retrieve concrete preconditioner object
605  const Teuchos::Ptr<DefaultPreconditioner<Scalar> > defaultPrec = Teuchos::ptr(dynamic_cast<DefaultPreconditioner<Scalar> *>(prec));
607 
608  if (fwdOp) {
609  // TODO: Implement properly instead of returning default value
610  *fwdOp = Teuchos::null;
611  }
612 
613  if (supportSolveUse) {
614  // TODO: Implement properly instead of returning default value
615  *supportSolveUse = Thyra::SUPPORT_SOLVE_UNSPECIFIED;
616  }
617 
618  defaultPrec->uninitialize();
619  }
620 
622 
625 
629  paramList_ = paramList;
630  }
633  RCP<ParameterList> savedParamList = paramList_;
634  paramList_ = Teuchos::null;
635  return savedParamList;
636  }
643  static RCP<const ParameterList> validPL;
644 
645  if (Teuchos::is_null(validPL))
646  validPL = rcp(new ParameterList());
647 
648  return validPL;
649  }
651 
654 
656  std::string description() const { return "Thyra::MueLuRefMaxwellPreconditionerFactory"; }
657 
658  // ToDo: Add an override of describe(...) to give more detail!
659 
661 
662  private:
664  }; // end specialization for Epetra
665 
666 #endif // HAVE_MUELU_EPETRA
667 
668 } // namespace Thyra
669 
670 #endif // #ifdef HAVE_MUELU_STRATIMIKOS
671 
672 #endif // THYRA_MUELU_REFMAXWELL_PRECONDITIONER_FACTORY_DECL_HPP
void initializePrec(const Teuchos::RCP< const LinearOpSourceBase< Scalar > > &fwdOpSrc, PreconditionerBase< Scalar > *prec, const ESupportSolveUse) const
T & get(const std::string &name, T def_value)
static RCP< Xpetra::MultiVector< typename Teuchos::ScalarTraits< Scalar >::magnitudeType, LocalOrdinal, GlobalOrdinal, Node > > ExtractCoordinatesFromParameterList(ParameterList &paramList)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
bool nonnull(const std::shared_ptr< T > &p)
bool is_null(const std::shared_ptr< T > &p)
bool isCompatible(const LinearOpSourceBase< Scalar > &fwdOp) const
Concrete preconditioner factory subclass for Thyra based on MueLu.Add support for MueLu preconditione...
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters() const
const Epetra_CrsGraph & toEpetra(const RCP< const CrsGraph< int, GlobalOrdinal, Node > > &graph)
Teuchos::RCP< PreconditionerBase< Scalar > > createPrec() const
void uninitializePrec(PreconditionerBase< Scalar > *prec, Teuchos::RCP< const LinearOpSourceBase< Scalar > > *fwdOp, ESupportSolveUse *supportSolveUse) const
void uninitializePrec(PreconditionerBase< Scalar > *prec, Teuchos::RCP< const LinearOpSourceBase< Scalar > > *fwdOp, ESupportSolveUse *supportSolveUse) const
Preconditioner (wrapped as a Xpetra::Operator) for Maxwell&#39;s equations in curl-curl form...
bool isParameter(const std::string &name) const
bool remove(std::string const &name, bool throwIfNotExists=true)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
void initializePrec(const Teuchos::RCP< const LinearOpSourceBase< Scalar > > &fwdOp, PreconditionerBase< Scalar > *prec, const ESupportSolveUse supportSolveUse) const
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &paramList)
RCP< const CrsGraph< int, GlobalOrdinal, Node > > toXpetra(const Epetra_CrsGraph &g)
bool isType(const std::string &name) const
static RCP< Matrix > Build(const RCP< const Map > &rowMap, size_t maxNumEntriesPerRow, Xpetra::ProfileType pftype=Xpetra::DynamicProfile)
Exception throws to report errors in the internal logical of the program.
#define TEUCHOS_ASSERT(assertion_test)
#define TEUCHOS_TEST_FOR_EXCEPT(throw_exception_test)
Teuchos::RCP< const Teuchos::ParameterList > getParameterList() const
bool is_null() const