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