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