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