Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_StridedEpetraOperator.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 "Epetra/Teko_StridedEpetraOperator.hpp"
48 #include "Epetra/Teko_StridedMappingStrategy.hpp"
49 #include "Epetra/Teko_ReorderedMappingStrategy.hpp"
50 
51 #include "Teuchos_VerboseObject.hpp"
52 
53 #include "Thyra_LinearOpBase.hpp"
54 #include "Thyra_EpetraLinearOp.hpp"
55 #include "Thyra_EpetraThyraWrappers.hpp"
56 #include "Thyra_DefaultProductMultiVector.hpp"
57 #include "Thyra_DefaultProductVectorSpace.hpp"
58 #include "Thyra_DefaultBlockedLinearOp.hpp"
59 #include "Thyra_get_Epetra_Operator.hpp"
60 
61 #include "Epetra_Vector.h"
62 #include "EpetraExt_MultiVectorOut.h"
63 #include "EpetraExt_RowMatrixOut.h"
64 
65 #include "Teko_Utilities.hpp"
66 
67 namespace Teko {
68 namespace Epetra {
69 
70 using Teuchos::RCP;
71 using Teuchos::rcp;
72 using Teuchos::rcp_dynamic_cast;
73 
74 StridedEpetraOperator::StridedEpetraOperator(int numVars,
75  const Teuchos::RCP<const Epetra_Operator>& content,
76  const std::string& label)
77  : Teko::Epetra::EpetraOperatorWrapper(), label_(label) {
78  std::vector<int> vars;
79 
80  // build vector describing the sub maps
81  for (int i = 0; i < numVars; i++) vars.push_back(1);
82 
83  SetContent(vars, content);
84 }
85 
86 StridedEpetraOperator::StridedEpetraOperator(const std::vector<int>& vars,
87  const Teuchos::RCP<const Epetra_Operator>& content,
88  const std::string& label)
89  : Teko::Epetra::EpetraOperatorWrapper(), label_(label) {
90  SetContent(vars, content);
91 }
92 
93 void StridedEpetraOperator::SetContent(const std::vector<int>& vars,
94  const Teuchos::RCP<const Epetra_Operator>& content) {
95  fullContent_ = content;
96  stridedMapping_ = rcp(new StridedMappingStrategy(
97  vars, Teuchos::rcpFromRef(fullContent_->OperatorDomainMap()), fullContent_->Comm()));
98  SetMapStrategy(stridedMapping_);
99 
100  // build thyra operator
101  BuildBlockedOperator();
102 }
103 
104 void StridedEpetraOperator::BuildBlockedOperator() {
105  TEUCHOS_ASSERT(stridedMapping_ != Teuchos::null);
106 
107  // get a CRS matrix
108  const RCP<const Epetra_CrsMatrix> crsContent =
109  rcp_dynamic_cast<const Epetra_CrsMatrix>(fullContent_);
110 
111  // ask the strategy to build the Thyra operator for you
112  if (stridedOperator_ == Teuchos::null) {
113  stridedOperator_ = stridedMapping_->buildBlockedThyraOp(crsContent, label_);
114  } else {
115  const RCP<Thyra::BlockedLinearOpBase<double> > blkOp =
116  rcp_dynamic_cast<Thyra::BlockedLinearOpBase<double> >(stridedOperator_, true);
117  stridedMapping_->rebuildBlockedThyraOp(crsContent, blkOp);
118  }
119 
120  // set whatever is returned
121  SetOperator(stridedOperator_, false);
122 
123  // reorder if neccessary
124  if (reorderManager_ != Teuchos::null) Reorder(*reorderManager_);
125 }
126 
127 const Teuchos::RCP<const Epetra_Operator> StridedEpetraOperator::GetBlock(int i, int j) const {
128  const RCP<const Thyra::BlockedLinearOpBase<double> > blkOp =
129  Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<double> >(getThyraOp());
130 
131  return Thyra::get_Epetra_Operator(*blkOp->getBlock(i, j));
132 }
133 
137 void StridedEpetraOperator::Reorder(const BlockReorderManager& brm) {
138  reorderManager_ = rcp(new BlockReorderManager(brm));
139 
140  // build reordered objects
141  RCP<const MappingStrategy> reorderMapping =
142  rcp(new ReorderedMappingStrategy(*reorderManager_, stridedMapping_));
143  RCP<const Thyra::BlockedLinearOpBase<double> > blockOp =
144  rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<double> >(stridedOperator_);
145 
146  RCP<const Thyra::LinearOpBase<double> > A = buildReorderedLinearOp(*reorderManager_, blockOp);
147 
148  // set them as working values
149  SetMapStrategy(reorderMapping);
150  SetOperator(A, false);
151 }
152 
154 void StridedEpetraOperator::RemoveReording() {
155  SetMapStrategy(stridedMapping_);
156  SetOperator(stridedOperator_, false);
157  reorderManager_ = Teuchos::null;
158 }
159 
162 void StridedEpetraOperator::WriteBlocks(const std::string& prefix) const {
163  RCP<Thyra::PhysicallyBlockedLinearOpBase<double> > blockOp =
164  rcp_dynamic_cast<Thyra::PhysicallyBlockedLinearOpBase<double> >(stridedOperator_);
165 
166  // get size of strided block operator
167  int rows = Teko::blockRowCount(blockOp);
168 
169  for (int i = 0; i < rows; i++) {
170  for (int j = 0; j < rows; j++) {
171  // get the row matrix object (Note: can't use "GetBlock" method b/c matrix might be reordered)
172  RCP<const Epetra_RowMatrix> mat = Teuchos::rcp_dynamic_cast<const Epetra_RowMatrix>(
173  Thyra::get_Epetra_Operator(*blockOp->getBlock(i, j)));
174 
175  // write to file
176  EpetraExt::RowMatrixToMatrixMarketFile(formatBlockName(prefix, i, j, rows).c_str(), *mat);
177  }
178  }
179 }
180 
188 std::string StridedEpetraOperator::PrintNorm(const eNormType& nrmType, const char newline) {
189  BlockedLinearOp blockOp = toBlockedLinearOp(stridedOperator_);
190 
191  // get size of strided block operator
192  int rowCount = Teko::blockRowCount(blockOp);
193  int colCount = Teko::blockRowCount(blockOp);
194 
195  std::stringstream ss;
196  ss.precision(4);
197  ss << std::scientific;
198  for (int row = 0; row < rowCount; row++) {
199  for (int col = 0; col < colCount; col++) {
200  // get the row matrix object (Note: can't use "GetBlock" method b/c matrix might be reordered)
201  RCP<const Epetra_CrsMatrix> mat = Teuchos::rcp_dynamic_cast<const Epetra_CrsMatrix>(
202  Thyra::get_Epetra_Operator(*blockOp->getBlock(row, col)));
203 
204  // compute the norm
205  double norm = 0.0;
206  switch (nrmType) {
207  case Inf: norm = mat->NormInf(); break;
208  case One: norm = mat->NormOne(); break;
209  case Frobenius: norm = mat->NormFrobenius(); break;
210  default:
211  TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
212  "StridedEpetraOperator::eNormType incorrectly specified");
213  }
214 
215  ss << norm << " ";
216  }
217  ss << newline;
218  }
219 
220  return ss.str();
221 }
222 
223 bool StridedEpetraOperator::testAgainstFullOperator(int count, double tol) const {
224  Epetra_Vector xf(OperatorRangeMap());
225  Epetra_Vector xs(OperatorRangeMap());
226  Epetra_Vector y(OperatorDomainMap());
227 
228  // test operator many times
229  bool result = true;
230  double diffNorm = 0.0, trueNorm = 0.0;
231  for (int i = 0; i < count; i++) {
232  xf.PutScalar(0.0);
233  xs.PutScalar(0.0);
234  y.Random();
235 
236  // apply operator
237  Apply(y, xs); // xs = A*y
238  fullContent_->Apply(y, xf); // xf = A*y
239 
240  // compute norms
241  xs.Update(-1.0, xf, 1.0);
242  xs.Norm2(&diffNorm);
243  xf.Norm2(&trueNorm);
244 
245  // check result
246  result &= (diffNorm / trueNorm < tol);
247  }
248 
249  return result;
250 }
251 
252 } // end namespace Epetra
253 } // end namespace Teko