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
95namespace 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
#define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory)
An factory which assigns each aggregate a quality estimate. Originally developed by Napov and Notay i...
AmalgamationFactory for subblocks of strided map based amalgamation data.
Factory for creating a graph based on a given matrix.
Factory for generating coarse level map. Used by TentativePFactory.
Factory for building the constraint operator.
Class that encapsulates direct solvers. Autoselection of AmesosSmoother or Amesos2Smoother according ...
Exception throws to report errors in the internal logical of the program.
This class specifies the default factory that should generate some data on a Level if the data does n...
const RCP< const FactoryBase > GetDefaultFactory(const std::string &varName) const
const RCP< const FactoryBase > SetAndReturnDefaultFactory(const std::string &varName, const RCP< const FactoryBase > &factory) const
void SetFactory(const std::string &varName, const RCP< const FactoryBase > &factory)
Set Factory.
bool hasFactory(const std::string &varName) const
Check.
const RCP< const FactoryBase > GetFactory(const std::string &varName) const
Get factory associated with a particular data name.
const RCP< FactoryBase > GetFactoryNonConst(const std::string &varName)
Get factory associated with a particular data name (NONCONST version)
Class for generating an initial LocalOrdinal-type BlockNumber vector, based on an input paraemter for...
Factory for building aggregates for Lagrange multipliers in surface-coupled problems.
Transfer mapping data for interface aggregation to the coarse level.
Factory for building line detection information.
static const RCP< const NoFactory > getRCP()
Static Get() functions.
static const NoFactory * get()
Factory for generating nullspace.
Factory for building nonzero patterns for energy minimization.
Factory for building coarse matrices.
Factory for building permutation matrix that can be be used to shuffle data (matrices,...
Factory for determing the number of partitions for rebalancing.
Factory for building Smoothed Aggregation prolongators.
Factory for generating a very special nullspace.
Generic Smoother Factory for generating the smoothers of the MG hierarchy.
Factory for building aggregates on structured grids.
Factory for building tentative prolongator.
Factory for building restriction operators.
Class that encapsulates external library smoothers.
Factory for building uncoupled aggregates.
Interface to Zoltan library.
Namespace for MueLu classes and methods.
@ Debug
Print additional debugging information.
@ Runtime1
Description of what is happening (more verbose)
std::string toString(const T &what)
Little helper function to convert non-string types to strings.