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