MueLu Version of the Day
Loading...
Searching...
No Matches
MueLu_ParameterListInterpreter_def.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// MueLu: A package for multigrid based preconditioning
4//
5// Copyright 2012 NTESS and the MueLu contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
10#ifndef MUELU_PARAMETERLISTINTERPRETER_DEF_HPP
11#define MUELU_PARAMETERLISTINTERPRETER_DEF_HPP
12
13#include <Teuchos_XMLParameterListHelpers.hpp>
14
15#include <Xpetra_Matrix.hpp>
16#include <Xpetra_MatrixUtils.hpp>
17
18#include "MueLu_ConfigDefs.hpp"
19
21
22#include "MueLu_MasterList.hpp"
23#include "MueLu_Level.hpp"
24#include "MueLu_Hierarchy.hpp"
25#include "MueLu_FactoryManager.hpp"
26
27#include "MueLu_AggregationExportFactory.hpp"
28#include "MueLu_AggregateQualityEstimateFactory.hpp"
29#include "MueLu_AmalgamationFactory.hpp"
30#include "MueLu_BrickAggregationFactory.hpp"
31#include "MueLu_ClassicalMapFactory.hpp"
32#include "MueLu_ClassicalPFactory.hpp"
33#include "MueLu_CoalesceDropFactory.hpp"
34#include "MueLu_CoarseMapFactory.hpp"
35#include "MueLu_ConstraintFactory.hpp"
36#include "MueLu_CoordinatesTransferFactory.hpp"
37#include "MueLu_DirectSolver.hpp"
38#include "MueLu_EdgeProlongatorPatternFactory.hpp"
39#include "MueLu_EminPFactory.hpp"
40#include "MueLu_Exceptions.hpp"
41#include "MueLu_FacadeClassFactory.hpp"
42#include "MueLu_FactoryFactory.hpp"
43#include "MueLu_FilteredAFactory.hpp"
44#include "MueLu_GenericRFactory.hpp"
45#include "MueLu_InitialBlockNumberFactory.hpp"
46#include "MueLu_LineDetectionFactory.hpp"
47#include "MueLu_LocalOrdinalTransferFactory.hpp"
48#include "MueLu_MatrixAnalysisFactory.hpp"
49#include "MueLu_MatrixTransferFactory.hpp"
50#include "MueLu_MultiVectorTransferFactory.hpp"
51#include "MueLu_NotayAggregationFactory.hpp"
52#include "MueLu_NullspaceFactory.hpp"
53#include "MueLu_PatternFactory.hpp"
54#include "MueLu_ReplicatePFactory.hpp"
55#include "MueLu_CombinePFactory.hpp"
56#include "MueLu_PgPFactory.hpp"
57#include "MueLu_RAPFactory.hpp"
58#include "MueLu_RAPShiftFactory.hpp"
59#include "MueLu_RebalanceAcFactory.hpp"
60#include "MueLu_RebalanceTransferFactory.hpp"
61#include "MueLu_RepartitionFactory.hpp"
62#include "MueLu_RepartitionHeuristicFactory.hpp"
63#include "MueLu_ReitzingerPFactory.hpp"
64#include "MueLu_SaPFactory.hpp"
65#include "MueLu_ScaledNullspaceFactory.hpp"
66#include "MueLu_SemiCoarsenPFactory.hpp"
67#include "MueLu_SmootherFactory.hpp"
68#include "MueLu_SmooVecCoalesceDropFactory.hpp"
69#include "MueLu_TentativePFactory.hpp"
70#include "MueLu_TogglePFactory.hpp"
71#include "MueLu_ToggleCoordinatesTransferFactory.hpp"
72#include "MueLu_TransPFactory.hpp"
73#include "MueLu_UncoupledAggregationFactory.hpp"
74#include "MueLu_ZoltanInterface.hpp"
75#include "MueLu_Zoltan2Interface.hpp"
76#include "MueLu_NodePartitionInterface.hpp"
77#include "MueLu_LowPrecisionFactory.hpp"
78
79#include "MueLu_CoalesceDropFactory_kokkos.hpp"
80#include "MueLu_SemiCoarsenPFactory_kokkos.hpp"
81#include "MueLu_TentativePFactory_kokkos.hpp"
82#include "Teuchos_Assert.hpp"
83
84#ifdef HAVE_MUELU_MATLAB
85#include "../matlab/src/MueLu_MatlabSmoother_decl.hpp"
86#include "../matlab/src/MueLu_MatlabSmoother_def.hpp"
87#include "../matlab/src/MueLu_TwoLevelMatlabFactory_decl.hpp"
88#include "../matlab/src/MueLu_TwoLevelMatlabFactory_def.hpp"
89#include "../matlab/src/MueLu_SingleLevelMatlabFactory_decl.hpp"
90#include "../matlab/src/MueLu_SingleLevelMatlabFactory_def.hpp"
91#endif
92
93#ifdef HAVE_MUELU_TEKO
96#endif
97
98#if defined(HAVE_MUELU_INTREPID2) && defined(HAVE_MUELU_EXPERIMENTAL)
99#include "MueLu_IntrepidPCoarsenFactory.hpp"
100#endif
101
102#include "MueLu_Behavior.hpp"
103
104#include <unordered_set>
105
106namespace MueLu {
107
108template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
109ParameterListInterpreter<Scalar, LocalOrdinal, GlobalOrdinal, Node>::ParameterListInterpreter(ParameterList& paramList, Teuchos::RCP<const Teuchos::Comm<int>> comm, Teuchos::RCP<FactoryFactory> factFact, Teuchos::RCP<FacadeClassFactory> facadeFact)
110 : factFact_(factFact) {
111 SetMinvAProjectionVariables(paramList);
112 RCP<Teuchos::TimeMonitor> tM = rcp(new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(std::string("MueLu: ParameterListInterpreter (ParameterList)"))));
113 if (facadeFact == Teuchos::null)
114 facadeFact_ = Teuchos::rcp(new FacadeClassFactory());
115 else
116 facadeFact_ = facadeFact;
117
118 if (paramList.isParameter("xml parameter file")) {
119 std::string filename = paramList.get("xml parameter file", "");
120 if (filename.length() != 0) {
121 TEUCHOS_TEST_FOR_EXCEPTION(comm.is_null(), Exceptions::RuntimeError, "xml parameter file requires a valid comm");
122
123 ParameterList paramList2 = paramList;
124 Teuchos::updateParametersFromXmlFileAndBroadcast(filename, Teuchos::Ptr<Teuchos::ParameterList>(&paramList2), *comm);
125 SetParameterList(paramList2);
126
127 } else {
128 SetParameterList(paramList);
129 }
130
131 } else {
132 SetParameterList(paramList);
133 }
134}
135
136template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
137ParameterListInterpreter<Scalar, LocalOrdinal, GlobalOrdinal, Node>::ParameterListInterpreter(const std::string& xmlFileName, const Teuchos::Comm<int>& comm, Teuchos::RCP<FactoryFactory> factFact, Teuchos::RCP<FacadeClassFactory> facadeFact)
138 : factFact_(factFact) {
139 RCP<Teuchos::TimeMonitor> tM = rcp(new Teuchos::TimeMonitor(*Teuchos::TimeMonitor::getNewTimer(std::string("MueLu: ParameterListInterpreter (XML)"))));
140 if (facadeFact == Teuchos::null)
141 facadeFact_ = Teuchos::rcp(new FacadeClassFactory());
142 else
143 facadeFact_ = facadeFact;
144
145 ParameterList paramList;
146 Teuchos::updateParametersFromXmlFileAndBroadcast(xmlFileName, Teuchos::Ptr<ParameterList>(&paramList), comm);
148 SetParameterList(paramList);
149}
150
151template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
153
154template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
157 WCycleStartLevel_ = Hierarchy::GetDefaultCycleStartLevel();
158 scalingFactor_ = Teuchos::ScalarTraits<double>::one();
159 blockSize_ = 1;
160 dofOffset_ = 0;
161 hierarchyLabel_ = "";
162
163 if (paramList.isSublist("Hierarchy")) {
164 SetFactoryParameterList(paramList);
165
166 } else if (paramList.isParameter("MueLu preconditioner") == true) {
167 this->GetOStream(Runtime0) << "Use facade class: " << paramList.get<std::string>("MueLu preconditioner") << std::endl;
168 Teuchos::RCP<ParameterList> pp = facadeFact_->SetParameterList(paramList);
169 SetFactoryParameterList(*pp);
170
171 } else {
172 // The validator doesn't work correctly for non-serializable data (Hint: template parameters), so strip it out
173 ParameterList serialList, nonSerialList;
174
175 ExtractNonSerializableData(paramList, serialList, nonSerialList);
176 Validate(serialList);
177 SetEasyParameterList(paramList);
178 }
179 if (paramList.isParameter("aggregation: strength-of-connection: matrix") && (paramList.get<std::string>("aggregation: strength-of-connection: matrix") == "MinvA") && paramList.isSublist("user data")) {
180 // check if Muelu option is inconsistent with user data provided. Here we
181 // assume that data has not been stripped out of user list.
182 bool Minv_Supplied = false, M_Supplied = false, MinvA_Supplied = false;
183 const Teuchos::ParameterList& userList = paramList.sublist("user data");
184 if (userList.isParameter("M")) M_Supplied = true;
185 if (userList.isParameter("Minv")) Minv_Supplied = true;
186 if (userList.isParameter("MinvA")) MinvA_Supplied = true;
187
188 if (paramList.isSublist("project auxiliary matrices")) {
189 auto projectList = paramList.sublist("project auxiliary matrices");
190 TEUCHOS_TEST_FOR_EXCEPTION(projectList.isParameter("M") && !M_Supplied, Exceptions::Incompatible, "MueLu_CreateXpetraPreconditioner: Must supply M as it is listed in the project auxiliary matrices sublist");
191 TEUCHOS_TEST_FOR_EXCEPTION(projectList.isParameter("Minv") && (projectList.get("Minv", "") == "NoFactory") && !Minv_Supplied, Exceptions::Incompatible,
192 "MueLu_CreateXpetraPreconditioner: Must supply Minv as NoFactory is listed as supplier of Minv in the project auxiliary matrices sublist");
193 TEUCHOS_TEST_FOR_EXCEPTION(projectList.isParameter("MinvA") && (projectList.get("MinvA", "") == "NoFactory") && !MinvA_Supplied, Exceptions::Incompatible,
194 "MueLu_CreateXpetraPreconditioner: Must supply MinvA as NoFactory is listed as supplier of MinvA in the project auxiliary matrices sublist");
195 } else { // default behavior if sublist("project auxiliary matrices") not user-supplied requires "M" to be user-supplied.
196 TEUCHOS_TEST_FOR_EXCEPTION(!M_Supplied, Exceptions::Incompatible, "MueLu_CreateXpetraPreconditioner: Must supply M when 'aggregation: strength-of-connection: matrix'= MinvA and sublist('project auxiliary matrices') not supplied.");
197 }
198 }
199}
200
201// =====================================================================================================
202// ====================================== EASY interpreter =============================================
203// =====================================================================================================
205static inline bool areSame(const ParameterList& list1, const ParameterList& list2);
206
207// Get value from one of the lists, or set it to default
208// Use case: check for a parameter value in a level-specific sublist, then in a root level list;
209// if it is absent from both, set it to default
210template <class paramType>
211static inline paramType set_var_2list(const Teuchos::ParameterList& paramList, const Teuchos::ParameterList& defaultList, const std::string& paramName) {
212 if (paramList.isParameter(paramName))
213 return paramList.get<paramType>(paramName);
214 else if (defaultList.isParameter(paramName))
215 return defaultList.get<paramType>(paramName);
216 else
217 return MasterList::getDefault<paramType>(paramName);
218}
219
220template <class paramType>
221static inline bool test_and_set_var(const Teuchos::ParameterList& paramList, const std::string& paramName, paramType& varName) {
222 if (paramList.isParameter(paramName)) {
223 varName = paramList.get<paramType>(paramName);
224 return true;
225 } else
226 return false;
227}
228
229template <class paramType>
230static inline void test_and_set_param_2list(const Teuchos::ParameterList& paramList, const Teuchos::ParameterList& defaultList, const std::string& paramName, Teuchos::ParameterList& listWrite) {
231 try {
232 if (paramList.isParameter(paramName))
233 listWrite.set(paramName, paramList.get<paramType>(paramName));
234 else if (defaultList.isParameter(paramName))
235 listWrite.set(paramName, defaultList.get<paramType>(paramName));
236 } catch (Teuchos::Exceptions::InvalidParameterType&) {
237 TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(true, Teuchos::Exceptions::InvalidParameterType,
238 "Error: parameter \"" << paramName << "\" must be of type " << Teuchos::TypeNameTraits<paramType>::name());
239 }
240}
241
242template <class paramType>
243static inline void test_and_set_var_from_masterlist(Teuchos::ParameterList& paramList, const std::string& paramName) {
244 if (!paramList.isParameter(paramName)) {
245 paramList.set(paramName, MasterList::getDefault<paramType>(paramName));
246 }
247}
248
249template <class paramType>
250static inline bool test_param_2list(const Teuchos::ParameterList& paramList, const Teuchos::ParameterList& defaultList, const std::string& paramName, const paramType& cmpValue) {
251 return (cmpValue == set_var_2list<paramType>(paramList, defaultList, paramName));
252}
253
254#define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory) \
255 RCP<Factory> varName; \
256 if (!useKokkos_) \
257 varName = rcp(new oldFactory()); \
258 else \
259 varName = rcp(new newFactory());
260#define MUELU_KOKKOS_FACTORY_NO_DECL(varName, oldFactory, newFactory) \
261 if (!useKokkos_) \
262 varName = rcp(new oldFactory()); \
263 else \
264 varName = rcp(new newFactory());
265
266template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
268 SetMinvAProjectionVariables(const ParameterList& constParamList) {
269 ParameterList paramList;
270 projectM_ = false;
271 projectMinv_ = false;
272 projectMinvA_ = true;
273 if (constParamList.isSublist("project auxiliary matrices")) {
274 auto projectList = constParamList.sublist("project auxiliary matrices");
275 if (projectList.isParameter("M")) {
276 projectM_ = true;
277 projectMinvA_ = false;
278 }
279 if (projectList.isParameter("Minv")) {
280 projectMinv_ = true;
281 projectMinvA_ = false;
282 }
283 if (projectList.isParameter("MinvA")) {
284 projectMinvA_ = true;
285 }
286 } else { // default settings when "project auxiliary matrices" not specified by user
287 projectM_ = false;
288 projectMinv_ = false;
289 projectMinvA_ = true;
290 }
291}
292template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
294 SetEasyParameterList(const ParameterList& constParamList) {
295 ParameterList paramList;
296
297 auto problemType = set_var_2list<std::string>(constParamList, constParamList, "problem: type");
298 if (problemType != "unknown") {
299 paramList = *MasterList::GetProblemSpecificList(problemType);
300 paramList.setParameters(constParamList);
301 } else {
302 // Create a non const copy of the parameter list
303 // Working with a modifiable list is much much easier than with original one
304 paramList = constParamList;
305 }
306
307 // Check for Kokkos
308 useKokkos_ = !Node::is_serial;
309 (void)test_and_set_var<bool>(paramList, "use kokkos refactor", useKokkos_);
310
311 // Check for timer synchronization
312 auto syncTimers = set_var_2list<bool>(paramList, paramList, "synchronize factory timers");
313 if (syncTimers)
315
316 // Translate cycle type parameter
317 if (paramList.isParameter("cycle type")) {
318 std::map<std::string, CycleType> cycleMap;
319 cycleMap["V"] = VCYCLE;
320 cycleMap["W"] = WCYCLE;
321
322 auto cycleType = paramList.get<std::string>("cycle type");
323 TEUCHOS_TEST_FOR_EXCEPTION(cycleMap.count(cycleType) == 0, Exceptions::RuntimeError,
324 "Invalid cycle type: \"" << cycleType << "\"");
325 Cycle_ = cycleMap[cycleType];
326 }
327
328 if (paramList.isParameter("W cycle start level")) {
329 WCycleStartLevel_ = paramList.get<int>("W cycle start level");
330 }
331
332 if (paramList.isParameter("hierarchy label")) {
333 this->hierarchyLabel_ = paramList.get<std::string>("hierarchy label");
334 }
335
336 if (paramList.isParameter("coarse grid correction scaling factor"))
337 scalingFactor_ = paramList.get<double>("coarse grid correction scaling factor");
338
339 this->maxCoarseSize_ = paramList.get<int>("coarse: max size", MasterList::getDefault<int>("coarse: max size"));
340 this->numDesiredLevel_ = paramList.get<int>("max levels", MasterList::getDefault<int>("max levels"));
341 blockSize_ = paramList.get<int>("number of equations", MasterList::getDefault<int>("number of equations"));
342
343 (void)test_and_set_var<int>(paramList, "debug: graph level", this->graphOutputLevel_);
344
345 // Generic data keeping (this keeps the data on all levels)
346 if (paramList.isParameter("keep data"))
347 this->dataToKeep_ = Teuchos::getArrayFromStringParameter<std::string>(paramList, "keep data");
348
349 // Export level data
350 if (paramList.isSublist("export data")) {
351 ParameterList printList = paramList.sublist("export data");
352
353 // Vectors, aggregates and other things that need special handling
354 if (printList.isParameter("Nullspace"))
355 this->nullspaceToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "Nullspace");
356 if (printList.isParameter("Coordinates"))
357 this->coordinatesToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "Coordinates");
358 if (printList.isParameter("Material"))
359 this->materialToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "Material");
360 if (printList.isParameter("Aggregates"))
361 this->aggregatesToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "Aggregates");
362 if (printList.isParameter("pcoarsen: element to node map"))
363 this->elementToNodeMapsToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList, "pcoarsen: element to node map");
364
365 // If we asked for an arbitrary matrix to be printed, we do that here
366 for (auto iter = printList.begin(); iter != printList.end(); iter++) {
367 const std::string& name = printList.name(iter);
368 // Ignore the special cases
369 if (name == "Nullspace" || name == "Coordinates" || name == "Material" || name == "Aggregates" || name == "pcoarsen: element to node map")
370 continue;
371
372 this->matricesToPrint_[name] = Teuchos::getArrayFromStringParameter<int>(printList, name);
373 }
374 }
375
376 // Set verbosity parameter
378 {
379 auto verbosityLevel = set_var_2list<std::string>(paramList, paramList, "verbosity");
380 this->verbosity_ = toVerbLevel(verbosityLevel);
381 VerboseObject::SetDefaultVerbLevel(this->verbosity_);
382 }
383
384 auto outputFilename = set_var_2list<std::string>(paramList, paramList, "output filename");
385 if (outputFilename != "")
387
388 // Detect if we need to transfer coordinates to coarse levels. We do that iff
389 // - we use "distance laplacian" dropping on some level, or
390 // - we use a repartitioner on some level that needs coordinates
391 // - we use brick aggregation
392 // - we use Ifpack2 line partitioner
393 // This is not ideal, as we may have "repartition: enable" turned on by default
394 // and not present in the list, but it is better than nothing.
395 useCoordinates_ = false;
396 useBlockNumber_ = false;
397 if (test_param_2list<std::string>(paramList, paramList, "aggregation: strength-of-connection: matrix", "distance laplacian"))
398 useCoordinates_ = true;
399 if (test_param_2list<bool>(paramList, paramList, "aggregation: use blocking", true))
400 useBlockNumber_ = true;
401 if (test_param_2list<std::string>(paramList, paramList, "aggregation: drop scheme", "distance laplacian") ||
402 test_param_2list<std::string>(paramList, paramList, "aggregation: type", "brick") ||
403 test_param_2list<bool>(paramList, paramList, "aggregation: export visualization data", true)) {
404 useCoordinates_ = true;
405 } else if (test_param_2list<std::string>(paramList, paramList, "aggregation: drop scheme", "block diagonal distance laplacian")) {
406 useCoordinates_ = true;
407 useBlockNumber_ = true;
408 } else if (test_param_2list<std::string>(paramList, paramList, "aggregation: drop scheme", "block diagonal") ||
409 test_param_2list<std::string>(paramList, paramList, "aggregation: drop scheme", "block diagonal classical") ||
410 test_param_2list<std::string>(paramList, paramList, "aggregation: drop scheme", "block diagonal signed classical") ||
411 test_param_2list<std::string>(paramList, paramList, "aggregation: drop scheme", "block diagonal colored signed classical") ||
412 test_param_2list<std::string>(paramList, paramList, "aggregation: drop scheme", "signed classical")) {
413 useBlockNumber_ = true;
414 } else if (paramList.isSublist("smoother: params")) {
415 const auto smooParamList = paramList.sublist("smoother: params");
416 if (smooParamList.isParameter("partitioner: type") &&
417 (smooParamList.get<std::string>("partitioner: type") == "line")) {
418 useCoordinates_ = true;
419 }
420 } else {
421 for (int levelID = 0; levelID < this->numDesiredLevel_; levelID++) {
422 std::string levelStr = "level " + toString(levelID);
423
424 if (paramList.isSublist(levelStr)) {
425 const ParameterList& levelList = paramList.sublist(levelStr);
426
427 if (test_param_2list<std::string>(levelList, paramList, "aggregation: drop scheme", "distance laplacian") ||
428 test_param_2list<std::string>(levelList, paramList, "aggregation: type", "brick") ||
429 test_param_2list<bool>(levelList, paramList, "aggregation: export visualization data", true)) {
430 useCoordinates_ = true;
431 } else if (test_param_2list<std::string>(levelList, paramList, "aggregation: drop scheme", "block diagonal distance laplacian")) {
432 useCoordinates_ = true;
433 useBlockNumber_ = true;
434 } else if (test_param_2list<std::string>(levelList, paramList, "aggregation: drop scheme", "block diagonal") ||
435 test_param_2list<std::string>(levelList, paramList, "aggregation: drop scheme", "block diagonal classical") ||
436 test_param_2list<std::string>(levelList, paramList, "aggregation: drop scheme", "block diagonal signed classical") ||
437 test_param_2list<std::string>(levelList, paramList, "aggregation: drop scheme", "block diagonal colored signed classical") ||
438 test_param_2list<std::string>(levelList, paramList, "aggregation: drop scheme", "signed classical")) {
439 useBlockNumber_ = true;
440 }
441 }
442 }
443 }
444
445 useMaterial_ = false;
446 if (test_param_2list<std::string>(paramList, paramList, "aggregation: distance laplacian metric", "material")) {
447 useMaterial_ = true;
448 }
449
450 if (test_param_2list<bool>(paramList, paramList, "repartition: enable", true)) {
451 // We don't need coordinates if we're doing the in-place restriction
452 if (test_param_2list<bool>(paramList, paramList, "repartition: use subcommunicators", true) &&
453 test_param_2list<bool>(paramList, paramList, "repartition: use subcommunicators in place", true)) {
454 // do nothing --- these don't need coordinates
455 } else if (!paramList.isSublist("repartition: params")) {
456 useCoordinates_ = true;
457 } else {
458 const ParameterList& repParams = paramList.sublist("repartition: params");
459 if (repParams.isType<std::string>("algorithm")) {
460 const std::string algo = repParams.get<std::string>("algorithm");
461 if (algo == "multijagged" || algo == "rcb") {
462 useCoordinates_ = true;
463 }
464 } else {
465 useCoordinates_ = true;
466 }
467 }
468 }
469 for (int levelID = 0; levelID < this->numDesiredLevel_; levelID++) {
470 std::string levelStr = "level " + toString(levelID);
471
472 if (paramList.isSublist(levelStr)) {
473 const ParameterList& levelList = paramList.sublist(levelStr);
474
475 if (test_param_2list<bool>(levelList, paramList, "repartition: enable", true)) {
476 if (!levelList.isSublist("repartition: params")) {
477 useCoordinates_ = true;
478 break;
479 } else {
480 const ParameterList& repParams = levelList.sublist("repartition: params");
481 if (repParams.isType<std::string>("algorithm")) {
482 const std::string algo = repParams.get<std::string>("algorithm");
483 if (algo == "multijagged" || algo == "rcb") {
484 useCoordinates_ = true;
485 break;
486 }
487 } else {
488 useCoordinates_ = true;
489 break;
490 }
491 }
492 }
493 }
494 }
495
496 // Detect if we do implicit P and R rebalance
497 changedPRrebalance_ = false;
498 changedPRViaCopyrebalance_ = false;
499 if (test_param_2list<bool>(paramList, paramList, "repartition: enable", true)) {
500 changedPRrebalance_ = test_and_set_var<bool>(paramList, "repartition: rebalance P and R", this->doPRrebalance_);
501 changedPRViaCopyrebalance_ = test_and_set_var<bool>(paramList, "repartition: explicit via new copy rebalance P and R", this->doPRViaCopyrebalance_);
502 }
503
504 // Detect if we use implicit transpose
505 changedImplicitTranspose_ = test_and_set_var<bool>(paramList, "transpose: use implicit", this->implicitTranspose_);
506
507 // Detect if we use fuse prolongation and update
508 (void)test_and_set_var<bool>(paramList, "fuse prolongation and update", this->fuseProlongationAndUpdate_);
509
510 // Detect if we suppress the dimension check of the user-given nullspace
511 (void)test_and_set_var<bool>(paramList, "nullspace: suppress dimension check", this->suppressNullspaceDimensionCheck_);
512
513 if (paramList.isSublist("matvec params"))
514 this->matvecParams_ = Teuchos::parameterList(paramList.sublist("matvec params"));
515
516 // Create default manager
517 // FIXME: should it be here, or higher up
518 RCP<FactoryManager> defaultManager = rcp(new FactoryManager());
519 defaultManager->SetVerbLevel(this->verbosity_);
520 defaultManager->SetKokkosRefactor(useKokkos_);
521
522 // We will ignore keeps0
523 std::vector<keep_pair> keeps0;
524 UpdateFactoryManager(paramList, ParameterList(), *defaultManager, 0 /*levelID*/, keeps0);
525
526 // std::cout<<"*** Default Manager ***"<<std::endl;
527 // defaultManager->Print();
528
529 // Create level specific factory managers
530 for (int levelID = 0; levelID < this->numDesiredLevel_; levelID++) {
531 // Note, that originally if there were no level specific parameters, we
532 // simply copied the defaultManager However, with the introduction of
533 // levelID to UpdateFactoryManager (required for reuse), we can no longer
534 // guarantee that the kept variables are the same for each level even if
535 // dependency structure does not change.
536 RCP<FactoryManager> levelManager = rcp(new FactoryManager(*defaultManager));
537 levelManager->SetVerbLevel(defaultManager->GetVerbLevel());
538
539 std::vector<keep_pair> keeps;
540 if (paramList.isSublist("level " + toString(levelID))) {
541 // We do this so the parameters on the level get flagged correctly as "used"
542 ParameterList& levelList = paramList.sublist("level " + toString(levelID), true /*mustAlreadyExist*/);
543 UpdateFactoryManager(levelList, paramList, *levelManager, levelID, keeps);
544
545 } else {
546 ParameterList levelList;
547 UpdateFactoryManager(levelList, paramList, *levelManager, levelID, keeps);
548 }
549
550 this->keep_[levelID] = keeps;
551 this->AddFactoryManager(levelID, 1, levelManager);
552
553 // std::cout<<"*** Level "<<levelID<<" Manager ***"<<std::endl;
554 // levelManager->Print();
555 }
556
557 // FIXME: parameters passed to packages, like Ifpack2, are not touched by us, resulting in "[unused]" flag
558 // being displayed. On the other hand, we don't want to simply iterate through them touching. I don't know
559 // what a good solution looks like
560 if (test_param_2list<bool>(paramList, paramList, "print initial parameters", true))
561 this->GetOStream(static_cast<MsgType>(Runtime1), 0) << paramList << std::endl;
562
563 if (test_param_2list<bool>(paramList, paramList, "print unused parameters", true)) {
564 // Check unused parameters
565 ParameterList unusedParamList;
566
567 // Check for unused parameters that aren't lists
568 for (ParameterList::ConstIterator it = paramList.begin(); it != paramList.end(); it++) {
569 const ParameterEntry& entry = paramList.entry(it);
570
571 if (!entry.isList() && !entry.isUsed())
572 unusedParamList.setEntry(paramList.name(it), entry);
573 }
574
575 // Check for unused parameters in level-specific sublists
576 for (int levelID = 0; levelID < this->numDesiredLevel_; levelID++) {
577 std::string levelStr = "level " + toString(levelID);
578
579 if (paramList.isSublist(levelStr)) {
580 const ParameterList& levelList = paramList.sublist(levelStr);
581
582 for (ParameterList::ConstIterator itr = levelList.begin(); itr != levelList.end(); ++itr) {
583 const ParameterEntry& entry = levelList.entry(itr);
584
585 if (!entry.isList() && !entry.isUsed())
586 unusedParamList.sublist(levelStr).setEntry(levelList.name(itr), entry);
587 }
588 }
589 }
590
591 if (unusedParamList.numParams() > 0) {
592 std::ostringstream unusedParamsStream;
593 int indent = 4;
594 unusedParamList.print(unusedParamsStream, indent);
595
596 this->GetOStream(Warnings1) << "The following parameters were not used:\n"
597 << unusedParamsStream.str() << std::endl;
598 }
599 }
600
602}
603
604// =====================================================================================================
605// ==================================== UpdateFactoryManager ===========================================
606// =====================================================================================================
607template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
609 UpdateFactoryManager(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
610 int levelID, std::vector<keep_pair>& keeps) const {
611 // NOTE: Factory::SetParameterList must be called prior to Factory::SetFactory, as
612 // SetParameterList sets default values for non mentioned parameters, including factories
613
614 using strings = std::unordered_set<std::string>;
615
616 // shortcut
617 if (paramList.numParams() == 0 && defaultList.numParams() > 0)
618 paramList = ParameterList(defaultList);
619
620 auto reuseType = set_var_2list<std::string>(paramList, defaultList, "reuse: type");
621 TEUCHOS_TEST_FOR_EXCEPTION(strings({"none", "tP", "RP", "emin", "RAP", "full", "S"}).count(reuseType) == 0,
622 Exceptions::RuntimeError, "Unknown \"reuse: type\" value: \"" << reuseType << "\". Please consult User's Guide.");
623
624 auto multigridAlgo = set_var_2list<std::string>(paramList, defaultList, "multigrid algorithm");
625 TEUCHOS_TEST_FOR_EXCEPTION(strings({"unsmoothed", "sa", "pg", "emin", "matlab", "pcoarsen", "classical", "smoothed reitzinger", "unsmoothed reitzinger", "emin reitzinger", "replicate", "combine"}).count(multigridAlgo) == 0,
626 Exceptions::RuntimeError, "Unknown \"multigrid algorithm\" value: \"" << multigridAlgo << "\". Please consult User's Guide.");
627#ifndef HAVE_MUELU_MATLAB
628 TEUCHOS_TEST_FOR_EXCEPTION(multigridAlgo == "matlab", Exceptions::RuntimeError,
629 "Cannot use matlab for multigrid algorithm - MueLu was not configured with MATLAB support.");
630#endif
631#ifndef HAVE_MUELU_INTREPID2
632 TEUCHOS_TEST_FOR_EXCEPTION(multigridAlgo == "pcoarsen", Exceptions::RuntimeError,
633 "Cannot use IntrepidPCoarsen prolongator factory - MueLu was not configured with Intrepid support.");
634#endif
635
636 // Only some combinations of reuse and multigrid algorithms are tested, all
637 // other are considered invalid at the moment
638 if (reuseType == "none" || reuseType == "S" || reuseType == "RP" || reuseType == "RAP") {
639 // This works for all kinds of multigrid algorithms
640
641 } else if (reuseType == "tP" && (multigridAlgo != "sa" && multigridAlgo != "unsmoothed")) {
642 reuseType = "none";
643 this->GetOStream(Warnings0) << "Ignoring \"tP\" reuse option as it is only compatible with \"sa\", "
644 "or \"unsmoothed\" multigrid algorithms"
645 << std::endl;
646
647 } else if (reuseType == "emin" && multigridAlgo != "emin") {
648 reuseType = "none";
649 this->GetOStream(Warnings0) << "Ignoring \"emin\" reuse option it is only compatible with "
650 "\"emin\" multigrid algorithm"
651 << std::endl;
652 }
653
654 // == Non-serializable data ===
655 // Check both the parameter and the type
656 bool have_userP = false;
657 if (paramList.isParameter("P") && !paramList.get<RCP<Matrix>>("P").is_null())
658 have_userP = true;
659
660 // === Coarse solver ===
661 UpdateFactoryManager_CoarseSolvers(paramList, defaultList, manager, levelID, keeps);
662
663 // == Smoothers ==
664 UpdateFactoryManager_Smoothers(paramList, defaultList, manager, levelID, keeps);
665
666 // === BlockNumber ===
667 if (levelID == 0)
668 UpdateFactoryManager_BlockNumber(paramList, defaultList, manager, levelID, keeps);
669
670 // === Aggregation ===
671 if (multigridAlgo == "unsmoothed reitzinger" || multigridAlgo == "smoothed reitzinger")
672 UpdateFactoryManager_Reitzinger(paramList, defaultList, manager, levelID, keeps);
673 else if (multigridAlgo == "emin reitzinger")
674 UpdateFactoryManager_EminReitzinger(paramList, defaultList, manager, levelID, keeps);
675 else
676 UpdateFactoryManager_Aggregation_TentativeP(paramList, defaultList, manager, levelID, keeps);
677
678 // === Nullspace ===
679 RCP<Factory> nullSpaceFactory; // Cache thcAN is guy for the combination of semi-coarsening & repartitioning
680 UpdateFactoryManager_Nullspace(paramList, defaultList, manager, levelID, keeps, nullSpaceFactory);
681
682 // === Prolongation ===
683 // NOTE: None of the UpdateFactoryManager routines called here check the
684 // multigridAlgo. This is intentional, to allow for reuse of components
685 // underneath. Thus, the multigridAlgo was checked in the beginning of the
686 // function.
687 if (have_userP) {
688 // User prolongator
689 manager.SetFactory("P", NoFactory::getRCP());
690
691 } else if (multigridAlgo == "unsmoothed" || multigridAlgo == "unsmoothed reitzinger") {
692 // Unsmoothed aggregation
693 manager.SetFactory("P", manager.GetFactory("Ptent"));
694
695 } else if (multigridAlgo == "classical") {
696 // Classical AMG
697 manager.SetFactory("P", manager.GetFactory("Ptent"));
698
699 } else if (multigridAlgo == "sa" || multigridAlgo == "smoothed reitzinger") {
700 // Smoothed aggregation
701 UpdateFactoryManager_SA(multigridAlgo, paramList, defaultList, manager, levelID, keeps);
702
703 } else if (multigridAlgo == "emin") {
704 // Energy minimization
705 UpdateFactoryManager_Emin(paramList, defaultList, manager, levelID, keeps);
706
707 } else if (multigridAlgo == "emin reitzinger") {
708 // pass
709
710 } else if (multigridAlgo == "replicate") {
711 UpdateFactoryManager_Replicate(paramList, defaultList, manager, levelID, keeps);
712
713 } else if (multigridAlgo == "combine") {
714 UpdateFactoryManager_Combine(paramList, defaultList, manager, levelID, keeps);
715
716 } else if (multigridAlgo == "pg") {
717 // Petrov-Galerkin
718 UpdateFactoryManager_PG(paramList, defaultList, manager, levelID, keeps);
719
720 } else if (multigridAlgo == "matlab") {
721 // Matlab Coarsneing
722 UpdateFactoryManager_Matlab(paramList, defaultList, manager, levelID, keeps);
723
724 } else if (multigridAlgo == "pcoarsen") {
725 // P-Coarsening
726 UpdateFactoryManager_PCoarsen(paramList, defaultList, manager, levelID, keeps);
727 }
728
729 // === Semi-coarsening ===
730 UpdateFactoryManager_SemiCoarsen(paramList, defaultList, manager, levelID, keeps);
731
732 // === Restriction ===
733 UpdateFactoryManager_Restriction(paramList, defaultList, manager, levelID, keeps);
734
735 // === RAP ===
736 UpdateFactoryManager_RAP(paramList, defaultList, manager, levelID, keeps);
737
738 if (multigridAlgo == "smoothed reitzinger") {
739 // === CurlCurl ===
740 auto saDampingFactor = set_var_2list<double>(paramList, defaultList, "sa: damping factor");
741 if (saDampingFactor != 0.0)
742 UpdateFactoryManager_MatrixTransfer("CurlCurl", paramList, defaultList, manager, levelID, keeps);
743 }
744
745 // == BlockNumber Transfer ==
746 UpdateFactoryManager_LocalOrdinalTransfer("BlockNumber", multigridAlgo, paramList, defaultList, manager, levelID, keeps);
747
748 // === Coordinates ===
749 UpdateFactoryManager_Coordinates(paramList, defaultList, manager, levelID, keeps);
750
751 // === Material ===
752 UpdateFactoryManager_Material(paramList, defaultList, manager, levelID, keeps);
753
754 // === Pre-Repartition Keeps for Reuse ===
755 if ((reuseType == "RP" || reuseType == "RAP" || reuseType == "full") && levelID)
756 keeps.push_back(keep_pair("Nullspace", manager.GetFactory("Nullspace").get()));
757
758 if (reuseType == "RP" && levelID) {
759 keeps.push_back(keep_pair("P", manager.GetFactory("P").get()));
760 if (!this->implicitTranspose_)
761 keeps.push_back(keep_pair("R", manager.GetFactory("R").get()));
762 }
763 if ((reuseType == "tP" || reuseType == "RP" || reuseType == "emin") && useCoordinates_ && levelID)
764 keeps.push_back(keep_pair("Coordinates", manager.GetFactory("Coordinates").get()));
765
766 // === Repartitioning ===
767 UpdateFactoryManager_Repartition(paramList, defaultList, manager, levelID, keeps, nullSpaceFactory);
768
769 // === Auxiliary mass matrix for MinvA ===
770 auto socMatrix = set_var_2list<std::string>(paramList, defaultList, "aggregation: strength-of-connection: matrix");
771 if (socMatrix == "MinvA") {
772 // we can either project MinvA or Minv or M to coarse levels. If we decide to project M, then
773 // it must be provided as "user data". If we decide to project Minv, then either Minv or M
774 // must be provided as "user data". In the later case, Minv will be created from M and then
775 // projected. Projecting MinvA is handled in a similar fashion to Minv. It can be provided
776 // as user data, or either M or Minv can be provided as user data. In these later cases,
777 // MinvA will be computed in CaolesceDrop factory.
778
779 // Default: M is provided on finest level and that Minv and MinvA are computed by CoalesceDrop.
780 std::string MinvFactory = "CoalesceDrop";
781 std::string MinvAFactory = "CoalesceDrop";
782 if (paramList.isSublist("project auxiliary matrices")) {
783 auto projectList = paramList.sublist("project auxiliary matrices");
784 if (projectList.isParameter("M")) {
785 TEUCHOS_TEST_FOR_EXCEPTION(projectList.get("M", "") != "NoFactory", Exceptions::InvalidArgument, "Must specify \"NoFactory\" when projecting M");
786 }
787 if (projectList.isParameter("Minv")) {
788 MinvFactory = projectList.get("Minv", "");
789 TEUCHOS_TEST_FOR_EXCEPTION((MinvFactory != "NoFactory") && (MinvFactory != "CoalesceDrop"), Exceptions::InvalidArgument, "Must specify \"NoFactory\" or \"CoalesceDrop\"");
790 }
791 if (projectList.isParameter("MinvA")) {
792 MinvAFactory = projectList.get("MinvA", "");
793 TEUCHOS_TEST_FOR_EXCEPTION((MinvAFactory != "NoFactory") && (MinvAFactory != "CoalesceDrop"), Exceptions::InvalidArgument, "Must specify \"NoFactory\" or \"CoalesceDrop\"");
794 }
795 }
796
797 // We don't really know what user data is supplied here. We know that if M is a parameter of sublist("project auxiliary matrices"), then M must be user-supplied.
798 // If Minv is a parameter of sublist("project auxiliary matrices") and MinvFactory == NoFactory, Minv must be user-supplied. If MinvA is a parameter of
799 // sublist("project auxiliary matrices") and MinvAFactory == NoFactory, MinvA must be user-supplied. However, M might be supplied even though it is not
800 // a parameter of sublist("project auxiliary matrices"). The same is true for Minv and MinvA. Notice that if Minv is parameter of sublist("project auxiliary matrices")
801 // and MinvFactory == CoalesceDrop, then M should be suuplied so that Minv can be computed by CoalesceDrop factory. Thus, we should set M's level 0 factory manager
802 // to NoFactory. The tricky part is when MinvA is parameter of sublist("project auxiliary matrices") and MinvAFactory == CoalesceDrop. In this case, there are
803 // two possibilities for CoalesceDrop() to compute MinvA: a) get user M, invert it, and do mat-mat mult or b) get user Minv and do mat-mat mult. Since we
804 // don't know what the user has supplied, it is safest to set the level 0 manager for both M and Minv to NoFactory.
805
806 if (projectM_) UpdateFactoryManager_MatrixTransfer("M", paramList, defaultList, manager, levelID, keeps);
807 if (!projectM_ && projectMinv_ && (MinvFactory == "CoalesceDrop") && (levelID == 0)) manager.SetFactory("M", NoFactory::getRCP()); // need to get M to created Minv
808 if (!projectM_ && !projectMinv_ && (MinvAFactory == "CoalesceDrop") && projectMinvA_ && (levelID == 0)) {
809 manager.SetFactory("M", NoFactory::getRCP()); // might need M to compute MinvA
810 manager.SetFactory("Minv", NoFactory::getRCP()); // might need Minv to compute MinvA
811 }
812 if (projectMinvA_) {
813 if ((levelID > 0) || (MinvAFactory == "NoFactory"))
814 UpdateFactoryManager_MatrixTransfer("MinvA", paramList, defaultList, manager, levelID, keeps);
815 else {
816 auto coalFact = rcp(new CoalesceDropFactory_kokkos());
817 manager.SetFactory("MinvA", coalFact);
818 } // kokkos guard ?????
819 }
820 if (projectMinv_) {
821 if ((levelID > 0) || (MinvFactory == "NoFactory"))
822 UpdateFactoryManager_MatrixTransfer("Minv", paramList, defaultList, manager, levelID, keeps);
823 else {
824 auto coalFact = rcp(new CoalesceDropFactory_kokkos());
825 manager.SetFactory("Minv", coalFact);
826 } // kokkos guard ?????
827 }
828 }
829
830 // === Lower precision transfers ===
831 UpdateFactoryManager_LowPrecision(paramList, defaultList, manager, levelID, keeps);
832
833 // === Final Keeps for Reuse ===
834 if ((reuseType == "RAP" || reuseType == "full") && levelID) {
835 keeps.push_back(keep_pair("P", manager.GetFactory("P").get()));
836 if (!this->implicitTranspose_)
837 keeps.push_back(keep_pair("R", manager.GetFactory("R").get()));
838 keeps.push_back(keep_pair("A", manager.GetFactory("A").get()));
839 }
840
841 // In case you ever want to inspect the FactoryManager as it is generated for each level
842 /*std::cout<<"*** Factory Manager on level "<<levelID<<" ***"<<std::endl;
843 manager.Print(); */
844}
845
846// =====================================================================================================
847// ========================================= Smoothers =================================================
848// =====================================================================================================
849template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
851 UpdateFactoryManager_Smoothers(ParameterList& paramList, const ParameterList& defaultList,
852 FactoryManager& manager, int levelID, std::vector<keep_pair>& keeps) const {
853 auto multigridAlgo = set_var_2list<std::string>(paramList, defaultList, "multigrid algorithm");
854 auto reuseType = set_var_2list<std::string>(paramList, defaultList, "reuse: type");
855 auto useMaxAbsDiagonalScaling = set_var_2list<bool>(paramList, defaultList, "sa: use rowsumabs diagonal scaling");
856
857 // === Smoothing ===
858 // FIXME: should custom smoother check default list too?
859 bool isCustomSmoother =
860 paramList.isParameter("smoother: pre or post") ||
861 paramList.isParameter("smoother: type") || paramList.isParameter("smoother: pre type") || paramList.isParameter("smoother: post type") ||
862 paramList.isSublist("smoother: params") || paramList.isSublist("smoother: pre params") || paramList.isSublist("smoother: post params") ||
863 paramList.isParameter("smoother: sweeps") || paramList.isParameter("smoother: pre sweeps") || paramList.isParameter("smoother: post sweeps") ||
864 paramList.isParameter("smoother: overlap") || paramList.isParameter("smoother: pre overlap") || paramList.isParameter("smoother: post overlap");
865
866 auto PreOrPost = set_var_2list<std::string>(paramList, defaultList, "smoother: pre or post");
867 if (PreOrPost == "none") {
868 manager.SetFactory("Smoother", Teuchos::null);
869
870 } else if (isCustomSmoother) {
871 // FIXME: get default values from the factory
872 // NOTE: none of the smoothers at the moment use parameter validation framework, so we
873 // cannot get the default values from it.
874#define TEST_MUTUALLY_EXCLUSIVE(arg1, arg2) \
875 TEUCHOS_TEST_FOR_EXCEPTION(paramList.isParameter(#arg1) && paramList.isParameter(#arg2), \
876 Exceptions::InvalidArgument, "You cannot specify both \"" #arg1 "\" and \"" #arg2 "\"");
877#define TEST_MUTUALLY_EXCLUSIVE_S(arg1, arg2) \
878 TEUCHOS_TEST_FOR_EXCEPTION(paramList.isSublist(#arg1) && paramList.isSublist(#arg2), \
879 Exceptions::InvalidArgument, "You cannot specify both \"" #arg1 "\" and \"" #arg2 "\"");
880
881 TEST_MUTUALLY_EXCLUSIVE("smoother: type", "smoother: pre type");
882 TEST_MUTUALLY_EXCLUSIVE("smoother: type", "smoother: post type");
883 TEST_MUTUALLY_EXCLUSIVE("smoother: sweeps", "smoother: pre sweeps");
884 TEST_MUTUALLY_EXCLUSIVE("smoother: sweeps", "smoother: post sweeps");
885 TEST_MUTUALLY_EXCLUSIVE("smoother: overlap", "smoother: pre overlap");
886 TEST_MUTUALLY_EXCLUSIVE("smoother: overlap", "smoother: post overlap");
887 TEST_MUTUALLY_EXCLUSIVE_S("smoother: params", "smoother: pre params");
888 TEST_MUTUALLY_EXCLUSIVE_S("smoother: params", "smoother: post params");
889 TEUCHOS_TEST_FOR_EXCEPTION(PreOrPost == "both" && (paramList.isParameter("smoother: pre type") != paramList.isParameter("smoother: post type")),
890 Exceptions::InvalidArgument, "You must specify both \"smoother: pre type\" and \"smoother: post type\"");
891
892 // Default values
893 int overlap = 0;
894 ParameterList defaultSmootherParams;
895 defaultSmootherParams.set("relaxation: type", "Symmetric Gauss-Seidel");
896 defaultSmootherParams.set("relaxation: sweeps", Teuchos::OrdinalTraits<LO>::one());
897 defaultSmootherParams.set("relaxation: damping factor", Teuchos::ScalarTraits<Scalar>::one());
898
899 RCP<SmootherFactory> preSmoother = Teuchos::null, postSmoother = Teuchos::null;
900 std::string preSmootherType, postSmootherType;
901 ParameterList preSmootherParams, postSmootherParams;
902
903 auto setChebyshevSettings = [&](const std::string& smootherType, Teuchos::ParameterList& smootherParams) {
904 auto upperCaseSmootherType = smootherType;
905 std::transform(smootherType.begin(), smootherType.end(), upperCaseSmootherType.begin(), ::toupper);
906 if (upperCaseSmootherType != "CHEBYSHEV") return;
907
908 if (smootherParams.isParameter("chebyshev: use rowsumabs diagonal scaling")) {
909 bool useMaxAbsDiagonalScalingCheby = smootherParams.get<bool>("chebyshev: use rowsumabs diagonal scaling");
910 TEUCHOS_TEST_FOR_EXCEPTION(useMaxAbsDiagonalScaling != useMaxAbsDiagonalScalingCheby,
911 Exceptions::RuntimeError, "'chebyshev: use rowsumabs diagonal scaling' (" << std::boolalpha << useMaxAbsDiagonalScalingCheby << ") must match 'sa: use rowsumabs diagonal scaling' (" << std::boolalpha << useMaxAbsDiagonalScaling << ")\n");
912 } else {
913 if (useMaxAbsDiagonalScaling)
914 smootherParams.set("chebyshev: use rowsumabs diagonal scaling", useMaxAbsDiagonalScaling);
915 }
916 };
917
918 if (paramList.isParameter("smoother: overlap"))
919 overlap = paramList.get<int>("smoother: overlap");
920
921 if (PreOrPost == "pre" || PreOrPost == "both") {
922 if (paramList.isParameter("smoother: pre type")) {
923 preSmootherType = paramList.get<std::string>("smoother: pre type");
924 } else {
925 auto preSmootherTypeTmp = set_var_2list<std::string>(paramList, defaultList, "smoother: type");
926 preSmootherType = preSmootherTypeTmp;
927 }
928 if (paramList.isParameter("smoother: pre overlap"))
929 overlap = paramList.get<int>("smoother: pre overlap");
930
931 if (paramList.isSublist("smoother: pre params"))
932 preSmootherParams = paramList.sublist("smoother: pre params");
933 else if (paramList.isSublist("smoother: params"))
934 preSmootherParams = paramList.sublist("smoother: params");
935 else if (defaultList.isSublist("smoother: params"))
936 preSmootherParams = defaultList.sublist("smoother: params");
937 else if (preSmootherType == "RELAXATION")
938 preSmootherParams = defaultSmootherParams;
939
940 setChebyshevSettings(preSmootherType, preSmootherParams);
941
942#if defined(HAVE_MUELU_INTREPID2) && defined(HAVE_MUELU_EXPERIMENTAL)
943 // Propagate P-coarsening for Topo smoothing
944 if (multigridAlgo == "pcoarsen" && preSmootherType == "TOPOLOGICAL" &&
945 defaultList.isParameter("pcoarsen: schedule") && defaultList.isParameter("pcoarsen: element")) {
946 // P-Coarsening by schedule (new interface)
947 // NOTE: levelID represents the *coarse* level in this case
948 auto pcoarsen_schedule = Teuchos::getArrayFromStringParameter<int>(defaultList, "pcoarsen: schedule");
949 auto pcoarsen_element = defaultList.get<std::string>("pcoarsen: element");
950
951 if (levelID < (int)pcoarsen_schedule.size()) {
952 // Topo info for P-Coarsening
953 auto lo = pcoarsen_element + std::to_string(pcoarsen_schedule[levelID]);
954 preSmootherParams.set("pcoarsen: hi basis", lo);
955 }
956 }
957#endif
958
959#ifdef HAVE_MUELU_MATLAB
960 if (preSmootherType == "matlab")
961 preSmoother = rcp(new SmootherFactory(rcp(new MatlabSmoother(preSmootherParams))));
962 else
963#endif
964#ifdef HAVE_MUELU_TEKO
965 if (preSmootherType == "teko")
966 preSmoother = rcp(new SmootherFactory(rcp(new TekoSmoother(preSmootherParams))));
967 else
968#endif
969 preSmoother = rcp(new SmootherFactory(rcp(new TrilinosSmoother(preSmootherType, preSmootherParams, overlap))));
970 }
971
972 if (PreOrPost == "post" || PreOrPost == "both") {
973 if (paramList.isParameter("smoother: post type"))
974 postSmootherType = paramList.get<std::string>("smoother: post type");
975 else {
976 auto postSmootherTypeTmp = set_var_2list<std::string>(paramList, defaultList, "smoother: type");
977 postSmootherType = postSmootherTypeTmp;
978 }
979
980 if (paramList.isSublist("smoother: post params"))
981 postSmootherParams = paramList.sublist("smoother: post params");
982 else if (paramList.isSublist("smoother: params"))
983 postSmootherParams = paramList.sublist("smoother: params");
984 else if (defaultList.isSublist("smoother: params"))
985 postSmootherParams = defaultList.sublist("smoother: params");
986 else if (postSmootherType == "RELAXATION")
987 postSmootherParams = defaultSmootherParams;
988 if (paramList.isParameter("smoother: post overlap"))
989 overlap = paramList.get<int>("smoother: post overlap");
990
991 setChebyshevSettings(postSmootherType, postSmootherParams);
992
993 if (postSmootherType == preSmootherType && areSame(preSmootherParams, postSmootherParams))
994 postSmoother = preSmoother;
995 else {
996#if defined(HAVE_MUELU_INTREPID2) && defined(HAVE_MUELU_EXPERIMENTAL)
997 // Propagate P-coarsening for Topo smoothing
998 if (multigridAlgo == "pcoarsen" && preSmootherType == "TOPOLOGICAL" &&
999 defaultList.isParameter("pcoarsen: schedule") && defaultList.isParameter("pcoarsen: element")) {
1000 // P-Coarsening by schedule (new interface)
1001 // NOTE: levelID represents the *coarse* level in this case
1002 auto pcoarsen_schedule = Teuchos::getArrayFromStringParameter<int>(defaultList, "pcoarsen: schedule");
1003 auto pcoarsen_element = defaultList.get<std::string>("pcoarsen: element");
1004
1005 if (levelID < (int)pcoarsen_schedule.size()) {
1006 // Topo info for P-Coarsening
1007 auto lo = pcoarsen_element + std::to_string(pcoarsen_schedule[levelID]);
1008 postSmootherParams.set("pcoarsen: hi basis", lo);
1009 }
1010 }
1011#endif
1012
1013#ifdef HAVE_MUELU_MATLAB
1014 if (postSmootherType == "matlab")
1015 postSmoother = rcp(new SmootherFactory(rcp(new MatlabSmoother(postSmootherParams))));
1016 else
1017#endif
1018#ifdef HAVE_MUELU_TEKO
1019 if (postSmootherType == "teko")
1020 postSmoother = rcp(new SmootherFactory(rcp(new TekoSmoother(postSmootherParams))));
1021 else
1022#endif
1023 postSmoother = rcp(new SmootherFactory(rcp(new TrilinosSmoother(postSmootherType, postSmootherParams, overlap))));
1024 }
1025 }
1026
1027 if (preSmoother == postSmoother)
1028 manager.SetFactory("Smoother", preSmoother);
1029 else {
1030 manager.SetFactory("PreSmoother", preSmoother);
1031 manager.SetFactory("PostSmoother", postSmoother);
1032 }
1033 }
1034
1035 // The first clause is not necessary, but it is here for clarity Smoothers
1036 // are reused if smoother explicitly said to reuse them, or if any other
1037 // reuse option is enabled
1038 bool reuseSmoothers = (reuseType == "S" || reuseType != "none");
1039 if (reuseSmoothers) {
1040 auto preSmootherFactory = rcp_const_cast<Factory>(rcp_dynamic_cast<const Factory>(manager.GetFactory("PreSmoother")));
1041
1042 if (preSmootherFactory != Teuchos::null) {
1043 ParameterList postSmootherFactoryParams;
1044 postSmootherFactoryParams.set("keep smoother data", true);
1045 preSmootherFactory->SetParameterList(postSmootherFactoryParams);
1046
1047 keeps.push_back(keep_pair("PreSmoother data", preSmootherFactory.get()));
1048 }
1049
1050 auto postSmootherFactory = rcp_const_cast<Factory>(rcp_dynamic_cast<const Factory>(manager.GetFactory("PostSmoother")));
1051 if (postSmootherFactory != Teuchos::null) {
1052 ParameterList postSmootherFactoryParams;
1053 postSmootherFactoryParams.set("keep smoother data", true);
1054 postSmootherFactory->SetParameterList(postSmootherFactoryParams);
1055
1056 keeps.push_back(keep_pair("PostSmoother data", postSmootherFactory.get()));
1057 }
1058
1059 auto coarseFactory = rcp_const_cast<Factory>(rcp_dynamic_cast<const Factory>(manager.GetFactory("CoarseSolver")));
1060 if (coarseFactory != Teuchos::null) {
1061 ParameterList coarseFactoryParams;
1062 coarseFactoryParams.set("keep smoother data", true);
1063 coarseFactory->SetParameterList(coarseFactoryParams);
1064
1065 keeps.push_back(keep_pair("PreSmoother data", coarseFactory.get()));
1066 }
1067 }
1068
1069 if ((reuseType == "RAP" && levelID) || (reuseType == "full")) {
1070 // The difference between "RAP" and "full" is keeping smoothers. However,
1071 // as in both cases we keep coarse matrices, we do not need to update
1072 // coarse smoothers. On the other hand, if a user changes fine level
1073 // matrix, "RAP" would update the fine level smoother, while "full" would
1074 // not
1075 keeps.push_back(keep_pair("PreSmoother", manager.GetFactory("PreSmoother").get()));
1076 keeps.push_back(keep_pair("PostSmoother", manager.GetFactory("PostSmoother").get()));
1077
1078 // We do keep_pair("PreSmoother", manager.GetFactory("CoarseSolver").get())
1079 // as the coarse solver factory is in fact a smoothing factory, so the
1080 // only pieces of data it generates are PreSmoother and PostSmoother
1081 keeps.push_back(keep_pair("PreSmoother", manager.GetFactory("CoarseSolver").get()));
1082 }
1083}
1084
1085// =====================================================================================================
1086// ====================================== Coarse Solvers ===============================================
1087// =====================================================================================================
1088template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1090 UpdateFactoryManager_CoarseSolvers(ParameterList& paramList, const ParameterList& defaultList,
1091 FactoryManager& manager, int /* levelID */, std::vector<keep_pair>& /* keeps */) const {
1092 // FIXME: should custom coarse solver check default list too?
1093 bool isCustomCoarseSolver =
1094 paramList.isParameter("coarse: type") ||
1095 paramList.isParameter("coarse: params");
1096 if (test_param_2list<std::string>(paramList, defaultList, "coarse: type", "none")) {
1097 manager.SetFactory("CoarseSolver", Teuchos::null);
1098
1099 } else if (isCustomCoarseSolver) {
1100 // FIXME: get default values from the factory
1101 // NOTE: none of the smoothers at the moment use parameter validation framework, so we
1102 // cannot get the default values from it.
1103 auto coarseType = set_var_2list<std::string>(paramList, defaultList, "coarse: type");
1104
1105 int overlap = 0;
1106 if (paramList.isParameter("coarse: overlap"))
1107 overlap = paramList.get<int>("coarse: overlap");
1108
1109 ParameterList coarseParams;
1110 if (paramList.isSublist("coarse: params"))
1111 coarseParams = paramList.sublist("coarse: params");
1112 else if (defaultList.isSublist("coarse: params"))
1113 coarseParams = defaultList.sublist("coarse: params");
1114
1115 using strings = std::unordered_set<std::string>;
1116
1117 RCP<SmootherPrototype> coarseSmoother;
1118 // TODO: this is not a proper place to check. If we consider direct solver to be a special
1119 // case of smoother, we would like to unify Amesos and Ifpack2 smoothers in src/Smoothers, and
1120 // have a single factory responsible for those. Then, this check would belong there.
1121 if (strings({"RELAXATION", "CHEBYSHEV", "ILUT", "ILU", "RILUK", "SCHWARZ", "Amesos",
1122 "BLOCK RELAXATION", "BLOCK_RELAXATION", "BLOCKRELAXATION",
1123 "SPARSE BLOCK RELAXATION", "SPARSE_BLOCK_RELAXATION", "SPARSEBLOCKRELAXATION",
1124 "LINESMOOTHING_BANDEDRELAXATION", "LINESMOOTHING_BANDED_RELAXATION", "LINESMOOTHING_BANDED RELAXATION",
1125 "LINESMOOTHING_TRIDIRELAXATION", "LINESMOOTHING_TRIDI_RELAXATION", "LINESMOOTHING_TRIDI RELAXATION",
1126 "LINESMOOTHING_TRIDIAGONALRELAXATION", "LINESMOOTHING_TRIDIAGONAL_RELAXATION", "LINESMOOTHING_TRIDIAGONAL RELAXATION",
1127 "TOPOLOGICAL", "FAST_ILU", "FAST_IC", "FAST_ILDL", "HIPTMAIR"})
1128 .count(coarseType)) {
1129 coarseSmoother = rcp(new TrilinosSmoother(coarseType, coarseParams, overlap));
1130 } else {
1131#ifdef HAVE_MUELU_MATLAB
1132 if (coarseType == "matlab")
1133 coarseSmoother = rcp(new MatlabSmoother(coarseParams));
1134 else
1135#endif
1136#ifdef HAVE_MUELU_TEKO
1137 if (coarseType == "teko")
1138 coarseSmoother = rcp(new TekoSmoother(coarseParams));
1139 else
1140#endif
1141 coarseSmoother = rcp(new DirectSolver(coarseType, coarseParams));
1142 }
1143
1144 manager.SetFactory("CoarseSolver", rcp(new SmootherFactory(coarseSmoother)));
1145 }
1146}
1147
1148// =====================================================================================================
1149// ========================================= Reitzinger =================================================
1150// =====================================================================================================
1151template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1153 UpdateFactoryManager_Reitzinger(ParameterList& paramList, const ParameterList& defaultList,
1154 FactoryManager& manager, int levelID, std::vector<keep_pair>& /*keeps*/) const {
1155 ParameterList rParams;
1156 test_and_set_param_2list<bool>(paramList, defaultList, "repartition: enable", rParams);
1157 test_and_set_param_2list<bool>(paramList, defaultList, "repartition: use subcommunicators", rParams);
1158 test_and_set_param_2list<bool>(paramList, defaultList, "tentative: constant column sums", rParams);
1159 test_and_set_param_2list<bool>(paramList, defaultList, "tentative: calculate qr", rParams);
1160
1161 RCP<Factory> rFactory = rcp(new ReitzingerPFactory());
1162 rFactory->SetParameterList(rParams);
1163
1164 // These are all going to be user provided, so NoFactory
1165 rFactory->SetFactory("Pnodal", NoFactory::getRCP());
1166 rFactory->SetFactory("NodeAggMatrix", NoFactory::getRCP());
1167 // rFactory->SetFactory("NodeMatrix", NoFactory::getRCP());
1168
1169 if (levelID > 1)
1170 rFactory->SetFactory("D0", this->GetFactoryManager(levelID - 1)->GetFactory("D0"));
1171 else
1172 rFactory->SetFactory("D0", NoFactory::getRCP());
1173
1174 manager.SetFactory("Ptent", rFactory);
1175 manager.SetFactory("D0", rFactory);
1176 manager.SetFactory("InPlaceMap", rFactory);
1177}
1178
1179// =====================================================================================================
1180// =============================== Algorithm: Energy Minimization Reitzinger ===========================
1181// =====================================================================================================
1182template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1184 UpdateFactoryManager_EminReitzinger(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
1185 int levelID, std::vector<keep_pair>& /*keeps*/) const {
1186 ParameterList rParams;
1187 test_and_set_param_2list<bool>(paramList, defaultList, "repartition: enable", rParams);
1188 test_and_set_param_2list<bool>(paramList, defaultList, "repartition: use subcommunicators", rParams);
1189 test_and_set_param_2list<bool>(paramList, defaultList, "tentative: constant column sums", rParams);
1190 test_and_set_param_2list<bool>(paramList, defaultList, "tentative: calculate qr", rParams);
1191
1192 RCP<Factory> rFactory = rcp(new ReitzingerPFactory());
1193 rFactory->SetParameterList(rParams);
1194
1195 // These are all going to be user provided, so NoFactory
1196 rFactory->SetFactory("Pnodal", NoFactory::getRCP());
1197 rFactory->SetFactory("NodeAggMatrix", NoFactory::getRCP());
1198 // rFactory->SetFactory("NodeMatrix", NoFactory::getRCP());
1199
1200 if (levelID > 1)
1201 rFactory->SetFactory("D0", this->GetFactoryManager(levelID - 1)->GetFactory("D0"));
1202 else
1203 rFactory->SetFactory("D0", NoFactory::getRCP());
1204
1205 manager.SetFactory("Ptent", rFactory);
1206 manager.SetFactory("D0", rFactory);
1207 manager.SetFactory("InPlaceMap", rFactory);
1208
1209 auto reuseType = set_var_2list<std::string>(paramList, defaultList, "reuse: type");
1210
1211 // Pattern
1212 auto patternFactory = rcp(new EdgeProlongatorPatternFactory());
1213 manager.SetFactory("Ppattern", patternFactory);
1214
1215 // Constraint
1216 auto constraintFactory = rcp(new ConstraintFactory());
1217 ParameterList constraintParams;
1218 constraintFactory->SetFactory("Ppattern", manager.GetFactory("Ppattern"));
1219 test_and_set_param_2list<std::string>(paramList, defaultList, "emin: least squares solver type", constraintParams);
1220 constraintParams.set("emin: constraint type", "maxwell");
1221 constraintFactory->SetParameterList(constraintParams);
1222 manager.SetFactory("Constraint", constraintFactory);
1223
1224 // Emin Factory
1225 auto P = rcp(new EminPFactory());
1226
1227 // Energy minimization
1228 ParameterList Pparams;
1229 test_and_set_param_2list<int>(paramList, defaultList, "emin: num iterations", Pparams);
1230 test_and_set_param_2list<std::string>(paramList, defaultList, "emin: iterative method", Pparams);
1231 if (reuseType == "emin") {
1232 test_and_set_param_2list<int>(paramList, defaultList, "emin: num reuse iterations", Pparams);
1233 Pparams.set("Keep P0", true);
1234 Pparams.set("Keep Constraint0", true);
1235 }
1236 P->SetParameterList(Pparams);
1237 P->SetFactory("P", constraintFactory);
1238 P->SetFactory("Constraint", constraintFactory);
1239 manager.SetFactory("P", P);
1240}
1241
1242// =====================================================================================================
1243// ========================================= TentativeP=================================================
1244// =====================================================================================================
1245template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1247 UpdateFactoryManager_Aggregation_TentativeP(ParameterList& paramList, const ParameterList& defaultList,
1248 FactoryManager& manager, int levelID, std::vector<keep_pair>& keeps) const {
1249 using strings = std::unordered_set<std::string>;
1250
1251 auto reuseType = set_var_2list<std::string>(paramList, defaultList, "reuse: type");
1252
1253 auto aggType = set_var_2list<std::string>(paramList, defaultList, "aggregation: type");
1254 TEUCHOS_TEST_FOR_EXCEPTION(!strings({"uncoupled", "coupled", "brick", "matlab", "notay", "classical"}).count(aggType),
1255 Exceptions::RuntimeError, "Unknown aggregation algorithm: \"" << aggType << "\". Please consult User's Guide.");
1256
1257 // Only doing this for classical because otherwise, the gold tests get broken badly
1258 RCP<AmalgamationFactory> amalgFact;
1259 if (aggType == "classical") {
1260 amalgFact = rcp(new AmalgamationFactory());
1261 manager.SetFactory("UnAmalgamationInfo", amalgFact);
1262 }
1263
1264 // Aggregation graph
1265 RCP<Factory> dropFactory;
1266
1267 if (test_param_2list<std::string>(paramList, paramList, "aggregation: drop scheme", "matlab")) {
1268#ifdef HAVE_MUELU_MATLAB
1269 dropFactory = rcp(new SingleLevelMatlabFactory());
1270 ParameterList socParams = paramList.sublist("strength-of-connection: params");
1271 dropFactory->SetParameterList(socParams);
1272#else
1273 throw std::runtime_error("Cannot use MATLAB evolutionary strength-of-connection - MueLu was not configured with MATLAB support.");
1274#endif
1275 } else if (test_param_2list<std::string>(paramList, paramList, "aggregation: drop scheme", "unsupported vector smoothing")) {
1277 ParameterList dropParams;
1278 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregation: drop scheme", dropParams);
1279 test_and_set_param_2list<int>(paramList, defaultList, "aggregation: block diagonal: interleaved blocksize", dropParams);
1280 test_and_set_param_2list<int>(paramList, defaultList, "aggregation: number of random vectors", dropParams);
1281 test_and_set_param_2list<int>(paramList, defaultList, "aggregation: number of times to pre or post smooth", dropParams);
1282 test_and_set_param_2list<Teuchos::Array<double>>(paramList, defaultList, "aggregation: penalty parameters", dropParams);
1283 dropFactory->SetParameterList(dropParams);
1284 } else {
1286 ParameterList dropParams;
1287 if (!rcp_dynamic_cast<CoalesceDropFactory>(dropFactory).is_null())
1288 dropParams.set("lightweight wrap", true);
1289 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregation: drop scheme", dropParams);
1290 test_and_set_param_2list<double>(paramList, defaultList, "aggregation: row sum drop tol", dropParams);
1291 test_and_set_param_2list<int>(paramList, defaultList, "aggregation: block diagonal: interleaved blocksize", dropParams);
1292 test_and_set_param_2list<double>(paramList, defaultList, "aggregation: drop tol", dropParams);
1293 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: use ml scaling of drop tol", dropParams);
1294
1295 test_and_set_param_2list<double>(paramList, defaultList, "aggregation: Dirichlet threshold", dropParams);
1296 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: greedy Dirichlet", dropParams);
1297 if (useKokkos_)
1298 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregation: distance laplacian metric", dropParams);
1299#ifdef HAVE_MUELU_COALESCEDROP_ALLOW_OLD_PARAMETERS
1300 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregation: distance laplacian algo", dropParams);
1301 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregation: classical algo", dropParams);
1302#endif
1303 test_and_set_param_2list<Teuchos::Array<double>>(paramList, defaultList, "aggregation: distance laplacian directional weights", dropParams);
1304 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: coloring: localize color graph", dropParams);
1305 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: dropping may create Dirichlet", dropParams);
1306 if (useKokkos_) {
1307 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: use blocking", dropParams);
1308 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: symmetrize graph after dropping", dropParams);
1309 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregation: strength-of-connection: matrix", dropParams);
1310 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregation: strength-of-connection: measure", dropParams);
1311 test_and_set_param_2list<bool>(paramList, defaultList, "filtered matrix: use lumping", dropParams);
1312 test_and_set_param_2list<bool>(paramList, defaultList, "filtered matrix: reuse graph", dropParams);
1313 test_and_set_param_2list<bool>(paramList, defaultList, "filtered matrix: reuse eigenvalue", dropParams);
1314 test_and_set_param_2list<bool>(paramList, defaultList, "filtered matrix: use root stencil", dropParams);
1315 test_and_set_param_2list<double>(paramList, defaultList, "filtered matrix: Dirichlet threshold", dropParams);
1316 test_and_set_param_2list<bool>(paramList, defaultList, "filtered matrix: use spread lumping", dropParams);
1317 test_and_set_param_2list<std::string>(paramList, defaultList, "filtered matrix: lumping choice", dropParams);
1318 test_and_set_param_2list<double>(paramList, defaultList, "filtered matrix: spread lumping diag dom growth factor", dropParams);
1319 test_and_set_param_2list<double>(paramList, defaultList, "filtered matrix: spread lumping diag dom cap", dropParams);
1320 test_and_set_param_2list<bool>(paramList, defaultList, "filtered matrix: count negative diagonals", dropParams);
1321 }
1322
1323#ifdef HAVE_MUELU_COALESCEDROP_ALLOW_OLD_PARAMETERS
1324 if (!dropParams.isParameter("aggregation: drop scheme") ||
1325 (dropParams.isParameter("aggregation: drop scheme") &&
1326 ((dropParams.get<std::string>("aggregation: drop scheme") != "point-wise") && (dropParams.get<std::string>("aggregation: drop scheme") != "cut-drop")))) {
1327 Teuchos::ParameterList dropParamsWithDefaults(dropParams);
1328
1329 test_and_set_var_from_masterlist<std::string>(dropParamsWithDefaults, "aggregation: drop scheme");
1330 test_and_set_var_from_masterlist<std::string>(dropParamsWithDefaults, "aggregation: strength-of-connection: matrix");
1331 test_and_set_var_from_masterlist<std::string>(dropParamsWithDefaults, "aggregation: strength-of-connection: measure");
1332 test_and_set_var_from_masterlist<bool>(dropParamsWithDefaults, "aggregation: use blocking");
1333
1334 // We are using the old style of dropping params
1335 TEUCHOS_TEST_FOR_EXCEPTION(dropParams.isParameter("aggregation: strength-of-connection: matrix") ||
1336 dropParams.isParameter("aggregation: strength-of-connection: measure") ||
1337 dropParams.isParameter("aggregation: use blocking"),
1338 Teuchos::Exceptions::InvalidParameterType,
1339 "The inputs contain a mix of old and new dropping parameters:\n\n"
1340 << dropParams << "\n\nKeep in mind that defaults are set for old parameters, so this gets interpreted as\n\n"
1341 << dropParamsWithDefaults);
1342 }
1343#endif
1344
1345 if (!amalgFact.is_null())
1346 dropFactory->SetFactory("UnAmalgamationInfo", manager.GetFactory("UnAmalgamationInfo"));
1347
1348 if (dropParams.isParameter("aggregation: drop scheme")) {
1349 std::string drop_scheme = dropParams.get<std::string>("aggregation: drop scheme");
1350 if (drop_scheme == "block diagonal colored signed classical")
1351 manager.SetFactory("Coloring Graph", dropFactory);
1352 if ((test_param_2list<bool>(dropParams, defaultList, "aggregation: use blocking", true)) ||
1353 (drop_scheme.find("block diagonal") != std::string::npos || drop_scheme == "signed classical")) {
1354 if (levelID > 0)
1355 dropFactory->SetFactory("BlockNumber", this->GetFactoryManager(levelID - 1)->GetFactory("BlockNumber"));
1356 else
1357 dropFactory->SetFactory("BlockNumber", manager.GetFactory("BlockNumber"));
1358 }
1359 }
1360
1361 if (useKokkos_ && (levelID > 0)) {
1362 if (dropParams.isParameter("aggregation: strength-of-connection: matrix") && dropParams.get<std::string>("aggregation: strength-of-connection: matrix") == "MinvA") {
1363 if (projectM_) dropFactory->SetFactory("M", this->GetFactoryManager(levelID - 1)->GetFactory("M"));
1364 if (projectMinv_) dropFactory->SetFactory("Minv", this->GetFactoryManager(levelID - 1)->GetFactory("Minv"));
1365 if (projectMinvA_) dropFactory->SetFactory("MinvA", this->GetFactoryManager(levelID - 1)->GetFactory("MinvA"));
1366 }
1367 }
1368
1369 auto socMatrix = set_var_2list<std::string>(paramList, defaultList, "aggregation: strength-of-connection: matrix");
1370 if ((socMatrix == "MinvA") && (paramList.isSublist("project auxiliary matrices"))) {
1371 auto projectList = paramList.sublist("project auxiliary matrices");
1372 dropParams.set("project auxiliary matrices", projectList);
1373 }
1374 dropFactory->SetParameterList(dropParams);
1375 }
1376 manager.SetFactory("Graph", dropFactory);
1377
1378// Aggregation scheme
1379#ifndef HAVE_MUELU_MATLAB
1380 if (aggType == "matlab")
1381 throw std::runtime_error("Cannot use MATLAB aggregation - MueLu was not configured with MATLAB support.");
1382#endif
1383 RCP<Factory> aggFactory;
1384 if (aggType == "uncoupled") {
1385 aggFactory = rcp(new UncoupledAggregationFactory());
1386 ParameterList aggParams;
1387 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregation: ordering", aggParams);
1388 test_and_set_param_2list<int>(paramList, defaultList, "aggregation: min agg size", aggParams);
1389 test_and_set_param_2list<int>(paramList, defaultList, "aggregation: max agg size", aggParams);
1390 test_and_set_param_2list<int>(paramList, defaultList, "aggregation: max selected neighbors", aggParams);
1391 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregation: backend", aggParams);
1392 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregation: phase 1 algorithm", aggParams);
1393 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: deterministic", aggParams);
1394 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregation: coloring algorithm", aggParams);
1395 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: enable phase 1", aggParams);
1396 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: enable phase 2a", aggParams);
1397 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: enable phase 2b", aggParams);
1398 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: enable phase 3", aggParams);
1399 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: match ML phase1", aggParams);
1400 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: match ML phase2a", aggParams);
1401 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: match ML phase2b", aggParams);
1402 test_and_set_param_2list<double>(paramList, defaultList, "aggregation: phase2a agg factor", aggParams);
1403 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: preserve Dirichlet points", aggParams);
1404 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: error on nodes with no on-rank neighbors", aggParams);
1405 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: phase3 avoid singletons", aggParams);
1406 aggFactory->SetParameterList(aggParams);
1407 // make sure that the aggregation factory has all necessary data
1408 aggFactory->SetFactory("DofsPerNode", manager.GetFactory("Graph"));
1409 aggFactory->SetFactory("Graph", manager.GetFactory("Graph"));
1410 // aggFactory->SetFactory("UnAmalgamationInfo", manager.GetFactory("UnAmalgamationInfo"));
1411
1412 if (test_param_2list<std::string>(paramList, defaultList, "aggregation: coloring algorithm", "mis2 aggregation") ||
1413 test_param_2list<std::string>(paramList, defaultList, "aggregation: coloring algorithm", "mis2 coarsening")) {
1414 if (test_param_2list<bool>(paramList, defaultList, "aggregation: symmetrize graph after dropping", false))
1415 TEUCHOS_TEST_FOR_EXCEPTION(true,
1417 "MIS2 algorithms require the use of a symmetrized graph. Please set \"aggregation: symmetrize graph after dropping\" to \"true\".");
1418 }
1419 } else if (aggType == "brick") {
1420 aggFactory = rcp(new BrickAggregationFactory());
1421 ParameterList aggParams;
1422 test_and_set_param_2list<int>(paramList, defaultList, "aggregation: brick x size", aggParams);
1423 test_and_set_param_2list<int>(paramList, defaultList, "aggregation: brick y size", aggParams);
1424 test_and_set_param_2list<int>(paramList, defaultList, "aggregation: brick z size", aggParams);
1425 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: brick x Dirichlet", aggParams);
1426 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: brick y Dirichlet", aggParams);
1427 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: brick z Dirichlet", aggParams);
1428 aggFactory->SetParameterList(aggParams);
1429
1430 // Unlike other factories, BrickAggregationFactory makes the Graph/DofsPerNode itself
1431 manager.SetFactory("Graph", aggFactory);
1432 manager.SetFactory("DofsPerNode", aggFactory);
1433 manager.SetFactory("Filtering", aggFactory);
1434 if (levelID > 1) {
1435 // We check for levelID > 0, as in the interpreter aggFactory for
1436 // levelID really corresponds to level 0. Managers are clunky, as they
1437 // contain factories for two different levels
1438 aggFactory->SetFactory("Coordinates", this->GetFactoryManager(levelID - 1)->GetFactory("Coordinates"));
1439 }
1440 } else if (aggType == "classical") {
1441 // Map and coloring
1442 RCP<Factory> mapFact = rcp(new ClassicalMapFactory());
1443 ParameterList mapParams;
1444 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: deterministic", mapParams);
1445 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregation: coloring algorithm", mapParams);
1446
1447 ParameterList tempParams;
1448 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregation: drop scheme", tempParams);
1449 std::string drop_algo = tempParams.get<std::string>("aggregation: drop scheme");
1450 if (drop_algo == "block diagonal colored signed classical") {
1451 mapParams.set("aggregation: coloring: use color graph", true);
1452 mapFact->SetFactory("Coloring Graph", manager.GetFactory("Coloring Graph"));
1453 }
1454 mapFact->SetParameterList(mapParams);
1455 mapFact->SetFactory("Graph", manager.GetFactory("Graph"));
1456 mapFact->SetFactory("UnAmalgamationInfo", manager.GetFactory("UnAmalgamationInfo"));
1457
1458 manager.SetFactory("FC Splitting", mapFact);
1459 manager.SetFactory("CoarseMap", mapFact);
1460
1461 aggFactory = rcp(new ClassicalPFactory());
1462 ParameterList aggParams;
1463 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregation: classical scheme", aggParams);
1464 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregation: drop scheme", aggParams);
1465 aggFactory->SetParameterList(aggParams);
1466 aggFactory->SetFactory("FC Splitting", manager.GetFactory("FC Splitting"));
1467 aggFactory->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
1468 aggFactory->SetFactory("DofsPerNode", manager.GetFactory("Graph"));
1469 aggFactory->SetFactory("Graph", manager.GetFactory("Graph"));
1470
1471 if (drop_algo.find("block diagonal") != std::string::npos || drop_algo == "signed classical") {
1472 if (levelID > 0)
1473 aggFactory->SetFactory("BlockNumber", this->GetFactoryManager(levelID - 1)->GetFactory("BlockNumber"));
1474 else
1475 aggFactory->SetFactory("BlockNumber", manager.GetFactory("BlockNumber"));
1476 }
1477
1478 // Now we short-circuit, because we neither need nor want TentativePFactory here
1479 manager.SetFactory("Ptent", aggFactory);
1480 manager.SetFactory("P Graph", aggFactory);
1481
1482 if (reuseType == "tP" && levelID) {
1483 // keeps.push_back(keep_pair("Nullspace", Ptent.get()));
1484 keeps.push_back(keep_pair("Ptent", aggFactory.get()));
1485 }
1486 return;
1487 } else if (aggType == "notay") {
1488 aggFactory = rcp(new NotayAggregationFactory());
1489 ParameterList aggParams;
1490 test_and_set_param_2list<int>(paramList, defaultList, "aggregation: pairwise: size", aggParams);
1491 test_and_set_param_2list<double>(paramList, defaultList, "aggregation: pairwise: tie threshold", aggParams);
1492 test_and_set_param_2list<double>(paramList, defaultList, "aggregation: Dirichlet threshold", aggParams);
1493 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregation: ordering", aggParams);
1494 aggFactory->SetParameterList(aggParams);
1495 aggFactory->SetFactory("DofsPerNode", manager.GetFactory("Graph"));
1496 aggFactory->SetFactory("Graph", manager.GetFactory("Graph"));
1497 }
1498#ifdef HAVE_MUELU_MATLAB
1499 else if (aggType == "matlab") {
1500 ParameterList aggParams = paramList.sublist("aggregation: params");
1501 aggFactory = rcp(new SingleLevelMatlabFactory());
1502 aggFactory->SetParameterList(aggParams);
1503 }
1504#endif
1505
1506 manager.SetFactory("Aggregates", aggFactory);
1507
1508 // Coarse map
1509 RCP<Factory> coarseMap = rcp(new CoarseMapFactory());
1510 coarseMap->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1511 manager.SetFactory("CoarseMap", coarseMap);
1512
1513 // Tentative P
1515 ParameterList ptentParams;
1516 if (paramList.isSublist("matrixmatrix: kernel params"))
1517 ptentParams.sublist("matrixmatrix: kernel params", false) = paramList.sublist("matrixmatrix: kernel params");
1518 if (defaultList.isSublist("matrixmatrix: kernel params"))
1519 ptentParams.sublist("matrixmatrix: kernel params", false) = defaultList.sublist("matrixmatrix: kernel params");
1520 test_and_set_param_2list<bool>(paramList, defaultList, "tentative: calculate qr", ptentParams);
1521 test_and_set_param_2list<bool>(paramList, defaultList, "tentative: build coarse coordinates", ptentParams);
1522 test_and_set_param_2list<bool>(paramList, defaultList, "sa: keep tentative prolongator", ptentParams);
1523 Ptent->SetParameterList(ptentParams);
1524 Ptent->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1525 Ptent->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
1526 manager.SetFactory("Ptent", Ptent);
1527
1528 if (reuseType == "tP" && levelID) {
1529 keeps.push_back(keep_pair("Nullspace", Ptent.get()));
1530 keeps.push_back(keep_pair("P", Ptent.get()));
1531 }
1532}
1533
1534// =====================================================================================================
1535// ============================================ RAP ====================================================
1536// =====================================================================================================
1537template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1539 UpdateFactoryManager_RAP(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
1540 int /*levelID*/, std::vector<keep_pair>& keeps) const {
1541 if (paramList.isParameter("A") && !paramList.get<RCP<Matrix>>("A").is_null()) {
1542 // We have user matrix A
1543 manager.SetFactory("A", NoFactory::getRCP());
1544 return;
1545 }
1546
1547 ParameterList RAPparams;
1548
1549 RCP<RAPFactory> RAP;
1550 RCP<RAPShiftFactory> RAPs;
1551 // Allow for Galerkin or shifted RAP
1552 // FIXME: Should this not be some form of set_var_2list?
1553 std::string alg = paramList.get("rap: algorithm", "galerkin");
1554 if (alg == "shift" || alg == "non-galerkin") {
1555 RAPs = rcp(new RAPShiftFactory());
1556 test_and_set_param_2list<double>(paramList, defaultList, "rap: shift", RAPparams);
1557 test_and_set_param_2list<bool>(paramList, defaultList, "rap: shift diagonal M", RAPparams);
1558 test_and_set_param_2list<bool>(paramList, defaultList, "rap: shift low storage", RAPparams);
1559 test_and_set_param_2list<Teuchos::Array<double>>(paramList, defaultList, "rap: shift array", RAPparams);
1560 test_and_set_param_2list<Teuchos::Array<double>>(paramList, defaultList, "rap: cfl array", RAPparams);
1561
1562 } else {
1563 RAP = rcp(new RAPFactory());
1564 }
1565
1566 test_and_set_param_2list<Teuchos::Array<double>>(paramList, defaultList, "rap: relative diagonal floor", RAPparams);
1567
1568 if (paramList.isSublist("matrixmatrix: kernel params"))
1569 RAPparams.sublist("matrixmatrix: kernel params", false) = paramList.sublist("matrixmatrix: kernel params");
1570 if (defaultList.isSublist("matrixmatrix: kernel params"))
1571 RAPparams.sublist("matrixmatrix: kernel params", false) = defaultList.sublist("matrixmatrix: kernel params");
1572 test_and_set_param_2list<bool>(paramList, defaultList, "transpose: use implicit", RAPparams);
1573 test_and_set_param_2list<bool>(paramList, defaultList, "rap: fix zero diagonals", RAPparams);
1574 test_and_set_param_2list<double>(paramList, defaultList, "rap: fix zero diagonals threshold", RAPparams);
1575 test_and_set_param_2list<Scalar>(paramList, defaultList, "rap: fix zero diagonals replacement", RAPparams);
1576
1577 // if "rap: triple product" has not been set and algorithm is "unsmoothed" switch triple product on
1578 if (!paramList.isParameter("rap: triple product") &&
1579 paramList.isType<std::string>("multigrid algorithm") &&
1580 paramList.get<std::string>("multigrid algorithm") == "unsmoothed")
1581 paramList.set("rap: triple product", true);
1582 else
1583 test_and_set_param_2list<bool>(paramList, defaultList, "rap: triple product", RAPparams);
1584
1585 try {
1586 if (paramList.isParameter("aggregation: allow empty prolongator columns")) {
1587 RAPparams.set("CheckMainDiagonal", paramList.get<bool>("aggregation: allow empty prolongator columns"));
1588 RAPparams.set("RepairMainDiagonal", paramList.get<bool>("aggregation: allow empty prolongator columns"));
1589 } else if (defaultList.isParameter("aggregation: allow empty prolongator columns")) {
1590 RAPparams.set("CheckMainDiagonal", defaultList.get<bool>("aggregation: allow empty prolongator columns"));
1591 RAPparams.set("RepairMainDiagonal", defaultList.get<bool>("aggregation: allow empty prolongator columns"));
1592 }
1593
1594 } catch (Teuchos::Exceptions::InvalidParameterType&) {
1595 TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(true, Teuchos::Exceptions::InvalidParameterType,
1596 "Error: parameter \"aggregation: allow empty prolongator columns\" must be of type " << Teuchos::TypeNameTraits<bool>::name());
1597 }
1598
1599 if (!RAP.is_null()) {
1600 RAP->SetParameterList(RAPparams);
1601 RAP->SetFactory("P", manager.GetFactory("P"));
1602 } else {
1603 RAPs->SetParameterList(RAPparams);
1604 RAPs->SetFactory("P", manager.GetFactory("P"));
1605 }
1606
1607 if (!this->implicitTranspose_) {
1608 if (!RAP.is_null())
1609 RAP->SetFactory("R", manager.GetFactory("R"));
1610 else
1611 RAPs->SetFactory("R", manager.GetFactory("R"));
1612 }
1613
1614 // Matrix analysis
1615 if (test_param_2list<bool>(paramList, defaultList, "matrix: compute analysis", true)) {
1616 RCP<Factory> matrixAnalysisFact = rcp(new MatrixAnalysisFactory());
1617
1618 if (!RAP.is_null())
1619 RAP->AddTransferFactory(matrixAnalysisFact);
1620 else
1621 RAPs->AddTransferFactory(matrixAnalysisFact);
1622 }
1623
1624 // Aggregate qualities
1625 if (test_param_2list<bool>(paramList, defaultList, "aggregation: compute aggregate qualities", true)) {
1626 RCP<Factory> aggQualityFact = rcp(new AggregateQualityEstimateFactory());
1627 ParameterList aggQualityParams;
1628 test_and_set_param_2list<double>(paramList, defaultList, "aggregate qualities: good aggregate threshold", aggQualityParams);
1629 test_and_set_param_2list<bool>(paramList, defaultList, "aggregate qualities: file output", aggQualityParams);
1630 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregate qualities: file base", aggQualityParams);
1631 test_and_set_param_2list<bool>(paramList, defaultList, "aggregate qualities: check symmetry", aggQualityParams);
1632 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregate qualities: algorithm", aggQualityParams);
1633 test_and_set_param_2list<double>(paramList, defaultList, "aggregate qualities: zero threshold", aggQualityParams);
1634 test_and_set_param_2list<Teuchos::Array<double>>(paramList, defaultList, "aggregate qualities: percentiles", aggQualityParams);
1635 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregate qualities: mode", aggQualityParams);
1636 aggQualityFact->SetParameterList(aggQualityParams);
1637 aggQualityFact->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1638 aggQualityFact->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
1639 manager.SetFactory("AggregateQualities", aggQualityFact);
1640
1641 if (!RAP.is_null())
1642 RAP->AddTransferFactory(aggQualityFact);
1643 else
1644 RAPs->AddTransferFactory(aggQualityFact);
1645 }
1646
1647 if (test_param_2list<bool>(paramList, defaultList, "aggregation: export visualization data", true)) {
1648 RCP<AggregationExportFactory> aggExport = rcp(new AggregationExportFactory());
1649 ParameterList aggExportParams;
1650 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregation: output filename", aggExportParams);
1651 test_and_set_param_2list<std::string>(paramList, defaultList, "aggregation: output file: agg style", aggExportParams);
1652 test_and_set_param_2list<int>(paramList, defaultList, "aggregation: output file: iter", aggExportParams);
1653 test_and_set_param_2list<int>(paramList, defaultList, "aggregation: output file: time step", aggExportParams);
1654 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: output file: fine graph edges", aggExportParams);
1655 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: output file: coarse graph edges", aggExportParams);
1656 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: output file: build colormap", aggExportParams);
1657 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: output file: aggregate qualities", aggExportParams);
1658 test_and_set_param_2list<bool>(paramList, defaultList, "aggregation: output file: material", aggExportParams);
1659 aggExport->SetParameterList(aggExportParams);
1660 aggExport->SetFactory("AggregateQualities", manager.GetFactory("AggregateQualities"));
1661 aggExport->SetFactory("DofsPerNode", manager.GetFactory("DofsPerNode"));
1662 aggExport->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1663 aggExport->SetFactory("Graph", manager.GetFactory("Graph"));
1664
1665 if (!RAP.is_null())
1666 RAP->AddTransferFactory(aggExport);
1667 else
1668 RAPs->AddTransferFactory(aggExport);
1669 }
1670 if (!RAP.is_null())
1671 manager.SetFactory("A", RAP);
1672 else
1673 manager.SetFactory("A", RAPs);
1674
1675 auto reuseType = set_var_2list<std::string>(paramList, defaultList, "reuse: type");
1676 auto useFiltering = set_var_2list<bool>(paramList, defaultList, "sa: use filtered matrix");
1677 bool filteringChangesMatrix = useFiltering && !test_param_2list<double>(paramList, defaultList, "aggregation: drop tol", 0);
1678
1679 if (reuseType == "RP" || (reuseType == "tP" && !filteringChangesMatrix)) {
1680 if (!RAP.is_null()) {
1681 keeps.push_back(keep_pair("AP reuse data", RAP.get()));
1682 keeps.push_back(keep_pair("RAP reuse data", RAP.get()));
1683
1684 } else {
1685 keeps.push_back(keep_pair("AP reuse data", RAPs.get()));
1686 keeps.push_back(keep_pair("RAP reuse data", RAPs.get()));
1687 }
1688 }
1689}
1690
1691// =====================================================================================================
1692// ======================================= Coordinates =================================================
1693// =====================================================================================================
1694template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1696 UpdateFactoryManager_Coordinates(ParameterList& paramList, const ParameterList& /* defaultList */,
1697 FactoryManager& manager, int /* levelID */, std::vector<keep_pair>& /* keeps */) const {
1698 bool have_userCO = false;
1699 if (paramList.isParameter("Coordinates") && !paramList.get<RCP<MultiVector>>("Coordinates").is_null())
1700 have_userCO = true;
1701
1702 if (useCoordinates_) {
1703 if (have_userCO) {
1704 manager.SetFactory("Coordinates", NoFactory::getRCP());
1705
1706 } else {
1707 RCP<Factory> coords = rcp(new CoordinatesTransferFactory());
1708 coords->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1709 coords->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
1710 manager.SetFactory("Coordinates", coords);
1711
1712 auto RAP = rcp_const_cast<RAPFactory>(rcp_dynamic_cast<const RAPFactory>(manager.GetFactory("A")));
1713 if (!RAP.is_null()) {
1714 RAP->AddTransferFactory(manager.GetFactory("Coordinates"));
1715 } else {
1716 auto RAPs = rcp_const_cast<RAPShiftFactory>(rcp_dynamic_cast<const RAPShiftFactory>(manager.GetFactory("A")));
1717 RAPs->AddTransferFactory(manager.GetFactory("Coordinates"));
1718 }
1719 }
1720 }
1721}
1722
1723// ======================================================================================================
1724// ======================================== Material ==================================================
1725// =====================================================================================================
1726template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1728 UpdateFactoryManager_Material(ParameterList& paramList, const ParameterList& /* defaultList */,
1729 FactoryManager& manager, int /* levelID */, std::vector<keep_pair>& /* keeps */) const {
1730 bool have_userMaterial = false;
1731 if (paramList.isParameter("Material") && !paramList.get<RCP<MultiVector>>("Material").is_null())
1732 have_userMaterial = true;
1733
1734 if (useMaterial_) {
1735 if (have_userMaterial) {
1736 manager.SetFactory("Material", NoFactory::getRCP());
1737 } else {
1738 RCP<Factory> materialTransfer = rcp(new MultiVectorTransferFactory());
1739 ParameterList materialTransferParameters;
1740 materialTransferParameters.set("Vector name", "Material");
1741 materialTransferParameters.set("Transfer name", "Aggregates");
1742 materialTransferParameters.set("Normalize", true);
1743 materialTransfer->SetParameterList(materialTransferParameters);
1744 materialTransfer->SetFactory("Transfer factory", manager.GetFactory("Aggregates"));
1745 materialTransfer->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
1746 manager.SetFactory("Material", materialTransfer);
1747
1748 auto RAP = rcp_const_cast<RAPFactory>(rcp_dynamic_cast<const RAPFactory>(manager.GetFactory("A")));
1749 if (!RAP.is_null()) {
1750 RAP->AddTransferFactory(manager.GetFactory("Material"));
1751 } else {
1752 auto RAPs = rcp_const_cast<RAPShiftFactory>(rcp_dynamic_cast<const RAPShiftFactory>(manager.GetFactory("A")));
1753 RAPs->AddTransferFactory(manager.GetFactory("Material"));
1754 }
1755 }
1756 }
1757}
1758
1759// =====================================================================================================
1760// ================================= LocalOrdinalTransfer =============================================
1761// =====================================================================================================
1762template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1764 UpdateFactoryManager_LocalOrdinalTransfer(const std::string& VarName, const std::string& multigridAlgo, ParameterList& /*paramList*/, const ParameterList& /* defaultList */,
1765 FactoryManager& manager, int levelID, std::vector<keep_pair>& /* keeps */) const {
1766 // NOTE: You would think this would be levelID > 0, but you'd be wrong, since the FactoryManager is basically
1767 // offset by a level from the things which actually do the work.
1768 if (useBlockNumber_ && (levelID > 0)) {
1769 auto RAP = rcp_const_cast<RAPFactory>(rcp_dynamic_cast<const RAPFactory>(manager.GetFactory("A")));
1770 auto RAPs = rcp_const_cast<RAPShiftFactory>(rcp_dynamic_cast<const RAPShiftFactory>(manager.GetFactory("A")));
1771 if (!RAP.is_null() || !RAPs.is_null()) {
1772 RCP<Factory> fact = rcp(new LocalOrdinalTransferFactory(VarName, multigridAlgo));
1773 if (multigridAlgo == "classical")
1774 fact->SetFactory("P Graph", manager.GetFactory("P Graph"));
1775 else
1776 fact->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1777 fact->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
1778
1779 fact->SetFactory(VarName, this->GetFactoryManager(levelID - 1)->GetFactory(VarName));
1780
1781 manager.SetFactory(VarName, fact);
1782
1783 if (!RAP.is_null())
1784 RAP->AddTransferFactory(manager.GetFactory(VarName));
1785 else
1786 RAPs->AddTransferFactory(manager.GetFactory(VarName));
1787 }
1788 }
1789}
1790
1791// =====================================================================================================
1792// ================================= MatrixTransferFactory ============================================
1793// =====================================================================================================
1794template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1796 UpdateFactoryManager_MatrixTransfer(const std::string& VarName, ParameterList& paramList, const ParameterList& defaultList,
1797 FactoryManager& manager, int levelID, std::vector<keep_pair>& /* keeps */) const {
1798 // NOTE: You would think this would be levelID > 0, but you'd be wrong, since the FactoryManager is basically
1799 // offset by a level from the things which actually do the work.
1800 if (levelID == 0)
1801 manager.SetFactory(VarName, NoFactory::getRCP());
1802 else if (levelID > 0) {
1803 auto Afact = manager.GetFactory("A");
1804 auto RebalAc = rcp_const_cast<RebalanceAcFactory>(rcp_dynamic_cast<const RebalanceAcFactory>(Afact));
1805 RCP<RAPFactory> RAP;
1806 RCP<RAPShiftFactory> RAPs;
1807 if (!RebalAc.is_null()) {
1808 auto Afact2 = RebalAc->GetFactory("A");
1809 RAP = rcp_const_cast<RAPFactory>(rcp_dynamic_cast<const RAPFactory>(Afact2));
1810 RAPs = rcp_const_cast<RAPShiftFactory>(rcp_dynamic_cast<const RAPShiftFactory>(Afact2));
1811 } else {
1812 RAP = rcp_const_cast<RAPFactory>(rcp_dynamic_cast<const RAPFactory>(Afact));
1813 RAPs = rcp_const_cast<RAPShiftFactory>(rcp_dynamic_cast<const RAPShiftFactory>(Afact));
1814 }
1815
1816 if (!RAP.is_null() || !RAPs.is_null()) {
1817 RCP<Factory> mtf = rcp(new MatrixTransferFactory());
1818
1819 ParameterList transferParameters;
1820 transferParameters.set("Matrix name", VarName);
1821 transferParameters.set("transpose: use implicit", this->implicitTranspose_);
1822 mtf->SetParameterList(transferParameters);
1823
1824 if (!RAP.is_null()) {
1825 mtf->SetFactory("P", RAP->GetFactory("P"));
1826 if (!this->implicitTranspose_)
1827 mtf->SetFactory("R", RAP->GetFactory("R"));
1828 RAP->AddTransferFactory(mtf);
1829 } else {
1830 mtf->SetFactory("P", RAPs->GetFactory("P"));
1831 if (!this->implicitTranspose_)
1832 mtf->SetFactory("R", RAPs->GetFactory("R"));
1833 RAPs->AddTransferFactory(mtf);
1834 }
1835
1836 auto enableRepart = set_var_2list<bool>(paramList, defaultList, "repartition: enable");
1837 if (!enableRepart) {
1838 manager.SetFactory(VarName, mtf);
1839 } else {
1840 auto rebalFact = rcp(new RebalanceAcFactory());
1841 Teuchos::ParameterList rebalParams;
1842 rebalParams.set("Matrix name", VarName);
1843 auto useSubCommInPlace = set_var_2list<bool>(paramList, defaultList, "repartition: use subcommunicators in place");
1844 rebalParams.set("repartition: use subcommunicators in place", useSubCommInPlace);
1845 if (useSubCommInPlace) {
1846 auto inPlaceMapFact = manager.GetFactory("InPlaceMap");
1847 rebalFact->SetFactory("InPlaceMap", inPlaceMapFact);
1848 } else {
1849 TEUCHOS_ASSERT(!RebalAc.is_null());
1850 RCP<const FactoryBase> importerFact;
1851 importerFact = RebalAc->GetFactory("Importer");
1852 rebalFact->SetFactory("Importer", importerFact);
1853 RebalAc->AddRebalanceFactory(rebalFact);
1854 }
1855
1856 rebalFact->SetParameterList(rebalParams);
1857 rebalFact->SetFactory("A", mtf);
1858
1859 manager.SetFactory(VarName, rebalFact);
1860 }
1861 }
1862 }
1863}
1864
1865// ======================================================================================================
1866// ====================================== BlockNumber =================================================
1867// =====================================================================================================
1868template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1870 UpdateFactoryManager_BlockNumber(ParameterList& paramList, const ParameterList& defaultList,
1871 FactoryManager& manager, int /*levelID*/, std::vector<keep_pair>& /*keeps*/) const {
1872 if (useBlockNumber_) {
1873 ParameterList myParams;
1874 RCP<Factory> fact = rcp(new InitialBlockNumberFactory());
1875 test_and_set_param_2list<int>(paramList, defaultList, "aggregation: block diagonal: interleaved blocksize", myParams);
1876 fact->SetParameterList(myParams);
1877 manager.SetFactory("BlockNumber", fact);
1878 }
1879}
1880
1881// =====================================================================================================
1882// =========================================== Restriction =============================================
1883// =====================================================================================================
1884template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1886 UpdateFactoryManager_Restriction(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
1887 int /*levelID*/, std::vector<keep_pair>& /* keeps */) const {
1888 auto multigridAlgo = set_var_2list<std::string>(paramList, defaultList, "multigrid algorithm");
1889 bool have_userR = false;
1890 if (paramList.isParameter("R") && !paramList.get<RCP<Matrix>>("R").is_null())
1891 have_userR = true;
1892
1893 // === Restriction ===
1894 RCP<Factory> R;
1895 if (!this->implicitTranspose_) {
1896 auto isSymmetric = set_var_2list<bool>(paramList, defaultList, "problem: symmetric");
1897
1898 if (isSymmetric == false && (multigridAlgo == "unsmoothed" || multigridAlgo == "emin")) {
1899 this->GetOStream(Warnings0) << "Switching \"problem: symmetric\" parameter to symmetric as multigrid algorithm. " << multigridAlgo << " is primarily supposed to be used for symmetric problems.\n\n"
1900 << "Please note: if you are using \"unsmoothed\" transfer operators the \"problem: symmetric\" parameter "
1901 << "has no real mathematical meaning, i.e. you can use it for non-symmetric\n"
1902 << "problems, too. With \"problem: symmetric\"=\"symmetric\" you can use implicit transpose for building "
1903 << "the restriction operators which may drastically reduce the amount of consumed memory." << std::endl;
1904 isSymmetric = true;
1905 }
1906 TEUCHOS_TEST_FOR_EXCEPTION(multigridAlgo == "pg" && isSymmetric == true, Exceptions::RuntimeError,
1907 "Petrov-Galerkin smoothed transfer operators are only allowed for non-symmetric problems: Set \"problem: symmetric\" to false!\n"
1908 "While PG smoothed transfer operators generally would also work for symmetric problems this is an unusual use case. "
1909 "You can use the factory-based xml interface though if you need PG-AMG for symmetric problems.");
1910
1911 if (have_userR) {
1912 manager.SetFactory("R", NoFactory::getRCP());
1913 } else {
1914 if (isSymmetric)
1915 R = rcp(new TransPFactory());
1916 else
1917 R = rcp(new GenericRFactory());
1918
1919 R->SetFactory("P", manager.GetFactory("P"));
1920 manager.SetFactory("R", R);
1921 }
1922
1923 } else {
1924 manager.SetFactory("R", Teuchos::null);
1925 }
1926
1927 // === Restriction: Nullspace Scaling ===
1928 if (paramList.isParameter("restriction: scale nullspace") && paramList.get<bool>("restriction: scale nullspace")) {
1929 RCP<TentativePFactory> tentPFactory = rcp(new TentativePFactory());
1930 Teuchos::ParameterList tentPlist;
1931 tentPlist.set("Nullspace name", "Scaled Nullspace");
1932 tentPFactory->SetParameterList(tentPlist);
1933 tentPFactory->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
1934 tentPFactory->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
1935
1936 if (R.is_null()) R = rcp(new TransPFactory());
1937 R->SetFactory("P", tentPFactory);
1938 }
1939}
1940
1941// =====================================================================================================
1942// ========================================= Repartition ===============================================
1943// =====================================================================================================
1944template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
1946 UpdateFactoryManager_Repartition(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
1947 int levelID, std::vector<keep_pair>& keeps, RCP<Factory>& nullSpaceFactory) const {
1948 // === Repartitioning ===
1949 auto reuseType = set_var_2list<std::string>(paramList, defaultList, "reuse: type");
1950 auto enableRepart = set_var_2list<bool>(paramList, defaultList, "repartition: enable");
1951 if (enableRepart) {
1952#if defined(HAVE_MPI) && (defined(HAVE_MUELU_ZOLTAN) || defined(HAVE_MUELU_ZOLTAN2)) // skip to the end, print warning, and turn off repartitioning if we don't have MPI and Zoltan/Zoltan2
1953 auto enableInPlace = set_var_2list<bool>(paramList, defaultList, "repartition: use subcommunicators in place");
1954 // Short summary of the issue: RebalanceTransferFactory shares ownership
1955 // of "P" with SaPFactory, and therefore, changes the stored version.
1956 // That means that if SaPFactory generated P, and stored it on the level,
1957 // then after rebalancing the value in that storage changed. It goes
1958 // against the concept of factories (I think), that every factory is
1959 // responsible for its own objects, and they are immutable outside.
1960 //
1961 // In reuse, this is what happens: as we reuse Importer across setups,
1962 // the order of factories changes, and coupled with shared ownership
1963 // leads to problems.
1964 // *First setup*
1965 // SaP builds P [and stores it]
1966 // TransP builds R [and stores it]
1967 // RAP builds A [and stores it]
1968 // RebalanceTransfer rebalances P [and changes the P stored by SaP] (*)
1969 // RebalanceTransfer rebalances R
1970 // RebalanceAc rebalances A
1971 // *Second setup* ("RP" reuse)
1972 // RebalanceTransfer rebalances P [which is incorrect due to (*)]
1973 // RebalanceTransfer rebalances R
1974 // RAP builds A [which is incorrect due to (*)]
1975 // RebalanceAc rebalances A [which throws due to map inconsistency]
1976 // ...
1977 // *Second setup* ("tP" reuse)
1978 // SaP builds P [and stores it]
1979 // RebalanceTransfer rebalances P [and changes the P stored by SaP] (**)
1980 // TransP builds R [which is incorrect due to (**)]
1981 // RebalanceTransfer rebalances R
1982 // ...
1983 //
1984 // Couple solutions to this:
1985 // 1. [implemented] Requre "tP" and "PR" reuse to only be used with
1986 // implicit rebalancing.
1987 // 2. Do deep copy of P, and changed domain map and importer there.
1988 // Need to investigate how expensive this is.
1989 TEUCHOS_TEST_FOR_EXCEPTION(this->doPRrebalance_ && (reuseType == "tP" || reuseType == "RP"), Exceptions::InvalidArgument,
1990 "Reuse types \"tP\" and \"PR\" require \"repartition: rebalance P and R\" set to \"false\"");
1991
1992 // TEUCHOS_TEST_FOR_EXCEPTION(aggType == "brick", Exceptions::InvalidArgument,
1993 // "Aggregation type \"brick\" requires \"repartition: enable\" set to \"false\"");
1994
1995 auto partName = set_var_2list<std::string>(paramList, defaultList, "repartition: partitioner");
1996 TEUCHOS_TEST_FOR_EXCEPTION(partName != "zoltan" && partName != "zoltan2", Exceptions::InvalidArgument,
1997 "Invalid partitioner name: \"" << partName << "\". Valid options: \"zoltan\", \"zoltan2\"");
1998
1999#ifndef HAVE_MUELU_ZOLTAN
2000 bool switched = false;
2001 if (partName == "zoltan") {
2002 this->GetOStream(Warnings0) << "Zoltan interface is not available, trying to switch to Zoltan2" << std::endl;
2003 partName = "zoltan2";
2004 switched = true;
2005 }
2006#else
2007#ifndef HAVE_MUELU_ZOLTAN2
2008 bool switched = false;
2009#endif // HAVE_MUELU_ZOLTAN2
2010#endif // HAVE_MUELU_ZOLTAN
2011
2012#ifndef HAVE_MUELU_ZOLTAN2
2013 if (partName == "zoltan2" && !switched) {
2014 this->GetOStream(Warnings0) << "Zoltan2 interface is not available, trying to switch to Zoltan" << std::endl;
2015 partName = "zoltan";
2016 }
2017#endif // HAVE_MUELU_ZOLTAN2
2018
2019 auto nodeRepartitionLevel = set_var_2list<int>(paramList, defaultList, "repartition: node repartition level");
2020
2021 // RepartitionHeuristic
2022 auto repartheurFactory = rcp(new RepartitionHeuristicFactory());
2023 ParameterList repartheurParams;
2024 test_and_set_param_2list<int>(paramList, defaultList, "repartition: node repartition level", repartheurParams);
2025 test_and_set_param_2list<int>(paramList, defaultList, "repartition: start level", repartheurParams);
2026 test_and_set_param_2list<int>(paramList, defaultList, "repartition: min rows per proc", repartheurParams);
2027 test_and_set_param_2list<int>(paramList, defaultList, "repartition: target rows per proc", repartheurParams);
2028 test_and_set_param_2list<int>(paramList, defaultList, "repartition: min rows per thread", repartheurParams);
2029 test_and_set_param_2list<int>(paramList, defaultList, "repartition: target rows per thread", repartheurParams);
2030 test_and_set_param_2list<double>(paramList, defaultList, "repartition: max imbalance", repartheurParams);
2031 test_and_set_param_2list<int>(paramList, defaultList, "repartition: put on single proc", repartheurParams);
2032 repartheurFactory->SetParameterList(repartheurParams);
2033 repartheurFactory->SetFactory("A", manager.GetFactory("A"));
2034 manager.SetFactory("number of partitions", repartheurFactory);
2035 manager.SetFactory("repartition: heuristic target rows per process", repartheurFactory);
2036
2037 // Partitioner
2038 RCP<Factory> partitioner;
2039 if (levelID == nodeRepartitionLevel) {
2040 // partitioner = rcp(new NodePartitionInterface());
2041 partitioner = rcp(new MueLu::NodePartitionInterface<SC, LO, GO, NO>());
2042 ParameterList partParams;
2043 test_and_set_param_2list<int>(paramList, defaultList, "repartition: node id", partParams);
2044 partitioner->SetParameterList(partParams);
2045 partitioner->SetFactory("Node Comm", manager.GetFactory("Node Comm"));
2046 } else if (partName == "zoltan") {
2047#ifdef HAVE_MUELU_ZOLTAN
2048 partitioner = rcp(new ZoltanInterface());
2049 // NOTE: ZoltanInterface ("zoltan") does not support external parameters through ParameterList
2050#else
2051 throw Exceptions::RuntimeError("Zoltan interface is not available");
2052#endif // HAVE_MUELU_ZOLTAN
2053 } else if (partName == "zoltan2") {
2054#ifdef HAVE_MUELU_ZOLTAN2
2055 partitioner = rcp(new Zoltan2Interface());
2056 ParameterList partParams;
2057 RCP<const ParameterList> partpartParams = rcp(new ParameterList(paramList.sublist("repartition: params", false)));
2058 partParams.set("ParameterList", partpartParams);
2059 partitioner->SetParameterList(partParams);
2060 partitioner->SetFactory("repartition: heuristic target rows per process",
2061 manager.GetFactory("repartition: heuristic target rows per process"));
2062#else
2063 throw Exceptions::RuntimeError("Zoltan2 interface is not available");
2064#endif // HAVE_MUELU_ZOLTAN2
2065 }
2066
2067 partitioner->SetFactory("A", manager.GetFactory("A"));
2068 partitioner->SetFactory("number of partitions", manager.GetFactory("number of partitions"));
2069 if (useCoordinates_)
2070 partitioner->SetFactory("Coordinates", manager.GetFactory("Coordinates"));
2071 manager.SetFactory("Partition", partitioner);
2072
2073 // Repartitioner
2074 auto repartFactory = rcp(new RepartitionFactory());
2075 ParameterList repartParams;
2076 test_and_set_param_2list<bool>(paramList, defaultList, "repartition: print partition distribution", repartParams);
2077 test_and_set_param_2list<bool>(paramList, defaultList, "repartition: remap parts", repartParams);
2078 test_and_set_param_2list<int>(paramList, defaultList, "repartition: remap num values", repartParams);
2079 test_and_set_param_2list<bool>(paramList, defaultList, "repartition: save importer", repartParams);
2080 repartFactory->SetParameterList(repartParams);
2081 repartFactory->SetFactory("A", manager.GetFactory("A"));
2082 repartFactory->SetFactory("number of partitions", manager.GetFactory("number of partitions"));
2083 repartFactory->SetFactory("Partition", manager.GetFactory("Partition"));
2084 manager.SetFactory("Importer", repartFactory);
2085 if (reuseType != "none" && reuseType != "S" && levelID)
2086 keeps.push_back(keep_pair("Importer", manager.GetFactory("Importer").get()));
2087
2088 if (enableInPlace) {
2089 // Rebalanced A (in place)
2090 // NOTE: This is for when we want to constrain repartitioning to match some other idea of what's going on.
2091 // The major application is the (1,1) hierarchy in the Maxwell1 preconditioner.
2092 auto newA = rcp(new RebalanceAcFactory());
2093 ParameterList rebAcParams;
2094 test_and_set_param_2list<bool>(paramList, defaultList, "repartition: use subcommunicators", rebAcParams);
2095 test_and_set_param_2list<bool>(paramList, defaultList, "repartition: use subcommunicators in place", rebAcParams);
2096 newA->SetParameterList(rebAcParams);
2097 newA->SetFactory("A", manager.GetFactory("A"));
2098 newA->SetFactory("InPlaceMap", manager.GetFactory("InPlaceMap"));
2099 manager.SetFactory("A", newA);
2100 } else {
2101 // Rebalanced A
2102 auto newA = rcp(new RebalanceAcFactory());
2103 ParameterList rebAcParams;
2104 test_and_set_param_2list<bool>(paramList, defaultList, "repartition: use subcommunicators", rebAcParams);
2105 newA->SetParameterList(rebAcParams);
2106 newA->SetFactory("A", manager.GetFactory("A"));
2107 newA->SetFactory("Importer", manager.GetFactory("Importer"));
2108 manager.SetFactory("A", newA);
2109
2110 // Rebalanced P
2111 auto newP = rcp(new RebalanceTransferFactory());
2112 ParameterList newPparams;
2113 newPparams.set("type", "Interpolation");
2114 if (changedPRrebalance_)
2115 newPparams.set("repartition: rebalance P and R", this->doPRrebalance_);
2116 if (changedPRViaCopyrebalance_)
2117 newPparams.set("repartition: explicit via new copy rebalance P and R", true);
2118 test_and_set_param_2list<bool>(paramList, defaultList, "repartition: use subcommunicators", newPparams);
2119 test_and_set_param_2list<std::string>(paramList, defaultList, "repartition: send type", newPparams);
2120 newP->SetParameterList(newPparams);
2121 newP->SetFactory("Importer", manager.GetFactory("Importer"));
2122 newP->SetFactory("P", manager.GetFactory("P"));
2123 manager.SetFactory("P", newP);
2124 if (!paramList.isParameter("semicoarsen: number of levels"))
2125 newP->SetFactory("Nullspace", manager.GetFactory("Ptent"));
2126 else
2127 newP->SetFactory("Nullspace", manager.GetFactory("P")); // TogglePFactory
2128 if (useCoordinates_) {
2129 newP->SetFactory("Coordinates", manager.GetFactory("Coordinates"));
2130 manager.SetFactory("Coordinates", newP);
2131 }
2132 if (useMaterial_) {
2133 newP->SetFactory("Material", manager.GetFactory("Material"));
2134 manager.SetFactory("Material", newP);
2135 }
2136 if (useBlockNumber_ && (levelID > 0)) {
2137 newP->SetFactory("BlockNumber", manager.GetFactory("BlockNumber"));
2138 manager.SetFactory("BlockNumber", newP);
2139 }
2140
2141 // Rebalanced R
2142 auto newR = rcp(new RebalanceTransferFactory());
2143 ParameterList newRparams;
2144 newRparams.set("type", "Restriction");
2145 test_and_set_param_2list<bool>(paramList, defaultList, "repartition: use subcommunicators", newRparams);
2146 test_and_set_param_2list<std::string>(paramList, defaultList, "repartition: send type", newRparams);
2147 if (changedPRrebalance_)
2148 newRparams.set("repartition: rebalance P and R", this->doPRrebalance_);
2149 if (changedPRViaCopyrebalance_)
2150 newPparams.set("repartition: explicit via new copy rebalance P and R", true);
2151 if (changedImplicitTranspose_)
2152 newRparams.set("transpose: use implicit", this->implicitTranspose_);
2153 newR->SetParameterList(newRparams);
2154 newR->SetFactory("Importer", manager.GetFactory("Importer"));
2155 if (!this->implicitTranspose_) {
2156 newR->SetFactory("R", manager.GetFactory("R"));
2157 manager.SetFactory("R", newR);
2158 }
2159
2160 // NOTE: the role of NullspaceFactory is to provide nullspace on the finest
2161 // level if a user does not do that. For all other levels it simply passes
2162 // nullspace from a real factory to whoever needs it. If we don't use
2163 // repartitioning, that factory is "TentativePFactory"; if we do, it is
2164 // "RebalanceTransferFactory". But we still have to have NullspaceFactory as
2165 // the "Nullspace" of the manager
2166 // NOTE: This really needs to be set on the *NullSpaceFactory*, not manager.get("Nullspace").
2167 ParameterList newNullparams;
2168 test_and_set_param_2list<bool>(paramList, defaultList, "nullspace: calculate rotations", newNullparams);
2169 nullSpaceFactory->SetFactory("Nullspace", newP);
2170 nullSpaceFactory->SetParameterList(newNullparams);
2171 }
2172#else
2173 paramList.set("repartition: enable", false);
2174#ifndef HAVE_MPI
2175 this->GetOStream(Warnings0) << "No repartitioning available for a serial run\n";
2176#else
2177 this->GetOStream(Warnings0) << "Zoltan/Zoltan2 are unavailable for repartitioning\n";
2178#endif // HAVE_MPI
2179#endif // defined(HAVE_MPI) && (defined(HAVE_MUELU_ZOLTAN) || defined(HAVE_MUELU_ZOLTAN2))
2180 }
2181}
2182
2183// =====================================================================================================
2184// ========================================= Low precision transfers ===================================
2185// =====================================================================================================
2186template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2188 UpdateFactoryManager_LowPrecision(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
2189 int /*levelID*/, std::vector<keep_pair>& /*keeps*/) const {
2190 auto enableLowPrecision = set_var_2list<bool>(paramList, defaultList, "transfers: half precision");
2191
2192 if (enableLowPrecision) {
2193 // Low precision P
2194 auto newP = rcp(new LowPrecisionFactory());
2195 ParameterList newPparams;
2196 newPparams.set("matrix key", "P");
2197 newP->SetParameterList(newPparams);
2198 newP->SetFactory("P", manager.GetFactory("P"));
2199 manager.SetFactory("P", newP);
2200
2201 if (!this->implicitTranspose_) {
2202 // Low precision R
2203 auto newR = rcp(new LowPrecisionFactory());
2204 ParameterList newRparams;
2205 newRparams.set("matrix key", "R");
2206 newR->SetParameterList(newRparams);
2207 newR->SetFactory("R", manager.GetFactory("R"));
2208 manager.SetFactory("R", newR);
2209 }
2210 }
2211}
2212
2213// =====================================================================================================
2214// =========================================== Nullspace ===============================================
2215// =====================================================================================================
2216template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2218 UpdateFactoryManager_Nullspace(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
2219 int /* levelID */, std::vector<keep_pair>& /* keeps */, RCP<Factory>& nullSpaceFactory) const {
2220 // Nullspace
2221 RCP<Factory> nullSpace = rcp(new NullspaceFactory());
2222
2223 bool have_userNS = false;
2224 if (paramList.isParameter("Nullspace") && !paramList.get<RCP<MultiVector>>("Nullspace").is_null())
2225 have_userNS = true;
2226
2227 if (!have_userNS) {
2228 ParameterList newNullparams;
2229 test_and_set_param_2list<bool>(paramList, defaultList, "nullspace: calculate rotations", newNullparams);
2230 nullSpace->SetParameterList(newNullparams);
2231 nullSpace->SetFactory("Nullspace", manager.GetFactory("Ptent"));
2232 manager.SetFactory("Nullspace", nullSpace);
2233 }
2234 nullSpaceFactory = nullSpace;
2235
2236 if (paramList.isParameter("restriction: scale nullspace") && paramList.get<bool>("restriction: scale nullspace")) {
2237 RCP<ScaledNullspaceFactory> scaledNSfactory = rcp(new ScaledNullspaceFactory());
2238 scaledNSfactory->SetFactory("Nullspace", nullSpaceFactory);
2239 manager.SetFactory("Scaled Nullspace", scaledNSfactory);
2240 }
2241}
2242
2243// =====================================================================================================
2244// ================================= Algorithm: SemiCoarsening =========================================
2245// =====================================================================================================
2246template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2248 UpdateFactoryManager_SemiCoarsen(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
2249 int /* levelID */, std::vector<keep_pair>& /* keeps */) const {
2250 // === Semi-coarsening ===
2251 RCP<Factory> semicoarsenFactory = Teuchos::null;
2252 if (paramList.isParameter("semicoarsen: number of levels") &&
2253 paramList.get<int>("semicoarsen: number of levels") > 0) {
2254 ParameterList togglePParams;
2255 ParameterList semicoarsenPParams;
2256 ParameterList linedetectionParams;
2257 test_and_set_param_2list<int>(paramList, defaultList, "semicoarsen: number of levels", togglePParams);
2258 test_and_set_param_2list<int>(paramList, defaultList, "semicoarsen: coarsen rate", semicoarsenPParams);
2259 test_and_set_param_2list<bool>(paramList, defaultList, "semicoarsen: piecewise constant", semicoarsenPParams);
2260 test_and_set_param_2list<bool>(paramList, defaultList, "semicoarsen: piecewise linear", semicoarsenPParams);
2261 test_and_set_param_2list<bool>(paramList, defaultList, "semicoarsen: calculate nonsym restriction", semicoarsenPParams);
2262 test_and_set_param_2list<std::string>(paramList, defaultList, "linedetection: orientation", linedetectionParams);
2263 test_and_set_param_2list<int>(paramList, defaultList, "linedetection: num layers", linedetectionParams);
2264
2266 RCP<LineDetectionFactory> linedetectionFactory = rcp(new LineDetectionFactory());
2267 RCP<TogglePFactory> togglePFactory = rcp(new TogglePFactory());
2268
2269 linedetectionFactory->SetParameterList(linedetectionParams);
2270 semicoarsenFactory->SetParameterList(semicoarsenPParams);
2271 togglePFactory->SetParameterList(togglePParams);
2272
2273 togglePFactory->AddCoarseNullspaceFactory(semicoarsenFactory);
2274 togglePFactory->AddProlongatorFactory(semicoarsenFactory);
2275 togglePFactory->AddPtentFactory(semicoarsenFactory);
2276 togglePFactory->AddCoarseNullspaceFactory(manager.GetFactory("Ptent"));
2277 togglePFactory->AddProlongatorFactory(manager.GetFactory("P"));
2278 togglePFactory->AddPtentFactory(manager.GetFactory("Ptent"));
2279
2280 manager.SetFactory("CoarseNumZLayers", linedetectionFactory);
2281 manager.SetFactory("LineDetection_Layers", linedetectionFactory);
2282 manager.SetFactory("LineDetection_VertLineIds", linedetectionFactory);
2283
2284 manager.SetFactory("P", togglePFactory);
2285 manager.SetFactory("Ptent", togglePFactory);
2286 manager.SetFactory("Nullspace", togglePFactory);
2287 }
2288
2289 if (paramList.isParameter("semicoarsen: number of levels") &&
2290 paramList.get<int>("semicoarsen: number of levels") > 0) {
2291 auto tf = rcp(new ToggleCoordinatesTransferFactory());
2292 tf->SetFactory("Chosen P", manager.GetFactory("P"));
2293 tf->AddCoordTransferFactory(semicoarsenFactory);
2294
2295 RCP<Factory> coords = rcp(new CoordinatesTransferFactory());
2296 coords->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
2297 coords->SetFactory("CoarseMap", manager.GetFactory("CoarseMap"));
2298 tf->AddCoordTransferFactory(coords);
2299 manager.SetFactory("Coordinates", tf);
2300 }
2301}
2302
2303// =====================================================================================================
2304// ================================== Algorithm: P-Coarsening ==========================================
2305// =====================================================================================================
2306template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2308 UpdateFactoryManager_PCoarsen(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
2309 int levelID, std::vector<keep_pair>& keeps) const {
2310#if defined(HAVE_MUELU_INTREPID2) && defined(HAVE_MUELU_EXPERIMENTAL)
2311 // This only makes sense to invoke from the default list.
2312 if (defaultList.isParameter("pcoarsen: schedule") && defaultList.isParameter("pcoarsen: element")) {
2313 // P-Coarsening by schedule (new interface)
2314 // NOTE: levelID represents the *coarse* level in this case
2315 auto pcoarsen_schedule = Teuchos::getArrayFromStringParameter<int>(defaultList, "pcoarsen: schedule");
2316 auto pcoarsen_element = defaultList.get<std::string>("pcoarsen: element");
2317
2318 if (levelID >= (int)pcoarsen_schedule.size()) {
2319 // Past the p-coarsening levels, we do Smoothed Aggregation
2320 // NOTE: We should probably consider allowing other options past p-coarsening
2321 std::string multigridAlgo = "SA";
2322 UpdateFactoryManager_SA(multigridAlgo, paramList, defaultList, manager, levelID, keeps);
2323
2324 } else {
2325 // P-Coarsening
2326 ParameterList Pparams;
2327 auto P = rcp(new IntrepidPCoarsenFactory());
2328 std::string lo = pcoarsen_element + std::to_string(pcoarsen_schedule[levelID]);
2329 std::string hi = (levelID ? pcoarsen_element + std::to_string(pcoarsen_schedule[levelID - 1]) : lo);
2330 Pparams.set("pcoarsen: hi basis", hi);
2331 Pparams.set("pcoarsen: lo basis", lo);
2332 P->SetParameterList(Pparams);
2333 manager.SetFactory("P", P);
2334
2335 // Add special nullspace handling
2336 rcp_dynamic_cast<Factory>(manager.GetFactoryNonConst("Nullspace"))->SetFactory("Nullspace", manager.GetFactory("P"));
2337 }
2338
2339 } else {
2340 // P-Coarsening by manual specification (old interface)
2341 ParameterList Pparams;
2342 auto P = rcp(new IntrepidPCoarsenFactory());
2343 test_and_set_param_2list<std::string>(paramList, defaultList, "pcoarsen: hi basis", Pparams);
2344 test_and_set_param_2list<std::string>(paramList, defaultList, "pcoarsen: lo basis", Pparams);
2345 P->SetParameterList(Pparams);
2346 manager.SetFactory("P", P);
2347
2348 // Add special nullspace handling
2349 rcp_dynamic_cast<Factory>(manager.GetFactoryNonConst("Nullspace"))->SetFactory("Nullspace", manager.GetFactory("P"));
2350 }
2351
2352#endif
2353}
2354
2355// =====================================================================================================
2356// ============================== Algorithm: Smoothed Aggregation ======================================
2357// =====================================================================================================
2358template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2360 UpdateFactoryManager_SA(std::string& multigridAlgo, ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager, int levelID, std::vector<keep_pair>& keeps) const {
2361 // Smoothed aggregation
2362 RCP<Factory> P = rcp(new SaPFactory());
2363 ParameterList Pparams;
2364 if (paramList.isSublist("matrixmatrix: kernel params"))
2365 Pparams.sublist("matrixmatrix: kernel params", false) = paramList.sublist("matrixmatrix: kernel params");
2366 if (defaultList.isSublist("matrixmatrix: kernel params"))
2367 Pparams.sublist("matrixmatrix: kernel params", false) = defaultList.sublist("matrixmatrix: kernel params");
2368 test_and_set_param_2list<double>(paramList, defaultList, "sa: damping factor", Pparams);
2369 test_and_set_param_2list<double>(paramList, defaultList, "sa: nodal damping factor", Pparams);
2370 test_and_set_param_2list<bool>(paramList, defaultList, "sa: calculate eigenvalue estimate", Pparams);
2371 test_and_set_param_2list<double>(paramList, defaultList, "sa: max eigenvalue", Pparams);
2372 test_and_set_param_2list<int>(paramList, defaultList, "sa: eigenvalue estimate num iterations", Pparams);
2373 test_and_set_param_2list<double>(paramList, defaultList, "sa: diagonal replacement tolerance", Pparams);
2374 test_and_set_param_2list<bool>(paramList, defaultList, "sa: use rowsumabs diagonal scaling", Pparams);
2375 test_and_set_param_2list<double>(paramList, defaultList, "sa: rowsumabs diagonal replacement tolerance", Pparams);
2376 test_and_set_param_2list<double>(paramList, defaultList, "sa: rowsumabs diagonal replacement value", Pparams);
2377 test_and_set_param_2list<bool>(paramList, defaultList, "sa: rowsumabs use automatic diagonal tolerance", Pparams);
2378 test_and_set_param_2list<bool>(paramList, defaultList, "sa: enforce constraints", Pparams);
2379 // test_and_set_param_2list<std::string>(paramList, defaultList, "sa: eigen-analysis type", Pparams);
2380 test_and_set_param_2list<bool>(paramList, defaultList, "tentative: calculate qr", Pparams);
2381
2382 if ((multigridAlgo == "smoothed reitzinger") && (levelID > 0)) {
2383 Pparams.set("sa: maxwell1 smoothing", true);
2384 if (!Pparams.isType<double>("sa: damping factor") || (Pparams.get<double>("sa: damping factor") != 0.0))
2385 P->SetFactory("CurlCurl", this->GetFactoryManager(levelID - 1)->GetFactory("CurlCurl"));
2386 }
2387
2388 P->SetParameterList(Pparams);
2389
2390 // Filtering
2391 auto useFiltering = set_var_2list<bool>(paramList, defaultList, "sa: use filtered matrix");
2392 if (useFiltering) {
2393 // NOTE: Here, non-Kokkos and Kokkos versions diverge in the way the
2394 // dependency tree is setup. The Kokkos version has merged the the
2395 // FilteredAFactory into the CoalesceDropFactory.
2396 if (!useKokkos_) {
2397 RCP<Factory> filterFactory = rcp(new FilteredAFactory());
2398
2399 ParameterList fParams;
2400 test_and_set_param_2list<bool>(paramList, defaultList, "filtered matrix: use lumping", fParams);
2401 test_and_set_param_2list<bool>(paramList, defaultList, "filtered matrix: reuse graph", fParams);
2402 test_and_set_param_2list<bool>(paramList, defaultList, "filtered matrix: reuse eigenvalue", fParams);
2403 test_and_set_param_2list<bool>(paramList, defaultList, "filtered matrix: use root stencil", fParams);
2404 test_and_set_param_2list<double>(paramList, defaultList, "filtered matrix: Dirichlet threshold", fParams);
2405 test_and_set_param_2list<bool>(paramList, defaultList, "filtered matrix: use spread lumping", fParams);
2406 // test_and_set_param_2list<std::string>(paramList, defaultList, "filtered matrix: lumping choice", fParams);
2407 test_and_set_param_2list<double>(paramList, defaultList, "filtered matrix: spread lumping diag dom growth factor", fParams);
2408 test_and_set_param_2list<double>(paramList, defaultList, "filtered matrix: spread lumping diag dom cap", fParams);
2409 test_and_set_param_2list<bool>(paramList, defaultList, "filtered matrix: count negative diagonals", fParams);
2410 filterFactory->SetParameterList(fParams);
2411 filterFactory->SetFactory("Graph", manager.GetFactory("Graph"));
2412 filterFactory->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
2413 filterFactory->SetFactory("UnAmalgamationInfo", manager.GetFactory("UnAmalgamationInfo"));
2414 // I'm not sure why we need this line. See comments for DofsPerNode for UncoupledAggregation above
2415 filterFactory->SetFactory("Filtering", manager.GetFactory("Graph"));
2416
2417 P->SetFactory("A", filterFactory);
2418
2419 } else {
2420 P->SetFactory("A", manager.GetFactory("Graph"));
2421 }
2422 }
2423
2424 P->SetFactory("P", manager.GetFactory("Ptent"));
2425 manager.SetFactory("P", P);
2426
2427 bool filteringChangesMatrix = useFiltering && !test_param_2list<double>(paramList, defaultList, "aggregation: drop tol", 0);
2428 auto reuseType = set_var_2list<std::string>(paramList, defaultList, "reuse: type");
2429 if (reuseType == "tP" && !filteringChangesMatrix)
2430 keeps.push_back(keep_pair("AP reuse data", P.get()));
2431}
2432
2433// =====================================================================================================
2434// =============================== Algorithm: Energy Minimization ======================================
2435// =====================================================================================================
2436template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2438 UpdateFactoryManager_Emin(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager,
2439 int /* levelID */, std::vector<keep_pair>& /* keeps */) const {
2440 auto patternType = set_var_2list<std::string>(paramList, defaultList, "emin: pattern");
2441 auto reuseType = set_var_2list<std::string>(paramList, defaultList, "reuse: type");
2442 TEUCHOS_TEST_FOR_EXCEPTION(patternType != "AkPtent", Exceptions::InvalidArgument,
2443 "Invalid pattern name: \"" << patternType << "\". Valid options: \"AkPtent\"");
2444 // Pattern
2445 auto patternFactory = rcp(new PatternFactory());
2446 ParameterList patternParams;
2447 test_and_set_param_2list<int>(paramList, defaultList, "emin: pattern order", patternParams);
2448 patternFactory->SetParameterList(patternParams);
2449 patternFactory->SetFactory("P", manager.GetFactory("Ptent"));
2450
2451 // Filtering
2452 auto useFiltering = set_var_2list<bool>(paramList, defaultList, "emin: use filtered matrix");
2453 if (useFiltering) {
2454 // NOTE: Here, non-Kokkos and Kokkos versions diverge in the way the
2455 // dependency tree is setup. The Kokkos version has merged the the
2456 // FilteredAFactory into the CoalesceDropFactory.
2457 if (!useKokkos_) {
2458 RCP<Factory> filterFactory = rcp(new FilteredAFactory());
2459
2460 ParameterList fParams;
2461 test_and_set_param_2list<bool>(paramList, defaultList, "filtered matrix: use lumping", fParams);
2462 test_and_set_param_2list<bool>(paramList, defaultList, "filtered matrix: reuse graph", fParams);
2463 test_and_set_param_2list<bool>(paramList, defaultList, "filtered matrix: reuse eigenvalue", fParams);
2464 test_and_set_param_2list<bool>(paramList, defaultList, "filtered matrix: use root stencil", fParams);
2465 test_and_set_param_2list<double>(paramList, defaultList, "filtered matrix: Dirichlet threshold", fParams);
2466 test_and_set_param_2list<bool>(paramList, defaultList, "filtered matrix: use spread lumping", fParams);
2467 test_and_set_param_2list<std::string>(paramList, defaultList, "filtered matrix: lumping choice", fParams);
2468 test_and_set_param_2list<double>(paramList, defaultList, "filtered matrix: spread lumping diag dom growth factor", fParams);
2469 test_and_set_param_2list<double>(paramList, defaultList, "filtered matrix: spread lumping diag dom cap", fParams);
2470 filterFactory->SetParameterList(fParams);
2471 filterFactory->SetFactory("Graph", manager.GetFactory("Graph"));
2472 filterFactory->SetFactory("Aggregates", manager.GetFactory("Aggregates"));
2473 filterFactory->SetFactory("UnAmalgamationInfo", manager.GetFactory("UnAmalgamationInfo"));
2474 // I'm not sure why we need this line. See comments for DofsPerNode for UncoupledAggregation above
2475 filterFactory->SetFactory("Filtering", manager.GetFactory("Graph"));
2476
2477 patternFactory->SetFactory("A", filterFactory);
2478
2479 } else {
2480 patternFactory->SetFactory("A", manager.GetFactory("Graph"));
2481 }
2482 }
2483
2484 manager.SetFactory("Ppattern", patternFactory);
2485
2486 // Constraint
2487 auto constraintFactory = rcp(new ConstraintFactory());
2488 Teuchos::ParameterList constraintParams;
2489 test_and_set_param_2list<std::string>(paramList, defaultList, "emin: least squares solver type", constraintParams);
2490 constraintParams.set("emin: constraint type", "nullspace");
2491 constraintFactory->SetFactory("Ppattern", manager.GetFactory("Ppattern"));
2492 constraintFactory->SetFactory("CoarseNullspace", manager.GetFactory("Ptent"));
2493 manager.SetFactory("Constraint", constraintFactory);
2494
2495 // Energy minimization
2496 ParameterList Pparams;
2497 test_and_set_param_2list<int>(paramList, defaultList, "emin: num iterations", Pparams);
2498 test_and_set_param_2list<std::string>(paramList, defaultList, "emin: iterative method", Pparams);
2499 if (reuseType == "emin") {
2500 test_and_set_param_2list<int>(paramList, defaultList, "emin: num reuse iterations", Pparams);
2501 Pparams.set("Keep P0", true);
2502 Pparams.set("Keep Constraint0", true);
2503 }
2504
2505 // Emin Factory
2506 auto P = rcp(new EminPFactory());
2507 P->SetParameterList(Pparams);
2508 P->SetFactory("P", manager.GetFactory("Ptent"));
2509 P->SetFactory("Constraint", manager.GetFactory("Constraint"));
2510 manager.SetFactory("P", P);
2511}
2512
2513// =====================================================================================================
2514// ================================= Algorithm: Petrov-Galerkin ========================================
2515// =====================================================================================================
2516template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2518 UpdateFactoryManager_PG(ParameterList& /* paramList */, const ParameterList& /* defaultList */, FactoryManager& manager,
2519 int /* levelID */, std::vector<keep_pair>& /* keeps */) const {
2520 TEUCHOS_TEST_FOR_EXCEPTION(this->implicitTranspose_, Exceptions::RuntimeError,
2521 "Implicit transpose not supported with Petrov-Galerkin smoothed transfer operators: Set \"transpose: use implicit\" to false!\n"
2522 "Petrov-Galerkin transfer operator smoothing for non-symmetric problems requires a separate handling of the restriction operator which "
2523 "does not allow the usage of implicit transpose easily.");
2524
2525 // Petrov-Galerkin
2526 auto P = rcp(new PgPFactory());
2527 P->SetFactory("P", manager.GetFactory("Ptent"));
2528 manager.SetFactory("P", P);
2529}
2530
2531// =====================================================================================================
2532// ================================= Algorithm: Replicate ========================================
2533// =====================================================================================================
2534template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2536 UpdateFactoryManager_Replicate(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager, int /* levelID */, std::vector<keep_pair>& /*keeps*/) const {
2538
2539 ParameterList Pparams;
2540 test_and_set_param_2list<int>(paramList, defaultList, "replicate: npdes", Pparams);
2541
2542 P->SetParameterList(Pparams);
2543 manager.SetFactory("P", P);
2544}
2545
2546// =====================================================================================================
2547// ====================================== Algorithm: Combine ============================================
2548// =====================================================================================================
2549template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2551 UpdateFactoryManager_Combine(ParameterList& paramList, const ParameterList& defaultList, FactoryManager& manager, int /* levelID */, std::vector<keep_pair>& /*keeps*/) const {
2553
2554 ParameterList Pparams;
2555 test_and_set_param_2list<int>(paramList, defaultList, "combine: numBlks", Pparams);
2556 test_and_set_param_2list<bool>(paramList, defaultList, "combine: useMaxLevels", Pparams);
2557
2558 P->SetParameterList(Pparams);
2559 manager.SetFactory("P", P);
2560}
2561
2562// =====================================================================================================
2563// ====================================== Algorithm: Matlab ============================================
2564// =====================================================================================================
2565template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2567 UpdateFactoryManager_Matlab(ParameterList& paramList, const ParameterList& /* defaultList */, FactoryManager& manager,
2568 int /* levelID */, std::vector<keep_pair>& /* keeps */) const {
2569#ifdef HAVE_MUELU_MATLAB
2570 ParameterList Pparams = paramList.sublist("transfer: params");
2571 auto P = rcp(new TwoLevelMatlabFactory());
2572 P->SetParameterList(Pparams);
2573 P->SetFactory("P", manager.GetFactory("Ptent"));
2574 manager.SetFactory("P", P);
2575#else
2576 (void)paramList;
2577 (void)manager;
2578#endif
2579}
2580
2581#undef MUELU_KOKKOS_FACTORY
2582
2583size_t LevenshteinDistance(const char* s, size_t len_s, const char* t, size_t len_t);
2584
2585template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2587 ParameterList paramList = constParamList;
2588 const ParameterList& validList = *MasterList::List();
2589 // Validate up to maxLevels level specific parameter sublists
2590 const int maxLevels = 100;
2591
2592 // Extract level specific list
2593 std::vector<ParameterList> paramLists;
2594 for (int levelID = 0; levelID < maxLevels; levelID++) {
2595 std::string sublistName = "level " + toString(levelID);
2596 if (paramList.isSublist(sublistName)) {
2597 paramLists.push_back(paramList.sublist(sublistName));
2598 // paramLists.back().setName(sublistName);
2599 paramList.remove(sublistName);
2600 }
2601 }
2602 paramLists.push_back(paramList);
2603 // paramLists.back().setName("main");
2604#ifdef HAVE_MUELU_MATLAB
2605 // If Muemex is supported, hide custom level variables from validator by removing them from paramList's sublists
2606 for (size_t i = 0; i < paramLists.size(); i++) {
2607 std::vector<std::string> customVars; // list of names (keys) to be removed from list
2608
2609 for (Teuchos::ParameterList::ConstIterator it = paramLists[i].begin(); it != paramLists[i].end(); it++) {
2610 std::string paramName = paramLists[i].name(it);
2611
2612 if (IsParamMuemexVariable(paramName))
2613 customVars.push_back(paramName);
2614 }
2615
2616 // Remove the keys
2617 for (size_t j = 0; j < customVars.size(); j++)
2618 paramLists[i].remove(customVars[j], false);
2619 }
2620#endif
2621
2622 const int maxDepth = 0;
2623 for (size_t i = 0; i < paramLists.size(); i++) {
2624 // validate every sublist
2625 try {
2626 paramLists[i].validateParameters(validList, maxDepth);
2627
2628 } catch (const Teuchos::Exceptions::InvalidParameterName& e) {
2629 std::string eString = e.what();
2630
2631 // Parse name from: <Error, the parameter {name="smoothe: type",...>
2632 size_t nameStart = eString.find_first_of('"') + 1;
2633 size_t nameEnd = eString.find_first_of('"', nameStart);
2634 std::string name = eString.substr(nameStart, nameEnd - nameStart);
2635
2636 size_t bestScore = 100;
2637 std::string bestName = "";
2638 for (ParameterList::ConstIterator it = validList.begin(); it != validList.end(); it++) {
2639 const std::string& pName = validList.name(it);
2640 this->GetOStream(Runtime1) << "| " << pName;
2641 size_t score = LevenshteinDistance(name.c_str(), name.length(), pName.c_str(), pName.length());
2642 this->GetOStream(Runtime1) << " -> " << score << std::endl;
2643 if (score < bestScore) {
2644 bestScore = score;
2645 bestName = pName;
2646 }
2647 }
2648 if (bestScore < 10 && bestName != "") {
2649 TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameterName,
2650 eString << "The parameter name \"" + name + "\" is not valid. Did you mean \"" + bestName << "\"?\n");
2651
2652 } else {
2653 TEUCHOS_TEST_FOR_EXCEPTION(true, Teuchos::Exceptions::InvalidParameterName,
2654 eString << "The parameter name \"" + name + "\" is not valid.\n");
2655 }
2656 }
2657 }
2658}
2659
2660// =====================================================================================================
2661// ==================================== FACTORY interpreter ============================================
2662// =====================================================================================================
2663template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2665 SetFactoryParameterList(const ParameterList& constParamList) {
2666 // Create a non const copy of the parameter list
2667 // Working with a modifiable list is much much easier than with original one
2668 ParameterList paramList = constParamList;
2669
2670 // Parameter List Parsing:
2671 // ---------
2672 // <ParameterList name="MueLu">
2673 // <ParameterList name="Matrix">
2674 // </ParameterList>
2675 if (paramList.isSublist("Matrix")) {
2676 blockSize_ = paramList.sublist("Matrix").get<int>("PDE equations", MasterList::getDefault<int>("number of equations"));
2677 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)
2678 }
2679
2680 // create new FactoryFactory object if necessary
2681 if (factFact_ == Teuchos::null)
2682 factFact_ = Teuchos::rcp(new FactoryFactory());
2683
2684 // Parameter List Parsing:
2685 // ---------
2686 // <ParameterList name="MueLu">
2687 // <ParameterList name="Factories"> <== call BuildFactoryMap() on this parameter list
2688 // ...
2689 // </ParameterList>
2690 // </ParameterList>
2691 FactoryMap factoryMap;
2692 FactoryManagerMap factoryManagers;
2693 if (paramList.isSublist("Factories"))
2694 this->BuildFactoryMap(paramList.sublist("Factories"), factoryMap, factoryMap, factoryManagers);
2695
2696 // Parameter List Parsing:
2697 // ---------
2698 // <ParameterList name="MueLu">
2699 // <ParameterList name="Hierarchy">
2700 // <Parameter name="verbose" type="string" value="Warnings"/> <== get
2701 // <Parameter name="numDesiredLevel" type="int" value="10"/> <== get
2702 //
2703 // <ParameterList name="firstLevel"> <== parse first args and call BuildFactoryMap() on the rest of this parameter list
2704 // ...
2705 // </ParameterList>
2706 // </ParameterList>
2707 // </ParameterList>
2708 if (paramList.isSublist("Hierarchy")) {
2709 ParameterList hieraList = paramList.sublist("Hierarchy"); // copy because list temporally modified (remove 'id')
2710
2711 // Get hierarchy options
2712 if (hieraList.isParameter("max levels")) {
2713 this->numDesiredLevel_ = hieraList.get<int>("max levels");
2714 hieraList.remove("max levels");
2715 }
2716
2717 if (hieraList.isParameter("coarse: max size")) {
2718 this->maxCoarseSize_ = hieraList.get<int>("coarse: max size");
2719 hieraList.remove("coarse: max size");
2720 }
2721
2722 if (hieraList.isParameter("repartition: rebalance P and R")) {
2723 this->doPRrebalance_ = hieraList.get<bool>("repartition: rebalance P and R");
2724 hieraList.remove("repartition: rebalance P and R");
2725 }
2726
2727 if (hieraList.isParameter("transpose: use implicit")) {
2728 this->implicitTranspose_ = hieraList.get<bool>("transpose: use implicit");
2729 hieraList.remove("transpose: use implicit");
2730 }
2731
2732 if (hieraList.isParameter("fuse prolongation and update")) {
2733 this->fuseProlongationAndUpdate_ = hieraList.get<bool>("fuse prolongation and update");
2734 hieraList.remove("fuse prolongation and update");
2735 }
2736
2737 if (hieraList.isParameter("nullspace: suppress dimension check")) {
2738 this->suppressNullspaceDimensionCheck_ = hieraList.get<bool>("nullspace: suppress dimension check");
2739 hieraList.remove("nullspace: suppress dimension check");
2740 }
2741
2742 if (hieraList.isParameter("number of vectors")) {
2743 this->sizeOfMultiVectors_ = hieraList.get<int>("number of vectors");
2744 hieraList.remove("number of vectors");
2745 }
2746
2747 if (hieraList.isSublist("matvec params"))
2748 this->matvecParams_ = Teuchos::parameterList(hieraList.sublist("matvec params"));
2749
2750 if (hieraList.isParameter("coarse grid correction scaling factor")) {
2751 this->scalingFactor_ = hieraList.get<double>("coarse grid correction scaling factor");
2752 hieraList.remove("coarse grid correction scaling factor");
2753 }
2754
2755 // Translate cycle type parameter
2756 if (hieraList.isParameter("cycle type")) {
2757 std::map<std::string, CycleType> cycleMap;
2758 cycleMap["V"] = VCYCLE;
2759 cycleMap["W"] = WCYCLE;
2760
2761 std::string cycleType = hieraList.get<std::string>("cycle type");
2762 TEUCHOS_TEST_FOR_EXCEPTION(cycleMap.count(cycleType) == 0, Exceptions::RuntimeError, "Invalid cycle type: \"" << cycleType << "\"");
2763 this->Cycle_ = cycleMap[cycleType];
2764 }
2765
2766 if (hieraList.isParameter("W cycle start level")) {
2767 this->WCycleStartLevel_ = hieraList.get<int>("W cycle start level");
2768 }
2769
2770 if (hieraList.isParameter("hierarchy label")) {
2771 this->hierarchyLabel_ = hieraList.get<std::string>("hierarchy label");
2772 }
2773
2774 if (hieraList.isParameter("verbosity")) {
2775 std::string vl = hieraList.get<std::string>("verbosity");
2776 hieraList.remove("verbosity");
2777 this->verbosity_ = toVerbLevel(vl);
2778 }
2779
2780 if (hieraList.isParameter("output filename"))
2781 VerboseObject::SetMueLuOFileStream(hieraList.get<std::string>("output filename"));
2782
2783 if (hieraList.isParameter("dependencyOutputLevel"))
2784 this->graphOutputLevel_ = hieraList.get<int>("dependencyOutputLevel");
2785
2786 // Check for the reuse case
2787 if (hieraList.isParameter("reuse"))
2789
2790 if (hieraList.isSublist("DataToWrite")) {
2791 // TODO We should be able to specify any data. If it exists, write it.
2792 // TODO This would requires something like std::set<dataName, Array<int> >
2793 ParameterList foo = hieraList.sublist("DataToWrite");
2794 std::string dataName = "Matrices";
2795 if (foo.isParameter(dataName))
2796 this->matricesToPrint_["A"] = Teuchos::getArrayFromStringParameter<int>(foo, dataName);
2797 dataName = "Prolongators";
2798 if (foo.isParameter(dataName))
2799 this->matricesToPrint_["P"] = Teuchos::getArrayFromStringParameter<int>(foo, dataName);
2800 dataName = "Restrictors";
2801 if (foo.isParameter(dataName))
2802 this->matricesToPrint_["R"] = Teuchos::getArrayFromStringParameter<int>(foo, dataName);
2803 dataName = "D0";
2804 if (foo.isParameter(dataName))
2805 this->matricesToPrint_["D0"] = Teuchos::getArrayFromStringParameter<int>(foo, dataName);
2806 }
2807
2808 // Get level configuration
2809 for (ParameterList::ConstIterator param = hieraList.begin(); param != hieraList.end(); ++param) {
2810 const std::string& paramName = hieraList.name(param);
2811
2812 if (paramName != "DataToWrite" && hieraList.isSublist(paramName)) {
2813 ParameterList levelList = hieraList.sublist(paramName); // copy because list temporally modified (remove 'id')
2814
2815 int startLevel = 0;
2816 if (levelList.isParameter("startLevel")) {
2817 startLevel = levelList.get<int>("startLevel");
2818 levelList.remove("startLevel");
2819 }
2820 int numDesiredLevel = 1;
2821 if (levelList.isParameter("numDesiredLevel")) {
2822 numDesiredLevel = levelList.get<int>("numDesiredLevel");
2823 levelList.remove("numDesiredLevel");
2824 }
2825
2826 // Parameter List Parsing:
2827 // ---------
2828 // <ParameterList name="firstLevel">
2829 // <Parameter name="startLevel" type="int" value="0"/>
2830 // <Parameter name="numDesiredLevel" type="int" value="1"/>
2831 // <Parameter name="verbose" type="string" value="Warnings"/>
2832 //
2833 // [] <== call BuildFactoryMap() on the rest of the parameter list
2834 //
2835 // </ParameterList>
2836 FactoryMap levelFactoryMap;
2837 BuildFactoryMap(levelList, factoryMap, levelFactoryMap, factoryManagers);
2838
2839 RCP<FactoryManager> m = rcp(new FactoryManager(levelFactoryMap));
2840 if (hieraList.isParameter("use kokkos refactor"))
2841 m->SetKokkosRefactor(hieraList.get<bool>("use kokkos refactor"));
2842
2843 if (startLevel >= 0)
2844 this->AddFactoryManager(startLevel, numDesiredLevel, m);
2845 else
2846 TEUCHOS_TEST_FOR_EXCEPTION(true, Exceptions::RuntimeError, "MueLu::ParameterListInterpreter():: invalid level id");
2847 } /* TODO: else { } */
2848 }
2849 }
2850}
2851
2852// TODO: static?
2886
2938
2975template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
2977 BuildFactoryMap(const ParameterList& paramList, const FactoryMap& factoryMapIn, FactoryMap& factoryMapOut, FactoryManagerMap& factoryManagers) const {
2978 for (ParameterList::ConstIterator param = paramList.begin(); param != paramList.end(); ++param) {
2979 const std::string& paramName = paramList.name(param); //< paramName contains the user chosen factory name (e.g., "smootherFact1")
2980 const Teuchos::ParameterEntry& paramValue = paramList.entry(param); //< for factories, paramValue should be either a list or just a MueLu Factory (e.g., TrilinosSmoother)
2981
2982 // TODO: do not allow name of existing MueLu classes (can be tested using FactoryFactory)
2983
2984 if (paramValue.isList()) {
2985 ParameterList paramList1 = Teuchos::getValue<ParameterList>(paramValue);
2986 if (paramList1.isParameter("factory")) { // default: just a factory definition
2987 // New Factory is a sublist with internal parameters and/or data dependencies
2988 TEUCHOS_TEST_FOR_EXCEPTION(paramList1.isParameter("dependency for") == true, Exceptions::RuntimeError,
2989 "MueLu::ParameterListInterpreter(): It seems that in the parameter lists for defining " << paramName << " there is both a 'factory' and 'dependency for' parameter. This is not allowed. Please remove the 'dependency for' parameter.");
2990
2991 factoryMapOut[paramName] = factFact_->BuildFactory(paramValue, factoryMapIn, factoryManagers);
2992
2993 } else if (paramList1.isParameter("dependency for")) { // add more data dependencies to existing factory
2994 TEUCHOS_TEST_FOR_EXCEPTION(paramList1.isParameter("factory") == true, Exceptions::RuntimeError,
2995 "MueLu::ParameterListInterpreter(): It seems that in the parameter lists for defining " << paramName << " there is both a 'factory' and 'dependency for' parameter. This is not allowed.");
2996
2997 std::string factoryName = paramList1.get<std::string>("dependency for");
2998
2999 RCP<const FactoryBase> factbase = factoryMapIn.find(factoryName /*paramName*/)->second; // access previously defined factory
3000 TEUCHOS_TEST_FOR_EXCEPTION(factbase.is_null() == true, Exceptions::RuntimeError,
3001 "MueLu::ParameterListInterpreter(): could not find factory " + factoryName + " in factory map. Did you define it before?");
3002
3003 RCP<const Factory> factoryconst = Teuchos::rcp_dynamic_cast<const Factory>(factbase);
3004 RCP<Factory> factory = Teuchos::rcp_const_cast<Factory>(factoryconst);
3005
3006 // Read the RCP<Factory> parameters of the class T
3007 RCP<const ParameterList> validParamList = factory->GetValidParameterList();
3008 for (ParameterList::ConstIterator vparam = validParamList->begin(); vparam != validParamList->end(); ++vparam) {
3009 const std::string& pName = validParamList->name(vparam);
3010
3011 if (!paramList1.isParameter(pName)) {
3012 // Ignore unknown parameters
3013 continue;
3014 }
3015
3016 if (validParamList->isType<RCP<const FactoryBase>>(pName)) {
3017 // Generate or get factory described by pName and set dependency
3018 RCP<const FactoryBase> generatingFact = factFact_->BuildFactory(paramList1.getEntry(pName), factoryMapIn, factoryManagers);
3019 factory->SetFactory(pName, generatingFact.create_weak());
3020
3021 } else if (validParamList->isType<RCP<const ParameterList>>(pName)) {
3022 if (pName == "ParameterList") {
3023 // NOTE: we cannot use
3024 // subList = sublist(rcpFromRef(paramList), pName)
3025 // here as that would result in sublist also being a reference to a temporary object.
3026 // The resulting dereferencing in the corresponding factory would then segfault
3027 RCP<const ParameterList> subList = Teuchos::sublist(rcp(new ParameterList(paramList1)), pName);
3028 factory->SetParameter(pName, ParameterEntry(subList));
3029 }
3030 } else {
3031 factory->SetParameter(pName, paramList1.getEntry(pName));
3032 }
3033 }
3034
3035 } else if (paramList1.isParameter("group")) { // definitiion of a factory group (for a factory manager)
3036 // Define a new (sub) FactoryManager
3037 std::string groupType = paramList1.get<std::string>("group");
3038 TEUCHOS_TEST_FOR_EXCEPTION(groupType != "FactoryManager", Exceptions::RuntimeError,
3039 "group must be of type \"FactoryManager\".");
3040
3041 ParameterList groupList = paramList1; // copy because list temporally modified (remove 'id')
3042 groupList.remove("group");
3043
3044 bool setKokkosRefactor = false;
3045 bool kokkosRefactor = useKokkos_;
3046 if (groupList.isParameter("use kokkos refactor")) {
3047 kokkosRefactor = groupList.get<bool>("use kokkos refactor");
3048 groupList.remove("use kokkos refactor");
3049 setKokkosRefactor = true;
3050 }
3051
3052 FactoryMap groupFactoryMap;
3053 BuildFactoryMap(groupList, factoryMapIn, groupFactoryMap, factoryManagers);
3054
3055 // do not store groupFactoryMap in factoryMapOut
3056 // Create a factory manager object from groupFactoryMap
3057 RCP<FactoryManager> m = rcp(new FactoryManager(groupFactoryMap));
3058 if (setKokkosRefactor)
3059 m->SetKokkosRefactor(kokkosRefactor);
3060 factoryManagers[paramName] = m;
3061
3062 } else {
3063 this->GetOStream(Warnings0) << "Could not interpret parameter list " << paramList1 << std::endl;
3064 TEUCHOS_TEST_FOR_EXCEPTION(false, Exceptions::RuntimeError,
3065 "XML Parameter list must either be of type \"factory\" or of type \"group\".");
3066 }
3067 } else {
3068 // default: just a factory (no parameter list)
3069 factoryMapOut[paramName] = factFact_->BuildFactory(paramValue, factoryMapIn, factoryManagers);
3070 }
3071 }
3072}
3073
3074// =====================================================================================================
3075// ======================================= MISC functions ==============================================
3076// =====================================================================================================
3077template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
3079 try {
3080 Matrix& A = dynamic_cast<Matrix&>(Op);
3081 if (A.IsFixedBlockSizeSet() && (A.GetFixedBlockSize() != blockSize_))
3082 this->GetOStream(Warnings0) << "Setting matrix block size to " << blockSize_ << " (value of the parameter in the list) "
3083 << "instead of " << A.GetFixedBlockSize() << " (provided matrix)." << std::endl
3084 << "You may want to check \"number of equations\" (or \"PDE equations\" for factory style list) parameter." << std::endl;
3085
3086 if ((blockSize_ != 1) || (dofOffset_ != 0))
3087 A.SetFixedBlockSize(blockSize_, dofOffset_);
3088
3089 if (Behavior::debug())
3090 MatrixUtils::checkLocalRowMapMatchesColMap(A);
3091
3092 } catch (std::bad_cast&) {
3093 this->GetOStream(Warnings0) << "Skipping setting block size as the operator is not a matrix" << std::endl;
3094 }
3095}
3096
3097template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
3099 H.SetCycle(Cycle_);
3100 H.SetCycleStartLevel(WCycleStartLevel_);
3101 H.SetProlongatorScalingFactor(scalingFactor_);
3102 H.SetLabel(hierarchyLabel_);
3104}
3105
3106static bool compare(const ParameterList& list1, const ParameterList& list2) {
3107 // First loop through and validate the parameters at this level.
3108 // In addition, we generate a list of sublists that we will search next
3109 for (ParameterList::ConstIterator it = list1.begin(); it != list1.end(); it++) {
3110 const std::string& name = it->first;
3111 const Teuchos::ParameterEntry& entry1 = it->second;
3112
3113 const Teuchos::ParameterEntry* entry2 = list2.getEntryPtr(name);
3114 if (!entry2) // entry is not present in the second list
3115 return false;
3116 if (entry1.isList() && entry2->isList()) { // sublist check
3117 compare(Teuchos::getValue<ParameterList>(entry1), Teuchos::getValue<ParameterList>(*entry2));
3118 continue;
3119 }
3120 if (entry1.getAny(false) != entry2->getAny(false)) // entries have different types or different values
3121 return false;
3122 }
3123
3124 return true;
3125}
3126
3127static inline bool areSame(const ParameterList& list1, const ParameterList& list2) {
3128 return compare(list1, list2) && compare(list2, list1);
3129}
3130
3131} // namespace MueLu
3132
3133#define MUELU_PARAMETERLISTINTERPRETER_SHORT
3134#endif /* MUELU_PARAMETERLISTINTERPRETER_DEF_HPP */
#define TEST_MUTUALLY_EXCLUSIVE_S(arg1, arg2)
#define MUELU_KOKKOS_FACTORY_NO_DECL(varName, oldFactory, newFactory)
#define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory)
#define TEST_MUTUALLY_EXCLUSIVE(arg1, arg2)
MueLu::DefaultGlobalOrdinal GlobalOrdinal
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.
static bool debug()
Whether MueLu is in debug mode.
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 creating a graph based on a given matrix.
Factory for generating coarse level map. Used by TentativePFactory.
Prolongator factory that replicates 'Psubblock' matrix to create new prolongator suitable for PDE sys...
Factory for building the constraint operator.
Class for transferring coordinates from a finer level to a coarser one.
Class that encapsulates direct solvers. Autoselection of AmesosSmoother or Amesos2Smoother according ...
Factory for building Energy Minimization prolongators.
Exception throws to report incompatible objects (like maps).
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.
static void EnableTimerSync()
static void DisableMultipleCheckGlobally()
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)
Factory for building filtered matrices using filtered graphs.
Factory for building restriction operators using a prolongator factory.
Provides methods to build a multigrid hierarchy and apply multigrid cycles.
static CycleType GetDefaultCycle()
void SetCycleStartLevel(int cycleStart)
void SetLabel(const std::string &hierarchyLabel)
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.
virtual void SetupHierarchy(Hierarchy &H) const
Setup Hierarchy object.
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,...
Factory for converting matrices to half precision operators.
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.
Class that encapsulates Matlab smoothers.
This class checks matrix properties of A on current level. This factory can be plugged in everywhere ...
Class for restricting a Matrix from a finer to a coarser level.
Class for restricting a MultiVector from a finer to a coarser level.
static const RCP< const NoFactory > getRCP()
Static Get() functions.
Factory for generating nullspace.
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 SetMinvAProjectionVariables(const Teuchos::ParameterList &paramList)
void UpdateFactoryManager_SA(std::string &multigridAlgo, 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_MatrixTransfer(const std::string &VarName, Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void UpdateFactoryManager_EminReitzinger(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
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_Replicate(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
void UpdateFactoryManager_LowPrecision(ParameterList &paramList, const ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
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 UpdateFactoryManager_Material(Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
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_Combine(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
virtual ~ParameterListInterpreter()
Destructor.
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.
Prolongator factory that replicates 'Psubblock' matrix to create new prolongator suitable for PDE sys...
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.
Interface to block smoothers in Teko package.
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.
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)
static bool test_and_set_var(const Teuchos::ParameterList &paramList, const std::string &paramName, paramType &varName)
MsgType toVerbLevel(const std::string &verbLevelStr)
static void test_and_set_param_2list(const Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, const std::string &paramName, Teuchos::ParameterList &listWrite)
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)
static void test_and_set_var_from_masterlist(Teuchos::ParameterList &paramList, const std::string &paramName)
std::string toString(const T &what)
Little helper function to convert non-string types to strings.
static paramType set_var_2list(const Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, const std::string &paramName)
static bool test_param_2list(const Teuchos::ParameterList &paramList, const Teuchos::ParameterList &defaultList, const std::string &paramName, const paramType &cmpValue)