Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_MLLinearOp.cpp
1 // @HEADER
2 // *****************************************************************************
3 // Teko: A package for block and physics based preconditioning
4 //
5 // Copyright 2010 NTESS and the Teko contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #include "Teko_MLLinearOp.hpp"
11 
12 #include "Teko_EpetraOperatorWrapper.hpp"
13 #include "Teko_mlutils.hpp"
14 #include "Teko_PreconditionerLinearOp.hpp"
15 
16 #include "ml_MultiLevelPreconditioner.h"
17 
18 namespace Teko {
19 
20 MLLinearOp::MLLinearOp(const Teuchos::RCP<ML_Epetra::MultiLevelPreconditioner> &mlPrecOp)
21  : mlPrecOp_(mlPrecOp) {
22  extractConversionInformation(*mlPrecOp_);
23 }
24 
25 void MLLinearOp::extractConversionInformation(ML_Epetra::MultiLevelPreconditioner &mlPrec) {
26  const ML *ml = mlPrec.GetML();
27  const ML_Smoother *preSmoother = ml->pre_smoother;
28  const ML_Smoother *postSmoother = ml->post_smoother;
29 
30  // grab data object
31  const mlutils::SmootherData *smootherData;
32  if (preSmoother != 0)
33  smootherData = (const mlutils::SmootherData *)ML_Get_MySmootherData(preSmoother);
34  else if (postSmoother != 0)
35  smootherData = (const mlutils::SmootherData *)ML_Get_MySmootherData(preSmoother);
36  else
37  TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
38  "MLLinearOp::extractConversionInformation pre and post smoother "
39  << "are both null, cannot build operator");
40 
41  Amat_ = Teuchos::rcp_dynamic_cast<Epetra::EpetraOperatorWrapper>(smootherData->Amat);
42 
43  // for doing Epetra_Vector -> Thyra vector conversion
44  mappingStrategy_ = Amat_->getMapStrategy();
45 
46  // to construct vectorspace for this object
47  BlockedLinearOp bloA = toBlockedLinearOp(Amat_->getThyraOp());
48  productDomain_ =
49  bloA->productRange(); // this operator is the inverse of bloA...hence swap range and domain
50  productRange_ = bloA->productDomain();
51 }
52 
53 void MLLinearOp::implicitApply(const BlockedMultiVector &x, BlockedMultiVector &y,
54  const double alpha, const double beta) const {
55  int columns = x->domain()->dim();
56  TEUCHOS_ASSERT(columns == y->domain()->dim()); // check for equal columns
57 
58  // (re)allocate vectors conditinolly if required size changed
59  if (eX_ == Teuchos::null || columns != eX_->NumVectors()) {
60  eX_ = Teuchos::rcp(new Epetra_MultiVector(mlPrecOp_->OperatorDomainMap(), x->domain()->dim()));
61  eY_ = Teuchos::rcp(new Epetra_MultiVector(mlPrecOp_->OperatorRangeMap(), y->domain()->dim()));
62  }
63 
64  BlockedMultiVector yCopy;
65  if (beta != 0)
66  yCopy = deepcopy(y);
67  else
68  yCopy = y;
69 
70  // initialize Epetra vectors
71  eY_->PutScalar(0.0);
72  mappingStrategy_->copyThyraIntoEpetra(x, *eX_);
73 
74  // run multigrid
75  mlPrecOp_->ApplyInverse(*eX_, *eY_);
76 
77  // fill thyra vectors
78  mappingStrategy_->copyEpetraIntoThyra(*eY_, yCopy.ptr());
79 
80  // scale result by alpha
81  if (beta != 0)
82  update(alpha, yCopy, beta, y); // y = alpha * yCopy + beta * y
83  else if (alpha != 1.0)
84  scale(alpha, y); // y = alpha * y
85 }
86 
87 void MLLinearOp::describe(Teuchos::FancyOStream &out_arg,
88  const Teuchos::EVerbosityLevel verbLevel) const {
89  out_arg << "MLLinearOp";
90 }
91 
92 Teuchos::RCP<const ML_Epetra::MultiLevelPreconditioner> MLLinearOp::getMLPreconditioner() const {
93  return mlPrecOp_;
94 }
95 
96 Teuchos::RCP<ML_Epetra::MultiLevelPreconditioner> MLLinearOp::getMLPreconditioner() {
97  return mlPrecOp_;
98 }
99 
100 Teuchos::RCP<const ML_Epetra::MultiLevelPreconditioner> getMLPreconditioner(
101  const Teko::LinearOp &lo) {
102  Teko::LinearOp precOp = lo;
103 
104  // try to pull it of a preconditioner linear op
105  Teuchos::RCP<const Teko::PreconditionerLinearOp<double> > plo =
106  Teuchos::rcp_dynamic_cast<const Teko::PreconditionerLinearOp<double> >(lo);
107  if (plo != Teuchos::null) precOp = plo->getOperator();
108 
109  // try to extract the ML operator
110  Teuchos::RCP<const MLLinearOp> mlOp = Teuchos::rcp_dynamic_cast<const MLLinearOp>(precOp);
111 
112  TEUCHOS_TEST_FOR_EXCEPTION(
113  mlOp == Teuchos::null, std::runtime_error,
114  "Teko::getMLPreconditioner could not extract a MLLinearOp from the passed in argument");
115 
116  return mlOp->getMLPreconditioner();
117 }
118 
119 } // namespace Teko
Teko::LinearOp getOperator() const
Get teko linear operator.
Class that wraps a PreconditionerBase object it makes it behave like a linear operator.