/** \brief Build this inverse operator from an Tpetra::Operator<ST,LO,GO,NT> * passed in to this object. * * Build this inverse opeerator from an Tpetra::Operator<ST,LO,GO,NT> * passed in to this object. If this Tpetra::Operator<ST,LO,GO,NT> * is an EpetraOperatorWrapper object then the block Thyra components * are extracted. * * \param[in] A The Epetra source operator. * \param[in] clear If true, than any previous state saved by the operator * is discarded. */ void InverseFactoryOperator::buildInverseOperator(const Teuchos::RCP<const Tpetra::Operator<ST,LO,GO,NT> > & A,bool clear) { Teko_DEBUG_SCOPE("InverseFactoryOperator::buildInverseOperator",10); // extract EpetraOperatorWrapper (throw on failure) and corresponding thyra operator RCP<const Thyra::LinearOpBase<ST> > thyraA = extractLinearOp(A); // set the mapping strategy SetMapStrategy(rcp(new InverseMappingStrategy(extractMappingStrategy(A)))); initInverse(clear); // actually build the inverse operator invOperator_ = Teko::buildInverse(*inverseFactory_,thyraA); SetOperator(invOperator_,false); firstBuildComplete_ = true; if(setConstFwdOp_) fwdOp_ = A; setConstFwdOp_ = true; TEUCHOS_ASSERT(invOperator_!=Teuchos::null); TEUCHOS_ASSERT(getForwardOp()!=Teuchos::null); TEUCHOS_ASSERT(getThyraOp()!=Teuchos::null); TEUCHOS_ASSERT(getMapStrategy()!=Teuchos::null); TEUCHOS_ASSERT(firstBuildComplete_==true); }
/** \brief Rebuild this inverse from an Tpetra::Operator<ST,LO,GO,NT> passed * in this to object. * * Rebuild this inverse from an Tpetra::Operator<ST,LO,GO,NT> passed * in this to object. If <code>buildInverseOperator</code> has not been called * the inverse operator will be built instead. Otherwise efforts are taken * to only rebuild what is neccessary. Also, that this Tpetra::Operator<ST,LO,GO,NT> * may be an EpetraOperatorWrapper object, so the block Thyra components * can be extracted. * * \param[in] A The Epetra source operator. (Should be a EpetraOperatorWrapper!) */ void InverseFactoryOperator::rebuildInverseOperator(const Teuchos::RCP<const Tpetra::Operator<ST,LO,GO,NT> > & A) { Teko_DEBUG_SCOPE("InverseFactoryOperator::rebuildPreconditioner",10); // if the inverse hasn't been built yet, rebuild from scratch if(not firstBuildComplete_) { buildInverseOperator(A,false); return; } RCP<const Thyra::LinearOpBase<ST> > thyraA = extractLinearOp(A); Teko::rebuildInverse(*inverseFactory_,thyraA,invOperator_); if(setConstFwdOp_) fwdOp_.initialize(A); SetOperator(invOperator_,false); setConstFwdOp_ = true; TEUCHOS_ASSERT(getForwardOp()!=Teuchos::null); TEUCHOS_ASSERT(invOperator_!=Teuchos::null); TEUCHOS_ASSERT(getThyraOp()!=Teuchos::null); TEUCHOS_ASSERT(firstBuildComplete_==true); }
/** \brief Builder function for creating preconditioner factories (yes * this is a factory factory. * * Builder function for creating preconditioner factories (yes * this is a factory factory. * * \param[in] name String name of factory to build * \param[in] settings Parameter list describing the parameters for the * factory to build * \param[in] invLib Inverse library for the factory to use. * * \returns If the name is associated with a preconditioner * a pointer is returned, otherwise Teuchos::null is returned. */ RCP<PreconditionerFactory> PreconditionerFactory::buildPreconditionerFactory(const std::string & name, const Teuchos::ParameterList & settings, const RCP<const InverseLibrary> & invLib) { Teko_DEBUG_SCOPE("PreconditionerFactory::buildPreconditionerFactory",10); // initialize the defaults if necessary if(precFactoryBuilder_.cloneCount()==0) initializePrecFactoryBuilder(); // request the preconditioner factory from the CloneFactory RCP<PreconditionerFactory> precFact = precFactoryBuilder_.build(name); Teko_DEBUG_MSG_BEGIN(5); DEBUG_STREAM << "Looked up \"" << name << "\"" << std::endl; DEBUG_STREAM << "Built " << precFact << std::endl; Teko_DEBUG_MSG_END(); if(precFact==Teuchos::null) return Teuchos::null; // add in the inverse library if(invLib!=Teuchos::null) { precFact->setInverseLibrary(invLib); precFact->setRequestHandler(invLib->getRequestHandler()); } // now that inverse library has been set, // pass in the parameter list precFact->initializeFromParameterList(settings); return precFact; }
/** \brief Build an inverse operator * * Build the inverse operator using this factory. * * \param[in] linearOp Linear operator needing to be inverted. * * \returns New linear operator that functions as the inverse * of <code>linearOp</code>. */ InverseLinearOp SolveInverseFactory::buildInverse(const LinearOp & linearOp) const { Teko_DEBUG_SCOPE("SolveInverseFactory::buildInverse(linearOp)",10); // build and initialize inverse linear op with solve Teuchos::RCP<Thyra::LinearOpWithSolveBase<double> > invLOWS = lowsFactory_->createOp(); lowsFactory_->initializeOp(Thyra::defaultLinearOpSource(linearOp),&*invLOWS,Thyra::SUPPORT_SOLVE_FORWARD_ONLY); return Thyra::nonconstInverse<double>(invLOWS); }
/** \brief Build an inverse operator and make sure it aware of some parents state * This functionality is only useful for Teko::PreconditionerFactory inverses. * * Build an inverse operator and make sure it aware of some parents state * This functionality is only useful for Teko::PreconditionerFactory inverses. * * \param[in] linearOp Linear operator needing to be inverted. * \param[in] parentState Current state object to be used. Only useful for preconditioners. * * \returns New linear operator that functions as the inverse * of <code>linearOp</code>. */ InverseLinearOp PreconditionerInverseFactory::buildInverse(const LinearOp & linearOp, const PreconditionerState & parentState) const { Teko_DEBUG_SCOPE("PreconditionerInverseFactory::buildInverse(A,parentState)",10); RCP<Thyra::PreconditionerBase<double> > prec = precFactory_->createPrec(); { Teko_DEBUG_SCOPE("Casting to Teko::Preconditioner",10); // pass state downward if a Teko::Preconditioner object is begin used RCP<Teko::Preconditioner> tekoPrec = Teuchos::rcp_dynamic_cast<Teko::Preconditioner>(prec); if(tekoPrec!=Teuchos::null) { Teko_DEBUG_SCOPE("Merging states",10); tekoPrec->mergeStateObject(parentState); } } precFactory_->initializePrec(Thyra::defaultLinearOpSource(linearOp),&*prec); RCP<Teko::PreconditionerLinearOp<double> > precOp = rcp(new Teko::PreconditionerLinearOp<double>(prec)); return precOp; }
/** returns an (approximate) inverse of the diagonal blocks of A * where A is closely related to the original source for invD0 and invD1 */ void InvFactoryDiagStrategy::getInvD(const BlockedLinearOp & A,BlockPreconditionerState & state,std::vector<LinearOp> & invDiag) const { Teko_DEBUG_SCOPE("InvFactoryDiagStrategy::getInvD",10); // loop over diagonals, build an inverse operator for each int diagCnt = A->productRange()->numBlocks(); int invCnt = invDiagFact_.size(); Teko_DEBUG_MSG("# diags = " << diagCnt << ", # inverses = " << invCnt,6); const std::string opPrefix = "JacobiDiagOp"; if(diagCnt<=invCnt) { for(int i=0;i<diagCnt;i++) invDiag.push_back(buildInverse(*invDiagFact_[i],getBlock(i,i,A),state,opPrefix,i)); } else { for(int i=0;i<invCnt;i++) invDiag.push_back(buildInverse(*invDiagFact_[i],getBlock(i,i,A),state,opPrefix,i)); for(int i=invCnt;i<diagCnt;i++) invDiag.push_back(buildInverse(*defaultInvFact_,getBlock(i,i,A),state,opPrefix,i)); } }
LinearOp ModALPreconditionerFactory::buildPreconditionerOperator(BlockedLinearOp & alOp, BlockPreconditionerState & state) const { Teko_DEBUG_SCOPE("ModALPreconditionerFactory::buildPreconditionerOperator()", 10); Teko_DEBUG_EXPR(Teuchos::Time timer("")); Teko_DEBUG_EXPR(Teuchos::Time totalTimer("")); Teko_DEBUG_EXPR(totalTimer.start()); // Only for 2D or 3D problems. int dim = blockRowCount(alOp) - 1; TEUCHOS_ASSERT(dim == 2 || dim == 3); // Build what is necessary for the state object. Teko_DEBUG_EXPR(timer.start(true)); invOpsStrategy_->buildState(alOp, state); Teko_DEBUG_EXPR(timer.stop()); Teko_DEBUG_MSG("ModALPreconditionerFactory::buildPreconditionerOperator():BuildStateTime = " << timer.totalElapsedTime(), 2); // Extract inverse operators from strategy Teko_DEBUG_EXPR(timer.start(true)); LinearOp invA11p = invOpsStrategy_->getInvA11p(state); LinearOp invA22p = invOpsStrategy_->getInvA22p(state); LinearOp invA33p; if(dim == 3) { invA33p = invOpsStrategy_->getInvA33p(state); } // The inverse of S can be built from strategy, // or just a diagonal matrix. ModALPrecondState * modALState = dynamic_cast<ModALPrecondState*>(&state); TEUCHOS_ASSERT(modALState != NULL); LinearOp invS; if(modALState->isStabilized_) { invS = invOpsStrategy_->getInvS(state); } else { invS = scale(modALState->gamma_, modALState->invPressureMassMatrix_); } Teko_DEBUG_EXPR(timer.stop()); Teko_DEBUG_MSG("ModALPrecFact::buildPreconditionerOperator(): GetInvTime = " << timer.totalElapsedTime(), 2); // Build diagonal operations. std::vector<LinearOp> invDiag; invDiag.resize(dim + 1); invDiag[0] = invA11p; invDiag[1] = invA22p; if(dim == 2) { invDiag[2] = scale(-1.0, invS); } else if(dim == 3) { invDiag[2] = invA33p; invDiag[3] = scale(-1.0, invS); } // Get the upper triangular matrix. BlockedLinearOp U = getUpperTriBlocks(alOp); Teko_DEBUG_EXPR(totalTimer.stop()); Teko_DEBUG_MSG("ModALPrecFact::buildPreconditionerOperator TotalTime = " << totalTimer.totalElapsedTime(), 2); // Create the preconditioner return createBlockUpperTriInverseOp(U, invDiag, "Modified AL preconditioner-Upper"); }