MueLu Version of the Day
Loading...
Searching...
No Matches
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_DirectSolver.hpp"
58#include "MueLu_InitialBlockNumberFactory.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_StructuredAggregationFactory.hpp"
75#include "MueLu_ZoltanInterface.hpp"
76#include "MueLu_InterfaceMappingTransferFactory.hpp"
77#include "MueLu_InterfaceAggregationFactory.hpp"
78#include "MueLu_InverseApproximationFactory.hpp"
79
80#include "MueLu_CoalesceDropFactory_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
87
88
89namespace MueLu {
90
91#define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory) \
92 (!useKokkos_) ? SetAndReturnDefaultFactory(varName, rcp(new oldFactory())) : \
93 SetAndReturnDefaultFactory(varName, rcp(new newFactory()));
94
95 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
96 void FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::SetFactory(const std::string& varName, const RCP<const FactoryBase>& factory) {
97 factoryTable_[varName] = factory;
98 }
99
100 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
101 const RCP<const FactoryBase> FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::GetFactory(const std::string& varName) const {
102 if (factoryTable_.count(varName)) {
103 // Search user provided factories
104 return factoryTable_.find(varName)->second;
105 }
106
107 // Search/create default factory for this name
108 return GetDefaultFactory(varName);
109 }
110
111 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
112 const RCP<FactoryBase> FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::GetFactoryNonConst(const std::string& varName) {
113 return Teuchos::rcp_const_cast<FactoryBase>(GetFactory(varName));
114 }
115
116 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
118 if (factoryTable_.count(varName)) return true;
119 return false;
120 }
121
122 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
123 const RCP<const FactoryBase> FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::GetDefaultFactory(const std::string& varName) const {
124 if (defaultFactoryTable_.count(varName)) {
125 // The factory for this name was already created (possibly, for previous level, if we reuse factory manager)
126 return defaultFactoryTable_.find(varName)->second;
127
128 } else {
129 // No factory was created for this name, but we may know which one to create
130 if (varName == "A") return SetAndReturnDefaultFactory(varName, rcp(new RAPFactory()));
131 if (varName == "Ainv") return SetAndReturnDefaultFactory(varName, rcp(new InverseApproximationFactory()));
132 if (varName == "RAP Pattern") return GetFactory("A");
133 if (varName == "AP Pattern") return GetFactory("A");
134 if (varName == "Ptent") return MUELU_KOKKOS_FACTORY(varName, TentativePFactory, TentativePFactory_kokkos);
135 if (varName == "P") {
136 // GetFactory("Ptent"): we need to use the same factory instance for both "P" and "Nullspace"
137 RCP<Factory> factory;
138 if (useKokkos_)
139 factory = rcp(new SaPFactory_kokkos());
140 else
141 factory = rcp(new SaPFactory());
142 factory->SetFactory("P", GetFactory("Ptent"));
143 return SetAndReturnDefaultFactory(varName, factory);
144 }
145 if (varName == "Nullspace") {
146 // GetFactory("Ptent"): we need to use the same factory instance for both "P" and "Nullspace"
147 RCP<Factory> factory;
148 if (useKokkos_)
149 factory = rcp(new NullspaceFactory_kokkos());
150 else
151 factory = rcp(new NullspaceFactory());
152 factory->SetFactory("Nullspace", GetFactory("Ptent"));
153 return SetAndReturnDefaultFactory(varName, factory);
154 }
155 if (varName == "Scaled Nullspace") return SetAndReturnDefaultFactory(varName, rcp(new ScaledNullspaceFactory()));
156
157 if (varName == "Coordinates") return GetFactory("Ptent");
158 if (varName == "Node Comm") return GetFactory("Ptent");
159
160 if (varName == "R") return SetAndReturnDefaultFactory(varName, rcp(new TransPFactory()));
161 if (varName == "RfromPfactory") return GetFactory("P");
162#if defined(HAVE_MUELU_ZOLTAN) && defined(HAVE_MPI)
163 if (varName == "Partition") return SetAndReturnDefaultFactory(varName, rcp(new ZoltanInterface()));
164#endif //ifdef HAVE_MPI
165
166 if (varName == "Importer") {
167#ifdef HAVE_MPI
168 return SetAndReturnDefaultFactory(varName, rcp(new RepartitionFactory()));
169#else
171#endif
172 }
173 if (varName == "number of partitions") {
174#ifdef HAVE_MPI
176#else
178#endif
179 }
180 if (varName == "repartition: heuristic target rows per process") return GetFactory("number of partitions");
181
182 if (varName == "Graph") return MUELU_KOKKOS_FACTORY(varName, CoalesceDropFactory, CoalesceDropFactory_kokkos);
183 if (varName == "UnAmalgamationInfo") return SetAndReturnDefaultFactory(varName, rcp(new AmalgamationFactory()));
184 if (varName == "Aggregates") return MUELU_KOKKOS_FACTORY(varName, UncoupledAggregationFactory, UncoupledAggregationFactory_kokkos);
185 if (varName == "AggregateQualities") return SetAndReturnDefaultFactory(varName, rcp(new AggregateQualityEstimateFactory()));
186 if (varName == "CoarseMap") return SetAndReturnDefaultFactory(varName, rcp(new CoarseMapFactory()));
187 if (varName == "DofsPerNode") return GetFactory("Graph");
188 if (varName == "Filtering") return GetFactory("Graph");
189 if (varName == "BlockNumber") return SetAndReturnDefaultFactory(varName, rcp(new InitialBlockNumberFactory()));
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 // Structured
195 if (varName == "structuredInterpolationOrder") return SetAndReturnDefaultFactory(varName, rcp(new StructuredAggregationFactory()));
196
197 // Non-Galerkin
198 if (varName == "K") return GetFactory("A");
199 if (varName == "M") return GetFactory("A");
200 if (varName == "Mdiag") return GetFactory("A");
201 if (varName == "cfl-based shift array") return GetFactory("A");
202
203 // Same factory for both Pre and Post Smoother. Factory for key "Smoother" can be set by users.
204 if (varName == "PreSmoother") return GetFactory("Smoother");
205 if (varName == "PostSmoother") return GetFactory("Smoother");
206
207 if (varName == "Ppattern") {
208 RCP<PatternFactory> PpFact = rcp(new PatternFactory);
209 PpFact->SetFactory("P", GetFactory("Ptent"));
210 return SetAndReturnDefaultFactory(varName, PpFact);
211 }
212 if (varName == "Constraint") return SetAndReturnDefaultFactory(varName, rcp(new ConstraintFactory()));
213
214 if (varName == "Smoother") {
215 Teuchos::ParameterList smootherParamList;
216 smootherParamList.set("relaxation: type", "Symmetric Gauss-Seidel");
217 smootherParamList.set("relaxation: sweeps", Teuchos::OrdinalTraits<LO>::one());
218 smootherParamList.set("relaxation: damping factor", Teuchos::ScalarTraits<Scalar>::one());
219 return SetAndReturnDefaultFactory(varName, rcp(new SmootherFactory(rcp(new TrilinosSmoother("RELAXATION", smootherParamList)))));
220 }
221 if (varName == "CoarseSolver") return SetAndReturnDefaultFactory(varName, rcp(new SmootherFactory(rcp(new DirectSolver()), Teuchos::null)));
222
223 if (varName == "DualNodeID2PrimalNodeID") return SetAndReturnDefaultFactory(varName, rcp(new InterfaceMappingTransferFactory()));
224 if (varName == "CoarseDualNodeID2PrimalNodeID") return SetAndReturnDefaultFactory(varName, rcp(new InterfaceAggregationFactory()));
225#ifdef HAVE_MUELU_INTREPID2
226 // If we're asking for it, find who made P
227 if (varName == "pcoarsen: element to node map") return GetFactory("P");
228#endif
229
230 // NOTE: These are user data, but we might want to print them, so they need a default factory
231 if (varName == "Pnodal") return NoFactory::getRCP();
232 if (varName == "NodeMatrix") return NoFactory::getRCP();
233 if (varName == "NodeAggMatrix") return NoFactory::getRCP();
234
235
236 TEUCHOS_TEST_FOR_EXCEPTION(true, MueLu::Exceptions::RuntimeError, "MueLu::FactoryManager::GetDefaultFactory(): No default factory available for building '" + varName + "'.");
237 }
238 }
239
240 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
241 const RCP<const FactoryBase> FactoryManager<Scalar, LocalOrdinal, GlobalOrdinal, Node>::SetAndReturnDefaultFactory(const std::string& varName, const RCP<const FactoryBase>& factory) const {
242 TEUCHOS_TEST_FOR_EXCEPTION(factory.is_null(), Exceptions::RuntimeError, "The default factory for building '" << varName << "' is null");
243
244 GetOStream(Runtime1) << "Using default factory (" << factory->ShortClassName() <<"["<<factory->GetID()<<"]) for building '" << varName << "'." << std::endl;
245
246 defaultFactoryTable_[varName] = factory;
247
248 return defaultFactoryTable_[varName];
249 }
250
251 template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
253 std::map<std::string, RCP<const FactoryBase> >::const_iterator it;
254 Teuchos::FancyOStream& fancy = GetOStream(Debug);
255 //auto & fancy = std::cout;// For debugging
256
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
#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 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...
MueLu::InterfaceAggregationFactory< Scalar, LocalOrdinal, GlobalOrdinal, Node > InterfaceAggregationFactory
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
bool useKokkos_
Whether or not to use kokkos factories.
std::map< std::string, RCP< const FactoryBase > > defaultFactoryTable_
Table that holds default factories.
void SetFactory(const std::string &varName, const RCP< const FactoryBase > &factory)
Set Factory.
bool hasFactory(const std::string &varName) const
Check.
MueLu::ScaledNullspaceFactory< Scalar, LocalOrdinal, GlobalOrdinal, Node > ScaledNullspaceFactory
std::map< std::string, RCP< const FactoryBase > > factoryTable_
User-defined factories.
MueLu::InterfaceMappingTransferFactory< LocalOrdinal, GlobalOrdinal, Node > InterfaceMappingTransferFactory
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 the approximate inverse of a matrix.
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 building Smoothed Aggregation prolongators.
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.
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
Interface to Zoltan library.
Namespace for MueLu classes and methods.
@ Debug
Print additional debugging information.
@ Runtime1
Description of what is happening (more verbose).