Belos Version of the Day
Loading...
Searching...
No Matches
BelosSolverFactory.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Belos: Block Linear Solvers Package
4//
5// Copyright 2004-2016 NTESS and the Belos contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef __Belos_SolverFactory_hpp
11#define __Belos_SolverFactory_hpp
12
13#include <BelosConfigDefs.hpp>
16
19
20#include <Teuchos_Describable.hpp>
21#include <Teuchos_StandardCatchMacros.hpp>
22#include <Teuchos_TypeNameTraits.hpp>
23
24#include <map>
25#include <sstream>
26#include <stdexcept>
27#include <vector>
28
29namespace Belos {
30namespace Impl {
31
33void
34printStringArray (std::ostream& out,
35 const Teuchos::ArrayView<const std::string>& array);
36
38void
39printStringArray (std::ostream& out,
40 const std::vector<std::string>& array);
41
43std::string
44upperCase (const std::string& s);
45
64template<class Scalar, class MV, class OP, class DM = DefaultDenseMatrix<int,Scalar>>
66 public Teuchos::Describable
67{
68protected:
69 // SolverFactoryParent should never be created directly. Usually it will be
70 // created through derived classes EpetraSolverFactory, TpetraSolverFactory,
71 // BelosSolverFactory, or XpetraSolverFactory. If you are doing custom types
72 // and include BelosSolverFactory_Generic.hpp you should explicitly use
73 // GenericSolverFactory, not SolverFactory, which will avoid an error trying
74 // to construct here. GenericSolverFactory is special because it registers
75 // all the solver managers for any type. Note that if you are using hard coded
76 // types it is possible that some the type sets will be connecting to an
77 // automatic solver factory such as TpetraSolverFactory while another type
78 // set could be going through the GenericSolverFactory.
80
81public:
87 typedef ::Belos::SolverManager<Scalar, MV, OP, DM> solver_base_type;
88
92
93protected:
131 virtual Teuchos::RCP<solver_base_type>
132 getSolver (const std::string& solverName,
133 const Teuchos::RCP<Teuchos::ParameterList>& solverParams);
134
135public:
145 virtual Teuchos::RCP<solver_base_type>
146 create (const std::string& solverName,
147 const Teuchos::RCP<Teuchos::ParameterList>& solverParams);
148
154 virtual int numSupportedSolvers () const;
155
161 virtual Teuchos::Array<std::string> supportedSolverNames () const;
162
164 virtual bool isSupported (const std::string& solverName) const;
165
180 void
181 addFactory (const Teuchos::RCP<custom_solver_factory_type>& factory);
182
190 void
192
194 static void
195 registerSolver (const std::string & solverName,
197 {
199 instance == Teuchos::null,
200 std::invalid_argument, "Belos::SolverFactoryParent::registerSolver "
201 "was given a null solver to register.");
202
203 get_solverManagers()[solverName] = instance;
204 }
205
207 static bool
208 isSolverRegistered (const std::string & solverName)
209 {
210 return (get_solverManagers().find(solverName) != get_solverManagers().end());
211 }
212
214
215
217 virtual std::string description() const;
218
224 virtual void
225 describe (Teuchos::FancyOStream& out,
226 const Teuchos::EVerbosityLevel verbLevel =
227 Teuchos::Describable::verbLevel_default) const;
229
230private:
232 static std::vector<Teuchos::RCP<custom_solver_factory_type> > factories_;
233
234 static std::map<const std::string, Teuchos::RCP<typename
236 get_solverManagers() {
237 static std::map<const std::string, Teuchos::RCP<typename
239 return solverManagers;
240 }
241};
242
243template<class Scalar, class MV, class OP, class DM>
244std::vector<Teuchos::RCP<typename SolverFactoryParent<Scalar, MV, OP, DM>::custom_solver_factory_type> >
245SolverFactoryParent<Scalar, MV, OP, DM>::factories_;
246
247template<class SolverClass, class Scalar, class MV, class OP, class DM = DefaultDenseMatrix<int,Scalar>>
254
255// specializations get a typedef "type"
256// If this compile fails then the error is likely that BelosSolverFactory.hpp
257// was included directly but the specific sub class of SolverFactoryParent was
258// not included. Examples are:
259// BelosSolverFactory_Belos.hpp, BelosSolverFactory_Epetra.hpp,
260// BelosSolverFactory_Tpetra.hpp, BelosSolverFactory_Xpetra.hpp
261// These were setup to be automatically included through the corresponding
262// adapter includes so something may have gone wrong with that.
263template<class SC, class MV, class OP, class DM = DefaultDenseMatrix<int,SC>>
265 public:
266 // TODO: This could be deleted except for the GenericSolverFactory which
267 // needs to be declared for all types. So I added this but then if you
268 // include GenericSolverFactory you will have SolverFactory simply point
269 // to SolverFactoryParent. I changed that constructor to be protected so
270 // using SolverFactory (pointing to SolverFactoryParent) will give a compile
271 // error. For GenericSolverFactory you must explicity use GenericSolverFactory
272 // in the code. This may be preferable because it makes it clear that
273 // factory is not connecting to the standard set of types. I'm not sure how
274 // to do this in a better way.
276};
277
278} // namespace Impl
279
280// Derived setups such as found in BelosSolverFactory_Tpetra.hpp will define
281// this specialization so that SolverFactory will be used as SolverFactoryTpetra.
282template<class SC, class MV, class OP, class DM = DefaultDenseMatrix<int,SC>>
283using SolverFactory = typename ::Belos::Impl::SolverFactorySelector<SC, MV, OP, DM>::type;
284
285namespace Impl {
286
287template<class Scalar, class MV, class OP, class DM>
288Teuchos::RCP<typename SolverFactoryParent<Scalar, MV, OP, DM>::solver_base_type>
290create (const std::string& solverName,
291 const Teuchos::RCP<Teuchos::ParameterList>& solverParams)
292{
293 using Teuchos::RCP;
296 (solver.is_null (), std::invalid_argument,
297 "Invalid or unsupported Belos solver name \"" << solverName << "\".");
298 return solver;
299}
300
301template<class Scalar, class MV, class OP, class DM>
302Teuchos::RCP<typename SolverFactoryParent<Scalar, MV, OP, DM>::solver_base_type>
304getSolver (const std::string& solverName,
305 const Teuchos::RCP<Teuchos::ParameterList>& solverParams)
306{
307 using Teuchos::RCP;
308
309 // First, check the overriding factories.
310 for (std::size_t k = 0; k < factories_.size (); ++k) {
312 if (! factory.is_null ()) {
314 factory->getSolver (solverName, solverParams);
315 if (! solver.is_null ()) {
316 return solver;
317 }
318 }
319 }
320
321 // Upper-case version of the input solver name.
322 const std::string solverNameUC = Impl::upperCase (solverName);
323
324 // Check whether the given name is an alias.
325 std::pair<std::string, bool> aliasResult =
327 const std::string candidateCanonicalName = aliasResult.first;
328 const bool isAnAlias = aliasResult.second;
329
330 // Get the standardized name for enum reference and map
331 std::string standardized_name = isAnAlias ?
334
335 // If the input list is null, we create a new list and use that.
336 // This is OK because the effect of a null parameter list input is
337 // to use default parameter values. Thus, we can always replace a
338 // null list with an empty list.
339 Teuchos::RCP<Teuchos::ParameterList> pl =
340 solverParams.is_null() ? Teuchos::parameterList() : solverParams;
341
342 // Possibly modify the input parameter list as needed.
343 if (isAnAlias) {
345 }
346
347 typename std::map<const std::string, Teuchos::RCP<
349 it = get_solverManagers().find (standardized_name);
350
352 it == get_solverManagers().end(),
353 std::invalid_argument, "Belos solver manager " << solverNameUC <<
354 " with standardized name " << standardized_name << " has not been"
355 " registered.");
356
358 it->second == Teuchos::null,
359 std::logic_error, "Belos::SolverFactoryParent: The registered "
360 "clone source for " << solverNameUC << " with standardized name "
361 << standardized_name << " is null which should never happen."
362 ". Please report this bug to the Belos developers.");
363
364 // clone the solver
365 RCP<solver_base_type> solver = (it->second)->clone ();
366
368 solver == Teuchos::null,
369 std::logic_error, "Belos::SolverFactoryParent: Failed "
370 "to clone SolverManager with name " << solverNameUC << " with standardized"
371 " name" << standardized_name << "."
372 ". Please report this bug to the Belos developers.");
373
374 // Some solvers may not like to get a null ParameterList. If params
375 // is null, replace it with an empty parameter list. The solver
376 // will fill in default parameters for that case. Use the name of
377 // the solver's default parameters to name the new empty list.
378 if (pl.is_null()) {
379 pl = Teuchos::parameterList (solver->getValidParameters ()->name ());
380 }
381
383 pl.is_null(), std::logic_error,
384 "Belos::SolverFactory: ParameterList to pass to solver is null. This "
385 "should never happen. Please report this bug to the Belos developers.");
386 solver->setParameters (pl);
387 return solver;
388}
389
390
391template<class Scalar, class MV, class OP, class DM>
392void
398
399
400template<class Scalar, class MV, class OP, class DM>
401void
404{
405 factories_.clear();
406}
407
408
409template<class Scalar, class MV, class OP, class DM>
410std::string
412description () const
413{
414 using Teuchos::TypeNameTraits;
415
416 std::ostringstream out;
417 out << "\"Belos::SolverFactory\": {";
418 if (this->getObjectLabel () != "") {
419 out << "Label: " << this->getObjectLabel () << ", ";
420 }
421 out << "Scalar: \"" << TypeNameTraits<Scalar>::name ()
422 << "\", MV: \"" << TypeNameTraits<MV>::name ()
423 << "\", OP: \"" << TypeNameTraits<OP>::name ()
424 << "\", DM: \"" << TypeNameTraits<DM>::name ()
425 << "\"}";
426 return out.str ();
427}
428
429
430template<class Scalar, class MV, class OP, class DM>
431void
433describe (Teuchos::FancyOStream& out,
434 const Teuchos::EVerbosityLevel verbLevel) const
435{
436 using Teuchos::TypeNameTraits;
437 using std::endl;
438
439 const Teuchos::EVerbosityLevel vl =
440 (verbLevel == Teuchos::VERB_DEFAULT) ? Teuchos::VERB_LOW : verbLevel;
441
442 if (vl == Teuchos::VERB_NONE) {
443 return;
444 }
445
446 // By convention, describe() always begins with a tab.
447 Teuchos::OSTab tab0 (out);
448 // The description prints in YAML format. The class name needs to
449 // be protected with quotes, so that YAML doesn't get confused
450 // between the colons in the class name and the colon separating
451 // (key,value) pairs.
452 out << "\"Belos::SolverFactory\":" << endl;
453 if (this->getObjectLabel () != "") {
454 out << "Label: " << this->getObjectLabel () << endl;
455 }
456 {
457 out << "Template parameters:" << endl;
458 Teuchos::OSTab tab1 (out);
459 out << "Scalar: \"" << TypeNameTraits<Scalar>::name () << "\"" << endl
460 << "MV: \"" << TypeNameTraits<MV>::name () << "\"" << endl
461 << "OP: \"" << TypeNameTraits<OP>::name () << "\"" << endl
462 << "DM: \"" << TypeNameTraits<DM>::name () << "\"" << endl;
463 }
464
465 // At higher verbosity levels, print out the list of supported solvers.
466 if (vl > Teuchos::VERB_LOW) {
467 Teuchos::OSTab tab1 (out);
468 out << "Number of solvers: " << numSupportedSolvers ()
469 << endl;
470 out << "Canonical solver names: ";
472 out << endl;
473
474 out << "Aliases to canonical names: ";
476 out << endl;
477 }
478}
479
480template<class Scalar, class MV, class OP, class DM>
481int
483numSupportedSolvers () const
484{
485 int numSupported = 0;
486
487 // First, check the overriding factories.
488 for (std::size_t k = 0; k < factories_.size (); ++k) {
489 using Teuchos::RCP;
491 if (! factory.is_null ()) {
492 numSupported += factory->numSupportedSolvers ();
493 }
494 }
495
496 // Now, see how many solvers this factory supports.
498}
499
500template<class Scalar, class MV, class OP, class DM>
501Teuchos::Array<std::string>
504{
505 typedef std::vector<std::string>::const_iterator iter_type;
506 Teuchos::Array<std::string> names;
507
508 // First, check the overriding factories.
509 const std::size_t numFactories = factories_.size ();
510 for (std::size_t factInd = 0; factInd < numFactories; ++factInd) {
511 Teuchos::RCP<custom_solver_factory_type> factory = factories_[factInd];
512 if (! factory.is_null ()) {
513 std::vector<std::string> supportedSolvers =
514 factory->supportedSolverNames ();
515 const std::size_t numSolvers = supportedSolvers.size ();
516 for (std::size_t solvInd = 0; solvInd < numSolvers; ++solvInd) {
517 names.push_back (supportedSolvers[solvInd]);
518 }
519 }
520 }
521
522 {
523 std::vector<std::string> aliases = Details::solverNameAliases ();
524 for (iter_type iter = aliases.begin (); iter != aliases.end (); ++iter) {
525 names.push_back (*iter);
526 }
527 }
528 {
529 std::vector<std::string> canonicalNames = Details::canonicalSolverNames ();
530 for (iter_type iter = canonicalNames.begin ();
531 iter != canonicalNames.end (); ++iter) {
532 names.push_back (*iter);
533 }
534 }
535 return names;
536}
537
538template<class Scalar, class MV, class OP, class DM>
539bool
541isSupported (const std::string& solverName) const
542{
543 // First, check the overriding factories.
544 const std::size_t numFactories = factories_.size ();
545 for (std::size_t factInd = 0; factInd < numFactories; ++factInd) {
546 using Teuchos::RCP;
548 if (! factory.is_null ()) {
549 if (factory->isSupported (solverName)) {
550 return true;
551 }
552 }
553 }
554 // Now, check this factory.
555
556 // Upper-case version of the input solver name.
557 const std::string solverNameUC = Impl::upperCase (solverName);
558
559 // Check whether the given name is an alias.
560 std::pair<std::string, bool> aliasResult =
562 const std::string candidateCanonicalName = aliasResult.first;
563 const bool validCanonicalName =
564 (get_solverManagers().find(candidateCanonicalName) != get_solverManagers().end());
565 return validCanonicalName;
566}
567
568} // namespace Impl
569} // namespace Belos
570
571// We have things like BelosSolverFactory_Tpetra.hpp which are automatically
572// included through the adapter includes to maintain backwards compatibility.
573// The Belos version itself doesn't have a place like that so included here
574// which is awkward. It might make more sense to just copy that code here but
575// it has symmetry with the other files and wanted to preserve that. To discuss.
577
578#endif // __Belos_SolverFactory_hpp
579
Declaration of alias functions for solver names.
Belos header file which uses auto-configuration information to include necessary C++ headers.
Class which manages the output and verbosity of the Belos solvers.
Pure virtual base class which describes the basic interface for a solver manager.
Specializations of Belos::SolverFactory may inherit from this class to get basic SolverFactory functi...
virtual int numSupportedSolvers() const
Number of supported solvers.
void clearFactories()
Clear all custom solver factories.
void addFactory(const Teuchos::RCP< custom_solver_factory_type > &factory)
Add a custom solver factory.
static bool isSolverRegistered(const std::string &solverName)
is solver registered for Inverted Injection (DII).
virtual Teuchos::RCP< solver_base_type > create(const std::string &solverName, const Teuchos::RCP< Teuchos::ParameterList > &solverParams)
Create, configure, and return the specified solver.
virtual Teuchos::Array< std::string > supportedSolverNames() const
List of supported solver names.
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...
virtual bool isSupported(const std::string &solverName) const
Whether the given solver name names a supported solver.
CustomSolverFactory< Scalar, MV, OP, DM > custom_solver_factory_type
The type of a solver factory that users may give to addFactory() (which see below)
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Describe this object.
static void registerSolver(const std::string &solverName, Teuchos::RCP< SolverFactoryParent< Scalar, MV, OP, DM >::solver_base_type > instance)
register a solver for Inverted Injection (DII).
::Belos::SolverManager< Scalar, MV, OP, DM > solver_base_type
The type of the solver returned by create().
virtual std::string description() const
A string description of this object.
SolverFactoryParent< SC, MV, OP, DM > type
Alternative run-time polymorphic interface for operators.
std::pair< std::string, bool > getCanonicalNameFromAlias(const std::string &candidateAlias)
Get the candidate canonical name for a given candidate alias.
void reviseParameterListForAlias(const std::string &aliasName, Teuchos::ParameterList &solverParams)
Modify the input ParameterList appropriately for the given solver alias.
std::vector< std::string > solverNameAliases()
List of supported aliases (to canonical solver names).
int numSupportedSolvers()
Number of Belos solvers supported for any linear algebra implementation ("generically").
std::vector< std::string > canonicalSolverNames()
List of canonical solver names.
void registerSolverSubclassForTypes(const std::string &solverName)
std::string upperCase(const std::string &s)
Return the upper-case version of s.
void printStringArray(std::ostream &out, const Teuchos::ArrayView< const std::string > &array)
Print the given array of strings, in YAML format, to out.
typename ::Belos::Impl::SolverFactorySelector< SC, MV, OP, DM >::type SolverFactory

Generated for Belos by doxygen 1.9.8