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 
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   if(!validParamList_.get()) {
00261     RCP<Teuchos::ParameterList>
00262       validParamList = Teuchos::rcp(new Teuchos::ParameterList);
00263     // Linear Solver Types
00264     lowsfValidator = Teuchos::rcp(
00265       new Teuchos::StringToIntegralParameterEntryValidator<int>(
00266         validLowsfNames_,LinearSolverType_name
00267         )
00268       );
00269     validParamList->set(
00270       LinearSolverType_name,defaultLOWSF_
00271       ,(std::string("Determines the type of linear solver that will be used.\n")
00272         + "The parameters for each solver type are specified in the sublist \""
00273         + LinearSolverTypes_name + "\"").c_str()
00274       ,lowsfValidator
00275       );
00276     Teuchos::ParameterList &linearSolverTypesSL = validParamList->sublist(
00277       LinearSolverTypes_name,false,
00278       "Sublists for each of the linear solver types set using the parameter\n"
00279       "\"" + LinearSolverType_name + "\".  Note that the options for each\n"
00280       "linear solver type given below will only be used if linear solvers\n"
00281       "of that type are created.  It is fine to list parameter sublists for\n"
00282       "linear solver types that are not used."
00283       );
00284     for( int i = 0; i < static_cast<int>(lowsfArray_.size()); ++i ) {
00285       const std::string
00286         &lsname = validLowsfNames_[i];
00287       const RCP<Thyra::LinearOpWithSolveFactoryBase<double> >
00288         lowsf = lowsfArray_[i]->create();
00289       linearSolverTypesSL.sublist(lsname).setParameters(*lowsf->getValidParameters());
00290     }
00291     // Preconditioner Type
00292     pfValidator = Teuchos::rcp(
00293       new Teuchos::StringToIntegralParameterEntryValidator<int>(
00294         validPfNames_,PreconditionerType_name
00295         )
00296       );
00297     validParamList->set(
00298       PreconditionerType_name,defaultPF_
00299       ,(std::string("Determines the type of preconditioner that will be used.\n")
00300         + "This option is only meaningful for linear solvers that accept preconditioner"
00301         + " factory objects!\n"
00302         + "The parameters for each preconditioner are specified in the sublist \""
00303         + PreconditionerTypes_name + "\"").c_str()
00304       ,pfValidator
00305       );
00306     Teuchos::ParameterList &precTypesSL = validParamList->sublist(
00307         PreconditionerTypes_name,false,
00308         "Sublists for each of the preconditioner types set using the parameter\n"
00309         "\"" + PreconditionerType_name + "\".  Note that the options for each\n"
00310         "preconditioner type given below will only be used if preconditioners\n"
00311         "of that type are created.  It is fine to list parameter sublists for\n"
00312         "preconditioner types that are not used."
00313         );
00314     for( int i = 0; i < static_cast<int>(pfArray_.size()); ++i ) {
00315       const std::string
00316         &pfname = validPfNames_[i+1]; // "None" is the 0th entry!
00317       const RCP<Thyra::PreconditionerFactoryBase<double> >
00318         pf = pfArray_[i]->create();
00319       precTypesSL.sublist(pfname).setParameters(*pf->getValidParameters());
00320     }
00321     // 
00322     validParamList->set(
00323       EnableDelayedSolverConstruction_name, EnableDelayedSolverConstruction_default,
00324       "When this option is set to true, the linear solver factory will be wrapped\n"
00325       "in a delayed evaluation Decorator factory object.  This results in a delay\n"
00326       "in the creation of a linear solver (and the associated preconditioner) until\n"
00327       "the first solve is actually performed.  This helps in cases where it is not\n"
00328       "known a-priori if a linear solve will be needed on a given linear operator and\n"
00329       "therefore can significantly improve performance for some types of algorithms\n"
00330       "such as NOX and LOCA."
00331       );
00332     //
00333     validParamList_ = validParamList;
00334   }
00335   return validParamList_;
00336 }
00337 
00338   
00339 // Overridden from LinearSolverBuilderBase.
00340 
00341 
00342 RCP<Thyra::LinearOpWithSolveFactoryBase<double> >
00343 DefaultLinearSolverBuilder::createLinearSolveStrategy(
00344   const std::string &linearSolveStrategyName
00345   ) const
00346 {
00347   // Get the name of the linear solve strategy
00348 #ifdef THYRA_DEFAULT_REAL_LINEAR_SOLVER_BUILDER_DUMP
00349   std::cout << "\nEntering DefaultLinearSolverBuilder"
00350             << "::createLinearSolveStrategy(...) ...\n";
00351   std::cout << "\nlinearSolveStrategyName = \""
00352             << linearSolveStrategyName << "\"\n";
00353   std::cout << "\nlinearSolveStrategyName.length() = "
00354             << linearSolveStrategyName.length() << "\n";
00355   std::cout << "\ndefaultLOWSF_ = \"" << defaultLOWSF_ << "\"\n";
00356   std::cout << "\nthis->getLinearSolveStrategyName() = \""
00357             << this->getLinearSolveStrategyName() << "\"\n";
00358 #endif
00359   const std::string
00360     lsname = ( linearSolveStrategyName.length()
00361              ? linearSolveStrategyName
00362              : this->getLinearSolveStrategyName() );
00363 #ifdef THYRA_DEFAULT_REAL_LINEAR_SOLVER_BUILDER_DUMP
00364   std::cout << "\nlsname = \"" << lsname << "\"\n";
00365 #endif
00366   // Get the index of this linear solver strategy (this will validate!)
00367   const int
00368     ls_idx = lowsfValidator->getIntegralValue(lsname,LinearSolverType_name);
00369   // Create the uninitialized LOWSFB object
00370   RCP<Thyra::LinearOpWithSolveFactoryBase<double> >
00371     lowsf = lowsfArray_[ls_idx]->create();
00372   // First, set the preconditioner factory and its parameters
00373   if(lowsf->acceptsPreconditionerFactory()) {
00374     const std::string &pfName = this->getPreconditionerStrategyName();
00375     RCP<Thyra::PreconditionerFactoryBase<double> >
00376       pf = this->createPreconditioningStrategy(pfName);
00377     if(pf.get())
00378       lowsf->setPreconditionerFactory(pf,pfName);
00379   }
00380   // Now set the parameters for the linear solver (some of which might
00381   // override some preconditioner factory parameters).
00382   lowsf->setParameterList(sublist(sublist(paramList_,LinearSolverTypes_name),lsname));
00383   //
00384   if (enableDelayedSolverConstruction_) {
00385     return Teuchos::rcp(
00386       new Thyra::DelayedLinearOpWithSolveFactory<double>(lowsf)
00387       );
00388   }
00389   return lowsf;
00390 }
00391 
00392 
00393 RCP<Thyra::PreconditionerFactoryBase<double> >
00394 DefaultLinearSolverBuilder::createPreconditioningStrategy(
00395   const std::string &preconditioningStrategyName
00396   ) const
00397 {
00398 
00399   // Get the name of the preconditioning strategy
00400   const std::string
00401     pfname = ( preconditioningStrategyName.length()
00402              ? preconditioningStrategyName
00403              : this->getPreconditionerStrategyName() );
00404   RCP<Thyra::PreconditionerFactoryBase<double> >
00405     pf = Teuchos::null;
00406 
00407   // Get the index of this preconditioning strategy (this will validate!)
00408   const int
00409     pf_idx = pfValidator->getIntegralValue(pfname,PreconditionerType_name);
00410   if( pf_idx != 0 ) {
00411     pf = pfArray_[pf_idx-1]->create(); // We offset by -1 since "None" is first!
00412     pf->setParameterList(
00413       sublist(sublist(paramList_,PreconditionerTypes_name),pfname));
00414   }
00415 
00416   return pf;
00417 
00418 }
00419 
00420 
00421 // private
00422 
00423 
00424 void DefaultLinearSolverBuilder::initializeDefaults()
00425 {
00426 
00427   using Teuchos::rcp;
00428   using Teuchos::abstractFactoryStd;
00429 
00430   defaultLOWSF_ = "";
00431   defaultPF_ = None_name;
00432   validLowsfNames_.resize(0);
00433   validPfNames_.resize(0);
00434   validPfNames_.push_back(None_name); // This will offset everything!
00435 
00436   //
00437   // Linear Solvers
00438   //
00439 
00440 #ifdef HAVE_STRATIMIKOS_BELOS
00441   setLinearSolveStrategyFactory(
00442     abstractFactoryStd<Thyra::LinearOpWithSolveFactoryBase<double>,
00443     Thyra::BelosLinearOpWithSolveFactory<double> >(),
00444     "Belos"
00445     );
00446 #endif
00447 
00448 #ifdef HAVE_STRATIMIKOS_AMESOS
00449   setLinearSolveStrategyFactory(
00450     abstractFactoryStd<Thyra::LinearOpWithSolveFactoryBase<double>,
00451     Thyra::AmesosLinearOpWithSolveFactory>(),
00452     "Amesos"
00453     );
00454 #endif
00455 
00456 #ifdef HAVE_STRATIMIKOS_AZTECOO
00457   setLinearSolveStrategyFactory(
00458     abstractFactoryStd<Thyra::LinearOpWithSolveFactoryBase<double>,
00459     Thyra::AztecOOLinearOpWithSolveFactory>(),
00460     "AztecOO"
00461     );
00462 #endif
00463 
00464 #ifdef HAVE_STRATIMIKOS_AMESOS
00465   if( Teuchos::GlobalMPISession::getNProc() == 1 ) {
00466     defaultLOWSF_ = "Amesos";
00467   }
00468 #endif
00469 
00470   // Note: ABove, the last LOWSF object set will be the default unless we are
00471   // on multiple processors!
00472 
00473   //
00474   // Preconditioners
00475   //
00476 
00477 #ifdef HAVE_STRATIMIKOS_ML
00478   setPreconditioningStrategyFactory(
00479     abstractFactoryStd<Thyra::PreconditionerFactoryBase<double>,
00480     Thyra::MLPreconditionerFactory>(),
00481     "ML"
00482     );
00483 #endif
00484 
00485 #ifdef HAVE_STRATIMIKOS_IFPACK
00486   setPreconditioningStrategyFactory(
00487     abstractFactoryStd<Thyra::PreconditionerFactoryBase<double>,
00488     Thyra::IfpackPreconditionerFactory>(),
00489     "Ifpack"
00490     );
00491 #endif
00492 
00493   // Note: Above, the last PF object set will be the default!
00494 
00495 }
00496 
00497 
00498 } // namespace Stratimikos

Generated on Wed Jul 22 12:56:30 2009 for Stratimikos by  doxygen 1.5.8