MueLu  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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 
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 
49 namespace MueLu {
50 
51 #define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory) \
52  (!useKokkos_) ? SetAndReturnDefaultFactory(varName, rcp(new oldFactory())) : SetAndReturnDefaultFactory(varName, rcp(new newFactory()));
53 
54 template <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 
60 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
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 
67 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
69 
70 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
72  factoryTable_[varName] = factory;
73 }
74 
75 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
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 
86 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
88  return Teuchos::rcp_const_cast<FactoryBase>(GetFactory(varName));
89 }
90 
91 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
93  if (factoryTable_.count(varName)) return true;
94  return false;
95 }
96 
97 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
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 
124  if (varName == "Coordinates") return GetFactory("Ptent");
125  if (varName == "Node Comm") return GetFactory("Ptent");
126 
127  if (varName == "R") return SetAndReturnDefaultFactory(varName, rcp(new TransPFactory()));
128  if (varName == "RfromPfactory") return GetFactory("P");
129 #if defined(HAVE_MUELU_ZOLTAN) && defined(HAVE_MPI)
130  if (varName == "Partition") return SetAndReturnDefaultFactory(varName, rcp(new ZoltanInterface()));
131 #endif // ifdef HAVE_MPI
132 
133  if (varName == "Importer") {
134 #ifdef HAVE_MPI
135  return SetAndReturnDefaultFactory(varName, rcp(new RepartitionFactory()));
136 #else
137  return SetAndReturnDefaultFactory(varName, NoFactory::getRCP());
138 #endif
139  }
140  if (varName == "number of partitions") {
141 #ifdef HAVE_MPI
142  return SetAndReturnDefaultFactory(varName, rcp(new RepartitionHeuristicFactory()));
143 #else
144  return SetAndReturnDefaultFactory(varName, NoFactory::getRCP());
145 #endif
146  }
147  if (varName == "repartition: heuristic target rows per process") return GetFactory("number of partitions");
148 
149  if (varName == "Graph") return MUELU_KOKKOS_FACTORY(varName, CoalesceDropFactory, CoalesceDropFactory_kokkos);
150  if (varName == "UnAmalgamationInfo") return SetAndReturnDefaultFactory(varName, rcp(new AmalgamationFactory()));
151  if (varName == "Aggregates") return SetAndReturnDefaultFactory(varName, rcp(new UncoupledAggregationFactory()));
152  if (varName == "AggregateQualities") return SetAndReturnDefaultFactory(varName, rcp(new AggregateQualityEstimateFactory()));
153  if (varName == "CoarseMap") return SetAndReturnDefaultFactory(varName, rcp(new CoarseMapFactory()));
154  if (varName == "DofsPerNode") return GetFactory("Graph");
155  if (varName == "Filtering") return GetFactory("Graph");
156  if (varName == "BlockNumber") return SetAndReturnDefaultFactory(varName, rcp(new InitialBlockNumberFactory()));
157  if (varName == "LineDetection_VertLineIds") return SetAndReturnDefaultFactory(varName, rcp(new LineDetectionFactory()));
158  if (varName == "LineDetection_Layers") return GetFactory("LineDetection_VertLineIds");
159  if (varName == "CoarseNumZLayers") return GetFactory("LineDetection_VertLineIds");
160 
161  // Structured
162  if (varName == "structuredInterpolationOrder") return SetAndReturnDefaultFactory(varName, rcp(new StructuredAggregationFactory()));
163 
164  // Non-Galerkin
165  if (varName == "K") return GetFactory("A");
166  if (varName == "M") return GetFactory("A");
167  if (varName == "Mdiag") return GetFactory("A");
168  if (varName == "cfl-based shift array") return GetFactory("A");
169 
170  // Same factory for both Pre and Post Smoother. Factory for key "Smoother" can be set by users.
171  if (varName == "PreSmoother") return GetFactory("Smoother");
172  if (varName == "PostSmoother") return GetFactory("Smoother");
173 
174  if (varName == "Ppattern") {
175  RCP<PatternFactory> PpFact = rcp(new PatternFactory);
176  PpFact->SetFactory("P", GetFactory("Ptent"));
177  return SetAndReturnDefaultFactory(varName, PpFact);
178  }
179  if (varName == "Constraint") return SetAndReturnDefaultFactory(varName, rcp(new ConstraintFactory()));
180 
181  if (varName == "Smoother") {
182  Teuchos::ParameterList smootherParamList;
183  smootherParamList.set("relaxation: type", "Symmetric Gauss-Seidel");
184  smootherParamList.set("relaxation: sweeps", Teuchos::OrdinalTraits<LO>::one());
185  smootherParamList.set("relaxation: damping factor", Teuchos::ScalarTraits<Scalar>::one());
186  return SetAndReturnDefaultFactory(varName, rcp(new SmootherFactory(rcp(new TrilinosSmoother("RELAXATION", smootherParamList)))));
187  }
188  if (varName == "CoarseSolver") return SetAndReturnDefaultFactory(varName, rcp(new SmootherFactory(rcp(new DirectSolver()), Teuchos::null)));
189 
190  if (varName == "DualNodeID2PrimalNodeID") return SetAndReturnDefaultFactory(varName, rcp(new InterfaceMappingTransferFactory()));
191  if (varName == "CoarseDualNodeID2PrimalNodeID") return SetAndReturnDefaultFactory(varName, rcp(new InterfaceAggregationFactory()));
192 #ifdef HAVE_MUELU_INTREPID2
193  // If we're asking for it, find who made P
194  if (varName == "pcoarsen: element to node map") return GetFactory("P");
195 #endif
196 
197  // NOTE: These are user data, but we might want to print them, so they need a default factory
198  if (varName == "Pnodal") return NoFactory::getRCP();
199  if (varName == "NodeMatrix") return NoFactory::getRCP();
200  if (varName == "NodeAggMatrix") return NoFactory::getRCP();
201 
202  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "MueLu::FactoryManager::GetDefaultFactory(): No default factory available for building '" + varName + "'.");
203  }
204 }
205 
206 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
208  TEUCHOS_TEST_FOR_EXCEPTION(factory.is_null(), Exceptions::RuntimeError, "The default factory for building '" << varName << "' is null");
209 
210  GetOStream(Runtime1) << "Using default factory (" << factory->ShortClassName() << "[" << factory->GetID() << "]) for building '" << varName << "'." << std::endl;
211 
212  defaultFactoryTable_[varName] = factory;
213 
214  return defaultFactoryTable_[varName];
215 }
216 
217 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
219  std::map<std::string, RCP<const FactoryBase> >::const_iterator it;
220  Teuchos::FancyOStream& fancy = GetOStream(Debug);
221  // auto & fancy = std::cout;// For debugging
222 
223  fancy << "Users factory table (factoryTable_):" << std::endl;
224  for (it = factoryTable_.begin(); it != factoryTable_.end(); it++) {
225  fancy << " " << it->first << " -> ";
226  if (it->second.get() == NoFactory::get())
227  fancy << "NoFactory";
228  else if (!it->second.get())
229  fancy << "NULL";
230  else {
231  fancy << it->second.get()->ShortClassName() << "[" << it->second.get()->GetID() << "]";
232 #ifdef HAVE_MUELU_DEBUG
233  fancy << "(" << Teuchos::toString(it->second.get()) << ")";
234 #endif
235  }
236  fancy << std::endl;
237  }
238 
239  fancy << "Default factory table (defaultFactoryTable_):" << std::endl;
240  for (it = defaultFactoryTable_.begin(); it != defaultFactoryTable_.end(); it++) {
241  fancy << " " << it->first << " -> ";
242  if (it->second.get() == NoFactory::get())
243  fancy << "NoFactory";
244  else if (!it->second.get())
245  fancy << "NULL";
246  else {
247  fancy << it->second.get()->ShortClassName() << "[" << it->second.get()->GetID() << "]";
248 #ifdef HAVE_MUELU_DEBUG
249  fancy << "(" << Teuchos::toString(it->second.get()) << ")";
250 #endif
251  }
252  fancy << std::endl;
253  }
254 }
255 
256 #ifdef HAVE_MUELU_DEBUG
257 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
259  std::map<std::string, RCP<const FactoryBase> >::const_iterator it;
260 
261  for (it = factoryTable_.begin(); it != factoryTable_.end(); it++)
262  if (!it->second.is_null())
263  it->second->ResetDebugData();
264 
265  for (it = defaultFactoryTable_.begin(); it != defaultFactoryTable_.end(); it++)
266  if (!it->second.is_null())
267  it->second->ResetDebugData();
268 }
269 #endif
270 
271 #undef MUELU_KOKKOS_FACTORY
272 
273 } // namespace MueLu
274 
275 // TODO: add operator[]
276 // 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.
277 // TODO: add an option 'NoDefault' to check if we are using any default factory.
278 // TODO: use Teuchos::ConstNonConstObjectContainer to allow user to modify factories after a GetFactory()
279 
280 #endif // MUELU_FACTORYMANAGER_DEF_HPP
Generic Smoother Factory for generating the smoothers of the MG hierarchy.
This class specifies the default factory that should generate some data on a Level if the data does n...
Factory for building aggregates on structured grids.
Factory for determing the number of partitions for rebalancing.
Factory for generating coarse level map. Used by TentativePFactory.
virtual void SetFactory(const std::string &varName, const RCP< const FactoryBase > &factory)
Configuration.
Class for generating an initial LocalOrdinal-type BlockNumber vector, based on an input paraemter for...
Class that encapsulates external library smoothers.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Factory for building permutation matrix that can be be used to shuffle data (matrices, vectors) among processes.
Print additional debugging information.
const RCP< const FactoryBase > GetDefaultFactory(const std::string &varName) const
int GetID() const
return unique factory id
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
bool hasFactory(const std::string &varName) const
Check.
Interface to Zoltan library.This interface provides access to partitioning methods in Zoltan...
const RCP< const FactoryBase > GetFactory(const std::string &varName) const
Get factory associated with a particular data name.
static const NoFactory * get()
Factory for building tentative prolongator.
Class that encapsulates direct solvers. Autoselection of AmesosSmoother or Amesos2Smoother according ...
virtual std::string ShortClassName() const
Return the class name of the object, without template parameters and without namespace.
const RCP< const FactoryBase > SetAndReturnDefaultFactory(const std::string &varName, const RCP< const FactoryBase > &factory) const
Base class for factories (e.g., R, P, and A_coarse).
Factory for building the approximate inverse of a matrix.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Factory for building line detection information.
Transfer mapping data for interface aggregation to the coarse level.
AmalgamationFactory for subblocks of strided map based amalgamation data.
static const RCP< const NoFactory > getRCP()
Static Get() functions.
Factory for building the constraint operator.
void SetFactory(const std::string &varName, const RCP< const FactoryBase > &factory)
Set Factory.
const RCP< FactoryBase > GetFactoryNonConst(const std::string &varName)
Get factory associated with a particular data name (NONCONST version)
Factory for generating a very special nullspace.
virtual ~FactoryManager()
Destructor.
Factory for building aggregates for Lagrange multipliers in surface-coupled problems.
Factory for creating a graph based on a given matrix.
Factory for building nonzero patterns for energy minimization.
#define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory)
Factory for building restriction operators.
Factory for creating a graph based on a given matrix.
Exception throws to report errors in the internal logical of the program.
Description of what is happening (more verbose)
Factory for building coarse matrices.
An factory which assigns each aggregate a quality estimate. Originally developed by Napov and Notay i...
Factory for building Smoothed Aggregation prolongators.Input/output of SaPFactory
Factory for building uncoupled aggregates.
std::string toString(const T &t)
Factory for generating nullspace.
bool is_null() const