10 #ifndef MUELU_COALESCEDROPFACTORY_KOKKOS_DEF_HPP
11 #define MUELU_COALESCEDROPFACTORY_KOKKOS_DEF_HPP
13 #include <Kokkos_Core.hpp>
14 #include <KokkosSparse_CrsMatrix.hpp>
22 #include "MueLu_AmalgamationInfo.hpp"
25 #include "MueLu_LWGraph_kokkos.hpp"
40 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
44 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
65 SET_VALID_ENTRY(
"filtered matrix: spread lumping diag dom growth factor");
69 #undef SET_VALID_ENTRY
70 validParamList->
set<
bool>(
"lightweight wrap",
true,
"Experimental option for lightweight graph access");
73 validParamList->
getEntry(
"aggregation: drop scheme").
setValidator(
rcp(
new Teuchos::StringValidator(Teuchos::tuple<std::string>(
"signed classical sa",
"classical",
"distance laplacian",
"signed classical",
"block diagonal",
"block diagonal classical",
"block diagonal distance laplacian",
"block diagonal signed classical",
"block diagonal colored signed classical"))));
79 validParamList->
set<
RCP<const FactoryBase>>(
"UnAmalgamationInfo", Teuchos::null,
"Generating factory for UnAmalgamationInfo");
84 return validParamList;
87 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
89 Input(currentLevel,
"A");
90 Input(currentLevel,
"UnAmalgamationInfo");
93 std::string algo = pL.
get<std::string>(
"aggregation: drop scheme");
94 std::string distLaplMetric = pL.
get<std::string>(
"aggregation: distance laplacian metric");
95 if (algo ==
"distance laplacian" || algo ==
"block diagonal distance laplacian") {
96 Input(currentLevel,
"Coordinates");
97 if (distLaplMetric ==
"material")
98 Input(currentLevel,
"Material");
100 if (algo ==
"signed classical sa")
102 else if (algo.find(
"block diagonal") != std::string::npos || algo.find(
"signed classical") != std::string::npos) {
103 Input(currentLevel,
"BlockNumber");
107 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
110 auto A = Get<RCP<Matrix>>(currentLevel,
"A");
112 LO blkSize = A->GetFixedBlockSize() / A->GetStorageBlockSize();
114 std::tuple<GlobalOrdinal, boundary_nodes_type> results;
116 results = BuildScalar(currentLevel);
118 results = BuildVector(currentLevel);
122 auto boundaryNodes = std::get<1>(results);
124 GO numLocalBoundaryNodes = 0;
125 GO numGlobalBoundaryNodes = 0;
127 Kokkos::parallel_reduce(
128 "MueLu:CoalesceDropF:Build:bnd",
range_type(0, boundaryNodes.extent(0)),
129 KOKKOS_LAMBDA(
const LO i,
GO& n) {
130 if (boundaryNodes(i))
133 numLocalBoundaryNodes);
135 auto comm = A->getRowMap()->getComm();
136 MueLu_sumAll(comm, numLocalBoundaryNodes, numGlobalBoundaryNodes);
138 GO numGlobalTotal = A->getGlobalNumEntries();
142 GetOStream(
Statistics1) <<
"Detected " << numGlobalBoundaryNodes <<
" Dirichlet nodes" << std::endl;
143 if (numGlobalTotal != 0) {
144 GetOStream(
Statistics1) <<
"Number of dropped entries: "
145 << numGlobalDropped <<
"/" << numGlobalTotal
146 <<
" (" << 100 * Teuchos::as<double>(numGlobalDropped) / Teuchos::as<double>(numGlobalTotal) <<
"%)" << std::endl;
151 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
152 std::tuple<Teuchos::RCP<Xpetra::Vector<LocalOrdinal, LocalOrdinal, GlobalOrdinal, Node>>,
Teuchos::RCP<Xpetra::Vector<LocalOrdinal, LocalOrdinal, GlobalOrdinal, Node>>>
CoalesceDropFactory_kokkos<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
156 GetOStream(
Statistics1) <<
"Using BlockDiagonal Graph before dropping (with provided blocking)" << std::endl;
159 auto A = Get<RCP<Matrix>>(currentLevel,
"A");
161 if (!importer.is_null()) {
164 ghostedBlockNumber->doImport(*BlockNumber, *importer,
Xpetra::INSERT);
166 ghostedBlockNumber = BlockNumber;
168 return std::make_tuple(BlockNumber, ghostedBlockNumber);
171 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
178 using local_matrix_type =
typename MatrixType::local_matrix_type;
179 using local_graph_type =
typename GraphType::local_graph_type;
180 using rowptr_type =
typename local_graph_type::row_map_type::non_const_type;
181 using entries_type =
typename local_graph_type::entries_type::non_const_type;
182 using values_type =
typename local_matrix_type::values_type::non_const_type;
183 using device_type =
typename Node::device_type;
184 using memory_space =
typename device_type::memory_space;
187 typedef typename STS::magnitudeType MT;
190 auto A = Get<RCP<Matrix>>(currentLevel,
"A");
197 const typename STS::magnitudeType dirichletThreshold = STS::magnitude(as<SC>(pL.get<
double>(
"aggregation: Dirichlet threshold")));
198 const typename STS::magnitudeType rowSumTol = as<typename STS::magnitudeType>(pL.get<
double>(
"aggregation: row sum drop tol"));
202 const std::string algo = pL.get<std::string>(
"aggregation: drop scheme");
203 std::string classicalAlgoStr = pL.get<std::string>(
"aggregation: classical algo");
204 std::string distanceLaplacianAlgoStr = pL.get<std::string>(
"aggregation: distance laplacian algo");
205 std::string distanceLaplacianMetric = pL.get<std::string>(
"aggregation: distance laplacian metric");
208 if (pL.get<
bool>(
"aggregation: use ml scaling of drop tol"))
209 threshold = pL.get<
double>(
"aggregation: drop tol") / pow(2.0, currentLevel.GetLevelID());
211 threshold = as<MT>(pL.get<
double>(
"aggregation: drop tol"));
212 bool aggregationMayCreateDirichlet = pL.get<
bool>(
"aggregation: dropping may create Dirichlet");
215 const bool lumping = pL.get<
bool>(
"filtered matrix: use lumping");
216 const bool reuseGraph = pL.get<
bool>(
"filtered matrix: reuse graph");
217 const bool reuseEigenvalue = pL.get<
bool>(
"filtered matrix: reuse eigenvalue");
219 const bool useRootStencil = pL.get<
bool>(
"filtered matrix: use root stencil");
220 const bool useSpreadLumping = pL.get<
bool>(
"filtered matrix: use spread lumping");
222 const MT filteringDirichletThreshold = as<MT>(pL.get<
double>(
"filtered matrix: Dirichlet threshold"));
226 if (algo ==
"classical")
227 GetOStream(
Runtime0) <<
"algorithm = \"" << algo <<
"\" classical algorithm = \"" << classicalAlgoStr <<
"\": threshold = " << threshold <<
", blocksize = " << A->GetFixedBlockSize() << std::endl;
228 else if (algo ==
"distance laplacian")
229 GetOStream(
Runtime0) <<
"algorithm = \"" << algo <<
"\" distance laplacian algorithm = \"" << distanceLaplacianAlgoStr <<
"\" distance laplacian metric = \"" << distanceLaplacianMetric <<
"\": threshold = " << threshold <<
", blocksize = " << A->GetFixedBlockSize() << std::endl;
231 GetOStream(
Runtime0) <<
"algorithm = \"" << algo <<
"\": threshold = " << threshold <<
", blocksize = " << A->GetFixedBlockSize() << std::endl;
233 if (((algo ==
"classical") && (classicalAlgoStr.find(
"scaled") != std::string::npos)) || ((algo ==
"distance laplacian") && (distanceLaplacianAlgoStr.find(
"scaled") != std::string::npos)))
237 if (algo ==
"distance laplacian")
238 aggregationMayCreateDirichlet =
true;
251 auto crsA = toCrsMatrix(A);
252 auto lclA = crsA->getLocalMatrixDevice();
270 #define MueLu_runBoundaryFunctors(...) \
272 auto boundaries = BoundaryDetection::BoundaryFunctor(lclA, __VA_ARGS__); \
273 Kokkos::parallel_for("CoalesceDrop::BoundaryDetection", range, boundaries); \
278 if (rowSumTol <= 0.) {
285 #undef MueLu_runBoundaryFunctors
317 auto filtered_rowptr = rowptr_type(
"filtered_rowptr", lclA.numRows() + 1);
321 auto results = Kokkos::View<DecisionType*, memory_space>(
"results", lclA.nnz());
325 std::string functorLabel =
"MueLu::CoalesceDrop::CountEntries";
328 #if !defined(HAVE_MUELU_DEBUG)
329 #define MueLu_runDroppingFunctors(...) \
331 auto countingFunctor = MatrixConstruction::PointwiseCountingFunctor(lclA, results, filtered_rowptr, __VA_ARGS__); \
332 Kokkos::parallel_scan(functorLabel, range, countingFunctor, nnz_filtered); \
335 #define MueLu_runDroppingFunctors(...) \
337 auto debug = Misc::DebugFunctor(lclA, results); \
338 auto countingFunctor = MatrixConstruction::PointwiseCountingFunctor(lclA, results, filtered_rowptr, __VA_ARGS__, debug); \
339 Kokkos::parallel_scan(functorLabel, range, countingFunctor, nnz_filtered); \
345 if (threshold != zero) {
349 if (algo ==
"classical" || algo ==
"block diagonal classical") {
350 if (algo ==
"block diagonal classical") {
351 auto BlockNumbers = GetBlockNumberMVs(currentLevel);
354 if (classicalAlgoStr ==
"default") {
357 if (aggregationMayCreateDirichlet) {
362 mark_singletons_as_boundary);
369 }
else if (classicalAlgoStr ==
"unscaled cut") {
377 }
else if (classicalAlgoStr ==
"scaled cut") {
385 }
else if (classicalAlgoStr ==
"scaled cut symmetric") {
402 if (classicalAlgoStr ==
"default") {
405 if (aggregationMayCreateDirichlet) {
409 mark_singletons_as_boundary);
415 }
else if (classicalAlgoStr ==
"unscaled cut") {
422 }
else if (classicalAlgoStr ==
"scaled cut") {
429 }
else if (classicalAlgoStr ==
"scaled cut symmetric") {
445 }
else if (algo ==
"signed classical" || algo ==
"block diagonal signed classical" || algo ==
"block diagonal colored signed classical") {
448 if (algo ==
"block diagonal signed classical" || algo ==
"block diagonal colored signed classical") {
449 auto BlockNumbers = GetBlockNumberMVs(currentLevel);
452 if (classicalAlgoStr ==
"default") {
453 if (aggregationMayCreateDirichlet) {
455 signed_classical_rs_dropping,
458 mark_singletons_as_boundary);
462 signed_classical_rs_dropping,
470 if (classicalAlgoStr ==
"default") {
471 if (aggregationMayCreateDirichlet) {
475 mark_singletons_as_boundary);
486 }
else if (algo ==
"signed classical sa") {
487 if (classicalAlgoStr ==
"default") {
490 if (aggregationMayCreateDirichlet) {
494 mark_singletons_as_boundary);
504 }
else if (algo ==
"distance laplacian" || algo ==
"block diagonal distance laplacian") {
506 auto coords = Get<RCP<doubleMultiVector>>(currentLevel,
"Coordinates");
508 if (algo ==
"block diagonal distance laplacian") {
509 auto BlockNumbers = GetBlockNumberMVs(currentLevel);
514 if (distanceLaplacianAlgoStr ==
"default") {
517 if (aggregationMayCreateDirichlet) {
519 dist_laplacian_dropping,
522 mark_singletons_as_boundary);
525 dist_laplacian_dropping,
529 }
else if (distanceLaplacianAlgoStr ==
"unscaled cut") {
537 }
else if (distanceLaplacianAlgoStr ==
"scaled cut") {
545 }
else if (distanceLaplacianAlgoStr ==
"scaled cut symmetric") {
561 if (distanceLaplacianAlgoStr ==
"default") {
562 if (distanceLaplacianMetric ==
"unweighted") {
566 if (aggregationMayCreateDirichlet) {
570 mark_singletons_as_boundary);
576 }
else if (distanceLaplacianMetric ==
"material") {
577 auto material = Get<RCP<MultiVector>>(currentLevel,
"Material");
578 if (material->getNumVectors() == 1) {
579 GetOStream(
Runtime0) <<
"material scalar mean = " << material->getVector(0)->meanValue() << std::endl;
584 if (aggregationMayCreateDirichlet) {
588 mark_singletons_as_boundary);
598 std::stringstream ss;
599 ss <<
"material tensor mean =" << std::endl;
601 for (
size_t i = 0; i < coords->getNumVectors(); ++i) {
603 for (
size_t j = 0; j < coords->getNumVectors(); ++j) {
604 ss << material->getVector(k)->meanValue() <<
" ";
615 if (aggregationMayCreateDirichlet) {
619 mark_singletons_as_boundary);
628 }
else if (distanceLaplacianAlgoStr ==
"unscaled cut") {
629 if (distanceLaplacianMetric ==
"unweighted") {
637 }
else if (distanceLaplacianMetric ==
"material") {
638 auto material = Get<RCP<MultiVector>>(currentLevel,
"Material");
639 if (material->getNumVectors() == 1) {
640 GetOStream(
Runtime0) <<
"material scalar mean = " << material->getVector(0)->meanValue() << std::endl;
653 std::stringstream ss;
654 ss <<
"material tensor mean =" << std::endl;
656 for (
size_t i = 0; i < coords->getNumVectors(); ++i) {
658 for (
size_t j = 0; j < coords->getNumVectors(); ++j) {
659 ss << material->getVector(k)->meanValue() <<
" ";
676 }
else if (distanceLaplacianAlgoStr ==
"scaled cut") {
677 if (distanceLaplacianMetric ==
"unweighted") {
685 }
else if (distanceLaplacianMetric ==
"material") {
686 auto material = Get<RCP<MultiVector>>(currentLevel,
"Material");
687 if (material->getNumVectors() == 1) {
688 GetOStream(
Runtime0) <<
"material scalar mean = " << material->getVector(0)->meanValue() << std::endl;
701 std::stringstream ss;
702 ss <<
"material tensor mean =" << std::endl;
704 for (
size_t i = 0; i < coords->getNumVectors(); ++i) {
706 for (
size_t j = 0; j < coords->getNumVectors(); ++j) {
707 ss << material->getVector(k)->meanValue() <<
" ";
724 }
else if (distanceLaplacianAlgoStr ==
"scaled cut symmetric") {
725 if (distanceLaplacianMetric ==
"unweighted") {
733 }
else if (distanceLaplacianMetric ==
"material") {
734 auto material = Get<RCP<MultiVector>>(currentLevel,
"Material");
735 if (material->getNumVectors() == 1) {
736 GetOStream(
Runtime0) <<
"material scalar mean = " << material->getVector(0)->meanValue() << std::endl;
749 std::stringstream ss;
750 ss <<
"material tensor mean =" << std::endl;
752 for (
size_t i = 0; i < coords->getNumVectors(); ++i) {
754 for (
size_t j = 0; j < coords->getNumVectors(); ++j) {
755 ss << material->getVector(k)->meanValue() <<
" ";
780 }
else if (algo ==
"block diagonal") {
781 auto BlockNumbers = GetBlockNumberMVs(currentLevel);
789 Kokkos::deep_copy(results,
KEEP);
795 #undef MueLu_runDroppingFunctors
797 GO numDropped = lclA.nnz() - nnz_filtered;
810 local_matrix_type lclFilteredA;
811 local_graph_type lclGraph;
813 filteredA = MatrixFactory::BuildCopy(A);
814 lclFilteredA = filteredA->getLocalMatrixDevice();
816 auto colidx = entries_type(
"entries", nnz_filtered);
817 lclGraph = local_graph_type(colidx, filtered_rowptr);
819 auto colidx = entries_type(
"entries", nnz_filtered);
820 auto values = values_type(
"values", nnz_filtered);
821 lclFilteredA = local_matrix_type(
"filteredA",
822 lclA.numRows(), lclA.numCols(),
824 values, filtered_rowptr, colidx);
830 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_lumped_reuse", range, fillFunctor);
833 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_lumped_noreuse", range, fillFunctor);
838 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_unlumped_reuse", range, fillFunctor);
841 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_unlumped_noreuse", range, fillFunctor);
846 filteredA = MatrixFactory::Build(lclFilteredA, A->getRowMap(), A->getColMap(), A->getDomainMap(), A->getRangeMap());
847 filteredA->SetFixedBlockSize(A->GetFixedBlockSize());
849 if (reuseEigenvalue) {
854 filteredA->SetMaxEigenvalueEstimate(A->GetMaxEigenvalueEstimate());
861 lclGraph = filteredA->getCrsGraph()->getLocalGraphDevice();
863 graph =
rcp(
new LWGraph_kokkos(lclGraph, filteredA->getRowMap(), filteredA->getColMap(),
"amalgamated graph of A"));
868 Set(currentLevel,
"DofsPerNode", dofsPerNode);
869 Set(currentLevel,
"Graph", graph);
870 Set(currentLevel,
"A", filteredA);
872 return std::make_tuple(numDropped, boundaryNodes);
875 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
882 using local_matrix_type =
typename MatrixType::local_matrix_type;
883 using local_graph_type =
typename GraphType::local_graph_type;
884 using rowptr_type =
typename local_graph_type::row_map_type::non_const_type;
885 using entries_type =
typename local_graph_type::entries_type::non_const_type;
886 using values_type =
typename local_matrix_type::values_type::non_const_type;
887 using device_type =
typename Node::device_type;
888 using memory_space =
typename device_type::memory_space;
891 typedef typename STS::magnitudeType MT;
894 auto A = Get<RCP<Matrix>>(currentLevel,
"A");
914 LO blkSize = A->GetFixedBlockSize() / A->GetStorageBlockSize();
916 auto amalInfo = Get<RCP<AmalgamationInfo>>(currentLevel,
"UnAmalgamationInfo");
928 Array<LO> rowTranslationArray = *(amalInfo->getRowTranslation());
929 Array<LO> colTranslationArray = *(amalInfo->getColTranslation());
931 Kokkos::View<LO*, Kokkos::MemoryUnmanaged>
932 rowTranslationView(rowTranslationArray.
getRawPtr(), rowTranslationArray.
size());
933 Kokkos::View<LO*, Kokkos::MemoryUnmanaged>
934 colTranslationView(colTranslationArray.
getRawPtr(), colTranslationArray.
size());
937 LO numNodes = Teuchos::as<LocalOrdinal>(uniqueMap->getLocalNumElements());
938 typedef typename Kokkos::View<LocalOrdinal*, typename Node::device_type> id_translation_type;
939 id_translation_type rowTranslation(
"dofId2nodeId", rowTranslationArray.
size());
940 id_translation_type colTranslation(
"ov_dofId2nodeId", colTranslationArray.
size());
941 Kokkos::deep_copy(rowTranslation, rowTranslationView);
942 Kokkos::deep_copy(colTranslation, colTranslationView);
945 blkSize = A->GetFixedBlockSize();
948 if (A->IsView(
"stridedMaps") ==
true) {
952 blkSize = Teuchos::as<const LocalOrdinal>(strMap->getFixedBlockSize());
953 blkId = strMap->getStridedBlockId();
955 blkPartSize = Teuchos::as<LocalOrdinal>(strMap->getStridingData()[blkId]);
965 const typename STS::magnitudeType dirichletThreshold = STS::magnitude(as<SC>(pL.get<
double>(
"aggregation: Dirichlet threshold")));
966 const typename STS::magnitudeType rowSumTol = as<typename STS::magnitudeType>(pL.get<
double>(
"aggregation: row sum drop tol"));
968 const bool useGreedyDirichlet = pL.get<
bool>(
"aggregation: greedy Dirichlet");
972 const std::string algo = pL.get<std::string>(
"aggregation: drop scheme");
973 std::string classicalAlgoStr = pL.get<std::string>(
"aggregation: classical algo");
974 std::string distanceLaplacianAlgoStr = pL.get<std::string>(
"aggregation: distance laplacian algo");
975 std::string distanceLaplacianMetric = pL.get<std::string>(
"aggregation: distance laplacian metric");
978 if (pL.get<
bool>(
"aggregation: use ml scaling of drop tol"))
979 threshold = pL.get<
double>(
"aggregation: drop tol") / pow(2.0, currentLevel.GetLevelID());
981 threshold = as<MT>(pL.get<
double>(
"aggregation: drop tol"));
982 bool aggregationMayCreateDirichlet = pL.get<
bool>(
"aggregation: dropping may create Dirichlet");
985 const bool lumping = pL.get<
bool>(
"filtered matrix: use lumping");
986 const bool reuseGraph = pL.get<
bool>(
"filtered matrix: reuse graph");
987 const bool reuseEigenvalue = pL.get<
bool>(
"filtered matrix: reuse eigenvalue");
989 const bool useRootStencil = pL.get<
bool>(
"filtered matrix: use root stencil");
990 const bool useSpreadLumping = pL.get<
bool>(
"filtered matrix: use spread lumping");
992 const MT filteringDirichletThreshold = as<MT>(pL.get<
double>(
"filtered matrix: Dirichlet threshold"));
997 if (algo ==
"classical") {
998 GetOStream(
Runtime0) <<
"algorithm = \"" << algo <<
"\" classical algorithm = \"" << classicalAlgoStr <<
"\": threshold = " << threshold <<
", blocksize = " << A->GetFixedBlockSize() << std::endl;
999 }
else if (algo ==
"distance laplacian") {
1000 GetOStream(
Runtime0) <<
"algorithm = \"" << algo <<
"\" distance laplacian algorithm = \"" << distanceLaplacianAlgoStr <<
"\" distance laplacian metric = \"" << distanceLaplacianMetric <<
"\": threshold = " << threshold <<
", blocksize = " << A->GetFixedBlockSize() << std::endl;
1002 GetOStream(
Runtime0) <<
"algorithm = \"" << algo <<
"\": threshold = " << threshold <<
", blocksize = " << A->GetFixedBlockSize() << std::endl;
1005 if (algo ==
"distance laplacian")
1006 aggregationMayCreateDirichlet =
true;
1019 auto crsA = toCrsMatrix(A);
1020 auto lclA = crsA->getLocalMatrixDevice();
1035 #define MueLu_runBoundaryFunctors(...) \
1037 auto boundaries = BoundaryDetection::BoundaryFunctor(lclA, __VA_ARGS__); \
1038 Kokkos::parallel_for("CoalesceDrop::BoundaryDetection", range, boundaries); \
1041 if (useGreedyDirichlet) {
1048 #undef MueLu_runBoundaryFunctors
1076 auto filtered_rowptr = rowptr_type(
"rowptr", lclA.numRows() + 1);
1077 auto graph_rowptr = rowptr_type(
"rowptr", numNodes + 1);
1079 Kokkos::pair<LocalOrdinal, LocalOrdinal> nnz = {0, 0};
1082 auto results = Kokkos::View<DecisionType*, memory_space>(
"results", lclA.nnz());
1086 std::string functorLabel =
"MueLu::CoalesceDrop::CountEntries";
1088 #if !defined(HAVE_MUELU_DEBUG)
1089 #define MueLu_runDroppingFunctors(...) \
1091 auto countingFunctor = MatrixConstruction::VectorCountingFunctor(lclA, blkPartSize, colTranslation, results, filtered_rowptr, graph_rowptr, __VA_ARGS__); \
1092 Kokkos::parallel_scan(functorLabel, range, countingFunctor, nnz); \
1095 #define MueLu_runDroppingFunctors(...) \
1097 auto debug = Misc::DebugFunctor(lclA, results); \
1098 auto countingFunctor = MatrixConstruction::VectorCountingFunctor(lclA, blkPartSize, colTranslation, results, filtered_rowptr, graph_rowptr, __VA_ARGS__, debug); \
1099 Kokkos::parallel_scan(functorLabel, range, countingFunctor, nnz); \
1105 if (threshold != zero) {
1109 if (algo ==
"classical") {
1110 if (classicalAlgoStr ==
"default") {
1113 if (aggregationMayCreateDirichlet) {
1117 mark_singletons_as_boundary);
1121 preserve_diagonals);
1123 }
else if (classicalAlgoStr ==
"unscaled cut") {
1125 }
else if (classicalAlgoStr ==
"scaled cut") {
1127 }
else if (classicalAlgoStr ==
"scaled cut symmetric") {
1130 TEUCHOS_TEST_FOR_EXCEPTION(
true,
Exceptions::RuntimeError,
"\"aggregation: classical algo\" must be one of (default|unscaled cut|scaled cut|scaled cut symmetric), not \"" << classicalAlgoStr <<
"\"");
1132 }
else if (algo ==
"signed classical" || algo ==
"block diagonal colored signed classical" || algo ==
"block diagonal signed classical") {
1135 if (aggregationMayCreateDirichlet) {
1139 mark_singletons_as_boundary);
1144 preserve_diagonals);
1146 }
else if (algo ==
"signed classical sa") {
1149 if (aggregationMayCreateDirichlet) {
1153 mark_singletons_as_boundary);
1158 preserve_diagonals);
1160 }
else if (algo ==
"distance laplacian") {
1162 auto coords = Get<RCP<doubleMultiVector>>(currentLevel,
"Coordinates");
1166 if (distanceLaplacianAlgoStr ==
"default") {
1169 if (aggregationMayCreateDirichlet) {
1173 mark_singletons_as_boundary);
1177 preserve_diagonals);
1179 }
else if (distanceLaplacianAlgoStr ==
"unscaled cut") {
1181 }
else if (distanceLaplacianAlgoStr ==
"scaled cut") {
1183 }
else if (distanceLaplacianAlgoStr ==
"scaled cut symmetric") {
1186 TEUCHOS_TEST_FOR_EXCEPTION(
true,
Exceptions::RuntimeError,
"\"aggregation: distance laplacian algo\" must be one of (default|unscaled cut|scaled cut|scaled cut symmetric), not \"" << distanceLaplacianAlgoStr <<
"\"");
1192 Kokkos::deep_copy(results,
KEEP);
1197 #undef MueLu_runDroppingFunctors
1201 GO numTotal = lclA.nnz();
1202 GO numDropped = numTotal - nnz_filtered;
1215 local_matrix_type lclFilteredA;
1217 lclFilteredA = local_matrix_type(
"filteredA", lclA.graph, lclA.numCols());
1219 auto colidx = entries_type(
"entries", nnz_filtered);
1220 auto values = values_type(
"values", nnz_filtered);
1221 lclFilteredA = local_matrix_type(
"filteredA",
1222 lclA.numRows(), lclA.numCols(),
1224 values, filtered_rowptr, colidx);
1227 local_graph_type lclGraph;
1229 auto colidx = entries_type(
"entries", nnz_graph);
1230 lclGraph = local_graph_type(colidx, graph_rowptr);
1236 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_lumped_reuse", range, fillFunctor);
1239 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_lumped_noreuse", range, fillFunctor);
1244 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_unlumped_reuse", range, fillFunctor);
1247 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_unlumped_noreuse", range, fillFunctor);
1252 filteredA->SetFixedBlockSize(blkSize);
1254 if (reuseEigenvalue) {
1259 filteredA->SetMaxEigenvalueEstimate(A->GetMaxEigenvalueEstimate());
1264 graph =
rcp(
new LWGraph_kokkos(lclGraph, uniqueMap, nonUniqueMap,
"amalgamated graph of A"));
1268 LO dofsPerNode = blkSize;
1270 Set(currentLevel,
"DofsPerNode", dofsPerNode);
1271 Set(currentLevel,
"Graph", graph);
1272 Set(currentLevel,
"A", filteredA);
1274 return std::make_tuple(numDropped, boundaryNodes);
1278 #endif // MUELU_COALESCEDROPFACTORY_KOKKOS_DEF_HPP
Drops entries the unscaled distance Laplacian.
#define MueLu_sumAll(rcpComm, in, out)
MueLu::DefaultLocalOrdinal LocalOrdinal
Lightweight MueLu representation of a compressed row storage graph.
KOKKOS_INLINE_FUNCTION void SetBoundaryNodeMap(const boundary_nodes_type bndry)
Set boolean array indicating which rows correspond to Dirichlet boundaries.
void setValidator(RCP< const ParameterEntryValidator > const &validator)
Functor that drops boundary nodes for a blockSize > 1 problem.
T & get(const std::string &name, T def_value)
Classical smoothed aggregation dropping criterion.
Functor that marks singletons (all off-diagonal entries in a row are dropped) as boundary.
Signed classical Ruge-Stueben dropping criterion.
Timer to be used in factories. Similar to Monitor but with additional timers.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
#define MueLu_runBoundaryFunctors(...)
One-liner description of what is happening.
ParameterList & set(std::string const &name, T &&value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Signed classical smoothed aggregation dropping criterion.
Orders entries of row by .
Orders entries of row by where is the distance Laplacian.
Functor that marks singletons (all off-diagonal entries in a row are dropped) as boundary.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Functor that symmetrizes the dropping decisions.
MueLu::DefaultGlobalOrdinal GlobalOrdinal
Functor that drops boundary nodes for a blockSize == 1 problem.
Class that holds all level-specific information.
Timer to be used in factories. Similar to SubMonitor but adds a timer level by level.
typename MueLu::LWGraph_kokkos< LocalOrdinal, GlobalOrdinal, Node >::boundary_nodes_type boundary_nodes_type
void DeclareInput(Level ¤tLevel) const
Input.
Functor that fills the filtered matrix while reusing the graph of the matrix before dropping...
Order each row by a criterion, compare the ratio of values and drop all entries once the ratio is bel...
Functor for marking nodes as Dirichlet.
Functor that drops all entries that are not on the block diagonal.
Functor that marks diagonal as kept, unless the are already marked as boundary.
Kokkos::RangePolicy< local_ordinal_type, execution_space > range_type
std::tuple< GlobalOrdinal, boundary_nodes_type > BuildVector(Level ¤tLevel) const
static RCP< Vector > Build(const Teuchos::RCP< const Map > &map, bool zeroOut=true)
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
void Build(Level ¤tLevel) const
Build an object with this factory.
Functor for marking nodes as Dirichlet based on rowsum.
#define SET_VALID_ENTRY(name)
std::tuple< RCP< LocalOrdinalVector >, RCP< LocalOrdinalVector > > GetBlockNumberMVs(Level ¤tLevel) const
Functor for marking nodes as Dirichlet in a block operator.
std::tuple< GlobalOrdinal, boundary_nodes_type > BuildScalar(Level ¤tLevel) const
Functor does not reuse the graph of the matrix for a problem with blockSize == 1. ...
static RCP< Matrix > Build(const RCP< const Map > &rowMap, size_t maxNumEntriesPerRow, Xpetra::ProfileType pftype=Xpetra::DynamicProfile)
Exception throws to report errors in the internal logical of the program.
#define TEUCHOS_ASSERT(assertion_test)
ParameterEntry & getEntry(const std::string &name)
Orders entries of row by .
#define MueLu_runDroppingFunctors(...)