MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_FactoryManager_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#ifndef MUELU_FACTORYMANAGER_DEF_HPP
11#define MUELU_FACTORYMANAGER_DEF_HPP
12
13#include <Teuchos_ParameterList.hpp>
14
15// Headers for factories used by default:
16#include "MueLu_AmalgamationFactory.hpp"
17#include "MueLu_CoalesceDropFactory.hpp"
18#include "MueLu_CoarseMapFactory.hpp"
19#include "MueLu_ConstraintFactory.hpp"
20#include "MueLu_AggregateQualityEstimateFactory.hpp"
21#include "MueLu_DirectSolver.hpp"
22#include "MueLu_InitialBlockNumberFactory.hpp"
23#include "MueLu_LineDetectionFactory.hpp"
24#include "MueLu_MultiVectorTransferFactory.hpp"
25#include "MueLu_NoFactory.hpp"
26#include "MueLu_NullspaceFactory.hpp"
27#include "MueLu_PatternFactory.hpp"
28#include "MueLu_RAPFactory.hpp"
29#include "MueLu_RepartitionHeuristicFactory.hpp"
30#include "MueLu_RepartitionFactory.hpp"
31#include "MueLu_SaPFactory.hpp"
32#include "MueLu_ScaledNullspaceFactory.hpp"
33#include "MueLu_SmootherFactory.hpp"
34#include "MueLu_TentativePFactory.hpp"
35#include "MueLu_TransPFactory.hpp"
36#include "MueLu_TrilinosSmoother.hpp"
37#include "MueLu_UncoupledAggregationFactory.hpp"
38#include "MueLu_StructuredAggregationFactory.hpp"
39#include "MueLu_ZoltanInterface.hpp"
40#include "MueLu_InterfaceMappingTransferFactory.hpp"
41#include "MueLu_InterfaceAggregationFactory.hpp"
42#include "MueLu_InverseApproximationFactory.hpp"
43
44#include "MueLu_CoalesceDropFactory_kokkos.hpp"
45#include "MueLu_TentativePFactory_kokkos.hpp"
46
48
49namespace MueLu {
50
51#define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory) \
52 (!useKokkos_) ? SetAndReturnDefaultFactory(varName, rcp(new oldFactory())) : SetAndReturnDefaultFactory(varName, rcp(new newFactory()));
53
54template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
56 SetIgnoreUserData(false); // set IgnorUserData flag to false (default behaviour)
57 useKokkos_ = !Node::is_serial;
58}
59
60template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
61FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::FactoryManager(const std::map<std::string, RCP<const FactoryBase> >& factoryTable) {
62 factoryTable_ = factoryTable;
63 SetIgnoreUserData(false); // set IgnorUserData flag to false (default behaviour) //TODO: use parent class constructor instead
64 useKokkos_ = !Node::is_serial;
65}
66
67template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
69
70template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
71void FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::SetFactory(const std::string& varName, const RCP<const FactoryBase>& factory) {
72 factoryTable_[varName] = factory;
73}
74
75template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
76const RCP<const FactoryBase> FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::GetFactory(const std::string& varName) const {
77 if (factoryTable_.count(varName)) {
78 // Search user provided factories
79 return factoryTable_.find(varName)->second;
80 }
81
82 // Search/create default factory for this name
83 return GetDefaultFactory(varName);
84}
85
86template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
88 return Teuchos::rcp_const_cast<FactoryBase>(GetFactory(varName));
89}
90
91template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
93 if (factoryTable_.count(varName)) return true;
94 return false;
95}
96
97template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
98const RCP<const FactoryBase> FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::GetDefaultFactory(const std::string& varName) const {
99 if (defaultFactoryTable_.count(varName)) {
100 // The factory for this name was already created (possibly, for previous level, if we reuse factory manager)
101 return defaultFactoryTable_.find(varName)->second;
102
103 } else {
104 // No factory was created for this name, but we may know which one to create
105 if (varName == "A") return SetAndReturnDefaultFactory(varName, rcp(new RAPFactory()));
106 if (varName == "Ainv") return SetAndReturnDefaultFactory(varName, rcp(new InverseApproximationFactory()));
107 if (varName == "RAP Pattern") return GetFactory("A");
108 if (varName == "AP Pattern") return GetFactory("A");
109 if (varName == "Ptent") return MUELU_KOKKOS_FACTORY(varName, TentativePFactory, TentativePFactory_kokkos);
110 if (varName == "P") {
111 // GetFactory("Ptent"): we need to use the same factory instance for both "P" and "Nullspace"
112 RCP<Factory> factory = rcp(new SaPFactory());
113 factory->SetFactory("P", GetFactory("Ptent"));
114 return SetAndReturnDefaultFactory(varName, factory);
115 }
116 if (varName == "Nullspace") {
117 // GetFactory("Ptent"): we need to use the same factory instance for both "P" and "Nullspace"
118 RCP<Factory> factory = rcp(new NullspaceFactory());
119 factory->SetFactory("Nullspace", GetFactory("Ptent"));
120 return SetAndReturnDefaultFactory(varName, factory);
121 }
122 if (varName == "Scaled Nullspace") return SetAndReturnDefaultFactory(varName, rcp(new ScaledNullspaceFactory()));
123 if (varName == "Material") {
124 auto fact = rcp(new MultiVectorTransferFactory());
125 Teuchos::ParameterList pl;
126 pl.set("Vector name", "Material");
127 pl.set("Transfer name", "Aggregates");
128 pl.set("Normalize", true);
129 fact->SetParameterList(pl);
130 return fact;
131 }
132 if (varName == "Coordinates") return GetFactory("Ptent");
133 if (varName == "Node Comm") return GetFactory("Ptent");
134
135 if (varName == "R") return SetAndReturnDefaultFactory(varName, rcp(new TransPFactory()));
136 if (varName == "RfromPfactory") return GetFactory("P");
137#if defined(HAVE_MUELU_ZOLTAN) && defined(HAVE_MPI)
138 if (varName == "Partition") return SetAndReturnDefaultFactory(varName, rcp(new ZoltanInterface()));
139#endif // ifdef HAVE_MPI
140
141 if (varName == "Importer") {
142#ifdef HAVE_MPI
143 return SetAndReturnDefaultFactory(varName, rcp(new RepartitionFactory()));
144#else
145 return SetAndReturnDefaultFactory(varName, NoFactory::getRCP());
146#endif
147 }
148 if (varName == "number of partitions") {
149#ifdef HAVE_MPI
150 return SetAndReturnDefaultFactory(varName, rcp(new RepartitionHeuristicFactory()));
151#else
152 return SetAndReturnDefaultFactory(varName, NoFactory::getRCP());
153#endif
154 }
155 if (varName == "repartition: heuristic target rows per process") return GetFactory("number of partitions");
156
157 if (varName == "Graph") return MUELU_KOKKOS_FACTORY(varName, CoalesceDropFactory, CoalesceDropFactory_kokkos);
158 if (varName == "UnAmalgamationInfo") return SetAndReturnDefaultFactory(varName, rcp(new AmalgamationFactory()));
159 if (varName == "Aggregates") return SetAndReturnDefaultFactory(varName, rcp(new UncoupledAggregationFactory()));
160 if (varName == "AggregateQualities") return SetAndReturnDefaultFactory(varName, rcp(new AggregateQualityEstimateFactory()));
161 if (varName == "CoarseMap") return SetAndReturnDefaultFactory(varName, rcp(new CoarseMapFactory()));
162 if (varName == "DofsPerNode") return GetFactory("Graph");
163 if (varName == "Filtering") return GetFactory("Graph");
164 if (varName == "BlockNumber") return SetAndReturnDefaultFactory(varName, rcp(new InitialBlockNumberFactory()));
165 if (varName == "LineDetection_VertLineIds") return SetAndReturnDefaultFactory(varName, rcp(new LineDetectionFactory()));
166 if (varName == "LineDetection_Layers") return GetFactory("LineDetection_VertLineIds");
167 if (varName == "CoarseNumZLayers") return GetFactory("LineDetection_VertLineIds");
168
169 // Structured
170 if (varName == "structuredInterpolationOrder") return SetAndReturnDefaultFactory(varName, rcp(new StructuredAggregationFactory()));
171
172 // Non-Galerkin
173 if (varName == "K") return GetFactory("A");
174 if (varName == "M") return GetFactory("A");
175 if (varName == "Mdiag") return GetFactory("A");
176 if (varName == "cfl-based shift array") return GetFactory("A");
177
178 // Same factory for both Pre and Post Smoother. Factory for key "Smoother" can be set by users.
179 if (varName == "PreSmoother") return GetFactory("Smoother");
180 if (varName == "PostSmoother") return GetFactory("Smoother");
181
182 if (varName == "Ppattern") {
183 RCP<PatternFactory> PpFact = rcp(new PatternFactory);
184 PpFact->SetFactory("P", GetFactory("Ptent"));
185 return SetAndReturnDefaultFactory(varName, PpFact);
186 }
187 if (varName == "Constraint") return SetAndReturnDefaultFactory(varName, rcp(new ConstraintFactory()));
188
189 if (varName == "Smoother") {
190 Teuchos::ParameterList smootherParamList;
191 smootherParamList.set("relaxation: type", "Symmetric Gauss-Seidel");
192 smootherParamList.set("relaxation: sweeps", Teuchos::OrdinalTraits<LO>::one());
193 smootherParamList.set("relaxation: damping factor", Teuchos::ScalarTraits<Scalar>::one());
194 return SetAndReturnDefaultFactory(varName, rcp(new SmootherFactory(rcp(new TrilinosSmoother("RELAXATION", smootherParamList)))));
195 }
196 if (varName == "CoarseSolver") return SetAndReturnDefaultFactory(varName, rcp(new SmootherFactory(rcp(new DirectSolver()), Teuchos::null)));
197
198 if (varName == "DualNodeID2PrimalNodeID") return SetAndReturnDefaultFactory(varName, rcp(new InterfaceMappingTransferFactory()));
199 if (varName == "CoarseDualNodeID2PrimalNodeID") return SetAndReturnDefaultFactory(varName, rcp(new InterfaceAggregationFactory()));
200#ifdef HAVE_MUELU_INTREPID2
201 // If we're asking for it, find who made P
202 if (varName == "pcoarsen: element to node map") return GetFactory("P");
203#endif
204
205 // NOTE: These are user data, but we might want to print them, so they need a default factory
206 if (varName == "Pnodal") return NoFactory::getRCP();
207 if (varName == "NodeMatrix") return NoFactory::getRCP();
208 if (varName == "NodeAggMatrix") return NoFactory::getRCP();
209
210 TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "MueLu::FactoryManager::GetDefaultFactory(): No default factory available for building '" + varName + "'.");
211 }
212}
213
214template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
215const RCP<const FactoryBase> FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::SetAndReturnDefaultFactory(const std::string& varName, const RCP<const FactoryBase>& factory) const {
216 TEUCHOS_TEST_FOR_EXCEPTION(factory.is_null(), Exceptions::RuntimeError, "The default factory for building '" << varName << "' is null");
217
218 GetOStream(Runtime1) << "Using default factory (" << factory->ShortClassName() << "[" << factory->GetID() << "]) for building '" << varName << "'." << std::endl;
219
220 defaultFactoryTable_[varName] = factory;
221
222 return defaultFactoryTable_[varName];
223}
224
225template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
227 std::map<std::string, RCP<const FactoryBase> >::const_iterator it;
228 Teuchos::FancyOStream& fancy = GetOStream(Debug);
229 // auto & fancy = std::cout;// For debugging
230
231 fancy << "Users factory table (factoryTable_):" << std::endl;
232 for (it = factoryTable_.begin(); it != factoryTable_.end(); it++) {
233 fancy << " " << it->first << " -> ";
234 if (it->second.get() == NoFactory::get())
235 fancy << "NoFactory";
236 else if (!it->second.get())
237 fancy << "NULL";
238 else {
239 fancy << it->second.get()->ShortClassName() << "[" << it->second.get()->GetID() << "]";
240#ifdef HAVE_MUELU_DEBUG
241 fancy << "(" << Teuchos::toString(it->second.get()) << ")";
242#endif
243 }
244 fancy << std::endl;
245 }
246
247 fancy << "Default factory table (defaultFactoryTable_):" << std::endl;
248 for (it = defaultFactoryTable_.begin(); it != defaultFactoryTable_.end(); it++) {
249 fancy << " " << it->first << " -> ";
250 if (it->second.get() == NoFactory::get())
251 fancy << "NoFactory";
252 else if (!it->second.get())
253 fancy << "NULL";
254 else {
255 fancy << it->second.get()->ShortClassName() << "[" << it->second.get()->GetID() << "]";
256#ifdef HAVE_MUELU_DEBUG
257 fancy << "(" << Teuchos::toString(it->second.get()) << ")";
258#endif
259 }
260 fancy << std::endl;
261 }
262}
263
264#ifdef HAVE_MUELU_DEBUG
265template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
267 std::map<std::string, RCP<const FactoryBase> >::const_iterator it;
268
269 for (it = factoryTable_.begin(); it != factoryTable_.end(); it++)
270 if (!it->second.is_null())
271 it->second->ResetDebugData();
272
273 for (it = defaultFactoryTable_.begin(); it != defaultFactoryTable_.end(); it++)
274 if (!it->second.is_null())
275 it->second->ResetDebugData();
276}
277#endif
278
279#undef MUELU_KOKKOS_FACTORY
280
281} // namespace MueLu
282
283// TODO: add operator[]
284// TODO: should we use a parameterList instead of a std::map? It might be useful to tag which factory have been used and report unused factory.
285// TODO: add an option 'NoDefault' to check if we are using any default factory.
286// TODO: use Teuchos::ConstNonConstObjectContainer to allow user to modify factories after a GetFactory()
287
288#endif // MUELU_FACTORYMANAGER_DEF_HPP
#define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory)
An factory which assigns each aggregate a quality estimate. Originally developed by Napov and Notay i...
AmalgamationFactory for subblocks of strided map based amalgamation data.
Factory for creating a graph based on a given matrix.
Factory for creating a graph based on a given matrix.
Factory for generating coarse level map. Used by TentativePFactory.
Factory for building the constraint operator.
Class that encapsulates direct solvers. Autoselection of AmesosSmoother or Amesos2Smoother according ...
Exception throws to report errors in the internal logical of the program.
This class specifies the default factory that should generate some data on a Level if the data does n...
const RCP< const FactoryBase > GetDefaultFactory(const std::string &varName) const
const RCP< const FactoryBase > SetAndReturnDefaultFactory(const std::string &varName, const RCP< const FactoryBase > &factory) const
void SetFactory(const std::string &varName, const RCP< const FactoryBase > &factory)
Set Factory.
bool hasFactory(const std::string &varName) const
Check.
const RCP< const FactoryBase > GetFactory(const std::string &varName) const
Get factory associated with a particular data name.
const RCP< FactoryBase > GetFactoryNonConst(const std::string &varName)
Get factory associated with a particular data name (NONCONST version)
virtual ~FactoryManager()
Destructor.
Class for generating an initial LocalOrdinal-type BlockNumber vector, based on an input paraemter for...
Factory for building aggregates for Lagrange multipliers in surface-coupled problems.
Transfer mapping data for interface aggregation to the coarse level.
Factory for building the approximate inverse of a matrix.
Factory for building line detection information.
Class for restricting a MultiVector from a finer to a coarser level.
static const RCP< const NoFactory > getRCP()
Static Get() functions.
static const NoFactory * get()
Factory for generating nullspace.
Factory for building nonzero patterns for energy minimization.
Factory for building coarse matrices.
Factory for building permutation matrix that can be be used to shuffle data (matrices,...
Factory for determing the number of partitions for rebalancing.
Factory for building Smoothed Aggregation prolongators.
Factory for generating a very special nullspace.
Generic Smoother Factory for generating the smoothers of the MG hierarchy.
Factory for building aggregates on structured grids.
Factory for building tentative prolongator.
Factory for building restriction operators.
Class that encapsulates external library smoothers.
Interface to Zoltan library.
Namespace for MueLu classes and methods.
@ Debug
Print additional debugging information.
@ Runtime1
Description of what is happening (more verbose)