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 // ***********************************************************************
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 
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_LineDetectionFactory.hpp"
60 // #include "MueLu_MultiVectorTransferFactory.hpp"
61 #include "MueLu_NoFactory.hpp"
62 #include "MueLu_NullspaceFactory.hpp"
63 #include "MueLu_PatternFactory.hpp"
64 #include "MueLu_RAPFactory.hpp"
65 #include "MueLu_RepartitionHeuristicFactory.hpp"
66 #include "MueLu_RepartitionFactory.hpp"
67 #include "MueLu_SaPFactory.hpp"
68 #include "MueLu_ScaledNullspaceFactory.hpp"
69 #include "MueLu_SmootherFactory.hpp"
70 #include "MueLu_TentativePFactory.hpp"
71 #include "MueLu_TransPFactory.hpp"
72 #include "MueLu_TrilinosSmoother.hpp"
73 #include "MueLu_UncoupledAggregationFactory.hpp"
74 #include "MueLu_HybridAggregationFactory.hpp"
75 #include "MueLu_ZoltanInterface.hpp"
76 #include "MueLu_InterfaceMappingTransferFactory.hpp"
77 #include "MueLu_InterfaceAggregationFactory.hpp"
78 
79 #ifdef HAVE_MUELU_KOKKOS_REFACTOR
80 #include "MueLu_AmalgamationFactory_kokkos.hpp"
81 #include "MueLu_CoalesceDropFactory_kokkos.hpp"
82 #include "MueLu_CoarseMapFactory_kokkos.hpp"
83 #include "MueLu_CoordinatesTransferFactory_kokkos.hpp"
84 #include "MueLu_NullspaceFactory_kokkos.hpp"
85 #include "MueLu_SaPFactory_kokkos.hpp"
86 #include "MueLu_TentativePFactory_kokkos.hpp"
87 #include "MueLu_UncoupledAggregationFactory_kokkos.hpp"
88 #endif
89 
91 
92 
93 namespace MueLu {
94 
95 #ifndef HAVE_MUELU_KOKKOS_REFACTOR
96 #define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory) \
97  SetAndReturnDefaultFactory(varName, rcp(new oldFactory()));
98 #else
99 #define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory) \
100  (!useKokkos_) ? SetAndReturnDefaultFactory(varName, rcp(new oldFactory())) : \
101  SetAndReturnDefaultFactory(varName, rcp(new newFactory()));
102 #endif
103 
104  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
106  factoryTable_[varName] = factory;
107  }
108 
109  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
111  if (factoryTable_.count(varName)) {
112  // Search user provided factories
113  return factoryTable_.find(varName)->second;
114  }
115 
116  // Search/create default factory for this name
117  return GetDefaultFactory(varName);
118  }
119 
120  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
122  return Teuchos::rcp_const_cast<FactoryBase>(GetFactory(varName));
123  }
124 
125  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
127  if (factoryTable_.count(varName)) return true;
128  return false;
129  }
130 
131  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
133  if (defaultFactoryTable_.count(varName)) {
134  // The factory for this name was already created (possibly, for previous level, if we reuse factory manager)
135  return defaultFactoryTable_.find(varName)->second;
136 
137  } else {
138  // No factory was created for this name, but we may know which one to create
139  if (varName == "A") return SetAndReturnDefaultFactory(varName, rcp(new RAPFactory()));
140  if (varName == "RAP Pattern") return GetFactory("A");
141  if (varName == "AP Pattern") return GetFactory("A");
142  if (varName == "Ptent") return MUELU_KOKKOS_FACTORY(varName, TentativePFactory, TentativePFactory_kokkos);
143  if (varName == "P") {
144  // GetFactory("Ptent"): we need to use the same factory instance for both "P" and "Nullspace"
145  RCP<Factory> factory;
146 #ifdef HAVE_MUELU_KOKKOS_REFACTOR
147  if (useKokkos_)
148  factory = rcp(new SaPFactory_kokkos());
149  else
150 #endif
151  factory = rcp(new SaPFactory());
152  factory->SetFactory("P", GetFactory("Ptent"));
153  return SetAndReturnDefaultFactory(varName, factory);
154  }
155  if (varName == "Nullspace") {
156  // GetFactory("Ptent"): we need to use the same factory instance for both "P" and "Nullspace"
157  RCP<Factory> factory;
158 #ifdef HAVE_MUELU_KOKKOS_REFACTOR
159  if (useKokkos_)
160  factory = rcp(new NullspaceFactory_kokkos());
161  else
162 #endif
163  factory = rcp(new NullspaceFactory());
164  factory->SetFactory("Nullspace", GetFactory("Ptent"));
165  return SetAndReturnDefaultFactory(varName, factory);
166  }
167  if (varName == "Scaled Nullspace") return SetAndReturnDefaultFactory(varName, rcp(new ScaledNullspaceFactory()));
168 
169  if (varName == "Coordinates") return GetFactory("Ptent");
170  if (varName == "Node Comm") return GetFactory("Ptent");
171 
172  if (varName == "R") return SetAndReturnDefaultFactory(varName, rcp(new TransPFactory()));
173 #if defined(HAVE_MUELU_ZOLTAN) && defined(HAVE_MPI)
174  if (varName == "Partition") return SetAndReturnDefaultFactory(varName, rcp(new ZoltanInterface()));
175 #endif //ifdef HAVE_MPI
176 
177  if (varName == "Importer") {
178 #ifdef HAVE_MPI
179  return SetAndReturnDefaultFactory(varName, rcp(new RepartitionFactory()));
180 #else
181  return SetAndReturnDefaultFactory(varName, NoFactory::getRCP());
182 #endif
183  }
184  if (varName == "number of partitions") {
185 #ifdef HAVE_MPI
186  return SetAndReturnDefaultFactory(varName, rcp(new RepartitionHeuristicFactory()));
187 #else
188  return SetAndReturnDefaultFactory(varName, NoFactory::getRCP());
189 #endif
190  }
191  if (varName == "repartition: heuristic target rows per process") return GetFactory("number of partitions");
192 
193  if (varName == "Graph") return MUELU_KOKKOS_FACTORY(varName, CoalesceDropFactory, CoalesceDropFactory_kokkos);
194  if (varName == "UnAmalgamationInfo") return MUELU_KOKKOS_FACTORY(varName, AmalgamationFactory, AmalgamationFactory_kokkos);
195  if (varName == "Aggregates") return MUELU_KOKKOS_FACTORY(varName, UncoupledAggregationFactory, UncoupledAggregationFactory_kokkos);
196  if (varName == "AggregateQualities") return SetAndReturnDefaultFactory(varName, rcp(new AggregateQualityEstimateFactory()));
197  if (varName == "CoarseMap") return MUELU_KOKKOS_FACTORY(varName, CoarseMapFactory, CoarseMapFactory_kokkos);
198  if (varName == "DofsPerNode") return GetFactory("Graph");
199  if (varName == "Filtering") return GetFactory("Graph");
200  if (varName == "LineDetection_VertLineIds") return SetAndReturnDefaultFactory(varName, rcp(new LineDetectionFactory()));
201  if (varName == "LineDetection_Layers") return GetFactory("LineDetection_VertLineIds");
202  if (varName == "CoarseNumZLayers") return GetFactory("LineDetection_VertLineIds");
203 
204  // Non-Galerkin
205  if (varName == "K") return GetFactory("A");
206  if (varName == "M") return GetFactory("A");
207  if (varName == "Mdiag") return GetFactory("A");
208  if (varName == "cfl-based shift array") return GetFactory("A");
209 
210  // Same factory for both Pre and Post Smoother. Factory for key "Smoother" can be set by users.
211  if (varName == "PreSmoother") return GetFactory("Smoother");
212  if (varName == "PostSmoother") return GetFactory("Smoother");
213 
214  if (varName == "Ppattern") {
215  RCP<PatternFactory> PpFact = rcp(new PatternFactory);
216  PpFact->SetFactory("P", GetFactory("Ptent"));
217  return SetAndReturnDefaultFactory(varName, PpFact);
218  }
219  if (varName == "Constraint") return SetAndReturnDefaultFactory(varName, rcp(new ConstraintFactory()));
220 
221  if (varName == "Smoother") {
222  Teuchos::ParameterList smootherParamList;
223  smootherParamList.set("relaxation: type", "Symmetric Gauss-Seidel");
224  smootherParamList.set("relaxation: sweeps", Teuchos::OrdinalTraits<LO>::one());
225  smootherParamList.set("relaxation: damping factor", Teuchos::ScalarTraits<Scalar>::one());
226  return SetAndReturnDefaultFactory(varName, rcp(new SmootherFactory(rcp(new TrilinosSmoother("RELAXATION", smootherParamList)))));
227  }
228  if (varName == "CoarseSolver") return SetAndReturnDefaultFactory(varName, rcp(new SmootherFactory(rcp(new DirectSolver()), Teuchos::null)));
229 
230  if (varName == "DualNodeID2PrimalNodeID") return SetAndReturnDefaultFactory(varName, rcp(new InterfaceMappingTransferFactory()));
231  if (varName == "CoarseDualNodeID2PrimalNodeID") return SetAndReturnDefaultFactory(varName, rcp(new InterfaceAggregationFactory()));
232 #ifdef HAVE_MUELU_INTREPID2
233  // If we're asking for it, find who made P
234  if (varName == "pcoarsen: element to node map") return GetFactory("P");
235 #endif
236 
237  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "MueLu::FactoryManager::GetDefaultFactory(): No default factory available for building '" + varName + "'.");
238  }
239  }
240 
241  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
243  TEUCHOS_TEST_FOR_EXCEPTION(factory.is_null(), Exceptions::RuntimeError, "The default factory for building '" << varName << "' is null");
244 
245  GetOStream(Runtime1) << "Using default factory (" << factory->ShortClassName() <<"["<<factory->GetID()<<"] "<< ") for building '" << varName << "'." << std::endl;
246 
247  defaultFactoryTable_[varName] = factory;
248 
249  return defaultFactoryTable_[varName];
250  }
251 
252  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
254  std::map<std::string, RCP<const FactoryBase> >::const_iterator it;
255 
256  Teuchos::FancyOStream& fancy = GetOStream(Debug);
257 
258  fancy << "Users factory table (factoryTable_):" << std::endl;
259  for (it = factoryTable_.begin(); it != factoryTable_.end(); it++) {
260  fancy << " " << it->first << " -> ";
261  if (it->second.get() == NoFactory::get()) fancy << "NoFactory";
262  else if (!it->second.get()) fancy<< "NULL";
263  else {
264  fancy << it->second.get()->ShortClassName()<<"["<<it->second.get()->GetID()<<"]";
265 #ifdef HAVE_MUELU_DEBUG
266  fancy<<"("<<Teuchos::toString(it->second.get()) <<")";
267 #endif
268  }
269  fancy<< std::endl;
270  }
271 
272  fancy << "Default factory table (defaultFactoryTable_):" << std::endl;
273  for (it = defaultFactoryTable_.begin(); it != defaultFactoryTable_.end(); it++) {
274  fancy << " " << it->first << " -> ";
275  if (it->second.get() == NoFactory::get()) fancy << "NoFactory";
276  else if (!it->second.get()) fancy<< "NULL";
277  else {
278  fancy << it->second.get()->ShortClassName()<<"["<<it->second.get()->GetID()<<"]";
279 #ifdef HAVE_MUELU_DEBUG
280  fancy<<"("<<Teuchos::toString(it->second.get()) <<")";
281 #endif
282  }
283  fancy<< std::endl;
284  }
285 
286  }
287 
288 #ifdef HAVE_MUELU_DEBUG
289  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
291  std::map<std::string, RCP<const FactoryBase> >::const_iterator it;
292 
293  for (it = factoryTable_.begin(); it != factoryTable_.end(); it++)
294  if (!it->second.is_null())
295  it->second->ResetDebugData();
296 
297  for (it = defaultFactoryTable_.begin(); it != defaultFactoryTable_.end(); it++)
298  if (!it->second.is_null())
299  it->second->ResetDebugData();
300  }
301 #endif
302 
303 
304 #undef MUELU_KOKKOS_FACTORY
305 
306 } // namespace MueLu
307 
308 //TODO: add operator[]
309 //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.
310 //TODO: add an option 'NoDefault' to check if we are using any default factory.
311 //TODO: use Teuchos::ConstNonConstObjectContainer to allow user to modify factories after a GetFactory()
312 
313 #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 determing the number of partitions for rebalancing.
Factory for generating coarse level map. Used by TentativePFactory.
Class that encapsulates external library smoothers.
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
#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
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).
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Factory for building line detection information.
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)
Factory for generating a very special nullspace.
Factory for building aggregates for Lagrange multipliers.
Factory for creating a graph base on a given matrix.
virtual void SetFactory(const std::string &varName, const RCP< const FactoryBase > &factory)=0
Configuration.
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.
Factory for building uncoupled aggregates.
std::string toString(const T &t)
Factory for generating nullspace.
static const RCP< const NoFactory > getRCP()
Static Get() functions.
bool is_null() const