MueLu  Version of the Day
MueLu_ParameterListInterpreter_def.hpp
Go to the documentation of this file.
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // MueLu: A package for multigrid based preconditioning
6 // Copyright 2012 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact
39 // Jonathan Hu (jhu@sandia.gov)
40 // Andrey Prokopenko (aprokop@sandia.gov)
41 // Ray Tuminaro (rstumin@sandia.gov)
42 //
43 // ***********************************************************************
44 //
45 // @HEADER
46 #ifndef MUELU_PARAMETERLISTINTERPRETER_DEF_HPP
47 #define MUELU_PARAMETERLISTINTERPRETER_DEF_HPP
48 
49 #include <Teuchos_XMLParameterListHelpers.hpp>
50 
51 #include <Xpetra_Matrix.hpp>
52 
53 #include "MueLu_ConfigDefs.hpp"
54 
56 
57 #include "MueLu_MasterList.hpp"
58 #include "MueLu_Level.hpp"
59 #include "MueLu_Hierarchy.hpp"
60 #include "MueLu_FactoryManager.hpp"
61 
62 #include "MueLu_AggregationExportFactory.hpp"
63 #include "MueLu_BrickAggregationFactory.hpp"
64 #include "MueLu_CoalesceDropFactory.hpp"
65 #include "MueLu_CoarseMapFactory.hpp"
66 #include "MueLu_ConstraintFactory.hpp"
67 #include "MueLu_CoordinatesTransferFactory.hpp"
68 #include "MueLu_CoupledAggregationFactory.hpp"
69 #include "MueLu_DirectSolver.hpp"
70 #include "MueLu_EminPFactory.hpp"
71 #include "MueLu_Exceptions.hpp"
72 #include "MueLu_FactoryFactory.hpp"
73 #include "MueLu_FilteredAFactory.hpp"
74 #include "MueLu_GenericRFactory.hpp"
75 #include "MueLu_LineDetectionFactory.hpp"
76 #include "MueLu_MasterList.hpp"
77 #include "MueLu_NullspaceFactory.hpp"
78 #include "MueLu_PatternFactory.hpp"
79 #include "MueLu_PgPFactory.hpp"
80 #include "MueLu_RAPFactory.hpp"
81 #include "MueLu_RebalanceAcFactory.hpp"
82 #include "MueLu_RebalanceTransferFactory.hpp"
83 #include "MueLu_RepartitionFactory.hpp"
84 #include "MueLu_SaPFactory.hpp"
85 #include "MueLu_SemiCoarsenPFactory.hpp"
86 #include "MueLu_SmootherFactory.hpp"
87 #include "MueLu_TentativePFactory.hpp"
88 #include "MueLu_TogglePFactory.hpp"
89 #include "MueLu_ToggleCoordinatesTransferFactory.hpp"
90 #include "MueLu_TransPFactory.hpp"
91 #include "MueLu_UncoupledAggregationFactory.hpp"
92 #include "MueLu_ZoltanInterface.hpp"
93 #include "MueLu_Zoltan2Interface.hpp"
94 
95 #ifdef HAVE_MUELU_KOKKOS_REFACTOR
96 #include "MueLu_SaPFactory_kokkos.hpp"
97 #include "MueLu_CoalesceDropFactory_kokkos.hpp"
98 #endif
99 
100 #ifdef HAVE_MUELU_MATLAB
101 #include "../matlab/src/MueLu_MatlabSmoother_decl.hpp"
102 #include "../matlab/src/MueLu_MatlabSmoother_def.hpp"
103 #include "../matlab/src/MueLu_TwoLevelMatlabFactory_decl.hpp"
104 #include "../matlab/src/MueLu_TwoLevelMatlabFactory_def.hpp"
105 #include "../matlab/src/MueLu_SingleLevelMatlabFactory_decl.hpp"
106 #include "../matlab/src/MueLu_SingleLevelMatlabFactory_def.hpp"
107 #endif
108 
109 // These code chunks should only be enabled once Tpetra supports proper graph
110 // reuse in MMM. At the moment, only Epetra does, while Tpetra throws
111 // #define REUSE_MATRIX_GRAPHS
112 
113 namespace MueLu {
114 
115  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
116  ParameterListInterpreter<Scalar, LocalOrdinal, GlobalOrdinal, Node>::ParameterListInterpreter(ParameterList& paramList, Teuchos::RCP<const Teuchos::Comm<int> > comm, Teuchos::RCP<FactoryFactory> factFact) : factFact_(factFact) {
117 
118  if(paramList.isParameter("xml parameter file")){
119  std::string filename = paramList.get("xml parameter file","");
120  if(filename.length()!=0) {
121  if(comm.is_null()) throw Exceptions::RuntimeError("xml parameter file requires a valid comm");
122  Teuchos::ParameterList paramList2 = paramList;
123  Teuchos::updateParametersFromXmlFileAndBroadcast(filename, Teuchos::Ptr<Teuchos::ParameterList>(&paramList2),*comm);
124  SetParameterList(paramList2);
125  }
126  else
127  SetParameterList(paramList);
128  }
129  else
130  SetParameterList(paramList);
131  }
132 
133  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
134  ParameterListInterpreter<Scalar, LocalOrdinal, GlobalOrdinal, Node>::ParameterListInterpreter(const std::string& xmlFileName, const Teuchos::Comm<int>& comm,Teuchos::RCP<FactoryFactory> factFact) : factFact_(factFact) {
135  ParameterList paramList;
136  Teuchos::updateParametersFromXmlFileAndBroadcast(xmlFileName, Teuchos::Ptr<ParameterList>(&paramList), comm);
137  SetParameterList(paramList);
138  }
139 
140  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
143  blockSize_ = 1;
144  dofOffset_ = 0;
145 
146  if (paramList.isSublist("Hierarchy")) {
147  SetFactoryParameterList(paramList);
148 
149  } else {
150  // The validator doesn't work correctly for non-serializable data (Hint: template parameters), so strip it out
151  ParameterList validList, nonSerialList;
152 
153  ExtractNonSerializableData(paramList, validList, nonSerialList);
154  Validate(validList);
155  SetEasyParameterList(paramList);
156  }
157  }
158 
159  // =====================================================================================================
160  // ====================================== EASY interpreter =============================================
161  // =====================================================================================================
163  static inline bool areSame(const ParameterList& list1, const ParameterList& list2);
164 
165  // Get value from one of the lists, or set it to default
166  // Use case: check for a parameter value in a level-specific sublist, then in a root level list;
167  // if it is absent from both, set it to default
168 #define MUELU_SET_VAR_2LIST(paramList, defaultList, paramName, paramType, varName) \
169  paramType varName; \
170  if (paramList.isParameter(paramName)) varName = paramList.get<paramType>(paramName); \
171  else if (defaultList.isParameter(paramName)) varName = defaultList.get<paramType>(paramName); \
172  else varName = MasterList::getDefault<paramType>(paramName);
173 
174 #define MUELU_TEST_AND_SET_VAR(paramList, paramName, paramType, varName) \
175  (paramList.isParameter(paramName) ? varName = paramList.get<paramType>(paramName), true : false)
176 
177  // Set parameter in a list if it is present in any of two lists
178  // User case: set factory specific parameter, first checking for a level-specific value, then cheking root level value
179 #define MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, paramName, paramType, listWrite) \
180  try { \
181  if (paramList .isParameter(paramName)) listWrite.set(paramName, paramList .get<paramType>(paramName)); \
182  else if (defaultList.isParameter(paramName)) listWrite.set(paramName, defaultList.get<paramType>(paramName)); \
183  } \
184  catch(Teuchos::Exceptions::InvalidParameterType) { \
185  TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(true, Teuchos::Exceptions::InvalidParameterType, \
186  "Error: parameter \"" << paramName << "\" must be of type " << Teuchos::TypeNameTraits<paramType>::name()); \
187  } \
188 
189 #define MUELU_TEST_PARAM_2LIST(paramList, defaultList, paramName, paramType, cmpValue) \
190  (cmpValue == ( \
191  paramList.isParameter(paramName) ? paramList .get<paramType>(paramName) : ( \
192  defaultList.isParameter(paramName) ? defaultList.get<paramType>(paramName) : \
193  MasterList::getDefault<paramType>(paramName) ) ) )
194 
195 #ifndef HAVE_MUELU_KOKKOS_REFACTOR
196 #define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory) \
197  RCP<Factory> varName = rcp(new oldFactory());
198 #else
199 #define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory) \
200  RCP<Factory> varName; \
201  if (!useKokkos) varName = rcp(new oldFactory()); \
202  else varName = rcp(new newFactory());
203 #endif
204 
205 #ifndef HAVE_MUELU_KOKKOS_REFACTOR
206 #define MUELU_KOKKOS_FACTORY_NO_DECL(varName, oldFactory, newFactory) \
207  varName = rcp(new oldFactory());
208 #else
209 #define MUELU_KOKKOS_FACTORY_NO_DECL(varName, oldFactory, newFactory) \
210  if (!useKokkos) varName = rcp(new oldFactory()); \
211  else varName = rcp(new newFactory());
212 #endif
213 
214  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
216  ParameterList paramList;
217 
218  MUELU_SET_VAR_2LIST(constParamList, constParamList, "problem: type", std::string, problemType);
219  if (problemType != "unknown") {
220  paramList = *MasterList::GetProblemSpecificList(problemType);
221  paramList.setParameters(constParamList);
222  } else {
223  // Create a non const copy of the parameter list
224  // Working with a modifiable list is much much easier than with original one
225  paramList = constParamList;
226  }
227 
228  // Translate cycle type parameter
229  if (paramList.isParameter("cycle type")) {
230  std::map<std::string,CycleType> cycleMap;
231  cycleMap["V"] = VCYCLE;
232  cycleMap["W"] = WCYCLE;
233 
234  std::string cycleType = paramList.get<std::string>("cycle type");
235  TEUCHOS_TEST_FOR_EXCEPTION(cycleMap.count(cycleType) == 0, Exceptions::RuntimeError, "Invalid cycle type: \"" << cycleType << "\"");
236  Cycle_ = cycleMap[cycleType];
237  }
238 
239  this->maxCoarseSize_ = paramList.get<int> ("coarse: max size", MasterList::getDefault<int>("coarse: max size"));
240  this->numDesiredLevel_ = paramList.get<int> ("max levels", MasterList::getDefault<int>("max levels"));
241  blockSize_ = paramList.get<int> ("number of equations", MasterList::getDefault<int>("number of equations"));
242 
243  (void)MUELU_TEST_AND_SET_VAR(paramList, "debug: graph level", int, this->graphOutputLevel_);
244 
245  // Save level data
246  if (paramList.isSublist("export data")) {
247  ParameterList printList = paramList.sublist("export data");
248 
249  if (printList.isParameter("A"))
250  this->matricesToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "A");
251  if (printList.isParameter("P"))
252  this->prolongatorsToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "P");
253  if (printList.isParameter("R"))
254  this->restrictorsToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "R");
255  }
256 
257  // Set verbosity parameter
258  {
259  std::map<std::string,MsgType> verbMap;
260  verbMap["none"] = None;
261  verbMap["low"] = Low;
262  verbMap["medium"] = Medium;
263  verbMap["high"] = High;
264  verbMap["extreme"] = Extreme;
265  verbMap["test"] = Test;
266 
267  MUELU_SET_VAR_2LIST(paramList, paramList, "verbosity", std::string, verbosityLevel);
268 
269  TEUCHOS_TEST_FOR_EXCEPTION(verbMap.count(verbosityLevel) == 0, Exceptions::RuntimeError,
270  "Invalid verbosity level: \"" << verbosityLevel << "\"");
271  this->verbosity_ = verbMap[verbosityLevel];
272  this->SetVerbLevel(this->verbosity_);
273  }
274 
275  // Detect if we need to transfer coordinates to coarse levels. We do that iff
276  // - we use "distance laplacian" dropping on some level, or
277  // - we use repartitioning on some level
278  // - we use brick aggregation
279  // This is not ideal, as we may have "repartition: enable" turned on by default
280  // and not present in the list, but it is better than nothing.
281  useCoordinates_ = false;
282  if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "repartition: enable", bool, true) ||
283  MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: drop scheme", std::string, "distance laplacian") ||
284  MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: type", std::string, "brick") ||
285  MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: export visualization data", bool, true)) {
286  useCoordinates_ = true;
287 
288  } else {
289  for (int levelID = 0; levelID < this->numDesiredLevel_; levelID++) {
290  std::string levelStr = "level " + toString(levelID);
291 
292  if (paramList.isSublist(levelStr)) {
293  const ParameterList& levelList = paramList.sublist(levelStr);
294 
295  if (MUELU_TEST_PARAM_2LIST(levelList, paramList, "repartition: enable", bool, true) ||
296  MUELU_TEST_PARAM_2LIST(levelList, paramList, "aggregation: drop scheme", std::string, "distance laplacian") ||
297  MUELU_TEST_PARAM_2LIST(levelList, paramList, "aggregation: type", std::string, "brick") ||
298  MUELU_TEST_PARAM_2LIST(levelList, paramList, "aggregation: export visualization data", bool, true)) {
299  useCoordinates_ = true;
300  break;
301  }
302  }
303  }
304  }
305 
306  // Detect if we do implicit P and R rebalance
307  changedPRrebalance_ = false;
308  if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "repartition: enable", bool, true))
309  changedPRrebalance_ = MUELU_TEST_AND_SET_VAR(paramList, "repartition: rebalance P and R", bool, this->doPRrebalance_);
310 
311  // Detect if we use implicit transpose
312  changedImplicitTranspose_ = MUELU_TEST_AND_SET_VAR(paramList, "transpose: use implicit", bool, this->implicitTranspose_);
313 
314  // Create default manager
315  // FIXME: should it be here, or higher up
316  RCP<FactoryManager> defaultManager = rcp(new FactoryManager());
317  defaultManager->SetVerbLevel(this->verbosity_);
318 
319  // We will ignore keeps0
320  std::vector<keep_pair> keeps0;
321  UpdateFactoryManager(paramList, ParameterList(), *defaultManager, 0/*levelID*/, keeps0);
322 
323  // Create level specific factory managers
324  for (int levelID = 0; levelID < this->numDesiredLevel_; levelID++) {
325  // Note, that originally if there were no level specific parameters, we
326  // simply copied the defaultManager However, with the introduction of
327  // levelID to UpdateFactoryManager (required for reuse), we can no longer
328  // guarantee that the kept variables are the same for each level even if
329  // dependency structure does not change.
330  RCP<FactoryManager> levelManager = rcp(new FactoryManager(*defaultManager));
331  levelManager->SetVerbLevel(defaultManager->GetVerbLevel());
332 
333  std::vector<keep_pair> keeps;
334  if (paramList.isSublist("level " + toString(levelID))) {
335  // We do this so the parameters on the level get flagged correctly as "used"
336  ParameterList& levelList = paramList.sublist("level " + toString(levelID), true/*mustAlreadyExist*/);
337  UpdateFactoryManager(levelList, paramList, *levelManager, levelID, keeps);
338 
339  } else {
340  ParameterList levelList;
341  UpdateFactoryManager(levelList, paramList, *levelManager, levelID, keeps);
342  }
343 
344  this->keep_[levelID] = keeps;
345  this->AddFactoryManager(levelID, 1, levelManager);
346  }
347 
348  // FIXME: parameters passed to packages, like Ifpack2, are not touched by us, resulting in "[unused]" flag
349  // being displayed. On the other hand, we don't want to simply iterate through them touching. I don't know
350  // what a good solution looks like
351  if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "print initial parameters", bool, true))
352  this->GetOStream(static_cast<MsgType>(Runtime1), 0) << paramList << std::endl;
353 
354  if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "print unused parameters", bool, true)) {
355  // Check unused parameters
356  ParameterList unusedParamList;
357 
358  // Check for unused parameters that aren't lists
359  for (ParameterList::ConstIterator it = paramList.begin(); it != paramList.end(); it++) {
360  const ParameterEntry& entry = paramList.entry(it);
361 
362  if (!entry.isList() && !entry.isUsed())
363  unusedParamList.setEntry(paramList.name(it), entry);
364  }
365 
366  // Check for unused parameters in level-specific sublists
367  for (int levelID = 0; levelID < this->numDesiredLevel_; levelID++) {
368  std::string levelStr = "level " + toString(levelID);
369 
370  if (paramList.isSublist(levelStr)) {
371  const ParameterList& levelList = paramList.sublist(levelStr);
372 
373  for (ParameterList::ConstIterator itr = levelList.begin(); itr != levelList.end(); ++itr) {
374  const ParameterEntry& entry = levelList.entry(itr);
375 
376  if (!entry.isList() && !entry.isUsed())
377  unusedParamList.sublist(levelStr).setEntry(levelList.name(itr), entry);
378  }
379  }
380  }
381 
382  if (unusedParamList.numParams() > 0) {
383  std::ostringstream unusedParamsStream;
384  int indent = 4;
385  unusedParamList.print(unusedParamsStream, indent);
386 
387  this->GetOStream(Warnings1) << "The following parameters were not used:\n" << unusedParamsStream.str() << std::endl;
388  }
389  }
390 
391  }
392 
393  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
395  const ParameterList& defaultList, FactoryManager& manager, int levelID, std::vector<keep_pair>& keeps) const {
396  // NOTE: Factory::SetParameterList must be called prior to Factory::SetFactory, as
397  // SetParameterList sets default values for non mentioned parameters, including factories
398 
399  // shortcut
400  if (paramList.numParams() == 0 && defaultList.numParams() > 0)
401  paramList = ParameterList(defaultList);
402 
403  MUELU_SET_VAR_2LIST(paramList, defaultList, "reuse: type", std::string, reuseType);
404  TEUCHOS_TEST_FOR_EXCEPTION(reuseType != "none" && reuseType != "tP" && reuseType != "RP" && reuseType != "emin" && reuseType != "RAP" && reuseType != "full",
405  Exceptions::RuntimeError, "Unknown \"reuse: type\" value: \"" << reuseType << "\". Please consult User's Guide.");
406 
407  MUELU_SET_VAR_2LIST(paramList, defaultList, "multigrid algorithm", std::string, multigridAlgo);
408  TEUCHOS_TEST_FOR_EXCEPTION(multigridAlgo != "unsmoothed" && multigridAlgo != "sa" && multigridAlgo != "pg" && multigridAlgo != "emin" && multigridAlgo != "matlab", Exceptions::RuntimeError, "Unknown \"multigrid algorithm\" value: \"" << multigridAlgo << "\". Please consult User's Guide.");
409  #ifndef HAVE_MUELU_MATLAB
410  if(multigridAlgo == "matlab")
411  throw std::runtime_error("Cannot use matlab for multigrid algorithm - MueLu was not configured with MATLAB support.");
412  #endif
413  // Only some combinations of reuse and multigrid algorithms are tested, all
414  // other are considered invalid at the moment
415  if (reuseType == "none" || reuseType == "RP" || reuseType == "RAP") {
416  // This works for all kinds of multigrid algorithms
417 
418  } else if (reuseType == "tP" && (multigridAlgo != "sa" && multigridAlgo != "unsmoothed")) {
419  reuseType = "none";
420  this->GetOStream(Warnings0) << "Ignoring \"tP\" reuse option as it is only compatible with \"sa\", or \"unsmoothed\" multigrid algorithms" << std::endl;
421 
422  } else if (reuseType == "emin" && multigridAlgo != "emin") {
423  reuseType = "none";
424  this->GetOStream(Warnings0) << "Ignoring \"emin\" reuse option it is only compatible with \"emin\" multigrid algorithm" << std::endl;
425  }
426 
427  MUELU_SET_VAR_2LIST(paramList, defaultList, "use kokkos refactor", bool, useKokkos);
428  (void) useKokkos;
429 
430  // == Non-serializable data ===
431  // Check both the parameter and the type
432  bool have_userA = false, have_userP = false, have_userR = false, have_userNS = false, have_userCO = false;
433  if (paramList.isParameter("A") && !paramList.get<RCP<Matrix> > ("A") .is_null()) have_userA = true;
434  if (paramList.isParameter("P") && !paramList.get<RCP<Matrix> > ("P") .is_null()) have_userP = true;
435  if (paramList.isParameter("R") && !paramList.get<RCP<Matrix> > ("R") .is_null()) have_userR = true;
436  if (paramList.isParameter("Nullspace") && !paramList.get<RCP<MultiVector> >("Nullspace") .is_null()) have_userNS = true;
437  if (paramList.isParameter("Coordinates") && !paramList.get<RCP<MultiVector> >("Coordinates").is_null()) have_userCO = true;
438 
439  // === Smoothing ===
440  // FIXME: should custom smoother check default list too?
441  bool isCustomSmoother =
442  paramList.isParameter("smoother: pre or post") ||
443  paramList.isParameter("smoother: type") || paramList.isParameter("smoother: pre type") || paramList.isParameter("smoother: post type") ||
444  paramList.isSublist ("smoother: params") || paramList.isSublist ("smoother: pre params") || paramList.isSublist ("smoother: post params") ||
445  paramList.isParameter("smoother: sweeps") || paramList.isParameter("smoother: pre sweeps") || paramList.isParameter("smoother: post sweeps") ||
446  paramList.isParameter("smoother: overlap") || paramList.isParameter("smoother: pre overlap") || paramList.isParameter("smoother: post overlap");
447  MUELU_SET_VAR_2LIST(paramList, defaultList, "smoother: pre or post", std::string, PreOrPost);
448  if (PreOrPost == "none") {
449  manager.SetFactory("Smoother", Teuchos::null);
450 
451  } else if (isCustomSmoother) {
452  // FIXME: get default values from the factory
453  // NOTE: none of the smoothers at the moment use parameter validation framework, so we
454  // cannot get the default values from it.
455 #define TEST_MUTUALLY_EXCLUSIVE(arg1,arg2) \
456  TEUCHOS_TEST_FOR_EXCEPTION(paramList.isParameter(#arg1) && paramList.isParameter(#arg2), \
457  Exceptions::InvalidArgument, "You cannot specify both \""#arg1"\" and \""#arg2"\"");
458 #define TEST_MUTUALLY_EXCLUSIVE_S(arg1,arg2) \
459  TEUCHOS_TEST_FOR_EXCEPTION(paramList.isSublist(#arg1) && paramList.isSublist(#arg2), \
460  Exceptions::InvalidArgument, "You cannot specify both \""#arg1"\" and \""#arg2"\"");
461 
462  TEST_MUTUALLY_EXCLUSIVE ("smoother: type", "smoother: pre type");
463  TEST_MUTUALLY_EXCLUSIVE ("smoother: type", "smoother: post type");
464  TEST_MUTUALLY_EXCLUSIVE ("smoother: sweeps", "smoother: pre sweeps");
465  TEST_MUTUALLY_EXCLUSIVE ("smoother: sweeps", "smoother: post sweeps");
466  TEST_MUTUALLY_EXCLUSIVE ("smoother: overlap", "smoother: pre overlap");
467  TEST_MUTUALLY_EXCLUSIVE ("smoother: overlap", "smoother: post overlap");
468  TEST_MUTUALLY_EXCLUSIVE_S("smoother: params", "smoother: pre params");
469  TEST_MUTUALLY_EXCLUSIVE_S("smoother: params", "smoother: post params");
470  TEUCHOS_TEST_FOR_EXCEPTION(PreOrPost == "both" && (paramList.isParameter("smoother: pre type") != paramList.isParameter("smoother: post type")),
471  Exceptions::InvalidArgument, "You must specify both \"smoother: pre type\" and \"smoother: post type\"");
472 
473  // Default values
474  int overlap = 0;
475  ParameterList defaultSmootherParams;
476  defaultSmootherParams.set("relaxation: type", "Symmetric Gauss-Seidel");
477  defaultSmootherParams.set("relaxation: sweeps", Teuchos::OrdinalTraits<LO>::one());
478  defaultSmootherParams.set("relaxation: damping factor", Teuchos::ScalarTraits<Scalar>::one());
479 
480  RCP<SmootherFactory> preSmoother = Teuchos::null, postSmoother = Teuchos::null;
481  std::string preSmootherType, postSmootherType;
482  ParameterList preSmootherParams, postSmootherParams;
483 
484  if (paramList.isParameter("smoother: overlap"))
485  overlap = paramList.get<int>("smoother: overlap");
486 
487  if (PreOrPost == "pre" || PreOrPost == "both") {
488  if (paramList.isParameter("smoother: pre type")) {
489  preSmootherType = paramList.get<std::string>("smoother: pre type");
490  } else {
491  MUELU_SET_VAR_2LIST(paramList, defaultList, "smoother: type", std::string, preSmootherTypeTmp);
492  preSmootherType = preSmootherTypeTmp;
493  }
494  if (paramList.isParameter("smoother: pre overlap"))
495  overlap = paramList.get<int>("smoother: pre overlap");
496 
497  if (paramList.isSublist("smoother: pre params"))
498  preSmootherParams = paramList.sublist("smoother: pre params");
499  else if (paramList.isSublist("smoother: params"))
500  preSmootherParams = paramList.sublist("smoother: params");
501  else if (defaultList.isSublist("smoother: params"))
502  preSmootherParams = defaultList.sublist("smoother: params");
503  else if (preSmootherType == "RELAXATION")
504  preSmootherParams = defaultSmootherParams;
505 #ifdef HAVE_MUELU_MATLAB
506  if(preSmootherType == "matlab")
507  preSmoother = rcp(new SmootherFactory(rcp(new MatlabSmoother<Scalar,LocalOrdinal, GlobalOrdinal, Node>(preSmootherParams))));
508  else
509 #endif
510  preSmoother = rcp(new SmootherFactory(rcp(new TrilinosSmoother(preSmootherType, preSmootherParams, overlap))));
511  }
512 
513  if (PreOrPost == "post" || PreOrPost == "both") {
514  if (paramList.isParameter("smoother: post type"))
515  postSmootherType = paramList.get<std::string>("smoother: post type");
516  else {
517  MUELU_SET_VAR_2LIST(paramList, defaultList, "smoother: type", std::string, postSmootherTypeTmp);
518  postSmootherType = postSmootherTypeTmp;
519  }
520 
521  if (paramList.isSublist("smoother: post params"))
522  postSmootherParams = paramList.sublist("smoother: post params");
523  else if (paramList.isSublist("smoother: params"))
524  postSmootherParams = paramList.sublist("smoother: params");
525  else if (defaultList.isSublist("smoother: params"))
526  postSmootherParams = defaultList.sublist("smoother: params");
527  else if (postSmootherType == "RELAXATION")
528  postSmootherParams = defaultSmootherParams;
529  if (paramList.isParameter("smoother: post overlap"))
530  overlap = paramList.get<int>("smoother: post overlap");
531 
532  if (postSmootherType == preSmootherType && areSame(preSmootherParams, postSmootherParams))
533  postSmoother = preSmoother;
534  else
535 #ifdef HAVE_MUELU_MATLAB
536  if(postSmootherType == "matlab")
537  postSmoother = rcp(new SmootherFactory(rcp(new MatlabSmoother<Scalar, LocalOrdinal, GlobalOrdinal, Node>(postSmootherParams))));
538  else
539 #endif
540  postSmoother = rcp(new SmootherFactory(rcp(new TrilinosSmoother(postSmootherType, postSmootherParams, overlap))));
541  }
542 
543  if (preSmoother == postSmoother)
544  manager.SetFactory("Smoother", preSmoother);
545  else {
546  manager.SetFactory("PreSmoother", preSmoother);
547  manager.SetFactory("PostSmoother", postSmoother);
548  }
549  }
550  if ((reuseType == "RAP" && levelID) || (reuseType == "full")) {
551  // The difference between "RAP" and "full" is keeping smoothers. However,
552  // as in both cases we keep coarse matrices, we do not need to update
553  // coarse smoothers. On the other hand, if a user changes fine level
554  // matrix, "RAP" would update the fine level smoother, while "full" would
555  // not
556  keeps.push_back(keep_pair("PreSmoother", manager.GetFactory("PreSmoother") .get()));
557  keeps.push_back(keep_pair("PostSmoother", manager.GetFactory("PostSmoother").get()));
558  }
559 
560  // === Coarse solver ===
561  // FIXME: should custom coarse solver check default list too?
562  bool isCustomCoarseSolver =
563  paramList.isParameter("coarse: type") ||
564  paramList.isParameter("coarse: params");
565  if (MUELU_TEST_PARAM_2LIST(paramList, defaultList, "coarse: type", std::string, "none")) {
566  manager.SetFactory("CoarseSolver", Teuchos::null);
567 
568  } else if (isCustomCoarseSolver) {
569  // FIXME: get default values from the factory
570  // NOTE: none of the smoothers at the moment use parameter validation framework, so we
571  // cannot get the default values from it.
572  MUELU_SET_VAR_2LIST(paramList, defaultList, "coarse: type", std::string, coarseType);
573 
574  int overlap = 0;
575  if (paramList.isParameter("coarse: overlap"))
576  overlap = paramList.get<int>("coarse: overlap");
577 
578  ParameterList coarseParams;
579  if (paramList.isSublist("coarse: params"))
580  coarseParams = paramList.sublist("coarse: params");
581  else if (defaultList.isSublist("coarse: params"))
582  coarseParams = defaultList.sublist("coarse: params");
583 
584  RCP<SmootherPrototype> coarseSmoother;
585  // TODO: this is not a proper place to check. If we consider direct solver to be a special
586  // case of smoother, we would like to unify Amesos and Ifpack2 smoothers in src/Smoothers, and
587  // have a single factory responsible for those. Then, this check would belong there.
588  if (coarseType == "RELAXATION" || coarseType == "CHEBYSHEV" ||
589  coarseType == "ILUT" || coarseType == "ILU" || coarseType == "RILUK" || coarseType == "SCHWARZ" ||
590  coarseType == "Amesos" ||
591  coarseType == "LINESMOOTHING_BANDEDRELAXATION" ||
592  coarseType == "LINESMOOTHING_BANDED_RELAXATION" ||
593  coarseType == "LINESMOOTHING_BANDED RELAXATION")
594  coarseSmoother = rcp(new TrilinosSmoother(coarseType, coarseParams, overlap));
595  else
596 #ifdef HAVE_MUELU_MATLAB
597  if(coarseType == "matlab")
598  coarseSmoother = rcp(new MatlabSmoother<Scalar,LocalOrdinal, GlobalOrdinal, Node>(coarseParams));
599  else
600 #endif
601  coarseSmoother = rcp(new DirectSolver(coarseType, coarseParams));
602 
603  manager.SetFactory("CoarseSolver", rcp(new SmootherFactory(coarseSmoother)));
604  }
605  if ((reuseType == "RAP" && levelID) || (reuseType == "full")) {
606  // We do keep_pair("PreSmoother", // manager.GetFactory("CoarseSolver").get())
607  // as the coarse solver factory is in fact a smoothing factory, so the
608  // only pieces of data it generates are PreSmoother and PostSmoother
609  keeps.push_back(keep_pair("PreSmoother", manager.GetFactory("CoarseSolver").get()));
610  }
611 
612  // === Aggregation ===
613  // Aggregation graph
614  RCP<Factory> dropFactory;
615 
616  if (MUELU_TEST_PARAM_2LIST(paramList, paramList, "aggregation: drop scheme", std::string, "matlab")) {
617 #ifdef HAVE_MUELU_MATLAB
619  ParameterList socParams = paramList.sublist("strength-of-connection: params");
620  dropFactory->SetParameterList(socParams);
621 #else
622  throw std::runtime_error("Cannot use MATLAB evolutionary strength-of-connection - MueLu was not configured with MATLAB support.");
623 #endif
624  } else {
625  MUELU_KOKKOS_FACTORY_NO_DECL(dropFactory, CoalesceDropFactory, CoalesceDropFactory_kokkos);
626  ParameterList dropParams;
627  dropParams.set("lightweight wrap", true);
628  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: drop scheme", std::string, dropParams);
629  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: drop tol", double, dropParams);
630  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: Dirichlet threshold", double, dropParams);
631  dropFactory->SetParameterList(dropParams);
632  }
633  manager.SetFactory("Graph", dropFactory);
634 
635  // Aggregation scheme
636  MUELU_SET_VAR_2LIST(paramList, defaultList, "aggregation: type", std::string, aggType);
637  TEUCHOS_TEST_FOR_EXCEPTION(aggType != "uncoupled" && aggType != "coupled" && aggType != "brick" && aggType != "matlab",
638  Exceptions::RuntimeError, "Unknown aggregation algorithm: \"" << aggType << "\". Please consult User's Guide.");
639  #ifndef HAVE_MUELU_MATLAB
640  if(aggType == "matlab")
641  throw std::runtime_error("Cannot use MATLAB aggregation - MueLu was not configured with MATLAB support.");
642  #endif
643  RCP<Factory> aggFactory;
644  if (aggType == "uncoupled") {
645  aggFactory = rcp(new UncoupledAggregationFactory());
646  ParameterList aggParams;
647  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: mode", std::string, aggParams);
648  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: ordering", std::string, aggParams);
649  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: min agg size", int, aggParams);
650  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: max agg size", int, aggParams);
651  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: max selected neighbors", int, aggParams);
652  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: enable phase 1", bool, aggParams);
653  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: enable phase 2a", bool, aggParams);
654  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: enable phase 2b", bool, aggParams);
655  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: enable phase 3", bool, aggParams);
656  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: preserve Dirichlet points", bool, aggParams);
657  aggFactory->SetParameterList(aggParams);
658  // make sure that the aggregation factory has all necessary data
659  aggFactory->SetFactory("DofsPerNode", manager.GetFactory("Graph"));
660  aggFactory->SetFactory("Graph", manager.GetFactory("Graph"));
661  } else if (aggType == "coupled") {
662  aggFactory = rcp(new CoupledAggregationFactory());
663  aggFactory->SetFactory("Graph", manager.GetFactory("Graph"));
664  } else if (aggType == "brick") {
665  aggFactory = rcp(new BrickAggregationFactory());
666  ParameterList aggParams;
667  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: brick x size", int, aggParams);
668  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: brick y size", int, aggParams);
669  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: brick z size", int, aggParams);
670  aggFactory->SetParameterList(aggParams);
671  if (levelID > 1) {
672  // We check for levelID > 0, as in the interpreter aggFactory for
673  // levelID really corresponds to level 0. Managers are clunky, as they
674  // contain factories for two different levels
675  aggFactory->SetFactory("Coordinates", this->GetFactoryManager(levelID-1)->GetFactory("Coordinates"));
676  }
677  }
678 #ifdef HAVE_MUELU_MATLAB
679  else if(aggType == "matlab") {
680  ParameterList aggParams = paramList.sublist("aggregation: params");
682  aggFactory->SetParameterList(aggParams);
683  }
684 #endif
685  manager.SetFactory("Aggregates", aggFactory);
686 
687  // Coarse map
688  RCP<CoarseMapFactory> coarseMap = rcp(new CoarseMapFactory());
689  coarseMap->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
690  manager.SetFactory("CoarseMap", coarseMap);
691 
692  // Tentative P
693  RCP<Factory> Ptent = rcp(new TentativePFactory());
694  Ptent->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
695  Ptent->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
696 
697  manager.SetFactory("Ptent", Ptent);
698 
699  if (reuseType == "tP") {
700  keeps.push_back(keep_pair("Nullspace", manager.GetFactory("Ptent").get()));
701  keeps.push_back(keep_pair("P", manager.GetFactory("Ptent").get()));
702  }
703 
704  // Nullspace
705  RCP<NullspaceFactory> nullSpace = rcp(new NullspaceFactory());
706  if (!have_userNS) {
707  nullSpace->SetFactory("Nullspace", manager.GetFactory("Ptent"));
708  manager.SetFactory("Nullspace", nullSpace);
709  }
710 
711  // === Prolongation ===
712  TEUCHOS_TEST_FOR_EXCEPTION(multigridAlgo != "unsmoothed" && multigridAlgo != "sa" && multigridAlgo != "pg" && multigridAlgo != "emin" && multigridAlgo != "matlab", Exceptions::RuntimeError, "Unknown multigrid algorithm: \"" << multigridAlgo << "\". Please consult User's Guide.");
713  #ifndef HAVE_MUELU_MATLAB
714  if(multigridAlgo == "matlab")
715  throw std::runtime_error("Cannot use MATLAB prolongator factory - MueLu was not configured with MATLAB support.");
716  #endif
717  if (have_userP) {
718  // User prolongator
719  manager.SetFactory("P", NoFactory::getRCP());
720  } else if (multigridAlgo == "unsmoothed") {
721  // Unsmoothed aggregation
722  manager.SetFactory("P", Ptent);
723  } else if (multigridAlgo == "sa") {
724  // Smoothed aggregation
725  MUELU_KOKKOS_FACTORY(P, SaPFactory, SaPFactory_kokkos);
726  ParameterList Pparams;
727  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "sa: damping factor", double, Pparams);
728 #if REUSE_MATRIX_GRAPHS
729  if (reuseType == "tP" && MUELU_TEST_PARAM_2LIST(paramList, defaultList, "sa: use filtered matrix", bool, false)) {
730  // Pattern can only be reuse when we don't use filtered matrix, as
731  // otherwise graph can potentially change
732  Pparams.set("Keep AP Pattern", true);
733  }
734 #endif
735  P->SetParameterList(Pparams);
736 
737  // Filtering
738  if (MUELU_TEST_PARAM_2LIST(paramList, defaultList, "sa: use filtered matrix", bool, true)) {
739  RCP<FilteredAFactory> filterFactory = rcp(new FilteredAFactory());
740  ParameterList fParams;
741  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: use lumping", bool, fParams);
742  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: reuse graph", bool, fParams);
743  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "filtered matrix: reuse eigenvalue", bool, fParams);
744  filterFactory->SetParameterList(fParams);
745  filterFactory->SetFactory("Graph", manager.GetFactory("Graph"));
746  // I'm not sure why we need this line. See comments for DofsPerNode for UncoupledAggregation above
747  filterFactory->SetFactory("Filtering", manager.GetFactory("Graph"));
748  P->SetFactory("A", filterFactory);
749  }
750 
751  P->SetFactory("P", manager.GetFactory("Ptent"));
752  manager.SetFactory("P", P);
753 
754  } else if (multigridAlgo == "emin") {
755  MUELU_SET_VAR_2LIST(paramList, defaultList, "emin: pattern", std::string, patternType);
756  TEUCHOS_TEST_FOR_EXCEPTION(patternType != "AkPtent", Exceptions::InvalidArgument,
757  "Invalid pattern name: \"" << patternType << "\". Valid options: \"AkPtent\"");
758  // Pattern
759  RCP<PatternFactory> patternFactory = rcp(new PatternFactory());
760  ParameterList patternParams;
761  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "emin: pattern order", int, patternParams);
762  patternFactory->SetParameterList(patternParams);
763  patternFactory->SetFactory("P", manager.GetFactory("Ptent"));
764  manager.SetFactory("Ppattern", patternFactory);
765 
766  // Constraint
767  RCP<ConstraintFactory> constraintFactory = rcp(new ConstraintFactory());
768  constraintFactory->SetFactory("Ppattern", manager.GetFactory("Ppattern"));
769  constraintFactory->SetFactory("CoarseNullspace", manager.GetFactory("Ptent"));
770  manager.SetFactory("Constraint", constraintFactory);
771 
772  // Energy minimization
773  RCP<EminPFactory> P = rcp(new EminPFactory());
774  ParameterList Pparams;
775  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "emin: num iterations", int, Pparams);
776  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "emin: iterative method", std::string, Pparams);
777  if (reuseType == "emin") {
778  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "emin: num reuse iterations", int, Pparams);
779  Pparams.set("Keep P0", true);
780  Pparams.set("Keep Constraint0", true);
781  }
782  P->SetParameterList(Pparams);
783  P->SetFactory("P", manager.GetFactory("Ptent"));
784  P->SetFactory("Constraint", manager.GetFactory("Constraint"));
785  manager.SetFactory("P", P);
786 
787  } else if (multigridAlgo == "pg") {
788  TEUCHOS_TEST_FOR_EXCEPTION(this->implicitTranspose_, Exceptions::RuntimeError,
789  "Implicit transpose not supported with Petrov-Galerkin smoothed transfer operators: Set \"transpose: use implicit\" to false!\n" \
790  "Petrov-Galerkin transfer operator smoothing for non-symmetric problems requires a separate handling of the restriction operator which " \
791  "does not allow the usage of implicit transpose easily.");
792 
793  // Petrov-Galerkin
794  RCP<PgPFactory> P = rcp(new PgPFactory());
795  P->SetFactory("P", manager.GetFactory("Ptent"));
796  manager.SetFactory("P", P);
797  }
798 #ifdef HAVE_MUELU_MATLAB
799  else if(multigridAlgo == "matlab") {
800  ParameterList Pparams = paramList.sublist("transfer: params");
801  RCP<TwoLevelMatlabFactory<Scalar,LocalOrdinal, GlobalOrdinal, Node> > P = rcp(new TwoLevelMatlabFactory<Scalar,LocalOrdinal, GlobalOrdinal, Node>());
802  P->SetParameterList(Pparams);
803  P->SetFactory("P",manager.GetFactory("Ptent"));
804  manager.SetFactory("P", P);
805  }
806 #endif
807 
808  // === Semi-coarsening ===
809  RCP<SemiCoarsenPFactory> semicoarsenFactory = Teuchos::null;
810  if (paramList.isParameter("semicoarsen: number of levels") &&
811  paramList.get<int>("semicoarsen: number of levels") > 0) {
812 
813  ParameterList togglePParams;
814  ParameterList semicoarsenPParams;
815  ParameterList linedetectionParams;
816  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "semicoarsen: number of levels", int, togglePParams);
817  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "semicoarsen: coarsen rate", int, semicoarsenPParams);
818  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "linedetection: orientation", std::string, linedetectionParams);
819  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "linedetection: num layers", int, linedetectionParams);
820 
821  semicoarsenFactory = rcp(new SemiCoarsenPFactory());
822  RCP<LineDetectionFactory> linedetectionFactory = rcp(new LineDetectionFactory());
823  RCP<TogglePFactory> togglePFactory = rcp(new TogglePFactory());
824 
825  linedetectionFactory->SetParameterList(linedetectionParams);
826  semicoarsenFactory->SetParameterList(semicoarsenPParams);
827  togglePFactory->SetParameterList(togglePParams);
828  togglePFactory->AddCoarseNullspaceFactory(semicoarsenFactory);
829  togglePFactory->AddProlongatorFactory(semicoarsenFactory);
830  togglePFactory->AddPtentFactory(semicoarsenFactory);
831  togglePFactory->AddCoarseNullspaceFactory(manager.GetFactory("Ptent"));
832  togglePFactory->AddProlongatorFactory(manager.GetFactory("P"));
833  togglePFactory->AddPtentFactory(manager.GetFactory("Ptent"));
834 
835  manager.SetFactory("CoarseNumZLayers", linedetectionFactory);
836  manager.SetFactory("LineDetection_Layers", linedetectionFactory);
837  manager.SetFactory("LineDetection_VertLineIds", linedetectionFactory);
838 
839  manager.SetFactory("P", togglePFactory);
840  manager.SetFactory("Ptent", togglePFactory);
841  manager.SetFactory("Nullspace", togglePFactory);
842  }
843 
844  // === Restriction ===
845  if (!this->implicitTranspose_) {
846  MUELU_SET_VAR_2LIST(paramList, defaultList, "problem: symmetric", bool, isSymmetric);
847  if (isSymmetric == false && (multigridAlgo == "unsmoothed" || multigridAlgo == "emin")) {
848  this->GetOStream(Warnings0) << "Switching \"problem: symmetric\" parameter to symmetric as multigrid algorithm. " << multigridAlgo << " is primarily supposed to be used for symmetric problems." << std::endl << std::endl;
849  this->GetOStream(Warnings0) << "Please note: if you are using \"unsmoothed\" transfer operators the \"problem: symmetric\" parameter has no real mathematical meaning, i.e. you can use it for non-symmetric" << std::endl;
850  this->GetOStream(Warnings0) << "problems, too. With \"problem: symmetric\"=\"symmetric\" you can use implicit transpose for building the restriction operators which may drastically reduce the amount of consumed memory." << std::endl;
851  isSymmetric = true;
852  }
853  TEUCHOS_TEST_FOR_EXCEPTION(multigridAlgo == "pg" && isSymmetric == true, Exceptions::RuntimeError,
854  "Petrov-Galerkin smoothed transfer operators are only allowed for non-symmetric problems: Set \"problem: symmetric\" to false!\n" \
855  "While PG smoothed transfer operators generally would also work for symmetric problems this is an unusual use case. " \
856  "You can use the factory-based xml interface though if you need PG-AMG for symmetric problems.");
857 
858  if (have_userR) {
859  manager.SetFactory("R", NoFactory::getRCP());
860  } else {
861  RCP<Factory> R;
862  if (isSymmetric) R = rcp(new TransPFactory());
863  else R = rcp(new GenericRFactory());
864 
865  R->SetFactory("P", manager.GetFactory("P"));
866  manager.SetFactory("R", R);
867  }
868 
869  } else {
870  manager.SetFactory("R", Teuchos::null);
871  }
872 
873  // === RAP ===
874  RCP<RAPFactory> RAP;
875  if (have_userA) {
876  manager.SetFactory("A", NoFactory::getRCP());
877 
878  } else {
879  RAP = rcp(new RAPFactory());
880  ParameterList RAPparams;
881  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "transpose: use implicit", bool, RAPparams);
882 #if REUSE_MATRIX_GRAPHS
883  // This should be enable once Tpetra supports proper graph reuse in MMM
884  // At the moment, only Epetra does, and Tpetra throws
885  if (reuseType == "RP") {
886  RAPparams.set("Keep AP Pattern", true);
887  RAPparams.set("Keep RAP Pattern", true);
888  }
889 #endif
890  RAP->SetParameterList(RAPparams);
891  RAP->SetFactory("P", manager.GetFactory("P"));
892  if (!this->implicitTranspose_)
893  RAP->SetFactory("R", manager.GetFactory("R"));
894  if (MUELU_TEST_PARAM_2LIST(paramList, defaultList, "aggregation: export visualization data", bool, true)) {
895  RCP<AggregationExportFactory> aggExport = rcp(new AggregationExportFactory());
896  ParameterList aggExportParams;
897  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output filename", std::string, aggExportParams);
898  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: agg style", std::string, aggExportParams);
899  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: iter", int, aggExportParams);
900  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: time step", int, aggExportParams);
901  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: fine graph edges", bool, aggExportParams);
902  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: coarse graph edges", bool, aggExportParams);
903  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "aggregation: output file: build colormap", bool, aggExportParams);
904  aggExport->SetParameterList(aggExportParams);
905  aggExport->SetFactory("DofsPerNode", manager.GetFactory("DofsPerNode"));
906  RAP->AddTransferFactory(aggExport);
907  }
908  manager.SetFactory("A", RAP);
909  }
910 
911  // === Coordinates ===
912  if (useCoordinates_) {
913  if (have_userCO) {
914  manager.SetFactory("Coordinates", NoFactory::getRCP());
915 
916  } else {
917  RCP<CoordinatesTransferFactory> coords = rcp(new CoordinatesTransferFactory());
918  coords->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
919  coords->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
920  manager.SetFactory("Coordinates", coords);
921 
922  if (paramList.isParameter("semicoarsen: number of levels")) {
923  RCP<ToggleCoordinatesTransferFactory> tf = rcp(new ToggleCoordinatesTransferFactory());
924  tf->SetFactory("Chosen P", manager.GetFactory("P"));
925  tf->AddCoordTransferFactory(semicoarsenFactory);
926  tf->AddCoordTransferFactory(coords);
927  manager.SetFactory("Coordinates", tf);
928 
929  }
930  RAP->AddTransferFactory(manager.GetFactory("Coordinates"));
931  }
932  }
933 
934  if (reuseType == "RP" || reuseType == "RAP" || reuseType == "full")
935  keeps.push_back(keep_pair("Nullspace", manager.GetFactory("Nullspace").get()));
936 
937  if (reuseType == "RP") {
938  keeps.push_back(keep_pair("P", manager.GetFactory("P").get()));
939  if (!this->implicitTranspose_)
940  keeps.push_back(keep_pair("R", manager.GetFactory("R").get()));
941  }
942  if ((reuseType == "tP" || reuseType == "RP" || reuseType == "emin") && useCoordinates_)
943  keeps.push_back(keep_pair("Coordinates", manager.GetFactory("Coordinates").get()));
944 
945  // === Repartitioning ===
946  MUELU_SET_VAR_2LIST(paramList, defaultList, "repartition: enable", bool, enableRepart);
947  if (enableRepart) {
948 #ifdef HAVE_MPI
949  // Short summary of the issue: RebalanceTransferFactory shares ownership
950  // of "P" with SaPFactory, and therefore, changes the stored version.
951  // That means that if SaPFactory generated P, and stored it on the level,
952  // then after rebalancing the value in that storage changed. It goes
953  // against the concept of factories (I think), that every factory is
954  // responsible for its own objects, and they are immutable outside.
955  //
956  // In reuse, this is what happens: as we reuse Importer across setups,
957  // the order of factories changes, and coupled with shared ownership
958  // leads to problems.
959  // *First setup*
960  // SaP builds P [and stores it]
961  // TransP builds R [and stores it]
962  // RAP builds A [and stores it]
963  // RebalanceTransfer rebalances P [and changes the P stored by SaP] (*)
964  // RebalanceTransfer rebalances R
965  // RebalanceAc rebalances A
966  // *Second setup* ("RP" reuse)
967  // RebalanceTransfer rebalances P [which is incorrect due to (*)]
968  // RebalanceTransfer rebalances R
969  // RAP builds A [which is incorrect due to (*)]
970  // RebalanceAc rebalances A [which throws due to map inconsistency]
971  // ...
972  // *Second setup* ("tP" reuse)
973  // SaP builds P [and stores it]
974  // RebalanceTransfer rebalances P [and changes the P stored by SaP] (**)
975  // TransP builds R [which is incorrect due to (**)]
976  // RebalanceTransfer rebalances R
977  // ...
978  //
979  // Couple solutions to this:
980  // 1. [implemented] Requre "tP" and "PR" reuse to only be used with
981  // implicit rebalancing.
982  // 2. Do deep copy of P, and changed domain map and importer there.
983  // Need to investigate how expensive this is.
984  TEUCHOS_TEST_FOR_EXCEPTION(this->doPRrebalance_ && (reuseType == "tP" || reuseType == "RP"), Exceptions::InvalidArgument,
985  "Reuse types \"tP\" and \"PR\" require \"repartition: rebalance P and R\" set to \"false\"");
986 
987  TEUCHOS_TEST_FOR_EXCEPTION(aggType == "brick", Exceptions::InvalidArgument,
988  "Aggregation type \"brick\" requires \"repartition: enable\" set to \"false\"");
989 
990  MUELU_SET_VAR_2LIST(paramList, defaultList, "repartition: partitioner", std::string, partName);
991  TEUCHOS_TEST_FOR_EXCEPTION(partName != "zoltan" && partName != "zoltan2", Exceptions::InvalidArgument,
992  "Invalid partitioner name: \"" << partName << "\". Valid options: \"zoltan\", \"zoltan2\"");
993  // Partitioner
994  RCP<Factory> partitioner;
995  if (partName == "zoltan") {
996 #ifdef HAVE_MUELU_ZOLTAN
997  partitioner = rcp(new ZoltanInterface());
998  // NOTE: ZoltanInteface ("zoltan") does not support external parameters through ParameterList
999 #else
1000  throw Exceptions::RuntimeError("Zoltan interface is not available");
1001 #endif
1002  } else if (partName == "zoltan2") {
1003 #ifdef HAVE_MUELU_ZOLTAN2
1004  partitioner = rcp(new Zoltan2Interface());
1005  ParameterList partParams;
1006  RCP<const ParameterList> partpartParams = rcp(new ParameterList(paramList.sublist("repartition: params", false)));
1007  partParams.set("ParameterList", partpartParams);
1008  partitioner->SetParameterList(partParams);
1009 #else
1010  throw Exceptions::RuntimeError("Zoltan2 interface is not available");
1011 #endif
1012  }
1013  partitioner->SetFactory("A", manager.GetFactory("A"));
1014  partitioner->SetFactory("Coordinates", manager.GetFactory("Coordinates"));
1015  manager.SetFactory("Partition", partitioner);
1016 
1017  // Repartitioner
1018  RCP<RepartitionFactory> repartFactory = rcp(new RepartitionFactory());
1019  ParameterList repartParams;
1020  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: start level", int, repartParams);
1021  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: min rows per proc", int, repartParams);
1022  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: max imbalance", double, repartParams);
1023  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: keep proc 0", bool, repartParams);
1024  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: print partition distribution", bool, repartParams);
1025  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: remap parts", bool, repartParams);
1026  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: remap num values", int, repartParams);
1027  repartFactory->SetParameterList(repartParams);
1028  repartFactory->SetFactory("A", manager.GetFactory("A"));
1029  repartFactory->SetFactory("Partition", manager.GetFactory("Partition"));
1030  manager.SetFactory("Importer", repartFactory);
1031  if (reuseType != "none")
1032  keeps.push_back(keep_pair("Importer", manager.GetFactory("Importer").get()));
1033 
1034  // Rebalanced A
1035  RCP<RebalanceAcFactory> newA = rcp(new RebalanceAcFactory());
1036  ParameterList rebAcParams;
1037  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: use subcommunicators", bool, rebAcParams);
1038  newA->SetParameterList(rebAcParams);
1039  newA->SetFactory("A", manager.GetFactory("A"));
1040  newA->SetFactory("Importer", manager.GetFactory("Importer"));
1041  manager.SetFactory("A", newA);
1042 
1043  // Rebalanced P
1044  RCP<RebalanceTransferFactory> newP = rcp(new RebalanceTransferFactory());
1045  ParameterList newPparams;
1046  newPparams.set("type", "Interpolation");
1047  if (changedPRrebalance_)
1048  newPparams.set("repartition: rebalance P and R", this->doPRrebalance_);
1049  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: use subcommunicators", bool, newPparams);
1050  newP-> SetParameterList(newPparams);
1051  newP-> SetFactory("Importer", manager.GetFactory("Importer"));
1052  newP-> SetFactory("P", manager.GetFactory("P"));
1053  if (!paramList.isParameter("semicoarsen: number of levels"))
1054  newP-> SetFactory("Nullspace", manager.GetFactory("Ptent"));
1055  else
1056  newP-> SetFactory("Nullspace", manager.GetFactory("P")); // TogglePFactory
1057  newP-> SetFactory("Coordinates", manager.GetFactory("Coordinates"));
1058  manager.SetFactory("P", newP);
1059  manager.SetFactory("Coordinates", newP);
1060 
1061  // Rebalanced R
1062  RCP<RebalanceTransferFactory> newR = rcp(new RebalanceTransferFactory());
1063  ParameterList newRparams;
1064  newRparams.set("type", "Restriction");
1065  MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, "repartition: use subcommunicators", bool, newRparams);
1066  if (changedPRrebalance_)
1067  newRparams.set("repartition: rebalance P and R", this->doPRrebalance_);
1069  newRparams.set("transpose: use implicit", this->implicitTranspose_);
1070  newR-> SetParameterList(newRparams);
1071  newR-> SetFactory("Importer", manager.GetFactory("Importer"));
1072  if (!this->implicitTranspose_) {
1073  newR->SetFactory("R", manager.GetFactory("R"));
1074  manager.SetFactory("R", newR);
1075  }
1076 
1077  // NOTE: the role of NullspaceFactory is to provide nullspace on the finest
1078  // level if a user does not do that. For all other levels it simply passes
1079  // nullspace from a real factory to whoever needs it. If we don't use
1080  // repartitioning, that factory is "TentativePFactory"; if we do, it is
1081  // "RebalanceTransferFactory". But we still have to have NullspaceFactory as
1082  // the "Nullspace" of the manager
1083  nullSpace->SetFactory("Nullspace", newP);
1084 #else
1085  throw Exceptions::RuntimeError("No repartitioning available for a serial run");
1086 #endif
1087  }
1088  if (reuseType == "RAP" || reuseType == "full") {
1089  keeps.push_back(keep_pair("P", manager.GetFactory("P").get()));
1090  if (!this->implicitTranspose_)
1091  keeps.push_back(keep_pair("R", manager.GetFactory("R").get()));
1092  keeps.push_back(keep_pair("A", manager.GetFactory("A").get()));
1093  }
1094  }
1095 #undef MUELU_SET_VAR_2LIST
1096 #undef MUELU_TEST_AND_SET_VAR
1097 #undef MUELU_TEST_AND_SET_PARAM_2LIST
1098 #undef MUELU_TEST_PARAM_2LIST
1099 
1100  int LevenshteinDistance(const char* s, size_t len_s, const char* t, size_t len_t);
1101 
1102  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1104  ParameterList paramList = constParamList;
1105  const ParameterList& validList = *MasterList::List();
1106  // Validate up to maxLevels level specific parameter sublists
1107  const int maxLevels = 100;
1108 
1109  // Extract level specific list
1110  std::vector<ParameterList> paramLists;
1111  for (int levelID = 0; levelID < maxLevels; levelID++) {
1112  std::string sublistName = "level " + toString(levelID);
1113  if (paramList.isSublist(sublistName)) {
1114  paramLists.push_back(paramList.sublist(sublistName));
1115  // paramLists.back().setName(sublistName);
1116  paramList.remove(sublistName);
1117  }
1118  }
1119  paramLists.push_back(paramList);
1120  // paramLists.back().setName("main");
1121  //If Muemex is supported, hide custom level variables from validator by removing them from paramList's sublists
1122  #ifdef HAVE_MUELU_MATLAB
1123  for(size_t i = 0; i < paramLists.size(); i++)
1124  {
1125  std::vector<std::string> customVars; //list of names (keys) to be removed from list
1126  for(Teuchos::ParameterList::ConstIterator it = paramLists[i].begin(); it != paramLists[i].end(); it++)
1127  {
1128  std::string paramName = paramLists[i].name(it);
1129  if(IsParamMuemexVariable(paramName))
1130  customVars.push_back(paramName);
1131  }
1132  //Remove the keys
1133  for(size_t j = 0; j < customVars.size(); j++)
1134  {
1135  paramLists[i].remove(customVars[j], false);
1136  }
1137  }
1138  #endif
1139  const int maxDepth = 0;
1140  for (size_t i = 0; i < paramLists.size(); i++)
1141  {
1142  // validate every sublist
1143  try
1144  {
1145  paramLists[i].validateParameters(validList, maxDepth);
1146  }
1147  catch (const Teuchos::Exceptions::InvalidParameterName& e)
1148  {
1149  std::string eString = e.what();
1150 
1151  // Parse name from: <Error, the parameter {name="smoothe: type",...>
1152  size_t nameStart = eString.find_first_of('"') + 1;
1153  size_t nameEnd = eString.find_first_of('"', nameStart);
1154  std::string name = eString.substr(nameStart, nameEnd - nameStart);
1155 
1156  int bestScore = 100;
1157  std::string bestName = "";
1158  for (ParameterList::ConstIterator it = validList.begin(); it != validList.end(); it++)
1159  {
1160  const std::string& pName = validList.name(it);
1161  this->GetOStream(Runtime1) << "| " << pName;
1162  int score = LevenshteinDistance(name.c_str(), name.length(), pName.c_str(), pName.length());
1163  this->GetOStream(Runtime1) << " -> " << score << std::endl;
1164  if (score < bestScore)
1165  {
1166  bestScore = score;
1167  bestName = pName;
1168  }
1169  }
1170  if (bestScore < 10 && bestName != "")
1171  {
1172  TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameterName, eString << "The parameter name \"" + name + "\" is not valid. Did you mean \"" + bestName << "\"?\n");
1173  }
1174  else
1175  {
1176  TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameterName, eString << "The parameter name \"" + name + "\" is not valid.\n");
1177  }
1178  }
1179  }
1180  }
1181 
1182  // =====================================================================================================
1183  // ==================================== FACTORY interpreter ============================================
1184  // =====================================================================================================
1185  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1187  // Create a non const copy of the parameter list
1188  // Working with a modifiable list is much much easier than with original one
1189  ParameterList paramList = constParamList;
1190 
1191  // Parameter List Parsing:
1192  // ---------
1193  // <ParameterList name="MueLu">
1194  // <ParameterList name="Matrix">
1195  // </ParameterList>
1196  if (paramList.isSublist("Matrix")) {
1197  blockSize_ = paramList.sublist("Matrix").get<int>("number of equations", MasterList::getDefault<int>("number of equations"));
1198  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)
1199  }
1200 
1201  // create new FactoryFactory object if necessary
1202  if (factFact_ == Teuchos::null)
1203  factFact_ = Teuchos::rcp(new FactoryFactory());
1204 
1205  // Parameter List Parsing:
1206  // ---------
1207  // <ParameterList name="MueLu">
1208  // <ParameterList name="Factories"> <== call BuildFactoryMap() on this parameter list
1209  // ...
1210  // </ParameterList>
1211  // </ParameterList>
1212  FactoryMap factoryMap;
1213  FactoryManagerMap factoryManagers;
1214  if (paramList.isSublist("Factories"))
1215  this->BuildFactoryMap(paramList.sublist("Factories"), factoryMap, factoryMap, factoryManagers);
1216 
1217  // Parameter List Parsing:
1218  // ---------
1219  // <ParameterList name="MueLu">
1220  // <ParameterList name="Hierarchy">
1221  // <Parameter name="verbose" type="string" value="Warnings"/> <== get
1222  // <Parameter name="numDesiredLevel" type="int" value="10"/> <== get
1223  //
1224  // <ParameterList name="firstLevel"> <== parse first args and call BuildFactoryMap() on the rest of this parameter list
1225  // ...
1226  // </ParameterList>
1227  // </ParameterList>
1228  // </ParameterList>
1229  if (paramList.isSublist("Hierarchy")) {
1230  ParameterList hieraList = paramList.sublist("Hierarchy"); // copy because list temporally modified (remove 'id')
1231 
1232  // Get hierarchy options
1233  if (hieraList.isParameter("max levels")) {
1234  this->numDesiredLevel_ = hieraList.get<int>("max levels");
1235  hieraList.remove("max levels");
1236  }
1237 
1238  if (hieraList.isParameter("coarse: max size")) {
1239  this->maxCoarseSize_ = hieraList.get<int>("coarse: max size");
1240  hieraList.remove("coarse: max size");
1241  }
1242 
1243  if (hieraList.isParameter("repartition: rebalance P and R")) {
1244  this->doPRrebalance_ = hieraList.get<bool>("repartition: rebalance P and R");
1245  hieraList.remove("repartition: rebalance P and R");
1246  }
1247 
1248  if (hieraList.isParameter("transpose: use implicit")) {
1249  this->implicitTranspose_ = hieraList.get<bool>("transpose: use implicit");
1250  hieraList.remove("transpose: use implicit");
1251  }
1252 
1253  //TODO Move this its own class or MueLu::Utils?
1254  std::map<std::string,MsgType> verbMap;
1255  //for developers
1256  verbMap["Errors"] = Errors;
1257  verbMap["Warnings0"] = Warnings0;
1258  verbMap["Warnings00"] = Warnings00;
1259  verbMap["Warnings1"] = Warnings1;
1260  verbMap["PerfWarnings"] = PerfWarnings;
1261  verbMap["Runtime0"] = Runtime0;
1262  verbMap["Runtime1"] = Runtime1;
1263  verbMap["RuntimeTimings"] = RuntimeTimings;
1264  verbMap["NoTimeReport"] = NoTimeReport;
1265  verbMap["Parameters0"] = Parameters0;
1266  verbMap["Parameters1"] = Parameters1;
1267  verbMap["Statistics0"] = Statistics0;
1268  verbMap["Statistics1"] = Statistics1;
1269  verbMap["Timings0"] = Timings0;
1270  verbMap["Timings1"] = Timings1;
1271  verbMap["TimingsByLevel"] = TimingsByLevel;
1272  verbMap["External"] = External;
1273  verbMap["Debug"] = Debug;
1274  verbMap["Test"] = Test;
1275  //for users and developers
1276  verbMap["None"] = None;
1277  verbMap["Low"] = Low;
1278  verbMap["Medium"] = Medium;
1279  verbMap["High"] = High;
1280  verbMap["Extreme"] = Extreme;
1281  if (hieraList.isParameter("verbosity")) {
1282  std::string vl = hieraList.get<std::string>("verbosity");
1283  hieraList.remove("verbosity");
1284  //TODO Move this to its own class or MueLu::Utils?
1285  if (verbMap.find(vl) != verbMap.end())
1286  this->verbosity_ = verbMap[vl];
1287  else
1288  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "MueLu::ParameterListInterpreter():: invalid verbosity level");
1289  }
1290 
1291  if (hieraList.isParameter("dependencyOutputLevel"))
1292  this->graphOutputLevel_ = hieraList.get<int>("dependencyOutputLevel");
1293 
1294  // Check for the reuse case
1295  if (hieraList.isParameter("reuse"))
1297 
1298  if (hieraList.isSublist("DataToWrite")) {
1299  //TODO We should be able to specify any data. If it exists, write it.
1300  //TODO This would requires something like std::set<dataName,Array<int> >
1301  ParameterList foo = hieraList.sublist("DataToWrite");
1302  std::string dataName = "Matrices";
1303  if (foo.isParameter(dataName))
1304  this->matricesToPrint_ = Teuchos::getArrayFromStringParameter<int>(foo,dataName);
1305  dataName = "Prolongators";
1306  if (foo.isParameter(dataName))
1307  this->prolongatorsToPrint_ = Teuchos::getArrayFromStringParameter<int>(foo,dataName);
1308  dataName = "Restrictors";
1309  if (foo.isParameter(dataName))
1310  this->restrictorsToPrint_ = Teuchos::getArrayFromStringParameter<int>(foo,dataName);
1311  }
1312 
1313  // Get level configuration
1314  for (ParameterList::ConstIterator param = hieraList.begin(); param != hieraList.end(); ++param) {
1315  const std::string & paramName = hieraList.name(param);
1316 
1317  if (paramName != "DataToWrite" && hieraList.isSublist(paramName)) {
1318  ParameterList levelList = hieraList.sublist(paramName); // copy because list temporally modified (remove 'id')
1319 
1320  int startLevel = 0; if(levelList.isParameter("startLevel")) { startLevel = levelList.get<int>("startLevel"); levelList.remove("startLevel"); }
1321  int numDesiredLevel = 1; if(levelList.isParameter("numDesiredLevel")) { numDesiredLevel = levelList.get<int>("numDesiredLevel"); levelList.remove("numDesiredLevel"); }
1322 
1323  // Parameter List Parsing:
1324  // ---------
1325  // <ParameterList name="firstLevel">
1326  // <Parameter name="startLevel" type="int" value="0"/>
1327  // <Parameter name="numDesiredLevel" type="int" value="1"/>
1328  // <Parameter name="verbose" type="string" value="Warnings"/>
1329  //
1330  // [] <== call BuildFactoryMap() on the rest of the parameter list
1331  //
1332  // </ParameterList>
1333  FactoryMap levelFactoryMap;
1334  BuildFactoryMap(levelList, factoryMap, levelFactoryMap, factoryManagers);
1335 
1336  RCP<FactoryManagerBase> m = rcp(new FactoryManager(levelFactoryMap));
1337 
1338  if (startLevel >= 0)
1339  this->AddFactoryManager(startLevel, numDesiredLevel, m);
1340  else
1341  TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "MueLu::ParameterListInterpreter():: invalid level id");
1342  } /* TODO: else { } */
1343  }
1344  }
1345  }
1346 
1347  // Parameter List Parsing:
1348  // Create an entry in factoryMap for each parameter of the list paramList
1349  // ---------
1350  // <ParameterList name="...">
1351  // <Parameter name="smootherFact0" type="string" value="TrilinosSmoother"/>
1352  //
1353  // <ParameterList name="smootherFact1">
1354  // <Parameter name="type" type="string" value="TrilinosSmoother"/>
1355  // ...
1356  // </ParameterList>
1357  // </ParameterList>
1358  //
1359  //TODO: static?
1360  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1362  BuildFactoryMap(const ParameterList& paramList, const FactoryMap& factoryMapIn, FactoryMap& factoryMapOut, FactoryManagerMap& factoryManagers) const {
1363  for (ParameterList::ConstIterator param = paramList.begin(); param != paramList.end(); ++param) {
1364  const std::string & paramName = paramList.name(param);
1365  const Teuchos::ParameterEntry & paramValue = paramList.entry(param);
1366 
1367  //TODO: do not allow name of existing MueLu classes (can be tested using FactoryFactory)
1368 
1369  // TODO: add support for "factory groups" which are stored in a map.
1370  // A factory group has a name and a list of factories
1371 
1372  if (paramValue.isList()) {
1373  ParameterList paramList1 = Teuchos::getValue<ParameterList>(paramValue);
1374  if (paramList1.isParameter("factory")) { // default: just a factory definition
1375  factoryMapOut[paramName] = factFact_->BuildFactory(paramValue, factoryMapIn, factoryManagers);
1376 
1377  } else if (paramList1.isParameter("group")) { // definitiion of a factory group (for a factory manager)
1378  std::string groupType = paramList1.get<std::string>("group");
1379  TEUCHOS_TEST_FOR_EXCEPTION(groupType!="FactoryManager", Exceptions::RuntimeError, "group must be of type \"FactoryManager\".");
1380 
1381  ParameterList groupList = paramList1; // copy because list temporally modified (remove 'id')
1382  groupList.remove("group");
1383 
1384  FactoryMap groupFactoryMap;
1385  BuildFactoryMap(groupList, factoryMapIn, groupFactoryMap, factoryManagers);
1386 
1387  // do not store groupFactoryMap in factoryMapOut
1388  // Create a factory manager object from groupFactoryMap
1389  RCP<FactoryManagerBase> m = rcp(new FactoryManager(groupFactoryMap));
1390 
1391  factoryManagers[paramName] = m;
1392 
1393  } else {
1394  this->GetOStream(Warnings0) << "Could not interpret parameter list " << paramList1 << std::endl;
1395  TEUCHOS_TEST_FOR_EXCEPTION(false, Exceptions::RuntimeError, "XML Parameter list must either be of type \"factory\" or of type \"group\".");
1396  }
1397  } else {
1398  // default: just a factory (no parameter list)
1399  factoryMapOut[paramName] = factFact_->BuildFactory(paramValue, factoryMapIn, factoryManagers);
1400  }
1401  }
1402  }
1403 
1404  // =====================================================================================================
1405  // ======================================= MISC functions ==============================================
1406  // =====================================================================================================
1407  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1409  try {
1410  Matrix& A = dynamic_cast<Matrix&>(Op);
1411  if (A.GetFixedBlockSize() != blockSize_)
1412  this->GetOStream(Warnings0) << "Setting matrix block size to " << blockSize_ << " (value of the parameter in the list) "
1413  << "instead of " << A.GetFixedBlockSize() << " (provided matrix)." << std::endl;
1414 
1415  A.SetFixedBlockSize(blockSize_, dofOffset_);
1416 
1417  } catch (std::bad_cast& e) {
1418  this->GetOStream(Warnings0) << "Skipping setting block size as the operator is not a matrix" << std::endl;
1419  }
1420  }
1421 
1422  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1425  H.SetCycle(Cycle_);
1426  }
1427 
1428 
1429  static bool compare(const ParameterList& list1, const ParameterList& list2) {
1430  // First loop through and validate the parameters at this level.
1431  // In addition, we generate a list of sublists that we will search next
1432  for (ParameterList::ConstIterator it = list1.begin(); it != list1.end(); it++) {
1433  const std::string& name = it->first;
1434  const Teuchos::ParameterEntry& entry1 = it->second;
1435 
1436  const Teuchos::ParameterEntry *entry2 = list2.getEntryPtr(name);
1437  if (!entry2) // entry is not present in the second list
1438  return false;
1439  if (entry1.isList() && entry2->isList()) { // sublist check
1440  compare(Teuchos::getValue<ParameterList>(entry1), Teuchos::getValue<ParameterList>(*entry2));
1441  continue;
1442  }
1443  if (entry1.getAny(false) != entry2->getAny(false)) // entries have different types or different values
1444  return false;
1445  }
1446 
1447  return true;
1448  }
1449  static inline bool areSame(const ParameterList& list1, const ParameterList& list2) {
1450  return compare(list1, list2) && compare(list2, list1);
1451  }
1452 
1453  } // namespace MueLu
1454 
1455 #define MUELU_PARAMETERLISTINTERPRETER_SHORT
1456 #endif /* MUELU_PARAMETERLISTINTERPRETER_DEF_HPP */
Important warning messages (one line)
Generic Smoother Factory for generating the smoothers of the MG hierarchy.
This class specifies the default factory that should generate some data on a Level if the data does n...
Teuchos::Array< int > matricesToPrint_
void SetupHierarchy(Hierarchy &H) const
Call the SetupHierarchy routine from the HiearchyManager object.
High level timing information (use Teuchos::TimeMonitor::summarize() to print)
#define MUELU_KOKKOS_FACTORY_NO_DECL(varName, oldFactory, newFactory)
Factory for generating coarse level map. Used by TentativePFactory.
std::string toString(const T &what)
Little helper function to convert non-string types to strings.
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.
int LevenshteinDistance(const char *s, size_t len_s, const char *t, size_t len_t)
Print external lib objects.
Class that encapsulates external library smoothers.
static void DisableMultipleCheckGlobally()
#define MUELU_TEST_AND_SET_VAR(paramList, paramName, paramType, varName)
Factory for building permutation matrix that can be be used to shuffle data (matrices, vectors) among processes.
Print more statistics.
Print additional debugging information.
void AddFactoryManager(int startLevel, int numDesiredLevel, RCP< FactoryManagerBase > manager)
One-liner description of what is happening.
void SetCycle(CycleType Cycle)
Supports VCYCLE and WCYCLE types.
Namespace for MueLu classes and methods.
#define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory)
Interface to Zoltan library.
bool IsParamMuemexVariable(const std::string &name)
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
Print skeleton for the run, i.e. factory calls and used parameters.
Factory for building tentative prolongator.
#define TEST_MUTUALLY_EXCLUSIVE(arg1, arg2)
Class that encapsulates direct solvers. Autoselection of AmesosSmoother or Amesos2Smoother according ...
Factory for coarsening a graph with uncoupled aggregation.
virtual void SetupOperator(Operator &A) const
Setup Operator object.
Prolongator factory performing semi-coarsening.
Factory for building restriction operators using a prolongator factory.
Additional warnings.
int blockSize_
block size of matrix (fixed block size)
Important warning messages (more verbose)
Print statistics that do not involve significant additional computation.
Teuchos::RCP< FactoryFactory > factFact_
Internal factory for factories.
#define MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, paramName, paramType, listWrite)
static bool compare(const ParameterList &list1, const ParameterList &list2)
static CycleType GetDefaultCycle()
Detailed timing information (use Teuchos::TimeMonitor::summarize() to print)
Factory for interacting with Matlab.
Factory for interacting with Matlab.
Factory for building line detection information.
void SetFactoryParameterList(const Teuchos::ParameterList &paramList)
Factory interpreter stuff.
std::pair< std::string, const FactoryBase * > keep_pair
Factory to export aggregation info or visualize aggregates using VTK.
Interface to Zoltan2 library.
Prolongator factory which allows switching between two different prolongator strategies.
By default, enabled timers appears in the teuchos time monitor summary. Use this option if you do not...
RCP< FactoryManagerBase > GetFactoryManager(int levelID) const
Factory for building the constraint operator.
ParameterListInterpreter(Teuchos::ParameterList &paramList, Teuchos::RCP< const Teuchos::Comm< int > > comm=Teuchos::null, Teuchos::RCP< FactoryFactory > factFact=Teuchos::null)
Constructor that accepts a user-provided ParameterList.
Applies permutation to grid transfer operators.
void SetFactory(const std::string &varName, const RCP< const FactoryBase > &factory)
Set Factory.
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
Print class parameters.
Timers that are enabled (using Timings0/Timings1) will be printed during the execution.
GlobalOrdinal dofOffset_
global offset variable describing offset of DOFs in operator
Performance warnings.
Record timing information level by level. Must be used in combinaison with Timings0/Timings1.
Factory for creating a graph base on a given matrix.
Teuchos::Array< int > prolongatorsToPrint_
void BuildFactoryMap(const Teuchos::ParameterList &paramList, const FactoryMap &factoryMapIn, FactoryMap &factoryMapOut, FactoryManagerMap &factoryManagers) const
Class that encapsulates Matlab smoothers.
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.
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.
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.
std::map< int, std::vector< keep_pair > > keep_
#define TEST_MUTUALLY_EXCLUSIVE_S(arg1, arg2)
void Validate(const Teuchos::ParameterList &paramList) const
#define MUELU_TEST_PARAM_2LIST(paramList, defaultList, paramName, paramType, cmpValue)
Print class parameters (more parameters, more verbose)
Factory for building coarse matrices.
Exception throws to report errors in the internal logical of the program.
Factory for building filtered matrices using filtered graphs.
std::pair< std::string, const FactoryBase * > keep_pair
Description of what is happening (more verbose)
Factory for building coarse matrices.
Factory for building Petrov-Galerkin Smoothed Aggregation prolongators.
Factory for building Smoothed Aggregation prolongators.Input/output of SaPFactory
Xpetra::global_size_t maxCoarseSize_
Factory for building uncoupled aggregates.
static Teuchos::RCP< const Teuchos::ParameterList > List()
Return a "master" list of all valid parameters and their default values.
#define MUELU_SET_VAR_2LIST(paramList, defaultList, paramName, paramType, varName)
Teuchos::Array< int > restrictorsToPrint_
void SetEasyParameterList(const Teuchos::ParameterList &paramList)
Provides methods to build a multigrid hierarchy and apply multigrid cycles.
Factory for generating nullspace.
long ExtractNonSerializableData(const Teuchos::ParameterList &inList, Teuchos::ParameterList &serialList, Teuchos::ParameterList &nonSerialList)
virtual void SetupHierarchy(Hierarchy &H) const
Setup Hierarchy object.
Exception throws to report invalid user entry.
static const RCP< const NoFactory > getRCP()
Static Get() functions.
CycleType Cycle_
multigrid cycle type (V-cycle or W-cycle)