Belos  Version of the Day
 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>
53 #include <Teuchos_StandardCatchMacros.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 
220  void
221  clearFactories ();
222 
224  static void
225  registerSolver (const std::string & solverName,
227  {
229  instance == Teuchos::null,
230  std::invalid_argument, "Belos::SolverFactoryParent::registerSolver "
231  "was given a null solver to register.");
232 
233  get_solverManagers()[solverName] = instance;
234  }
235 
237  static bool
238  isSolverRegistered (const std::string & solverName)
239  {
240  return (get_solverManagers().find(solverName) != get_solverManagers().end());
241  }
242 
244 
245 
247  virtual std::string description() const;
248 
254  virtual void
256  const Teuchos::EVerbosityLevel verbLevel =
259 
260 private:
262  static std::vector<Teuchos::RCP<custom_solver_factory_type> > factories_;
263 
264  static std::map<const std::string, Teuchos::RCP<typename
266  get_solverManagers() {
267  static std::map<const std::string, Teuchos::RCP<typename
269  return solverManagers;
270  }
271 };
272 
273 template<class Scalar, class MV, class OP>
274 std::vector<Teuchos::RCP<typename SolverFactoryParent<Scalar, MV, OP>::custom_solver_factory_type> >
275 SolverFactoryParent<Scalar, MV, OP>::factories_;
276 
277 template<class SolverClass, class Scalar, class MV, class OP>
278 void registerSolverSubclassForTypes (const std::string & solverName) {
280  Teuchos::RCP<SolverClass> solver (new SolverClass);
282  }
283 }
284 
285 // specializations get a typedef "type"
286 // If this compile fails then the error is likely that BelosSolverFactory.hpp
287 // was included directly but the specific sub class of SolverFactoryParent was
288 // not included. Examples are:
289 // BelosSolverFactory_Belos.hpp, BelosSolverFactory_Epetra.hpp,
290 // BelosSolverFactory_Tpetra.hpp, BelosSolverFactory_Xpetra.hpp
291 // These were setup to be automatically included through the corresponding
292 // adapter includes so something may have gone wrong with that.
293 template<class SC, class MV, class OP>
295  public:
296  // TODO: This could be deleted except for the GenericSolverFactory which
297  // needs to be declared for all types. So I added this but then if you
298  // include GenericSolverFactory you will have SolverFactory simply point
299  // to SolverFactoryParent. I changed that constructor to be protected so
300  // using SolverFactory (pointing to SolverFactoryParent) will give a compile
301  // error. For GenericSolverFactory you must explicity use GenericSolverFactory
302  // in the code. This may be preferable because it makes it clear that
303  // factory is not connecting to the standard set of types. I'm not sure how
304  // to do this in a better way.
306 };
307 
308 } // namespace Impl
309 
310 // Derived setups such as found in BelosSolverFactory_Tpetra.hpp will define
311 // this specialization so that SolverFactory will be used as SolverFactoryTpetra.
312 template<class SC, class MV, class OP>
313 using SolverFactory = typename ::Belos::Impl::SolverFactorySelector<SC, MV, OP>::type;
314 
315 namespace Impl {
316 
317 template<class Scalar, class MV, class OP>
320 create (const std::string& solverName,
321  const Teuchos::RCP<Teuchos::ParameterList>& solverParams)
322 {
323  using Teuchos::RCP;
324  RCP<solver_base_type> solver = this->getSolver (solverName, solverParams);
326  (solver.is_null (), std::invalid_argument,
327  "Invalid or unsupported Belos solver name \"" << solverName << "\".");
328  return solver;
329 }
330 
331 template<class Scalar, class MV, class OP>
334 getSolver (const std::string& solverName,
335  const Teuchos::RCP<Teuchos::ParameterList>& solverParams)
336 {
337  using Teuchos::RCP;
338 
339  // First, check the overriding factories.
340  for (std::size_t k = 0; k < factories_.size (); ++k) {
341  RCP<CustomSolverFactory<Scalar, MV, OP> > factory = factories_[k];
342  if (! factory.is_null ()) {
343  RCP<SolverManager<Scalar, MV, OP> > solver =
344  factory->getSolver (solverName, solverParams);
345  if (! solver.is_null ()) {
346  return solver;
347  }
348  }
349  }
350 
351  // Upper-case version of the input solver name.
352  const std::string solverNameUC = Impl::upperCase (solverName);
353 
354  // Check whether the given name is an alias.
355  std::pair<std::string, bool> aliasResult =
356  Details::getCanonicalNameFromAlias (solverNameUC);
357  const std::string candidateCanonicalName = aliasResult.first;
358  const bool isAnAlias = aliasResult.second;
359 
360  // Get the standardized name for enum reference and map
361  std::string standardized_name = isAnAlias ?
362  candidateCanonicalName :
363  solverNameUC;
364 
365  // If the input list is null, we create a new list and use that.
366  // This is OK because the effect of a null parameter list input is
367  // to use default parameter values. Thus, we can always replace a
368  // null list with an empty list.
370  solverParams.is_null() ? Teuchos::parameterList() : solverParams;
371 
372  // Possibly modify the input parameter list as needed.
373  if (isAnAlias) {
374  Details::reviseParameterListForAlias (solverNameUC, *pl);
375  }
376 
377  typename std::map<const std::string, Teuchos::RCP<
379  it = get_solverManagers().find (standardized_name);
380 
382  it == get_solverManagers().end(),
383  std::invalid_argument, "Belos solver manager " << solverNameUC <<
384  " with standardized name " << standardized_name << " has not been"
385  " registered.");
386 
388  it->second == Teuchos::null,
389  std::logic_error, "Belos::SolverFactoryParent: The registered "
390  "clone source for " << solverNameUC << " with standardized name "
391  << standardized_name << " is null which should never happen."
392  ". Please report this bug to the Belos developers.");
393 
394  // clone the solver
395  RCP<solver_base_type> solver = (it->second)->clone ();
396 
398  solver == Teuchos::null,
399  std::logic_error, "Belos::SolverFactoryParent: Failed "
400  "to clone SolverManager with name " << solverNameUC << " with standardized"
401  " name" << standardized_name << "."
402  ". Please report this bug to the Belos developers.");
403 
404  // Some solvers may not like to get a null ParameterList. If params
405  // is null, replace it with an empty parameter list. The solver
406  // will fill in default parameters for that case. Use the name of
407  // the solver's default parameters to name the new empty list.
408  if (pl.is_null()) {
409  pl = Teuchos::parameterList (solver->getValidParameters ()->name ());
410  }
411 
413  pl.is_null(), std::logic_error,
414  "Belos::SolverFactory: ParameterList to pass to solver is null. This "
415  "should never happen. Please report this bug to the Belos developers.");
416  solver->setParameters (pl);
417  return solver;
418 }
419 
420 
421 template<class Scalar, class MV, class OP>
422 void
425 {
426  factories_.push_back (factory);
427 }
428 
429 
430 template<class Scalar, class MV, class OP>
431 void
434 {
435  factories_.clear();
436 }
437 
438 
439 template<class Scalar, class MV, class OP>
440 std::string
442 description () const
443 {
445 
446  std::ostringstream out;
447  out << "\"Belos::SolverFactory\": {";
448  if (this->getObjectLabel () != "") {
449  out << "Label: " << this->getObjectLabel () << ", ";
450  }
451  out << "Scalar: \"" << TypeNameTraits<Scalar>::name ()
452  << "\", MV: \"" << TypeNameTraits<MV>::name ()
453  << "\", OP: \"" << TypeNameTraits<OP>::name ()
454  << "\"}";
455  return out.str ();
456 }
457 
458 
459 template<class Scalar, class MV, class OP>
460 void
463  const Teuchos::EVerbosityLevel verbLevel) const
464 {
466  using std::endl;
467 
468  const Teuchos::EVerbosityLevel vl =
469  (verbLevel == Teuchos::VERB_DEFAULT) ? Teuchos::VERB_LOW : verbLevel;
470 
471  if (vl == Teuchos::VERB_NONE) {
472  return;
473  }
474 
475  // By convention, describe() always begins with a tab.
476  Teuchos::OSTab tab0 (out);
477  // The description prints in YAML format. The class name needs to
478  // be protected with quotes, so that YAML doesn't get confused
479  // between the colons in the class name and the colon separating
480  // (key,value) pairs.
481  out << "\"Belos::SolverFactory\":" << endl;
482  if (this->getObjectLabel () != "") {
483  out << "Label: " << this->getObjectLabel () << endl;
484  }
485  {
486  out << "Template parameters:" << endl;
487  Teuchos::OSTab tab1 (out);
488  out << "Scalar: \"" << TypeNameTraits<Scalar>::name () << "\"" << endl
489  << "MV: \"" << TypeNameTraits<MV>::name () << "\"" << endl
490  << "OP: \"" << TypeNameTraits<OP>::name () << "\"" << endl;
491  }
492 
493  // At higher verbosity levels, print out the list of supported solvers.
494  if (vl > Teuchos::VERB_LOW) {
495  Teuchos::OSTab tab1 (out);
496  out << "Number of solvers: " << numSupportedSolvers ()
497  << endl;
498  out << "Canonical solver names: ";
500  out << endl;
501 
502  out << "Aliases to canonical names: ";
504  out << endl;
505  }
506 }
507 
508 template<class Scalar, class MV, class OP>
509 int
512 {
513  int numSupported = 0;
514 
515  // First, check the overriding factories.
516  for (std::size_t k = 0; k < factories_.size (); ++k) {
517  using Teuchos::RCP;
518  RCP<custom_solver_factory_type> factory = factories_[k];
519  if (! factory.is_null ()) {
520  numSupported += factory->numSupportedSolvers ();
521  }
522  }
523 
524  // Now, see how many solvers this factory supports.
525  return numSupported + Details::numSupportedSolvers ();
526 }
527 
528 template<class Scalar, class MV, class OP>
532 {
533  typedef std::vector<std::string>::const_iterator iter_type;
535 
536  // First, check the overriding factories.
537  const std::size_t numFactories = factories_.size ();
538  for (std::size_t factInd = 0; factInd < numFactories; ++factInd) {
539  Teuchos::RCP<custom_solver_factory_type> factory = factories_[factInd];
540  if (! factory.is_null ()) {
541  std::vector<std::string> supportedSolvers =
542  factory->supportedSolverNames ();
543  const std::size_t numSolvers = supportedSolvers.size ();
544  for (std::size_t solvInd = 0; solvInd < numSolvers; ++solvInd) {
545  names.push_back (supportedSolvers[solvInd]);
546  }
547  }
548  }
549 
550  {
551  std::vector<std::string> aliases = Details::solverNameAliases ();
552  for (iter_type iter = aliases.begin (); iter != aliases.end (); ++iter) {
553  names.push_back (*iter);
554  }
555  }
556  {
557  std::vector<std::string> canonicalNames = Details::canonicalSolverNames ();
558  for (iter_type iter = canonicalNames.begin ();
559  iter != canonicalNames.end (); ++iter) {
560  names.push_back (*iter);
561  }
562  }
563  return names;
564 }
565 
566 template<class Scalar, class MV, class OP>
567 bool
569 isSupported (const std::string& solverName) const
570 {
571  // First, check the overriding factories.
572  const std::size_t numFactories = factories_.size ();
573  for (std::size_t factInd = 0; factInd < numFactories; ++factInd) {
574  using Teuchos::RCP;
575  RCP<custom_solver_factory_type> factory = factories_[factInd];
576  if (! factory.is_null ()) {
577  if (factory->isSupported (solverName)) {
578  return true;
579  }
580  }
581  }
582  // Now, check this factory.
583 
584  // Upper-case version of the input solver name.
585  const std::string solverNameUC = Impl::upperCase (solverName);
586 
587  // Check whether the given name is an alias.
588  std::pair<std::string, bool> aliasResult =
589  Details::getCanonicalNameFromAlias (solverNameUC);
590  const std::string candidateCanonicalName = aliasResult.first;
591  const bool validCanonicalName =
592  (get_solverManagers().find(candidateCanonicalName) != get_solverManagers().end());
593  return validCanonicalName;
594 }
595 
596 } // namespace Impl
597 } // namespace Belos
598 
599 // We have things like BelosSolverFactory_Tpetra.hpp which are automatically
600 // included through the adapter includes to maintain backwards compatibility.
601 // The Belos version itself doesn't have a place like that so included here
602 // which is awkward. It might make more sense to just copy that code here but
603 // it has symmetry with the other files and wanted to preserve that. To discuss.
605 
606 #endif // __Belos_SolverFactory_hpp
607 
Interface for custom Belos solver factories.
Class which manages the output and verbosity of the Belos solvers.
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)
void clearFactories()
Clear all custom solver factories.
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. ...
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
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...
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...
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.
bool is_null() const

Generated on Tue Apr 23 2024 09:24:56 for Belos by doxygen 1.8.5