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