MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_BlockedPFactory_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_BLOCKEDPFACTORY_DEF_HPP_
11#define MUELU_BLOCKEDPFACTORY_DEF_HPP_
12
13#include <Xpetra_MultiVectorFactory.hpp>
14#include <Xpetra_VectorFactory.hpp>
15#include <Xpetra_ImportFactory.hpp>
16#include <Xpetra_ExportFactory.hpp>
17#include <Xpetra_CrsMatrixWrap.hpp>
18
19#include <Xpetra_BlockedCrsMatrix.hpp>
20#include <Xpetra_Map.hpp>
21#include <Xpetra_MapFactory.hpp>
22#include <Xpetra_MapExtractor.hpp>
23#include <Xpetra_MapExtractorFactory.hpp>
24
26#include "MueLu_FactoryBase.hpp"
27#include "MueLu_FactoryManager.hpp"
28#include "MueLu_Monitor.hpp"
29#include "MueLu_HierarchyUtils.hpp"
30
31namespace MueLu {
32
33template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
35 RCP<ParameterList> validParamList = rcp(new ParameterList());
36
37 validParamList->set<RCP<const FactoryBase> >("A", null, "Generating factory of the matrix A (block matrix)");
38 validParamList->set<bool>("backwards", false, "Forward/backward order");
39
40 return validParamList;
41}
42
43template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
45 Input(fineLevel, "A");
46
47 const ParameterList& pL = GetParameterList();
48 const bool backwards = pL.get<bool>("backwards");
49
50 const int numFactManagers = FactManager_.size();
51 for (int k = 0; k < numFactManagers; k++) {
52 int i = (backwards ? numFactManagers - 1 - k : k);
53 const RCP<const FactoryManagerBase>& factManager = FactManager_[i];
54
55 SetFactoryManager fineSFM(rcpFromRef(fineLevel), factManager);
56 SetFactoryManager coarseSFM(rcpFromRef(coarseLevel), factManager);
57
58 if (!restrictionMode_)
59 coarseLevel.DeclareInput("P", factManager->GetFactory("P").get(), this);
60 else
61 coarseLevel.DeclareInput("R", factManager->GetFactory("R").get(), this);
62 }
63}
64
65template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
66void BlockedPFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildP(Level& /* fineLevel */, Level& /* coarseLevel */) const {}
67
68template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
70 FactoryMonitor m(*this, "Build", coarseLevel);
71
72 RCP<Matrix> Ain = Get<RCP<Matrix> >(fineLevel, "A");
73
74 RCP<BlockedCrsMatrix> A = rcp_dynamic_cast<BlockedCrsMatrix>(Ain);
75 TEUCHOS_TEST_FOR_EXCEPTION(A.is_null(), Exceptions::BadCast, "Input matrix A is not a BlockedCrsMatrix.");
76
77 const int numFactManagers = FactManager_.size();
78
79 // Plausibility check
80 TEUCHOS_TEST_FOR_EXCEPTION(A->Rows() != as<size_t>(numFactManagers), Exceptions::RuntimeError,
81 "Number of block rows [" << A->Rows() << "] does not match the number of SubFactorManagers [" << numFactManagers << "]");
82 TEUCHOS_TEST_FOR_EXCEPTION(A->Cols() != as<size_t>(numFactManagers), Exceptions::RuntimeError,
83 "Number of block cols [" << A->Cols() << "] does not match the number of SubFactorManagers [" << numFactManagers << "]");
84
85 // Build blocked prolongator
86 std::vector<RCP<Matrix> > subBlockP(numFactManagers);
87 std::vector<RCP<const Map> > subBlockPRangeMaps(numFactManagers);
88 std::vector<RCP<const Map> > subBlockPDomainMaps(numFactManagers);
89
90 std::vector<GO> fullRangeMapVector;
91 std::vector<GO> fullDomainMapVector;
92
93 RCP<const MapExtractor> rangeAMapExtractor = A->getRangeMapExtractor();
94 RCP<const MapExtractor> domainAMapExtractor = A->getDomainMapExtractor();
95
96 const ParameterList& pL = GetParameterList();
97 const bool backwards = pL.get<bool>("backwards");
98
99 // Build and store the subblocks and the corresponding range and domain
100 // maps. Since we put together the full range and domain map from the
101 // submaps, we do not have to use the maps from blocked A
102 for (int k = 0; k < numFactManagers; k++) {
103 int i = (backwards ? numFactManagers - 1 - k : k);
104 if (restrictionMode_)
105 GetOStream(Runtime1) << "Generating R for block " << k << "/" << numFactManagers << std::endl;
106 else
107 GetOStream(Runtime1) << "Generating P for block " << k << "/" << numFactManagers << std::endl;
108
109 const RCP<const FactoryManagerBase>& factManager = FactManager_[i];
110
111 SetFactoryManager fineSFM(rcpFromRef(fineLevel), factManager);
112 SetFactoryManager coarseSFM(rcpFromRef(coarseLevel), factManager);
113
114 if (!restrictionMode_)
115 subBlockP[i] = coarseLevel.Get<RCP<Matrix> >("P", factManager->GetFactory("P").get());
116 else
117 subBlockP[i] = coarseLevel.Get<RCP<Matrix> >("R", factManager->GetFactory("R").get());
118
119 // Check if prolongator/restrictor operators have strided maps
120 TEUCHOS_TEST_FOR_EXCEPTION(subBlockP[i]->IsView("stridedMaps") == false, Exceptions::BadCast,
121 "subBlock P operator [" << i << "] has no strided map information.");
122
123 // Append strided row map (= range map) to list of range maps.
124 // TAW the row map GIDs extracted here represent the actual row map GIDs.
125 // No support for nested operators! (at least if Thyra style gids are used)
126 RCP<const StridedMap> strPartialMap = Teuchos::rcp_dynamic_cast<const StridedMap>(subBlockP[i]->getRowMap("stridedMaps"));
127 std::vector<size_t> stridedRgData = strPartialMap->getStridingData();
128 subBlockPRangeMaps[i] = StridedMapFactory::Build(
129 subBlockP[i]->getRangeMap(), // actual global IDs (Thyra or Xpetra)
130 stridedRgData,
131 strPartialMap->getStridedBlockId(),
132 strPartialMap->getOffset());
133 // subBlockPRangeMaps[i] = subBlockP[i]->getRowMap("stridedMaps");
134
135 // Use plain range map to determine the DOF ids
136 ArrayView<const GO> nodeRangeMap = subBlockPRangeMaps[i]->getLocalElementList();
137 fullRangeMapVector.insert(fullRangeMapVector.end(), nodeRangeMap.begin(), nodeRangeMap.end());
138
139 // Append strided col map (= domain map) to list of range maps.
140 RCP<const StridedMap> strPartialMap2 = Teuchos::rcp_dynamic_cast<const StridedMap>(subBlockP[i]->getColMap("stridedMaps"));
141 std::vector<size_t> stridedRgData2 = strPartialMap2->getStridingData();
142 subBlockPDomainMaps[i] = StridedMapFactory::Build(
143 subBlockP[i]->getDomainMap(), // actual global IDs (Thyra or Xpetra)
144 stridedRgData2,
145 strPartialMap2->getStridedBlockId(),
146 strPartialMap2->getOffset());
147 // subBlockPDomainMaps[i] = subBlockP[i]->getColMap("stridedMaps");
148
149 // Use plain domain map to determine the DOF ids
150 ArrayView<const GO> nodeDomainMap = subBlockPDomainMaps[i]->getLocalElementList();
151 fullDomainMapVector.insert(fullDomainMapVector.end(), nodeDomainMap.begin(), nodeDomainMap.end());
152 }
153
154 // check if GIDs for full maps have to be sorted:
155 // For the Thyra mode ordering they do not have to be sorted since the GIDs are
156 // numbered as 0...n1,0...,n2 (starting with zero for each subblock). The MapExtractor
157 // generates unique GIDs during the construction.
158 // For Xpetra style, the GIDs have to be reordered. Such that one obtains a ordered
159 // list of GIDs in an increasing ordering. In Xpetra, the GIDs are all unique through
160 // out all submaps.
161 bool bDoSortRangeGIDs = rangeAMapExtractor->getThyraMode() ? false : true;
162 bool bDoSortDomainGIDs = domainAMapExtractor->getThyraMode() ? false : true;
163
164 if (bDoSortRangeGIDs) {
165 sort(fullRangeMapVector.begin(), fullRangeMapVector.end());
166 fullRangeMapVector.erase(std::unique(fullRangeMapVector.begin(), fullRangeMapVector.end()), fullRangeMapVector.end());
167 }
168 if (bDoSortDomainGIDs) {
169 sort(fullDomainMapVector.begin(), fullDomainMapVector.end());
170 fullDomainMapVector.erase(std::unique(fullDomainMapVector.begin(), fullDomainMapVector.end()), fullDomainMapVector.end());
171 }
172
173 // extract map index base from maps of blocked A
174 GO rangeIndexBase = 0;
175 GO domainIndexBase = 0;
176 if (!restrictionMode_) {
177 // Prolongation mode: just use index base of range and domain map of A
178 rangeIndexBase = A->getRangeMap()->getIndexBase();
179 domainIndexBase = A->getDomainMap()->getIndexBase();
180
181 } else {
182 // Restriction mode: switch range and domain map for blocked restriction operator
183 rangeIndexBase = A->getDomainMap()->getIndexBase();
184 domainIndexBase = A->getRangeMap()->getIndexBase();
185 }
186
187 // Build full range map.
188 // If original range map has striding information, then transfer it to the
189 // new range map
190 RCP<const StridedMap> stridedRgFullMap = rcp_dynamic_cast<const StridedMap>(rangeAMapExtractor->getFullMap());
191 RCP<const Map> fullRangeMap = Teuchos::null;
192
193 ArrayView<GO> fullRangeMapGIDs(fullRangeMapVector.size() ? &fullRangeMapVector[0] : 0, fullRangeMapVector.size());
194 if (stridedRgFullMap != Teuchos::null) {
195 std::vector<size_t> stridedData = stridedRgFullMap->getStridingData();
196 fullRangeMap = StridedMapFactory::Build(
197 A->getRangeMap()->lib(),
198 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
199 fullRangeMapGIDs,
200 rangeIndexBase,
201 stridedData,
202 A->getRangeMap()->getComm(),
203 -1, /* the full map vector should always have strided block id -1! */
204 stridedRgFullMap->getOffset());
205 } else {
206 fullRangeMap = MapFactory::Build(
207 A->getRangeMap()->lib(),
208 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
209 fullRangeMapGIDs,
210 rangeIndexBase,
211 A->getRangeMap()->getComm());
212 }
213
214 ArrayView<GO> fullDomainMapGIDs(fullDomainMapVector.size() ? &fullDomainMapVector[0] : 0, fullDomainMapVector.size());
215 RCP<const StridedMap> stridedDoFullMap = rcp_dynamic_cast<const StridedMap>(domainAMapExtractor->getFullMap());
216 RCP<const Map> fullDomainMap = null;
217 if (stridedDoFullMap != null) {
218 TEUCHOS_TEST_FOR_EXCEPTION(stridedDoFullMap == Teuchos::null, Exceptions::BadCast,
219 "MueLu::BlockedPFactory::Build: full map in domain map extractor has no striding information!");
220
221 std::vector<size_t> stridedData2 = stridedDoFullMap->getStridingData();
222 fullDomainMap = StridedMapFactory::Build(
223 A->getDomainMap()->lib(),
224 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
225 fullDomainMapGIDs,
226 domainIndexBase,
227 stridedData2,
228 A->getDomainMap()->getComm(),
229 -1, /* the full map vector should always have strided block id -1! */
230 stridedDoFullMap->getOffset());
231 } else {
232 fullDomainMap = MapFactory::Build(
233 A->getDomainMap()->lib(),
234 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
235 fullDomainMapGIDs,
236 domainIndexBase,
237 A->getDomainMap()->getComm());
238 }
239
240 // Build map extractors
241 RCP<const MapExtractor> rangeMapExtractor = MapExtractorFactory::Build(fullRangeMap, subBlockPRangeMaps, rangeAMapExtractor->getThyraMode());
242 RCP<const MapExtractor> domainMapExtractor = MapExtractorFactory::Build(fullDomainMap, subBlockPDomainMaps, domainAMapExtractor->getThyraMode());
243
244 RCP<BlockedCrsMatrix> P = rcp(new BlockedCrsMatrix(rangeMapExtractor, domainMapExtractor, 10));
245 for (size_t i = 0; i < subBlockPRangeMaps.size(); i++)
246 for (size_t j = 0; j < subBlockPRangeMaps.size(); j++)
247 if (i == j) {
248 RCP<CrsMatrixWrap> crsOpii = rcp_dynamic_cast<CrsMatrixWrap>(subBlockP[i]);
249 TEUCHOS_TEST_FOR_EXCEPTION(crsOpii == Teuchos::null, Xpetra::Exceptions::BadCast,
250 "Block [" << i << "," << j << "] must be of type CrsMatrixWrap.");
251 P->setMatrix(i, i, crsOpii);
252 } else {
253 P->setMatrix(i, j, Teuchos::null);
254 }
255
256 P->fillComplete();
257
258 // Level Set
259 if (!restrictionMode_) {
260 // Prolongation mode
261 coarseLevel.Set("P", rcp_dynamic_cast<Matrix>(P), this);
262 // Stick the CoarseMap on the level if somebody wants it (useful for repartitioning)
263 coarseLevel.Set("CoarseMap", P->getBlockedDomainMap(), this);
264 } else {
265 // Restriction mode
266 // We do not have to transpose the blocked R operator since the subblocks
267 // on the diagonal are already valid R subblocks
268 coarseLevel.Set("R", Teuchos::rcp_dynamic_cast<Matrix>(P), this);
269 }
270}
271
272} // namespace MueLu
273
274#endif /* MUELU_BLOCKEDPFACTORY_DEF_HPP_ */
void Build(Level &fineLevel, Level &coarseLevel) const
Build method.
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Input.
void BuildP(Level &fineLevel, Level &coarseLevel) const
Abstract Build method.
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.
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
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())
An exception safe way to call the method 'Level::SetFactoryManager()'.
Namespace for MueLu classes and methods.
@ Runtime1
Description of what is happening (more verbose)