|
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_AkxFactory_hpp 00043 #define __Belos_AkxFactory_hpp 00044 00045 #include <BelosMonomialOpAkx.hpp> 00046 #include <Teuchos_ParameterList.hpp> 00047 00048 #include <algorithm> 00049 #include <cctype> 00050 00051 // TODO Include other OpAkx implementations, and other Akx 00052 // implementations (that don't implement OpAkx) as they are completed. 00053 00054 namespace Belos { 00055 00069 template<class Scalar, class MV> 00070 class AkxFactory { 00071 public: 00075 typedef Akx<Scalar, MV> akx_base_type; 00076 00080 AkxFactory(); 00081 00103 template<class OP> 00104 Teuchos::RCP<akx_base_type> 00105 makeOpAkx (const Teuchos::RCP<const OP>& A, 00106 const Teuchos::RCP<const OP>& M_left, 00107 const Teuchos::RCP<const OP>& M_right, 00108 const Teuchos::RCP<const Teuchos::ParameterList>& params); 00109 00111 Teuchos::RCP<const Teuchos::ParameterList> 00112 getDefaultParameters (); 00113 00119 const std::string& parameterListName () const { 00120 return listName_; 00121 } 00122 00123 private: 00133 std::string 00134 validateBasisName (const std::string& basisName) const; 00135 00137 const std::string listName_; 00138 00140 std::vector<std::string> validBasisNames_; 00141 00145 Teuchos::RCP<const Teuchos::ParameterList> defaultParams_; 00146 }; 00147 00148 00149 template<class Scalar, class MV> 00150 AkxFactory<Scalar, MV>::AkxFactory() : listName_ ("Akx") 00151 { 00152 typedef std::vector<std::string>::size_type size_type; 00153 // 00154 // TODO (mfh 14 Feb 2011) Support more basis types later. 00155 // 00156 const size_type numValidBasisNames = 1; 00157 const char* validBasisNames[] = {"Monomial"}; 00158 validBasisNames_.resize (numValidBasisNames); 00159 00160 for (size_type k = 0; k < numValidBasisNames; ++k) 00161 validBasisNames_.push_back (validBasisNames[k]); 00162 } 00163 00164 template<class Scalar, class MV> 00165 Teuchos::RCP<typename AkxFactory<Scalar, MV>::akx_base_type> 00166 AkxFactory<Scalar, MV>:: 00167 makeOpAkx (const Teuchos::RCP<const OP>& A, 00168 const Teuchos::RCP<const OP>& M_left, 00169 const Teuchos::RCP<const OP>& M_right, 00170 const Teuchos::RCP<const Teuchos::ParameterList>& params) 00171 { 00172 using Teuchos::ParameterList; 00173 using Teuchos::RCP; 00174 using Teuchos::Exceptions::InvalidParameter; 00175 using Teuchos::Exceptions::InvalidParameterName; 00176 using Teuchos::Exceptions::InvalidParameterType; 00177 00178 RCP<const ParameterList> plist = 00179 params.is_null() ? getDefaultParameters() : params; 00180 00181 std::string basisType; 00182 try { 00183 basisType = plist->get<std::string> ("Basis Type"); 00184 } catch (InvalidParameter& e) { 00185 // FIXME (mfh 14 Feb 2011, 03 Mar 2011) 00186 // 00187 // Just rethrow for now. Later we might wrap and rethrow, or 00188 // implement more tolerant behavior. 00189 throw e; 00190 } 00191 // Canonicalize (case, etc.) the string and validate it. Throw an 00192 // exception if invalid, else return the canonicalized name. 00193 const std::string validName = validateBasisName (basisType); 00194 00195 // Recommended (at least initially) basis length. 00196 int basisLength = 5; // a reasonable default 00197 try { 00198 basisLength = plist->get<int> ("Basis Length"); 00199 } catch (InvalidParameter& e) { 00200 // Do nothing; let the default stay 00201 } 00202 TEUCHOS_TEST_FOR_EXCEPTION(basisLength < 1, std::invalid_argument, 00203 "The \"Basis Length\" parameter must be >= 1, " 00204 "but its value here is " << basisLength << "."); 00205 if (validName == "Monomial") 00206 { 00207 typedef MonomialOpAkx<Scalar, MV, OP> akx_impl_type; 00208 RCP<akx_impl_type> akx (new akx_impl_type (A, M_left, M_right, basisLength)); 00209 return akx; 00210 } 00211 else 00212 { 00213 TEUCHOS_TEST_FOR_EXCEPTION(validName != "Monomial", std::logic_error, 00214 "We have not yet implemented the \"" 00215 << validName << "\" basis."); 00216 throw std::logic_error("Should never get here!"); 00217 } 00218 } 00219 00220 template<class Scalar, class MV> 00221 Teuchos::RCP<const Teuchos::ParameterList> 00222 AkxFactory<Scalar, MV>::getDefaultParameters () 00223 { 00224 using Teuchos::RCP; 00225 using Teuchos::ParameterList; 00226 using Teuchos::parameterList; 00227 00228 if (defaultParams_.is_null()) 00229 { 00230 RCP<ParameterList> plist = parameterList (parameterListName ()); 00231 // Default basis type is monomial for now; this will likely 00232 // change to the Newton basis. 00233 const std::string defaultBasis ("Monomial"); 00234 { 00235 std::ostringstream os; 00236 os << "Default basis type. Valid choices include: {"; 00237 for (std::vector<std::string>::size_type k = 0; 00238 k < validBasisNames_.size(); ++k) 00239 { 00240 os << validBasisNames_[k]; 00241 if (k < validBasisNames_.size() - 1) 00242 os << ", "; 00243 } 00244 os << "}."; 00245 plist->set ("Basis Type", defaultBasis, os.str()); 00246 } 00247 // An initial basis length of 5 is a reasonable first guess. 00248 // Solvers should revise this dynamically, based on their 00249 // estimates of the condition number and rank of the generated 00250 // candidate basis. 00251 const int defaultBasisLength = 5; 00252 plist->set ("Basis Length", defaultBasisLength, 00253 "Default recommended basis length."); 00254 defaultParams_ = plist; 00255 } 00256 return defaultParams_; 00257 } 00258 00259 template<class Scalar, class MV> 00260 std::string 00261 AkxFactory<Scalar, MV>::validateBasisName (const std::string& basisName) const 00262 { 00263 // Canonicalize the basis name. First, strip whitespace. 00264 // Second, capitalize the first letter and lowercase the rest. 00265 TEUCHOS_TEST_FOR_EXCEPTION(basisName.empty(), std::invalid_argument, 00266 "The matrix powers kernel basis name is an empty " 00267 "string."); 00268 const size_t npos = std::string::npos; 00269 size_t firstNonSpacePos = basisName.find_first_not_of (" \t\n"); 00270 size_t lastNonSpacePos = basisName.find_last_not_of (" \t\n"); 00271 TEUCHOS_TEST_FOR_EXCEPTION(firstNonSpacePos == npos, std::invalid_argument, 00272 "The matrix powers kernel basis name \"" << basisName 00273 << "\" contains only whitespace."); 00274 // canonName must have length at least one. 00275 std::string canonName = 00276 basisName.substr (firstNonSpacePos, lastNonSpacePos-firstNonSpacePos+1); 00277 // Capitalize the first letter and lowercase the rest, in place. 00278 canonName[0] = toupper (canonName[0]); 00279 std::transform (canonName.begin()+1, canonName.end(), 00280 canonName.begin()+1, tolower); 00281 const bool foundIt = validBasisNames_.end() != 00282 std::find (validBasisNames_.begin(), validBasisNames_.end(), canonName); 00283 TEUCHOS_TEST_FOR_EXCEPTION(! foundIt, std::invalid_argument, 00284 "Invalid basis name \"" << basisName << "\"."); 00285 return canonName; 00286 } 00287 00288 00289 } // namespace Belos 00290 00291 #endif // __Belos_AkxFactory_hpp
1.7.4