10 #ifndef MUELU_UTILITIESBASE_DEF_HPP
11 #define MUELU_UTILITIESBASE_DEF_HPP
17 #include <Kokkos_Core.hpp>
18 #include <KokkosSparse_CrsMatrix.hpp>
19 #include <KokkosSparse_getDiagCopy.hpp>
21 #include <Xpetra_BlockedVector.hpp>
22 #include <Xpetra_BlockedMap.hpp>
23 #include <Xpetra_BlockedMultiVector.hpp>
31 #include <Xpetra_CrsMatrixWrap.hpp>
32 #include <Xpetra_StridedMap.hpp>
37 #include <KokkosKernels_Handle.hpp>
38 #include <KokkosGraph_RCM.hpp>
42 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
43 RCP<Xpetra::Matrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
48 return rcp(
new CrsMatrixWrap(Op));
58 const bool keepDiagonal) {
60 using row_ptr_type =
typename crs_matrix::local_graph_type::row_map_type::non_const_type;
61 using col_idx_type =
typename crs_matrix::local_graph_type::entries_type::non_const_type;
62 using vals_type =
typename crs_matrix::local_matrix_type::values_type;
63 using execution_space =
typename crs_matrix::local_matrix_type::execution_space;
65 #if KOKKOS_VERSION >= 40799
66 using ATS = KokkosKernels::ArithTraits<Scalar>;
68 using ATS = Kokkos::ArithTraits<Scalar>;
70 using impl_SC =
typename ATS::val_type;
71 #if KOKKOS_VERSION >= 40799
72 using impl_ATS = KokkosKernels::ArithTraits<impl_SC>;
74 using impl_ATS = Kokkos::ArithTraits<impl_SC>;
77 auto lclA = A->getLocalMatrixDevice();
79 auto rowptr = row_ptr_type(
"rowptr", lclA.numRows() + 1);
85 auto lclRowMap = A->
getRowMap()->getLocalMap();
86 auto lclColMap = A->getColMap()->getLocalMap();
87 Kokkos::parallel_scan(
88 "removeSmallEntries::rowptr",
89 Kokkos::RangePolicy<LocalOrdinal, execution_space>(0, lclA.numRows()),
91 auto row = lclA.row(rlid);
92 auto rowInCol = lclColMap.getLocalElement(lclRowMap.getGlobalElement(rlid));
94 if ((impl_ATS::magnitude(row.value(k)) > threshold) || (row.colidx(k) == rowInCol)) {
99 rowptr(rlid + 1) = partial_nnz;
103 idx = col_idx_type(
"idx", nnz);
104 vals = vals_type(
"vals", nnz);
106 Kokkos::parallel_for(
107 "removeSmallEntries::indicesValues",
108 Kokkos::RangePolicy<LocalOrdinal, execution_space>(0, lclA.numRows()),
110 auto row = lclA.row(rlid);
111 auto rowInCol = lclColMap.getLocalElement(lclRowMap.getGlobalElement(rlid));
112 auto I = rowptr(rlid);
114 if ((impl_ATS::magnitude(row.value(k)) > threshold) || (row.colidx(k) == rowInCol)) {
115 idx(
I) = row.colidx(k);
116 vals(
I) = row.value(k);
124 Kokkos::parallel_scan(
125 "removeSmallEntries::rowptr",
126 Kokkos::RangePolicy<LocalOrdinal, execution_space>(0, lclA.numRows()),
128 auto row = lclA.row(rlid);
130 if (impl_ATS::magnitude(row.value(k)) > threshold) {
135 rowptr(rlid + 1) = partial_nnz;
139 idx = col_idx_type(
"idx", nnz);
140 vals = vals_type(
"vals", nnz);
142 Kokkos::parallel_for(
143 "removeSmallEntries::indicesValues",
144 Kokkos::RangePolicy<LocalOrdinal, execution_space>(0, lclA.numRows()),
146 auto row = lclA.row(rlid);
147 auto I = rowptr(rlid);
149 if (impl_ATS::magnitude(row.value(k)) > threshold) {
150 idx(
I) = row.colidx(k);
151 vals(
I) = row.value(k);
160 auto lclNewA =
typename crs_matrix::local_matrix_type(
"thresholdedMatrix", lclA.numRows(), lclA.numCols(), nnz, vals, rowptr, idx);
166 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
167 RCP<Xpetra::CrsMatrixWrap<Scalar, LocalOrdinal, GlobalOrdinal, Node>>
170 auto crsWrap = rcp_dynamic_cast<CrsMatrixWrap>(Ain);
171 if (!crsWrap.is_null()) {
172 auto crsMat = crsWrap->getCrsMatrix();
174 return rcp_static_cast<CrsMatrixWrap>(filteredMat);
179 RCP<CrsMatrixWrap> Aout =
rcp(
new CrsMatrixWrap(rowmap, expectedNNZperRow <= 0 ? Ain->getGlobalMaxNumRowEntries() : expectedNNZperRow));
181 for (
size_t row = 0; row < Ain->getLocalNumRows(); row++) {
182 size_t nnz = Ain->getNumEntriesInLocalRow(row);
186 Ain->getLocalRowView(row, indices, vals);
192 size_t nNonzeros = 0;
195 LocalOrdinal lclColIdx = colmap->getLocalElement(glbRow);
196 for (
size_t i = 0; i < (size_t)indices.
size(); i++) {
198 indout[nNonzeros] = colmap->getGlobalElement(indices[i]);
199 valout[nNonzeros] = vals[i];
204 for (
size_t i = 0; i < (size_t)indices.
size(); i++) {
206 indout[nNonzeros] = colmap->getGlobalElement(indices[i]);
207 valout[nNonzeros] = vals[i];
213 valout.resize(nNonzeros);
215 Aout->insertGlobalValues(Ain->getRowMap()->getGlobalElement(row), indout.view(0, indout.size()), valout.view(0, valout.size()));
217 Aout->fillComplete(Ain->getDomainMap(), Ain->getRangeMap());
222 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
227 RCP<CrsGraph> sparsityPattern = CrsGraphFactory::Build(A->getRowMap(), expectedNNZperRow <= 0 ? A->getGlobalMaxNumRowEntries() : expectedNNZperRow);
229 RCP<Vector> diag = GetMatrixOverlappedDiagonal(*A);
232 for (
size_t row = 0; row < A->getLocalNumRows(); row++) {
235 A->getLocalRowView(row, indices, vals);
237 GlobalOrdinal globalRow = A->getRowMap()->getGlobalElement(row);
238 LocalOrdinal col = A->getColMap()->getLocalElement(globalRow);
240 const Scalar Dk = STS::magnitude(D[col]) > 0.0 ? STS::magnitude(D[col]) : 1.0;
243 for (
size_t i = 0; i < size_t(indices.
size()); i++)
245 if (col == indices[i] || STS::magnitude(STS::squareroot(Dk) * vals[i] * STS::squareroot(Dk)) > STS::magnitude(threshold))
246 indicesNew.
append(A->getColMap()->getGlobalElement(indices[i]));
250 sparsityPattern->fillComplete();
252 return sparsityPattern;
255 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
259 size_t numRows = A.getRowMap()->getLocalNumElements();
263 for (
size_t i = 0; i < numRows; ++i) {
266 for (; j < cols.
size(); ++j) {
267 if (Teuchos::as<size_t>(cols[j]) == i) {
272 if (j == cols.
size()) {
280 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
284 const auto rowMap = A.getRowMap();
287 const CrsMatrixWrap* crsOp =
dynamic_cast<const CrsMatrixWrap*
>(&A);
289 using device_type =
typename CrsGraph::device_type;
290 Kokkos::View<size_t*, device_type> offsets(
"offsets", rowMap->getLocalNumElements());
291 crsOp->getCrsGraph()->getLocalDiagOffsets(offsets);
292 crsOp->getCrsMatrix()->getLocalDiagCopy(*diag, offsets);
294 A.getLocalDiagCopy(*diag);
316 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
322 const bool doLumped) {
335 using local_matrix_type =
typename Matrix::local_matrix_type;
337 using value_type =
typename local_matrix_type::value_type;
338 using values_type =
typename local_matrix_type::values_type;
339 using scalar_type =
typename values_type::non_const_value_type;
340 using ordinal_type =
typename local_matrix_type::ordinal_type;
341 using execution_space =
typename local_matrix_type::execution_space;
348 #if KOKKOS_VERSION >= 40799
349 using KAT = KokkosKernels::ArithTraits<value_type>;
351 using KAT = Kokkos::ArithTraits<value_type>;
356 RCP<Vector> diag = VectorFactory::Build(rowMap,
false);
359 local_matrix_type localMatrix = A.getLocalMatrixDevice();
360 auto diagVals = diag->getLocalViewDevice(Xpetra::Access::ReadWrite);
362 ordinal_type numRows = localMatrix.graph.numRows();
364 scalar_type valReplacement_dev = valReplacement;
371 Kokkos::parallel_for(
372 "Utilities::GetMatrixDiagonalInverse",
373 Kokkos::RangePolicy<ordinal_type, execution_space>(0, numRows),
374 KOKKOS_LAMBDA(
const ordinal_type rowIdx) {
375 bool foundDiagEntry =
false;
376 auto myRow = localMatrix.rowConst(rowIdx);
377 for (ordinal_type entryIdx = 0; entryIdx < myRow.length; ++entryIdx) {
378 if (myRow.colidx(entryIdx) == rowIdx) {
379 foundDiagEntry =
true;
380 if (KAT::magnitude(myRow.value(entryIdx)) > KAT::magnitude(tol)) {
381 diagVals(rowIdx, 0) = KAT::one() / myRow.value(entryIdx);
383 diagVals(rowIdx, 0) = valReplacement_dev;
389 if (!foundDiagEntry) {
390 diagVals(rowIdx, 0) = KAT::zero();
394 Kokkos::parallel_for(
395 "Utilities::GetMatrixDiagonalInverse",
396 Kokkos::RangePolicy<ordinal_type, execution_space>(0, numRows),
397 KOKKOS_LAMBDA(
const ordinal_type rowIdx) {
398 auto myRow = localMatrix.rowConst(rowIdx);
399 for (ordinal_type entryIdx = 0; entryIdx < myRow.length; ++entryIdx) {
400 diagVals(rowIdx, 0) += KAT::magnitude(myRow.value(entryIdx));
402 if (KAT::magnitude(diagVals(rowIdx, 0)) > KAT::magnitude(tol))
403 diagVals(rowIdx, 0) = KAT::one() / diagVals(rowIdx, 0);
405 diagVals(rowIdx, 0) = valReplacement_dev;
411 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
417 const bool replaceSingleEntryRowWithZero,
418 const bool useAverageAbsDiagVal) {
422 const Scalar zero = TST::zero();
423 const Scalar one = TST::one();
424 const Scalar two = one + one;
430 if (bA == Teuchos::null) {
434 if (rowMap->lib() == Xpetra::UnderlyingLib::UseTpetra) {
437 using local_vector_type =
typename Vector::dual_view_type::t_dev_um;
438 using local_matrix_type =
typename Matrix::local_matrix_type;
439 using execution_space =
typename local_vector_type::execution_space;
442 using values_type =
typename local_matrix_type::values_type;
443 using scalar_type =
typename values_type::non_const_value_type;
444 #if KOKKOS_VERSION >= 40799
445 using mag_type =
typename KokkosKernels::ArithTraits<scalar_type>::mag_type;
447 using mag_type =
typename Kokkos::ArithTraits<scalar_type>::mag_type;
449 #if KOKKOS_VERSION >= 40799
450 using KAT_S =
typename KokkosKernels::ArithTraits<scalar_type>;
452 using KAT_S =
typename Kokkos::ArithTraits<scalar_type>;
454 #if KOKKOS_VERSION >= 40799
455 using KAT_M =
typename KokkosKernels::ArithTraits<mag_type>;
457 using KAT_M =
typename Kokkos::ArithTraits<mag_type>;
459 using size_type =
typename local_matrix_type::non_const_size_type;
461 local_vector_type diag_dev = diag->getLocalViewDevice(Xpetra::Access::OverwriteAll);
462 local_matrix_type local_mat_dev = rcpA->getLocalMatrixDevice();
463 Kokkos::RangePolicy<execution_space, int> my_policy(0, static_cast<int>(diag_dev.extent(0)));
464 scalar_type valReplacement_dev = valReplacement;
467 Kokkos::View<int*, execution_space> nnzPerRow(
"nnz per rows", diag_dev.extent(0));
468 Kokkos::View<scalar_type*, execution_space> regSum(
"regSum", diag_dev.extent(0));
469 Kokkos::View<mag_type, execution_space> avgAbsDiagVal_dev(
"avgAbsDiagVal");
470 Kokkos::View<int, execution_space> numDiagsEqualToOne_dev(
"numDiagsEqualToOne");
474 Kokkos::parallel_for(
475 "GetLumpedMatrixDiagonal", my_policy,
476 KOKKOS_LAMBDA(
const int rowIdx) {
477 diag_dev(rowIdx, 0) = KAT_S::zero();
478 for (size_type entryIdx = local_mat_dev.graph.row_map(rowIdx);
479 entryIdx < local_mat_dev.graph.row_map(rowIdx + 1);
481 regSum(rowIdx) += local_mat_dev.values(entryIdx);
482 if (KAT_M::zero() < KAT_S::abs(local_mat_dev.values(entryIdx))) {
485 diag_dev(rowIdx, 0) += KAT_S::abs(local_mat_dev.values(entryIdx));
486 if (rowIdx == local_mat_dev.graph.entries(entryIdx)) {
487 Kokkos::atomic_add(&avgAbsDiagVal_dev(), KAT_S::abs(local_mat_dev.values(entryIdx)));
491 if (nnzPerRow(rowIdx) == 1 && KAT_S::magnitude(diag_dev(rowIdx, 0)) == KAT_M::one()) {
492 Kokkos::atomic_add(&numDiagsEqualToOne_dev(), 1);
496 if (useAverageAbsDiagVal) {
498 typename Kokkos::View<mag_type, execution_space>::host_mirror_type avgAbsDiagVal = Kokkos::create_mirror_view(avgAbsDiagVal_dev);
499 Kokkos::deep_copy(avgAbsDiagVal, avgAbsDiagVal_dev);
500 int numDiagsEqualToOne;
501 Kokkos::deep_copy(numDiagsEqualToOne, numDiagsEqualToOne_dev);
508 Kokkos::parallel_for(
509 "ComputeLumpedDiagonalInverse", my_policy,
510 KOKKOS_LAMBDA(
const int rowIdx) {
511 if (replaceSingleEntryRowWithZero && nnzPerRow(rowIdx) <= 1) {
512 diag_dev(rowIdx, 0) = KAT_S::zero();
513 }
else if ((diag_dev(rowIdx, 0) != KAT_S::zero()) && (KAT_S::magnitude(diag_dev(rowIdx, 0)) < KAT_S::magnitude(2 * regSum(rowIdx)))) {
514 diag_dev(rowIdx, 0) = KAT_S::one() / KAT_S::magnitude(2 * regSum(rowIdx));
516 if (KAT_S::magnitude(diag_dev(rowIdx, 0)) > tol) {
517 diag_dev(rowIdx, 0) = KAT_S::one() / diag_dev(rowIdx, 0);
519 diag_dev(rowIdx, 0) = valReplacement_dev;
527 Kokkos::parallel_for(
528 "GetLumpedMatrixDiagonal", my_policy,
529 KOKKOS_LAMBDA(
const int rowIdx) {
530 diag_dev(rowIdx, 0) = KAT_S::zero();
531 for (size_type entryIdx = local_mat_dev.graph.row_map(rowIdx);
532 entryIdx < local_mat_dev.graph.row_map(rowIdx + 1);
534 diag_dev(rowIdx, 0) += KAT_S::magnitude(local_mat_dev.values(entryIdx));
546 std::vector<int> nnzPerRow(rowMap->getLocalNumElements());
551 const Magnitude zeroMagn = TST::magnitude(zero);
552 Magnitude avgAbsDiagVal = TST::magnitude(zero);
553 int numDiagsEqualToOne = 0;
554 for (
size_t i = 0; i < rowMap->getLocalNumElements(); ++i) {
556 rcpA->getLocalRowView(i, cols, vals);
559 regSum[i] += vals[j];
560 const Magnitude rowEntryMagn = TST::magnitude(vals[j]);
561 if (rowEntryMagn > zeroMagn)
563 diagVals[i] += rowEntryMagn;
564 if (static_cast<size_t>(cols[j]) == i)
565 avgAbsDiagVal += rowEntryMagn;
567 if (nnzPerRow[i] == 1 && TST::magnitude(diagVals[i]) == 1.)
568 numDiagsEqualToOne++;
570 if (useAverageAbsDiagVal)
573 for (
size_t i = 0; i < rowMap->getLocalNumElements(); ++i) {
574 if (replaceSingleEntryRowWithZero && nnzPerRow[i] <= static_cast<int>(1))
576 else if ((diagVals[i] != zero) && (TST::magnitude(diagVals[i]) < TST::magnitude(two * regSum[i])))
577 diagVals[i] = one / TST::magnitude((two * regSum[i]));
579 if (TST::magnitude(diagVals[i]) > tol)
580 diagVals[i] = one / diagVals[i];
582 diagVals[i] = valReplacement;
590 "UtilitiesBase::GetLumpedMatrixDiagonal(): extracting reciprocal of diagonal of a blocked matrix is not supported");
593 for (
size_t row = 0; row < bA->Rows(); ++row) {
594 for (
size_t col = 0; col < bA->Cols(); ++col) {
595 if (!bA->getMatrix(row, col).
is_null()) {
598 RCP<Vector> ddtemp = bA->getRangeMapExtractor()->ExtractVector(diag, row, bThyraMode);
600 ddtemp->update(Teuchos::as<Scalar>(1.0), *dd, Teuchos::as<Scalar>(1.0));
601 bA->getRangeMapExtractor()->InsertVector(ddtemp, row, diag, bThyraMode);
610 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
619 using local_vector_type =
typename Vector::dual_view_type::t_dev_um;
620 using local_matrix_type =
typename Matrix::local_matrix_type;
621 using execution_space =
typename local_vector_type::execution_space;
622 using values_type =
typename local_matrix_type::values_type;
623 using scalar_type =
typename values_type::non_const_value_type;
624 #if KOKKOS_VERSION >= 40799
625 using KAT_S =
typename KokkosKernels::ArithTraits<scalar_type>;
627 using KAT_S =
typename Kokkos::ArithTraits<scalar_type>;
630 auto diag_dev = diag->getLocalViewDevice(Xpetra::Access::OverwriteAll);
631 auto local_mat_dev = A.getLocalMatrixDevice();
632 Kokkos::RangePolicy<execution_space, int> my_policy(0, static_cast<int>(diag_dev.extent(0)));
634 Kokkos::parallel_for(
635 "GetMatrixMaxMinusOffDiagonal", my_policy,
637 auto mymax = KAT_S::zero();
638 auto row = local_mat_dev.rowConst(rowIdx);
639 for (
LocalOrdinal entryIdx = 0; entryIdx < row.length; ++entryIdx) {
640 if (rowIdx != row.colidx(entryIdx)) {
641 if (KAT_S::real(mymax) < -KAT_S::real(row.value(entryIdx)))
642 mymax = -KAT_S::real(row.value(entryIdx));
645 diag_dev(rowIdx, 0) = mymax;
651 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
655 TEUCHOS_TEST_FOR_EXCEPTION(!A.getColMap()->isSameAs(*BlockNumber.
getMap()), std::runtime_error,
"GetMatrixMaxMinusOffDiagonal: BlockNumber must match's A's column map.");
662 using local_vector_type =
typename Vector::dual_view_type::t_dev_um;
663 using local_matrix_type =
typename Matrix::local_matrix_type;
664 using execution_space =
typename local_vector_type::execution_space;
665 using values_type =
typename local_matrix_type::values_type;
666 using scalar_type =
typename values_type::non_const_value_type;
667 #if KOKKOS_VERSION >= 40799
668 using KAT_S =
typename KokkosKernels::ArithTraits<scalar_type>;
670 using KAT_S =
typename Kokkos::ArithTraits<scalar_type>;
673 auto diag_dev = diag->getLocalViewDevice(Xpetra::Access::OverwriteAll);
674 auto local_mat_dev = A.getLocalMatrixDevice();
675 auto local_block_dev = BlockNumber.getLocalViewDevice(Xpetra::Access::ReadOnly);
676 Kokkos::RangePolicy<execution_space, int> my_policy(0, static_cast<int>(diag_dev.extent(0)));
678 Kokkos::parallel_for(
679 "GetMatrixMaxMinusOffDiagonal", my_policy,
681 auto mymax = KAT_S::zero();
682 auto row = local_mat_dev.row(rowIdx);
683 for (
LocalOrdinal entryIdx = 0; entryIdx < row.length; ++entryIdx) {
684 if ((rowIdx != row.colidx(entryIdx)) && (local_block_dev(rowIdx, 0) == local_block_dev(row.colidx(entryIdx), 0))) {
685 if (KAT_S::real(mymax) < -KAT_S::real(row.value(entryIdx)))
686 mymax = -KAT_S::real(row.value(entryIdx));
689 diag_dev(rowIdx, 0) = mymax;
695 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
703 if (bv.is_null() ==
false) {
707 for (
size_t r = 0; r < bmap->getNumMaps(); ++r) {
711 bret->setMultiVector(r, subvecinf, bmap->getThyraMode());
719 for (
size_t i = 0; i < v->getMap()->getLocalNumElements(); ++i) {
723 retVals[i] = valReplacement;
766 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
773 if (importer.
is_null() && !rowMap->isSameAs(*colMap)) {
774 importer = ImportFactory::Build(rowMap, colMap);
777 RCP<Vector> diagonal = VectorFactory::Build(colMap);
784 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
793 if (!browMap.
is_null()) rowMap = browMap->getMap();
799 for (
LO row = 0; row < static_cast<LO>(A.getRowMap()->getLocalNumElements()); ++row) {
807 for (
LO colID = 0; colID < static_cast<LO>(nnz); colID++) {
808 if (indices[colID] != row) {
817 if (importer == Teuchos::null) {
824 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
836 if (!browMap.
is_null()) rowMap = browMap->getMap();
842 for (
LO rowIdx = 0; rowIdx < static_cast<LO>(A.getRowMap()->getLocalNumElements()); ++rowIdx) {
850 for (
LO colID = 0; colID < static_cast<LO>(nnz); ++colID) {
851 if (indices[colID] != rowIdx) {
852 si += STS::magnitude(vals[colID]);
855 localVals[rowIdx] = si;
860 if (importer == Teuchos::null) {
867 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
871 using local_matrix_type =
typename Matrix::local_matrix_type;
872 using execution_space =
typename local_matrix_type::execution_space;
873 #if KOKKOS_VERSION >= 40799
874 using KAT_S =
typename KokkosKernels::ArithTraits<typename local_matrix_type::value_type>;
876 using KAT_S =
typename Kokkos::ArithTraits<typename local_matrix_type::value_type>;
879 auto local_mat_dev = A.getLocalMatrixDevice();
880 Kokkos::RangePolicy<execution_space, int> my_policy(0, static_cast<int>(local_mat_dev.numRows()));
883 Kokkos::parallel_reduce(
884 "CountNegativeDiagonalEntries", my_policy,
886 auto row = local_mat_dev.row(rowIdx);
887 for (
LocalOrdinal entryIdx = 0; entryIdx < row.length; ++entryIdx) {
888 if (rowIdx == row.colidx(entryIdx) && KAT_S::real(row.value(entryIdx)) < 0)
894 MueLu_sumAll(A.getRowMap()->getComm(), count_l, count_g);
898 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
903 const size_t numVecs = X.getNumVectors();
910 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
915 const size_t numVecs = X.getNumVectors();
916 Residual(Op, X, RHS, Resid);
922 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
927 const size_t numVecs = X.getNumVectors();
930 Op.residual(X, RHS, *RES);
934 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
939 Op.residual(X, RHS, Resid);
942 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
948 "Utils::PowerMethod: operator must have domain and range maps that are equivalent.");
953 diagInvVec = GetMatrixDiagonalInverse(A);
956 Scalar lambda = PowerMethod(A, diagInvVec, niters, tolerance, verbose, seed);
960 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
963 PowerMethod(
const Matrix& A,
const RCP<Vector>& diagInvVec,
966 "Utils::PowerMethod: operator must have domain and range maps that are equivalent.");
980 const Scalar zero = STS::zero(), one = STS::one();
983 Magnitude
residual = STS::magnitude(zero);
986 for (
int iter = 0;
iter < niters; ++
iter) {
988 q->update(one / norms[0], *z, zero);
990 if (diagInvVec != Teuchos::null)
991 z->elementWiseMultiply(one, *diagInvVec, *z, zero);
994 if (iter % 100 == 0 || iter + 1 == niters) {
995 r->update(1.0, *z, -lambda, *q, zero);
997 residual = STS::magnitude(norms[0] / lambda);
999 std::cout <<
"Iter = " <<
iter
1000 <<
" Lambda = " << lambda
1001 <<
" Residual of A*q - lambda*q = " << residual
1005 if (residual < tolerance)
1011 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1012 RCP<Teuchos::FancyOStream>
1019 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1023 const size_t numVectors = v.size();
1026 for (
size_t j = 0; j < numVectors; j++) {
1027 d += (v[j][i0] - v[j][i1]) * (v[j][i0] - v[j][i1]);
1032 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1036 const size_t numVectors = v.size();
1040 for (
size_t j = 0; j < numVectors; j++) {
1041 d += Teuchos::as<MT>(weight[j]) * (v[j][i0] - v[j][i1]) * (v[j][i0] - v[j][i1]);
1046 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1053 if (count_twos_as_dirichlet) {
1061 for (col = 0; col < nnz; col++)
1062 if ((indices[col] != row) && STS::magnitude(vals[col]) > tol) {
1063 if (!boundaryNodes[row])
1065 boundaryNodes[row] =
false;
1068 boundaryNodes[row] =
true;
1078 for (
size_t col = 0; col < nnz; col++)
1079 if ((indices[col] != row) && STS::magnitude(vals[col]) > tol) {
1080 boundaryNodes[row] =
false;
1085 return boundaryNodes;
1088 template <
class CrsMatrix>
1089 KOKKOS_FORCEINLINE_FUNCTION
bool isDirichletRow(
typename CrsMatrix::ordinal_type rowId,
1090 KokkosSparse::SparseRowViewConst<CrsMatrix>& row,
1091 #
if KOKKOS_VERSION >= 40799
1092 const typename KokkosKernels::ArithTraits<typename CrsMatrix::value_type>::magnitudeType& tol,
1094 const typename Kokkos::ArithTraits<typename CrsMatrix::value_type>::magnitudeType& tol,
1096 const bool count_twos_as_dirichlet) {
1097 #if KOKKOS_VERSION >= 40799
1098 using ATS = KokkosKernels::ArithTraits<typename CrsMatrix::value_type>;
1100 using ATS = Kokkos::ArithTraits<typename CrsMatrix::value_type>;
1103 auto length = row.length;
1104 bool boundaryNode =
true;
1106 if (count_twos_as_dirichlet) {
1108 decltype(length) colID = 0;
1109 for (; colID < length; colID++)
1110 if ((row.colidx(colID) != rowId) &&
1111 (ATS::magnitude(row.value(colID)) > tol)) {
1114 boundaryNode =
false;
1116 if (colID == length)
1117 boundaryNode =
true;
1120 for (decltype(length) colID = 0; colID < length; colID++)
1121 if ((row.colidx(colID) != rowId) &&
1122 (ATS::magnitude(row.value(colID)) > tol)) {
1123 boundaryNode =
false;
1127 return boundaryNode;
1130 template <
class SC,
class LO,
class GO,
class NO,
class memory_space>
1131 Kokkos::View<bool*, memory_space>
1134 const bool count_twos_as_dirichlet) {
1135 #if KOKKOS_VERSION >= 40799
1136 using impl_scalar_type =
typename KokkosKernels::ArithTraits<SC>::val_type;
1138 using impl_scalar_type =
typename Kokkos::ArithTraits<SC>::val_type;
1140 #if KOKKOS_VERSION >= 40799
1141 using ATS = KokkosKernels::ArithTraits<impl_scalar_type>;
1143 using ATS = Kokkos::ArithTraits<impl_scalar_type>;
1145 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1148 Kokkos::View<bool*, typename NO::device_type::memory_space> boundaryNodes;
1150 if (helpers::isTpetraBlockCrs(A)) {
1152 auto b_graph = Am.getCrsGraph().getLocalGraphDevice();
1153 auto b_rowptr = Am.getCrsGraph().getLocalRowPtrsDevice();
1158 boundaryNodes = Kokkos::View<bool*, typename NO::device_type::memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"boundaryNodes"), numBlockRows);
1160 if (count_twos_as_dirichlet)
1163 Kokkos::parallel_for(
1164 "MueLu:Utils::DetectDirichletRowsBlockCrs", range_type(0, numBlockRows),
1165 KOKKOS_LAMBDA(
const LO row) {
1166 auto rowView = b_graph.rowConst(row);
1167 auto length = rowView.length;
1168 LO valstart = b_rowptr[row] * stride;
1170 boundaryNodes(row) =
true;
1171 decltype(length) colID = 0;
1172 for (; colID < length; colID++) {
1173 if (rowView.colidx(colID) != row) {
1174 LO current = valstart + colID * stride;
1175 for (
LO k = 0; k < stride; k++) {
1176 if (ATS::magnitude(values[current + k]) > tol) {
1177 boundaryNodes(row) =
false;
1182 if (boundaryNodes(row) ==
false)
1187 auto localMatrix = A.getLocalMatrixDevice();
1188 LO numRows = A.getLocalNumRows();
1189 boundaryNodes = Kokkos::View<bool*, typename NO::device_type::memory_space>(Kokkos::ViewAllocateWithoutInitializing(
"boundaryNodes"), numRows);
1191 Kokkos::parallel_for(
1192 "MueLu:Utils::DetectDirichletRows", range_type(0, numRows),
1193 KOKKOS_LAMBDA(
const LO row) {
1194 auto rowView = localMatrix.rowConst(row);
1195 boundaryNodes(row) =
isDirichletRow(row, rowView, tol, count_twos_as_dirichlet);
1198 if constexpr (std::is_same<memory_space, typename NO::device_type::memory_space>::value)
1199 return boundaryNodes;
1201 Kokkos::View<bool*, memory_space> boundaryNodes2(Kokkos::ViewAllocateWithoutInitializing(
"boundaryNodes"), boundaryNodes.extent(0));
1202 Kokkos::deep_copy(boundaryNodes2, boundaryNodes);
1203 return boundaryNodes2;
1206 Kokkos::View<bool*, memory_space> dummy(
"dummy", 0);
1210 template <
class SC,
class LO,
class GO,
class NO>
1211 Kokkos::View<bool*, typename NO::device_type::memory_space>
1215 const bool count_twos_as_dirichlet) {
1216 return MueLu::DetectDirichletRows_kokkos<SC, LO, GO, NO, typename NO::device_type::memory_space>(A, tol, count_twos_as_dirichlet);
1219 template <
class SC,
class LO,
class GO,
class NO>
1220 Kokkos::View<bool*, typename Kokkos::HostSpace>
1224 const bool count_twos_as_dirichlet) {
1225 return MueLu::DetectDirichletRows_kokkos<SC, LO, GO, NO, typename Kokkos::HostSpace>(A, tol, count_twos_as_dirichlet);
1228 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1233 bHasZeroDiagonal =
false;
1247 bool bHasDiag =
false;
1248 for (decltype(indices.
size()) col = 0; col < indices.
size(); col++) {
1249 if (indices[col] != row) {
1250 if (STS::magnitude(vals[col] / STS::magnitude(sqrt(STS::magnitude(diagVecData[row]) * STS::magnitude(diagVecData[col])))) > tol) {
1256 if (bHasDiag ==
false)
1257 bHasZeroDiagonal =
true;
1259 boundaryNodes[row] =
true;
1261 return boundaryNodes;
1264 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1270 const bool count_twos_as_dirichlet) {
1271 using range_type = Kokkos::RangePolicy<LO, typename Node::execution_space>;
1280 auto lclRHS = RHS.getLocalViewDevice(Xpetra::Access::ReadOnly);
1281 auto lclInitialGuess = InitialGuess.getLocalViewDevice(Xpetra::Access::ReadWrite);
1282 auto lclA = A.getLocalMatrixDevice();
1284 Kokkos::parallel_for(
1285 "MueLu:Utils::EnforceInitialCondition", range_type(0, numRows),
1286 KOKKOS_LAMBDA(
const LO i) {
1287 auto row = lclA.rowConst(i);
1290 lclInitialGuess(i, j) = lclRHS(i, j);
1295 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1302 for (
size_t i = 0; i < static_cast<size_t>(vals.
size()); i++) {
1308 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1311 Kokkos::View<bool*, typename Node::device_type> nonzeros) {
1312 #if KOKKOS_VERSION >= 40799
1313 using ATS = KokkosKernels::ArithTraits<Scalar>;
1315 using ATS = Kokkos::ArithTraits<Scalar>;
1317 #if KOKKOS_VERSION >= 40799
1318 using impl_ATS = KokkosKernels::ArithTraits<typename ATS::val_type>;
1320 using impl_ATS = Kokkos::ArithTraits<typename ATS::val_type>;
1322 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1324 const typename ATS::magnitudeType eps = 2.0 * impl_ATS::eps();
1326 Kokkos::parallel_for(
1327 "MueLu:Maxwell1::FindNonZeros", range_type(0, vals.extent(0)),
1328 KOKKOS_LAMBDA(
const size_t i) {
1329 nonzeros(i) = (impl_ATS::magnitude(vals(i, 0)) > eps);
1333 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1343 TEUCHOS_ASSERT(static_cast<size_t>(dirichletRows.
size()) == rowMap->getLocalNumElements());
1344 TEUCHOS_ASSERT(static_cast<size_t>(dirichletCols.
size()) == colMap->getLocalNumElements());
1345 TEUCHOS_ASSERT(static_cast<size_t>(dirichletDomain.
size()) == domMap->getLocalNumElements());
1348 for (
size_t i = 0; i < (size_t)dirichletRows.
size(); i++) {
1349 if (dirichletRows[i]) {
1353 for (
size_t j = 0; j < static_cast<size_t>(indices.
size()); j++)
1354 myColsToZero->replaceLocalValue(indices[j], 0, one);
1363 globalColsToZero->doExport(*myColsToZero, *importer,
Xpetra::ADD);
1365 myColsToZero->doImport(*globalColsToZero, *importer,
Xpetra::INSERT);
1367 globalColsToZero = myColsToZero;
1369 FindNonZeros(globalColsToZero->getData(0), dirichletDomain);
1370 FindNonZeros(myColsToZero->getData(0), dirichletCols);
1373 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1376 const Kokkos::View<bool*, typename Node::device_type>& dirichletRows,
1377 Kokkos::View<bool*, typename Node::device_type> dirichletCols,
1378 Kokkos::View<bool*, typename Node::device_type> dirichletDomain) {
1379 #if KOKKOS_VERSION >= 40799
1380 using ATS = KokkosKernels::ArithTraits<Scalar>;
1382 using ATS = Kokkos::ArithTraits<Scalar>;
1384 #if KOKKOS_VERSION >= 40799
1385 using impl_ATS = KokkosKernels::ArithTraits<typename ATS::val_type>;
1387 using impl_ATS = Kokkos::ArithTraits<typename ATS::val_type>;
1389 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1393 TEUCHOS_ASSERT(dirichletRows.extent(0) == rowMap->getLocalNumElements());
1394 TEUCHOS_ASSERT(dirichletCols.extent(0) == colMap->getLocalNumElements());
1395 TEUCHOS_ASSERT(dirichletDomain.extent(0) == domMap->getLocalNumElements());
1398 auto myColsToZeroView = myColsToZero->getLocalViewDevice(Xpetra::Access::ReadWrite);
1399 auto localMatrix = A.getLocalMatrixDevice();
1400 Kokkos::parallel_for(
1401 "MueLu:Maxwell1::DetectDirichletCols", range_type(0, rowMap->getLocalNumElements()),
1403 if (dirichletRows(row)) {
1404 auto rowView = localMatrix.row(row);
1405 auto length = rowView.length;
1407 for (decltype(length) colID = 0; colID < length; colID++)
1408 myColsToZeroView(rowView.colidx(colID), 0) = impl_ATS::one();
1417 globalColsToZero->doExport(*myColsToZero, *importer,
Xpetra::ADD);
1419 myColsToZero->doImport(*globalColsToZero, *importer,
Xpetra::INSERT);
1421 globalColsToZero = myColsToZero;
1426 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1433 for (
LocalOrdinal row = 0; row < Teuchos::as<LocalOrdinal>(rowmap->getLocalNumElements()); ++row) {
1439 Scalar rowsum = STS::zero();
1440 Scalar diagval = STS::zero();
1442 for (
LocalOrdinal colID = 0; colID < Teuchos::as<LocalOrdinal>(nnz); colID++) {
1445 diagval = vals[colID];
1446 rowsum += vals[colID];
1449 if (rowSumTol < MTS::one() && STS::magnitude(rowsum) > STS::magnitude(diagval) * rowSumTol) {
1451 dirichletRows[row] =
true;
1456 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1462 RCP<const Xpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> rowmap = A.getRowMap();
1464 TEUCHOS_TEST_FOR_EXCEPTION(!A.getColMap()->isSameAs(*BlockNumber.
getMap()), std::runtime_error,
"ApplyRowSumCriterion: BlockNumber must match's A's column map.");
1467 for (
LocalOrdinal row = 0; row < Teuchos::as<LocalOrdinal>(rowmap->getLocalNumElements()); ++row) {
1469 ArrayView<const LocalOrdinal> indices;
1470 ArrayView<const Scalar> vals;
1473 Scalar rowsum = STS::zero();
1474 Scalar diagval = STS::zero();
1475 for (
LocalOrdinal colID = 0; colID < Teuchos::as<LocalOrdinal>(nnz); colID++) {
1478 diagval = vals[colID];
1479 if (block_id[row] == block_id[col])
1480 rowsum += vals[colID];
1484 if (rowSumTol < MTS::one() && STS::magnitude(rowsum) > STS::magnitude(diagval) * rowSumTol) {
1486 dirichletRows[row] =
true;
1492 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node,
class memory_space>
1495 Kokkos::View<bool*, memory_space>& dirichletRows) {
1499 auto dirichletRowsHost = Kokkos::create_mirror_view(dirichletRows);
1500 Kokkos::deep_copy(dirichletRowsHost, dirichletRows);
1502 for (
LocalOrdinal row = 0; row < Teuchos::as<LocalOrdinal>(rowmap->getLocalNumElements()); ++row) {
1508 Scalar rowsum = STS::zero();
1509 Scalar diagval = STS::zero();
1510 for (
LocalOrdinal colID = 0; colID < Teuchos::as<LocalOrdinal>(nnz); colID++) {
1513 diagval = vals[colID];
1514 rowsum += vals[colID];
1516 if (STS::real(rowsum) > STS::magnitude(diagval) * rowSumTol)
1517 dirichletRowsHost(row) =
true;
1520 Kokkos::deep_copy(dirichletRows, dirichletRowsHost);
1523 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1527 Kokkos::View<bool*, typename Node::device_type::memory_space>& dirichletRows) {
1528 MueLu::ApplyRowSumCriterion<Scalar, LocalOrdinal, GlobalOrdinal, Node, typename Node::device_type::memory_space>(A, rowSumTol, dirichletRows);
1531 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1535 Kokkos::View<bool*, Kokkos::HostSpace>& dirichletRows) {
1536 MueLu::ApplyRowSumCriterion<Scalar, LocalOrdinal, GlobalOrdinal, Node, Kokkos::HostSpace>(A, rowSumTol, dirichletRows);
1540 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node,
class memory_space>
1544 Kokkos::View<bool*, memory_space>& dirichletRows) {
1548 TEUCHOS_TEST_FOR_EXCEPTION(!A.getColMap()->isSameAs(*BlockNumber.
getMap()), std::runtime_error,
"ApplyRowSumCriterion: BlockNumber must match's A's column map.");
1550 auto dirichletRowsHost = Kokkos::create_mirror_view(dirichletRows);
1551 Kokkos::deep_copy(dirichletRowsHost, dirichletRows);
1554 for (
LocalOrdinal row = 0; row < Teuchos::as<LocalOrdinal>(rowmap->getLocalNumElements()); ++row) {
1560 Scalar rowsum = STS::zero();
1561 Scalar diagval = STS::zero();
1562 for (
LocalOrdinal colID = 0; colID < Teuchos::as<LocalOrdinal>(nnz); colID++) {
1565 diagval = vals[colID];
1566 if (block_id[row] == block_id[col])
1567 rowsum += vals[colID];
1569 if (STS::real(rowsum) > STS::magnitude(diagval) * rowSumTol)
1570 dirichletRowsHost(row) =
true;
1573 Kokkos::deep_copy(dirichletRows, dirichletRowsHost);
1576 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1581 Kokkos::View<bool*, typename Node::device_type::memory_space>& dirichletRows) {
1582 MueLu::ApplyRowSumCriterion<Scalar, LocalOrdinal, GlobalOrdinal, Node, typename Node::device_type::memory_space>(A, BlockNumber, rowSumTol, dirichletRows);
1585 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1590 Kokkos::View<bool*, Kokkos::HostSpace>& dirichletRows) {
1591 MueLu::ApplyRowSumCriterion<Scalar, LocalOrdinal, GlobalOrdinal, Node, Kokkos::HostSpace>(A, BlockNumber, rowSumTol, dirichletRows);
1594 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1604 myColsToZero->putScalar(zero);
1606 for (
size_t i = 0; i < (size_t)dirichletRows.
size(); i++) {
1607 if (dirichletRows[i]) {
1611 for (
size_t j = 0; j < static_cast<size_t>(indices.
size()); j++)
1612 myColsToZero->replaceLocalValue(indices[j], 0, one);
1617 globalColsToZero->putScalar(zero);
1620 globalColsToZero->doExport(*myColsToZero, *exporter,
Xpetra::ADD);
1622 myColsToZero->doImport(*globalColsToZero, *exporter,
Xpetra::INSERT);
1626 for (
size_t i = 0; i < colMap->getLocalNumElements(); i++) {
1629 return dirichletCols;
1632 template <
class SC,
class LO,
class GO,
class NO>
1633 Kokkos::View<bool*, typename NO::device_type>
1636 const Kokkos::View<const bool*, typename NO::device_type>& dirichletRows) {
1637 #if KOKKOS_VERSION >= 40799
1638 using ATS = KokkosKernels::ArithTraits<SC>;
1640 using ATS = Kokkos::ArithTraits<SC>;
1642 #if KOKKOS_VERSION >= 40799
1643 using impl_ATS = KokkosKernels::ArithTraits<typename ATS::val_type>;
1645 using impl_ATS = Kokkos::ArithTraits<typename ATS::val_type>;
1647 using range_type = Kokkos::RangePolicy<LO, typename NO::execution_space>;
1649 SC zero = ATS::zero();
1651 auto localMatrix = A.getLocalMatrixDevice();
1652 LO numRows = A.getLocalNumRows();
1657 myColsToZero->putScalar(zero);
1658 auto myColsToZeroView = myColsToZero->getLocalViewDevice(Xpetra::Access::ReadWrite);
1660 Kokkos::parallel_for(
1661 "MueLu:Utils::DetectDirichletCols1", range_type(0, numRows),
1662 KOKKOS_LAMBDA(
const LO row) {
1663 if (dirichletRows(row)) {
1664 auto rowView = localMatrix.row(row);
1665 auto length = rowView.length;
1667 for (decltype(length) colID = 0; colID < length; colID++)
1668 myColsToZeroView(rowView.colidx(colID), 0) = impl_ATS::one();
1673 globalColsToZero->putScalar(zero);
1676 globalColsToZero->doExport(*myColsToZero, *exporter,
Xpetra::ADD);
1678 myColsToZero->doImport(*globalColsToZero, *exporter,
Xpetra::INSERT);
1680 auto myCols = myColsToZero->getLocalViewDevice(Xpetra::Access::ReadOnly);
1681 size_t numColEntries = colMap->getLocalNumElements();
1682 Kokkos::View<bool*, typename NO::device_type> dirichletCols(Kokkos::ViewAllocateWithoutInitializing(
"dirichletCols"), numColEntries);
1683 const typename ATS::magnitudeType eps = 2.0 * ATS::eps();
1685 Kokkos::parallel_for(
1686 "MueLu:Utils::DetectDirichletCols2", range_type(0, numColEntries),
1687 KOKKOS_LAMBDA(
const size_t i) {
1688 dirichletCols(i) = impl_ATS::magnitude(myCols(i, 0)) > eps;
1690 return dirichletCols;
1693 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1704 const Map& AColMap = *A.getColMap();
1705 const Map& BColMap = *B.getColMap();
1709 size_t nnzA = 0, nnzB = 0;
1725 size_t numRows = A.getLocalNumRows();
1726 for (
size_t i = 0; i < numRows; i++) {
1733 for (
size_t j = 0; j < nnzB; j++)
1734 valBAll[indB[j]] = valB[j];
1736 for (
size_t j = 0; j < nnzA; j++) {
1739 LocalOrdinal ind = BColMap.getLocalElement(AColMap.getGlobalElement(indA[j]));
1741 f += valBAll[ind] * valA[j];
1745 for (
size_t j = 0; j < nnzB; j++)
1746 valBAll[indB[j]] = zero;
1754 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1762 int maxint = INT_MAX;
1763 int mySeed = Teuchos::as<int>((maxint - 1) * (one - (comm.
getRank() + 1) / (comm.
getSize() + one)));
1764 if (mySeed < 1 || mySeed == maxint) {
1765 std::ostringstream errStr;
1766 errStr <<
"Error detected with random seed = " << mySeed <<
". It should be in the interval [1,2^31-2].";
1778 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1781 std::vector<LocalOrdinal>& dirichletRows,
bool count_twos_as_dirichlet) {
1783 dirichletRows.resize(0);
1784 for (
size_t i = 0; i < A->getLocalNumRows(); i++) {
1789 for (
size_t j = 0; j < (size_t)indices.
size(); j++) {
1794 if (nnz == 1 || (count_twos_as_dirichlet && nnz == 2)) {
1795 dirichletRows.push_back(i);
1800 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1803 const std::vector<LocalOrdinal>& dirichletRows) {
1809 for (
size_t i = 0; i < dirichletRows.size(); i++) {
1810 GlobalOrdinal row_gid = Rmap->getGlobalElement(dirichletRows[i]);
1817 for (
size_t j = 0; j < (size_t)indices.
size(); j++) {
1818 if (Cmap->getGlobalElement(indices[j]) == row_gid)
1826 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1835 TEUCHOS_ASSERT(static_cast<size_t>(dirichletRows.
size()) == Rmap->getLocalNumElements());
1839 for (
size_t i = 0; i < (size_t)dirichletRows.
size(); i++) {
1840 if (dirichletRows[i]) {
1848 for (
size_t j = 0; j < (size_t)indices.
size(); j++) {
1849 if (Cmap->getGlobalElement(indices[j]) == row_gid)
1860 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1863 const Kokkos::View<const bool*, typename Node::device_type>& dirichletRows) {
1865 #if KOKKOS_VERSION >= 40799
1866 using ATS = KokkosKernels::ArithTraits<Scalar>;
1868 using ATS = Kokkos::ArithTraits<Scalar>;
1870 #if KOKKOS_VERSION >= 40799
1871 using impl_ATS = KokkosKernels::ArithTraits<typename ATS::val_type>;
1873 using impl_ATS = Kokkos::ArithTraits<typename ATS::val_type>;
1875 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1882 TEUCHOS_ASSERT(static_cast<size_t>(dirichletRows.size()) == Rmap->getLocalNumElements());
1884 auto localMatrix = A->getLocalMatrixDevice();
1885 auto localRmap = Rmap->getLocalMap();
1886 auto localCmap = Cmap->getLocalMap();
1888 Kokkos::parallel_for(
1889 "MueLu::Utils::ApplyOAZ", range_type(0, dirichletRows.extent(0)),
1891 if (dirichletRows(row)) {
1892 auto rowView = localMatrix.row(row);
1893 auto length = rowView.length;
1894 auto row_gid = localRmap.getGlobalElement(row);
1895 auto row_lid = localCmap.getLocalElement(row_gid);
1897 for (decltype(length) colID = 0; colID < length; colID++)
1898 if (rowView.colidx(colID) == row_lid)
1899 rowView.value(colID) = impl_ATS::one();
1901 rowView.value(colID) = impl_ATS::zero();
1906 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1909 const std::vector<LocalOrdinal>& dirichletRows,
1911 for (
size_t i = 0; i < dirichletRows.size(); i++) {
1917 for (
size_t j = 0; j < (size_t)indices.
size(); j++)
1918 valuesNC[j] = replaceWith;
1922 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1927 TEUCHOS_ASSERT(static_cast<size_t>(dirichletRows.
size()) == A->getRowMap()->getLocalNumElements());
1928 for (
size_t i = 0; i < (size_t)dirichletRows.
size(); i++) {
1929 if (dirichletRows[i]) {
1935 for (
size_t j = 0; j < (size_t)indices.
size(); j++)
1936 valuesNC[j] = replaceWith;
1941 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1946 TEUCHOS_ASSERT(static_cast<size_t>(dirichletRows.
size()) == X->getMap()->getLocalNumElements());
1947 for (
size_t i = 0; i < (size_t)dirichletRows.
size(); i++) {
1948 if (dirichletRows[i]) {
1949 for (
size_t j = 0; j < X->getNumVectors(); j++)
1950 X->replaceLocalValue(i, j, replaceWith);
1955 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1958 const Kokkos::View<const bool*, typename Node::device_type>& dirichletRows,
1960 #if KOKKOS_VERSION >= 40799
1961 using ATS = KokkosKernels::ArithTraits<Scalar>;
1963 using ATS = Kokkos::ArithTraits<Scalar>;
1965 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1967 typename ATS::val_type impl_replaceWith = replaceWith;
1969 auto localMatrix = A->getLocalMatrixDevice();
1972 Kokkos::parallel_for(
1973 "MueLu:Utils::ZeroDirichletRows", range_type(0, numRows),
1975 if (dirichletRows(row)) {
1976 auto rowView = localMatrix.row(row);
1977 auto length = rowView.length;
1978 for (decltype(length) colID = 0; colID < length; colID++)
1979 rowView.value(colID) = impl_replaceWith;
1984 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1987 const Kokkos::View<const bool*, typename Node::device_type>& dirichletRows,
1989 #if KOKKOS_VERSION >= 40799
1990 using ATS = KokkosKernels::ArithTraits<Scalar>;
1992 using ATS = Kokkos::ArithTraits<Scalar>;
1994 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
1996 typename ATS::val_type impl_replaceWith = replaceWith;
1998 auto myCols = X->getLocalViewDevice(Xpetra::Access::ReadWrite);
1999 size_t numVecs = X->getNumVectors();
2000 Kokkos::parallel_for(
2001 "MueLu:Utils::ZeroDirichletRows_MV", range_type(0, dirichletRows.size()),
2002 KOKKOS_LAMBDA(
const size_t i) {
2003 if (dirichletRows(i)) {
2004 for (
size_t j = 0; j < numVecs; j++)
2005 myCols(i, j) = impl_replaceWith;
2010 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2015 TEUCHOS_ASSERT(static_cast<size_t>(dirichletCols.
size()) == A->getColMap()->getLocalNumElements());
2016 for (
size_t i = 0; i < A->getLocalNumRows(); i++) {
2019 A->getLocalRowView(i, indices, values);
2022 for (
size_t j = 0; j < static_cast<size_t>(indices.
size()); j++)
2023 if (dirichletCols[indices[j]])
2024 valuesNC[j] = replaceWith;
2028 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2031 const Kokkos::View<const bool*, typename Node::device_type>& dirichletCols,
2033 #if KOKKOS_VERSION >= 40799
2034 using ATS = KokkosKernels::ArithTraits<Scalar>;
2036 using ATS = Kokkos::ArithTraits<Scalar>;
2038 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
2040 typename ATS::val_type impl_replaceWith = replaceWith;
2042 auto localMatrix = A->getLocalMatrixDevice();
2045 Kokkos::parallel_for(
2046 "MueLu:Utils::ZeroDirichletCols", range_type(0, numRows),
2048 auto rowView = localMatrix.row(row);
2049 auto length = rowView.length;
2050 for (decltype(length) colID = 0; colID < length; colID++)
2051 if (dirichletCols(rowView.colidx(colID))) {
2052 rowView.value(colID) = impl_replaceWith;
2057 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2064 throw std::runtime_error(
"UtilitiesBase::FindDirichletRowsAndPropagateToCols row and domain maps must match.");
2067 bool has_import = !importer.
is_null();
2070 std::vector<LocalOrdinal> dirichletRows;
2071 FindDirichletRows(A, dirichletRows);
2074 printf(
"[%d] DirichletRow Ids = ",A->getRowMap()->getComm()->getRank());
2075 for(
size_t i=0; i<(size_t) dirichletRows.size(); i++)
2076 printf(
"%d ",dirichletRows[i]);
2089 for (
size_t i = 0; i < (size_t)dirichletRows.size(); i++) {
2090 dr[dirichletRows[i]] = 1;
2091 if (!has_import) dc[dirichletRows[i]] = 1;
2096 isDirichletCol->doImport(*
isDirichletRow, *importer, Xpetra::CombineMode::ADD);
2099 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2103 #if KOKKOS_VERSION >= 40799
2104 using ISC =
typename KokkosKernels::ArithTraits<Scalar>::val_type;
2106 using ISC =
typename Kokkos::ArithTraits<Scalar>::val_type;
2108 using range_type = Kokkos::RangePolicy<LocalOrdinal, typename Node::execution_space>;
2109 using local_matrix_type =
typename CrsMatrix::local_matrix_type;
2110 using values_type =
typename local_matrix_type::values_type;
2112 #if KOKKOS_VERSION >= 40799
2113 const ISC ONE = KokkosKernels::ArithTraits<ISC>::one();
2115 const ISC ONE = Kokkos::ArithTraits<ISC>::one();
2117 #if KOKKOS_VERSION >= 40799
2118 const ISC
ZERO = KokkosKernels::ArithTraits<ISC>::zero();
2120 const ISC ZERO = Kokkos::ArithTraits<ISC>::zero();
2124 auto localMatrix = original->getLocalMatrixDevice();
2126 values_type new_values(
"values", localMatrix.nnz());
2128 Kokkos::parallel_for(
2129 "ReplaceNonZerosWithOnes", range_type(0, localMatrix.nnz()), KOKKOS_LAMBDA(
const size_t i) {
2130 if (localMatrix.values(i) != ZERO)
2131 new_values(i) = ONE;
2133 new_values(i) = ZERO;
2139 NewMatrix->fillComplete(original->getDomainMap(), original->getRangeMap());
2143 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2154 if (!stridedMap.
is_null()) fullMap = stridedMap->getMap();
2157 const size_t numSubMaps = sourceBlockedMap.
getNumMaps();
2159 throw std::runtime_error(
"GenerateBlockedTargetMap(): Map compatibility error");
2164 for (
size_t i = 0; i < numSubMaps; i++) {
2167 for (
size_t j = 0; j < map->getLocalNumElements(); j++) {
2168 LocalOrdinal jj = fullMap->getLocalElement(map->getGlobalElement(j));
2169 block_ids->replaceLocalValue(jj, (
int)i);
2176 new_block_ids->doImport(*block_ids, Importer, Xpetra::CombineMode::ADD);
2182 for (
size_t i = 0; i < targetMap->getLocalNumElements(); i++) {
2183 elementsInSubMap[data[i]].
push_back(targetMap->getGlobalElement(i));
2187 std::vector<RCP<const Map>> subMaps(numSubMaps);
2188 for (
size_t i = 0; i < numSubMaps; i++) {
2193 return rcp(
new BlockedMap(targetMap, subMaps));
2196 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2202 return tpColMap.isLocallyFitted(tpRowMap);
2208 const size_t numElements = rowElements.
size();
2210 if (
size_t(colElements.
size()) < numElements)
2213 bool goodMap =
true;
2214 for (
size_t i = 0; i < numElements; i++)
2215 if (rowElements[i] != colElements[i]) {
2223 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2228 using local_graph_type =
typename local_matrix_type::staticcrsgraph_type;
2229 using lno_nnz_view_t =
typename local_graph_type::entries_type::non_const_type;
2230 using device =
typename local_graph_type::device_type;
2231 using execution_space =
typename local_matrix_type::execution_space;
2232 using ordinal_type =
typename local_matrix_type::ordinal_type;
2234 local_graph_type localGraph = Op.getLocalMatrixDevice().graph;
2236 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);
2242 auto view1D = Kokkos::subview(retval->getLocalViewDevice(Xpetra::Access::ReadWrite), Kokkos::ALL(), 0);
2243 Kokkos::parallel_for(
2244 "Utilities::ReverseCuthillMcKee",
2245 Kokkos::RangePolicy<ordinal_type, execution_space>(0, localGraph.numRows()),
2246 KOKKOS_LAMBDA(
const ordinal_type rowIdx) {
2247 view1D(rcmOrder(rowIdx)) = rowIdx;
2252 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
2257 using local_graph_type =
typename local_matrix_type::staticcrsgraph_type;
2258 using lno_nnz_view_t =
typename local_graph_type::entries_type::non_const_type;
2259 using device =
typename local_graph_type::device_type;
2260 using execution_space =
typename local_matrix_type::execution_space;
2261 using ordinal_type =
typename local_matrix_type::ordinal_type;
2263 local_graph_type localGraph = Op.getLocalMatrixDevice().graph;
2266 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);
2272 auto view1D = Kokkos::subview(retval->getLocalViewDevice(Xpetra::Access::ReadWrite), Kokkos::ALL(), 0);
2274 Kokkos::parallel_for(
2275 "Utilities::ReverseCuthillMcKee",
2276 Kokkos::RangePolicy<ordinal_type, execution_space>(0, numRows),
2277 KOKKOS_LAMBDA(
const ordinal_type rowIdx) {
2278 view1D(rcmOrder(numRows - 1 - rowIdx)) = rowIdx;
2285 #define MUELU_UTILITIESBASE_SHORT
2286 #endif // MUELU_UTILITIESBASE_DEF_HPP
static void FindNonZeros(const Teuchos::ArrayRCP< const Scalar > vals, Teuchos::ArrayRCP< bool > nonzeros)
Find non-zero values in an ArrayRCP Compares the value to 2 * machine epsilon.
KOKKOS_FORCEINLINE_FUNCTION bool isDirichletRow(typename CrsMatrix::ordinal_type rowId, KokkosSparse::SparseRowViewConst< CrsMatrix > &row, const typename Kokkos::ArithTraits< typename CrsMatrix::value_type >::magnitudeType &tol, const bool count_twos_as_dirichlet)
static RCP< Export< LocalOrdinal, GlobalOrdinal, Node > > Build(const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &source, const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &target)
static RCP< Vector > GetMatrixDiagonal(const Matrix &A)
Extract Matrix Diagonal.
static void ApplyOAZToMatrixRows(Teuchos::RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> &A, const std::vector< LocalOrdinal > &dirichletRows)
static Teuchos::RCP< Vector > GetMatrixMaxMinusOffDiagonal(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A)
Return vector containing: max_{i=k}(-a_ik), for each for i in the matrix.
static void ZeroDirichletCols(Teuchos::RCP< Matrix > &A, const Teuchos::ArrayRCP< const bool > &dirichletCols, Scalar replaceWith=Teuchos::ScalarTraits< Scalar >::zero())
static void DetectDirichletColsAndDomains(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Teuchos::ArrayRCP< bool > &dirichletRows, Teuchos::ArrayRCP< bool > dirichletCols, Teuchos::ArrayRCP< bool > dirichletDomain)
Detects Dirichlet columns & domains from a list of Dirichlet rows.
#define MueLu_sumAll(rcpComm, in, out)
Array< T > & append(const T &x)
virtual int getSize() const =0
MueLu::DefaultLocalOrdinal LocalOrdinal
void ApplyRowSumCriterion(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const typename Teuchos::ScalarTraits< Scalar >::magnitudeType rowSumTol, Kokkos::View< bool *, memory_space > &dirichletRows)
virtual LO getBlockSize() const override
static bool MapsAreNested(const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &rowMap, const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > &colMap)
static RCP< Xpetra::Vector< LocalOrdinal, LocalOrdinal, GlobalOrdinal, Node > > ReverseCuthillMcKee(const Matrix &Op)
static void FindDirichletRowsAndPropagateToCols(Teuchos::RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> &A, Teuchos::RCP< Xpetra::Vector< int, LocalOrdinal, GlobalOrdinal, Node >> &isDirichletRow, Teuchos::RCP< Xpetra::Vector< int, LocalOrdinal, GlobalOrdinal, Node >> &isDirichletCol)
virtual int getRank() const =0
static void ApplyRowSumCriterionHost(const Matrix &A, const typename Teuchos::ScalarTraits< Scalar >::magnitudeType rowSumTol, Kokkos::View< bool *, Kokkos::HostSpace > &dirichletRows)
static Teuchos::RCP< MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > > Build(const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node >> &map, size_t NumVectors, bool zeroOut=true)
static magnitudeType eps()
Teuchos::RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > removeSmallEntries(Teuchos::RCP< Xpetra::CrsMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> &A, const typename Teuchos::ScalarTraits< Scalar >::magnitudeType threshold, const bool keepDiagonal)
static Scalar PowerMethod(const Matrix &A, bool scaleByDiag=true, LocalOrdinal niters=10, Magnitude tolerance=1e-2, bool verbose=false, unsigned int seed=123)
Power method.
static GlobalOrdinal CountNegativeDiagonalEntries(const Matrix &A)
Counts the number of negative diagonal entries.
static void ApplyRowSumCriterion(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Magnitude rowSumTol, Teuchos::ArrayRCP< bool > &dirichletRows)
Apply Rowsum Criterion.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
static RCP< Vector > GetMatrixOverlappedDeletedRowsum(const Matrix &A)
Extract Overlapped Matrix Deleted Rowsum.
virtual const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getRowMap() const =0
static RCP< Xpetra::CrsGraph< LocalOrdinal, GlobalOrdinal, Node > > GetThresholdedGraph(const RCP< Matrix > &A, const Magnitude threshold, const GlobalOrdinal expectedNNZperRow=-1)
Threshold a graph.
virtual void resumeFill(const RCP< ParameterList > ¶ms=null)=0
static void ZeroDirichletRows(Teuchos::RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> &A, const std::vector< LocalOrdinal > &dirichletRows, Scalar replaceWith=Teuchos::ScalarTraits< Scalar >::zero())
static RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > ReplaceNonZerosWithOnes(const RCP< Matrix > &original)
Creates a copy of a matrix where the non-zero entries are replaced by ones.
size_t getLocalNumRows() const override
Exception throws to report incompatible objects (like maps).
static void SetRandomSeed(const Teuchos::Comm< int > &comm)
Set seed for random number generator.
static RCP< Xpetra::Vector< LocalOrdinal, LocalOrdinal, GlobalOrdinal, Node > > CuthillMcKee(const Matrix &Op)
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getTargetMap() const =0
static RCP< Time > getNewTimer(const std::string &name)
void resize(const size_type n, const T &val=T())
virtual void fillComplete(const RCP< const Map > &domainMap, const RCP< const Map > &rangeMap, const RCP< ParameterList > ¶ms=null)=0
virtual void getLocalDiagCopy(Vector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &diag) const =0
static RCP< MultiVector > Residual(const Xpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, const MultiVector &X, const MultiVector &RHS)
static Teuchos::ArrayRCP< const bool > DetectDirichletCols(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Teuchos::ArrayRCP< const bool > &dirichletRows)
Detect Dirichlet columns based on Dirichlet rows.
virtual void getLocalRowView(LocalOrdinal LocalRow, ArrayView< const LocalOrdinal > &indices, ArrayView< const Scalar > &values) const =0
static void FindDirichletRows(Teuchos::RCP< Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node >> &A, std::vector< LocalOrdinal > &dirichletRows, bool count_twos_as_dirichlet=false)
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
MueLu::DefaultScalar Scalar
Kokkos::View< bool *, memory_space > DetectDirichletRows_kokkos(const Xpetra::Matrix< SC, LO, GO, NO > &A, const typename Teuchos::ScalarTraits< SC >::magnitudeType &tol, const bool count_twos_as_dirichlet)
MueLu::DefaultGlobalOrdinal GlobalOrdinal
static RCP< CrsMatrixWrap > GetThresholdedMatrix(const RCP< Matrix > &Ain, const Magnitude threshold, const bool keepDiagonal=true, const GlobalOrdinal expectedNNZperRow=-1)
Threshold a matrix.
static Teuchos::RCP< Map< LocalOrdinal, GlobalOrdinal, Node > > Build(UnderlyingLib lib, global_size_t numGlobalElements, GlobalOrdinal indexBase, const Teuchos::RCP< const Teuchos::Comm< int >> &comm, LocalGlobal lg=Xpetra::GloballyDistributed)
static Teuchos::ArrayRCP< const bool > DetectDirichletRows(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Magnitude &tol=Teuchos::ScalarTraits< Magnitude >::zero(), bool count_twos_as_dirichlet=false)
Detect Dirichlet rows.
virtual bool isFillComplete() const =0
static RCP< Xpetra::Vector< Magnitude, LocalOrdinal, GlobalOrdinal, Node > > GetMatrixOverlappedAbsDeletedRowsum(const Matrix &A)
size_t getNumMaps() const
virtual void replaceLocalValues(LocalOrdinal localRow, const ArrayView< const LocalOrdinal > &cols, const ArrayView< const Scalar > &vals)=0
static Teuchos::ArrayRCP< Scalar > GetMatrixDiagonal_arcp(const Matrix &A)
Extract Matrix Diagonal.
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getMap() const =0
static RCP< const Xpetra::BlockedMap< LocalOrdinal, GlobalOrdinal, Node > > GeneratedBlockedTargetMap(const Xpetra::BlockedMap< LocalOrdinal, GlobalOrdinal, Node > &sourceBlockedMap, const Xpetra::Import< LocalOrdinal, GlobalOrdinal, Node > &Importer)
static RCP< Vector > GetMatrixOverlappedDiagonal(const Matrix &A)
Extract Overlapped Matrix Diagonal.
Teuchos::ScalarTraits< Scalar >::magnitudeType Magnitude
virtual size_t getNumEntriesInLocalRow(LocalOrdinal localRow) const =0
static RCP< Vector > GetMatrixDiagonalInverse(const Matrix &A, Magnitude tol=Teuchos::ScalarTraits< Scalar >::eps()*100, Scalar valReplacement=Teuchos::ScalarTraits< Scalar >::zero(), const bool doLumped=false)
Extract Matrix Diagonal.
static void seedrandom(unsigned int s)
static Teuchos::ArrayRCP< const bool > DetectDirichletRowsExt(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, bool &bHasZeroDiagonal, const Magnitude &tol=Teuchos::ScalarTraits< Scalar >::zero())
Detect Dirichlet rows (extended version)
static RCP< Vector > Build(const Teuchos::RCP< const Map > &map, bool zeroOut=true)
const RCP< const Xpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > getMap(size_t i, bool bThyraMode=false) const
virtual UnderlyingLib lib() const
static magnitudeType magnitude(T a)
RCP< const Tpetra::CrsGraph< LocalOrdinal, GlobalOrdinal, Node > > toTpetra(const RCP< const CrsGraph< LocalOrdinal, GlobalOrdinal, Node > > &graph)
void push_back(const value_type &x)
virtual RCP< const CrsGraph > getCrsGraph() const =0
static Teuchos::Array< Magnitude > ResidualNorm(const Xpetra::Operator< Scalar, LocalOrdinal, GlobalOrdinal, Node > &Op, const MultiVector &X, const MultiVector &RHS)
static void EnforceInitialCondition(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &RHS, Xpetra::MultiVector< Scalar, LocalOrdinal, GlobalOrdinal, Node > &InitialGuess, const Magnitude &tol=Teuchos::ScalarTraits< Magnitude >::zero(), const bool count_twos_as_dirichlet=false)
Detect Dirichlet rows and copy values from RHS multivector to InitialGuess for Dirichlet rows...
impl_scalar_type_dualview::t_dev::const_type getValuesDevice(const LO &lclRow) const
virtual Teuchos::RCP< const Map > getRangeMap() const =0
static RCP< Teuchos::FancyOStream > MakeFancy(std::ostream &os)
static RCP< Matrix > Build(const RCP< const Map > &rowMap, size_t maxNumEntriesPerRow, Xpetra::ProfileType pftype=Xpetra::DynamicProfile)
void residual(const Operator< SC, LO, GO, NO > &Aop, const MultiVector< SC, LO, GO, NO > &X_in, const MultiVector< SC, LO, GO, NO > &B_in, MultiVector< SC, LO, GO, NO > &R_in)
Exception throws to report errors in the internal logical of the program.
static Scalar Frobenius(const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Xpetra::Matrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &B)
Frobenius inner product of two matrices.
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getSourceMap() const =0
#define TEUCHOS_ASSERT(assertion_test)
#define TEUCHOS_ASSERT_EQUALITY(val1, val2)
static Teuchos::RCP< Vector > GetInverse(Teuchos::RCP< const Vector > v, Magnitude tol=Teuchos::ScalarTraits< Scalar >::eps()*100, Scalar valReplacement=Teuchos::ScalarTraits< Scalar >::zero())
Return vector containing inverse of input vector.
static Kokkos::View< bool *, typename Kokkos::HostSpace > DetectDirichletRows_kokkos_host(const Matrix &A, const Magnitude &tol=Teuchos::ScalarTraits< typename Teuchos::ScalarTraits< SC >::magnitudeType >::zero(), const bool count_twos_as_dirichlet=false)
virtual size_t getNumVectors() const =0
static Teuchos::ScalarTraits< Scalar >::magnitudeType Distance2(const Teuchos::Array< Teuchos::ArrayRCP< const Scalar >> &v, LocalOrdinal i0, LocalOrdinal i1)
Squared distance between two rows in a multivector.
static Teuchos::RCP< Vector > GetLumpedMatrixDiagonal(Matrix const &A, const bool doReciprocal=false, Magnitude tol=Teuchos::ScalarTraits< Scalar >::magnitude(Teuchos::ScalarTraits< Scalar >::zero()), Scalar valReplacement=Teuchos::ScalarTraits< Scalar >::zero(), const bool replaceSingleEntryRowWithZero=false, const bool useAverageAbsDiagVal=false)
Extract Matrix Diagonal of lumped matrix.
virtual UnderlyingLib lib() const =0
static Kokkos::View< bool *, typename NO::device_type::memory_space > DetectDirichletRows_kokkos(const Matrix &A, const Magnitude &tol=Teuchos::ScalarTraits< typename Teuchos::ScalarTraits< SC >::magnitudeType >::zero(), const bool count_twos_as_dirichlet=false)
Detect Dirichlet rows.
static RCP< Matrix > Crs2Op(RCP< CrsMatrix > Op)
virtual Teuchos::ArrayRCP< const Scalar > getData(size_t j) const =0
virtual Teuchos::RCP< const Map > getDomainMap() const =0
static RCP< Import< LocalOrdinal, GlobalOrdinal, Node > > Build(const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &source, const RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &target, const Teuchos::RCP< Teuchos::ParameterList > &plist=Teuchos::null)