Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_EpetraHelpers.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_EpetraHelpers.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 using Teuchos::null;
73 using Teuchos::RCP;
74 using Teuchos::rcp;
75 using Teuchos::rcp_dynamic_cast;
76 using Teuchos::rcpFromRef;
77 
78 namespace Teko {
79 namespace Epetra {
80 
91 const Teuchos::RCP<const Thyra::LinearOpBase<double> > thyraDiagOp(
92  const RCP<const Epetra_Vector>& ev, const Epetra_Map& map, const std::string& lbl) {
93  const RCP<const Thyra::VectorBase<double> > thyraVec // need a Thyra::VectorBase object
94  = Thyra::create_Vector(ev, Thyra::create_VectorSpace(rcpFromRef(map)));
95  Teuchos::RCP<Thyra::LinearOpBase<double> > op =
96  Teuchos::rcp(new Thyra::DefaultDiagonalLinearOp<double>(thyraVec));
97  op->setObjectLabel(lbl);
98  return op;
99 }
100 
111 const Teuchos::RCP<Thyra::LinearOpBase<double> > thyraDiagOp(const RCP<Epetra_Vector>& ev,
112  const Epetra_Map& map,
113  const std::string& lbl) {
114  const RCP<Thyra::VectorBase<double> > thyraVec // need a Thyra::VectorBase object
115  = Thyra::create_Vector(ev, Thyra::create_VectorSpace(rcpFromRef(map)));
116  Teuchos::RCP<Thyra::LinearOpBase<double> > op =
117  Teuchos::rcp(new Thyra::DefaultDiagonalLinearOp<double>(thyraVec));
118  op->setObjectLabel(lbl);
119  return op;
120 }
121 
131 void fillDefaultSpmdMultiVector(Teuchos::RCP<Thyra::DefaultSpmdMultiVector<double> >& spmdMV,
132  Teuchos::RCP<Epetra_MultiVector>& epetraMV) {
133  // first get desired range and domain
134  const RCP<const Thyra::SpmdVectorSpaceBase<double> > range = spmdMV->spmdSpace();
135  const RCP<const Thyra::ScalarProdVectorSpaceBase<double> > domain =
136  rcp_dynamic_cast<const Thyra::ScalarProdVectorSpaceBase<double> >(spmdMV->domain());
137 
138  TEUCHOS_ASSERT(domain->dim() == epetraMV->NumVectors());
139 
140  // New local view of raw data
141  double* localValues;
142  int leadingDim;
143  if (epetraMV->ConstantStride())
144  epetraMV->ExtractView(&localValues, &leadingDim);
145  else
146  TEUCHOS_TEST_FOR_EXCEPT(true); // ToDo: Implement views of non-contiguous mult-vectors!
147 
148  // Build the MultiVector
149  spmdMV->initialize(range, domain,
150  Teuchos::arcp(localValues, 0, leadingDim * epetraMV->NumVectors(), false),
151  leadingDim);
152 
153  // make sure the Epetra_MultiVector doesn't disappear prematurely
154  Teuchos::set_extra_data<RCP<Epetra_MultiVector> >(epetraMV, "Epetra_MultiVector",
155  Teuchos::outArg(spmdMV));
156 }
157 
167 void identityRowIndices(const Epetra_Map& rowMap, const Epetra_CrsMatrix& mat,
168  std::vector<int>& outIndices) {
169  int maxSz = mat.GlobalMaxNumEntries();
170  std::vector<double> values(maxSz);
171  std::vector<int> indices(maxSz);
172 
173  // loop over elements owned by this processor
174  for (int i = 0; i < rowMap.NumMyElements(); i++) {
175  bool rowIsIdentity = true;
176  int sz = 0;
177  int rowGID = rowMap.GID(i);
178  mat.ExtractGlobalRowCopy(rowGID, maxSz, sz, &values[0], &indices[0]);
179 
180  // loop over the columns of this row
181  for (int j = 0; j < sz; j++) {
182  int colGID = indices[j];
183 
184  // look at row entries
185  if (colGID == rowGID)
186  rowIsIdentity &= values[j] == 1.0;
187  else
188  rowIsIdentity &= values[j] == 0.0;
189 
190  // not a dirchlet row...quit
191  if (not rowIsIdentity) break;
192  }
193 
194  // save a row that is dirchlet
195  if (rowIsIdentity) outIndices.push_back(rowGID);
196  }
197 }
198 
209 void zeroMultiVectorRowIndices(Epetra_MultiVector& mv, const std::vector<int>& zeroIndices) {
210  int colCnt = mv.NumVectors();
211  std::vector<int>::const_iterator itr;
212 
213  // loop over the indices to zero
214  for (itr = zeroIndices.begin(); itr != zeroIndices.end(); ++itr) {
215  // loop over columns
216  for (int j = 0; j < colCnt; j++) TEUCHOS_TEST_FOR_EXCEPT(mv.ReplaceGlobalValue(*itr, j, 0.0));
217  }
218 }
219 
229 ZeroedOperator::ZeroedOperator(const std::vector<int>& zeroIndices,
230  const Teuchos::RCP<const Epetra_Operator>& op)
231  : zeroIndices_(zeroIndices), epetraOp_(op) {
232  label_ = "zeroed( " + std::string(epetraOp_->Label()) + " )";
233 }
234 
236 int ZeroedOperator::Apply(const Epetra_MultiVector& X, Epetra_MultiVector& Y) const {
237  /*
238  Epetra_MultiVector temp(X);
239  zeroMultiVectorRowIndices(temp,zeroIndices_);
240  int result = epetraOp_->Apply(temp,Y);
241  */
242 
243  int result = epetraOp_->Apply(X, Y);
244 
245  // zero a few of the rows
246  zeroMultiVectorRowIndices(Y, zeroIndices_);
247 
248  return result;
249 }
250 
251 } // end namespace Epetra
252 } // 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.