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