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",
"signed classical distance laplacian",
"signed classical sa distance laplacian"))));
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) {
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>
158 using local_matrix_type =
typename MatrixType::local_matrix_type;
159 using local_graph_type =
typename GraphType::local_graph_type;
160 using rowptr_type =
typename local_graph_type::row_map_type::non_const_type;
161 using entries_type =
typename local_graph_type::entries_type::non_const_type;
162 using values_type =
typename local_matrix_type::values_type::non_const_type;
163 using device_type =
typename Node::device_type;
164 using memory_space =
typename device_type::memory_space;
167 typedef typename STS::magnitudeType MT;
170 auto A = Get<RCP<Matrix>>(currentLevel,
"A");
177 const typename STS::magnitudeType dirichletThreshold = STS::magnitude(as<SC>(pL.get<
double>(
"aggregation: Dirichlet threshold")));
178 const typename STS::magnitudeType rowSumTol = as<typename STS::magnitudeType>(pL.get<
double>(
"aggregation: row sum drop tol"));
182 const std::string algo = pL.get<std::string>(
"aggregation: drop scheme");
183 std::string classicalAlgoStr = pL.get<std::string>(
"aggregation: classical algo");
184 std::string distanceLaplacianAlgoStr = pL.get<std::string>(
"aggregation: distance laplacian algo");
185 std::string distanceLaplacianMetric = pL.get<std::string>(
"aggregation: distance laplacian metric");
188 if (pL.get<
bool>(
"aggregation: use ml scaling of drop tol"))
189 threshold = pL.get<
double>(
"aggregation: drop tol") / pow(2.0, currentLevel.GetLevelID());
191 threshold = as<MT>(pL.get<
double>(
"aggregation: drop tol"));
192 bool aggregationMayCreateDirichlet = pL.get<
bool>(
"aggregation: dropping may create Dirichlet");
195 const bool lumping = pL.get<
bool>(
"filtered matrix: use lumping");
196 const bool reuseGraph = pL.get<
bool>(
"filtered matrix: reuse graph");
197 const bool reuseEigenvalue = pL.get<
bool>(
"filtered matrix: reuse eigenvalue");
199 const bool useRootStencil = pL.get<
bool>(
"filtered matrix: use root stencil");
200 const bool useSpreadLumping = pL.get<
bool>(
"filtered matrix: use spread lumping");
202 const MT filteringDirichletThreshold = as<MT>(pL.get<
double>(
"filtered matrix: Dirichlet threshold"));
206 if (algo ==
"classical")
207 GetOStream(
Runtime0) <<
"algorithm = \"" << algo <<
"\" classical algorithm = \"" << classicalAlgoStr <<
"\": threshold = " << threshold <<
", blocksize = " << A->GetFixedBlockSize() << std::endl;
208 else if (algo ==
"distance laplacian")
209 GetOStream(
Runtime0) <<
"algorithm = \"" << algo <<
"\" distance laplacian algorithm = \"" << distanceLaplacianAlgoStr <<
"\" distance laplacian metric = \"" << distanceLaplacianMetric <<
"\": threshold = " << threshold <<
", blocksize = " << A->GetFixedBlockSize() << std::endl;
211 GetOStream(
Runtime0) <<
"algorithm = \"" << algo <<
"\": threshold = " << threshold <<
", blocksize = " << A->GetFixedBlockSize() << std::endl;
213 if (((algo ==
"classical") && (classicalAlgoStr.find(
"scaled") != std::string::npos)) || ((algo ==
"distance laplacian") && (distanceLaplacianAlgoStr.find(
"scaled") != std::string::npos)))
227 auto crsA = toCrsMatrix(A);
228 auto lclA = crsA->getLocalMatrixDevice();
246 #define MueLu_runBoundaryFunctors(...) \
248 auto boundaries = BoundaryDetection::BoundaryFunctor(lclA, __VA_ARGS__); \
249 Kokkos::parallel_for("CoalesceDrop::BoundaryDetection", range, boundaries); \
254 if (rowSumTol <= 0.) {
261 #undef MueLu_runBoundaryFunctors
289 auto filtered_rowptr = rowptr_type(
"filtered_rowptr", lclA.numRows() + 1);
293 auto results = Kokkos::View<DecisionType*, memory_space>(
"results", lclA.nnz());
297 std::string functorLabel =
"MueLu::CoalesceDrop::CountEntries";
300 #if !defined(HAVE_MUELU_DEBUG)
301 #define MueLu_runDroppingFunctors(...) \
303 auto countingFunctor = MatrixConstruction::PointwiseCountingFunctor(lclA, results, filtered_rowptr, __VA_ARGS__); \
304 Kokkos::parallel_scan(functorLabel, range, countingFunctor, nnz_filtered); \
307 #define MueLu_runDroppingFunctors(...) \
309 auto debug = Misc::DebugFunctor(lclA, results); \
310 auto countingFunctor = MatrixConstruction::PointwiseCountingFunctor(lclA, results, filtered_rowptr, __VA_ARGS__, debug); \
311 Kokkos::parallel_scan(functorLabel, range, countingFunctor, nnz_filtered); \
317 if (threshold != zero) {
321 if (algo ==
"classical" || algo ==
"block diagonal classical") {
324 if (algo ==
"block diagonal classical") {
325 auto BlockNumber = Get<RCP<LocalOrdinalVector>>(currentLevel,
"BlockNumber");
328 if (classicalAlgoStr ==
"default") {
329 auto classical_dropping = ClassicalDropping::make_drop_functor<SoC>(*A, threshold, results);
331 if (aggregationMayCreateDirichlet) {
336 mark_singletons_as_boundary);
343 }
else if (classicalAlgoStr ==
"unscaled cut") {
351 }
else if (classicalAlgoStr ==
"scaled cut") {
352 auto comparison = CutDrop::make_scaled_comparison_functor<SoC>(*A, results);
359 }
else if (classicalAlgoStr ==
"scaled cut symmetric") {
360 auto comparison = CutDrop::make_scaled_comparison_functor<SoC>(*A, results);
376 if (classicalAlgoStr ==
"default") {
377 auto classical_dropping = ClassicalDropping::make_drop_functor<SoC>(*A, threshold, results);
379 if (aggregationMayCreateDirichlet) {
383 mark_singletons_as_boundary);
389 }
else if (classicalAlgoStr ==
"unscaled cut") {
396 }
else if (classicalAlgoStr ==
"scaled cut") {
397 auto comparison = CutDrop::make_scaled_comparison_functor<SoC>(*A, results);
403 }
else if (classicalAlgoStr ==
"scaled cut symmetric") {
404 auto comparison = CutDrop::make_scaled_comparison_functor<SoC>(*A, results);
419 }
else if (algo ==
"signed classical" || algo ==
"block diagonal signed classical" || algo ==
"block diagonal colored signed classical") {
422 auto signed_classical_rs_dropping = ClassicalDropping::make_drop_functor<SoC>(*A, threshold, results);
424 if (algo ==
"block diagonal signed classical" || algo ==
"block diagonal colored signed classical") {
425 auto BlockNumber = Get<RCP<LocalOrdinalVector>>(currentLevel,
"BlockNumber");
428 if (classicalAlgoStr ==
"default") {
429 if (aggregationMayCreateDirichlet) {
431 signed_classical_rs_dropping,
434 mark_singletons_as_boundary);
438 signed_classical_rs_dropping,
446 if (classicalAlgoStr ==
"default") {
447 if (aggregationMayCreateDirichlet) {
451 mark_singletons_as_boundary);
462 }
else if (algo ==
"signed classical sa") {
464 if (classicalAlgoStr ==
"default") {
465 auto signed_classical_sa_dropping = ClassicalDropping::make_drop_functor<SoC>(*A, threshold, results);
467 if (aggregationMayCreateDirichlet) {
471 mark_singletons_as_boundary);
481 }
else if (algo ==
"distance laplacian" || algo ==
"block diagonal distance laplacian" || algo ==
"signed classical distance laplacian" || algo ==
"signed classical sa distance laplacian") {
483 auto coords = Get<RCP<doubleMultiVector>>(currentLevel,
"Coordinates");
485 if (algo ==
"block diagonal distance laplacian") {
488 auto BlockNumber = Get<RCP<LocalOrdinalVector>>(currentLevel,
"BlockNumber");
493 if (distanceLaplacianAlgoStr ==
"default") {
494 auto dist_laplacian_dropping = DistanceLaplacian::make_drop_functor<SoC>(*A, threshold, dist2, results);
496 if (aggregationMayCreateDirichlet) {
498 dist_laplacian_dropping,
501 mark_singletons_as_boundary);
504 dist_laplacian_dropping,
508 }
else if (distanceLaplacianAlgoStr ==
"unscaled cut") {
516 }
else if (distanceLaplacianAlgoStr ==
"scaled cut") {
517 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
524 }
else if (distanceLaplacianAlgoStr ==
"scaled cut symmetric") {
525 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
539 }
else if (algo ==
"distance laplacian") {
542 if (distanceLaplacianAlgoStr ==
"default") {
543 if (distanceLaplacianMetric ==
"unweighted") {
545 auto dist_laplacian_dropping = DistanceLaplacian::make_drop_functor<SoC>(*A, threshold, dist2, results);
547 if (aggregationMayCreateDirichlet) {
551 mark_singletons_as_boundary);
557 }
else if (distanceLaplacianMetric ==
"material") {
558 auto material = Get<RCP<MultiVector>>(currentLevel,
"Material");
559 if (material->getNumVectors() == 1) {
560 GetOStream(
Runtime0) <<
"material scalar mean = " << material->getVector(0)->meanValue() << std::endl;
563 auto dist_laplacian_dropping = DistanceLaplacian::make_drop_functor<SoC>(*A, threshold, dist2, results);
565 if (aggregationMayCreateDirichlet) {
569 mark_singletons_as_boundary);
579 std::stringstream ss;
580 ss <<
"material tensor mean =" << std::endl;
582 for (
size_t i = 0; i < coords->getNumVectors(); ++i) {
584 for (
size_t j = 0; j < coords->getNumVectors(); ++j) {
585 ss << material->getVector(k)->meanValue() <<
" ";
594 auto dist_laplacian_dropping = DistanceLaplacian::make_drop_functor<SoC>(*A, threshold, dist2, results);
596 if (aggregationMayCreateDirichlet) {
600 mark_singletons_as_boundary);
609 }
else if (distanceLaplacianAlgoStr ==
"unscaled cut") {
610 if (distanceLaplacianMetric ==
"unweighted") {
618 }
else if (distanceLaplacianMetric ==
"material") {
619 auto material = Get<RCP<MultiVector>>(currentLevel,
"Material");
620 if (material->getNumVectors() == 1) {
621 GetOStream(
Runtime0) <<
"material scalar mean = " << material->getVector(0)->meanValue() << std::endl;
634 std::stringstream ss;
635 ss <<
"material tensor mean =" << std::endl;
637 for (
size_t i = 0; i < coords->getNumVectors(); ++i) {
639 for (
size_t j = 0; j < coords->getNumVectors(); ++j) {
640 ss << material->getVector(k)->meanValue() <<
" ";
657 }
else if (distanceLaplacianAlgoStr ==
"scaled cut") {
658 if (distanceLaplacianMetric ==
"unweighted") {
660 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
666 }
else if (distanceLaplacianMetric ==
"material") {
667 auto material = Get<RCP<MultiVector>>(currentLevel,
"Material");
668 if (material->getNumVectors() == 1) {
669 GetOStream(
Runtime0) <<
"material scalar mean = " << material->getVector(0)->meanValue() << std::endl;
672 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
682 std::stringstream ss;
683 ss <<
"material tensor mean =" << std::endl;
685 for (
size_t i = 0; i < coords->getNumVectors(); ++i) {
687 for (
size_t j = 0; j < coords->getNumVectors(); ++j) {
688 ss << material->getVector(k)->meanValue() <<
" ";
697 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
705 }
else if (distanceLaplacianAlgoStr ==
"scaled cut symmetric") {
706 if (distanceLaplacianMetric ==
"unweighted") {
708 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
714 }
else if (distanceLaplacianMetric ==
"material") {
715 auto material = Get<RCP<MultiVector>>(currentLevel,
"Material");
716 if (material->getNumVectors() == 1) {
717 GetOStream(
Runtime0) <<
"material scalar mean = " << material->getVector(0)->meanValue() << std::endl;
720 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
730 std::stringstream ss;
731 ss <<
"material tensor mean =" << std::endl;
733 for (
size_t i = 0; i < coords->getNumVectors(); ++i) {
735 for (
size_t j = 0; j < coords->getNumVectors(); ++j) {
736 ss << material->getVector(k)->meanValue() <<
" ";
745 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
760 }
else if (algo ==
"signed classical distance laplacian") {
762 if (distanceLaplacianAlgoStr ==
"default") {
763 if (distanceLaplacianMetric ==
"unweighted") {
765 auto dist_laplacian_dropping = DistanceLaplacian::make_drop_functor<SoC>(*A, threshold, dist2, results);
767 if (aggregationMayCreateDirichlet) {
771 mark_singletons_as_boundary);
777 }
else if (distanceLaplacianMetric ==
"material") {
778 auto material = Get<RCP<MultiVector>>(currentLevel,
"Material");
779 if (material->getNumVectors() == 1) {
780 GetOStream(
Runtime0) <<
"material scalar mean = " << material->getVector(0)->meanValue() << std::endl;
783 auto dist_laplacian_dropping = DistanceLaplacian::make_drop_functor<SoC>(*A, threshold, dist2, results);
785 if (aggregationMayCreateDirichlet) {
789 mark_singletons_as_boundary);
799 std::stringstream ss;
800 ss <<
"material tensor mean =" << std::endl;
802 for (
size_t i = 0; i < coords->getNumVectors(); ++i) {
804 for (
size_t j = 0; j < coords->getNumVectors(); ++j) {
805 ss << material->getVector(k)->meanValue() <<
" ";
814 auto dist_laplacian_dropping = DistanceLaplacian::make_drop_functor<SoC>(*A, threshold, dist2, results);
816 if (aggregationMayCreateDirichlet) {
820 mark_singletons_as_boundary);
829 }
else if (distanceLaplacianAlgoStr ==
"unscaled cut") {
830 if (distanceLaplacianMetric ==
"unweighted") {
838 }
else if (distanceLaplacianMetric ==
"material") {
839 auto material = Get<RCP<MultiVector>>(currentLevel,
"Material");
840 if (material->getNumVectors() == 1) {
841 GetOStream(
Runtime0) <<
"material scalar mean = " << material->getVector(0)->meanValue() << std::endl;
854 std::stringstream ss;
855 ss <<
"material tensor mean =" << std::endl;
857 for (
size_t i = 0; i < coords->getNumVectors(); ++i) {
859 for (
size_t j = 0; j < coords->getNumVectors(); ++j) {
860 ss << material->getVector(k)->meanValue() <<
" ";
877 }
else if (distanceLaplacianAlgoStr ==
"scaled cut") {
878 if (distanceLaplacianMetric ==
"unweighted") {
880 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
886 }
else if (distanceLaplacianMetric ==
"material") {
887 auto material = Get<RCP<MultiVector>>(currentLevel,
"Material");
888 if (material->getNumVectors() == 1) {
889 GetOStream(
Runtime0) <<
"material scalar mean = " << material->getVector(0)->meanValue() << std::endl;
892 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
902 std::stringstream ss;
903 ss <<
"material tensor mean =" << std::endl;
905 for (
size_t i = 0; i < coords->getNumVectors(); ++i) {
907 for (
size_t j = 0; j < coords->getNumVectors(); ++j) {
908 ss << material->getVector(k)->meanValue() <<
" ";
917 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
925 }
else if (distanceLaplacianAlgoStr ==
"scaled cut symmetric") {
926 if (distanceLaplacianMetric ==
"unweighted") {
928 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
934 }
else if (distanceLaplacianMetric ==
"material") {
935 auto material = Get<RCP<MultiVector>>(currentLevel,
"Material");
936 if (material->getNumVectors() == 1) {
937 GetOStream(
Runtime0) <<
"material scalar mean = " << material->getVector(0)->meanValue() << std::endl;
940 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
950 std::stringstream ss;
951 ss <<
"material tensor mean =" << std::endl;
953 for (
size_t i = 0; i < coords->getNumVectors(); ++i) {
955 for (
size_t j = 0; j < coords->getNumVectors(); ++j) {
956 ss << material->getVector(k)->meanValue() <<
" ";
965 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
980 }
else if (algo ==
"signed classical sa distance laplacian") {
983 if (distanceLaplacianAlgoStr ==
"default") {
984 if (distanceLaplacianMetric ==
"unweighted") {
986 auto dist_laplacian_dropping = DistanceLaplacian::make_drop_functor<SoC>(*A, threshold, dist2, results);
988 if (aggregationMayCreateDirichlet) {
992 mark_singletons_as_boundary);
998 }
else if (distanceLaplacianMetric ==
"material") {
999 auto material = Get<RCP<MultiVector>>(currentLevel,
"Material");
1000 if (material->getNumVectors() == 1) {
1001 GetOStream(
Runtime0) <<
"material scalar mean = " << material->getVector(0)->meanValue() << std::endl;
1004 auto dist_laplacian_dropping = DistanceLaplacian::make_drop_functor<SoC>(*A, threshold, dist2, results);
1006 if (aggregationMayCreateDirichlet) {
1010 mark_singletons_as_boundary);
1014 preserve_diagonals);
1020 std::stringstream ss;
1021 ss <<
"material tensor mean =" << std::endl;
1023 for (
size_t i = 0; i < coords->getNumVectors(); ++i) {
1025 for (
size_t j = 0; j < coords->getNumVectors(); ++j) {
1026 ss << material->getVector(k)->meanValue() <<
" ";
1035 auto dist_laplacian_dropping = DistanceLaplacian::make_drop_functor<SoC>(*A, threshold, dist2, results);
1037 if (aggregationMayCreateDirichlet) {
1041 mark_singletons_as_boundary);
1045 preserve_diagonals);
1050 }
else if (distanceLaplacianAlgoStr ==
"unscaled cut") {
1051 if (distanceLaplacianMetric ==
"unweighted") {
1059 }
else if (distanceLaplacianMetric ==
"material") {
1060 auto material = Get<RCP<MultiVector>>(currentLevel,
"Material");
1061 if (material->getNumVectors() == 1) {
1062 GetOStream(
Runtime0) <<
"material scalar mean = " << material->getVector(0)->meanValue() << std::endl;
1075 std::stringstream ss;
1076 ss <<
"material tensor mean =" << std::endl;
1078 for (
size_t i = 0; i < coords->getNumVectors(); ++i) {
1080 for (
size_t j = 0; j < coords->getNumVectors(); ++j) {
1081 ss << material->getVector(k)->meanValue() <<
" ";
1098 }
else if (distanceLaplacianAlgoStr ==
"scaled cut") {
1099 if (distanceLaplacianMetric ==
"unweighted") {
1101 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
1107 }
else if (distanceLaplacianMetric ==
"material") {
1108 auto material = Get<RCP<MultiVector>>(currentLevel,
"Material");
1109 if (material->getNumVectors() == 1) {
1110 GetOStream(
Runtime0) <<
"material scalar mean = " << material->getVector(0)->meanValue() << std::endl;
1113 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
1123 std::stringstream ss;
1124 ss <<
"material tensor mean =" << std::endl;
1126 for (
size_t i = 0; i < coords->getNumVectors(); ++i) {
1128 for (
size_t j = 0; j < coords->getNumVectors(); ++j) {
1129 ss << material->getVector(k)->meanValue() <<
" ";
1138 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
1146 }
else if (distanceLaplacianAlgoStr ==
"scaled cut symmetric") {
1147 if (distanceLaplacianMetric ==
"unweighted") {
1149 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
1155 }
else if (distanceLaplacianMetric ==
"material") {
1156 auto material = Get<RCP<MultiVector>>(currentLevel,
"Material");
1157 if (material->getNumVectors() == 1) {
1158 GetOStream(
Runtime0) <<
"material scalar mean = " << material->getVector(0)->meanValue() << std::endl;
1161 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
1171 std::stringstream ss;
1172 ss <<
"material tensor mean =" << std::endl;
1174 for (
size_t i = 0; i < coords->getNumVectors(); ++i) {
1176 for (
size_t j = 0; j < coords->getNumVectors(); ++j) {
1177 ss << material->getVector(k)->meanValue() <<
" ";
1186 auto comparison = CutDrop::make_scaled_dlap_comparison_functor<SoC>(*A, dist2, results);
1202 }
else if (algo ==
"block diagonal") {
1203 auto BlockNumber = Get<RCP<LocalOrdinalVector>>(currentLevel,
"BlockNumber");
1211 Kokkos::deep_copy(results,
KEEP);
1217 #undef MueLu_runDroppingFunctors
1219 GO numDropped = lclA.nnz() - nnz_filtered;
1232 local_matrix_type lclFilteredA;
1233 local_graph_type lclGraph;
1235 filteredA = MatrixFactory::BuildCopy(A);
1236 lclFilteredA = filteredA->getLocalMatrixDevice();
1238 auto colidx = entries_type(
"entries", nnz_filtered);
1239 lclGraph = local_graph_type(colidx, filtered_rowptr);
1241 auto colidx = entries_type(
"entries", nnz_filtered);
1242 auto values = values_type(
"values", nnz_filtered);
1243 lclFilteredA = local_matrix_type(
"filteredA",
1244 lclA.numRows(), lclA.numCols(),
1246 values, filtered_rowptr, colidx);
1252 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_lumped_reuse", range, fillFunctor);
1255 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_lumped_noreuse", range, fillFunctor);
1260 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_unlumped_reuse", range, fillFunctor);
1263 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_unlumped_noreuse", range, fillFunctor);
1268 filteredA = MatrixFactory::Build(lclFilteredA, A->getRowMap(), A->getColMap(), A->getDomainMap(), A->getRangeMap());
1269 filteredA->SetFixedBlockSize(A->GetFixedBlockSize());
1271 if (reuseEigenvalue) {
1276 filteredA->SetMaxEigenvalueEstimate(A->GetMaxEigenvalueEstimate());
1283 lclGraph = filteredA->getCrsGraph()->getLocalGraphDevice();
1285 graph =
rcp(
new LWGraph_kokkos(lclGraph, filteredA->getRowMap(), filteredA->getColMap(),
"amalgamated graph of A"));
1290 Set(currentLevel,
"DofsPerNode", dofsPerNode);
1291 Set(currentLevel,
"Graph", graph);
1292 Set(currentLevel,
"A", filteredA);
1294 return std::make_tuple(numDropped, boundaryNodes);
1297 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1304 using local_matrix_type =
typename MatrixType::local_matrix_type;
1305 using local_graph_type =
typename GraphType::local_graph_type;
1306 using rowptr_type =
typename local_graph_type::row_map_type::non_const_type;
1307 using entries_type =
typename local_graph_type::entries_type::non_const_type;
1308 using values_type =
typename local_matrix_type::values_type::non_const_type;
1309 using device_type =
typename Node::device_type;
1310 using memory_space =
typename device_type::memory_space;
1313 typedef typename STS::magnitudeType MT;
1316 auto A = Get<RCP<Matrix>>(currentLevel,
"A");
1336 LO blkSize = A->GetFixedBlockSize() / A->GetStorageBlockSize();
1338 auto amalInfo = Get<RCP<AmalgamationInfo>>(currentLevel,
"UnAmalgamationInfo");
1350 Array<LO> rowTranslationArray = *(amalInfo->getRowTranslation());
1351 Array<LO> colTranslationArray = *(amalInfo->getColTranslation());
1353 Kokkos::View<LO*, Kokkos::MemoryUnmanaged>
1354 rowTranslationView(rowTranslationArray.
getRawPtr(), rowTranslationArray.
size());
1355 Kokkos::View<LO*, Kokkos::MemoryUnmanaged>
1356 colTranslationView(colTranslationArray.
getRawPtr(), colTranslationArray.
size());
1359 LO numNodes = Teuchos::as<LocalOrdinal>(uniqueMap->getLocalNumElements());
1360 typedef typename Kokkos::View<LocalOrdinal*, typename Node::device_type> id_translation_type;
1361 id_translation_type rowTranslation(
"dofId2nodeId", rowTranslationArray.
size());
1362 id_translation_type colTranslation(
"ov_dofId2nodeId", colTranslationArray.
size());
1363 Kokkos::deep_copy(rowTranslation, rowTranslationView);
1364 Kokkos::deep_copy(colTranslation, colTranslationView);
1367 blkSize = A->GetFixedBlockSize();
1370 if (A->IsView(
"stridedMaps") ==
true) {
1374 blkSize = Teuchos::as<const LocalOrdinal>(strMap->getFixedBlockSize());
1375 blkId = strMap->getStridedBlockId();
1377 blkPartSize = Teuchos::as<LocalOrdinal>(strMap->getStridingData()[blkId]);
1387 const typename STS::magnitudeType dirichletThreshold = STS::magnitude(as<SC>(pL.get<
double>(
"aggregation: Dirichlet threshold")));
1388 const typename STS::magnitudeType rowSumTol = as<typename STS::magnitudeType>(pL.get<
double>(
"aggregation: row sum drop tol"));
1390 const bool useGreedyDirichlet = pL.get<
bool>(
"aggregation: greedy Dirichlet");
1394 const std::string algo = pL.get<std::string>(
"aggregation: drop scheme");
1395 std::string classicalAlgoStr = pL.get<std::string>(
"aggregation: classical algo");
1396 std::string distanceLaplacianAlgoStr = pL.get<std::string>(
"aggregation: distance laplacian algo");
1397 std::string distanceLaplacianMetric = pL.get<std::string>(
"aggregation: distance laplacian metric");
1400 if (pL.get<
bool>(
"aggregation: use ml scaling of drop tol"))
1401 threshold = pL.get<
double>(
"aggregation: drop tol") / pow(2.0, currentLevel.GetLevelID());
1403 threshold = as<MT>(pL.get<
double>(
"aggregation: drop tol"));
1404 bool aggregationMayCreateDirichlet = pL.get<
bool>(
"aggregation: dropping may create Dirichlet");
1407 const bool lumping = pL.get<
bool>(
"filtered matrix: use lumping");
1408 const bool reuseGraph = pL.get<
bool>(
"filtered matrix: reuse graph");
1409 const bool reuseEigenvalue = pL.get<
bool>(
"filtered matrix: reuse eigenvalue");
1411 const bool useRootStencil = pL.get<
bool>(
"filtered matrix: use root stencil");
1412 const bool useSpreadLumping = pL.get<
bool>(
"filtered matrix: use spread lumping");
1414 const MT filteringDirichletThreshold = as<MT>(pL.get<
double>(
"filtered matrix: Dirichlet threshold"));
1419 if (algo ==
"classical") {
1420 GetOStream(
Runtime0) <<
"algorithm = \"" << algo <<
"\" classical algorithm = \"" << classicalAlgoStr <<
"\": threshold = " << threshold <<
", blocksize = " << A->GetFixedBlockSize() << std::endl;
1421 }
else if (algo ==
"distance laplacian") {
1422 GetOStream(
Runtime0) <<
"algorithm = \"" << algo <<
"\" distance laplacian algorithm = \"" << distanceLaplacianAlgoStr <<
"\" distance laplacian metric = \"" << distanceLaplacianMetric <<
"\": threshold = " << threshold <<
", blocksize = " << A->GetFixedBlockSize() << std::endl;
1424 GetOStream(
Runtime0) <<
"algorithm = \"" << algo <<
"\": threshold = " << threshold <<
", blocksize = " << A->GetFixedBlockSize() << std::endl;
1437 auto crsA = toCrsMatrix(A);
1438 auto lclA = crsA->getLocalMatrixDevice();
1453 #define MueLu_runBoundaryFunctors(...) \
1455 auto boundaries = BoundaryDetection::BoundaryFunctor(lclA, __VA_ARGS__); \
1456 Kokkos::parallel_for("CoalesceDrop::BoundaryDetection", range, boundaries); \
1459 if (useGreedyDirichlet) {
1466 #undef MueLu_runBoundaryFunctors
1492 auto filtered_rowptr = rowptr_type(
"rowptr", lclA.numRows() + 1);
1493 auto graph_rowptr = rowptr_type(
"rowptr", numNodes + 1);
1495 Kokkos::pair<LocalOrdinal, LocalOrdinal> nnz = {0, 0};
1498 auto results = Kokkos::View<DecisionType*, memory_space>(
"results", lclA.nnz());
1502 std::string functorLabel =
"MueLu::CoalesceDrop::CountEntries";
1504 #if !defined(HAVE_MUELU_DEBUG)
1505 #define MueLu_runDroppingFunctors(...) \
1507 auto countingFunctor = MatrixConstruction::VectorCountingFunctor(lclA, blkPartSize, colTranslation, results, filtered_rowptr, graph_rowptr, __VA_ARGS__); \
1508 Kokkos::parallel_scan(functorLabel, range, countingFunctor, nnz); \
1511 #define MueLu_runDroppingFunctors(...) \
1513 auto debug = Misc::DebugFunctor(lclA, results); \
1514 auto countingFunctor = MatrixConstruction::VectorCountingFunctor(lclA, blkPartSize, colTranslation, results, filtered_rowptr, graph_rowptr, __VA_ARGS__, debug); \
1515 Kokkos::parallel_scan(functorLabel, range, countingFunctor, nnz); \
1521 if (threshold != zero) {
1525 if (algo ==
"classical" || algo ==
"block diagonal classical") {
1528 if (classicalAlgoStr ==
"default") {
1529 auto classical_dropping = ClassicalDropping::make_drop_functor<SoC>(*A, threshold, results);
1531 if (algo ==
"block diagonal classical") {
1532 auto BlockNumber = Get<RCP<LocalOrdinalVector>>(currentLevel,
"BlockNumber");
1535 if (aggregationMayCreateDirichlet) {
1540 mark_singletons_as_boundary);
1545 preserve_diagonals);
1548 if (aggregationMayCreateDirichlet) {
1552 mark_singletons_as_boundary);
1556 preserve_diagonals);
1559 }
else if (classicalAlgoStr ==
"unscaled cut") {
1561 }
else if (classicalAlgoStr ==
"scaled cut") {
1563 }
else if (classicalAlgoStr ==
"scaled cut symmetric") {
1566 TEUCHOS_TEST_FOR_EXCEPTION(
true,
Exceptions::RuntimeError,
"\"aggregation: classical algo\" must be one of (default|unscaled cut|scaled cut|scaled cut symmetric), not \"" << classicalAlgoStr <<
"\"");
1568 }
else if (algo ==
"signed classical" || algo ==
"block diagonal colored signed classical" || algo ==
"block diagonal signed classical") {
1571 auto signed_classical_rs_dropping = ClassicalDropping::make_drop_functor<SoC>(*A, threshold, results);
1573 if (algo ==
"block diagonal signed classical" || algo ==
"block diagonal colored signed classical") {
1574 auto BlockNumber = Get<RCP<LocalOrdinalVector>>(currentLevel,
"BlockNumber");
1577 if (aggregationMayCreateDirichlet) {
1579 signed_classical_rs_dropping,
1582 mark_singletons_as_boundary);
1586 signed_classical_rs_dropping,
1588 preserve_diagonals);
1591 if (aggregationMayCreateDirichlet) {
1595 mark_singletons_as_boundary);
1600 preserve_diagonals);
1603 }
else if (algo ==
"signed classical sa") {
1606 auto signed_classical_sa_dropping = ClassicalDropping::make_drop_functor<SoC>(*A, threshold, results);
1608 if (aggregationMayCreateDirichlet) {
1612 mark_singletons_as_boundary);
1617 preserve_diagonals);
1619 }
else if (algo ==
"distance laplacian" || algo ==
"block diagonal distance laplacian") {
1621 auto coords = Get<RCP<doubleMultiVector>>(currentLevel,
"Coordinates");
1623 bool use_block_algorithm = (algo ==
"block diagonal classical" || algo ==
"block diagonal distance laplacian");
1625 enum { NO_WEIGHTS = 0,
1628 int use_dlap_weights = NO_WEIGHTS;
1629 if (algo ==
"distance laplacian") {
1632 bool non_unity =
false;
1633 for (LO i = 0; !non_unity && i < (LO)dlap_weights.
size(); i++) {
1634 if (dlap_weights[i] != 1.0) {
1639 LO blocksize = use_block_algorithm ? as<LO>(pL.get<
int>(
"aggregation: block diagonal: interleaved blocksize")) : 1;
1640 if ((LO)dlap_weights.
size() == dim)
1641 use_dlap_weights = SINGLE_WEIGHTS;
1642 else if ((LO)dlap_weights.
size() == blocksize * dim)
1643 use_dlap_weights = BLOCK_WEIGHTS;
1646 "length of 'aggregation: distance laplacian directional weights' must equal the coordinate dimension OR the coordinate dimension times the blocksize");
1649 GetOStream(
Statistics1) <<
"Using distance laplacian weights: " << dlap_weights << std::endl;
1652 TEUCHOS_TEST_FOR_EXCEPTION(use_dlap_weights != NO_WEIGHTS,
Exceptions::RuntimeError,
"Only the NO_WEIGHTS option is implemented for distance laplacian ");
1658 auto merged_rowptr = rowptr_type(
"rowptr", numNodes + 1);
1662 Kokkos::parallel_scan(
"MergeCount", range, functor, nnz_merged);
1664 local_graph_type lclMergedGraph;
1665 auto colidx_merged = entries_type(
"entries", nnz_merged);
1666 auto values_merged = values_type(
"values", nnz_merged);
1668 local_matrix_type lclMergedA = local_matrix_type(
"mergedA",
1669 numNodes, nonUniqueMap->getLocalNumElements(),
1671 values_merged, merged_rowptr, colidx_merged);
1674 Kokkos::parallel_for(
"MueLu::CoalesceDrop::MergeFill", range, fillFunctor);
1679 if (algo ==
"block diagonal distance laplacian") {
1680 auto BlockNumber = Get<RCP<LocalOrdinalVector>>(currentLevel,
"BlockNumber");
1683 if (distanceLaplacianAlgoStr ==
"default") {
1686 if (distanceLaplacianMetric ==
"unweighted") {
1688 auto dist_laplacian_dropping = DistanceLaplacian::make_vector_drop_functor<SoC>(*A, *mergedA, threshold, dist2, results, rowTranslation, colTranslation);
1690 if (aggregationMayCreateDirichlet) {
1692 dist_laplacian_dropping,
1695 mark_singletons_as_boundary);
1698 dist_laplacian_dropping,
1700 preserve_diagonals);
1702 }
else if (distanceLaplacianMetric ==
"material") {
1703 auto material = Get<RCP<MultiVector>>(currentLevel,
"Material");
1704 if (material->getNumVectors() == 1) {
1705 GetOStream(
Runtime0) <<
"material scalar mean = " << material->getVector(0)->meanValue() << std::endl;
1708 auto dist_laplacian_dropping = DistanceLaplacian::make_vector_drop_functor<SoC>(*A, *mergedA, threshold, dist2, results, rowTranslation, colTranslation);
1710 if (aggregationMayCreateDirichlet) {
1712 dist_laplacian_dropping,
1715 mark_singletons_as_boundary);
1718 dist_laplacian_dropping,
1720 preserve_diagonals);
1723 TEUCHOS_TEST_FOR_EXCEPTION(coords->getNumVectors() * coords->getNumVectors() != material->getNumVectors(),
Exceptions::RuntimeError,
"Need \"Material\" to have spatialDim^2 vectors.");
1726 std::stringstream ss;
1727 ss <<
"material tensor mean =" << std::endl;
1729 for (
size_t i = 0; i < coords->getNumVectors(); ++i) {
1731 for (
size_t j = 0; j < coords->getNumVectors(); ++j) {
1732 ss << material->getVector(k)->meanValue() <<
" ";
1741 auto dist_laplacian_dropping = DistanceLaplacian::make_vector_drop_functor<SoC>(*A, *mergedA, threshold, dist2, results, rowTranslation, colTranslation);
1743 if (aggregationMayCreateDirichlet) {
1745 dist_laplacian_dropping,
1748 mark_singletons_as_boundary);
1751 dist_laplacian_dropping,
1753 preserve_diagonals);
1757 }
else if (distanceLaplacianAlgoStr ==
"unscaled cut") {
1759 }
else if (distanceLaplacianAlgoStr ==
"scaled cut") {
1761 }
else if (distanceLaplacianAlgoStr ==
"scaled cut symmetric") {
1764 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 <<
"\"");
1767 if (distanceLaplacianAlgoStr ==
"default") {
1770 if (distanceLaplacianMetric ==
"unweighted") {
1772 auto dist_laplacian_dropping = DistanceLaplacian::make_vector_drop_functor<SoC>(*A, *mergedA, threshold, dist2, results, rowTranslation, colTranslation);
1774 if (aggregationMayCreateDirichlet) {
1778 mark_singletons_as_boundary);
1782 preserve_diagonals);
1784 }
else if (distanceLaplacianMetric ==
"material") {
1785 auto material = Get<RCP<MultiVector>>(currentLevel,
"Material");
1786 if (material->getNumVectors() == 1) {
1787 GetOStream(
Runtime0) <<
"material scalar mean = " << material->getVector(0)->meanValue() << std::endl;
1790 auto dist_laplacian_dropping = DistanceLaplacian::make_vector_drop_functor<SoC>(*A, *mergedA, threshold, dist2, results, rowTranslation, colTranslation);
1792 if (aggregationMayCreateDirichlet) {
1796 mark_singletons_as_boundary);
1800 preserve_diagonals);
1803 TEUCHOS_TEST_FOR_EXCEPTION(coords->getNumVectors() * coords->getNumVectors() != material->getNumVectors(),
Exceptions::RuntimeError,
"Need \"Material\" to have spatialDim^2 vectors.");
1806 std::stringstream ss;
1807 ss <<
"material tensor mean =" << std::endl;
1809 for (
size_t i = 0; i < coords->getNumVectors(); ++i) {
1811 for (
size_t j = 0; j < coords->getNumVectors(); ++j) {
1812 ss << material->getVector(k)->meanValue() <<
" ";
1821 auto dist_laplacian_dropping = DistanceLaplacian::make_vector_drop_functor<SoC>(*A, *mergedA, threshold, dist2, results, rowTranslation, colTranslation);
1823 if (aggregationMayCreateDirichlet) {
1827 mark_singletons_as_boundary);
1831 preserve_diagonals);
1835 }
else if (distanceLaplacianAlgoStr ==
"unscaled cut") {
1837 }
else if (distanceLaplacianAlgoStr ==
"scaled cut") {
1839 }
else if (distanceLaplacianAlgoStr ==
"scaled cut symmetric") {
1842 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 <<
"\"");
1846 }
else if (algo ==
"block diagonal") {
1847 auto BlockNumber = Get<RCP<LocalOrdinalVector>>(currentLevel,
"BlockNumber");
1855 Kokkos::deep_copy(results,
KEEP);
1860 #undef MueLu_runDroppingFunctors
1864 GO numTotal = lclA.nnz();
1865 GO numDropped = numTotal - nnz_filtered;
1878 local_matrix_type lclFilteredA;
1880 lclFilteredA = local_matrix_type(
"filteredA", lclA.graph, lclA.numCols());
1882 auto colidx = entries_type(
"entries", nnz_filtered);
1883 auto values = values_type(
"values", nnz_filtered);
1884 lclFilteredA = local_matrix_type(
"filteredA",
1885 lclA.numRows(), lclA.numCols(),
1887 values, filtered_rowptr, colidx);
1890 local_graph_type lclGraph;
1892 auto colidx = entries_type(
"entries", nnz_graph);
1893 lclGraph = local_graph_type(colidx, graph_rowptr);
1899 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_lumped_reuse", range, fillFunctor);
1902 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_lumped_noreuse", range, fillFunctor);
1907 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_unlumped_reuse", range, fillFunctor);
1910 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_unlumped_noreuse", range, fillFunctor);
1915 filteredA->SetFixedBlockSize(blkSize);
1917 if (reuseEigenvalue) {
1922 filteredA->SetMaxEigenvalueEstimate(A->GetMaxEigenvalueEstimate());
1927 graph =
rcp(
new LWGraph_kokkos(lclGraph, uniqueMap, nonUniqueMap,
"amalgamated graph of A"));
1931 LO dofsPerNode = blkSize;
1933 Set(currentLevel,
"DofsPerNode", dofsPerNode);
1934 Set(currentLevel,
"Graph", graph);
1935 Set(currentLevel,
"A", filteredA);
1937 return std::make_tuple(numDropped, boundaryNodes);
1941 #endif // MUELU_COALESCEDROPFACTORY_KOKKOS_DEF_HPP
#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)
Functor that marks singletons (all off-diagonal entries in a row are dropped) as boundary.
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)
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
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)
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)
Functor that drops all entries that are not on the block diagonal.
virtual size_t getNumVectors() const =0
ParameterEntry & getEntry(const std::string &name)
Orders entries of row by .
#define MueLu_runDroppingFunctors(...)