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