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