Thyra_MLPreconditionerFactory.cpp
Go to the documentation of this file.
00001 /*@HEADER
00002 // ***********************************************************************
00003 // 
00004 //       Ifpack: Object-Oriented Algebraic Preconditioner Package
00005 //                 Copyright (2002) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 //@HEADER
00028 */
00029 
00030 #include "Thyra_MLPreconditionerFactory.hpp"
00031 
00032 #ifndef TRILINOS_6
00033 
00034 #include "Thyra_EpetraOperatorViewExtractorStd.hpp"
00035 #include "Thyra_EpetraLinearOp.hpp"
00036 #include "Thyra_DefaultPreconditioner.hpp"
00037 #include "ml_MultiLevelPreconditioner.h"
00038 #include "ml_MultiLevelOperator.h"
00039 #include "Epetra_RowMatrix.h"
00040 #include "Teuchos_dyn_cast.hpp"
00041 
00042 using namespace Thyra ;
00043 
00044 
00045 // Constructors/initializers/accessors
00046   
00047 MLPreconditionerFactory
00048 ::MLPreconditionerFactory(const RCP<ParameterList>& params)
00049   :epetraFwdOpViewExtractor_(Teuchos::rcp(new EpetraOperatorViewExtractorStd())),
00050    paramList_(params)
00051 {}
00052   
00053 MLPreconditionerFactory
00054 ::MLPreconditionerFactory(const EMLProblemType& probType,
00055                           const ParameterList& revisions)
00056   :epetraFwdOpViewExtractor_(Teuchos::rcp(new EpetraOperatorViewExtractorStd())),
00057    paramList_(reviseDefaultList(*defaultParameters(probType), revisions))
00058 {}
00059   
00060 MLPreconditionerFactory
00061 ::MLPreconditionerFactory(const std::string& probType,
00062                           const ParameterList& revisions)
00063   : epetraFwdOpViewExtractor_(Teuchos::rcp(new EpetraOperatorViewExtractorStd())),
00064     paramList_(reviseDefaultList(*defaultParameters(probType), revisions))
00065 {}
00066   
00067 std::string MLPreconditionerFactory
00068 ::probToString(const EMLProblemType& probType) const
00069 {
00070   switch(probType)
00071     {
00072     case ML_Maxwell:
00073       return "maxwell";
00074     case ML_DomainDecomposition:
00075       return "DD";
00076     case ML_DomainDecompositionML:
00077       return "DD-ML";
00078     default:
00079       return "SA";
00080     }
00081 }
00082   
00083 RCP<ParameterList> MLPreconditionerFactory
00084 ::defaultParameters(const EMLProblemType& probType) const 
00085 {
00086   return defaultParameters(probToString(probType));
00087 }
00088 
00089   
00090 RCP<ParameterList> MLPreconditionerFactory
00091 ::defaultParameters(const std::string& probType) const 
00092 {
00093   RCP<ParameterList> rtn = rcp(new ParameterList());
00094   int err = ML_Epetra::SetDefaults(probType, *rtn);
00095   TEST_FOR_EXCEPTION(err != 0, std::runtime_error,
00096                      "unable to find default parameters for problem type "
00097                      << probType);
00098   return rtn;
00099 }
00100 
00101 
00102 // Overridden from PreconditionerFactoryBase
00103 
00104 bool MLPreconditionerFactory::isCompatible( const LinearOpBase<double> &fwdOp ) const
00105 {
00106   Teuchos::RCP<const Epetra_Operator> epetraFwdOp;
00107   EOpTransp                                     epetraFwdOpTransp;
00108   EApplyEpetraOpAs                            epetraFwdOpApplyAs;
00109   EAdjointEpetraOp                            epetraFwdOpAdjointSupport;
00110   double                                      epetraFwdOpScalar;
00111   epetraFwdOpViewExtractor_->getEpetraOpView(
00112                                              Teuchos::rcp(&fwdOp,false)
00113                                              ,&epetraFwdOp,&epetraFwdOpTransp,
00114                                              &epetraFwdOpApplyAs,
00115                                              &epetraFwdOpAdjointSupport,
00116                                              &epetraFwdOpScalar
00117                                              );
00118   if( !dynamic_cast<const Epetra_RowMatrix*>(&*epetraFwdOp) )
00119     return false;
00120   return true;
00121 }
00122 
00123 bool MLPreconditionerFactory::applySupportsConj(EConj conj) const
00124 {
00125   return true;
00126 }
00127 
00128 bool MLPreconditionerFactory::applyTransposeSupportsConj(EConj conj) const
00129 {
00130   return false; // See comment below
00131 }
00132 
00133 Teuchos::RCP<PreconditionerBase<double> >
00134 MLPreconditionerFactory::createPrec() const
00135 {
00136   return Teuchos::rcp(new DefaultPreconditioner<double>());
00137 }
00138 
00139 void MLPreconditionerFactory::initializePrec(
00140                                              const Teuchos::RCP<const LinearOpBase<double> >    &fwdOp
00141                                              ,PreconditionerBase<double>                                *prec
00142                                              ,const ESupportSolveUse                                    supportSolveUse
00143                                              ) const
00144 {
00145   using Teuchos::OSTab;
00146   using Teuchos::dyn_cast;
00147   using Teuchos::RefCountPtr;
00148   using Teuchos::null;
00149   using Teuchos::rcp;
00150   using Teuchos::rcp_dynamic_cast;
00151   using Teuchos::rcp_const_cast;
00152   using Teuchos::set_extra_data;
00153   using Teuchos::get_optional_extra_data;
00154   Teuchos::Time totalTimer(""), timer("");
00155   totalTimer.start(true);
00156   const Teuchos::RCP<Teuchos::FancyOStream> out       = this->getOStream();
00157   const Teuchos::EVerbosityLevel                    verbLevel = this->getVerbLevel();
00158   Teuchos::OSTab tab(out);
00159   if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW))
00160     *out << "\nEntering Thyra::MLPreconditionerFactory::initializePrec(...) ...\n";
00161 #ifdef _DEBUG
00162   TEST_FOR_EXCEPT(fwdOp.get()==NULL);
00163   TEST_FOR_EXCEPT(prec==NULL);
00164 #endif
00165   //
00166   // Unwrap and get the forward Epetra_Operator object
00167   //
00168   Teuchos::RCP<const Epetra_Operator> epetraFwdOp;
00169   EOpTransp                                     epetraFwdOpTransp;
00170   EApplyEpetraOpAs                            epetraFwdOpApplyAs;
00171   EAdjointEpetraOp                            epetraFwdOpAdjointSupport;
00172   double                                      epetraFwdOpScalar;
00173   epetraFwdOpViewExtractor_->getEpetraOpView(
00174                                              fwdOp,&epetraFwdOp,&epetraFwdOpTransp,&epetraFwdOpApplyAs,&epetraFwdOpAdjointSupport,&epetraFwdOpScalar
00175                                              );
00176   // Validate what we get is what we need
00177   RCP<const Epetra_RowMatrix>
00178     epetraFwdRowMat = rcp_dynamic_cast<const Epetra_RowMatrix>(epetraFwdOp,true);
00179   TEST_FOR_EXCEPTION(
00180                      epetraFwdOpApplyAs != EPETRA_OP_APPLY_APPLY, std::logic_error
00181                      ,"Error, incorrect apply mode for an Epetra_RowMatrix"
00182                      );
00183   //
00184   // Get the concrete precondtioner object
00185   //
00186   DefaultPreconditioner<double>
00187     *defaultPrec = &Teuchos::dyn_cast<DefaultPreconditioner<double> >(*prec);
00188   //
00189   // Get the EpetraLinearOp object that is used to implement the preconditoner linear op
00190   //
00191   RCP<EpetraLinearOp>
00192     epetra_precOp = rcp_dynamic_cast<EpetraLinearOp>(defaultPrec->getNonconstUnspecifiedPrecOp(),true);
00193   //
00194   // Get the embedded ML_Epetra::MultiLevelPreconditioner object if it exists
00195   //
00196   Teuchos::RCP<ML_Epetra::MultiLevelPreconditioner> ml_precOp;
00197   if(epetra_precOp.get())
00198     ml_precOp = rcp_dynamic_cast<ML_Epetra::MultiLevelPreconditioner>(epetra_precOp->epetra_op(),true);
00199   //
00200   // Get the attached forward operator if it exists and make sure that it matches
00201   //
00202   if(ml_precOp.get()) {
00203     // ToDo: Get the forward operator and make sure that it matches what is
00204     // already being used!
00205   }
00206   //
00207   // Permform initialization if needed
00208   //
00209   const bool startingOver = (ml_precOp.get() == NULL);
00210   if(startingOver) 
00211     {
00212       if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW))
00213         *out << "\nCreating the initial ML_Epetra::MultiLevelPreconditioner object...\n";
00214       timer.start(true);
00215       // Create the initial preconditioner
00216       ml_precOp = rcp(new ML_Epetra::MultiLevelPreconditioner(*epetraFwdRowMat,
00217                                                               *paramList_));
00218       
00219       timer.stop();
00220       if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW))
00221         *OSTab(out).getOStream() <<"\n=> Creation time = "<<timer.totalElapsedTime()<<" sec\n";
00222       // RAB: Above, I am just passing a std::string to ML::Create(...) in order
00223       // get this code written.  However, in the future, it would be good to
00224       // copy the contents of what is in ML::Create(...) into a local
00225       // function and then use switch(...) to create the initial
00226       // ML_Epetra::MultiLevelPreconditioner object.  This would result in better validation
00227       // and faster code.
00228       // Set parameters if the list exists
00229       if(paramList_.get())
00230         TEST_FOR_EXCEPT(0!=ml_precOp->SetParameterList(*paramList_)); // This will create new sublist if it does not exist!
00231       // Initailize the structure for the preconditioner
00232       //      TEST_FOR_EXCEPT(0!=ml_precOp->Initialize());
00233     }
00234   //
00235   // Attach the epetraFwdOp to the ml_precOp to guarantee that it will not go away
00236   //
00237   set_extra_data(epetraFwdOp, "IFPF::epetraFwdOp", Teuchos::inOutArg(ml_precOp),
00238     Teuchos::POST_DESTROY, false);
00239   //
00240   // Update the factorization
00241   //
00242   if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW))
00243     *out << "\nComputing the factorization of the preconditioner ...\n";
00244   timer.start(true);
00245   TEST_FOR_EXCEPT(0!=ml_precOp->ComputePreconditioner());
00246   timer.stop();
00247   if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW))
00248     *OSTab(out).getOStream() <<"\n=> Factorization time = "<<timer.totalElapsedTime()<<" sec\n";
00249   //
00250   // Compute the conditioner number estimate if asked
00251   //
00252 
00253   // ToDo: Implement
00254 
00255   //
00256   // Attach fwdOp to the ml_precOp
00257   //
00258   set_extra_data(fwdOp, "IFPF::fwdOp", Teuchos::inOutArg(ml_precOp),
00259     Teuchos::POST_DESTROY, false);
00260   //
00261   // Initialize the output EpetraLinearOp
00262   //
00263   if(startingOver) {
00264     epetra_precOp = rcp(new EpetraLinearOp);
00265   }
00266   epetra_precOp->initialize(
00267                             ml_precOp
00268                             ,epetraFwdOpTransp
00269                             ,EPETRA_OP_APPLY_APPLY_INVERSE
00270                             ,EPETRA_OP_ADJOINT_UNSUPPORTED  // ToDo: Look into adjoints again.
00271                             );
00272   //
00273   // Initialize the preconditioner
00274   //
00275   defaultPrec->initializeUnspecified(
00276                                      Teuchos::rcp_implicit_cast<LinearOpBase<double> >(epetra_precOp)
00277                                      );
00278   totalTimer.stop();
00279   if(out.get() && static_cast<int>(verbLevel) >= static_cast<int>(Teuchos::VERB_LOW))
00280     *out
00281       << "\nTotal time = "<<totalTimer.totalElapsedTime()<<" sec\n"
00282       << "\nLeaving Thyra::MLPreconditionerFactory::initializePrec(...) ...\n";
00283 }
00284 
00285 void MLPreconditionerFactory::uninitializePrec(
00286                                                PreconditionerBase<double>                          *prec
00287                                                ,Teuchos::RCP<const LinearOpBase<double> >  *fwdOp
00288                                                ,ESupportSolveUse                                   *supportSolveUse
00289                                                ) const
00290 {
00291   TEST_FOR_EXCEPT(true);
00292 }
00293 
00294 // Overridden from ParameterListAcceptor
00295 
00296 void MLPreconditionerFactory::setParameterList(Teuchos::RCP<Teuchos::ParameterList> const& paramList)
00297 {
00298   TEST_FOR_EXCEPT(paramList.get()==NULL);
00299   // Don't know how to validate an ML list
00300   //  paramList->validateParameters(*this->getValidParameters(),1);
00301   paramList_ = paramList;
00302 }
00303 
00304 Teuchos::RCP<Teuchos::ParameterList>
00305 MLPreconditionerFactory::getNonconstParameterList()
00306 {
00307   return paramList_;
00308 }
00309 
00310 Teuchos::RCP<Teuchos::ParameterList>
00311 MLPreconditionerFactory::unsetParameterList()
00312 {
00313   Teuchos::RCP<Teuchos::ParameterList> _paramList = paramList_;
00314   paramList_ = Teuchos::null;
00315   return _paramList;
00316 }
00317 
00318 Teuchos::RCP<const Teuchos::ParameterList>
00319 MLPreconditionerFactory::getParameterList() const
00320 {
00321   return paramList_;
00322 }
00323 
00324 
00325 // Public functions overridden from Teuchos::Describable
00326 
00327 std::string MLPreconditionerFactory::description() const
00328 {
00329   std::ostringstream oss;
00330   oss << "Thyra::MLPreconditionerFactory";
00331   return oss.str();
00332 }
00333 
00334 RCP<ParameterList> MLPreconditionerFactory
00335 ::reviseDefaultList(const ParameterList& defaults, const ParameterList& revisions) const
00336 {
00337   RCP<ParameterList> rtn = rcp(new ParameterList(defaults));
00338 
00339   for (ParameterList::ConstIterator i=revisions.begin(); i != revisions.end(); i++)
00340     {
00341       rtn->setEntry(revisions.name(i), revisions.entry(i));
00342     }
00343   return rtn;
00344 }
00345 
00346 #endif

Site Contact