Teko  Version of the Day
 All Classes Files Functions Variables Pages
Teko_ALOperator.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 /*
11  * Author: Zhen Wang
12  * Email: wangz@ornl.gov
13  * zhen.wang@alum.emory.edu
14  */
15 
16 #include "Teko_BlockedEpetraOperator.hpp"
17 #include "Teko_BlockedMappingStrategy.hpp"
18 #include "Teko_ReorderedMappingStrategy.hpp"
19 
20 #include "Teuchos_VerboseObject.hpp"
21 
22 #include "Thyra_LinearOpBase.hpp"
23 #include "Thyra_EpetraLinearOp.hpp"
24 #include "Thyra_EpetraThyraWrappers.hpp"
25 #include "Thyra_DefaultProductMultiVector.hpp"
26 #include "Thyra_DefaultProductVectorSpace.hpp"
27 #include "Thyra_DefaultBlockedLinearOp.hpp"
28 #include "Thyra_get_Epetra_Operator.hpp"
29 
30 #include "EpetraExt_MultiVectorOut.h"
31 #include "EpetraExt_RowMatrixOut.h"
32 
33 #include "Teko_Utilities.hpp"
34 
35 #include "Teko_ALOperator.hpp"
36 
37 namespace Teko {
38 
39 namespace NS {
40 
41 ALOperator::ALOperator(const std::vector<std::vector<int> >& vars,
42  const Teuchos::RCP<Epetra_Operator>& content, LinearOp pressureMassMatrix,
43  double gamma, const std::string& label)
44  : Teko::Epetra::BlockedEpetraOperator(vars, content, label),
45  pressureMassMatrix_(pressureMassMatrix),
46  gamma_(gamma) {
47  checkDim(vars);
48  SetContent(vars, content);
50 }
51 
52 ALOperator::ALOperator(const std::vector<std::vector<int> >& vars,
53  const Teuchos::RCP<Epetra_Operator>& content, double gamma,
54  const std::string& label)
55  : Teko::Epetra::BlockedEpetraOperator(vars, content, label),
56  pressureMassMatrix_(Teuchos::null),
57  gamma_(gamma) {
58  checkDim(vars);
59  SetContent(vars, content);
61 }
62 
63 void ALOperator::setPressureMassMatrix(LinearOp pressureMassMatrix) {
64  if (pressureMassMatrix != Teuchos::null) {
65  pressureMassMatrix_ = pressureMassMatrix;
66  }
67 }
68 
69 void ALOperator::setGamma(double gamma) {
70  TEUCHOS_ASSERT(gamma > 0.0);
71  gamma_ = gamma;
72 }
73 
74 const Teuchos::RCP<const Epetra_Operator> ALOperator::GetBlock(int i, int j) const {
75  const Teuchos::RCP<Thyra::BlockedLinearOpBase<double> > blkOp =
76  Teuchos::rcp_dynamic_cast<Thyra::BlockedLinearOpBase<double> >(blockedOperator_, true);
77 
78  return Thyra::get_Epetra_Operator(*blkOp->getBlock(i, j));
79 }
80 
81 void ALOperator::checkDim(const std::vector<std::vector<int> >& vars) {
82  dim_ = vars.size() - 1;
83  TEUCHOS_ASSERT(dim_ == 2 || dim_ == 3);
84 }
85 
87  TEUCHOS_ASSERT(blockedMapping_ != Teuchos::null);
88 
89  // Get an Epetra_CrsMatrix.
90  const Teuchos::RCP<const Epetra_CrsMatrix> crsContent =
91  Teuchos::rcp_dynamic_cast<const Epetra_CrsMatrix>(fullContent_);
92 
93  // Ask the strategy to build the Thyra operator for you.
94  if (blockedOperator_ == Teuchos::null) {
95  blockedOperator_ = blockedMapping_->buildBlockedThyraOp(crsContent, label_);
96  } else {
97  const Teuchos::RCP<Thyra::BlockedLinearOpBase<double> > blkOp =
98  Teuchos::rcp_dynamic_cast<Thyra::BlockedLinearOpBase<double> >(blockedOperator_, true);
99  blockedMapping_->rebuildBlockedThyraOp(crsContent, blkOp);
100  }
101 
102  // Extract blocks.
103  const Teuchos::RCP<Thyra::BlockedLinearOpBase<double> > blkOp =
104  Teuchos::rcp_dynamic_cast<Thyra::BlockedLinearOpBase<double> >(blockedOperator_, true);
105  numBlockRows_ = blkOp->productRange()->numBlocks();
106  Teuchos::RCP<const Thyra::LinearOpBase<double> > blockedOpBlocks[4][4];
107  for (int i = 0; i <= dim_; i++) {
108  for (int j = 0; j <= dim_; j++) {
109  blockedOpBlocks[i][j] = blkOp->getBlock(i, j);
110  }
111  }
112 
113  // Pressure mass matrix.
114  if (pressureMassMatrix_ != Teuchos::null) {
115  invPressureMassMatrix_ = getInvDiagonalOp(pressureMassMatrix_);
116  }
117  // We need the size of the sub-block to build the identity matrix.
118  else {
119  std::cout << "Pressure mass matrix is null. Use identity." << std::endl;
120  pressureMassMatrix_ = Thyra::identity<double>(blockedOpBlocks[dim_][0]->range());
121  invPressureMassMatrix_ = Thyra::identity<double>(blockedOpBlocks[dim_][0]->range());
122  }
123 
124  // Build the AL operator.
125  Teuchos::RCP<Thyra::DefaultBlockedLinearOp<double> > alOperator =
126  Thyra::defaultBlockedLinearOp<double>();
127  alOperator->beginBlockFill(dim_ + 1, dim_ + 1);
128 
129  // Set blocks for the velocity parts and gradient.
130  for (int i = 0; i < dim_; i++) {
131  for (int j = 0; j < dim_; j++) {
132  // build the blocks and place it the right location
133  alOperator->setBlock(
134  i, j,
135  Thyra::add(
136  blockedOpBlocks[i][j],
137  Thyra::scale(gamma_, Thyra::multiply(blockedOpBlocks[i][dim_], invPressureMassMatrix_,
138  blockedOpBlocks[dim_][j]))));
139  } // end for j
140  } // end for i
141 
142  // Last row. Divergence and (possible) stabilization matrix.
143  for (int j = 0; j <= dim_; j++) {
144  alOperator->setBlock(dim_, j, blockedOpBlocks[dim_][j]);
145  }
146 
147  // Last column. Gradient.
148  for (int i = 0; i < dim_; i++) {
149  alOperator->setBlock(
150  i, dim_,
151  Thyra::add(
152  blockedOpBlocks[i][dim_],
153  Thyra::scale(gamma_, Thyra::multiply(blockedOpBlocks[i][dim_], invPressureMassMatrix_,
154  blockedOpBlocks[dim_][dim_]))));
155  }
156 
157  alOperator->endBlockFill();
158 
159  // Set whatever is returned.
160  SetOperator(alOperator, false);
161 
162  // Set operator for augmenting the right-hand side.
163  Teuchos::RCP<Thyra::DefaultBlockedLinearOp<double> > alOpRhs_ =
164  Thyra::defaultBlockedLinearOp<double>();
165  alOpRhs_->beginBlockFill(dim_ + 1, dim_ + 1);
166 
167  // Identity matrices on the main diagonal.
168  for (int i = 0; i < dim_; i++) {
169  // build the blocks and place it the right location
170  alOpRhs_->setBlock(i, i, Thyra::identity<double>(blockedOpBlocks[0][0]->range()));
171  } // end for i
172  alOpRhs_->setBlock(dim_, dim_, Thyra::identity<double>(blockedOpBlocks[dim_][dim_]->range()));
173 
174  // Last column.
175  for (int i = 0; i < dim_; i++) {
176  alOpRhs_->setBlock(
177  i, dim_,
178  Thyra::scale(gamma_, Thyra::multiply(blockedOpBlocks[i][dim_], invPressureMassMatrix_)));
179  }
180 
181  alOpRhs_->endBlockFill();
182 
183  alOperatorRhs_ = alOpRhs_;
184 
185  // reorder if necessary
186  if (reorderManager_ != Teuchos::null) Reorder(*reorderManager_);
187 }
188 
189 void ALOperator::augmentRHS(const Epetra_MultiVector& b, Epetra_MultiVector& bAugmented) {
190  Teuchos::RCP<const Teko::Epetra::MappingStrategy> mapping = this->getMapStrategy();
191  Teuchos::RCP<Thyra::MultiVectorBase<double> > bThyra =
192  Thyra::createMembers(thyraOp_->range(), b.NumVectors());
193  Teuchos::RCP<Thyra::MultiVectorBase<double> > bThyraAugmented =
194  Thyra::createMembers(thyraOp_->range(), b.NumVectors());
195  // std::cout << Teuchos::describe(*bThyra, Teuchos::VERB_EXTREME) << std::endl;
196  // Copy Epetra vector to Thyra vector.
197  mapping->copyEpetraIntoThyra(b, bThyra.ptr());
198  // Apply operator.
199  alOperatorRhs_->apply(Thyra::NOTRANS, *bThyra, bThyraAugmented.ptr(), 1.0, 0.0);
200  // Copy Thyra vector to Epetra vector.
201  mapping->copyThyraIntoEpetra(bThyraAugmented, bAugmented);
202 }
203 
204 } // end namespace NS
205 
206 } // end namespace Teko
Teuchos::RCP< Thyra::LinearOpBase< double > > alOperatorRhs_
void augmentRHS(const Epetra_MultiVector &b, Epetra_MultiVector &bAugmented)
void checkDim(const std::vector< std::vector< int > > &vars)
void Reorder(const BlockReorderManager &brm)
void setPressureMassMatrix(LinearOp pressureMassMatrix)
virtual void SetContent(const std::vector< std::vector< int > > &vars, const Teuchos::RCP< const Epetra_Operator > &content)
const RCP< const MappingStrategy > getMapStrategy() const
Get the mapping strategy for this wrapper (translate between Thyra and Epetra)
const Teuchos::RCP< const Epetra_Operator > GetBlock(int i, int j) const
ALOperator(const std::vector< std::vector< int > > &vars, const Teuchos::RCP< Epetra_Operator > &content, LinearOp pressureMassMatrix, double gamma=0.05, const std::string &label="<ANYM>")
void setGamma(double gamma)