Teko Version of the Day
Loading...
Searching...
No Matches
Teko_BlockDiagonalInverseOp.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_BlockDiagonalInverseOp.hpp"
11
12#include "Teuchos_Utils.hpp"
13
14namespace Teko {
15
16using Teuchos::RCP;
17
18BlockDiagonalInverseOp::BlockDiagonalInverseOp(BlockedLinearOp& A,
19 const std::vector<LinearOp>& invDiag)
20 : invDiag_(invDiag) {
21 // sanity check
22 int blocks = blockRowCount(A);
23 TEUCHOS_ASSERT(blocks > 0);
24 TEUCHOS_ASSERT(blocks == blockColCount(A));
25 TEUCHOS_ASSERT(blocks == (int)invDiag_.size());
26
27 // create the range and product space
29
30 // just flip flop them!
31 productRange_ = A->productDomain();
32 productDomain_ = A->productRange();
33}
34
35void BlockDiagonalInverseOp::implicitApply(const BlockedMultiVector& src, BlockedMultiVector& dst,
36 const double alpha, const double beta) const {
37 // call the no tranpose version
38 implicitApply(Thyra::NOTRANS, src, dst, alpha, beta);
39}
40
41namespace {
42bool compatibleMultiVectors(const BlockedMultiVector& a, const BlockedMultiVector& b) {
43 if (!a || !b) return false;
44
45 return a->domain()->dim() == b->domain()->dim();
46}
47} // namespace
48
49void BlockDiagonalInverseOp::implicitApply(const Thyra::EOpTransp M_trans,
50 const BlockedMultiVector& src, BlockedMultiVector& dst,
51 const double alpha, const double beta) const {
52 int blocks = blockCount(src);
53
54 TEUCHOS_ASSERT(blocks == (int)invDiag_.size());
55
56 bool needsAlloc = !allocated;
57 needsAlloc |= !compatibleMultiVectors(srcScrap_, src);
58 needsAlloc |= !compatibleMultiVectors(dstScrap_, dst);
59 if (needsAlloc) {
60 srcScrap_ = deepcopy(src);
61 dstScrap_ = deepcopy(dst);
62 allocated = true;
63 }
64
65 // build a scrap vector for storing work
66 Thyra::assign<double>(srcScrap_.ptr(), *src);
67 BlockedMultiVector dstCopy;
68 if (beta != 0.0) {
69 Thyra::assign<double>(dstScrap_.ptr(), *dst);
70 dstCopy = dstScrap_;
71 } else
72 dstCopy = dst; // shallow copy
73
74 // extract the blocks components from
75 // the source and destination vectors
76 std::vector<MultiVector> dstVec;
77 std::vector<MultiVector> scrapVec;
78 for (int b = 0; b < blocks; b++) {
79 dstVec.push_back(getBlock(b, dstCopy));
80 scrapVec.push_back(getBlock(b, srcScrap_));
81 }
82
83 if (M_trans == Thyra::NOTRANS) {
84 for (int b = 0; b < blocks; b++) {
85 applyOp(invDiag_[b], scrapVec[b], dstVec[b]);
86 }
87 } else if (M_trans == Thyra::TRANS || M_trans == Thyra::CONJTRANS) {
88 for (int b = 0; b < blocks; b++) {
89 applyTransposeOp(invDiag_[b], scrapVec[b], dstVec[b]);
90 }
91 } else {
92 TEUCHOS_TEST_FOR_EXCEPT(true);
93 }
94
95 // scale result by alpha
96 if (beta != 0)
97 update(alpha, dstCopy, beta, dst); // dst = alpha * dstCopy + beta * dst
98 else if (alpha != 1.0)
99 scale(alpha, dst); // dst = alpha * dst
100}
101
102void BlockDiagonalInverseOp::describe(Teuchos::FancyOStream& out_arg,
103 const Teuchos::EVerbosityLevel verbLevel) const {
104 using Teuchos::OSTab;
105
106 RCP<Teuchos::FancyOStream> out = rcp(&out_arg, false);
107 OSTab tab(out);
108 switch (verbLevel) {
109 case Teuchos::VERB_DEFAULT:
110 case Teuchos::VERB_LOW: *out << this->description() << std::endl; break;
111 case Teuchos::VERB_MEDIUM:
112 case Teuchos::VERB_HIGH:
113 case Teuchos::VERB_EXTREME: {
114 *out << Teuchos::Describable::description() << "{"
115 << "rangeDim=" << this->range()->dim() << ",domainDim=" << this->domain()->dim()
116 << ",rows=" << invDiag_.size() << ",cols=" << invDiag_.size() << "}\n";
117 {
118 OSTab tab2(out);
119 *out << "[invDiag Operators]:\n";
120 tab.incrTab();
121 for (auto i = 0U; i < invDiag_.size(); i++) {
122 *out << "[invD(" << i << ")] = ";
123 *out << Teuchos::describe(*invDiag_[i], verbLevel);
124 }
125 }
126 break;
127 }
128 default: TEUCHOS_TEST_FOR_EXCEPT(true); // Should never get here!
129 }
130}
131
132} // 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 domain() const
Domain space of this operator.
Teuchos::RCP< const Thyra::ProductVectorSpaceBase< double > > productRange_
Range vector space.
virtual VectorSpace range() const
Range space of this operator.
std::vector< LinearOp > invDiag_
(Approximate) Inverses of the diagonal operators
Teuchos::RCP< const Thyra::ProductVectorSpaceBase< double > > productDomain_
Domain vector space.
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.