498 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
499 Teuchos::ArrayRCP<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>
502 size_t numRows = A.getRowMap()->getLocalNumElements();
503 Magnitude ZERO = Teuchos::ScalarTraits<Magnitude>::zero();
504 Teuchos::ArrayRCP<Magnitude> maxvec(numRows);
505 Teuchos::ArrayView<const LocalOrdinal> cols;
506 Teuchos::ArrayView<const Scalar> vals;
507 for (
size_t i = 0; i < numRows; ++i) {
508 A.getLocalRowView(i, cols, vals);
511 if (Teuchos::as<size_t>(cols[j]) != i) {
512 mymax = std::max(mymax,-Teuchos::ScalarTraits<Scalar>::real(vals[j]));
520 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
521 Teuchos::ArrayRCP<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>
523 GetMatrixMaxMinusOffDiagonal(
const Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>& A,
const Xpetra::Vector<LocalOrdinal,LocalOrdinal,GlobalOrdinal,Node> &BlockNumber) {
524 TEUCHOS_TEST_FOR_EXCEPTION(!A.getColMap()->isSameAs(*BlockNumber.getMap()),std::runtime_error,
"GetMatrixMaxMinusOffDiagonal: BlockNumber must match's A's column map.");
526 Teuchos::ArrayRCP<const LocalOrdinal> block_id = BlockNumber.getData(0);
528 size_t numRows = A.getRowMap()->getLocalNumElements();
529 Magnitude ZERO = Teuchos::ScalarTraits<Magnitude>::zero();
530 Teuchos::ArrayRCP<Magnitude> maxvec(numRows);
531 Teuchos::ArrayView<const LocalOrdinal> cols;
532 Teuchos::ArrayView<const Scalar> vals;
533 for (
size_t i = 0; i < numRows; ++i) {
534 A.getLocalRowView(i, cols, vals);
537 if (Teuchos::as<size_t>(cols[j]) != i && block_id[i] == block_id[cols[j]]) {
538 mymax = std::max(mymax,-Teuchos::ScalarTraits<Scalar>::real(vals[j]));
549 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
550 Teuchos::RCP<Xpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >
552 GetInverse(Teuchos::RCP<
const Xpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > v,
typename Teuchos::ScalarTraits<Scalar>::magnitudeType tol,
Scalar valReplacement) {
554 RCP<Vector> ret = Xpetra::VectorFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(v->getMap(),
true);
557 RCP<const BlockedVector> bv = Teuchos::rcp_dynamic_cast<const BlockedVector>(v);
558 if(bv.is_null() ==
false) {
559 RCP<BlockedVector> bret = Teuchos::rcp_dynamic_cast<BlockedVector>(ret);
560 TEUCHOS_TEST_FOR_EXCEPTION(bret.is_null() ==
true,
MueLu::Exceptions::RuntimeError,
"MueLu::UtilitiesBase::GetInverse: return vector should be of type BlockedVector");
561 RCP<const BlockedMap> bmap = bv->getBlockedMap();
562 for(
size_t r = 0; r < bmap->getNumMaps(); ++r) {
563 RCP<const MultiVector> submvec = bv->getMultiVector(r,bmap->getThyraMode());
564 RCP<const Vector> subvec = submvec->getVector(0);
566 bret->setMultiVector(r, subvecinf, bmap->getThyraMode());
572 ArrayRCP<Scalar> retVals = ret->getDataNonConst(0);
573 ArrayRCP<const Scalar> inputVals = v->getData(0);
574 for (
size_t i = 0; i < v->getMap()->getLocalNumElements(); ++i) {
575 if(Teuchos::ScalarTraits<Scalar>::magnitude(inputVals[i]) > tol)
576 retVals[i] = Teuchos::ScalarTraits<Scalar>::one() / inputVals[i];
578 retVals[i] = valReplacement;
623 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
624 RCP<Xpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >
628 RCP<const Map> rowMap = A.getRowMap(), colMap = A.getColMap();
629 RCP<Vector> localDiag = VectorFactory::Build(rowMap);
631 const CrsMatrixWrap* crsOp =
dynamic_cast<const CrsMatrixWrap*
>(&A);
632 if ((crsOp != NULL) && (rowMap->lib() == Xpetra::UseTpetra)) {
633 Teuchos::ArrayRCP<size_t> offsets;
634 crsOp->getLocalDiagOffsets(offsets);
635 crsOp->getLocalDiagCopy(*localDiag,offsets());
638 auto localDiagVals = localDiag->getDeviceLocalView(Xpetra::Access::ReadWrite);
639 const auto diagVals =
GetMatrixDiagonal(A)->getDeviceLocalView(Xpetra::Access::ReadOnly);
640 Kokkos::deep_copy(localDiagVals, diagVals);
643 RCP<Vector> diagonal = VectorFactory::Build(colMap);
644 RCP< const Import> importer;
645 importer = A.getCrsGraph()->getImporter();
646 if (importer == Teuchos::null) {
647 importer = ImportFactory::Build(rowMap, colMap);
649 diagonal->doImport(*localDiag, *(importer), Xpetra::INSERT);
655 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
656 RCP<Xpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >
659 using STS =
typename Teuchos::ScalarTraits<SC>;
662 RCP<const Map> rowMap = A.getRowMap(), colMap = A.getColMap();
663 RCP<const BlockedMap> browMap = Teuchos::rcp_dynamic_cast<const BlockedMap>(rowMap);
664 if(!browMap.is_null()) rowMap = browMap->getMap();
666 RCP<Vector> local = Xpetra::VectorFactory<SC,LO,GO,Node>::Build(rowMap);
667 RCP<Vector> ghosted = Xpetra::VectorFactory<SC,LO,GO,Node>::Build(colMap,
true);
668 ArrayRCP<SC> localVals = local->getDataNonConst(0);
670 for (LO row = 0; row < static_cast<LO>(A.getRowMap()->getLocalNumElements()); ++row) {
671 size_t nnz = A.getNumEntriesInLocalRow(row);
672 ArrayView<const LO> indices;
673 ArrayView<const SC> vals;
674 A.getLocalRowView(row, indices, vals);
678 for (LO colID = 0; colID < static_cast<LO>(nnz); colID++) {
679 if(indices[colID] != row) {
686 RCP< const Xpetra::Import<LO,GO,Node> > importer;
687 importer = A.getCrsGraph()->getImporter();
688 if (importer == Teuchos::null) {
689 importer = Xpetra::ImportFactory<LO,GO,Node>::Build(rowMap, colMap);
691 ghosted->doImport(*local, *(importer), Xpetra::INSERT);
697 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
701 RCP<const Map> rowMap = A.getRowMap(), colMap = A.getColMap();
702 using STS =
typename Teuchos::ScalarTraits<Scalar>;
703 using MTS =
typename Teuchos::ScalarTraits<Magnitude>;
705 using RealValuedVector = Xpetra::Vector<MT,LO,GO,Node>;
708 RCP<const BlockedMap> browMap = Teuchos::rcp_dynamic_cast<const BlockedMap>(rowMap);
709 if(!browMap.is_null()) rowMap = browMap->getMap();
711 RCP<RealValuedVector> local = Xpetra::VectorFactory<MT,LO,GO,Node>::Build(rowMap);
712 RCP<RealValuedVector> ghosted = Xpetra::VectorFactory<MT,LO,GO,Node>::Build(colMap,
true);
713 ArrayRCP<MT> localVals = local->getDataNonConst(0);
715 for (LO rowIdx = 0; rowIdx < static_cast<LO>(A.getRowMap()->getLocalNumElements()); ++rowIdx) {
716 size_t nnz = A.getNumEntriesInLocalRow(rowIdx);
717 ArrayView<const LO> indices;
718 ArrayView<const SC> vals;
719 A.getLocalRowView(rowIdx, indices, vals);
723 for (LO colID = 0; colID < static_cast<LO>(nnz); ++colID) {
724 if(indices[colID] != rowIdx) {
725 si += STS::magnitude(vals[colID]);
728 localVals[rowIdx] = si;
731 RCP< const Xpetra::Import<LO,GO,Node> > importer;
732 importer = A.getCrsGraph()->getImporter();
733 if (importer == Teuchos::null) {
734 importer = Xpetra::ImportFactory<LO,GO,Node>::Build(rowMap, colMap);
736 ghosted->doImport(*local, *(importer), Xpetra::INSERT);
741 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
742 Teuchos::Array<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>
744 ResidualNorm(
const Xpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Op,
const MultiVector& X,
const MultiVector& RHS) {
745 TEUCHOS_TEST_FOR_EXCEPTION(X.getNumVectors() != RHS.getNumVectors(),
Exceptions::RuntimeError,
"Number of solution vectors != number of right-hand sides")
746 const size_t numVecs = X.getNumVectors();
747 RCP<MultiVector> RES =
Residual(Op, X, RHS);
748 Teuchos::Array<Magnitude> norms(numVecs);
753 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
754 Teuchos::Array<typename Teuchos::ScalarTraits<Scalar>::magnitudeType>
756 ResidualNorm(
const Xpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Op,
const MultiVector& X,
const MultiVector& RHS, MultiVector & Resid) {
757 TEUCHOS_TEST_FOR_EXCEPTION(X.getNumVectors() != RHS.getNumVectors(),
Exceptions::RuntimeError,
"Number of solution vectors != number of right-hand sides")
758 const size_t numVecs = X.getNumVectors();
760 Teuchos::Array<Magnitude> norms(numVecs);
765 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
766 RCP<Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >
768 Residual(
const Xpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Op,
const MultiVector& X,
const MultiVector& RHS) {
769 TEUCHOS_TEST_FOR_EXCEPTION(X.getNumVectors() != RHS.getNumVectors(),
Exceptions::RuntimeError,
"Number of solution vectors != number of right-hand sides")
770 const size_t numVecs = X.getNumVectors();
772 RCP<MultiVector> RES = Xpetra::MultiVectorFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(RHS.getMap(), numVecs,
false);
773 Op.residual(X,RHS,*RES);
778 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
781 Residual(
const Xpetra::Operator<Scalar,LocalOrdinal,GlobalOrdinal,Node>& Op,
const MultiVector& X,
const MultiVector& RHS, MultiVector & Resid) {
782 TEUCHOS_TEST_FOR_EXCEPTION(X.getNumVectors() != RHS.getNumVectors(),
Exceptions::RuntimeError,
"Number of solution vectors != number of right-hand sides");
783 TEUCHOS_TEST_FOR_EXCEPTION(Resid.getNumVectors() != RHS.getNumVectors(),
Exceptions::RuntimeError,
"Number of residual vectors != number of right-hand sides");
784 Op.residual(X,RHS,Resid);
788 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
792 LocalOrdinal niters,
typename Teuchos::ScalarTraits<Scalar>::magnitudeType tolerance,
bool verbose,
unsigned int seed) {
794 "Utils::PowerMethod: operator must have domain and range maps that are equivalent.");
797 RCP<Vector> diagInvVec;
799 RCP<Vector> diagVec = Xpetra::VectorFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(A.getRowMap());
800 A.getLocalDiagCopy(*diagVec);
801 diagInvVec = Xpetra::VectorFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(A.getRowMap());
802 diagInvVec->reciprocal(*diagVec);
805 Scalar lambda = PowerMethod(A, diagInvVec, niters, tolerance, verbose, seed);
810 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
813 PowerMethod(
const Matrix& A,
const RCP<Vector> &diagInvVec,
814 LocalOrdinal niters,
typename Teuchos::ScalarTraits<Scalar>::magnitudeType tolerance,
bool verbose,
unsigned int seed) {
816 "Utils::PowerMethod: operator must have domain and range maps that are equivalent.");
819 RCP<Vector> q = Xpetra::VectorFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(A.getDomainMap());
820 RCP<Vector> r = Xpetra::VectorFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(A.getRangeMap());
821 RCP<Vector> z = Xpetra::VectorFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(A.getRangeMap());
826 Teuchos::Array<Magnitude> norms(1);
828 typedef Teuchos::ScalarTraits<Scalar> STS;
830 const Scalar zero = STS::zero(), one = STS::one();
833 Magnitude residual = STS::magnitude(zero);
836 for (
int iter = 0; iter < niters; ++iter) {
838 q->update(one/norms[0], *z, zero);
840 if (diagInvVec != Teuchos::null)
841 z->elementWiseMultiply(one, *diagInvVec, *z, zero);
844 if (iter % 100 == 0 || iter + 1 == niters) {
845 r->update(1.0, *z, -lambda, *q, zero);
847 residual = STS::magnitude(norms[0] / lambda);
849 std::cout <<
"Iter = " << iter
850 <<
" Lambda = " << lambda
851 <<
" Residual of A*q - lambda*q = " << residual
855 if (residual < tolerance)
861 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
862 RCP<Teuchos::FancyOStream>
865 RCP<Teuchos::FancyOStream> fancy = Teuchos::fancyOStream(Teuchos::rcpFromRef(os));
870 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
871 typename Teuchos::ScalarTraits<Scalar>::magnitudeType
874 const size_t numVectors = v.size();
876 Scalar d = Teuchos::ScalarTraits<Scalar>::zero();
877 for (
size_t j = 0; j < numVectors; j++) {
878 d += (v[j][i0] - v[j][i1])*(v[j][i0] - v[j][i1]);
880 return Teuchos::ScalarTraits<Scalar>::magnitude(d);
884 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
885 typename Teuchos::ScalarTraits<Scalar>::magnitudeType
888 const size_t numVectors = v.size();
889 using MT =
typename Teuchos::ScalarTraits<Scalar>::magnitudeType;
891 Scalar d = Teuchos::ScalarTraits<Scalar>::zero();
892 for (
size_t j = 0; j < numVectors; j++) {
893 d += Teuchos::as<MT>(weight[j])*(v[j][i0] - v[j][i1])*(v[j][i0] - v[j][i1]);
895 return Teuchos::ScalarTraits<Scalar>::magnitude(d);
899 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
900 Teuchos::ArrayRCP<const bool>
902 DetectDirichletRows(
const Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>& A,
const typename Teuchos::ScalarTraits<Scalar>::magnitudeType& tol,
bool count_twos_as_dirichlet) {
904 typedef Teuchos::ScalarTraits<Scalar> STS;
905 ArrayRCP<bool> boundaryNodes(numRows,
true);
906 if (count_twos_as_dirichlet) {
908 ArrayView<const LocalOrdinal> indices;
909 ArrayView<const Scalar> vals;
910 A.getLocalRowView(row, indices, vals);
911 size_t nnz = A.getNumEntriesInLocalRow(row);
914 for (col = 0; col < nnz; col++)
915 if ( (indices[col] != row) && STS::magnitude(vals[col]) > tol) {
916 if (!boundaryNodes[row])
918 boundaryNodes[row] =
false;
921 boundaryNodes[row] =
true;
926 ArrayView<const LocalOrdinal> indices;
927 ArrayView<const Scalar> vals;
928 A.getLocalRowView(row, indices, vals);
929 size_t nnz = A.getNumEntriesInLocalRow(row);
931 for (
size_t col = 0; col < nnz; col++)
932 if ( (indices[col] != row) && STS::magnitude(vals[col]) > tol) {
933 boundaryNodes[row] =
false;
938 return boundaryNodes;
941 template <
class SC,
class LO,
class GO,
class NO>
942 Kokkos::View<bool*, typename NO::device_type>
945 const typename Teuchos::ScalarTraits<SC>::magnitudeType& tol,
946 const bool count_twos_as_dirichlet) {
947 using impl_scalar_type =
typename Kokkos::ArithTraits<SC>::val_type;
948 using ATS = Kokkos::ArithTraits<impl_scalar_type>;
949 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
950 using helpers = Xpetra::Helpers<SC,LO,GO,NO>;
953 if(helpers::isTpetraBlockCrs(A)) {
954 const Tpetra::BlockCrsMatrix<SC,LO,GO,NO> & Am = helpers::Op2TpetraBlockCrs(A);
955 auto b_graph = Am.getCrsGraph().getLocalGraphDevice();
956 auto b_rowptr = Am.getCrsGraph().getLocalRowPtrsDevice();
957 auto values = Am.getValuesDevice();
958 LO numBlockRows = Am.getLocalNumRows();
959 const LO stride = Am.getBlockSize() * Am.getBlockSize();
961 Kokkos::View<bool*, typename NO::device_type> boundaryNodes(Kokkos::ViewAllocateWithoutInitializing(
"boundaryNodes"), numBlockRows);
963 if (count_twos_as_dirichlet)
966 Kokkos::parallel_for(
"MueLu:Utils::DetectDirichletRowsBlockCrs", range_type(0,numBlockRows),
967 KOKKOS_LAMBDA(
const LO row) {
968 auto rowView = b_graph.rowConst(row);
969 auto length = rowView.length;
970 LO valstart = b_rowptr[row] * stride;
972 boundaryNodes(row) =
true;
973 decltype(length) colID =0;
974 for (; colID < length; colID++) {
975 if (rowView.colidx(colID) != row) {
976 LO current = valstart + colID*stride;
977 for(LO k=0; k<stride; k++) {
978 if (ATS::magnitude(values[current+ k]) > tol) {
979 boundaryNodes(row) =
false;
984 if(boundaryNodes(row) ==
false)
989 return boundaryNodes;
992 auto localMatrix = A.getLocalMatrixDevice();
993 LO numRows = A.getLocalNumRows();
994 Kokkos::View<bool*, typename NO::device_type> boundaryNodes(Kokkos::ViewAllocateWithoutInitializing(
"boundaryNodes"), numRows);
996 if (count_twos_as_dirichlet)
997 Kokkos::parallel_for(
"MueLu:Utils::DetectDirichletRows_Twos_As_Dirichlet", range_type(0,numRows),
998 KOKKOS_LAMBDA(
const LO row) {
999 auto rowView = localMatrix.row(row);
1000 auto length = rowView.length;
1002 boundaryNodes(row) =
true;
1004 decltype(length) colID =0;
1005 for ( ; colID < length; colID++)
1006 if ((rowView.colidx(colID) != row) &&
1007 (ATS::magnitude(rowView.value(colID)) > tol)) {
1008 if (!boundaryNodes(row))
1010 boundaryNodes(row) =
false;
1012 if (colID == length)
1013 boundaryNodes(row) =
true;
1017 Kokkos::parallel_for(
"MueLu:Utils::DetectDirichletRows", range_type(0,numRows),
1018 KOKKOS_LAMBDA(
const LO row) {
1019 auto rowView = localMatrix.row(row);
1020 auto length = rowView.length;
1022 boundaryNodes(row) =
true;
1023 for (
decltype(length) colID = 0; colID < length; colID++)
1024 if ((rowView.colidx(colID) != row) &&
1025 (ATS::magnitude(rowView.value(colID)) > tol)) {
1026 boundaryNodes(row) =
false;
1030 return boundaryNodes;
1036 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1037 Teuchos::ArrayRCP<const bool>
1039 DetectDirichletRowsExt(
const Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>& A,
bool & bHasZeroDiagonal,
const typename Teuchos::ScalarTraits<Scalar>::magnitudeType& tol) {
1042 bHasZeroDiagonal =
false;
1044 Teuchos::RCP<Vector> diagVec = Xpetra::VectorFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(A.getRowMap());
1045 A.getLocalDiagCopy(*diagVec);
1046 Teuchos::ArrayRCP< const Scalar > diagVecData = diagVec->getData(0);
1049 typedef Teuchos::ScalarTraits<Scalar> STS;
1050 ArrayRCP<bool> boundaryNodes(numRows,
false);
1052 ArrayView<const LocalOrdinal> indices;
1053 ArrayView<const Scalar> vals;
1054 A.getLocalRowView(row, indices, vals);
1056 bool bHasDiag =
false;
1057 for (
decltype(indices.size()) col = 0; col < indices.size(); col++) {
1058 if ( indices[col] != row) {
1059 if (STS::magnitude(vals[col] / STS::magnitude(sqrt(STS::magnitude(diagVecData[row]) * STS::magnitude(diagVecData[col]))) ) > tol) {
1062 }
else bHasDiag =
true;
1064 if (bHasDiag ==
false) bHasZeroDiagonal =
true;
1065 else if(nnz == 0) boundaryNodes[row] =
true;
1067 return boundaryNodes;
1071 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1074 FindNonZeros(
const Teuchos::ArrayRCP<const Scalar> vals,
1075 Teuchos::ArrayRCP<bool> nonzeros) {
1076 TEUCHOS_ASSERT(vals.size() == nonzeros.size());
1077 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType magnitudeType;
1078 const magnitudeType eps = 2.0*Teuchos::ScalarTraits<magnitudeType>::eps();
1079 for(
size_t i=0; i<static_cast<size_t>(vals.size()); i++) {
1080 nonzeros[i] = (Teuchos::ScalarTraits<Scalar>::magnitude(vals[i]) > eps);
1085 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1088 FindNonZeros(
const typename Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node>::dual_view_type::t_dev_const_um vals,
1089 Kokkos::View<bool*, typename Node::device_type> nonzeros) {
1090 using ATS = Kokkos::ArithTraits<Scalar>;
1091 using impl_ATS = Kokkos::ArithTraits<typename ATS::val_type>;
1092 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1093 TEUCHOS_ASSERT(vals.extent(0) == nonzeros.extent(0));
1094 const typename ATS::magnitudeType eps = 2.0*impl_ATS::eps();
1096 Kokkos::parallel_for(
"MueLu:Maxwell1::FindNonZeros", range_type(0,vals.extent(0)),
1097 KOKKOS_LAMBDA (
const size_t i) {
1098 nonzeros(i) = (impl_ATS::magnitude(vals(i,0)) > eps);
1103 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1107 const Teuchos::ArrayRCP<bool>& dirichletRows,
1108 Teuchos::ArrayRCP<bool> dirichletCols,
1109 Teuchos::ArrayRCP<bool> dirichletDomain) {
1110 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1111 RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > domMap = A .getDomainMap();
1112 RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > rowMap = A.getRowMap();
1113 RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > colMap = A.getColMap();
1114 TEUCHOS_ASSERT(
static_cast<size_t>(dirichletRows.size()) == rowMap->getLocalNumElements());
1115 TEUCHOS_ASSERT(
static_cast<size_t>(dirichletCols.size()) == colMap->getLocalNumElements());
1116 TEUCHOS_ASSERT(
static_cast<size_t>(dirichletDomain.size()) == domMap->getLocalNumElements());
1117 RCP<Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > myColsToZero = Xpetra::MultiVectorFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(colMap, 1,
true);
1119 for(
size_t i=0; i<(size_t) dirichletRows.size(); i++) {
1120 if (dirichletRows[i]) {
1121 ArrayView<const LocalOrdinal> indices;
1122 ArrayView<const Scalar> values;
1123 A.getLocalRowView(i,indices,values);
1124 for(
size_t j=0; j<static_cast<size_t>(indices.size()); j++)
1125 myColsToZero->replaceLocalValue(indices[j],0,one);
1129 RCP<Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > globalColsToZero;
1130 RCP<const Xpetra::Import<LocalOrdinal,GlobalOrdinal,Node> > importer = A.getCrsGraph()->getImporter();
1131 if (!importer.is_null()) {
1132 globalColsToZero = Xpetra::MultiVectorFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(domMap, 1,
true);
1134 globalColsToZero->doExport(*myColsToZero,*importer,Xpetra::ADD);
1136 myColsToZero->doImport(*globalColsToZero,*importer,Xpetra::INSERT);
1139 globalColsToZero = myColsToZero;
1141 FindNonZeros(globalColsToZero->getData(0),dirichletDomain);
1146 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1150 const Kokkos::View<bool*, typename Node::device_type> & dirichletRows,
1151 Kokkos::View<bool*, typename Node::device_type> dirichletCols,
1152 Kokkos::View<bool*, typename Node::device_type> dirichletDomain) {
1153 using ATS = Kokkos::ArithTraits<Scalar>;
1154 using impl_ATS = Kokkos::ArithTraits<typename ATS::val_type>;
1155 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1156 RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > domMap = A.getDomainMap();
1157 RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > rowMap = A.getRowMap();
1158 RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > colMap = A.getColMap();
1159 TEUCHOS_ASSERT(dirichletRows.extent(0) == rowMap->getLocalNumElements());
1160 TEUCHOS_ASSERT(dirichletCols.extent(0) == colMap->getLocalNumElements());
1161 TEUCHOS_ASSERT(dirichletDomain.extent(0) == domMap->getLocalNumElements());
1162 RCP<Xpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > myColsToZero = Xpetra::VectorFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(colMap,
true);
1164 auto myColsToZeroView = myColsToZero->getDeviceLocalView(Xpetra::Access::ReadWrite);
1165 auto localMatrix = A.getLocalMatrixDevice();
1166 Kokkos::parallel_for(
"MueLu:Maxwell1::DetectDirichletCols", range_type(0,rowMap->getLocalNumElements()),
1168 if (dirichletRows(row)) {
1169 auto rowView = localMatrix.row(row);
1170 auto length = rowView.length;
1172 for (
decltype(length) colID = 0; colID < length; colID++)
1173 myColsToZeroView(rowView.colidx(colID),0) = impl_ATS::one();
1177 RCP<Xpetra::Vector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > globalColsToZero;
1178 RCP<const Xpetra::Import<LocalOrdinal,GlobalOrdinal,Node> > importer = A.getCrsGraph()->getImporter();
1179 if (!importer.is_null()) {
1180 globalColsToZero = Xpetra::VectorFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(domMap,
true);
1182 globalColsToZero->doExport(*myColsToZero,*importer,Xpetra::ADD);
1184 myColsToZero->doImport(*globalColsToZero,*importer,Xpetra::INSERT);
1187 globalColsToZero = myColsToZero;
1194 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1197 ApplyRowSumCriterion(
const Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>& A,
const typename Teuchos::ScalarTraits<Scalar>::magnitudeType rowSumTol, Teuchos::ArrayRCP<bool>& dirichletRows) {
1198 typedef Teuchos::ScalarTraits<Scalar> STS;
1199 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType MT;
1200 typedef Teuchos::ScalarTraits<MT> MTS;
1201 RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node>> rowmap = A.getRowMap();
1202 for (
LocalOrdinal row = 0; row < Teuchos::as<LocalOrdinal>(rowmap->getLocalNumElements()); ++row) {
1203 size_t nnz = A.getNumEntriesInLocalRow(row);
1204 ArrayView<const LocalOrdinal> indices;
1205 ArrayView<const Scalar> vals;
1206 A.getLocalRowView(row, indices, vals);
1208 Scalar rowsum = STS::zero();
1209 Scalar diagval = STS::zero();
1211 for (
LocalOrdinal colID = 0; colID < Teuchos::as<LocalOrdinal>(nnz); colID++) {
1214 diagval = vals[colID];
1215 rowsum += vals[colID];
1218 if (rowSumTol < MTS::one() && STS::magnitude(rowsum) > STS::magnitude(diagval) * rowSumTol) {
1220 dirichletRows[row] =
true;
1225 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1228 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) {
1229 typedef Teuchos::ScalarTraits<Scalar> STS;
1230 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType MT;
1231 typedef Teuchos::ScalarTraits<MT> MTS;
1232 RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > rowmap = A.getRowMap();
1234 TEUCHOS_TEST_FOR_EXCEPTION(!A.getColMap()->isSameAs(*BlockNumber.getMap()),std::runtime_error,
"ApplyRowSumCriterion: BlockNumber must match's A's column map.");
1236 Teuchos::ArrayRCP<const LocalOrdinal> block_id = BlockNumber.getData(0);
1237 for (
LocalOrdinal row = 0; row < Teuchos::as<LocalOrdinal>(rowmap->getLocalNumElements()); ++row) {
1238 size_t nnz = A.getNumEntriesInLocalRow(row);
1239 ArrayView<const LocalOrdinal> indices;
1240 ArrayView<const Scalar> vals;
1241 A.getLocalRowView(row, indices, vals);
1243 Scalar rowsum = STS::zero();
1244 Scalar diagval = STS::zero();
1245 for (
LocalOrdinal colID = 0; colID < Teuchos::as<LocalOrdinal>(nnz); colID++) {
1248 diagval = vals[colID];
1249 if(block_id[row] == block_id[col])
1250 rowsum += vals[colID];
1254 if (rowSumTol < MTS::one() && STS::magnitude(rowsum) > STS::magnitude(diagval) * rowSumTol) {
1256 dirichletRows[row] =
true;
1263 template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1267 const typename Teuchos::ScalarTraits<Scalar>::magnitudeType rowSumTol,
1268 Kokkos::View<bool*, typename Node::device_type> & dirichletRows)
1270 typedef Teuchos::ScalarTraits<Scalar> STS;
1271 RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node>> rowmap = A.getRowMap();
1273 auto dirichletRowsHost = Kokkos::create_mirror_view(dirichletRows);
1274 Kokkos::deep_copy(dirichletRowsHost, dirichletRows);
1276 for (
LocalOrdinal row = 0; row < Teuchos::as<LocalOrdinal>(rowmap->getLocalNumElements()); ++row) {
1277 size_t nnz = A.getNumEntriesInLocalRow(row);
1278 ArrayView<const LocalOrdinal> indices;
1279 ArrayView<const Scalar> vals;
1280 A.getLocalRowView(row, indices, vals);
1282 Scalar rowsum = STS::zero();
1283 Scalar diagval = STS::zero();
1284 for (
LocalOrdinal colID = 0; colID < Teuchos::as<LocalOrdinal>(nnz); colID++) {
1287 diagval = vals[colID];
1288 rowsum += vals[colID];
1290 if (STS::real(rowsum) > STS::magnitude(diagval) * rowSumTol)
1291 dirichletRowsHost(row) =
true;
1294 Kokkos::deep_copy(dirichletRows, dirichletRowsHost);
1298 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1299 Teuchos::ArrayRCP<const bool>
1302 const Teuchos::ArrayRCP<const bool>& dirichletRows) {
1303 Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
1304 Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1305 Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > domMap = A.getDomainMap();
1306 Teuchos::RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > colMap = A.getColMap();
1307 Teuchos::RCP<Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > myColsToZero = Xpetra::MultiVectorFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(colMap,1);
1308 myColsToZero->putScalar(zero);
1310 for(
size_t i=0; i<(size_t) dirichletRows.size(); i++) {
1311 if (dirichletRows[i]) {
1312 Teuchos::ArrayView<const LocalOrdinal> indices;
1313 Teuchos::ArrayView<const Scalar> values;
1314 A.getLocalRowView(i,indices,values);
1315 for(
size_t j=0; j<static_cast<size_t>(indices.size()); j++)
1316 myColsToZero->replaceLocalValue(indices[j],0,one);
1320 Teuchos::RCP<Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> > globalColsToZero = Xpetra::MultiVectorFactory<Scalar,LocalOrdinal,GlobalOrdinal,Node>::Build(domMap,1);
1321 globalColsToZero->putScalar(zero);
1322 Teuchos::RCP<Xpetra::Export<LocalOrdinal,GlobalOrdinal,Node> > exporter = Xpetra::ExportFactory<LocalOrdinal,GlobalOrdinal,Node>::Build(colMap,domMap);
1324 globalColsToZero->doExport(*myColsToZero,*exporter,Xpetra::ADD);
1326 myColsToZero->doImport(*globalColsToZero,*exporter,Xpetra::INSERT);
1327 Teuchos::ArrayRCP<const Scalar> myCols = myColsToZero->getData(0);
1328 Teuchos::ArrayRCP<bool> dirichletCols(colMap->getLocalNumElements(),
true);
1329 Magnitude eps = Teuchos::ScalarTraits<Magnitude>::eps();
1330 for(
size_t i=0; i<colMap->getLocalNumElements(); i++) {
1331 dirichletCols[i] = Teuchos::ScalarTraits<Scalar>::magnitude(myCols[i])>2.0*eps;
1333 return dirichletCols;
1337 template <
class SC,
class LO,
class GO,
class NO>
1338 Kokkos::View<bool*, typename NO::device_type>
1341 const Kokkos::View<const bool*, typename NO::device_type>& dirichletRows) {
1342 using ATS = Kokkos::ArithTraits<SC>;
1343 using impl_ATS = Kokkos::ArithTraits<typename ATS::val_type>;
1344 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1346 SC zero = ATS::zero();
1348 auto localMatrix = A.getLocalMatrixDevice();
1349 LO numRows = A.getLocalNumRows();
1351 Teuchos::RCP<const Xpetra::Map<LO,GO,NO> > domMap = A.getDomainMap();
1352 Teuchos::RCP<const Xpetra::Map<LO,GO,NO> > colMap = A.getColMap();
1353 Teuchos::RCP<Xpetra::MultiVector<SC,LO,GO,NO> > myColsToZero = Xpetra::MultiVectorFactory<SC,LO,GO,NO>::Build(colMap,1);
1354 myColsToZero->putScalar(zero);
1355 auto myColsToZeroView = myColsToZero->getDeviceLocalView(Xpetra::Access::ReadWrite);
1357 Kokkos::parallel_for(
"MueLu:Utils::DetectDirichletCols1", range_type(0,numRows),
1358 KOKKOS_LAMBDA(
const LO row) {
1359 if (dirichletRows(row)) {
1360 auto rowView = localMatrix.row(row);
1361 auto length = rowView.length;
1363 for (
decltype(length) colID = 0; colID < length; colID++)
1364 myColsToZeroView(rowView.colidx(colID),0) = impl_ATS::one();
1368 Teuchos::RCP<Xpetra::MultiVector<SC,LO,GO,NO> > globalColsToZero = Xpetra::MultiVectorFactory<SC,LO,GO,NO>::Build(domMap,1);
1369 globalColsToZero->putScalar(zero);
1370 Teuchos::RCP<Xpetra::Export<LO,GO,NO> > exporter = Xpetra::ExportFactory<LO,GO,NO>::Build(colMap,domMap);
1372 globalColsToZero->doExport(*myColsToZero,*exporter,Xpetra::ADD);
1374 myColsToZero->doImport(*globalColsToZero,*exporter,Xpetra::INSERT);
1376 auto myCols = myColsToZero->getDeviceLocalView(Xpetra::Access::ReadOnly);
1377 size_t numColEntries = colMap->getLocalNumElements();
1378 Kokkos::View<bool*, typename NO::device_type> dirichletCols(Kokkos::ViewAllocateWithoutInitializing(
"dirichletCols"), numColEntries);
1379 const typename ATS::magnitudeType eps = 2.0*ATS::eps();
1381 Kokkos::parallel_for(
"MueLu:Utils::DetectDirichletCols2", range_type(0,numColEntries),
1382 KOKKOS_LAMBDA (
const size_t i) {
1383 dirichletCols(i) = impl_ATS::magnitude(myCols(i,0))>eps;
1385 return dirichletCols;
1389 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1392 Frobenius(
const Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>& A,
const Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>& B) {
1397 TEUCHOS_TEST_FOR_EXCEPTION(!A.getRowMap()->isSameAs(*B.getRowMap()),
Exceptions::Incompatible,
"MueLu::CGSolver::Frobenius: row maps are incompatible");
1398 TEUCHOS_TEST_FOR_EXCEPTION(!A.isFillComplete() || !B.isFillComplete(),
Exceptions::RuntimeError,
"Matrices must be fill completed");
1400 const Map& AColMap = *A.getColMap();
1401 const Map& BColMap = *B.getColMap();
1403 Teuchos::ArrayView<const LocalOrdinal> indA, indB;
1404 Teuchos::ArrayView<const Scalar> valA, valB;
1405 size_t nnzA = 0, nnzB = 0;
1417 Teuchos::Array<Scalar> valBAll(BColMap.getLocalNumElements());
1419 LocalOrdinal invalid = Teuchos::OrdinalTraits<LocalOrdinal>::invalid();
1420 Scalar zero = Teuchos::ScalarTraits<Scalar> ::zero(), f = zero, gf;
1421 size_t numRows = A.getLocalNumRows();
1422 for (
size_t i = 0; i < numRows; i++) {
1423 A.getLocalRowView(i, indA, valA);
1424 B.getLocalRowView(i, indB, valB);
1429 for (
size_t j = 0; j < nnzB; j++)
1430 valBAll[indB[j]] = valB[j];
1432 for (
size_t j = 0; j < nnzA; j++) {
1435 LocalOrdinal ind = BColMap.getLocalElement(AColMap.getGlobalElement(indA[j]));
1437 f += valBAll[ind] * valA[j];
1441 for (
size_t j = 0; j < nnzB; j++)
1442 valBAll[indB[j]] = zero;
1451 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1460 int maxint = INT_MAX;
1461 int mySeed = Teuchos::as<int>((maxint-1) * (one -(comm.getRank()+1)/(comm.getSize()+one)) );
1462 if (mySeed < 1 || mySeed == maxint) {
1463 std::ostringstream errStr;
1464 errStr <<
"Error detected with random seed = " << mySeed <<
". It should be in the interval [1,2^31-2].";
1469 Teuchos::ScalarTraits<Scalar>::seedrandom(mySeed);
1478 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1481 FindDirichletRows(Teuchos::RCP<Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> > &A,
1482 std::vector<LocalOrdinal>& dirichletRows,
bool count_twos_as_dirichlet) {
1483 typedef typename Teuchos::ScalarTraits<Scalar>::magnitudeType MT;
1484 dirichletRows.resize(0);
1485 for(
size_t i=0; i<A->getLocalNumRows(); i++) {
1486 Teuchos::ArrayView<const LocalOrdinal> indices;
1487 Teuchos::ArrayView<const Scalar> values;
1488 A->getLocalRowView(i,indices,values);
1490 for (
size_t j=0; j<(size_t)indices.size(); j++) {
1491 if (Teuchos::ScalarTraits<Scalar>::magnitude(values[j]) > Teuchos::ScalarTraits<MT>::eps()) {
1495 if (nnz == 1 || (count_twos_as_dirichlet && nnz == 2)) {
1496 dirichletRows.push_back(i);
1502 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1506 const std::vector<LocalOrdinal>& dirichletRows) {
1507 RCP<const Map> Rmap = A->getRowMap();
1508 RCP<const Map> Cmap = A->getColMap();
1509 Scalar one =Teuchos::ScalarTraits<Scalar>::one();
1510 Scalar zero =Teuchos::ScalarTraits<Scalar>::zero();
1512 for(
size_t i=0; i<dirichletRows.size(); i++) {
1513 GlobalOrdinal row_gid = Rmap->getGlobalElement(dirichletRows[i]);
1515 Teuchos::ArrayView<const LocalOrdinal> indices;
1516 Teuchos::ArrayView<const Scalar> values;
1517 A->getLocalRowView(dirichletRows[i],indices,values);
1519 Scalar* valuesNC =
const_cast<Scalar*
>(values.getRawPtr());
1520 for(
size_t j=0; j<(size_t)indices.size(); j++) {
1521 if(Cmap->getGlobalElement(indices[j])==row_gid)
1529 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1533 const Teuchos::ArrayRCP<const bool>& dirichletRows) {
1534 TEUCHOS_ASSERT(A->isFillComplete());
1535 RCP<const Map> domMap = A->getDomainMap();
1536 RCP<const Map> ranMap = A->getRangeMap();
1537 RCP<const Map> Rmap = A->getRowMap();
1538 RCP<const Map> Cmap = A->getColMap();
1539 TEUCHOS_ASSERT(
static_cast<size_t>(dirichletRows.size()) == Rmap->getLocalNumElements());
1540 const Scalar one = Teuchos::ScalarTraits<Scalar>::one();
1541 const Scalar zero = Teuchos::ScalarTraits<Scalar>::zero();
1543 for(
size_t i=0; i<(size_t) dirichletRows.size(); i++) {
1544 if (dirichletRows[i]){
1547 Teuchos::ArrayView<const LocalOrdinal> indices;
1548 Teuchos::ArrayView<const Scalar> values;
1549 A->getLocalRowView(i,indices,values);
1551 Teuchos::ArrayRCP<Scalar> valuesNC(values.size());
1552 for(
size_t j=0; j<(size_t)indices.size(); j++) {
1553 if(Cmap->getGlobalElement(indices[j])==row_gid)
1558 A->replaceLocalValues(i,indices,valuesNC());
1561 A->fillComplete(domMap, ranMap);
1565 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1569 const Kokkos::View<const bool*, typename Node::device_type>& dirichletRows) {
1570 TEUCHOS_ASSERT(A->isFillComplete());
1571 using ATS = Kokkos::ArithTraits<Scalar>;
1572 using impl_ATS = Kokkos::ArithTraits<typename ATS::val_type>;
1573 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1575 RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > domMap = A->getDomainMap();
1576 RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > ranMap = A->getRangeMap();
1577 RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > Rmap = A->getRowMap();
1578 RCP<const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > Cmap = A->getColMap();
1580 TEUCHOS_ASSERT(
static_cast<size_t>(dirichletRows.size()) == Rmap->getLocalNumElements());
1582 auto localMatrix = A->getLocalMatrixDevice();
1583 auto localRmap = Rmap->getLocalMap();
1584 auto localCmap = Cmap->getLocalMap();
1586 Kokkos::parallel_for(
"MueLu::Utils::ApplyOAZ",range_type(0,dirichletRows.extent(0)),
1588 if (dirichletRows(row)){
1589 auto rowView = localMatrix.row(row);
1590 auto length = rowView.length;
1591 auto row_gid = localRmap.getGlobalElement(row);
1592 auto row_lid = localCmap.getLocalElement(row_gid);
1594 for (
decltype(length) colID = 0; colID < length; colID++)
1595 if (rowView.colidx(colID) == row_lid)
1596 rowView.value(colID) = impl_ATS::one();
1598 rowView.value(colID) = impl_ATS::zero();
1604 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1607 ZeroDirichletRows(Teuchos::RCP<Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >& A,
1608 const std::vector<LocalOrdinal>& dirichletRows,
1610 for(
size_t i=0; i<dirichletRows.size(); i++) {
1611 Teuchos::ArrayView<const LocalOrdinal> indices;
1612 Teuchos::ArrayView<const Scalar> values;
1613 A->getLocalRowView(dirichletRows[i],indices,values);
1615 Scalar* valuesNC =
const_cast<Scalar*
>(values.getRawPtr());
1616 for(
size_t j=0; j<(size_t)indices.size(); j++)
1617 valuesNC[j]=replaceWith;
1622 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1625 ZeroDirichletRows(Teuchos::RCP<Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >& A,
1626 const Teuchos::ArrayRCP<const bool>& dirichletRows,
1628 TEUCHOS_ASSERT(
static_cast<size_t>(dirichletRows.size()) == A->getRowMap()->getLocalNumElements());
1629 for(
size_t i=0; i<(size_t) dirichletRows.size(); i++) {
1630 if (dirichletRows[i]) {
1631 Teuchos::ArrayView<const LocalOrdinal> indices;
1632 Teuchos::ArrayView<const Scalar> values;
1633 A->getLocalRowView(i,indices,values);
1635 Scalar* valuesNC =
const_cast<Scalar*
>(values.getRawPtr());
1636 for(
size_t j=0; j<(size_t)indices.size(); j++)
1637 valuesNC[j]=replaceWith;
1643 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1646 ZeroDirichletRows(Teuchos::RCP<Xpetra::MultiVector<Scalar,LocalOrdinal,GlobalOrdinal,Node> >& X,
1647 const Teuchos::ArrayRCP<const bool>& dirichletRows,
1649 TEUCHOS_ASSERT(
static_cast<size_t>(dirichletRows.size()) == X->getMap()->getLocalNumElements());
1650 for(
size_t i=0; i<(size_t) dirichletRows.size(); i++) {
1651 if (dirichletRows[i]) {
1652 for(
size_t j=0; j<X->getNumVectors(); j++)
1653 X->replaceLocalValue(i,j,replaceWith);
1659 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1662 ZeroDirichletRows(RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >& A,
1663 const Kokkos::View<const bool*, typename Node::device_type>& dirichletRows,
1665 using ATS = Kokkos::ArithTraits<Scalar>;
1666 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1668 typename ATS::val_type impl_replaceWith = replaceWith;
1670 auto localMatrix = A->getLocalMatrixDevice();
1673 Kokkos::parallel_for(
"MueLu:Utils::ZeroDirichletRows", range_type(0,numRows),
1675 if (dirichletRows(row)) {
1676 auto rowView = localMatrix.row(row);
1677 auto length = rowView.length;
1678 for (
decltype(length) colID = 0; colID < length; colID++)
1679 rowView.value(colID) = impl_replaceWith;
1685 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1688 ZeroDirichletRows(RCP<Xpetra::MultiVector<Scalar, LocalOrdinal, GlobalOrdinal, Node> >& X,
1689 const Kokkos::View<const bool*, typename Node::device_type>& dirichletRows,
1691 using ATS = Kokkos::ArithTraits<Scalar>;
1692 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1694 typename ATS::val_type impl_replaceWith = replaceWith;
1696 auto myCols = X->getDeviceLocalView(Xpetra::Access::ReadWrite);
1697 size_t numVecs = X->getNumVectors();
1698 Kokkos::parallel_for(
"MueLu:Utils::ZeroDirichletRows_MV", range_type(0,dirichletRows.size()),
1699 KOKKOS_LAMBDA(
const size_t i) {
1700 if (dirichletRows(i)) {
1701 for(
size_t j=0; j<numVecs; j++)
1702 myCols(i,j) = impl_replaceWith;
1709 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1713 const Teuchos::ArrayRCP<const bool>& dirichletCols,
1715 TEUCHOS_ASSERT(
static_cast<size_t>(dirichletCols.size()) == A->getColMap()->getLocalNumElements());
1716 for(
size_t i=0; i<A->getLocalNumRows(); i++) {
1717 Teuchos::ArrayView<const LocalOrdinal> indices;
1718 Teuchos::ArrayView<const Scalar> values;
1719 A->getLocalRowView(i,indices,values);
1721 Scalar* valuesNC =
const_cast<Scalar*
>(values.getRawPtr());
1722 for(
size_t j=0; j<static_cast<size_t>(indices.size()); j++)
1723 if (dirichletCols[indices[j]])
1724 valuesNC[j] = replaceWith;
1729 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1732 ZeroDirichletCols(RCP<Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >& A,
1733 const Kokkos::View<const bool*, typename Node::device_type>& dirichletCols,
1735 using ATS = Kokkos::ArithTraits<Scalar>;
1736 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1738 typename ATS::val_type impl_replaceWith = replaceWith;
1740 auto localMatrix = A->getLocalMatrixDevice();
1743 Kokkos::parallel_for(
"MueLu:Utils::ZeroDirichletCols", range_type(0,numRows),
1745 auto rowView = localMatrix.row(row);
1746 auto length = rowView.length;
1747 for (
decltype(length) colID = 0; colID < length; colID++)
1748 if (dirichletCols(rowView.colidx(colID))) {
1749 rowView.value(colID) = impl_replaceWith;
1755 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1759 Teuchos::RCP<Xpetra::Vector<int,LocalOrdinal,GlobalOrdinal,Node> >& isDirichletRow,
1760 Teuchos::RCP<Xpetra::Vector<int,LocalOrdinal,GlobalOrdinal,Node> >& isDirichletCol) {
1763 if(!A->getRowMap()->isSameAs(*A->getDomainMap())) {
1764 throw std::runtime_error(
"UtilitiesBase::FindDirichletRowsAndPropagateToCols row and domain maps must match.");
1766 RCP<const Xpetra::Import<LocalOrdinal,GlobalOrdinal,Node> > importer = A->getCrsGraph()->getImporter();
1767 bool has_import = !importer.is_null();
1770 std::vector<LocalOrdinal> dirichletRows;
1774 printf(
"[%d] DirichletRow Ids = ",A->getRowMap()->getComm()->getRank());
1775 for(
size_t i=0; i<(size_t) dirichletRows.size(); i++)
1776 printf(
"%d ",dirichletRows[i]);
1781 isDirichletRow = Xpetra::VectorFactory<int,LocalOrdinal,GlobalOrdinal,Node>::Build(A->getRowMap(),
true);
1782 isDirichletCol = Xpetra::VectorFactory<int,LocalOrdinal,GlobalOrdinal,Node>::Build(A->getColMap(),
true);
1785 Teuchos::ArrayRCP<int> dr_rcp = isDirichletRow->getDataNonConst(0);
1786 Teuchos::ArrayView<int> dr = dr_rcp();
1787 Teuchos::ArrayRCP<int> dc_rcp = isDirichletCol->getDataNonConst(0);
1788 Teuchos::ArrayView<int> dc = dc_rcp();
1789 for(
size_t i=0; i<(size_t) dirichletRows.size(); i++) {
1790 dr[dirichletRows[i]] = 1;
1791 if(!has_import) dc[dirichletRows[i]] = 1;
1796 isDirichletCol->doImport(*isDirichletRow,*importer,Xpetra::CombineMode::ADD);
1801template<
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1802RCP<Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node> >
1805 using ISC =
typename Kokkos::ArithTraits<Scalar>::val_type;
1806 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1807 using local_matrix_type =
typename CrsMatrix::local_matrix_type;
1808 using values_type =
typename local_matrix_type::values_type;
1810 const ISC ONE = Kokkos::ArithTraits<ISC>::one();
1811 const ISC ZERO = Kokkos::ArithTraits<ISC>::zero();
1814 auto localMatrix = original->getLocalMatrixDevice();
1815 TEUCHOS_TEST_FOR_EXCEPTION(!original->hasCrsGraph(),
Exceptions::RuntimeError,
"ReplaceNonZerosWithOnes: Cannot get CrsGraph");
1816 values_type new_values(
"values",localMatrix.nnz());
1818 Kokkos::parallel_for(
"ReplaceNonZerosWithOnes",range_type(0,localMatrix.nnz()),KOKKOS_LAMBDA(
const size_t i) {
1819 if (localMatrix.values(i) != ZERO)
1820 new_values(i) = ONE;
1822 new_values(i) = ZERO;
1826 RCP<Matrix> NewMatrix = Xpetra::MatrixFactory<SC,LO,GO,NO>::Build(original->getCrsGraph(),new_values);
1827 TEUCHOS_TEST_FOR_EXCEPTION(NewMatrix.is_null(),
Exceptions::RuntimeError,
"ReplaceNonZerosWithOnes: MatrixFactory::Build() did not return matrix");
1828 NewMatrix->fillComplete(original->getDomainMap(),original->getRangeMap());
1835 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1836 RCP<const Xpetra::BlockedMap<LocalOrdinal,GlobalOrdinal,Node> >
1839 const Xpetra::Import<LocalOrdinal,GlobalOrdinal,Node> & Importer) {
1840 typedef Xpetra::Vector<int,LocalOrdinal,GlobalOrdinal,Node> IntVector;
1841 Xpetra::UnderlyingLib lib = sourceBlockedMap.lib();
1844 RCP<const Map> fullMap = sourceBlockedMap.getMap();
1845 RCP<const Map> stridedMap = Teuchos::rcp_dynamic_cast<const Xpetra::StridedMap<LocalOrdinal,GlobalOrdinal,Node> >(fullMap);
1846 if(!stridedMap.is_null()) fullMap = stridedMap->getMap();
1849 const size_t numSubMaps = sourceBlockedMap.getNumMaps();
1850 if(!Importer.getSourceMap()->isCompatible(*fullMap))
1851 throw std::runtime_error(
"GenerateBlockedTargetMap(): Map compatibility error");
1854 RCP<IntVector> block_ids = Xpetra::VectorFactory<int,LocalOrdinal,GlobalOrdinal,Node>::Build(fullMap);
1856 for(
size_t i=0; i<numSubMaps; i++) {
1857 RCP<const Map> map = sourceBlockedMap.getMap(i);
1859 for(
size_t j=0; j<map->getLocalNumElements(); j++) {
1860 LocalOrdinal jj = fullMap->getLocalElement(map->getGlobalElement(j));
1861 block_ids->replaceLocalValue(jj,(
int)i);
1866 RCP<const Map> targetMap = Importer.getTargetMap();
1867 RCP<IntVector> new_block_ids = Xpetra::VectorFactory<int,LocalOrdinal,GlobalOrdinal,Node>::Build(targetMap);
1868 new_block_ids->doImport(*block_ids,Importer,Xpetra::CombineMode::ADD);
1869 Teuchos::ArrayRCP<const int> dataRCP = new_block_ids->getData(0);
1870 Teuchos::ArrayView<const int> data = dataRCP();
1874 Teuchos::Array<Teuchos::Array<GlobalOrdinal> > elementsInSubMap(numSubMaps);
1875 for(
size_t i=0; i<targetMap->getLocalNumElements(); i++) {
1876 elementsInSubMap[data[i]].push_back(targetMap->getGlobalElement(i));
1880 std::vector<RCP<const Map> > subMaps(numSubMaps);
1881 for(
size_t i=0; i<numSubMaps; i++) {
1882 subMaps[i] = Xpetra::MapFactory<LocalOrdinal,GlobalOrdinal,Node>::Build(lib,Teuchos::OrdinalTraits<GlobalOrdinal>::invalid(),elementsInSubMap[i](),targetMap->getIndexBase(),targetMap->getComm());
1886 return rcp(
new BlockedMap(targetMap,subMaps));
1891 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1894 MapsAreNested(
const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node>& rowMap,
const Xpetra::Map<LocalOrdinal,GlobalOrdinal,Node>& colMap) {
1895 ArrayView<const GlobalOrdinal> rowElements = rowMap.getLocalElementList();
1896 ArrayView<const GlobalOrdinal> colElements = colMap.getLocalElementList();
1898 const size_t numElements = rowElements.size();
1900 if (
size_t(colElements.size()) < numElements)
1903 bool goodMap =
true;
1904 for (
size_t i = 0; i < numElements; i++)
1905 if (rowElements[i] != colElements[i]) {
1914 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1915 Teuchos::RCP<Xpetra::Vector<LocalOrdinal,LocalOrdinal,GlobalOrdinal,Node> >
1918 using local_matrix_type =
typename Xpetra::Matrix<Scalar,LocalOrdinal,GlobalOrdinal,Node>::local_matrix_type;
1919 using local_graph_type =
typename local_matrix_type::staticcrsgraph_type;
1920 using lno_nnz_view_t =
typename local_graph_type::entries_type::non_const_type;
1921 using device =
typename local_graph_type::device_type;
1922 using execution_space =
typename local_matrix_type::execution_space;
1923 using ordinal_type =
typename local_matrix_type::ordinal_type;
1925 local_graph_type localGraph = Op.getLocalMatrixDevice().graph;
1927 lno_nnz_view_t rcmOrder = KokkosGraph::Experimental::graph_rcm
1928 <device,
typename local_graph_type::row_map_type,
typename local_graph_type::entries_type, lno_nnz_view_t>
1929 (localGraph.row_map, localGraph.entries);
1931 RCP<Xpetra::Vector<LocalOrdinal,LocalOrdinal,GlobalOrdinal,Node> > retval =
1932 Xpetra::VectorFactory<LocalOrdinal,LocalOrdinal,GlobalOrdinal,Node>::Build(Op.getRowMap());
1935 auto view1D = Kokkos::subview(retval->getDeviceLocalView(Xpetra::Access::ReadWrite),Kokkos::ALL (), 0);
1936 Kokkos::parallel_for(
"Utilities::ReverseCuthillMcKee",
1937 Kokkos::RangePolicy<ordinal_type, execution_space>(0, localGraph.numRows()),
1938 KOKKOS_LAMBDA(
const ordinal_type rowIdx) {
1939 view1D(rcmOrder(rowIdx)) = rowIdx;