MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_SubBlockAFactory_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_SUBBLOCKAFACTORY_DEF_HPP_
11#define MUELU_SUBBLOCKAFACTORY_DEF_HPP_
12
14
15#include <Xpetra_BlockedCrsMatrix.hpp>
16#include <Xpetra_MapExtractor.hpp>
17#include <Xpetra_Matrix.hpp>
18#include <Xpetra_StridedMapFactory.hpp>
19
20#include "MueLu_Level.hpp"
21#include "MueLu_Monitor.hpp"
22
23namespace MueLu {
24
25template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
27 RCP<ParameterList> validParamList = rcp(new ParameterList());
28
29 validParamList->set<RCP<const FactoryBase>>("A", MueLu::NoFactory::getRCP(), "Generating factory for A.");
30
31 validParamList->set<int>("block row", 0, "Block row of subblock matrix A");
32 validParamList->set<int>("block col", 0, "Block column of subblock matrix A");
33
34 validParamList->set<std::string>("Range map: Striding info", "{}", "Striding information for range map");
35 validParamList->set<LocalOrdinal>("Range map: Strided block id", -1, "Strided block id for range map");
36 validParamList->set<std::string>("Domain map: Striding info", "{}", "Striding information for domain map");
37 validParamList->set<LocalOrdinal>("Domain map: Strided block id", -1, "Strided block id for domain map");
38
39 return validParamList;
40}
41
42template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
44 Input(currentLevel, "A");
45}
46
47template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
49 FactoryMonitor m(*this, "Build", currentLevel);
50
51 const ParameterList& pL = GetParameterList();
52 size_t row = Teuchos::as<size_t>(pL.get<int>("block row"));
53 size_t col = Teuchos::as<size_t>(pL.get<int>("block col"));
54
55 RCP<Matrix> Ain = currentLevel.Get<RCP<Matrix>>("A", this->GetFactory("A").get());
56 RCP<BlockedCrsMatrix> A = rcp_dynamic_cast<BlockedCrsMatrix>(Ain);
57
58 TEUCHOS_TEST_FOR_EXCEPTION(A.is_null(), Exceptions::BadCast, "Input matrix A is not a BlockedCrsMatrix.");
59 TEUCHOS_TEST_FOR_EXCEPTION(row > A->Rows(), Exceptions::RuntimeError, "row [" << row << "] > A.Rows() [" << A->Rows() << "].");
60 TEUCHOS_TEST_FOR_EXCEPTION(col > A->Cols(), Exceptions::RuntimeError, "col [" << col << "] > A.Cols() [" << A->Cols() << "].");
61
62 // get sub-matrix
63 RCP<Matrix> Op = A->getMatrix(row, col);
64
65 // Check if it is a BlockedCrsMatrix object
66 // If it is a BlockedCrsMatrix object (most likely a ReorderedBlockedCrsMatrix)
67 // we have to distinguish whether it is a 1x1 leaf block in the ReorderedBlockedCrsMatrix
68 // or a nxm block. If it is a 1x1 leaf block, we "unpack" it and return the underlying
69 // CrsMatrixWrap object.
70 RCP<BlockedCrsMatrix> bOp = rcp_dynamic_cast<BlockedCrsMatrix>(Op);
71 if (bOp != Teuchos::null) {
72 // check if it is a 1x1 leaf block
73 if (bOp->Rows() == 1 && bOp->Cols() == 1) {
74 // return the unwrapped CrsMatrixWrap object underneath
75 Op = bOp->getCrsMatrix();
76 TEUCHOS_TEST_FOR_EXCEPTION(rcp_dynamic_cast<CrsMatrixWrap>(Op) == Teuchos::null, Exceptions::BadCast,
77 "SubBlockAFactory::Build: sub block A[" << row << "," << col << "] must be a single block CrsMatrixWrap object!");
78 } else {
79 // If it is a regular nxm blocked operator, just return it.
80 // We do not set any kind of striding or blocking information as this
81 // usually would not make sense for general blocked operators
82 GetOStream(Statistics1) << "A(" << row << "," << col << ") is a " << bOp->Rows() << "x" << bOp->Cols() << " block matrix" << std::endl;
83 GetOStream(Statistics2) << "with altogether " << bOp->getGlobalNumRows() << "x" << bOp->getGlobalNumCols() << " rows and columns." << std::endl;
84 currentLevel.Set("A", Op, this);
85 return;
86 }
87 }
88
89 // The sub-block is not a BlockedCrsMatrix object, that is, we expect
90 // it to be of type CrsMatrixWrap allowing direct access to the corresponding
91 // data. For a single block CrsMatrixWrap type matrix we can/should set the
92 // corresponding striding/blocking information for the algorithms to work
93 // properly.
94 //
95 // TAW: In fact, a 1x1 BlockedCrsMatrix object also allows to access the data
96 // directly, but this feature is nowhere really used in the algorithms.
97 // So let's keep checking for the CrsMatrixWrap class to avoid screwing
98 // things up
99 //
100 TEUCHOS_TEST_FOR_EXCEPTION(rcp_dynamic_cast<CrsMatrixWrap>(Op) == Teuchos::null, Exceptions::BadCast,
101 "SubBlockAFactory::Build: sub block A[" << row << "," << col << "] is NOT a BlockedCrsMatrix, but also NOT a CrsMatrixWrap object. This cannot be.");
102
103 // strided maps for range and domain map of sub matrix
104 RCP<const StridedMap> stridedRangeMap = Teuchos::null;
105 RCP<const StridedMap> stridedDomainMap = Teuchos::null;
106
107 // check for user-specified striding information from XML file
108 std::vector<size_t> rangeStridingInfo;
109 std::vector<size_t> domainStridingInfo;
110 LocalOrdinal rangeStridedBlockId = 0;
111 LocalOrdinal domainStridedBlockId = 0;
112 bool bRangeUserSpecified = CheckForUserSpecifiedBlockInfo(true, rangeStridingInfo, rangeStridedBlockId);
113 bool bDomainUserSpecified = CheckForUserSpecifiedBlockInfo(false, domainStridingInfo, domainStridedBlockId);
114 TEUCHOS_TEST_FOR_EXCEPTION(bRangeUserSpecified != bDomainUserSpecified, Exceptions::RuntimeError,
115 "MueLu::SubBlockAFactory[" << row << "," << col << "]: the user has to specify either both domain and range map or none.");
116
117 // extract map information from MapExtractor
118 RCP<const MapExtractor> rangeMapExtractor = A->getRangeMapExtractor();
119 RCP<const MapExtractor> domainMapExtractor = A->getDomainMapExtractor();
120
121 bool thyraMode = rangeMapExtractor->getThyraMode();
122
123 RCP<const Map> rangeMap = rangeMapExtractor->getMap(row, thyraMode);
124 RCP<const Map> domainMap = domainMapExtractor->getMap(col, thyraMode);
125
126 // use user-specified striding information if available. Otherwise try to use internal striding information from the submaps!
127 if (bRangeUserSpecified)
128 stridedRangeMap = rcp(new StridedMap(rangeMap, rangeStridingInfo, rangeMap->getIndexBase(), rangeStridedBlockId, 0));
129 else
130 stridedRangeMap = rcp_dynamic_cast<const StridedMap>(rangeMap);
131
132 if (bDomainUserSpecified)
133 stridedDomainMap = rcp(new StridedMap(domainMap, domainStridingInfo, domainMap->getIndexBase(), domainStridedBlockId, 0));
134 else
135 stridedDomainMap = rcp_dynamic_cast<const StridedMap>(domainMap);
136
137 // In case that both user-specified and internal striding information from the submaps
138 // does not contain valid striding information, try to extract it from the global maps
139 // in the map extractor.
140 if (stridedRangeMap.is_null()) {
141 RCP<const Map> fullRangeMap = rangeMapExtractor->getFullMap();
142 RCP<const StridedMap> stridedFullRangeMap = rcp_dynamic_cast<const StridedMap>(fullRangeMap);
143 TEUCHOS_TEST_FOR_EXCEPTION(stridedFullRangeMap.is_null(), Exceptions::BadCast, "Full rangeMap is not a strided map.");
144
145 std::vector<size_t> stridedData = stridedFullRangeMap->getStridingData();
146 if (stridedData.size() == 1 && row > 0) {
147 // We have block matrices. use striding block information 0
148 stridedRangeMap = StridedMapFactory::Build(rangeMap, stridedData, 0, stridedFullRangeMap->getOffset());
149
150 } else {
151 // We have strided matrices. use striding information of the corresponding block
152 stridedRangeMap = StridedMapFactory::Build(rangeMap, stridedData, row, stridedFullRangeMap->getOffset());
153 }
154 }
155
156 if (stridedDomainMap.is_null()) {
157 RCP<const Map> fullDomainMap = domainMapExtractor->getFullMap();
158 RCP<const StridedMap> stridedFullDomainMap = rcp_dynamic_cast<const StridedMap>(fullDomainMap);
159 TEUCHOS_TEST_FOR_EXCEPTION(stridedFullDomainMap.is_null(), Exceptions::BadCast, "Full domainMap is not a strided map");
160
161 std::vector<size_t> stridedData = stridedFullDomainMap->getStridingData();
162 if (stridedData.size() == 1 && col > 0) {
163 // We have block matrices. use striding block information 0
164 stridedDomainMap = StridedMapFactory::Build(domainMap, stridedData, 0, stridedFullDomainMap->getOffset());
165
166 } else {
167 // We have strided matrices. use striding information of the corresponding block
168 stridedDomainMap = StridedMapFactory::Build(domainMap, stridedData, col, stridedFullDomainMap->getOffset());
169 }
170 }
171
172 TEUCHOS_TEST_FOR_EXCEPTION(stridedRangeMap.is_null(), Exceptions::BadCast, "rangeMap " << row << " is not a strided map.");
173 TEUCHOS_TEST_FOR_EXCEPTION(stridedDomainMap.is_null(), Exceptions::BadCast, "domainMap " << col << " is not a strided map.");
174
175 GetOStream(Statistics1) << "A(" << row << "," << col << ") is a single block and has strided maps:"
176 << "\n range map fixed block size = " << stridedRangeMap->getFixedBlockSize() << ", strided block id = " << stridedRangeMap->getStridedBlockId()
177 << "\n domain map fixed block size = " << stridedDomainMap->getFixedBlockSize() << ", strided block id = " << stridedDomainMap->getStridedBlockId() << std::endl;
178 GetOStream(Statistics2) << "A(" << row << "," << col << ") has " << Op->getGlobalNumRows() << "x" << Op->getGlobalNumCols() << " rows and columns." << std::endl;
179
180 // TODO do we really need that? we moved the code to getMatrix...
181 if (Op->IsView("stridedMaps") == true)
182 Op->RemoveView("stridedMaps");
183 Op->CreateView("stridedMaps", stridedRangeMap, stridedDomainMap);
184
185 TEUCHOS_TEST_FOR_EXCEPTION(Op->IsView("stridedMaps") == false, Exceptions::RuntimeError, "Failed to set \"stridedMaps\" view.");
186
187 currentLevel.Set("A", Op, this);
188}
189
190template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
192 CheckForUserSpecifiedBlockInfo(bool bRange, std::vector<size_t>& stridingInfo, LocalOrdinal& stridedBlockId) const {
193 const ParameterList& pL = GetParameterList();
194
195 if (bRange == true)
196 stridedBlockId = pL.get<LocalOrdinal>("Range map: Strided block id");
197 else
198 stridedBlockId = pL.get<LocalOrdinal>("Domain map: Strided block id");
199
200 // read in stridingInfo from parameter list and fill the internal member variable
201 // read the data only if the parameter "Striding info" exists and is non-empty
202 std::string str;
203 if (bRange == true)
204 str = std::string("Range map: Striding info");
205 else
206 str = std::string("Domain map: Striding info");
207
208 if (pL.isParameter(str)) {
209 std::string strStridingInfo = pL.get<std::string>(str);
210 if (strStridingInfo.empty() == false) {
211 Array<size_t> arrayVal = Teuchos::fromStringToArray<size_t>(strStridingInfo);
212 stridingInfo = Teuchos::createVector(arrayVal);
213 }
214 }
215
216 if (stridingInfo.size() > 0) return true;
217 return false;
218}
219
220} // namespace MueLu
221
222#endif /* MUELU_SUBBLOCKAFACTORY_DEF_HPP_ */
MueLu::DefaultLocalOrdinal LocalOrdinal
Exception indicating invalid cast attempted.
Exception throws to report errors in the internal logical of the program.
Timer to be used in factories. Similar to Monitor but with additional timers.
Class that holds all level-specific information.
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access)....
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
static const RCP< const NoFactory > getRCP()
Static Get() functions.
void DeclareInput(Level &currentLevel) const override
Specifies the data that this class needs, and the factories that generate that data.
bool CheckForUserSpecifiedBlockInfo(bool bRange, std::vector< size_t > &stridingInfo, LocalOrdinal &stridedBlockId) const
void Build(Level &currentLevel) const override
Build an object with this factory.
RCP< const ParameterList > GetValidParameterList() const override
Input.
Namespace for MueLu classes and methods.
@ Statistics2
Print even more statistics.
@ Statistics1
Print more statistics.