Teko  Version of the Day
 All Classes Files Functions Variables Pages
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 #include "Teko_ConfigDefs.hpp"
49 
50 #ifdef TEKO_HAVE_EPETRA
51 #include "Thyra_EpetraLinearOp.hpp"
52 #include "Thyra_EpetraThyraWrappers.hpp"
53 
54 // Epetra includes
55 #include "Epetra_Vector.h"
56 
57 // EpetraExt includes
58 #include "EpetraExt_ProductOperator.h"
59 #include "EpetraExt_MatrixMatrix.h"
60 
61 #include "Teko_EpetraOperatorWrapper.hpp"
62 #endif
63 
64 // Thyra Includes
65 #include "Thyra_BlockedLinearOpBase.hpp"
66 #include "Thyra_DefaultMultipliedLinearOp.hpp"
67 #include "Thyra_DefaultDiagonalLinearOp.hpp"
68 #include "Thyra_DefaultZeroLinearOp.hpp"
69 #include "Thyra_DefaultBlockedLinearOp.hpp"
70 
71 #include "Thyra_SpmdVectorBase.hpp"
72 #include "Thyra_SpmdVectorSpaceBase.hpp"
73 #include "Thyra_ScalarProdVectorSpaceBase.hpp"
74 
75 // Teko includes
76 #include "Teko_Utilities.hpp"
77 
78 // Tpetra
79 #include "Thyra_TpetraLinearOp.hpp"
80 #include "Thyra_TpetraMultiVector.hpp"
81 #include "Tpetra_CrsMatrix.hpp"
82 #include "Tpetra_Vector.hpp"
83 #include "Thyra_TpetraThyraWrappers.hpp"
84 #include "TpetraExt_MatrixMatrix.hpp"
85 
86 using Teuchos::null;
87 using Teuchos::RCP;
88 using Teuchos::rcp;
89 using Teuchos::rcp_dynamic_cast;
90 using Teuchos::rcpFromRef;
91 
92 namespace Teko {
93 namespace TpetraHelpers {
94 
105 const Teuchos::RCP<const Thyra::LinearOpBase<ST> > thyraDiagOp(
106  const RCP<const Tpetra::Vector<ST, LO, GO, NT> >& tv, const Tpetra::Map<LO, GO, NT>& map,
107  const std::string& lbl) {
108  const RCP<const Thyra::VectorBase<ST> > thyraVec // need a Thyra::VectorBase object
109  = Thyra::createConstVector<ST, LO, GO, NT>(
110  tv, Thyra::createVectorSpace<ST, LO, GO, NT>(rcpFromRef(map)));
111  Teuchos::RCP<Thyra::LinearOpBase<ST> > op =
112  Teuchos::rcp(new Thyra::DefaultDiagonalLinearOp<ST>(thyraVec));
113  op->setObjectLabel(lbl);
114  return op;
115 }
116 
127 const Teuchos::RCP<Thyra::LinearOpBase<ST> > thyraDiagOp(
128  const RCP<Tpetra::Vector<ST, LO, GO, NT> >& tv, const Tpetra::Map<LO, GO, NT>& map,
129  const std::string& lbl) {
130  const RCP<Thyra::VectorBase<ST> > thyraVec // need a Thyra::VectorBase object
131  = Thyra::createVector<ST, LO, GO, NT>(
132  tv, Thyra::createVectorSpace<ST, LO, GO, NT>(rcpFromRef(map)));
133  Teuchos::RCP<Thyra::LinearOpBase<ST> > op =
134  Teuchos::rcp(new Thyra::DefaultDiagonalLinearOp<ST>(thyraVec));
135  op->setObjectLabel(lbl);
136  return op;
137 }
138 
148 void fillDefaultSpmdMultiVector(Teuchos::RCP<Thyra::TpetraMultiVector<ST, LO, GO, NT> >& spmdMV,
149  Teuchos::RCP<Tpetra::MultiVector<ST, LO, GO, NT> >& tpetraMV) {
150  // first get desired range and domain
151  // const RCP<const Thyra::SpmdVectorSpaceBase<ST> > range = spmdMV->spmdSpace();
152  const RCP<Thyra::TpetraVectorSpace<ST, LO, GO, NT> > range =
153  Thyra::tpetraVectorSpace<ST, LO, GO, NT>(tpetraMV->getMap());
154  const RCP<const Thyra::ScalarProdVectorSpaceBase<ST> > domain =
155  rcp_dynamic_cast<const Thyra::ScalarProdVectorSpaceBase<ST> >(spmdMV->domain());
156 
157  TEUCHOS_ASSERT((size_t)domain->dim() == tpetraMV->getNumVectors());
158 
159  // New local view of raw data
160  if (!tpetraMV->isConstantStride())
161  TEUCHOS_TEST_FOR_EXCEPT(true); // ToDo: Implement views of non-contiguous mult-vectors!
162 
163  // Build the MultiVector
164  spmdMV->initialize(range, domain, tpetraMV);
165 
166  // make sure the Epetra_MultiVector doesn't disappear prematurely
167  Teuchos::set_extra_data<RCP<Tpetra::MultiVector<ST, LO, GO, NT> > >(
168  tpetraMV, "Tpetra::MultiVector", Teuchos::outArg(spmdMV));
169 }
170 
180 void identityRowIndices(const Tpetra::Map<LO, GO, NT>& rowMap,
181  const Tpetra::CrsMatrix<ST, LO, GO, NT>& mat, std::vector<GO>& outIndices) {
182  // loop over elements owned by this processor
183  for (size_t i = 0; i < rowMap.getLocalNumElements(); i++) {
184  bool rowIsIdentity = true;
185  GO rowGID = rowMap.getGlobalElement(i);
186 
187  size_t numEntries = mat.getNumEntriesInGlobalRow(i);
188  auto indices = typename Tpetra::CrsMatrix<ST, LO, GO, NT>::nonconst_global_inds_host_view_type(
189  Kokkos::ViewAllocateWithoutInitializing("rowIndices"), numEntries);
190  auto values = typename Tpetra::CrsMatrix<ST, LO, GO, NT>::nonconst_values_host_view_type(
191  Kokkos::ViewAllocateWithoutInitializing("rowIndices"), numEntries);
192 
193  mat.getGlobalRowCopy(rowGID, indices, values, numEntries);
194 
195  // loop over the columns of this row
196  for (size_t j = 0; j < numEntries; j++) {
197  GO colGID = indices(j);
198 
199  // look at row entries
200  if (colGID == rowGID)
201  rowIsIdentity &= values(j) == 1.0;
202  else
203  rowIsIdentity &= values(j) == 0.0;
204 
205  // not a dirchlet row...quit
206  if (not rowIsIdentity) break;
207  }
208 
209  // save a row that is dirchlet
210  if (rowIsIdentity) outIndices.push_back(rowGID);
211  }
212 }
213 
224 void zeroMultiVectorRowIndices(Tpetra::MultiVector<ST, LO, GO, NT>& mv,
225  const std::vector<GO>& zeroIndices) {
226  LO colCnt = mv.getNumVectors();
227  std::vector<GO>::const_iterator itr;
228 
229  // loop over the indices to zero
230  for (itr = zeroIndices.begin(); itr != zeroIndices.end(); ++itr) {
231  // loop over columns
232  for (int j = 0; j < colCnt; j++) mv.replaceGlobalValue(*itr, j, 0.0);
233  }
234 }
235 
245 ZeroedOperator::ZeroedOperator(const std::vector<GO>& zeroIndices,
246  const Teuchos::RCP<const Tpetra::Operator<ST, LO, GO, NT> >& op)
247  : zeroIndices_(zeroIndices), tpetraOp_(op) {}
248 
250 void ZeroedOperator::apply(const Tpetra::MultiVector<ST, LO, GO, NT>& X,
251  Tpetra::MultiVector<ST, LO, GO, NT>& Y, Teuchos::ETransp mode, ST alpha,
252  ST beta) const {
253  /*
254  Epetra_MultiVector temp(X);
255  zeroMultiVectorRowIndices(temp,zeroIndices_);
256  int result = epetraOp_->Apply(temp,Y);
257  */
258 
259  tpetraOp_->apply(X, Y, mode, alpha, beta);
260 
261  // zero a few of the rows
262  zeroMultiVectorRowIndices(Y, zeroIndices_);
263 }
264 
265 bool isTpetraLinearOp(const LinearOp& op) {
266  // See if the operator is a TpetraLinearOp
267  RCP<const Thyra::TpetraLinearOp<ST, LO, GO, NT> > tOp =
268  rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST, LO, GO, NT> >(op);
269  if (!tOp.is_null()) return true;
270 
271  // See if the operator is a wrapped TpetraLinearOp
272  ST scalar = 0.0;
273  Thyra::EOpTransp transp = Thyra::NOTRANS;
274  RCP<const Thyra::LinearOpBase<ST> > wrapped_op;
275  Thyra::unwrap(op, &scalar, &transp, &wrapped_op);
276  tOp = rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST, LO, GO, NT> >(wrapped_op);
277  if (!tOp.is_null()) return true;
278 
279  return false;
280 }
281 
282 RCP<const Tpetra::CrsMatrix<ST, LO, GO, NT> > getTpetraCrsMatrix(const LinearOp& op, ST* scalar,
283  bool* transp) {
284  // If the operator is a TpetraLinearOp
285  RCP<const Thyra::TpetraLinearOp<ST, LO, GO, NT> > tOp =
286  rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST, LO, GO, NT> >(op);
287  if (!tOp.is_null()) {
288  RCP<const Tpetra::CrsMatrix<ST, LO, GO, NT> > matrix =
289  rcp_dynamic_cast<const Tpetra::CrsMatrix<ST, LO, GO, NT> >(tOp->getConstTpetraOperator(),
290  true);
291  *scalar = 1.0;
292  *transp = false;
293  return matrix;
294  }
295 
296  // If the operator is a wrapped TpetraLinearOp
297  RCP<const Thyra::LinearOpBase<ST> > wrapped_op;
298  Thyra::EOpTransp eTransp = Thyra::NOTRANS;
299  Thyra::unwrap(op, scalar, &eTransp, &wrapped_op);
300  tOp = rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST, LO, GO, NT> >(wrapped_op, true);
301  if (!tOp.is_null()) {
302  RCP<const Tpetra::CrsMatrix<ST, LO, GO, NT> > matrix =
303  rcp_dynamic_cast<const Tpetra::CrsMatrix<ST, LO, GO, NT> >(tOp->getConstTpetraOperator(),
304  true);
305  *transp = true;
306  if (eTransp == Thyra::NOTRANS) *transp = false;
307  return matrix;
308  }
309 
310  return Teuchos::null;
311 }
312 
313 #ifdef TEKO_HAVE_EPETRA
314 RCP<const Tpetra::CrsMatrix<ST, LO, GO, NT> > epetraCrsMatrixToTpetra(
315  const RCP<const Epetra_CrsMatrix> A_e, const RCP<const Teuchos::Comm<int> > comm) {
316  int* ptr;
317  int* ind;
318  double* val;
319 
320  int info = A_e->ExtractCrsDataPointers(ptr, ind, val);
321  TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
322  "Could not extract data from Epetra_CrsMatrix");
323  const LO numRows = A_e->Graph().NumMyRows();
324  const LO nnz = A_e->Graph().NumMyEntries();
325 
326  Teuchos::ArrayRCP<size_t> ptr2(numRows + 1);
327  Teuchos::ArrayRCP<int> ind2(nnz);
328  Teuchos::ArrayRCP<double> val2(nnz);
329 
330  std::copy(ptr, ptr + numRows + 1, ptr2.begin());
331  std::copy(ind, ind + nnz, ind2.begin());
332  std::copy(val, val + nnz, val2.begin());
333 
334  RCP<const Tpetra::Map<LO, GO, NT> > rowMap = epetraMapToTpetra(A_e->RowMap(), comm);
335  RCP<Tpetra::CrsMatrix<ST, LO, GO, NT> > A_t =
336  Tpetra::createCrsMatrix<ST, LO, GO, NT>(rowMap, A_e->GlobalMaxNumEntries());
337 
338  RCP<const Tpetra::Map<LO, GO, NT> > domainMap = epetraMapToTpetra(A_e->OperatorDomainMap(), comm);
339  RCP<const Tpetra::Map<LO, GO, NT> > rangeMap = epetraMapToTpetra(A_e->OperatorRangeMap(), comm);
340  RCP<const Tpetra::Map<LO, GO, NT> > colMap = epetraMapToTpetra(A_e->ColMap(), comm);
341 
342  A_t->replaceColMap(colMap);
343  A_t->setAllValues(ptr2, ind2, val2);
344  A_t->fillComplete(domainMap, rangeMap);
345  return A_t;
346 }
347 
348 RCP<Tpetra::CrsMatrix<ST, LO, GO, NT> > nonConstEpetraCrsMatrixToTpetra(
349  const RCP<Epetra_CrsMatrix> A_e, const RCP<const Teuchos::Comm<int> > comm) {
350  int* ptr;
351  int* ind;
352  double* val;
353 
354  int info = A_e->ExtractCrsDataPointers(ptr, ind, val);
355  TEUCHOS_TEST_FOR_EXCEPTION(info != 0, std::logic_error,
356  "Could not extract data from Epetra_CrsMatrix");
357  const LO numRows = A_e->Graph().NumMyRows();
358  const LO nnz = A_e->Graph().NumMyEntries();
359 
360  Teuchos::ArrayRCP<size_t> ptr2(numRows + 1);
361  Teuchos::ArrayRCP<int> ind2(nnz);
362  Teuchos::ArrayRCP<double> val2(nnz);
363 
364  std::copy(ptr, ptr + numRows + 1, ptr2.begin());
365  std::copy(ind, ind + nnz, ind2.begin());
366  std::copy(val, val + nnz, val2.begin());
367 
368  RCP<const Tpetra::Map<LO, GO, NT> > rowMap = epetraMapToTpetra(A_e->RowMap(), comm);
369  RCP<Tpetra::CrsMatrix<ST, LO, GO, NT> > A_t =
370  Tpetra::createCrsMatrix<ST, LO, GO, NT>(rowMap, A_e->GlobalMaxNumEntries());
371 
372  RCP<const Tpetra::Map<LO, GO, NT> > domainMap = epetraMapToTpetra(A_e->OperatorDomainMap(), comm);
373  RCP<const Tpetra::Map<LO, GO, NT> > rangeMap = epetraMapToTpetra(A_e->OperatorRangeMap(), comm);
374  RCP<const Tpetra::Map<LO, GO, NT> > colMap = epetraMapToTpetra(A_e->ColMap(), comm);
375 
376  A_t->replaceColMap(colMap);
377  A_t->setAllValues(ptr2, ind2, val2);
378  A_t->fillComplete(domainMap, rangeMap);
379  return A_t;
380 }
381 
382 RCP<const Tpetra::Map<LO, GO, NT> > epetraMapToTpetra(const Epetra_Map eMap,
383  const RCP<const Teuchos::Comm<int> > comm) {
384  std::vector<int> intGIDs(eMap.NumMyElements());
385  eMap.MyGlobalElements(&intGIDs[0]);
386 
387  std::vector<GO> myGIDs(eMap.NumMyElements());
388  for (int k = 0; k < eMap.NumMyElements(); k++) myGIDs[k] = (GO)intGIDs[k];
389 
390  return rcp(
391  new const Tpetra::Map<LO, GO, NT>(Teuchos::OrdinalTraits<Tpetra::global_size_t>::invalid(),
392  Teuchos::ArrayView<GO>(myGIDs), 0, comm));
393 }
394 #endif // TEKO_HAVE_EPETRA
395 
396 } // end namespace TpetraHelpers
397 } // 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.