Stratimikos_DefaultLinearSolverBuilder.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 "Stratimikos_InternalConfig.h"
00032 #include "Stratimikos_DefaultLinearSolverBuilder.hpp"
00033 #include "Thyra_DelayedLinearOpWithSolveFactory.hpp"
00034 #include "Teuchos_AbstractFactoryStd.hpp"
00035 #include "Teuchos_CommandLineProcessor.hpp"
00036 #include "Teuchos_XMLParameterListHelpers.hpp"
00037 #include "Teuchos_GlobalMPISession.hpp"
00038 #include "Teuchos_StandardParameterEntryValidators.hpp"
00039 
00040 #ifdef HAVE_STRATIMIKOS_AMESOS
00041 #  include "Thyra_AmesosLinearOpWithSolveFactory.hpp"
00042 #endif
00043 #ifdef HAVE_STRATIMIKOS_AZTECOO
00044 #  include "Thyra_AztecOOLinearOpWithSolveFactory.hpp"
00045 #endif
00046 #ifdef HAVE_STRATIMIKOS_BELOS
00047 #  include "Thyra_BelosLinearOpWithSolveFactory.hpp"
00048 #endif
00049 #ifdef HAVE_STRATIMIKOS_IFPACK
00050 #  include "Thyra_IfpackPreconditionerFactory.hpp"
00051 #endif
00052 #ifdef HAVE_STRATIMIKOS_ML
00053 #  include "Thyra_MLPreconditionerFactory.hpp"
00054 #endif
00055 
00056 
00057 namespace {
00058 
00059 
00060 const std::string LinearSolverType_name    = "Linear Solver Type";
00061 const std::string LinearSolverTypes_name   = "Linear Solver Types";
00062 const std::string PreconditionerType_name    = "Preconditioner Type";
00063 const std::string PreconditionerTypes_name   = "Preconditioner Types";
00064 const std::string None_name = "None";
00065 const std::string EnableDelayedSolverConstruction_name = "Enable Delayed Solver Construction";
00066 const bool EnableDelayedSolverConstruction_default = false;
00067 
00068 
00069 Teuchos::RCP<const Teuchos::StringToIntegralParameterEntryValidator<int> >
00070 lowsfValidator;
00071 
00072 
00073 Teuchos::RCP<const Teuchos::StringToIntegralParameterEntryValidator<int> >
00074 pfValidator;
00075 
00076 
00077 } // namespace 
00078 
00079 
00080 namespace Stratimikos {
00081 
00082 
00083 // Constructors/Initializers/Accessors
00084 
00085 
00086 DefaultLinearSolverBuilder::DefaultLinearSolverBuilder(
00087   const std::string    &paramsXmlFileName
00088   ,const std::string   &extraParamsXmlString
00089   ,const std::string   &paramsUsedXmlOutFileName
00090   ,const std::string   &paramsXmlFileNameOption
00091   ,const std::string   &extraParamsXmlStringOption
00092   ,const std::string   &paramsUsedXmlOutFileNameOption
00093   )
00094   :paramsXmlFileName_(paramsXmlFileName)
00095   ,extraParamsXmlString_(extraParamsXmlString)
00096   ,paramsUsedXmlOutFileName_(paramsUsedXmlOutFileName)
00097   ,paramsXmlFileNameOption_(paramsXmlFileNameOption)
00098   ,extraParamsXmlStringOption_(extraParamsXmlStringOption)
00099   ,paramsUsedXmlOutFileNameOption_(paramsUsedXmlOutFileNameOption)
00100   ,enableDelayedSolverConstruction_(EnableDelayedSolverConstruction_default)
00101 {
00102   this->initializeDefaults();
00103 }
00104 
00105 
00106 DefaultLinearSolverBuilder::~DefaultLinearSolverBuilder()
00107 {
00108 #ifdef TEUCHOS_DEBUG
00109   // Validate that we read the parameters correctly!
00110   if(paramList_.get())
00111     paramList_->validateParameters(*this->getValidParameters(),1);
00112 #endif    
00113 }
00114 
00115 
00116 void DefaultLinearSolverBuilder::setLinearSolveStrategyFactory(
00117   const RCP<const AbstractFactory<Thyra::LinearOpWithSolveFactoryBase<double> > >
00118   &solveStrategyFactory,
00119   const std::string &solveStrategyName
00120   )
00121 {
00122   validLowsfNames_.push_back(solveStrategyName);
00123   lowsfArray_.push_back(solveStrategyFactory);
00124   defaultLOWSF_ = solveStrategyName;
00125   validParamList_ = Teuchos::null;
00126 }
00127 
00128 
00129 void DefaultLinearSolverBuilder::setPreconditioningStrategyFactory(
00130   const RCP<const AbstractFactory<Thyra::PreconditionerFactoryBase<double> > >
00131   &precStrategyFactory,
00132   const std::string &precStrategyName
00133   )
00134 {
00135   validPfNames_.push_back(precStrategyName);
00136   pfArray_.push_back(precStrategyFactory);
00137   defaultPF_ = precStrategyName;
00138   validParamList_ = Teuchos::null;
00139 }
00140 
00141 
00142 void DefaultLinearSolverBuilder::setupCLP( Teuchos::CommandLineProcessor *clp )
00143 {
00144   TEST_FOR_EXCEPT(clp==NULL);
00145   clp->setOption(
00146     paramsXmlFileNameOption().c_str(),&paramsXmlFileName_
00147     ,"Name of an XML file containing parameters for linear solver "
00148     "options to be appended first."
00149     );
00150   clp->setOption(
00151     extraParamsXmlStringOption().c_str(),&extraParamsXmlString_
00152     ,"An XML string containing linear solver parameters to be appended second."
00153     );
00154   clp->setOption(
00155     paramsUsedXmlOutFileNameOption().c_str(),&paramsUsedXmlOutFileName_
00156     ,"Name of an XML file that can be written with the parameter list after it "
00157     "has been used on completion of this program."
00158     );
00159 }
00160 
00161 
00162 void DefaultLinearSolverBuilder::readParameters( std::ostream *out )
00163 {
00164   if(!paramList_.get())
00165     paramList_ = Teuchos::parameterList("DefaultLinearSolverBuilder");
00166   if(paramsXmlFileName().length()) {
00167     if(out) *out
00168       << "\nReading parameters from XML file \""<<paramsXmlFileName()<<"\" ...\n";
00169     Teuchos::updateParametersFromXmlFile(paramsXmlFileName(),&*paramList_);
00170   }
00171   if(extraParamsXmlString().length()) {
00172     if(out) *out
00173       << "\nAppending extra parameters from the XML string \""
00174       <<extraParamsXmlString()<<"\" ...\n";
00175     Teuchos::updateParametersFromXmlString(extraParamsXmlString(),&*paramList_);
00176   }
00177 }
00178 
00179 
00180 void DefaultLinearSolverBuilder::writeParamsFile(
00181   const Thyra::LinearOpWithSolveFactoryBase<double> &lowsFactory,
00182   const std::string &outputXmlFileName
00183   ) const
00184 {
00185   TEST_FOR_EXCEPT(!paramList_.get());
00186   std::string xmlOutputFile
00187     = ( outputXmlFileName.length() ? outputXmlFileName : paramsUsedXmlOutFileName() );
00188   if(xmlOutputFile.length()) {
00189     Teuchos::writeParameterListToXmlFile(*paramList_,xmlOutputFile);
00190   }
00191 }
00192 
00193 
00194 std::string
00195 DefaultLinearSolverBuilder::getLinearSolveStrategyName() const
00196 {
00197   TEST_FOR_EXCEPT(!paramList_.get());
00198   if(!lowsfValidator.get()) // Make sure lowsfValidator has been initialized!
00199     this->getValidParameters();
00200   return lowsfValidator->getStringValue(
00201     *paramList_,LinearSolverType_name,defaultLOWSF_);
00202 }
00203 
00204 
00205 std::string
00206 DefaultLinearSolverBuilder::getPreconditionerStrategyName() const
00207 {
00208   TEST_FOR_EXCEPT(!paramList_.get());
00209   if(!pfValidator.get()) // Make sure pfValidator has been initialized!
00210     this->getValidParameters();
00211   return pfValidator->getStringValue(
00212     *paramList_,PreconditionerType_name,defaultPF_);
00213 }
00214 
00215 
00216 // Overridden from ParameterListAcceptor
00217 
00218 
00219 void DefaultLinearSolverBuilder::setParameterList(
00220   RCP<Teuchos::ParameterList> const& paramList
00221   )
00222 {
00223   TEST_FOR_EXCEPT(!paramList.get());
00224   // Only validate the zeroth and first level of parameters and sublists as
00225   // these are all that this class directly controls.  All other parameters
00226   // and sublusts are handed off to different LOWSFB and PFB objects.
00227   paramList->validateParameters(*this->getValidParameters(),1);
00228   paramList_ = paramList;
00229   enableDelayedSolverConstruction_ = paramList_->get(
00230     EnableDelayedSolverConstruction_name, EnableDelayedSolverConstruction_default );
00231 }
00232 
00233 
00234 RCP<Teuchos::ParameterList>
00235 DefaultLinearSolverBuilder::getNonconstParameterList()
00236 {
00237   return paramList_;
00238 }
00239 
00240 
00241 RCP<Teuchos::ParameterList>
00242 DefaultLinearSolverBuilder::unsetParameterList()
00243 {
00244   RCP<Teuchos::ParameterList> _paramList = paramList_;
00245   paramList_ = Teuchos::null;
00246   return _paramList;
00247 }
00248 
00249 
00250 RCP<const Teuchos::ParameterList>
00251 DefaultLinearSolverBuilder::getParameterList() const
00252 {
00253   return paramList_;
00254 }
00255 
00256 
00257 RCP<const Teuchos::ParameterList>
00258 DefaultLinearSolverBuilder::getValidParameters() const
00259 {
00260   using Teuchos::rcp_implicit_cast;
00261   typedef Teuchos::ParameterEntryValidator PEV;
00262   if(!validParamList_.get()) {
00263     RCP<Teuchos::ParameterList>
00264       validParamList = Teuchos::rcp(new Teuchos::ParameterList);
00265     // Linear Solver Types
00266     lowsfValidator = Teuchos::rcp(
00267       new Teuchos::StringToIntegralParameterEntryValidator<int>(
00268         validLowsfNames_,LinearSolverType_name
00269         )
00270       );
00271     validParamList->set(
00272       LinearSolverType_name, defaultLOWSF_,
00273       (std::string("Determines the type of linear solver that will be used.\n")
00274         + "The parameters for each solver type are specified in the sublist \""
00275         + LinearSolverTypes_name + "\"").c_str(),
00276       rcp_implicit_cast<const PEV>(lowsfValidator)
00277       );
00278     Teuchos::ParameterList &linearSolverTypesSL = validParamList->sublist(
00279       LinearSolverTypes_name,false,
00280       "Sublists for each of the linear solver types set using the parameter\n"
00281       "\"" + LinearSolverType_name + "\".  Note that the options for each\n"
00282       "linear solver type given below will only be used if linear solvers\n"
00283       "of that type are created.  It is fine to list parameter sublists for\n"
00284       "linear solver types that are not used."
00285       );
00286     for( int i = 0; i < static_cast<int>(lowsfArray_.size()); ++i ) {
00287       const std::string
00288         &lsname = validLowsfNames_[i];
00289       const RCP<Thyra::LinearOpWithSolveFactoryBase<double> >
00290         lowsf = lowsfArray_[i]->create();
00291       linearSolverTypesSL.sublist(lsname).setParameters(*lowsf->getValidParameters());
00292     }
00293     // Preconditioner Type
00294     pfValidator = Teuchos::rcp(
00295       new Teuchos::StringToIntegralParameterEntryValidator<int>(
00296         validPfNames_,PreconditionerType_name
00297         )
00298       );
00299     validParamList->set(
00300       PreconditionerType_name, defaultPF_,
00301       (std::string("Determines the type of preconditioner that will be used.\n")
00302         + "This option is only meaningful for linear solvers that accept preconditioner"
00303         + " factory objects!\n"
00304         + "The parameters for each preconditioner are specified in the sublist \""
00305         + PreconditionerTypes_name + "\"").c_str(),
00306       rcp_implicit_cast<const PEV>(pfValidator)
00307       );
00308     Teuchos::ParameterList &precTypesSL = validParamList->sublist(
00309         PreconditionerTypes_name,false,
00310         "Sublists for each of the preconditioner types set using the parameter\n"
00311         "\"" + PreconditionerType_name + "\".  Note that the options for each\n"
00312         "preconditioner type given below will only be used if preconditioners\n"
00313         "of that type are created.  It is fine to list parameter sublists for\n"
00314         "preconditioner types that are not used."
00315         );
00316     for( int i = 0; i < static_cast<int>(pfArray_.size()); ++i ) {
00317       const std::string
00318         &pfname = validPfNames_[i+1]; // "None" is the 0th entry!
00319       const RCP<Thyra::PreconditionerFactoryBase<double> >
00320         pf = pfArray_[i]->create();
00321       precTypesSL.sublist(pfname).setParameters(*pf->getValidParameters());
00322     }
00323     // 
00324     validParamList->set(
00325       EnableDelayedSolverConstruction_name, EnableDelayedSolverConstruction_default,
00326       "When this option is set to true, the linear solver factory will be wrapped\n"
00327       "in a delayed evaluation Decorator factory object.  This results in a delay\n"
00328       "in the creation of a linear solver (and the associated preconditioner) until\n"
00329       "the first solve is actually performed.  This helps in cases where it is not\n"
00330       "known a-priori if a linear solve will be needed on a given linear operator and\n"
00331       "therefore can significantly improve performance for some types of algorithms\n"
00332       "such as NOX and LOCA."
00333       );
00334     //
00335     validParamList_ = validParamList;
00336   }
00337   return validParamList_;
00338 }
00339 
00340   
00341 // Overridden from LinearSolverBuilderBase.
00342 
00343 
00344 RCP<Thyra::LinearOpWithSolveFactoryBase<double> >
00345 DefaultLinearSolverBuilder::createLinearSolveStrategy(
00346   const std::string &linearSolveStrategyName
00347   ) const
00348 {
00349   // Get the name of the linear solve strategy
00350 #ifdef THYRA_DEFAULT_REAL_LINEAR_SOLVER_BUILDER_DUMP
00351   std::cout << "\nEntering DefaultLinearSolverBuilder"
00352             << "::createLinearSolveStrategy(...) ...\n";
00353   std::cout << "\nlinearSolveStrategyName = \""
00354             << linearSolveStrategyName << "\"\n";
00355   std::cout << "\nlinearSolveStrategyName.length() = "
00356             << linearSolveStrategyName.length() << "\n";
00357   std::cout << "\ndefaultLOWSF_ = \"" << defaultLOWSF_ << "\"\n";
00358   std::cout << "\nthis->getLinearSolveStrategyName() = \""
00359             << this->getLinearSolveStrategyName() << "\"\n";
00360 #endif
00361   const std::string
00362     lsname = ( linearSolveStrategyName.length()
00363              ? linearSolveStrategyName
00364              : this->getLinearSolveStrategyName() );
00365 #ifdef THYRA_DEFAULT_REAL_LINEAR_SOLVER_BUILDER_DUMP
00366   std::cout << "\nlsname = \"" << lsname << "\"\n";
00367 #endif
00368   // Get the index of this linear solver strategy (this will validate!)
00369   const int
00370     ls_idx = lowsfValidator->getIntegralValue(lsname,LinearSolverType_name);
00371   // Create the uninitialized LOWSFB object
00372   RCP<Thyra::LinearOpWithSolveFactoryBase<double> >
00373     lowsf = lowsfArray_[ls_idx]->create();
00374   // First, set the preconditioner factory and its parameters
00375   if(lowsf->acceptsPreconditionerFactory()) {
00376     const std::string &pfName = this->getPreconditionerStrategyName();
00377     RCP<Thyra::PreconditionerFactoryBase<double> >
00378       pf = this->createPreconditioningStrategy(pfName);
00379     if(pf.get())
00380       lowsf->setPreconditionerFactory(pf,pfName);
00381   }
00382   // Now set the parameters for the linear solver (some of which might
00383   // override some preconditioner factory parameters).
00384   lowsf->setParameterList(sublist(sublist(paramList_,LinearSolverTypes_name),lsname));
00385   //
00386   if (enableDelayedSolverConstruction_) {
00387     return Teuchos::rcp(
00388       new Thyra::DelayedLinearOpWithSolveFactory<double>(lowsf)
00389       );
00390   }
00391   return lowsf;
00392 }
00393 
00394 
00395 RCP<Thyra::PreconditionerFactoryBase<double> >
00396 DefaultLinearSolverBuilder::createPreconditioningStrategy(
00397   const std::string &preconditioningStrategyName
00398   ) const
00399 {
00400 
00401   // Get the name of the preconditioning strategy
00402   const std::string
00403     pfname = ( preconditioningStrategyName.length()
00404              ? preconditioningStrategyName
00405              : this->getPreconditionerStrategyName() );
00406   RCP<Thyra::PreconditionerFactoryBase<double> >
00407     pf = Teuchos::null;
00408 
00409   // Get the index of this preconditioning strategy (this will validate!)
00410   const int
00411     pf_idx = pfValidator->getIntegralValue(pfname,PreconditionerType_name);
00412   if( pf_idx != 0 ) {
00413     pf = pfArray_[pf_idx-1]->create(); // We offset by -1 since "None" is first!
00414     pf->setParameterList(
00415       sublist(sublist(paramList_,PreconditionerTypes_name),pfname));
00416   }
00417 
00418   return pf;
00419 
00420 }
00421 
00422 
00423 // private
00424 
00425 
00426 void DefaultLinearSolverBuilder::initializeDefaults()
00427 {
00428 
00429   using Teuchos::rcp;
00430   using Teuchos::abstractFactoryStd;
00431 
00432   defaultLOWSF_ = "";
00433   defaultPF_ = None_name;
00434   validLowsfNames_.resize(0);
00435   validPfNames_.resize(0);
00436   validPfNames_.push_back(None_name); // This will offset everything!
00437 
00438   //
00439   // Linear Solvers
00440   //
00441 
00442 #ifdef HAVE_STRATIMIKOS_BELOS
00443   setLinearSolveStrategyFactory(
00444     abstractFactoryStd<Thyra::LinearOpWithSolveFactoryBase<double>,
00445     Thyra::BelosLinearOpWithSolveFactory<double> >(),
00446     "Belos"
00447     );
00448 #endif
00449 
00450 #ifdef HAVE_STRATIMIKOS_AMESOS
00451   setLinearSolveStrategyFactory(
00452     abstractFactoryStd<Thyra::LinearOpWithSolveFactoryBase<double>,
00453     Thyra::AmesosLinearOpWithSolveFactory>(),
00454     "Amesos"
00455     );
00456 #endif
00457 
00458 #ifdef HAVE_STRATIMIKOS_AZTECOO
00459   setLinearSolveStrategyFactory(
00460     abstractFactoryStd<Thyra::LinearOpWithSolveFactoryBase<double>,
00461     Thyra::AztecOOLinearOpWithSolveFactory>(),
00462     "AztecOO"
00463     );
00464 #endif
00465 
00466 #ifdef HAVE_STRATIMIKOS_AMESOS
00467   if( Teuchos::GlobalMPISession::getNProc() == 1 ) {
00468     defaultLOWSF_ = "Amesos";
00469   }
00470 #endif
00471 
00472   // Note: ABove, the last LOWSF object set will be the default unless we are
00473   // on multiple processors!
00474 
00475   //
00476   // Preconditioners
00477   //
00478 
00479 #ifdef HAVE_STRATIMIKOS_ML
00480   setPreconditioningStrategyFactory(
00481     abstractFactoryStd<Thyra::PreconditionerFactoryBase<double>,
00482     Thyra::MLPreconditionerFactory>(),
00483     "ML"
00484     );
00485 #endif
00486 
00487 #ifdef HAVE_STRATIMIKOS_IFPACK
00488   setPreconditioningStrategyFactory(
00489     abstractFactoryStd<Thyra::PreconditionerFactoryBase<double>,
00490     Thyra::IfpackPreconditionerFactory>(),
00491     "Ifpack"
00492     );
00493 #endif
00494 
00495   // Note: Above, the last PF object set will be the default!
00496 
00497 }
00498 
00499 
00500 } // namespace Stratimikos
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends
Generated on Wed Apr 13 10:20:45 2011 for Stratimikos by  doxygen 1.6.3