Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_TpetraOperatorWrapper.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_TpetraOperatorWrapper.hpp"
11 #include "Thyra_SpmdVectorBase.hpp"
12 #include "Thyra_MultiVectorStdOps.hpp"
13 #include "Teuchos_DefaultSerialComm.hpp"
14 #include "Thyra_TpetraLinearOp.hpp"
15 #include "Tpetra_Vector.hpp"
16 #include "Thyra_TpetraThyraWrappers.hpp"
17 
18 // #include "Thyra_LinearOperator.hpp"
19 #include "Thyra_BlockedLinearOpBase.hpp"
20 #include "Thyra_ProductVectorSpaceBase.hpp"
21 #include "Thyra_TpetraLinearOp.hpp"
22 
23 #include "Teko_TpetraThyraConverter.hpp"
24 #include "Teuchos_Ptr.hpp"
25 
26 namespace Teko {
27 namespace TpetraHelpers {
28 
29 using namespace Teuchos;
30 using namespace Thyra;
31 
32 DefaultMappingStrategy::DefaultMappingStrategy(
33  const RCP<const Thyra::LinearOpBase<double> >& thyraOp,
34  const Teuchos::Comm<Thyra::Ordinal>& comm) {
35  RCP<Teuchos::Comm<Thyra::Ordinal> > newComm = comm.duplicate();
36 
37  // extract vector spaces from linear operator
38  domainSpace_ = thyraOp->domain();
39  rangeSpace_ = thyraOp->range();
40 
41  domainMap_ = Teko::TpetraHelpers::thyraVSToTpetraMap(*domainSpace_, newComm);
42  rangeMap_ = Teko::TpetraHelpers::thyraVSToTpetraMap(*rangeSpace_, newComm);
43 }
44 
46  const Tpetra::MultiVector<ST, LO, GO, NT>& x,
47  const Ptr<Thyra::MultiVectorBase<ST> >& thyraVec) const {
48  Teko::TpetraHelpers::blockTpetraToThyra(x, thyraVec);
49 }
50 
52  const RCP<const Thyra::MultiVectorBase<ST> >& thyraVec,
53  Tpetra::MultiVector<ST, LO, GO, NT>& v) const {
54  Teko::TpetraHelpers::blockThyraToTpetra(thyraVec, v);
55 }
56 
57 TpetraOperatorWrapper::TpetraOperatorWrapper() {
58  useTranspose_ = false;
59  mapStrategy_ = Teuchos::null;
60  thyraOp_ = Teuchos::null;
61  comm_ = Teuchos::null;
62  label_ = Teuchos::null;
63 }
64 
65 TpetraOperatorWrapper::TpetraOperatorWrapper(const RCP<const Thyra::LinearOpBase<ST> >& thyraOp) {
66  SetOperator(thyraOp);
67 }
68 
69 TpetraOperatorWrapper::TpetraOperatorWrapper(const RCP<const Thyra::LinearOpBase<ST> >& thyraOp,
70  const RCP<const MappingStrategy>& mapStrategy)
71  : mapStrategy_(mapStrategy) {
72  SetOperator(thyraOp);
73 }
74 
75 TpetraOperatorWrapper::TpetraOperatorWrapper(const RCP<const MappingStrategy>& mapStrategy)
76  : mapStrategy_(mapStrategy) {
77  useTranspose_ = false;
78  thyraOp_ = Teuchos::null;
79  comm_ = Teuchos::null;
80  label_ = Teuchos::null;
81 }
82 
83 void TpetraOperatorWrapper::SetOperator(const RCP<const LinearOpBase<ST> >& thyraOp,
84  bool buildMap) {
85  useTranspose_ = false;
86  thyraOp_ = thyraOp;
87  comm_ = getThyraComm(*thyraOp);
88  label_ = thyraOp_->description();
89  if (mapStrategy_ == Teuchos::null && buildMap)
90  mapStrategy_ = Teuchos::rcp(new DefaultMappingStrategy(thyraOp, *comm_));
91 }
92 
93 double TpetraOperatorWrapper::NormInf() const {
94  TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
95  "TpetraOperatorWrapper::NormInf not implemated");
96  return 1.0;
97 }
98 
99 void TpetraOperatorWrapper::apply(const Tpetra::MultiVector<ST, LO, GO, NT>& X,
100  Tpetra::MultiVector<ST, LO, GO, NT>& Y,
101  Teuchos::ETransp /* mode */, ST alpha, ST beta) const {
102  if (!useTranspose_) {
103  // allocate space for each vector
104  RCP<Thyra::MultiVectorBase<ST> > tX;
105  RCP<Thyra::MultiVectorBase<ST> > tY;
106 
107  tX = Thyra::createMembers(thyraOp_->domain(), X.getNumVectors());
108  tY = Thyra::createMembers(thyraOp_->range(), X.getNumVectors());
109 
110  Thyra::assign(tX.ptr(), 0.0);
111  Thyra::assign(tY.ptr(), 0.0);
112 
113  // copy epetra X into thyra X
114  mapStrategy_->copyTpetraIntoThyra(X, tX.ptr());
115  mapStrategy_->copyTpetraIntoThyra(
116  Y, tY.ptr()); // if this matrix isn't block square, this probably won't work!
117 
118  // perform matrix vector multiplication
119  thyraOp_->apply(Thyra::NOTRANS, *tX, tY.ptr(), alpha, beta);
120 
121  // copy thyra Y into epetra Y
122  mapStrategy_->copyThyraIntoTpetra(tY, Y);
123  } else {
124  TEUCHOS_ASSERT(false);
125  }
126 }
127 
128 void TpetraOperatorWrapper::applyInverse(const Tpetra::MultiVector<ST, LO, GO, NT>& /* X */,
129  Tpetra::MultiVector<ST, LO, GO, NT>& /* Y */,
130  Teuchos::ETransp /* mode */, ST /* alpha */,
131  ST /* beta */) const {
132  TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
133  "TpetraOperatorWrapper::applyInverse not implemented");
134 }
135 
136 RCP<const Teuchos::Comm<Thyra::Ordinal> > TpetraOperatorWrapper::getThyraComm(
137  const Thyra::LinearOpBase<ST>& inOp) const {
138  RCP<const VectorSpaceBase<ST> > vs = inOp.domain();
139 
140  RCP<const SpmdVectorSpaceBase<ST> > spmd;
141  RCP<const VectorSpaceBase<ST> > current = vs;
142  while (current != Teuchos::null) {
143  // try to cast to a product vector space first
144  RCP<const ProductVectorSpaceBase<ST> > prod =
145  rcp_dynamic_cast<const ProductVectorSpaceBase<ST> >(current);
146 
147  // figure out what type it is
148  if (prod == Teuchos::null) {
149  // hopfully this is a SPMD vector space
150  spmd = rcp_dynamic_cast<const SpmdVectorSpaceBase<ST> >(current);
151 
152  break;
153  } else // get first convenient vector space
154  current = prod->getBlock(0);
155  }
156 
157  TEUCHOS_TEST_FOR_EXCEPTION(spmd == Teuchos::null, std::runtime_error,
158  "TpetraOperatorWrapper requires std::vector space "
159  "blocks to be SPMD std::vector spaces");
160 
161  return spmd->getComm();
162  /*
163  const Thyra::ConstLinearOperator<double> thyraOp = rcpFromRef(inOp);
164 
165  RCP<Epetra_Comm> rtn;
166  // VectorSpace<double> vs = thyraOp.domain().getBlock(0);
167  RCP<const VectorSpaceBase<double> > vs = thyraOp.domain().getBlock(0).constPtr();
168 
169  // search for an SpmdVectorSpaceBase object
170  RCP<const SpmdVectorSpaceBase<double> > spmd;
171  RCP<const VectorSpaceBase<double> > current = vs;
172  while(current!=Teuchos::null) {
173  // try to cast to a product vector space first
174  RCP<const ProductVectorSpaceBase<double> > prod
175  = rcp_dynamic_cast<const ProductVectorSpaceBase<double> >(current);
176 
177  // figure out what type it is
178  if(prod==Teuchos::null) {
179  // hopfully this is a SPMD vector space
180  spmd = rcp_dynamic_cast<const SpmdVectorSpaceBase<double> >(current);
181 
182  break;
183  }
184  else {
185  // get first convenient vector space
186  current = prod->getBlock(0);
187  }
188  }
189 
190  TEUCHOS_TEST_FOR_EXCEPTION(spmd==Teuchos::null, std::runtime_error,
191  "TpetraOperatorWrapper requires std::vector space "
192  "blocks to be SPMD std::vector spaces");
193 
194  const SerialComm<Thyra::Ordinal>* serialComm
195  = dynamic_cast<const SerialComm<Thyra::Ordinal>*>(spmd->getComm().get());
196 
197  #ifdef HAVE_MPI
198  const MpiComm<Thyra::Ordinal>* mpiComm
199  = dynamic_cast<const MpiComm<Thyra::Ordinal>*>(spmd->getComm().get());
200 
201  TEUCHOS_TEST_FOR_EXCEPTION(mpiComm==0 && serialComm==0, std::runtime_error,
202  "SPMD std::vector space has a communicator that is "
203  "neither a serial comm nor an MPI comm");
204 
205  if (mpiComm != 0)
206  {
207  rtn = rcp(new Epetra_MpiComm(MPI_COMM_WORLD));
208  }
209  else
210  {
211  rtn = rcp(new Epetra_SerialComm());
212  }
213  #else
214  TEUCHOS_TEST_FOR_EXCEPTION(serialComm==0, std::runtime_error,
215  "SPMD std::vector space has a communicator that is "
216  "neither a serial comm nor an MPI comm");
217  rtn = rcp(new Epetra_SerialComm());
218 
219  #endif
220 
221  TEUCHOS_TEST_FOR_EXCEPTION(rtn.get()==0, std::runtime_error, "null communicator created");
222  return rtn;
223  */
224 }
225 
227  const RCP<const Thyra::BlockedLinearOpBase<ST> > blkOp =
228  Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<ST> >(getThyraOp());
229 
230  return blkOp->productRange()->numBlocks();
231 }
232 
234  const RCP<const Thyra::BlockedLinearOpBase<ST> > blkOp =
235  Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<ST> >(getThyraOp());
236 
237  return blkOp->productDomain()->numBlocks();
238 }
239 
240 Teuchos::RCP<const Tpetra::Operator<ST, LO, GO, NT> > TpetraOperatorWrapper::GetBlock(int i,
241  int j) const {
242  const RCP<const Thyra::BlockedLinearOpBase<ST> > blkOp =
243  Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<ST> >(getThyraOp());
244 
245  RCP<const Thyra::TpetraLinearOp<ST, LO, GO, NT> > tOp =
246  rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST, LO, GO, NT> >(blkOp->getBlock(i, j));
247 
248  return tOp->getConstTpetraOperator();
249 }
250 
251 } // namespace TpetraHelpers
252 } // namespace Teko
virtual void copyThyraIntoTpetra(const RCP< const Thyra::MultiVectorBase< ST > > &thyraX, Tpetra::MultiVector< ST, LO, GO, NT > &tpetraX) const
Copy an Thyra::MultiVectorBase into a Epetra_MultiVector.
const RCP< const Thyra::LinearOpBase< ST > > getThyraOp() const
Return the thyra operator associated with this wrapper.
virtual void copyTpetraIntoThyra(const Tpetra::MultiVector< ST, LO, GO, NT > &tpetraX, const Teuchos::Ptr< Thyra::MultiVectorBase< ST > > &thyraX) const
Copy an Epetra_MultiVector into a Thyra::MultiVectorBase.
Teuchos::RCP< const Tpetra::Operator< ST, LO, GO, NT > > GetBlock(int i, int j) const
Grab the i,j block.
virtual int GetBlockRowCount()
Get the number of block rows in this operator.
virtual int GetBlockColCount()
Get the number of block columns in this operator.