|
Belos
Version of the Day
|
00001 //@HEADER 00002 // ************************************************************************ 00003 // 00004 // Belos: Block Linear Solvers Package 00005 // Copyright 2004 Sandia Corporation 00006 // 00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, 00008 // the U.S. Government retains certain rights in this software. 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 Michael A. Heroux (maherou@sandia.gov) 00038 // 00039 // ************************************************************************ 00040 //@HEADER 00041 00042 #ifndef __Belos_SolverFactory_hpp 00043 #define __Belos_SolverFactory_hpp 00044 00045 #include <BelosConfigDefs.hpp> 00046 #include <BelosOutputManager.hpp> 00047 #include <BelosSolverManager.hpp> 00048 00049 #include <BelosBlockGmresSolMgr.hpp> 00050 #include <BelosPseudoBlockGmresSolMgr.hpp> 00051 #include <BelosBlockCGSolMgr.hpp> 00052 #include <BelosPseudoBlockCGSolMgr.hpp> 00053 #include <BelosGCRODRSolMgr.hpp> 00054 #include <BelosRCGSolMgr.hpp> 00055 #include <BelosMinresSolMgr.hpp> 00056 #include <BelosLSQRSolMgr.hpp> 00057 00058 #include <Teuchos_Array.hpp> 00059 #include <Teuchos_Describable.hpp> 00060 #include <Teuchos_StandardCatchMacros.hpp> 00061 #include <Teuchos_TypeNameTraits.hpp> 00062 00063 #include <algorithm> 00064 #include <map> 00065 #include <sstream> 00066 #include <stdexcept> 00067 #include <vector> 00068 00069 namespace Belos { 00070 00071 namespace details { 00072 00091 enum EBelosSolverType { 00092 SOLVER_TYPE_BLOCK_GMRES, 00093 SOLVER_TYPE_PSEUDO_BLOCK_GMRES, 00094 SOLVER_TYPE_BLOCK_CG, 00095 SOLVER_TYPE_PSEUDO_BLOCK_CG, 00096 SOLVER_TYPE_GCRODR, 00097 SOLVER_TYPE_RCG, 00098 SOLVER_TYPE_MINRES, 00099 SOLVER_TYPE_LSQR 00100 }; 00101 00102 } // namespace details 00103 00211 template<class Scalar, class MV, class OP> 00212 class SolverFactory : public Teuchos::Describable { 00213 public: 00220 typedef SolverManager<Scalar, MV, OP> solver_base_type; 00221 00223 SolverFactory(); 00224 00254 Teuchos::RCP<solver_base_type> 00255 create (const std::string& solverName, 00256 const Teuchos::RCP<Teuchos::ParameterList>& solverParams); 00257 00263 int numSupportedSolvers () const; 00264 00270 Teuchos::Array<std::string> supportedSolverNames () const; 00271 00273 bool isSupported (const std::string& solverName) const; 00274 00276 00277 00279 std::string description() const; 00280 00286 void describe (Teuchos::FancyOStream& out, 00287 const Teuchos::EVerbosityLevel verbLevel = Teuchos::Describable::verbLevel_default) const; 00289 00290 private: 00303 std::map<std::string, std::string> aliasToCanonicalName_; 00304 00318 std::map<std::string, details::EBelosSolverType> canonicalNameToEnum_; 00319 00325 void 00326 reviseParameterListForAlias (const std::string& aliasName, 00327 const Teuchos::RCP<Teuchos::ParameterList>& solverParams); 00328 00330 Teuchos::Array<std::string> canonicalSolverNames () const; 00331 00333 Teuchos::Array<std::string> solverNameAliases () const; 00334 }; 00335 00336 00337 namespace details { 00338 00357 template<class SolverManagerBaseType, class SolverManagerType> 00358 Teuchos::RCP<SolverManagerBaseType> 00359 makeSolverManagerTmpl (const Teuchos::RCP<Teuchos::ParameterList>& params); 00360 00379 template<class Scalar, class MV, class OP> 00380 Teuchos::RCP<SolverManager<Scalar, MV, OP> > 00381 makeSolverManagerFromEnum (const EBelosSolverType solverType, 00382 const Teuchos::RCP<Teuchos::ParameterList>& params) 00383 { 00384 typedef SolverManager<Scalar, MV, OP> base_type; 00385 00386 switch (solverType) { 00387 case SOLVER_TYPE_BLOCK_GMRES: { 00388 typedef BlockGmresSolMgr<Scalar, MV, OP> impl_type; 00389 return makeSolverManagerTmpl<base_type, impl_type> (params); 00390 break; 00391 } 00392 case SOLVER_TYPE_PSEUDO_BLOCK_GMRES: { 00393 typedef PseudoBlockGmresSolMgr<Scalar, MV, OP> impl_type; 00394 return makeSolverManagerTmpl<base_type, impl_type> (params); 00395 break; 00396 } 00397 case SOLVER_TYPE_BLOCK_CG: { 00398 typedef BlockCGSolMgr<Scalar, MV, OP> impl_type; 00399 return makeSolverManagerTmpl<base_type, impl_type> (params); 00400 break; 00401 } 00402 case SOLVER_TYPE_PSEUDO_BLOCK_CG: { 00403 typedef PseudoBlockCGSolMgr<Scalar, MV, OP> impl_type; 00404 return makeSolverManagerTmpl<base_type, impl_type> (params); 00405 break; 00406 } 00407 case SOLVER_TYPE_GCRODR: { 00408 typedef GCRODRSolMgr<Scalar, MV, OP> impl_type; 00409 return makeSolverManagerTmpl<base_type, impl_type> (params); 00410 break; 00411 } 00412 case SOLVER_TYPE_RCG: { 00413 typedef RCGSolMgr<Scalar, MV, OP> impl_type; 00414 return makeSolverManagerTmpl<base_type, impl_type> (params); 00415 break; 00416 } 00417 case SOLVER_TYPE_MINRES: { 00418 typedef MinresSolMgr<Scalar, MV, OP> impl_type; 00419 return makeSolverManagerTmpl<base_type, impl_type> (params); 00420 break; 00421 } 00422 case SOLVER_TYPE_LSQR: { 00423 typedef LSQRSolMgr<Scalar, MV, OP> impl_type; 00424 return makeSolverManagerTmpl<base_type, impl_type> (params); 00425 break; 00426 } 00427 default: 00428 TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, 00429 "Invalid EBelosSolverType enum value " << solverType 00430 << ". Please report this bug to the Belos developers."); 00431 // Compiler guard. 00432 return Teuchos::null; 00433 } 00434 } 00435 00436 template<class SolverManagerBaseType, class SolverManagerType> 00437 Teuchos::RCP<SolverManagerBaseType> 00438 makeSolverManagerTmpl (const Teuchos::RCP<Teuchos::ParameterList>& params) 00439 { 00440 using Teuchos::ParameterList; 00441 using Teuchos::parameterList; 00442 using Teuchos::RCP; 00443 00444 RCP<SolverManagerType> solver = rcp (new SolverManagerType); 00445 00446 // Some solvers may not like to get a null ParameterList. If params 00447 // is null, replace it with the solver's default parameters. 00448 RCP<ParameterList> pl; 00449 if (params.is_null()) { 00450 pl = parameterList (*solver->getValidParameters()); 00451 } else { 00452 pl = params; 00453 } 00454 TEUCHOS_TEST_FOR_EXCEPTION(pl.is_null(), std::logic_error, 00455 "ParameterList to pass to solver is null. This " 00456 "should never happen. Please report this bug to " 00457 "the Belos developers."); 00458 solver->setParameters (pl); 00459 return solver; 00460 } 00461 00462 } // namespace details 00463 00464 00465 template<class Scalar, class MV, class OP> 00466 SolverFactory<Scalar, MV, OP>::SolverFactory() 00467 { 00468 aliasToCanonicalName_["GMRES"] = "Pseudoblock GMRES"; 00469 // NOTE (mfh 29 Nov 2011) Accessing the flexible capability requires 00470 // setting a parameter in the solver's parameter list. This affects 00471 // the SolverFactory's interface, since using the "Flexible GMRES" 00472 // alias requires modifying the user's parameter list if necessary. 00473 // This is a good idea because users may not know about the 00474 // parameter, or may have forgotten. 00475 aliasToCanonicalName_["Flexible GMRES"] = "Block GMRES"; 00476 aliasToCanonicalName_["CG"] = "Pseudoblock CG"; 00477 aliasToCanonicalName_["Recycling CG"] = "RCG"; 00478 aliasToCanonicalName_["Recycling GMRES"] = "GCRODR"; 00479 // For compatibility with Stratimikos' Belos adapter. 00480 aliasToCanonicalName_["Pseudo Block GMRES"] = "Pseudoblock GMRES"; 00481 aliasToCanonicalName_["Pseudo Block CG"] = "Pseudoblock CG"; 00482 00483 // Mapping from canonical solver name (a string) to its 00484 // corresponding enum value. This mapping is one-to-one. 00485 canonicalNameToEnum_["Block GMRES"] = details::SOLVER_TYPE_BLOCK_GMRES; 00486 canonicalNameToEnum_["Pseudoblock GMRES"] = details::SOLVER_TYPE_PSEUDO_BLOCK_GMRES; 00487 canonicalNameToEnum_["Block CG"] = details::SOLVER_TYPE_BLOCK_CG; 00488 canonicalNameToEnum_["Pseudoblock CG"] = details::SOLVER_TYPE_PSEUDO_BLOCK_CG; 00489 canonicalNameToEnum_["GCRODR"] = details::SOLVER_TYPE_GCRODR; 00490 canonicalNameToEnum_["RCG"] = details::SOLVER_TYPE_RCG; 00491 canonicalNameToEnum_["MINRES"] = details::SOLVER_TYPE_MINRES; 00492 canonicalNameToEnum_["LSQR"] = details::SOLVER_TYPE_LSQR; 00493 } 00494 00495 00496 template<class Scalar, class MV, class OP> 00497 void 00498 SolverFactory<Scalar, MV, OP>:: 00499 reviseParameterListForAlias (const std::string& aliasName, 00500 const Teuchos::RCP<Teuchos::ParameterList>& solverParams) 00501 { 00502 TEUCHOS_TEST_FOR_EXCEPTION(solverParams.is_null(), std::logic_error, 00503 "Belos::SolverFactory::reviseParameterListForAlias: the input " 00504 "ParameterList is supposed to be nonnull. Please report this " 00505 "bug to the Belos developers."); 00506 if (aliasName == "Flexible GMRES") { 00507 // "Gmres" uses title case in this solver's parameter list. For 00508 // our alias, we prefer the all-capitals "GMRES" that the 00509 // algorithm's authors (Saad and Schultz) used. 00510 solverParams->set ("Flexible Gmres", true); 00511 } 00512 } 00513 00514 00515 template<class Scalar, class MV, class OP> 00516 Teuchos::RCP<typename SolverFactory<Scalar, MV, OP>::solver_base_type> 00517 SolverFactory<Scalar, MV, OP>:: 00518 create (const std::string& solverName, 00519 const Teuchos::RCP<Teuchos::ParameterList>& solverParams) 00520 { 00521 // Check whether the given name is an alias. 00522 std::map<std::string, std::string>::const_iterator aliasIter = 00523 aliasToCanonicalName_.find (solverName); 00524 const bool isAnAlias = (aliasIter != aliasToCanonicalName_.end()); 00525 const std::string candidateCanonicalName = 00526 isAnAlias ? aliasIter->second : solverName; 00527 00528 // Get the canonical name. 00529 std::map<std::string, details::EBelosSolverType>::const_iterator canonicalIter = 00530 canonicalNameToEnum_.find (candidateCanonicalName); 00531 const bool validCanonicalName = (canonicalIter != canonicalNameToEnum_.end()); 00532 00533 // Check whether we found a canonical name. If we didn't and the 00534 // input name is a valid alias, that's a bug. Otherwise, the input 00535 // name is invalid. 00536 TEUCHOS_TEST_FOR_EXCEPTION(! validCanonicalName && isAnAlias, std::logic_error, 00537 "Valid alias \"" << solverName << "\" has candidate canonical name \"" 00538 << candidateCanonicalName << "\", which is not a canonical solver name. " 00539 "Please report this bug to the Belos developers."); 00540 TEUCHOS_TEST_FOR_EXCEPTION(! validCanonicalName && ! isAnAlias, 00541 std::invalid_argument, "Invalid solver name \"" << solverName << "\"."); 00542 00543 // If the input list is null, we create a new list and use that. 00544 // This is OK because the effect of a null parameter list input is 00545 // to use default parameter values. Thus, we can always replace a 00546 // null list with an empty list. 00547 Teuchos::RCP<Teuchos::ParameterList> pl = 00548 solverParams.is_null() ? Teuchos::parameterList() : solverParams; 00549 00550 // Possibly modify the input parameter list as needed. 00551 if (isAnAlias) { 00552 reviseParameterListForAlias (solverName, pl); 00553 } 00554 00555 return details::makeSolverManagerFromEnum<Scalar, MV, OP> (canonicalIter->second, pl); 00556 } 00557 00558 00559 template<class Scalar, class MV, class OP> 00560 std::string 00561 SolverFactory<Scalar, MV, OP>::description() const 00562 { 00563 using Teuchos::TypeNameTraits; 00564 std::ostringstream os; 00565 os << "Belos::SolverFactory<" << TypeNameTraits<Scalar>::name() 00566 << ", " << TypeNameTraits<Scalar>::name() 00567 << ", " << TypeNameTraits<MV>::name() 00568 << ", " << TypeNameTraits<OP>::name() 00569 << ">"; 00570 return os.str(); 00571 } 00572 00573 template<class Scalar, class MV, class OP> 00574 void 00575 SolverFactory<Scalar, MV, OP>:: 00576 describe (Teuchos::FancyOStream& out, 00577 const Teuchos::EVerbosityLevel verbLevel) const 00578 { 00579 using std::endl; 00580 typedef Teuchos::Array<std::string>::const_iterator iter_type; 00581 00582 Teuchos::OSTab tab1 (out); 00583 out << this->description(); 00584 00585 // At higher verbosity levels, print out the list of supported solvers. 00586 if (static_cast<int> (verbLevel) > static_cast<int> (Teuchos::VERB_LOW)) { 00587 out << ":" << endl; 00588 Teuchos::OSTab tab2 (out); 00589 out << "Number of supported solvers: " << numSupportedSolvers() 00590 << endl; 00591 out << "Supported canonical solver names:"; 00592 { 00593 Teuchos::Array<std::string> names = canonicalSolverNames(); 00594 for (iter_type iter = names.begin(); iter != names.end(); ++iter) { 00595 out << *iter; 00596 if (iter + 1 != names.end()) { 00597 out << ", "; 00598 } 00599 } 00600 } 00601 out << "Supported aliases to canonical names:"; 00602 { 00603 Teuchos::Array<std::string> names = solverNameAliases(); 00604 for (iter_type iter = names.begin(); iter != names.end(); ++iter) { 00605 out << *iter; 00606 if (iter + 1 != names.end()) { 00607 out << ", "; 00608 } 00609 } 00610 } 00611 } 00612 } 00613 00614 template<class Scalar, class MV, class OP> 00615 int 00616 SolverFactory<Scalar, MV, OP>::numSupportedSolvers () const 00617 { 00618 return static_cast<int> (canonicalNameToEnum_.size()); 00619 } 00620 00621 template<class Scalar, class MV, class OP> 00622 Teuchos::Array<std::string> 00623 SolverFactory<Scalar, MV, OP>::canonicalSolverNames () const 00624 { 00625 Teuchos::Array<std::string> canonicalNames; 00626 typedef std::map<std::string, details::EBelosSolverType>::const_iterator iter_type; 00627 for (iter_type iter = canonicalNameToEnum_.begin(); 00628 iter != canonicalNameToEnum_.end(); ++iter) { 00629 canonicalNames.push_back (iter->first); 00630 } 00631 return canonicalNames; 00632 } 00633 00634 template<class Scalar, class MV, class OP> 00635 Teuchos::Array<std::string> 00636 SolverFactory<Scalar, MV, OP>::solverNameAliases () const 00637 { 00638 Teuchos::Array<std::string> names; 00639 { 00640 typedef std::map<std::string, std::string>::const_iterator iter_type; 00641 for (iter_type iter = aliasToCanonicalName_.begin(); 00642 iter != aliasToCanonicalName_.end(); ++iter) { 00643 names.push_back (iter->first); 00644 } 00645 } 00646 return names; 00647 } 00648 00649 template<class Scalar, class MV, class OP> 00650 Teuchos::Array<std::string> 00651 SolverFactory<Scalar, MV, OP>::supportedSolverNames () const 00652 { 00653 Teuchos::Array<std::string> names; 00654 { 00655 typedef std::map<std::string, std::string>::const_iterator iter_type; 00656 for (iter_type iter = aliasToCanonicalName_.begin(); 00657 iter != aliasToCanonicalName_.end(); ++iter) { 00658 names.push_back (iter->first); 00659 } 00660 } 00661 { 00662 typedef std::map<std::string, details::EBelosSolverType>::const_iterator iter_type; 00663 for (iter_type iter = canonicalNameToEnum_.begin(); 00664 iter != canonicalNameToEnum_.end(); ++iter) { 00665 names.push_back (iter->first); 00666 } 00667 } 00668 return names; 00669 } 00670 00671 } // namespace Belos 00672 00673 #endif // __Belos_SolverFactory_hpp 00674
1.7.6.1