472 const Magnitude zeroMagn = TST::magnitude(zero);
473 Magnitude avgAbsDiagVal = TST::magnitude(zero);
474 int numDiagsEqualToOne = 0;
475 for (
size_t i = 0; i < rowMap->getLocalNumElements(); ++i) {
477 rcpA->getLocalRowView(i, cols, vals);
480 regSum[i] += vals[j];
481 const Magnitude rowEntryMagn = TST::magnitude(vals[j]);
482 if (rowEntryMagn > zeroMagn)
484 diagVals[i] += rowEntryMagn;
485 if (
static_cast<size_t>(cols[j]) == i)
486 avgAbsDiagVal += rowEntryMagn;
488 if (nnzPerRow[i] == 1 && TST::magnitude(diagVals[i]) == 1.)
489 numDiagsEqualToOne++;
491 if (useAverageAbsDiagVal)
492 tol = TST::magnitude(100 * Teuchos::ScalarTraits<Scalar>::eps()) * (avgAbsDiagVal - numDiagsEqualToOne) / (rowMap->getLocalNumElements() - numDiagsEqualToOne);
494 for (
size_t i = 0; i < rowMap->getLocalNumElements(); ++i) {
495 if (replaceSingleEntryRowWithZero && nnzPerRow[i] <=
static_cast<int>(1))
497 else if ((diagVals[i] != zero) && (TST::magnitude(diagVals[i]) < TST::magnitude(two * regSum[i])))
498 diagVals[i] = one / TST::magnitude((two * regSum[i]));
500 if (TST::magnitude(diagVals[i]) > tol)
501 diagVals[i] = one / diagVals[i];
503 diagVals[i] = valReplacement;
510 TEUCHOS_TEST_FOR_EXCEPTION(doReciprocal, Xpetra::Exceptions::RuntimeError,
511 "UtilitiesBase::GetLumpedMatrixDiagonal(): extracting reciprocal of diagonal of a blocked matrix is not supported");
512 diag = Xpetra::VectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(bA->getRangeMapExtractor()->getFullMap(),
true);
514 for (
size_t row = 0; row < bA->Rows(); ++row) {
515 for (
size_t col = 0; col < bA->Cols(); ++col) {
516 if (!bA->getMatrix(row, col).is_null()) {
518 bool bThyraMode = bA->getRangeMapExtractor()->getThyraMode() && (Teuchos::rcp_dynamic_cast<Xpetra::BlockedCrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>(bA->getMatrix(row, col)) == Teuchos::null);
519 RCP<Vector> ddtemp = bA->getRangeMapExtractor()->ExtractVector(diag, row, bThyraMode);
520 RCP<const Vector> dd = GetLumpedMatrixDiagonal(*(bA->getMatrix(row, col)));
521 ddtemp->update(Teuchos::as<Scalar>(1.0), *dd, Teuchos::as<Scalar>(1.0));
522 bA->getRangeMapExtractor()->InsertVector(ddtemp, row, diag, bThyraMode);
531template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
532Teuchos::RCP<Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
536 RCP<const Map> rowMap = A.getRowMap();
537 auto diag = Xpetra::VectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(rowMap,
false);
540 using local_vector_type =
typename Vector::dual_view_type::t_dev_um;
541 using local_matrix_type =
typename Matrix::local_matrix_device_type;
542 using execution_space =
typename local_vector_type::execution_space;
543 using values_type =
typename local_matrix_type::values_type;
544 using scalar_type =
typename values_type::non_const_value_type;
545#if KOKKOS_VERSION >= 40799
546 using KAT_S =
typename KokkosKernels::ArithTraits<scalar_type>;
548 using KAT_S =
typename Kokkos::ArithTraits<scalar_type>;
551 auto diag_dev = diag->getLocalViewDevice(Tpetra::Access::OverwriteAll);
552 auto local_mat_dev = A.getLocalMatrixDevice();
553 Kokkos::RangePolicy<execution_space, int> my_policy(0,
static_cast<int>(diag_dev.extent(0)));
555 Kokkos::parallel_for(
556 "GetMatrixMaxMinusOffDiagonal", my_policy,
558 auto mymax = KAT_S::zero();
559 auto row = local_mat_dev.rowConst(rowIdx);
560 for (
LocalOrdinal entryIdx = 0; entryIdx < row.length; ++entryIdx) {
561 if (rowIdx != row.colidx(entryIdx)) {
562 if (KAT_S::real(mymax) < -KAT_S::real(row.value(entryIdx)))
563 mymax = -KAT_S::real(row.value(entryIdx));
566 diag_dev(rowIdx, 0) = mymax;
572template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
573Teuchos::RCP<Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
575 GetMatrixMaxMinusOffDiagonal(
const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& A,
const Xpetra::Vector<LocalOrdinal, LocalOrdinal, GlobalOrdinal, Node>& BlockNumber) {
576 TEUCHOS_TEST_FOR_EXCEPTION(!A.getColMap()->isSameAs(*BlockNumber.getMap()), std::runtime_error,
"GetMatrixMaxMinusOffDiagonal: BlockNumber must match's A's column map.");
579 RCP<const Map> rowMap = A.getRowMap();
580 auto diag = Xpetra::VectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(rowMap,
false);
583 using local_vector_type =
typename Vector::dual_view_type::t_dev_um;
584 using local_matrix_type =
typename Matrix::local_matrix_device_type;
585 using execution_space =
typename local_vector_type::execution_space;
586 using values_type =
typename local_matrix_type::values_type;
587 using scalar_type =
typename values_type::non_const_value_type;
588#if KOKKOS_VERSION >= 40799
589 using KAT_S =
typename KokkosKernels::ArithTraits<scalar_type>;
591 using KAT_S =
typename Kokkos::ArithTraits<scalar_type>;
594 auto diag_dev = diag->getLocalViewDevice(Tpetra::Access::OverwriteAll);
595 auto local_mat_dev = A.getLocalMatrixDevice();
596 auto local_block_dev = BlockNumber.getLocalViewDevice(Tpetra::Access::ReadOnly);
597 Kokkos::RangePolicy<execution_space, int> my_policy(0,
static_cast<int>(diag_dev.extent(0)));
599 Kokkos::parallel_for(
600 "GetMatrixMaxMinusOffDiagonal", my_policy,
602 auto mymax = KAT_S::zero();
603 auto row = local_mat_dev.row(rowIdx);
604 for (
LocalOrdinal entryIdx = 0; entryIdx < row.length; ++entryIdx) {
605 if ((rowIdx != row.colidx(entryIdx)) && (local_block_dev(rowIdx, 0) == local_block_dev(row.colidx(entryIdx), 0))) {
606 if (KAT_S::real(mymax) < -KAT_S::real(row.value(entryIdx)))
607 mymax = -KAT_S::real(row.value(entryIdx));
610 diag_dev(rowIdx, 0) = mymax;
616template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
617Teuchos::RCP<Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
619 GetInverse(Teuchos::RCP<
const Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> v,
typename Teuchos::ScalarTraits<Scalar>::magnitudeType tol,
Scalar valReplacement) {
620 RCP<Vector> ret = Xpetra::VectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(v->getMap(),
true);
623 RCP<const BlockedVector> bv = Teuchos::rcp_dynamic_cast<const BlockedVector>(v);
624 if (bv.is_null() ==
false) {
625 RCP<BlockedVector> bret = Teuchos::rcp_dynamic_cast<BlockedVector>(ret);
626 TEUCHOS_TEST_FOR_EXCEPTION(bret.is_null() ==
true,
MueLu::Exceptions::RuntimeError,
"MueLu::UtilitiesBase::GetInverse: return vector should be of type BlockedVector");
627 RCP<const BlockedMap> bmap = bv->getBlockedMap();
628 for (
size_t r = 0; r < bmap->getNumMaps(); ++r) {
629 RCP<const MultiVector> submvec = bv->getMultiVector(r, bmap->getThyraMode());
630 RCP<const Vector> subvec = submvec->getVector(0);
632 bret->setMultiVector(r, subvecinf, bmap->getThyraMode());
638 ArrayRCP<Scalar> retVals = ret->getDataNonConst(0);
639 ArrayRCP<const Scalar> inputVals = v->getData(0);
640 for (
size_t i = 0; i < v->getMap()->getLocalNumElements(); ++i) {
641 if (Teuchos::ScalarTraits<Scalar>::magnitude(inputVals[i]) > tol)
642 retVals[i] = Teuchos::ScalarTraits<Scalar>::one() / inputVals[i];
644 retVals[i] = valReplacement;
687template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
688RCP<Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
691 RCP<const Map> rowMap = A.getRowMap(), colMap = A.getColMap();
692 RCP<Vector> localDiag = GetMatrixDiagonal(A);
693 RCP<const Import> importer = A.getCrsGraph()->getImporter();
694 if (importer.is_null() && !rowMap->isSameAs(*colMap)) {
695 importer = ImportFactory::Build(rowMap, colMap);
697 if (!importer.is_null()) {
698 RCP<Vector> diagonal = VectorFactory::Build(colMap);
699 diagonal->doImport(*localDiag, *(importer), Xpetra::INSERT);
705template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
706RCP<Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
709 using STS =
typename Teuchos::ScalarTraits<SC>;
712 RCP<const Map> rowMap = A.getRowMap(), colMap = A.getColMap();
713 RCP<const BlockedMap> browMap = Teuchos::rcp_dynamic_cast<const BlockedMap>(rowMap);
714 if (!browMap.is_null()) rowMap = browMap->getMap();
716 RCP<Vector> local = Xpetra::VectorFactory<SC, LO, GO, Node>::Build(rowMap);
717 RCP<Vector> ghosted = Xpetra::VectorFactory<SC, LO, GO, Node>::Build(colMap,
true);
718 ArrayRCP<SC> localVals = local->getDataNonConst(0);
720 for (LO row = 0; row < static_cast<LO>(A.getRowMap()->getLocalNumElements()); ++row) {
721 size_t nnz = A.getNumEntriesInLocalRow(row);
722 ArrayView<const LO> indices;
723 ArrayView<const SC> vals;
724 A.getLocalRowView(row, indices, vals);
728 for (LO colID = 0; colID < static_cast<LO>(nnz); colID++) {
729 if (indices[colID] != row) {
736 RCP<const Xpetra::Import<LO, GO, Node>> importer;
737 importer = A.getCrsGraph()->getImporter();
738 if (importer == Teuchos::null) {
739 importer = Xpetra::ImportFactory<LO, GO, Node>::Build(rowMap, colMap);
741 ghosted->doImport(*local, *(importer), Xpetra::INSERT);
745template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
749 RCP<const Map> rowMap = A.getRowMap(), colMap = A.getColMap();
750 using STS =
typename Teuchos::ScalarTraits<Scalar>;
751 using MTS =
typename Teuchos::ScalarTraits<Magnitude>;
753 using RealValuedVector = Xpetra::Vector<MT, LO, GO, Node>;
756 RCP<const BlockedMap> browMap = Teuchos::rcp_dynamic_cast<const BlockedMap>(rowMap);
757 if (!browMap.is_null()) rowMap = browMap->getMap();
759 RCP<RealValuedVector> local = Xpetra::VectorFactory<MT, LO, GO, Node>::Build(rowMap);
760 RCP<RealValuedVector> ghosted = Xpetra::VectorFactory<MT, LO, GO, Node>::Build(colMap,
true);
761 ArrayRCP<MT> localVals = local->getDataNonConst(0);
763 for (LO rowIdx = 0; rowIdx < static_cast<LO>(A.getRowMap()->getLocalNumElements()); ++rowIdx) {
764 size_t nnz = A.getNumEntriesInLocalRow(rowIdx);
765 ArrayView<const LO> indices;
766 ArrayView<const SC> vals;
767 A.getLocalRowView(rowIdx, indices, vals);
771 for (LO colID = 0; colID < static_cast<LO>(nnz); ++colID) {
772 if (indices[colID] != rowIdx) {
773 si += STS::magnitude(vals[colID]);
776 localVals[rowIdx] = si;
779 RCP<const Xpetra::Import<LO, GO, Node>> importer;
780 importer = A.getCrsGraph()->getImporter();
781 if (importer == Teuchos::null) {
782 importer = Xpetra::ImportFactory<LO, GO, Node>::Build(rowMap, colMap);
784 ghosted->doImport(*local, *(importer), Xpetra::INSERT);
788template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
792 using local_matrix_type =
typename Matrix::local_matrix_device_type;
793 using execution_space =
typename local_matrix_type::execution_space;
794#if KOKKOS_VERSION >= 40799
795 using KAT_S =
typename KokkosKernels::ArithTraits<typename local_matrix_type::value_type>;
797 using KAT_S =
typename Kokkos::ArithTraits<typename local_matrix_type::value_type>;
800 auto local_mat_dev = A.getLocalMatrixDevice();
801 Kokkos::RangePolicy<execution_space, int> my_policy(0,
static_cast<int>(local_mat_dev.numRows()));
804 Kokkos::parallel_reduce(
805 "CountNegativeDiagonalEntries", my_policy,
807 auto row = local_mat_dev.row(rowIdx);
808 for (
LocalOrdinal entryIdx = 0; entryIdx < row.length; ++entryIdx) {
809 if (rowIdx == row.colidx(entryIdx) && KAT_S::real(row.value(entryIdx)) < 0)
815 MueLu_sumAll(A.getRowMap()->getComm(), count_l, count_g);
819template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
820Teuchos::Array<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>
822 ResidualNorm(
const Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Op,
const MultiVector& X,
const MultiVector& RHS) {
823 TEUCHOS_TEST_FOR_EXCEPTION(X.getNumVectors() != RHS.getNumVectors(),
Exceptions::RuntimeError,
"Number of solution vectors != number of right-hand sides")
824 const size_t numVecs = X.getNumVectors();
825 RCP<MultiVector> RES = Residual(Op, X, RHS);
826 Teuchos::Array<Magnitude> norms(numVecs);
831template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
832Teuchos::Array<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>
834 ResidualNorm(
const Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Op,
const MultiVector& X,
const MultiVector& RHS, MultiVector& Resid) {
835 TEUCHOS_TEST_FOR_EXCEPTION(X.getNumVectors() != RHS.getNumVectors(),
Exceptions::RuntimeError,
"Number of solution vectors != number of right-hand sides")
836 const size_t numVecs = X.getNumVectors();
837 Residual(Op, X, RHS, Resid);
838 Teuchos::Array<Magnitude> norms(numVecs);
843template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
844RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
846 Residual(
const Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Op,
const MultiVector& X,
const MultiVector& RHS) {
847 TEUCHOS_TEST_FOR_EXCEPTION(X.getNumVectors() != RHS.getNumVectors(),
Exceptions::RuntimeError,
"Number of solution vectors != number of right-hand sides")
848 const size_t numVecs = X.getNumVectors();
850 RCP<MultiVector> RES = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(RHS.getMap(), numVecs,
false);
851 Op.residual(X, RHS, *RES);
855template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
857 Residual(
const Xpetra::Operator<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Op,
const MultiVector& X,
const MultiVector& RHS, MultiVector& Resid) {
858 TEUCHOS_TEST_FOR_EXCEPTION(X.getNumVectors() != RHS.getNumVectors(),
Exceptions::RuntimeError,
"Number of solution vectors != number of right-hand sides");
859 TEUCHOS_TEST_FOR_EXCEPTION(Resid.getNumVectors() != RHS.getNumVectors(),
Exceptions::RuntimeError,
"Number of residual vectors != number of right-hand sides");
860 Op.residual(X, RHS, Resid);
863template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
867 LocalOrdinal niters,
typename Teuchos::ScalarTraits<Scalar>::magnitudeType tolerance,
bool verbose,
unsigned int seed) {
869 "Utils::PowerMethod: operator must have domain and range maps that are equivalent.");
872 RCP<Vector> diagInvVec;
874 diagInvVec = GetMatrixDiagonalInverse(A);
877 Scalar lambda = PowerMethod(A, diagInvVec, niters, tolerance, verbose, seed);
881template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
883UtilitiesBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
884 PowerMethod(
const Matrix& A,
const RCP<Vector>& diagInvVec,
885 LocalOrdinal niters,
typename Teuchos::ScalarTraits<Scalar>::magnitudeType tolerance,
bool verbose,
unsigned int seed) {
886 TEUCHOS_TEST_FOR_EXCEPTION(!(A.getRangeMap()->isSameAs(*(A.getDomainMap()))), Exceptions::Incompatible,
887 "Utils::PowerMethod: operator must have domain and range maps that are equivalent.");
890 RCP<Vector> q = Xpetra::VectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(A.getDomainMap());
891 RCP<Vector> r = Xpetra::VectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(A.getRangeMap());
892 RCP<Vector> z = Xpetra::VectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(A.getRangeMap());
897 Teuchos::Array<Magnitude> norms(1);
899 typedef Teuchos::ScalarTraits<Scalar> STS;
901 const Scalar zero = STS::zero(), one = STS::one();
904 Magnitude residual = STS::magnitude(zero);
907 for (
int iter = 0; iter < niters; ++iter) {
909 q->update(one / norms[0], *z, zero);
911 if (diagInvVec != Teuchos::null)
912 z->elementWiseMultiply(one, *diagInvVec, *z, zero);
915 if (iter % 100 == 0 || iter + 1 == niters) {
916 r->update(1.0, *z, -lambda, *q, zero);
918 residual = STS::magnitude(norms[0] / lambda);
920 std::cout <<
"Iter = " << iter
921 <<
" Lambda = " << lambda
922 <<
" Residual of A*q - lambda*q = " << residual
926 if (residual < tolerance)
932template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
933RCP<Teuchos::FancyOStream>
936 RCP<Teuchos::FancyOStream> fancy = Teuchos::fancyOStream(Teuchos::rcpFromRef(os));
940template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
941typename Teuchos::ScalarTraits<Scalar>::magnitudeType
944 const size_t numVectors = v.size();
946 Scalar d = Teuchos::ScalarTraits<Scalar>::zero();
947 for (
size_t j = 0; j < numVectors; j++) {
948 d += (v[j][i0] - v[j][i1]) * (v[j][i0] - v[j][i1]);
950 return Teuchos::ScalarTraits<Scalar>::magnitude(d);
953template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
954typename Teuchos::ScalarTraits<Scalar>::magnitudeType
957 const size_t numVectors = v.size();
958 using MT =
typename Teuchos::ScalarTraits<Scalar>::magnitudeType;
960 Scalar d = Teuchos::ScalarTraits<Scalar>::zero();
961 for (
size_t j = 0; j < numVectors; j++) {
962 d += Teuchos::as<MT>(weight[j]) * (v[j][i0] - v[j][i1]) * (v[j][i0] - v[j][i1]);
964 return Teuchos::ScalarTraits<Scalar>::magnitude(d);
967template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
968Teuchos::ArrayRCP<const bool>
970 DetectDirichletRows(
const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& A,
const typename Teuchos::ScalarTraits<Scalar>::magnitudeType& tol,
bool count_twos_as_dirichlet) {
972 typedef Teuchos::ScalarTraits<Scalar> STS;
973 ArrayRCP<bool> boundaryNodes(numRows,
true);
974 if (count_twos_as_dirichlet) {
976 ArrayView<const LocalOrdinal> indices;
977 ArrayView<const Scalar> vals;
978 A.getLocalRowView(row, indices, vals);
979 size_t nnz = A.getNumEntriesInLocalRow(row);
982 for (col = 0; col < nnz; col++)
983 if ((indices[col] != row) && STS::magnitude(vals[col]) > tol) {
984 if (!boundaryNodes[row])
986 boundaryNodes[row] =
false;
989 boundaryNodes[row] =
true;
994 ArrayView<const LocalOrdinal> indices;
995 ArrayView<const Scalar> vals;
996 A.getLocalRowView(row, indices, vals);
997 size_t nnz = A.getNumEntriesInLocalRow(row);
999 for (
size_t col = 0; col < nnz; col++)
1000 if ((indices[col] != row) && STS::magnitude(vals[col]) > tol) {
1001 boundaryNodes[row] =
false;
1006 return boundaryNodes;
1009template <
class CrsMatrix>
1010KOKKOS_FORCEINLINE_FUNCTION
bool isDirichletRow(
typename CrsMatrix::ordinal_type rowId,
1011 KokkosSparse::SparseRowViewConst<CrsMatrix>& row,
1012#
if KOKKOS_VERSION >= 40799
1013 const typename KokkosKernels::ArithTraits<typename CrsMatrix::value_type>::magnitudeType& tol,
1015 const typename Kokkos::ArithTraits<typename CrsMatrix::value_type>::magnitudeType& tol,
1017 const bool count_twos_as_dirichlet) {
1018#if KOKKOS_VERSION >= 40799
1019 using ATS = KokkosKernels::ArithTraits<typename CrsMatrix::value_type>;
1021 using ATS = Kokkos::ArithTraits<typename CrsMatrix::value_type>;
1024 auto length = row.length;
1025 bool boundaryNode =
true;
1027 if (count_twos_as_dirichlet) {
1029 decltype(length) colID = 0;
1030 for (; colID < length; colID++)
1031 if ((row.colidx(colID) != rowId) &&
1032 (ATS::magnitude(row.value(colID)) > tol)) {
1035 boundaryNode =
false;
1037 if (colID == length)
1038 boundaryNode =
true;
1041 for (
decltype(length) colID = 0; colID < length; colID++)
1042 if ((row.colidx(colID) != rowId) &&
1043 (ATS::magnitude(row.value(colID)) > tol)) {
1044 boundaryNode =
false;
1048 return boundaryNode;
1051template <
class SC,
class LO,
class GO,
class NO,
class memory_space>
1052Kokkos::View<bool*, memory_space>
1054 const typename Teuchos::ScalarTraits<SC>::magnitudeType& tol,
1055 const bool count_twos_as_dirichlet) {
1056#if KOKKOS_VERSION >= 40799
1057 using impl_scalar_type =
typename KokkosKernels::ArithTraits<SC>::val_type;
1059 using impl_scalar_type =
typename Kokkos::ArithTraits<SC>::val_type;
1061#if KOKKOS_VERSION >= 40799
1062 using ATS = KokkosKernels::ArithTraits<impl_scalar_type>;
1064 using ATS = Kokkos::ArithTraits<impl_scalar_type>;
1066 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1067 using helpers = Xpetra::Helpers<SC, LO, GO, NO>;
1069 Kokkos::View<bool*, typename NO::device_type::memory_space> boundaryNodes;
1071 if (helpers::isTpetraBlockCrs(A)) {
1072 const Tpetra::BlockCrsMatrix<SC, LO, GO, NO>& Am = toTpetraBlock(A);
1073 auto b_graph = Am.getCrsGraph().getLocalGraphDevice();
1074 auto b_rowptr = Am.getCrsGraph().getLocalRowPtrsDevice();
1075 auto values = Am.getValuesDevice();
1076 LO numBlockRows = Am.getLocalNumRows();
1077 const LO stride = Am.getBlockSize() * Am.getBlockSize();
1079 boundaryNodes = Kokkos::View<bool*, typename NO::device_type::memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"boundaryNodes"), numBlockRows);
1081 if (count_twos_as_dirichlet)
1084 Kokkos::parallel_for(
1085 "MueLu:Utils::DetectDirichletRowsBlockCrs", range_type(0, numBlockRows),
1086 KOKKOS_LAMBDA(
const LO row) {
1087 auto rowView = b_graph.rowConst(row);
1088 auto length = rowView.length;
1089 LO valstart = b_rowptr[row] * stride;
1091 boundaryNodes(row) =
true;
1092 decltype(length) colID = 0;
1093 for (; colID < length; colID++) {
1094 if (rowView.colidx(colID) != row) {
1095 LO current = valstart + colID * stride;
1096 for (LO k = 0; k < stride; k++) {
1097 if (ATS::magnitude(values[current + k]) > tol) {
1098 boundaryNodes(row) =
false;
1103 if (boundaryNodes(row) ==
false)
1108 auto localMatrix = A.getLocalMatrixDevice();
1109 LO numRows = A.getLocalNumRows();
1110 boundaryNodes = Kokkos::View<bool*, typename NO::device_type::memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"boundaryNodes"), numRows);
1112 Kokkos::parallel_for(
1113 "MueLu:Utils::DetectDirichletRows", range_type(0, numRows),
1114 KOKKOS_LAMBDA(
const LO row) {
1115 auto rowView = localMatrix.rowConst(row);
1116 boundaryNodes(row) =
isDirichletRow(row, rowView, tol, count_twos_as_dirichlet);
1119 if constexpr (std::is_same<memory_space, typename NO::device_type::memory_space>::value)
1120 return boundaryNodes;
1122 Kokkos::View<bool*, memory_space> boundaryNodes2(Kokkos::ViewAllocateWithoutInitializing(
"boundaryNodes"), boundaryNodes.extent(0));
1123 Kokkos::deep_copy(boundaryNodes2, boundaryNodes);
1124 return boundaryNodes2;
1127 Kokkos::View<bool*, memory_space> dummy(
"dummy", 0);
1131template <
class SC,
class LO,
class GO,
class NO>
1132Kokkos::View<bool*, typename NO::device_type::memory_space>
1135 const typename Teuchos::ScalarTraits<SC>::magnitudeType& tol,
1136 const bool count_twos_as_dirichlet) {
1137 return MueLu::DetectDirichletRows_kokkos<SC, LO, GO, NO, typename NO::device_type::memory_space>(A, tol, count_twos_as_dirichlet);
1140template <
class SC,
class LO,
class GO,
class NO>
1141Kokkos::View<bool*, typename Kokkos::HostSpace>
1144 const typename Teuchos::ScalarTraits<SC>::magnitudeType& tol,
1145 const bool count_twos_as_dirichlet) {
1146 return MueLu::DetectDirichletRows_kokkos<SC, LO, GO, NO, typename Kokkos::HostSpace>(A, tol, count_twos_as_dirichlet);
1149template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1150Teuchos::ArrayRCP<const bool>
1152 DetectDirichletRowsExt(
const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& A,
bool& bHasZeroDiagonal,
const typename Teuchos::ScalarTraits<Scalar>::magnitudeType& tol) {
1154 bHasZeroDiagonal =
false;
1156 Teuchos::RCP<Vector> diagVec = Xpetra::VectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(A.getRowMap());
1157 A.getLocalDiagCopy(*diagVec);
1158 Teuchos::ArrayRCP<const Scalar> diagVecData = diagVec->getData(0);
1161 typedef Teuchos::ScalarTraits<Scalar> STS;
1162 ArrayRCP<bool> boundaryNodes(numRows,
false);
1164 ArrayView<const LocalOrdinal> indices;
1165 ArrayView<const Scalar> vals;
1166 A.getLocalRowView(row, indices, vals);
1168 bool bHasDiag =
false;
1169 for (
decltype(indices.size()) col = 0; col < indices.size(); col++) {
1170 if (indices[col] != row) {
1171 if (STS::magnitude(vals[col] / STS::magnitude(sqrt(STS::magnitude(diagVecData[row]) * STS::magnitude(diagVecData[col])))) > tol) {
1177 if (bHasDiag ==
false)
1178 bHasZeroDiagonal =
true;
1180 boundaryNodes[row] =
true;
1182 return boundaryNodes;
1185template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1188 const Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& RHS,
1189 Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>& InitialGuess,
1190 const typename Teuchos::ScalarTraits<SC>::magnitudeType& tol,
1191 const bool count_twos_as_dirichlet) {
1192 using range_type = Kokkos::RangePolicy<LO, typename Node::execution_space>;
1196 TEUCHOS_ASSERT_EQUALITY(numVectors, Teuchos::as<LocalOrdinal>(InitialGuess.getNumVectors()));
1198 TEUCHOS_ASSERT(RHS.getMap()->isCompatible(InitialGuess.getMap()));
1201 auto lclRHS = RHS.getLocalViewDevice(Tpetra::Access::ReadOnly);
1202 auto lclInitialGuess = InitialGuess.getLocalViewDevice(Tpetra::Access::ReadWrite);
1203 auto lclA = A.getLocalMatrixDevice();
1205 Kokkos::parallel_for(
1206 "MueLu:Utils::EnforceInitialCondition", range_type(0, numRows),
1207 KOKKOS_LAMBDA(
const LO i) {
1208 auto row = lclA.rowConst(i);
1211 lclInitialGuess(i, j) = lclRHS(i, j);
1216template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1218 FindNonZeros(
const Teuchos::ArrayRCP<const Scalar> vals,
1219 Teuchos::ArrayRCP<bool> nonzeros) {
1220 TEUCHOS_ASSERT(vals.size() == nonzeros.size());
1221 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType magnitudeType;
1222 const magnitudeType eps = 2.0 * Teuchos::ScalarTraits<magnitudeType>::eps();
1223 for (
size_t i = 0; i < static_cast<size_t>(vals.size()); i++) {
1224 nonzeros[i] = (Teuchos::ScalarTraits<Scalar>::magnitude(vals[i]) > eps);
1229template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1231 FindNonZeros(
const typename Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>::dual_view_type::t_dev_const_um vals,
1232 Kokkos::View<bool*, typename Node::device_type> nonzeros) {
1233#if KOKKOS_VERSION >= 40799
1234 using ATS = KokkosKernels::ArithTraits<Scalar>;
1236 using ATS = Kokkos::ArithTraits<Scalar>;
1238#if KOKKOS_VERSION >= 40799
1239 using impl_ATS = KokkosKernels::ArithTraits<typename ATS::val_type>;
1241 using impl_ATS = Kokkos::ArithTraits<typename ATS::val_type>;
1243 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1244 TEUCHOS_ASSERT(vals.extent(0) == nonzeros.extent(0));
1245 const typename ATS::magnitudeType eps = 2.0 * impl_ATS::eps();
1247 Kokkos::parallel_for(
1248 "MueLu:Maxwell1::FindNonZeros", range_type(0, vals.extent(0)),
1249 KOKKOS_LAMBDA(
const size_t i) {
1250 nonzeros(i) = (impl_ATS::magnitude(vals(i, 0)) > eps);
1254template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1257 const Teuchos::ArrayRCP<bool>& dirichletRows,
1258 Teuchos::ArrayRCP<bool> dirichletCols,
1259 Teuchos::ArrayRCP<bool> dirichletDomain) {
1260 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1261 RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> domMap = A.getDomainMap();
1262 RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> rowMap = A.getRowMap();
1263 RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> colMap = A.getColMap();
1264 TEUCHOS_ASSERT(
static_cast<size_t>(dirichletRows.size()) == rowMap->getLocalNumElements());
1265 TEUCHOS_ASSERT(
static_cast<size_t>(dirichletCols.size()) == colMap->getLocalNumElements());
1266 TEUCHOS_ASSERT(
static_cast<size_t>(dirichletDomain.size()) == domMap->getLocalNumElements());
1267 RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> myColsToZero = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(colMap, 1,
true);
1269 for (
size_t i = 0; i < (size_t)dirichletRows.size(); i++) {
1270 if (dirichletRows[i]) {
1271 ArrayView<const LocalOrdinal> indices;
1272 ArrayView<const Scalar> values;
1273 A.getLocalRowView(i, indices, values);
1274 for (
size_t j = 0; j < static_cast<size_t>(indices.size()); j++)
1275 myColsToZero->replaceLocalValue(indices[j], 0, one);
1279 RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> globalColsToZero;
1280 RCP<const Xpetra::Import<LocalOrdinal, GlobalOrdinal, Node>> importer = A.getCrsGraph()->getImporter();
1281 if (!importer.is_null()) {
1282 globalColsToZero = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(domMap, 1,
true);
1284 globalColsToZero->doExport(*myColsToZero, *importer, Xpetra::ADD);
1286 myColsToZero->doImport(*globalColsToZero, *importer, Xpetra::INSERT);
1288 globalColsToZero = myColsToZero;
1290 FindNonZeros(globalColsToZero->getData(0), dirichletDomain);
1291 FindNonZeros(myColsToZero->getData(0), dirichletCols);
1294template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1297 const Kokkos::View<bool*, typename Node::device_type>& dirichletRows,
1298 Kokkos::View<bool*, typename Node::device_type> dirichletCols,
1299 Kokkos::View<bool*, typename Node::device_type> dirichletDomain) {
1300#if KOKKOS_VERSION >= 40799
1301 using ATS = KokkosKernels::ArithTraits<Scalar>;
1303 using ATS = Kokkos::ArithTraits<Scalar>;
1305#if KOKKOS_VERSION >= 40799
1306 using impl_ATS = KokkosKernels::ArithTraits<typename ATS::val_type>;
1308 using impl_ATS = Kokkos::ArithTraits<typename ATS::val_type>;
1310 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1311 RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> domMap = A.getDomainMap();
1312 RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> rowMap = A.getRowMap();
1313 RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> colMap = A.getColMap();
1314 TEUCHOS_ASSERT(dirichletRows.extent(0) == rowMap->getLocalNumElements());
1315 TEUCHOS_ASSERT(dirichletCols.extent(0) == colMap->getLocalNumElements());
1316 TEUCHOS_ASSERT(dirichletDomain.extent(0) == domMap->getLocalNumElements());
1317 RCP<Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> myColsToZero = Xpetra::VectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(colMap,
true);
1319 auto myColsToZeroView = myColsToZero->getLocalViewDevice(Tpetra::Access::ReadWrite);
1320 auto localMatrix = A.getLocalMatrixDevice();
1321 Kokkos::parallel_for(
1322 "MueLu:Maxwell1::DetectDirichletCols", range_type(0, rowMap->getLocalNumElements()),
1324 if (dirichletRows(row)) {
1325 auto rowView = localMatrix.row(row);
1326 auto length = rowView.length;
1328 for (
decltype(length) colID = 0; colID < length; colID++)
1329 myColsToZeroView(rowView.colidx(colID), 0) = impl_ATS::one();
1333 RCP<Xpetra::Vector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> globalColsToZero;
1334 RCP<const Xpetra::Import<LocalOrdinal, GlobalOrdinal, Node>> importer = A.getCrsGraph()->getImporter();
1335 if (!importer.is_null()) {
1336 globalColsToZero = Xpetra::VectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(domMap,
true);
1338 globalColsToZero->doExport(*myColsToZero, *importer, Xpetra::ADD);
1340 myColsToZero->doImport(*globalColsToZero, *importer, Xpetra::INSERT);
1342 globalColsToZero = myColsToZero;
1347template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1349 ApplyRowSumCriterion(
const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& A,
const typename Teuchos::ScalarTraits<Scalar>::magnitudeType rowSumTol, Teuchos::ArrayRCP<bool>& dirichletRows) {
1350 typedef Teuchos::ScalarTraits<Scalar> STS;
1351 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType MT;
1352 typedef Teuchos::ScalarTraits<MT> MTS;
1353 RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> rowmap = A.getRowMap();
1354 for (
LocalOrdinal row = 0; row < Teuchos::as<LocalOrdinal>(rowmap->getLocalNumElements()); ++row) {
1355 size_t nnz = A.getNumEntriesInLocalRow(row);
1356 ArrayView<const LocalOrdinal> indices;
1357 ArrayView<const Scalar> vals;
1358 A.getLocalRowView(row, indices, vals);
1360 Scalar rowsum = STS::zero();
1361 Scalar diagval = STS::zero();
1363 for (
LocalOrdinal colID = 0; colID < Teuchos::as<LocalOrdinal>(nnz); colID++) {
1366 diagval = vals[colID];
1367 rowsum += vals[colID];
1370 if (rowSumTol < MTS::one() && STS::magnitude(rowsum) > STS::magnitude(diagval) * rowSumTol) {
1372 dirichletRows[row] =
true;
1377template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1378void UtilitiesBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
1379 ApplyRowSumCriterion(
const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& A,
const Xpetra::Vector<LocalOrdinal, LocalOrdinal, GlobalOrdinal, Node>& BlockNumber,
const typename Teuchos::ScalarTraits<Scalar>::magnitudeType rowSumTol, Teuchos::ArrayRCP<bool>& dirichletRows) {
1380 typedef Teuchos::ScalarTraits<Scalar> STS;
1381 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType MT;
1382 typedef Teuchos::ScalarTraits<MT> MTS;
1383 RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> rowmap = A.getRowMap();
1385 TEUCHOS_TEST_FOR_EXCEPTION(!A.getColMap()->isSameAs(*BlockNumber.getMap()), std::runtime_error,
"ApplyRowSumCriterion: BlockNumber must match's A's column map.");
1387 Teuchos::ArrayRCP<const LocalOrdinal> block_id = BlockNumber.getData(0);
1388 for (
LocalOrdinal row = 0; row < Teuchos::as<LocalOrdinal>(rowmap->getLocalNumElements()); ++row) {
1389 size_t nnz = A.getNumEntriesInLocalRow(row);
1390 ArrayView<const LocalOrdinal> indices;
1391 ArrayView<const Scalar> vals;
1392 A.getLocalRowView(row, indices, vals);
1394 Scalar rowsum = STS::zero();
1395 Scalar diagval = STS::zero();
1396 for (
LocalOrdinal colID = 0; colID < Teuchos::as<LocalOrdinal>(nnz); colID++) {
1399 diagval = vals[colID];
1400 if (block_id[row] == block_id[col])
1401 rowsum += vals[colID];
1405 if (rowSumTol < MTS::one() && STS::magnitude(rowsum) > STS::magnitude(diagval) * rowSumTol) {
1407 dirichletRows[row] =
true;
1413template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node,
class memory_space>
1415 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType rowSumTol,
1416 Kokkos::View<bool*, memory_space>& dirichletRows) {
1417 typedef Teuchos::ScalarTraits<Scalar> STS;
1418 RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> rowmap = A.getRowMap();
1420 auto dirichletRowsHost = Kokkos::create_mirror_view(dirichletRows);
1421 Kokkos::deep_copy(dirichletRowsHost, dirichletRows);
1423 for (
LocalOrdinal row = 0; row < Teuchos::as<LocalOrdinal>(rowmap->getLocalNumElements()); ++row) {
1424 size_t nnz = A.getNumEntriesInLocalRow(row);
1425 ArrayView<const LocalOrdinal> indices;
1426 ArrayView<const Scalar> vals;
1427 A.getLocalRowView(row, indices, vals);
1429 Scalar rowsum = STS::zero();
1430 Scalar diagval = STS::zero();
1431 for (
LocalOrdinal colID = 0; colID < Teuchos::as<LocalOrdinal>(nnz); colID++) {
1434 diagval = vals[colID];
1435 rowsum += vals[colID];
1437 if (STS::real(rowsum) > STS::magnitude(diagval) * rowSumTol)
1438 dirichletRowsHost(row) =
true;
1441 Kokkos::deep_copy(dirichletRows, dirichletRowsHost);
1444template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1445void UtilitiesBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
1446 ApplyRowSumCriterion(
const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& A,
1447 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType rowSumTol,
1448 Kokkos::View<bool*, typename Node::device_type::memory_space>& dirichletRows) {
1449 MueLu::ApplyRowSumCriterion<Scalar, LocalOrdinal, GlobalOrdinal, Node, typename Node::device_type::memory_space>(A, rowSumTol, dirichletRows);
1452template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1453void UtilitiesBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
1454 ApplyRowSumCriterionHost(
const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& A,
1455 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType rowSumTol,
1456 Kokkos::View<bool*, Kokkos::HostSpace>& dirichletRows) {
1457 MueLu::ApplyRowSumCriterion<Scalar, LocalOrdinal, GlobalOrdinal, Node, Kokkos::HostSpace>(A, rowSumTol, dirichletRows);
1461template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node,
class memory_space>
1463 const Xpetra::Vector<LocalOrdinal, LocalOrdinal, GlobalOrdinal, Node>& BlockNumber,
1464 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType rowSumTol,
1465 Kokkos::View<bool*, memory_space>& dirichletRows) {
1466 typedef Teuchos::ScalarTraits<Scalar> STS;
1467 RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> rowmap = A.getRowMap();
1469 TEUCHOS_TEST_FOR_EXCEPTION(!A.getColMap()->isSameAs(*BlockNumber.getMap()), std::runtime_error,
"ApplyRowSumCriterion: BlockNumber must match's A's column map.");
1471 auto dirichletRowsHost = Kokkos::create_mirror_view(dirichletRows);
1472 Kokkos::deep_copy(dirichletRowsHost, dirichletRows);
1474 Teuchos::ArrayRCP<const LocalOrdinal> block_id = BlockNumber.getData(0);
1475 for (
LocalOrdinal row = 0; row < Teuchos::as<LocalOrdinal>(rowmap->getLocalNumElements()); ++row) {
1476 size_t nnz = A.getNumEntriesInLocalRow(row);
1477 ArrayView<const LocalOrdinal> indices;
1478 ArrayView<const Scalar> vals;
1479 A.getLocalRowView(row, indices, vals);
1481 Scalar rowsum = STS::zero();
1482 Scalar diagval = STS::zero();
1483 for (
LocalOrdinal colID = 0; colID < Teuchos::as<LocalOrdinal>(nnz); colID++) {
1486 diagval = vals[colID];
1487 if (block_id[row] == block_id[col])
1488 rowsum += vals[colID];
1490 if (STS::real(rowsum) > STS::magnitude(diagval) * rowSumTol)
1491 dirichletRowsHost(row) =
true;
1494 Kokkos::deep_copy(dirichletRows, dirichletRowsHost);
1497template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1498void UtilitiesBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
1499 ApplyRowSumCriterion(
const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& A,
1500 const Xpetra::Vector<LocalOrdinal, LocalOrdinal, GlobalOrdinal, Node>& BlockNumber,
1501 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType rowSumTol,
1502 Kokkos::View<bool*, typename Node::device_type::memory_space>& dirichletRows) {
1503 MueLu::ApplyRowSumCriterion<Scalar, LocalOrdinal, GlobalOrdinal, Node, typename Node::device_type::memory_space>(A, BlockNumber, rowSumTol, dirichletRows);
1506template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1507void UtilitiesBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
1508 ApplyRowSumCriterionHost(
const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& A,
1509 const Xpetra::Vector<LocalOrdinal, LocalOrdinal, GlobalOrdinal, Node>& BlockNumber,
1510 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType rowSumTol,
1511 Kokkos::View<bool*, Kokkos::HostSpace>& dirichletRows) {
1512 MueLu::ApplyRowSumCriterion<Scalar, LocalOrdinal, GlobalOrdinal, Node, Kokkos::HostSpace>(A, BlockNumber, rowSumTol, dirichletRows);
1515template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1516Teuchos::ArrayRCP<const bool>
1519 const Teuchos::ArrayRCP<const bool>& dirichletRows) {
1520 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
1521 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1522 Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> domMap = A.getDomainMap();
1523 Teuchos::RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> colMap = A.getColMap();
1524 Teuchos::RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> myColsToZero = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(colMap, 1);
1525 myColsToZero->putScalar(zero);
1527 for (
size_t i = 0; i < (size_t)dirichletRows.size(); i++) {
1528 if (dirichletRows[i]) {
1529 Teuchos::ArrayView<const LocalOrdinal> indices;
1530 Teuchos::ArrayView<const Scalar> values;
1531 A.getLocalRowView(i, indices, values);
1532 for (
size_t j = 0; j < static_cast<size_t>(indices.size()); j++)
1533 myColsToZero->replaceLocalValue(indices[j], 0, one);
1537 Teuchos::RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>> globalColsToZero = Xpetra::MultiVectorFactory<Scalar, LocalOrdinal, GlobalOrdinal, Node>::Build(domMap, 1);
1538 globalColsToZero->putScalar(zero);
1539 Teuchos::RCP<Xpetra::Export<LocalOrdinal, GlobalOrdinal, Node>> exporter = Xpetra::ExportFactory<LocalOrdinal, GlobalOrdinal, Node>::Build(colMap, domMap);
1541 globalColsToZero->doExport(*myColsToZero, *exporter, Xpetra::ADD);
1543 myColsToZero->doImport(*globalColsToZero, *exporter, Xpetra::INSERT);
1544 Teuchos::ArrayRCP<const Scalar> myCols = myColsToZero->getData(0);
1545 Teuchos::ArrayRCP<bool> dirichletCols(colMap->getLocalNumElements(),
true);
1546 Magnitude eps = Teuchos::ScalarTraits<Magnitude>::eps();
1547 for (
size_t i = 0; i < colMap->getLocalNumElements(); i++) {
1548 dirichletCols[i] = Teuchos::ScalarTraits<Scalar>::magnitude(myCols[i]) > 2.0 * eps;
1550 return dirichletCols;
1553template <
class SC,
class LO,
class GO,
class NO>
1554Kokkos::View<bool*, typename NO::device_type>
1557 const Kokkos::View<const bool*, typename NO::device_type>& dirichletRows) {
1558#if KOKKOS_VERSION >= 40799
1559 using ATS = KokkosKernels::ArithTraits<SC>;
1561 using ATS = Kokkos::ArithTraits<SC>;
1563#if KOKKOS_VERSION >= 40799
1564 using impl_ATS = KokkosKernels::ArithTraits<typename ATS::val_type>;
1566 using impl_ATS = Kokkos::ArithTraits<typename ATS::val_type>;
1568 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1570 SC zero = ATS::zero();
1572 auto localMatrix = A.getLocalMatrixDevice();
1573 LO numRows = A.getLocalNumRows();
1575 Teuchos::RCP<const Xpetra::Map<LO, GO, NO>> domMap = A.getDomainMap();
1576 Teuchos::RCP<const Xpetra::Map<LO, GO, NO>> colMap = A.getColMap();
1577 Teuchos::RCP<Xpetra::MultiVector<SC, LO, GO, NO>> myColsToZero = Xpetra::MultiVectorFactory<SC, LO, GO, NO>::Build(colMap, 1);
1578 myColsToZero->putScalar(zero);
1579 auto myColsToZeroView = myColsToZero->getLocalViewDevice(Tpetra::Access::ReadWrite);
1581 Kokkos::parallel_for(
1582 "MueLu:Utils::DetectDirichletCols1", range_type(0, numRows),
1583 KOKKOS_LAMBDA(
const LO row) {
1584 if (dirichletRows(row)) {
1585 auto rowView = localMatrix.row(row);
1586 auto length = rowView.length;
1588 for (
decltype(length) colID = 0; colID < length; colID++)
1589 myColsToZeroView(rowView.colidx(colID), 0) = impl_ATS::one();
1593 Teuchos::RCP<Xpetra::MultiVector<SC, LO, GO, NO>> globalColsToZero = Xpetra::MultiVectorFactory<SC, LO, GO, NO>::Build(domMap, 1);
1594 globalColsToZero->putScalar(zero);
1595 Teuchos::RCP<Xpetra::Export<LO, GO, NO>> exporter = Xpetra::ExportFactory<LO, GO, NO>::Build(colMap, domMap);
1597 globalColsToZero->doExport(*myColsToZero, *exporter, Xpetra::ADD);
1599 myColsToZero->doImport(*globalColsToZero, *exporter, Xpetra::INSERT);
1601 auto myCols = myColsToZero->getLocalViewDevice(Tpetra::Access::ReadOnly);
1602 size_t numColEntries = colMap->getLocalNumElements();
1603 Kokkos::View<bool*, typename NO::device_type> dirichletCols(Kokkos::ViewAllocateWithoutInitializing(
"dirichletCols"), numColEntries);
1604 const typename ATS::magnitudeType eps = 2.0 * ATS::eps();
1606 Kokkos::parallel_for(
1607 "MueLu:Utils::DetectDirichletCols2", range_type(0, numColEntries),
1608 KOKKOS_LAMBDA(
const size_t i) {
1609 dirichletCols(i) = impl_ATS::magnitude(myCols(i, 0)) > eps;
1611 return dirichletCols;
1614template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1617 Frobenius(
const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& A,
const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& B) {
1622 TEUCHOS_TEST_FOR_EXCEPTION(!A.getRowMap()->isSameAs(*B.getRowMap()),
Exceptions::Incompatible,
"MueLu::CGSolver::Frobenius: row maps are incompatible");
1623 TEUCHOS_TEST_FOR_EXCEPTION(!A.isFillComplete() || !B.isFillComplete(),
Exceptions::RuntimeError,
"Matrices must be fill completed");
1625 const Map& AColMap = *A.getColMap();
1626 const Map& BColMap = *B.getColMap();
1628 Teuchos::ArrayView<const LocalOrdinal> indA, indB;
1629 Teuchos::ArrayView<const Scalar> valA, valB;
1630 size_t nnzA = 0, nnzB = 0;
1642 Teuchos::Array<Scalar> valBAll(BColMap.getLocalNumElements());
1644 LocalOrdinal invalid = Teuchos::OrdinalTraits<LocalOrdinal>::invalid();
1645 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero(), f = zero, gf;
1646 size_t numRows = A.getLocalNumRows();
1647 for (
size_t i = 0; i < numRows; i++) {
1648 A.getLocalRowView(i, indA, valA);
1649 B.getLocalRowView(i, indB, valB);
1654 for (
size_t j = 0; j < nnzB; j++)
1655 valBAll[indB[j]] = valB[j];
1657 for (
size_t j = 0; j < nnzA; j++) {
1660 LocalOrdinal ind = BColMap.getLocalElement(AColMap.getGlobalElement(indA[j]));
1662 f += valBAll[ind] * valA[j];
1666 for (
size_t j = 0; j < nnzB; j++)
1667 valBAll[indB[j]] = zero;
1675template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1683 int maxint = INT_MAX;
1684 int mySeed = Teuchos::as<int>((maxint - 1) * (one - (comm.getRank() + 1) / (comm.getSize() + one)));
1685 if (mySeed < 1 || mySeed == maxint) {
1686 std::ostringstream errStr;
1687 errStr <<
"Error detected with random seed = " << mySeed <<
". It should be in the interval [1,2^31-2].";
1692 Teuchos::ScalarTraits<Scalar>::seedrandom(mySeed);
1699template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1701 FindDirichletRows(Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>& A,
1702 std::vector<LocalOrdinal>& dirichletRows,
bool count_twos_as_dirichlet) {
1703 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType MT;
1704 dirichletRows.resize(0);
1705 for (
size_t i = 0; i < A->getLocalNumRows(); i++) {
1706 Teuchos::ArrayView<const LocalOrdinal> indices;
1707 Teuchos::ArrayView<const Scalar> values;
1708 A->getLocalRowView(i, indices, values);
1710 for (
size_t j = 0; j < (size_t)indices.size(); j++) {
1711 if (Teuchos::ScalarTraits<Scalar>::magnitude(values[j]) > Teuchos::ScalarTraits<MT>::eps()) {
1715 if (nnz == 1 || (count_twos_as_dirichlet && nnz == 2)) {
1716 dirichletRows.push_back(i);
1721template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1723 ApplyOAZToMatrixRows(Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>& A,
1724 const std::vector<LocalOrdinal>& dirichletRows) {
1725 RCP<const Map> Rmap = A->getRowMap();
1726 RCP<const Map> Cmap = A->getColMap();
1727 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1728 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
1730 for (
size_t i = 0; i < dirichletRows.size(); i++) {
1731 GlobalOrdinal row_gid = Rmap->getGlobalElement(dirichletRows[i]);
1733 Teuchos::ArrayView<const LocalOrdinal> indices;
1734 Teuchos::ArrayView<const Scalar> values;
1735 A->getLocalRowView(dirichletRows[i], indices, values);
1737 Scalar* valuesNC =
const_cast<Scalar*
>(values.getRawPtr());
1738 for (
size_t j = 0; j < (size_t)indices.size(); j++) {
1739 if (Cmap->getGlobalElement(indices[j]) == row_gid)
1747template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1749 ApplyOAZToMatrixRows(Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>& A,
1750 const Teuchos::ArrayRCP<const bool>& dirichletRows) {
1751 TEUCHOS_ASSERT(A->isFillComplete());
1752 RCP<const Map> domMap = A->getDomainMap();
1753 RCP<const Map> ranMap = A->getRangeMap();
1754 RCP<const Map> Rmap = A->getRowMap();
1755 RCP<const Map> Cmap = A->getColMap();
1756 TEUCHOS_ASSERT(
static_cast<size_t>(dirichletRows.size()) == Rmap->getLocalNumElements());
1757 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1758 const Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
1760 for (
size_t i = 0; i < (size_t)dirichletRows.size(); i++) {
1761 if (dirichletRows[i]) {
1764 Teuchos::ArrayView<const LocalOrdinal> indices;
1765 Teuchos::ArrayView<const Scalar> values;
1766 A->getLocalRowView(i, indices, values);
1768 Teuchos::ArrayRCP<Scalar> valuesNC(values.size());
1769 for (
size_t j = 0; j < (size_t)indices.size(); j++) {
1770 if (Cmap->getGlobalElement(indices[j]) == row_gid)
1775 A->replaceLocalValues(i, indices, valuesNC());
1778 A->fillComplete(domMap, ranMap);
1781template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1783 ApplyOAZToMatrixRows(Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>& A,
1784 const Kokkos::View<const bool*, typename Node::device_type>& dirichletRows) {
1785 TEUCHOS_ASSERT(A->isFillComplete());
1786#if KOKKOS_VERSION >= 40799
1787 using ATS = KokkosKernels::ArithTraits<Scalar>;
1789 using ATS = Kokkos::ArithTraits<Scalar>;
1791#if KOKKOS_VERSION >= 40799
1792 using impl_ATS = KokkosKernels::ArithTraits<typename ATS::val_type>;
1794 using impl_ATS = Kokkos::ArithTraits<typename ATS::val_type>;
1796 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1798 RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> domMap = A->getDomainMap();
1799 RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> ranMap = A->getRangeMap();
1800 RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> Rmap = A->getRowMap();
1801 RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> Cmap = A->getColMap();
1803 TEUCHOS_ASSERT(
static_cast<size_t>(dirichletRows.size()) == Rmap->getLocalNumElements());
1805 auto localMatrix = A->getLocalMatrixDevice();
1806 auto localRmap = Rmap->getLocalMap();
1807 auto localCmap = Cmap->getLocalMap();
1809 Kokkos::parallel_for(
1810 "MueLu::Utils::ApplyOAZ", range_type(0, dirichletRows.extent(0)),
1812 if (dirichletRows(row)) {
1813 auto rowView = localMatrix.row(row);
1814 auto length = rowView.length;
1815 auto row_gid = localRmap.getGlobalElement(row);
1816 auto row_lid = localCmap.getLocalElement(row_gid);
1818 for (
decltype(length) colID = 0; colID < length; colID++)
1819 if (rowView.colidx(colID) == row_lid)
1820 rowView.value(colID) = impl_ATS::one();
1822 rowView.value(colID) = impl_ATS::zero();
1827template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1829 ZeroDirichletRows(Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>& A,
1830 const std::vector<LocalOrdinal>& dirichletRows,
1832 for (
size_t i = 0; i < dirichletRows.size(); i++) {
1833 Teuchos::ArrayView<const LocalOrdinal> indices;
1834 Teuchos::ArrayView<const Scalar> values;
1835 A->getLocalRowView(dirichletRows[i], indices, values);
1837 Scalar* valuesNC =
const_cast<Scalar*
>(values.getRawPtr());
1838 for (
size_t j = 0; j < (size_t)indices.size(); j++)
1839 valuesNC[j] = replaceWith;
1843template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1845 ZeroDirichletRows(Teuchos::RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>& A,
1846 const Teuchos::ArrayRCP<const bool>& dirichletRows,
1848 TEUCHOS_ASSERT(
static_cast<size_t>(dirichletRows.size()) == A->getRowMap()->getLocalNumElements());
1849 for (
size_t i = 0; i < (size_t)dirichletRows.size(); i++) {
1850 if (dirichletRows[i]) {
1851 Teuchos::ArrayView<const LocalOrdinal> indices;
1852 Teuchos::ArrayView<const Scalar> values;
1853 A->getLocalRowView(i, indices, values);
1855 Scalar* valuesNC =
const_cast<Scalar*
>(values.getRawPtr());
1856 for (
size_t j = 0; j < (size_t)indices.size(); j++)
1857 valuesNC[j] = replaceWith;
1862template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1864 ZeroDirichletRows(Teuchos::RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>& X,
1865 const Teuchos::ArrayRCP<const bool>& dirichletRows,
1867 TEUCHOS_ASSERT(
static_cast<size_t>(dirichletRows.size()) == X->getMap()->getLocalNumElements());
1868 for (
size_t i = 0; i < (size_t)dirichletRows.size(); i++) {
1869 if (dirichletRows[i]) {
1870 for (
size_t j = 0; j < X->getNumVectors(); j++)
1871 X->replaceLocalValue(i, j, replaceWith);
1876template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1878 ZeroDirichletRows(RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>& A,
1879 const Kokkos::View<const bool*, typename Node::device_type>& dirichletRows,
1881#if KOKKOS_VERSION >= 40799
1882 using ATS = KokkosKernels::ArithTraits<Scalar>;
1884 using ATS = Kokkos::ArithTraits<Scalar>;
1886 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1888 typename ATS::val_type impl_replaceWith = replaceWith;
1890 auto localMatrix = A->getLocalMatrixDevice();
1893 Kokkos::parallel_for(
1894 "MueLu:Utils::ZeroDirichletRows", range_type(0, numRows),
1896 if (dirichletRows(row)) {
1897 auto rowView = localMatrix.row(row);
1898 auto length = rowView.length;
1899 for (
decltype(length) colID = 0; colID < length; colID++)
1900 rowView.value(colID) = impl_replaceWith;
1905template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1906void UtilitiesBase<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
1907 ZeroDirichletRows(RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node>>& X,
1908 const Kokkos::View<const bool*, typename Node::device_type>& dirichletRows,
1910#if KOKKOS_VERSION >= 40799
1911 using ATS = KokkosKernels::ArithTraits<Scalar>;
1913 using ATS = Kokkos::ArithTraits<Scalar>;
1915 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1917 typename ATS::val_type impl_replaceWith = replaceWith;
1919 auto myCols = X->getLocalViewDevice(Tpetra::Access::ReadWrite);
1920 size_t numVecs = X->getNumVectors();
1921 Kokkos::parallel_for(
1922 "MueLu:Utils::ZeroDirichletRows_MV", range_type(0, dirichletRows.size()),
1923 KOKKOS_LAMBDA(
const size_t i) {
1924 if (dirichletRows(i)) {
1925 for (
size_t j = 0; j < numVecs; j++)
1926 myCols(i, j) = impl_replaceWith;
1931template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1934 const Teuchos::ArrayRCP<const bool>& dirichletCols,
1936 TEUCHOS_ASSERT(
static_cast<size_t>(dirichletCols.size()) == A->getColMap()->getLocalNumElements());
1937 for (
size_t i = 0; i < A->getLocalNumRows(); i++) {
1938 Teuchos::ArrayView<const LocalOrdinal> indices;
1939 Teuchos::ArrayView<const Scalar> values;
1940 A->getLocalRowView(i, indices, values);
1942 Scalar* valuesNC =
const_cast<Scalar*
>(values.getRawPtr());
1943 for (
size_t j = 0; j < static_cast<size_t>(indices.size()); j++)
1944 if (dirichletCols[indices[j]])
1945 valuesNC[j] = replaceWith;
1949template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1951 ZeroDirichletCols(RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>& A,
1952 const Kokkos::View<const bool*, typename Node::device_type>& dirichletCols,
1954#if KOKKOS_VERSION >= 40799
1955 using ATS = KokkosKernels::ArithTraits<Scalar>;
1957 using ATS = Kokkos::ArithTraits<Scalar>;
1959 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1961 typename ATS::val_type impl_replaceWith = replaceWith;
1963 auto localMatrix = A->getLocalMatrixDevice();
1966 Kokkos::parallel_for(
1967 "MueLu:Utils::ZeroDirichletCols", range_type(0, numRows),
1969 auto rowView = localMatrix.row(row);
1970 auto length = rowView.length;
1971 for (
decltype(length) colID = 0; colID < length; colID++)
1972 if (dirichletCols(rowView.colidx(colID))) {
1973 rowView.value(colID) = impl_replaceWith;
1978template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1981 Teuchos::RCP<Xpetra::Vector<int, LocalOrdinal, GlobalOrdinal, Node>>& isDirichletRow,
1982 Teuchos::RCP<Xpetra::Vector<int, LocalOrdinal, GlobalOrdinal, Node>>& isDirichletCol) {
1984 if (!A->getRowMap()->isSameAs(*A->getDomainMap())) {
1985 throw std::runtime_error(
"UtilitiesBase::FindDirichletRowsAndPropagateToCols row and domain maps must match.");
1987 RCP<const Xpetra::Import<LocalOrdinal, GlobalOrdinal, Node>> importer = A->getCrsGraph()->getImporter();
1988 bool has_import = !importer.is_null();
1991 std::vector<LocalOrdinal> dirichletRows;
1992 FindDirichletRows(A, dirichletRows);
1995 printf(
"[%d] DirichletRow Ids = ",A->getRowMap()->getComm()->getRank());
1996 for(
size_t i=0; i<(size_t) dirichletRows.size(); i++)
1997 printf(
"%d ",dirichletRows[i]);
2002 isDirichletRow = Xpetra::VectorFactory<int, LocalOrdinal, GlobalOrdinal, Node>::Build(A->getRowMap(),
true);
2003 isDirichletCol = Xpetra::VectorFactory<int, LocalOrdinal, GlobalOrdinal, Node>::Build(A->getColMap(),
true);
2006 Teuchos::ArrayRCP<int> dr_rcp =
isDirichletRow->getDataNonConst(0);
2007 Teuchos::ArrayView<int> dr = dr_rcp();
2008 Teuchos::ArrayRCP<int> dc_rcp = isDirichletCol->getDataNonConst(0);
2009 Teuchos::ArrayView<int> dc = dc_rcp();
2010 for (
size_t i = 0; i < (size_t)dirichletRows.size(); i++) {
2011 dr[dirichletRows[i]] = 1;
2012 if (!has_import) dc[dirichletRows[i]] = 1;
2017 isDirichletCol->doImport(*
isDirichletRow, *importer, Xpetra::CombineMode::ADD);
2020template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2021RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
2024#if KOKKOS_VERSION >= 40799
2025 using ISC =
typename KokkosKernels::ArithTraits<Scalar>::val_type;
2027 using ISC =
typename Kokkos::ArithTraits<Scalar>::val_type;
2029 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
2030 using local_matrix_type =
typename CrsMatrix::local_matrix_device_type;
2031 using values_type =
typename local_matrix_type::values_type;
2033#if KOKKOS_VERSION >= 40799
2034 const ISC ONE = KokkosKernels::ArithTraits<ISC>::one();
2036 const ISC ONE = Kokkos::ArithTraits<ISC>::one();
2038#if KOKKOS_VERSION >= 40799
2039 const ISC ZERO = KokkosKernels::ArithTraits<ISC>::zero();
2041 const ISC ZERO = Kokkos::ArithTraits<ISC>::zero();
2045 auto localMatrix = original->getLocalMatrixDevice();
2046 TEUCHOS_TEST_FOR_EXCEPTION(!original->hasCrsGraph(),
Exceptions::RuntimeError,
"ReplaceNonZerosWithOnes: Cannot get CrsGraph");
2047 values_type new_values(
"values", localMatrix.nnz());
2049 Kokkos::parallel_for(
2050 "ReplaceNonZerosWithOnes", range_type(0, localMatrix.nnz()), KOKKOS_LAMBDA(
const size_t i) {
2051 if (localMatrix.values(i) != ZERO)
2052 new_values(i) = ONE;
2054 new_values(i) = ZERO;
2058 RCP<Matrix> NewMatrix = Xpetra::MatrixFactory<SC, LO, GO, NO>::Build(original->getCrsGraph(), new_values);
2059 TEUCHOS_TEST_FOR_EXCEPTION(NewMatrix.is_null(),
Exceptions::RuntimeError,
"ReplaceNonZerosWithOnes: MatrixFactory::Build() did not return matrix");
2060 NewMatrix->fillComplete(original->getDomainMap(), original->getRangeMap());
2064template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2065RCP<const Xpetra::BlockedMap<LocalOrdinal, GlobalOrdinal, Node>>
2068 const Xpetra::Import<LocalOrdinal, GlobalOrdinal, Node>& Importer) {
2069 typedef Xpetra::Vector<int, LocalOrdinal, GlobalOrdinal, Node> IntVector;
2070 Xpetra::UnderlyingLib lib = sourceBlockedMap.lib();
2073 RCP<const Map> fullMap = sourceBlockedMap.getMap();
2074 RCP<const Map> stridedMap = Teuchos::rcp_dynamic_cast<const Xpetra::StridedMap<LocalOrdinal, GlobalOrdinal, Node>>(fullMap);
2075 if (!stridedMap.is_null()) fullMap = stridedMap->getMap();
2078 const size_t numSubMaps = sourceBlockedMap.getNumMaps();
2079 if (!Importer.getSourceMap()->isCompatible(*fullMap))
2080 throw std::runtime_error(
"GenerateBlockedTargetMap(): Map compatibility error");
2083 RCP<IntVector> block_ids = Xpetra::VectorFactory<int, LocalOrdinal, GlobalOrdinal, Node>::Build(fullMap);
2085 for (
size_t i = 0; i < numSubMaps; i++) {
2086 RCP<const Map> map = sourceBlockedMap.getMap(i);
2088 for (
size_t j = 0; j < map->getLocalNumElements(); j++) {
2089 LocalOrdinal jj = fullMap->getLocalElement(map->getGlobalElement(j));
2090 block_ids->replaceLocalValue(jj, (
int)i);
2095 RCP<const Map> targetMap = Importer.getTargetMap();
2096 RCP<IntVector> new_block_ids = Xpetra::VectorFactory<int, LocalOrdinal, GlobalOrdinal, Node>::Build(targetMap);
2097 new_block_ids->doImport(*block_ids, Importer, Xpetra::CombineMode::ADD);
2098 Teuchos::ArrayRCP<const int> dataRCP = new_block_ids->getData(0);
2099 Teuchos::ArrayView<const int> data = dataRCP();
2102 Teuchos::Array<Teuchos::Array<GlobalOrdinal>> elementsInSubMap(numSubMaps);
2103 for (
size_t i = 0; i < targetMap->getLocalNumElements(); i++) {
2104 elementsInSubMap[data[i]].push_back(targetMap->getGlobalElement(i));
2108 std::vector<RCP<const Map>> subMaps(numSubMaps);
2109 for (
size_t i = 0; i < numSubMaps; i++) {
2110 subMaps[i] = Xpetra::MapFactory<LocalOrdinal, GlobalOrdinal, Node>::Build(lib, Teuchos::OrdinalTraits<GlobalOrdinal>::invalid(), elementsInSubMap[i](), targetMap->getIndexBase(), targetMap->getComm());
2114 return rcp(
new BlockedMap(targetMap, subMaps));
2117template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2119 MapsAreNested(
const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>& rowMap,
const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>& colMap) {
2120 if ((rowMap.lib() == Xpetra::UseTpetra) && (colMap.lib() == Xpetra::UseTpetra)) {
2121 auto tpRowMap = toTpetra(rowMap);
2122 auto tpColMap = toTpetra(colMap);
2123 return tpColMap.isLocallyFitted(tpRowMap);
2126 ArrayView<const GlobalOrdinal> rowElements = rowMap.getLocalElementList();
2127 ArrayView<const GlobalOrdinal> colElements = colMap.getLocalElementList();
2129 const size_t numElements = rowElements.size();
2131 if (
size_t(colElements.size()) < numElements)
2134 bool goodMap =
true;
2135 for (
size_t i = 0; i < numElements; i++)
2136 if (rowElements[i] != colElements[i]) {
2144template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2145Teuchos::RCP<Xpetra::Vector<LocalOrdinal, LocalOrdinal, GlobalOrdinal, Node>>
2147 ReverseCuthillMcKee(
const Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& Op) {
2148 using local_matrix_type =
typename Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_matrix_device_type;
2149 using local_graph_type =
typename local_matrix_type::staticcrsgraph_type;
2150 using lno_nnz_view_t =
typename local_graph_type::entries_type::non_const_type;
2151 using device =
typename local_graph_type::device_type;
2152 using execution_space =
typename local_matrix_type::execution_space;
2153 using ordinal_type =
typename local_matrix_type::ordinal_type;
2155 local_graph_type localGraph = Op.getLocalMatrixDevice().graph;
2157 lno_nnz_view_t rcmOrder = KokkosGraph::Experimental::graph_rcm<device, typename local_graph_type::row_map_type, typename local_graph_type::entries_type, lno_nnz_view_t>(localGraph.row_map, localGraph.entries);
2159 RCP<Xpetra::Vector<LocalOrdinal, LocalOrdinal, GlobalOrdinal, Node>> retval =
2160 Xpetra::VectorFactory<LocalOrdinal, LocalOrdinal, GlobalOrdinal, Node>::Build(Op.getRowMap());
2163 auto view1D = Kokkos::subview(retval->getLocalViewDevice(Tpetra::Access::ReadWrite), Kokkos::ALL(), 0);
2164 Kokkos::parallel_for(
2165 "Utilities::ReverseCuthillMcKee",
2166 Kokkos::RangePolicy<ordinal_type, execution_space>(0, localGraph.numRows()),
2167 KOKKOS_LAMBDA(
const ordinal_type rowIdx) {
2168 view1D(rcmOrder(rowIdx)) = rowIdx;