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
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);
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.
std::vector< Teuchos::RCP< const FactoryManagerBase > > FactManager_
Input factories.
Exception indicating invalid cast attempted.
Exception throws to report errors in the internal logical of the program.
void Input(Level &level, const std::string &varName) const
T Get(Level &level, const std::string &varName) const
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())
virtual const Teuchos::ParameterList & GetParameterList() const
An exception safe way to call the method 'Level::SetFactoryManager()'.
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
Namespace for MueLu classes and methods.
@ Runtime1
Description of what is happening (more verbose).