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