//! create an explicit copy of a given matrix //! This routine supports blocked and single-block operators static RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > BuildCopy(const RCP<const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> > A) { RCP<const BlockedCrsMatrix> input = Teuchos::rcp_dynamic_cast<const BlockedCrsMatrix>(A); if(input == Teuchos::null) return Xpetra::MatrixFactory2<Scalar,LocalOrdinal,GlobalOrdinal,Node>::BuildCopy(A); // deep copy of MapExtractors (and underlying maps) RCP<const MapExtractor> rgMapExt = Teuchos::rcp(new MapExtractor(*(input->getRangeMapExtractor()))); RCP<const MapExtractor> doMapExt = Teuchos::rcp(new MapExtractor(*(input->getDomainMapExtractor()))); // create new BlockedCrsMatrix object RCP<BlockedCrsMatrix> bop = Teuchos::rcp(new BlockedCrsMatrix(rgMapExt, doMapExt, input->getNodeMaxNumRowEntries())); for (size_t r = 0; r < input->Rows(); ++r) { for (size_t c = 0; c < input->Cols(); ++c) if(input->getMatrix(r,c) != Teuchos::null) { // make a deep copy of the matrix // This is a recursive call to this function RCP<Matrix> mat = Xpetra::MatrixFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::BuildCopy(input->getMatrix(r,c)); bop->setMatrix(r,c,mat); } } if(input->isFillComplete()) bop->fillComplete(); return bop; }
void BlockedGaussSeidelSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Setup(Level ¤tLevel) { //typedef Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> BlockedCrsOMatrix; RCP<Teuchos::FancyOStream> out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout)); FactoryMonitor m(*this, "Setup blocked Gauss-Seidel Smoother", currentLevel); if (SmootherPrototype::IsSetup() == true) this->GetOStream(Warnings0) << "MueLu::BlockedGaussSeidelSmoother::Setup(): Setup() has already been called"; // extract blocked operator A from current level A_ = Factory::Get< RCP<Matrix> >(currentLevel, "A"); // A needed for extracting map extractors RCP<BlockedCrsMatrix> bA = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(A_); TEUCHOS_TEST_FOR_EXCEPTION(bA==Teuchos::null, Exceptions::BadCast, "MueLu::BlockedPFactory::Build: input matrix A is not of type BlockedCrsMatrix! error."); // plausibility check TEUCHOS_TEST_FOR_EXCEPTION(bA->Rows() != FactManager_.size(), Exceptions::RuntimeError, "MueLu::BlockedPFactory::Build: number of block rows of A does not match number of SubFactoryManagers. error."); TEUCHOS_TEST_FOR_EXCEPTION(bA->Cols() != FactManager_.size(), Exceptions::RuntimeError, "MueLu::BlockedPFactory::Build: number of block cols of A does not match number of SubFactoryManagers. error."); // store map extractors rangeMapExtractor_ = bA->getRangeMapExtractor(); domainMapExtractor_ = bA->getDomainMapExtractor(); Teuchos::RCP<Teuchos::FancyOStream> fos = Teuchos::getFancyOStream(Teuchos::rcpFromRef(std::cout)); // loop over all factory managers for the subblocks of blocked operator A size_t bgsOrderingIndex = 0; //std::map<size_t,size_t> bgsOrderingIndex2blockRowIndex; std::vector<Teuchos::RCP<const FactoryManagerBase> >::const_iterator it; for(it = FactManager_.begin(); it!=FactManager_.end(); ++it) { SetFactoryManager currentSFM (rcpFromRef(currentLevel), *it); // extract Smoother for current block row (BGS ordering) RCP<const SmootherBase> Smoo = currentLevel.Get< RCP<SmootherBase> >("PreSmoother",(*it)->GetFactory("Smoother").get()); Inverse_.push_back(Smoo); // extract i-th diagonal block Aii -> determine block /*currentLevel.print(*out, Teuchos::VERB_EXTREME); std::cout << "BGS: need A from factory " << (*it)->GetFactory("A").get() << std::endl; RCP<Matrix> Aii = currentLevel.Get< RCP<Matrix> >("A",(*it)->GetFactory("A").get()); currentLevel.print(*out, Teuchos::VERB_EXTREME); for(size_t i = 0; i<rangeMapExtractor_->NumMaps(); i++) { if(rangeMapExtractor_->getMap(i)->isSameAs(*(Aii->getRangeMap()))) { // map found: i is the true block row index // fill std::map with information bgsOrderingIndex -> i bgsOrderingIndex2blockRowIndex_[bgsOrderingIndex] = i; break; } }*/ bgsOrderingIndex2blockRowIndex_[bgsOrderingIndex] = bgsOrderingIndex; // TODO fix me bgsOrderingIndex++; } SmootherPrototype::IsSetup(true); }
void SubBlockAFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps>::Build(Level & currentLevel) const { typedef Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps> OMatrix; //TODO typedef Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps> CrsMatrixClass; //TODO typedef Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps> CrsMatrixWrapClass; //TODO typedef Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps> BlockedCrsOMatrix; //TODO typedef Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node> MapExtractorClass; const ParameterList & pL = GetParameterList(); size_t row = Teuchos::as<size_t>(pL.get<int>("block row")); size_t col = Teuchos::as<size_t>(pL.get<int>("block col")); RCP<OMatrix> Ain = Teuchos::null; Ain = Get< RCP<OMatrix> >(currentLevel, "A"); RCP<BlockedCrsOMatrix> bA = Teuchos::rcp_dynamic_cast<BlockedCrsOMatrix>(Ain); TEUCHOS_TEST_FOR_EXCEPTION(bA==Teuchos::null, Exceptions::BadCast, "MueLu::SubBlockAFactory::Build: input matrix A is not of type BlockedCrsMatrix! error."); TEUCHOS_TEST_FOR_EXCEPTION(row > bA->Rows(), Exceptions::RuntimeError, "MueLu::SubBlockAFactory::Build: A.Rows() > rows_! error."); TEUCHOS_TEST_FOR_EXCEPTION(col > bA->Cols(), Exceptions::RuntimeError, "MueLu::SubBlockAFactory::Build: A.Cols() > cols_! error."); Teuchos::RCP<CrsMatrixClass> A = bA->getMatrix(row, col); Teuchos::RCP<CrsMatrixWrapClass> Op = Teuchos::rcp(new CrsMatrixWrapClass(A)); //////////////// EXPERIMENTAL // extract striding information from RangeMapExtractor Teuchos::RCP<const MapExtractorClass> rgMapExtractor = bA->getRangeMapExtractor(); Teuchos::RCP<const MapExtractorClass> doMapExtractor = bA->getDomainMapExtractor(); Teuchos::RCP<const Map> rgMap = rgMapExtractor->getMap(row); Teuchos::RCP<const Map> doMap = doMapExtractor->getMap(col); Teuchos::RCP<const StridedMap> srgMap = Teuchos::rcp_dynamic_cast<const StridedMap>(rgMap); Teuchos::RCP<const StridedMap> sdoMap = Teuchos::rcp_dynamic_cast<const StridedMap>(doMap); if(srgMap == Teuchos::null) { Teuchos::RCP<const Map> fullRgMap = rgMapExtractor->getFullMap(); Teuchos::RCP<const StridedMap> sFullRgMap = Teuchos::rcp_dynamic_cast<const StridedMap>(fullRgMap); TEUCHOS_TEST_FOR_EXCEPTION(sFullRgMap==Teuchos::null, Exceptions::BadCast, "MueLu::SubBlockAFactory::Build: full rangeMap is not a strided map"); std::vector<size_t> stridedData = sFullRgMap->getStridingData(); if(stridedData.size() == 1 && row > 0) // we have block matrices. use striding block information 0 srgMap = StridedMapFactory::Build(rgMap, stridedData, 0, sFullRgMap->getOffset()); else // we have strided matrices. use striding information of the corresponding block srgMap = StridedMapFactory::Build(rgMap, stridedData, row, sFullRgMap->getOffset()); } if(sdoMap == Teuchos::null) { Teuchos::RCP<const Map> fullDoMap = doMapExtractor->getFullMap(); Teuchos::RCP<const StridedMap> sFullDoMap = Teuchos::rcp_dynamic_cast<const StridedMap>(fullDoMap); TEUCHOS_TEST_FOR_EXCEPTION(sFullDoMap==Teuchos::null, Exceptions::BadCast, "MueLu::SubBlockAFactory::Build: full domainMap is not a strided map"); std::vector<size_t> stridedData2 = sFullDoMap->getStridingData(); if(stridedData2.size() == 1 && col > 0) // we have block matrices. use striding block information 0 sdoMap = StridedMapFactory::Build(doMap, stridedData2, 0, sFullDoMap->getOffset()); else // we have strided matrices. use striding information of the corresponding block sdoMap = StridedMapFactory::Build(doMap, stridedData2, col, sFullDoMap->getOffset()); } TEUCHOS_TEST_FOR_EXCEPTION(srgMap==Teuchos::null, Exceptions::BadCast, "MueLu::SubBlockAFactory::Build: rangeMap " << row << " is not a strided map"); TEUCHOS_TEST_FOR_EXCEPTION(sdoMap==Teuchos::null, Exceptions::BadCast, "MueLu::SubBlockAFactory::Build: domainMap " << col << " is not a strided map"); GetOStream(Statistics1) << "A(" << row << "," << col << ") has strided maps: range map fixed block size=" << srgMap->getFixedBlockSize() << " strided block id = " << srgMap->getStridedBlockId() << ", domain map fixed block size=" << sdoMap->getFixedBlockSize() << ", strided block id=" << sdoMap->getStridedBlockId() << std::endl; if(Op->IsView("stridedMaps") == true) Op->RemoveView("stridedMaps"); Op->CreateView("stridedMaps", srgMap, sdoMap); TEUCHOS_TEST_FOR_EXCEPTION(Op->IsView("stridedMaps")==false, Exceptions::RuntimeError, "MueLu::SubBlockAFactory::Build: failed to set stridedMaps"); //////////////// EXPERIMENTAL currentLevel.Set("A", Teuchos::rcp_dynamic_cast<OMatrix>(Op), this); }
void BlockedRAPFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(Level &fineLevel, Level &coarseLevel) const { //FIXME make fineLevel const!! FactoryMonitor m(*this, "Computing Ac (block)", coarseLevel); const Teuchos::ParameterList& pL = GetParameterList(); RCP<Matrix> A = Get< RCP<Matrix> >(fineLevel, "A"); RCP<Matrix> P = Get< RCP<Matrix> >(coarseLevel, "P"); RCP<BlockedCrsMatrix> bA = rcp_dynamic_cast<BlockedCrsMatrix>(A); RCP<BlockedCrsMatrix> bP = rcp_dynamic_cast<BlockedCrsMatrix>(P); TEUCHOS_TEST_FOR_EXCEPTION(bA.is_null() || bP.is_null(), Exceptions::BadCast, "Matrices R, A and P must be of type BlockedCrsMatrix."); RCP<BlockedCrsMatrix> bAP; RCP<BlockedCrsMatrix> bAc; { SubFactoryMonitor subM(*this, "MxM: A x P", coarseLevel); // Triple matrix product for BlockedCrsMatrixClass TEUCHOS_TEST_FOR_EXCEPTION((bA->Cols() != bP->Rows()), Exceptions::BadCast, "Block matrix dimensions do not match: " "A is " << bA->Rows() << "x" << bA->Cols() << "P is " << bP->Rows() << "x" << bP->Cols()); bAP = Utils::TwoMatrixMultiplyBlock(*bA, false, *bP, false, GetOStream(Statistics2), true, true); } // If we do not modify matrix later, allow optimization of storage. // This is necessary for new faster Epetra MM kernels. bool doOptimizeStorage = !checkAc_; const bool doTranspose = true; const bool doFillComplete = true; if (pL.get<bool>("transpose: use implicit") == true) { SubFactoryMonitor m2(*this, "MxM: P' x (AP) (implicit)", coarseLevel); bAc = Utils::TwoMatrixMultiplyBlock(*bP, doTranspose, *bAP, !doTranspose, GetOStream(Statistics2), doFillComplete, doOptimizeStorage); } else { RCP<Matrix> R = Get< RCP<Matrix> >(coarseLevel, "R"); RCP<BlockedCrsMatrix> bR = rcp_dynamic_cast<BlockedCrsMatrix>(R); TEUCHOS_TEST_FOR_EXCEPTION(bR.is_null(), Exceptions::BadCast, "Matrix R must be of type BlockedCrsMatrix."); TEUCHOS_TEST_FOR_EXCEPTION(bA->Rows() != bR->Cols(), Exceptions::BadCast, "Block matrix dimensions do not match: " "R is " << bR->Rows() << "x" << bR->Cols() << "A is " << bA->Rows() << "x" << bA->Cols()); SubFactoryMonitor m2(*this, "MxM: R x (AP) (explicit)", coarseLevel); bAc = Utils::TwoMatrixMultiplyBlock(*bR, !doTranspose, *bAP, !doTranspose, GetOStream(Statistics2), doFillComplete, doOptimizeStorage); } if (checkAc_) CheckMainDiagonal(bAc); GetOStream(Statistics1) << PerfUtils::PrintMatrixInfo(*bAc, "Ac (blocked)"); // static int run = 1; // RCP<CrsMatrixWrap> A11 = rcp(new CrsMatrixWrap(bAc->getMatrix(0,0))); // Utils::Write(toString(run) + "_A_11.mm", *A11); // if (!bAc->getMatrix(1,1).is_null()) { // RCP<CrsMatrixWrap> A22 = rcp(new CrsMatrixWrap(bAc->getMatrix(1,1))); // Utils::Write(toString(run) + "_A_22.mm", *A22); // } // RCP<CrsMatrixWrap> Am = rcp(new CrsMatrixWrap(bAc->Merge())); // Utils::Write(toString(run) + "_A.mm", *Am); // run++; Set<RCP <Matrix> >(coarseLevel, "A", bAc); if (transferFacts_.begin() != transferFacts_.end()) { SubFactoryMonitor m1(*this, "Projections", coarseLevel); // call Build of all user-given transfer factories for (std::vector<RCP<const FactoryBase> >::const_iterator it = transferFacts_.begin(); it != transferFacts_.end(); ++it) { RCP<const FactoryBase> fac = *it; GetOStream(Runtime0) << "BlockRAPFactory: call transfer factory: " << fac->description() << std::endl; fac->CallBuild(coarseLevel); // AP (11/11/13): I am not sure exactly why we need to call Release, but we do need it to get rid // of dangling data for CoordinatesTransferFactory coarseLevel.Release(*fac); } } }
void SubBlockAFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(Level& currentLevel) const { FactoryMonitor m(*this, "Build", currentLevel); const ParameterList& pL = GetParameterList(); size_t row = Teuchos::as<size_t>(pL.get<int>("block row")); size_t col = Teuchos::as<size_t>(pL.get<int>("block col")); RCP<Matrix> Ain = currentLevel.Get< RCP<Matrix> >("A",this->GetFactory("A").get()); RCP<BlockedCrsMatrix> A = rcp_dynamic_cast<BlockedCrsMatrix>(Ain); TEUCHOS_TEST_FOR_EXCEPTION(A.is_null(), Exceptions::BadCast, "Input matrix A is not a BlockedCrsMatrix."); TEUCHOS_TEST_FOR_EXCEPTION(row > A->Rows(), Exceptions::RuntimeError, "row [" << row << "] > A.Rows() [" << A->Rows() << "]."); TEUCHOS_TEST_FOR_EXCEPTION(col > A->Cols(), Exceptions::RuntimeError, "col [" << col << "] > A.Cols() [" << A->Cols() << "]."); // get sub-matrix RCP<Matrix> Op = A->getMatrix(row, col); // Check if it is a BlockedCrsMatrix object // If it is a BlockedCrsMatrix object (most likely a ReorderedBlockedCrsMatrix) // we have to distinguish whether it is a 1x1 leaf block in the ReorderedBlockedCrsMatrix // or a nxm block. If it is a 1x1 leaf block, we "unpack" it and return the underlying // CrsMatrixWrap object. RCP<BlockedCrsMatrix> bOp = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Op); if (bOp != Teuchos::null) { // check if it is a 1x1 leaf block if (bOp->Rows() == 1 && bOp->Cols() == 1) { // return the unwrapped CrsMatrixWrap object underneath Op = bOp->getCrsMatrix(); TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::rcp_dynamic_cast<CrsMatrixWrap>(Op) == Teuchos::null, Exceptions::BadCast, "SubBlockAFactory::Build: sub block A[" << row << "," << col << "] must be a single block CrsMatrixWrap object!"); } else { // If it is a regular nxm blocked operator, just return it. // We do not set any kind of striding or blocking information as this // usually would not make sense for general blocked operators GetOStream(Statistics1) << "A(" << row << "," << col << ") is a " << bOp->Rows() << "x" << bOp->Cols() << " block matrix" << std::endl; GetOStream(Statistics2) << "with altogether " << bOp->getGlobalNumRows() << "x" << bOp->getGlobalNumCols() << " rows and columns." << std::endl; currentLevel.Set("A", Op, this); return; } } // The sub-block is not a BlockedCrsMatrix object, that is, we expect // it to be of type CrsMatrixWrap allowing direct access to the corresponding // data. For a single block CrsMatrixWrap type matrix we can/should set the // corresponding striding/blocking information for the algorithms to work // properly // // TAW: In fact, a 1x1 BlockedCrsMatrix object also allows to access the data // directly, but this feature is nowhere really used in the algorithms. // So let's keep checking for the CrsMatrixWrap class to avoid skrewing // things up // TEUCHOS_TEST_FOR_EXCEPTION(Teuchos::rcp_dynamic_cast<CrsMatrixWrap>(Op) == Teuchos::null, Exceptions::BadCast, "SubBlockAFactory::Build: sub block A[" << row << "," << col << "] is NOT a BlockedCrsMatrix but also NOT a CrsMatrixWrap object? This cannot be."); // strided maps for range and domain map of sub matrix RCP<const StridedMap> srangeMap = Teuchos::null; RCP<const StridedMap> sdomainMap = Teuchos::null; // check for user-specified striding information from XML file std::vector<size_t> rangeStridingInfo; std::vector<size_t> domainStridingInfo; LocalOrdinal rangeStridedBlockId = 0; LocalOrdinal domainStridedBlockId = 0; bool bRangeUserSpecified = CheckForUserSpecifiedBlockInfo(true, rangeStridingInfo, rangeStridedBlockId); bool bDomainUserSpecified = CheckForUserSpecifiedBlockInfo(false, domainStridingInfo, domainStridedBlockId); TEUCHOS_TEST_FOR_EXCEPTION(bRangeUserSpecified != bDomainUserSpecified, Exceptions::RuntimeError, "MueLu::SubBlockAFactory[" << row << "," << col << "]: the user has to specify either both domain and range map or none."); // extract map information from MapExtractor RCP<const MapExtractor> rangeMapExtractor = A->getRangeMapExtractor(); RCP<const MapExtractor> domainMapExtractor = A->getDomainMapExtractor(); RCP<const Map> rangeMap = rangeMapExtractor ->getMap(row); RCP<const Map> domainMap = domainMapExtractor->getMap(col); // use user-specified striding information if available. Otherwise try to use internal striding information from the submaps! if(bRangeUserSpecified) srangeMap = Teuchos::rcp(new StridedMap(rangeMap,rangeStridingInfo,rangeMap->getIndexBase(),rangeStridedBlockId,0)); else srangeMap = rcp_dynamic_cast<const StridedMap>(rangeMap); if(bDomainUserSpecified) sdomainMap = Teuchos::rcp(new StridedMap(domainMap,domainStridingInfo,domainMap->getIndexBase(),domainStridedBlockId,0)); else sdomainMap = rcp_dynamic_cast<const StridedMap>(domainMap); // In case that both user-specified and internal striding information from the submaps // does not contain valid striding information, try to extract it from the global maps // in the map extractor. if (srangeMap.is_null()) { RCP<const Map> fullRangeMap = rangeMapExtractor->getFullMap(); RCP<const StridedMap> sFullRangeMap = rcp_dynamic_cast<const StridedMap>(fullRangeMap); TEUCHOS_TEST_FOR_EXCEPTION(sFullRangeMap.is_null(), Exceptions::BadCast, "Full rangeMap is not a strided map."); std::vector<size_t> stridedData = sFullRangeMap->getStridingData(); if (stridedData.size() == 1 && row > 0) { // We have block matrices. use striding block information 0 srangeMap = StridedMapFactory::Build(rangeMap, stridedData, 0, sFullRangeMap->getOffset()); } else { // We have strided matrices. use striding information of the corresponding block srangeMap = StridedMapFactory::Build(rangeMap, stridedData, row, sFullRangeMap->getOffset()); } } if (sdomainMap.is_null()) { RCP<const Map> fullDomainMap = domainMapExtractor->getFullMap(); RCP<const StridedMap> sFullDomainMap = rcp_dynamic_cast<const StridedMap>(fullDomainMap); TEUCHOS_TEST_FOR_EXCEPTION(sFullDomainMap.is_null(), Exceptions::BadCast, "Full domainMap is not a strided map"); std::vector<size_t> stridedData = sFullDomainMap->getStridingData(); if (stridedData.size() == 1 && col > 0) { // We have block matrices. use striding block information 0 sdomainMap = StridedMapFactory::Build(domainMap, stridedData, 0, sFullDomainMap->getOffset()); } else { // We have strided matrices. use striding information of the corresponding block sdomainMap = StridedMapFactory::Build(domainMap, stridedData, col, sFullDomainMap->getOffset()); } } TEUCHOS_TEST_FOR_EXCEPTION(srangeMap.is_null(), Exceptions::BadCast, "rangeMap " << row << " is not a strided map."); TEUCHOS_TEST_FOR_EXCEPTION(sdomainMap.is_null(), Exceptions::BadCast, "domainMap " << col << " is not a strided map."); GetOStream(Statistics1) << "A(" << row << "," << col << ") is a single block and has strided maps:" << "\n range map fixed block size = " << srangeMap ->getFixedBlockSize() << ", strided block id = " << srangeMap ->getStridedBlockId() << "\n domain map fixed block size = " << sdomainMap->getFixedBlockSize() << ", strided block id = " << sdomainMap->getStridedBlockId() << std::endl; GetOStream(Statistics2) << "A(" << row << "," << col << ") has " << Op->getGlobalNumRows() << "x" << Op->getGlobalNumCols() << " rows and columns." << std::endl; // TODO do we really need that? we moved the code to getMatrix... if (Op->IsView("stridedMaps") == true) Op->RemoveView("stridedMaps"); Op->CreateView("stridedMaps", srangeMap, sdomainMap); TEUCHOS_TEST_FOR_EXCEPTION(Op->IsView("stridedMaps") == false, Exceptions::RuntimeError, "Failed to set \"stridedMaps\" view."); currentLevel.Set("A", Op, this); }
void BlockedPFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps>::Build(Level& fineLevel, Level &coarseLevel) const { typedef Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps> MatrixClass; typedef Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps> CrsMatrixClass; typedef Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps> CrsMatrixWrapClass; typedef Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps> BlockedCrsOMatrix; typedef Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node> MapClass; typedef Xpetra::MapFactory<LocalOrdinal, GlobalOrdinal, Node> MapFactoryClass; typedef Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node> MapExtractorClass; typedef Xpetra::MapExtractorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node> MapExtractorFactoryClass; //Teuchos::RCP<Teuchos::FancyOStream> fos = Teuchos::getFancyOStream(Teuchos::rcpFromRef(std::cout)); //std::ostringstream buf; buf << coarseLevel.GetLevelID(); // Level Get //RCP<Matrix> A = fineLevel. Get< RCP<Matrix> >("A", AFact_.get()); // IMPORTANT: use main factory manager for getting A RCP<Matrix> A = Get< RCP<Matrix> >(fineLevel, "A"); RCP<BlockedCrsOMatrix> bA = Teuchos::rcp_dynamic_cast<BlockedCrsOMatrix>(A); TEUCHOS_TEST_FOR_EXCEPTION(bA==Teuchos::null, Exceptions::BadCast, "MueLu::BlockedPFactory::Build: input matrix A is not of type BlockedCrsMatrix! error."); // plausibility check TEUCHOS_TEST_FOR_EXCEPTION(bA->Rows() != FactManager_.size(), Exceptions::RuntimeError, "MueLu::BlockedPFactory::Build: number of block rows of A does not match number of SubFactoryManagers. error."); TEUCHOS_TEST_FOR_EXCEPTION(bA->Cols() != FactManager_.size(), Exceptions::RuntimeError, "MueLu::BlockedPFactory::Build: number of block cols of A does not match number of SubFactoryManagers. error."); // build blocked prolongator std::vector<RCP<Matrix> > subBlockP; std::vector<RCP<const MapClass> > subBlockPRangeMaps; std::vector<RCP<const MapClass > > subBlockPDomainMaps; std::vector<GO> fullRangeMapVector; std::vector<GO> fullDomainMapVector; subBlockP.reserve(FactManager_.size()); // reserve size for block P operators subBlockPRangeMaps.reserve(FactManager_.size()); // reserve size for block P operators subBlockPDomainMaps.reserve(FactManager_.size()); // reserve size for block P operators // build and store the subblocks and the corresponding range and domain maps // since we put together the full range and domain map from the submaps we do not have // to use the maps from blocked A std::vector<Teuchos::RCP<const FactoryManagerBase> >::const_iterator it; for(it = FactManager_.begin(); it!=FactManager_.end(); ++it) { SetFactoryManager fineSFM (rcpFromRef(fineLevel), *it); SetFactoryManager coarseSFM(rcpFromRef(coarseLevel), *it); if(!restrictionMode_) { subBlockP.push_back(coarseLevel.Get<RCP<Matrix> >("P", (*it)->GetFactory("P").get())); // create and return block P operator } else { subBlockP.push_back(coarseLevel.Get<RCP<Matrix> >("R", (*it)->GetFactory("R").get())); // create and return block R operator } // check if prolongator/restrictor operators have strided maps TEUCHOS_TEST_FOR_EXCEPTION(subBlockP.back()->IsView("stridedMaps")==false, Exceptions::BadCast, "MueLu::BlockedPFactory::Build: subBlock P operator has no strided map information. error."); // append strided row map (= range map) to list of range maps. Teuchos::RCP<const Map> rangeMap = subBlockP.back()->getRowMap("stridedMaps"); /* getRangeMap(); //*/ subBlockPRangeMaps.push_back(rangeMap); // use plain range map to determine the DOF ids Teuchos::ArrayView< const GlobalOrdinal > nodeRangeMap = subBlockP.back()->getRangeMap()->getNodeElementList(); //subBlockPRangeMaps.back()->getNodeElementList(); fullRangeMapVector.insert(fullRangeMapVector.end(), nodeRangeMap.begin(), nodeRangeMap.end()); sort(fullRangeMapVector.begin(), fullRangeMapVector.end()); // append strided col map (= domain map) to list of range maps. Teuchos::RCP<const Map> domainMap = subBlockP.back()->getColMap("stridedMaps"); /* getDomainMap(); //*/ subBlockPDomainMaps.push_back(domainMap); // use plain domain map to determine the DOF ids Teuchos::ArrayView< const GlobalOrdinal > nodeDomainMap = subBlockP.back()->getDomainMap()->getNodeElementList(); //subBlockPDomainMaps.back()->getNodeElementList(); fullDomainMapVector.insert(fullDomainMapVector.end(), nodeDomainMap.begin(), nodeDomainMap.end()); sort(fullDomainMapVector.begin(), fullDomainMapVector.end()); } // extract map index base from maps of blocked A GO rangeIndexBase = 0; GO domainIndexBase = 0; if(!restrictionMode_) { // prolongation mode: just use index base of range and domain map of bA rangeIndexBase = bA->getRangeMap()->getIndexBase(); domainIndexBase= bA->getDomainMap()->getIndexBase(); } else { // restriction mode: switch range and domain map for blocked restriction operator rangeIndexBase = bA->getDomainMap()->getIndexBase(); domainIndexBase= bA->getRangeMap()->getIndexBase(); } // build full range map. // If original range map has striding information, then transfer it to the new range map RCP<const MapExtractorClass> rangeAMapExtractor = bA->getRangeMapExtractor(); Teuchos::ArrayView<GO> fullRangeMapGIDs(&fullRangeMapVector[0],fullRangeMapVector.size()); Teuchos::RCP<const StridedMap> stridedRgFullMap = Teuchos::rcp_dynamic_cast<const StridedMap>(rangeAMapExtractor->getFullMap()); Teuchos::RCP<const Map > fullRangeMap = Teuchos::null; if(stridedRgFullMap != Teuchos::null) { std::vector<size_t> stridedData = stridedRgFullMap->getStridingData(); fullRangeMap = StridedMapFactory::Build( bA->getRangeMap()->lib(), Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(), fullRangeMapGIDs, rangeIndexBase, stridedData, bA->getRangeMap()->getComm(), stridedRgFullMap->getStridedBlockId(), stridedRgFullMap->getOffset()); } else { fullRangeMap = MapFactory::Build( bA->getRangeMap()->lib(), Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(), fullRangeMapGIDs, rangeIndexBase, bA->getRangeMap()->getComm()); } RCP<const MapExtractorClass> domainAMapExtractor = bA->getDomainMapExtractor(); Teuchos::ArrayView<GO> fullDomainMapGIDs(&fullDomainMapVector[0],fullDomainMapVector.size()); Teuchos::RCP<const StridedMap> stridedDoFullMap = Teuchos::rcp_dynamic_cast<const StridedMap>(domainAMapExtractor->getFullMap()); Teuchos::RCP<const Map > fullDomainMap = Teuchos::null; if(stridedDoFullMap != Teuchos::null) { TEUCHOS_TEST_FOR_EXCEPTION(stridedDoFullMap==Teuchos::null, Exceptions::BadCast, "MueLu::BlockedPFactory::Build: full map in domain map extractor has no striding information! error."); std::vector<size_t> stridedData2 = stridedDoFullMap->getStridingData(); fullDomainMap = StridedMapFactory::Build( bA->getDomainMap()->lib(), Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(), fullDomainMapGIDs, domainIndexBase, stridedData2, bA->getDomainMap()->getComm(), stridedDoFullMap->getStridedBlockId(), stridedDoFullMap->getOffset()); } else { fullDomainMap = MapFactory::Build( bA->getDomainMap()->lib(), Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(), fullDomainMapGIDs, domainIndexBase, bA->getDomainMap()->getComm()); } // build map extractors Teuchos::RCP<const MapExtractorClass> rangeMapExtractor = MapExtractorFactoryClass::Build(fullRangeMap, subBlockPRangeMaps); Teuchos::RCP<const MapExtractorClass> domainMapExtractor = MapExtractorFactoryClass::Build(fullDomainMap, subBlockPDomainMaps); Teuchos::RCP<BlockedCrsOMatrix> bP = Teuchos::rcp(new BlockedCrsOMatrix(rangeMapExtractor,domainMapExtractor,10)); for(size_t i = 0; i<subBlockPRangeMaps.size(); i++) { Teuchos::RCP<CrsMatrixWrapClass> crsOpii = Teuchos::rcp_dynamic_cast<CrsMatrixWrapClass>(subBlockP[i]); Teuchos::RCP<CrsMatrixClass> crsMatii = crsOpii->getCrsMatrix(); bP->setMatrix(i,i,crsMatii); } bP->fillComplete(); //bP->describe(*fos,Teuchos::VERB_EXTREME); // Level Set if(!restrictionMode_) { // prolongation factory is in prolongation mode coarseLevel.Set("P", Teuchos::rcp_dynamic_cast<MatrixClass>(bP), this); } else { // prolongation factory is in restriction mode // we do not have to transpose the blocked R operator since the subblocks on the diagonal // are already valid R subblocks coarseLevel.Set("R", Teuchos::rcp_dynamic_cast<MatrixClass>(bP), this); } }
void SubBlockAFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(Level& currentLevel) const { const ParameterList& pL = GetParameterList(); size_t row = Teuchos::as<size_t>(pL.get<int>("block row")); size_t col = Teuchos::as<size_t>(pL.get<int>("block col")); RCP<Matrix> Ain = Get<RCP<Matrix> >(currentLevel, "A"); RCP<BlockedCrsMatrix> A = rcp_dynamic_cast<BlockedCrsMatrix>(Ain); TEUCHOS_TEST_FOR_EXCEPTION(A.is_null(), Exceptions::BadCast, "Input matrix A is not a BlockedCrsMatrix."); TEUCHOS_TEST_FOR_EXCEPTION(row > A->Rows(), Exceptions::RuntimeError, "row [" << row << "] > A.Rows() [" << A->Rows() << "]."); TEUCHOS_TEST_FOR_EXCEPTION(col > A->Cols(), Exceptions::RuntimeError, "col [" << col << "] > A.Cols() [" << A->Cols() << "]."); RCP<CrsMatrixWrap> Op = Teuchos::rcp(new CrsMatrixWrap(A->getMatrix(row, col))); //////////////// EXPERIMENTAL // extract striding information from RangeMapExtractor RCP<const MapExtractor> rangeMapExtractor = A->getRangeMapExtractor(); RCP<const MapExtractor> domainMapExtractor = A->getDomainMapExtractor(); RCP<const Map> rangeMap = rangeMapExtractor ->getMap(row); RCP<const Map> domainMap = domainMapExtractor->getMap(col); RCP<const StridedMap> srangeMap = rcp_dynamic_cast<const StridedMap>(rangeMap); RCP<const StridedMap> sdomainMap = rcp_dynamic_cast<const StridedMap>(domainMap); if (srangeMap.is_null()) { RCP<const Map> fullRangeMap = rangeMapExtractor->getFullMap(); RCP<const StridedMap> sFullRangeMap = rcp_dynamic_cast<const StridedMap>(fullRangeMap); TEUCHOS_TEST_FOR_EXCEPTION(sFullRangeMap.is_null(), Exceptions::BadCast, "Full rangeMap is not a strided map."); std::vector<size_t> stridedData = sFullRangeMap->getStridingData(); if (stridedData.size() == 1 && row > 0) { // We have block matrices. use striding block information 0 srangeMap = StridedMapFactory::Build(rangeMap, stridedData, 0, sFullRangeMap->getOffset()); } else { // We have strided matrices. use striding information of the corresponding block srangeMap = StridedMapFactory::Build(rangeMap, stridedData, row, sFullRangeMap->getOffset()); } } if (sdomainMap.is_null()) { RCP<const Map> fullDomainMap = domainMapExtractor->getFullMap(); RCP<const StridedMap> sFullDomainMap = rcp_dynamic_cast<const StridedMap>(fullDomainMap); TEUCHOS_TEST_FOR_EXCEPTION(sFullDomainMap.is_null(), Exceptions::BadCast, "Full domainMap is not a strided map"); std::vector<size_t> stridedData = sFullDomainMap->getStridingData(); if (stridedData.size() == 1 && col > 0) { // We have block matrices. use striding block information 0 sdomainMap = StridedMapFactory::Build(domainMap, stridedData, 0, sFullDomainMap->getOffset()); } else { // We have strided matrices. use striding information of the corresponding block sdomainMap = StridedMapFactory::Build(domainMap, stridedData, col, sFullDomainMap->getOffset()); } } TEUCHOS_TEST_FOR_EXCEPTION(srangeMap.is_null(), Exceptions::BadCast, "rangeMap " << row << " is not a strided map."); TEUCHOS_TEST_FOR_EXCEPTION(sdomainMap.is_null(), Exceptions::BadCast, "domainMap " << col << " is not a strided map."); GetOStream(Statistics1) << "A(" << row << "," << col << ") has strided maps:" << "\n range map fixed block size = " << srangeMap ->getFixedBlockSize() << ", strided block id = " << srangeMap ->getStridedBlockId() << "\n domain map fixed block size = " << sdomainMap->getFixedBlockSize() << ", strided block id = " << sdomainMap->getStridedBlockId() << std::endl; if (Op->IsView("stridedMaps") == true) Op->RemoveView("stridedMaps"); Op->CreateView("stridedMaps", srangeMap, sdomainMap); TEUCHOS_TEST_FOR_EXCEPTION(Op->IsView("stridedMaps") == false, Exceptions::RuntimeError, "Failed to set \"stridedMaps\" view."); //////////////// EXPERIMENTAL currentLevel.Set("A", rcp_dynamic_cast<Matrix>(Op), this); }
void SimpleSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Apply(MultiVector& X, const MultiVector& B, bool InitialGuessIsZero) const { TEUCHOS_TEST_FOR_EXCEPTION(SmootherPrototype::IsSetup() == false, Exceptions::RuntimeError, "MueLu::SimpleSmoother::Apply(): Setup() has not been called"); #ifdef HAVE_MUELU_DEBUG TEUCHOS_TEST_FOR_EXCEPTION(A_->getRangeMap()->isSameAs(*(B.getMap())) == false, Exceptions::RuntimeError, "MueLu::SimpleSmoother::Apply(): The map of RHS vector B is not the same as range map of the blocked operator A. Please check the map of B and A."); TEUCHOS_TEST_FOR_EXCEPTION(A_->getDomainMap()->isSameAs(*(X.getMap())) == false, Exceptions::RuntimeError, "MueLu::SimpleSmoother::Apply(): The map of the solution vector X is not the same as domain map of the blocked operator A. Please check the map of X and A."); #endif Teuchos::RCP<Teuchos::FancyOStream> fos = Teuchos::getFancyOStream(Teuchos::rcpFromRef(std::cout)); SC zero = Teuchos::ScalarTraits<SC>::zero(), one = Teuchos::ScalarTraits<SC>::one(); // extract parameters from internal parameter list const ParameterList & pL = Factory::GetParameterList(); LocalOrdinal nSweeps = pL.get<LocalOrdinal>("Sweeps"); Scalar omega = pL.get<Scalar>("Damping factor"); // The boolean flags check whether we use Thyra or Xpetra style GIDs // However, assuming that SIMPLE always only works for 2x2 blocked operators, we // most often have to use the ReorderedBlockedCrsOperator as input. If either the // F or Z (or SchurComplement block S) are 1x1 blocked operators with Thyra style // GIDs we need an extra transformation of vectors // In this case, we use the Xpetra (offset) GIDs for all operations and only transform // the input/output vectors before and after the subsolver calls! bool bRangeThyraModePredict = rangeMapExtractor_->getThyraMode() && (Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(F_) == Teuchos::null); bool bDomainThyraModePredict = domainMapExtractor_->getThyraMode() && (Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(F_) == Teuchos::null); bool bRangeThyraModeSchur = rangeMapExtractor_->getThyraMode() && (Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Z_) == Teuchos::null); bool bDomainThyraModeSchur = domainMapExtractor_->getThyraMode() && (Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Z_) == Teuchos::null); // The following boolean flags catch the case where we need special transformation // for the GIDs when calling the subsmoothers. RCP<BlockedCrsMatrix> bF = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(F_); RCP<BlockedCrsMatrix> bZ = Teuchos::rcp_dynamic_cast<BlockedCrsMatrix>(Z_); bool bFThyraSpecialTreatment = false; bool bZThyraSpecialTreatment = false; if (bF != Teuchos::null) { if(bF->Rows() == 1 && bF->Cols() == 1 && rangeMapExtractor_->getThyraMode() == true) bFThyraSpecialTreatment = true; } if (bZ != Teuchos::null) { if(bZ->Rows() == 1 && bZ->Cols() == 1 && rangeMapExtractor_->getThyraMode() == true) bZThyraSpecialTreatment = true; } #if 1// new implementation // create a new vector for storing the current residual in a blocked multi vector RCP<MultiVector> res = MultiVectorFactory::Build(B.getMap(), B.getNumVectors()); RCP<BlockedMultiVector> residual = Teuchos::rcp(new BlockedMultiVector(rangeMapExtractor_,res)); // create a new solution vector as a blocked multi vector RCP<MultiVector> rcpX = Teuchos::rcpFromRef(X); RCP<BlockedMultiVector> bX = Teuchos::rcp(new BlockedMultiVector(domainMapExtractor_,rcpX)); // create a blocked rhs vector RCP<const MultiVector> rcpB = Teuchos::rcpFromRef(B); RCP<const BlockedMultiVector> bB = Teuchos::rcp(new const BlockedMultiVector(rangeMapExtractor_,rcpB)); // incrementally improve solution vector X for (LocalOrdinal run = 0; run < nSweeps; ++run) { // 1) calculate current residual residual->update(one,*bB,zero); // r = B A_->apply(*bX, *residual, Teuchos::NO_TRANS, -one, one); // split residual vector Teuchos::RCP<MultiVector> r1 = rangeMapExtractor_->ExtractVector(residual, 0, bRangeThyraModePredict); Teuchos::RCP<MultiVector> r2 = rangeMapExtractor_->ExtractVector(residual, 1, bRangeThyraModeSchur); // 2) solve F * \Delta \tilde{x}_1 = r_1 // start with zero guess \Delta \tilde{x}_1 RCP<MultiVector> xtilde1 = domainMapExtractor_->getVector(0, X.getNumVectors(), bDomainThyraModePredict); xtilde1->putScalar(zero); if(bFThyraSpecialTreatment == true) { xtilde1->replaceMap(domainMapExtractor_->getMap(0,true)); r1->replaceMap(rangeMapExtractor_->getMap(0,true)); velPredictSmoo_->Apply(*xtilde1,*r1); xtilde1->replaceMap(domainMapExtractor_->getMap(0,false)); } else { velPredictSmoo_->Apply(*xtilde1,*r1); } // 3) calculate rhs for SchurComp equation // r_2 - D \Delta \tilde{x}_1 RCP<MultiVector> schurCompRHS = rangeMapExtractor_->getVector(1, B.getNumVectors(), bRangeThyraModeSchur); D_->apply(*xtilde1,*schurCompRHS); schurCompRHS->update(one,*r2,-one); // 4) solve SchurComp equation // start with zero guess \Delta \tilde{x}_2 RCP<MultiVector> xtilde2 = domainMapExtractor_->getVector(1, X.getNumVectors(), bDomainThyraModeSchur); xtilde2->putScalar(zero); // Special handling if SchurComplement operator was a 1x1 blocked operator in Thyra mode // Then, we have to translate the Xpetra offset GIDs to plain Thyra GIDs and vice versa if(bZThyraSpecialTreatment == true) { xtilde2->replaceMap(domainMapExtractor_->getMap(1,true)); schurCompRHS->replaceMap(rangeMapExtractor_->getMap(1,true)); schurCompSmoo_->Apply(*xtilde2,*schurCompRHS); xtilde2->replaceMap(domainMapExtractor_->getMap(1,false)); } else { schurCompSmoo_->Apply(*xtilde2,*schurCompRHS); } // 5) scale xtilde2 with omega // store this in xhat2 RCP<MultiVector> xhat2 = domainMapExtractor_->getVector(1, X.getNumVectors(), bDomainThyraModeSchur); xhat2->update(omega,*xtilde2,zero); // 6) calculate xhat1 RCP<MultiVector> xhat1 = domainMapExtractor_->getVector(0, X.getNumVectors(), bDomainThyraModePredict); RCP<MultiVector> xhat1_temp = domainMapExtractor_->getVector(0, X.getNumVectors(), bDomainThyraModePredict); G_->apply(*xhat2,*xhat1_temp); // store result temporarely in xtilde1_temp xhat1->elementWiseMultiply(one/*/omega*/,*diagFinv_,*xhat1_temp,zero); xhat1->update(one,*xtilde1,-one); // 7) extract parts of solution vector X Teuchos::RCP<MultiVector> x1 = domainMapExtractor_->ExtractVector(bX, 0, bDomainThyraModePredict); Teuchos::RCP<MultiVector> x2 = domainMapExtractor_->ExtractVector(bX, 1, bDomainThyraModeSchur); // 8) update solution vector with increments xhat1 and xhat2 // rescale increment for x2 with omega_ x1->update(one,*xhat1,one); // x1 = x1_old + xhat1 x2->update(/*omega*/ one,*xhat2,one); // x2 = x2_old + omega xhat2 // write back solution in global vector X domainMapExtractor_->InsertVector(x1, 0, bX, bDomainThyraModePredict); domainMapExtractor_->InsertVector(x2, 1, bX, bDomainThyraModeSchur); } // write back solution domainMapExtractor_->InsertVector(bX->getMultiVector(0,bDomainThyraModePredict), 0, rcpX, bDomainThyraModePredict); domainMapExtractor_->InsertVector(bX->getMultiVector(1,bDomainThyraModeSchur), 1, rcpX, bDomainThyraModeSchur); #else // wrap current solution vector in RCP RCP<MultiVector> rcpX = Teuchos::rcpFromRef(X); // create residual vector // contains current residual of current solution X with rhs B RCP<MultiVector> residual = MultiVectorFactory::Build(B.getMap(), B.getNumVectors()); // incrementally improve solution vector X for (LocalOrdinal run = 0; run < nSweeps; ++run) { // 1) calculate current residual residual->update(one,B,zero); // residual = B A_->apply(*rcpX, *residual, Teuchos::NO_TRANS, -one, one); // split residual vector Teuchos::RCP<MultiVector> r1 = rangeMapExtractor_->ExtractVector(residual, 0, bRangeThyraModePredict); Teuchos::RCP<MultiVector> r2 = rangeMapExtractor_->ExtractVector(residual, 1, bRangeThyraModeSchur); // 2) solve F * \Delta \tilde{x}_1 = r_1 // start with zero guess \Delta \tilde{x}_1 RCP<MultiVector> xtilde1 = domainMapExtractor_->getVector(0, X.getNumVectors(), bDomainThyraModePredict); xtilde1->putScalar(zero); // Special handling in case that F block is a 1x1 blocked operator in Thyra mode // Then we have to feed the smoother with real Thyra-based vectors if(bFThyraSpecialTreatment == true) { // create empty solution vector based on Thyra GIDs RCP<MultiVector> xtilde1_thyra = domainMapExtractor_->getVector(0, X.getNumVectors(), true); // create new RHS vector based on Thyra GIDs Teuchos::RCP<MultiVector> r1_thyra = rangeMapExtractor_->ExtractVector(residual, 0, true); velPredictSmoo_->Apply(*xtilde1_thyra,*r1_thyra); for(size_t k=0; k < xtilde1_thyra->getNumVectors(); k++) { Teuchos::ArrayRCP<Scalar> xpetraVecData = xtilde1->getDataNonConst(k); Teuchos::ArrayRCP<const Scalar> thyraVecData = xtilde1_thyra->getData(k); for(size_t i=0; i < xtilde1_thyra->getLocalLength(); i++) { xpetraVecData[i] = thyraVecData[i]; } } } else { velPredictSmoo_->Apply(*xtilde1,*r1); } // 3) calculate rhs for SchurComp equation // r_2 - D \Delta \tilde{x}_1 RCP<MultiVector> schurCompRHS = rangeMapExtractor_->getVector(1, B.getNumVectors(), bRangeThyraModeSchur); D_->apply(*xtilde1,*schurCompRHS); schurCompRHS->update(one,*r2,-one); // 4) solve SchurComp equation // start with zero guess \Delta \tilde{x}_2 RCP<MultiVector> xtilde2 = domainMapExtractor_->getVector(1, X.getNumVectors(), bDomainThyraModeSchur); xtilde2->putScalar(zero); // Special handling if SchurComplement operator was a 1x1 blocked operator in Thyra mode // Then, we have to translate the Xpetra offset GIDs to plain Thyra GIDs and vice versa if(bZThyraSpecialTreatment == true) { // create empty solution vector based on Thyra GIDs RCP<MultiVector> xtilde2_thyra = domainMapExtractor_->getVector(1, X.getNumVectors(), true); // create new RHS vector based on Thyra GIDs RCP<MultiVector> schurCompRHS_thyra = rangeMapExtractor_->getVector(1, B.getNumVectors(), true); // transform vector for(size_t k=0; k < schurCompRHS->getNumVectors(); k++) { Teuchos::ArrayRCP<const Scalar> xpetraVecData = schurCompRHS->getData(k); Teuchos::ArrayRCP<Scalar> thyraVecData = schurCompRHS_thyra->getDataNonConst(k); for(size_t i=0; i < schurCompRHS->getLocalLength(); i++) { thyraVecData[i] = xpetraVecData[i]; } } schurCompSmoo_->Apply(*xtilde2_thyra,*schurCompRHS_thyra); for(size_t k=0; k < xtilde2_thyra->getNumVectors(); k++) { Teuchos::ArrayRCP<Scalar> xpetraVecData = xtilde2->getDataNonConst(k); Teuchos::ArrayRCP<const Scalar> thyraVecData = xtilde2_thyra->getData(k); for(size_t i=0; i < xtilde2_thyra->getLocalLength(); i++) { xpetraVecData[i] = thyraVecData[i]; } } } else { schurCompSmoo_->Apply(*xtilde2,*schurCompRHS); } // 5) scale xtilde2 with omega // store this in xhat2 RCP<MultiVector> xhat2 = domainMapExtractor_->getVector(1, X.getNumVectors(), bDomainThyraModeSchur); xhat2->update(omega,*xtilde2,zero); // 6) calculate xhat1 RCP<MultiVector> xhat1 = domainMapExtractor_->getVector(0, X.getNumVectors(), bDomainThyraModePredict); RCP<MultiVector> xhat1_temp = domainMapExtractor_->getVector(0, X.getNumVectors(), bDomainThyraModePredict); G_->apply(*xhat2,*xhat1_temp); // store result temporarely in xtilde1_temp xhat1->elementWiseMultiply(one/*/omega*/,*diagFinv_,*xhat1_temp,zero); xhat1->update(one,*xtilde1,-one); // 7) extract parts of solution vector X Teuchos::RCP<MultiVector> x1 = domainMapExtractor_->ExtractVector(rcpX, 0, bDomainThyraModePredict); Teuchos::RCP<MultiVector> x2 = domainMapExtractor_->ExtractVector(rcpX, 1, bDomainThyraModeSchur); // 8) update solution vector with increments xhat1 and xhat2 // rescale increment for x2 with omega_ x1->update(one,*xhat1,one); // x1 = x1_old + xhat1 x2->update(/*omega*/ one,*xhat2,one); // x2 = x2_old + omega xhat2 // write back solution in global vector X domainMapExtractor_->InsertVector(x1, 0, rcpX, bDomainThyraModePredict); domainMapExtractor_->InsertVector(x2, 1, rcpX, bDomainThyraModeSchur); } #endif }
void RebalanceBlockRestrictionFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps>::Build(Level &fineLevel, Level &coarseLevel) const { FactoryMonitor m(*this, "Build", coarseLevel); //const Teuchos::ParameterList & pL = GetParameterList(); RCP<Teuchos::FancyOStream> out = Teuchos::fancyOStream(Teuchos::rcpFromRef(std::cout)); Teuchos::RCP<Matrix> originalTransferOp = Teuchos::null; originalTransferOp = Get< RCP<Matrix> >(coarseLevel, "R"); RCP<Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps> > bOriginalTransferOp = Teuchos::rcp_dynamic_cast<Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps> >(originalTransferOp); TEUCHOS_TEST_FOR_EXCEPTION(bOriginalTransferOp==Teuchos::null, Exceptions::BadCast, "MueLu::RebalanceBlockTransferFactory::Build: input matrix P or R is not of type BlockedCrsMatrix! error."); // plausibility check TEUCHOS_TEST_FOR_EXCEPTION(bOriginalTransferOp->Rows() != 2,Exceptions::RuntimeError, "MueLu::RebalanceBlockTransferFactory::Build: number of block rows of transfer operator is not equal 2. error."); TEUCHOS_TEST_FOR_EXCEPTION(bOriginalTransferOp->Cols() != 2,Exceptions::RuntimeError, "MueLu::RebalanceBlockTransferFactory::Build: number of block columns of transfer operator is not equal 2. error."); // rebuild rebalanced blocked P operator std::vector<GO> fullRangeMapVector; std::vector<GO> fullDomainMapVector; std::vector<RCP<const Map> > subBlockRRangeMaps; std::vector<RCP<const Map> > subBlockRDomainMaps; subBlockRRangeMaps.reserve(bOriginalTransferOp->Rows()); // reserve size for block P operators subBlockRDomainMaps.reserve(bOriginalTransferOp->Cols()); // reserve size for block P operators std::vector<Teuchos::RCP<Matrix> > subBlockRebR; subBlockRebR.reserve(bOriginalTransferOp->Cols()); int curBlockId = 0; Teuchos::RCP<const Import> rebalanceImporter = Teuchos::null; std::vector<Teuchos::RCP<const FactoryManagerBase> >::const_iterator it; for (it = FactManager_.begin(); it != FactManager_.end(); ++it) { // begin SubFactoryManager environment SetFactoryManager fineSFM (rcpFromRef(fineLevel), *it); SetFactoryManager coarseSFM(rcpFromRef(coarseLevel), *it); rebalanceImporter = coarseLevel.Get<Teuchos::RCP<const Import> >("Importer", (*it)->GetFactory("Importer").get()); // extract matrix block Teuchos::RCP<CrsMatrix> Rmii = bOriginalTransferOp->getMatrix(curBlockId, curBlockId); Teuchos::RCP<CrsMatrixWrap> Rwii = Teuchos::rcp(new CrsMatrixWrap(Rmii)); Teuchos::RCP<Matrix> Rii = Teuchos::rcp_dynamic_cast<Matrix>(Rwii); Teuchos::RCP<Matrix> rebRii; if(rebalanceImporter != Teuchos::null) { std::stringstream ss; ss << "Rebalancing restriction block R(" << curBlockId << "," << curBlockId << ")"; SubFactoryMonitor m1(*this, ss.str(), coarseLevel); { SubFactoryMonitor subM(*this, "Rebalancing restriction -- fusedImport", coarseLevel); // Note: The 3rd argument says to use originalR's domain map. RCP<Map> dummy; rebRii = MatrixFactory::Build(Rii,*rebalanceImporter,dummy,rebalanceImporter->getTargetMap()); } RCP<ParameterList> params = rcp(new ParameterList()); params->set("printLoadBalancingInfo", true); std::stringstream ss2; ss2 << "R(" << curBlockId << "," << curBlockId << ") rebalanced:"; GetOStream(Statistics0) << PerfUtils::PrintMatrixInfo(*rebRii, ss2.str(), params); } else { rebRii = Rii; RCP<ParameterList> params = rcp(new ParameterList()); params->set("printLoadBalancingInfo", true); std::stringstream ss2; ss2 << "R(" << curBlockId << "," << curBlockId << ") not rebalanced:"; GetOStream(Statistics0) << PerfUtils::PrintMatrixInfo(*rebRii, ss2.str(), params); } // fix striding information for rebalanced diagonal block rebRii RCP<const Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node> > rgRMapExtractor = bOriginalTransferOp->getRangeMapExtractor(); // original map extractor Teuchos::RCP<const StridedMap> orig_stridedRgMap = Teuchos::rcp_dynamic_cast<const StridedMap>(rgRMapExtractor->getMap(Teuchos::as<size_t>(curBlockId))); Teuchos::RCP<const Map> stridedRgMap = Teuchos::null; if(orig_stridedRgMap != Teuchos::null) { std::vector<size_t> stridingData = orig_stridedRgMap->getStridingData(); Teuchos::ArrayView< const GlobalOrdinal > nodeRangeMapii = rebRii->getRangeMap()->getNodeElementList(); stridedRgMap = StridedMapFactory::Build( originalTransferOp->getRangeMap()->lib(), Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(), nodeRangeMapii, rebRii->getRangeMap()->getIndexBase(), stridingData, originalTransferOp->getRangeMap()->getComm(), orig_stridedRgMap->getStridedBlockId(), orig_stridedRgMap->getOffset()); } RCP<const Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node> > doRMapExtractor = bOriginalTransferOp->getDomainMapExtractor(); // original map extractor Teuchos::RCP<const StridedMap> orig_stridedDoMap = Teuchos::rcp_dynamic_cast<const StridedMap>(doRMapExtractor->getMap(Teuchos::as<size_t>(curBlockId))); Teuchos::RCP<const Map> stridedDoMap = Teuchos::null; if(orig_stridedDoMap != Teuchos::null) { std::vector<size_t> stridingData = orig_stridedDoMap->getStridingData(); Teuchos::ArrayView< const GlobalOrdinal > nodeDomainMapii = rebRii->getDomainMap()->getNodeElementList(); stridedDoMap = StridedMapFactory::Build( originalTransferOp->getDomainMap()->lib(), Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(), nodeDomainMapii, rebRii->getDomainMap()->getIndexBase(), stridingData, originalTransferOp->getDomainMap()->getComm(), orig_stridedDoMap->getStridedBlockId(), orig_stridedDoMap->getOffset()); } TEUCHOS_TEST_FOR_EXCEPTION(stridedRgMap == Teuchos::null,Exceptions::RuntimeError, "MueLu::RebalanceBlockRestrictionFactory::Build: failed to generate striding information. error."); TEUCHOS_TEST_FOR_EXCEPTION(stridedDoMap == Teuchos::null,Exceptions::RuntimeError, "MueLu::RebalanceBlockRestrictionFactory::Build: failed to generate striding information. error."); // replace stridedMaps view in diagonal sub block if(rebRii->IsView("stridedMaps")) rebRii->RemoveView("stridedMaps"); rebRii->CreateView("stridedMaps", stridedRgMap, stridedDoMap); // store rebalanced subblock subBlockRebR.push_back(rebRii); // append strided row map (= range map) to list of range maps. Teuchos::RCP<const Map> rangeMapii = rebRii->getRowMap("stridedMaps"); //rebRii->getRangeMap(); subBlockRRangeMaps.push_back(rangeMapii); Teuchos::ArrayView< const GlobalOrdinal > nodeRangeMapii = rebRii->getRangeMap()->getNodeElementList(); fullRangeMapVector.insert(fullRangeMapVector.end(), nodeRangeMapii.begin(), nodeRangeMapii.end()); sort(fullRangeMapVector.begin(), fullRangeMapVector.end()); // append strided col map (= domain map) to list of range maps. Teuchos::RCP<const Map> domainMapii = rebRii->getColMap("stridedMaps"); //rebRii->getDomainMap(); subBlockRDomainMaps.push_back(domainMapii); Teuchos::ArrayView< const GlobalOrdinal > nodeDomainMapii = rebRii->getDomainMap()->getNodeElementList(); fullDomainMapVector.insert(fullDomainMapVector.end(), nodeDomainMapii.begin(), nodeDomainMapii.end()); sort(fullDomainMapVector.begin(), fullDomainMapVector.end()); //////////////////////////////////////////////////////////// // rebalance null space if(rebalanceImporter != Teuchos::null) { // rebalance null space std::stringstream ss2; ss2 << "Rebalancing nullspace block(" << curBlockId << "," << curBlockId << ")"; SubFactoryMonitor subM(*this, ss2.str(), coarseLevel); RCP<MultiVector> nullspace = coarseLevel.Get<RCP<MultiVector> >("Nullspace", (*it)->GetFactory("Nullspace").get()); RCP<MultiVector> permutedNullspace = MultiVectorFactory::Build(rebalanceImporter->getTargetMap(), nullspace->getNumVectors()); permutedNullspace->doImport(*nullspace, *rebalanceImporter, Xpetra::INSERT); // TODO think about this //if (pL.get<bool>("useSubcomm") == true) // TODO either useSubcomm is enabled everywhere or nowhere //permutedNullspace->replaceMap(permutedNullspace->getMap()->removeEmptyProcesses()); coarseLevel.Set<RCP<MultiVector> >("Nullspace", permutedNullspace, (*it)->GetFactory("Nullspace").get()); } // end rebalance null space else { // do nothing RCP<MultiVector> nullspace = coarseLevel.Get<RCP<MultiVector> >("Nullspace", (*it)->GetFactory("Nullspace").get()); coarseLevel.Set<RCP<MultiVector> >("Nullspace", nullspace, (*it)->GetFactory("Nullspace").get()); } //////////////////////////////////////////////////////////// curBlockId++; } // end for loop // extract map index base from maps of blocked P GO rangeIndexBase = originalTransferOp->getRangeMap()->getIndexBase(); GO domainIndexBase= originalTransferOp->getDomainMap()->getIndexBase(); // check this RCP<const Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node> > rangeRMapExtractor = bOriginalTransferOp->getRangeMapExtractor(); // original map extractor Teuchos::ArrayView<GO> fullRangeMapGIDs(&fullRangeMapVector[0],fullRangeMapVector.size()); Teuchos::RCP<const StridedMap> stridedRgFullMap = Teuchos::rcp_dynamic_cast<const StridedMap>(rangeRMapExtractor->getFullMap()); Teuchos::RCP<const Map > fullRangeMap = Teuchos::null; if(stridedRgFullMap != Teuchos::null) { std::vector<size_t> stridedData = stridedRgFullMap->getStridingData(); fullRangeMap = StridedMapFactory::Build( originalTransferOp->getRangeMap()->lib(), Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(), fullRangeMapGIDs, rangeIndexBase, stridedData, originalTransferOp->getRangeMap()->getComm(), stridedRgFullMap->getStridedBlockId(), stridedRgFullMap->getOffset()); } else { fullRangeMap = MapFactory::Build( originalTransferOp->getRangeMap()->lib(), Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(), fullRangeMapGIDs, rangeIndexBase, originalTransferOp->getRangeMap()->getComm()); } RCP<const Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node> > domainAMapExtractor = bOriginalTransferOp->getDomainMapExtractor(); Teuchos::ArrayView<GO> fullDomainMapGIDs(&fullDomainMapVector[0],fullDomainMapVector.size()); Teuchos::RCP<const StridedMap> stridedDoFullMap = Teuchos::rcp_dynamic_cast<const StridedMap>(domainAMapExtractor->getFullMap()); Teuchos::RCP<const Map > fullDomainMap = Teuchos::null; if(stridedDoFullMap != Teuchos::null) { TEUCHOS_TEST_FOR_EXCEPTION(stridedDoFullMap==Teuchos::null, Exceptions::BadCast, "MueLu::BlockedPFactory::Build: full map in domain map extractor has no striding information! error."); std::vector<size_t> stridedData2 = stridedDoFullMap->getStridingData(); fullDomainMap = StridedMapFactory::Build( originalTransferOp->getDomainMap()->lib(), Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(), fullDomainMapGIDs, domainIndexBase, stridedData2, originalTransferOp->getDomainMap()->getComm(), stridedDoFullMap->getStridedBlockId(), stridedDoFullMap->getOffset()); } else { fullDomainMap = MapFactory::Build( originalTransferOp->getDomainMap()->lib(), Teuchos::OrdinalTraits<Xpetra::global_size_t>::invalid(), fullDomainMapGIDs, domainIndexBase, originalTransferOp->getDomainMap()->getComm()); } // build map extractors Teuchos::RCP<const Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node> > rangeMapExtractor = Xpetra::MapExtractorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(fullRangeMap, subBlockRRangeMaps); Teuchos::RCP<const Xpetra::MapExtractor<Scalar, LocalOrdinal, GlobalOrdinal, Node> > domainMapExtractor = Xpetra::MapExtractorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(fullDomainMap, subBlockRDomainMaps); Teuchos::RCP<BlockedCrsMatrix> bRebR = Teuchos::rcp(new BlockedCrsMatrix(rangeMapExtractor,domainMapExtractor,10)); for(size_t i = 0; i<subBlockRRangeMaps.size(); i++) { Teuchos::RCP<const CrsMatrixWrap> crsOpii = Teuchos::rcp_dynamic_cast<const CrsMatrixWrap>(subBlockRebR[i]); Teuchos::RCP<CrsMatrix> crsMatii = crsOpii->getCrsMatrix(); bRebR->setMatrix(i,i,crsMatii); } bRebR->fillComplete(); Set(coarseLevel, "R", Teuchos::rcp_dynamic_cast<Matrix>(bRebR)); // do nothing // TODO remove this! } // Build