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