MueLu Version of the Day
Loading...
Searching...
No Matches
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
32namespace MueLu {
33template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
34TopSmootherFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::TopSmootherFactory(RCP<const FactoryManagerBase> parentFactoryManager, const std::string& varName) {
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
66template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
68
69template <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
77template <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_ */
Exception throws to report errors in the internal logical of the program.
Class that holds all level-specific information.
void DeclareInput(const std::string &ename, const FactoryBase *factory, const FactoryBase *requestedBy=NoFactory::get())
Callback from FactoryBase::CallDeclareInput() and FactoryBase::DeclareInput()
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)
T & Get(const std::string &ename, const FactoryBase *factory=NoFactory::get())
Get data without decrementing associated storage counter (i.e., read-only access)....
void Set(const std::string &ename, const T &entry, const FactoryBase *factory=NoFactory::get())
static const NoFactory * get()
TopSmootherFactory(RCP< const FactoryManagerBase > parentFactoryManager, const std::string &varName)
void Build(Level &level) const
Build an object with this factory.
void DeclareInput(Level &level) const
Specifies the data that this class needs, and the factories that generate that data.
Namespace for MueLu classes and methods.
@ Final
Keep data only for this run. Used to keep data useful for Hierarchy::Iterate(). Data will be deleted ...
@ UserData
User data are always kept. This flag is set automatically when Level::Set("data", data) is used....