MueLu  Version of the Day
MueLu_FactoryManager_def.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 #ifndef MUELU_FACTORYMANAGER_DEF_HPP
47 #define MUELU_FACTORYMANAGER_DEF_HPP
48 
49 #include <Teuchos_ParameterList.hpp>
50 
51 // Headers for factories used by default:
52 #include "MueLu_AmalgamationFactory.hpp"
53 #include "MueLu_CoalesceDropFactory.hpp"
54 #include "MueLu_CoarseMapFactory.hpp"
55 #include "MueLu_ConstraintFactory.hpp"
56 #include "MueLu_AggregateQualityEstimateFactory.hpp"
57 #include "MueLu_CoordinatesTransferFactory.hpp"
58 #include "MueLu_DirectSolver.hpp"
59 #include "MueLu_InitialBlockNumberFactory.hpp"
60 #include "MueLu_LineDetectionFactory.hpp"
61 // #include "MueLu_MultiVectorTransferFactory.hpp"
62 #include "MueLu_NoFactory.hpp"
63 #include "MueLu_NullspaceFactory.hpp"
64 #include "MueLu_PatternFactory.hpp"
65 #include "MueLu_RAPFactory.hpp"
66 #include "MueLu_RepartitionHeuristicFactory.hpp"
67 #include "MueLu_RepartitionFactory.hpp"
68 #include "MueLu_SaPFactory.hpp"
69 #include "MueLu_ScaledNullspaceFactory.hpp"
70 #include "MueLu_SmootherFactory.hpp"
71 #include "MueLu_TentativePFactory.hpp"
72 #include "MueLu_TransPFactory.hpp"
73 #include "MueLu_TrilinosSmoother.hpp"
74 #include "MueLu_UncoupledAggregationFactory.hpp"
75 #include "MueLu_StructuredAggregationFactory.hpp"
76 #include "MueLu_HybridAggregationFactory.hpp"
77 #include "MueLu_ZoltanInterface.hpp"
78 #include "MueLu_InterfaceMappingTransferFactory.hpp"
79 #include "MueLu_InterfaceAggregationFactory.hpp"
80 
81 #ifdef HAVE_MUELU_KOKKOS_REFACTOR
82 #include "MueLu_AmalgamationFactory_kokkos.hpp"
83 #include "MueLu_CoalesceDropFactory_kokkos.hpp"
84 #include "MueLu_CoarseMapFactory_kokkos.hpp"
85 #include "MueLu_CoordinatesTransferFactory_kokkos.hpp"
86 #include "MueLu_NullspaceFactory_kokkos.hpp"
87 #include "MueLu_SaPFactory_kokkos.hpp"
88 #include "MueLu_TentativePFactory_kokkos.hpp"
89 #include "MueLu_UncoupledAggregationFactory_kokkos.hpp"
90 #endif
91 
93 
94 
95 namespace MueLu {
96 
97 #ifndef HAVE_MUELU_KOKKOS_REFACTOR
98 #define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory) \
99  SetAndReturnDefaultFactory(varName, rcp(new oldFactory()));
100 #else
101 #define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory) \
102  (!useKokkos_) ? SetAndReturnDefaultFactory(varName, rcp(new oldFactory())) : \
103  SetAndReturnDefaultFactory(varName, rcp(new newFactory()));
104 #endif
105 
106  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
107  void FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::SetFactory(const std::string& varName, const RCP<const FactoryBase>& factory) {
108  factoryTable_[varName] = factory;
109  }
110 
111  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
112  const RCP<const FactoryBase> FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::GetFactory(const std::string& varName) const {
113  if (factoryTable_.count(varName)) {
114  // Search user provided factories
115  return factoryTable_.find(varName)->second;
116  }
117 
118  // Search/create default factory for this name
119  return GetDefaultFactory(varName);
120  }
121 
122  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
123  const RCP<FactoryBase> FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::GetFactoryNonConst(const std::string& varName) {
124  return Teuchos::rcp_const_cast<FactoryBase>(GetFactory(varName));
125  }
126 
127  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
129  if (factoryTable_.count(varName)) return true;
130  return false;
131  }
132 
133  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
134  const RCP<const FactoryBase> FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::GetDefaultFactory(const std::string& varName) const {
135  if (defaultFactoryTable_.count(varName)) {
136  // The factory for this name was already created (possibly, for previous level, if we reuse factory manager)
137  return defaultFactoryTable_.find(varName)->second;
138 
139  } else {
140  // No factory was created for this name, but we may know which one to create
141  if (varName == "A") return SetAndReturnDefaultFactory(varName, rcp(new RAPFactory()));
142  if (varName == "RAP Pattern") return GetFactory("A");
143  if (varName == "AP Pattern") return GetFactory("A");
144  if (varName == "Ptent") return MUELU_KOKKOS_FACTORY(varName, TentativePFactory, TentativePFactory_kokkos);
145  if (varName == "P") {
146  // GetFactory("Ptent"): we need to use the same factory instance for both "P" and "Nullspace"
147  RCP<Factory> factory;
148 #ifdef HAVE_MUELU_KOKKOS_REFACTOR
149  if (useKokkos_)
150  factory = rcp(new SaPFactory_kokkos());
151  else
152 #endif
153  factory = rcp(new SaPFactory());
154  factory->SetFactory("P", GetFactory("Ptent"));
155  return SetAndReturnDefaultFactory(varName, factory);
156  }
157  if (varName == "Nullspace") {
158  // GetFactory("Ptent"): we need to use the same factory instance for both "P" and "Nullspace"
159  RCP<Factory> factory;
160 #ifdef HAVE_MUELU_KOKKOS_REFACTOR
161  if (useKokkos_)
162  factory = rcp(new NullspaceFactory_kokkos());
163  else
164 #endif
165  factory = rcp(new NullspaceFactory());
166  factory->SetFactory("Nullspace", GetFactory("Ptent"));
167  return SetAndReturnDefaultFactory(varName, factory);
168  }
169  if (varName == "Scaled Nullspace") return SetAndReturnDefaultFactory(varName, rcp(new ScaledNullspaceFactory()));
170 
171  if (varName == "Coordinates") return GetFactory("Ptent");
172  if (varName == "Node Comm") return GetFactory("Ptent");
173 
174  if (varName == "R") return SetAndReturnDefaultFactory(varName, rcp(new TransPFactory()));
175 #if defined(HAVE_MUELU_ZOLTAN) && defined(HAVE_MPI)
176  if (varName == "Partition") return SetAndReturnDefaultFactory(varName, rcp(new ZoltanInterface()));
177 #endif //ifdef HAVE_MPI
178 
179  if (varName == "Importer") {
180 #ifdef HAVE_MPI
181  return SetAndReturnDefaultFactory(varName, rcp(new RepartitionFactory()));
182 #else
183  return SetAndReturnDefaultFactory(varName, NoFactory::getRCP());
184 #endif
185  }
186  if (varName == "number of partitions") {
187 #ifdef HAVE_MPI
188  return SetAndReturnDefaultFactory(varName, rcp(new RepartitionHeuristicFactory()));
189 #else
190  return SetAndReturnDefaultFactory(varName, NoFactory::getRCP());
191 #endif
192  }
193  if (varName == "repartition: heuristic target rows per process") return GetFactory("number of partitions");
194 
195  if (varName == "Graph") return MUELU_KOKKOS_FACTORY(varName, CoalesceDropFactory, CoalesceDropFactory_kokkos);
196  if (varName == "UnAmalgamationInfo") return MUELU_KOKKOS_FACTORY(varName, AmalgamationFactory, AmalgamationFactory_kokkos);
197  if (varName == "Aggregates") return MUELU_KOKKOS_FACTORY(varName, UncoupledAggregationFactory, UncoupledAggregationFactory_kokkos);
198  if (varName == "AggregateQualities") return SetAndReturnDefaultFactory(varName, rcp(new AggregateQualityEstimateFactory()));
199  if (varName == "CoarseMap") return MUELU_KOKKOS_FACTORY(varName, CoarseMapFactory, CoarseMapFactory_kokkos);
200  if (varName == "DofsPerNode") return GetFactory("Graph");
201  if (varName == "Filtering") return GetFactory("Graph");
202  if (varName == "BlockNumber") return SetAndReturnDefaultFactory(varName, rcp(new InitialBlockNumberFactory()));
203  if (varName == "LineDetection_VertLineIds") return SetAndReturnDefaultFactory(varName, rcp(new LineDetectionFactory()));
204  if (varName == "LineDetection_Layers") return GetFactory("LineDetection_VertLineIds");
205  if (varName == "CoarseNumZLayers") return GetFactory("LineDetection_VertLineIds");
206 
207  // Structured
208  if (varName == "structuredInterpolationOrder") return SetAndReturnDefaultFactory(varName, rcp(new StructuredAggregationFactory()));
209 
210  // Non-Galerkin
211  if (varName == "K") return GetFactory("A");
212  if (varName == "M") return GetFactory("A");
213  if (varName == "Mdiag") return GetFactory("A");
214  if (varName == "cfl-based shift array") return GetFactory("A");
215 
216  // Same factory for both Pre and Post Smoother. Factory for key "Smoother" can be set by users.
217  if (varName == "PreSmoother") return GetFactory("Smoother");
218  if (varName == "PostSmoother") return GetFactory("Smoother");
219 
220  if (varName == "Ppattern") {
221  RCP<PatternFactory> PpFact = rcp(new PatternFactory);
222  PpFact->SetFactory("P", GetFactory("Ptent"));
223  return SetAndReturnDefaultFactory(varName, PpFact);
224  }
225  if (varName == "Constraint") return SetAndReturnDefaultFactory(varName, rcp(new ConstraintFactory()));
226 
227  if (varName == "Smoother") {
228  Teuchos::ParameterList smootherParamList;
229  smootherParamList.set("relaxation: type", "Symmetric Gauss-Seidel");
230  smootherParamList.set("relaxation: sweeps", Teuchos::OrdinalTraits<LO>::one());
231  smootherParamList.set("relaxation: damping factor", Teuchos::ScalarTraits<Scalar>::one());
232  return SetAndReturnDefaultFactory(varName, rcp(new SmootherFactory(rcp(new TrilinosSmoother("RELAXATION", smootherParamList)))));
233  }
234  if (varName == "CoarseSolver") return SetAndReturnDefaultFactory(varName, rcp(new SmootherFactory(rcp(new DirectSolver()), Teuchos::null)));
235 
236  if (varName == "DualNodeID2PrimalNodeID") return SetAndReturnDefaultFactory(varName, rcp(new InterfaceMappingTransferFactory()));
237  if (varName == "CoarseDualNodeID2PrimalNodeID") return SetAndReturnDefaultFactory(varName, rcp(new InterfaceAggregationFactory()));
238 #ifdef HAVE_MUELU_INTREPID2
239  // If we're asking for it, find who made P
240  if (varName == "pcoarsen: element to node map") return GetFactory("P");
241 #endif
242 
243  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "MueLu::FactoryManager::GetDefaultFactory(): No default factory available for building '" + varName + "'.");
244  }
245  }
246 
247  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
248  const RCP<const FactoryBase> FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::SetAndReturnDefaultFactory(const std::string& varName, const RCP<const FactoryBase>& factory) const {
249  TEUCHOS_TEST_FOR_EXCEPTION(factory.is_null(), Exceptions::RuntimeError, "The default factory for building '" << varName << "' is null");
250 
251  GetOStream(Runtime1) << "Using default factory (" << factory->ShortClassName() <<"["<<factory->GetID()<<"] "<< ") for building '" << varName << "'." << std::endl;
252 
253  defaultFactoryTable_[varName] = factory;
254 
255  return defaultFactoryTable_[varName];
256  }
257 
258  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
260  std::map<std::string, RCP<const FactoryBase> >::const_iterator it;
261  Teuchos::FancyOStream& fancy = GetOStream(Debug);
262  //auto & fancy = std::cout;// For debugging
263 
264 
265  fancy << "Users factory table (factoryTable_):" << std::endl;
266  for (it = factoryTable_.begin(); it != factoryTable_.end(); it++) {
267  fancy << " " << it->first << " -> ";
268  if (it->second.get() == NoFactory::get()) fancy << "NoFactory";
269  else if (!it->second.get()) fancy<< "NULL";
270  else {
271  fancy << it->second.get()->ShortClassName()<<"["<<it->second.get()->GetID()<<"]";
272 #ifdef HAVE_MUELU_DEBUG
273  fancy<<"("<<Teuchos::toString(it->second.get()) <<")";
274 #endif
275  }
276  fancy<< std::endl;
277  }
278 
279  fancy << "Default factory table (defaultFactoryTable_):" << std::endl;
280  for (it = defaultFactoryTable_.begin(); it != defaultFactoryTable_.end(); it++) {
281  fancy << " " << it->first << " -> ";
282  if (it->second.get() == NoFactory::get()) fancy << "NoFactory";
283  else if (!it->second.get()) fancy<< "NULL";
284  else {
285  fancy << it->second.get()->ShortClassName()<<"["<<it->second.get()->GetID()<<"]";
286 #ifdef HAVE_MUELU_DEBUG
287  fancy<<"("<<Teuchos::toString(it->second.get()) <<")";
288 #endif
289  }
290  fancy<< std::endl;
291  }
292 
293  }
294 
295 #ifdef HAVE_MUELU_DEBUG
296  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
298  std::map<std::string, RCP<const FactoryBase> >::const_iterator it;
299 
300  for (it = factoryTable_.begin(); it != factoryTable_.end(); it++)
301  if (!it->second.is_null())
302  it->second->ResetDebugData();
303 
304  for (it = defaultFactoryTable_.begin(); it != defaultFactoryTable_.end(); it++)
305  if (!it->second.is_null())
306  it->second->ResetDebugData();
307  }
308 #endif
309 
310 
311 #undef MUELU_KOKKOS_FACTORY
312 
313 } // namespace MueLu
314 
315 //TODO: add operator[]
316 //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.
317 //TODO: add an option 'NoDefault' to check if we are using any default factory.
318 //TODO: use Teuchos::ConstNonConstObjectContainer to allow user to modify factories after a GetFactory()
319 
320 #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.
std::string toString(const T &what)
Little helper function to convert non-string types to strings.
Class for generating an initial LocalOrdinal-type BlockNumber vector, based on an input paraemter for...
bool hasFactory(const std::string &varName) const
Check.
Class that encapsulates external library smoothers.
Factory for building permutation matrix that can be be used to shuffle data (matrices, vectors) among processes.
Print additional debugging information.
Namespace for MueLu classes and methods.
Interface to Zoltan library.This interface provides access to partitioning methods in Zoltan...
static const NoFactory * get()
Factory for building tentative prolongator.
Class that encapsulates direct solvers. Autoselection of AmesosSmoother or Amesos2Smoother according ...
Base class for factories (e.g., R, P, and A_coarse).
const RCP< const FactoryBase > SetAndReturnDefaultFactory(const std::string &varName, const RCP< const FactoryBase > &factory) const
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.
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)
const RCP< const FactoryBase > GetFactory(const std::string &varName) const
Get factory associated with a particular data name.
Factory for generating a very special nullspace.
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.
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.
const RCP< const FactoryBase > GetDefaultFactory(const std::string &varName) const
Factory for building uncoupled aggregates.
Factory for generating nullspace.
static const RCP< const NoFactory > getRCP()
Static Get() functions.