|
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 <BelosBlockCGSolMgr.hpp> 00050 #include <BelosBlockGmresSolMgr.hpp> 00051 #include <BelosGCRODRSolMgr.hpp> 00052 #include <BelosPseudoBlockCGSolMgr.hpp> 00053 #include <BelosPseudoBlockGmresSolMgr.hpp> 00054 #include <BelosPseudoBlockStochasticCGSolMgr.hpp> 00055 #include <BelosLSQRSolMgr.hpp> 00056 #include <BelosMinresSolMgr.hpp> 00057 #include <BelosGmresPolySolMgr.hpp> 00058 #include <BelosPCPGSolMgr.hpp> 00059 #include <BelosRCGSolMgr.hpp> 00060 #include <BelosTFQMRSolMgr.hpp> 00061 00062 #include <Teuchos_Array.hpp> 00063 #include <Teuchos_Describable.hpp> 00064 #include <Teuchos_StandardCatchMacros.hpp> 00065 #include <Teuchos_TypeNameTraits.hpp> 00066 00067 #include <algorithm> 00068 #include <map> 00069 #include <sstream> 00070 #include <stdexcept> 00071 #include <vector> 00072 00073 namespace Belos { 00074 00075 namespace details { 00076 00095 enum EBelosSolverType { 00096 SOLVER_TYPE_BLOCK_GMRES, 00097 SOLVER_TYPE_PSEUDO_BLOCK_GMRES, 00098 SOLVER_TYPE_BLOCK_CG, 00099 SOLVER_TYPE_PSEUDO_BLOCK_CG, 00100 SOLVER_TYPE_GCRODR, 00101 SOLVER_TYPE_RCG, 00102 SOLVER_TYPE_MINRES, 00103 SOLVER_TYPE_LSQR, 00104 SOLVER_TYPE_STOCHASTIC_CG, 00105 SOLVER_TYPE_TFQMR, 00106 SOLVER_TYPE_GMRES_POLY, 00107 SOLVER_TYPE_PCPG 00108 }; 00109 00110 } // namespace details 00111 00219 template<class Scalar, class MV, class OP> 00220 class SolverFactory : public Teuchos::Describable { 00221 public: 00228 typedef SolverManager<Scalar, MV, OP> solver_base_type; 00229 00231 SolverFactory(); 00232 00262 Teuchos::RCP<solver_base_type> 00263 create (const std::string& solverName, 00264 const Teuchos::RCP<Teuchos::ParameterList>& solverParams); 00265 00271 int numSupportedSolvers () const; 00272 00278 Teuchos::Array<std::string> supportedSolverNames () const; 00279 00281 bool isSupported (const std::string& solverName) const; 00282 00284 00285 00287 std::string description() const; 00288 00294 void describe (Teuchos::FancyOStream& out, 00295 const Teuchos::EVerbosityLevel verbLevel = Teuchos::Describable::verbLevel_default) const; 00297 00298 private: 00311 std::map<std::string, std::string> aliasToCanonicalName_; 00312 00326 std::map<std::string, details::EBelosSolverType> canonicalNameToEnum_; 00327 00333 void 00334 reviseParameterListForAlias (const std::string& aliasName, 00335 const Teuchos::RCP<Teuchos::ParameterList>& solverParams); 00336 00338 Teuchos::Array<std::string> canonicalSolverNames () const; 00339 00341 Teuchos::Array<std::string> solverNameAliases () const; 00342 00344 static void 00345 printStringArray (std::ostream& out, 00346 const Teuchos::ArrayView<const std::string>& array) 00347 { 00348 typedef Teuchos::ArrayView<std::string>::const_iterator iter_type; 00349 00350 out << "["; 00351 for (iter_type iter = array.begin(); iter != array.end(); ++iter) { 00352 out << "\"" << *iter << "\""; 00353 if (iter + 1 != array.end()) { 00354 out << ", "; 00355 } 00356 } 00357 out << "]"; 00358 } 00359 }; 00360 00361 00362 namespace details { 00363 00382 template<class SolverManagerBaseType, class SolverManagerType> 00383 Teuchos::RCP<SolverManagerBaseType> 00384 makeSolverManagerTmpl (const Teuchos::RCP<Teuchos::ParameterList>& params); 00385 00404 template<class Scalar, class MV, class OP> 00405 Teuchos::RCP<SolverManager<Scalar, MV, OP> > 00406 makeSolverManagerFromEnum (const EBelosSolverType solverType, 00407 const Teuchos::RCP<Teuchos::ParameterList>& params) 00408 { 00409 typedef SolverManager<Scalar, MV, OP> base_type; 00410 00411 switch (solverType) { 00412 case SOLVER_TYPE_BLOCK_GMRES: { 00413 typedef BlockGmresSolMgr<Scalar, MV, OP> impl_type; 00414 return makeSolverManagerTmpl<base_type, impl_type> (params); 00415 break; 00416 } 00417 case SOLVER_TYPE_PSEUDO_BLOCK_GMRES: { 00418 typedef PseudoBlockGmresSolMgr<Scalar, MV, OP> impl_type; 00419 return makeSolverManagerTmpl<base_type, impl_type> (params); 00420 break; 00421 } 00422 case SOLVER_TYPE_BLOCK_CG: { 00423 typedef BlockCGSolMgr<Scalar, MV, OP> impl_type; 00424 return makeSolverManagerTmpl<base_type, impl_type> (params); 00425 break; 00426 } 00427 case SOLVER_TYPE_PSEUDO_BLOCK_CG: { 00428 typedef PseudoBlockCGSolMgr<Scalar, MV, OP> impl_type; 00429 return makeSolverManagerTmpl<base_type, impl_type> (params); 00430 break; 00431 } 00432 case SOLVER_TYPE_GCRODR: { 00433 typedef GCRODRSolMgr<Scalar, MV, OP> impl_type; 00434 return makeSolverManagerTmpl<base_type, impl_type> (params); 00435 break; 00436 } 00437 case SOLVER_TYPE_RCG: { 00438 typedef RCGSolMgr<Scalar, MV, OP> impl_type; 00439 return makeSolverManagerTmpl<base_type, impl_type> (params); 00440 break; 00441 } 00442 case SOLVER_TYPE_MINRES: { 00443 typedef MinresSolMgr<Scalar, MV, OP> impl_type; 00444 return makeSolverManagerTmpl<base_type, impl_type> (params); 00445 break; 00446 } 00447 case SOLVER_TYPE_LSQR: { 00448 typedef LSQRSolMgr<Scalar, MV, OP> impl_type; 00449 return makeSolverManagerTmpl<base_type, impl_type> (params); 00450 break; 00451 } 00452 case SOLVER_TYPE_STOCHASTIC_CG: { 00453 typedef PseudoBlockStochasticCGSolMgr<Scalar, MV, OP> impl_type; 00454 return makeSolverManagerTmpl<base_type, impl_type> (params); 00455 } 00456 case SOLVER_TYPE_TFQMR: { 00457 typedef TFQMRSolMgr<Scalar, MV, OP> impl_type; 00458 return makeSolverManagerTmpl<base_type, impl_type> (params); 00459 } 00460 case SOLVER_TYPE_GMRES_POLY: { 00461 typedef GmresPolySolMgr<Scalar, MV, OP> impl_type; 00462 return makeSolverManagerTmpl<base_type, impl_type> (params); 00463 } 00464 case SOLVER_TYPE_PCPG: { 00465 typedef PCPGSolMgr<Scalar, MV, OP> impl_type; 00466 return makeSolverManagerTmpl<base_type, impl_type> (params); 00467 } 00468 default: // Fall through; let the code below handle it. 00469 TEUCHOS_TEST_FOR_EXCEPTION( 00470 true, std::logic_error, "Belos::SolverFactory: Invalid EBelosSolverType " 00471 "enum value " << solverType << ". Please report this bug to the Belos " 00472 "developers."); 00473 } 00474 00475 // Compiler guard. This may result in a warning on some compilers 00476 // for an unreachable statement, but it will prevent a warning on 00477 // other compilers for a "missing return statement at end of 00478 // non-void function." 00479 return Teuchos::null; 00480 } 00481 00482 template<class SolverManagerBaseType, class SolverManagerType> 00483 Teuchos::RCP<SolverManagerBaseType> 00484 makeSolverManagerTmpl (const Teuchos::RCP<Teuchos::ParameterList>& params) 00485 { 00486 using Teuchos::ParameterList; 00487 using Teuchos::parameterList; 00488 using Teuchos::RCP; 00489 00490 RCP<SolverManagerType> solver = rcp (new SolverManagerType); 00491 00492 // Some solvers may not like to get a null ParameterList. If params 00493 // is null, replace it with the solver's default parameters. 00494 RCP<ParameterList> pl; 00495 if (params.is_null()) { 00496 pl = parameterList (*solver->getValidParameters ()); 00497 } else { 00498 pl = params; 00499 } 00500 TEUCHOS_TEST_FOR_EXCEPTION( 00501 pl.is_null(), std::logic_error, 00502 "Belos::SolverFactory: ParameterList to pass to solver is null. This " 00503 "should never happen. Please report this bug to the Belos developers."); 00504 solver->setParameters (pl); 00505 return solver; 00506 } 00507 00508 } // namespace details 00509 00510 00511 template<class Scalar, class MV, class OP> 00512 SolverFactory<Scalar, MV, OP>::SolverFactory() 00513 { 00514 aliasToCanonicalName_["GMRES"] = "Pseudoblock GMRES"; 00515 // NOTE (mfh 29 Nov 2011) Accessing the flexible capability requires 00516 // setting a parameter in the solver's parameter list. This affects 00517 // the SolverFactory's interface, since using the "Flexible GMRES" 00518 // alias requires modifying the user's parameter list if necessary. 00519 // This is a good idea because users may not know about the 00520 // parameter, or may have forgotten. 00521 aliasToCanonicalName_["Block GMRES"] = "Block GMRES"; 00522 aliasToCanonicalName_["Flexible GMRES"] = "Block GMRES"; 00523 aliasToCanonicalName_["CG"] = "Pseudoblock CG"; 00524 aliasToCanonicalName_["PseudoBlockCG"] = "Pseudoblock CG"; 00525 aliasToCanonicalName_["Stochastic CG"] = "Pseudoblock Stochastic CG"; 00526 aliasToCanonicalName_["Recycling CG"] = "RCG"; 00527 aliasToCanonicalName_["Recycling GMRES"] = "GCRODR"; 00528 // For compatibility with Stratimikos' Belos adapter. 00529 aliasToCanonicalName_["Pseudo Block GMRES"] = "Pseudoblock GMRES"; 00530 aliasToCanonicalName_["PseudoBlockGmres"] = "Pseudoblock GMRES"; 00531 aliasToCanonicalName_["Pseudo Block CG"] = "Pseudoblock CG"; 00532 aliasToCanonicalName_["PseudoBlockCG"] = "Pseudoblock CG"; 00533 aliasToCanonicalName_["Transpose-Free QMR"] = "TFQMR"; 00534 aliasToCanonicalName_["GmresPoly"] = "Hybrid Block GMRES"; 00535 aliasToCanonicalName_["Seed GMRES"] = "Hybrid Block GMRES"; 00536 aliasToCanonicalName_["CGPoly"] = "PCPG"; 00537 aliasToCanonicalName_["Seed CG"] = "PCPG"; 00538 00539 // Mapping from canonical solver name (a string) to its 00540 // corresponding enum value. This mapping is one-to-one. 00541 canonicalNameToEnum_["Block GMRES"] = details::SOLVER_TYPE_BLOCK_GMRES; 00542 canonicalNameToEnum_["Pseudoblock GMRES"] = details::SOLVER_TYPE_PSEUDO_BLOCK_GMRES; 00543 canonicalNameToEnum_["Block CG"] = details::SOLVER_TYPE_BLOCK_CG; 00544 canonicalNameToEnum_["Pseudoblock CG"] = details::SOLVER_TYPE_PSEUDO_BLOCK_CG; 00545 canonicalNameToEnum_["Pseudoblock Stochastic CG"] = details::SOLVER_TYPE_STOCHASTIC_CG; 00546 canonicalNameToEnum_["GCRODR"] = details::SOLVER_TYPE_GCRODR; 00547 canonicalNameToEnum_["RCG"] = details::SOLVER_TYPE_RCG; 00548 canonicalNameToEnum_["MINRES"] = details::SOLVER_TYPE_MINRES; 00549 canonicalNameToEnum_["LSQR"] = details::SOLVER_TYPE_LSQR; 00550 canonicalNameToEnum_["TFQMR"] = details::SOLVER_TYPE_TFQMR; 00551 canonicalNameToEnum_["Hybrid Block GMRES"] = details::SOLVER_TYPE_GMRES_POLY; 00552 canonicalNameToEnum_["PCPG"] = details::SOLVER_TYPE_PCPG; 00553 } 00554 00555 00556 template<class Scalar, class MV, class OP> 00557 void 00558 SolverFactory<Scalar, MV, OP>:: 00559 reviseParameterListForAlias (const std::string& aliasName, 00560 const Teuchos::RCP<Teuchos::ParameterList>& solverParams) 00561 { 00562 TEUCHOS_TEST_FOR_EXCEPTION(solverParams.is_null(), std::logic_error, 00563 "Belos::SolverFactory::reviseParameterListForAlias: the input " 00564 "ParameterList is supposed to be nonnull. Please report this " 00565 "bug to the Belos developers."); 00566 if (aliasName == "Flexible GMRES") { 00567 // "Gmres" uses title case in this solver's parameter list. For 00568 // our alias, we prefer the all-capitals "GMRES" that the 00569 // algorithm's authors (Saad and Schultz) used. 00570 solverParams->set ("Flexible Gmres", true); 00571 } 00572 } 00573 00574 00575 template<class Scalar, class MV, class OP> 00576 Teuchos::RCP<typename SolverFactory<Scalar, MV, OP>::solver_base_type> 00577 SolverFactory<Scalar, MV, OP>:: 00578 create (const std::string& solverName, 00579 const Teuchos::RCP<Teuchos::ParameterList>& solverParams) 00580 { 00581 // Check whether the given name is an alias. 00582 std::map<std::string, std::string>::const_iterator aliasIter = 00583 aliasToCanonicalName_.find (solverName); 00584 const bool isAnAlias = (aliasIter != aliasToCanonicalName_.end()); 00585 const std::string candidateCanonicalName = 00586 isAnAlias ? aliasIter->second : solverName; 00587 00588 // Get the canonical name. 00589 std::map<std::string, details::EBelosSolverType>::const_iterator canonicalIter = 00590 canonicalNameToEnum_.find (candidateCanonicalName); 00591 const bool validCanonicalName = (canonicalIter != canonicalNameToEnum_.end()); 00592 00593 // Check whether we found a canonical name. If we didn't and the 00594 // input name is a valid alias, that's a bug. Otherwise, the input 00595 // name is invalid. 00596 TEUCHOS_TEST_FOR_EXCEPTION(! validCanonicalName && isAnAlias, std::logic_error, 00597 "Valid alias \"" << solverName << "\" has candidate canonical name \"" 00598 << candidateCanonicalName << "\", which is not a canonical solver name. " 00599 "Please report this bug to the Belos developers."); 00600 TEUCHOS_TEST_FOR_EXCEPTION(! validCanonicalName && ! isAnAlias, 00601 std::invalid_argument, "Invalid solver name \"" << solverName << "\"."); 00602 00603 // If the input list is null, we create a new list and use that. 00604 // This is OK because the effect of a null parameter list input is 00605 // to use default parameter values. Thus, we can always replace a 00606 // null list with an empty list. 00607 Teuchos::RCP<Teuchos::ParameterList> pl = 00608 solverParams.is_null() ? Teuchos::parameterList() : solverParams; 00609 00610 // Possibly modify the input parameter list as needed. 00611 if (isAnAlias) { 00612 reviseParameterListForAlias (solverName, pl); 00613 } 00614 00615 return details::makeSolverManagerFromEnum<Scalar, MV, OP> (canonicalIter->second, pl); 00616 } 00617 00618 00619 template<class Scalar, class MV, class OP> 00620 std::string 00621 SolverFactory<Scalar, MV, OP>::description() const 00622 { 00623 using Teuchos::TypeNameTraits; 00624 00625 std::ostringstream out; 00626 out << "\"Belos::SolverFactory\": {"; 00627 if (this->getObjectLabel () != "") { 00628 out << "Label: " << this->getObjectLabel () << ", "; 00629 } 00630 out << "Scalar: " << TypeNameTraits<Scalar>::name () 00631 << ", MV: " << TypeNameTraits<MV>::name () 00632 << ", OP: " << TypeNameTraits<OP>::name () 00633 << "}"; 00634 return out.str (); 00635 } 00636 00637 00638 template<class Scalar, class MV, class OP> 00639 void 00640 SolverFactory<Scalar, MV, OP>:: 00641 describe (Teuchos::FancyOStream& out, 00642 const Teuchos::EVerbosityLevel verbLevel) const 00643 { 00644 using Teuchos::TypeNameTraits; 00645 using std::endl; 00646 00647 const Teuchos::EVerbosityLevel vl = 00648 (verbLevel == Teuchos::VERB_DEFAULT) ? Teuchos::VERB_LOW : verbLevel; 00649 00650 if (vl == Teuchos::VERB_NONE) { 00651 return; 00652 } 00653 00654 // By convention, describe() always begins with a tab. 00655 Teuchos::OSTab tab0 (out); 00656 // The description prints in YAML format. The class name needs to 00657 // be protected with quotes, so that YAML doesn't get confused 00658 // between the colons in the class name and the colon separating 00659 // (key,value) pairs. 00660 out << "\"Belos::SolverFactory\":" << endl; 00661 if (this->getObjectLabel () != "") { 00662 out << "Label: " << this->getObjectLabel () << endl; 00663 } 00664 { 00665 out << "Template parameters:" << endl; 00666 Teuchos::OSTab tab1 (out); 00667 out << "Scalar: " << TypeNameTraits<Scalar>::name () << endl 00668 << "MV: " << TypeNameTraits<MV>::name () << endl 00669 << "OP: " << TypeNameTraits<OP>::name () << endl; 00670 } 00671 00672 // At higher verbosity levels, print out the list of supported solvers. 00673 if (vl > Teuchos::VERB_LOW) { 00674 Teuchos::OSTab tab1 (out); 00675 out << "Number of solvers: " << numSupportedSolvers () 00676 << endl; 00677 out << "Canonical solver names: "; 00678 printStringArray (out, canonicalSolverNames ()); 00679 out << endl; 00680 00681 out << "Aliases to canonical names: "; 00682 printStringArray (out, solverNameAliases ()); 00683 out << endl; 00684 } 00685 } 00686 00687 template<class Scalar, class MV, class OP> 00688 int 00689 SolverFactory<Scalar, MV, OP>::numSupportedSolvers () const 00690 { 00691 return static_cast<int> (canonicalNameToEnum_.size()); 00692 } 00693 00694 template<class Scalar, class MV, class OP> 00695 Teuchos::Array<std::string> 00696 SolverFactory<Scalar, MV, OP>::canonicalSolverNames () const 00697 { 00698 Teuchos::Array<std::string> canonicalNames; 00699 typedef std::map<std::string, details::EBelosSolverType>::const_iterator iter_type; 00700 for (iter_type iter = canonicalNameToEnum_.begin(); 00701 iter != canonicalNameToEnum_.end(); ++iter) { 00702 canonicalNames.push_back (iter->first); 00703 } 00704 return canonicalNames; 00705 } 00706 00707 template<class Scalar, class MV, class OP> 00708 Teuchos::Array<std::string> 00709 SolverFactory<Scalar, MV, OP>::solverNameAliases () const 00710 { 00711 Teuchos::Array<std::string> names; 00712 { 00713 typedef std::map<std::string, std::string>::const_iterator iter_type; 00714 for (iter_type iter = aliasToCanonicalName_.begin(); 00715 iter != aliasToCanonicalName_.end(); ++iter) { 00716 names.push_back (iter->first); 00717 } 00718 } 00719 return names; 00720 } 00721 00722 template<class Scalar, class MV, class OP> 00723 Teuchos::Array<std::string> 00724 SolverFactory<Scalar, MV, OP>::supportedSolverNames () const 00725 { 00726 Teuchos::Array<std::string> names; 00727 { 00728 typedef std::map<std::string, std::string>::const_iterator iter_type; 00729 for (iter_type iter = aliasToCanonicalName_.begin(); 00730 iter != aliasToCanonicalName_.end(); ++iter) { 00731 names.push_back (iter->first); 00732 } 00733 } 00734 { 00735 typedef std::map<std::string, details::EBelosSolverType>::const_iterator iter_type; 00736 for (iter_type iter = canonicalNameToEnum_.begin(); 00737 iter != canonicalNameToEnum_.end(); ++iter) { 00738 names.push_back (iter->first); 00739 } 00740 } 00741 return names; 00742 } 00743 00744 } // namespace Belos 00745 00746 #endif // __Belos_SolverFactory_hpp 00747
1.7.6.1