Teko Version of the Day
Loading...
Searching...
No Matches
Teko_BlockUpperTriInverseOp.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_BlockUpperTriInverseOp.hpp"
11
12#include "Teuchos_Utils.hpp"
13
14namespace Teko {
15
16using Teuchos::RCP;
17
28BlockUpperTriInverseOp::BlockUpperTriInverseOp(BlockedLinearOp& U,
29 const std::vector<LinearOp>& invDiag)
30 : U_(U) {
31 invDiag_ = invDiag;
32
33 // sanity check
34 int blocks = blockRowCount(U_);
35 TEUCHOS_ASSERT(blocks > 0);
36 TEUCHOS_ASSERT(blocks == blockColCount(U_));
37 TEUCHOS_ASSERT(blocks == (int)invDiag_.size());
38
39 // create the range and product space
41
42 // just flip flop them!
43 productRange_ = U->productDomain();
44 productDomain_ = U->productRange();
45}
46
47void BlockUpperTriInverseOp::implicitApply(const BlockedMultiVector& src, BlockedMultiVector& dst,
48 const double alpha, const double beta) const {
49 // call the no tranpose version
50 implicitApply(Thyra::NOTRANS, src, dst, alpha, beta);
51}
52
53namespace {
54bool compatibleMultiVectors(const BlockedMultiVector& a, const BlockedMultiVector& b) {
55 if (!a || !b) return false;
56
57 return a->domain()->dim() == b->domain()->dim();
58}
59} // namespace
60
73void BlockUpperTriInverseOp::implicitApply(const Thyra::EOpTransp M_trans,
74 const BlockedMultiVector& src, BlockedMultiVector& dst,
75 const double alpha, const double beta) const {
76 int blocks = blockCount(src);
77
78 TEUCHOS_ASSERT(blocks == blockRowCount(U_));
79 TEUCHOS_ASSERT(blocks == blockCount(dst));
80
81 bool needsAlloc = !allocated;
82 needsAlloc |= !compatibleMultiVectors(srcScrap_, src);
83 needsAlloc |= !compatibleMultiVectors(dstScrap_, dst);
84 if (needsAlloc) {
85 srcScrap_ = deepcopy(src);
86 dstScrap_ = deepcopy(dst);
87 allocated = true;
88 }
89
90 // build a scrap vector for storing work
91 Thyra::assign<double>(srcScrap_.ptr(), *src);
92 BlockedMultiVector dstCopy;
93 if (beta != 0.0) {
94 Thyra::assign<double>(dstScrap_.ptr(), *dst);
95 dstCopy = dstScrap_;
96 } else
97 dstCopy = dst; // shallow copy
98
99 // extract the blocks components from
100 // the source and destination vectors
101 std::vector<MultiVector> dstVec;
102 std::vector<MultiVector> scrapVec;
103 for (int b = 0; b < blocks; b++) {
104 dstVec.push_back(getBlock(b, dstCopy));
105 scrapVec.push_back(getBlock(b, srcScrap_));
106 }
107
108 // run back-substituion: run over each column
109 // From Heath pg. 66
110 if (M_trans == Thyra::NOTRANS) {
111 for (int b = blocks - 1; b >= 0; b--) {
112 applyOp(invDiag_[b], scrapVec[b], dstVec[b]);
113
114 // loop over each row
115 for (int i = 0; i < b; i++) {
116 LinearOp u_ib = getBlock(i, b, U_);
117 if (u_ib != Teuchos::null) {
118 applyOp(u_ib, dstVec[b], scrapVec[i], -1.0, 1.0);
119 }
120 }
121 }
122 } else if (M_trans == Thyra::TRANS || M_trans == Thyra::CONJTRANS) {
123 for (int b = 0; b < blocks; b++) {
124 applyTransposeOp(invDiag_[b], scrapVec[b], dstVec[b]);
125
126 // loop over each row
127 for (int i = b + 1; i < blocks; i++) {
128 LinearOp u_bi = getBlock(b, i, U_);
129 if (u_bi != Teuchos::null) {
130 applyTransposeOp(u_bi, dstVec[b], scrapVec[i], -1.0, 1.0);
131 }
132 }
133 }
134 } else {
135 TEUCHOS_TEST_FOR_EXCEPT(true);
136 }
137
138 // scale result by alpha
139 if (beta != 0)
140 update(alpha, dstCopy, beta, dst); // dst = alpha * dstCopy + beta * dst
141 else if (alpha != 1.0)
142 scale(alpha, dst); // dst = alpha * dst
143}
144
145void BlockUpperTriInverseOp::describe(Teuchos::FancyOStream& out_arg,
146 const Teuchos::EVerbosityLevel verbLevel) const {
147 using Teuchos::OSTab;
148
149 RCP<Teuchos::FancyOStream> out = rcp(&out_arg, false);
150 OSTab tab(out);
151 switch (verbLevel) {
152 case Teuchos::VERB_DEFAULT:
153 case Teuchos::VERB_LOW: *out << this->description() << std::endl; break;
154 case Teuchos::VERB_MEDIUM:
155 case Teuchos::VERB_HIGH:
156 case Teuchos::VERB_EXTREME: {
157 *out << Teuchos::Describable::description() << "{"
158 << "rangeDim=" << this->range()->dim() << ",domainDim=" << this->domain()->dim()
159 << ",rows=" << blockRowCount(U_) << ",cols=" << blockColCount(U_) << "}\n";
160 {
161 OSTab tab2(out);
162 *out << "[U Operator] = ";
163 *out << Teuchos::describe(*U_, verbLevel);
164 }
165 {
166 OSTab tab2(out);
167 *out << "[invDiag Operators]:\n";
168 tab.incrTab();
169 for (int i = 0; i < blockRowCount(U_); i++) {
170 *out << "[invD(" << i << ")] = ";
171 *out << Teuchos::describe(*invDiag_[i], verbLevel);
172 }
173 }
174 break;
175 }
176 default: TEUCHOS_TEST_FOR_EXCEPT(true); // Should never get here!
177 }
178}
179
180} // end namespace Teko
void scale(const double alpha, MultiVector &x)
Scale a multivector by a constant.
int blockRowCount(const BlockedLinearOp &blo)
Get the row count in a block linear operator.
int blockCount(const BlockedMultiVector &bmv)
Get the column count in a block linear operator.
MultiVector getBlock(int i, const BlockedMultiVector &bmv)
Get the ith block from a BlockedMultiVector object.
MultiVector deepcopy(const MultiVector &v)
Perform a deep copy of the vector.
int blockColCount(const BlockedLinearOp &blo)
Get the column count in a block linear operator.
Teuchos::RCP< const Thyra::ProductVectorSpaceBase< double > > productDomain_
Domain vector space.
virtual VectorSpace domain() const
Domain space of this operator.
virtual void implicitApply(const BlockedMultiVector &x, BlockedMultiVector &y, const double alpha=1.0, const double beta=0.0) const
Perform a matrix vector multiply with this operator.
Teuchos::RCP< const Thyra::ProductVectorSpaceBase< double > > productRange_
Range vector space.
std::vector< LinearOp > invDiag_
(Approximate) Inverses of the diagonal operators
virtual VectorSpace range() const
Range space of this operator.