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