MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MueLu_TopSmootherFactory_def.hpp
Go to the documentation of this file.
1 // @HEADER
2 // *****************************************************************************
3 // MueLu: A package for multigrid based preconditioning
4 //
5 // Copyright 2012 NTESS and the MueLu contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 /*
11  * MueLu_TopSmootherFactory_def.hpp
12  *
13  * Created on: Jan 25, 2016
14  * Author: tawiesn
15  */
16 
17 #ifndef PACKAGES_MUELU_SRC_MUECENTRAL_MUELU_TOPSMOOTHERFACTORY_DEF_HPP_
18 #define PACKAGES_MUELU_SRC_MUECENTRAL_MUELU_TOPSMOOTHERFACTORY_DEF_HPP_
19 
20 #include "MueLu_ConfigDefs.hpp"
21 
22 //#include "MueLu_FactoryManager_fwd.hpp"
24 //#include "MueLu_HierarchyHelpers_fwd.hpp"
26 //#include "MueLu_SmootherBase_fwd.hpp"
27 #include "MueLu_SmootherFactory.hpp"
28 #include "MueLu_SmootherPrototype.hpp"
29 //#include "MueLu_Hierarchy_fwd.hpp"
30 //#include "MueLu_HierarchyManager_fwd.hpp"
31 
32 namespace MueLu {
33 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
35  TEUCHOS_TEST_FOR_EXCEPTION(varName != "CoarseSolver" && varName != "Smoother", Exceptions::RuntimeError, "varName should be either \"CoarseSolver\" or \"Smoother\"");
36 
37  if (varName == "CoarseSolver") {
38  // For coarsest level, we only need one smoother/solver
39  // If a user wants to do something weird there (like, solve coarsest system by using 2 forward
40  // GS and 1 backward GS), one can use MergedSmoother
41  RCP<const FactoryBase> coarseSolverFactory = parentFactoryManager->GetFactory("CoarseSolver");
42  RCP<const SmootherFactory> coarseSmootherFactory = Teuchos::rcp_dynamic_cast<const SmootherFactory>(coarseSolverFactory);
43  if (coarseSmootherFactory != Teuchos::null) {
44  RCP<SmootherPrototype> preProto;
45  RCP<SmootherPrototype> postProto;
46  coarseSmootherFactory->GetSmootherPrototypes(preProto, postProto);
47 
48  if (preProto == postProto)
49  preSmootherFact_ = parentFactoryManager->GetFactory("CoarseSolver");
50  else {
51  // check whether pre- and/or post-smoothing is desired on coarsest level
52  if (preProto != Teuchos::null)
53  preSmootherFact_ = parentFactoryManager->GetFactory("CoarseSolver");
54  if (postProto != Teuchos::null)
55  postSmootherFact_ = parentFactoryManager->GetFactory("CoarseSolver");
56  }
57  } else // default handling: get default direct solver as presmoother on coarsest level
58  preSmootherFact_ = parentFactoryManager->GetFactory("CoarseSolver");
59 
60  } else {
61  preSmootherFact_ = parentFactoryManager->GetFactory("PreSmoother");
62  postSmootherFact_ = parentFactoryManager->GetFactory("PostSmoother");
63  }
64 }
65 
66 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
68 
69 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
71  if (preSmootherFact_ != Teuchos::null)
72  level.DeclareInput("PreSmoother", preSmootherFact_.get());
73  if (postSmootherFact_ != Teuchos::null)
74  level.DeclareInput("PostSmoother", postSmootherFact_.get());
75 }
76 
77 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
79  if (preSmootherFact_.is_null() && postSmootherFact_.is_null())
80  return;
81 
82  // NOTE 1: We need to set at least some keep flag for the smoothers, otherwise it is going to be removed as soon as all requests are released.
83  // We choose to set the Final flag for the data. In addition, we allow this data to be retrieved by only using the name by the means
84  // of using NoFactory. However, any data set with NoFactory gets UserData flag by default. We don't really want that flag, so we remove it.
85 
86  // NOTE 2: some smoother factories are tricky (see comments in MueLu::SmootherFactory
87  // Sometimes, we don't know whether the factory is able to generate "PreSmoother" or "PostSmoother"
88  // For the SmootherFactory, however, we are able to check that.
89 
90  if (!preSmootherFact_.is_null()) {
91  // Checking for null is not sufficient, as SmootherFactory(null, something) does not generate "PreSmoother"
92  bool isAble = true;
93  RCP<const SmootherFactory> s = rcp_dynamic_cast<const SmootherFactory>(preSmootherFact_);
94  if (!s.is_null()) {
95  RCP<SmootherPrototype> pre, post;
96  s->GetSmootherPrototypes(pre, post);
97  if (pre.is_null())
98  isAble = false;
99  } else {
100  // We assume that if presmoother factory is not SmootherFactory, it *is* able to generate "PreSmoother"
101  }
102 
103  if (isAble) {
104  RCP<SmootherBase> Pre = level.Get<RCP<SmootherBase> >("PreSmoother", preSmootherFact_.get());
105 
106  level.Set("PreSmoother", Pre, NoFactory::get());
107 
108  level.AddKeepFlag("PreSmoother", NoFactory::get(), MueLu::Final);
109  level.RemoveKeepFlag("PreSmoother", NoFactory::get(), MueLu::UserData);
110  }
111  }
112 
113  if (!postSmootherFact_.is_null()) {
114  // Checking for null is not sufficient, as SmootherFactory(something, null) does not generate "PostSmoother"
115  bool isAble = true;
116  RCP<const SmootherFactory> s = rcp_dynamic_cast<const SmootherFactory>(postSmootherFact_);
117  if (!s.is_null()) {
118  RCP<SmootherPrototype> pre, post;
119  s->GetSmootherPrototypes(pre, post);
120  if (post.is_null())
121  isAble = false;
122  } else {
123  // We assume that if presmoother factory is not SmootherFactory, it *is* able to generate "PreSmoother"
124  }
125 
126  if (isAble) {
127  RCP<SmootherBase> Post = level.Get<RCP<SmootherBase> >("PostSmoother", postSmootherFact_.get());
128 
129  level.Set("PostSmoother", Post, NoFactory::get());
130 
131  level.AddKeepFlag("PostSmoother", NoFactory::get(), MueLu::Final);
132  level.RemoveKeepFlag("PostSmoother", NoFactory::get(), MueLu::UserData);
133  }
134  }
135 }
136 } // namespace MueLu
137 
138 #endif /* PACKAGES_MUELU_SRC_MUECENTRAL_MUELU_TOPSMOOTHERFACTORY_DEF_HPP_ */
Generic Smoother Factory for generating the smoothers of the MG hierarchy.
void Build(Level &level) const
Build an object with this factory.
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access). Usage: Level-&gt;Get&lt; RCP&lt;Matrix&gt; &gt;(&quot;A&quot;, factory) if factory == NULL =&gt; use default factory.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
User data are always kept. This flag is set automatically when Level::Set(&quot;data&quot;, data) is used...
static const NoFactory * get()
virtual const RCP< const FactoryBase > GetFactory(const std::string &varName) const =0
Get.
Class that holds all level-specific information.
Definition: MueLu_Level.hpp:63
Keep data only for this run. Used to keep data useful for Hierarchy::Iterate(). Data will be deleted ...
void RemoveKeepFlag(const std::string &ename, const FactoryBase *factory, KeepType keep=MueLu::All)
void AddKeepFlag(const std::string &ename, const FactoryBase *factory=NoFactory::get(), KeepType keep=MueLu::Keep)
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
void GetSmootherPrototypes(RCP< SmootherPrototype > &preSmootherPrototype, RCP< SmootherPrototype > &postSmootherPrototype) const
Get smoother prototypes.
Exception throws to report errors in the internal logical of the program.
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
void DeclareInput(Level &level) const
Specifies the data that this class needs, and the factories that generate that data.
TopSmootherFactory(RCP< const FactoryManagerBase > parentFactoryManager, const std::string &varName)
bool is_null() const