MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_ParameterListInterpreter_def.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// MueLu: A package for multigrid based preconditioning
4//
5// Copyright 2012 NTESS and the MueLu contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef MUELU_PARAMETERLISTINTERPRETER_DEF_HPP
11#define MUELU_PARAMETERLISTINTERPRETER_DEF_HPP
12
13#include <Teuchos_XMLParameterListHelpers.hpp>
14
15#include <Xpetra_Matrix.hpp>
16#include <Xpetra_MatrixUtils.hpp>
17
18#include "MueLu_ConfigDefs.hpp"
19
21
22#include "MueLu_MasterList.hpp"
23#include "MueLu_Level.hpp"
24#include "MueLu_Hierarchy.hpp"
25#include "MueLu_FactoryManager.hpp"
26
27#include "MueLu_AggregationExportFactory.hpp"
28#include "MueLu_AggregateQualityEstimateFactory.hpp"
29#include "MueLu_AmalgamationFactory.hpp"
30#include "MueLu_BrickAggregationFactory.hpp"
31#include "MueLu_ClassicalMapFactory.hpp"
32#include "MueLu_ClassicalPFactory.hpp"
33#include "MueLu_CoalesceDropFactory.hpp"
34#include "MueLu_CoarseMapFactory.hpp"
35#include "MueLu_ConstraintFactory.hpp"
36#include "MueLu_CoordinatesTransferFactory.hpp"
37#include "MueLu_DirectSolver.hpp"
38#include "MueLu_EminPFactory.hpp"
39#include "MueLu_Exceptions.hpp"
40#include "MueLu_FacadeClassFactory.hpp"
41#include "MueLu_FactoryFactory.hpp"
42#include "MueLu_FilteredAFactory.hpp"
43#include "MueLu_GenericRFactory.hpp"
44#include "MueLu_InitialBlockNumberFactory.hpp"
45#include "MueLu_LineDetectionFactory.hpp"
46#include "MueLu_LocalOrdinalTransferFactory.hpp"
47#include "MueLu_MatrixAnalysisFactory.hpp"
48#include "MueLu_MultiVectorTransferFactory.hpp"
49#include "MueLu_NotayAggregationFactory.hpp"
50#include "MueLu_NullspaceFactory.hpp"
51#include "MueLu_PatternFactory.hpp"
52#include "MueLu_ReplicatePFactory.hpp"
53#include "MueLu_CombinePFactory.hpp"
54#include "MueLu_PgPFactory.hpp"
55#include "MueLu_RAPFactory.hpp"
56#include "MueLu_RAPShiftFactory.hpp"
57#include "MueLu_RebalanceAcFactory.hpp"
58#include "MueLu_RebalanceTransferFactory.hpp"
59#include "MueLu_RepartitionFactory.hpp"
60#include "MueLu_RepartitionHeuristicFactory.hpp"
61#include "MueLu_ReitzingerPFactory.hpp"
62#include "MueLu_SaPFactory.hpp"
63#include "MueLu_ScaledNullspaceFactory.hpp"
64#include "MueLu_SemiCoarsenPFactory.hpp"
65#include "MueLu_SmootherFactory.hpp"
66#include "MueLu_SmooVecCoalesceDropFactory.hpp"
67#include "MueLu_TentativePFactory.hpp"
68#include "MueLu_TogglePFactory.hpp"
69#include "MueLu_ToggleCoordinatesTransferFactory.hpp"
70#include "MueLu_TransPFactory.hpp"
71#include "MueLu_UncoupledAggregationFactory.hpp"
72#include "MueLu_ZoltanInterface.hpp"
73#include "MueLu_Zoltan2Interface.hpp"
74#include "MueLu_NodePartitionInterface.hpp"
75#include "MueLu_LowPrecisionFactory.hpp"
76
77#include "MueLu_CoalesceDropFactory_kokkos.hpp"
78#include "MueLu_SemiCoarsenPFactory_kokkos.hpp"
79#include "MueLu_TentativePFactory_kokkos.hpp"
80
81#ifdef HAVE_MUELU_MATLAB
82#include "../matlab/src/MueLu_MatlabSmoother_decl.hpp"
83#include "../matlab/src/MueLu_MatlabSmoother_def.hpp"
84#include "../matlab/src/MueLu_TwoLevelMatlabFactory_decl.hpp"
85#include "../matlab/src/MueLu_TwoLevelMatlabFactory_def.hpp"
86#include "../matlab/src/MueLu_SingleLevelMatlabFactory_decl.hpp"
87#include "../matlab/src/MueLu_SingleLevelMatlabFactory_def.hpp"
88#endif
89
90#ifdef HAVE_MUELU_INTREPID2
91#include "MueLu_IntrepidPCoarsenFactory.hpp"
92#endif
93
94#include <unordered_set>
95
96namespace MueLu {
97
98template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
99ParameterListInterpreter<Scalar, LocalOrdinal, GlobalOrdinal, Node>::ParameterListInterpreter(ParameterList& paramList, Teuchos::RCP<const Teuchos::Comm<int> > comm, Teuchos::RCP<FactoryFactory> factFact, Teuchos::RCP<FacadeClassFactory> facadeFact)
100 : factFact_(factFact) {
101 RCP<Teuchos::TimeMonitor> tM = rcp(new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(std::string("MueLu: ParameterListInterpreter (ParameterList)"))));
102 if (facadeFact == Teuchos::null)
103 facadeFact_ = Teuchos::rcp(new FacadeClassFactory());
104 else
105 facadeFact_ = facadeFact;
106
107 if (paramList.isParameter("xml parameter file")) {
108 std::string filename = paramList.get("xml parameter file", "");
109 if (filename.length() != 0) {
110 TEUCHOS_TEST_FOR_EXCEPTION(comm.is_null(), Exceptions::RuntimeError, "xml parameter file requires a valid comm");
111
112 ParameterList paramList2 = paramList;
113 Teuchos::updateParametersFromXmlFileAndBroadcast(filename, Teuchos::Ptr<Teuchos::ParameterList>(&paramList2), *comm);
114 SetParameterList(paramList2);
115
116 } else {
117 SetParameterList(paramList);
118 }
119
120 } else {
121 SetParameterList(paramList);
122 }
123}
124
125template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
126ParameterListInterpreter<Scalar, LocalOrdinal, GlobalOrdinal, Node>::ParameterListInterpreter(const std::string& xmlFileName, const Teuchos::Comm<int>& comm, Teuchos::RCP<FactoryFactory> factFact, Teuchos::RCP<FacadeClassFactory> facadeFact)
127 : factFact_(factFact) {
128 RCP<Teuchos::TimeMonitor> tM = rcp(new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(std::string("MueLu: ParameterListInterpreter (XML)"))));
129 if (facadeFact == Teuchos::null)
130 facadeFact_ = Teuchos::rcp(new FacadeClassFactory());
131 else
132 facadeFact_ = facadeFact;
133
134 ParameterList paramList;
135 Teuchos::updateParametersFromXmlFileAndBroadcast(xmlFileName, Teuchos::Ptr<ParameterList>(&paramList), comm);
136 SetParameterList(paramList);
137}
138
139template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
141
142template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
146 scalingFactor_ = Teuchos::ScalarTraits<double>::one();
147 blockSize_ = 1;
148 dofOffset_ = 0;
149
150 if (paramList.isSublist("Hierarchy")) {
151 SetFactoryParameterList(paramList);
152
153 } else if (paramList.isParameter("MueLu preconditioner") == true) {
154 this->GetOStream(Runtime0) << "Use facade class: " << paramList.get<std::string>("MueLu preconditioner") << std::endl;
155 Teuchos::RCP<ParameterList> pp = facadeFact_->SetParameterList(paramList);
157
158 } else {
159 // The validator doesn't work correctly for non-serializable data (Hint: template parameters), so strip it out
160 ParameterList serialList, nonSerialList;
161
162 ExtractNonSerializableData(paramList, serialList, nonSerialList);
163 Validate(serialList);
164 SetEasyParameterList(paramList);
165 }
166}
167
168// =====================================================================================================
169// ====================================== EASY interpreter =============================================
170// =====================================================================================================
172static inline bool areSame(const ParameterList& list1, const ParameterList& list2);
173
174// Get value from one of the lists, or set it to default
175// Use case: check for a parameter value in a level-specific sublist, then in a root level list;
176// if it is absent from both, set it to default
177#define MUELU_SET_VAR_2LIST(paramList, defaultList, paramName, paramType, varName) \
178 paramType varName; \
179 if (paramList.isParameter(paramName)) \
180 varName = paramList.get<paramType>(paramName); \
181 else if (defaultList.isParameter(paramName)) \
182 varName = defaultList.get<paramType>(paramName); \
183 else \
184 varName = MasterList::getDefault<paramType>(paramName);
185
186#define MUELU_TEST_AND_SET_VAR(paramList, paramName, paramType, varName) \
187 (paramList.isParameter(paramName) ? varName = paramList.get<paramType>(paramName), true : false)
188
189// Set parameter in a list if it is present in any of two lists
190// User case: set factory specific parameter, first checking for a level-specific value, then cheking root level value
191#define MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, paramName, paramType, listWrite) \
192 try { \
193 if (paramList.isParameter(paramName)) \
194 listWrite.set(paramName, paramList.get<paramType>(paramName)); \
195 else if (defaultList.isParameter(paramName)) \
196 listWrite.set(paramName, defaultList.get<paramType>(paramName)); \
197 } catch (Teuchos::Exceptions::InvalidParameterType&) { \
198 TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(true, Teuchos::Exceptions::InvalidParameterType, \
199 "Error: parameter \"" << paramName << "\" must be of type " << Teuchos::TypeNameTraits<paramType>::name()); \
200 }
201
202#define MUELU_TEST_PARAM_2LIST(paramList, defaultList, paramName, paramType, cmpValue) \
203 (cmpValue == (paramList.isParameter(paramName) ? paramList.get<paramType>(paramName) : (defaultList.isParameter(paramName) ? defaultList.get<paramType>(paramName) : MasterList::getDefault<paramType>(paramName))))
204
205#define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory) \
206 RCP<Factory> varName; \
207 if (!useKokkos_) \
208 varName = rcp(new oldFactory()); \
209 else \
210 varName = rcp(new newFactory());
211#define MUELU_KOKKOS_FACTORY_NO_DECL(varName, oldFactory, newFactory) \
212 if (!useKokkos_) \
213 varName = rcp(new oldFactory()); \
214 else \
215 varName = rcp(new newFactory());
216
217template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
219 SetEasyParameterList(const ParameterList& constParamList) {
220 ParameterList paramList;
221
222 MUELU_SET_VAR_2LIST(constParamList, constParamList, "problem: type", std::string, problemType);
223 if (problemType != "unknown") {
224 paramList = *MasterList::GetProblemSpecificList(problemType);
225 paramList.setParameters(constParamList);
226 } else {
227 // Create a non const copy of the parameter list
228 // Working with a modifiable list is much much easier than with original one
229 paramList = constParamList;
230 }
231
232 // Check for Kokkos
233 useKokkos_ = !Node::is_serial;
234 (void)MUELU_TEST_AND_SET_VAR(paramList, "use kokkos refactor", bool, useKokkos_);
235
236 // Check for timer synchronization
237 MUELU_SET_VAR_2LIST(paramList, paramList, "synchronize factory timers", bool, syncTimers);
238 if (syncTimers)
240
241 // Translate cycle type parameter
242 if (paramList.isParameter("cycle type")) {
243 std::map<std::string, CycleType> cycleMap;
244 cycleMap["V"] = VCYCLE;
245 cycleMap["W"] = WCYCLE;
246
247 auto cycleType = paramList.get<std::string>("cycle type");
248 TEUCHOS_TEST_FOR_EXCEPTION(cycleMap.count(cycleType) == 0, Exceptions::RuntimeError,
249 "Invalid cycle type: \"" << cycleType << "\"");
250 Cycle_ = cycleMap[cycleType];
251 }
252
253 if (paramList.isParameter("W cycle start level")) {
254 WCycleStartLevel_ = paramList.get<int>("W cycle start level");
255 }
256
257 if (paramList.isParameter("coarse grid correction scaling factor"))
258 scalingFactor_ = paramList.get<double>("coarse grid correction scaling factor");
259
260 this->maxCoarseSize_ = paramList.get<int>("coarse: max size", MasterList::getDefault<int>("coarse: max size"));
261 this->numDesiredLevel_ = paramList.get<int>("max levels", MasterList::getDefault<int>("max levels"));
262 blockSize_ = paramList.get<int>("number of equations", MasterList::getDefault<int>("number of equations"));
263
264 (void)MUELU_TEST_AND_SET_VAR(paramList, "debug: graph level", int, this->graphOutputLevel_);
265
266 // Generic data keeping (this keeps the data on all levels)
267 if (paramList.isParameter("keep data"))
268 this->dataToKeep_ = Teuchos::getArrayFromStringParameter<std::string>(paramList, "keep data");
269
270 // Export level data
271 if (paramList.isSublist("export data")) {
272 ParameterList printList = paramList.sublist("export data");
273
274 // Vectors, aggregates and other things that need special handling
275 if (printList.isParameter("Nullspace"))
276 this->nullspaceToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "Nullspace");
277 if (printList.isParameter("Coordinates"))
278 this->coordinatesToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "Coordinates");
279 if (printList.isParameter("Material"))
280 this->materialToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "Material");
281 if (printList.isParameter("Aggregates"))
282 this->aggregatesToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "Aggregates");
283 if (printList.isParameter("pcoarsen: element to node map"))
284 this->elementToNodeMapsToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "pcoarsen: element to node map");
285
286 // If we asked for an arbitrary matrix to be printed, we do that here
287 for (auto iter = printList.begin(); iter != printList.end(); iter++) {
288 const std::string& name = printList.name(iter);
289 // Ignore the special cases
290 if (name == "Nullspace" || name == "Coordinates" || name == "Material" || name == "Aggregates" || name == "pcoarsen: element to node map")
291 continue;
292
293 this->matricesToPrint_[name] = Teuchos::getArrayFromStringParameter<int>(printList, name);
294 }
295 }
296
297 // Set verbosity parameter
299 {
300 MUELU_SET_VAR_2LIST(paramList, paramList, "verbosity", std::string, verbosityLevel);
301 this->verbosity_ = toVerbLevel(verbosityLevel);
303 }
304
305 MUELU_SET_VAR_2LIST(paramList, paramList, "output filename", std::string, outputFilename);
306 if (outputFilename != "")
308
309 // Detect if we need to transfer coordinates to coarse levels. We do that iff
310 // - we use "distance laplacian" dropping on some level, or
311 // - we use a repartitioner on some level that needs coordinates
312 // - we use brick aggregation
313 // - we use Ifpack2 line partitioner
314 // This is not ideal, as we may have "repartition: enable" turned on by default
315 // and not present in the list, but it is better than nothing.
316 useCoordinates_ = false;
317 useBlockNumber_ = false;
318 if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: drop scheme", std::string, "distance laplacian") ||
319 MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: type", std::string, "brick") ||
320 MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: export visualization data", bool, true)) {
321 useCoordinates_ = true;
322 } else if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: drop scheme", std::string, "block diagonal distance laplacian")) {
323 useCoordinates_ = true;
324 useBlockNumber_ = true;
325 } else if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: drop scheme", std::string, "block diagonal") ||
326 MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: drop scheme", std::string, "block diagonal classical") ||
327 MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: drop scheme", std::string, "block diagonal signed classical") ||
328 MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: drop scheme", std::string, "block diagonal colored signed classical") ||
329 MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: drop scheme", std::string, "signed classical")) {
330 useBlockNumber_ = true;
331 } else if (paramList.isSublist("smoother: params")) {
332 const auto smooParamList = paramList.sublist("smoother: params");
333 if (smooParamList.isParameter("partitioner: type") &&
334 (smooParamList.get<std::string>("partitioner: type") == "line")) {
335 useCoordinates_ = true;
336 }
337 } else {
338 for (int levelID = 0; levelID < this->numDesiredLevel_; levelID++) {
339 std::string levelStr = "level " + toString(levelID);
340
341 if (paramList.isSublist(levelStr)) {
342 const ParameterList& levelList = paramList.sublist(levelStr);
343
344 if (MUELU_TEST_PARAM_2LIST(levelList, paramList, "aggregation: drop scheme", std::string, "distance laplacian") ||
345 MUELU_TEST_PARAM_2LIST(levelList, paramList, "aggregation: type", std::string, "brick") ||
346 MUELU_TEST_PARAM_2LIST(levelList, paramList, "aggregation: export visualization data", bool, true)) {
347 useCoordinates_ = true;
348 } else if (MUELU_TEST_PARAM_2LIST(levelList, paramList, "aggregation: drop scheme", std::string, "block diagonal distance laplacian")) {
349 useCoordinates_ = true;
350 useBlockNumber_ = true;
351 } else if (MUELU_TEST_PARAM_2LIST(levelList, paramList, "aggregation: drop scheme", std::string, "block diagonal") ||
352 MUELU_TEST_PARAM_2LIST(levelList, paramList, "aggregation: drop scheme", std::string, "block diagonal classical") ||
353 MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: drop scheme", std::string, "block diagonal signed classical") ||
354 MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: drop scheme", std::string, "block diagonal colored signed classical") ||
355 MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: drop scheme", std::string, "signed classical")) {
356 useBlockNumber_ = true;
357 }
358 }
359 }
360 }
361
362 useMaterial_ = false;
363 if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: distance laplacian metric", std::string, "material")) {
364 useMaterial_ = true;
365 }
366
367 if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "repartition: enable", bool, true)) {
368 // We don't need coordinates if we're doing the in-place restriction
369 if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "repartition: use subcommunicators", bool, true) &&
370 MUELU_TEST_PARAM_2LIST(paramList, paramList, "repartition: use subcommunicators in place", bool, true)) {
371 // do nothing --- these don't need coordinates
372 } else if (!paramList.isSublist("repartition: params")) {
373 useCoordinates_ = true;
374 } else {
375 const ParameterList& repParams = paramList.sublist("repartition: params");
376 if (repParams.isType<std::string>("algorithm")) {
377 const std::string algo = repParams.get<std::string>("algorithm");
378 if (algo == "multijagged" || algo == "rcb") {
379 useCoordinates_ = true;
380 }
381 } else {
382 useCoordinates_ = true;
383 }
384 }
385 }
386 for (int levelID = 0; levelID < this->numDesiredLevel_; levelID++) {
387 std::string levelStr = "level " + toString(levelID);
388
389 if (paramList.isSublist(levelStr)) {
390 const ParameterList& levelList = paramList.sublist(levelStr);
391
392 if (MUELU_TEST_PARAM_2LIST(levelList, paramList, "repartition: enable", bool, true)) {
393 if (!levelList.isSublist("repartition: params")) {
394 useCoordinates_ = true;
395 break;
396 } else {
397 const ParameterList& repParams = levelList.sublist("repartition: params");
398 if (repParams.isType<std::string>("algorithm")) {
399 const std::string algo = repParams.get<std::string>("algorithm");
400 if (algo == "multijagged" || algo == "rcb") {
401 useCoordinates_ = true;
402 break;
403 }
404 } else {
405 useCoordinates_ = true;
406 break;
407 }
408 }
409 }
410 }
411 }
412
413 // Detect if we do implicit P and R rebalance
414 changedPRrebalance_ = false;
416 if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "repartition: enable", bool, true)) {
417 changedPRrebalance_ = MUELU_TEST_AND_SET_VAR(paramList, "repartition: rebalance P and R", bool, this->doPRrebalance_);
418 changedPRViaCopyrebalance_ = MUELU_TEST_AND_SET_VAR(paramList, "repartition: explicit via new copy rebalance P and R", bool, this->doPRViaCopyrebalance_);
419 }
420
421 // Detect if we use implicit transpose
422 changedImplicitTranspose_ = MUELU_TEST_AND_SET_VAR(paramList, "transpose: use implicit", bool, this->implicitTranspose_);
423
424 // Detect if we use fuse prolongation and update
425 (void)MUELU_TEST_AND_SET_VAR(paramList, "fuse prolongation and update", bool, this->fuseProlongationAndUpdate_);
426
427 // Detect if we suppress the dimension check of the user-given nullspace
428 (void)MUELU_TEST_AND_SET_VAR(paramList, "nullspace: suppress dimension check", bool, this->suppressNullspaceDimensionCheck_);
429
430 if (paramList.isSublist("matvec params"))
431 this->matvecParams_ = Teuchos::parameterList(paramList.sublist("matvec params"));
432
433 // Create default manager
434 // FIXME: should it be here, or higher up
435 RCP<FactoryManager> defaultManager = rcp(new FactoryManager());
436 defaultManager->SetVerbLevel(this->verbosity_);
437 defaultManager->SetKokkosRefactor(useKokkos_);
438
439 // We will ignore keeps0
440 std::vector<keep_pair> keeps0;
441 UpdateFactoryManager(paramList, ParameterList(), *defaultManager, 0 /*levelID*/, keeps0);
442
443 // std::cout<<"*** Default Manager ***"<<std::endl;
444 // defaultManager->Print();
445
446 // Create level specific factory managers
447 for (int levelID = 0; levelID < this->numDesiredLevel_; levelID++) {
448 // Note, that originally if there were no level specific parameters, we
449 // simply copied the defaultManager However, with the introduction of
450 // levelID to UpdateFactoryManager (required for reuse), we can no longer
451 // guarantee that the kept variables are the same for each level even if
452 // dependency structure does not change.
453 RCP<FactoryManager> levelManager = rcp(new FactoryManager(*defaultManager));
454 levelManager->SetVerbLevel(defaultManager->GetVerbLevel());
455
456 std::vector<keep_pair> keeps;
457 if (paramList.isSublist("level " + toString(levelID))) {
458 // We do this so the parameters on the level get flagged correctly as "used"
459 ParameterList& levelList = paramList.sublist("level " + toString(levelID), true /*mustAlreadyExist*/);
460 UpdateFactoryManager(levelList, paramList, *levelManager, levelID, keeps);
461
462 } else {
463 ParameterList levelList;
464 UpdateFactoryManager(levelList, paramList, *levelManager, levelID, keeps);
465 }
466
467 this->keep_[levelID] = keeps;
468 this->AddFactoryManager(levelID, 1, levelManager);
469
470 // std::cout<<"*** Level "<<levelID<<" Manager ***"<<std::endl;
471 // levelManager->Print();
472 }
473
474 // FIXME: parameters passed to packages, like Ifpack2, are not touched by us, resulting in "[unused]" flag
475 // being displayed. On the other hand, we don't want to simply iterate through them touching. I don't know
476 // what a good solution looks like
477 if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "print initial parameters", bool, true))
478 this->GetOStream(static_cast<MsgType>(Runtime1), 0) << paramList << std::endl;
479
480 if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "print unused parameters", bool, true)) {
481 // Check unused parameters
482 ParameterList unusedParamList;
483
484 // Check for unused parameters that aren't lists
485 for (ParameterList::ConstIterator it = paramList.begin(); it != paramList.end(); it++) {
486 const ParameterEntry& entry = paramList.entry(it);
487
488 if (!entry.isList() && !entry.isUsed())
489 unusedParamList.setEntry(paramList.name(it), entry);
490 }
491
492 // Check for unused parameters in level-specific sublists
493 for (int levelID = 0; levelID < this->numDesiredLevel_; levelID++) {
494 std::string levelStr = "level " + toString(levelID);
495
496 if (paramList.isSublist(levelStr)) {
497 const ParameterList& levelList = paramList.sublist(levelStr);
498
499 for (ParameterList::ConstIterator itr = levelList.begin(); itr != levelList.end(); ++itr) {
500 const ParameterEntry& entry = levelList.entry(itr);
501
502 if (!entry.isList() && !entry.isUsed())
503 unusedParamList.sublist(levelStr).setEntry(levelList.name(itr), entry);
504 }
505 }
506 }
507
508 if (unusedParamList.numParams() > 0) {
509 std::ostringstream unusedParamsStream;
510 int indent = 4;
511 unusedParamList.print(unusedParamsStream, indent);
512
513 this->GetOStream(Warnings1) << "The following parameters were not used:\n"
514 << unusedParamsStream.str() << std::endl;
515 }
516 }
517
519}
520
521// =====================================================================================================
522// ==================================== UpdateFactoryManager ===========================================
523// =====================================================================================================
524template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
526 UpdateFactoryManager(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
527 int levelID, std::vector<keep_pair>& keeps) const {
528 // NOTE: Factory::SetParameterList must be called prior to Factory::SetFactory, as
529 // SetParameterList sets default values for non mentioned parameters, including factories
530
531 using strings = std::unordered_set<std::string>;
532
533 // shortcut
534 if (paramList.numParams() == 0 && defaultList.numParams() > 0)
535 paramList = ParameterList(defaultList);
536
537 MUELU_SET_VAR_2LIST(paramList, defaultList, "reuse: type", std::string, reuseType);
538 TEUCHOS_TEST_FOR_EXCEPTION(strings({"none", "tP", "RP", "emin", "RAP", "full", "S"}).count(reuseType) == 0,
539 Exceptions::RuntimeError, "Unknown \"reuse: type\" value: \"" << reuseType << "\". Please consult User's Guide.");
540
541 MUELU_SET_VAR_2LIST(paramList, defaultList, "multigrid algorithm", std::string, multigridAlgo);
542 TEUCHOS_TEST_FOR_EXCEPTION(strings({"unsmoothed", "sa", "pg", "emin", "matlab", "pcoarsen", "classical", "smoothed reitzinger", "unsmoothed reitzinger", "replicate", "combine"}).count(multigridAlgo) == 0,
543 Exceptions::RuntimeError, "Unknown \"multigrid algorithm\" value: \"" << multigridAlgo << "\". Please consult User's Guide.");
544#ifndef HAVE_MUELU_MATLAB
545 TEUCHOS_TEST_FOR_EXCEPTION(multigridAlgo == "matlab", Exceptions::RuntimeError,
546 "Cannot use matlab for multigrid algorithm - MueLu was not configured with MATLAB support.");
547#endif
548#ifndef HAVE_MUELU_INTREPID2
549 TEUCHOS_TEST_FOR_EXCEPTION(multigridAlgo == "pcoarsen", Exceptions::RuntimeError,
550 "Cannot use IntrepidPCoarsen prolongator factory - MueLu was not configured with Intrepid support.");
551#endif
552
553 // Only some combinations of reuse and multigrid algorithms are tested, all
554 // other are considered invalid at the moment
555 if (reuseType == "none" || reuseType == "S" || reuseType == "RP" || reuseType == "RAP") {
556 // This works for all kinds of multigrid algorithms
557
558 } else if (reuseType == "tP" && (multigridAlgo != "sa" && multigridAlgo != "unsmoothed")) {
559 reuseType = "none";
560 this->GetOStream(Warnings0) << "Ignoring \"tP\" reuse option as it is only compatible with \"sa\", "
561 "or \"unsmoothed\" multigrid algorithms"
562 << std::endl;
563
564 } else if (reuseType == "emin" && multigridAlgo != "emin") {
565 reuseType = "none";
566 this->GetOStream(Warnings0) << "Ignoring \"emin\" reuse option it is only compatible with "
567 "\"emin\" multigrid algorithm"
568 << std::endl;
569 }
570
571 // == Non-serializable data ===
572 // Check both the parameter and the type
573 bool have_userP = false;
574 if (paramList.isParameter("P") && !paramList.get<RCP<Matrix> >("P").is_null())
575 have_userP = true;
576
577 // === Coarse solver ===
578 UpdateFactoryManager_CoarseSolvers(paramList, defaultList, manager, levelID, keeps);
579
580 // == Smoothers ==
581 UpdateFactoryManager_Smoothers(paramList, defaultList, manager, levelID, keeps);
582
583 // === BlockNumber ===
584 if (levelID == 0)
585 UpdateFactoryManager_BlockNumber(paramList, defaultList, manager, levelID, keeps);
586
587 // === Aggregation ===
588 if (multigridAlgo == "unsmoothed reitzinger" || multigridAlgo == "smoothed reitzinger")
589 UpdateFactoryManager_Reitzinger(paramList, defaultList, manager, levelID, keeps);
590 else
591 UpdateFactoryManager_Aggregation_TentativeP(paramList, defaultList, manager, levelID, keeps);
592
593 // === Nullspace ===
594 RCP<Factory> nullSpaceFactory; // Cache thcAN is guy for the combination of semi-coarsening & repartitioning
595 UpdateFactoryManager_Nullspace(paramList, defaultList, manager, levelID, keeps, nullSpaceFactory);
596
597 // === Prolongation ===
598 // NOTE: None of the UpdateFactoryManager routines called here check the
599 // multigridAlgo. This is intentional, to allow for reuse of components
600 // underneath. Thus, the multigridAlgo was checked in the beginning of the
601 // function.
602 if (have_userP) {
603 // User prolongator
604 manager.SetFactory("P", NoFactory::getRCP());
605
606 } else if (multigridAlgo == "unsmoothed" || multigridAlgo == "unsmoothed reitzinger") {
607 // Unsmoothed aggregation
608 manager.SetFactory("P", manager.GetFactory("Ptent"));
609
610 } else if (multigridAlgo == "classical") {
611 // Classical AMG
612 manager.SetFactory("P", manager.GetFactory("Ptent"));
613
614 } else if (multigridAlgo == "sa" || multigridAlgo == "smoothed reitzinger") {
615 // Smoothed aggregation
616 UpdateFactoryManager_SA(paramList, defaultList, manager, levelID, keeps);
617
618 } else if (multigridAlgo == "emin") {
619 // Energy minimization
620 UpdateFactoryManager_Emin(paramList, defaultList, manager, levelID, keeps);
621
622 } else if (multigridAlgo == "replicate") {
623 UpdateFactoryManager_Replicate(paramList, defaultList, manager, levelID, keeps);
624
625 } else if (multigridAlgo == "combine") {
626 UpdateFactoryManager_Combine(paramList, defaultList, manager, levelID, keeps);
627
628 } else if (multigridAlgo == "pg") {
629 // Petrov-Galerkin
630 UpdateFactoryManager_PG(paramList, defaultList, manager, levelID, keeps);
631
632 } else if (multigridAlgo == "matlab") {
633 // Matlab Coarsneing
634 UpdateFactoryManager_Matlab(paramList, defaultList, manager, levelID, keeps);
635
636 } else if (multigridAlgo == "pcoarsen") {
637 // P-Coarsening
638 UpdateFactoryManager_PCoarsen(paramList, defaultList, manager, levelID, keeps);
639 }
640
641 // === Semi-coarsening ===
642 UpdateFactoryManager_SemiCoarsen(paramList, defaultList, manager, levelID, keeps);
643
644 // === Restriction ===
645 UpdateFactoryManager_Restriction(paramList, defaultList, manager, levelID, keeps);
646
647 // === RAP ===
648 UpdateFactoryManager_RAP(paramList, defaultList, manager, levelID, keeps);
649
650 // == BlockNumber Transfer ==
651 UpdateFactoryManager_LocalOrdinalTransfer("BlockNumber", multigridAlgo, paramList, defaultList, manager, levelID, keeps);
652
653 // === Coordinates ===
654 UpdateFactoryManager_Coordinates(paramList, defaultList, manager, levelID, keeps);
655
656 // === Material ===
657 UpdateFactoryManager_Material(paramList, defaultList, manager, levelID, keeps);
658
659 // === Pre-Repartition Keeps for Reuse ===
660 if ((reuseType == "RP" || reuseType == "RAP" || reuseType == "full") && levelID)
661 keeps.push_back(keep_pair("Nullspace", manager.GetFactory("Nullspace").get()));
662
663 if (reuseType == "RP" && levelID) {
664 keeps.push_back(keep_pair("P", manager.GetFactory("P").get()));
665 if (!this->implicitTranspose_)
666 keeps.push_back(keep_pair("R", manager.GetFactory("R").get()));
667 }
668 if ((reuseType == "tP" || reuseType == "RP" || reuseType == "emin") && useCoordinates_ && levelID)
669 keeps.push_back(keep_pair("Coordinates", manager.GetFactory("Coordinates").get()));
670
671 // === Repartitioning ===
672 UpdateFactoryManager_Repartition(paramList, defaultList, manager, levelID, keeps, nullSpaceFactory);
673
674 // === Lower precision transfers ===
675 UpdateFactoryManager_LowPrecision(paramList, defaultList, manager, levelID, keeps);
676
677 // === Final Keeps for Reuse ===
678 if ((reuseType == "RAP" || reuseType == "full") && levelID) {
679 keeps.push_back(keep_pair("P", manager.GetFactory("P").get()));
680 if (!this->implicitTranspose_)
681 keeps.push_back(keep_pair("R", manager.GetFactory("R").get()));
682 keeps.push_back(keep_pair("A", manager.GetFactory("A").get()));
683 }
684
685 // In case you ever want to inspect the FactoryManager as it is generated for each level
686 /*std::cout<<"*** Factory Manager on level "<<levelID<<" ***"<<std::endl;
687 manager.Print(); */
688}
689
690// =====================================================================================================
691// ========================================= Smoothers =================================================
692// =====================================================================================================
693template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
695 UpdateFactoryManager_Smoothers(ParameterList& paramList, const ParameterList& defaultList,
696 FactoryManager& manager, int levelID, std::vector<keep_pair>& keeps) const {
697 MUELU_SET_VAR_2LIST(paramList, defaultList, "multigrid algorithm", std::string, multigridAlgo);
698 MUELU_SET_VAR_2LIST(paramList, defaultList, "reuse: type", std::string, reuseType);
699 bool useMaxAbsDiagonalScaling = false;
700 if (defaultList.isParameter("sa: use rowsumabs diagonal scaling"))
701 useMaxAbsDiagonalScaling = defaultList.get<bool>("sa: use rowsumabs diagonal scaling");
702
703 // === Smoothing ===
704 // FIXME: should custom smoother check default list too?
705 bool isCustomSmoother =
706 paramList.isParameter("smoother: pre or post") ||
707 paramList.isParameter("smoother: type") || paramList.isParameter("smoother: pre type") || paramList.isParameter("smoother: post type") ||
708 paramList.isSublist("smoother: params") || paramList.isSublist("smoother: pre params") || paramList.isSublist("smoother: post params") ||
709 paramList.isParameter("smoother: sweeps") || paramList.isParameter("smoother: pre sweeps") || paramList.isParameter("smoother: post sweeps") ||
710 paramList.isParameter("smoother: overlap") || paramList.isParameter("smoother: pre overlap") || paramList.isParameter("smoother: post overlap");
711
712 MUELU_SET_VAR_2LIST(paramList, defaultList, "smoother: pre or post", std::string, PreOrPost);
713 if (PreOrPost == "none") {
714 manager.SetFactory("Smoother", Teuchos::null);
715
716 } else if (isCustomSmoother) {
717 // FIXME: get default values from the factory
718 // NOTE: none of the smoothers at the moment use parameter validation framework, so we
719 // cannot get the default values from it.
720#define TEST_MUTUALLY_EXCLUSIVE(arg1, arg2) \
721 TEUCHOS_TEST_FOR_EXCEPTION(paramList.isParameter(#arg1) && paramList.isParameter(#arg2), \
722 Exceptions::InvalidArgument, "You cannot specify both \"" #arg1 "\" and \"" #arg2 "\"");
723#define TEST_MUTUALLY_EXCLUSIVE_S(arg1, arg2) \
724 TEUCHOS_TEST_FOR_EXCEPTION(paramList.isSublist(#arg1) && paramList.isSublist(#arg2), \
725 Exceptions::InvalidArgument, "You cannot specify both \"" #arg1 "\" and \"" #arg2 "\"");
726
727 TEST_MUTUALLY_EXCLUSIVE("smoother: type", "smoother: pre type");
728 TEST_MUTUALLY_EXCLUSIVE("smoother: type", "smoother: post type");
729 TEST_MUTUALLY_EXCLUSIVE("smoother: sweeps", "smoother: pre sweeps");
730 TEST_MUTUALLY_EXCLUSIVE("smoother: sweeps", "smoother: post sweeps");
731 TEST_MUTUALLY_EXCLUSIVE("smoother: overlap", "smoother: pre overlap");
732 TEST_MUTUALLY_EXCLUSIVE("smoother: overlap", "smoother: post overlap");
733 TEST_MUTUALLY_EXCLUSIVE_S("smoother: params", "smoother: pre params");
734 TEST_MUTUALLY_EXCLUSIVE_S("smoother: params", "smoother: post params");
735 TEUCHOS_TEST_FOR_EXCEPTION(PreOrPost == "both" && (paramList.isParameter("smoother: pre type") != paramList.isParameter("smoother: post type")),
736 Exceptions::InvalidArgument, "You must specify both \"smoother: pre type\" and \"smoother: post type\"");
737
738 // Default values
739 int overlap = 0;
740 ParameterList defaultSmootherParams;
741 defaultSmootherParams.set("relaxation: type", "Symmetric Gauss-Seidel");
742 defaultSmootherParams.set("relaxation: sweeps", Teuchos::OrdinalTraits<LO>::one());
743 defaultSmootherParams.set("relaxation: damping factor", Teuchos::ScalarTraits<Scalar>::one());
744
745 RCP<SmootherFactory> preSmoother = Teuchos::null, postSmoother = Teuchos::null;
746 std::string preSmootherType, postSmootherType;
747 ParameterList preSmootherParams, postSmootherParams;
748
749 if (paramList.isParameter("smoother: overlap"))
750 overlap = paramList.get<int>("smoother: overlap");
751
752 if (PreOrPost == "pre" || PreOrPost == "both") {
753 if (paramList.isParameter("smoother: pre type")) {
754 preSmootherType = paramList.get<std::string>("smoother: pre type");
755 } else {
756 MUELU_SET_VAR_2LIST(paramList, defaultList, "smoother: type", std::string, preSmootherTypeTmp);
757 preSmootherType = preSmootherTypeTmp;
758 }
759 if (paramList.isParameter("smoother: pre overlap"))
760 overlap = paramList.get<int>("smoother: pre overlap");
761
762 if (paramList.isSublist("smoother: pre params"))
763 preSmootherParams = paramList.sublist("smoother: pre params");
764 else if (paramList.isSublist("smoother: params"))
765 preSmootherParams = paramList.sublist("smoother: params");
766 else if (defaultList.isSublist("smoother: params"))
767 preSmootherParams = defaultList.sublist("smoother: params");
768 else if (preSmootherType == "RELAXATION")
769 preSmootherParams = defaultSmootherParams;
770
771 if (preSmootherType == "CHEBYSHEV" && useMaxAbsDiagonalScaling)
772 preSmootherParams.set("chebyshev: use rowsumabs diagonal scaling", true);
773
774#ifdef HAVE_MUELU_INTREPID2
775 // Propagate P-coarsening for Topo smoothing
776 if (multigridAlgo == "pcoarsen" && preSmootherType == "TOPOLOGICAL" &&
777 defaultList.isParameter("pcoarsen: schedule") && defaultList.isParameter("pcoarsen: element")) {
778 // P-Coarsening by schedule (new interface)
779 // NOTE: levelID represents the *coarse* level in this case
780 auto pcoarsen_schedule = Teuchos::getArrayFromStringParameter<int>(defaultList, "pcoarsen: schedule");
781 auto pcoarsen_element = defaultList.get<std::string>("pcoarsen: element");
782
783 if (levelID < (int)pcoarsen_schedule.size()) {
784 // Topo info for P-Coarsening
785 auto lo = pcoarsen_element + std::to_string(pcoarsen_schedule[levelID]);
786 preSmootherParams.set("pcoarsen: hi basis", lo);
787 }
788 }
789#endif
790
791#ifdef HAVE_MUELU_MATLAB
792 if (preSmootherType == "matlab")
793 preSmoother = rcp(new SmootherFactory(rcp(new MatlabSmoother(preSmootherParams))));
794 else
795#endif
796 preSmoother = rcp(new SmootherFactory(rcp(new TrilinosSmoother(preSmootherType, preSmootherParams, overlap))));
797 }
798
799 if (PreOrPost == "post" || PreOrPost == "both") {
800 if (paramList.isParameter("smoother: post type"))
801 postSmootherType = paramList.get<std::string>("smoother: post type");
802 else {
803 MUELU_SET_VAR_2LIST(paramList, defaultList, "smoother: type", std::string, postSmootherTypeTmp);
804 postSmootherType = postSmootherTypeTmp;
805 }
806
807 if (paramList.isSublist("smoother: post params"))
808 postSmootherParams = paramList.sublist("smoother: post params");
809 else if (paramList.isSublist("smoother: params"))
810 postSmootherParams = paramList.sublist("smoother: params");
811 else if (defaultList.isSublist("smoother: params"))
812 postSmootherParams = defaultList.sublist("smoother: params");
813 else if (postSmootherType == "RELAXATION")
814 postSmootherParams = defaultSmootherParams;
815 if (paramList.isParameter("smoother: post overlap"))
816 overlap = paramList.get<int>("smoother: post overlap");
817
818 if (postSmootherType == "CHEBYSHEV" && useMaxAbsDiagonalScaling)
819 postSmootherParams.set("chebyshev: use rowsumabs diagonal scaling", true);
820
821 if (postSmootherType == preSmootherType && areSame(preSmootherParams, postSmootherParams))
822 postSmoother = preSmoother;
823 else {
824#ifdef HAVE_MUELU_INTREPID2
825 // Propagate P-coarsening for Topo smoothing
826 if (multigridAlgo == "pcoarsen" && preSmootherType == "TOPOLOGICAL" &&
827 defaultList.isParameter("pcoarsen: schedule") && defaultList.isParameter("pcoarsen: element")) {
828 // P-Coarsening by schedule (new interface)
829 // NOTE: levelID represents the *coarse* level in this case
830 auto pcoarsen_schedule = Teuchos::getArrayFromStringParameter<int>(defaultList, "pcoarsen: schedule");
831 auto pcoarsen_element = defaultList.get<std::string>("pcoarsen: element");
832
833 if (levelID < (int)pcoarsen_schedule.size()) {
834 // Topo info for P-Coarsening
835 auto lo = pcoarsen_element + std::to_string(pcoarsen_schedule[levelID]);
836 postSmootherParams.set("pcoarsen: hi basis", lo);
837 }
838 }
839#endif
840
841#ifdef HAVE_MUELU_MATLAB
842 if (postSmootherType == "matlab")
843 postSmoother = rcp(new SmootherFactory(rcp(new MatlabSmoother(postSmootherParams))));
844 else
845#endif
846 postSmoother = rcp(new SmootherFactory(rcp(new TrilinosSmoother(postSmootherType, postSmootherParams, overlap))));
847 }
848 }
849
850 if (preSmoother == postSmoother)
851 manager.SetFactory("Smoother", preSmoother);
852 else {
853 manager.SetFactory("PreSmoother", preSmoother);
854 manager.SetFactory("PostSmoother", postSmoother);
855 }
856 }
857
858 // The first clause is not necessary, but it is here for clarity Smoothers
859 // are reused if smoother explicitly said to reuse them, or if any other
860 // reuse option is enabled
861 bool reuseSmoothers = (reuseType == "S" || reuseType != "none");
862 if (reuseSmoothers) {
863 auto preSmootherFactory = rcp_const_cast<Factory>(rcp_dynamic_cast<const Factory>(manager.GetFactory("PreSmoother")));
864
865 if (preSmootherFactory != Teuchos::null) {
866 ParameterList postSmootherFactoryParams;
867 postSmootherFactoryParams.set("keep smoother data", true);
868 preSmootherFactory->SetParameterList(postSmootherFactoryParams);
869
870 keeps.push_back(keep_pair("PreSmoother data", preSmootherFactory.get()));
871 }
872
873 auto postSmootherFactory = rcp_const_cast<Factory>(rcp_dynamic_cast<const Factory>(manager.GetFactory("PostSmoother")));
874 if (postSmootherFactory != Teuchos::null) {
875 ParameterList postSmootherFactoryParams;
876 postSmootherFactoryParams.set("keep smoother data", true);
877 postSmootherFactory->SetParameterList(postSmootherFactoryParams);
878
879 keeps.push_back(keep_pair("PostSmoother data", postSmootherFactory.get()));
880 }
881
882 auto coarseFactory = rcp_const_cast<Factory>(rcp_dynamic_cast<const Factory>(manager.GetFactory("CoarseSolver")));
883 if (coarseFactory != Teuchos::null) {
884 ParameterList coarseFactoryParams;
885 coarseFactoryParams.set("keep smoother data", true);
886 coarseFactory->SetParameterList(coarseFactoryParams);
887
888 keeps.push_back(keep_pair("PreSmoother data", coarseFactory.get()));
889 }
890 }
891
892 if ((reuseType == "RAP" && levelID) || (reuseType == "full")) {
893 // The difference between "RAP" and "full" is keeping smoothers. However,
894 // as in both cases we keep coarse matrices, we do not need to update
895 // coarse smoothers. On the other hand, if a user changes fine level
896 // matrix, "RAP" would update the fine level smoother, while "full" would
897 // not
898 keeps.push_back(keep_pair("PreSmoother", manager.GetFactory("PreSmoother").get()));
899 keeps.push_back(keep_pair("PostSmoother", manager.GetFactory("PostSmoother").get()));
900
901 // We do keep_pair("PreSmoother", manager.GetFactory("CoarseSolver").get())
902 // as the coarse solver factory is in fact a smoothing factory, so the
903 // only pieces of data it generates are PreSmoother and PostSmoother
904 keeps.push_back(keep_pair("PreSmoother", manager.GetFactory("CoarseSolver").get()));
905 }
906}
907
908// =====================================================================================================
909// ====================================== Coarse Solvers ===============================================
910// =====================================================================================================
911template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
913 UpdateFactoryManager_CoarseSolvers(ParameterList& paramList, const ParameterList& defaultList,
914 FactoryManager& manager, int /* levelID */, std::vector<keep_pair>& /* keeps */) const {
915 // FIXME: should custom coarse solver check default list too?
916 bool isCustomCoarseSolver =
917 paramList.isParameter("coarse: type") ||
918 paramList.isParameter("coarse: params");
919 if (MUELU_TEST_PARAM_2LIST(paramList, defaultList, "coarse: type", std::string, "none")) {
920 manager.SetFactory("CoarseSolver", Teuchos::null);
921
922 } else if (isCustomCoarseSolver) {
923 // FIXME: get default values from the factory
924 // NOTE: none of the smoothers at the moment use parameter validation framework, so we
925 // cannot get the default values from it.
926 MUELU_SET_VAR_2LIST(paramList, defaultList, "coarse: type", std::string, coarseType);
927
928 int overlap = 0;
929 if (paramList.isParameter("coarse: overlap"))
930 overlap = paramList.get<int>("coarse: overlap");
931
932 ParameterList coarseParams;
933 if (paramList.isSublist("coarse: params"))
934 coarseParams = paramList.sublist("coarse: params");
935 else if (defaultList.isSublist("coarse: params"))
936 coarseParams = defaultList.sublist("coarse: params");
937
938 using strings = std::unordered_set<std::string>;
939
940 RCP<SmootherPrototype> coarseSmoother;
941 // TODO: this is not a proper place to check. If we consider direct solver to be a special
942 // case of smoother, we would like to unify Amesos and Ifpack2 smoothers in src/Smoothers, and
943 // have a single factory responsible for those. Then, this check would belong there.
944 if (strings({"RELAXATION", "CHEBYSHEV", "ILUT", "ILU", "RILUK", "SCHWARZ", "Amesos",
945 "BLOCK RELAXATION", "BLOCK_RELAXATION", "BLOCKRELAXATION",
946 "SPARSE BLOCK RELAXATION", "SPARSE_BLOCK_RELAXATION", "SPARSEBLOCKRELAXATION",
947 "LINESMOOTHING_BANDEDRELAXATION", "LINESMOOTHING_BANDED_RELAXATION", "LINESMOOTHING_BANDED RELAXATION",
948 "LINESMOOTHING_TRIDIRELAXATION", "LINESMOOTHING_TRIDI_RELAXATION", "LINESMOOTHING_TRIDI RELAXATION",
949 "LINESMOOTHING_TRIDIAGONALRELAXATION", "LINESMOOTHING_TRIDIAGONAL_RELAXATION", "LINESMOOTHING_TRIDIAGONAL RELAXATION",
950 "TOPOLOGICAL", "FAST_ILU", "FAST_IC", "FAST_ILDL", "HIPTMAIR"})
951 .count(coarseType)) {
952 coarseSmoother = rcp(new TrilinosSmoother(coarseType, coarseParams, overlap));
953 } else {
954#ifdef HAVE_MUELU_MATLAB
955 if (coarseType == "matlab")
956 coarseSmoother = rcp(new MatlabSmoother(coarseParams));
957 else
958#endif
959 coarseSmoother = rcp(new DirectSolver(coarseType, coarseParams));
960 }
961
962 manager.SetFactory("CoarseSolver", rcp(new SmootherFactory(coarseSmoother)));
963 }
964}
965
966// =====================================================================================================
967// ========================================= TentativeP=================================================
968// =====================================================================================================
969template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
971 UpdateFactoryManager_Reitzinger(ParameterList& paramList, const ParameterList& defaultList,
972 FactoryManager& manager, int levelID, std::vector<keep_pair>& keeps) const {
973 ParameterList rParams;
974 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: enable", bool, rParams);
975 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: use subcommunicators", bool, rParams);
976 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "tentative: constant column sums", bool, rParams);
977 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "tentative: calculate qr", bool, rParams);
978
979 RCP<Factory> rFactory = rcp(new ReitzingerPFactory());
980 rFactory->SetParameterList(rParams);
981
982 // These are all going to be user provided, so NoFactory
983 rFactory->SetFactory("Pnodal", NoFactory::getRCP());
984 rFactory->SetFactory("NodeAggMatrix", NoFactory::getRCP());
985 // rFactory->SetFactory("NodeMatrix", NoFactory::getRCP());
986
987 if (levelID > 1)
988 rFactory->SetFactory("D0", this->GetFactoryManager(levelID - 1)->GetFactory("D0"));
989 else
990 rFactory->SetFactory("D0", NoFactory::getRCP());
991
992 manager.SetFactory("Ptent", rFactory);
993 manager.SetFactory("D0", rFactory);
994 manager.SetFactory("InPlaceMap", rFactory);
995}
996
997// =====================================================================================================
998// ========================================= TentativeP=================================================
999// =====================================================================================================
1000template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1002 UpdateFactoryManager_Aggregation_TentativeP(ParameterList& paramList, const ParameterList& defaultList,
1003 FactoryManager& manager, int levelID, std::vector<keep_pair>& keeps) const {
1004 using strings = std::unordered_set<std::string>;
1005
1006 MUELU_SET_VAR_2LIST(paramList, defaultList, "reuse: type", std::string, reuseType);
1007
1008 MUELU_SET_VAR_2LIST(paramList, defaultList, "aggregation: type", std::string, aggType);
1009 TEUCHOS_TEST_FOR_EXCEPTION(!strings({"uncoupled", "coupled", "brick", "matlab", "notay", "classical"}).count(aggType),
1010 Exceptions::RuntimeError, "Unknown aggregation algorithm: \"" << aggType << "\". Please consult User's Guide.");
1011
1012 // Only doing this for classical because otherwise, the gold tests get broken badly
1013 RCP<AmalgamationFactory> amalgFact;
1014 if (aggType == "classical") {
1015 amalgFact = rcp(new AmalgamationFactory());
1016 manager.SetFactory("UnAmalgamationInfo", amalgFact);
1017 }
1018
1019 // Aggregation graph
1020 RCP<Factory> dropFactory;
1021
1022 if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: drop scheme", std::string, "matlab")) {
1023#ifdef HAVE_MUELU_MATLAB
1024 dropFactory = rcp(new SingleLevelMatlabFactory());
1025 ParameterList socParams = paramList.sublist("strength-of-connection: params");
1026 dropFactory->SetParameterList(socParams);
1027#else
1028 throw std::runtime_error("Cannot use MATLAB evolutionary strength-of-connection - MueLu was not configured with MATLAB support.");
1029#endif
1030 } else if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: drop scheme", std::string, "unsupported vector smoothing")) {
1032 ParameterList dropParams;
1033 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: drop scheme", std::string, dropParams);
1034 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: block diagonal: interleaved blocksize", int, dropParams);
1035 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: number of random vectors", int, dropParams);
1036 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: number of times to pre or post smooth", int, dropParams);
1037 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: penalty parameters", Teuchos::Array<double>, dropParams);
1038 dropFactory->SetParameterList(dropParams);
1039 } else {
1041 ParameterList dropParams;
1042 if (!rcp_dynamic_cast<CoalesceDropFactory>(dropFactory).is_null())
1043 dropParams.set("lightweight wrap", true);
1044 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: drop scheme", std::string, dropParams);
1045 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: row sum drop tol", double, dropParams);
1046 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: block diagonal: interleaved blocksize", int, dropParams);
1047 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: drop tol", double, dropParams);
1048 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: use ml scaling of drop tol", bool, dropParams);
1049
1050 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: Dirichlet threshold", double, dropParams);
1051 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: greedy Dirichlet", bool, dropParams);
1052 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: distance laplacian algo", std::string, dropParams);
1053 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: distance laplacian metric", std::string, dropParams);
1054 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: classical algo", std::string, dropParams);
1055 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: distance laplacian directional weights", Teuchos::Array<double>, dropParams);
1056 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: coloring: localize color graph", bool, dropParams);
1057 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: dropping may create Dirichlet", bool, dropParams);
1058 if (useKokkos_) {
1059 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: use lumping", bool, dropParams);
1060 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: reuse graph", bool, dropParams);
1061 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: reuse eigenvalue", bool, dropParams);
1062 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: use root stencil", bool, dropParams);
1063 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: Dirichlet threshold", double, dropParams);
1064 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: use spread lumping", bool, dropParams);
1065 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: spread lumping diag dom growth factor", double, dropParams);
1066 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: spread lumping diag dom cap", double, dropParams);
1067 }
1068
1069 if (!amalgFact.is_null())
1070 dropFactory->SetFactory("UnAmalgamationInfo", manager.GetFactory("UnAmalgamationInfo"));
1071
1072 if (dropParams.isParameter("aggregation: drop scheme")) {
1073 std::string drop_scheme = dropParams.get<std::string>("aggregation: drop scheme");
1074 if (drop_scheme == "block diagonal colored signed classical")
1075 manager.SetFactory("Coloring Graph", dropFactory);
1076 if (drop_scheme.find("block diagonal") != std::string::npos || drop_scheme == "signed classical") {
1077 if (levelID > 0)
1078 dropFactory->SetFactory("BlockNumber", this->GetFactoryManager(levelID - 1)->GetFactory("BlockNumber"));
1079 else
1080 dropFactory->SetFactory("BlockNumber", manager.GetFactory("BlockNumber"));
1081 }
1082 }
1083
1084 dropFactory->SetParameterList(dropParams);
1085 }
1086 manager.SetFactory("Graph", dropFactory);
1087
1088// Aggregation scheme
1089#ifndef HAVE_MUELU_MATLAB
1090 if (aggType == "matlab")
1091 throw std::runtime_error("Cannot use MATLAB aggregation - MueLu was not configured with MATLAB support.");
1092#endif
1093 RCP<Factory> aggFactory;
1094 if (aggType == "uncoupled") {
1095 aggFactory = rcp(new UncoupledAggregationFactory());
1096 ParameterList aggParams;
1097 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: mode", std::string, aggParams);
1098 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: ordering", std::string, aggParams);
1099 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: min agg size", int, aggParams);
1100 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: max agg size", int, aggParams);
1101 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: max selected neighbors", int, aggParams);
1102 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: backend", std::string, aggParams);
1103 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: phase 1 algorithm", std::string, aggParams);
1104 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: deterministic", bool, aggParams);
1105 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: coloring algorithm", std::string, aggParams);
1106 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: enable phase 1", bool, aggParams);
1107 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: enable phase 2a", bool, aggParams);
1108 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: enable phase 2b", bool, aggParams);
1109 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: enable phase 3", bool, aggParams);
1110 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: match ML phase1", bool, aggParams);
1111 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: match ML phase2a", bool, aggParams);
1112 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: match ML phase2b", bool, aggParams);
1113 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: phase2a agg factor", double, aggParams);
1114 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: preserve Dirichlet points", bool, aggParams);
1115 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: error on nodes with no on-rank neighbors", bool, aggParams);
1116 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: phase3 avoid singletons", bool, aggParams);
1117 aggFactory->SetParameterList(aggParams);
1118 // make sure that the aggregation factory has all necessary data
1119 aggFactory->SetFactory("DofsPerNode", manager.GetFactory("Graph"));
1120 aggFactory->SetFactory("Graph", manager.GetFactory("Graph"));
1121 // aggFactory->SetFactory("UnAmalgamationInfo", manager.GetFactory("UnAmalgamationInfo"));
1122
1123 } else if (aggType == "brick") {
1124 aggFactory = rcp(new BrickAggregationFactory());
1125 ParameterList aggParams;
1126 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: brick x size", int, aggParams);
1127 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: brick y size", int, aggParams);
1128 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: brick z size", int, aggParams);
1129 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: brick x Dirichlet", bool, aggParams);
1130 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: brick y Dirichlet", bool, aggParams);
1131 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: brick z Dirichlet", bool, aggParams);
1132 aggFactory->SetParameterList(aggParams);
1133
1134 // Unlike other factories, BrickAggregationFactory makes the Graph/DofsPerNode itself
1135 manager.SetFactory("Graph", aggFactory);
1136 manager.SetFactory("DofsPerNode", aggFactory);
1137 manager.SetFactory("Filtering", aggFactory);
1138 if (levelID > 1) {
1139 // We check for levelID > 0, as in the interpreter aggFactory for
1140 // levelID really corresponds to level 0. Managers are clunky, as they
1141 // contain factories for two different levels
1142 aggFactory->SetFactory("Coordinates", this->GetFactoryManager(levelID - 1)->GetFactory("Coordinates"));
1143 }
1144 } else if (aggType == "classical") {
1145 // Map and coloring
1146 RCP<Factory> mapFact = rcp(new ClassicalMapFactory());
1147 ParameterList mapParams;
1148 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: deterministic", bool, mapParams);
1149 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: coloring algorithm", std::string, mapParams);
1150
1151 ParameterList tempParams;
1152 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: drop scheme", std::string, tempParams);
1153 std::string drop_algo = tempParams.get<std::string>("aggregation: drop scheme");
1154 if (drop_algo == "block diagonal colored signed classical") {
1155 mapParams.set("aggregation: coloring: use color graph", true);
1156 mapFact->SetFactory("Coloring Graph", manager.GetFactory("Coloring Graph"));
1157 }
1158 mapFact->SetParameterList(mapParams);
1159 mapFact->SetFactory("Graph", manager.GetFactory("Graph"));
1160 mapFact->SetFactory("UnAmalgamationInfo", manager.GetFactory("UnAmalgamationInfo"));
1161
1162 manager.SetFactory("FC Splitting", mapFact);
1163 manager.SetFactory("CoarseMap", mapFact);
1164
1165 aggFactory = rcp(new ClassicalPFactory());
1166 ParameterList aggParams;
1167 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: classical scheme", std::string, aggParams);
1168 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: drop scheme", std::string, aggParams);
1169 aggFactory->SetParameterList(aggParams);
1170 aggFactory->SetFactory("FC Splitting", manager.GetFactory("FC Splitting"));
1171 aggFactory->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
1172 aggFactory->SetFactory("DofsPerNode", manager.GetFactory("Graph"));
1173 aggFactory->SetFactory("Graph", manager.GetFactory("Graph"));
1174
1175 if (drop_algo.find("block diagonal") != std::string::npos || drop_algo == "signed classical") {
1176 if (levelID > 0)
1177 aggFactory->SetFactory("BlockNumber", this->GetFactoryManager(levelID - 1)->GetFactory("BlockNumber"));
1178 else
1179 aggFactory->SetFactory("BlockNumber", manager.GetFactory("BlockNumber"));
1180 }
1181
1182 // Now we short-circuit, because we neither need nor want TentativePFactory here
1183 manager.SetFactory("Ptent", aggFactory);
1184 manager.SetFactory("P Graph", aggFactory);
1185
1186 if (reuseType == "tP" && levelID) {
1187 // keeps.push_back(keep_pair("Nullspace", Ptent.get()));
1188 keeps.push_back(keep_pair("Ptent", aggFactory.get()));
1189 }
1190 return;
1191 } else if (aggType == "notay") {
1192 aggFactory = rcp(new NotayAggregationFactory());
1193 ParameterList aggParams;
1194 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: pairwise: size", int, aggParams);
1195 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: pairwise: tie threshold", double, aggParams);
1196 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: Dirichlet threshold", double, aggParams);
1197 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: ordering", std::string, aggParams);
1198 aggFactory->SetParameterList(aggParams);
1199 aggFactory->SetFactory("DofsPerNode", manager.GetFactory("Graph"));
1200 aggFactory->SetFactory("Graph", manager.GetFactory("Graph"));
1201 }
1202#ifdef HAVE_MUELU_MATLAB
1203 else if (aggType == "matlab") {
1204 ParameterList aggParams = paramList.sublist("aggregation: params");
1205 aggFactory = rcp(new SingleLevelMatlabFactory());
1206 aggFactory->SetParameterList(aggParams);
1207 }
1208#endif
1209
1210 manager.SetFactory("Aggregates", aggFactory);
1211
1212 // Coarse map
1213 RCP<Factory> coarseMap = rcp(new CoarseMapFactory());
1214 coarseMap->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1215 manager.SetFactory("CoarseMap", coarseMap);
1216
1217 // Tentative P
1219 ParameterList ptentParams;
1220 if (paramList.isSublist("matrixmatrix: kernel params"))
1221 ptentParams.sublist("matrixmatrix: kernel params", false) = paramList.sublist("matrixmatrix: kernel params");
1222 if (defaultList.isSublist("matrixmatrix: kernel params"))
1223 ptentParams.sublist("matrixmatrix: kernel params", false) = defaultList.sublist("matrixmatrix: kernel params");
1224 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "tentative: calculate qr", bool, ptentParams);
1225 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "tentative: build coarse coordinates", bool, ptentParams);
1226 Ptent->SetParameterList(ptentParams);
1227 Ptent->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1228 Ptent->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
1229 manager.SetFactory("Ptent", Ptent);
1230
1231 if (reuseType == "tP" && levelID) {
1232 keeps.push_back(keep_pair("Nullspace", Ptent.get()));
1233 keeps.push_back(keep_pair("P", Ptent.get()));
1234 }
1235}
1236
1237// =====================================================================================================
1238// ============================================ RAP ====================================================
1239// =====================================================================================================
1240template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1242 UpdateFactoryManager_RAP(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
1243 int levelID, std::vector<keep_pair>& keeps) const {
1244 if (paramList.isParameter("A") && !paramList.get<RCP<Matrix> >("A").is_null()) {
1245 // We have user matrix A
1246 manager.SetFactory("A", NoFactory::getRCP());
1247 return;
1248 }
1249
1250 ParameterList RAPparams;
1251
1252 RCP<RAPFactory> RAP;
1253 RCP<RAPShiftFactory> RAPs;
1254 // Allow for Galerkin or shifted RAP
1255 // FIXME: Should this not be some form of MUELU_SET_VAR_2LIST?
1256 std::string alg = paramList.get("rap: algorithm", "galerkin");
1257 if (alg == "shift" || alg == "non-galerkin") {
1258 RAPs = rcp(new RAPShiftFactory());
1259 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "rap: shift", double, RAPparams);
1260 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "rap: shift diagonal M", bool, RAPparams);
1261 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "rap: shift low storage", bool, RAPparams);
1262 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "rap: shift array", Teuchos::Array<double>, RAPparams);
1263 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "rap: cfl array", Teuchos::Array<double>, RAPparams);
1264
1265 } else {
1266 RAP = rcp(new RAPFactory());
1267 }
1268
1269 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "rap: relative diagonal floor", Teuchos::Array<double>, RAPparams);
1270
1271 if (paramList.isSublist("matrixmatrix: kernel params"))
1272 RAPparams.sublist("matrixmatrix: kernel params", false) = paramList.sublist("matrixmatrix: kernel params");
1273 if (defaultList.isSublist("matrixmatrix: kernel params"))
1274 RAPparams.sublist("matrixmatrix: kernel params", false) = defaultList.sublist("matrixmatrix: kernel params");
1275 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "transpose: use implicit", bool, RAPparams);
1276 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "rap: fix zero diagonals", bool, RAPparams);
1277 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "rap: fix zero diagonals threshold", double, RAPparams);
1278 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "rap: fix zero diagonals replacement", Scalar, RAPparams);
1279
1280 // if "rap: triple product" has not been set and algorithm is "unsmoothed" switch triple product on
1281 if (!paramList.isParameter("rap: triple product") &&
1282 paramList.isType<std::string>("multigrid algorithm") &&
1283 paramList.get<std::string>("multigrid algorithm") == "unsmoothed")
1284 paramList.set("rap: triple product", true);
1285 else
1286 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "rap: triple product", bool, RAPparams);
1287
1288 try {
1289 if (paramList.isParameter("aggregation: allow empty prolongator columns")) {
1290 RAPparams.set("CheckMainDiagonal", paramList.get<bool>("aggregation: allow empty prolongator columns"));
1291 RAPparams.set("RepairMainDiagonal", paramList.get<bool>("aggregation: allow empty prolongator columns"));
1292 } else if (defaultList.isParameter("aggregation: allow empty prolongator columns")) {
1293 RAPparams.set("CheckMainDiagonal", defaultList.get<bool>("aggregation: allow empty prolongator columns"));
1294 RAPparams.set("RepairMainDiagonal", defaultList.get<bool>("aggregation: allow empty prolongator columns"));
1295 }
1296
1297 } catch (Teuchos::Exceptions::InvalidParameterType&) {
1298 TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(true, Teuchos::Exceptions::InvalidParameterType,
1299 "Error: parameter \"aggregation: allow empty prolongator columns\" must be of type " << Teuchos::TypeNameTraits<bool>::name());
1300 }
1301
1302 if (!RAP.is_null()) {
1303 RAP->SetParameterList(RAPparams);
1304 RAP->SetFactory("P", manager.GetFactory("P"));
1305 } else {
1306 RAPs->SetParameterList(RAPparams);
1307 RAPs->SetFactory("P", manager.GetFactory("P"));
1308 }
1309
1310 if (!this->implicitTranspose_) {
1311 if (!RAP.is_null())
1312 RAP->SetFactory("R", manager.GetFactory("R"));
1313 else
1314 RAPs->SetFactory("R", manager.GetFactory("R"));
1315 }
1316
1317 // Matrix analysis
1318 if (MUELU_TEST_PARAM_2LIST(paramList, defaultList, "matrix: compute analysis", bool, true)) {
1319 RCP<Factory> matrixAnalysisFact = rcp(new MatrixAnalysisFactory());
1320
1321 if (!RAP.is_null())
1322 RAP->AddTransferFactory(matrixAnalysisFact);
1323 else
1324 RAPs->AddTransferFactory(matrixAnalysisFact);
1325 }
1326
1327 // Aggregate qualities
1328 if (MUELU_TEST_PARAM_2LIST(paramList, defaultList, "aggregation: compute aggregate qualities", bool, true)) {
1329 RCP<Factory> aggQualityFact = rcp(new AggregateQualityEstimateFactory());
1330 ParameterList aggQualityParams;
1331 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregate qualities: good aggregate threshold", double, aggQualityParams);
1332 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregate qualities: file output", bool, aggQualityParams);
1333 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregate qualities: file base", std::string, aggQualityParams);
1334 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregate qualities: check symmetry", bool, aggQualityParams);
1335 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregate qualities: algorithm", std::string, aggQualityParams);
1336 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregate qualities: zero threshold", double, aggQualityParams);
1337 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregate qualities: percentiles", Teuchos::Array<double>, aggQualityParams);
1338 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregate qualities: mode", std::string, aggQualityParams);
1339 aggQualityFact->SetParameterList(aggQualityParams);
1340 aggQualityFact->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1341 aggQualityFact->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
1342 manager.SetFactory("AggregateQualities", aggQualityFact);
1343
1344 if (!RAP.is_null())
1345 RAP->AddTransferFactory(aggQualityFact);
1346 else
1347 RAPs->AddTransferFactory(aggQualityFact);
1348 }
1349
1350 if (MUELU_TEST_PARAM_2LIST(paramList, defaultList, "aggregation: export visualization data", bool, true)) {
1351 RCP<AggregationExportFactory> aggExport = rcp(new AggregationExportFactory());
1352 ParameterList aggExportParams;
1353 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output filename", std::string, aggExportParams);
1354 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: agg style", std::string, aggExportParams);
1355 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: iter", int, aggExportParams);
1356 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: time step", int, aggExportParams);
1357 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: fine graph edges", bool, aggExportParams);
1358 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: coarse graph edges", bool, aggExportParams);
1359 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: build colormap", bool, aggExportParams);
1360 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: aggregate qualities", bool, aggExportParams);
1361 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: material", bool, aggExportParams);
1362 aggExport->SetParameterList(aggExportParams);
1363 aggExport->SetFactory("AggregateQualities", manager.GetFactory("AggregateQualities"));
1364 aggExport->SetFactory("DofsPerNode", manager.GetFactory("DofsPerNode"));
1365 aggExport->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1366 aggExport->SetFactory("Graph", manager.GetFactory("Graph"));
1367
1368 if (!RAP.is_null())
1369 RAP->AddTransferFactory(aggExport);
1370 else
1371 RAPs->AddTransferFactory(aggExport);
1372 }
1373 if (!RAP.is_null())
1374 manager.SetFactory("A", RAP);
1375 else
1376 manager.SetFactory("A", RAPs);
1377
1378 MUELU_SET_VAR_2LIST(paramList, defaultList, "reuse: type", std::string, reuseType);
1379 MUELU_SET_VAR_2LIST(paramList, defaultList, "sa: use filtered matrix", bool, useFiltering);
1380 bool filteringChangesMatrix = useFiltering && !MUELU_TEST_PARAM_2LIST(paramList, defaultList, "aggregation: drop tol", double, 0);
1381
1382 if (reuseType == "RP" || (reuseType == "tP" && !filteringChangesMatrix)) {
1383 if (!RAP.is_null()) {
1384 keeps.push_back(keep_pair("AP reuse data", RAP.get()));
1385 keeps.push_back(keep_pair("RAP reuse data", RAP.get()));
1386
1387 } else {
1388 keeps.push_back(keep_pair("AP reuse data", RAPs.get()));
1389 keeps.push_back(keep_pair("RAP reuse data", RAPs.get()));
1390 }
1391 }
1392}
1393
1394// =====================================================================================================
1395// ======================================= Coordinates =================================================
1396// =====================================================================================================
1397template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1399 UpdateFactoryManager_Coordinates(ParameterList& paramList, const ParameterList& /* defaultList */,
1400 FactoryManager& manager, int /* levelID */, std::vector<keep_pair>& /* keeps */) const {
1401 bool have_userCO = false;
1402 if (paramList.isParameter("Coordinates") && !paramList.get<RCP<MultiVector> >("Coordinates").is_null())
1403 have_userCO = true;
1404
1405 if (useCoordinates_) {
1406 if (have_userCO) {
1407 manager.SetFactory("Coordinates", NoFactory::getRCP());
1408
1409 } else {
1410 RCP<Factory> coords = rcp(new CoordinatesTransferFactory());
1411 coords->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1412 coords->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
1413 manager.SetFactory("Coordinates", coords);
1414
1415 auto RAP = rcp_const_cast<RAPFactory>(rcp_dynamic_cast<const RAPFactory>(manager.GetFactory("A")));
1416 if (!RAP.is_null()) {
1417 RAP->AddTransferFactory(manager.GetFactory("Coordinates"));
1418 } else {
1419 auto RAPs = rcp_const_cast<RAPShiftFactory>(rcp_dynamic_cast<const RAPShiftFactory>(manager.GetFactory("A")));
1420 RAPs->AddTransferFactory(manager.GetFactory("Coordinates"));
1421 }
1422 }
1423 }
1424}
1425
1426// ======================================================================================================
1427// ======================================== Material ==================================================
1428// =====================================================================================================
1429template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1431 UpdateFactoryManager_Material(ParameterList& paramList, const ParameterList& /* defaultList */,
1432 FactoryManager& manager, int /* levelID */, std::vector<keep_pair>& /* keeps */) const {
1433 bool have_userMaterial = false;
1434 if (paramList.isParameter("Material") && !paramList.get<RCP<MultiVector> >("Material").is_null())
1435 have_userMaterial = true;
1436
1437 if (useMaterial_) {
1438 if (have_userMaterial) {
1439 manager.SetFactory("Material", NoFactory::getRCP());
1440 } else {
1441 RCP<Factory> materialTransfer = rcp(new MultiVectorTransferFactory());
1442 ParameterList materialTransferParameters;
1443 materialTransferParameters.set("Vector name", "Material");
1444 materialTransferParameters.set("Transfer name", "P");
1445 materialTransferParameters.set("Normalize", true);
1446 materialTransfer->SetParameterList(materialTransferParameters);
1447 materialTransfer->SetFactory("Transfer factory", manager.GetFactory("Ptent"));
1448 manager.SetFactory("Material", materialTransfer);
1449
1450 auto RAP = rcp_const_cast<RAPFactory>(rcp_dynamic_cast<const RAPFactory>(manager.GetFactory("A")));
1451 if (!RAP.is_null()) {
1452 RAP->AddTransferFactory(manager.GetFactory("Material"));
1453 } else {
1454 auto RAPs = rcp_const_cast<RAPShiftFactory>(rcp_dynamic_cast<const RAPShiftFactory>(manager.GetFactory("A")));
1455 RAPs->AddTransferFactory(manager.GetFactory("Material"));
1456 }
1457 }
1458 }
1459}
1460
1461// =====================================================================================================
1462// ================================= LocalOrdinalTransfer =============================================
1463// =====================================================================================================
1464template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1466 UpdateFactoryManager_LocalOrdinalTransfer(const std::string& VarName, const std::string& multigridAlgo, ParameterList& paramList, const ParameterList& /* defaultList */,
1467 FactoryManager& manager, int levelID, std::vector<keep_pair>& /* keeps */) const {
1468 // NOTE: You would think this would be levelID > 0, but you'd be wrong, since the FactoryManager is basically
1469 // offset by a level from the things which actually do the work.
1470 if (useBlockNumber_ && (levelID > 0)) {
1471 auto RAP = rcp_const_cast<RAPFactory>(rcp_dynamic_cast<const RAPFactory>(manager.GetFactory("A")));
1472 auto RAPs = rcp_const_cast<RAPShiftFactory>(rcp_dynamic_cast<const RAPShiftFactory>(manager.GetFactory("A")));
1473 if (!RAP.is_null() || !RAPs.is_null()) {
1474 RCP<Factory> fact = rcp(new LocalOrdinalTransferFactory(VarName, multigridAlgo));
1475 if (multigridAlgo == "classical")
1476 fact->SetFactory("P Graph", manager.GetFactory("P Graph"));
1477 else
1478 fact->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1479 fact->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
1480
1481 fact->SetFactory(VarName, this->GetFactoryManager(levelID - 1)->GetFactory(VarName));
1482
1483 manager.SetFactory(VarName, fact);
1484
1485 if (!RAP.is_null())
1486 RAP->AddTransferFactory(manager.GetFactory(VarName));
1487 else
1488 RAPs->AddTransferFactory(manager.GetFactory(VarName));
1489 }
1490 }
1491}
1492
1493// ======================================================================================================
1494// ====================================== BlockNumber =================================================
1495// =====================================================================================================
1496template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1498 UpdateFactoryManager_BlockNumber(ParameterList& paramList, const ParameterList& defaultList,
1499 FactoryManager& manager, int levelID, std::vector<keep_pair>& keeps) const {
1500 if (useBlockNumber_) {
1501 ParameterList myParams;
1502 RCP<Factory> fact = rcp(new InitialBlockNumberFactory());
1503 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: block diagonal: interleaved blocksize", int, myParams);
1504 fact->SetParameterList(myParams);
1505 manager.SetFactory("BlockNumber", fact);
1506 }
1507}
1508
1509// =====================================================================================================
1510// =========================================== Restriction =============================================
1511// =====================================================================================================
1512template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1514 UpdateFactoryManager_Restriction(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
1515 int levelID, std::vector<keep_pair>& /* keeps */) const {
1516 MUELU_SET_VAR_2LIST(paramList, defaultList, "multigrid algorithm", std::string, multigridAlgo);
1517 bool have_userR = false;
1518 if (paramList.isParameter("R") && !paramList.get<RCP<Matrix> >("R").is_null())
1519 have_userR = true;
1520
1521 // === Restriction ===
1522 RCP<Factory> R;
1523 if (!this->implicitTranspose_) {
1524 MUELU_SET_VAR_2LIST(paramList, defaultList, "problem: symmetric", bool, isSymmetric);
1525
1526 if (isSymmetric == false && (multigridAlgo == "unsmoothed" || multigridAlgo == "emin")) {
1527 this->GetOStream(Warnings0) << "Switching \"problem: symmetric\" parameter to symmetric as multigrid algorithm. " << multigridAlgo << " is primarily supposed to be used for symmetric problems.\n\n"
1528 << "Please note: if you are using \"unsmoothed\" transfer operators the \"problem: symmetric\" parameter "
1529 << "has no real mathematical meaning, i.e. you can use it for non-symmetric\n"
1530 << "problems, too. With \"problem: symmetric\"=\"symmetric\" you can use implicit transpose for building "
1531 << "the restriction operators which may drastically reduce the amount of consumed memory." << std::endl;
1532 isSymmetric = true;
1533 }
1534 TEUCHOS_TEST_FOR_EXCEPTION(multigridAlgo == "pg" && isSymmetric == true, Exceptions::RuntimeError,
1535 "Petrov-Galerkin smoothed transfer operators are only allowed for non-symmetric problems: Set \"problem: symmetric\" to false!\n"
1536 "While PG smoothed transfer operators generally would also work for symmetric problems this is an unusual use case. "
1537 "You can use the factory-based xml interface though if you need PG-AMG for symmetric problems.");
1538
1539 if (have_userR) {
1540 manager.SetFactory("R", NoFactory::getRCP());
1541 } else {
1542 if (isSymmetric)
1543 R = rcp(new TransPFactory());
1544 else
1545 R = rcp(new GenericRFactory());
1546
1547 R->SetFactory("P", manager.GetFactory("P"));
1548 manager.SetFactory("R", R);
1549 }
1550
1551 } else {
1552 manager.SetFactory("R", Teuchos::null);
1553 }
1554
1555 // === Restriction: Nullspace Scaling ===
1556 if (paramList.isParameter("restriction: scale nullspace") && paramList.get<bool>("restriction: scale nullspace")) {
1557 RCP<TentativePFactory> tentPFactory = rcp(new TentativePFactory());
1558 Teuchos::ParameterList tentPlist;
1559 tentPlist.set("Nullspace name", "Scaled Nullspace");
1560 tentPFactory->SetParameterList(tentPlist);
1561 tentPFactory->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1562 tentPFactory->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
1563
1564 if (R.is_null()) R = rcp(new TransPFactory());
1565 R->SetFactory("P", tentPFactory);
1566 }
1567}
1568
1569// =====================================================================================================
1570// ========================================= Repartition ===============================================
1571// =====================================================================================================
1572template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1574 UpdateFactoryManager_Repartition(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
1575 int levelID, std::vector<keep_pair>& keeps, RCP<Factory>& nullSpaceFactory) const {
1576 // === Repartitioning ===
1577 MUELU_SET_VAR_2LIST(paramList, defaultList, "reuse: type", std::string, reuseType);
1578 MUELU_SET_VAR_2LIST(paramList, defaultList, "repartition: enable", bool, enableRepart);
1579 if (enableRepart) {
1580#if defined(HAVE_MPI) && (defined(HAVE_MUELU_ZOLTAN) || defined(HAVE_MUELU_ZOLTAN2)) // skip to the end, print warning, and turn off repartitioning if we don't have MPI and Zoltan/Zoltan2
1581 MUELU_SET_VAR_2LIST(paramList, defaultList, "repartition: use subcommunicators in place", bool, enableInPlace);
1582 // Short summary of the issue: RebalanceTransferFactory shares ownership
1583 // of "P" with SaPFactory, and therefore, changes the stored version.
1584 // That means that if SaPFactory generated P, and stored it on the level,
1585 // then after rebalancing the value in that storage changed. It goes
1586 // against the concept of factories (I think), that every factory is
1587 // responsible for its own objects, and they are immutable outside.
1588 //
1589 // In reuse, this is what happens: as we reuse Importer across setups,
1590 // the order of factories changes, and coupled with shared ownership
1591 // leads to problems.
1592 // *First setup*
1593 // SaP builds P [and stores it]
1594 // TransP builds R [and stores it]
1595 // RAP builds A [and stores it]
1596 // RebalanceTransfer rebalances P [and changes the P stored by SaP] (*)
1597 // RebalanceTransfer rebalances R
1598 // RebalanceAc rebalances A
1599 // *Second setup* ("RP" reuse)
1600 // RebalanceTransfer rebalances P [which is incorrect due to (*)]
1601 // RebalanceTransfer rebalances R
1602 // RAP builds A [which is incorrect due to (*)]
1603 // RebalanceAc rebalances A [which throws due to map inconsistency]
1604 // ...
1605 // *Second setup* ("tP" reuse)
1606 // SaP builds P [and stores it]
1607 // RebalanceTransfer rebalances P [and changes the P stored by SaP] (**)
1608 // TransP builds R [which is incorrect due to (**)]
1609 // RebalanceTransfer rebalances R
1610 // ...
1611 //
1612 // Couple solutions to this:
1613 // 1. [implemented] Requre "tP" and "PR" reuse to only be used with
1614 // implicit rebalancing.
1615 // 2. Do deep copy of P, and changed domain map and importer there.
1616 // Need to investigate how expensive this is.
1617 TEUCHOS_TEST_FOR_EXCEPTION(this->doPRrebalance_ && (reuseType == "tP" || reuseType == "RP"), Exceptions::InvalidArgument,
1618 "Reuse types \"tP\" and \"PR\" require \"repartition: rebalance P and R\" set to \"false\"");
1619
1620 // TEUCHOS_TEST_FOR_EXCEPTION(aggType == "brick", Exceptions::InvalidArgument,
1621 // "Aggregation type \"brick\" requires \"repartition: enable\" set to \"false\"");
1622
1623 MUELU_SET_VAR_2LIST(paramList, defaultList, "repartition: partitioner", std::string, partName);
1624 TEUCHOS_TEST_FOR_EXCEPTION(partName != "zoltan" && partName != "zoltan2", Exceptions::InvalidArgument,
1625 "Invalid partitioner name: \"" << partName << "\". Valid options: \"zoltan\", \"zoltan2\"");
1626
1627#ifndef HAVE_MUELU_ZOLTAN
1628 bool switched = false;
1629 if (partName == "zoltan") {
1630 this->GetOStream(Warnings0) << "Zoltan interface is not available, trying to switch to Zoltan2" << std::endl;
1631 partName = "zoltan2";
1632 switched = true;
1633 }
1634#else
1635#ifndef HAVE_MUELU_ZOLTAN2
1636 bool switched = false;
1637#endif // HAVE_MUELU_ZOLTAN2
1638#endif // HAVE_MUELU_ZOLTAN
1639
1640#ifndef HAVE_MUELU_ZOLTAN2
1641 if (partName == "zoltan2" && !switched) {
1642 this->GetOStream(Warnings0) << "Zoltan2 interface is not available, trying to switch to Zoltan" << std::endl;
1643 partName = "zoltan";
1644 }
1645#endif // HAVE_MUELU_ZOLTAN2
1646
1647 MUELU_SET_VAR_2LIST(paramList, defaultList, "repartition: node repartition level", int, nodeRepartitionLevel);
1648
1649 // RepartitionHeuristic
1650 auto repartheurFactory = rcp(new RepartitionHeuristicFactory());
1651 ParameterList repartheurParams;
1652 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: node repartition level", int, repartheurParams);
1653 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: start level", int, repartheurParams);
1654 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: min rows per proc", int, repartheurParams);
1655 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: target rows per proc", int, repartheurParams);
1656 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: min rows per thread", int, repartheurParams);
1657 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: target rows per thread", int, repartheurParams);
1658 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: max imbalance", double, repartheurParams);
1659 repartheurFactory->SetParameterList(repartheurParams);
1660 repartheurFactory->SetFactory("A", manager.GetFactory("A"));
1661 manager.SetFactory("number of partitions", repartheurFactory);
1662 manager.SetFactory("repartition: heuristic target rows per process", repartheurFactory);
1663
1664 // Partitioner
1665 RCP<Factory> partitioner;
1666 if (levelID == nodeRepartitionLevel) {
1667 // partitioner = rcp(new NodePartitionInterface());
1668 partitioner = rcp(new MueLu::NodePartitionInterface<SC, LO, GO, NO>());
1669 ParameterList partParams;
1670 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: node id", int, repartheurParams);
1671 partitioner->SetParameterList(partParams);
1672 partitioner->SetFactory("Node Comm", manager.GetFactory("Node Comm"));
1673 } else if (partName == "zoltan") {
1674#ifdef HAVE_MUELU_ZOLTAN
1675 partitioner = rcp(new ZoltanInterface());
1676 // NOTE: ZoltanInterface ("zoltan") does not support external parameters through ParameterList
1677#else
1678 throw Exceptions::RuntimeError("Zoltan interface is not available");
1679#endif // HAVE_MUELU_ZOLTAN
1680 } else if (partName == "zoltan2") {
1681#ifdef HAVE_MUELU_ZOLTAN2
1682 partitioner = rcp(new Zoltan2Interface());
1683 ParameterList partParams;
1684 RCP<const ParameterList> partpartParams = rcp(new ParameterList(paramList.sublist("repartition: params", false)));
1685 partParams.set("ParameterList", partpartParams);
1686 partitioner->SetParameterList(partParams);
1687 partitioner->SetFactory("repartition: heuristic target rows per process",
1688 manager.GetFactory("repartition: heuristic target rows per process"));
1689#else
1690 throw Exceptions::RuntimeError("Zoltan2 interface is not available");
1691#endif // HAVE_MUELU_ZOLTAN2
1692 }
1693
1694 partitioner->SetFactory("A", manager.GetFactory("A"));
1695 partitioner->SetFactory("number of partitions", manager.GetFactory("number of partitions"));
1696 if (useCoordinates_)
1697 partitioner->SetFactory("Coordinates", manager.GetFactory("Coordinates"));
1698 manager.SetFactory("Partition", partitioner);
1699
1700 // Repartitioner
1701 auto repartFactory = rcp(new RepartitionFactory());
1702 ParameterList repartParams;
1703 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: print partition distribution", bool, repartParams);
1704 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: remap parts", bool, repartParams);
1705 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: remap num values", int, repartParams);
1706 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: save importer", bool, repartParams);
1707 repartFactory->SetParameterList(repartParams);
1708 repartFactory->SetFactory("A", manager.GetFactory("A"));
1709 repartFactory->SetFactory("number of partitions", manager.GetFactory("number of partitions"));
1710 repartFactory->SetFactory("Partition", manager.GetFactory("Partition"));
1711 manager.SetFactory("Importer", repartFactory);
1712 if (reuseType != "none" && reuseType != "S" && levelID)
1713 keeps.push_back(keep_pair("Importer", manager.GetFactory("Importer").get()));
1714
1715 if (enableInPlace) {
1716 // Rebalanced A (in place)
1717 // NOTE: This is for when we want to constrain repartitioning to match some other idea of what's going on.
1718 // The major application is the (1,1) hierarchy in the Maxwell1 preconditioner.
1719 auto newA = rcp(new RebalanceAcFactory());
1720 ParameterList rebAcParams;
1721 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: use subcommunicators", bool, rebAcParams);
1722 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: use subcommunicators in place", bool, rebAcParams);
1723 newA->SetParameterList(rebAcParams);
1724 newA->SetFactory("A", manager.GetFactory("A"));
1725 newA->SetFactory("InPlaceMap", manager.GetFactory("InPlaceMap"));
1726 manager.SetFactory("A", newA);
1727 } else {
1728 // Rebalanced A
1729 auto newA = rcp(new RebalanceAcFactory());
1730 ParameterList rebAcParams;
1731 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: use subcommunicators", bool, rebAcParams);
1732 newA->SetParameterList(rebAcParams);
1733 newA->SetFactory("A", manager.GetFactory("A"));
1734 newA->SetFactory("Importer", manager.GetFactory("Importer"));
1735 manager.SetFactory("A", newA);
1736
1737 // Rebalanced P
1738 auto newP = rcp(new RebalanceTransferFactory());
1739 ParameterList newPparams;
1740 newPparams.set("type", "Interpolation");
1742 newPparams.set("repartition: rebalance P and R", this->doPRrebalance_);
1744 newPparams.set("repartition: explicit via new copy rebalance P and R", true);
1745 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: use subcommunicators", bool, newPparams);
1746 newP->SetParameterList(newPparams);
1747 newP->SetFactory("Importer", manager.GetFactory("Importer"));
1748 newP->SetFactory("P", manager.GetFactory("P"));
1749 manager.SetFactory("P", newP);
1750 if (!paramList.isParameter("semicoarsen: number of levels"))
1751 newP->SetFactory("Nullspace", manager.GetFactory("Ptent"));
1752 else
1753 newP->SetFactory("Nullspace", manager.GetFactory("P")); // TogglePFactory
1754 if (useCoordinates_) {
1755 newP->SetFactory("Coordinates", manager.GetFactory("Coordinates"));
1756 manager.SetFactory("Coordinates", newP);
1757 }
1758 if (useMaterial_) {
1759 newP->SetFactory("Material", manager.GetFactory("Material"));
1760 manager.SetFactory("Material", newP);
1761 }
1762 if (useBlockNumber_ && (levelID > 0)) {
1763 newP->SetFactory("BlockNumber", manager.GetFactory("BlockNumber"));
1764 manager.SetFactory("BlockNumber", newP);
1765 }
1766
1767 // Rebalanced R
1768 auto newR = rcp(new RebalanceTransferFactory());
1769 ParameterList newRparams;
1770 newRparams.set("type", "Restriction");
1771 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: use subcommunicators", bool, newRparams);
1773 newRparams.set("repartition: rebalance P and R", this->doPRrebalance_);
1775 newPparams.set("repartition: explicit via new copy rebalance P and R", true);
1777 newRparams.set("transpose: use implicit", this->implicitTranspose_);
1778 newR->SetParameterList(newRparams);
1779 newR->SetFactory("Importer", manager.GetFactory("Importer"));
1780 if (!this->implicitTranspose_) {
1781 newR->SetFactory("R", manager.GetFactory("R"));
1782 manager.SetFactory("R", newR);
1783 }
1784
1785 // NOTE: the role of NullspaceFactory is to provide nullspace on the finest
1786 // level if a user does not do that. For all other levels it simply passes
1787 // nullspace from a real factory to whoever needs it. If we don't use
1788 // repartitioning, that factory is "TentativePFactory"; if we do, it is
1789 // "RebalanceTransferFactory". But we still have to have NullspaceFactory as
1790 // the "Nullspace" of the manager
1791 // NOTE: This really needs to be set on the *NullSpaceFactory*, not manager.get("Nullspace").
1792 ParameterList newNullparams;
1793 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "nullspace: calculate rotations", bool, newNullparams);
1794 nullSpaceFactory->SetFactory("Nullspace", newP);
1795 nullSpaceFactory->SetParameterList(newNullparams);
1796 }
1797#else
1798 paramList.set("repartition: enable", false);
1799#ifndef HAVE_MPI
1800 this->GetOStream(Warnings0) << "No repartitioning available for a serial run\n";
1801#else
1802 this->GetOStream(Warnings0) << "Zoltan/Zoltan2 are unavailable for repartitioning\n";
1803#endif // HAVE_MPI
1804#endif // defined(HAVE_MPI) && (defined(HAVE_MUELU_ZOLTAN) || defined(HAVE_MUELU_ZOLTAN2))
1805 }
1806}
1807
1808// =====================================================================================================
1809// ========================================= Low precision transfers ===================================
1810// =====================================================================================================
1811template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1813 UpdateFactoryManager_LowPrecision(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
1814 int levelID, std::vector<keep_pair>& keeps) const {
1815 MUELU_SET_VAR_2LIST(paramList, defaultList, "transfers: half precision", bool, enableLowPrecision);
1816
1817 if (enableLowPrecision) {
1818 // Low precision P
1819 auto newP = rcp(new LowPrecisionFactory());
1820 ParameterList newPparams;
1821 newPparams.set("matrix key", "P");
1822 newP->SetParameterList(newPparams);
1823 newP->SetFactory("P", manager.GetFactory("P"));
1824 manager.SetFactory("P", newP);
1825
1826 if (!this->implicitTranspose_) {
1827 // Low precision R
1828 auto newR = rcp(new LowPrecisionFactory());
1829 ParameterList newRparams;
1830 newRparams.set("matrix key", "R");
1831 newR->SetParameterList(newRparams);
1832 newR->SetFactory("R", manager.GetFactory("R"));
1833 manager.SetFactory("R", newR);
1834 }
1835 }
1836}
1837
1838// =====================================================================================================
1839// =========================================== Nullspace ===============================================
1840// =====================================================================================================
1841template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1843 UpdateFactoryManager_Nullspace(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
1844 int /* levelID */, std::vector<keep_pair>& /* keeps */, RCP<Factory>& nullSpaceFactory) const {
1845 // Nullspace
1846 RCP<Factory> nullSpace = rcp(new NullspaceFactory());
1847
1848 bool have_userNS = false;
1849 if (paramList.isParameter("Nullspace") && !paramList.get<RCP<MultiVector> >("Nullspace").is_null())
1850 have_userNS = true;
1851
1852 if (!have_userNS) {
1853 ParameterList newNullparams;
1854 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "nullspace: calculate rotations", bool, newNullparams);
1855 nullSpace->SetParameterList(newNullparams);
1856 nullSpace->SetFactory("Nullspace", manager.GetFactory("Ptent"));
1857 manager.SetFactory("Nullspace", nullSpace);
1858 }
1859 nullSpaceFactory = nullSpace;
1860
1861 if (paramList.isParameter("restriction: scale nullspace") && paramList.get<bool>("restriction: scale nullspace")) {
1862 RCP<ScaledNullspaceFactory> scaledNSfactory = rcp(new ScaledNullspaceFactory());
1863 scaledNSfactory->SetFactory("Nullspace", nullSpaceFactory);
1864 manager.SetFactory("Scaled Nullspace", scaledNSfactory);
1865 }
1866}
1867
1868// =====================================================================================================
1869// ================================= Algorithm: SemiCoarsening =========================================
1870// =====================================================================================================
1871template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1873 UpdateFactoryManager_SemiCoarsen(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
1874 int /* levelID */, std::vector<keep_pair>& /* keeps */) const {
1875 // === Semi-coarsening ===
1876 RCP<Factory> semicoarsenFactory = Teuchos::null;
1877 if (paramList.isParameter("semicoarsen: number of levels") &&
1878 paramList.get<int>("semicoarsen: number of levels") > 0) {
1879 ParameterList togglePParams;
1880 ParameterList semicoarsenPParams;
1881 ParameterList linedetectionParams;
1882 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "semicoarsen: number of levels", int, togglePParams);
1883 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "semicoarsen: coarsen rate", int, semicoarsenPParams);
1884 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "semicoarsen: piecewise constant", bool, semicoarsenPParams);
1885 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "semicoarsen: piecewise linear", bool, semicoarsenPParams);
1886 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "semicoarsen: calculate nonsym restriction", bool, semicoarsenPParams);
1887 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "linedetection: orientation", std::string, linedetectionParams);
1888 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "linedetection: num layers", int, linedetectionParams);
1889
1891 RCP<LineDetectionFactory> linedetectionFactory = rcp(new LineDetectionFactory());
1892 RCP<TogglePFactory> togglePFactory = rcp(new TogglePFactory());
1893
1894 linedetectionFactory->SetParameterList(linedetectionParams);
1895 semicoarsenFactory->SetParameterList(semicoarsenPParams);
1896 togglePFactory->SetParameterList(togglePParams);
1897
1898 togglePFactory->AddCoarseNullspaceFactory(semicoarsenFactory);
1899 togglePFactory->AddProlongatorFactory(semicoarsenFactory);
1900 togglePFactory->AddPtentFactory(semicoarsenFactory);
1901 togglePFactory->AddCoarseNullspaceFactory(manager.GetFactory("Ptent"));
1902 togglePFactory->AddProlongatorFactory(manager.GetFactory("P"));
1903 togglePFactory->AddPtentFactory(manager.GetFactory("Ptent"));
1904
1905 manager.SetFactory("CoarseNumZLayers", linedetectionFactory);
1906 manager.SetFactory("LineDetection_Layers", linedetectionFactory);
1907 manager.SetFactory("LineDetection_VertLineIds", linedetectionFactory);
1908
1909 manager.SetFactory("P", togglePFactory);
1910 manager.SetFactory("Ptent", togglePFactory);
1911 manager.SetFactory("Nullspace", togglePFactory);
1912 }
1913
1914 if (paramList.isParameter("semicoarsen: number of levels")) {
1915 auto tf = rcp(new ToggleCoordinatesTransferFactory());
1916 tf->SetFactory("Chosen P", manager.GetFactory("P"));
1917 tf->AddCoordTransferFactory(semicoarsenFactory);
1918
1919 RCP<Factory> coords = rcp(new CoordinatesTransferFactory());
1920 coords->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1921 coords->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
1922 tf->AddCoordTransferFactory(coords);
1923 manager.SetFactory("Coordinates", tf);
1924 }
1925}
1926
1927// =====================================================================================================
1928// ================================== Algorithm: P-Coarsening ==========================================
1929// =====================================================================================================
1930template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1932 UpdateFactoryManager_PCoarsen(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
1933 int levelID, std::vector<keep_pair>& keeps) const {
1934#ifdef HAVE_MUELU_INTREPID2
1935 // This only makes sense to invoke from the default list.
1936 if (defaultList.isParameter("pcoarsen: schedule") && defaultList.isParameter("pcoarsen: element")) {
1937 // P-Coarsening by schedule (new interface)
1938 // NOTE: levelID represents the *coarse* level in this case
1939 auto pcoarsen_schedule = Teuchos::getArrayFromStringParameter<int>(defaultList, "pcoarsen: schedule");
1940 auto pcoarsen_element = defaultList.get<std::string>("pcoarsen: element");
1941
1942 if (levelID >= (int)pcoarsen_schedule.size()) {
1943 // Past the p-coarsening levels, we do Smoothed Aggregation
1944 // NOTE: We should probably consider allowing other options past p-coarsening
1945 UpdateFactoryManager_SA(paramList, defaultList, manager, levelID, keeps);
1946
1947 } else {
1948 // P-Coarsening
1949 ParameterList Pparams;
1950 auto P = rcp(new IntrepidPCoarsenFactory());
1951 std::string lo = pcoarsen_element + std::to_string(pcoarsen_schedule[levelID]);
1952 std::string hi = (levelID ? pcoarsen_element + std::to_string(pcoarsen_schedule[levelID - 1]) : lo);
1953 Pparams.set("pcoarsen: hi basis", hi);
1954 Pparams.set("pcoarsen: lo basis", lo);
1955 P->SetParameterList(Pparams);
1956 manager.SetFactory("P", P);
1957
1958 // Add special nullspace handling
1959 rcp_dynamic_cast<Factory>(manager.GetFactoryNonConst("Nullspace"))->SetFactory("Nullspace", manager.GetFactory("P"));
1960 }
1961
1962 } else {
1963 // P-Coarsening by manual specification (old interface)
1964 ParameterList Pparams;
1965 auto P = rcp(new IntrepidPCoarsenFactory());
1966 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "pcoarsen: hi basis", std::string, Pparams);
1967 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "pcoarsen: lo basis", std::string, Pparams);
1968 P->SetParameterList(Pparams);
1969 manager.SetFactory("P", P);
1970
1971 // Add special nullspace handling
1972 rcp_dynamic_cast<Factory>(manager.GetFactoryNonConst("Nullspace"))->SetFactory("Nullspace", manager.GetFactory("P"));
1973 }
1974
1975#endif
1976}
1977
1978// =====================================================================================================
1979// ============================== Algorithm: Smoothed Aggregation ======================================
1980// =====================================================================================================
1981template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1983 UpdateFactoryManager_SA(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager, int /* levelID */, std::vector<keep_pair>& keeps) const {
1984 // Smoothed aggregation
1985 RCP<Factory> P = rcp(new SaPFactory());
1986 ParameterList Pparams;
1987 if (paramList.isSublist("matrixmatrix: kernel params"))
1988 Pparams.sublist("matrixmatrix: kernel params", false) = paramList.sublist("matrixmatrix: kernel params");
1989 if (defaultList.isSublist("matrixmatrix: kernel params"))
1990 Pparams.sublist("matrixmatrix: kernel params", false) = defaultList.sublist("matrixmatrix: kernel params");
1991 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "sa: damping factor", double, Pparams);
1992 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "sa: calculate eigenvalue estimate", bool, Pparams);
1993 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "sa: max eigenvalue", double, Pparams);
1994 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "sa: eigenvalue estimate num iterations", int, Pparams);
1995 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "sa: use rowsumabs diagonal scaling", bool, Pparams);
1996 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "sa: rowsumabs diagonal replacement tolerance", double, Pparams);
1997 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "sa: rowsumabs diagonal replacement value", double, Pparams);
1998 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "sa: rowsumabs use automatic diagonal tolerance", bool, Pparams);
1999 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "sa: enforce constraints", bool, Pparams);
2000 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "sa: eigen-analysis type", std::string, Pparams);
2001 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "tentative: calculate qr", bool, Pparams);
2002
2003 P->SetParameterList(Pparams);
2004
2005 // Filtering
2006 MUELU_SET_VAR_2LIST(paramList, defaultList, "sa: use filtered matrix", bool, useFiltering);
2007 if (useFiltering) {
2008 // NOTE: Here, non-Kokkos and Kokkos versions diverge in the way the
2009 // dependency tree is setup. The Kokkos version has merged the the
2010 // FilteredAFactory into the CoalesceDropFactory.
2011 if (!useKokkos_) {
2012 RCP<Factory> filterFactory = rcp(new FilteredAFactory());
2013
2014 ParameterList fParams;
2015 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: use lumping", bool, fParams);
2016 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: reuse graph", bool, fParams);
2017 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: reuse eigenvalue", bool, fParams);
2018 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: use root stencil", bool, fParams);
2019 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: Dirichlet threshold", double, fParams);
2020 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: use spread lumping", bool, fParams);
2021 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: spread lumping diag dom growth factor", double, fParams);
2022 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: spread lumping diag dom cap", double, fParams);
2023 filterFactory->SetParameterList(fParams);
2024 filterFactory->SetFactory("Graph", manager.GetFactory("Graph"));
2025 filterFactory->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
2026 filterFactory->SetFactory("UnAmalgamationInfo", manager.GetFactory("UnAmalgamationInfo"));
2027 // I'm not sure why we need this line. See comments for DofsPerNode for UncoupledAggregation above
2028 filterFactory->SetFactory("Filtering", manager.GetFactory("Graph"));
2029
2030 P->SetFactory("A", filterFactory);
2031
2032 } else {
2033 P->SetFactory("A", manager.GetFactory("Graph"));
2034 }
2035 }
2036
2037 P->SetFactory("P", manager.GetFactory("Ptent"));
2038 manager.SetFactory("P", P);
2039
2040 bool filteringChangesMatrix = useFiltering && !MUELU_TEST_PARAM_2LIST(paramList, defaultList, "aggregation: drop tol", double, 0);
2041 MUELU_SET_VAR_2LIST(paramList, defaultList, "reuse: type", std::string, reuseType);
2042 if (reuseType == "tP" && !filteringChangesMatrix)
2043 keeps.push_back(keep_pair("AP reuse data", P.get()));
2044}
2045
2046// =====================================================================================================
2047// =============================== Algorithm: Energy Minimization ======================================
2048// =====================================================================================================
2049template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2051 UpdateFactoryManager_Emin(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
2052 int /* levelID */, std::vector<keep_pair>& /* keeps */) const {
2053 MUELU_SET_VAR_2LIST(paramList, defaultList, "emin: pattern", std::string, patternType);
2054 MUELU_SET_VAR_2LIST(paramList, defaultList, "reuse: type", std::string, reuseType);
2055 TEUCHOS_TEST_FOR_EXCEPTION(patternType != "AkPtent", Exceptions::InvalidArgument,
2056 "Invalid pattern name: \"" << patternType << "\". Valid options: \"AkPtent\"");
2057 // Pattern
2058 auto patternFactory = rcp(new PatternFactory());
2059 ParameterList patternParams;
2060 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "emin: pattern order", int, patternParams);
2061 patternFactory->SetParameterList(patternParams);
2062 patternFactory->SetFactory("P", manager.GetFactory("Ptent"));
2063 manager.SetFactory("Ppattern", patternFactory);
2064
2065 // Constraint
2066 auto constraintFactory = rcp(new ConstraintFactory());
2067 constraintFactory->SetFactory("Ppattern", manager.GetFactory("Ppattern"));
2068 constraintFactory->SetFactory("CoarseNullspace", manager.GetFactory("Ptent"));
2069 manager.SetFactory("Constraint", constraintFactory);
2070
2071 // Emin Factory
2072 auto P = rcp(new EminPFactory());
2073 // Filtering
2074 MUELU_SET_VAR_2LIST(paramList, defaultList, "emin: use filtered matrix", bool, useFiltering);
2075 if (useFiltering) {
2076 // NOTE: Here, non-Kokkos and Kokkos versions diverge in the way the
2077 // dependency tree is setup. The Kokkos version has merged the the
2078 // FilteredAFactory into the CoalesceDropFactory.
2079 if (!useKokkos_) {
2080 RCP<Factory> filterFactory = rcp(new FilteredAFactory());
2081
2082 ParameterList fParams;
2083 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: use lumping", bool, fParams);
2084 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: reuse graph", bool, fParams);
2085 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: reuse eigenvalue", bool, fParams);
2086 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: use root stencil", bool, fParams);
2087 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: Dirichlet threshold", double, fParams);
2088 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: use spread lumping", bool, fParams);
2089 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: spread lumping diag dom growth factor", double, fParams);
2090 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: spread lumping diag dom cap", double, fParams);
2091 filterFactory->SetParameterList(fParams);
2092 filterFactory->SetFactory("Graph", manager.GetFactory("Graph"));
2093 filterFactory->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
2094 filterFactory->SetFactory("UnAmalgamationInfo", manager.GetFactory("UnAmalgamationInfo"));
2095 // I'm not sure why we need this line. See comments for DofsPerNode for UncoupledAggregation above
2096 filterFactory->SetFactory("Filtering", manager.GetFactory("Graph"));
2097
2098 P->SetFactory("A", filterFactory);
2099
2100 } else {
2101 P->SetFactory("A", manager.GetFactory("Graph"));
2102 }
2103 }
2104
2105 // Energy minimization
2106 ParameterList Pparams;
2107 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "emin: num iterations", int, Pparams);
2108 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "emin: iterative method", std::string, Pparams);
2109 if (reuseType == "emin") {
2110 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "emin: num reuse iterations", int, Pparams);
2111 Pparams.set("Keep P0", true);
2112 Pparams.set("Keep Constraint0", true);
2113 }
2114 P->SetParameterList(Pparams);
2115 P->SetFactory("P", manager.GetFactory("Ptent"));
2116 P->SetFactory("Constraint", manager.GetFactory("Constraint"));
2117 manager.SetFactory("P", P);
2118}
2119
2120// =====================================================================================================
2121// ================================= Algorithm: Petrov-Galerkin ========================================
2122// =====================================================================================================
2123template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2125 UpdateFactoryManager_PG(ParameterList& /* paramList */, const ParameterList& /* defaultList */, FactoryManager& manager,
2126 int /* levelID */, std::vector<keep_pair>& /* keeps */) const {
2127 TEUCHOS_TEST_FOR_EXCEPTION(this->implicitTranspose_, Exceptions::RuntimeError,
2128 "Implicit transpose not supported with Petrov-Galerkin smoothed transfer operators: Set \"transpose: use implicit\" to false!\n"
2129 "Petrov-Galerkin transfer operator smoothing for non-symmetric problems requires a separate handling of the restriction operator which "
2130 "does not allow the usage of implicit transpose easily.");
2131
2132 // Petrov-Galerkin
2133 auto P = rcp(new PgPFactory());
2134 P->SetFactory("P", manager.GetFactory("Ptent"));
2135 manager.SetFactory("P", P);
2136}
2137
2138// =====================================================================================================
2139// ================================= Algorithm: Replicate ========================================
2140// =====================================================================================================
2141template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2143 UpdateFactoryManager_Replicate(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager, int /* levelID */, std::vector<keep_pair>& keeps) const {
2145
2146 ParameterList Pparams;
2147 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "replicate: npdes", int, Pparams);
2148
2149 P->SetParameterList(Pparams);
2150 manager.SetFactory("P", P);
2151}
2152
2153// =====================================================================================================
2154// ====================================== Algorithm: Combine ============================================
2155// =====================================================================================================
2156template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2158 UpdateFactoryManager_Combine(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager, int /* levelID */, std::vector<keep_pair>& keeps) const {
2160
2161 ParameterList Pparams;
2162 MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "combine: numBlks", int, Pparams);
2163
2164 P->SetParameterList(Pparams);
2165 manager.SetFactory("P", P);
2166}
2167
2168// =====================================================================================================
2169// ====================================== Algorithm: Matlab ============================================
2170// =====================================================================================================
2171template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2173 UpdateFactoryManager_Matlab(ParameterList& paramList, const ParameterList& /* defaultList */, FactoryManager& manager,
2174 int /* levelID */, std::vector<keep_pair>& /* keeps */) const {
2175#ifdef HAVE_MUELU_MATLAB
2176 ParameterList Pparams = paramList.sublist("transfer: params");
2177 auto P = rcp(new TwoLevelMatlabFactory());
2178 P->SetParameterList(Pparams);
2179 P->SetFactory("P", manager.GetFactory("Ptent"));
2180 manager.SetFactory("P", P);
2181#else
2182 (void)paramList;
2183 (void)manager;
2184#endif
2185}
2186
2187#undef MUELU_SET_VAR_2LIST
2188#undef MUELU_TEST_AND_SET_VAR
2189#undef MUELU_TEST_AND_SET_PARAM_2LIST
2190#undef MUELU_TEST_PARAM_2LIST
2191#undef MUELU_KOKKOS_FACTORY
2192
2193size_t LevenshteinDistance(const char* s, size_t len_s, const char* t, size_t len_t);
2194
2195template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2197 ParameterList paramList = constParamList;
2198 const ParameterList& validList = *MasterList::List();
2199 // Validate up to maxLevels level specific parameter sublists
2200 const int maxLevels = 100;
2201
2202 // Extract level specific list
2203 std::vector<ParameterList> paramLists;
2204 for (int levelID = 0; levelID < maxLevels; levelID++) {
2205 std::string sublistName = "level " + toString(levelID);
2206 if (paramList.isSublist(sublistName)) {
2207 paramLists.push_back(paramList.sublist(sublistName));
2208 // paramLists.back().setName(sublistName);
2209 paramList.remove(sublistName);
2210 }
2211 }
2212 paramLists.push_back(paramList);
2213 // paramLists.back().setName("main");
2214#ifdef HAVE_MUELU_MATLAB
2215 // If Muemex is supported, hide custom level variables from validator by removing them from paramList's sublists
2216 for (size_t i = 0; i < paramLists.size(); i++) {
2217 std::vector<std::string> customVars; // list of names (keys) to be removed from list
2218
2219 for (Teuchos::ParameterList::ConstIterator it = paramLists[i].begin(); it != paramLists[i].end(); it++) {
2220 std::string paramName = paramLists[i].name(it);
2221
2222 if (IsParamMuemexVariable(paramName))
2223 customVars.push_back(paramName);
2224 }
2225
2226 // Remove the keys
2227 for (size_t j = 0; j < customVars.size(); j++)
2228 paramLists[i].remove(customVars[j], false);
2229 }
2230#endif
2231
2232 const int maxDepth = 0;
2233 for (size_t i = 0; i < paramLists.size(); i++) {
2234 // validate every sublist
2235 try {
2236 paramLists[i].validateParameters(validList, maxDepth);
2237
2238 } catch (const Teuchos::Exceptions::InvalidParameterName& e) {
2239 std::string eString = e.what();
2240
2241 // Parse name from: <Error, the parameter {name="smoothe: type",...>
2242 size_t nameStart = eString.find_first_of('"') + 1;
2243 size_t nameEnd = eString.find_first_of('"', nameStart);
2244 std::string name = eString.substr(nameStart, nameEnd - nameStart);
2245
2246 size_t bestScore = 100;
2247 std::string bestName = "";
2248 for (ParameterList::ConstIterator it = validList.begin(); it != validList.end(); it++) {
2249 const std::string& pName = validList.name(it);
2250 this->GetOStream(Runtime1) << "| " << pName;
2251 size_t score = LevenshteinDistance(name.c_str(), name.length(), pName.c_str(), pName.length());
2252 this->GetOStream(Runtime1) << " -> " << score << std::endl;
2253 if (score < bestScore) {
2254 bestScore = score;
2255 bestName = pName;
2256 }
2257 }
2258 if (bestScore < 10 && bestName != "") {
2259 TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameterName,
2260 eString << "The parameter name \"" + name + "\" is not valid. Did you mean \"" + bestName << "\"?\n");
2261
2262 } else {
2263 TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameterName,
2264 eString << "The parameter name \"" + name + "\" is not valid.\n");
2265 }
2266 }
2267 }
2268}
2269
2270// =====================================================================================================
2271// ==================================== FACTORY interpreter ============================================
2272// =====================================================================================================
2273template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2275 SetFactoryParameterList(const ParameterList& constParamList) {
2276 // Create a non const copy of the parameter list
2277 // Working with a modifiable list is much much easier than with original one
2278 ParameterList paramList = constParamList;
2279
2280 // Parameter List Parsing:
2281 // ---------
2282 // <ParameterList name="MueLu">
2283 // <ParameterList name="Matrix">
2284 // </ParameterList>
2285 if (paramList.isSublist("Matrix")) {
2286 blockSize_ = paramList.sublist("Matrix").get<int>("PDE equations", MasterList::getDefault<int>("number of equations"));
2287 dofOffset_ = paramList.sublist("Matrix").get<GlobalOrdinal>("DOF offset", 0); // undocumented parameter allowing to define a DOF offset of the global dofs of an operator (defaul = 0)
2288 }
2289
2290 // create new FactoryFactory object if necessary
2291 if (factFact_ == Teuchos::null)
2292 factFact_ = Teuchos::rcp(new FactoryFactory());
2293
2294 // Parameter List Parsing:
2295 // ---------
2296 // <ParameterList name="MueLu">
2297 // <ParameterList name="Factories"> <== call BuildFactoryMap() on this parameter list
2298 // ...
2299 // </ParameterList>
2300 // </ParameterList>
2301 FactoryMap factoryMap;
2302 FactoryManagerMap factoryManagers;
2303 if (paramList.isSublist("Factories"))
2304 this->BuildFactoryMap(paramList.sublist("Factories"), factoryMap, factoryMap, factoryManagers);
2305
2306 // Parameter List Parsing:
2307 // ---------
2308 // <ParameterList name="MueLu">
2309 // <ParameterList name="Hierarchy">
2310 // <Parameter name="verbose" type="string" value="Warnings"/> <== get
2311 // <Parameter name="numDesiredLevel" type="int" value="10"/> <== get
2312 //
2313 // <ParameterList name="firstLevel"> <== parse first args and call BuildFactoryMap() on the rest of this parameter list
2314 // ...
2315 // </ParameterList>
2316 // </ParameterList>
2317 // </ParameterList>
2318 if (paramList.isSublist("Hierarchy")) {
2319 ParameterList hieraList = paramList.sublist("Hierarchy"); // copy because list temporally modified (remove 'id')
2320
2321 // Get hierarchy options
2322 if (hieraList.isParameter("max levels")) {
2323 this->numDesiredLevel_ = hieraList.get<int>("max levels");
2324 hieraList.remove("max levels");
2325 }
2326
2327 if (hieraList.isParameter("coarse: max size")) {
2328 this->maxCoarseSize_ = hieraList.get<int>("coarse: max size");
2329 hieraList.remove("coarse: max size");
2330 }
2331
2332 if (hieraList.isParameter("repartition: rebalance P and R")) {
2333 this->doPRrebalance_ = hieraList.get<bool>("repartition: rebalance P and R");
2334 hieraList.remove("repartition: rebalance P and R");
2335 }
2336
2337 if (hieraList.isParameter("transpose: use implicit")) {
2338 this->implicitTranspose_ = hieraList.get<bool>("transpose: use implicit");
2339 hieraList.remove("transpose: use implicit");
2340 }
2341
2342 if (hieraList.isParameter("fuse prolongation and update")) {
2343 this->fuseProlongationAndUpdate_ = hieraList.get<bool>("fuse prolongation and update");
2344 hieraList.remove("fuse prolongation and update");
2345 }
2346
2347 if (hieraList.isParameter("nullspace: suppress dimension check")) {
2348 this->suppressNullspaceDimensionCheck_ = hieraList.get<bool>("nullspace: suppress dimension check");
2349 hieraList.remove("nullspace: suppress dimension check");
2350 }
2351
2352 if (hieraList.isParameter("number of vectors")) {
2353 this->sizeOfMultiVectors_ = hieraList.get<int>("number of vectors");
2354 hieraList.remove("number of vectors");
2355 }
2356
2357 if (hieraList.isSublist("matvec params"))
2358 this->matvecParams_ = Teuchos::parameterList(hieraList.sublist("matvec params"));
2359
2360 if (hieraList.isParameter("coarse grid correction scaling factor")) {
2361 this->scalingFactor_ = hieraList.get<double>("coarse grid correction scaling factor");
2362 hieraList.remove("coarse grid correction scaling factor");
2363 }
2364
2365 // Translate cycle type parameter
2366 if (hieraList.isParameter("cycle type")) {
2367 std::map<std::string, CycleType> cycleMap;
2368 cycleMap["V"] = VCYCLE;
2369 cycleMap["W"] = WCYCLE;
2370
2371 std::string cycleType = hieraList.get<std::string>("cycle type");
2372 TEUCHOS_TEST_FOR_EXCEPTION(cycleMap.count(cycleType) == 0, Exceptions::RuntimeError, "Invalid cycle type: \"" << cycleType << "\"");
2373 this->Cycle_ = cycleMap[cycleType];
2374 }
2375
2376 if (hieraList.isParameter("W cycle start level")) {
2377 this->WCycleStartLevel_ = hieraList.get<int>("W cycle start level");
2378 }
2379
2380 if (hieraList.isParameter("verbosity")) {
2381 std::string vl = hieraList.get<std::string>("verbosity");
2382 hieraList.remove("verbosity");
2383 this->verbosity_ = toVerbLevel(vl);
2384 }
2385
2386 if (hieraList.isParameter("output filename"))
2387 VerboseObject::SetMueLuOFileStream(hieraList.get<std::string>("output filename"));
2388
2389 if (hieraList.isParameter("dependencyOutputLevel"))
2390 this->graphOutputLevel_ = hieraList.get<int>("dependencyOutputLevel");
2391
2392 // Check for the reuse case
2393 if (hieraList.isParameter("reuse"))
2395
2396 if (hieraList.isSublist("DataToWrite")) {
2397 // TODO We should be able to specify any data. If it exists, write it.
2398 // TODO This would requires something like std::set<dataName, Array<int> >
2399 ParameterList foo = hieraList.sublist("DataToWrite");
2400 std::string dataName = "Matrices";
2401 if (foo.isParameter(dataName))
2402 this->matricesToPrint_["A"] = Teuchos::getArrayFromStringParameter<int>(foo, dataName);
2403 dataName = "Prolongators";
2404 if (foo.isParameter(dataName))
2405 this->matricesToPrint_["P"] = Teuchos::getArrayFromStringParameter<int>(foo, dataName);
2406 dataName = "Restrictors";
2407 if (foo.isParameter(dataName))
2408 this->matricesToPrint_["R"] = Teuchos::getArrayFromStringParameter<int>(foo, dataName);
2409 dataName = "D0";
2410 if (foo.isParameter(dataName))
2411 this->matricesToPrint_["D0"] = Teuchos::getArrayFromStringParameter<int>(foo, dataName);
2412 }
2413
2414 // Get level configuration
2415 for (ParameterList::ConstIterator param = hieraList.begin(); param != hieraList.end(); ++param) {
2416 const std::string& paramName = hieraList.name(param);
2417
2418 if (paramName != "DataToWrite" && hieraList.isSublist(paramName)) {
2419 ParameterList levelList = hieraList.sublist(paramName); // copy because list temporally modified (remove 'id')
2420
2421 int startLevel = 0;
2422 if (levelList.isParameter("startLevel")) {
2423 startLevel = levelList.get<int>("startLevel");
2424 levelList.remove("startLevel");
2425 }
2426 int numDesiredLevel = 1;
2427 if (levelList.isParameter("numDesiredLevel")) {
2428 numDesiredLevel = levelList.get<int>("numDesiredLevel");
2429 levelList.remove("numDesiredLevel");
2430 }
2431
2432 // Parameter List Parsing:
2433 // ---------
2434 // <ParameterList name="firstLevel">
2435 // <Parameter name="startLevel" type="int" value="0"/>
2436 // <Parameter name="numDesiredLevel" type="int" value="1"/>
2437 // <Parameter name="verbose" type="string" value="Warnings"/>
2438 //
2439 // [] <== call BuildFactoryMap() on the rest of the parameter list
2440 //
2441 // </ParameterList>
2442 FactoryMap levelFactoryMap;
2443 BuildFactoryMap(levelList, factoryMap, levelFactoryMap, factoryManagers);
2444
2445 RCP<FactoryManager> m = rcp(new FactoryManager(levelFactoryMap));
2446 if (hieraList.isParameter("use kokkos refactor"))
2447 m->SetKokkosRefactor(hieraList.get<bool>("use kokkos refactor"));
2448
2449 if (startLevel >= 0)
2450 this->AddFactoryManager(startLevel, numDesiredLevel, m);
2451 else
2452 TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "MueLu::ParameterListInterpreter():: invalid level id");
2453 } /* TODO: else { } */
2454 }
2455 }
2456}
2457
2458// TODO: static?
2492
2544
2581template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2583 BuildFactoryMap(const ParameterList& paramList, const FactoryMap& factoryMapIn, FactoryMap& factoryMapOut, FactoryManagerMap& factoryManagers) const {
2584 for (ParameterList::ConstIterator param = paramList.begin(); param != paramList.end(); ++param) {
2585 const std::string& paramName = paramList.name(param); //< paramName contains the user chosen factory name (e.g., "smootherFact1")
2586 const Teuchos::ParameterEntry& paramValue = paramList.entry(param); //< for factories, paramValue should be either a list or just a MueLu Factory (e.g., TrilinosSmoother)
2587
2588 // TODO: do not allow name of existing MueLu classes (can be tested using FactoryFactory)
2589
2590 if (paramValue.isList()) {
2591 ParameterList paramList1 = Teuchos::getValue<ParameterList>(paramValue);
2592 if (paramList1.isParameter("factory")) { // default: just a factory definition
2593 // New Factory is a sublist with internal parameters and/or data dependencies
2594 TEUCHOS_TEST_FOR_EXCEPTION(paramList1.isParameter("dependency for") == true, Exceptions::RuntimeError,
2595 "MueLu::ParameterListInterpreter(): It seems that in the parameter lists for defining " << paramName << " there is both a 'factory' and 'dependency for' parameter. This is not allowed. Please remove the 'dependency for' parameter.");
2596
2597 factoryMapOut[paramName] = factFact_->BuildFactory(paramValue, factoryMapIn, factoryManagers);
2598
2599 } else if (paramList1.isParameter("dependency for")) { // add more data dependencies to existing factory
2600 TEUCHOS_TEST_FOR_EXCEPTION(paramList1.isParameter("factory") == true, Exceptions::RuntimeError,
2601 "MueLu::ParameterListInterpreter(): It seems that in the parameter lists for defining " << paramName << " there is both a 'factory' and 'dependency for' parameter. This is not allowed.");
2602
2603 std::string factoryName = paramList1.get<std::string>("dependency for");
2604
2605 RCP<const FactoryBase> factbase = factoryMapIn.find(factoryName /*paramName*/)->second; // access previously defined factory
2606 TEUCHOS_TEST_FOR_EXCEPTION(factbase.is_null() == true, Exceptions::RuntimeError,
2607 "MueLu::ParameterListInterpreter(): could not find factory " + factoryName + " in factory map. Did you define it before?");
2608
2609 RCP<const Factory> factoryconst = Teuchos::rcp_dynamic_cast<const Factory>(factbase);
2610 RCP<Factory> factory = Teuchos::rcp_const_cast<Factory>(factoryconst);
2611
2612 // Read the RCP<Factory> parameters of the class T
2613 RCP<const ParameterList> validParamList = factory->GetValidParameterList();
2614 for (ParameterList::ConstIterator vparam = validParamList->begin(); vparam != validParamList->end(); ++vparam) {
2615 const std::string& pName = validParamList->name(vparam);
2616
2617 if (!paramList1.isParameter(pName)) {
2618 // Ignore unknown parameters
2619 continue;
2620 }
2621
2622 if (validParamList->isType<RCP<const FactoryBase> >(pName)) {
2623 // Generate or get factory described by pName and set dependency
2624 RCP<const FactoryBase> generatingFact = factFact_->BuildFactory(paramList1.getEntry(pName), factoryMapIn, factoryManagers);
2625 factory->SetFactory(pName, generatingFact.create_weak());
2626
2627 } else if (validParamList->isType<RCP<const ParameterList> >(pName)) {
2628 if (pName == "ParameterList") {
2629 // NOTE: we cannot use
2630 // subList = sublist(rcpFromRef(paramList), pName)
2631 // here as that would result in sublist also being a reference to a temporary object.
2632 // The resulting dereferencing in the corresponding factory would then segfault
2633 RCP<const ParameterList> subList = Teuchos::sublist(rcp(new ParameterList(paramList1)), pName);
2634 factory->SetParameter(pName, ParameterEntry(subList));
2635 }
2636 } else {
2637 factory->SetParameter(pName, paramList1.getEntry(pName));
2638 }
2639 }
2640
2641 } else if (paramList1.isParameter("group")) { // definitiion of a factory group (for a factory manager)
2642 // Define a new (sub) FactoryManager
2643 std::string groupType = paramList1.get<std::string>("group");
2644 TEUCHOS_TEST_FOR_EXCEPTION(groupType != "FactoryManager", Exceptions::RuntimeError,
2645 "group must be of type \"FactoryManager\".");
2646
2647 ParameterList groupList = paramList1; // copy because list temporally modified (remove 'id')
2648 groupList.remove("group");
2649
2650 bool setKokkosRefactor = false;
2651 bool kokkosRefactor = useKokkos_;
2652 if (groupList.isParameter("use kokkos refactor")) {
2653 kokkosRefactor = groupList.get<bool>("use kokkos refactor");
2654 groupList.remove("use kokkos refactor");
2655 setKokkosRefactor = true;
2656 }
2657
2658 FactoryMap groupFactoryMap;
2659 BuildFactoryMap(groupList, factoryMapIn, groupFactoryMap, factoryManagers);
2660
2661 // do not store groupFactoryMap in factoryMapOut
2662 // Create a factory manager object from groupFactoryMap
2663 RCP<FactoryManager> m = rcp(new FactoryManager(groupFactoryMap));
2664 if (setKokkosRefactor)
2665 m->SetKokkosRefactor(kokkosRefactor);
2666 factoryManagers[paramName] = m;
2667
2668 } else {
2669 this->GetOStream(Warnings0) << "Could not interpret parameter list " << paramList1 << std::endl;
2670 TEUCHOS_TEST_FOR_EXCEPTION(false, Exceptions::RuntimeError,
2671 "XML Parameter list must either be of type \"factory\" or of type \"group\".");
2672 }
2673 } else {
2674 // default: just a factory (no parameter list)
2675 factoryMapOut[paramName] = factFact_->BuildFactory(paramValue, factoryMapIn, factoryManagers);
2676 }
2677 }
2678}
2679
2680// =====================================================================================================
2681// ======================================= MISC functions ==============================================
2682// =====================================================================================================
2683template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2685 try {
2686 Matrix& A = dynamic_cast<Matrix&>(Op);
2687 if (A.IsFixedBlockSizeSet() && (A.GetFixedBlockSize() != blockSize_))
2688 this->GetOStream(Warnings0) << "Setting matrix block size to " << blockSize_ << " (value of the parameter in the list) "
2689 << "instead of " << A.GetFixedBlockSize() << " (provided matrix)." << std::endl
2690 << "You may want to check \"number of equations\" (or \"PDE equations\" for factory style list) parameter." << std::endl;
2691
2692 A.SetFixedBlockSize(blockSize_, dofOffset_);
2693
2694#ifdef HAVE_MUELU_DEBUG
2695 MatrixUtils::checkLocalRowMapMatchesColMap(A);
2696#endif // HAVE_MUELU_DEBUG
2697
2698 } catch (std::bad_cast&) {
2699 this->GetOStream(Warnings0) << "Skipping setting block size as the operator is not a matrix" << std::endl;
2700 }
2701}
2702
2703template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2710
2711static bool compare(const ParameterList& list1, const ParameterList& list2) {
2712 // First loop through and validate the parameters at this level.
2713 // In addition, we generate a list of sublists that we will search next
2714 for (ParameterList::ConstIterator it = list1.begin(); it != list1.end(); it++) {
2715 const std::string& name = it->first;
2716 const Teuchos::ParameterEntry& entry1 = it->second;
2717
2718 const Teuchos::ParameterEntry* entry2 = list2.getEntryPtr(name);
2719 if (!entry2) // entry is not present in the second list
2720 return false;
2721 if (entry1.isList() && entry2->isList()) { // sublist check
2722 compare(Teuchos::getValue<ParameterList>(entry1), Teuchos::getValue<ParameterList>(*entry2));
2723 continue;
2724 }
2725 if (entry1.getAny(false) != entry2->getAny(false)) // entries have different types or different values
2726 return false;
2727 }
2728
2729 return true;
2730}
2731
2732static inline bool areSame(const ParameterList& list1, const ParameterList& list2) {
2733 return compare(list1, list2) && compare(list2, list1);
2734}
2735
2736} // namespace MueLu
2737
2738#define MUELU_PARAMETERLISTINTERPRETER_SHORT
2739#endif /* MUELU_PARAMETERLISTINTERPRETER_DEF_HPP */
#define MUELU_TEST_AND_SET_VAR(paramList, paramName, paramType, varName)
#define MUELU_SET_VAR_2LIST(paramList, defaultList, paramName, paramType, varName)
#define TEST_MUTUALLY_EXCLUSIVE_S(arg1, arg2)
#define MUELU_KOKKOS_FACTORY_NO_DECL(varName, oldFactory, newFactory)
#define MUELU_TEST_PARAM_2LIST(paramList, defaultList, paramName, paramType, cmpValue)
#define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory)
#define TEST_MUTUALLY_EXCLUSIVE(arg1, arg2)
#define MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, paramName, paramType, listWrite)
MueLu::DefaultScalar Scalar
MueLu::DefaultGlobalOrdinal GlobalOrdinal
An factory which assigns each aggregate a quality estimate. Originally developed by Napov and Notay i...
Factory to export aggregation info or visualize aggregates using VTK.
AmalgamationFactory for subblocks of strided map based amalgamation data.
Factory for generating F/C-splitting and a coarse level map. Used by ClassicalPFactory.
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.
Prolongator factory that replicates 'Psubblock' matrix to create new prolongator suitable for PDE sys...
Factory for building the constraint operator.
Class for transferring coordinates from a finer level to a coarser one.
Class that encapsulates direct solvers. Autoselection of AmesosSmoother or Amesos2Smoother according ...
Factory for building Energy Minimization prolongators.
Exception throws to report invalid user entry.
Exception throws to report errors in the internal logical of the program.
Factory that can generate other factories from.
This class specifies the default factory that should generate some data on a Level if the data does n...
void SetFactory(const std::string &varName, const RCP< const FactoryBase > &factory)
Set Factory.
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).
static void EnableTimerSync()
static void DisableMultipleCheckGlobally()
Factory for building filtered matrices using filtered graphs.
Factory for building restriction operators using a prolongator factory.
void AddFactoryManager(int startLevel, int numDesiredLevel, RCP< FactoryManagerBase > manager)
virtual void SetupHierarchy(Hierarchy &H) const
Setup Hierarchy object.
Provides methods to build a multigrid hierarchy and apply multigrid cycles.
static CycleType GetDefaultCycle()
void SetCycleStartLevel(int cycleStart)
static int GetDefaultCycleStartLevel()
void SetCycle(CycleType Cycle)
Supports VCYCLE and WCYCLE types.
void SetProlongatorScalingFactor(double scalingFactor)
Specify damping factor alpha such that x = x + alpha*P*c, where c is the coarse grid correction.
Class for generating an initial LocalOrdinal-type BlockNumber vector, based on an input paraemter for...
Factory for building transfer operators based on coarsening in polynomial degree, following the Intre...
Factory for building line detection information.
Class for transferring a vector of local ordinals from a finer level to a coarser one,...
Factory for converting matrices to half precision operators.
static Teuchos::RCP< Teuchos::ParameterList > GetProblemSpecificList(std::string const &problemType)
Return default parameter settings for the specified problem type.
static const T & getDefault(const std::string &name)
Returns default value on the "master" list for a parameter with the specified name and type.
static Teuchos::RCP< const Teuchos::ParameterList > List()
Return a "master" list of all valid parameters and their default values.
Class that encapsulates Matlab smoothers.
This class checks matrix properties of A on current level. This factory can be plugged in everywhere ...
Class for restricting a MultiVector from a finer to a coarser level.
static const RCP< const NoFactory > getRCP()
Static Get() functions.
Factory for generating nullspace.
void UpdateFactoryManager_SA(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void UpdateFactoryManager_Nullspace(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps, RCP< Factory > &nullSpaceFactory) const
void UpdateFactoryManager_Reitzinger(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void UpdateFactoryManager_RAP(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void UpdateFactoryManager_Smoothers(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void UpdateFactoryManager_Aggregation_TentativeP(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void SetEasyParameterList(const Teuchos::ParameterList &paramList)
GlobalOrdinal dofOffset_
global offset variable describing offset of DOFs in operator
void UpdateFactoryManager_Coordinates(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
int blockSize_
block size of matrix (fixed block size)
void BuildFactoryMap(const Teuchos::ParameterList &paramList, const FactoryMap &factoryMapIn, FactoryMap &factoryMapOut, FactoryManagerMap &factoryManagers) const
Interpret "Factories" sublist.
int WCycleStartLevel_
in case of W-cycle, level on which cycle should start
void UpdateFactoryManager_Restriction(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
virtual void SetupOperator(Operator &A) const
Setup Operator object.
void UpdateFactoryManager_Replicate(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void UpdateFactoryManager_LowPrecision(ParameterList &paramList, const ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void UpdateFactoryManager_PCoarsen(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
Teuchos::RCP< MueLu::FacadeClassFactory< Scalar, LocalOrdinal, GlobalOrdinal, Node > > facadeFact_
FacadeClass factory.
std::pair< std::string, const FactoryBase * > keep_pair
void UpdateFactoryManager_PG(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void SetParameterList(const Teuchos::ParameterList &paramList)
Set parameter list for Parameter list interpreter.
void UpdateFactoryManager_Material(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void Validate(const Teuchos::ParameterList &paramList) const
void UpdateFactoryManager_Emin(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void UpdateFactoryManager_Combine(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
CycleType Cycle_
multigrid cycle type (V-cycle or W-cycle)
void UpdateFactoryManager_Matlab(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
std::map< std::string, RCP< FactoryManagerBase > > FactoryManagerMap
virtual ~ParameterListInterpreter()
Destructor.
void UpdateFactoryManager_LocalOrdinalTransfer(const std::string &VarName, const std::string &multigridAlgo, Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
Teuchos::RCP< FactoryFactory > factFact_
Internal factory for factories.
void UpdateFactoryManager_SemiCoarsen(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void UpdateFactoryManager_BlockNumber(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void UpdateFactoryManager(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
std::map< std::string, RCP< const FactoryBase > > FactoryMap
void SetupHierarchy(Hierarchy &H) const
Call the SetupHierarchy routine from the HiearchyManager object.
void SetFactoryParameterList(const Teuchos::ParameterList &paramList)
Factory interpreter stuff.
void UpdateFactoryManager_CoarseSolvers(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void UpdateFactoryManager_Repartition(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps, RCP< Factory > &nullSpaceFactory) const
Factory for building nonzero patterns for energy minimization.
Factory for building Petrov-Galerkin Smoothed Aggregation prolongators.
Factory for building coarse matrices.
Factory for building coarse grid matrices, when the matrix is of the form K+a*M. Useful when you want...
Factory for building coarse matrices.
Applies permutation to grid transfer operators.
Factory for building tentative prolongator.
Factory for building permutation matrix that can be be used to shuffle data (matrices,...
Factory for determing the number of partitions for rebalancing.
Prolongator factory that replicates 'Psubblock' matrix to create new prolongator suitable for PDE sys...
Factory for building Smoothed Aggregation prolongators.
Factory for generating a very special nullspace.
Prolongator factory performing semi-coarsening.
Prolongator factory performing semi-coarsening.
Factory for creating a graph base on a given matrix.
Generic Smoother Factory for generating the smoothers of the MG hierarchy.
Factory for building tentative prolongator.
Class for transferring coordinates from a finer level to a coarser one.
Prolongator factory which allows switching between two different prolongator strategies.
Factory for building restriction operators.
Class that encapsulates external library smoothers.
Factory for interacting with Matlab.
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
static VerbLevel GetDefaultVerbLevel()
Get the default (global) verbosity level.
static void SetDefaultVerbLevel(const VerbLevel defaultVerbLevel)
Set the default (global) verbosity level.
static void SetMueLuOFileStream(const std::string &filename)
Interface to Zoltan2 library.
Interface to Zoltan library.
Namespace for MueLu classes and methods.
bool IsParamMuemexVariable(const std::string &name)
long ExtractNonSerializableData(const Teuchos::ParameterList &inList, Teuchos::ParameterList &serialList, Teuchos::ParameterList &nonSerialList)
Extract non-serializable data from level-specific sublists and move it to a separate parameter list.
@ Warnings0
Important warning messages (one line).
@ Runtime0
One-liner description of what is happening.
@ Runtime1
Description of what is happening (more verbose).
@ Warnings1
Additional warnings.
size_t LevenshteinDistance(const char *s, size_t len_s, const char *t, size_t len_t)
MsgType toVerbLevel(const std::string &verbLevelStr)
static bool areSame(const ParameterList &list1, const ParameterList &list2)
Helper functions to compare two paramter lists.
static bool compare(const ParameterList &list1, const ParameterList &list2)
std::string toString(const T &what)
Little helper function to convert non-string types to strings.