Belos Package Browser (Single Doxygen Collection)  Development
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BelosSolverFactory.hpp
Go to the documentation of this file.
1 //@HEADER
2 // ************************************************************************
3 //
4 // Belos: Block Linear Solvers Package
5 // Copyright 2004 Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ************************************************************************
40 //@HEADER
41 
42 #ifndef __Belos_SolverFactory_hpp
43 #define __Belos_SolverFactory_hpp
44 
45 #include <BelosConfigDefs.hpp>
46 #include <BelosOutputManager.hpp>
47 #include <BelosSolverManager.hpp>
48 
51 
52 #include <Teuchos_Describable.hpp>
55 
56 #include <map>
57 #include <sstream>
58 #include <stdexcept>
59 #include <vector>
60 
61 namespace Belos {
62 namespace Impl {
63 
65 void
66 printStringArray (std::ostream& out,
68 
70 void
71 printStringArray (std::ostream& out,
72  const std::vector<std::string>& array);
73 
75 std::string
76 upperCase (const std::string& s);
77 
94 template<class Scalar, class MV, class OP>
97 {
98 protected:
99  // SolverFactoryParent should never be created directly. Usually it will be
100  // created through derived classes EpetraSolverFactory, TpetraSolverFactory,
101  // BelosSolverFactory, or XpetraSolverFactory. If you are doing custom types
102  // and include BelosSolverFactory_Generic.hpp you should explicitly use
103  // GenericSolverFactory, not SolverFactory, which will avoid an error trying
104  // to construct here. GenericSolverFactory is special because it registers
105  // all the solver managers for any type. Note that if you are using hard coded
106  // types it is possible that some the type sets will be connecting to an
107  // automatic solver factory such as TpetraSolverFactory while another type
108  // set could be going through the GenericSolverFactory.
110 
111 public:
117  typedef ::Belos::SolverManager<Scalar, MV, OP> solver_base_type;
118 
122 
123 protected:
162  getSolver (const std::string& solverName,
163  const Teuchos::RCP<Teuchos::ParameterList>& solverParams);
164 
165 public:
176  create (const std::string& solverName,
177  const Teuchos::RCP<Teuchos::ParameterList>& solverParams);
178 
184  virtual int numSupportedSolvers () const;
185 
192 
194  virtual bool isSupported (const std::string& solverName) const;
195 
210  void
212 
214  static void
215  registerSolver (const std::string & solverName,
217  {
219  instance == Teuchos::null,
220  std::invalid_argument, "Belos::SolverFactoryParent::registerSolver "
221  "was given a null solver to register.");
222 
223  get_solverManagers()[solverName] = instance;
224  }
225 
227  static bool
228  isSolverRegistered (const std::string & solverName)
229  {
230  return (get_solverManagers().find(solverName) != get_solverManagers().end());
231  }
232 
234 
235 
237  virtual std::string description() const;
238 
244  virtual void
246  const Teuchos::EVerbosityLevel verbLevel =
249 
250 private:
252  static std::vector<Teuchos::RCP<custom_solver_factory_type> > factories_;
253 
254  static std::map<const std::string, Teuchos::RCP<typename
257  static std::map<const std::string, Teuchos::RCP<typename
259  return solverManagers;
260  }
261 };
262 
263 template<class Scalar, class MV, class OP>
264 std::vector<Teuchos::RCP<typename SolverFactoryParent<Scalar, MV, OP>::custom_solver_factory_type> >
265 SolverFactoryParent<Scalar, MV, OP>::factories_;
266 
267 template<class SolverClass, class Scalar, class MV, class OP>
268 void registerSolverSubclassForTypes (const std::string & solverName) {
270  Teuchos::RCP<SolverClass> solver (new SolverClass);
272  }
273 }
274 
275 // specializations get a typedef "type"
276 // If this compile fails then the error is likely that BelosSolverFactory.hpp
277 // was included directly but the specific sub class of SolverFactoryParent was
278 // not included. Examples are:
279 // BelosSolverFactory_Belos.hpp, BelosSolverFactory_Epetra.hpp,
280 // BelosSolverFactory_Tpetra.hpp, BelosSolverFactory_Xpetra.hpp
281 // These were setup to be automatically included through the corresponding
282 // adapter includes so something may have gone wrong with that.
283 template<class SC, class MV, class OP>
285  public:
286  // TODO: This could be deleted except for the GenericSolverFactory which
287  // needs to be declared for all types. So I added this but then if you
288  // include GenericSolverFactory you will have SolverFactory simply point
289  // to SolverFactoryParent. I changed that constructor to be protected so
290  // using SolverFactory (pointing to SolverFactoryParent) will give a compile
291  // error. For GenericSolverFactory you must explicity use GenericSolverFactory
292  // in the code. This may be preferable because it makes it clear that
293  // factory is not connecting to the standard set of types. I'm not sure how
294  // to do this in a better way.
296 };
297 
298 } // namespace Impl
299 
300 // Derived setups such as found in BelosSolverFactory_Tpetra.hpp will define
301 // this specialization so that SolverFactory will be used as SolverFactoryTpetra.
302 template<class SC, class MV, class OP>
303 using SolverFactory = typename ::Belos::Impl::SolverFactorySelector<SC, MV, OP>::type;
304 
305 namespace Impl {
306 
307 template<class Scalar, class MV, class OP>
310 create (const std::string& solverName,
311  const Teuchos::RCP<Teuchos::ParameterList>& solverParams)
312 {
313  using Teuchos::RCP;
314  RCP<solver_base_type> solver = this->getSolver (solverName, solverParams);
316  (solver.is_null (), std::invalid_argument,
317  "Invalid or unsupported Belos solver name \"" << solverName << "\".");
318  return solver;
319 }
320 
321 template<class Scalar, class MV, class OP>
324 getSolver (const std::string& solverName,
325  const Teuchos::RCP<Teuchos::ParameterList>& solverParams)
326 {
327  using Teuchos::RCP;
328 
329  // First, check the overriding factories.
330  for (std::size_t k = 0; k < factories_.size (); ++k) {
331  RCP<CustomSolverFactory<Scalar, MV, OP> > factory = factories_[k];
332  if (! factory.is_null ()) {
333  RCP<SolverManager<Scalar, MV, OP> > solver =
334  factory->getSolver (solverName, solverParams);
335  if (! solver.is_null ()) {
336  return solver;
337  }
338  }
339  }
340 
341  // Upper-case version of the input solver name.
342  const std::string solverNameUC = Impl::upperCase (solverName);
343 
344  // Check whether the given name is an alias.
345  std::pair<std::string, bool> aliasResult =
346  Details::getCanonicalNameFromAlias (solverNameUC);
347  const std::string candidateCanonicalName = aliasResult.first;
348  const bool isAnAlias = aliasResult.second;
349 
350  // Get the standardized name for enum reference and map
351  std::string standardized_name = isAnAlias ?
352  candidateCanonicalName :
353  solverNameUC;
354 
355  // If the input list is null, we create a new list and use that.
356  // This is OK because the effect of a null parameter list input is
357  // to use default parameter values. Thus, we can always replace a
358  // null list with an empty list.
360  solverParams.is_null() ? Teuchos::parameterList() : solverParams;
361 
362  // Possibly modify the input parameter list as needed.
363  if (isAnAlias) {
364  Details::reviseParameterListForAlias (solverNameUC, *pl);
365  }
366 
367  typename std::map<const std::string, Teuchos::RCP<
369  it = get_solverManagers().find (standardized_name);
370 
372  it == get_solverManagers().end(),
373  std::invalid_argument, "Belos solver manager " << solverNameUC <<
374  " with standardized name " << standardized_name << " has not been"
375  " registered.");
376 
378  it->second == Teuchos::null,
379  std::logic_error, "Belos::SolverFactoryParent: The registered "
380  "clone source for " << solverNameUC << " with standardized name "
381  << standardized_name << " is null which should never happen."
382  ". Please report this bug to the Belos developers.");
383 
384  // clone the solver
385  RCP<solver_base_type> solver = (it->second)->clone ();
386 
388  solver == Teuchos::null,
389  std::logic_error, "Belos::SolverFactoryParent: Failed "
390  "to clone SolverManager with name " << solverNameUC << " with standardized"
391  " name" << standardized_name << "."
392  ". Please report this bug to the Belos developers.");
393 
394  // Some solvers may not like to get a null ParameterList. If params
395  // is null, replace it with an empty parameter list. The solver
396  // will fill in default parameters for that case. Use the name of
397  // the solver's default parameters to name the new empty list.
398  if (pl.is_null()) {
399  pl = Teuchos::parameterList (solver->getValidParameters ()->name ());
400  }
401 
403  pl.is_null(), std::logic_error,
404  "Belos::SolverFactory: ParameterList to pass to solver is null. This "
405  "should never happen. Please report this bug to the Belos developers.");
406  solver->setParameters (pl);
407  return solver;
408 }
409 
410 
411 template<class Scalar, class MV, class OP>
412 void
415 {
416  factories_.push_back (factory);
417 }
418 
419 
420 template<class Scalar, class MV, class OP>
421 std::string
423 description () const
424 {
426 
427  std::ostringstream out;
428  out << "\"Belos::SolverFactory\": {";
429  if (this->getObjectLabel () != "") {
430  out << "Label: " << this->getObjectLabel () << ", ";
431  }
432  out << "Scalar: \"" << TypeNameTraits<Scalar>::name ()
433  << "\", MV: \"" << TypeNameTraits<MV>::name ()
434  << "\", OP: \"" << TypeNameTraits<OP>::name ()
435  << "\"}";
436  return out.str ();
437 }
438 
439 
440 template<class Scalar, class MV, class OP>
441 void
444  const Teuchos::EVerbosityLevel verbLevel) const
445 {
447  using std::endl;
448 
449  const Teuchos::EVerbosityLevel vl =
450  (verbLevel == Teuchos::VERB_DEFAULT) ? Teuchos::VERB_LOW : verbLevel;
451 
452  if (vl == Teuchos::VERB_NONE) {
453  return;
454  }
455 
456  // By convention, describe() always begins with a tab.
457  Teuchos::OSTab tab0 (out);
458  // The description prints in YAML format. The class name needs to
459  // be protected with quotes, so that YAML doesn't get confused
460  // between the colons in the class name and the colon separating
461  // (key,value) pairs.
462  out << "\"Belos::SolverFactory\":" << endl;
463  if (this->getObjectLabel () != "") {
464  out << "Label: " << this->getObjectLabel () << endl;
465  }
466  {
467  out << "Template parameters:" << endl;
468  Teuchos::OSTab tab1 (out);
469  out << "Scalar: \"" << TypeNameTraits<Scalar>::name () << "\"" << endl
470  << "MV: \"" << TypeNameTraits<MV>::name () << "\"" << endl
471  << "OP: \"" << TypeNameTraits<OP>::name () << "\"" << endl;
472  }
473 
474  // At higher verbosity levels, print out the list of supported solvers.
475  if (vl > Teuchos::VERB_LOW) {
476  Teuchos::OSTab tab1 (out);
477  out << "Number of solvers: " << numSupportedSolvers ()
478  << endl;
479  out << "Canonical solver names: ";
481  out << endl;
482 
483  out << "Aliases to canonical names: ";
485  out << endl;
486  }
487 }
488 
489 template<class Scalar, class MV, class OP>
490 int
493 {
494  int numSupported = 0;
495 
496  // First, check the overriding factories.
497  for (std::size_t k = 0; k < factories_.size (); ++k) {
498  using Teuchos::RCP;
499  RCP<custom_solver_factory_type> factory = factories_[k];
500  if (! factory.is_null ()) {
501  numSupported += factory->numSupportedSolvers ();
502  }
503  }
504 
505  // Now, see how many solvers this factory supports.
506  return numSupported + Details::numSupportedSolvers ();
507 }
508 
509 template<class Scalar, class MV, class OP>
513 {
514  typedef std::vector<std::string>::const_iterator iter_type;
516 
517  // First, check the overriding factories.
518  const std::size_t numFactories = factories_.size ();
519  for (std::size_t factInd = 0; factInd < numFactories; ++factInd) {
520  Teuchos::RCP<custom_solver_factory_type> factory = factories_[factInd];
521  if (! factory.is_null ()) {
522  std::vector<std::string> supportedSolvers =
523  factory->supportedSolverNames ();
524  const std::size_t numSolvers = supportedSolvers.size ();
525  for (std::size_t solvInd = 0; solvInd < numSolvers; ++solvInd) {
526  names.push_back (supportedSolvers[solvInd]);
527  }
528  }
529  }
530 
531  {
532  std::vector<std::string> aliases = Details::solverNameAliases ();
533  for (iter_type iter = aliases.begin (); iter != aliases.end (); ++iter) {
534  names.push_back (*iter);
535  }
536  }
537  {
538  std::vector<std::string> canonicalNames = Details::canonicalSolverNames ();
539  for (iter_type iter = canonicalNames.begin ();
540  iter != canonicalNames.end (); ++iter) {
541  names.push_back (*iter);
542  }
543  }
544  return names;
545 }
546 
547 template<class Scalar, class MV, class OP>
548 bool
550 isSupported (const std::string& solverName) const
551 {
552  // First, check the overriding factories.
553  const std::size_t numFactories = factories_.size ();
554  for (std::size_t factInd = 0; factInd < numFactories; ++factInd) {
555  using Teuchos::RCP;
556  RCP<custom_solver_factory_type> factory = factories_[factInd];
557  if (! factory.is_null ()) {
558  if (factory->isSupported (solverName)) {
559  return true;
560  }
561  }
562  }
563  // Now, check this factory.
564 
565  // Upper-case version of the input solver name.
566  const std::string solverNameUC = Impl::upperCase (solverName);
567 
568  // Check whether the given name is an alias.
569  std::pair<std::string, bool> aliasResult =
570  Details::getCanonicalNameFromAlias (solverNameUC);
571  const std::string candidateCanonicalName = aliasResult.first;
572  const bool validCanonicalName =
573  (get_solverManagers().find(candidateCanonicalName) != get_solverManagers().end());
574  return validCanonicalName;
575 }
576 
577 } // namespace Impl
578 } // namespace Belos
579 
580 // We have things like BelosSolverFactory_Tpetra.hpp which are automatically
581 // included through the adapter includes to maintain backwards compatibility.
582 // The Belos version itself doesn't have a place like that so included here
583 // which is awkward. It might make more sense to just copy that code here but
584 // it has symmetry with the other files and wanted to preserve that. To discuss.
586 
587 #endif // __Belos_SolverFactory_hpp
588 
Interface for custom Belos solver factories.
Class which manages the output and verbosity of the Belos solvers.
static std::vector< Teuchos::RCP< custom_solver_factory_type > > factories_
The list of solver factories given to addFactory.
SolverFactoryParent< SC, MV, OP > type
static void registerSolver(const std::string &solverName, Teuchos::RCP< SolverFactoryParent< Scalar, MV, OP >::solver_base_type > instance)
register a solver for Inverted Injection (DII).
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
std::string upperCase(const std::string &s)
Return the upper-case version of s.
virtual int numSupportedSolvers() const
Number of supported solvers.
void addFactory(const Teuchos::RCP< custom_solver_factory_type > &factory)
Add a custom solver factory.
Declaration of alias functions for solver names.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Describe this object.
Pure virtual base class which describes the basic interface for a solver manager. ...
bool is_null(const RCP< T > &p)
std::vector< std::string > solverNameAliases()
List of supported aliases (to canonical solver names).
void printStringArray(std::ostream &out, const Teuchos::ArrayView< const std::string > &array)
Print the given array of strings, in YAML format, to out.
int numSupportedSolvers()
Number of Belos solvers supported for any linear algebra implementation (&quot;generically&quot;).
The Belos::SolverManager is a templated virtual base class that defines the basic interface that any ...
virtual Teuchos::RCP< solver_base_type > getSolver(const std::string &solverName, const Teuchos::RCP< Teuchos::ParameterList > &solverParams)
Return an instance of the specified solver, or Teuchos::null if this factory does not provide the req...
static const EVerbosityLevel verbLevel_default
TransListIter iter
virtual Teuchos::Array< std::string > supportedSolverNames() const
List of supported solver names.
void push_back(const value_type &x)
virtual Teuchos::RCP< solver_base_type > create(const std::string &solverName, const Teuchos::RCP< Teuchos::ParameterList > &solverParams)
Create, configure, and return the specified solver.
Specializations of Belos::SolverFactory may inherit from this class to get basic SolverFactory functi...
static std::map< const std::string, Teuchos::RCP< typename SolverFactoryParent< Scalar, MV, OP >::solver_base_type > > & get_solverManagers()
std::pair< std::string, bool > getCanonicalNameFromAlias(const std::string &candidateAlias)
Get the candidate canonical name for a given candidate alias.
::Belos::SolverManager< Scalar, MV, OP > solver_base_type
The type of the solver returned by create().
size_type size() const
void reviseParameterListForAlias(const std::string &aliasName, Teuchos::ParameterList &solverParams)
Modify the input ParameterList appropriately for the given solver alias.
void registerSolverSubclassForTypes(const std::string &solverName)
virtual bool isSupported(const std::string &solverName) const
Whether the given solver name names a supported solver.
Belos header file which uses auto-configuration information to include necessary C++ headers...
TransListIter end
typename::Belos::Impl::SolverFactorySelector< SC, MV, OP >::type SolverFactory
virtual std::string description() const
A string description of this object.
static bool isSolverRegistered(const std::string &solverName)
is solver registered for Inverted Injection (DII).
CustomSolverFactory< Scalar, MV, OP > custom_solver_factory_type
The type of a solver factory that users may give to addFactory() (which see below) ...
std::vector< std::string > canonicalSolverNames()
List of canonical solver names.