Teko Version of the Day
Loading...
Searching...
No Matches
Teko_BlockLowerTriInverseOp.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_BlockLowerTriInverseOp.hpp"
11
12#include "Teuchos_Utils.hpp"
13
14namespace Teko {
15
16using Teuchos::RCP;
17
18BlockLowerTriInverseOp::BlockLowerTriInverseOp(BlockedLinearOp& L,
19 const std::vector<LinearOp>& invDiag)
20 : L_(L) {
21 invDiag_ = invDiag;
22
23 // sanity check
24 int blocks = blockRowCount(L_);
25 TEUCHOS_ASSERT(blocks > 0);
26 TEUCHOS_ASSERT(blocks == blockColCount(L_));
27 TEUCHOS_ASSERT(blocks == (int)invDiag_.size());
28
29 // create the range and product space
31
32 // just flip flop them!
33 productRange_ = L_->productDomain();
34 productDomain_ = L_->productRange();
35}
36
37namespace {
38bool compatibleMultiVectors(const BlockedMultiVector& a, const BlockedMultiVector& b) {
39 if (!a || !b) return false;
40
41 return a->domain()->dim() == b->domain()->dim();
42}
43} // namespace
44
57void BlockLowerTriInverseOp::implicitApply(const BlockedMultiVector& src, BlockedMultiVector& dst,
58 const double alpha, const double beta) const {
59 int blocks = blockCount(src);
60
61 TEUCHOS_ASSERT(blocks == blockRowCount(L_));
62 TEUCHOS_ASSERT(blocks == blockCount(dst));
63
64 bool needsAlloc = !allocated;
65 needsAlloc |= !compatibleMultiVectors(srcScrap_, src);
66 needsAlloc |= !compatibleMultiVectors(dstScrap_, dst);
67 if (needsAlloc) {
68 srcScrap_ = deepcopy(src);
69 dstScrap_ = deepcopy(dst);
70 allocated = true;
71 }
72
73 // build a scrap vector for storing work
74 Thyra::assign<double>(srcScrap_.ptr(), *src);
75 BlockedMultiVector dstCopy;
76 if (beta != 0.0) {
77 Thyra::assign<double>(dstScrap_.ptr(), *dst);
78 dstCopy = dstScrap_;
79 } else
80 dstCopy = dst; // shallow copy
81
82 // extract the blocks componets from
83 // the source and destination vectors
84 std::vector<MultiVector> dstVec;
85 std::vector<MultiVector> scrapVec;
86 for (int b = 0; b < blocks; b++) {
87 dstVec.push_back(getBlock(b, dstCopy));
88 scrapVec.push_back(getBlock(b, srcScrap_));
89 }
90
91 // run forward-substituion: run over each column
92 // From Heath pg. 65
93 for (int b = 0; b < blocks; b++) {
94 applyOp(invDiag_[b], scrapVec[b], dstVec[b]);
95
96 // loop over each row
97 for (int i = b + 1; i < blocks; i++) {
98 LinearOp u_ib = getBlock(i, b, L_);
99 if (u_ib != Teuchos::null) {
100 applyOp(u_ib, dstVec[b], scrapVec[i], -1.0, 1.0);
101 }
102 }
103 }
104
105 // scale result by alpha
106 if (beta != 0)
107 update(alpha, dstCopy, beta, dst); // dst = alpha * dstCopy + beta * dst
108 else if (alpha != 1.0)
109 scale(alpha, dst); // dst = alpha * dst
110}
111
112void BlockLowerTriInverseOp::describe(Teuchos::FancyOStream& out_arg,
113 const Teuchos::EVerbosityLevel verbLevel) const {
114 using Teuchos::OSTab;
115
116 RCP<Teuchos::FancyOStream> out = rcp(&out_arg, false);
117 OSTab tab(out);
118 switch (verbLevel) {
119 case Teuchos::VERB_DEFAULT:
120 case Teuchos::VERB_LOW: *out << this->description() << std::endl; break;
121 case Teuchos::VERB_MEDIUM:
122 case Teuchos::VERB_HIGH:
123 case Teuchos::VERB_EXTREME: {
124 *out << Teuchos::Describable::description() << "{"
125 << "rangeDim=" << this->range()->dim() << ",domainDim=" << this->domain()->dim()
126 << ",rows=" << blockRowCount(L_) << ",cols=" << blockColCount(L_) << "}\n";
127 {
128 OSTab tab2(out);
129 *out << "[L Operator] = ";
130 *out << Teuchos::describe(*L_, verbLevel);
131 }
132 {
133 OSTab tab2(out);
134 *out << "[invDiag Operators]:\n";
135 tab.incrTab();
136 for (int i = 0; i < blockRowCount(L_); i++) {
137 *out << "[invD(" << i << ")] = ";
138 *out << Teuchos::describe(*invDiag_[i], verbLevel);
139 }
140 }
141 break;
142 }
143 default: TEUCHOS_TEST_FOR_EXCEPT(true); // Should never get here!
144 }
145}
146
147} // 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.
virtual VectorSpace range() const
Range space of this operator.
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
Teuchos::RCP< const Thyra::ProductVectorSpaceBase< double > > productDomain_
Domain vector space.