Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_EpetraHelpers.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_EpetraHelpers.hpp"
11 
12 // Thyra Includes
13 #include "Thyra_EpetraLinearOp.hpp"
14 #include "Thyra_BlockedLinearOpBase.hpp"
15 #include "Thyra_DefaultMultipliedLinearOp.hpp"
16 #include "Thyra_DefaultDiagonalLinearOp.hpp"
17 #include "Thyra_DefaultZeroLinearOp.hpp"
18 #include "Thyra_DefaultBlockedLinearOp.hpp"
19 #include "Thyra_EpetraThyraWrappers.hpp"
20 #include "Thyra_SpmdVectorBase.hpp"
21 #include "Thyra_SpmdVectorSpaceBase.hpp"
22 #include "Thyra_ScalarProdVectorSpaceBase.hpp"
23 
24 // Epetra includes
25 #include "Epetra_Vector.h"
26 
27 // EpetraExt includes
28 #include "EpetraExt_ProductOperator.h"
29 #include "EpetraExt_MatrixMatrix.h"
30 
31 // Teko includes
32 #include "Teko_EpetraOperatorWrapper.hpp"
33 #include "Teko_Utilities.hpp"
34 
35 using Teuchos::null;
36 using Teuchos::RCP;
37 using Teuchos::rcp;
38 using Teuchos::rcp_dynamic_cast;
39 using Teuchos::rcpFromRef;
40 
41 namespace Teko {
42 namespace Epetra {
43 
54 const Teuchos::RCP<const Thyra::LinearOpBase<double> > thyraDiagOp(
55  const RCP<const Epetra_Vector>& ev, const Epetra_Map& map, const std::string& lbl) {
56  const RCP<const Thyra::VectorBase<double> > thyraVec // need a Thyra::VectorBase object
57  = Thyra::create_Vector(ev, Thyra::create_VectorSpace(rcpFromRef(map)));
58  Teuchos::RCP<Thyra::LinearOpBase<double> > op =
59  Teuchos::rcp(new Thyra::DefaultDiagonalLinearOp<double>(thyraVec));
60  op->setObjectLabel(lbl);
61  return op;
62 }
63 
74 const Teuchos::RCP<Thyra::LinearOpBase<double> > thyraDiagOp(const RCP<Epetra_Vector>& ev,
75  const Epetra_Map& map,
76  const std::string& lbl) {
77  const RCP<Thyra::VectorBase<double> > thyraVec // need a Thyra::VectorBase object
78  = Thyra::create_Vector(ev, Thyra::create_VectorSpace(rcpFromRef(map)));
79  Teuchos::RCP<Thyra::LinearOpBase<double> > op =
80  Teuchos::rcp(new Thyra::DefaultDiagonalLinearOp<double>(thyraVec));
81  op->setObjectLabel(lbl);
82  return op;
83 }
84 
94 void fillDefaultSpmdMultiVector(Teuchos::RCP<Thyra::DefaultSpmdMultiVector<double> >& spmdMV,
95  Teuchos::RCP<Epetra_MultiVector>& epetraMV) {
96  // first get desired range and domain
97  const RCP<const Thyra::SpmdVectorSpaceBase<double> > range = spmdMV->spmdSpace();
98  const RCP<const Thyra::ScalarProdVectorSpaceBase<double> > domain =
99  rcp_dynamic_cast<const Thyra::ScalarProdVectorSpaceBase<double> >(spmdMV->domain());
100 
101  TEUCHOS_ASSERT(domain->dim() == epetraMV->NumVectors());
102 
103  // New local view of raw data
104  double* localValues;
105  int leadingDim;
106  if (epetraMV->ConstantStride())
107  epetraMV->ExtractView(&localValues, &leadingDim);
108  else
109  TEUCHOS_TEST_FOR_EXCEPT(true); // ToDo: Implement views of non-contiguous mult-vectors!
110 
111  // Build the MultiVector
112  spmdMV->initialize(range, domain,
113  Teuchos::arcp(localValues, 0, leadingDim * epetraMV->NumVectors(), false),
114  leadingDim);
115 
116  // make sure the Epetra_MultiVector doesn't disappear prematurely
117  Teuchos::set_extra_data<RCP<Epetra_MultiVector> >(epetraMV, "Epetra_MultiVector",
118  Teuchos::outArg(spmdMV));
119 }
120 
130 void identityRowIndices(const Epetra_Map& rowMap, const Epetra_CrsMatrix& mat,
131  std::vector<int>& outIndices) {
132  int maxSz = mat.GlobalMaxNumEntries();
133  std::vector<double> values(maxSz);
134  std::vector<int> indices(maxSz);
135 
136  // loop over elements owned by this processor
137  for (int i = 0; i < rowMap.NumMyElements(); i++) {
138  bool rowIsIdentity = true;
139  int sz = 0;
140  int rowGID = rowMap.GID(i);
141  mat.ExtractGlobalRowCopy(rowGID, maxSz, sz, &values[0], &indices[0]);
142 
143  // loop over the columns of this row
144  for (int j = 0; j < sz; j++) {
145  int colGID = indices[j];
146 
147  // look at row entries
148  if (colGID == rowGID)
149  rowIsIdentity &= values[j] == 1.0;
150  else
151  rowIsIdentity &= values[j] == 0.0;
152 
153  // not a dirchlet row...quit
154  if (not rowIsIdentity) break;
155  }
156 
157  // save a row that is dirchlet
158  if (rowIsIdentity) outIndices.push_back(rowGID);
159  }
160 }
161 
172 void zeroMultiVectorRowIndices(Epetra_MultiVector& mv, const std::vector<int>& zeroIndices) {
173  int colCnt = mv.NumVectors();
174  std::vector<int>::const_iterator itr;
175 
176  // loop over the indices to zero
177  for (itr = zeroIndices.begin(); itr != zeroIndices.end(); ++itr) {
178  // loop over columns
179  for (int j = 0; j < colCnt; j++) TEUCHOS_TEST_FOR_EXCEPT(mv.ReplaceGlobalValue(*itr, j, 0.0));
180  }
181 }
182 
192 ZeroedOperator::ZeroedOperator(const std::vector<int>& zeroIndices,
193  const Teuchos::RCP<const Epetra_Operator>& op)
194  : zeroIndices_(zeroIndices), epetraOp_(op) {
195  label_ = "zeroed( " + std::string(epetraOp_->Label()) + " )";
196 }
197 
199 int ZeroedOperator::Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const {
200  /*
201  Epetra_MultiVector temp(X);
202  zeroMultiVectorRowIndices(temp,zeroIndices_);
203  int result = epetraOp_->Apply(temp,Y);
204  */
205 
206  int result = epetraOp_->Apply(X, Y);
207 
208  // zero a few of the rows
209  zeroMultiVectorRowIndices(Y, zeroIndices_);
210 
211  return result;
212 }
213 
214 } // end namespace Epetra
215 } // end namespace Teko
ZeroedOperator(const std::vector< int > &zeroIndices, const Teuchos::RCP< const Epetra_Operator > &op)
Constructor for a ZeroedOperator.
int Apply(const Epetra_MultiVector &X, Epetra_MultiVector &Y) const
Perform a matrix-vector product with certain rows zeroed out.