Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_StridedTpetraOperator.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_StridedTpetraOperator.hpp"
11 #include "Teko_TpetraStridedMappingStrategy.hpp"
12 #include "Teko_TpetraReorderedMappingStrategy.hpp"
13 
14 #include "Teuchos_VerboseObject.hpp"
15 
16 #include "Thyra_LinearOpBase.hpp"
17 #include "Thyra_TpetraLinearOp.hpp"
18 #include "Thyra_TpetraThyraWrappers.hpp"
19 #include "Thyra_DefaultProductMultiVector.hpp"
20 #include "Thyra_DefaultProductVectorSpace.hpp"
21 #include "Thyra_DefaultBlockedLinearOp.hpp"
22 
23 #include "Tpetra_Vector.hpp"
24 #include "MatrixMarket_Tpetra.hpp"
25 
26 #include "Teko_Utilities.hpp"
27 
28 namespace Teko {
29 namespace TpetraHelpers {
30 
31 using Teuchos::RCP;
32 using Teuchos::rcp;
33 using Teuchos::rcp_dynamic_cast;
34 
35 StridedTpetraOperator::StridedTpetraOperator(
36  int numVars, const Teuchos::RCP<const Tpetra::Operator<ST, LO, GO, NT> >& content,
37  const std::string& label)
38  : Teko::TpetraHelpers::TpetraOperatorWrapper(), label_(label) {
39  std::vector<int> vars;
40 
41  // build vector describing the sub maps
42  for (int i = 0; i < numVars; i++) vars.push_back(1);
43 
44  SetContent(vars, content);
45 }
46 
47 StridedTpetraOperator::StridedTpetraOperator(
48  const std::vector<int>& vars,
49  const Teuchos::RCP<const Tpetra::Operator<ST, LO, GO, NT> >& content, const std::string& label)
50  : Teko::TpetraHelpers::TpetraOperatorWrapper(), label_(label) {
51  SetContent(vars, content);
52 }
53 
54 void StridedTpetraOperator::SetContent(
55  const std::vector<int>& vars,
56  const Teuchos::RCP<const Tpetra::Operator<ST, LO, GO, NT> >& content) {
57  fullContent_ = content;
58  stridedMapping_ = rcp(new TpetraStridedMappingStrategy(vars, fullContent_->getDomainMap(),
59  *fullContent_->getDomainMap()->getComm()));
60  SetMapStrategy(stridedMapping_);
61 
62  // build thyra operator
63  BuildBlockedOperator();
64 }
65 
66 void StridedTpetraOperator::BuildBlockedOperator() {
67  TEUCHOS_ASSERT(stridedMapping_ != Teuchos::null);
68 
69  // get a CRS matrix
70  const RCP<const Tpetra::CrsMatrix<ST, LO, GO, NT> > crsContent =
71  rcp_dynamic_cast<const Tpetra::CrsMatrix<ST, LO, GO, NT> >(fullContent_);
72 
73  // ask the strategy to build the Thyra operator for you
74  if (stridedOperator_ == Teuchos::null) {
75  stridedOperator_ = stridedMapping_->buildBlockedThyraOp(crsContent, label_);
76  } else {
77  const RCP<Thyra::BlockedLinearOpBase<ST> > blkOp =
78  rcp_dynamic_cast<Thyra::BlockedLinearOpBase<ST> >(stridedOperator_, true);
79  stridedMapping_->rebuildBlockedThyraOp(crsContent, blkOp);
80  }
81 
82  // set whatever is returned
83  SetOperator(stridedOperator_, false);
84 
85  // reorder if neccessary
86  if (reorderManager_ != Teuchos::null) Reorder(*reorderManager_);
87 }
88 
89 const Teuchos::RCP<const Tpetra::Operator<ST, LO, GO, NT> > StridedTpetraOperator::GetBlock(
90  int i, int j) const {
91  const RCP<const Thyra::BlockedLinearOpBase<ST> > blkOp =
92  Teuchos::rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<ST> >(getThyraOp());
93 
94  RCP<const Thyra::TpetraLinearOp<ST, LO, GO, NT> > tOp =
95  rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST, LO, GO, NT> >(blkOp->getBlock(i, j), true);
96  return tOp->getConstTpetraOperator();
97 }
98 
102 void StridedTpetraOperator::Reorder(const BlockReorderManager& brm) {
103  reorderManager_ = rcp(new BlockReorderManager(brm));
104 
105  // build reordered objects
106  RCP<const MappingStrategy> reorderMapping =
107  rcp(new TpetraReorderedMappingStrategy(*reorderManager_, stridedMapping_));
108  RCP<const Thyra::BlockedLinearOpBase<ST> > blockOp =
109  rcp_dynamic_cast<const Thyra::BlockedLinearOpBase<ST> >(stridedOperator_);
110 
111  RCP<const Thyra::LinearOpBase<ST> > A = buildReorderedLinearOp(*reorderManager_, blockOp);
112 
113  // set them as working values
114  SetMapStrategy(reorderMapping);
115  SetOperator(A, false);
116 }
117 
119 void StridedTpetraOperator::RemoveReording() {
120  SetMapStrategy(stridedMapping_);
121  SetOperator(stridedOperator_, false);
122  reorderManager_ = Teuchos::null;
123 }
124 
127 void StridedTpetraOperator::WriteBlocks(const std::string& prefix) const {
128  RCP<Thyra::PhysicallyBlockedLinearOpBase<ST> > blockOp =
129  rcp_dynamic_cast<Thyra::PhysicallyBlockedLinearOpBase<ST> >(stridedOperator_);
130 
131  // get size of strided block operator
132  int rows = Teko::blockRowCount(blockOp);
133 
134  for (int i = 0; i < rows; i++) {
135  for (int j = 0; j < rows; j++) {
136  // get the row matrix object (Note: can't use "GetBlock" method b/c matrix might be reordered)
137  RCP<const Thyra::TpetraLinearOp<ST, LO, GO, NT> > tOp =
138  rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST, LO, GO, NT> >(blockOp->getBlock(i, j));
139  RCP<const Tpetra::CrsMatrix<ST, LO, GO, NT> > mat =
140  Teuchos::rcp_dynamic_cast<const Tpetra::CrsMatrix<ST, LO, GO, NT> >(
141  tOp->getConstTpetraOperator());
142 
143  // write to file
144  Tpetra::MatrixMarket::Writer<Tpetra::CrsMatrix<ST, LO, GO, NT> >::writeSparseFile(
145  formatBlockName(prefix, i, j, rows).c_str(), mat);
146  }
147  }
148 }
149 
157 std::string StridedTpetraOperator::PrintNorm(const eNormType& nrmType, const char newline) {
158  BlockedLinearOp blockOp = toBlockedLinearOp(stridedOperator_);
159 
160  // get size of strided block operator
161  int rowCount = Teko::blockRowCount(blockOp);
162  int colCount = Teko::blockRowCount(blockOp);
163 
164  std::stringstream ss;
165  ss.precision(4);
166  ss << std::scientific;
167  for (int row = 0; row < rowCount; row++) {
168  for (int col = 0; col < colCount; col++) {
169  // get the row matrix object (Note: can't use "GetBlock" method b/c matrix might be reordered)
170  RCP<const Thyra::TpetraLinearOp<ST, LO, GO, NT> > Aij =
171  rcp_dynamic_cast<const Thyra::TpetraLinearOp<ST, LO, GO, NT> >(
172  blockOp->getBlock(row, col), true);
173  RCP<const Tpetra::CrsMatrix<ST, LO, GO, NT> > mat =
174  Teuchos::rcp_dynamic_cast<const Tpetra::CrsMatrix<ST, LO, GO, NT> >(
175  Aij->getConstTpetraOperator(), true);
176 
177  // compute the norm
178  ST norm = 0.0;
179  switch (nrmType) {
180  // case Inf:
181  // norm = mat->normInf();
182  // break;
183  // case One:
184  // norm = mat->normOne();
185  // break;
186  case Frobenius: norm = mat->getFrobeniusNorm(); break;
187  default:
188  TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
189  "StridedTpetraOperator::NormType incorrectly specified. Only "
190  "Frobenius norm implemented for Tpetra matrices.");
191  }
192 
193  ss << norm << " ";
194  }
195  ss << newline;
196  }
197 
198  return ss.str();
199 }
200 
201 bool StridedTpetraOperator::testAgainstFullOperator(int count, ST tol) const {
202  Tpetra::Vector<ST, LO, GO, NT> xf(getRangeMap());
203  Tpetra::Vector<ST, LO, GO, NT> xs(getRangeMap());
204  Tpetra::Vector<ST, LO, GO, NT> y(getDomainMap());
205 
206  // test operator many times
207  bool result = true;
208  ST diffNorm = 0.0, trueNorm = 0.0;
209  for (int i = 0; i < count; i++) {
210  xf.putScalar(0.0);
211  xs.putScalar(0.0);
212  y.randomize();
213 
214  // apply operator
215  apply(y, xs); // xs = A*y
216  fullContent_->apply(y, xf); // xf = A*y
217 
218  // compute norms
219  xs.update(-1.0, xf, 1.0);
220  diffNorm = xs.norm2();
221  trueNorm = xf.norm2();
222 
223  // check result
224  result &= (diffNorm / trueNorm < tol);
225  }
226 
227  return result;
228 }
229 
230 } // end namespace TpetraHelpers
231 } // end namespace Teko