void IfpackPreconditionerFactory::initializePrec( const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc ,PreconditionerBase<double> *prec ,const ESupportSolveUse supportSolveUse ) const { using Teuchos::outArg; using Teuchos::OSTab; using Teuchos::dyn_cast; using Teuchos::RCP; using Teuchos::null; using Teuchos::rcp; using Teuchos::rcp_dynamic_cast; using Teuchos::rcp_const_cast; using Teuchos::set_extra_data; using Teuchos::get_optional_extra_data; using Teuchos::implicit_cast; Teuchos::Time totalTimer(""), timer(""); totalTimer.start(true); Teuchos::TimeMonitor overallTimeMonitor(*overallTimer); const Teuchos::RCP<Teuchos::FancyOStream> out = this->getOStream(); const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel(); Teuchos::OSTab tab(out); if(out.get() && implicit_cast<int>(verbLevel) > implicit_cast<int>(Teuchos::VERB_LOW)) *out << "\nEntering Thyra::IfpackPreconditionerFactory::initializePrec(...) ...\n"; #ifdef TEUCHOS_DEBUG TEST_FOR_EXCEPT(fwdOpSrc.get()==NULL); TEST_FOR_EXCEPT(prec==NULL); #endif Teuchos::RCP<const LinearOpBase<double> > fwdOp = fwdOpSrc->getOp(); #ifdef TEUCHOS_DEBUG TEST_FOR_EXCEPT(fwdOp.get()==NULL); #endif // // Unwrap and get the forward Epetra_Operator object // Teuchos::RCP<const Epetra_Operator> epetraFwdOp; EOpTransp epetraFwdOpTransp; EApplyEpetraOpAs epetraFwdOpApplyAs; EAdjointEpetraOp epetraFwdOpAdjointSupport; double epetraFwdOpScalar; epetraFwdOpViewExtractor_->getEpetraOpView( fwdOp, outArg(epetraFwdOp), outArg(epetraFwdOpTransp), outArg(epetraFwdOpApplyAs), outArg(epetraFwdOpAdjointSupport), outArg(epetraFwdOpScalar) ); // Validate what we get is what we need RCP<const Epetra_RowMatrix> epetraFwdRowMat = rcp_dynamic_cast<const Epetra_RowMatrix>(epetraFwdOp,true); TEST_FOR_EXCEPTION( epetraFwdOpApplyAs != EPETRA_OP_APPLY_APPLY, std::logic_error ,"Error, incorrect apply mode for an Epetra_RowMatrix" ); // // Get the concrete precondtioner object // DefaultPreconditioner<double> *defaultPrec = &Teuchos::dyn_cast<DefaultPreconditioner<double> >(*prec); // // Get the EpetraLinearOp object that is used to implement the preconditoner linear op // RCP<EpetraLinearOp> epetra_precOp = rcp_dynamic_cast<EpetraLinearOp>(defaultPrec->getNonconstUnspecifiedPrecOp(),true); // // Get the embedded Ifpack_Preconditioner object if it exists // Teuchos::RCP<Ifpack_Preconditioner> ifpack_precOp; if(epetra_precOp.get()) ifpack_precOp = rcp_dynamic_cast<Ifpack_Preconditioner>(epetra_precOp->epetra_op(),true); // // Get the attached forward operator if it exists and make sure that it matches // if(ifpack_precOp.get()) { // ToDo: Get the forward operator and make sure that it matches what is // already being used! } // // Permform initialization if needed // //const bool startingOver = (ifpack_precOp.get() == NULL); const bool startingOver = true; // ToDo: Comment back in the above original version of startingOver to allow // for resuse. Rob H. just pointed out to me that a memory leak is being // created when you just call Ifpack_ILU::Compute() over and over again. // Rob H. said that he will check in a fix the the development branch when // he can. if(startingOver) { if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) *out << "\nCreating the initial Ifpack_Preconditioner object of type \'"<<Ifpack::toString(precType_)<<"\' ...\n"; timer.start(true); Teuchos::TimeMonitor creationTimeMonitor(*creationTimer); // Create the initial preconditioner ifpack_precOp = rcp( ::Ifpack::Create( precType_ ,const_cast<Epetra_RowMatrix*>(&*epetraFwdRowMat) ,overlap_ ) ); timer.stop(); if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) OSTab(out).o() <<"=> Creation time = "<<timer.totalElapsedTime()<<" sec\n"; // Set parameters if the list exists if(paramList_.get()) { Teuchos::ParameterList &ifpackSettingsPL = paramList_->sublist(IfpackSettings_name); // Above will create new sublist if it does not exist! TEST_FOR_EXCEPT(0!=ifpack_precOp->SetParameters(ifpackSettingsPL)); // Above, I have not idea how any error messages for a mistake will be // reported back to the user! } // Initailize the structure for the preconditioner TEST_FOR_EXCEPT(0!=ifpack_precOp->Initialize()); } // // Attach the epetraFwdOp to the ifpack_precOp to guarantee that it will not go away // set_extra_data(epetraFwdOp, "IFPF::epetraFwdOp", Teuchos::inOutArg(ifpack_precOp), Teuchos::POST_DESTROY, false); // // Update the factorization // { if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) *out << "\nComputing the factorization of the preconditioner ...\n"; Teuchos::TimeMonitor factorizationTimeMonitor(*factorizationTimer); timer.start(true); TEST_FOR_EXCEPT(0!=ifpack_precOp->Compute()); timer.stop(); if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) OSTab(out).o() <<"=> Factorization time = "<<timer.totalElapsedTime()<<" sec\n"; } // // Compute the conditioner number estimate if asked // // ToDo: Implement // // Attach fwdOp to the ifpack_precOp // set_extra_data(fwdOpSrc, "IFPF::fwdOpSrc", Teuchos::inOutArg(ifpack_precOp), Teuchos::POST_DESTROY, false); // // Initialize the output EpetraLinearOp // if(startingOver) { epetra_precOp = rcp(new EpetraLinearOp); } epetra_precOp->initialize( ifpack_precOp ,epetraFwdOpTransp ,EPETRA_OP_APPLY_APPLY_INVERSE ,EPETRA_OP_ADJOINT_SUPPORTED ); if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_MEDIUM)) { *out << "\nDescription of created preconditioner:\n"; OSTab tab(out); ifpack_precOp->Print(*out); } // // Initialize the preconditioner // defaultPrec->initializeUnspecified( Teuchos::rcp_implicit_cast<LinearOpBase<double> >(epetra_precOp) ); totalTimer.stop(); if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) *out << "\nTotal time in IfpackPreconditionerFactory = "<<totalTimer.totalElapsedTime()<<" sec\n"; if(out.get() && implicit_cast<int>(verbLevel) > implicit_cast<int>(Teuchos::VERB_LOW)) *out << "\nLeaving Thyra::IfpackPreconditionerFactory::initializePrec(...) ...\n"; }
void MLPreconditionerFactory::initializePrec( const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc, PreconditionerBase<double> *prec, const ESupportSolveUse supportSolveUse ) const { using Teuchos::outArg; using Teuchos::OSTab; using Teuchos::dyn_cast; using Teuchos::RCP; using Teuchos::null; using Teuchos::rcp; using Teuchos::rcp_dynamic_cast; using Teuchos::rcp_const_cast; using Teuchos::set_extra_data; using Teuchos::get_optional_extra_data; using Teuchos::implicit_cast; Teuchos::Time totalTimer(""), timer(""); totalTimer.start(true); const RCP<Teuchos::FancyOStream> out = this->getOStream(); const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel(); Teuchos::OSTab tab(out); if(out.get() && implicit_cast<int>(verbLevel) > implicit_cast<int>(Teuchos::VERB_LOW)) *out << "\nEntering Thyra::MLPreconditionerFactory::initializePrec(...) ...\n"; Teuchos::RCP<const LinearOpBase<double> > fwdOp = fwdOpSrc->getOp(); #ifdef _DEBUG TEUCHOS_TEST_FOR_EXCEPT(fwdOp.get()==NULL); TEUCHOS_TEST_FOR_EXCEPT(prec==NULL); #endif // // Unwrap and get the forward Epetra_Operator object // Teuchos::RCP<const Epetra_Operator> epetraFwdOp; EOpTransp epetraFwdOpTransp; EApplyEpetraOpAs epetraFwdOpApplyAs; EAdjointEpetraOp epetraFwdOpAdjointSupport; double epetraFwdOpScalar; epetraFwdOpViewExtractor_->getEpetraOpView( fwdOp,outArg(epetraFwdOp),outArg(epetraFwdOpTransp),outArg(epetraFwdOpApplyAs), outArg(epetraFwdOpAdjointSupport),outArg(epetraFwdOpScalar) ); // Validate what we get is what we need RCP<const Epetra_RowMatrix> epetraFwdRowMat = rcp_dynamic_cast<const Epetra_RowMatrix>(epetraFwdOp,true); TEUCHOS_TEST_FOR_EXCEPTION( epetraFwdOpApplyAs != EPETRA_OP_APPLY_APPLY, std::logic_error ,"Error, incorrect apply mode for an Epetra_RowMatrix" ); // // Get the concrete preconditioner object // DefaultPreconditioner<double> *defaultPrec = &Teuchos::dyn_cast<DefaultPreconditioner<double> >(*prec); // // Get the EpetraLinearOp object that is used to implement the preconditoner linear op // RCP<EpetraLinearOp> epetra_precOp = rcp_dynamic_cast<EpetraLinearOp>(defaultPrec->getNonconstUnspecifiedPrecOp(),true); // // Get the embedded ML_Epetra::MultiLevelPreconditioner object if it exists // Teuchos::RCP<ML_Epetra::MultiLevelPreconditioner> ml_precOp; if(epetra_precOp.get()) ml_precOp = rcp_dynamic_cast<ML_Epetra::MultiLevelPreconditioner>(epetra_precOp->epetra_op(),true); // // Get the attached forward operator if it exists and make sure that it matches // if(ml_precOp!=Teuchos::null) { // Get the forward operator and make sure that it matches what is // already being used! const Epetra_RowMatrix & rm = ml_precOp->RowMatrix(); TEUCHOS_TEST_FOR_EXCEPTION( &rm!=&*epetraFwdRowMat, std::logic_error ,"ML requires Epetra_RowMatrix to be the same for each initialization of the preconditioner" ); } // // Perform initialization if needed // const bool startingOver = (ml_precOp.get() == NULL); if(startingOver) { if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) *out << "\nCreating the initial ML_Epetra::MultiLevelPreconditioner object...\n"; timer.start(true); // Create the initial preconditioner: DO NOT compute it yet ml_precOp = rcp( new ML_Epetra::MultiLevelPreconditioner( *epetraFwdRowMat, paramList_->sublist(MLSettings_name),false ) ); timer.stop(); if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) OSTab(out).o() <<"> Creation time = "<<timer.totalElapsedTime()<<" sec\n"; // RAB: Above, I am just passing a string to ML::Create(...) in order // get this code written. However, in the future, it would be good to // copy the contents of what is in ML::Create(...) into a local // function and then use switch(...) to create the initial // ML_Epetra::MultiLevelPreconditioner object. This would result in better validation // and faster code. // Set parameters if the list exists if(paramList_.get()) TEUCHOS_TEST_FOR_EXCEPT( 0!=ml_precOp->SetParameterList(paramList_->sublist(MLSettings_name)) ); // Initialize the structure for the preconditioner // TEUCHOS_TEST_FOR_EXCEPT(0!=ml_precOp->Initialize()); } // // Attach the epetraFwdOp to the ml_precOp to guarantee that it will not go away // set_extra_data(epetraFwdOp, "IFPF::epetraFwdOp", Teuchos::inOutArg(ml_precOp), Teuchos::POST_DESTROY, false); // // Update the factorization // if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) *out << "\nComputing the preconditioner ...\n"; timer.start(true); if (startingOver) { TEUCHOS_TEST_FOR_EXCEPT(0!=ml_precOp->ComputePreconditioner()); } else { TEUCHOS_TEST_FOR_EXCEPT(0!=ml_precOp->ReComputePreconditioner(paramList_->get<bool>(ReuseFineLevelSmoother_name))); } timer.stop(); if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) OSTab(out).o() <<"=> Setup time = "<<timer.totalElapsedTime()<<" sec\n"; // // Compute the conditioner number estimate if asked // // ToDo: Implement // // Attach fwdOp to the ml_precOp // set_extra_data(fwdOp, "IFPF::fwdOp", Teuchos::inOutArg(ml_precOp), Teuchos::POST_DESTROY, false); // // Initialize the output EpetraLinearOp // if(startingOver) { epetra_precOp = rcp(new EpetraLinearOp); } epetra_precOp->initialize( ml_precOp ,epetraFwdOpTransp ,EPETRA_OP_APPLY_APPLY_INVERSE ,EPETRA_OP_ADJOINT_UNSUPPORTED // ToDo: Look into adjoints again. ); // // Initialize the preconditioner // defaultPrec->initializeUnspecified( Teuchos::rcp_implicit_cast<LinearOpBase<double> >(epetra_precOp) ); totalTimer.stop(); if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) *out << "\nTotal time in MLPreconditionerFactory = "<<totalTimer.totalElapsedTime()<<" sec\n"; if(out.get() && implicit_cast<int>(verbLevel) > implicit_cast<int>(Teuchos::VERB_LOW)) *out << "\nLeaving Thyra::MLPreconditionerFactory::initializePrec(...) ...\n"; }
void MueLuPreconditionerFactory::initializePrec( const Teuchos::RCP<const LinearOpSourceBase<double> > &fwdOpSrc, PreconditionerBase<double> *prec, const ESupportSolveUse supportSolveUse ) const { using Teuchos::outArg; using Teuchos::OSTab; using Teuchos::dyn_cast; using Teuchos::RCP; using Teuchos::null; using Teuchos::rcp; using Teuchos::rcp_dynamic_cast; using Teuchos::rcp_const_cast; using Teuchos::set_extra_data; using Teuchos::get_optional_extra_data; using Teuchos::implicit_cast; typedef KokkosClassic::DefaultNode::DefaultNodeType NO; typedef KokkosClassic::DefaultKernels<double,int,NO>::SparseOps LMO; Teuchos::Time totalTimer(""), timer(""); totalTimer.start(true); const RCP<Teuchos::FancyOStream> out = this->getOStream(); const Teuchos::EVerbosityLevel verbLevel = this->getVerbLevel(); Teuchos::OSTab tab(out); if(out.get() && implicit_cast<int>(verbLevel) > implicit_cast<int>(Teuchos::VERB_LOW)) *out << "\nEntering Thyra::MueLuPreconditionerFactory::initializePrec(...) ...\n"; Teuchos::RCP<const LinearOpBase<double> > fwdOp = fwdOpSrc->getOp(); #ifdef _DEBUG TEUCHOS_TEST_FOR_EXCEPT(fwdOp.get()==NULL); TEUCHOS_TEST_FOR_EXCEPT(prec==NULL); #endif // // Unwrap and get the forward Epetra_Operator object // Teuchos::RCP<const Epetra_Operator> epetraFwdOp; EOpTransp epetraFwdOpTransp; EApplyEpetraOpAs epetraFwdOpApplyAs; EAdjointEpetraOp epetraFwdOpAdjointSupport; double epetraFwdOpScalar; epetraFwdOpViewExtractor_->getEpetraOpView( fwdOp,outArg(epetraFwdOp),outArg(epetraFwdOpTransp),outArg(epetraFwdOpApplyAs), outArg(epetraFwdOpAdjointSupport),outArg(epetraFwdOpScalar) ); // Validate what we get is what we need RCP<const Epetra_CrsMatrix> epetraFwdCrsMat = rcp_dynamic_cast<const Epetra_CrsMatrix>(epetraFwdOp,true); TEUCHOS_TEST_FOR_EXCEPTION( epetraFwdOpApplyAs != EPETRA_OP_APPLY_APPLY, std::logic_error ,"Error, incorrect apply mode for an Epetra_CrsMatrix" ); // // Get the concrete preconditioner object // DefaultPreconditioner<double> *defaultPrec = &Teuchos::dyn_cast<DefaultPreconditioner<double> >(*prec); // // Get the EpetraLinearOp object that is used to implement the preconditoner linear op // RCP<EpetraLinearOp> epetra_precOp = rcp_dynamic_cast<EpetraLinearOp>(defaultPrec->getNonconstUnspecifiedPrecOp(),true); // // Get the embedded MueLu::EpetraOperator object if it exists // Teuchos::RCP<MueLu::EpetraOperator> muelu_precOp; if(epetra_precOp.get()) muelu_precOp = rcp_dynamic_cast<MueLu::EpetraOperator>(epetra_precOp->epetra_op(),true); // // Get the attached forward operator if it exists and make sure that it matches // if(muelu_precOp!=Teuchos::null) { // TODO // // Get the forward operator and make sure that it matches what is // // already being used! // const Epetra_CrsMatrix & rm = muelu_precOp->CrsMatrix(); // TEUCHOS_TEST_FOR_EXCEPTION( // &rm!=&*epetraFwdRowMat, std::logic_error // ,"MueLu requires Epetra_RowMatrix to be the same for each initialization of the preconditioner" // ); } MueLu::ParameterListInterpreter<double, int, int, NO, LMO> mueluFactory(*paramList_); // // Perform initialization if needed // const bool startingOver = (muelu_precOp.get() == NULL); if(startingOver) { if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) *out << "\nCreating the initial MueLu::EpetraOperator object...\n"; timer.start(true); // Create the initial preconditioner: DO NOT compute it yet // Turns a Epetra_CrsMatrix into a Xpetra::Matrix RCP<Epetra_CrsMatrix> epetraFwdCrsMatNonConst = rcp_const_cast<Epetra_CrsMatrix>(epetraFwdCrsMat); // !! TODO: MueLu interface should accept const matrix as input. RCP<Xpetra::CrsMatrix<double, int, int, NO, LMO> > mueluAcrs = rcp(new Xpetra::EpetraCrsMatrix(epetraFwdCrsMatNonConst)); //TODO: should not be needed RCP<Xpetra::Matrix <double, int, int, NO, LMO> > mueluA = rcp(new Xpetra::CrsMatrixWrap<double, int, int, NO, LMO>(mueluAcrs)); const RCP<MueLu::Hierarchy<double,int, int, NO, LMO > > muelu_hierarchy = mueluFactory.CreateHierarchy(); muelu_hierarchy->GetLevel(0)->Set("A", mueluA); muelu_precOp = rcp(new MueLu::EpetraOperator(muelu_hierarchy)); timer.stop(); if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) OSTab(out).o() <<"> Creation time = "<<timer.totalElapsedTime()<<" sec\n"; // if(paramList_.get()) // TEUCHOS_TEST_FOR_EXCEPT( // 0!=muelu_precOp->SetParameterList(paramList_->sublist(MueLuSettings_name)) // ); } // // Attach the epetraFwdOp to the muelu_precOp to guarantee that it will not go away // set_extra_data(epetraFwdOp, "IFPF::epetraFwdOp", Teuchos::inOutArg(muelu_precOp), Teuchos::POST_DESTROY, false); // // Update the factorization // if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) *out << "\nComputing the preconditioner ...\n"; timer.start(true); mueluFactory.SetupHierarchy(*muelu_precOp->GetHierarchy()); timer.stop(); if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) OSTab(out).o() <<"=> Setup time = "<<timer.totalElapsedTime()<<" sec\n"; // // Compute the conditioner number estimate if asked // // ToDo: Implement // // Attach fwdOp to the muelu_precOp // set_extra_data(fwdOp, "IFPF::fwdOp", Teuchos::inOutArg(muelu_precOp), Teuchos::POST_DESTROY, false); // // Initialize the output EpetraLinearOp // if(startingOver) { epetra_precOp = rcp(new EpetraLinearOp); } epetra_precOp->initialize( muelu_precOp ,epetraFwdOpTransp ,EPETRA_OP_APPLY_APPLY_INVERSE ,EPETRA_OP_ADJOINT_UNSUPPORTED // ToDo: Look into adjoints again. ); // // Initialize the preconditioner // defaultPrec->initializeUnspecified( Teuchos::rcp_implicit_cast<LinearOpBase<double> >(epetra_precOp) ); totalTimer.stop(); if(out.get() && implicit_cast<int>(verbLevel) >= implicit_cast<int>(Teuchos::VERB_LOW)) *out << "\nTotal time in MLPreconditionerFactory = "<<totalTimer.totalElapsedTime()<<" sec\n"; if(out.get() && implicit_cast<int>(verbLevel) > implicit_cast<int>(Teuchos::VERB_LOW)) *out << "\nLeaving Thyra::MLPreconditionerFactory::initializePrec(...) ...\n"; }