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