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