void SaPFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::DeclareInput(Level &fineLevel, Level &coarseLevel) const { Input(fineLevel, "A"); // Get default tentative prolongator factory // Getting it that way ensure that the same factory instance will be used for both SaPFactory and NullspaceFactory. RCP<const FactoryBase> initialPFact = GetFactory("P"); if (initialPFact == Teuchos::null) { initialPFact = coarseLevel.GetFactoryManager()->GetFactory("Ptent"); } coarseLevel.DeclareInput("P", initialPFact.get(), this); // -- }
void MapTransferFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps>::Build(Level & fineLevel, Level & coarseLevel) const { typedef Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps> OperatorClass; //TODO typedef Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node> MapClass; typedef Xpetra::MapFactory<LocalOrdinal, GlobalOrdinal, Node> MapFactoryClass; Monitor m(*this, "Contact Map transfer factory"); if (fineLevel.IsAvailable(mapName_, mapFact_.get())==false) { GetOStream(Runtime0, 0) << "MapTransferFactory::Build: User provided map " << mapName_ << " not found in Level class." << std::endl; } // fetch map extractor from level RCP<const MapClass> transferMap = fineLevel.Get<RCP<const MapClass> >(mapName_,mapFact_.get()); // Get default tentative prolongator factory // Getting it that way ensure that the same factory instance will be used for both SaPFactory and NullspaceFactory. // -- Warning: Do not use directly initialPFact_. Use initialPFact instead everywhere! RCP<const FactoryBase> tentPFact = GetFactory("P"); if (tentPFact == Teuchos::null) { tentPFact = coarseLevel.GetFactoryManager()->GetFactory("Ptent"); } TEUCHOS_TEST_FOR_EXCEPTION(!coarseLevel.IsAvailable("P",tentPFact.get()),Exceptions::RuntimeError, "MueLu::MapTransferFactory::Build(): P (generated by TentativePFactory) not available."); RCP<OperatorClass> Ptent = coarseLevel.Get<RCP<OperatorClass> >("P", tentPFact.get()); std::vector<GlobalOrdinal > coarseMapGids; // loop over local rows of Ptent for(size_t row=0; row<Ptent->getNodeNumRows(); row++) { GlobalOrdinal grid = Ptent->getRowMap()->getGlobalElement(row); if(transferMap->isNodeGlobalElement(grid)) { Teuchos::ArrayView<const LocalOrdinal> indices; Teuchos::ArrayView<const Scalar> vals; Ptent->getLocalRowView(row, indices, vals); for(size_t i=0; i<(size_t)indices.size(); i++) { // mark all columns in Ptent(grid,*) to be coarse Dofs of next level transferMap GlobalOrdinal gcid = Ptent->getColMap()->getGlobalElement(indices[i]); coarseMapGids.push_back(gcid); } } // end if isNodeGlobalElement(grid) } // build column maps std::sort(coarseMapGids.begin(), coarseMapGids.end()); coarseMapGids.erase(std::unique(coarseMapGids.begin(), coarseMapGids.end()), coarseMapGids.end()); Teuchos::ArrayView<GlobalOrdinal> coarseMapGidsView (&coarseMapGids[0],coarseMapGids.size()); Teuchos::RCP<const MapClass> coarseTransferMap = MapFactoryClass::Build(Ptent->getColMap()->lib(), -1, coarseMapGidsView, Ptent->getColMap()->getIndexBase(), Ptent->getColMap()->getComm()); // store map extractor in coarse level coarseLevel.Set(mapName_, coarseTransferMap, mapFact_.get()); }
void GenericRFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(Level & fineLevel, Level & coarseLevel) const { FactoryMonitor m(*this, "Call prolongator factory for calculating restrictor", coarseLevel); RCP<const FactoryBase> PFact1 = GetFactory("P"); if (PFact1 == Teuchos::null) { PFact1 = coarseLevel.GetFactoryManager()->GetFactory("P"); } RCP<PFactory> PFact = Teuchos::rcp_const_cast<PFactory>(rcp_dynamic_cast<const PFactory>(PFact1));; MueLu::DisableMultipleCallCheck check(PFact); // BuildR bool rmode = PFact->isRestrictionModeSet(); PFact->setRestrictionMode(true); // switch prolongator factory to restriction mode //PFact->Build(fineLevel, coarseLevel); // call PFactory::Build explicitely RCP<Matrix> R = coarseLevel.Get<RCP<Matrix> >("R",PFact.get()); PFact->setRestrictionMode(rmode); // reset restriction mode flag Set(coarseLevel, "R", R); } //BuildR
void GenericRFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::DeclareInput(Level &fineLevel, Level &coarseLevel) const { RCP<const FactoryBase> PFact1 = GetFactory("P"); if (PFact1 == Teuchos::null) { PFact1 = coarseLevel.GetFactoryManager()->GetFactory("P"); } RCP<PFactory> PFact = Teuchos::rcp_const_cast<PFactory>(rcp_dynamic_cast<const PFactory>(PFact1));; bool rmode = PFact->isRestrictionModeSet(); PFact->setRestrictionMode(true); // set restriction mode // force request call for PFact // in general, Request is only called once for each factory, // since we can reuse data generated by the factory // however, here we have to run the code in PFact.Build again, // so we have to request the dependencies of PFact first! // The dependencies are (automatically) cleaned up after the second // run of PFact.Build in coarseLevel.Get<RCP<Matrix> >("R",PFact.get())! coarseLevel.DeclareDependencies(PFact.get()); coarseLevel.DeclareInput("R", PFact.get(), this); // we expect the prolongation operator factory to produce "R" as output // call declareInput is called within DeclareInput call PFact->setRestrictionMode(rmode); // reset restriciton mode flag }
void SaPFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildP(Level &fineLevel, Level &coarseLevel) const { FactoryMonitor m(*this, "Prolongator smoothing", coarseLevel); std::ostringstream levelstr; levelstr << coarseLevel.GetLevelID(); typedef typename Teuchos::ScalarTraits<SC>::magnitudeType Magnitude; // Get default tentative prolongator factory // Getting it that way ensure that the same factory instance will be used for both SaPFactory and NullspaceFactory. // -- Warning: Do not use directly initialPFact_. Use initialPFact instead everywhere! RCP<const FactoryBase> initialPFact = GetFactory("P"); if (initialPFact == Teuchos::null) { initialPFact = coarseLevel.GetFactoryManager()->GetFactory("Ptent"); } // Level Get RCP<Matrix> A = Get< RCP<Matrix> >(fineLevel, "A"); RCP<Matrix> Ptent = coarseLevel.Get< RCP<Matrix> >("P", initialPFact.get()); if(restrictionMode_) { SubFactoryMonitor m2(*this, "Transpose A", coarseLevel); A = Utils2::Transpose(*A, true); // build transpose of A explicitely } //Build final prolongator RCP<Matrix> finalP; // output const ParameterList & pL = GetParameterList(); Scalar dampingFactor = as<Scalar>(pL.get<double>("sa: damping factor")); LO maxEigenIterations = as<LO>(pL.get<int>("sa: eigenvalue estimate num iterations")); bool estimateMaxEigen = pL.get<bool>("sa: calculate eigenvalue estimate"); if (dampingFactor != Teuchos::ScalarTraits<Scalar>::zero()) { Scalar lambdaMax; { SubFactoryMonitor m2(*this, "Eigenvalue estimate", coarseLevel); lambdaMax = A->GetMaxEigenvalueEstimate(); if (lambdaMax == -Teuchos::ScalarTraits<SC>::one() || estimateMaxEigen) { GetOStream(Statistics1) << "Calculating max eigenvalue estimate now (max iters = "<< maxEigenIterations << ")" << std::endl; Magnitude stopTol = 1e-4; lambdaMax = Utils::PowerMethod(*A, true, maxEigenIterations, stopTol); A->SetMaxEigenvalueEstimate(lambdaMax); } else { GetOStream(Statistics1) << "Using cached max eigenvalue estimate" << std::endl; } GetOStream(Statistics0) << "Prolongator damping factor = " << dampingFactor/lambdaMax << " (" << dampingFactor << " / " << lambdaMax << ")" << std::endl; } { SubFactoryMonitor m2(*this, "Fused (I-omega*D^{-1} A)*Ptent", coarseLevel); Teuchos::RCP<Vector> invDiag = Utils::GetMatrixDiagonalInverse(*A); SC omega = dampingFactor / lambdaMax; // finalP = Ptent + (I - \omega D^{-1}A) Ptent finalP = Utils::Jacobi(omega, *invDiag, *A, *Ptent, finalP, GetOStream(Statistics2),std::string("MueLu::SaP-")+levelstr.str()); } } else { finalP = Ptent; } // Level Set if (!restrictionMode_) { // prolongation factory is in prolongation mode Set(coarseLevel, "P", finalP); // NOTE: EXPERIMENTAL if (Ptent->IsView("stridedMaps")) finalP->CreateView("stridedMaps", Ptent); } else { // prolongation factory is in restriction mode RCP<Matrix> R = Utils2::Transpose(*finalP, true); // use Utils2 -> specialization for double Set(coarseLevel, "R", R); // NOTE: EXPERIMENTAL if (Ptent->IsView("stridedMaps")) R->CreateView("stridedMaps", Ptent, true); } if (IsPrint(Statistics1)) { RCP<ParameterList> params = rcp(new ParameterList()); params->set("printLoadBalancingInfo", true); params->set("printCommInfo", true); GetOStream(Statistics1) << PerfUtils::PrintMatrixInfo(*finalP, (!restrictionMode_ ? "P" : "R"), params); } } //Build()
void SaPFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps>::BuildP(Level &fineLevel, Level &coarseLevel) const { FactoryMonitor m(*this, "Prolongator smoothing", coarseLevel); typedef typename Teuchos::ScalarTraits<SC>::magnitudeType Magnitude; // Get default tentative prolongator factory // Getting it that way ensure that the same factory instance will be used for both SaPFactory and NullspaceFactory. // -- Warning: Do not use directly initialPFact_. Use initialPFact instead everywhere! RCP<const FactoryBase> initialPFact = GetFactory("P"); if (initialPFact == Teuchos::null) { initialPFact = coarseLevel.GetFactoryManager()->GetFactory("Ptent"); } // Level Get RCP<Matrix> A = Get< RCP<Matrix> >(fineLevel, "A"); RCP<Matrix> Ptent = coarseLevel.Get< RCP<Matrix> >("P", initialPFact.get()); if(restrictionMode_) { SubFactoryMonitor m2(*this, "Transpose A", coarseLevel); A = Utils2::Transpose(A, true); // build transpose of A explicitely } //Build final prolongator RCP<Matrix> finalP; // output //FIXME Xpetra::Matrix should calculate/stash max eigenvalue //FIXME SC lambdaMax = A->GetDinvALambda(); const ParameterList & pL = GetParameterList(); Scalar dampingFactor = pL.get<Scalar>("Damping factor"); if (dampingFactor != Teuchos::ScalarTraits<Scalar>::zero()) { //Teuchos::ParameterList matrixList; //RCP<Matrix> I = MueLu::Gallery::CreateCrsMatrix<SC, LO, GO, Map, CrsMatrixWrap>("Identity", Get< RCP<Matrix> >(fineLevel, "A")->getRowMap(), matrixList); //RCP<Matrix> newPtent = Utils::TwoMatrixMultiply(I, false, Ptent, false); //Ptent = newPtent; //I tried a checkout of the original Ptent, and it seems to be gone now (which is good) RCP<Matrix> AP; { SubFactoryMonitor m2(*this, "MxM: A x Ptentative", coarseLevel); //JJH -- If I switch doFillComplete to false, the resulting matrix seems weird when printed with describe. //JJH -- The final prolongator is wrong, to boot. So right now, I fillComplete AP, but avoid fillComplete //JJH -- in the scaling. Long story short, we're doing 2 fillCompletes, where ideally we'd do just one. bool doFillComplete=true; bool optimizeStorage=true; // FIXME: ADD() need B.getProfileType()==DynamicProfile if (A->getRowMap()->lib() == Xpetra::UseTpetra) { optimizeStorage=false; } bool allowMLMultiply = true; #ifdef HAVE_MUELU_EXPERIMENTAL // Energy minimization uses AP pattern for restriction. The problem with ML multiply is that it automatically // removes zero valued entries in the matrix product, resulting in incorrect pattern for the minimization. // One could try to mitigate that by multiply matrices with all entries equal to zero, which would produce the // correct graph. However, that is one extra MxM we don't need. // Instead, I disable ML multiply when experimental option is specified. // NOTE: Thanks to C.Siefert, native EPetra MxM multiply version should actually be comparable with ML in time allowMLMultiply = false; #endif AP = Utils::Multiply(*A, false, *Ptent, false, doFillComplete, optimizeStorage, allowMLMultiply); } { SubFactoryMonitor m2(*this, "Scaling (A x Ptentative) by D^{-1}", coarseLevel); bool doFillComplete=true; bool optimizeStorage=false; Teuchos::ArrayRCP<SC> diag = Utils::GetMatrixDiagonal(*A); Utils::MyOldScaleMatrix(AP, diag, true, doFillComplete, optimizeStorage); //scale matrix with reciprocal of diag } Scalar lambdaMax; { SubFactoryMonitor m2(*this, "Eigenvalue estimate", coarseLevel); lambdaMax = A->GetMaxEigenvalueEstimate(); if (lambdaMax == -Teuchos::ScalarTraits<SC>::one()) { GetOStream(Statistics1, 0) << "Calculating max eigenvalue estimate now" << std::endl; Magnitude stopTol = 1e-4; lambdaMax = Utils::PowerMethod(*A, true, (LO) 10, stopTol); A->SetMaxEigenvalueEstimate(lambdaMax); } else { GetOStream(Statistics1, 0) << "Using cached max eigenvalue estimate" << std::endl; } GetOStream(Statistics1, 0) << "Damping factor = " << dampingFactor/lambdaMax << " (" << dampingFactor << " / " << lambdaMax << ")" << std::endl; } { SubFactoryMonitor m2(*this, "M+M: P = (Ptentative) + (D^{-1} x A x Ptentative)", coarseLevel); bool doTranspose=false; bool PtentHasFixedNnzPerRow=true; Utils2::TwoMatrixAdd(Ptent, doTranspose, Teuchos::ScalarTraits<Scalar>::one(), AP, doTranspose, -dampingFactor/lambdaMax, finalP, PtentHasFixedNnzPerRow); } { SubFactoryMonitor m2(*this, "FillComplete() of P", coarseLevel); finalP->fillComplete( Ptent->getDomainMap(), Ptent->getRangeMap() ); } } else { finalP = Ptent; } // Level Set if (!restrictionMode_) { // prolongation factory is in prolongation mode Set(coarseLevel, "P", finalP); // NOTE: EXPERIMENTAL if (Ptent->IsView("stridedMaps")) finalP->CreateView("stridedMaps", Ptent); } else { // prolongation factory is in restriction mode RCP<Matrix> R = Utils2::Transpose(finalP, true); // use Utils2 -> specialization for double Set(coarseLevel, "R", R); // NOTE: EXPERIMENTAL if (Ptent->IsView("stridedMaps")) R->CreateView("stridedMaps", Ptent, true); } RCP<ParameterList> params = rcp(new ParameterList()); params->set("printLoadBalancingInfo", true); GetOStream(Statistics0,0) << Utils::PrintMatrixInfo(*finalP, (!restrictionMode_ ? "P" : "R"), params); } //Build()
void SaPFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps>::BuildP(Level &fineLevel, Level &coarseLevel) const { FactoryMonitor m(*this, "Prolongator smoothing", coarseLevel); typedef typename Teuchos::ScalarTraits<SC>::magnitudeType Magnitude; // Get default tentative prolongator factory // Getting it that way ensure that the same factory instance will be used for both SaPFactory and NullspaceFactory. // -- Warning: Do not use directly initialPFact_. Use initialPFact instead everywhere! RCP<const FactoryBase> initialPFact = GetFactory("P"); if (initialPFact == Teuchos::null) { initialPFact = coarseLevel.GetFactoryManager()->GetFactory("Ptent"); } // Level Get RCP<Matrix> A = Get< RCP<Matrix> >(fineLevel, "A"); RCP<Matrix> Ptent = coarseLevel.Get< RCP<Matrix> >("P", initialPFact.get()); if(restrictionMode_) { SubFactoryMonitor m2(*this, "Transpose A", coarseLevel); A = Utils2::Transpose(*A, true); // build transpose of A explicitely } //Build final prolongator RCP<Matrix> finalP; // output //FIXME Xpetra::Matrix should calculate/stash max eigenvalue //FIXME SC lambdaMax = A->GetDinvALambda(); const ParameterList & pL = GetParameterList(); Scalar dampingFactor = pL.get<Scalar>("Damping factor"); if (dampingFactor != Teuchos::ScalarTraits<Scalar>::zero()) { //Teuchos::ParameterList matrixList; //RCP<Matrix> I = MueLu::Gallery::CreateCrsMatrix<SC, LO, GO, Map, CrsMatrixWrap>("Identity", Get< RCP<Matrix> >(fineLevel, "A")->getRowMap(), matrixList); //RCP<Matrix> newPtent = Utils::TwoMatrixMultiply(I, false, Ptent, false); //Ptent = newPtent; //I tried a checkout of the original Ptent, and it seems to be gone now (which is good) Scalar lambdaMax; { SubFactoryMonitor m2(*this, "Eigenvalue estimate", coarseLevel); lambdaMax = A->GetMaxEigenvalueEstimate(); if (lambdaMax == -Teuchos::ScalarTraits<SC>::one()) { GetOStream(Statistics1, 0) << "Calculating max eigenvalue estimate now" << std::endl; Magnitude stopTol = 1e-4; lambdaMax = Utils::PowerMethod(*A, true, (LO) 10, stopTol); A->SetMaxEigenvalueEstimate(lambdaMax); } else { GetOStream(Statistics1, 0) << "Using cached max eigenvalue estimate" << std::endl; } GetOStream(Statistics0, 0) << "Prolongator damping factor = " << dampingFactor/lambdaMax << " (" << dampingFactor << " / " << lambdaMax << ")" << std::endl; } { SubFactoryMonitor m2(*this, "Fused (I-omega*D^{-1} A)*Ptent", coarseLevel); Teuchos::RCP<Vector> invDiag = Utils::GetMatrixDiagonalInverse(*A); SC omega = dampingFactor / lambdaMax; finalP=Utils::Jacobi(omega,*invDiag,*A, *Ptent, finalP,GetOStream(Statistics2,0)); } } else { finalP = Ptent; } // Level Set if (!restrictionMode_) { // prolongation factory is in prolongation mode Set(coarseLevel, "P", finalP); // NOTE: EXPERIMENTAL if (Ptent->IsView("stridedMaps")) finalP->CreateView("stridedMaps", Ptent); } else { // prolongation factory is in restriction mode RCP<Matrix> R = Utils2::Transpose(*finalP, true); // use Utils2 -> specialization for double Set(coarseLevel, "R", R); // NOTE: EXPERIMENTAL if (Ptent->IsView("stridedMaps")) R->CreateView("stridedMaps", Ptent, true); } RCP<ParameterList> params = rcp(new ParameterList()); params->set("printLoadBalancingInfo", true); GetOStream(Statistics1,0) << Utils::PrintMatrixInfo(*finalP, (!restrictionMode_ ? "P" : "R"), params); } //Build()
void FilteredAFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps>::Build(Level& currentLevel) const { FactoryMonitor m(*this, "Matrix filtering", currentLevel); RCP<Matrix> A = Get< RCP<Matrix> >(currentLevel, "A"); if (currentLevel.Get<bool>("Filtering", currentLevel.GetFactoryManager()->GetFactory("Filtering").get()) == false) { GetOStream(Runtime0) << "Filtered matrix is not being constructed as no filtering is being done" << std::endl; Set(currentLevel, "A", A); return; } size_t blkSize = A->GetFixedBlockSize(); const ParameterList& pL = GetParameterList(); bool lumping = pL.get<bool>("lumping"); if (lumping) GetOStream(Runtime0) << "Lumping dropped entries" << std::endl; RCP<GraphBase> G = Get< RCP<GraphBase> >(currentLevel, "Graph"); SC zero = Teuchos::ScalarTraits<SC>::zero(); // Both Epetra and Tpetra matrix-matrix multiply use the following trick: // if an entry of the left matrix is zero, it does not compute or store the // zero value. // // This trick allows us to bypass constructing a new matrix. Instead, we // make a deep copy of the original one, and fill it in with zeros, which // are ignored during the prolongator smoothing. RCP<Matrix> filteredA = MatrixFactory::Build(A->getCrsGraph()); filteredA->resumeFill(); ArrayView<const LO> inds; ArrayView<const SC> valsA; #ifdef ASSUME_DIRECT_ACCESS_TO_ROW ArrayView<SC> vals; #else Array<SC> vals; #endif Array<char> filter(blkSize * G->GetImportMap()->getNodeNumElements(), 0); size_t numGRows = G->GetNodeNumVertices(); for (size_t i = 0; i < numGRows; i++) { // Set up filtering array ArrayView<const LO> indsG = G->getNeighborVertices(i); for (size_t j = 0; j < as<size_t>(indsG.size()); j++) for (size_t k = 0; k < blkSize; k++) filter[indsG[j]*blkSize+k] = 1; for (size_t k = 0; k < blkSize; k++) { LO row = i*blkSize + k; A->getLocalRowView(row, inds, valsA); size_t nnz = inds.size(); if (nnz == 0) continue; #ifdef ASSUME_DIRECT_ACCESS_TO_ROW // Transform ArrayView<const SC> into ArrayView<SC> ArrayView<const SC> vals1; filteredA->getLocalRowView(row, inds, vals1); vals = ArrayView<SC>(const_cast<SC*>(vals1.getRawPtr()), nnz); memcpy(vals.getRawPtr(), valsA.getRawPtr(), nnz*sizeof(SC)); #else vals = Array<SC>(valsA); #endif if (lumping == false) { for (size_t j = 0; j < nnz; j++) if (!filter[inds[j]]) vals[j] = zero; } else { LO diagIndex = -1; SC diagExtra = zero; for (size_t j = 0; j < nnz; j++) { if (filter[inds[j]]) continue; if (inds[j] == row) { // Remember diagonal position diagIndex = j; } else { diagExtra += vals[j]; } vals[j] = zero; } // Lump dropped entries // NOTE // * Does it make sense to lump for elasticity? // * Is it different for diffusion and elasticity? if (diagIndex != -1) vals[diagIndex] += diagExtra; } #ifndef ASSUME_DIRECT_ACCESS_TO_ROW // Because we used a column map in the construction of the matrix // we can just use insertLocalValues here instead of insertGlobalValues filteredA->replaceLocalValues(row, inds, vals); #endif } // Reset filtering array for (size_t j = 0; j < as<size_t> (indsG.size()); j++) for (size_t k = 0; k < blkSize; k++) filter[indsG[j]*blkSize+k] = 0; } RCP<ParameterList> fillCompleteParams(new ParameterList); fillCompleteParams->set("No Nonlocal Changes", true); filteredA->fillComplete(fillCompleteParams); filteredA->SetFixedBlockSize(blkSize); if (pL.get<bool>("filtered matrix: reuse eigenvalue")) { // Reuse max eigenvalue from A // It is unclear what eigenvalue is the best for the smoothing, but we already may have // the D^{-1}A estimate in A, may as well use it. // NOTE: ML does that too filteredA->SetMaxEigenvalueEstimate(A->GetMaxEigenvalueEstimate()); } Set(currentLevel, "A", filteredA); }
void FilteredAFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps>::DeclareInput(Level& currentLevel) const { Input(currentLevel, "A"); Input(currentLevel, "Graph"); // NOTE: we do this DeclareInput in such complicated fashion because this is not a part of the parameter list currentLevel.DeclareInput("Filtering", currentLevel.GetFactoryManager()->GetFactory("Filtering").get()); }
void MapTransferFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps>::DeclareInput(Level &fineLevel, Level &coarseLevel) const { fineLevel.DeclareInput(mapName_,mapFact_.get(),this); Teuchos::RCP<const FactoryBase> tentPFact = GetFactory("P"); if (tentPFact == Teuchos::null) { tentPFact = coarseLevel.GetFactoryManager()->GetFactory("Ptent"); } coarseLevel.DeclareInput("P", tentPFact.get(), this); }
void FilteredAFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node, LocalMatOps>::Build(Level& currentLevel) const { using Teuchos::as; FactoryMonitor m(*this, "Matrix filtering", currentLevel); RCP<Matrix> A = Get< RCP<Matrix> >(currentLevel, "A"); if (currentLevel.Get<bool>("Filtering", currentLevel.GetFactoryManager()->GetFactory("Filtering").get()) == false) { GetOStream(Runtime0,0) << "Filtered matrix is not being constructed as no filtering is being done" << std::endl; Set(currentLevel, "A", A); return; } const ParameterList& pL = GetParameterList(); RCP<GraphBase> G = Get< RCP<GraphBase> >(currentLevel, "Graph"); bool lumping = pL.get<bool>("lumping"); size_t blkSize = A->GetFixedBlockSize(); if (lumping) GetOStream(Runtime0,0) << "Lumping dropped entries" << std::endl; // Calculate max entries per row RCP<Matrix> filteredA = MatrixFactory::Build(A->getRowMap(), A->getColMap(), A->getNodeMaxNumRowEntries(), Xpetra::StaticProfile); Array<LO> newInds; Array<SC> newVals; Array<char> filter(blkSize*G->GetImportMap()->getNodeNumElements(), 0); size_t numGRows = G->GetNodeNumVertices(), numInds = 0, diagIndex; SC diagExtra; for (size_t i = 0; i < numGRows; i++) { // Set up filtering array Teuchos::ArrayView<const LO> indsG = G->getNeighborVertices(i); for (size_t j = 0; j < as<size_t> (indsG.size()); j++) for (size_t k = 0; k < blkSize; k++) filter[indsG[j]*blkSize+k] = 1; for (size_t k = 0; k < blkSize; k++) { LocalOrdinal row = i*blkSize+k; ArrayView<const LO> oldInds; ArrayView<const SC> oldVals; A->getLocalRowView(row, oldInds, oldVals); diagIndex = as<size_t>(-1); diagExtra = Teuchos::ScalarTraits<SC>::zero(); newInds.resize(oldInds.size()); newVals.resize(oldVals.size()); numInds = 0; for (size_t j = 0; j < as<size_t> (oldInds.size()); j++) if (filter[oldInds[j]]) { newInds[numInds] = oldInds[j]; newVals[numInds] = oldVals[j]; // Remember diagonal position if (newInds[numInds] == row) diagIndex = numInds; numInds++; } else { diagExtra += oldVals[j]; } // Lump dropped entries // NOTE // * Does it make sense to lump for elasticity? // * Is it different for diffusion and elasticity? if (lumping) newVals[diagIndex] += diagExtra; newInds.resize(numInds); newVals.resize(numInds); // Because we used a column map in the construction of the matrix // we can just use insertLocalValues here instead of insertGlobalValues filteredA->insertLocalValues(row, newInds, newVals); } // Clean up filtering array for (size_t j = 0; j < as<size_t> (indsG.size()); j++) for (size_t k = 0; k < blkSize; k++) filter[indsG[j]*blkSize+k] = 0; } RCP<ParameterList> fillCompleteParams(new ParameterList); fillCompleteParams->set("No Nonlocal Changes", true); filteredA->fillComplete(A->getDomainMap(), A->getRangeMap(), fillCompleteParams); filteredA->SetFixedBlockSize(blkSize); // TODO: Can we reuse max eigenvalue from A? // filteredA->SetMaxEigenvalueEstimate(A->GetMaxEigenvalueEstimate()); Set(currentLevel, "A", filteredA); }
void SaPFactory_kokkos<Scalar,LocalOrdinal,GlobalOrdinal,Kokkos::Compat::KokkosDeviceWrapperNode<DeviceType>>::BuildP(Level& fineLevel, Level& coarseLevel) const { FactoryMonitor m(*this, "Prolongator smoothing", coarseLevel); // Add debugging information DeviceType::execution_space::print_configuration(GetOStream(Runtime1)); typedef typename Teuchos::ScalarTraits<SC>::magnitudeType Magnitude; // Get default tentative prolongator factory // Getting it that way ensure that the same factory instance will be used for both SaPFactory_kokkos and NullspaceFactory. // -- Warning: Do not use directly initialPFact_. Use initialPFact instead everywhere! RCP<const FactoryBase> initialPFact = GetFactory("P"); if (initialPFact == Teuchos::null) { initialPFact = coarseLevel.GetFactoryManager()->GetFactory("Ptent"); } // Level Get RCP<Matrix> A = Get< RCP<Matrix> >(fineLevel, "A"); RCP<Matrix> Ptent = coarseLevel.Get< RCP<Matrix> >("P", initialPFact.get()); if(restrictionMode_) { SubFactoryMonitor m2(*this, "Transpose A", coarseLevel); A = Utilities_kokkos::Transpose(*A, true); // build transpose of A explicitly } //Build final prolongator RCP<Matrix> finalP; // output // Reuse pattern if available RCP<ParameterList> APparams = rcp(new ParameterList); if (coarseLevel.IsAvailable("AP reuse data", this)) { GetOStream(static_cast<MsgType>(Runtime0 | Test)) << "Reusing previous AP data" << std::endl; APparams = coarseLevel.Get< RCP<ParameterList> >("AP reuse data", this); if (APparams->isParameter("graph")) finalP = APparams->get< RCP<Matrix> >("graph"); } const ParameterList& pL = GetParameterList(); SC dampingFactor = as<SC>(pL.get<double>("sa: damping factor")); LO maxEigenIterations = as<LO>(pL.get<int>("sa: eigenvalue estimate num iterations")); bool estimateMaxEigen = pL.get<bool>("sa: calculate eigenvalue estimate"); if (dampingFactor != Teuchos::ScalarTraits<SC>::zero()) { SC lambdaMax; { SubFactoryMonitor m2(*this, "Eigenvalue estimate", coarseLevel); lambdaMax = A->GetMaxEigenvalueEstimate(); if (lambdaMax == -Teuchos::ScalarTraits<SC>::one() || estimateMaxEigen) { GetOStream(Statistics1) << "Calculating max eigenvalue estimate now (max iters = "<< maxEigenIterations << ")" << std::endl; Magnitude stopTol = 1e-4; lambdaMax = Utilities_kokkos::PowerMethod(*A, true, maxEigenIterations, stopTol); A->SetMaxEigenvalueEstimate(lambdaMax); } else { GetOStream(Statistics1) << "Using cached max eigenvalue estimate" << std::endl; } GetOStream(Statistics0) << "Prolongator damping factor = " << dampingFactor/lambdaMax << " (" << dampingFactor << " / " << lambdaMax << ")" << std::endl; } { SubFactoryMonitor m2(*this, "Fused (I-omega*D^{-1} A)*Ptent", coarseLevel); RCP<Vector> invDiag = Utilities_kokkos::GetMatrixDiagonalInverse(*A); SC omega = dampingFactor / lambdaMax; // finalP = Ptent + (I - \omega D^{-1}A) Ptent finalP = Xpetra::IteratorOps<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Jacobi(omega, *invDiag, *A, *Ptent, finalP, GetOStream(Statistics2), std::string("MueLu::SaP-") + toString(coarseLevel.GetLevelID()), APparams); } } else { finalP = Ptent; } // Level Set if (!restrictionMode_) { // prolongation factory is in prolongation mode Set(coarseLevel, "P", finalP); // NOTE: EXPERIMENTAL if (Ptent->IsView("stridedMaps")) finalP->CreateView("stridedMaps", Ptent); } else { // prolongation factory is in restriction mode RCP<Matrix> R = Utilities_kokkos::Transpose(*finalP, true); Set(coarseLevel, "R", R); // NOTE: EXPERIMENTAL if (Ptent->IsView("stridedMaps")) R->CreateView("stridedMaps", Ptent, true); } if (IsPrint(Statistics1)) { RCP<ParameterList> params = rcp(new ParameterList()); params->set("printLoadBalancingInfo", true); params->set("printCommInfo", true); GetOStream(Statistics1) << PerfUtils::PrintMatrixInfo(*finalP, (!restrictionMode_ ? "P" : "R"), params); } } //Build()