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_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
94namespace 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
#define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory)
An factory which assigns each aggregate a quality estimate. Originally developed by Napov and Notay i...
AmalgamationFactory_kokkos for subblocks of strided map based amalgamation data.
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...
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 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.
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.
Interface to Zoltan library.
Namespace for MueLu classes and methods.
@ Debug
Print additional debugging information.
@ Runtime1
Description of what is happening (more verbose)