Thyra_DefaultRealLinearSolverBuilder.cpp

00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //         Stratimikos: Thyra-based strategies for linear solvers
00005 //                Copyright (2006) 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 Roscoe A. Bartlett (rabartl@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 //#define THYRA_DEFAULT_REAL_LINEAR_SOLVER_BUILDER_DUMP
00030 
00031 #include "Thyra_DefaultRealLinearSolverBuilder.hpp"
00032 #include "Teuchos_AbstractFactoryStd.hpp"
00033 #include "Teuchos_CommandLineProcessor.hpp"
00034 #include "Teuchos_XMLParameterListHelpers.hpp"
00035 #include "Teuchos_GlobalMPISession.hpp"
00036 
00037 #ifdef HAVE_STRATIMIKOS_AMESOS_THYRA
00038 #  include "Thyra_AmesosLinearOpWithSolveFactory.hpp"
00039 #endif
00040 #ifdef HAVE_STRATIMIKOS_AZTECOO_THYRA
00041 #  include "Thyra_AztecOOLinearOpWithSolveFactory.hpp"
00042 #endif
00043 #ifdef HAVE_STRATIMIKOS_BELOS_THYRA
00044 #  include "Thyra_BelosLinearOpWithSolveFactory.hpp"
00045 #endif
00046 #ifdef HAVE_STRATIMIKOS_IFPACK_THYRA
00047 #  include "Thyra_IfpackPreconditionerFactory.hpp"
00048 #endif
00049 #ifdef HAVE_STRATIMIKOS_ML_THYRA
00050 #  include "Thyra_MLPreconditionerFactory.hpp"
00051 #endif
00052 
00053 namespace {
00054 
00055 const std::string LinearSolverType_name    = "Linear Solver Type";
00056 const std::string LinearSolverTypes_name   = "Linear Solver Types";
00057 const std::string PreconditionerType_name    = "Preconditioner Type";
00058 const std::string PreconditionerTypes_name   = "Preconditioner Types";
00059 
00060 } // namespace 
00061 
00062 namespace Thyra {
00063 
00064 // Constructors/Initializers/Accessors
00065 
00066 DefaultRealLinearSolverBuilder::DefaultRealLinearSolverBuilder(
00067   const std::string    &paramsXmlFileName
00068   ,const std::string   &extraParamsXmlString
00069   ,const std::string   &paramsUsedXmlOutFileName
00070   ,const std::string   &paramsXmlFileNameOption
00071   ,const std::string   &extraParamsXmlStringOption
00072   ,const std::string   &paramsUsedXmlOutFileNameOption
00073   )
00074   :paramsXmlFileName_(paramsXmlFileName)
00075    ,extraParamsXmlString_(extraParamsXmlString)
00076    ,paramsUsedXmlOutFileName_(paramsUsedXmlOutFileName)
00077    ,paramsXmlFileNameOption_(paramsXmlFileNameOption)
00078    ,extraParamsXmlStringOption_(extraParamsXmlStringOption)
00079    ,paramsUsedXmlOutFileNameOption_(paramsUsedXmlOutFileNameOption)
00080 {
00081   this->initializeDefaults();
00082 }
00083 
00084 DefaultRealLinearSolverBuilder::~DefaultRealLinearSolverBuilder()
00085 {
00086 #ifdef TEUCHOS_DEBUG
00087   // Validate that we read the parameters correctly!
00088   if(paramList_.get())
00089     paramList_->validateParameters(*this->getValidParameters(),0);
00090 #endif    
00091 }
00092 
00093 void DefaultRealLinearSolverBuilder::setLinearSolveStrategyFactory(
00094   const Teuchos::RefCountPtr<const Teuchos::AbstractFactory<LinearOpWithSolveFactoryBase<double> > >  &solveStrategyFactory
00095   ,const std::string                                                                                  &solveStrategyName
00096   )
00097 {
00098   lowsf_map_[solveStrategyName] = solveStrategyFactory;
00099   validLowsfNames_.push_back(solveStrategyName);
00100   defaultLOWSF_ = solveStrategyName;
00101   validParamList_ = Teuchos::null;
00102 }
00103 
00104 void DefaultRealLinearSolverBuilder::setPreconditioningStrategyFactory(
00105   const Teuchos::RefCountPtr<const Teuchos::AbstractFactory<PreconditionerFactoryBase<double> > >     &precStrategyFactory
00106   ,const std::string                                                                                  &precStrategyName
00107   )
00108 {
00109   pf_map_[precStrategyName] = precStrategyFactory;
00110   validPfNames_.push_back(precStrategyName);
00111   defaultPF_ = precStrategyName;
00112   validParamList_ = Teuchos::null;
00113 }
00114 
00115 void DefaultRealLinearSolverBuilder::setupCLP( Teuchos::CommandLineProcessor *clp )
00116 {
00117   TEST_FOR_EXCEPT(clp==NULL);
00118   clp->setOption(
00119     paramsXmlFileNameOption().c_str(),&paramsXmlFileName_
00120     ,"Name of an XML file containing parameters for linear solver options to be appended first."
00121     );
00122   clp->setOption(
00123     extraParamsXmlStringOption().c_str(),&extraParamsXmlString_
00124     ,"An XML string containing linear solver parameters to be appended second."
00125     );
00126   clp->setOption(
00127     paramsUsedXmlOutFileNameOption().c_str(),&paramsUsedXmlOutFileName_
00128     ,"Name of an XML file that can be written with the parameter list after it has been used on completion of this program."
00129     );
00130 }
00131 
00132 void DefaultRealLinearSolverBuilder::readParameters( std::ostream *out )
00133 {
00134   if(!paramList_.get())
00135     paramList_ = Teuchos::rcp(new Teuchos::ParameterList("DefaultRealLinearSolverBuilder"));
00136   if(paramsXmlFileName().length()) {
00137     if(out) *out << "\nReading parameters from XML file \""<<paramsXmlFileName()<<"\" ...\n";
00138     Teuchos::updateParametersFromXmlFile(paramsXmlFileName(),&*paramList_);
00139   }
00140   if(extraParamsXmlString().length()) {
00141     if(out) *out << "\nAppending extra parameters from the XML string \""<<extraParamsXmlString()<<"\" ...\n";
00142     Teuchos::updateParametersFromXmlString(extraParamsXmlString(),&*paramList_);
00143   }
00144 }
00145 
00146 void DefaultRealLinearSolverBuilder::writeParamsFile(
00147   const LinearOpWithSolveFactoryBase<double>   &lowsFactory
00148   ,const std::string                           &outputXmlFileName
00149   ) const
00150 {
00151   TEST_FOR_EXCEPT(!paramList_.get());
00152   std::string xmlOutputFile
00153     = ( outputXmlFileName.length() ? outputXmlFileName : paramsUsedXmlOutFileName() );
00154   if(xmlOutputFile.length()) {
00155     Teuchos::writeParameterListToXmlFile(*paramList_,xmlOutputFile);
00156   }
00157 }
00158 
00159 std::string
00160 DefaultRealLinearSolverBuilder::getLinearSolveStrategyName() const
00161 {
00162   TEST_FOR_EXCEPT(!paramList_.get());
00163   return paramList_->get(LinearSolverType_name,defaultLOWSF_);
00164 }
00165 
00166 std::string
00167 DefaultRealLinearSolverBuilder::getPreconditionerStrategyName() const
00168 {
00169   TEST_FOR_EXCEPT(!paramList_.get());
00170   return paramList_->get(PreconditionerType_name,defaultPF_);
00171 }
00172 
00173 
00174 // Overridden from ParameterListAcceptor
00175 
00176 void DefaultRealLinearSolverBuilder::setParameterList(
00177   Teuchos::RefCountPtr<Teuchos::ParameterList> const& paramList
00178   )
00179 {
00180   TEST_FOR_EXCEPT(!paramList.get());
00181   // Only validate this level of parameters and sublists
00182   paramList->validateParameters(*this->getValidParameters(),0);
00183   paramList_ = paramList;
00184 }
00185 
00186 Teuchos::RefCountPtr<Teuchos::ParameterList>
00187 DefaultRealLinearSolverBuilder::getParameterList()
00188 {
00189   return paramList_;
00190 }
00191 
00192 Teuchos::RefCountPtr<Teuchos::ParameterList>
00193 DefaultRealLinearSolverBuilder::unsetParameterList()
00194 {
00195   Teuchos::RefCountPtr<Teuchos::ParameterList> _paramList = paramList_;
00196   paramList_ = Teuchos::null;
00197   return _paramList;
00198 }
00199 
00200 Teuchos::RefCountPtr<const Teuchos::ParameterList>
00201 DefaultRealLinearSolverBuilder::getParameterList() const
00202 {
00203   return paramList_;
00204 }
00205 
00206 Teuchos::RefCountPtr<const Teuchos::ParameterList>
00207 DefaultRealLinearSolverBuilder::getValidParameters() const
00208 {
00209   if(!validParamList_.get()) {
00210     Teuchos::RefCountPtr<Teuchos::ParameterList>
00211       validParamList = Teuchos::rcp(new Teuchos::ParameterList);
00212     // Linear Solver Types
00213     validParamList->set(LinearSolverType_name,defaultLOWSF_);
00214     Teuchos::RefCountPtr<Teuchos::ParameterList>
00215       linearSolverTypesSL = sublist(validParamList,LinearSolverTypes_name);
00216     for(
00217       lowsf_map_t::const_iterator itr = lowsf_map_.begin();
00218       itr != lowsf_map_.end();
00219       ++itr
00220       )
00221     {
00222       const std::string
00223         &name = itr->first;
00224       const Teuchos::RefCountPtr<LinearOpWithSolveFactoryBase<double> >
00225         lowsf = itr->second->create();
00226       linearSolverTypesSL->sublist(name).setParameters(*lowsf->getValidParameters());
00227     }
00228     // Preconditioner Type
00229     validParamList->set(PreconditionerType_name,defaultPF_);
00230     Teuchos::RefCountPtr<Teuchos::ParameterList>
00231       precTypesSL = sublist(validParamList,PreconditionerTypes_name);
00232     for(
00233       pf_map_t::const_iterator itr = pf_map_.begin();
00234       itr != pf_map_.end();
00235       ++itr
00236       )
00237     {
00238       const std::string
00239         &name = itr->first;
00240       const Teuchos::RefCountPtr<PreconditionerFactoryBase<double> >
00241         pf = itr->second->create();
00242       precTypesSL->sublist(name).setParameters(*pf->getValidParameters());
00243     }
00244     validParamList_ = validParamList;
00245   }
00246   return validParamList_;
00247 }
00248   
00249 // Overridden from LinearSolverBuilderBase.
00250 
00251 Teuchos::RefCountPtr<LinearOpWithSolveFactoryBase<double> >
00252 DefaultRealLinearSolverBuilder::createLinearSolveStrategy(
00253   const std::string &linearSolveStrategyName
00254   ) const
00255 {
00256   // Get the name of the linear solve strategy
00257 #ifdef THYRA_DEFAULT_REAL_LINEAR_SOLVER_BUILDER_DUMP
00258   std::cout << "\nEntering DefaultRealLinearSolverBuilder::createLinearSolveStrategy(...) ...\n";
00259   std::cout << "\nlinearSolveStrategyName = \"" << linearSolveStrategyName << "\"\n";
00260   std::cout << "\nlinearSolveStrategyName.length() = " << linearSolveStrategyName.length() << "\n";
00261   std::cout << "\ndefaultLOWSF_ = \"" << defaultLOWSF_ << "\"\n";
00262   std::cout << "\nthis->getLinearSolveStrategyName() = \"" << this->getLinearSolveStrategyName() << "\"\n";
00263 #endif
00264   const std::string
00265     name = ( linearSolveStrategyName.length()
00266              ? linearSolveStrategyName
00267              : this->getLinearSolveStrategyName() );
00268 #ifdef THYRA_DEFAULT_REAL_LINEAR_SOLVER_BUILDER_DUMP
00269   std::cout << "\nname = \"" << name << "\"\n";
00270 #endif
00271   // Validate that the linear solver strategy with this name exists
00272   lowsf_map_t::const_iterator itr = lowsf_map_.find(name);
00273   TEST_FOR_EXCEPTION(
00274     itr == lowsf_map_.end(), std::invalid_argument
00275     ,"Error, the value \""<<LinearSolverType_name<<"\"=\""<<name<<"\" is not a valid"
00276     " linear solver type.  Valid linear solve strategy names include "
00277     <<validLinearSolveStrategyNames()<<"!"
00278     );
00279   // Create the uninitialized LOWSFB object
00280   Teuchos::RefCountPtr<LinearOpWithSolveFactoryBase<double> >
00281     lowsf = itr->second->create();
00282   // First, set the preconditioner factory and its parameters
00283   if(lowsf->acceptsPreconditionerFactory()) {
00284     const std::string &pfName = this->getPreconditionerStrategyName();
00285     Teuchos::RefCountPtr<PreconditionerFactoryBase<double> >
00286       pf = this->createPreconditioningStrategy(pfName);
00287     if(pf.get())
00288       lowsf->setPreconditionerFactory(pf,pfName);
00289   }
00290   // Now set the parameters for the linear solver (some of which might
00291   // override some preconditioner factory parameters).
00292   lowsf->setParameterList(sublist(sublist(paramList_,LinearSolverTypes_name),name));
00293   //
00294   return lowsf;
00295 }
00296 
00297 Teuchos::RefCountPtr<PreconditionerFactoryBase<double> >
00298 DefaultRealLinearSolverBuilder::createPreconditioningStrategy(
00299   const std::string &preconditioningStrategyName
00300   ) const
00301 {
00302   // Get the name of the preconditioning strategy
00303   const std::string
00304     name = ( preconditioningStrategyName.length()
00305              ? preconditioningStrategyName
00306              : this->getPreconditionerStrategyName() );
00307   Teuchos::RefCountPtr<PreconditionerFactoryBase<double> >
00308     pf = Teuchos::null;
00309   if( name != "None" ) {
00310     pf_map_t::const_iterator itr = pf_map_.find(name);
00311     TEST_FOR_EXCEPTION(
00312       itr == pf_map_.end(), std::invalid_argument
00313       ,"Error, the value \""<<PreconditionerType_name<<"\"=\""<<name<<"\" is not a valid"
00314       " preconditioner type.  Valid preconditioning strategy names include "
00315       <<validPreconditioningStrategyNames()<<"!"
00316       );
00317     pf = itr->second->create();
00318     pf->setParameterList(sublist(sublist(paramList_,PreconditionerTypes_name),name));
00319   }
00320   return pf;
00321 }
00322 
00323 // private
00324 
00325 void DefaultRealLinearSolverBuilder::initializeDefaults()
00326 {
00327   using Teuchos::rcp;
00328   using Teuchos::AbstractFactoryStd;
00329   defaultLOWSF_ = "";
00330   defaultPF_ = "";
00331   // Solvers
00332 #ifdef HAVE_STRATIMIKOS_BELOS_THYRA
00333   setLinearSolveStrategyFactory(
00334     rcp(new AbstractFactoryStd<LinearOpWithSolveFactoryBase<double>,BelosLinearOpWithSolveFactory<double> >())
00335     ,"Belos"
00336     );
00337 #endif
00338 #ifdef HAVE_STRATIMIKOS_AMESOS_THYRA
00339   setLinearSolveStrategyFactory(
00340     rcp(new AbstractFactoryStd<LinearOpWithSolveFactoryBase<double>,AmesosLinearOpWithSolveFactory>())
00341     ,"Amesos"
00342     );
00343 #endif
00344 #ifdef HAVE_STRATIMIKOS_AZTECOO_THYRA
00345   setLinearSolveStrategyFactory(
00346     rcp(new AbstractFactoryStd<LinearOpWithSolveFactoryBase<double>,AztecOOLinearOpWithSolveFactory>())
00347     ,"AztecOO"
00348     );
00349 #endif
00350 #ifdef HAVE_STRATIMIKOS_AMESOS_THYRA
00351   if( Teuchos::GlobalMPISession::getNProc() == 1 ) {
00352     defaultLOWSF_ = "Amesos";
00353   }
00354 #endif
00355   // Preconditioners
00356 #ifdef HAVE_STRATIMIKOS_IFPACK_THYRA
00357   setPreconditioningStrategyFactory(
00358     rcp(new AbstractFactoryStd<PreconditionerFactoryBase<double>,IfpackPreconditionerFactory>())
00359     ,"Ifpack"
00360     );
00361 #endif
00362 #ifdef HAVE_STRATIMIKOS_ML_THYRA
00363   setPreconditioningStrategyFactory(
00364     rcp(new AbstractFactoryStd<PreconditionerFactoryBase<double>,MLPreconditionerFactory>())
00365     ,"ML"
00366     );
00367 #endif
00368 }
00369 
00370 std::string
00371 DefaultRealLinearSolverBuilder::validLinearSolveStrategyNames() const
00372 {
00373   std::ostringstream oss;
00374   oss << "{";
00375   for( int i = 0; i < int(validLowsfNames_.size()); ++i ) {
00376     oss << "\"" << validLowsfNames_[i] << "\"";
00377     if( i != int(validLowsfNames_.size()-1) )
00378       oss << ",";
00379   }
00380   oss << "}";
00381   return oss.str();
00382 }
00383 
00384 std::string
00385 DefaultRealLinearSolverBuilder::validPreconditioningStrategyNames() const
00386 {
00387   std::ostringstream oss;
00388   oss << "{";
00389   for( int i = 0; i < int(validPfNames_.size()); ++i ) {
00390     oss << "\"" << validPfNames_[i] << "\"";
00391     if( i != int(validPfNames_.size()-1) )
00392       oss << ",";
00393   }
00394   oss << "}";
00395   return oss.str();
00396 }
00397 
00398 } // namespace Thyra

Generated on Thu Sep 18 12:37:39 2008 for Stratimikos by doxygen 1.3.9.1