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