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