|
Stratimikos Package Browser (Single Doxygen Collection) Version of the Day
|
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 ¶msXmlFileName 00088 ,const std::string &extraParamsXmlString 00089 ,const std::string ¶msUsedXmlOutFileName 00090 ,const std::string ¶msXmlFileNameOption 00091 ,const std::string &extraParamsXmlStringOption 00092 ,const std::string ¶msUsedXmlOutFileNameOption 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(),¶msXmlFileName_ 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(),¶msUsedXmlOutFileName_ 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
1.7.4