46 #ifndef MUELU_REBALANCEBLOCKINTERPOLATIONFACTORY_DEF_HPP_ 47 #define MUELU_REBALANCEBLOCKINTERPOLATIONFACTORY_DEF_HPP_ 49 #ifdef HAVE_MUELU_EXPERIMENTAL 51 #include <Teuchos_Tuple.hpp> 53 #include "Xpetra_MultiVector.hpp" 54 #include "Xpetra_MultiVectorFactory.hpp" 55 #include "Xpetra_Vector.hpp" 56 #include "Xpetra_VectorFactory.hpp" 57 #include <Xpetra_Matrix.hpp> 58 #include <Xpetra_BlockedCrsMatrix.hpp> 59 #include <Xpetra_MapFactory.hpp> 60 #include <Xpetra_MapExtractor.hpp> 61 #include <Xpetra_MapExtractorFactory.hpp> 62 #include <Xpetra_MatrixFactory.hpp> 63 #include <Xpetra_Import.hpp> 64 #include <Xpetra_ImportFactory.hpp> 69 #include "MueLu_HierarchyUtils.hpp" 72 #include "MueLu_PerfUtils.hpp" 76 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
78 RCP<ParameterList> validParamList = rcp(
new ParameterList());
80 validParamList->set< RCP<const FactoryBase> >(
"P", Teuchos::null,
"Factory of the prolongation operator that need to be rebalanced (only used if type=Interpolation)");
81 validParamList->set< RCP<const FactoryBase> >(
"A", Teuchos::null,
"Factory for generating the non-rebalanced coarse level A. We need this to make sure the non-rebalanced coarse A is calculated first before rebalancing takes place.");
83 validParamList->set< RCP<const FactoryBase> >(
"Coordinates", Teuchos::null,
"Factory for generating the non-rebalanced Coordinates.");
84 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name)) 86 #undef SET_VALID_ENTRY 92 return validParamList;
95 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
97 FactManager_.push_back(FactManager);
100 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
102 Input(coarseLevel,
"P");
103 Input(coarseLevel,
"A");
105 std::vector<Teuchos::RCP<const FactoryManagerBase> >::const_iterator it;
106 for(it = FactManager_.begin(); it!=FactManager_.end(); ++it) {
112 coarseLevel.
DeclareInput(
"Importer",(*it)->GetFactory(
"Importer").get(),
this);
113 if((*it)->hasFactory(
"Coordinates") ==
true)
114 coarseLevel.
DeclareInput(
"Coordinates",(*it)->GetFactory(
"Coordinates").get(),
this);
118 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
124 Teuchos::RCP<Matrix> nonrebCoarseA = Get< RCP<Matrix> >(coarseLevel,
"A");
126 Teuchos::RCP<Matrix> originalTransferOp = Teuchos::null;
127 originalTransferOp = Get< RCP<Matrix> >(coarseLevel,
"P");
129 RCP<Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > bOriginalTransferOp =
130 Teuchos::rcp_dynamic_cast<Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > (originalTransferOp);
131 TEUCHOS_TEST_FOR_EXCEPTION(bOriginalTransferOp==Teuchos::null,
Exceptions::BadCast,
"MueLu::RebalanceBlockTransferFactory::Build: input matrix P or R is not of type BlockedCrsMatrix! error.");
133 RCP<const MapExtractor> rangeMapExtractor = bOriginalTransferOp->getRangeMapExtractor();
134 RCP<const MapExtractor> domainMapExtractor = bOriginalTransferOp->getDomainMapExtractor();
143 bool bThyraRangeGIDs = rangeMapExtractor->getThyraMode();
144 bool bThyraDomainGIDs = domainMapExtractor->getThyraMode();
147 std::vector<GO> fullRangeMapVector;
148 std::vector<GO> fullDomainMapVector;
149 std::vector<RCP<const Map> > subBlockPRangeMaps;
150 std::vector<RCP<const Map> > subBlockPDomainMaps;
151 subBlockPRangeMaps.reserve(bOriginalTransferOp->Rows());
152 subBlockPDomainMaps.reserve(bOriginalTransferOp->Cols());
154 std::vector<Teuchos::RCP<Matrix> > subBlockRebP;
155 subBlockRebP.reserve(bOriginalTransferOp->Rows());
158 Teuchos::RCP<const Import> rebalanceImporter = Teuchos::null;
159 std::vector<Teuchos::RCP<const FactoryManagerBase> >::const_iterator it;
160 for (it = FactManager_.begin(); it != FactManager_.end(); ++it) {
166 rebalanceImporter = coarseLevel.Get<Teuchos::RCP<const Import> >(
"Importer", (*it)->GetFactory(
"Importer").get());
169 Teuchos::RCP<Matrix> Pii = bOriginalTransferOp->getMatrix(curBlockId, curBlockId);
170 Teuchos::RCP<CrsMatrixWrap> Pwii = Teuchos::rcp_dynamic_cast<CrsMatrixWrap>(Pii);
171 TEUCHOS_TEST_FOR_EXCEPTION(Pwii == Teuchos::null,Xpetra::Exceptions::BadCast,
"MueLu::RebalanceBlockTransferFactory::Build: block " << curBlockId <<
" is not of type CrsMatrixWrap. We need an underlying CsrMatrix to replace domain map and importer!");
175 "MueLu::RebalanceBlockInterpolationFactory::Build: inconsistent Thyra GIDs. Thyra global ids for block range " << curBlockId <<
" start with " << Pii->getRowMap()->getMinAllGlobalIndex() <<
" but should start with 0");
178 "MueLu::RebalanceBlockInterpolationFactory::Build: inconsistent Thyra GIDs. Thyra global ids for block domain " << curBlockId <<
" start with " << Pii->getColMap()->getMinAllGlobalIndex() <<
" but should start with 0");
181 if(rebalanceImporter != Teuchos::null) {
182 std::stringstream ss; ss <<
"Rebalancing prolongator block P(" << curBlockId <<
"," << curBlockId <<
")";
196 RCP<const Import> newImporter;
198 SubFactoryMonitor subM(*
this,
"Rebalancing prolongator -- fast map replacement", coarseLevel);
199 newImporter = ImportFactory::Build(rebalanceImporter->getTargetMap(), Pii->getColMap());
200 Pwii->getCrsMatrix()->replaceDomainMapAndImporter(rebalanceImporter->getTargetMap(), newImporter);
203 RCP<ParameterList> params = rcp(
new ParameterList());
204 params->set(
"printLoadBalancingInfo",
true);
205 std::stringstream ss2; ss2 <<
"P(" << curBlockId <<
"," << curBlockId <<
") rebalanced:";
209 subBlockRebP.push_back(Pii);
215 if((*it)->hasFactory(
"Coordinates") ==
true && coarseLevel.IsAvailable(
"Coordinates",(*it)->GetFactory(
"Coordinates").get()) ==
true) {
216 typedef Xpetra::MultiVector<double, LO, GO, NO> xdMV;
217 RCP<xdMV> coords = coarseLevel.Get< RCP<xdMV> >(
"Coordinates",(*it)->GetFactory(
"Coordinates").get());
222 LO nodeNumElts = coords->getMap()->getNodeNumElements();
225 LO myBlkSize = 0, blkSize = 0;
227 if (nodeNumElts > 0) {
230 "MueLu::RebalanceBlockInterpolationFactory::Build: block size. " << rebalanceImporter->getSourceMap()->getNodeNumElements() <<
" not divisable by " << nodeNumElts);
231 myBlkSize = rebalanceImporter->getSourceMap()->getNodeNumElements() / nodeNumElts;
234 MueLu_maxAll(coords->getMap()->getComm(), myBlkSize, blkSize);
236 RCP<const Import> coordImporter = Teuchos::null;
238 coordImporter = rebalanceImporter;
244 RCP<const Map> origMap = coords->getMap();
245 GO indexBase = origMap->getIndexBase();
247 ArrayView<const GO> OEntries = rebalanceImporter->getTargetMap()->getNodeElementList();
248 LO numEntries = OEntries.size()/blkSize;
249 ArrayRCP<GO> Entries(numEntries);
250 for (LO i = 0; i < numEntries; i++)
251 Entries[i] = (OEntries[i*blkSize]-indexBase)/blkSize + indexBase;
253 RCP<const Map> targetMap = MapFactory::Build(origMap->lib(), origMap->getGlobalNumElements(), Entries(), indexBase, origMap->getComm());
254 coordImporter = ImportFactory::Build(origMap, targetMap);
257 RCP<xdMV> permutedCoords = Xpetra::MultiVectorFactory<double,LO,GO,NO>::Build(coordImporter->getTargetMap(), coords->getNumVectors());
258 permutedCoords->doImport(*coords, *coordImporter, Xpetra::INSERT);
260 const ParameterList& pL = GetParameterList();
261 if (pL.isParameter(
"repartition: use subcommunicators") ==
true && pL.get<
bool>(
"repartition: use subcommunicators") ==
true)
262 permutedCoords->replaceMap(permutedCoords->getMap()->removeEmptyProcesses());
264 Set(coarseLevel,
"Coordinates", permutedCoords);
268 RCP<ParameterList> params = rcp(
new ParameterList());
269 params->set(
"printLoadBalancingInfo",
true);
270 std::stringstream ss; ss <<
"P(" << curBlockId <<
"," << curBlockId <<
") not rebalanced:";
273 subBlockRebP.push_back(Pii);
278 if((*it)->hasFactory(
"Coordinates") ==
true && coarseLevel.IsAvailable(
"Coordinates",(*it)->GetFactory(
"Coordinates").get()) ==
true) {
279 typedef Xpetra::MultiVector<double, LO, GO, NO> xdMV;
280 coarseLevel.Set(
"Coordinates", coarseLevel.Get< RCP<xdMV> >(
"Coordinates",(*it)->GetFactory(
"Coordinates").get()),
this);
286 Teuchos::RCP<const StridedMap> orig_stridedRgMap = Teuchos::rcp_dynamic_cast<
const StridedMap>(rangeMapExtractor->getMap(Teuchos::as<size_t>(curBlockId),rangeMapExtractor->getThyraMode()));
287 Teuchos::RCP<const Map> stridedRgMap = Teuchos::null;
288 if(orig_stridedRgMap != Teuchos::null) {
289 std::vector<size_t> stridingData = orig_stridedRgMap->getStridingData();
290 Teuchos::ArrayView< const GlobalOrdinal > nodeRangeMapii = Pii->getRangeMap()->getNodeElementList();
291 stridedRgMap = StridedMapFactory::Build(
292 originalTransferOp->getRangeMap()->lib(),
293 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
295 Pii->getRangeMap()->getIndexBase(),
297 originalTransferOp->getRangeMap()->getComm(),
298 orig_stridedRgMap->getStridedBlockId(),
299 orig_stridedRgMap->getOffset());
300 }
else stridedRgMap = Pii->getRangeMap();
303 Teuchos::RCP<const StridedMap> orig_stridedDoMap = Teuchos::rcp_dynamic_cast<
const StridedMap>(domainMapExtractor->getMap(Teuchos::as<size_t>(curBlockId),domainMapExtractor->getThyraMode()));
305 Teuchos::RCP<const Map> stridedDoMap = Teuchos::null;
306 if(orig_stridedDoMap != Teuchos::null) {
307 std::vector<size_t> stridingData = orig_stridedDoMap->getStridingData();
308 Teuchos::ArrayView< const GlobalOrdinal > nodeDomainMapii = Pii->getDomainMap()->getNodeElementList();
309 stridedDoMap = StridedMapFactory::Build(originalTransferOp->getDomainMap()->lib(),
310 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
312 Pii->getDomainMap()->getIndexBase(),
314 originalTransferOp->getDomainMap()->getComm(),
315 orig_stridedDoMap->getStridedBlockId(),
316 orig_stridedDoMap->getOffset());
317 }
else stridedDoMap = Pii->getDomainMap();
319 TEUCHOS_TEST_FOR_EXCEPTION(stridedRgMap == Teuchos::null,
Exceptions::RuntimeError,
"MueLu::RebalanceBlockInterpolationFactory::Build: failed to generate striding information. error.");
320 TEUCHOS_TEST_FOR_EXCEPTION(stridedDoMap == Teuchos::null,
Exceptions::RuntimeError,
"MueLu::RebalanceBlockInterpolationFactory::Build: failed to generate striding information. error.");
323 if(Pii->IsView(
"stridedMaps")) Pii->RemoveView(
"stridedMaps");
324 Pii->CreateView(
"stridedMaps", stridedRgMap, stridedDoMap);
327 Teuchos::RCP<const Map> rangeMapii = Pii->getRowMap(
"stridedMaps");
328 subBlockPRangeMaps.push_back(rangeMapii);
329 Teuchos::ArrayView< const GlobalOrdinal > nodeRangeMapii = Pii->getRangeMap()->getNodeElementList();
331 fullRangeMapVector.insert(fullRangeMapVector.end(), nodeRangeMapii.begin(), nodeRangeMapii.end());
332 if(bThyraRangeGIDs ==
false)
333 sort(fullRangeMapVector.begin(), fullRangeMapVector.end());
336 Teuchos::RCP<const Map> domainMapii = Pii->getColMap(
"stridedMaps");
337 subBlockPDomainMaps.push_back(domainMapii);
338 Teuchos::ArrayView< const GlobalOrdinal > nodeDomainMapii = Pii->getDomainMap()->getNodeElementList();
340 fullDomainMapVector.insert(fullDomainMapVector.end(), nodeDomainMapii.begin(), nodeDomainMapii.end());
341 if(bThyraDomainGIDs ==
false)
342 sort(fullDomainMapVector.begin(), fullDomainMapVector.end());
349 GO rangeIndexBase = originalTransferOp->getRangeMap()->getIndexBase();
350 GO domainIndexBase= originalTransferOp->getDomainMap()->getIndexBase();
352 RCP<const Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node> > rangePMapExtractor = bOriginalTransferOp->getRangeMapExtractor();
353 Teuchos::ArrayView<GO> fullRangeMapGIDs(fullRangeMapVector.size() ? &fullRangeMapVector[0] : 0,fullRangeMapVector.size());
354 Teuchos::RCP<const StridedMap> stridedRgFullMap = Teuchos::rcp_dynamic_cast<
const StridedMap>(rangePMapExtractor->getFullMap());
355 Teuchos::RCP<const Map > fullRangeMap = Teuchos::null;
356 if(stridedRgFullMap != Teuchos::null) {
357 std::vector<size_t> stridedData = stridedRgFullMap->getStridingData();
359 StridedMapFactory::Build(
360 originalTransferOp->getRangeMap()->lib(),
361 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
365 originalTransferOp->getRangeMap()->getComm(),
366 stridedRgFullMap->getStridedBlockId(),
367 stridedRgFullMap->getOffset());
371 originalTransferOp->getRangeMap()->lib(),
372 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
375 originalTransferOp->getRangeMap()->getComm());
378 RCP<const Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node> > domainAMapExtractor = bOriginalTransferOp->getDomainMapExtractor();
379 Teuchos::ArrayView<GO> fullDomainMapGIDs(fullDomainMapVector.size() ? &fullDomainMapVector[0] : 0,fullDomainMapVector.size());
380 Teuchos::RCP<const StridedMap> stridedDoFullMap = Teuchos::rcp_dynamic_cast<
const StridedMap>(domainAMapExtractor->getFullMap());
381 Teuchos::RCP<const Map > fullDomainMap = Teuchos::null;
382 if(stridedDoFullMap != Teuchos::null) {
383 TEUCHOS_TEST_FOR_EXCEPTION(stridedDoFullMap==Teuchos::null,
Exceptions::BadCast,
"MueLu::BlockedPFactory::Build: full map in domain map extractor has no striding information! error.");
384 std::vector<size_t> stridedData2 = stridedDoFullMap->getStridingData();
386 StridedMapFactory::Build(
387 originalTransferOp->getDomainMap()->lib(),
388 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
392 originalTransferOp->getDomainMap()->getComm(),
393 stridedDoFullMap->getStridedBlockId(),
394 stridedDoFullMap->getOffset());
399 originalTransferOp->getDomainMap()->lib(),
400 Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(),
403 originalTransferOp->getDomainMap()->getComm());
407 Teuchos::RCP<const MapExtractor> rebrangeMapExtractor =
408 MapExtractorFactory::Build(fullRangeMap, subBlockPRangeMaps, bThyraRangeGIDs);
409 Teuchos::RCP<const MapExtractor> rebdomainMapExtractor =
410 MapExtractorFactory::Build(fullDomainMap, subBlockPDomainMaps, bThyraDomainGIDs);
412 Teuchos::RCP<BlockedCrsMatrix> bRebP = Teuchos::rcp(
new BlockedCrsMatrix(rebrangeMapExtractor,rebdomainMapExtractor,10));
413 for(
size_t i = 0; i<subBlockPRangeMaps.size(); i++) {
414 Teuchos::RCP<CrsMatrixWrap> crsOpii = Teuchos::rcp_dynamic_cast<CrsMatrixWrap>(subBlockRebP[i]);
415 TEUCHOS_TEST_FOR_EXCEPTION(crsOpii == Teuchos::null,Xpetra::Exceptions::BadCast,
"MueLu::RebalanceBlockTransferFactory::Build: block P" << i <<
" is not of type CrsMatrixWrap.");
416 bRebP->setMatrix(i,i,crsOpii);
418 bRebP->fillComplete();
420 Set(coarseLevel,
"P", Teuchos::rcp_dynamic_cast<Matrix>(bRebP));
Exception indicating invalid cast attempted.
#define MueLu_maxAll(rcpComm, in, out)
void Build(Level &fineLevel, Level &coarseLevel) const
Build an object with this factory.
Timer to be used in factories. Similar to Monitor but with additional timers.
Namespace for MueLu classes and methods.
Print statistics that do not involve significant additional computation.
Class that holds all level-specific information.
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
static std::string PrintMatrixInfo(const Matrix &A, const std::string &msgTag, RCP< const Teuchos::ParameterList > params=Teuchos::null)
void DeclareInput(Level &fineLevel, Level &coarseLevel) const
Specifies the data that this class needs, and the factories that generate that data.
Exception throws to report errors in the internal logical of the program.
#define MUELU_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
An exception safe way to call the method 'Level::SetFactoryManager()'.
void AddFactoryManager(RCP< const FactoryManagerBase > FactManager)
Add a factory manager.
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()