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