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 //
5 // MueLu: A package for multigrid based preconditioning
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 #ifndef MUELU_PARAMETERLISTINTERPRETER_DEF_HPP
47 #define MUELU_PARAMETERLISTINTERPRETER_DEF_HPP
48 
50 
51 #include <Xpetra_Matrix.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_BrickAggregationFactory.hpp"
64 #include "MueLu_CoalesceDropFactory.hpp"
65 #include "MueLu_CoarseMapFactory.hpp"
66 #include "MueLu_ConstraintFactory.hpp"
67 #include "MueLu_CoordinatesTransferFactory.hpp"
68 #include "MueLu_CoupledAggregationFactory.hpp"
69 #include "MueLu_DirectSolver.hpp"
70 #include "MueLu_EminPFactory.hpp"
71 #include "MueLu_Exceptions.hpp"
72 #include "MueLu_FacadeClassFactory.hpp"
73 #include "MueLu_FactoryFactory.hpp"
74 #include "MueLu_FilteredAFactory.hpp"
75 #include "MueLu_GenericRFactory.hpp"
76 #include "MueLu_LineDetectionFactory.hpp"
77 #include "MueLu_MasterList.hpp"
78 #include "MueLu_NullspaceFactory.hpp"
79 #include "MueLu_PatternFactory.hpp"
80 #include "MueLu_PgPFactory.hpp"
81 #include "MueLu_RAPFactory.hpp"
82 #include "MueLu_RAPShiftFactory.hpp"
83 #include "MueLu_RebalanceAcFactory.hpp"
84 #include "MueLu_RebalanceTransferFactory.hpp"
85 #include "MueLu_RepartitionFactory.hpp"
86 #include "MueLu_SaPFactory.hpp"
87 #include "MueLu_SemiCoarsenPFactory.hpp"
88 #include "MueLu_SmootherFactory.hpp"
89 #include "MueLu_TentativePFactory.hpp"
90 #include "MueLu_TogglePFactory.hpp"
91 #include "MueLu_ToggleCoordinatesTransferFactory.hpp"
92 #include "MueLu_TransPFactory.hpp"
93 #include "MueLu_UncoupledAggregationFactory.hpp"
94 #include "MueLu_HybridAggregationFactory.hpp"
95 #include "MueLu_ZoltanInterface.hpp"
96 #include "MueLu_Zoltan2Interface.hpp"
97 #include "MueLu_NodePartitionInterface.hpp"
98 
99 #ifdef HAVE_MUELU_KOKKOS_REFACTOR
100 #include "MueLu_CoalesceDropFactory_kokkos.hpp"
101 #include "MueLu_CoarseMapFactory_kokkos.hpp"
102 #include "MueLu_CoordinatesTransferFactory_kokkos.hpp"
103 #include "MueLu_NullspaceFactory_kokkos.hpp"
104 #include "MueLu_SaPFactory_kokkos.hpp"
105 #include "MueLu_TentativePFactory_kokkos.hpp"
106 #include "MueLu_UncoupledAggregationFactory_kokkos.hpp"
107 #endif
108 
109 #ifdef HAVE_MUELU_MATLAB
110 #include "../matlab/src/MueLu_MatlabSmoother_decl.hpp"
111 #include "../matlab/src/MueLu_MatlabSmoother_def.hpp"
112 #include "../matlab/src/MueLu_TwoLevelMatlabFactory_decl.hpp"
113 #include "../matlab/src/MueLu_TwoLevelMatlabFactory_def.hpp"
114 #include "../matlab/src/MueLu_SingleLevelMatlabFactory_decl.hpp"
115 #include "../matlab/src/MueLu_SingleLevelMatlabFactory_def.hpp"
116 #endif
117 
118 #ifdef HAVE_MUELU_INTREPID2
119 #include "MueLu_IntrepidPCoarsenFactory.hpp"
120 #endif
121 
122 #include <unordered_set>
123 
124 namespace MueLu {
125 
126  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
128  RCP<Teuchos::TimeMonitor> tM = rcp(new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(std::string("MueLu: ParameterListInterpreter (ParameterList)"))));
129  if(facadeFact == Teuchos::null)
131  else
132  facadeFact_ = facadeFact;
133 
134  if (paramList.isParameter("xml parameter file")) {
135  std::string filename = paramList.get("xml parameter file", "");
136  if (filename.length() != 0) {
137  TEUCHOS_TEST_FOR_EXCEPTION(comm.is_null(), Exceptions::RuntimeError, "xml parameter file requires a valid comm");
138 
139  ParameterList paramList2 = paramList;
140  Teuchos::updateParametersFromXmlFileAndBroadcast(filename, Teuchos::Ptr<Teuchos::ParameterList>(&paramList2), *comm);
141  SetParameterList(paramList2);
142 
143  } else {
144  SetParameterList(paramList);
145  }
146 
147  } else {
148  SetParameterList(paramList);
149  }
150  }
151 
152  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
154  RCP<Teuchos::TimeMonitor> tM = rcp(new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(std::string("MueLu: ParameterListInterpreter (XML)"))));
155  if(facadeFact == Teuchos::null)
157  else
158  facadeFact_ = facadeFact;
159 
160  ParameterList paramList;
161  Teuchos::updateParametersFromXmlFileAndBroadcast(xmlFileName, Teuchos::Ptr<ParameterList>(&paramList), comm);
162  SetParameterList(paramList);
163  }
164 
165  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
167  Cycle_ = Hierarchy::GetDefaultCycle();
168  scalingFactor_= Teuchos::ScalarTraits<double>::one();
169  blockSize_ = 1;
170  dofOffset_ = 0;
171 
172  if (paramList.isSublist("Hierarchy")) {
173  SetFactoryParameterList(paramList);
174 
175  } else if (paramList.isParameter("MueLu preconditioner") == true) {
176  this->GetOStream(Runtime0) << "Use facade class: " << paramList.get<std::string>("MueLu preconditioner") << std::endl;
177  Teuchos::RCP<ParameterList> pp = facadeFact_->SetParameterList(paramList);
178  SetFactoryParameterList(*pp);
179 
180  } else {
181  // The validator doesn't work correctly for non-serializable data (Hint: template parameters), so strip it out
182  ParameterList serialList, nonSerialList;
183 
184  ExtractNonSerializableData(paramList, serialList, nonSerialList);
185  Validate(serialList);
186  SetEasyParameterList(paramList);
187  }
188  }
189 
190  // =====================================================================================================
191  // ====================================== EASY interpreter =============================================
192  // =====================================================================================================
194  static inline bool areSame(const ParameterList& list1, const ParameterList& list2);
195 
196  // Get value from one of the lists, or set it to default
197  // Use case: check for a parameter value in a level-specific sublist, then in a root level list;
198  // if it is absent from both, set it to default
199 #define MUELU_SET_VAR_2LIST(paramList, defaultList, paramName, paramType, varName) \
200  paramType varName; \
201  if (paramList.isParameter(paramName)) varName = paramList.get<paramType>(paramName); \
202  else if (defaultList.isParameter(paramName)) varName = defaultList.get<paramType>(paramName); \
203  else varName = MasterList::getDefault<paramType>(paramName);
204 
205 #define MUELU_TEST_AND_SET_VAR(paramList, paramName, paramType, varName) \
206  (paramList.isParameter(paramName) ? varName = paramList.get<paramType>(paramName), true : false)
207 
208  // Set parameter in a list if it is present in any of two lists
209  // User case: set factory specific parameter, first checking for a level-specific value, then cheking root level value
210 #define MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, paramName, paramType, listWrite) \
211  try { \
212  if (paramList .isParameter(paramName)) listWrite.set(paramName, paramList .get<paramType>(paramName)); \
213  else if (defaultList.isParameter(paramName)) listWrite.set(paramName, defaultList.get<paramType>(paramName)); \
214  } \
215  catch(Teuchos::Exceptions::InvalidParameterType) { \
216  TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(true, Teuchos::Exceptions::InvalidParameterType, \
217  "Error: parameter \"" << paramName << "\" must be of type " << Teuchos::TypeNameTraits<paramType>::name()); \
218  } \
219 
220 #define MUELU_TEST_PARAM_2LIST(paramList, defaultList, paramName, paramType, cmpValue) \
221  (cmpValue == ( \
222  paramList.isParameter(paramName) ? paramList .get<paramType>(paramName) : ( \
223  defaultList.isParameter(paramName) ? defaultList.get<paramType>(paramName) : \
224  MasterList::getDefault<paramType>(paramName) ) ) )
225 
226 #ifndef HAVE_MUELU_KOKKOS_REFACTOR
227 #define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory) \
228  RCP<Factory> varName = rcp(new oldFactory());
229 #define MUELU_KOKKOS_FACTORY_NO_DECL(varName, oldFactory, newFactory) \
230  varName = rcp(new oldFactory());
231 #else
232 #define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory) \
233  RCP<Factory> varName; \
234  if (!useKokkos_) varName = rcp(new oldFactory()); \
235  else varName = rcp(new newFactory());
236 #define MUELU_KOKKOS_FACTORY_NO_DECL(varName, oldFactory, newFactory) \
237  if (!useKokkos_) varName = rcp(new oldFactory()); \
238  else varName = rcp(new newFactory());
239 #endif
240 
241  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
243  SetEasyParameterList(const ParameterList& constParamList) {
244  ParameterList paramList;
245 
246  MUELU_SET_VAR_2LIST(constParamList, constParamList, "problem: type", std::string, problemType);
247  if (problemType != "unknown") {
248  paramList = *MasterList::GetProblemSpecificList(problemType);
249  paramList.setParameters(constParamList);
250  } else {
251  // Create a non const copy of the parameter list
252  // Working with a modifiable list is much much easier than with original one
253  paramList = constParamList;
254  }
255 
256  // Check for Kokkos
257 #if !defined(HAVE_MUELU_KOKKOS_REFACTOR)
258  useKokkos_ = false;
259 #elif defined(HAVE_MUELU_KOKKOS_REFACTOR_USE_BY_DEFAULT)
260  ParameterList tempList("tempList");
261  tempList.set("use kokkos refactor",true);
262  MUELU_SET_VAR_2LIST(paramList, tempList, "use kokkos refactor", bool, useKokkos);
263  useKokkos_ = useKokkos;
264 #else
265  MUELU_SET_VAR_2LIST(paramList, paramList, "use kokkos refactor", bool, useKokkos);
266  useKokkos_ = useKokkos;
267 #endif
268 
269  // Check for timer synchronization
270  MUELU_SET_VAR_2LIST(paramList, paramList, "synchronize factory timers", bool, syncTimers);
271  if (syncTimers)
272  Factory::EnableTimerSync();
273 
274  // Translate cycle type parameter
275  if (paramList.isParameter("cycle type")) {
276  std::map<std::string, CycleType> cycleMap;
277  cycleMap["V"] = VCYCLE;
278  cycleMap["W"] = WCYCLE;
279 
280  auto cycleType = paramList.get<std::string>("cycle type");
281  TEUCHOS_TEST_FOR_EXCEPTION(cycleMap.count(cycleType) == 0, Exceptions::RuntimeError,
282  "Invalid cycle type: \"" << cycleType << "\"");
283  Cycle_ = cycleMap[cycleType];
284  }
285 
286  if (paramList.isParameter("coarse grid correction scaling factor"))
287  scalingFactor_ = paramList.get<double>("coarse grid correction scaling factor");
288 
289  this->maxCoarseSize_ = paramList.get<int> ("coarse: max size", MasterList::getDefault<int>("coarse: max size"));
290  this->numDesiredLevel_ = paramList.get<int> ("max levels", MasterList::getDefault<int>("max levels"));
291  blockSize_ = paramList.get<int> ("number of equations", MasterList::getDefault<int>("number of equations"));
292 
293  (void)MUELU_TEST_AND_SET_VAR(paramList, "debug: graph level", int, this->graphOutputLevel_);
294 
295  // Save level data
296  if (paramList.isSublist("export data")) {
297  ParameterList printList = paramList.sublist("export data");
298 
299  if (printList.isParameter("A"))
300  this->matricesToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "A");
301  if (printList.isParameter("P"))
302  this->prolongatorsToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "P");
303  if (printList.isParameter("R"))
304  this->restrictorsToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "R");
305  if (printList.isParameter("Nullspace"))
306  this->nullspaceToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "Nullspace");
307  if (printList.isParameter("Coordinates"))
308  this->coordinatesToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "Coordinates");
309  if (printList.isParameter("pcoarsen: element to node map"))
310  this->elementToNodeMapsToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "pcoarsen: element to node map");
311  }
312 
313  // Set verbosity parameter
315  {
316  std::map<std::string, MsgType> verbMap;
317  verbMap["none"] = None;
318  verbMap["low"] = Low;
319  verbMap["medium"] = Medium;
320  verbMap["high"] = High;
321  verbMap["extreme"] = Extreme;
322  verbMap["test"] = Test;
323 
324  MUELU_SET_VAR_2LIST(paramList, paramList, "verbosity", std::string, verbosityLevel);
325 
326  TEUCHOS_TEST_FOR_EXCEPTION(verbMap.count(verbosityLevel) == 0, Exceptions::RuntimeError,
327  "Invalid verbosity level: \"" << verbosityLevel << "\"");
328  this->verbosity_ = verbMap[verbosityLevel];
329  VerboseObject::SetDefaultVerbLevel(this->verbosity_);
330  }
331 
332  // Detect if we need to transfer coordinates to coarse levels. We do that iff
333  // - we use "distance laplacian" dropping on some level, or
334  // - we use a repartitioner on some level that needs coordinates
335  // - we use brick aggregation
336  // - we use Ifpack2 line partitioner
337  // This is not ideal, as we may have "repartition: enable" turned on by default
338  // and not present in the list, but it is better than nothing.
339  useCoordinates_ = false;
340  if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: drop scheme", std::string, "distance laplacian") ||
341  MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: type", std::string, "brick") ||
342  MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: export visualization data", bool, true)) {
343  useCoordinates_ = true;
344  } else if(paramList.isSublist("smoother: params")) {
345  const auto smooParamList = paramList.sublist("smoother: params");
346  if(smooParamList.isParameter("partitioner: type") &&
347  (smooParamList.get<std::string>("partitioner: type") == "line")) {
348  useCoordinates_ = true;
349  }
350  } else {
351  for (int levelID = 0; levelID < this->numDesiredLevel_; levelID++) {
352  std::string levelStr = "level " + toString(levelID);
353 
354  if (paramList.isSublist(levelStr)) {
355  const ParameterList& levelList = paramList.sublist(levelStr);
356 
357  if (MUELU_TEST_PARAM_2LIST(levelList, paramList, "aggregation: drop scheme", std::string, "distance laplacian") ||
358  MUELU_TEST_PARAM_2LIST(levelList, paramList, "aggregation: type", std::string, "brick") ||
359  MUELU_TEST_PARAM_2LIST(levelList, paramList, "aggregation: export visualization data", bool, true)) {
360  useCoordinates_ = true;
361  break;
362  }
363  }
364  }
365  }
366 
367  if(MUELU_TEST_PARAM_2LIST(paramList, paramList, "repartition: enable", bool, true)) {
368  if (!paramList.isSublist("repartition: params")) {
369  useCoordinates_ = true;
370  } else {
371  const ParameterList& repParams = paramList.sublist("repartition: params");
372  if (repParams.isType<std::string>("algorithm")) {
373  const std::string algo = repParams.get<std::string>("algorithm");
374  if (algo == "multijagged" || algo == "rcb") {
375  useCoordinates_ = true;
376  }
377  } else {
378  useCoordinates_ = true;
379  }
380  }
381  }
382  for (int levelID = 0; levelID < this->numDesiredLevel_; levelID++) {
383  std::string levelStr = "level " + toString(levelID);
384 
385  if (paramList.isSublist(levelStr)) {
386  const ParameterList& levelList = paramList.sublist(levelStr);
387 
388  if (MUELU_TEST_PARAM_2LIST(levelList, paramList, "repartition: enable", bool, true)) {
389  if (!levelList.isSublist("repartition: params")) {
390  useCoordinates_ = true;
391  break;
392  } else {
393  const ParameterList& repParams = levelList.sublist("repartition: params");
394  if (repParams.isType<std::string>("algorithm")) {
395  const std::string algo = repParams.get<std::string>("algorithm");
396  if (algo == "multijagged" || algo == "rcb"){
397  useCoordinates_ = true;
398  break;
399  }
400  } else {
401  useCoordinates_ = true;
402  break;
403  }
404  }
405  }
406  }
407  }
408 
409  // Detect if we do implicit P and R rebalance
410  changedPRrebalance_ = false;
411  if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "repartition: enable", bool, true))
412  changedPRrebalance_ = MUELU_TEST_AND_SET_VAR(paramList, "repartition: rebalance P and R", bool, this->doPRrebalance_);
413 
414  // Detect if we use implicit transpose
415  changedImplicitTranspose_ = MUELU_TEST_AND_SET_VAR(paramList, "transpose: use implicit", bool, this->implicitTranspose_);
416 
417  // Create default manager
418  // FIXME: should it be here, or higher up
419  RCP<FactoryManager> defaultManager = rcp(new FactoryManager());
420  defaultManager->SetVerbLevel(this->verbosity_);
421 
422  // We will ignore keeps0
423  std::vector<keep_pair> keeps0;
424  UpdateFactoryManager(paramList, ParameterList(), *defaultManager, 0/*levelID*/, keeps0);
425 
426  // Create level specific factory managers
427  for (int levelID = 0; levelID < this->numDesiredLevel_; levelID++) {
428  // Note, that originally if there were no level specific parameters, we
429  // simply copied the defaultManager However, with the introduction of
430  // levelID to UpdateFactoryManager (required for reuse), we can no longer
431  // guarantee that the kept variables are the same for each level even if
432  // dependency structure does not change.
433  RCP<FactoryManager> levelManager = rcp(new FactoryManager(*defaultManager));
434  levelManager->SetVerbLevel(defaultManager->GetVerbLevel());
435 
436  std::vector<keep_pair> keeps;
437  if (paramList.isSublist("level " + toString(levelID))) {
438  // We do this so the parameters on the level get flagged correctly as "used"
439  ParameterList& levelList = paramList.sublist("level " + toString(levelID), true/*mustAlreadyExist*/);
440  UpdateFactoryManager(levelList, paramList, *levelManager, levelID, keeps);
441 
442  } else {
443  ParameterList levelList;
444  UpdateFactoryManager(levelList, paramList, *levelManager, levelID, keeps);
445  }
446 
447  this->keep_[levelID] = keeps;
448  this->AddFactoryManager(levelID, 1, levelManager);
449  }
450 
451  // FIXME: parameters passed to packages, like Ifpack2, are not touched by us, resulting in "[unused]" flag
452  // being displayed. On the other hand, we don't want to simply iterate through them touching. I don't know
453  // what a good solution looks like
454  if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "print initial parameters", bool, true))
455  this->GetOStream(static_cast<MsgType>(Runtime1), 0) << paramList << std::endl;
456 
457  if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "print unused parameters", bool, true)) {
458  // Check unused parameters
459  ParameterList unusedParamList;
460 
461  // Check for unused parameters that aren't lists
462  for (ParameterList::ConstIterator it = paramList.begin(); it != paramList.end(); it++) {
463  const ParameterEntry& entry = paramList.entry(it);
464 
465  if (!entry.isList() && !entry.isUsed())
466  unusedParamList.setEntry(paramList.name(it), entry);
467  }
468 
469  // Check for unused parameters in level-specific sublists
470  for (int levelID = 0; levelID < this->numDesiredLevel_; levelID++) {
471  std::string levelStr = "level " + toString(levelID);
472 
473  if (paramList.isSublist(levelStr)) {
474  const ParameterList& levelList = paramList.sublist(levelStr);
475 
476  for (ParameterList::ConstIterator itr = levelList.begin(); itr != levelList.end(); ++itr) {
477  const ParameterEntry& entry = levelList.entry(itr);
478 
479  if (!entry.isList() && !entry.isUsed())
480  unusedParamList.sublist(levelStr).setEntry(levelList.name(itr), entry);
481  }
482  }
483  }
484 
485  if (unusedParamList.numParams() > 0) {
486  std::ostringstream unusedParamsStream;
487  int indent = 4;
488  unusedParamList.print(unusedParamsStream, indent);
489 
490  this->GetOStream(Warnings1) << "The following parameters were not used:\n" << unusedParamsStream.str() << std::endl;
491  }
492  }
493 
495  }
496 
497 
498  // =====================================================================================================
499  // ==================================== UpdateFactoryManager ===========================================
500  // =====================================================================================================
501  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
503  UpdateFactoryManager(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
504  int levelID, std::vector<keep_pair>& keeps) const
505  {
506  // NOTE: Factory::SetParameterList must be called prior to Factory::SetFactory, as
507  // SetParameterList sets default values for non mentioned parameters, including factories
508 
509  using strings = std::unordered_set<std::string>;
510 
511  // shortcut
512  if (paramList.numParams() == 0 && defaultList.numParams() > 0)
513  paramList = ParameterList(defaultList);
514 
515  MUELU_SET_VAR_2LIST(paramList, defaultList, "reuse: type", std::string, reuseType);
516  TEUCHOS_TEST_FOR_EXCEPTION(strings({"none", "tP", "RP", "emin", "RAP", "full", "S"}).count(reuseType) == 0,
517  Exceptions::RuntimeError, "Unknown \"reuse: type\" value: \"" << reuseType << "\". Please consult User's Guide.");
518 
519  MUELU_SET_VAR_2LIST(paramList, defaultList, "multigrid algorithm", std::string, multigridAlgo);
520  TEUCHOS_TEST_FOR_EXCEPTION(strings({"unsmoothed", "sa", "pg", "emin", "matlab", "pcoarsen"}).count(multigridAlgo) == 0,
521  Exceptions::RuntimeError, "Unknown \"multigrid algorithm\" value: \"" << multigridAlgo << "\". Please consult User's Guide.");
522 #ifndef HAVE_MUELU_MATLAB
523  TEUCHOS_TEST_FOR_EXCEPTION(multigridAlgo == "matlab", Exceptions::RuntimeError,
524  "Cannot use matlab for multigrid algorithm - MueLu was not configured with MATLAB support.");
525 #endif
526 #ifndef HAVE_MUELU_INTREPID2
527  TEUCHOS_TEST_FOR_EXCEPTION(multigridAlgo == "pcoarsen", Exceptions::RuntimeError,
528  "Cannot use IntrepidPCoarsen prolongator factory - MueLu was not configured with Intrepid support.");
529 #endif
530 
531  // Only some combinations of reuse and multigrid algorithms are tested, all
532  // other are considered invalid at the moment
533  if (reuseType == "none" || reuseType == "S" || reuseType == "RP" || reuseType == "RAP") {
534  // This works for all kinds of multigrid algorithms
535 
536  } else if (reuseType == "tP" && (multigridAlgo != "sa" && multigridAlgo != "unsmoothed")) {
537  reuseType = "none";
538  this->GetOStream(Warnings0) << "Ignoring \"tP\" reuse option as it is only compatible with \"sa\", "
539  "or \"unsmoothed\" multigrid algorithms" << std::endl;
540 
541  } else if (reuseType == "emin" && multigridAlgo != "emin") {
542  reuseType = "none";
543  this->GetOStream(Warnings0) << "Ignoring \"emin\" reuse option it is only compatible with "
544  "\"emin\" multigrid algorithm" << std::endl;
545  }
546 
547  // == Non-serializable data ===
548  // Check both the parameter and the type
549  bool have_userP = false;
550  if (paramList.isParameter("P") && !paramList.get<RCP<Matrix> >("P").is_null())
551  have_userP = true;
552 
553  // == Smoothers ==
554  UpdateFactoryManager_Smoothers(paramList, defaultList, manager, levelID, keeps);
555 
556  // === Coarse solver ===
557  UpdateFactoryManager_CoarseSolvers(paramList, defaultList, manager, levelID, keeps);
558 
559  // === Aggregation ===
560  UpdateFactoryManager_Aggregation_TentativeP(paramList, defaultList, manager, levelID, keeps);
561 
562  // === Nullspace ===
563  RCP<Factory> nullSpaceFactory; // Cache this guy for the combination of semi-coarsening & repartitioning
564  UpdateFactoryManager_Nullspace(paramList, defaultList, manager, levelID, keeps, nullSpaceFactory);
565 
566  // === Prolongation ===
567  // NOTE: None of the UpdateFactoryManager routines called here check the
568  // multigridAlgo. This is intentional, to allow for reuse of components
569  // underneath. Thus, the multigridAlgo was checked in the beginning of the
570  // function.
571  if (have_userP) {
572  // User prolongator
573  manager.SetFactory("P", NoFactory::getRCP());
574 
575  } else if (multigridAlgo == "unsmoothed") {
576  // Unsmoothed aggregation
577  manager.SetFactory("P", manager.GetFactory("Ptent"));
578 
579  } else if (multigridAlgo == "sa") {
580  // Smoothed aggregation
581  UpdateFactoryManager_SA(paramList, defaultList, manager, levelID, keeps);
582 
583  } else if (multigridAlgo == "emin") {
584  // Energy minimization
585  UpdateFactoryManager_Emin(paramList, defaultList, manager, levelID, keeps);
586 
587  } else if (multigridAlgo == "pg") {
588  // Petrov-Galerkin
589  UpdateFactoryManager_PG(paramList, defaultList, manager, levelID, keeps);
590 
591  } else if (multigridAlgo == "matlab") {
592  // Matlab Coarsneing
593  UpdateFactoryManager_Matlab(paramList, defaultList, manager, levelID, keeps);
594 
595  } else if (multigridAlgo == "pcoarsen") {
596  // P-Coarsening
597  UpdateFactoryManager_PCoarsen(paramList, defaultList, manager, levelID, keeps);
598  }
599 
600  // === Semi-coarsening ===
601  UpdateFactoryManager_SemiCoarsen(paramList, defaultList, manager, levelID, keeps);
602 
603  // === Restriction ===
604  UpdateFactoryManager_Restriction(paramList, defaultList, manager, levelID, keeps);
605 
606  // === RAP ===
607  UpdateFactoryManager_RAP(paramList, defaultList, manager, levelID, keeps);
608 
609  // === Coordinates ===
610  UpdateFactoryManager_Coordinates(paramList, defaultList, manager, levelID, keeps);
611 
612  // === Pre-Repartition Keeps for Reuse ===
613  if ((reuseType == "RP" || reuseType == "RAP" || reuseType == "full") && levelID)
614  keeps.push_back(keep_pair("Nullspace", manager.GetFactory("Nullspace").get()));
615 
616  if (reuseType == "RP" && levelID) {
617  keeps.push_back(keep_pair("P", manager.GetFactory("P").get()));
618  if (!this->implicitTranspose_)
619  keeps.push_back(keep_pair("R", manager.GetFactory("R").get()));
620  }
621  if ((reuseType == "tP" || reuseType == "RP" || reuseType == "emin") && useCoordinates_ && levelID)
622  keeps.push_back(keep_pair("Coordinates", manager.GetFactory("Coordinates").get()));
623 
624  // === Repartitioning ===
625  UpdateFactoryManager_Repartition(paramList, defaultList, manager, levelID, keeps, nullSpaceFactory);
626 
627  // === Final Keeps for Reuse ===
628  if ((reuseType == "RAP" || reuseType == "full") && levelID) {
629  keeps.push_back(keep_pair("P", manager.GetFactory("P").get()));
630  if (!this->implicitTranspose_)
631  keeps.push_back(keep_pair("R", manager.GetFactory("R").get()));
632  keeps.push_back(keep_pair("A", manager.GetFactory("A").get()));
633  }
634  }
635 
636  // =====================================================================================================
637  // ========================================= Smoothers =================================================
638  // =====================================================================================================
639  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
642  FactoryManager& manager, int levelID, std::vector<keep_pair>& keeps) const
643  {
644  MUELU_SET_VAR_2LIST(paramList, defaultList, "multigrid algorithm", std::string, multigridAlgo);
645  MUELU_SET_VAR_2LIST(paramList, defaultList, "reuse: type", std::string, reuseType);
646 
647  // === Smoothing ===
648  // FIXME: should custom smoother check default list too?
649  bool isCustomSmoother =
650  paramList.isParameter("smoother: pre or post") ||
651  paramList.isParameter("smoother: type") || paramList.isParameter("smoother: pre type") || paramList.isParameter("smoother: post type") ||
652  paramList.isSublist ("smoother: params") || paramList.isSublist ("smoother: pre params") || paramList.isSublist ("smoother: post params") ||
653  paramList.isParameter("smoother: sweeps") || paramList.isParameter("smoother: pre sweeps") || paramList.isParameter("smoother: post sweeps") ||
654  paramList.isParameter("smoother: overlap") || paramList.isParameter("smoother: pre overlap") || paramList.isParameter("smoother: post overlap");
655 
656  MUELU_SET_VAR_2LIST(paramList, defaultList, "smoother: pre or post", std::string, PreOrPost);
657  if (PreOrPost == "none") {
658  manager.SetFactory("Smoother", Teuchos::null);
659 
660  } else if (isCustomSmoother) {
661  // FIXME: get default values from the factory
662  // NOTE: none of the smoothers at the moment use parameter validation framework, so we
663  // cannot get the default values from it.
664 #define TEST_MUTUALLY_EXCLUSIVE(arg1,arg2) \
665  TEUCHOS_TEST_FOR_EXCEPTION(paramList.isParameter(#arg1) && paramList.isParameter(#arg2), \
666  Exceptions::InvalidArgument, "You cannot specify both \""#arg1"\" and \""#arg2"\"");
667 #define TEST_MUTUALLY_EXCLUSIVE_S(arg1,arg2) \
668  TEUCHOS_TEST_FOR_EXCEPTION(paramList.isSublist(#arg1) && paramList.isSublist(#arg2), \
669  Exceptions::InvalidArgument, "You cannot specify both \""#arg1"\" and \""#arg2"\"");
670 
671  TEST_MUTUALLY_EXCLUSIVE ("smoother: type", "smoother: pre type");
672  TEST_MUTUALLY_EXCLUSIVE ("smoother: type", "smoother: post type");
673  TEST_MUTUALLY_EXCLUSIVE ("smoother: sweeps", "smoother: pre sweeps");
674  TEST_MUTUALLY_EXCLUSIVE ("smoother: sweeps", "smoother: post sweeps");
675  TEST_MUTUALLY_EXCLUSIVE ("smoother: overlap", "smoother: pre overlap");
676  TEST_MUTUALLY_EXCLUSIVE ("smoother: overlap", "smoother: post overlap");
677  TEST_MUTUALLY_EXCLUSIVE_S("smoother: params", "smoother: pre params");
678  TEST_MUTUALLY_EXCLUSIVE_S("smoother: params", "smoother: post params");
679  TEUCHOS_TEST_FOR_EXCEPTION(PreOrPost == "both" && (paramList.isParameter("smoother: pre type") != paramList.isParameter("smoother: post type")),
680  Exceptions::InvalidArgument, "You must specify both \"smoother: pre type\" and \"smoother: post type\"");
681 
682  // Default values
683  int overlap = 0;
684  ParameterList defaultSmootherParams;
685  defaultSmootherParams.set("relaxation: type", "Symmetric Gauss-Seidel");
686  defaultSmootherParams.set("relaxation: sweeps", Teuchos::OrdinalTraits<LO>::one());
687  defaultSmootherParams.set("relaxation: damping factor", Teuchos::ScalarTraits<Scalar>::one());
688 
689  RCP<SmootherFactory> preSmoother = Teuchos::null, postSmoother = Teuchos::null;
690  std::string preSmootherType, postSmootherType;
691  ParameterList preSmootherParams, postSmootherParams;
692 
693  if (paramList.isParameter("smoother: overlap"))
694  overlap = paramList.get<int>("smoother: overlap");
695 
696  if (PreOrPost == "pre" || PreOrPost == "both") {
697  if (paramList.isParameter("smoother: pre type")) {
698  preSmootherType = paramList.get<std::string>("smoother: pre type");
699  } else {
700  MUELU_SET_VAR_2LIST(paramList, defaultList, "smoother: type", std::string, preSmootherTypeTmp);
701  preSmootherType = preSmootherTypeTmp;
702  }
703  if (paramList.isParameter("smoother: pre overlap"))
704  overlap = paramList.get<int>("smoother: pre overlap");
705 
706  if (paramList.isSublist("smoother: pre params"))
707  preSmootherParams = paramList.sublist("smoother: pre params");
708  else if (paramList.isSublist("smoother: params"))
709  preSmootherParams = paramList.sublist("smoother: params");
710  else if (defaultList.isSublist("smoother: params"))
711  preSmootherParams = defaultList.sublist("smoother: params");
712  else if (preSmootherType == "RELAXATION")
713  preSmootherParams = defaultSmootherParams;
714 
715 #ifdef HAVE_MUELU_INTREPID2
716  // Propagate P-coarsening for Topo smoothing
717  if (multigridAlgo == "pcoarsen" && preSmootherType == "TOPOLOGICAL" &&
718  defaultList.isParameter("pcoarsen: schedule") && defaultList.isParameter("pcoarsen: element")) {
719  // P-Coarsening by schedule (new interface)
720  // NOTE: levelID represents the *coarse* level in this case
721  auto pcoarsen_schedule = Teuchos::getArrayFromStringParameter<int>(defaultList, "pcoarsen: schedule");
722  auto pcoarsen_element = defaultList.get<std::string>("pcoarsen: element");
723 
724  if (levelID < (int)pcoarsen_schedule.size()) {
725  // Topo info for P-Coarsening
726  auto lo = pcoarsen_element + std::to_string(pcoarsen_schedule[levelID]);
727  preSmootherParams.set("pcoarsen: hi basis", lo);
728  }
729  }
730 #endif
731 
732 #ifdef HAVE_MUELU_MATLAB
733  if (preSmootherType == "matlab")
734  preSmoother = rcp(new SmootherFactory(rcp(new MatlabSmoother(preSmootherParams))));
735  else
736 #endif
737  preSmoother = rcp(new SmootherFactory(rcp(new TrilinosSmoother(preSmootherType, preSmootherParams, overlap))));
738  }
739 
740  if (PreOrPost == "post" || PreOrPost == "both") {
741  if (paramList.isParameter("smoother: post type"))
742  postSmootherType = paramList.get<std::string>("smoother: post type");
743  else {
744  MUELU_SET_VAR_2LIST(paramList, defaultList, "smoother: type", std::string, postSmootherTypeTmp);
745  postSmootherType = postSmootherTypeTmp;
746  }
747 
748  if (paramList.isSublist("smoother: post params"))
749  postSmootherParams = paramList.sublist("smoother: post params");
750  else if (paramList.isSublist("smoother: params"))
751  postSmootherParams = paramList.sublist("smoother: params");
752  else if (defaultList.isSublist("smoother: params"))
753  postSmootherParams = defaultList.sublist("smoother: params");
754  else if (postSmootherType == "RELAXATION")
755  postSmootherParams = defaultSmootherParams;
756  if (paramList.isParameter("smoother: post overlap"))
757  overlap = paramList.get<int>("smoother: post overlap");
758 
759  if (postSmootherType == preSmootherType && areSame(preSmootherParams, postSmootherParams))
760  postSmoother = preSmoother;
761  else {
762 #ifdef HAVE_MUELU_INTREPID2
763  // Propagate P-coarsening for Topo smoothing
764  if (multigridAlgo == "pcoarsen" && preSmootherType == "TOPOLOGICAL" &&
765  defaultList.isParameter("pcoarsen: schedule") && defaultList.isParameter("pcoarsen: element")) {
766  // P-Coarsening by schedule (new interface)
767  // NOTE: levelID represents the *coarse* level in this case
768  auto pcoarsen_schedule = Teuchos::getArrayFromStringParameter<int>(defaultList,"pcoarsen: schedule");
769  auto pcoarsen_element = defaultList.get<std::string>("pcoarsen: element");
770 
771  if (levelID < (int)pcoarsen_schedule.size()) {
772  // Topo info for P-Coarsening
773  auto lo = pcoarsen_element + std::to_string(pcoarsen_schedule[levelID]);
774  postSmootherParams.set("pcoarsen: hi basis", lo);
775  }
776  }
777 #endif
778 
779 #ifdef HAVE_MUELU_MATLAB
780  if (postSmootherType == "matlab")
781  postSmoother = rcp(new SmootherFactory(rcp(new MatlabSmoother(postSmootherParams))));
782  else
783 #endif
784  postSmoother = rcp(new SmootherFactory(rcp(new TrilinosSmoother(postSmootherType, postSmootherParams, overlap))));
785  }
786  }
787 
788  if (preSmoother == postSmoother)
789  manager.SetFactory("Smoother", preSmoother);
790  else {
791  manager.SetFactory("PreSmoother", preSmoother);
792  manager.SetFactory("PostSmoother", postSmoother);
793  }
794  }
795 
796  // The first clause is not necessary, but it is here for clarity Smoothers
797  // are reused if smoother explicitly said to reuse them, or if any other
798  // reuse option is enabled
799  bool reuseSmoothers = (reuseType == "S" || reuseType != "none");
800  if (reuseSmoothers) {
801  auto preSmootherFactory = rcp_const_cast<Factory>(rcp_dynamic_cast<const Factory>(manager.GetFactory("PreSmoother")));
802 
803  if (preSmootherFactory != Teuchos::null) {
804  ParameterList postSmootherFactoryParams;
805  postSmootherFactoryParams.set("keep smoother data", true);
806  preSmootherFactory->SetParameterList(postSmootherFactoryParams);
807 
808  keeps.push_back(keep_pair("PreSmoother data", preSmootherFactory.get()));
809  }
810 
811  auto postSmootherFactory = rcp_const_cast<Factory>(rcp_dynamic_cast<const Factory>(manager.GetFactory("PostSmoother")));
812  if (postSmootherFactory != Teuchos::null) {
813  ParameterList postSmootherFactoryParams;
814  postSmootherFactoryParams.set("keep smoother data", true);
815  postSmootherFactory->SetParameterList(postSmootherFactoryParams);
816 
817  keeps.push_back(keep_pair("PostSmoother data", postSmootherFactory.get()));
818  }
819 
820  auto coarseFactory = rcp_const_cast<Factory>(rcp_dynamic_cast<const Factory>(manager.GetFactory("CoarseSolver")));
821  if (coarseFactory != Teuchos::null) {
822  ParameterList coarseFactoryParams;
823  coarseFactoryParams.set("keep smoother data", true);
824  coarseFactory->SetParameterList(coarseFactoryParams);
825 
826  keeps.push_back(keep_pair("PreSmoother data", coarseFactory.get()));
827  }
828  }
829 
830  if ((reuseType == "RAP" && levelID) || (reuseType == "full")) {
831  // The difference between "RAP" and "full" is keeping smoothers. However,
832  // as in both cases we keep coarse matrices, we do not need to update
833  // coarse smoothers. On the other hand, if a user changes fine level
834  // matrix, "RAP" would update the fine level smoother, while "full" would
835  // not
836  keeps.push_back(keep_pair("PreSmoother", manager.GetFactory("PreSmoother") .get()));
837  keeps.push_back(keep_pair("PostSmoother", manager.GetFactory("PostSmoother").get()));
838 
839  // We do keep_pair("PreSmoother", manager.GetFactory("CoarseSolver").get())
840  // as the coarse solver factory is in fact a smoothing factory, so the
841  // only pieces of data it generates are PreSmoother and PostSmoother
842  keeps.push_back(keep_pair("PreSmoother", manager.GetFactory("CoarseSolver").get()));
843  }
844  }
845 
846  // =====================================================================================================
847  // ====================================== Coarse Solvers ===============================================
848  // =====================================================================================================
849  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
852  FactoryManager& manager, int /* levelID */, std::vector<keep_pair>& /* keeps */) const
853  {
854  // FIXME: should custom coarse solver check default list too?
855  bool isCustomCoarseSolver =
856  paramList.isParameter("coarse: type") ||
857  paramList.isParameter("coarse: params");
858  if (MUELU_TEST_PARAM_2LIST(paramList, defaultList, "coarse: type", std::string, "none")) {
859  this->GetOStream(Warnings0) << "No coarse grid solver" << std::endl;
860  manager.SetFactory("CoarseSolver", Teuchos::null);
861 
862  } else if (isCustomCoarseSolver) {
863  // FIXME: get default values from the factory
864  // NOTE: none of the smoothers at the moment use parameter validation framework, so we
865  // cannot get the default values from it.
866  MUELU_SET_VAR_2LIST(paramList, defaultList, "coarse: type", std::string, coarseType);
867 
868  int overlap = 0;
869  if (paramList.isParameter("coarse: overlap"))
870  overlap = paramList.get<int>("coarse: overlap");
871 
872  ParameterList coarseParams;
873  if (paramList.isSublist("coarse: params"))
874  coarseParams = paramList.sublist("coarse: params");
875  else if (defaultList.isSublist("coarse: params"))
876  coarseParams = defaultList.sublist("coarse: params");
877 
878  using strings = std::unordered_set<std::string>;
879 
880  RCP<SmootherPrototype> coarseSmoother;
881  // TODO: this is not a proper place to check. If we consider direct solver to be a special
882  // case of smoother, we would like to unify Amesos and Ifpack2 smoothers in src/Smoothers, and
883  // have a single factory responsible for those. Then, this check would belong there.
884  if (strings({"RELAXATION", "CHEBYSHEV", "ILUT", "ILU", "RILUK", "SCHWARZ", "Amesos",
885  "BLOCK RELAXATION", "BLOCK_RELAXATION", "BLOCKRELAXATION" ,
886  "SPARSE BLOCK RELAXATION", "SPARSE_BLOCK_RELAXATION", "SPARSEBLOCKRELAXATION",
887  "LINESMOOTHING_BANDEDRELAXATION", "LINESMOOTHING_BANDED_RELAXATION", "LINESMOOTHING_BANDED RELAXATION",
888  "LINESMOOTHING_TRIDIRELAXATION", "LINESMOOTHING_TRIDI_RELAXATION", "LINESMOOTHING_TRIDI RELAXATION",
889  "LINESMOOTHING_TRIDIAGONALRELAXATION", "LINESMOOTHING_TRIDIAGONAL_RELAXATION", "LINESMOOTHING_TRIDIAGONAL RELAXATION",
890  "TOPOLOGICAL", "FAST_ILU", "FAST_IC", "FAST_ILDL"}).count(coarseType)) {
891  coarseSmoother = rcp(new TrilinosSmoother(coarseType, coarseParams, overlap));
892  } else {
893 #ifdef HAVE_MUELU_MATLAB
894  if (coarseType == "matlab")
895  coarseSmoother = rcp(new MatlabSmoother(coarseParams));
896  else
897 #endif
898  coarseSmoother = rcp(new DirectSolver(coarseType, coarseParams));
899  }
900 
901  manager.SetFactory("CoarseSolver", rcp(new SmootherFactory(coarseSmoother)));
902  }
903  }
904 
905  // =====================================================================================================
906  // ========================================= Smoothers =================================================
907  // =====================================================================================================
908  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
911  FactoryManager& manager, int levelID, std::vector<keep_pair>& keeps) const
912  {
913  using strings = std::unordered_set<std::string>;
914 
915  MUELU_SET_VAR_2LIST(paramList, defaultList, "reuse: type", std::string, reuseType);
916 
917  // Aggregation graph
918  RCP<Factory> dropFactory;
919 
920  if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: drop scheme", std::string, "matlab")) {
921 #ifdef HAVE_MUELU_MATLAB
922  dropFactory = rcp(new SingleLevelMatlabFactory());
923  ParameterList socParams = paramList.sublist("strength-of-connection: params");
924  dropFactory->SetParameterList(socParams);
925 #else
926  throw std::runtime_error("Cannot use MATLAB evolutionary strength-of-connection - MueLu was not configured with MATLAB support.");
927 #endif
928  } else {
929  MUELU_KOKKOS_FACTORY_NO_DECL(dropFactory, CoalesceDropFactory, CoalesceDropFactory_kokkos);
930  ParameterList dropParams;
931  dropParams.set("lightweight wrap", true);
932  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: drop scheme", std::string, dropParams);
933  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: drop tol", double, dropParams);
934  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: Dirichlet threshold", double, dropParams);
935  if (useKokkos_) {
936  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: use lumping", bool, dropParams);
937  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: reuse graph", bool, dropParams);
938  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: reuse eigenvalue", bool, dropParams);
939  }
940  dropFactory->SetParameterList(dropParams);
941  }
942  manager.SetFactory("Graph", dropFactory);
943 
944  // Aggregation scheme
945  MUELU_SET_VAR_2LIST(paramList, defaultList, "aggregation: type", std::string, aggType);
946  TEUCHOS_TEST_FOR_EXCEPTION(!strings({"uncoupled", "coupled", "brick", "matlab"}).count(aggType),
947  Exceptions::RuntimeError, "Unknown aggregation algorithm: \"" << aggType << "\". Please consult User's Guide.");
948  #ifndef HAVE_MUELU_MATLAB
949  if (aggType == "matlab")
950  throw std::runtime_error("Cannot use MATLAB aggregation - MueLu was not configured with MATLAB support.");
951  #endif
952  RCP<Factory> aggFactory;
953  if (aggType == "uncoupled") {
954  MUELU_KOKKOS_FACTORY_NO_DECL(aggFactory, UncoupledAggregationFactory, UncoupledAggregationFactory_kokkos);
955  ParameterList aggParams;
956  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: mode", std::string, aggParams);
957  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: ordering", std::string, aggParams);
958  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: min agg size", int, aggParams);
959  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: max agg size", int, aggParams);
960  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: max selected neighbors", int, aggParams);
961  if(useKokkos_) {
962  //if not using kokkos refactor Uncoupled, there is no algorithm option (always Serial)
963  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: phase 1 algorithm", std::string, aggParams);
964  }
965  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: enable phase 1", bool, aggParams);
966  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: enable phase 2a", bool, aggParams);
967  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: enable phase 2b", bool, aggParams);
968  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: enable phase 3", bool, aggParams);
969  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: preserve Dirichlet points", bool, aggParams);
970  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: error on nodes with no on-rank neighbors", bool, aggParams);
971  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: phase3 avoid singletons", bool, aggParams);
972  aggFactory->SetParameterList(aggParams);
973  // make sure that the aggregation factory has all necessary data
974  aggFactory->SetFactory("DofsPerNode", manager.GetFactory("Graph"));
975  aggFactory->SetFactory("Graph", manager.GetFactory("Graph"));
976 
977  } else if (aggType == "coupled") {
978  aggFactory = rcp(new CoupledAggregationFactory());
979  aggFactory->SetFactory("Graph", manager.GetFactory("Graph"));
980 
981  } else if (aggType == "brick") {
982  aggFactory = rcp(new BrickAggregationFactory());
983  ParameterList aggParams;
984  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: brick x size", int, aggParams);
985  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: brick y size", int, aggParams);
986  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: brick z size", int, aggParams);
987  aggFactory->SetParameterList(aggParams);
988 
989  if (levelID > 1) {
990  // We check for levelID > 0, as in the interpreter aggFactory for
991  // levelID really corresponds to level 0. Managers are clunky, as they
992  // contain factories for two different levels
993  aggFactory->SetFactory("Coordinates", this->GetFactoryManager(levelID-1)->GetFactory("Coordinates"));
994  }
995  }
996 #ifdef HAVE_MUELU_MATLAB
997  else if(aggType == "matlab") {
998  ParameterList aggParams = paramList.sublist("aggregation: params");
999  aggFactory = rcp(new SingleLevelMatlabFactory());
1000  aggFactory->SetParameterList(aggParams);
1001  }
1002 #endif
1003  manager.SetFactory("Aggregates", aggFactory);
1004 
1005  // Coarse map
1006  MUELU_KOKKOS_FACTORY(coarseMap, CoarseMapFactory, CoarseMapFactory_kokkos);
1007  coarseMap->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1008  manager.SetFactory("CoarseMap", coarseMap);
1009 
1010  // Tentative P
1011  MUELU_KOKKOS_FACTORY(Ptent, TentativePFactory, TentativePFactory_kokkos);
1012  ParameterList ptentParams;
1013  if (paramList.isSublist("matrixmatrix: kernel params"))
1014  ptentParams.sublist("matrixmatrix: kernel params", false) = paramList.sublist("matrixmatrix: kernel params");
1015  if (defaultList.isSublist("matrixmatrix: kernel params"))
1016  ptentParams.sublist("matrixmatrix: kernel params", false) = defaultList.sublist("matrixmatrix: kernel params");
1017  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "tentative: calculate qr", bool, ptentParams);
1018  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "tentative: build coarse coordinates", bool, ptentParams);
1019  Ptent->SetParameterList(ptentParams);
1020  Ptent->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1021  Ptent->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
1022  manager.SetFactory("Ptent", Ptent);
1023 
1024  if (reuseType == "tP" && levelID) {
1025  keeps.push_back(keep_pair("Nullspace", Ptent.get()));
1026  keeps.push_back(keep_pair("P", Ptent.get()));
1027  }
1028  }
1029 
1030  // =====================================================================================================
1031  // ============================================ RAP ====================================================
1032  // =====================================================================================================
1033  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1035  UpdateFactoryManager_RAP(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
1036  int /* levelID */, std::vector<keep_pair>& keeps) const
1037  {
1038  if (paramList.isParameter("A") && !paramList.get<RCP<Matrix> >("A").is_null()) {
1039  // We have user matrix A
1040  manager.SetFactory("A", NoFactory::getRCP());
1041  return;
1042  }
1043 
1044  ParameterList RAPparams;
1045 
1046  RCP<RAPFactory> RAP;
1047  RCP<RAPShiftFactory> RAPs;
1048  // Allow for Galerkin or shifted RAP
1049  // FIXME: Should this not be some form of MUELU_SET_VAR_2LIST?
1050  std::string alg = paramList.get("rap: algorithm", "galerkin");
1051  if (alg == "shift" || alg == "non-galerkin") {
1052  RAPs = rcp(new RAPShiftFactory());
1053  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "rap: shift", double, RAPparams);
1054  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "rap: shift diagonal M", bool, RAPparams);
1055  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "rap: shift low storage", bool, RAPparams);
1056  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "rap: shift array", Teuchos::Array<double>, RAPparams);
1057  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "rap: cfl array", Teuchos::Array<double>, RAPparams);
1058 
1059  } else {
1060  RAP = rcp(new RAPFactory());
1061  }
1062 
1063  if (paramList.isSublist("matrixmatrix: kernel params"))
1064  RAPparams.sublist("matrixmatrix: kernel params", false) = paramList.sublist("matrixmatrix: kernel params");
1065  if (defaultList.isSublist("matrixmatrix: kernel params"))
1066  RAPparams.sublist("matrixmatrix: kernel params", false) = defaultList.sublist("matrixmatrix: kernel params");
1067  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "transpose: use implicit", bool, RAPparams);
1068  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "rap: fix zero diagonals", bool, RAPparams);
1069  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "rap: triple product", bool, RAPparams);
1070 
1071  try {
1072  if (paramList.isParameter("aggregation: allow empty prolongator columns")) {
1073  RAPparams.set("CheckMainDiagonal", paramList.get<bool>("aggregation: allow empty prolongator columns"));
1074  RAPparams.set("RepairMainDiagonal", paramList.get<bool>("aggregation: allow empty prolongator columns"));
1075  }
1076  else if (defaultList.isParameter("aggregation: allow empty prolongator columns")) {
1077  RAPparams.set("CheckMainDiagonal", defaultList.get<bool>("aggregation: allow empty prolongator columns"));
1078  RAPparams.set("RepairMainDiagonal", defaultList.get<bool>("aggregation: allow empty prolongator columns"));
1079  }
1080 
1083  "Error: parameter \"aggregation: allow empty prolongator columns\" must be of type " << Teuchos::TypeNameTraits<bool>::name());
1084  }
1085 
1086  if (!RAP.is_null()) {
1087  RAP->SetParameterList(RAPparams);
1088  RAP->SetFactory("P", manager.GetFactory("P"));
1089  } else {
1090  RAPs->SetParameterList(RAPparams);
1091  RAPs->SetFactory("P", manager.GetFactory("P"));
1092  }
1093 
1094  if (!this->implicitTranspose_) {
1095  if (!RAP.is_null())
1096  RAP->SetFactory("R", manager.GetFactory("R"));
1097  else
1098  RAPs->SetFactory("R", manager.GetFactory("R"));
1099  }
1100 
1101  if (MUELU_TEST_PARAM_2LIST(paramList, defaultList, "aggregation: export visualization data", bool, true)) {
1103  ParameterList aggExportParams;
1104  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output filename", std::string, aggExportParams);
1105  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: agg style", std::string, aggExportParams);
1106  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: iter", int, aggExportParams);
1107  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: time step", int, aggExportParams);
1108  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: fine graph edges", bool, aggExportParams);
1109  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: coarse graph edges", bool, aggExportParams);
1110  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: build colormap", bool, aggExportParams);
1111  aggExport->SetParameterList(aggExportParams);
1112  aggExport->SetFactory("DofsPerNode", manager.GetFactory("DofsPerNode"));
1113 
1114  if (!RAP.is_null())
1115  RAP->AddTransferFactory(aggExport);
1116  else
1117  RAPs->AddTransferFactory(aggExport);
1118  }
1119  if (!RAP.is_null())
1120  manager.SetFactory("A", RAP);
1121  else
1122  manager.SetFactory("A", RAPs);
1123 
1124  MUELU_SET_VAR_2LIST(paramList, defaultList, "reuse: type", std::string, reuseType);
1125  MUELU_SET_VAR_2LIST(paramList, defaultList, "sa: use filtered matrix", bool, useFiltering);
1126  bool filteringChangesMatrix = useFiltering && !MUELU_TEST_PARAM_2LIST(paramList, defaultList, "aggregation: drop tol", double, 0);
1127 
1128  if (reuseType == "RP" || (reuseType == "tP" && !filteringChangesMatrix)) {
1129  if (!RAP.is_null()) {
1130  keeps.push_back(keep_pair("AP reuse data", RAP.get()));
1131  keeps.push_back(keep_pair("RAP reuse data", RAP.get()));
1132 
1133  } else {
1134  keeps.push_back(keep_pair("AP reuse data", RAPs.get()));
1135  keeps.push_back(keep_pair("RAP reuse data", RAPs.get()));
1136  }
1137  }
1138  }
1139 
1140  // =====================================================================================================
1141  // ======================================= Restriction =================================================
1142  // =====================================================================================================
1143  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1146  FactoryManager& manager, int /* levelID */, std::vector<keep_pair>& /* keeps */) const
1147  {
1148  bool have_userCO = false;
1149  if (paramList.isParameter("Coordinates") && !paramList.get<RCP<MultiVector> >("Coordinates").is_null())
1150  have_userCO = true;
1151 
1152  if (useCoordinates_) {
1153  if (have_userCO) {
1154  manager.SetFactory("Coordinates", NoFactory::getRCP());
1155 
1156  } else {
1157  MUELU_KOKKOS_FACTORY(coords, CoordinatesTransferFactory, CoordinatesTransferFactory_kokkos);
1158  coords->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1159  coords->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
1160  manager.SetFactory("Coordinates", coords);
1161 
1162  auto RAP = rcp_const_cast<RAPFactory>(rcp_dynamic_cast<const RAPFactory>(manager.GetFactory("A")));
1163  if (!RAP.is_null()) {
1164  RAP->AddTransferFactory(manager.GetFactory("Coordinates"));
1165  } else {
1166  auto RAPs = rcp_const_cast<RAPShiftFactory>(rcp_dynamic_cast<const RAPShiftFactory>(manager.GetFactory("A")));
1167  RAPs->AddTransferFactory(manager.GetFactory("Coordinates"));
1168  }
1169  }
1170  }
1171  }
1172 
1173  // =====================================================================================================
1174  // ======================================= Restriction =================================================
1175  // =====================================================================================================
1176  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1179  FactoryManager& manager, int /* levelID */, std::vector<keep_pair>& /* keeps */) const
1180  {
1181  MUELU_SET_VAR_2LIST(paramList, defaultList, "multigrid algorithm", std::string, multigridAlgo);
1182  bool have_userR = false;
1183  if (paramList.isParameter("R") && !paramList.get<RCP<Matrix> >("R").is_null())
1184  have_userR = true;
1185 
1186  // === Restriction ===
1187  if (!this->implicitTranspose_) {
1188  MUELU_SET_VAR_2LIST(paramList, defaultList, "problem: symmetric", bool, isSymmetric);
1189 
1190  if (isSymmetric == false && (multigridAlgo == "unsmoothed" || multigridAlgo == "emin")) {
1191  this->GetOStream(Warnings0) <<
1192  "Switching \"problem: symmetric\" parameter to symmetric as multigrid algorithm. " <<
1193  multigridAlgo << " is primarily supposed to be used for symmetric problems.\n\n" <<
1194  "Please note: if you are using \"unsmoothed\" transfer operators the \"problem: symmetric\" parameter " <<
1195  "has no real mathematical meaning, i.e. you can use it for non-symmetric\n" <<
1196  "problems, too. With \"problem: symmetric\"=\"symmetric\" you can use implicit transpose for building " <<
1197  "the restriction operators which may drastically reduce the amount of consumed memory." << std::endl;
1198  isSymmetric = true;
1199  }
1200  TEUCHOS_TEST_FOR_EXCEPTION(multigridAlgo == "pg" && isSymmetric == true, Exceptions::RuntimeError,
1201  "Petrov-Galerkin smoothed transfer operators are only allowed for non-symmetric problems: Set \"problem: symmetric\" to false!\n" \
1202  "While PG smoothed transfer operators generally would also work for symmetric problems this is an unusual use case. " \
1203  "You can use the factory-based xml interface though if you need PG-AMG for symmetric problems.");
1204 
1205  if (have_userR) {
1206  manager.SetFactory("R", NoFactory::getRCP());
1207  } else {
1208  RCP<Factory> R;
1209  if (isSymmetric) R = rcp(new TransPFactory());
1210  else R = rcp(new GenericRFactory());
1211 
1212  R->SetFactory("P", manager.GetFactory("P"));
1213  manager.SetFactory("R", R);
1214  }
1215 
1216  } else {
1217  manager.SetFactory("R", Teuchos::null);
1218  }
1219  }
1220 
1221  // =====================================================================================================
1222  // ========================================= Repartition ===============================================
1223  // =====================================================================================================
1224  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1227  int levelID, std::vector<keep_pair>& keeps, RCP<Factory> & nullSpaceFactory) const
1228  {
1229  // === Repartitioning ===
1230  MUELU_SET_VAR_2LIST(paramList, defaultList, "reuse: type", std::string, reuseType);
1231  MUELU_SET_VAR_2LIST(paramList, defaultList, "repartition: enable", bool, enableRepart);
1232  MUELU_SET_VAR_2LIST(paramList, defaultList, "repartition: node repartition level",int,nodeRepartitionLevel);
1233 
1234  if (enableRepart) {
1235 #ifdef HAVE_MPI
1236  // Short summary of the issue: RebalanceTransferFactory shares ownership
1237  // of "P" with SaPFactory, and therefore, changes the stored version.
1238  // That means that if SaPFactory generated P, and stored it on the level,
1239  // then after rebalancing the value in that storage changed. It goes
1240  // against the concept of factories (I think), that every factory is
1241  // responsible for its own objects, and they are immutable outside.
1242  //
1243  // In reuse, this is what happens: as we reuse Importer across setups,
1244  // the order of factories changes, and coupled with shared ownership
1245  // leads to problems.
1246  // *First setup*
1247  // SaP builds P [and stores it]
1248  // TransP builds R [and stores it]
1249  // RAP builds A [and stores it]
1250  // RebalanceTransfer rebalances P [and changes the P stored by SaP] (*)
1251  // RebalanceTransfer rebalances R
1252  // RebalanceAc rebalances A
1253  // *Second setup* ("RP" reuse)
1254  // RebalanceTransfer rebalances P [which is incorrect due to (*)]
1255  // RebalanceTransfer rebalances R
1256  // RAP builds A [which is incorrect due to (*)]
1257  // RebalanceAc rebalances A [which throws due to map inconsistency]
1258  // ...
1259  // *Second setup* ("tP" reuse)
1260  // SaP builds P [and stores it]
1261  // RebalanceTransfer rebalances P [and changes the P stored by SaP] (**)
1262  // TransP builds R [which is incorrect due to (**)]
1263  // RebalanceTransfer rebalances R
1264  // ...
1265  //
1266  // Couple solutions to this:
1267  // 1. [implemented] Requre "tP" and "PR" reuse to only be used with
1268  // implicit rebalancing.
1269  // 2. Do deep copy of P, and changed domain map and importer there.
1270  // Need to investigate how expensive this is.
1271  TEUCHOS_TEST_FOR_EXCEPTION(this->doPRrebalance_ && (reuseType == "tP" || reuseType == "RP"), Exceptions::InvalidArgument,
1272  "Reuse types \"tP\" and \"PR\" require \"repartition: rebalance P and R\" set to \"false\"");
1273 
1274  // TEUCHOS_TEST_FOR_EXCEPTION(aggType == "brick", Exceptions::InvalidArgument,
1275  // "Aggregation type \"brick\" requires \"repartition: enable\" set to \"false\"");
1276 
1277  MUELU_SET_VAR_2LIST(paramList, defaultList, "repartition: partitioner", std::string, partName);
1278  TEUCHOS_TEST_FOR_EXCEPTION(partName != "zoltan" && partName != "zoltan2", Exceptions::InvalidArgument,
1279  "Invalid partitioner name: \"" << partName << "\". Valid options: \"zoltan\", \"zoltan2\"");
1280 
1281  bool switched = false;
1282  (void)switched;
1283 #ifndef HAVE_MUELU_ZOLTAN
1284  if (partName == "zoltan") {
1285  this->GetOStream(Warnings0) << "Zoltan interface is not available, trying to switch to Zoltan2" << std::endl;
1286  partName = "zoltan2";
1287  switched = true;
1288  }
1289 #endif
1290 #ifndef HAVE_MUELU_ZOLTAN2
1291  if (partName == "zoltan2" && !switched) {
1292  this->GetOStream(Warnings0) << "Zoltan2 interface is not available, trying to switch to Zoltan" << std::endl;
1293  partName = "zoltan";
1294  }
1295 #endif
1296 
1297  // RepartitionHeuristic
1298  auto repartheurFactory = rcp(new RepartitionHeuristicFactory());
1299  ParameterList repartheurParams;
1300  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: node repartition level",int,repartheurParams);
1301  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: start level", int, repartheurParams);
1302  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: min rows per proc", int, repartheurParams);
1303  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: target rows per proc", int, repartheurParams);
1304  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: max imbalance", double, repartheurParams);
1305  repartheurFactory->SetParameterList(repartheurParams);
1306  repartheurFactory->SetFactory("A", manager.GetFactory("A"));
1307  manager.SetFactory("number of partitions", repartheurFactory);
1308  manager.SetFactory("repartition: heuristic target rows per process", repartheurFactory);
1309 
1310  // Partitioner
1311  RCP<Factory> partitioner;
1312  if (levelID == nodeRepartitionLevel) {
1313 #ifdef HAVE_MPI
1314  // partitioner = rcp(new NodePartitionInterface());
1315  partitioner = rcp(new MueLu::NodePartitionInterface<SC,LO,GO,NO>());
1316  ParameterList partParams;
1317  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: node id" ,int,repartheurParams);
1318  partitioner->SetParameterList(partParams);
1319  partitioner->SetFactory("Node Comm", manager.GetFactory("Node Comm"));
1320 #else
1321  throw Exceptions::RuntimeError("MPI is not available");
1322 #endif
1323  }
1324  else if (partName == "zoltan") {
1325 #ifdef HAVE_MUELU_ZOLTAN
1326  partitioner = rcp(new ZoltanInterface());
1327  // NOTE: ZoltanInteface ("zoltan") does not support external parameters through ParameterList
1328 #else
1329  throw Exceptions::RuntimeError("Zoltan interface is not available");
1330 #endif
1331  } else if (partName == "zoltan2") {
1332 #ifdef HAVE_MUELU_ZOLTAN2
1333  partitioner = rcp(new Zoltan2Interface());
1334  ParameterList partParams;
1335  RCP<const ParameterList> partpartParams = rcp(new ParameterList(paramList.sublist("repartition: params", false)));
1336  partParams.set("ParameterList", partpartParams);
1337  partitioner->SetParameterList(partParams);
1338  partitioner->SetFactory("repartition: heuristic target rows per process",
1339  manager.GetFactory("repartition: heuristic target rows per process"));
1340 #else
1341  throw Exceptions::RuntimeError("Zoltan2 interface is not available");
1342 #endif
1343  }
1344 
1345  partitioner->SetFactory("A", manager.GetFactory("A"));
1346  partitioner->SetFactory("number of partitions", manager.GetFactory("number of partitions"));
1347  if (useCoordinates_)
1348  partitioner->SetFactory("Coordinates", manager.GetFactory("Coordinates"));
1349  manager.SetFactory("Partition", partitioner);
1350 
1351  // Repartitioner
1352  auto repartFactory = rcp(new RepartitionFactory());
1353  ParameterList repartParams;
1354  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: print partition distribution", bool, repartParams);
1355  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: remap parts", bool, repartParams);
1356  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: remap num values", int, repartParams);
1357  repartFactory->SetParameterList(repartParams);
1358  repartFactory->SetFactory("A", manager.GetFactory("A"));
1359  repartFactory->SetFactory("number of partitions", manager.GetFactory("number of partitions"));
1360  repartFactory->SetFactory("Partition", manager.GetFactory("Partition"));
1361  manager.SetFactory("Importer", repartFactory);
1362  if (reuseType != "none" && reuseType != "S" && levelID)
1363  keeps.push_back(keep_pair("Importer", manager.GetFactory("Importer").get()));
1364 
1365  // Rebalanced A
1366  auto newA = rcp(new RebalanceAcFactory());
1367  ParameterList rebAcParams;
1368  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: use subcommunicators", bool, rebAcParams);
1369  newA->SetParameterList(rebAcParams);
1370  newA->SetFactory("A", manager.GetFactory("A"));
1371  newA->SetFactory("Importer", manager.GetFactory("Importer"));
1372  manager.SetFactory("A", newA);
1373 
1374  // Rebalanced P
1375  auto newP = rcp(new RebalanceTransferFactory());
1376  ParameterList newPparams;
1377  newPparams.set("type", "Interpolation");
1378  if (changedPRrebalance_)
1379  newPparams.set("repartition: rebalance P and R", this->doPRrebalance_);
1380  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: use subcommunicators", bool, newPparams);
1381  newP-> SetParameterList(newPparams);
1382  newP-> SetFactory("Importer", manager.GetFactory("Importer"));
1383  newP-> SetFactory("P", manager.GetFactory("P"));
1384  if (!paramList.isParameter("semicoarsen: number of levels"))
1385  newP->SetFactory("Nullspace", manager.GetFactory("Ptent"));
1386  else
1387  newP->SetFactory("Nullspace", manager.GetFactory("P")); // TogglePFactory
1388  if (useCoordinates_)
1389  newP-> SetFactory("Coordinates", manager.GetFactory("Coordinates"));
1390  manager.SetFactory("P", newP);
1391  if (useCoordinates_)
1392  manager.SetFactory("Coordinates", newP);
1393 
1394  // Rebalanced R
1395  auto newR = rcp(new RebalanceTransferFactory());
1396  ParameterList newRparams;
1397  newRparams.set("type", "Restriction");
1398  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: use subcommunicators", bool, newRparams);
1399  if (changedPRrebalance_)
1400  newRparams.set("repartition: rebalance P and R", this->doPRrebalance_);
1401  if (changedImplicitTranspose_)
1402  newRparams.set("transpose: use implicit", this->implicitTranspose_);
1403  newR-> SetParameterList(newRparams);
1404  newR-> SetFactory("Importer", manager.GetFactory("Importer"));
1405  if (!this->implicitTranspose_) {
1406  newR->SetFactory("R", manager.GetFactory("R"));
1407  manager.SetFactory("R", newR);
1408  }
1409 
1410  // NOTE: the role of NullspaceFactory is to provide nullspace on the finest
1411  // level if a user does not do that. For all other levels it simply passes
1412  // nullspace from a real factory to whoever needs it. If we don't use
1413  // repartitioning, that factory is "TentativePFactory"; if we do, it is
1414  // "RebalanceTransferFactory". But we still have to have NullspaceFactory as
1415  // the "Nullspace" of the manager
1416  // NOTE: This really needs to be set on the *NullSpaceFactory*, not manager.get("Nullspace").
1417  nullSpaceFactory->SetFactory("Nullspace", newP);
1418 #else
1419  throw Exceptions::RuntimeError("No repartitioning available for a serial run");
1420 #endif
1421  }
1422  }
1423 
1424  // =====================================================================================================
1425  // =========================================== Nullspace ===============================================
1426  // =====================================================================================================
1427  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1429  UpdateFactoryManager_Nullspace(ParameterList& paramList, const ParameterList& /* defaultList */, FactoryManager& manager,
1430  int /* levelID */, std::vector<keep_pair>& /* keeps */, RCP<Factory> & nullSpaceFactory) const
1431  {
1432  // Nullspace
1433  MUELU_KOKKOS_FACTORY(nullSpace, NullspaceFactory, NullspaceFactory_kokkos);
1434 
1435  bool have_userNS = false;
1436  if (paramList.isParameter("Nullspace") && !paramList.get<RCP<MultiVector> >("Nullspace").is_null())
1437  have_userNS = true;
1438 
1439  if (!have_userNS) {
1440  nullSpace->SetFactory("Nullspace", manager.GetFactory("Ptent"));
1441  manager.SetFactory("Nullspace", nullSpace);
1442  }
1443  nullSpaceFactory = nullSpace;
1444  }
1445 
1446  // =====================================================================================================
1447  // ================================= Algorithm: SemiCoarsening =========================================
1448  // =====================================================================================================
1449  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1452  int /* levelID */, std::vector<keep_pair>& /* keeps */) const
1453  {
1454  // === Semi-coarsening ===
1455  RCP<SemiCoarsenPFactory> semicoarsenFactory = Teuchos::null;
1456  if (paramList.isParameter("semicoarsen: number of levels") &&
1457  paramList.get<int>("semicoarsen: number of levels") > 0) {
1458 
1459  ParameterList togglePParams;
1460  ParameterList semicoarsenPParams;
1461  ParameterList linedetectionParams;
1462  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "semicoarsen: number of levels", int, togglePParams);
1463  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "semicoarsen: coarsen rate", int, semicoarsenPParams);
1464  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "linedetection: orientation", std::string, linedetectionParams);
1465  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "linedetection: num layers", int, linedetectionParams);
1466 
1467  semicoarsenFactory = rcp(new SemiCoarsenPFactory());
1468  RCP<LineDetectionFactory> linedetectionFactory = rcp(new LineDetectionFactory());
1469  RCP<TogglePFactory> togglePFactory = rcp(new TogglePFactory());
1470 
1471  linedetectionFactory->SetParameterList(linedetectionParams);
1472  semicoarsenFactory ->SetParameterList(semicoarsenPParams);
1473  togglePFactory ->SetParameterList(togglePParams);
1474 
1475  togglePFactory->AddCoarseNullspaceFactory (semicoarsenFactory);
1476  togglePFactory->AddProlongatorFactory (semicoarsenFactory);
1477  togglePFactory->AddPtentFactory (semicoarsenFactory);
1478  togglePFactory->AddCoarseNullspaceFactory (manager.GetFactory("Ptent"));
1479  togglePFactory->AddProlongatorFactory (manager.GetFactory("P"));
1480  togglePFactory->AddPtentFactory (manager.GetFactory("Ptent"));
1481 
1482  manager.SetFactory("CoarseNumZLayers", linedetectionFactory);
1483  manager.SetFactory("LineDetection_Layers", linedetectionFactory);
1484  manager.SetFactory("LineDetection_VertLineIds", linedetectionFactory);
1485 
1486  manager.SetFactory("P", togglePFactory);
1487  manager.SetFactory("Ptent", togglePFactory);
1488  manager.SetFactory("Nullspace", togglePFactory);
1489  }
1490 
1491 
1492  if (paramList.isParameter("semicoarsen: number of levels")) {
1493  auto tf = rcp(new ToggleCoordinatesTransferFactory());
1494  tf->SetFactory("Chosen P", manager.GetFactory("P"));
1495  tf->AddCoordTransferFactory(semicoarsenFactory);
1496 
1497  MUELU_KOKKOS_FACTORY(coords, CoordinatesTransferFactory, CoordinatesTransferFactory_kokkos);
1498  coords->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1499  coords->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
1500  tf->AddCoordTransferFactory(coords);
1501  manager.SetFactory("Coordinates", tf);
1502  }
1503  }
1504 
1505 
1506  // =====================================================================================================
1507  // ================================== Algorithm: P-Coarsening ==========================================
1508  // =====================================================================================================
1509  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1512  int levelID, std::vector<keep_pair>& keeps) const
1513  {
1514 #ifdef HAVE_MUELU_INTREPID2
1515  // This only makes sense to invoke from the default list.
1516  if (defaultList.isParameter("pcoarsen: schedule") && defaultList.isParameter("pcoarsen: element")) {
1517  // P-Coarsening by schedule (new interface)
1518  // NOTE: levelID represents the *coarse* level in this case
1519  auto pcoarsen_schedule = Teuchos::getArrayFromStringParameter<int>(defaultList,"pcoarsen: schedule");
1520  auto pcoarsen_element = defaultList.get<std::string>("pcoarsen: element");
1521 
1522  if (levelID >= (int)pcoarsen_schedule.size()) {
1523  // Past the p-coarsening levels, we do Smoothed Aggregation
1524  // NOTE: We should probably consider allowing other options past p-coarsening
1525  UpdateFactoryManager_SA(paramList, defaultList, manager, levelID, keeps);
1526 
1527  } else {
1528  // P-Coarsening
1529  ParameterList Pparams;
1530  auto P = rcp(new IntrepidPCoarsenFactory());
1531  std::string lo = pcoarsen_element + std::to_string(pcoarsen_schedule[levelID]);
1532  std::string hi = (levelID ? pcoarsen_element + std::to_string(pcoarsen_schedule[levelID-1]) : lo);
1533  Pparams.set("pcoarsen: hi basis", hi);
1534  Pparams.set("pcoarsen: lo basis", lo);
1535  P->SetParameterList(Pparams);
1536  manager.SetFactory("P", P);
1537 
1538  // Add special nullspace handling
1539  rcp_dynamic_cast<Factory>(manager.GetFactoryNonConst("Nullspace"))->SetFactory("Nullspace", manager.GetFactory("P"));
1540  }
1541 
1542  } else {
1543  // P-Coarsening by manual specification (old interface)
1544  ParameterList Pparams;
1545  auto P = rcp(new IntrepidPCoarsenFactory());
1546  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "pcoarsen: hi basis", std::string, Pparams);
1547  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "pcoarsen: lo basis", std::string, Pparams);
1548  P->SetParameterList(Pparams);
1549  manager.SetFactory("P", P);
1550 
1551  // Add special nullspace handling
1552  rcp_dynamic_cast<Factory>(manager.GetFactoryNonConst("Nullspace"))->SetFactory("Nullspace", manager.GetFactory("P"));
1553  }
1554 
1555 #endif
1556  }
1557 
1558  // =====================================================================================================
1559  // ============================== Algorithm: Smoothed Aggregation ======================================
1560  // =====================================================================================================
1561  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1563  UpdateFactoryManager_SA(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager, int /* levelID */, std::vector<keep_pair>& keeps) const {
1564  // Smoothed aggregation
1565  MUELU_KOKKOS_FACTORY(P, SaPFactory, SaPFactory_kokkos);
1566  ParameterList Pparams;
1567  if (paramList.isSublist("matrixmatrix: kernel params"))
1568  Pparams.sublist("matrixmatrix: kernel params", false) = paramList.sublist("matrixmatrix: kernel params");
1569  if (defaultList.isSublist("matrixmatrix: kernel params"))
1570  Pparams.sublist("matrixmatrix: kernel params", false) = defaultList.sublist("matrixmatrix: kernel params");
1571  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "sa: damping factor", double, Pparams);
1572  P->SetParameterList(Pparams);
1573 
1574  // Filtering
1575  MUELU_SET_VAR_2LIST(paramList, defaultList, "sa: use filtered matrix", bool, useFiltering);
1576  if (useFiltering) {
1577  // NOTE: Here, non-Kokkos and Kokkos versions diverge in the way the
1578  // dependency tree is setup. The Kokkos version has merged the the
1579  // FilteredAFactory into the CoalesceDropFactory.
1580  if (!useKokkos_) {
1581  RCP<Factory> filterFactory = rcp(new FilteredAFactory());
1582 
1583  ParameterList fParams;
1584  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: use lumping", bool, fParams);
1585  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: reuse graph", bool, fParams);
1586  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: reuse eigenvalue", bool, fParams);
1587  filterFactory->SetParameterList(fParams);
1588  filterFactory->SetFactory("Graph", manager.GetFactory("Graph"));
1589  // I'm not sure why we need this line. See comments for DofsPerNode for UncoupledAggregation above
1590  filterFactory->SetFactory("Filtering", manager.GetFactory("Graph"));
1591 
1592  P->SetFactory("A", filterFactory);
1593 
1594  } else {
1595  P->SetFactory("A", manager.GetFactory("Graph"));
1596  }
1597  }
1598 
1599  P->SetFactory("P", manager.GetFactory("Ptent"));
1600  manager.SetFactory("P", P);
1601 
1602  bool filteringChangesMatrix = useFiltering && !MUELU_TEST_PARAM_2LIST(paramList, defaultList, "aggregation: drop tol", double, 0);
1603  MUELU_SET_VAR_2LIST(paramList, defaultList, "reuse: type", std::string, reuseType);
1604  if (reuseType == "tP" && !filteringChangesMatrix)
1605  keeps.push_back(keep_pair("AP reuse data", P.get()));
1606  }
1607 
1608  // =====================================================================================================
1609  // =============================== Algorithm: Energy Minimization ======================================
1610  // =====================================================================================================
1611  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1614  int /* levelID */, std::vector<keep_pair>& /* keeps */) const
1615  {
1616  MUELU_SET_VAR_2LIST(paramList, defaultList, "emin: pattern", std::string, patternType);
1617  MUELU_SET_VAR_2LIST(paramList, defaultList, "reuse: type", std::string, reuseType);
1618  TEUCHOS_TEST_FOR_EXCEPTION(patternType != "AkPtent", Exceptions::InvalidArgument,
1619  "Invalid pattern name: \"" << patternType << "\". Valid options: \"AkPtent\"");
1620  // Pattern
1621  auto patternFactory = rcp(new PatternFactory());
1622  ParameterList patternParams;
1623  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "emin: pattern order", int, patternParams);
1624  patternFactory->SetParameterList(patternParams);
1625  patternFactory->SetFactory("P", manager.GetFactory("Ptent"));
1626  manager.SetFactory("Ppattern", patternFactory);
1627 
1628  // Constraint
1629  auto constraintFactory = rcp(new ConstraintFactory());
1630  constraintFactory->SetFactory("Ppattern", manager.GetFactory("Ppattern"));
1631  constraintFactory->SetFactory("CoarseNullspace", manager.GetFactory("Ptent"));
1632  manager.SetFactory("Constraint", constraintFactory);
1633 
1634  // Energy minimization
1635  auto P = rcp(new EminPFactory());
1636  ParameterList Pparams;
1637  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "emin: num iterations", int, Pparams);
1638  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "emin: iterative method", std::string, Pparams);
1639  if (reuseType == "emin") {
1640  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "emin: num reuse iterations", int, Pparams);
1641  Pparams.set("Keep P0", true);
1642  Pparams.set("Keep Constraint0", true);
1643  }
1644  P->SetParameterList(Pparams);
1645  P->SetFactory("P", manager.GetFactory("Ptent"));
1646  P->SetFactory("Constraint", manager.GetFactory("Constraint"));
1647  manager.SetFactory("P", P);
1648  }
1649 
1650  // =====================================================================================================
1651  // ================================= Algorithm: Petrov-Galerkin ========================================
1652  // =====================================================================================================
1653  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1655  UpdateFactoryManager_PG(ParameterList& /* paramList */, const ParameterList& /* defaultList */, FactoryManager& manager,
1656  int /* levelID */, std::vector<keep_pair>& /* keeps */) const
1657  {
1658  TEUCHOS_TEST_FOR_EXCEPTION(this->implicitTranspose_, Exceptions::RuntimeError,
1659  "Implicit transpose not supported with Petrov-Galerkin smoothed transfer operators: Set \"transpose: use implicit\" to false!\n" \
1660  "Petrov-Galerkin transfer operator smoothing for non-symmetric problems requires a separate handling of the restriction operator which " \
1661  "does not allow the usage of implicit transpose easily.");
1662 
1663  // Petrov-Galerkin
1664  auto P = rcp(new PgPFactory());
1665  P->SetFactory("P", manager.GetFactory("Ptent"));
1666  manager.SetFactory("P", P);
1667  }
1668 
1669 
1670  // =====================================================================================================
1671  // ====================================== Algorithm: Matlab ============================================
1672  // =====================================================================================================
1673  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1675  UpdateFactoryManager_Matlab(ParameterList& paramList, const ParameterList& /* defaultList */, FactoryManager& manager,
1676  int /* levelID */, std::vector<keep_pair>& /* keeps */) const {
1677 #ifdef HAVE_MUELU_MATLAB
1678  ParameterList Pparams = paramList.sublist("transfer: params");
1679  auto P = rcp(new TwoLevelMatlabFactory());
1680  P->SetParameterList(Pparams);
1681  P->SetFactory("P", manager.GetFactory("Ptent"));
1682  manager.SetFactory("P", P);
1683 #else
1684  (void)paramList;
1685  (void)manager;
1686 #endif
1687  }
1688 
1689 #undef MUELU_SET_VAR_2LIST
1690 #undef MUELU_TEST_AND_SET_VAR
1691 #undef MUELU_TEST_AND_SET_PARAM_2LIST
1692 #undef MUELU_TEST_PARAM_2LIST
1693 #undef MUELU_KOKKOS_FACTORY
1694 
1695  size_t LevenshteinDistance(const char* s, size_t len_s, const char* t, size_t len_t);
1696 
1697  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1699  ParameterList paramList = constParamList;
1700  const ParameterList& validList = *MasterList::List();
1701  // Validate up to maxLevels level specific parameter sublists
1702  const int maxLevels = 100;
1703 
1704  // Extract level specific list
1705  std::vector<ParameterList> paramLists;
1706  for (int levelID = 0; levelID < maxLevels; levelID++) {
1707  std::string sublistName = "level " + toString(levelID);
1708  if (paramList.isSublist(sublistName)) {
1709  paramLists.push_back(paramList.sublist(sublistName));
1710  // paramLists.back().setName(sublistName);
1711  paramList.remove(sublistName);
1712  }
1713  }
1714  paramLists.push_back(paramList);
1715  // paramLists.back().setName("main");
1716 #ifdef HAVE_MUELU_MATLAB
1717  // If Muemex is supported, hide custom level variables from validator by removing them from paramList's sublists
1718  for (size_t i = 0; i < paramLists.size(); i++) {
1719  std::vector<std::string> customVars; // list of names (keys) to be removed from list
1720 
1721  for(Teuchos::ParameterList::ConstIterator it = paramLists[i].begin(); it != paramLists[i].end(); it++) {
1722  std::string paramName = paramLists[i].name(it);
1723 
1724  if (IsParamMuemexVariable(paramName))
1725  customVars.push_back(paramName);
1726  }
1727 
1728  // Remove the keys
1729  for (size_t j = 0; j < customVars.size(); j++)
1730  paramLists[i].remove(customVars[j], false);
1731  }
1732 #endif
1733 
1734  const int maxDepth = 0;
1735  for (size_t i = 0; i < paramLists.size(); i++) {
1736  // validate every sublist
1737  try {
1738  paramLists[i].validateParameters(validList, maxDepth);
1739 
1740  } catch (const Teuchos::Exceptions::InvalidParameterName& e) {
1741  std::string eString = e.what();
1742 
1743  // Parse name from: <Error, the parameter {name="smoothe: type",...>
1744  size_t nameStart = eString.find_first_of('"') + 1;
1745  size_t nameEnd = eString.find_first_of('"', nameStart);
1746  std::string name = eString.substr(nameStart, nameEnd - nameStart);
1747 
1748  size_t bestScore = 100;
1749  std::string bestName = "";
1750  for (ParameterList::ConstIterator it = validList.begin(); it != validList.end(); it++) {
1751  const std::string& pName = validList.name(it);
1752  this->GetOStream(Runtime1) << "| " << pName;
1753  size_t score = LevenshteinDistance(name.c_str(), name.length(), pName.c_str(), pName.length());
1754  this->GetOStream(Runtime1) << " -> " << score << std::endl;
1755  if (score < bestScore) {
1756  bestScore = score;
1757  bestName = pName;
1758  }
1759  }
1760  if (bestScore < 10 && bestName != "") {
1762  eString << "The parameter name \"" + name + "\" is not valid. Did you mean \"" + bestName << "\"?\n");
1763 
1764  } else {
1766  eString << "The parameter name \"" + name + "\" is not valid.\n");
1767  }
1768  }
1769  }
1770  }
1771 
1772  // =====================================================================================================
1773  // ==================================== FACTORY interpreter ============================================
1774  // =====================================================================================================
1775  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1777  SetFactoryParameterList(const ParameterList& constParamList) {
1778  // Create a non const copy of the parameter list
1779  // Working with a modifiable list is much much easier than with original one
1780  ParameterList paramList = constParamList;
1781 
1782  // Parameter List Parsing:
1783  // ---------
1784  // <ParameterList name="MueLu">
1785  // <ParameterList name="Matrix">
1786  // </ParameterList>
1787  if (paramList.isSublist("Matrix")) {
1788  blockSize_ = paramList.sublist("Matrix").get<int>("PDE equations", MasterList::getDefault<int>("number of equations"));
1789  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)
1790  }
1791 
1792  // create new FactoryFactory object if necessary
1793  if (factFact_ == Teuchos::null)
1794  factFact_ = Teuchos::rcp(new FactoryFactory());
1795 
1796  // Parameter List Parsing:
1797  // ---------
1798  // <ParameterList name="MueLu">
1799  // <ParameterList name="Factories"> <== call BuildFactoryMap() on this parameter list
1800  // ...
1801  // </ParameterList>
1802  // </ParameterList>
1803  FactoryMap factoryMap;
1804  FactoryManagerMap factoryManagers;
1805  if (paramList.isSublist("Factories"))
1806  this->BuildFactoryMap(paramList.sublist("Factories"), factoryMap, factoryMap, factoryManagers);
1807 
1808  // Parameter List Parsing:
1809  // ---------
1810  // <ParameterList name="MueLu">
1811  // <ParameterList name="Hierarchy">
1812  // <Parameter name="verbose" type="string" value="Warnings"/> <== get
1813  // <Parameter name="numDesiredLevel" type="int" value="10"/> <== get
1814  //
1815  // <ParameterList name="firstLevel"> <== parse first args and call BuildFactoryMap() on the rest of this parameter list
1816  // ...
1817  // </ParameterList>
1818  // </ParameterList>
1819  // </ParameterList>
1820  if (paramList.isSublist("Hierarchy")) {
1821  ParameterList hieraList = paramList.sublist("Hierarchy"); // copy because list temporally modified (remove 'id')
1822 
1823  // Get hierarchy options
1824  if (hieraList.isParameter("max levels")) {
1825  this->numDesiredLevel_ = hieraList.get<int>("max levels");
1826  hieraList.remove("max levels");
1827  }
1828 
1829  if (hieraList.isParameter("coarse: max size")) {
1830  this->maxCoarseSize_ = hieraList.get<int>("coarse: max size");
1831  hieraList.remove("coarse: max size");
1832  }
1833 
1834  if (hieraList.isParameter("repartition: rebalance P and R")) {
1835  this->doPRrebalance_ = hieraList.get<bool>("repartition: rebalance P and R");
1836  hieraList.remove("repartition: rebalance P and R");
1837  }
1838 
1839  if (hieraList.isParameter("transpose: use implicit")) {
1840  this->implicitTranspose_ = hieraList.get<bool>("transpose: use implicit");
1841  hieraList.remove("transpose: use implicit");
1842  }
1843 
1844  if (hieraList.isParameter("coarse grid correction scaling factor")) {
1845  this->scalingFactor_ = hieraList.get<double>("coarse grid correction scaling factor");
1846  hieraList.remove("coarse grid correction scaling factor");
1847  }
1848 
1849  // Translate cycle type parameter
1850  if (hieraList.isParameter("cycle type")) {
1851  std::map<std::string, CycleType> cycleMap;
1852  cycleMap["V"] = VCYCLE;
1853  cycleMap["W"] = WCYCLE;
1854 
1855  std::string cycleType = hieraList.get<std::string>("cycle type");
1856  TEUCHOS_TEST_FOR_EXCEPTION(cycleMap.count(cycleType) == 0, Exceptions::RuntimeError, "Invalid cycle type: \"" << cycleType << "\"");
1857  this->Cycle_ = cycleMap[cycleType];
1858  }
1859 
1860  //TODO Move this its own class or MueLu::Utils?
1861  std::map<std::string, MsgType> verbMap;
1862  //for developers
1863  verbMap["Errors"] = Errors;
1864  verbMap["Warnings0"] = Warnings0;
1865  verbMap["Warnings00"] = Warnings00;
1866  verbMap["Warnings1"] = Warnings1;
1867  verbMap["PerfWarnings"] = PerfWarnings;
1868  verbMap["Runtime0"] = Runtime0;
1869  verbMap["Runtime1"] = Runtime1;
1870  verbMap["RuntimeTimings"] = RuntimeTimings;
1871  verbMap["NoTimeReport"] = NoTimeReport;
1872  verbMap["Parameters0"] = Parameters0;
1873  verbMap["Parameters1"] = Parameters1;
1874  verbMap["Statistics0"] = Statistics0;
1875  verbMap["Statistics1"] = Statistics1;
1876  verbMap["Timings0"] = Timings0;
1877  verbMap["Timings1"] = Timings1;
1878  verbMap["TimingsByLevel"] = TimingsByLevel;
1879  verbMap["External"] = External;
1880  verbMap["Debug"] = Debug;
1881  verbMap["Test"] = Test;
1882  //for users and developers
1883  verbMap["None"] = None;
1884  verbMap["Low"] = Low;
1885  verbMap["Medium"] = Medium;
1886  verbMap["High"] = High;
1887  verbMap["Extreme"] = Extreme;
1888  if (hieraList.isParameter("verbosity")) {
1889  std::string vl = hieraList.get<std::string>("verbosity");
1890  hieraList.remove("verbosity");
1891  //TODO Move this to its own class or MueLu::Utils?
1892  if (verbMap.find(vl) != verbMap.end())
1893  this->verbosity_ = verbMap[vl];
1894  else
1895  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "MueLu::ParameterListInterpreter():: invalid verbosity level");
1896  }
1897 
1898  if (hieraList.isParameter("dependencyOutputLevel"))
1899  this->graphOutputLevel_ = hieraList.get<int>("dependencyOutputLevel");
1900 
1901  // Check for the reuse case
1902  if (hieraList.isParameter("reuse"))
1904 
1905  if (hieraList.isSublist("DataToWrite")) {
1906  //TODO We should be able to specify any data. If it exists, write it.
1907  //TODO This would requires something like std::set<dataName, Array<int> >
1908  ParameterList foo = hieraList.sublist("DataToWrite");
1909  std::string dataName = "Matrices";
1910  if (foo.isParameter(dataName))
1911  this->matricesToPrint_ = Teuchos::getArrayFromStringParameter<int>(foo, dataName);
1912  dataName = "Prolongators";
1913  if (foo.isParameter(dataName))
1914  this->prolongatorsToPrint_ = Teuchos::getArrayFromStringParameter<int>(foo, dataName);
1915  dataName = "Restrictors";
1916  if (foo.isParameter(dataName))
1917  this->restrictorsToPrint_ = Teuchos::getArrayFromStringParameter<int>(foo, dataName);
1918  }
1919 
1920  // Get level configuration
1921  for (ParameterList::ConstIterator param = hieraList.begin(); param != hieraList.end(); ++param) {
1922  const std::string & paramName = hieraList.name(param);
1923 
1924  if (paramName != "DataToWrite" && hieraList.isSublist(paramName)) {
1925  ParameterList levelList = hieraList.sublist(paramName); // copy because list temporally modified (remove 'id')
1926 
1927  int startLevel = 0; if(levelList.isParameter("startLevel")) { startLevel = levelList.get<int>("startLevel"); levelList.remove("startLevel"); }
1928  int numDesiredLevel = 1; if(levelList.isParameter("numDesiredLevel")) { numDesiredLevel = levelList.get<int>("numDesiredLevel"); levelList.remove("numDesiredLevel"); }
1929 
1930  // Parameter List Parsing:
1931  // ---------
1932  // <ParameterList name="firstLevel">
1933  // <Parameter name="startLevel" type="int" value="0"/>
1934  // <Parameter name="numDesiredLevel" type="int" value="1"/>
1935  // <Parameter name="verbose" type="string" value="Warnings"/>
1936  //
1937  // [] <== call BuildFactoryMap() on the rest of the parameter list
1938  //
1939  // </ParameterList>
1940  FactoryMap levelFactoryMap;
1941  BuildFactoryMap(levelList, factoryMap, levelFactoryMap, factoryManagers);
1942 
1943  RCP<FactoryManager> m = rcp(new FactoryManager(levelFactoryMap));
1944  if (hieraList.isParameter("use kokkos refactor"))
1945  m->SetKokkosRefactor(hieraList.get<bool>("use kokkos refactor"));
1946 
1947  if (startLevel >= 0)
1948  this->AddFactoryManager(startLevel, numDesiredLevel, m);
1949  else
1950  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "MueLu::ParameterListInterpreter():: invalid level id");
1951  } /* TODO: else { } */
1952  }
1953  }
1954  }
1955 
1956 
1957  //TODO: static?
1991 
2043 
2080  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2082  BuildFactoryMap(const ParameterList& paramList, const FactoryMap& factoryMapIn, FactoryMap& factoryMapOut, FactoryManagerMap& factoryManagers) const {
2083  for (ParameterList::ConstIterator param = paramList.begin(); param != paramList.end(); ++param) {
2084  const std::string & paramName = paramList.name(param); //< paramName contains the user chosen factory name (e.g., "smootherFact1")
2085  const Teuchos::ParameterEntry & paramValue = paramList.entry(param); //< for factories, paramValue should be either a list or just a MueLu Factory (e.g., TrilinosSmoother)
2086 
2087  //TODO: do not allow name of existing MueLu classes (can be tested using FactoryFactory)
2088 
2089  if (paramValue.isList()) {
2090  ParameterList paramList1 = Teuchos::getValue<ParameterList>(paramValue);
2091  if (paramList1.isParameter("factory")) { // default: just a factory definition
2092  // New Factory is a sublist with internal parameters and/or data dependencies
2093  TEUCHOS_TEST_FOR_EXCEPTION(paramList1.isParameter("dependency for") == true, Exceptions::RuntimeError,
2094  "MueLu::ParameterListInterpreter(): It seems that in the parameter lists for defining " << paramName <<
2095  " there is both a 'factory' and 'dependency for' parameter. This is not allowed. Please remove the 'dependency for' parameter.");
2096 
2097  factoryMapOut[paramName] = factFact_->BuildFactory(paramValue, factoryMapIn, factoryManagers);
2098 
2099  } else if (paramList1.isParameter("dependency for")) { // add more data dependencies to existing factory
2100  TEUCHOS_TEST_FOR_EXCEPTION(paramList1.isParameter("factory") == true, Exceptions::RuntimeError,
2101  "MueLu::ParameterListInterpreter(): It seems that in the parameter lists for defining " << paramName <<
2102  " there is both a 'factory' and 'dependency for' parameter. This is not allowed.");
2103 
2104  std::string factoryName = paramList1.get<std::string>("dependency for");
2105 
2106  RCP<const FactoryBase> factbase = factoryMapIn.find(factoryName /*paramName*/)->second; // access previously defined factory
2107  TEUCHOS_TEST_FOR_EXCEPTION(factbase.is_null() == true, Exceptions::RuntimeError,
2108  "MueLu::ParameterListInterpreter(): could not find factory " + factoryName + " in factory map. Did you define it before?");
2109 
2110  RCP<const Factory> factoryconst = Teuchos::rcp_dynamic_cast<const Factory>(factbase);
2111  RCP< Factory> factory = Teuchos::rcp_const_cast<Factory>(factoryconst);
2112 
2113  // Read the RCP<Factory> parameters of the class T
2114  RCP<const ParameterList> validParamList = factory->GetValidParameterList();
2115  for (ParameterList::ConstIterator vparam = validParamList->begin(); vparam != validParamList->end(); ++vparam) {
2116  const std::string& pName = validParamList->name(vparam);
2117 
2118  if (!paramList1.isParameter(pName)) {
2119  // Ignore unknown parameters
2120  continue;
2121  }
2122 
2123  if (validParamList->isType< RCP<const FactoryBase> >(pName)) {
2124  // Generate or get factory described by pName and set dependency
2125  RCP<const FactoryBase> generatingFact = factFact_->BuildFactory(paramList1.getEntry(pName), factoryMapIn, factoryManagers);
2126  factory->SetFactory(pName, generatingFact.create_weak());
2127 
2128  } else if (validParamList->isType<RCP<const ParameterList> >(pName)) {
2129  if (pName == "ParameterList") {
2130  // NOTE: we cannot use
2131  // subList = sublist(rcpFromRef(paramList), pName)
2132  // here as that would result in sublist also being a reference to a temporary object.
2133  // The resulting dereferencing in the corresponding factory would then segfault
2134  RCP<const ParameterList> subList = Teuchos::sublist(rcp(new ParameterList(paramList1)), pName);
2135  factory->SetParameter(pName, ParameterEntry(subList));
2136  }
2137  } else {
2138  factory->SetParameter(pName, paramList1.getEntry(pName));
2139  }
2140  }
2141 
2142  } else if (paramList1.isParameter("group")) { // definitiion of a factory group (for a factory manager)
2143  // Define a new (sub) FactoryManager
2144  std::string groupType = paramList1.get<std::string>("group");
2145  TEUCHOS_TEST_FOR_EXCEPTION(groupType!="FactoryManager", Exceptions::RuntimeError,
2146  "group must be of type \"FactoryManager\".");
2147 
2148  ParameterList groupList = paramList1; // copy because list temporally modified (remove 'id')
2149  groupList.remove("group");
2150 
2151  FactoryMap groupFactoryMap;
2152  BuildFactoryMap(groupList, factoryMapIn, groupFactoryMap, factoryManagers);
2153 
2154  // do not store groupFactoryMap in factoryMapOut
2155  // Create a factory manager object from groupFactoryMap
2156  RCP<FactoryManagerBase> m = rcp(new FactoryManager(groupFactoryMap));
2157 
2158  factoryManagers[paramName] = m;
2159 
2160  } else {
2161  this->GetOStream(Warnings0) << "Could not interpret parameter list " << paramList1 << std::endl;
2163  "XML Parameter list must either be of type \"factory\" or of type \"group\".");
2164  }
2165  } else {
2166  // default: just a factory (no parameter list)
2167  factoryMapOut[paramName] = factFact_->BuildFactory(paramValue, factoryMapIn, factoryManagers);
2168  }
2169  }
2170  }
2171 
2172  // =====================================================================================================
2173  // ======================================= MISC functions ==============================================
2174  // =====================================================================================================
2175  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2177  try {
2178  Matrix& A = dynamic_cast<Matrix&>(Op);
2179  if (A.GetFixedBlockSize() != blockSize_)
2180  this->GetOStream(Warnings0) << "Setting matrix block size to " << blockSize_ << " (value of the parameter in the list) "
2181  << "instead of " << A.GetFixedBlockSize() << " (provided matrix)." << std::endl
2182  << "You may want to check \"number of equations\" (or \"PDE equations\" for factory style list) parameter." << std::endl;
2183 
2184  A.SetFixedBlockSize(blockSize_, dofOffset_);
2185 
2186  } catch (std::bad_cast& e) {
2187  this->GetOStream(Warnings0) << "Skipping setting block size as the operator is not a matrix" << std::endl;
2188  }
2189  }
2190 
2191  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2193  H.SetCycle(Cycle_);
2194  H.SetProlongatorScalingFactor(scalingFactor_);
2196  }
2197 
2198  static bool compare(const ParameterList& list1, const ParameterList& list2) {
2199  // First loop through and validate the parameters at this level.
2200  // In addition, we generate a list of sublists that we will search next
2201  for (ParameterList::ConstIterator it = list1.begin(); it != list1.end(); it++) {
2202  const std::string& name = it->first;
2203  const Teuchos::ParameterEntry& entry1 = it->second;
2204 
2205  const Teuchos::ParameterEntry *entry2 = list2.getEntryPtr(name);
2206  if (!entry2) // entry is not present in the second list
2207  return false;
2208  if (entry1.isList() && entry2->isList()) { // sublist check
2209  compare(Teuchos::getValue<ParameterList>(entry1), Teuchos::getValue<ParameterList>(*entry2));
2210  continue;
2211  }
2212  if (entry1.getAny(false) != entry2->getAny(false)) // entries have different types or different values
2213  return false;
2214  }
2215 
2216  return true;
2217  }
2218 
2219  static inline bool areSame(const ParameterList& list1, const ParameterList& list2) {
2220  return compare(list1, list2) && compare(list2, list1);
2221  }
2222 
2223 } // namespace MueLu
2224 
2225 #define MUELU_PARAMETERLISTINTERPRETER_SHORT
2226 #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.
High level timing information (use Teuchos::TimeMonitor::summarize() to print)
static VerbLevel GetDefaultVerbLevel()
Get the default (global) verbosity level.
ConstIterator end() 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...
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.
Print external lib objects.
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.
Print more statistics.
void SetKokkosRefactor(const bool useKokkos)
Print additional debugging information.
One-liner description of what is happening.
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)
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.
#define TEST_MUTUALLY_EXCLUSIVE(arg1, arg2)
Class that encapsulates direct solvers. Autoselection of AmesosSmoother or Amesos2Smoother according ...
Factory for coarsening a graph with uncoupled aggregation.
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.
ParameterList & setEntry(const std::string &name, const ParameterEntry &entry)
Important warning messages (more verbose)
bool isParameter(const std::string &name) const
Print statistics that do not involve significant additional computation.
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)
void UpdateFactoryManager_Coordinates(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
bool isSublist(const std::string &name) const
Detailed timing information (use Teuchos::TimeMonitor::summarize() to print)
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...
By default, enabled timers appears in the teuchos time monitor summary. Use this option if you do not...
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
Applies permutation to grid transfer operators.
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)
const ParameterEntry & entry(ConstIterator i) const
Print class parameters.
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
Timers that are enabled (using Timings0/Timings1) will be printed during the execution.
void AddTransferFactory(const RCP< const FactoryBase > &factory)
Add transfer factory in the end of list of transfer factories in RepartitionAcFactory.
Performance warnings.
Record timing information level by level. Must be used in combinaison with Timings0/Timings1.
Factory for creating a graph base 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.
void SetParameterList(const Teuchos::ParameterList &paramList)
Set parameter list for Parameter list interpreter.
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
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="")
#define TEST_MUTUALLY_EXCLUSIVE_S(arg1, arg2)
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)
Print class parameters (more parameters, more verbose)
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.
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.
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.
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)
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