MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_BlockedRAPFactory_def.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// MueLu: A package for multigrid based preconditioning
4//
5// Copyright 2012 NTESS and the MueLu contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef MUELU_BLOCKEDRAPFACTORY_DEF_HPP
11#define MUELU_BLOCKEDRAPFACTORY_DEF_HPP
12
13#include <Xpetra_BlockedCrsMatrix.hpp>
14#include <Xpetra_MatrixFactory.hpp>
15#include <Xpetra_Matrix.hpp>
16#include <Xpetra_MatrixMatrix.hpp>
17
19
20#include "MueLu_MasterList.hpp"
21#include "MueLu_Monitor.hpp"
22#include "MueLu_PerfUtils.hpp"
24
25namespace MueLu {
26
27template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
29 : checkAc_(false)
30 , repairZeroDiagonals_(false) {}
31
32template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
34 RCP<ParameterList> validParamList = rcp(new ParameterList());
35
36#define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
37 SET_VALID_ENTRY("transpose: use implicit");
38#undef SET_VALID_ENTRY
39 validParamList->set<RCP<const FactoryBase> >("A", null, "Generating factory of the matrix A used during the prolongator smoothing process");
40 validParamList->set<RCP<const FactoryBase> >("P", null, "Prolongator factory");
41 validParamList->set<RCP<const FactoryBase> >("R", null, "Restrictor factory");
42
43 return validParamList;
44}
45
46template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
48 const Teuchos::ParameterList &pL = GetParameterList();
49 if (pL.get<bool>("transpose: use implicit") == false)
50 Input(coarseLevel, "R");
51
52 Input(fineLevel, "A");
53 Input(coarseLevel, "P");
54
55 // call DeclareInput of all user-given transfer factories
56 for (std::vector<RCP<const FactoryBase> >::const_iterator it = transferFacts_.begin(); it != transferFacts_.end(); ++it)
57 (*it)->CallDeclareInput(coarseLevel);
58}
59
60template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
61void BlockedRAPFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(Level &fineLevel, Level &coarseLevel) const { // FIXME make fineLevel const!!
62 FactoryMonitor m(*this, "Computing Ac (block)", coarseLevel);
63
64 const ParameterList &pL = GetParameterList();
65
66 RCP<Matrix> A = Get<RCP<Matrix> >(fineLevel, "A");
67 RCP<Matrix> P = Get<RCP<Matrix> >(coarseLevel, "P");
68
69 RCP<BlockedCrsMatrix> bA = rcp_dynamic_cast<BlockedCrsMatrix>(A);
70 RCP<BlockedCrsMatrix> bP = rcp_dynamic_cast<BlockedCrsMatrix>(P);
71 TEUCHOS_TEST_FOR_EXCEPTION(bA.is_null() || bP.is_null(), Exceptions::BadCast, "Matrices A and P must be of type BlockedCrsMatrix.");
72
73 RCP<BlockedCrsMatrix> bAP;
74 RCP<BlockedCrsMatrix> bAc;
75 {
76 SubFactoryMonitor subM(*this, "MxM: A x P", coarseLevel);
77
78 // Triple matrix product for BlockedCrsMatrixClass
79 TEUCHOS_TEST_FOR_EXCEPTION((bA->Cols() != bP->Rows()), Exceptions::BadCast,
80 "Block matrix dimensions do not match: "
81 "A is "
82 << bA->Rows() << "x" << bA->Cols() << "P is " << bP->Rows() << "x" << bP->Cols());
83
84 bAP = MatrixMatrix::TwoMatrixMultiplyBlock(*bA, false, *bP, false, GetOStream(Statistics2), true, true);
85 }
86
87 // If we do not modify matrix later, allow optimization of storage.
88 // This is necessary for new faster Epetra MM kernels.
89 bool doOptimizeStorage = !checkAc_;
90
91 const bool doTranspose = true;
92 const bool doFillComplete = true;
93 if (pL.get<bool>("transpose: use implicit") == true) {
94 SubFactoryMonitor m2(*this, "MxM: P' x (AP) (implicit)", coarseLevel);
95 bAc = MatrixMatrix::TwoMatrixMultiplyBlock(*bP, doTranspose, *bAP, !doTranspose, GetOStream(Statistics2), doFillComplete, doOptimizeStorage);
96
97 } else {
98 RCP<Matrix> R = Get<RCP<Matrix> >(coarseLevel, "R");
99 RCP<BlockedCrsMatrix> bR = rcp_dynamic_cast<BlockedCrsMatrix>(R);
100 TEUCHOS_TEST_FOR_EXCEPTION(bR.is_null(), Exceptions::BadCast, "Matrix R must be of type BlockedCrsMatrix.");
101
102 TEUCHOS_TEST_FOR_EXCEPTION(bA->Rows() != bR->Cols(), Exceptions::BadCast,
103 "Block matrix dimensions do not match: "
104 "R is "
105 << bR->Rows() << "x" << bR->Cols() << "A is " << bA->Rows() << "x" << bA->Cols());
106
107 SubFactoryMonitor m2(*this, "MxM: R x (AP) (explicit)", coarseLevel);
108 bAc = MatrixMatrix::TwoMatrixMultiplyBlock(*bR, !doTranspose, *bAP, !doTranspose, GetOStream(Statistics2), doFillComplete, doOptimizeStorage);
109 }
110
111 if (checkAc_)
112 CheckMainDiagonal(bAc);
113
114 GetOStream(Statistics1) << PerfUtils::PrintMatrixInfo(*bAc, "Ac (blocked)");
115
116 Set<RCP<Matrix> >(coarseLevel, "A", bAc);
117
118 if (transferFacts_.begin() != transferFacts_.end()) {
119 SubFactoryMonitor m1(*this, "Projections", coarseLevel);
120
121 // call Build of all user-given transfer factories
122 for (std::vector<RCP<const FactoryBase> >::const_iterator it = transferFacts_.begin(); it != transferFacts_.end(); ++it) {
123 RCP<const FactoryBase> fac = *it;
124
125 GetOStream(Runtime0) << "BlockRAPFactory: call transfer factory: " << fac->description() << std::endl;
126
127 fac->CallBuild(coarseLevel);
128
129 // AP (11/11/13): I am not sure exactly why we need to call Release, but we do need it to get rid
130 // of dangling data for CoordinatesTransferFactory
131 coarseLevel.Release(*fac);
132 }
133 }
134}
135
136template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
137void BlockedRAPFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::CheckMainDiagonal(RCP<BlockedCrsMatrix> &bAc, bool repairZeroDiagonals) {
138 RCP<Matrix> c00 = bAc->getMatrix(0, 0);
139 RCP<Matrix> Aout = MatrixFactory::Build(c00->getRowMap(), c00->getGlobalMaxNumRowEntries());
140
141 RCP<Vector> diagVec = VectorFactory::Build(c00->getRowMap());
142 c00->getLocalDiagCopy(*diagVec);
143 ArrayRCP<SC> diagVal = diagVec->getDataNonConst(0);
144
145 // loop over local rows
146 for (size_t row = 0; row < c00->getLocalNumRows(); row++) {
147 // get global row id
148 GO grid = c00->getRowMap()->getGlobalElement(row); // global row id
149
150 ArrayView<const LO> indices;
151 ArrayView<const SC> vals;
152 c00->getLocalRowView(row, indices, vals);
153
154 // just copy all values in output
155 ArrayRCP<GO> indout(indices.size(), Teuchos::OrdinalTraits<GO>::zero());
156 ArrayRCP<SC> valout(indices.size(), Teuchos::ScalarTraits<SC>::zero());
157
158 // just copy values
159 for (size_t i = 0; i < as<size_t>(indices.size()); i++) {
160 GO gcid = c00->getColMap()->getGlobalElement(indices[i]); // LID -> GID (column)
161 indout[i] = gcid;
162 valout[i] = vals[i];
163 }
164
165 Aout->insertGlobalValues(grid, indout.view(0, indout.size()), valout.view(0, valout.size()));
166 if (diagVal[row] == Teuchos::ScalarTraits<SC>::zero() && repairZeroDiagonals) {
167 // always overwrite diagonal entry
168 Aout->insertGlobalValues(grid, Teuchos::tuple<GO>(grid), Teuchos::tuple<SC>(1.0));
169 }
170 }
171
172 Aout->fillComplete(c00->getDomainMap(), c00->getRangeMap());
173
174 bAc->setMatrix(0, 0, Aout);
175}
176
177template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
179 // check if it's a TwoLevelFactoryBase based transfer factory
180 TEUCHOS_TEST_FOR_EXCEPTION(rcp_dynamic_cast<const TwoLevelFactoryBase>(factory) == Teuchos::null, Exceptions::BadCast,
181 "Transfer factory is not derived from TwoLevelFactoryBase. This is very strange. "
182 "(Note: you can remove this exception if there's a good reason for)");
183 transferFacts_.push_back(factory);
184}
185
186} // namespace MueLu
187
188#define MUELU_BLOCKEDRAPFACTORY_SHORT
189#endif // MUELU_BLOCKEDRAPFACTORY_DEF_HPP
190
191// TODO add plausibility check
192// TODO add CheckMainDiagonal for Blocked operator
193// Avoid copying block matrix!
194// create new empty Operator
#define SET_VALID_ENTRY(name)
static void CheckMainDiagonal(RCP< BlockedCrsMatrix > &bAc, bool repairZeroDiagonals=false)
void Build(Level &fineLevel, Level &coarseLevel) const override
Build an object with this factory.
void DeclareInput(Level &fineLevel, Level &coarseLevel) const override
Input.
RCP< const ParameterList > GetValidParameterList() const override
Return a const parameter list of valid parameters that setParameterList() will accept.
void AddTransferFactory(const RCP< const FactoryBase > &factory)
Add transfer factory in the end of list of transfer factories in RepartitionAcFactory.
Exception indicating invalid cast attempted.
Timer to be used in factories. Similar to Monitor but with additional timers.
Class that holds all level-specific information.
void Release(const FactoryBase &factory)
Decrement the storage counter for all the inputs of a factory.
static std::string PrintMatrixInfo(const Matrix &A, const std::string &msgTag, RCP< const Teuchos::ParameterList > params=Teuchos::null)
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
Namespace for MueLu classes and methods.
@ Statistics2
Print even more statistics.
@ Statistics1
Print more statistics.
@ Runtime0
One-liner description of what is happening.