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
62template<class Scalar, class MV, class OP>
64 public Teuchos::Describable
65{
66protected:
67 // SolverFactoryParent should never be created directly. Usually it will be
68 // created through derived classes EpetraSolverFactory, TpetraSolverFactory,
69 // BelosSolverFactory, or XpetraSolverFactory. If you are doing custom types
70 // and include BelosSolverFactory_Generic.hpp you should explicitly use
71 // GenericSolverFactory, not SolverFactory, which will avoid an error trying
72 // to construct here. GenericSolverFactory is special because it registers
73 // all the solver managers for any type. Note that if you are using hard coded
74 // types it is possible that some the type sets will be connecting to an
75 // automatic solver factory such as TpetraSolverFactory while another type
76 // set could be going through the GenericSolverFactory.
78
79public:
85 typedef ::Belos::SolverManager<Scalar, MV, OP> solver_base_type;
86
90
91protected:
129 virtual Teuchos::RCP<solver_base_type>
130 getSolver (const std::string& solverName,
131 const Teuchos::RCP<Teuchos::ParameterList>& solverParams);
132
133public:
143 virtual Teuchos::RCP<solver_base_type>
144 create (const std::string& solverName,
145 const Teuchos::RCP<Teuchos::ParameterList>& solverParams);
146
152 virtual int numSupportedSolvers () const;
153
159 virtual Teuchos::Array<std::string> supportedSolverNames () const;
160
162 virtual bool isSupported (const std::string& solverName) const;
163
178 void
179 addFactory (const Teuchos::RCP<custom_solver_factory_type>& factory);
180
188 void
190
192 static void
193 registerSolver (const std::string & solverName,
195 {
197 instance == Teuchos::null,
198 std::invalid_argument, "Belos::SolverFactoryParent::registerSolver "
199 "was given a null solver to register.");
200
201 get_solverManagers()[solverName] = instance;
202 }
203
205 static bool
206 isSolverRegistered (const std::string & solverName)
207 {
208 return (get_solverManagers().find(solverName) != get_solverManagers().end());
209 }
210
212
213
215 virtual std::string description() const;
216
222 virtual void
223 describe (Teuchos::FancyOStream& out,
224 const Teuchos::EVerbosityLevel verbLevel =
225 Teuchos::Describable::verbLevel_default) const;
227
228private:
230 static std::vector<Teuchos::RCP<custom_solver_factory_type> > factories_;
231
232 static std::map<const std::string, Teuchos::RCP<typename
234 get_solverManagers() {
235 static std::map<const std::string, Teuchos::RCP<typename
237 return solverManagers;
238 }
239};
240
241template<class Scalar, class MV, class OP>
242std::vector<Teuchos::RCP<typename SolverFactoryParent<Scalar, MV, OP>::custom_solver_factory_type> >
243SolverFactoryParent<Scalar, MV, OP>::factories_;
244
245template<class SolverClass, class Scalar, class MV, class OP>
252
253// specializations get a typedef "type"
254// If this compile fails then the error is likely that BelosSolverFactory.hpp
255// was included directly but the specific sub class of SolverFactoryParent was
256// not included. Examples are:
257// BelosSolverFactory_Belos.hpp, BelosSolverFactory_Epetra.hpp,
258// BelosSolverFactory_Tpetra.hpp, BelosSolverFactory_Xpetra.hpp
259// These were setup to be automatically included through the corresponding
260// adapter includes so something may have gone wrong with that.
261template<class SC, class MV, class OP>
263 public:
264 // TODO: This could be deleted except for the GenericSolverFactory which
265 // needs to be declared for all types. So I added this but then if you
266 // include GenericSolverFactory you will have SolverFactory simply point
267 // to SolverFactoryParent. I changed that constructor to be protected so
268 // using SolverFactory (pointing to SolverFactoryParent) will give a compile
269 // error. For GenericSolverFactory you must explicity use GenericSolverFactory
270 // in the code. This may be preferable because it makes it clear that
271 // factory is not connecting to the standard set of types. I'm not sure how
272 // to do this in a better way.
274};
275
276} // namespace Impl
277
278// Derived setups such as found in BelosSolverFactory_Tpetra.hpp will define
279// this specialization so that SolverFactory will be used as SolverFactoryTpetra.
280template<class SC, class MV, class OP>
281using SolverFactory = typename ::Belos::Impl::SolverFactorySelector<SC, MV, OP>::type;
282
283namespace Impl {
284
285template<class Scalar, class MV, class OP>
286Teuchos::RCP<typename SolverFactoryParent<Scalar, MV, OP>::solver_base_type>
288create (const std::string& solverName,
289 const Teuchos::RCP<Teuchos::ParameterList>& solverParams)
290{
291 using Teuchos::RCP;
294 (solver.is_null (), std::invalid_argument,
295 "Invalid or unsupported Belos solver name \"" << solverName << "\".");
296 return solver;
297}
298
299template<class Scalar, class MV, class OP>
300Teuchos::RCP<typename SolverFactoryParent<Scalar, MV, OP>::solver_base_type>
302getSolver (const std::string& solverName,
303 const Teuchos::RCP<Teuchos::ParameterList>& solverParams)
304{
305 using Teuchos::RCP;
306
307 // First, check the overriding factories.
308 for (std::size_t k = 0; k < factories_.size (); ++k) {
310 if (! factory.is_null ()) {
312 factory->getSolver (solverName, solverParams);
313 if (! solver.is_null ()) {
314 return solver;
315 }
316 }
317 }
318
319 // Upper-case version of the input solver name.
320 const std::string solverNameUC = Impl::upperCase (solverName);
321
322 // Check whether the given name is an alias.
323 std::pair<std::string, bool> aliasResult =
325 const std::string candidateCanonicalName = aliasResult.first;
326 const bool isAnAlias = aliasResult.second;
327
328 // Get the standardized name for enum reference and map
329 std::string standardized_name = isAnAlias ?
332
333 // If the input list is null, we create a new list and use that.
334 // This is OK because the effect of a null parameter list input is
335 // to use default parameter values. Thus, we can always replace a
336 // null list with an empty list.
337 Teuchos::RCP<Teuchos::ParameterList> pl =
338 solverParams.is_null() ? Teuchos::parameterList() : solverParams;
339
340 // Possibly modify the input parameter list as needed.
341 if (isAnAlias) {
343 }
344
345 typename std::map<const std::string, Teuchos::RCP<
347 it = get_solverManagers().find (standardized_name);
348
350 it == get_solverManagers().end(),
351 std::invalid_argument, "Belos solver manager " << solverNameUC <<
352 " with standardized name " << standardized_name << " has not been"
353 " registered.");
354
356 it->second == Teuchos::null,
357 std::logic_error, "Belos::SolverFactoryParent: The registered "
358 "clone source for " << solverNameUC << " with standardized name "
359 << standardized_name << " is null which should never happen."
360 ". Please report this bug to the Belos developers.");
361
362 // clone the solver
363 RCP<solver_base_type> solver = (it->second)->clone ();
364
366 solver == Teuchos::null,
367 std::logic_error, "Belos::SolverFactoryParent: Failed "
368 "to clone SolverManager with name " << solverNameUC << " with standardized"
369 " name" << standardized_name << "."
370 ". Please report this bug to the Belos developers.");
371
372 // Some solvers may not like to get a null ParameterList. If params
373 // is null, replace it with an empty parameter list. The solver
374 // will fill in default parameters for that case. Use the name of
375 // the solver's default parameters to name the new empty list.
376 if (pl.is_null()) {
377 pl = Teuchos::parameterList (solver->getValidParameters ()->name ());
378 }
379
381 pl.is_null(), std::logic_error,
382 "Belos::SolverFactory: ParameterList to pass to solver is null. This "
383 "should never happen. Please report this bug to the Belos developers.");
384 solver->setParameters (pl);
385 return solver;
386}
387
388
389template<class Scalar, class MV, class OP>
390void
393{
394 factories_.push_back (factory);
395}
396
397
398template<class Scalar, class MV, class OP>
399void
402{
403 factories_.clear();
404}
405
406
407template<class Scalar, class MV, class OP>
408std::string
410description () const
411{
412 using Teuchos::TypeNameTraits;
413
414 std::ostringstream out;
415 out << "\"Belos::SolverFactory\": {";
416 if (this->getObjectLabel () != "") {
417 out << "Label: " << this->getObjectLabel () << ", ";
418 }
419 out << "Scalar: \"" << TypeNameTraits<Scalar>::name ()
420 << "\", MV: \"" << TypeNameTraits<MV>::name ()
421 << "\", OP: \"" << TypeNameTraits<OP>::name ()
422 << "\"}";
423 return out.str ();
424}
425
426
427template<class Scalar, class MV, class OP>
428void
430describe (Teuchos::FancyOStream& out,
431 const Teuchos::EVerbosityLevel verbLevel) const
432{
433 using Teuchos::TypeNameTraits;
434 using std::endl;
435
436 const Teuchos::EVerbosityLevel vl =
437 (verbLevel == Teuchos::VERB_DEFAULT) ? Teuchos::VERB_LOW : verbLevel;
438
439 if (vl == Teuchos::VERB_NONE) {
440 return;
441 }
442
443 // By convention, describe() always begins with a tab.
444 Teuchos::OSTab tab0 (out);
445 // The description prints in YAML format. The class name needs to
446 // be protected with quotes, so that YAML doesn't get confused
447 // between the colons in the class name and the colon separating
448 // (key,value) pairs.
449 out << "\"Belos::SolverFactory\":" << endl;
450 if (this->getObjectLabel () != "") {
451 out << "Label: " << this->getObjectLabel () << endl;
452 }
453 {
454 out << "Template parameters:" << endl;
455 Teuchos::OSTab tab1 (out);
456 out << "Scalar: \"" << TypeNameTraits<Scalar>::name () << "\"" << endl
457 << "MV: \"" << TypeNameTraits<MV>::name () << "\"" << endl
458 << "OP: \"" << TypeNameTraits<OP>::name () << "\"" << endl;
459 }
460
461 // At higher verbosity levels, print out the list of supported solvers.
462 if (vl > Teuchos::VERB_LOW) {
463 Teuchos::OSTab tab1 (out);
464 out << "Number of solvers: " << numSupportedSolvers ()
465 << endl;
466 out << "Canonical solver names: ";
468 out << endl;
469
470 out << "Aliases to canonical names: ";
472 out << endl;
473 }
474}
475
476template<class Scalar, class MV, class OP>
477int
479numSupportedSolvers () const
480{
481 int numSupported = 0;
482
483 // First, check the overriding factories.
484 for (std::size_t k = 0; k < factories_.size (); ++k) {
485 using Teuchos::RCP;
487 if (! factory.is_null ()) {
488 numSupported += factory->numSupportedSolvers ();
489 }
490 }
491
492 // Now, see how many solvers this factory supports.
494}
495
496template<class Scalar, class MV, class OP>
497Teuchos::Array<std::string>
500{
501 typedef std::vector<std::string>::const_iterator iter_type;
502 Teuchos::Array<std::string> names;
503
504 // First, check the overriding factories.
505 const std::size_t numFactories = factories_.size ();
506 for (std::size_t factInd = 0; factInd < numFactories; ++factInd) {
507 Teuchos::RCP<custom_solver_factory_type> factory = factories_[factInd];
508 if (! factory.is_null ()) {
509 std::vector<std::string> supportedSolvers =
510 factory->supportedSolverNames ();
511 const std::size_t numSolvers = supportedSolvers.size ();
512 for (std::size_t solvInd = 0; solvInd < numSolvers; ++solvInd) {
513 names.push_back (supportedSolvers[solvInd]);
514 }
515 }
516 }
517
518 {
519 std::vector<std::string> aliases = Details::solverNameAliases ();
520 for (iter_type iter = aliases.begin (); iter != aliases.end (); ++iter) {
521 names.push_back (*iter);
522 }
523 }
524 {
525 std::vector<std::string> canonicalNames = Details::canonicalSolverNames ();
526 for (iter_type iter = canonicalNames.begin ();
527 iter != canonicalNames.end (); ++iter) {
528 names.push_back (*iter);
529 }
530 }
531 return names;
532}
533
534template<class Scalar, class MV, class OP>
535bool
537isSupported (const std::string& solverName) const
538{
539 // First, check the overriding factories.
540 const std::size_t numFactories = factories_.size ();
541 for (std::size_t factInd = 0; factInd < numFactories; ++factInd) {
542 using Teuchos::RCP;
544 if (! factory.is_null ()) {
545 if (factory->isSupported (solverName)) {
546 return true;
547 }
548 }
549 }
550 // Now, check this factory.
551
552 // Upper-case version of the input solver name.
553 const std::string solverNameUC = Impl::upperCase (solverName);
554
555 // Check whether the given name is an alias.
556 std::pair<std::string, bool> aliasResult =
558 const std::string candidateCanonicalName = aliasResult.first;
559 const bool validCanonicalName =
560 (get_solverManagers().find(candidateCanonicalName) != get_solverManagers().end());
561 return validCanonicalName;
562}
563
564} // namespace Impl
565} // namespace Belos
566
567// We have things like BelosSolverFactory_Tpetra.hpp which are automatically
568// included through the adapter includes to maintain backwards compatibility.
569// The Belos version itself doesn't have a place like that so included here
570// which is awkward. It might make more sense to just copy that code here but
571// it has symmetry with the other files and wanted to preserve that. To discuss.
573
574#endif // __Belos_SolverFactory_hpp
575
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.
Declaration of alias functions for solver names.
Specializations of Belos::SolverFactory may inherit from this class to get basic SolverFactory functi...
CustomSolverFactory< Scalar, MV, OP > custom_solver_factory_type
The type of a solver factory that users may give to addFactory() (which see below)
static void registerSolver(const std::string &solverName, Teuchos::RCP< SolverFactoryParent< Scalar, MV, OP >::solver_base_type > instance)
register a solver for Inverted Injection (DII).
void addFactory(const Teuchos::RCP< custom_solver_factory_type > &factory)
Add a custom solver factory.
void clearFactories()
Clear all custom solver factories.
virtual int numSupportedSolvers() const
Number of supported solvers.
virtual Teuchos::Array< std::string > supportedSolverNames() const
List of supported solver names.
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 bool isSupported(const std::string &solverName) const
Whether the given solver name names a supported solver.
::Belos::SolverManager< Scalar, MV, OP > solver_base_type
The type of the solver returned by create().
virtual std::string description() const
A string description of this object.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Describe this object.
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...
SolverFactoryParent< SC, MV, OP > 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.
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.
void registerSolverSubclassForTypes(const std::string &solverName)
typename ::Belos::Impl::SolverFactorySelector< SC, MV, OP >::type SolverFactory

Generated for Belos by doxygen 1.9.8