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
136namespace 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>
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 != "")
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 */
#define MUELU_TEST_AND_SET_VAR(paramList, paramName, paramType, varName)
#define MUELU_SET_VAR_2LIST(paramList, defaultList, paramName, paramType, varName)
#define TEST_MUTUALLY_EXCLUSIVE_S(arg1, arg2)
#define MUELU_KOKKOS_FACTORY_NO_DECL(varName, oldFactory, newFactory)
#define MUELU_TEST_PARAM_2LIST(paramList, defaultList, paramName, paramType, cmpValue)
#define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory)
#define TEST_MUTUALLY_EXCLUSIVE(arg1, arg2)
#define MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, paramName, paramType, listWrite)
MueLu::DefaultScalar Scalar
MueLu::DefaultGlobalOrdinal GlobalOrdinal
MueLu::DefaultNode Node
An factory which assigns each aggregate a quality estimate. Originally developed by Napov and Notay i...
Factory to export aggregation info or visualize aggregates using VTK.
AmalgamationFactory for subblocks of strided map based amalgamation data.
Factory for generating F/C-splitting and a coarse level map. Used by ClassicalPFactory.
Factory for creating a graph based on a given matrix.
Factory for generating coarse level map. Used by TentativePFactory.
Factory for building the constraint operator.
Class for transferring coordinates from a finer level to a coarser one.
Factory for coarsening a graph with uncoupled aggregation.
Class that encapsulates direct solvers. Autoselection of AmesosSmoother or Amesos2Smoother according ...
Factory for building Energy Minimization prolongators.
Exception throws to report invalid user entry.
Exception throws to report errors in the internal logical of the program.
Factory that can generate other factories from.
This class specifies the default factory that should generate some data on a Level if the data does n...
void SetFactory(const std::string &varName, const RCP< const FactoryBase > &factory)
Set Factory.
const RCP< const FactoryBase > GetFactory(const std::string &varName) const
Get factory associated with a particular data name.
const RCP< FactoryBase > GetFactoryNonConst(const std::string &varName)
Get factory associated with a particular data name (NONCONST version)
static void DisableMultipleCheckGlobally()
static void EnableTimerSync()
Factory for building filtered matrices using filtered graphs.
Factory for building restriction operators using a prolongator factory.
virtual void SetupHierarchy(Hierarchy &H) const
Setup Hierarchy object.
Provides methods to build a multigrid hierarchy and apply multigrid cycles.
static CycleType GetDefaultCycle()
void SetCycleStartLevel(int cycleStart)
static int GetDefaultCycleStartLevel()
void SetCycle(CycleType Cycle)
Supports VCYCLE and WCYCLE types.
void SetProlongatorScalingFactor(double scalingFactor)
Specify damping factor alpha such that x = x + alpha*P*c, where c is the coarse grid correction.
Class for generating an initial LocalOrdinal-type BlockNumber vector, based on an input paraemter for...
Factory for building transfer operators based on coarsening in polynomial degree, following the Intre...
Factory for building line detection information.
Class for transferring a vector of local ordinals from a finer level to a coarser one,...
static Teuchos::RCP< Teuchos::ParameterList > GetProblemSpecificList(std::string const &problemType)
Return default parameter settings for the specified problem type.
static Teuchos::RCP< const Teuchos::ParameterList > List()
Return a "master" list of all valid parameters and their default values.
static const RCP< const NoFactory > getRCP()
Static Get() functions.
Factory for generating nullspace.
void UpdateFactoryManager_SA(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void UpdateFactoryManager_Nullspace(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps, RCP< Factory > &nullSpaceFactory) const
void UpdateFactoryManager_Reitzinger(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
void UpdateFactoryManager_Smoothers(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void UpdateFactoryManager_Aggregation_TentativeP(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void SetEasyParameterList(const Teuchos::ParameterList &paramList)
void UpdateFactoryManager_Coordinates(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void BuildFactoryMap(const Teuchos::ParameterList &paramList, const FactoryMap &factoryMapIn, FactoryMap &factoryMapOut, FactoryManagerMap &factoryManagers) const
Interpret "Factories" sublist.
void UpdateFactoryManager_Restriction(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 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.
std::pair< std::string, const FactoryBase * > keep_pair
void UpdateFactoryManager_PG(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.
void Validate(const Teuchos::ParameterList &paramList) const
void UpdateFactoryManager_Emin(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void UpdateFactoryManager_Matlab(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
std::map< std::string, RCP< FactoryManagerBase > > FactoryManagerMap
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
void UpdateFactoryManager_SemiCoarsen(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void UpdateFactoryManager_BlockNumber(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void UpdateFactoryManager(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
std::map< std::string, RCP< const FactoryBase > > FactoryMap
void SetupHierarchy(Hierarchy &H) const
Call the SetupHierarchy routine from the HiearchyManager object.
void SetFactoryParameterList(const Teuchos::ParameterList &paramList)
Factory interpreter stuff.
void UpdateFactoryManager_CoarseSolvers(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void UpdateFactoryManager_Repartition(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps, RCP< Factory > &nullSpaceFactory) const
Factory for building nonzero patterns for energy minimization.
Factory for building Petrov-Galerkin Smoothed Aggregation prolongators.
Factory for building coarse matrices.
Factory for building coarse grid matrices, when the matrix is of the form K+a*M. Useful when you want...
Factory for building coarse matrices.
Applies permutation to grid transfer operators.
Factory for building tentative prolongator.
Factory for building permutation matrix that can be be used to shuffle data (matrices,...
Factory for determing the number of partitions for rebalancing.
Factory for building Smoothed Aggregation prolongators.
Factory for generating a very special nullspace.
Prolongator factory performing semi-coarsening.
Prolongator factory performing semi-coarsening.
Factory for creating a graph base on a given matrix.
Generic Smoother Factory for generating the smoothers of the MG hierarchy.
Factory for building tentative prolongator.
Class for transferring coordinates from a finer level to a coarser one.
Prolongator factory which allows switching between two different prolongator strategies.
Factory for building restriction operators.
Class that encapsulates external library smoothers.
Factory for interacting with Matlab.
Factory for building uncoupled aggregates.
static VerbLevel GetDefaultVerbLevel()
Get the default (global) verbosity level.
static void SetDefaultVerbLevel(const VerbLevel defaultVerbLevel)
Set the default (global) verbosity level.
static void SetMueLuOFileStream(const std::string &filename)
Interface to Zoltan2 library.
Interface to Zoltan library.
Namespace for MueLu classes and methods.
bool IsParamMuemexVariable(const std::string &name)
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.
@ Warnings0
Important warning messages (one line)
@ Runtime0
One-liner description of what is happening.
@ Runtime1
Description of what is happening (more verbose)
@ Warnings1
Additional warnings.
size_t LevenshteinDistance(const char *s, size_t len_s, const char *t, size_t len_t)
MsgType toVerbLevel(const std::string &verbLevelStr)
static bool areSame(const ParameterList &list1, const ParameterList &list2)
Helper functions to compare two paramter lists.
static bool compare(const ParameterList &list1, const ParameterList &list2)
std::string toString(const T &what)
Little helper function to convert non-string types to strings.