46 #ifndef MUELU_PARAMETERLISTINTERPRETER_DEF_HPP 47 #define MUELU_PARAMETERLISTINTERPRETER_DEF_HPP 49 #include <Teuchos_XMLParameterListHelpers.hpp> 51 #include <Xpetra_Matrix.hpp> 59 #include "MueLu_Hierarchy.hpp" 60 #include "MueLu_FactoryManager.hpp" 62 #include "MueLu_AggregationExportFactory.hpp" 63 #include "MueLu_BrickAggregationFactory.hpp" 64 #include "MueLu_CoalesceDropFactory.hpp" 65 #include "MueLu_CoarseMapFactory.hpp" 66 #include "MueLu_ConstraintFactory.hpp" 67 #include "MueLu_CoordinatesTransferFactory.hpp" 68 #include "MueLu_CoupledAggregationFactory.hpp" 69 #include "MueLu_DirectSolver.hpp" 70 #include "MueLu_EminPFactory.hpp" 72 #include "MueLu_FactoryFactory.hpp" 73 #include "MueLu_FilteredAFactory.hpp" 74 #include "MueLu_GenericRFactory.hpp" 75 #include "MueLu_LineDetectionFactory.hpp" 77 #include "MueLu_NullspaceFactory.hpp" 78 #include "MueLu_PatternFactory.hpp" 79 #include "MueLu_PgPFactory.hpp" 80 #include "MueLu_RAPFactory.hpp" 81 #include "MueLu_RebalanceAcFactory.hpp" 82 #include "MueLu_RebalanceTransferFactory.hpp" 83 #include "MueLu_RepartitionFactory.hpp" 84 #include "MueLu_SaPFactory.hpp" 85 #include "MueLu_SemiCoarsenPFactory.hpp" 86 #include "MueLu_SmootherFactory.hpp" 87 #include "MueLu_TentativePFactory.hpp" 88 #include "MueLu_TogglePFactory.hpp" 89 #include "MueLu_ToggleCoordinatesTransferFactory.hpp" 90 #include "MueLu_TransPFactory.hpp" 91 #include "MueLu_UncoupledAggregationFactory.hpp" 92 #include "MueLu_ZoltanInterface.hpp" 93 #include "MueLu_Zoltan2Interface.hpp" 95 #ifdef HAVE_MUELU_KOKKOS_REFACTOR 96 #include "MueLu_SaPFactory_kokkos.hpp" 97 #include "MueLu_CoalesceDropFactory_kokkos.hpp" 100 #ifdef HAVE_MUELU_MATLAB 101 #include "../matlab/src/MueLu_MatlabSmoother_decl.hpp" 102 #include "../matlab/src/MueLu_MatlabSmoother_def.hpp" 103 #include "../matlab/src/MueLu_TwoLevelMatlabFactory_decl.hpp" 104 #include "../matlab/src/MueLu_TwoLevelMatlabFactory_def.hpp" 105 #include "../matlab/src/MueLu_SingleLevelMatlabFactory_decl.hpp" 106 #include "../matlab/src/MueLu_SingleLevelMatlabFactory_def.hpp" 115 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
118 if(paramList.isParameter(
"xml parameter file")){
119 std::string filename = paramList.get(
"xml parameter file",
"");
120 if(filename.length()!=0) {
121 if(comm.is_null())
throw Exceptions::RuntimeError(
"xml parameter file requires a valid comm");
122 Teuchos::ParameterList paramList2 = paramList;
123 Teuchos::updateParametersFromXmlFileAndBroadcast(filename, Teuchos::Ptr<Teuchos::ParameterList>(¶mList2),*comm);
124 SetParameterList(paramList2);
127 SetParameterList(paramList);
130 SetParameterList(paramList);
133 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
135 ParameterList paramList;
136 Teuchos::updateParametersFromXmlFileAndBroadcast(xmlFileName, Teuchos::Ptr<ParameterList>(¶mList), comm);
140 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
146 if (paramList.isSublist(
"Hierarchy")) {
151 ParameterList validList, nonSerialList;
163 static inline bool areSame(
const ParameterList& list1,
const ParameterList& list2);
168 #define MUELU_SET_VAR_2LIST(paramList, defaultList, paramName, paramType, varName) \ 170 if (paramList.isParameter(paramName)) varName = paramList.get<paramType>(paramName); \ 171 else if (defaultList.isParameter(paramName)) varName = defaultList.get<paramType>(paramName); \ 172 else varName = MasterList::getDefault<paramType>(paramName); 174 #define MUELU_TEST_AND_SET_VAR(paramList, paramName, paramType, varName) \ 175 (paramList.isParameter(paramName) ? varName = paramList.get<paramType>(paramName), true : false) 179 #define MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, paramName, paramType, listWrite) \ 181 if (paramList .isParameter(paramName)) listWrite.set(paramName, paramList .get<paramType>(paramName)); \ 182 else if (defaultList.isParameter(paramName)) listWrite.set(paramName, defaultList.get<paramType>(paramName)); \ 184 catch(Teuchos::Exceptions::InvalidParameterType) { \ 185 TEUCHOS_TEST_FOR_EXCEPTION_PURE_MSG(true, Teuchos::Exceptions::InvalidParameterType, \ 186 "Error: parameter \"" << paramName << "\" must be of type " << Teuchos::TypeNameTraits<paramType>::name()); \ 189 #define MUELU_TEST_PARAM_2LIST(paramList, defaultList, paramName, paramType, cmpValue) \ 191 paramList.isParameter(paramName) ? paramList .get<paramType>(paramName) : ( \ 192 defaultList.isParameter(paramName) ? defaultList.get<paramType>(paramName) : \ 193 MasterList::getDefault<paramType>(paramName) ) ) ) 195 #ifndef HAVE_MUELU_KOKKOS_REFACTOR 196 #define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory) \ 197 RCP<Factory> varName = rcp(new oldFactory()); 199 #define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory) \ 200 RCP<Factory> varName; \ 201 if (!useKokkos) varName = rcp(new oldFactory()); \ 202 else varName = rcp(new newFactory()); 205 #ifndef HAVE_MUELU_KOKKOS_REFACTOR 206 #define MUELU_KOKKOS_FACTORY_NO_DECL(varName, oldFactory, newFactory) \ 207 varName = rcp(new oldFactory()); 209 #define MUELU_KOKKOS_FACTORY_NO_DECL(varName, oldFactory, newFactory) \ 210 if (!useKokkos) varName = rcp(new oldFactory()); \ 211 else varName = rcp(new newFactory()); 214 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
216 ParameterList paramList;
218 MUELU_SET_VAR_2LIST(constParamList, constParamList,
"problem: type", std::string, problemType);
219 if (problemType !=
"unknown") {
221 paramList.setParameters(constParamList);
225 paramList = constParamList;
229 if (paramList.isParameter(
"cycle type")) {
230 std::map<std::string,CycleType> cycleMap;
234 std::string cycleType = paramList.get<std::string>(
"cycle type");
235 TEUCHOS_TEST_FOR_EXCEPTION(cycleMap.count(cycleType) == 0,
Exceptions::RuntimeError,
"Invalid cycle type: \"" << cycleType <<
"\"");
236 Cycle_ = cycleMap[cycleType];
239 this->
maxCoarseSize_ = paramList.get<
int> (
"coarse: max size", MasterList::getDefault<int>(
"coarse: max size"));
240 this->
numDesiredLevel_ = paramList.get<
int> (
"max levels", MasterList::getDefault<int>(
"max levels"));
241 blockSize_ = paramList.get<
int> (
"number of equations", MasterList::getDefault<int>(
"number of equations"));
246 if (paramList.isSublist(
"export data")) {
247 ParameterList printList = paramList.sublist(
"export data");
249 if (printList.isParameter(
"A"))
250 this->
matricesToPrint_ = Teuchos::getArrayFromStringParameter<int>(printList,
"A");
251 if (printList.isParameter(
"P"))
253 if (printList.isParameter(
"R"))
259 std::map<std::string,MsgType> verbMap;
260 verbMap[
"none"] =
None;
261 verbMap[
"low"] =
Low;
262 verbMap[
"medium"] =
Medium;
263 verbMap[
"high"] =
High;
265 verbMap[
"test"] =
Test;
270 "Invalid verbosity level: \"" << verbosityLevel <<
"\"");
283 MUELU_TEST_PARAM_2LIST(paramList, paramList,
"aggregation: drop scheme", std::string,
"distance laplacian") ||
290 std::string levelStr =
"level " +
toString(levelID);
292 if (paramList.isSublist(levelStr)) {
293 const ParameterList& levelList = paramList.sublist(levelStr);
296 MUELU_TEST_PARAM_2LIST(levelList, paramList,
"aggregation: drop scheme", std::string,
"distance laplacian") ||
317 defaultManager->SetVerbLevel(this->
verbosity_);
320 std::vector<keep_pair> keeps0;
330 RCP<FactoryManager> levelManager = rcp(
new FactoryManager(*defaultManager));
331 levelManager->SetVerbLevel(defaultManager->GetVerbLevel());
333 std::vector<keep_pair> keeps;
334 if (paramList.isSublist(
"level " +
toString(levelID))) {
336 ParameterList& levelList = paramList.sublist(
"level " +
toString(levelID),
true);
340 ParameterList levelList;
344 this->
keep_[levelID] = keeps;
356 ParameterList unusedParamList;
359 for (ParameterList::ConstIterator it = paramList.begin(); it != paramList.end(); it++) {
360 const ParameterEntry& entry = paramList.entry(it);
362 if (!entry.isList() && !entry.isUsed())
363 unusedParamList.setEntry(paramList.name(it), entry);
368 std::string levelStr =
"level " +
toString(levelID);
370 if (paramList.isSublist(levelStr)) {
371 const ParameterList& levelList = paramList.sublist(levelStr);
373 for (ParameterList::ConstIterator itr = levelList.begin(); itr != levelList.end(); ++itr) {
374 const ParameterEntry& entry = levelList.entry(itr);
376 if (!entry.isList() && !entry.isUsed())
377 unusedParamList.sublist(levelStr).setEntry(levelList.name(itr), entry);
382 if (unusedParamList.numParams() > 0) {
383 std::ostringstream unusedParamsStream;
385 unusedParamList.print(unusedParamsStream, indent);
387 this->
GetOStream(
Warnings1) <<
"The following parameters were not used:\n" << unusedParamsStream.str() << std::endl;
393 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
395 const ParameterList& defaultList,
FactoryManager& manager,
int levelID, std::vector<keep_pair>& keeps)
const {
400 if (paramList.numParams() == 0 && defaultList.numParams() > 0)
401 paramList = ParameterList(defaultList);
404 TEUCHOS_TEST_FOR_EXCEPTION(reuseType !=
"none" && reuseType !=
"tP" && reuseType !=
"RP" && reuseType !=
"emin" && reuseType !=
"RAP" && reuseType !=
"full",
407 MUELU_SET_VAR_2LIST(paramList, defaultList,
"multigrid algorithm", std::string, multigridAlgo);
408 TEUCHOS_TEST_FOR_EXCEPTION(multigridAlgo !=
"unsmoothed" && multigridAlgo !=
"sa" && multigridAlgo !=
"pg" && multigridAlgo !=
"emin" && multigridAlgo !=
"matlab",
Exceptions::RuntimeError,
"Unknown \"multigrid algorithm\" value: \"" << multigridAlgo <<
"\". Please consult User's Guide.");
409 #ifndef HAVE_MUELU_MATLAB 410 if(multigridAlgo ==
"matlab")
411 throw std::runtime_error(
"Cannot use matlab for multigrid algorithm - MueLu was not configured with MATLAB support.");
415 if (reuseType ==
"none" || reuseType ==
"RP" || reuseType ==
"RAP") {
418 }
else if (reuseType ==
"tP" && (multigridAlgo !=
"sa" && multigridAlgo !=
"unsmoothed")) {
420 this->
GetOStream(
Warnings0) <<
"Ignoring \"tP\" reuse option as it is only compatible with \"sa\", or \"unsmoothed\" multigrid algorithms" << std::endl;
422 }
else if (reuseType ==
"emin" && multigridAlgo !=
"emin") {
424 this->
GetOStream(
Warnings0) <<
"Ignoring \"emin\" reuse option it is only compatible with \"emin\" multigrid algorithm" << std::endl;
432 bool have_userA =
false, have_userP =
false, have_userR =
false, have_userNS =
false, have_userCO =
false;
433 if (paramList.isParameter(
"A") && !paramList.get<RCP<Matrix> > (
"A") .is_null()) have_userA =
true;
434 if (paramList.isParameter(
"P") && !paramList.get<RCP<Matrix> > (
"P") .is_null()) have_userP =
true;
435 if (paramList.isParameter(
"R") && !paramList.get<RCP<Matrix> > (
"R") .is_null()) have_userR =
true;
436 if (paramList.isParameter(
"Nullspace") && !paramList.get<RCP<MultiVector> >(
"Nullspace") .is_null()) have_userNS =
true;
437 if (paramList.isParameter(
"Coordinates") && !paramList.get<RCP<MultiVector> >(
"Coordinates").is_null()) have_userCO =
true;
441 bool isCustomSmoother =
442 paramList.isParameter(
"smoother: pre or post") ||
443 paramList.isParameter(
"smoother: type") || paramList.isParameter(
"smoother: pre type") || paramList.isParameter(
"smoother: post type") ||
444 paramList.isSublist (
"smoother: params") || paramList.isSublist (
"smoother: pre params") || paramList.isSublist (
"smoother: post params") ||
445 paramList.isParameter(
"smoother: sweeps") || paramList.isParameter(
"smoother: pre sweeps") || paramList.isParameter(
"smoother: post sweeps") ||
446 paramList.isParameter(
"smoother: overlap") || paramList.isParameter(
"smoother: pre overlap") || paramList.isParameter(
"smoother: post overlap");
449 manager.
SetFactory(
"Smoother", Teuchos::null);
451 }
else if (isCustomSmoother) {
455 #define TEST_MUTUALLY_EXCLUSIVE(arg1,arg2) \ 456 TEUCHOS_TEST_FOR_EXCEPTION(paramList.isParameter(#arg1) && paramList.isParameter(#arg2), \ 457 Exceptions::InvalidArgument, "You cannot specify both \""#arg1"\" and \""#arg2"\""); 458 #define TEST_MUTUALLY_EXCLUSIVE_S(arg1,arg2) \ 459 TEUCHOS_TEST_FOR_EXCEPTION(paramList.isSublist(#arg1) && paramList.isSublist(#arg2), \ 460 Exceptions::InvalidArgument, "You cannot specify both \""#arg1"\" and \""#arg2"\""); 470 TEUCHOS_TEST_FOR_EXCEPTION(
PreOrPost ==
"both" && (paramList.isParameter(
"smoother: pre type") != paramList.isParameter(
"smoother: post type")),
475 ParameterList defaultSmootherParams;
476 defaultSmootherParams.set(
"relaxation: type",
"Symmetric Gauss-Seidel");
477 defaultSmootherParams.set(
"relaxation: sweeps", Teuchos::OrdinalTraits<LO>::one());
478 defaultSmootherParams.set(
"relaxation: damping factor", Teuchos::ScalarTraits<Scalar>::one());
480 RCP<SmootherFactory> preSmoother = Teuchos::null, postSmoother = Teuchos::null;
481 std::string preSmootherType, postSmootherType;
482 ParameterList preSmootherParams, postSmootherParams;
484 if (paramList.isParameter(
"smoother: overlap"))
485 overlap = paramList.get<
int>(
"smoother: overlap");
488 if (paramList.isParameter(
"smoother: pre type")) {
489 preSmootherType = paramList.get<std::string>(
"smoother: pre type");
491 MUELU_SET_VAR_2LIST(paramList, defaultList,
"smoother: type", std::string, preSmootherTypeTmp);
492 preSmootherType = preSmootherTypeTmp;
494 if (paramList.isParameter(
"smoother: pre overlap"))
495 overlap = paramList.get<
int>(
"smoother: pre overlap");
497 if (paramList.isSublist(
"smoother: pre params"))
498 preSmootherParams = paramList.sublist(
"smoother: pre params");
499 else if (paramList.isSublist(
"smoother: params"))
500 preSmootherParams = paramList.sublist(
"smoother: params");
501 else if (defaultList.isSublist(
"smoother: params"))
502 preSmootherParams = defaultList.sublist(
"smoother: params");
503 else if (preSmootherType ==
"RELAXATION")
504 preSmootherParams = defaultSmootherParams;
505 #ifdef HAVE_MUELU_MATLAB 506 if(preSmootherType ==
"matlab")
514 if (paramList.isParameter(
"smoother: post type"))
515 postSmootherType = paramList.get<std::string>(
"smoother: post type");
517 MUELU_SET_VAR_2LIST(paramList, defaultList,
"smoother: type", std::string, postSmootherTypeTmp);
518 postSmootherType = postSmootherTypeTmp;
521 if (paramList.isSublist(
"smoother: post params"))
522 postSmootherParams = paramList.sublist(
"smoother: post params");
523 else if (paramList.isSublist(
"smoother: params"))
524 postSmootherParams = paramList.sublist(
"smoother: params");
525 else if (defaultList.isSublist(
"smoother: params"))
526 postSmootherParams = defaultList.sublist(
"smoother: params");
527 else if (postSmootherType ==
"RELAXATION")
528 postSmootherParams = defaultSmootherParams;
529 if (paramList.isParameter(
"smoother: post overlap"))
530 overlap = paramList.get<
int>(
"smoother: post overlap");
532 if (postSmootherType == preSmootherType &&
areSame(preSmootherParams, postSmootherParams))
533 postSmoother = preSmoother;
535 #ifdef HAVE_MUELU_MATLAB 536 if(postSmootherType ==
"matlab")
543 if (preSmoother == postSmoother)
546 manager.
SetFactory(
"PreSmoother", preSmoother);
547 manager.
SetFactory(
"PostSmoother", postSmoother);
550 if ((reuseType ==
"RAP" && levelID) || (reuseType ==
"full")) {
562 bool isCustomCoarseSolver =
563 paramList.isParameter(
"coarse: type") ||
564 paramList.isParameter(
"coarse: params");
566 manager.
SetFactory(
"CoarseSolver", Teuchos::null);
568 }
else if (isCustomCoarseSolver) {
575 if (paramList.isParameter(
"coarse: overlap"))
576 overlap = paramList.get<
int>(
"coarse: overlap");
578 ParameterList coarseParams;
579 if (paramList.isSublist(
"coarse: params"))
580 coarseParams = paramList.sublist(
"coarse: params");
581 else if (defaultList.isSublist(
"coarse: params"))
582 coarseParams = defaultList.sublist(
"coarse: params");
584 RCP<SmootherPrototype> coarseSmoother;
588 if (coarseType ==
"RELAXATION" || coarseType ==
"CHEBYSHEV" ||
589 coarseType ==
"ILUT" || coarseType ==
"ILU" || coarseType ==
"RILUK" || coarseType ==
"SCHWARZ" ||
590 coarseType ==
"Amesos" ||
591 coarseType ==
"LINESMOOTHING_BANDEDRELAXATION" ||
592 coarseType ==
"LINESMOOTHING_BANDED_RELAXATION" ||
593 coarseType ==
"LINESMOOTHING_BANDED RELAXATION")
594 coarseSmoother = rcp(
new TrilinosSmoother(coarseType, coarseParams, overlap));
596 #ifdef HAVE_MUELU_MATLAB 597 if(coarseType ==
"matlab")
601 coarseSmoother = rcp(
new DirectSolver(coarseType, coarseParams));
605 if ((reuseType ==
"RAP" && levelID) || (reuseType ==
"full")) {
614 RCP<Factory> dropFactory;
617 #ifdef HAVE_MUELU_MATLAB 619 ParameterList socParams = paramList.sublist(
"strength-of-connection: params");
620 dropFactory->SetParameterList(socParams);
622 throw std::runtime_error(
"Cannot use MATLAB evolutionary strength-of-connection - MueLu was not configured with MATLAB support.");
626 ParameterList dropParams;
627 dropParams.set(
"lightweight wrap",
true);
631 dropFactory->SetParameterList(dropParams);
637 TEUCHOS_TEST_FOR_EXCEPTION(aggType !=
"uncoupled" && aggType !=
"coupled" && aggType !=
"brick" && aggType !=
"matlab",
639 #ifndef HAVE_MUELU_MATLAB 640 if(aggType ==
"matlab")
641 throw std::runtime_error(
"Cannot use MATLAB aggregation - MueLu was not configured with MATLAB support.");
643 RCP<Factory> aggFactory;
644 if (aggType ==
"uncoupled") {
646 ParameterList aggParams;
657 aggFactory->SetParameterList(aggParams);
659 aggFactory->SetFactory(
"DofsPerNode", manager.
GetFactory(
"Graph"));
660 aggFactory->SetFactory(
"Graph", manager.
GetFactory(
"Graph"));
661 }
else if (aggType ==
"coupled") {
663 aggFactory->SetFactory(
"Graph", manager.
GetFactory(
"Graph"));
664 }
else if (aggType ==
"brick") {
666 ParameterList aggParams;
670 aggFactory->SetParameterList(aggParams);
675 aggFactory->SetFactory(
"Coordinates", this->
GetFactoryManager(levelID-1)->GetFactory(
"Coordinates"));
678 #ifdef HAVE_MUELU_MATLAB 679 else if(aggType ==
"matlab") {
680 ParameterList aggParams = paramList.sublist(
"aggregation: params");
682 aggFactory->SetParameterList(aggParams);
689 coarseMap->SetFactory(
"Aggregates", manager.
GetFactory(
"Aggregates"));
694 Ptent->SetFactory(
"Aggregates", manager.
GetFactory(
"Aggregates"));
695 Ptent->SetFactory(
"CoarseMap", manager.
GetFactory(
"CoarseMap"));
699 if (reuseType ==
"tP") {
707 nullSpace->SetFactory(
"Nullspace", manager.
GetFactory(
"Ptent"));
712 TEUCHOS_TEST_FOR_EXCEPTION(multigridAlgo !=
"unsmoothed" && multigridAlgo !=
"sa" && multigridAlgo !=
"pg" && multigridAlgo !=
"emin" && multigridAlgo !=
"matlab",
Exceptions::RuntimeError,
"Unknown multigrid algorithm: \"" << multigridAlgo <<
"\". Please consult User's Guide.");
713 #ifndef HAVE_MUELU_MATLAB 714 if(multigridAlgo ==
"matlab")
715 throw std::runtime_error(
"Cannot use MATLAB prolongator factory - MueLu was not configured with MATLAB support.");
720 }
else if (multigridAlgo ==
"unsmoothed") {
723 }
else if (multigridAlgo ==
"sa") {
726 ParameterList Pparams;
728 #if REUSE_MATRIX_GRAPHS 729 if (reuseType ==
"tP" &&
MUELU_TEST_PARAM_2LIST(paramList, defaultList,
"sa: use filtered matrix",
bool,
false)) {
732 Pparams.set(
"Keep AP Pattern",
true);
735 P->SetParameterList(Pparams);
740 ParameterList fParams;
744 filterFactory->SetParameterList(fParams);
745 filterFactory->SetFactory(
"Graph", manager.
GetFactory(
"Graph"));
747 filterFactory->SetFactory(
"Filtering", manager.
GetFactory(
"Graph"));
748 P->SetFactory(
"A", filterFactory);
751 P->SetFactory(
"P", manager.
GetFactory(
"Ptent"));
754 }
else if (multigridAlgo ==
"emin") {
757 "Invalid pattern name: \"" << patternType <<
"\". Valid options: \"AkPtent\"");
760 ParameterList patternParams;
762 patternFactory->SetParameterList(patternParams);
763 patternFactory->SetFactory(
"P", manager.
GetFactory(
"Ptent"));
764 manager.
SetFactory(
"Ppattern", patternFactory);
768 constraintFactory->SetFactory(
"Ppattern", manager.
GetFactory(
"Ppattern"));
769 constraintFactory->SetFactory(
"CoarseNullspace", manager.
GetFactory(
"Ptent"));
770 manager.
SetFactory(
"Constraint", constraintFactory);
774 ParameterList Pparams;
777 if (reuseType ==
"emin") {
779 Pparams.set(
"Keep P0",
true);
780 Pparams.set(
"Keep Constraint0",
true);
782 P->SetParameterList(Pparams);
783 P->SetFactory(
"P", manager.
GetFactory(
"Ptent"));
784 P->SetFactory(
"Constraint", manager.
GetFactory(
"Constraint"));
787 }
else if (multigridAlgo ==
"pg") {
789 "Implicit transpose not supported with Petrov-Galerkin smoothed transfer operators: Set \"transpose: use implicit\" to false!\n" \
790 "Petrov-Galerkin transfer operator smoothing for non-symmetric problems requires a separate handling of the restriction operator which " \
791 "does not allow the usage of implicit transpose easily.");
795 P->SetFactory(
"P", manager.
GetFactory(
"Ptent"));
798 #ifdef HAVE_MUELU_MATLAB 799 else if(multigridAlgo ==
"matlab") {
800 ParameterList Pparams = paramList.sublist(
"transfer: params");
802 P->SetParameterList(Pparams);
803 P->SetFactory(
"P",manager.
GetFactory(
"Ptent"));
809 RCP<SemiCoarsenPFactory> semicoarsenFactory = Teuchos::null;
810 if (paramList.isParameter(
"semicoarsen: number of levels") &&
811 paramList.get<
int>(
"semicoarsen: number of levels") > 0) {
813 ParameterList togglePParams;
814 ParameterList semicoarsenPParams;
815 ParameterList linedetectionParams;
825 linedetectionFactory->SetParameterList(linedetectionParams);
826 semicoarsenFactory->SetParameterList(semicoarsenPParams);
827 togglePFactory->SetParameterList(togglePParams);
828 togglePFactory->AddCoarseNullspaceFactory(semicoarsenFactory);
829 togglePFactory->AddProlongatorFactory(semicoarsenFactory);
830 togglePFactory->AddPtentFactory(semicoarsenFactory);
831 togglePFactory->AddCoarseNullspaceFactory(manager.
GetFactory(
"Ptent"));
832 togglePFactory->AddProlongatorFactory(manager.
GetFactory(
"P"));
833 togglePFactory->AddPtentFactory(manager.
GetFactory(
"Ptent"));
835 manager.
SetFactory(
"CoarseNumZLayers", linedetectionFactory);
836 manager.
SetFactory(
"LineDetection_Layers", linedetectionFactory);
837 manager.
SetFactory(
"LineDetection_VertLineIds", linedetectionFactory);
841 manager.
SetFactory(
"Nullspace", togglePFactory);
847 if (isSymmetric ==
false && (multigridAlgo ==
"unsmoothed" || multigridAlgo ==
"emin")) {
848 this->
GetOStream(
Warnings0) <<
"Switching \"problem: symmetric\" parameter to symmetric as multigrid algorithm. " << multigridAlgo <<
" is primarily supposed to be used for symmetric problems." << std::endl << std::endl;
849 this->
GetOStream(
Warnings0) <<
"Please note: if you are using \"unsmoothed\" transfer operators the \"problem: symmetric\" parameter has no real mathematical meaning, i.e. you can use it for non-symmetric" << std::endl;
850 this->
GetOStream(
Warnings0) <<
"problems, too. With \"problem: symmetric\"=\"symmetric\" you can use implicit transpose for building the restriction operators which may drastically reduce the amount of consumed memory." << std::endl;
854 "Petrov-Galerkin smoothed transfer operators are only allowed for non-symmetric problems: Set \"problem: symmetric\" to false!\n" \
855 "While PG smoothed transfer operators generally would also work for symmetric problems this is an unusual use case. " \
856 "You can use the factory-based xml interface though if you need PG-AMG for symmetric problems.");
880 ParameterList RAPparams;
882 #if REUSE_MATRIX_GRAPHS 885 if (reuseType ==
"RP") {
886 RAPparams.set(
"Keep AP Pattern",
true);
887 RAPparams.set(
"Keep RAP Pattern",
true);
890 RAP->SetParameterList(RAPparams);
891 RAP->SetFactory(
"P", manager.
GetFactory(
"P"));
893 RAP->SetFactory(
"R", manager.
GetFactory(
"R"));
894 if (
MUELU_TEST_PARAM_2LIST(paramList, defaultList,
"aggregation: export visualization data",
bool,
true)) {
896 ParameterList aggExportParams;
904 aggExport->SetParameterList(aggExportParams);
905 aggExport->SetFactory(
"DofsPerNode", manager.
GetFactory(
"DofsPerNode"));
906 RAP->AddTransferFactory(aggExport);
918 coords->SetFactory(
"Aggregates", manager.
GetFactory(
"Aggregates"));
919 coords->SetFactory(
"CoarseMap", manager.
GetFactory(
"CoarseMap"));
922 if (paramList.isParameter(
"semicoarsen: number of levels")) {
924 tf->SetFactory(
"Chosen P", manager.
GetFactory(
"P"));
925 tf->AddCoordTransferFactory(semicoarsenFactory);
926 tf->AddCoordTransferFactory(coords);
930 RAP->AddTransferFactory(manager.
GetFactory(
"Coordinates"));
934 if (reuseType ==
"RP" || reuseType ==
"RAP" || reuseType ==
"full")
937 if (reuseType ==
"RP") {
942 if ((reuseType ==
"tP" || reuseType ==
"RP" || reuseType ==
"emin") &&
useCoordinates_)
985 "Reuse types \"tP\" and \"PR\" require \"repartition: rebalance P and R\" set to \"false\"");
988 "Aggregation type \"brick\" requires \"repartition: enable\" set to \"false\"");
990 MUELU_SET_VAR_2LIST(paramList, defaultList,
"repartition: partitioner", std::string, partName);
992 "Invalid partitioner name: \"" << partName <<
"\". Valid options: \"zoltan\", \"zoltan2\"");
994 RCP<Factory> partitioner;
995 if (partName ==
"zoltan") {
996 #ifdef HAVE_MUELU_ZOLTAN 1002 }
else if (partName ==
"zoltan2") {
1003 #ifdef HAVE_MUELU_ZOLTAN2 1005 ParameterList partParams;
1006 RCP<const ParameterList> partpartParams = rcp(
new ParameterList(paramList.sublist(
"repartition: params",
false)));
1007 partParams.set(
"ParameterList", partpartParams);
1008 partitioner->SetParameterList(partParams);
1013 partitioner->SetFactory(
"A", manager.
GetFactory(
"A"));
1014 partitioner->SetFactory(
"Coordinates", manager.
GetFactory(
"Coordinates"));
1015 manager.
SetFactory(
"Partition", partitioner);
1019 ParameterList repartParams;
1027 repartFactory->SetParameterList(repartParams);
1028 repartFactory->SetFactory(
"A", manager.
GetFactory(
"A"));
1029 repartFactory->SetFactory(
"Partition", manager.
GetFactory(
"Partition"));
1030 manager.
SetFactory(
"Importer", repartFactory);
1031 if (reuseType !=
"none")
1036 ParameterList rebAcParams;
1038 newA->SetParameterList(rebAcParams);
1039 newA->SetFactory(
"A", manager.
GetFactory(
"A"));
1040 newA->SetFactory(
"Importer", manager.
GetFactory(
"Importer"));
1045 ParameterList newPparams;
1046 newPparams.set(
"type",
"Interpolation");
1048 newPparams.set(
"repartition: rebalance P and R", this->
doPRrebalance_);
1051 newP-> SetFactory(
"Importer", manager.
GetFactory(
"Importer"));
1052 newP-> SetFactory(
"P", manager.
GetFactory(
"P"));
1053 if (!paramList.isParameter(
"semicoarsen: number of levels"))
1054 newP-> SetFactory(
"Nullspace", manager.
GetFactory(
"Ptent"));
1056 newP-> SetFactory(
"Nullspace", manager.
GetFactory(
"P"));
1057 newP-> SetFactory(
"Coordinates", manager.
GetFactory(
"Coordinates"));
1063 ParameterList newRparams;
1064 newRparams.set(
"type",
"Restriction");
1067 newRparams.set(
"repartition: rebalance P and R", this->
doPRrebalance_);
1071 newR-> SetFactory(
"Importer", manager.
GetFactory(
"Importer"));
1073 newR->SetFactory(
"R", manager.
GetFactory(
"R"));
1083 nullSpace->SetFactory(
"Nullspace", newP);
1088 if (reuseType ==
"RAP" || reuseType ==
"full") {
1095 #undef MUELU_SET_VAR_2LIST 1096 #undef MUELU_TEST_AND_SET_VAR 1097 #undef MUELU_TEST_AND_SET_PARAM_2LIST 1098 #undef MUELU_TEST_PARAM_2LIST 1102 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1104 ParameterList paramList = constParamList;
1107 const int maxLevels = 100;
1110 std::vector<ParameterList> paramLists;
1111 for (
int levelID = 0; levelID < maxLevels; levelID++) {
1112 std::string sublistName =
"level " +
toString(levelID);
1113 if (paramList.isSublist(sublistName)) {
1114 paramLists.push_back(paramList.sublist(sublistName));
1116 paramList.remove(sublistName);
1119 paramLists.push_back(paramList);
1122 #ifdef HAVE_MUELU_MATLAB 1123 for(
size_t i = 0; i < paramLists.size(); i++)
1125 std::vector<std::string> customVars;
1126 for(Teuchos::ParameterList::ConstIterator it = paramLists[i].begin(); it != paramLists[i].end(); it++)
1128 std::string paramName = paramLists[i].name(it);
1130 customVars.push_back(paramName);
1133 for(
size_t j = 0; j < customVars.size(); j++)
1135 paramLists[i].remove(customVars[j],
false);
1139 const int maxDepth = 0;
1140 for (
size_t i = 0; i < paramLists.size(); i++)
1145 paramLists[i].validateParameters(validList, maxDepth);
1147 catch (
const Teuchos::Exceptions::InvalidParameterName& e)
1149 std::string eString = e.what();
1152 size_t nameStart = eString.find_first_of(
'"') + 1;
1153 size_t nameEnd = eString.find_first_of(
'"', nameStart);
1154 std::string name = eString.substr(nameStart, nameEnd - nameStart);
1156 int bestScore = 100;
1157 std::string bestName =
"";
1158 for (ParameterList::ConstIterator it = validList.begin(); it != validList.end(); it++)
1160 const std::string& pName = validList.name(it);
1162 int score =
LevenshteinDistance(name.c_str(), name.length(), pName.c_str(), pName.length());
1164 if (score < bestScore)
1170 if (bestScore < 10 && bestName !=
"")
1172 TEUCHOS_TEST_FOR_EXCEPTION(
true, Teuchos::Exceptions::InvalidParameterName, eString <<
"The parameter name \"" + name +
"\" is not valid. Did you mean \"" + bestName <<
"\"?\n");
1176 TEUCHOS_TEST_FOR_EXCEPTION(
true, Teuchos::Exceptions::InvalidParameterName, eString <<
"The parameter name \"" + name +
"\" is not valid.\n");
1185 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1189 ParameterList paramList = constParamList;
1196 if (paramList.isSublist(
"Matrix")) {
1197 blockSize_ = paramList.sublist(
"Matrix").get<
int>(
"number of equations", MasterList::getDefault<int>(
"number of equations"));
1198 dofOffset_ = paramList.sublist(
"Matrix").get<GlobalOrdinal>(
"DOF offset", 0);
1214 if (paramList.isSublist(
"Factories"))
1215 this->
BuildFactoryMap(paramList.sublist(
"Factories"), factoryMap, factoryMap, factoryManagers);
1229 if (paramList.isSublist(
"Hierarchy")) {
1230 ParameterList hieraList = paramList.sublist(
"Hierarchy");
1233 if (hieraList.isParameter(
"max levels")) {
1235 hieraList.remove(
"max levels");
1238 if (hieraList.isParameter(
"coarse: max size")) {
1240 hieraList.remove(
"coarse: max size");
1243 if (hieraList.isParameter(
"repartition: rebalance P and R")) {
1244 this->
doPRrebalance_ = hieraList.get<
bool>(
"repartition: rebalance P and R");
1245 hieraList.remove(
"repartition: rebalance P and R");
1248 if (hieraList.isParameter(
"transpose: use implicit")) {
1250 hieraList.remove(
"transpose: use implicit");
1254 std::map<std::string,MsgType> verbMap;
1256 verbMap[
"Errors"] =
Errors;
1273 verbMap[
"Debug"] =
Debug;
1274 verbMap[
"Test"] =
Test;
1276 verbMap[
"None"] =
None;
1277 verbMap[
"Low"] =
Low;
1278 verbMap[
"Medium"] =
Medium;
1279 verbMap[
"High"] =
High;
1281 if (hieraList.isParameter(
"verbosity")) {
1282 std::string vl = hieraList.get<std::string>(
"verbosity");
1283 hieraList.remove(
"verbosity");
1285 if (verbMap.find(vl) != verbMap.end())
1288 TEUCHOS_TEST_FOR_EXCEPTION(
true,
Exceptions::RuntimeError,
"MueLu::ParameterListInterpreter():: invalid verbosity level");
1291 if (hieraList.isParameter(
"dependencyOutputLevel"))
1295 if (hieraList.isParameter(
"reuse"))
1298 if (hieraList.isSublist(
"DataToWrite")) {
1301 ParameterList foo = hieraList.sublist(
"DataToWrite");
1302 std::string dataName =
"Matrices";
1303 if (foo.isParameter(dataName))
1304 this->
matricesToPrint_ = Teuchos::getArrayFromStringParameter<int>(foo,dataName);
1305 dataName =
"Prolongators";
1306 if (foo.isParameter(dataName))
1308 dataName =
"Restrictors";
1309 if (foo.isParameter(dataName))
1314 for (ParameterList::ConstIterator param = hieraList.begin(); param != hieraList.end(); ++param) {
1315 const std::string & paramName = hieraList.name(param);
1317 if (paramName !=
"DataToWrite" && hieraList.isSublist(paramName)) {
1318 ParameterList levelList = hieraList.sublist(paramName);
1320 int startLevel = 0;
if(levelList.isParameter(
"startLevel")) { startLevel = levelList.get<
int>(
"startLevel"); levelList.remove(
"startLevel"); }
1321 int numDesiredLevel = 1;
if(levelList.isParameter(
"numDesiredLevel")) { numDesiredLevel = levelList.get<
int>(
"numDesiredLevel"); levelList.remove(
"numDesiredLevel"); }
1334 BuildFactoryMap(levelList, factoryMap, levelFactoryMap, factoryManagers);
1336 RCP<FactoryManagerBase> m = rcp(
new FactoryManager(levelFactoryMap));
1338 if (startLevel >= 0)
1341 TEUCHOS_TEST_FOR_EXCEPTION(
true,
Exceptions::RuntimeError,
"MueLu::ParameterListInterpreter():: invalid level id");
1360 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1363 for (ParameterList::ConstIterator param = paramList.begin(); param != paramList.end(); ++param) {
1364 const std::string & paramName = paramList.name(param);
1365 const Teuchos::ParameterEntry & paramValue = paramList.entry(param);
1372 if (paramValue.isList()) {
1373 ParameterList paramList1 = Teuchos::getValue<ParameterList>(paramValue);
1374 if (paramList1.isParameter(
"factory")) {
1375 factoryMapOut[paramName] =
factFact_->BuildFactory(paramValue, factoryMapIn, factoryManagers);
1377 }
else if (paramList1.isParameter(
"group")) {
1378 std::string groupType = paramList1.get<std::string>(
"group");
1379 TEUCHOS_TEST_FOR_EXCEPTION(groupType!=
"FactoryManager",
Exceptions::RuntimeError,
"group must be of type \"FactoryManager\".");
1381 ParameterList groupList = paramList1;
1382 groupList.remove(
"group");
1385 BuildFactoryMap(groupList, factoryMapIn, groupFactoryMap, factoryManagers);
1389 RCP<FactoryManagerBase> m = rcp(
new FactoryManager(groupFactoryMap));
1391 factoryManagers[paramName] = m;
1394 this->
GetOStream(
Warnings0) <<
"Could not interpret parameter list " << paramList1 << std::endl;
1395 TEUCHOS_TEST_FOR_EXCEPTION(
false,
Exceptions::RuntimeError,
"XML Parameter list must either be of type \"factory\" or of type \"group\".");
1399 factoryMapOut[paramName] =
factFact_->BuildFactory(paramValue, factoryMapIn, factoryManagers);
1407 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1410 Matrix& A =
dynamic_cast<Matrix&
>(Op);
1413 <<
"instead of " << A.GetFixedBlockSize() <<
" (provided matrix)." << std::endl;
1417 }
catch (std::bad_cast& e) {
1418 this->
GetOStream(
Warnings0) <<
"Skipping setting block size as the operator is not a matrix" << std::endl;
1422 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1429 static bool compare(
const ParameterList& list1,
const ParameterList& list2) {
1432 for (ParameterList::ConstIterator it = list1.begin(); it != list1.end(); it++) {
1433 const std::string& name = it->first;
1434 const Teuchos::ParameterEntry& entry1 = it->second;
1436 const Teuchos::ParameterEntry *entry2 = list2.getEntryPtr(name);
1439 if (entry1.isList() && entry2->isList()) {
1440 compare(Teuchos::getValue<ParameterList>(entry1), Teuchos::getValue<ParameterList>(*entry2));
1443 if (entry1.getAny(
false) != entry2->getAny(
false))
1449 static inline bool areSame(
const ParameterList& list1,
const ParameterList& list2) {
1455 #define MUELU_PARAMETERLISTINTERPRETER_SHORT Important warning messages (one line)
Generic Smoother Factory for generating the smoothers of the MG hierarchy.
This class specifies the default factory that should generate some data on a Level if the data does n...
Teuchos::Array< int > matricesToPrint_
void SetupHierarchy(Hierarchy &H) const
Call the SetupHierarchy routine from the HiearchyManager object.
High level timing information (use Teuchos::TimeMonitor::summarize() to print)
#define MUELU_KOKKOS_FACTORY_NO_DECL(varName, oldFactory, newFactory)
Factory for generating coarse level map. Used by TentativePFactory.
bool changedPRrebalance_
Easy interpreter stuff.
std::string toString(const T &what)
Little helper function to convert non-string types to strings.
void SetVerbLevel(const VerbLevel verbLevel)
Set the verbosity level of this object.
void UpdateFactoryManager(Teuchos::ParameterList ¶mList, const Teuchos::ParameterList &defaultList, FactoryManager &manager, int levelID, std::vector< keep_pair > &keeps) const
Factory that can generate other factories from.
int LevenshteinDistance(const char *s, size_t len_s, const char *t, size_t len_t)
Print external lib objects.
Class that encapsulates external library smoothers.
static void DisableMultipleCheckGlobally()
#define MUELU_TEST_AND_SET_VAR(paramList, paramName, paramType, varName)
Factory for building permutation matrix that can be be used to shuffle data (matrices, vectors) among processes.
Print additional debugging information.
void AddFactoryManager(int startLevel, int numDesiredLevel, RCP< FactoryManagerBase > manager)
One-liner description of what is happening.
void SetCycle(CycleType Cycle)
Supports VCYCLE and WCYCLE types.
Namespace for MueLu classes and methods.
#define MUELU_KOKKOS_FACTORY(varName, oldFactory, newFactory)
Interface to Zoltan library.
bool IsParamMuemexVariable(const std::string &name)
const RCP< const FactoryBase > GetFactory(const std::string &varName) const
Get factory associated with a particular data name.
std::map< std::string, RCP< FactoryManagerBase > > FactoryManagerMap
std::map< std::string, RCP< const FactoryBase > > FactoryMap
Print skeleton for the run, i.e. factory calls and used parameters.
Factory for building tentative prolongator.
#define TEST_MUTUALLY_EXCLUSIVE(arg1, arg2)
Class that encapsulates direct solvers. Autoselection of AmesosSmoother or Amesos2Smoother according ...
Factory for coarsening a graph with uncoupled aggregation.
virtual void SetupOperator(Operator &A) const
Setup Operator object.
Prolongator factory performing semi-coarsening.
Factory for building restriction operators using a prolongator factory.
int blockSize_
block size of matrix (fixed block size)
Important warning messages (more verbose)
Print statistics that do not involve significant additional computation.
Teuchos::RCP< FactoryFactory > factFact_
Internal factory for factories.
#define MUELU_TEST_AND_SET_PARAM_2LIST(paramList, defaultList, paramName, paramType, listWrite)
static bool compare(const ParameterList &list1, const ParameterList &list2)
static CycleType GetDefaultCycle()
Detailed timing information (use Teuchos::TimeMonitor::summarize() to print)
Factory for interacting with Matlab.
Factory for interacting with Matlab.
Factory for building line detection information.
bool changedImplicitTranspose_
void SetFactoryParameterList(const Teuchos::ParameterList ¶mList)
Factory interpreter stuff.
std::pair< std::string, const FactoryBase * > keep_pair
Factory to export aggregation info or visualize aggregates using VTK.
Interface to Zoltan2 library.
Prolongator factory which allows switching between two different prolongator strategies.
By default, enabled timers appears in the teuchos time monitor summary. Use this option if you do not...
RCP< FactoryManagerBase > GetFactoryManager(int levelID) const
Factory for building the constraint operator.
ParameterListInterpreter(Teuchos::ParameterList ¶mList, Teuchos::RCP< const Teuchos::Comm< int > > comm=Teuchos::null, Teuchos::RCP< FactoryFactory > factFact=Teuchos::null)
Constructor that accepts a user-provided ParameterList.
Applies permutation to grid transfer operators.
void SetFactory(const std::string &varName, const RCP< const FactoryBase > &factory)
Set Factory.
Teuchos::FancyOStream & GetOStream(MsgType type, int thisProcRankOnly=0) const
Get an output stream for outputting the input message type.
Timers that are enabled (using Timings0/Timings1) will be printed during the execution.
GlobalOrdinal dofOffset_
global offset variable describing offset of DOFs in operator
Record timing information level by level. Must be used in combinaison with Timings0/Timings1.
Factory for creating a graph base on a given matrix.
Teuchos::Array< int > prolongatorsToPrint_
void BuildFactoryMap(const Teuchos::ParameterList ¶mList, const FactoryMap &factoryMapIn, FactoryMap &factoryMapOut, FactoryManagerMap &factoryManagers) const
Class that encapsulates Matlab smoothers.
void SetParameterList(const Teuchos::ParameterList ¶mList)
Set parameter list for Parameter list interpreter.
Class for transferring coordinates from a finer level to a coarser one.
Factory for building nonzero patterns for energy minimization.
static Teuchos::RCP< Teuchos::ParameterList > GetProblemSpecificList(std::string const &problemType)
Return default parameter settings for the specified problem type.
Class for transferring coordinates from a finer level to a coarser one.
Factory for building restriction operators.
Factory for building Energy Minimization prolongators.
static bool areSame(const ParameterList &list1, const ParameterList &list2)
Helper functions to compare two paramter lists.
std::map< int, std::vector< keep_pair > > keep_
#define TEST_MUTUALLY_EXCLUSIVE_S(arg1, arg2)
void Validate(const Teuchos::ParameterList ¶mList) const
#define MUELU_TEST_PARAM_2LIST(paramList, defaultList, paramName, paramType, cmpValue)
Print class parameters (more parameters, more verbose)
Factory for building coarse matrices.
Exception throws to report errors in the internal logical of the program.
Factory for building filtered matrices using filtered graphs.
std::pair< std::string, const FactoryBase * > keep_pair
Description of what is happening (more verbose)
Factory for building coarse matrices.
Factory for building Petrov-Galerkin Smoothed Aggregation prolongators.
Factory for building Smoothed Aggregation prolongators.Input/output of SaPFactory
Xpetra::global_size_t maxCoarseSize_
Factory for building uncoupled aggregates.
static Teuchos::RCP< const Teuchos::ParameterList > List()
Return a "master" list of all valid parameters and their default values.
#define MUELU_SET_VAR_2LIST(paramList, defaultList, paramName, paramType, varName)
Teuchos::Array< int > restrictorsToPrint_
void SetEasyParameterList(const Teuchos::ParameterList ¶mList)
Provides methods to build a multigrid hierarchy and apply multigrid cycles.
Factory for generating nullspace.
long ExtractNonSerializableData(const Teuchos::ParameterList &inList, Teuchos::ParameterList &serialList, Teuchos::ParameterList &nonSerialList)
virtual void SetupHierarchy(Hierarchy &H) const
Setup Hierarchy object.
Exception throws to report invalid user entry.
static const RCP< const NoFactory > getRCP()
Static Get() functions.
CycleType Cycle_
multigrid cycle type (V-cycle or W-cycle)