Teko  Version of the Day
Teko_TpetraHelpers.cpp
1 /*
2 // @HEADER
3 //
4 // ***********************************************************************
5 //
6 // Teko: A package for block and physics based preconditioning
7 // Copyright 2010 Sandia Corporation
8 //
9 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
10 // the U.S. Government retains certain rights in this software.
11 //
12 // Redistribution and use in source and binary forms, with or without
13 // modification, are permitted provided that the following conditions are
14 // met:
15 //
16 // 1. Redistributions of source code must retain the above copyright
17 // notice, this list of conditions and the following disclaimer.
18 //
19 // 2. Redistributions in binary form must reproduce the above copyright
20 // notice, this list of conditions and the following disclaimer in the
21 // documentation and/or other materials provided with the distribution.
22 //
23 // 3. Neither the name of the Corporation nor the names of the
24 // contributors may be used to endorse or promote products derived from
25 // this software without specific prior written permission.
26 //
27 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
28 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
31 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 //
39 // Questions? Contact Eric C. Cyr (eccyr@sandia.gov)
40 //
41 // ***********************************************************************
42 //
43 // @HEADER
44 
45 */
46 
47 #include "Teko_TpetraHelpers.hpp"
48 
49 // Thyra Includes
50 #include "Thyra_EpetraLinearOp.hpp"
51 #include "Thyra_BlockedLinearOpBase.hpp"
52 #include "Thyra_DefaultMultipliedLinearOp.hpp"
53 #include "Thyra_DefaultDiagonalLinearOp.hpp"
54 #include "Thyra_DefaultZeroLinearOp.hpp"
55 #include "Thyra_DefaultBlockedLinearOp.hpp"
56 #include "Thyra_EpetraThyraWrappers.hpp"
57 #include "Thyra_SpmdVectorBase.hpp"
58 #include "Thyra_SpmdVectorSpaceBase.hpp"
59 #include "Thyra_ScalarProdVectorSpaceBase.hpp"
60 
61 // Epetra includes
62 #include "Epetra_Vector.h"
63 
64 // EpetraExt includes
65 #include "EpetraExt_ProductOperator.h"
66 #include "EpetraExt_MatrixMatrix.h"
67 
68 // Teko includes
69 #include "Teko_EpetraOperatorWrapper.hpp"
70 #include "Teko_Utilities.hpp"
71 
72 // Tpetra
73 #include "Thyra_TpetraLinearOp.hpp"
74 #include "Thyra_TpetraMultiVector.hpp"
75 #include "Tpetra_CrsMatrix.hpp"
76 #include "Tpetra_Vector.hpp"
77 #include "Thyra_TpetraThyraWrappers.hpp"
78 #include "TpetraExt_MatrixMatrix.hpp"
79 
80 using Teuchos::RCP;
81 using Teuchos::rcp;
82 using Teuchos::rcpFromRef;
83 using Teuchos::rcp_dynamic_cast;
84 using Teuchos::null;
85 
86 namespace Teko {
87 namespace TpetraHelpers {
88 
99 const Teuchos::RCP<const Thyra::LinearOpBase<ST> > thyraDiagOp(const RCP<const Tpetra::Vector<ST,LO,GO,NT> > & tv,const Tpetra::Map<LO,GO,NT> & map,
100  const std::string & lbl)
101 {
102  const RCP<const Thyra::VectorBase<ST> > thyraVec // need a Thyra::VectorBase object
103  = Thyra::createConstVector<ST,LO,GO,NT>(tv,Thyra::createVectorSpace<ST,LO,GO,NT>(rcpFromRef(map)));
104  Teuchos::RCP<Thyra::LinearOpBase<ST> > op
105  = Teuchos::rcp(new Thyra::DefaultDiagonalLinearOp<ST>(thyraVec));
106  op->setObjectLabel(lbl);
107  return op;
108 }
109 
120 const Teuchos::RCP<Thyra::LinearOpBase<ST> > thyraDiagOp(const RCP<Tpetra::Vector<ST,LO,GO,NT> > & tv,const Tpetra::Map<LO,GO,NT> & map,
121  const std::string & lbl)
122 {
123  const RCP<Thyra::VectorBase<ST> > thyraVec // need a Thyra::VectorBase object
124  = Thyra::createVector<ST,LO,GO,NT>(tv,Thyra::createVectorSpace<ST,LO,GO,NT>(rcpFromRef(map)));
125  Teuchos::RCP<Thyra::LinearOpBase<ST> > op
126  = Teuchos::rcp(new Thyra::DefaultDiagonalLinearOp<ST>(thyraVec));
127  op->setObjectLabel(lbl);
128  return op;
129 }
130 
140 void fillDefaultSpmdMultiVector(Teuchos::RCP<Thyra::TpetraMultiVector<ST,LO,GO,NT> > & spmdMV,
141  Teuchos::RCP<Tpetra::MultiVector<ST,LO,GO,NT> > & tpetraMV)
142 {
143  // first get desired range and domain
144  //const RCP<const Thyra::SpmdVectorSpaceBase<ST> > range = spmdMV->spmdSpace();
145  const RCP<Thyra::TpetraVectorSpace<ST,LO,GO,NT> > range = Thyra::tpetraVectorSpace<ST,LO,GO,NT>(tpetraMV->getMap());
146  const RCP<const Thyra::ScalarProdVectorSpaceBase<ST> > domain
147  = rcp_dynamic_cast<const Thyra::ScalarProdVectorSpaceBase<ST> >(spmdMV->domain());
148 
149  TEUCHOS_ASSERT((size_t) domain->dim()==tpetraMV->getNumVectors());
150 
151  // New local view of raw data
152  if(!tpetraMV->isConstantStride())
153  TEUCHOS_TEST_FOR_EXCEPT(true); // ToDo: Implement views of non-contiguous mult-vectors!
154 
155  // Build the MultiVector
156  spmdMV->initialize(range, domain, tpetraMV);
157 
158  // make sure the Epetra_MultiVector doesn't disappear prematurely
159  Teuchos::set_extra_data<RCP<Tpetra::MultiVector<ST,LO,GO,NT> > >(tpetraMV,"Tpetra::MultiVector",Teuchos::outArg(spmdMV));
160 }
161 
171 void identityRowIndices(const Tpetra::Map<LO,GO,NT> & rowMap, const Tpetra::CrsMatrix<ST,LO,GO,NT> & mat,std::vector<GO> & outIndices)
172 {
173  GO maxSz = mat.getGlobalMaxNumRowEntries();
174  std::vector<ST> values(maxSz);
175  std::vector<GO> indices(maxSz);
176 
177  // loop over elements owned by this processor
178  for(size_t i=0;i<rowMap.getNodeNumElements();i++) {
179  bool rowIsIdentity = true;
180  GO rowGID = rowMap.getGlobalElement(i);
181 
182  size_t numEntries = mat.getNumEntriesInGlobalRow (i);
183  auto indices = typename Tpetra::CrsMatrix<ST,LO,GO,NT>::nonconst_global_inds_host_view_type(Kokkos::ViewAllocateWithoutInitializing("rowIndices"),numEntries);
184  auto values = typename Tpetra::CrsMatrix<ST,LO,GO,NT>::nonconst_values_host_view_type(Kokkos::ViewAllocateWithoutInitializing("rowIndices"),numEntries);
185 
186  mat.getGlobalRowCopy(rowGID,indices,values,numEntries);
187 
188  // loop over the columns of this row
189  for(size_t j=0;j<numEntries;j++) {
190  GO colGID = indices(j);
191 
192  // look at row entries
193  if(colGID==rowGID) rowIsIdentity &= values(j)==1.0;
194  else rowIsIdentity &= values(j)==0.0;
195 
196  // not a dirchlet row...quit
197  if(not rowIsIdentity)
198  break;
199  }
200 
201  // save a row that is dirchlet
202  if(rowIsIdentity)
203  outIndices.push_back(rowGID);
204  }
205 }
206 
217 void zeroMultiVectorRowIndices(Tpetra::MultiVector<ST,LO,GO,NT> & mv,const std::vector<GO> & zeroIndices)
218 {
219  LO colCnt = mv.getNumVectors();
220  std::vector<GO>::const_iterator itr;
221 
222  // loop over the indices to zero
223  for(itr=zeroIndices.begin();itr!=zeroIndices.end();++itr) {
224 
225  // loop over columns
226  for(int j=0;j<colCnt;j++)
227  mv.replaceGlobalValue(*itr,j,0.0);
228  }
229 }
230 
240 ZeroedOperator::ZeroedOperator(const std::vector<GO> & zeroIndices,
241  const Teuchos::RCP<const Tpetra::Operator<ST,LO,GO,NT> > & op)
242  : zeroIndices_(zeroIndices), tpetraOp_(op)
243 { }
244 
246 void ZeroedOperator::apply(const Tpetra::MultiVector<ST,LO,GO,NT> & X, Tpetra::MultiVector<ST,LO,GO,NT> & Y, Teuchos::ETransp mode, ST alpha, ST beta) const
247 {
248 /*
249  Epetra_MultiVector temp(X);
250  zeroMultiVectorRowIndices(temp,zeroIndices_);
251  int result = epetraOp_->Apply(temp,Y);
252 */
253 
254  tpetraOp_->apply(X,Y,mode,alpha,beta);
255 
256  // zero a few of the rows
257  zeroMultiVectorRowIndices(Y,zeroIndices_);
258 }
259 
260 bool isTpetraLinearOp(const LinearOp & op)
261 {
262  // See if the operator is a TpetraLinearOp
263  RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op);
264  if (!tOp.is_null())
265  return true;
266 
267  // See if the operator is a wrapped TpetraLinearOp
268  ST scalar = 0.0;
269  Thyra::EOpTransp transp = Thyra::NOTRANS;
270  RCP<const Thyra::LinearOpBase<ST> > wrapped_op;
271  Thyra::unwrap(op, &scalar, &transp, &wrapped_op);
272  tOp = rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(wrapped_op);
273  if (!tOp.is_null())
274  return true;
275 
276  return false;
277 }
278 
279 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > getTpetraCrsMatrix(const LinearOp & op, ST *scalar, bool *transp)
280 {
281  // If the operator is a TpetraLinearOp
282  RCP<const Thyra::TpetraLinearOp<ST,LO,GO,NT> > tOp = rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(op);
283  if(!tOp.is_null()){
284  RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > matrix = rcp_dynamic_cast<const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),true);
285  *scalar = 1.0;
286  *transp = false;
287  return matrix;
288  }
289 
290  // If the operator is a wrapped TpetraLinearOp
291  RCP<const Thyra::LinearOpBase<ST> > wrapped_op;
292  Thyra::EOpTransp eTransp = Thyra::NOTRANS;
293  Thyra::unwrap(op, scalar, &eTransp, &wrapped_op);
294  tOp = rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST,LO,GO,NT> >(wrapped_op,true);
295  if(!tOp.is_null()){
296  RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > matrix = rcp_dynamic_cast<const Tpetra::CrsMatrix<ST,LO,GO,NT> >(tOp->getConstTpetraOperator(),true);
297  *transp = true;
298  if(eTransp == Thyra::NOTRANS)
299  *transp = false;
300  return matrix;
301  }
302 
303  return Teuchos::null;
304 }
305 
306 
307 RCP<const Tpetra::CrsMatrix<ST,LO,GO,NT> > epetraCrsMatrixToTpetra(const RCP<const Epetra_CrsMatrix> A_e, const RCP<const Teuchos::Comm<int> > comm)
308 {
309  int* ptr;
310  int* ind;
311  double* val;
312 
313  int info = A_e->ExtractCrsDataPointers (ptr, ind, val);
314  TEUCHOS_TEST_FOR_EXCEPTION(info!=0,std::logic_error, "Could not extract data from Epetra_CrsMatrix");
315  const LO numRows = A_e->Graph ().NumMyRows ();
316  const LO nnz = A_e->Graph ().NumMyEntries ();
317 
318  Teuchos::ArrayRCP<size_t> ptr2 (numRows+1);
319  Teuchos::ArrayRCP<int> ind2 (nnz);
320  Teuchos::ArrayRCP<double> val2 (nnz);
321 
322  std::copy (ptr, ptr + numRows + 1, ptr2.begin ());
323  std::copy (ind, ind + nnz, ind2.begin ());
324  std::copy (val, val + nnz, val2.begin ());
325 
326  RCP<const Tpetra::Map<LO,GO,NT> > rowMap = epetraMapToTpetra(A_e->RowMap(),comm);
327  RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > A_t = Tpetra::createCrsMatrix<ST,LO,GO,NT>(rowMap, A_e->GlobalMaxNumEntries());
328 
329  RCP<const Tpetra::Map<LO,GO,NT> > domainMap = epetraMapToTpetra(A_e->OperatorDomainMap(),comm);
330  RCP<const Tpetra::Map<LO,GO,NT> > rangeMap = epetraMapToTpetra(A_e->OperatorRangeMap(),comm);
331  RCP<const Tpetra::Map<LO,GO,NT> > colMap = epetraMapToTpetra(A_e->ColMap(),comm);
332 
333  A_t->replaceColMap(colMap);
334  A_t->setAllValues (ptr2, ind2, val2);
335  A_t->fillComplete(domainMap,rangeMap);
336  return A_t;
337 
338 }
339 
340 RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > nonConstEpetraCrsMatrixToTpetra(const RCP<Epetra_CrsMatrix> A_e, const RCP<const Teuchos::Comm<int> > comm)
341 {
342  int* ptr;
343  int* ind;
344  double* val;
345 
346  int info = A_e->ExtractCrsDataPointers (ptr, ind, val);
347  TEUCHOS_TEST_FOR_EXCEPTION(info!=0,std::logic_error, "Could not extract data from Epetra_CrsMatrix");
348  const LO numRows = A_e->Graph ().NumMyRows ();
349  const LO nnz = A_e->Graph ().NumMyEntries ();
350 
351  Teuchos::ArrayRCP<size_t> ptr2 (numRows+1);
352  Teuchos::ArrayRCP<int> ind2 (nnz);
353  Teuchos::ArrayRCP<double> val2 (nnz);
354 
355  std::copy (ptr, ptr + numRows + 1, ptr2.begin ());
356  std::copy (ind, ind + nnz, ind2.begin ());
357  std::copy (val, val + nnz, val2.begin ());
358 
359  RCP<const Tpetra::Map<LO,GO,NT> > rowMap = epetraMapToTpetra(A_e->RowMap(),comm);
360  RCP<Tpetra::CrsMatrix<ST,LO,GO,NT> > A_t = Tpetra::createCrsMatrix<ST,LO,GO,NT>(rowMap, A_e->GlobalMaxNumEntries());
361 
362  RCP<const Tpetra::Map<LO,GO,NT> > domainMap = epetraMapToTpetra(A_e->OperatorDomainMap(),comm);
363  RCP<const Tpetra::Map<LO,GO,NT> > rangeMap = epetraMapToTpetra(A_e->OperatorRangeMap(),comm);
364  RCP<const Tpetra::Map<LO,GO,NT> > colMap = epetraMapToTpetra(A_e->ColMap(),comm);
365 
366  A_t->replaceColMap(colMap);
367  A_t->setAllValues (ptr2, ind2, val2);
368  A_t->fillComplete(domainMap,rangeMap);
369  return A_t;
370 
371 }
372 
373 RCP<const Tpetra::Map<LO,GO,NT> > epetraMapToTpetra(const Epetra_Map eMap, const RCP<const Teuchos::Comm<int> > comm)
374 {
375  std::vector<int> intGIDs(eMap.NumMyElements());
376  eMap.MyGlobalElements(&intGIDs[0]);
377 
378  std::vector<GO> myGIDs(eMap.NumMyElements());
379  for(int k = 0; k < eMap.NumMyElements(); k++)
380  myGIDs[k] = (GO) intGIDs[k];
381 
382  return rcp(new const Tpetra::Map<LO,GO,NT>(Teuchos::OrdinalTraits<Tpetra::global_size_t>::invalid(),Teuchos::ArrayView<GO>(myGIDs),0,comm));
383 }
384 
385 } // end namespace TpetraHelpers
386 } // end namespace Teko
void apply(const Tpetra::MultiVector< ST, LO, GO, NT > &X, Tpetra::MultiVector< ST, LO, GO, NT > &Y, Teuchos::ETransp mode=Teuchos::NO_TRANS, ST alpha=Teuchos::ScalarTraits< ST >::one(), ST beta=Teuchos::ScalarTraits< ST >::zero()) const
Perform a matrix-vector product with certain rows zeroed out.
ZeroedOperator(const std::vector< GO > &zeroIndices, const Teuchos::RCP< const Tpetra::Operator< ST, LO, GO, NT > > &op)
Constructor for a ZeroedOperator.