Belos Version of the Day
Loading...
Searching...
No Matches
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>
48
51
52#include <Teuchos_Describable.hpp>
53#include <Teuchos_StandardCatchMacros.hpp>
54#include <Teuchos_TypeNameTraits.hpp>
55
56#include <map>
57#include <sstream>
58#include <stdexcept>
59#include <vector>
60
61namespace Belos {
62namespace Impl {
63
65void
66printStringArray (std::ostream& out,
67 const Teuchos::ArrayView<const std::string>& array);
68
70void
71printStringArray (std::ostream& out,
72 const std::vector<std::string>& array);
73
75std::string
76upperCase (const std::string& s);
77
94template<class Scalar, class MV, class OP>
96 public Teuchos::Describable
97{
98protected:
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
111public:
117 typedef ::Belos::SolverManager<Scalar, MV, OP> solver_base_type;
118
122
123protected:
161 virtual Teuchos::RCP<solver_base_type>
162 getSolver (const std::string& solverName,
163 const Teuchos::RCP<Teuchos::ParameterList>& solverParams);
164
165public:
175 virtual Teuchos::RCP<solver_base_type>
176 create (const std::string& solverName,
177 const Teuchos::RCP<Teuchos::ParameterList>& solverParams);
178
184 virtual int numSupportedSolvers () const;
185
191 virtual Teuchos::Array<std::string> supportedSolverNames () const;
192
194 virtual bool isSupported (const std::string& solverName) const;
195
210 void
211 addFactory (const Teuchos::RCP<custom_solver_factory_type>& factory);
212
214 static void
215 registerSolver (const std::string & solverName,
217 {
218 TEUCHOS_TEST_FOR_EXCEPTION(
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
245 describe (Teuchos::FancyOStream& out,
246 const Teuchos::EVerbosityLevel verbLevel =
247 Teuchos::Describable::verbLevel_default) const;
249
250private:
252 static std::vector<Teuchos::RCP<custom_solver_factory_type> > factories_;
253
254 static std::map<const std::string, Teuchos::RCP<typename
256 get_solverManagers() {
257 static std::map<const std::string, Teuchos::RCP<typename
259 return solverManagers;
260 }
261};
262
263template<class Scalar, class MV, class OP>
264std::vector<Teuchos::RCP<typename SolverFactoryParent<Scalar, MV, OP>::custom_solver_factory_type> >
265SolverFactoryParent<Scalar, MV, OP>::factories_;
266
267template<class SolverClass, class Scalar, class MV, class OP>
268void 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.
283template<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.
302template<class SC, class MV, class OP>
303using SolverFactory = typename ::Belos::Impl::SolverFactorySelector<SC, MV, OP>::type;
304
305namespace Impl {
306
307template<class Scalar, class MV, class OP>
308Teuchos::RCP<typename SolverFactoryParent<Scalar, MV, OP>::solver_base_type>
310create (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);
315 TEUCHOS_TEST_FOR_EXCEPTION
316 (solver.is_null (), std::invalid_argument,
317 "Invalid or unsupported Belos solver name \"" << solverName << "\".");
318 return solver;
319}
320
321template<class Scalar, class MV, class OP>
322Teuchos::RCP<typename SolverFactoryParent<Scalar, MV, OP>::solver_base_type>
324getSolver (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 =
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.
359 Teuchos::RCP<Teuchos::ParameterList> pl =
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
371 TEUCHOS_TEST_FOR_EXCEPTION(
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
377 TEUCHOS_TEST_FOR_EXCEPTION(
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
387 TEUCHOS_TEST_FOR_EXCEPTION(
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
402 TEUCHOS_TEST_FOR_EXCEPTION(
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
411template<class Scalar, class MV, class OP>
412void
414addFactory (const Teuchos::RCP<CustomSolverFactory<Scalar, MV, OP> >& factory)
415{
416 factories_.push_back (factory);
417}
418
419
420template<class Scalar, class MV, class OP>
421std::string
423description () const
424{
425 using Teuchos::TypeNameTraits;
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
440template<class Scalar, class MV, class OP>
441void
443describe (Teuchos::FancyOStream& out,
444 const Teuchos::EVerbosityLevel verbLevel) const
445{
446 using Teuchos::TypeNameTraits;
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
489template<class Scalar, class MV, class OP>
490int
492numSupportedSolvers () const
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
509template<class Scalar, class MV, class OP>
510Teuchos::Array<std::string>
513{
514 typedef std::vector<std::string>::const_iterator iter_type;
515 Teuchos::Array<std::string> names;
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
547template<class Scalar, class MV, class OP>
548bool
550isSupported (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 =
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
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.
Interface for custom Belos solver factories.
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.
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
The Belos::SolverManager is a templated virtual base class that defines the basic interface that any ...
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.10.0