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