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

Generated on Wed Jul 22 13:20:35 2009 for Stratimikos by doxygen 1.5.8