46 #ifndef MUELU_FILTEREDAFACTORY_DEF_HPP
47 #define MUELU_FILTEREDAFACTORY_DEF_HPP
58 #include "MueLu_Aggregates.hpp"
59 #include "MueLu_AmalgamationInfo.hpp"
60 #include "MueLu_Utilities.hpp"
63 #define MUELU_FILTEREDAFACTORY_LOTS_OF_PRINTING 0
69 std::sort(array.begin(), array.end());
70 std::unique(array.begin(), array.end());
73 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
77 #define SET_VALID_ENTRY(name) validParamList->setEntry(name, MasterList::getEntry(name))
83 SET_VALID_ENTRY(
"filtered matrix: spread lumping diag dom growth factor");
86 #undef SET_VALID_ENTRY
88 validParamList->
set<
RCP<const FactoryBase> >(
"A", Teuchos::null,
"Generating factory of the matrix A used for filtering");
94 validParamList->
set<
RCP<const FactoryBase> >(
"UnAmalgamationInfo", Teuchos::null,
"Generating factory of UnAmalgamationInfo");
95 return validParamList;
98 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
100 Input(currentLevel,
"A");
101 Input(currentLevel,
"Filtering");
102 Input(currentLevel,
"Graph");
104 if (pL.
isParameter(
"filtered matrix: use root stencil") && pL.
get<
bool>(
"filtered matrix: use root stencil") ==
true) {
105 Input(currentLevel,
"Aggregates");
106 Input(currentLevel,
"UnAmalgamationInfo");
110 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
114 RCP<Matrix> A = Get<RCP<Matrix> >(currentLevel,
"A");
115 if (Get<bool>(currentLevel,
"Filtering") ==
false) {
116 GetOStream(
Runtime0) <<
"Filtered matrix is not being constructed as no filtering is being done" << std::endl;
117 Set(currentLevel,
"A", A);
122 bool lumping = pL.
get<
bool>(
"filtered matrix: use lumping");
124 GetOStream(
Runtime0) <<
"Lumping dropped entries" << std::endl;
126 bool use_spread_lumping = pL.
get<
bool>(
"filtered matrix: use spread lumping");
127 if (use_spread_lumping && (!lumping))
128 throw std::runtime_error(
"Must also request 'filtered matrix: use lumping' in order to use spread lumping");
130 if (use_spread_lumping) {
131 GetOStream(
Runtime0) <<
"using spread lumping " << std::endl;
134 double DdomAllowGrowthRate = 1.1;
135 double DdomCap = 2.0;
136 if (use_spread_lumping) {
137 DdomAllowGrowthRate = pL.
get<
double>(
"filtered matrix: spread lumping diag dom growth factor");
138 DdomCap = pL.
get<
double>(
"filtered matrix: spread lumping diag dom cap");
140 bool use_root_stencil = lumping && pL.
get<
bool>(
"filtered matrix: use root stencil");
141 if (use_root_stencil)
142 GetOStream(
Runtime0) <<
"Using root stencil for dropping" << std::endl;
143 double dirichlet_threshold = pL.
get<
double>(
"filtered matrix: Dirichlet threshold");
144 if (dirichlet_threshold >= 0.0)
145 GetOStream(
Runtime0) <<
"Filtering Dirichlet threshold of " << dirichlet_threshold << std::endl;
147 if (use_root_stencil || pL.
get<
bool>(
"filtered matrix: reuse graph"))
148 GetOStream(
Runtime0) <<
"Reusing graph" << std::endl;
150 GetOStream(
Runtime0) <<
"Generating new graph" << std::endl;
152 RCP<LWGraph> G = Get<RCP<LWGraph> >(currentLevel,
"Graph");
154 FILE* f = fopen(
"graph.dat",
"w");
156 for (
size_t i = 0; i < numGRows; i++) {
159 for (
size_t j = 0; j < (size_t)indsG.length; j++) {
160 fprintf(f,
"%d %d 1.0\n", (
int)i, (
int)indsG(j));
167 fillCompleteParams->
set(
"No Nonlocal Changes",
true);
170 if (use_root_stencil) {
171 filteredA = MatrixFactory::Build(A->getCrsGraph());
172 filteredA->fillComplete(fillCompleteParams);
173 filteredA->resumeFill();
174 BuildNewUsingRootStencil(*A, *G, dirichlet_threshold, currentLevel, *filteredA, use_spread_lumping, DdomAllowGrowthRate, DdomCap);
175 filteredA->fillComplete(fillCompleteParams);
177 }
else if (pL.
get<
bool>(
"filtered matrix: reuse graph")) {
178 filteredA = MatrixFactory::Build(A->getCrsGraph());
179 filteredA->resumeFill();
180 BuildReuse(*A, *G, (lumping != use_spread_lumping), dirichlet_threshold, *filteredA);
184 if (use_spread_lumping) ExperimentalLumping(*A, *filteredA, DdomAllowGrowthRate, DdomCap);
185 filteredA->fillComplete(fillCompleteParams);
188 filteredA = MatrixFactory::Build(A->getRowMap(), A->getColMap(), A->getLocalMaxNumRowEntries());
189 BuildNew(*A, *G, (lumping != use_spread_lumping), dirichlet_threshold, *filteredA);
192 if (use_spread_lumping) ExperimentalLumping(*A, *filteredA, DdomAllowGrowthRate, DdomCap);
193 filteredA->fillComplete(A->getDomainMap(), A->getRangeMap(), fillCompleteParams);
201 RCP<Matrix> origFilteredA = MatrixFactory::Build(A->getRowMap(), A->getColMap(), A->getLocalMaxNumRowEntries());
202 BuildNew(*A, *G, lumping, dirichlet_threshold, *origFilteredA);
203 if (use_spread_lumping) ExperimentalLumping(*A, *origFilteredA, DdomAllowGrowthRate, DdomCap);
204 origFilteredA->fillComplete(A->getDomainMap(), A->getRangeMap(), fillCompleteParams);
208 filteredA->SetFixedBlockSize(A->GetFixedBlockSize());
210 if (pL.
get<
bool>(
"filtered matrix: reuse eigenvalue")) {
215 filteredA->SetMaxEigenvalueEstimate(A->GetMaxEigenvalueEstimate());
218 Set(currentLevel,
"A", filteredA);
236 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
238 BuildReuse(
const Matrix& A,
const LWGraph& G,
const bool lumping,
double dirichletThresh, Matrix& filteredA)
const {
240 SC zero = TST::zero();
242 size_t blkSize = A.GetFixedBlockSize();
246 #ifdef ASSUME_DIRECT_ACCESS_TO_ROW
253 A.getColMap()->getLocalNumElements()),
257 for (
size_t i = 0; i < numGRows; i++) {
260 for (
size_t j = 0; j < as<size_t>(indsG.length); j++)
261 for (
size_t k = 0; k < blkSize; k++)
262 filter[indsG(j) * blkSize + k] = 1;
264 for (
size_t k = 0; k < blkSize; k++) {
265 LO row = i * blkSize + k;
267 A.getLocalRowView(row, inds, valsA);
269 size_t nnz = inds.
size();
273 #ifdef ASSUME_DIRECT_ACCESS_TO_ROW
276 filteredA.getLocalRowView(row, inds, vals1);
286 SC A_rowsum = ZERO, F_rowsum = ZERO;
287 for (
LO l = 0; l < (
LO)inds.
size(); l++)
288 A_rowsum += valsA[l];
290 if (lumping ==
false) {
291 for (
size_t j = 0; j < nnz; j++)
292 if (!filter[inds[j]])
299 for (
size_t j = 0; j < nnz; j++) {
300 if (filter[inds[j]]) {
301 if (inds[j] == row) {
308 diagExtra += vals[j];
318 if (diagIndex != -1) {
320 vals[diagIndex] += diagExtra;
321 if (dirichletThresh >= 0.0 && TST::real(vals[diagIndex]) <= dirichletThresh) {
323 for (
LO l = 0; l < (
LO)nnz; l++)
326 vals[diagIndex] = TST::one();
331 #ifndef ASSUME_DIRECT_ACCESS_TO_ROW
334 filteredA.replaceLocalValues(row, inds, vals);
339 for (
size_t j = 0; j < as<size_t>(indsG.length); j++)
340 for (
size_t k = 0; k < blkSize; k++)
341 filter[indsG(j) * blkSize + k] = 0;
345 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
347 BuildNew(
const Matrix& A,
const LWGraph& G,
const bool lumping,
double dirichletThresh, Matrix& filteredA)
const {
351 size_t blkSize = A.GetFixedBlockSize();
361 for (
size_t i = 0; i < numGRows; i++) {
364 for (
size_t j = 0; j < as<size_t>(indsG.length); j++)
365 for (
size_t k = 0; k < blkSize; k++)
366 filter[indsG(j) * blkSize + k] = 1;
368 for (
size_t k = 0; k < blkSize; k++) {
369 LO row = i * blkSize + k;
371 A.getLocalRowView(row, indsA, valsA);
373 size_t nnz = indsA.
size();
381 if (lumping ==
false) {
382 for (
size_t j = 0; j < nnz; j++)
383 if (filter[indsA[j]]) {
384 inds[numInds] = indsA[j];
385 vals[numInds] = valsA[j];
393 for (
size_t j = 0; j < nnz; j++) {
394 if (filter[indsA[j]]) {
395 inds[numInds] = indsA[j];
396 vals[numInds] = valsA[j];
399 if (inds[numInds] == row)
405 diagExtra += valsA[j];
413 if (diagIndex != -1) {
414 vals[diagIndex] += diagExtra;
415 if (dirichletThresh >= 0.0 && TST::real(vals[diagIndex]) <= dirichletThresh) {
421 vals[diagIndex] = TST::one();
430 filteredA.insertLocalValues(row, inds, vals);
434 for (
size_t j = 0; j < as<size_t>(indsG.length); j++)
435 for (
size_t k = 0; k < blkSize; k++)
436 filter[indsG(j) * blkSize + k] = 0;
440 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
442 BuildNewUsingRootStencil(
const Matrix& A,
const LWGraph& G,
double dirichletThresh,
Level& currentLevel, Matrix& filteredA,
bool use_spread_lumping,
double DdomAllowGrowthRate,
double DdomCap)
const {
444 using Teuchos::arcp_const_cast;
450 RCP<Aggregates> aggregates = Get<RCP<Aggregates> >(currentLevel,
"Aggregates");
455 size_t blkSize = A.GetFixedBlockSize();
456 size_t numRows = A.getMap()->getLocalNumElements();
467 RCP<CrsMatrix> filteredAcrs =
dynamic_cast<const CrsMatrixWrap*
>(&filteredA)->getCrsMatrix();
468 filteredAcrs->getAllValues(rowptr, inds, vals_const);
469 vals = arcp_const_cast<
SC>(vals_const);
487 typename Aggregates::LO_view::HostMirror ptr_h, nodes_h, unaggregated_h;
490 nodesInAgg.ptr_h = Kokkos::create_mirror_view(nodesInAgg.ptr);
491 nodesInAgg.nodes_h = Kokkos::create_mirror_view(nodesInAgg.nodes);
492 nodesInAgg.unaggregated_h = Kokkos::create_mirror_view(nodesInAgg.unaggregated);
493 Kokkos::deep_copy(nodesInAgg.ptr_h, nodesInAgg.ptr);
494 Kokkos::deep_copy(nodesInAgg.nodes_h, nodesInAgg.nodes);
495 Kokkos::deep_copy(nodesInAgg.unaggregated_h, nodesInAgg.unaggregated);
502 for (
LO i = 0; i < (
LO)nodesInAgg.unaggregated_h.extent(0); i++) {
503 for (
LO m = 0; m < (
LO)blkSize; m++) {
504 LO row = amalgInfo->ComputeLocalDOF(nodesInAgg.unaggregated_h(i), m);
505 if (row >= (
LO)numRows)
continue;
506 size_t index_start = rowptr[row];
507 A.getLocalRowView(row, indsA, valsA);
508 for (
LO k = 0; k < (
LO)indsA.
size(); k++) {
509 if (row == indsA[k]) {
510 vals[index_start + k] = ONE;
513 vals[index_start + k] = ZERO;
518 std::vector<LO> badCount(numAggs, 0);
522 for (
LO i = 0; i < numAggs; i++)
523 maxAggSize = std::max(maxAggSize, nodesInAgg.ptr_h(i + 1) - nodesInAgg.ptr_h(i));
529 size_t numNewDrops = 0;
530 size_t numOldDrops = 0;
531 size_t numFixedDiags = 0;
532 size_t numSymDrops = 0;
534 for (
LO i = 0; i < numAggs; i++) {
535 LO numNodesInAggregate = nodesInAgg.ptr_h(i + 1) - nodesInAgg.ptr_h(i);
536 if (numNodesInAggregate == 0)
continue;
539 LO root_node = INVALID;
540 for (
LO k = nodesInAgg.ptr_h(i); k < nodesInAgg.ptr_h(i + 1); k++) {
541 if (aggregates->
IsRoot(nodesInAgg.nodes_h(k))) {
542 root_node = nodesInAgg.nodes_h(k);
554 goodAggNeighbors.resize(0);
555 for (
LO k = 0; k < (
LO)goodNodeNeighbors.length; k++) {
556 goodAggNeighbors.push_back(vertex2AggId[goodNodeNeighbors(k)]);
563 badAggNeighbors.resize(0);
564 for (
LO j = 0; j < (
LO)blkSize; j++) {
565 LO row = amalgInfo->ComputeLocalDOF(root_node, j);
566 if (row >= (
LO)numRows)
continue;
567 A.getLocalRowView(row, indsA, valsA);
568 for (
LO k = 0; k < (
LO)indsA.
size(); k++) {
569 if ((indsA[k] < (
LO)numRows) && (TST::magnitude(valsA[k]) != TST::magnitude(ZERO))) {
570 LO node = amalgInfo->ComputeLocalNode(indsA[k]);
571 LO agg = vertex2AggId[node];
572 if (!std::binary_search(goodAggNeighbors.begin(), goodAggNeighbors.end(), agg))
573 badAggNeighbors.push_back(agg);
582 for (
LO k = nodesInAgg.ptr_h(i); k < nodesInAgg.ptr_h(i + 1); k++) {
584 for (
LO kk = 0; kk < nodeNeighbors.length; kk++) {
585 if ((vertex2AggId[nodeNeighbors(kk)] >= 0) && (vertex2AggId[nodeNeighbors(kk)] < numAggs))
586 (badCount[vertex2AggId[nodeNeighbors(kk)]])++;
590 reallyBadAggNeighbors.resize(0);
591 for (
LO k = 0; k < (
LO)badAggNeighbors.size(); k++) {
592 if (badCount[badAggNeighbors[k]] <= 1) reallyBadAggNeighbors.push_back(badAggNeighbors[k]);
594 for (
LO k = nodesInAgg.ptr_h(i); k < nodesInAgg.ptr_h(i + 1); k++) {
596 for (
LO kk = 0; kk < nodeNeighbors.length; kk++) {
597 if ((vertex2AggId[nodeNeighbors(kk)] >= 0) && (vertex2AggId[nodeNeighbors(kk)] < numAggs))
598 badCount[vertex2AggId[nodeNeighbors(kk)]] = 0;
604 for (
LO b = 0; b < (
LO)reallyBadAggNeighbors.size(); b++) {
605 LO bad_agg = reallyBadAggNeighbors[b];
606 for (
LO k = nodesInAgg.ptr_h(bad_agg); k < nodesInAgg.ptr_h(bad_agg + 1); k++) {
607 LO bad_node = nodesInAgg.nodes_h(k);
608 for (
LO j = 0; j < (
LO)blkSize; j++) {
609 LO bad_row = amalgInfo->ComputeLocalDOF(bad_node, j);
610 if (bad_row >= (
LO)numRows)
continue;
611 size_t index_start = rowptr[bad_row];
612 A.getLocalRowView(bad_row, indsA, valsA);
613 for (
LO l = 0; l < (
LO)indsA.
size(); l++) {
614 if (indsA[l] < (
LO)numRows && vertex2AggId[amalgInfo->ComputeLocalNode(indsA[l])] == i && vals_dropped_indicator[index_start + l] ==
false) {
615 vals_dropped_indicator[index_start + l] =
true;
616 vals[index_start + l] = ZERO;
617 diagExtra[bad_row] += valsA[l];
628 for (
LO k = nodesInAgg.ptr_h(i); k < nodesInAgg.ptr_h(i + 1); k++) {
629 LO row_node = nodesInAgg.nodes_h(k);
633 for (
size_t j = 0; j < as<size_t>(indsG.length); j++)
634 filter[indsG(j)] =
true;
636 for (
LO m = 0; m < (
LO)blkSize; m++) {
637 LO row = amalgInfo->ComputeLocalDOF(row_node, m);
638 if (row >= (
LO)numRows)
continue;
639 size_t index_start = rowptr[row];
640 A.getLocalRowView(row, indsA, valsA);
642 for (
LO l = 0; l < (
LO)indsA.
size(); l++) {
643 int col_node = amalgInfo->ComputeLocalNode(indsA[l]);
644 bool is_good = filter[col_node];
645 if (indsA[l] == row) {
647 vals[index_start + l] = valsA[l];
652 if (vals_dropped_indicator[index_start + l] ==
true) {
662 if (is_good && indsA[l] < (
LO)numRows) {
663 int agg = vertex2AggId[col_node];
664 if (std::binary_search(reallyBadAggNeighbors.begin(), reallyBadAggNeighbors.end(), agg))
669 vals[index_start + l] = valsA[l];
671 if (!filter[col_node])
675 diagExtra[row] += valsA[l];
676 vals[index_start + l] = ZERO;
677 vals_dropped_indicator[index_start + l] =
true;
684 for (
size_t j = 0; j < as<size_t>(indsG.length); j++)
685 filter[indsG(j)] =
false;
690 if (!use_spread_lumping) {
692 for (
LO row = 0; row < (
LO)numRows; row++) {
693 if (diagIndex[row] != INVALID) {
694 size_t index_start = rowptr[row];
695 size_t diagIndexInMatrix = index_start + diagIndex[row];
697 vals[diagIndexInMatrix] += diagExtra[row];
698 SC A_rowsum = ZERO, A_absrowsum = ZERO, F_rowsum = ZERO;
700 if ((dirichletThresh >= 0.0 && TST::real(vals[diagIndexInMatrix]) <= dirichletThresh) || TST::real(vals[diagIndexInMatrix]) == ZERO) {
702 A.getLocalRowView(row, indsA, valsA);
706 for (
LO l = 0; l < (
LO)indsA.
size(); l++) {
707 A_rowsum += valsA[l];
708 A_absrowsum += std::abs(valsA[l]);
710 for (
LO l = 0; l < (
LO)indsA.
size(); l++)
711 F_rowsum += vals[index_start + l];
725 for (
size_t l = rowptr[row]; l < rowptr[row + 1]; l++) {
728 vals[diagIndexInMatrix] = TST::one();
732 GetOStream(
Runtime0) <<
"WARNING: Row " << row <<
" has no diagonal " << std::endl;
738 for (
LO row = 0; row < (
LO)numRows; row++) {
739 filteredA.replaceLocalValues(row, inds(rowptr[row], rowptr[row + 1] - rowptr[row]), vals(rowptr[row], rowptr[row + 1] - rowptr[row]));
741 if (use_spread_lumping) ExperimentalLumping(A, filteredA, DdomAllowGrowthRate, DdomCap);
743 size_t g_newDrops = 0, g_oldDrops = 0, g_fixedDiags = 0;
745 MueLu_sumAll(A.getRowMap()->getComm(), numNewDrops, g_newDrops);
746 MueLu_sumAll(A.getRowMap()->getComm(), numOldDrops, g_oldDrops);
747 MueLu_sumAll(A.getRowMap()->getComm(), numFixedDiags, g_fixedDiags);
748 GetOStream(
Runtime0) <<
"Filtering out " << g_newDrops <<
" edges, in addition to the " << g_oldDrops <<
" edges dropped earlier" << std::endl;
749 GetOStream(
Runtime0) <<
"Fixing " << g_fixedDiags <<
" zero diagonal values" << std::endl;
763 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
767 SC zero = TST::zero();
775 SC PosOffSum, NegOffSum, PosOffDropSum, NegOffDropSum;
776 SC diag, gamma, alpha;
777 LO NumPosKept, NumNegKept;
781 SC PosFilteredSum, NegFilteredSum;
784 SC rho = as<Scalar>(irho);
785 SC rho2 = as<Scalar>(irho2);
787 for (
LO row = 0; row < (
LO)A.getRowMap()->getLocalNumElements(); row++) {
788 noLumpDdom = as<Scalar>(10000.0);
802 A.getLocalRowView(row, inds, vals);
803 size_t nnz = inds.
size();
804 if (nnz == 0)
continue;
805 filteredA.getLocalRowView(row, finds, tvals);
809 LO diagIndex = -1, fdiagIndex = -1;
813 PosOffDropSum = zero;
814 NegOffDropSum = zero;
820 for (
size_t j = 0; j < nnz; j++) {
821 if (inds[j] == row) {
825 if (TST::real(vals[j]) > TST::real(zero))
826 PosOffSum += vals[j];
828 NegOffSum += vals[j];
831 PosOffDropSum = PosOffSum;
832 NegOffDropSum = NegOffSum;
836 for (
size_t jj = 0; jj < (size_t)finds.
size(); jj++) {
837 while (inds[j] != finds[jj]) j++;
839 if (finds[jj] == row)
842 if (TST::real(vals[j]) > TST::real(zero)) {
843 PosOffDropSum -= fvals[jj];
844 if (TST::real(fvals[jj]) != TST::real(zero)) NumPosKept++;
846 NegOffDropSum -= fvals[jj];
847 if (TST::real(fvals[jj]) != TST::real(zero)) NumNegKept++;
853 if (TST::magnitude(diag) != TST::magnitude(zero))
854 noLumpDdom = (PosOffSum - NegOffSum) / diag;
859 Target = rho * noLumpDdom;
860 if (TST::magnitude(Target) <= TST::magnitude(rho)) Target = rho2;
862 PosFilteredSum = PosOffSum - PosOffDropSum;
863 NegFilteredSum = NegOffSum - NegOffDropSum;
873 diag += PosOffDropSum;
876 gamma = -NegOffDropSum - PosFilteredSum;
878 if (TST::real(gamma) < TST::real(zero)) {
886 if (fdiagIndex != -1) fvals[fdiagIndex] = diag;
888 for (
LO jj = 0; jj < (
LO)finds.
size(); jj++) {
889 while (inds[j] != finds[jj]) j++;
891 if ((j != diagIndex) && (TST::real(vals[j]) > TST::real(zero)) && (TST::magnitude(fvals[jj]) != TST::magnitude(zero)))
892 fvals[jj] = -gamma * (vals[j] / PosFilteredSum);
904 bool flipPosOffDiagsToNeg =
false;
916 if ((TST::real(diag) > TST::real(gamma)) &&
917 (TST::real((-NegFilteredSum) / (diag - gamma)) <= TST::real(Target))) {
924 if (fdiagIndex != -1) fvals[fdiagIndex] = diag - gamma;
925 }
else if (NumNegKept > 0) {
931 numer = -NegFilteredSum - Target * (diag - gamma);
932 denom = gamma * (Target - TST::one());
954 if (TST::magnitude(denom) < TST::magnitude(numer))
957 alpha = numer / denom;
958 if (TST::real(alpha) < TST::real(zero)) alpha = zero;
959 if (TST::real(diag) < TST::real((one - alpha) * gamma)) alpha = TST::one();
963 if (fdiagIndex != -1) fvals[fdiagIndex] = diag - (one - alpha) * gamma;
973 SC temp = (NegFilteredSum + alpha * gamma) / NegFilteredSum;
975 for (
LO jj = 0; jj < (
LO)finds.
size(); jj++) {
976 while (inds[j] != finds[jj]) j++;
978 if ((jj != fdiagIndex) && (TST::magnitude(fvals[jj]) != TST::magnitude(zero)) &&
979 (TST::real(vals[j]) < TST::real(zero)))
980 fvals[jj] = temp * vals[j];
985 if (NumPosKept > 0) {
988 flipPosOffDiagsToNeg =
true;
991 for (
LO jj = 0; jj < (
LO)finds.
size(); jj++) {
992 while (inds[j] != finds[jj]) j++;
994 if ((j != diagIndex) && (TST::magnitude(fvals[jj]) != TST::magnitude(zero)) &&
995 (TST::real(vals[j]) > TST::real(zero)))
996 fvals[jj] = -gamma / ((
SC)NumPosKept);
1001 if (!flipPosOffDiagsToNeg) {
1006 for (
LO jj = 0; jj < (
LO)finds.
size(); jj++) {
1007 while (inds[j] != finds[jj]) j++;
1009 if ((jj != fdiagIndex) && (TST::real(vals[j]) > TST::real(zero))) fvals[jj] = zero;
1019 #endif // MUELU_FILTEREDAFACTORY_DEF_HPP
void sort_and_unique(T &array)
void BuildReuse(const Matrix &A, const LWGraph &G, const bool lumping, double dirichletThresh, Matrix &filteredA) const
#define MueLu_sumAll(rcpComm, in, out)
static bool MapsAreNested(const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &rowMap, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &colMap)
KOKKOS_INLINE_FUNCTION LO GetNumAggregates() const
RCP< const ParameterList > GetValidParameterList() const
Return a const parameter list of valid parameters that setParameterList() will accept.
T & get(const std::string &name, T def_value)
ParameterList & set(std::string const &name, T const &value, std::string const &docString="", RCP< const ParameterEntryValidator > const &validator=null)
Timer to be used in factories. Similar to Monitor but with additional timers.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
static void Write(const std::string &fileName, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &M)
One-liner description of what is happening.
KOKKOS_INLINE_FUNCTION size_type GetNodeNumVertices() const
Return number of graph vertices.
void Build(Level ¤tLevel) const
Build method.
KOKKOS_INLINE_FUNCTION size_type getLocalMaxNumRowEntries() const
Returns the maximum number of entries across all rows/columns on this node.
bool isParameter(const std::string &name) const
#define MUELU_FILTEREDAFACTORY_LOTS_OF_PRINTING
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Class that holds all level-specific information.
void ComputeNodesInAggregate(LO_view &aggPtr, LO_view &aggNodes, LO_view &unaggregated) const
Generates a compressed list of nodes in each aggregate, where the entries in aggNodes[aggPtr[i]] up t...
const RCP< LOMultiVector > & GetVertex2AggId() const
Returns constant vector that maps local node IDs to local aggregates IDs.
void resize(size_type new_size, const value_type &x=value_type())
void ExperimentalLumping(const Matrix &A, Matrix &filteredA, double rho, double rho2) const
KOKKOS_INLINE_FUNCTION neighbor_vertices_type getNeighborVertices(LO i) const
Return the list of vertices adjacent to the vertex 'v'.
const RCP< const Map > GetImportMap() const
Return overlapping import map (nodes).
#define SET_VALID_ENTRY(name)
Kokkos::View< local_ordinal_type *, device_type > LO_view
Lightweight MueLu representation of a compressed row storage graph.
bool IsRoot(LO i) const
Returns true if node with given local node id is marked to be a root node.
void BuildNew(const Matrix &A, const LWGraph &G, const bool lumping, double dirichletThresh, Matrix &filteredA) const
void DeclareInput(Level ¤tLevel) const
Input.
Exception throws to report errors in the internal logical of the program.
void BuildNewUsingRootStencil(const Matrix &A, const LWGraph &G, double dirichletThresh, Level ¤tLevel, Matrix &filteredA, bool use_spread_lumping, double DdomAllowGrowthRate, double DdomCap) const