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 #include "MueLu_InverseApproximationFactory.hpp"
81 
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 
92 
93 
94 namespace MueLu {
95 
96 #define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory) \
97  (!useKokkos_) ? SetAndReturnDefaultFactory(varName, rcp(new oldFactory())) : \
98  SetAndReturnDefaultFactory(varName, rcp(new newFactory()));
99 
100  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
101  void FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::SetFactory(const std::string& varName, const RCP<const FactoryBase>& factory) {
102  factoryTable_[varName] = factory;
103  }
104 
105  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
106  const RCP<const FactoryBase> FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::GetFactory(const std::string& varName) const {
107  if (factoryTable_.count(varName)) {
108  // Search user provided factories
109  return factoryTable_.find(varName)->second;
110  }
111 
112  // Search/create default factory for this name
113  return GetDefaultFactory(varName);
114  }
115 
116  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
117  const RCP<FactoryBase> FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::GetFactoryNonConst(const std::string& varName) {
118  return Teuchos::rcp_const_cast<FactoryBase>(GetFactory(varName));
119  }
120 
121  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
123  if (factoryTable_.count(varName)) return true;
124  return false;
125  }
126 
127  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
128  const RCP<const FactoryBase> FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::GetDefaultFactory(const std::string& varName) const {
129  if (defaultFactoryTable_.count(varName)) {
130  // The factory for this name was already created (possibly, for previous level, if we reuse factory manager)
131  return defaultFactoryTable_.find(varName)->second;
132 
133  } else {
134  // No factory was created for this name, but we may know which one to create
135  if (varName == "A") return SetAndReturnDefaultFactory(varName, rcp(new RAPFactory()));
136  if (varName == "Ainv") return SetAndReturnDefaultFactory(varName, rcp(new InverseApproximationFactory()));
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  if (useKokkos_)
144  factory = rcp(new SaPFactory_kokkos());
145  else
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  if (useKokkos_)
154  factory = rcp(new NullspaceFactory_kokkos());
155  else
156  factory = rcp(new NullspaceFactory());
157  factory->SetFactory("Nullspace", GetFactory("Ptent"));
158  return SetAndReturnDefaultFactory(varName, factory);
159  }
160  if (varName == "Scaled Nullspace") return SetAndReturnDefaultFactory(varName, rcp(new ScaledNullspaceFactory()));
161 
162  if (varName == "Coordinates") return GetFactory("Ptent");
163  if (varName == "Node Comm") return GetFactory("Ptent");
164 
165  if (varName == "R") return SetAndReturnDefaultFactory(varName, rcp(new TransPFactory()));
166  if (varName == "RfromPfactory") return GetFactory("P");
167 #if defined(HAVE_MUELU_ZOLTAN) && defined(HAVE_MPI)
168  if (varName == "Partition") return SetAndReturnDefaultFactory(varName, rcp(new ZoltanInterface()));
169 #endif //ifdef HAVE_MPI
170 
171  if (varName == "Importer") {
172 #ifdef HAVE_MPI
173  return SetAndReturnDefaultFactory(varName, rcp(new RepartitionFactory()));
174 #else
175  return SetAndReturnDefaultFactory(varName, NoFactory::getRCP());
176 #endif
177  }
178  if (varName == "number of partitions") {
179 #ifdef HAVE_MPI
180  return SetAndReturnDefaultFactory(varName, rcp(new RepartitionHeuristicFactory()));
181 #else
182  return SetAndReturnDefaultFactory(varName, NoFactory::getRCP());
183 #endif
184  }
185  if (varName == "repartition: heuristic target rows per process") return GetFactory("number of partitions");
186 
187  if (varName == "Graph") return MUELU_KOKKOS_FACTORY(varName, CoalesceDropFactory, CoalesceDropFactory_kokkos);
188  if (varName == "UnAmalgamationInfo") return MUELU_KOKKOS_FACTORY(varName, AmalgamationFactory, AmalgamationFactory_kokkos);
189  if (varName == "Aggregates") return MUELU_KOKKOS_FACTORY(varName, UncoupledAggregationFactory, UncoupledAggregationFactory_kokkos);
190  if (varName == "AggregateQualities") return SetAndReturnDefaultFactory(varName, rcp(new AggregateQualityEstimateFactory()));
191  if (varName == "CoarseMap") return MUELU_KOKKOS_FACTORY(varName, CoarseMapFactory, CoarseMapFactory_kokkos);
192  if (varName == "DofsPerNode") return GetFactory("Graph");
193  if (varName == "Filtering") return GetFactory("Graph");
194  if (varName == "BlockNumber") return SetAndReturnDefaultFactory(varName, rcp(new InitialBlockNumberFactory()));
195  if (varName == "LineDetection_VertLineIds") return SetAndReturnDefaultFactory(varName, rcp(new LineDetectionFactory()));
196  if (varName == "LineDetection_Layers") return GetFactory("LineDetection_VertLineIds");
197  if (varName == "CoarseNumZLayers") return GetFactory("LineDetection_VertLineIds");
198 
199  // Structured
200  if (varName == "structuredInterpolationOrder") return SetAndReturnDefaultFactory(varName, rcp(new StructuredAggregationFactory()));
201 
202  // Non-Galerkin
203  if (varName == "K") return GetFactory("A");
204  if (varName == "M") return GetFactory("A");
205  if (varName == "Mdiag") return GetFactory("A");
206  if (varName == "cfl-based shift array") return GetFactory("A");
207 
208  // Same factory for both Pre and Post Smoother. Factory for key "Smoother" can be set by users.
209  if (varName == "PreSmoother") return GetFactory("Smoother");
210  if (varName == "PostSmoother") return GetFactory("Smoother");
211 
212  if (varName == "Ppattern") {
213  RCP<PatternFactory> PpFact = rcp(new PatternFactory);
214  PpFact->SetFactory("P", GetFactory("Ptent"));
215  return SetAndReturnDefaultFactory(varName, PpFact);
216  }
217  if (varName == "Constraint") return SetAndReturnDefaultFactory(varName, rcp(new ConstraintFactory()));
218 
219  if (varName == "Smoother") {
220  Teuchos::ParameterList smootherParamList;
221  smootherParamList.set("relaxation: type", "Symmetric Gauss-Seidel");
222  smootherParamList.set("relaxation: sweeps", Teuchos::OrdinalTraits<LO>::one());
223  smootherParamList.set("relaxation: damping factor", Teuchos::ScalarTraits<Scalar>::one());
224  return SetAndReturnDefaultFactory(varName, rcp(new SmootherFactory(rcp(new TrilinosSmoother("RELAXATION", smootherParamList)))));
225  }
226  if (varName == "CoarseSolver") return SetAndReturnDefaultFactory(varName, rcp(new SmootherFactory(rcp(new DirectSolver()), Teuchos::null)));
227 
228  if (varName == "DualNodeID2PrimalNodeID") return SetAndReturnDefaultFactory(varName, rcp(new InterfaceMappingTransferFactory()));
229  if (varName == "CoarseDualNodeID2PrimalNodeID") return SetAndReturnDefaultFactory(varName, rcp(new InterfaceAggregationFactory()));
230 #ifdef HAVE_MUELU_INTREPID2
231  // If we're asking for it, find who made P
232  if (varName == "pcoarsen: element to node map") return GetFactory("P");
233 #endif
234 
235  TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "MueLu::FactoryManager::GetDefaultFactory(): No default factory available for building '" + varName + "'.");
236  }
237  }
238 
239  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
240  const RCP<const FactoryBase> FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::SetAndReturnDefaultFactory(const std::string& varName, const RCP<const FactoryBase>& factory) const {
241  TEUCHOS_TEST_FOR_EXCEPTION(factory.is_null(), Exceptions::RuntimeError, "The default factory for building '" << varName << "' is null");
242 
243  GetOStream(Runtime1) << "Using default factory (" << factory->ShortClassName() <<"["<<factory->GetID()<<"]) for building '" << varName << "'." << std::endl;
244 
245  defaultFactoryTable_[varName] = factory;
246 
247  return defaultFactoryTable_[varName];
248  }
249 
250  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
252  std::map<std::string, RCP<const FactoryBase> >::const_iterator it;
253  Teuchos::FancyOStream& fancy = GetOStream(Debug);
254  //auto & fancy = std::cout;// For debugging
255 
256 
257  fancy << "Users factory table (factoryTable_):" << std::endl;
258  for (it = factoryTable_.begin(); it != factoryTable_.end(); it++) {
259  fancy << " " << it->first << " -> ";
260  if (it->second.get() == NoFactory::get()) fancy << "NoFactory";
261  else if (!it->second.get()) fancy<< "NULL";
262  else {
263  fancy << it->second.get()->ShortClassName()<<"["<<it->second.get()->GetID()<<"]";
264 #ifdef HAVE_MUELU_DEBUG
265  fancy<<"("<<Teuchos::toString(it->second.get()) <<")";
266 #endif
267  }
268  fancy<< std::endl;
269  }
270 
271  fancy << "Default factory table (defaultFactoryTable_):" << std::endl;
272  for (it = defaultFactoryTable_.begin(); it != defaultFactoryTable_.end(); it++) {
273  fancy << " " << it->first << " -> ";
274  if (it->second.get() == NoFactory::get()) fancy << "NoFactory";
275  else if (!it->second.get()) fancy<< "NULL";
276  else {
277  fancy << it->second.get()->ShortClassName()<<"["<<it->second.get()->GetID()<<"]";
278 #ifdef HAVE_MUELU_DEBUG
279  fancy<<"("<<Teuchos::toString(it->second.get()) <<")";
280 #endif
281  }
282  fancy<< std::endl;
283  }
284 
285  }
286 
287 #ifdef HAVE_MUELU_DEBUG
288  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
290  std::map<std::string, RCP<const FactoryBase> >::const_iterator it;
291 
292  for (it = factoryTable_.begin(); it != factoryTable_.end(); it++)
293  if (!it->second.is_null())
294  it->second->ResetDebugData();
295 
296  for (it = defaultFactoryTable_.begin(); it != defaultFactoryTable_.end(); it++)
297  if (!it->second.is_null())
298  it->second->ResetDebugData();
299  }
300 #endif
301 
302 
303 #undef MUELU_KOKKOS_FACTORY
304 
305 } // namespace MueLu
306 
307 //TODO: add operator[]
308 //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.
309 //TODO: add an option 'NoDefault' to check if we are using any default factory.
310 //TODO: use Teuchos::ConstNonConstObjectContainer to allow user to modify factories after a GetFactory()
311 
312 #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.
AmalgamationFactory_kokkos for subblocks of strided map based amalgamation data.
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).
Factory for building the approximate inverse of a matrix.
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.
Factory for building Smoothed Aggregation prolongators.Input/output of SaPFactory_kokkos
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.
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.
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.