299 using MatrixType = Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>;
300 using GraphType = Xpetra::CrsGraph<LocalOrdinal, GlobalOrdinal, Node>;
301 using local_matrix_type =
typename MatrixType::local_matrix_device_type;
302 using local_graph_type =
typename GraphType::local_graph_device_type;
303 using rowptr_type =
typename local_graph_type::row_map_type::non_const_type;
304 using entries_type =
typename local_graph_type::entries_type::non_const_type;
305 using values_type =
typename local_matrix_type::values_type::non_const_type;
306 using device_type =
typename Node::device_type;
307 using memory_space =
typename device_type::memory_space;
308 using results_view_type = Kokkos::View<DecisionType*, memory_space>;
309 using magnitudeType =
typename Teuchos::ScalarTraits<Scalar>::magnitudeType;
310 using doubleMultiVector = Xpetra::MultiVector<magnitudeType, LO, GO, NO>;
312 typedef Teuchos::ScalarTraits<Scalar> STS;
313 const magnitudeType zero = Teuchos::ScalarTraits<magnitudeType>::zero();
317 const bool needToBuildFilteredA = currentLevel.
IsRequested(
"A",
this);
324 const magnitudeType dirichletThreshold = STS::magnitude(as<SC>(pL.get<
double>(
"aggregation: Dirichlet threshold")));
325 const magnitudeType rowSumTol = as<magnitudeType>(pL.get<
double>(
"aggregation: row sum drop tol"));
329 bool useBlocking = pL.get<
bool>(
"aggregation: use blocking");
330 std::string droppingMethod = pL.get<std::string>(
"aggregation: drop scheme");
331 std::string socUsesMatrix = pL.get<std::string>(
"aggregation: strength-of-connection: matrix");
332 std::string socUsesMeasure = pL.get<std::string>(
"aggregation: strength-of-connection: measure");
333 std::string distanceLaplacianMetric = pL.get<std::string>(
"aggregation: distance laplacian metric");
334 std::string MinvScheme = pL.get<std::string>(
"aggregation: Minv scheme");
335 std::string symmetrizeDroppedGraph = pL.get<std::string>(
"aggregation: symmetrize graph after dropping");
336 std::string symmetrizeColoringGraph = pL.get<std::string>(
"aggregation: symmetrize color graph");
337 magnitudeType threshold;
339 if (pL.get<
bool>(
"aggregation: use ml scaling of drop tol"))
340 threshold = pL.get<
double>(
"aggregation: drop tol") / pow(2.0, currentLevel.
GetLevelID());
342 threshold = as<magnitudeType>(pL.get<
double>(
"aggregation: drop tol"));
343 bool aggregationMayCreateDirichlet = pL.get<
bool>(
"aggregation: dropping may create Dirichlet");
346 const bool reuseGraph = pL.get<
bool>(
"filtered matrix: reuse graph") && needToBuildFilteredA;
347 const bool reuseEigenvalue = pL.get<
bool>(
"filtered matrix: reuse eigenvalue");
349 const bool useRootStencil = pL.get<
bool>(
"filtered matrix: use root stencil");
350 const bool useSpreadLumping = pL.get<
bool>(
"filtered matrix: use spread lumping");
351 const std::string lumpingChoiceString = pL.get<std::string>(
"filtered matrix: lumping choice");
353 if (needToBuildFilteredA) {
354 if (lumpingChoiceString ==
"diag lumping")
356 else if (lumpingChoiceString ==
"distributed lumping")
360 const magnitudeType filteringDirichletThreshold = as<magnitudeType>(pL.get<
double>(
"filtered matrix: Dirichlet threshold"));
363 bool generateColoringGraph = pL.get<
bool>(
"aggregation: coloring: use color graph");
364 const bool localizeColoringGraph = pL.get<
bool>(
"aggregation: coloring: localize color graph");
366#ifdef HAVE_MUELU_COALESCEDROP_ALLOW_OLD_PARAMETERS
367 translateOldAlgoParam(pL, droppingMethod, useBlocking, socUsesMatrix, socUsesMeasure, symmetrizeDroppedGraph, generateColoringGraph, threshold, lumpingChoice);
371 std::stringstream ss;
372 ss <<
"dropping scheme = \"" << droppingMethod <<
"\", strength-of-connection measure = \"" << socUsesMeasure <<
"\", strength-of-connection matrix = \"" << socUsesMatrix <<
"\", ";
373 if (socUsesMatrix ==
"distance laplacian")
374 ss <<
"distance laplacian metric = \"" << distanceLaplacianMetric <<
"\", ";
375 ss <<
"threshold = " << threshold <<
", blocksize = " << A->GetFixedBlockSize() <<
", useBlocking = " << useBlocking;
376 ss <<
", symmetrizeDroppedGraph = " << symmetrizeDroppedGraph << std::endl;
381 TEUCHOS_ASSERT(!useRootStencil);
382 TEUCHOS_ASSERT(!useSpreadLumping);
384 if (droppingMethod ==
"cut-drop")
385 TEUCHOS_TEST_FOR_EXCEPTION(threshold > 1.0,
Exceptions::RuntimeError,
"For cut-drop algorithms, \"aggregation: drop tol\" = " << threshold <<
", needs to be <= 1.0");
400 if (threshold != zero) {
401 if ((socUsesMatrix ==
"A") || (socUsesMatrix ==
"MinvA")) {
403 if (socUsesMatrix ==
"A")
405 else if (socUsesMatrix ==
"MinvA") {
406 bool storeMinvOnLevel =
false, storeMinvAOnLevel =
false;
407 if (pL.isSublist(
"project auxiliary matrices")) {
408 auto projectList = pL.sublist(
"project auxiliary matrices");
409 if (projectList.isParameter(
"MinvA"))
410 storeMinvAOnLevel =
true;
412 if (projectList.isParameter(
"Minv"))
413 storeMinvOnLevel =
true;
415 storeMinvAOnLevel =
true;
418 storeMinvAOnLevel =
true;
424 bool MueLu_Minv =
IsAvailable(currentLevel,
"Minv");
426 if (MueLu_Minv || User_Minv) {
440#ifdef moreExperimentsToSeeIfHelpful
444 for (
size_t iii = 0; iii < A->getLocalNumRows(); iii++)
445 if (boundaryNodes[iii]) nAbc++;
448 for (
size_t iii = 0; iii < M->getLocalNumRows(); iii++)
449 if (MbcBefore[iii]) nMbcBefore++;
450 GetOStream(
Statistics1) <<
"MueLu_CoalesceDropFactory_kokkos_def: # A bcs = " << nAbc <<
", # M bcs before MueLu enforcement = " << nMbcBefore;
456 for (
size_t iii = 0; iii < M->getLocalNumRows(); iii++)
457 if (MbcAfter[iii]) nMbcAfter++;
466 if (storeMinvOnLevel) currentLevel.
Set(
"Minv", Minv);
470 A_drop = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::BuildCopy(A);
471 auto params = Teuchos::rcp(
new Teuchos::ParameterList());
472 params->set(
"MM Throw For Non-Existent Entries",
false);
473 A_drop = Xpetra::MatrixMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Multiply(*Minv,
false, *A,
false, A_drop,
GetOStream(
Statistics2),
true,
true, std::string(
"MinvA"), params);
481 if (storeMinvAOnLevel) currentLevel.
Set(
"MinvA", A_drop);
487 auto crsA = toCrsMatrix(A);
488 auto lclA = crsA->getLocalMatrixDevice();
508 if (rowSumTol <= 0.) {
541 auto filtered_rowptr = rowptr_type(
"filtered_rowptr", lclA.numRows() + 1);
545 auto results = results_view_type(
"results", lclA.nnz());
549 if (threshold != zero) {
550 if ((socUsesMatrix ==
"A") || (socUsesMatrix ==
"MinvA")) {
551 if (socUsesMeasure ==
"unscaled") {
552 ScalarDroppingClassical<Scalar, LocalOrdinal, GlobalOrdinal, Node, Misc::UnscaledMeasure>::runDroppingFunctors_on_A(*A_drop, results, filtered_rowptr, nnz_filtered, boundaryNodes, droppingMethod, threshold,
553 aggregationMayCreateDirichlet, symmetrizeDroppedGraph, useBlocking, currentLevel, *
this);
554 }
else if (socUsesMeasure ==
"smoothed aggregation") {
555 ScalarDroppingClassical<Scalar, LocalOrdinal, GlobalOrdinal, Node, Misc::SmoothedAggregationMeasure>::runDroppingFunctors_on_A(*A_drop, results, filtered_rowptr, nnz_filtered, boundaryNodes, droppingMethod, threshold,
556 aggregationMayCreateDirichlet, symmetrizeDroppedGraph, useBlocking, currentLevel, *
this);
557 }
else if (socUsesMeasure ==
"signed ruge-stueben") {
558 ScalarDroppingClassical<Scalar, LocalOrdinal, GlobalOrdinal, Node, Misc::SignedRugeStuebenMeasure>::runDroppingFunctors_on_A(*A_drop, results, filtered_rowptr, nnz_filtered, boundaryNodes, droppingMethod, threshold,
559 aggregationMayCreateDirichlet, symmetrizeDroppedGraph, useBlocking, currentLevel, *
this);
560 }
else if (socUsesMeasure ==
"signed smoothed aggregation") {
561 ScalarDroppingClassical<Scalar, LocalOrdinal, GlobalOrdinal, Node, Misc::SignedSmoothedAggregationMeasure>::runDroppingFunctors_on_A(*A_drop, results, filtered_rowptr, nnz_filtered, boundaryNodes, droppingMethod, threshold,
562 aggregationMayCreateDirichlet, symmetrizeDroppedGraph, useBlocking, currentLevel, *
this);
564 }
else if (socUsesMatrix ==
"distance laplacian") {
566 if (socUsesMeasure ==
"unscaled") {
567 ScalarDroppingDistanceLaplacian<Scalar, LocalOrdinal, GlobalOrdinal, Node, Misc::UnscaledMeasure>::runDroppingFunctors_on_dlap(*A, results, filtered_rowptr, nnz_filtered, boundaryNodes, droppingMethod, threshold, aggregationMayCreateDirichlet, symmetrizeDroppedGraph, useBlocking, distanceLaplacianMetric, currentLevel, *
this);
568 }
else if (socUsesMeasure ==
"smoothed aggregation") {
569 ScalarDroppingDistanceLaplacian<Scalar, LocalOrdinal, GlobalOrdinal, Node, Misc::SmoothedAggregationMeasure>::runDroppingFunctors_on_dlap(*A, results, filtered_rowptr, nnz_filtered, boundaryNodes, droppingMethod, threshold, aggregationMayCreateDirichlet, symmetrizeDroppedGraph, useBlocking, distanceLaplacianMetric, currentLevel, *
this);
570 }
else if (socUsesMeasure ==
"signed ruge-stueben") {
571 ScalarDroppingDistanceLaplacian<Scalar, LocalOrdinal, GlobalOrdinal, Node, Misc::SignedRugeStuebenMeasure>::runDroppingFunctors_on_dlap(*A, results, filtered_rowptr, nnz_filtered, boundaryNodes, droppingMethod, threshold, aggregationMayCreateDirichlet, symmetrizeDroppedGraph, useBlocking, distanceLaplacianMetric, currentLevel, *
this);
572 }
else if (socUsesMeasure ==
"signed smoothed aggregation") {
573 ScalarDroppingDistanceLaplacian<Scalar, LocalOrdinal, GlobalOrdinal, Node, Misc::SignedSmoothedAggregationMeasure>::runDroppingFunctors_on_dlap(*A, results, filtered_rowptr, nnz_filtered, boundaryNodes, droppingMethod, threshold, aggregationMayCreateDirichlet, symmetrizeDroppedGraph, useBlocking, distanceLaplacianMetric, currentLevel, *
this);
577 Kokkos::deep_copy(results,
KEEP);
579 if (symmetrizeDroppedGraph !=
"no symmetrization") {
581 ScalarDroppingBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::template runDroppingFunctors<>(*A, results, filtered_rowptr, nnz_filtered, useBlocking, currentLevel, *
this, drop_boundaries);
584 ScalarDroppingBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::template runDroppingFunctors<>(*A, results, filtered_rowptr, nnz_filtered, useBlocking, currentLevel, *
this, no_op);
596 if (symmetrizeDroppedGraph ==
"strong wins") {
598 ScalarDroppingBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::template runDroppingFunctors<>(*A, results, filtered_rowptr, nnz_filtered, useBlocking, currentLevel, *
this, symmetrize);
599 }
else if ((symmetrizeDroppedGraph ==
"weak wins") && (!pL.get<
bool>(
"aggregation: dropping may create Dirichlet"))) {
601 ScalarDroppingBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::template runDroppingFunctors<>(*A, results, filtered_rowptr, nnz_filtered, useBlocking, currentLevel, *
this, symmetrize);
602 }
else if (symmetrizeDroppedGraph ==
"weak wins") {
604 ScalarDroppingBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::template runDroppingFunctors<>(*A, results, filtered_rowptr, nnz_filtered, useBlocking, currentLevel, *
this, symmetrize);
607 GO numDropped = lclA.nnz() - nnz_filtered;
609 Teuchos::reduceAll(*A->getRowMap()->getComm(), Teuchos::REDUCE_SUM, 1, &numDropped, &numGlobalDropped);
617 RCP<LWGraph_kokkos> graph;
618 RCP<Matrix> filteredA;
619 if (numGlobalDropped > 0) {
622 local_graph_type lclGraph;
623 local_matrix_type lclFilteredA;
624 auto colidx = entries_type(
"entries", nnz_filtered);
625 lclGraph = local_graph_type(colidx, filtered_rowptr);
628 filteredA = MatrixFactory::BuildCopy(A);
629 lclFilteredA = filteredA->getLocalMatrixDevice();
630 }
else if (needToBuildFilteredA) {
631 auto values = values_type(
"values", nnz_filtered);
632 lclFilteredA = local_matrix_type(
"filteredA", lclGraph, lclA.numCols());
638 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_lumped_reuse", range, fillFunctor);
642 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_lumped_noreuse", range, fillFunctor);
645 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_lumped_noreuse", range, fillFunctor);
651 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_unlumped_reuse", range, fillFunctor);
653 if (needToBuildFilteredA) {
655 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_unlumped_noreuse", range, fillFunctor);
658 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_unlumped_noreuse", range, fillFunctor);
663 if (needToBuildFilteredA) {
665 filteredA = MatrixFactory::Build(lclFilteredA, A->getRowMap(), A->getColMap(), A->getDomainMap(), A->getRangeMap());
666 filteredA->SetFixedBlockSize(A->GetFixedBlockSize());
668 if (reuseEigenvalue) {
673 filteredA->SetMaxEigenvalueEstimate(A->GetMaxEigenvalueEstimate());
675 filteredA->SetMaxEigenvalueEstimate(-Teuchos::ScalarTraits<SC>::one());
679 graph = rcp(
new LWGraph_kokkos(lclGraph, A->getRowMap(), A->getColMap(),
"amalgamated graph of A"));
680 graph->SetBoundaryNodeMap(boundaryNodes);
682 if (needToBuildFilteredA)
684 graph = rcp(
new LWGraph_kokkos(A->getCrsGraph()->getLocalGraphDevice(), A->getRowMap(), A->getColMap(),
"amalgamated graph of A"));
685 graph->SetBoundaryNodeMap(boundaryNodes);
689 if (generateColoringGraph) {
690 SubFactoryMonitor mColoringGraph(*
this,
"Construct coloring graph", currentLevel);
692 filtered_rowptr = rowptr_type(
"rowptr_coloring_graph", lclA.numRows() + 1);
693 if (localizeColoringGraph) {
695 ScalarDroppingBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::template runDroppingFunctors<>(*A, results, filtered_rowptr, nnz_filtered, useBlocking, currentLevel, *
this, drop_offrank);
697 if (symmetrizeColoringGraph ==
"strong wins") {
699 ScalarDroppingBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::template runDroppingFunctors<>(*A, results, filtered_rowptr, nnz_filtered, useBlocking, currentLevel, *
this, symmetrize);
701 if (!pL.get<
bool>(
"aggregation: dropping may create Dirichlet")) {
703 ScalarDroppingBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::template runDroppingFunctors<>(*A, results, filtered_rowptr, nnz_filtered, useBlocking, currentLevel, *
this, symmetrize);
706 ScalarDroppingBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::template runDroppingFunctors<>(*A, results, filtered_rowptr, nnz_filtered, useBlocking, currentLevel, *
this, symmetrize);
709 auto colidx = entries_type(
"entries_coloring_graph", nnz_filtered);
710 auto lclGraph = local_graph_type(colidx, filtered_rowptr);
712 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Construct_coloring_graph", range, graphConstruction);
714 auto colorGraph = rcp(
new LWGraph_kokkos(lclGraph, A->getRowMap(), A->getColMap(),
"coloring graph"));
715 Set(currentLevel,
"Coloring Graph", colorGraph);
718 if (needToBuildFilteredA && pL.get<
bool>(
"filtered matrix: count negative diagonals")) {
721 GetOStream(
Runtime0) <<
"CoalesceDrop: Negative diagonals: " << neg_count << std::endl;
725 Set(currentLevel,
"DofsPerNode", dofsPerNode);
726 Set(currentLevel,
"Graph", graph);
727 if (needToBuildFilteredA)
728 Set(currentLevel,
"A", filteredA);
730 return std::make_tuple(numDropped, (
GlobalOrdinal)nnz_filtered, boundaryNodes);
738 using MatrixType = Xpetra::CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>;
739 using GraphType = Xpetra::CrsGraph<LocalOrdinal, GlobalOrdinal, Node>;
740 using local_matrix_type =
typename MatrixType::local_matrix_device_type;
741 using local_graph_type =
typename GraphType::local_graph_device_type;
742 using rowptr_type =
typename local_graph_type::row_map_type::non_const_type;
743 using entries_type =
typename local_graph_type::entries_type::non_const_type;
744 using values_type =
typename local_matrix_type::values_type::non_const_type;
745 using device_type =
typename Node::device_type;
746 using memory_space =
typename device_type::memory_space;
747 using results_view_type = Kokkos::View<DecisionType*, memory_space>;
748 using magnitudeType =
typename Teuchos::ScalarTraits<Scalar>::magnitudeType;
749 using doubleMultiVector = Xpetra::MultiVector<magnitudeType, LO, GO, NO>;
751 typedef Teuchos::ScalarTraits<Scalar> STS;
752 const magnitudeType zero = Teuchos::ScalarTraits<magnitudeType>::zero();
756 const bool needToBuildFilteredA = currentLevel.
IsRequested(
"A",
this);
775 TEUCHOS_TEST_FOR_EXCEPTION(A->GetFixedBlockSize() % A->GetStorageBlockSize() != 0,
Exceptions::RuntimeError,
"A->GetFixedBlockSize() needs to be a multiple of A->GetStorageBlockSize()");
776 LO blkSize = A->GetFixedBlockSize() / A->GetStorageBlockSize();
780 const RCP<const Map> rowMap = A->getRowMap();
781 const RCP<const Map> colMap = A->getColMap();
788 const RCP<const Map> uniqueMap = amalInfo->getNodeRowMap();
789 const RCP<const Map> nonUniqueMap = amalInfo->getNodeColMap();
790 Array<LO> rowTranslationArray = *(amalInfo->getRowTranslation());
791 Array<LO> colTranslationArray = *(amalInfo->getColTranslation());
793 Kokkos::View<LO*, Kokkos::MemoryUnmanaged>
794 rowTranslationView(rowTranslationArray.getRawPtr(), rowTranslationArray.size());
795 Kokkos::View<LO*, Kokkos::MemoryUnmanaged>
796 colTranslationView(colTranslationArray.getRawPtr(), colTranslationArray.size());
799 LO numNodes = Teuchos::as<LocalOrdinal>(uniqueMap->getLocalNumElements());
800 typedef typename Kokkos::View<LocalOrdinal*, typename Node::device_type> id_translation_type;
801 id_translation_type rowTranslation(
"dofId2nodeId", rowTranslationArray.size());
802 id_translation_type colTranslation(
"ov_dofId2nodeId", colTranslationArray.size());
803 Kokkos::deep_copy(rowTranslation, rowTranslationView);
804 Kokkos::deep_copy(colTranslation, colTranslationView);
807 blkSize = A->GetFixedBlockSize();
810 if (A->IsView(
"stridedMaps") ==
true) {
811 const RCP<const Map> myMap = A->getRowMap(
"stridedMaps");
812 const RCP<const StridedMap> strMap = Teuchos::rcp_dynamic_cast<const StridedMap>(myMap);
814 blkSize = Teuchos::as<const LocalOrdinal>(strMap->getFixedBlockSize());
815 blkId = strMap->getStridedBlockId();
817 blkPartSize = Teuchos::as<LocalOrdinal>(strMap->getStridingData()[blkId]);
820 TEUCHOS_TEST_FOR_EXCEPTION(A->getRowMap()->getLocalNumElements() % blkPartSize != 0,
MueLu::Exceptions::RuntimeError,
"MueLu::CoalesceDropFactory: Number of local elements is " << A->getRowMap()->getLocalNumElements() <<
" but should be a multiple of " << blkPartSize);
827 const magnitudeType dirichletThreshold = STS::magnitude(as<SC>(pL.get<
double>(
"aggregation: Dirichlet threshold")));
828 const magnitudeType rowSumTol = as<magnitudeType>(pL.get<
double>(
"aggregation: row sum drop tol"));
830 const bool useGreedyDirichlet = pL.get<
bool>(
"aggregation: greedy Dirichlet");
831 TEUCHOS_TEST_FOR_EXCEPTION(rowSumTol > zero,
MueLu::Exceptions::RuntimeError,
"MueLu::CoalesceDropFactory: RowSum is not implemented for vectorial problems.");
834 bool useBlocking = pL.get<
bool>(
"aggregation: use blocking");
835 std::string droppingMethod = pL.get<std::string>(
"aggregation: drop scheme");
836 std::string socUsesMatrix = pL.get<std::string>(
"aggregation: strength-of-connection: matrix");
837 std::string socUsesMeasure = pL.get<std::string>(
"aggregation: strength-of-connection: measure");
838 std::string distanceLaplacianMetric = pL.get<std::string>(
"aggregation: distance laplacian metric");
839 std::string symmetrizeDroppedGraph = pL.get<std::string>(
"aggregation: symmetrize graph after dropping");
840 std::string symmetrizeColoringGraph = pL.get<std::string>(
"aggregation: symmetrize color graph");
841 magnitudeType threshold;
843 if (pL.get<
bool>(
"aggregation: use ml scaling of drop tol"))
844 threshold = pL.get<
double>(
"aggregation: drop tol") / pow(2.0, currentLevel.
GetLevelID());
846 threshold = as<magnitudeType>(pL.get<
double>(
"aggregation: drop tol"));
847 bool aggregationMayCreateDirichlet = pL.get<
bool>(
"aggregation: dropping may create Dirichlet");
850 const bool reuseGraph = pL.get<
bool>(
"filtered matrix: reuse graph") && needToBuildFilteredA;
851 const bool reuseEigenvalue = pL.get<
bool>(
"filtered matrix: reuse eigenvalue");
853 const bool useRootStencil = pL.get<
bool>(
"filtered matrix: use root stencil");
854 const bool useSpreadLumping = pL.get<
bool>(
"filtered matrix: use spread lumping");
855 const std::string lumpingChoiceString = pL.get<std::string>(
"filtered matrix: lumping choice");
857 if (needToBuildFilteredA) {
858 if (lumpingChoiceString ==
"diag lumping")
860 else if (lumpingChoiceString ==
"distributed lumping")
864 const magnitudeType filteringDirichletThreshold = as<magnitudeType>(pL.get<
double>(
"filtered matrix: Dirichlet threshold"));
867 bool generateColoringGraph = pL.get<
bool>(
"aggregation: coloring: use color graph");
868 const bool localizeColoringGraph = pL.get<
bool>(
"aggregation: coloring: localize color graph");
870#ifdef HAVE_MUELU_COALESCEDROP_ALLOW_OLD_PARAMETERS
871 translateOldAlgoParam(pL, droppingMethod, useBlocking, socUsesMatrix, socUsesMeasure, symmetrizeDroppedGraph, generateColoringGraph, threshold, lumpingChoice);
874 std::stringstream ss;
875 ss <<
"dropping scheme = \"" << droppingMethod <<
"\", strength-of-connection measure = \"" << socUsesMeasure <<
"\", strength-of-connection matrix = \"" << socUsesMatrix <<
"\", ";
876 if (socUsesMatrix ==
"distance laplacian")
877 ss <<
"distance laplacian metric = \"" << distanceLaplacianMetric <<
"\", ";
878 ss <<
"threshold = " << threshold <<
", blocksize = " << A->GetFixedBlockSize() <<
", useBlocking = " << useBlocking;
879 ss <<
", symmetrizeDroppedGraph = " << symmetrizeDroppedGraph << std::endl;
884 TEUCHOS_ASSERT(!useRootStencil);
885 TEUCHOS_ASSERT(!useSpreadLumping);
887 if (droppingMethod ==
"cut-drop")
888 TEUCHOS_TEST_FOR_EXCEPTION(threshold > 1.0,
Exceptions::RuntimeError,
"For cut-drop algorithms, \"aggregation: drop tol\" = " << threshold <<
", needs to be <= 1.0");
901 auto crsA = toCrsMatrix(A);
902 auto lclA = crsA->getLocalMatrixDevice();
917 if (useGreedyDirichlet) {
947 auto filtered_rowptr = rowptr_type(
"rowptr", lclA.numRows() + 1);
948 auto graph_rowptr = rowptr_type(
"rowptr", numNodes + 1);
950 Kokkos::pair<LocalOrdinal, LocalOrdinal> nnz = {0, 0};
953 auto results = results_view_type(
"results", lclA.nnz());
962 auto merged_rowptr = rowptr_type(
"rowptr", numNodes + 1);
966 Kokkos::parallel_scan(
"MergeCount", range, functor, nnz_merged);
968 local_graph_type lclMergedGraph;
969 auto colidx_merged = entries_type(
"entries", nnz_merged);
970 auto values_merged = values_type(
"values", nnz_merged);
972 local_matrix_type lclMergedA = local_matrix_type(
"mergedA",
973 numNodes, nonUniqueMap->getLocalNumElements(),
975 values_merged, merged_rowptr, colidx_merged);
978 Kokkos::parallel_for(
"MueLu::CoalesceDrop::MergeFill", range, fillFunctor);
980 mergedA = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(lclMergedA, uniqueMap, nonUniqueMap, uniqueMap, uniqueMap);
983 if (threshold != zero) {
984 if (socUsesMatrix ==
"A") {
985 if (socUsesMeasure ==
"unscaled") {
986 VectorDroppingClassical<Scalar, LocalOrdinal, GlobalOrdinal, Node, Misc::UnscaledMeasure>::runDroppingFunctors_on_A(*A, *mergedA, blkPartSize, rowTranslation, colTranslation, results, filtered_rowptr, graph_rowptr, nnz, boundaryNodes, droppingMethod, threshold, aggregationMayCreateDirichlet, symmetrizeDroppedGraph, useBlocking, currentLevel, *
this);
987 }
else if (socUsesMeasure ==
"smoothed aggregation") {
988 VectorDroppingClassical<Scalar, LocalOrdinal, GlobalOrdinal, Node, Misc::SmoothedAggregationMeasure>::runDroppingFunctors_on_A(*A, *mergedA, blkPartSize, rowTranslation, colTranslation, results, filtered_rowptr, graph_rowptr, nnz, boundaryNodes, droppingMethod, threshold, aggregationMayCreateDirichlet, symmetrizeDroppedGraph, useBlocking, currentLevel, *
this);
989 }
else if (socUsesMeasure ==
"signed ruge-stueben") {
990 VectorDroppingClassical<Scalar, LocalOrdinal, GlobalOrdinal, Node, Misc::SignedRugeStuebenMeasure>::runDroppingFunctors_on_A(*A, *mergedA, blkPartSize, rowTranslation, colTranslation, results, filtered_rowptr, graph_rowptr, nnz, boundaryNodes, droppingMethod, threshold, aggregationMayCreateDirichlet, symmetrizeDroppedGraph, useBlocking, currentLevel, *
this);
991 }
else if (socUsesMeasure ==
"signed smoothed aggregation") {
992 VectorDroppingClassical<Scalar, LocalOrdinal, GlobalOrdinal, Node, Misc::SignedSmoothedAggregationMeasure>::runDroppingFunctors_on_A(*A, *mergedA, blkPartSize, rowTranslation, colTranslation, results, filtered_rowptr, graph_rowptr, nnz, boundaryNodes, droppingMethod, threshold, aggregationMayCreateDirichlet, symmetrizeDroppedGraph, useBlocking, currentLevel, *
this);
994 }
else if (socUsesMatrix ==
"distance laplacian") {
997 Array<double> dlap_weights = pL.get<Array<double>>(
"aggregation: distance laplacian directional weights");
998 LocalOrdinal interleaved_blocksize = as<LocalOrdinal>(pL.get<
int>(
"aggregation: block diagonal: interleaved blocksize"));
999 if (socUsesMeasure ==
"distance laplacian") {
1000 LO dim = (LO)coords->getNumVectors();
1002 bool non_unity =
false;
1003 for (LO i = 0; !non_unity && i < (LO)dlap_weights.size(); i++) {
1004 if (dlap_weights[i] != 1.0) {
1009 if ((LO)dlap_weights.size() == dim) {
1010 distanceLaplacianMetric =
"weighted";
1011 }
else if ((LO)dlap_weights.size() == interleaved_blocksize * dim)
1012 distanceLaplacianMetric =
"block weighted";
1015 "length of 'aggregation: distance laplacian directional weights' must equal the coordinate dimension OR the coordinate dimension times the blocksize");
1022 if (socUsesMeasure ==
"unscaled") {
1023 VectorDroppingDistanceLaplacian<Scalar, LocalOrdinal, GlobalOrdinal, Node, Misc::UnscaledMeasure>::runDroppingFunctors_on_dlap(*A, *mergedA, blkPartSize, rowTranslation, colTranslation, results, filtered_rowptr, graph_rowptr, nnz, boundaryNodes, droppingMethod, threshold, aggregationMayCreateDirichlet, symmetrizeDroppedGraph, useBlocking, distanceLaplacianMetric, dlap_weights, interleaved_blocksize, currentLevel, *
this);
1024 }
else if (socUsesMeasure ==
"smoothed aggregation") {
1025 VectorDroppingDistanceLaplacian<Scalar, LocalOrdinal, GlobalOrdinal, Node, Misc::SmoothedAggregationMeasure>::runDroppingFunctors_on_dlap(*A, *mergedA, blkPartSize, rowTranslation, colTranslation, results, filtered_rowptr, graph_rowptr, nnz, boundaryNodes, droppingMethod, threshold, aggregationMayCreateDirichlet, symmetrizeDroppedGraph, useBlocking, distanceLaplacianMetric, dlap_weights, interleaved_blocksize, currentLevel, *
this);
1026 }
else if (socUsesMeasure ==
"signed ruge-stueben") {
1027 VectorDroppingDistanceLaplacian<Scalar, LocalOrdinal, GlobalOrdinal, Node, Misc::SignedRugeStuebenMeasure>::runDroppingFunctors_on_dlap(*A, *mergedA, blkPartSize, rowTranslation, colTranslation, results, filtered_rowptr, graph_rowptr, nnz, boundaryNodes, droppingMethod, threshold, aggregationMayCreateDirichlet, symmetrizeDroppedGraph, useBlocking, distanceLaplacianMetric, dlap_weights, interleaved_blocksize, currentLevel, *
this);
1028 }
else if (socUsesMeasure ==
"signed smoothed aggregation") {
1029 VectorDroppingDistanceLaplacian<Scalar, LocalOrdinal, GlobalOrdinal, Node, Misc::SignedSmoothedAggregationMeasure>::runDroppingFunctors_on_dlap(*A, *mergedA, blkPartSize, rowTranslation, colTranslation, results, filtered_rowptr, graph_rowptr, nnz, boundaryNodes, droppingMethod, threshold, aggregationMayCreateDirichlet, symmetrizeDroppedGraph, useBlocking, distanceLaplacianMetric, dlap_weights, interleaved_blocksize, currentLevel, *
this);
1033 Kokkos::deep_copy(results,
KEEP);
1036 VectorDroppingBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::template runDroppingFunctors<>(*A, *mergedA, blkPartSize, rowTranslation, colTranslation, results, filtered_rowptr, graph_rowptr, nnz, useBlocking, currentLevel, *
this, no_op);
1039 if (symmetrizeDroppedGraph ==
"strong wins") {
1041 VectorDroppingBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::template runDroppingFunctors<>(*A, *mergedA, blkPartSize, rowTranslation, colTranslation, results, filtered_rowptr, graph_rowptr, nnz, useBlocking, currentLevel, *
this, symmetrize);
1042 }
else if ((symmetrizeDroppedGraph ==
"weak wins") && (!pL.get<
bool>(
"aggregation: dropping may create Dirichlet"))) {
1044 VectorDroppingBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::template runDroppingFunctors<>(*A, *mergedA, blkPartSize, rowTranslation, colTranslation, results, filtered_rowptr, graph_rowptr, nnz, useBlocking, currentLevel, *
this, symmetrize);
1045 }
else if (symmetrizeDroppedGraph ==
"weak wins") {
1047 VectorDroppingBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::template runDroppingFunctors<>(*A, *mergedA, blkPartSize, rowTranslation, colTranslation, results, filtered_rowptr, graph_rowptr, nnz, useBlocking, currentLevel, *
this, symmetrize);
1052 GO numTotal = mergedA->getLocalNumEntries();
1053 GO numDropped = numTotal - nnz_graph;
1054 GO numGlobalDropped;
1055 Teuchos::reduceAll(*A->getRowMap()->getComm(), Teuchos::REDUCE_SUM, 1, &numDropped, &numGlobalDropped);
1063 RCP<LWGraph_kokkos> graph;
1064 RCP<Matrix> filteredA;
1065 if (numGlobalDropped > 0) {
1068 local_graph_type lclGraph;
1070 auto colidx = entries_type(
"entries", nnz_graph);
1071 lclGraph = local_graph_type(colidx, graph_rowptr);
1074 local_matrix_type lclFilteredA;
1077 lclFilteredA = local_matrix_type(
"filteredA", lclA.graph, lclA.numCols());
1078 }
else if (needToBuildFilteredA) {
1079 auto colidx = entries_type(
"entries", nnz_filtered);
1080 auto values = values_type(
"values", nnz_filtered);
1081 lclFilteredA = local_matrix_type(
"filteredA",
1082 lclA.numRows(), lclA.numCols(),
1084 values, filtered_rowptr, colidx);
1090 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_lumped_reuse", range, fillFunctor);
1093 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_lumped_noreuse", range, fillFunctor);
1098 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_unlumped_reuse", range, fillFunctor);
1100 if (needToBuildFilteredA) {
1102 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_unlumped_noreuse", range, fillFunctor);
1104 auto fillFunctor =
MatrixConstruction::VectorFillFunctor<local_matrix_type,
false,
false,
false>(lclA, blkSize, colTranslation, results, lclFilteredA, lclGraph, filteringDirichletThreshold);
1105 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Fill_unlumped_noreuse", range, fillFunctor);
1110 if (needToBuildFilteredA) {
1111 filteredA = Xpetra::MatrixFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(lclFilteredA, A->getRowMap(), A->getColMap(), A->getDomainMap(), A->getRangeMap());
1112 filteredA->SetFixedBlockSize(blkSize);
1114 if (reuseEigenvalue) {
1119 filteredA->SetMaxEigenvalueEstimate(A->GetMaxEigenvalueEstimate());
1121 filteredA->SetMaxEigenvalueEstimate(-Teuchos::ScalarTraits<SC>::one());
1125 graph = rcp(
new LWGraph_kokkos(lclGraph, uniqueMap, nonUniqueMap,
"amalgamated graph of A"));
1126 graph->SetBoundaryNodeMap(boundaryNodes);
1128 if (needToBuildFilteredA)
1130 graph = rcp(
new LWGraph_kokkos(mergedA->getCrsGraph()->getLocalGraphDevice(), uniqueMap, nonUniqueMap,
"amalgamated graph of A"));
1131 graph->SetBoundaryNodeMap(boundaryNodes);
1135 if (generateColoringGraph) {
1136 SubFactoryMonitor mColoringGraph(*
this,
"Construct coloring graph", currentLevel);
1138 filtered_rowptr = rowptr_type(
"rowptr_coloring_graph", lclA.numRows() + 1);
1139 graph_rowptr = rowptr_type(
"rowptr", numNodes + 1);
1140 if (localizeColoringGraph) {
1142 VectorDroppingBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::template runDroppingFunctors<>(*A, *mergedA, blkPartSize, rowTranslation, colTranslation, results, filtered_rowptr, graph_rowptr, nnz, useBlocking, currentLevel, *
this, drop_offrank);
1144 if (symmetrizeColoringGraph ==
"strong wins") {
1146 VectorDroppingBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::template runDroppingFunctors<>(*A, *mergedA, blkPartSize, rowTranslation, colTranslation, results, filtered_rowptr, graph_rowptr, nnz, useBlocking, currentLevel, *
this, symmetrize);
1148 if (!pL.get<
bool>(
"aggregation: dropping may create Dirichlet")) {
1150 VectorDroppingBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::template runDroppingFunctors<>(*A, *mergedA, blkPartSize, rowTranslation, colTranslation, results, filtered_rowptr, graph_rowptr, nnz, useBlocking, currentLevel, *
this, symmetrize);
1153 VectorDroppingBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::template runDroppingFunctors<>(*A, *mergedA, blkPartSize, rowTranslation, colTranslation, results, filtered_rowptr, graph_rowptr, nnz, useBlocking, currentLevel, *
this, symmetrize);
1156 auto colidx = entries_type(
"entries_coloring_graph", nnz_filtered);
1157 auto lclGraph = local_graph_type(colidx, filtered_rowptr);
1159 Kokkos::parallel_for(
"MueLu::CoalesceDrop::Construct_coloring_graph", range, graphConstruction);
1161 auto colorGraph = rcp(
new LWGraph_kokkos(lclGraph, A->getRowMap(), A->getColMap(),
"coloring graph"));
1162 Set(currentLevel,
"Coloring Graph", colorGraph);
1165 LO dofsPerNode = blkSize;
1167 Set(currentLevel,
"DofsPerNode", dofsPerNode);
1168 Set(currentLevel,
"Graph", graph);
1169 if (needToBuildFilteredA)
1170 Set(currentLevel,
"A", filteredA);
1172 return std::make_tuple(numDropped, (
GlobalOrdinal)nnz_graph, boundaryNodes);