10#ifndef TPETRA_COMPUTEROWANDCOLUMNONENORMS_DEF_HPP
11#define TPETRA_COMPUTEROWANDCOLUMNONENORMS_DEF_HPP
20#include "KokkosKernels_ArithTraits.hpp"
21#include "Kokkos_Macros.hpp"
24#include "Tpetra_CrsMatrix.hpp"
25#include "Tpetra_Export.hpp"
26#include "Tpetra_Map.hpp"
27#include "Tpetra_MultiVector.hpp"
28#include "Tpetra_RowMatrix.hpp"
29#include "Kokkos_Core.hpp"
30#include "Teuchos_CommHelpers.hpp"
36template <
class SC,
class LO,
class GO,
class NT>
39 const auto& rowMap = *(A.getRowMap());
40 const LO lclNumRows =
static_cast<LO
>(rowMap.getLocalNumElements());
42 std::size_t maxNumEnt{0};
43 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
44 const std::size_t numEnt = A.getNumEntriesInLocalRow(lclRow);
45 maxNumEnt = numEnt > maxNumEnt ? numEnt : maxNumEnt;
50template <
class SC,
class LO,
class GO,
class NT>
51void forEachLocalRowMatrixRow(
54 const std::size_t maxNumEnt,
57 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_local_inds_host_view_type& ,
58 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_values_host_view_type& ,
61 using lids_type =
typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_local_inds_host_view_type;
62 using vals_type =
typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_values_host_view_type;
63 lids_type indBuf(
"indices", maxNumEnt);
64 vals_type valBuf(
"values", maxNumEnt);
66 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
67 std::size_t numEnt = A.getNumEntriesInLocalRow(lclRow);
68 lids_type ind = Kokkos::subview(indBuf, std::make_pair((
size_t)0, numEnt));
69 vals_type val = Kokkos::subview(valBuf, std::make_pair((
size_t)0, numEnt));
70 A.getLocalRowCopy(lclRow, ind, val, numEnt);
71 doForEachRow(lclRow, ind, val, numEnt);
75template <
class SC,
class LO,
class GO,
class NT>
76void forEachLocalRowMatrixRow(
80 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_local_inds_host_view_type& ,
81 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_values_host_view_type& ,
84 const auto& rowMap = *(A.getRowMap());
85 const LO lclNumRows =
static_cast<LO
>(rowMap.getLocalNumElements());
86 const std::size_t maxNumEnt = lclMaxNumEntriesRowMatrix(A);
88 forEachLocalRowMatrixRow<SC, LO, GO, NT>(A, lclNumRows, maxNumEnt, doForEachRow);
94template <
class SC,
class LO,
class GO,
class NT>
96 typename NT::device_type>&
result,
98 using KAT = KokkosKernels::ArithTraits<SC>;
99 using mag_type =
typename KAT::mag_type;
100 using KAV = KokkosKernels::ArithTraits<typename KAT::val_type>;
110 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_local_inds_host_view_type&
ind,
111 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_values_host_view_type&
val,
114 for (std::size_t
k = 0;
k <
numEnt; ++
k) {
128template <
class SC,
class LO,
class GO,
class NT>
131 using KAT = KokkosKernels::ArithTraits<SC>;
132 using val_type =
typename KAT::val_type;
133 using KAV = KokkosKernels::ArithTraits<val_type>;
134 using mag_type =
typename KAT::mag_type;
135 using KAM = KokkosKernels::ArithTraits<mag_type>;
136 using device_type =
typename NT::device_type;
139 const auto& rowMap = *(
A.getRowMap());
140 const auto& colMap = *(
A.getColMap());
141 const LO
lclNumRows =
static_cast<LO
>(rowMap.getLocalNumElements());
143 constexpr bool assumeSymmetric =
false;
152 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_local_inds_host_view_type&
ind,
153 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_values_host_view_type&
val,
161 for (std::size_t
k = 0;
k <
numEnt; ++
k) {
199template <
class SC,
class LO,
class GO,
class NT>
202 const bool assumeSymmetric) {
203 using KAT = KokkosKernels::ArithTraits<SC>;
204 using val_type =
typename KAT::val_type;
205 using KAV = KokkosKernels::ArithTraits<val_type>;
206 using mag_type =
typename KAT::mag_type;
207 using KAM = KokkosKernels::ArithTraits<mag_type>;
208 using device_type =
typename NT::device_type;
210 const auto& rowMap = *(
A.getRowMap());
211 const auto& colMap = *(
A.getColMap());
212 const LO
lclNumRows =
static_cast<LO
>(rowMap.getLocalNumElements());
213 const LO
lclNumCols =
static_cast<LO
>(colMap.getLocalNumElements());
223 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_local_inds_host_view_type&
ind,
224 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_values_host_view_type&
val,
232 for (std::size_t
k = 0;
k <
numEnt; ++
k) {
246 if (!assumeSymmetric) {
265 if (!assumeSymmetric &&
266 lclDiagColInd != Tpetra::Details::OrdinalTraits<LO>::invalid()) {
275template <
class SC,
class LO,
class GO,
class NT>
276class ComputeLocalRowScaledColumnNorms {
279 using val_type =
typename KokkosKernels::ArithTraits<SC>::val_type;
280 using mag_type =
typename KokkosKernels::ArithTraits<val_type>::mag_type;
282 using policy_type = Kokkos::TeamPolicy<typename device_type::execution_space, LO>;
284 ComputeLocalRowScaledColumnNorms(
const Kokkos::View<mag_type*, device_type>& rowScaledColNorms,
285 const Kokkos::View<const mag_type*, device_type>& rowNorms,
286 const crs_matrix_type&
A)
287 : rowScaledColNorms_(rowScaledColNorms)
288 , rowNorms_(rowNorms)
289 , A_lcl_(
A.getLocalMatrixDevice()) {}
291 KOKKOS_INLINE_FUNCTION
void operator()(
const typename policy_type::member_type& team)
const {
292 using KAT = KokkosKernels::ArithTraits<val_type>;
294 const LO lclRow = team.league_rank();
295 const auto curRow = A_lcl_.rowConst(lclRow);
296 const mag_type rowNorm = rowNorms_[lclRow];
297 const LO numEnt = curRow.length;
298 Kokkos::parallel_for(Kokkos::TeamThreadRange(team, numEnt), [&](
const LO k) {
299 const mag_type matrixAbsVal = KAT::abs(curRow.value(k));
300 const LO lclCol = curRow.colidx(k);
302 Kokkos::atomic_add(&rowScaledColNorms_[lclCol], matrixAbsVal / rowNorm);
307 run(
const Kokkos::View<mag_type*, device_type>& rowScaledColNorms,
308 const Kokkos::View<const mag_type*, device_type>& rowNorms,
309 const crs_matrix_type& A) {
310 using functor_type = ComputeLocalRowScaledColumnNorms<SC, LO, GO, NT>;
312 functor_type functor(rowScaledColNorms, rowNorms, A);
313 const LO lclNumRows =
314 static_cast<LO
>(A.getRowMap()->getLocalNumElements());
315 Kokkos::parallel_for(
"computeLocalRowScaledColumnNorms",
316 policy_type(lclNumRows, Kokkos::AUTO), functor);
320 Kokkos::View<mag_type*, device_type> rowScaledColNorms_;
321 Kokkos::View<const mag_type*, device_type> rowNorms_;
324 local_matrix_device_type A_lcl_;
327template <
class SC,
class LO,
class GO,
class NT>
328void computeLocalRowScaledColumnNorms_CrsMatrix(EquilibrationInfo<
typename KokkosKernels::ArithTraits<SC>::val_type,
329 typename NT::device_type>& result,
331 using impl_type = ComputeLocalRowScaledColumnNorms<SC, LO, GO, NT>;
332 impl_type::run(result.rowScaledColNorms, result.rowNorms, A);
335template <
class SC,
class LO,
class GO,
class NT>
336void computeLocalRowScaledColumnNorms(EquilibrationInfo<
typename KokkosKernels::ArithTraits<SC>::val_type,
337 typename NT::device_type>& result,
340 using val_type =
typename KokkosKernels::ArithTraits<SC>::val_type;
341 using mag_type =
typename KokkosKernels::ArithTraits<val_type>::mag_type;
342 using device_type =
typename NT::device_type;
344 auto colMapPtr = A.getColMap();
345 TEUCHOS_TEST_FOR_EXCEPTION(colMapPtr.get() ==
nullptr, std::invalid_argument,
346 "computeLocalRowScaledColumnNorms: "
347 "Input matrix A must have a nonnull column Map.");
348 const LO lclNumCols =
static_cast<LO
>(colMapPtr->getLocalNumElements());
349 if (
static_cast<std::size_t
>(result.rowScaledColNorms.extent(0)) !=
350 static_cast<std::size_t
>(lclNumCols)) {
351 result.rowScaledColNorms =
352 Kokkos::View<mag_type*, device_type>(
"rowScaledColNorms", lclNumCols);
355 const crs_matrix_type* A_crs =
dynamic_cast<const crs_matrix_type*
>(&A);
356 if (A_crs ==
nullptr) {
359 computeLocalRowScaledColumnNorms_CrsMatrix(result, *A_crs);
365template <
class SC,
class LO,
class GO,
class NT>
366class ComputeLocalRowOneNorms {
368 using val_type =
typename KokkosKernels::ArithTraits<SC>::val_type;
369 using equib_info_type = EquilibrationInfo<val_type, typename NT::device_type>;
370 using local_matrix_device_type =
371 typename ::Tpetra::CrsMatrix<SC, LO, GO, NT>::local_matrix_device_type;
372 using local_map_type = typename ::Tpetra::Map<LO, GO, NT>::local_map_type;
373 using policy_type = Kokkos::TeamPolicy<typename local_matrix_device_type::execution_space, LO>;
375 ComputeLocalRowOneNorms(
const equib_info_type& equib,
376 const local_matrix_device_type& A_lcl,
377 const local_map_type& rowMap,
378 const local_map_type& colMap)
391 using value_type = int;
393 KOKKOS_INLINE_FUNCTION
void init(value_type& dst)
const {
397 KOKKOS_INLINE_FUNCTION
void
398 join(value_type& dst,
399 const value_type& src)
const {
403 KOKKOS_INLINE_FUNCTION
void
404 operator()(
const typename policy_type::member_type& team, value_type& dst)
const {
405 using KAT = KokkosKernels::ArithTraits<val_type>;
406 using mag_type =
typename KAT::mag_type;
407 using KAM = KokkosKernels::ArithTraits<mag_type>;
409 const LO lclRow = team.league_rank();
410 const GO gblRow = rowMap_.getGlobalElement(lclRow);
412 const GO lclDiagColInd = colMap_.getLocalElement(gblRow);
414 const auto curRow = A_lcl_.rowConst(lclRow);
415 const LO numEnt = curRow.length;
417 const auto val_zero = KAT::zero();
418 const auto mag_zero = KAM::zero();
420 mag_type rowNorm = mag_zero;
421 val_type diagVal = val_zero;
422 value_type dstThread{0};
424 Kokkos::parallel_reduce(
425 Kokkos::TeamThreadRange(team, numEnt), [&](
const LO k, mag_type& normContrib, val_type& diagContrib, value_type& dstContrib) {
426 const val_type matrixVal = curRow.value(k);
427 if (KAT::isInf(matrixVal)) {
430 if (KAT::isNan(matrixVal)) {
433 const mag_type matrixAbsVal = KAT::abs(matrixVal);
434 normContrib += matrixAbsVal;
435 const LO lclCol = curRow.colidx(k);
436 if (lclCol == lclDiagColInd) {
437 diagContrib = curRow.value(k);
440 Kokkos::Sum<mag_type>(rowNorm), Kokkos::Sum<val_type>(diagVal), Kokkos::BOr<value_type>(dstThread));
444 Kokkos::single(Kokkos::PerTeam(team), [&]() {
446 if (diagVal == KAT::zero()) {
449 if (rowNorm == KAM::zero()) {
452 equib_.rowDiagonalEntries[lclRow] = diagVal;
453 equib_.rowNorms[lclRow] = rowNorm;
458 equib_info_type equib_;
459 local_matrix_device_type A_lcl_;
460 local_map_type rowMap_;
461 local_map_type colMap_;
466template <
class SC,
class LO,
class GO,
class NT>
467class ComputeLocalRowAndColumnOneNorms {
469 using val_type =
typename KokkosKernels::ArithTraits<SC>::val_type;
470 using equib_info_type = EquilibrationInfo<val_type, typename NT::device_type>;
471 using local_matrix_device_type = typename ::Tpetra::CrsMatrix<SC, LO, GO, NT>::local_matrix_device_type;
472 using local_map_type = typename ::Tpetra::Map<LO, GO, NT>::local_map_type;
473 using policy_type = Kokkos::TeamPolicy<typename local_matrix_device_type::execution_space, LO>;
476 ComputeLocalRowAndColumnOneNorms(
const equib_info_type& equib,
477 const local_matrix_device_type& A_lcl,
478 const local_map_type& rowMap,
479 const local_map_type& colMap)
492 using value_type = int;
494 KOKKOS_INLINE_FUNCTION
void init(value_type& dst)
const {
498 KOKKOS_INLINE_FUNCTION
void
499 join(value_type& dst,
500 const value_type& src)
const {
504 KOKKOS_INLINE_FUNCTION
void
505 operator()(
const typename policy_type::member_type& team, value_type& dst)
const {
506 using KAT = KokkosKernels::ArithTraits<val_type>;
507 using mag_type =
typename KAT::mag_type;
508 using KAM = KokkosKernels::ArithTraits<mag_type>;
510 const LO lclRow = team.league_rank();
511 const GO gblRow = rowMap_.getGlobalElement(lclRow);
513 const GO lclDiagColInd = colMap_.getLocalElement(gblRow);
515 const auto curRow = A_lcl_.rowConst(lclRow);
516 const LO numEnt = curRow.length;
518 const auto val_zero = KAT::zero();
519 const auto mag_zero = KAM::zero();
521 mag_type rowNorm = mag_zero;
522 val_type diagVal = val_zero;
523 value_type dstThread{0};
525 Kokkos::parallel_reduce(
526 Kokkos::TeamThreadRange(team, numEnt), [&](
const LO k, mag_type& normContrib, val_type& diagContrib, value_type& dstContrib) {
527 const val_type matrixVal = curRow.value(k);
528 if (KAT::isInf(matrixVal)) {
531 if (KAT::isNan(matrixVal)) {
534 const mag_type matrixAbsVal = KAT::abs(matrixVal);
535 normContrib += matrixAbsVal;
536 const LO lclCol = curRow.colidx(k);
537 if (lclCol == lclDiagColInd) {
538 diagContrib = curRow.value(k);
540 if (!equib_.assumeSymmetric) {
541 Kokkos::atomic_add(&(equib_.colNorms[lclCol]), matrixAbsVal);
544 Kokkos::Sum<mag_type>(rowNorm), Kokkos::Sum<val_type>(diagVal), Kokkos::BOr<value_type>(dstThread));
548 Kokkos::single(Kokkos::PerTeam(team), [&]() {
550 if (diagVal == KAT::zero()) {
553 if (rowNorm == KAM::zero()) {
560 equib_.rowDiagonalEntries[lclRow] = diagVal;
561 equib_.rowNorms[lclRow] = rowNorm;
562 if (!equib_.assumeSymmetric &&
563 lclDiagColInd != Tpetra::Details::OrdinalTraits<LO>::invalid()) {
566 equib_.colDiagonalEntries[lclDiagColInd] += diagVal;
572 equib_info_type equib_;
573 local_matrix_device_type A_lcl_;
574 local_map_type rowMap_;
575 local_map_type colMap_;
580template <
class SC,
class LO,
class GO,
class NT>
581EquilibrationInfo<typename KokkosKernels::ArithTraits<SC>::val_type,
typename NT::device_type>
583 using execution_space =
typename NT::device_type::execution_space;
584 using policy_type = Kokkos::TeamPolicy<execution_space, LO>;
586 using val_type =
typename KokkosKernels::ArithTraits<SC>::val_type;
587 using device_type =
typename NT::device_type;
590 const LO
lclNumRows =
static_cast<LO
>(
A.getRowMap()->getLocalNumElements());
592 constexpr bool assumeSymmetric =
false;
596 A.getRowMap()->getLocalMap(),
597 A.getColMap()->getLocalMap());
599 Kokkos::parallel_reduce(
"computeLocalRowOneNorms",
611template <
class SC,
class LO,
class GO,
class NT>
614 const bool assumeSymmetric) {
615 using execution_space =
typename NT::device_type::execution_space;
616 using policy_type = Kokkos::TeamPolicy<execution_space, LO>;
618 using val_type =
typename KokkosKernels::ArithTraits<SC>::val_type;
619 using device_type =
typename NT::device_type;
622 const LO
lclNumRows =
static_cast<LO
>(
A.getRowMap()->getLocalNumElements());
623 const LO
lclNumCols =
static_cast<LO
>(
A.getColMap()->getLocalNumElements());
627 A.getRowMap()->getLocalMap(),
628 A.getColMap()->getLocalMap());
630 Kokkos::parallel_reduce(
"computeLocalRowAndColumnOneNorms",
644template <
class SC,
class LO,
class GO,
class NT>
646 typename NT::device_type>
649 const crs_matrix_type*
A_crs =
dynamic_cast<const crs_matrix_type*
>(&
A);
651 if (
A_crs ==
nullptr) {
679template <
class SC,
class LO,
class GO,
class NT>
682 const bool assumeSymmetric) {
684 const crs_matrix_type*
A_crs =
dynamic_cast<const crs_matrix_type*
>(&
A);
686 if (
A_crs ==
nullptr) {
693template <
class SC,
class LO,
class GO,
class NT>
694auto getLocalView_1d_readOnly(
697 ->
decltype(Kokkos::subview(
X.getLocalViewDevice(Access::ReadOnly),
699 if (
X.isConstantStride()) {
700 return Kokkos::subview(
X.getLocalViewDevice(Access::ReadOnly),
703 auto X_whichColumn = X.getVector(whichColumn);
704 return Kokkos::subview(X_whichColumn->getLocalViewDevice(Access::ReadOnly),
709template <
class SC,
class LO,
class GO,
class NT>
710auto getLocalView_1d_writeOnly(
712 const LO whichColumn)
713 ->
decltype(Kokkos::subview(X.getLocalViewDevice(Access::ReadWrite),
714 Kokkos::ALL(), whichColumn)) {
715 if (X.isConstantStride()) {
716 return Kokkos::subview(X.getLocalViewDevice(Access::ReadWrite),
717 Kokkos::ALL(), whichColumn);
719 auto X_whichColumn = X.getVectorNonConst(whichColumn);
720 return Kokkos::subview(X_whichColumn->getLocalViewDevice(Access::ReadWrite),
725template <
class SC,
class LO,
class GO,
class NT,
class ViewValueType>
726void copy1DViewIntoMultiVectorColumn(
728 const LO whichColumn,
729 const Kokkos::View<ViewValueType*, typename NT::device_type>& view) {
730 auto X_lcl = getLocalView_1d_writeOnly(X, whichColumn);
734template <
class SC,
class LO,
class GO,
class NT,
class ViewValueType>
735void copy1DViewIntoMultiVectorColumn_mag(
737 const LO whichColumn,
738 const Kokkos::View<ViewValueType*, typename NT::device_type>& view) {
739 using KAT = KokkosKernels::ArithTraits<ViewValueType>;
740 using execution_space =
typename NT::execution_space;
741 using range_type = Kokkos::RangePolicy<execution_space, LO>;
742 auto X_lcl = getLocalView_1d_writeOnly(X, whichColumn);
743 Kokkos::parallel_for(
745 range_type(0, X_lcl.extent(0)),
746 KOKKOS_LAMBDA(
const LO i) {
747 X_lcl(i) = KAT::magnitude(view(i));
751template <
class SC,
class LO,
class GO,
class NT,
class ViewValueType>
752void copyMultiVectorColumnInto1DView(
753 const Kokkos::View<ViewValueType*, typename NT::device_type>& view,
755 const LO whichColumn) {
756 auto X_lcl = getLocalView_1d_readOnly(X, whichColumn);
760template <
class SC,
class LO,
class GO,
class NT,
class ViewValueType>
761void copyMultiVectorColumnInto1DView_mag(
762 const Kokkos::View<ViewValueType*, typename NT::device_type>& view,
764 const LO whichColumn) {
765 using implScalar =
typename KokkosKernels::ArithTraits<SC>::val_type;
766 using KAT = KokkosKernels::ArithTraits<implScalar>;
767 using range_type = Kokkos::RangePolicy<typename NT::execution_space, LO>;
768 auto X_lcl = getLocalView_1d_readOnly(X, whichColumn);
769 Kokkos::parallel_for(
771 range_type(0, X_lcl.extent(0)),
772 KOKKOS_LAMBDA(LO i) {
773 view(i) = KAT::magnitude(X_lcl(i));
777template <
class OneDViewType,
class IndexType>
780 static_assert(OneDViewType::rank == 1,
781 "OneDViewType must be a rank-1 Kokkos::View.");
782 static_assert(std::is_integral<IndexType>::value,
783 "IndexType must be a built-in integer type.");
784 FindZero(
const OneDViewType& x)
788 KOKKOS_INLINE_FUNCTION
void
789 operator()(
const IndexType i,
int& result)
const {
790 using val_type =
typename OneDViewType::non_const_value_type;
791 result = (x_(i) == KokkosKernels::ArithTraits<val_type>::zero()) ? 1 : result;
798template <
class OneDViewType>
799bool findZero(
const OneDViewType& x) {
800 using view_type =
typename OneDViewType::const_type;
801 using execution_space =
typename view_type::execution_space;
802 using size_type =
typename view_type::size_type;
803 using functor_type = FindZero<view_type, size_type>;
805 Kokkos::RangePolicy<execution_space, size_type> range(0, x.extent(0));
806 range.set_chunk_size(500);
809 Kokkos::parallel_reduce(
"findZero", range, functor_type(x), foundZero);
810 return foundZero == 1;
813template <
class SC,
class LO,
class GO,
class NT>
814void globalizeRowOneNorms(EquilibrationInfo<
typename KokkosKernels::ArithTraits<SC>::val_type,
815 typename NT::device_type>& equib,
819 auto G = A.getGraph();
820 TEUCHOS_TEST_FOR_EXCEPTION(G.get() ==
nullptr, std::invalid_argument,
821 "globalizeRowOneNorms: Input RowMatrix A must have a nonnull graph "
822 "(that is, getGraph() must return nonnull).");
823 TEUCHOS_TEST_FOR_EXCEPTION(!G->isFillComplete(), std::invalid_argument,
824 "globalizeRowOneNorms: Input CrsGraph G must be fillComplete.");
826 auto exp = G->getExporter();
827 if (!exp.is_null()) {
837 mv_type rowMapMV(G->getRowMap(), 2,
false);
839 copy1DViewIntoMultiVectorColumn(rowMapMV, 0, equib.rowNorms);
840 copy1DViewIntoMultiVectorColumn(rowMapMV, 1, equib.rowDiagonalEntries);
842 mv_type rangeMapMV(G->getRangeMap(), 2,
true);
846 copyMultiVectorColumnInto1DView_mag(equib.rowNorms, rowMapMV, 0);
847 copyMultiVectorColumnInto1DView(equib.rowDiagonalEntries, rowMapMV, 1);
852 equib.foundZeroDiag = findZero(equib.rowDiagonalEntries);
853 equib.foundZeroRowNorm = findZero(equib.rowNorms);
856 constexpr int allReduceCount = 4;
857 int lclNaughtyMatrix[allReduceCount];
858 lclNaughtyMatrix[0] = equib.foundInf ? 1 : 0;
859 lclNaughtyMatrix[1] = equib.foundNan ? 1 : 0;
860 lclNaughtyMatrix[2] = equib.foundZeroDiag ? 1 : 0;
861 lclNaughtyMatrix[3] = equib.foundZeroRowNorm ? 1 : 0;
863 using Teuchos::outArg;
864 using Teuchos::REDUCE_MAX;
865 using Teuchos::reduceAll;
866 auto comm = G->getComm();
867 int gblNaughtyMatrix[allReduceCount];
868 reduceAll<int, int>(*comm, REDUCE_MAX, allReduceCount,
869 lclNaughtyMatrix, gblNaughtyMatrix);
871 equib.foundInf = gblNaughtyMatrix[0] == 1;
872 equib.foundNan = gblNaughtyMatrix[1] == 1;
873 equib.foundZeroDiag = gblNaughtyMatrix[2] == 1;
874 equib.foundZeroRowNorm = gblNaughtyMatrix[3] == 1;
877template <
class SC,
class LO,
class GO,
class NT>
878void globalizeColumnOneNorms(EquilibrationInfo<
typename KokkosKernels::ArithTraits<SC>::val_type,
879 typename NT::device_type>& equib,
881 const bool assumeSymmetric)
883 using val_type =
typename KokkosKernels::ArithTraits<SC>::val_type;
884 using mag_type =
typename KokkosKernels::ArithTraits<val_type>::mag_type;
886 using device_type =
typename NT::device_type;
888 auto G = A.getGraph();
889 TEUCHOS_TEST_FOR_EXCEPTION(G.get() ==
nullptr, std::invalid_argument,
890 "globalizeColumnOneNorms: Input RowMatrix A must have a nonnull graph "
891 "(that is, getGraph() must return nonnull).");
892 TEUCHOS_TEST_FOR_EXCEPTION(!G->isFillComplete(), std::invalid_argument,
893 "globalizeColumnOneNorms: Input CrsGraph G must be fillComplete.");
895 auto imp = G->getImporter();
896 if (assumeSymmetric) {
897 const LO numCols = 2;
901 mv_type rowNorms_domMap(G->getDomainMap(), numCols,
false);
902 const bool rowMapSameAsDomainMap = G->getRowMap()->isSameAs(*(G->getDomainMap()));
903 if (rowMapSameAsDomainMap) {
904 copy1DViewIntoMultiVectorColumn(rowNorms_domMap, 0, equib.rowNorms);
905 copy1DViewIntoMultiVectorColumn_mag(rowNorms_domMap, 1, equib.rowDiagonalEntries);
910 mv_type rowNorms_rowMap(G->getRowMap(), numCols,
true);
911 copy1DViewIntoMultiVectorColumn(rowNorms_rowMap, 0, equib.rowNorms);
912 copy1DViewIntoMultiVectorColumn_mag(rowNorms_rowMap, 1, equib.rowDiagonalEntries);
918 std::unique_ptr<mv_type> rowNorms_colMap;
922 std::unique_ptr<mv_type>(
new mv_type(rowNorms_domMap, *(G->getColMap())));
925 std::unique_ptr<mv_type>(
new mv_type(G->getColMap(), numCols,
true));
930 const LO lclNumCols =
931 static_cast<LO
>(G->getColMap()->getLocalNumElements());
932 if (
static_cast<LO
>(equib.colNorms.extent(0)) != lclNumCols) {
934 Kokkos::View<mag_type*, device_type>(
"colNorms", lclNumCols);
936 if (
static_cast<LO
>(equib.colDiagonalEntries.extent(0)) != lclNumCols) {
937 equib.colDiagonalEntries =
938 Kokkos::View<val_type*, device_type>(
"colDiagonalEntries", lclNumCols);
943 copyMultiVectorColumnInto1DView(equib.colNorms, *rowNorms_colMap, 0);
944 copyMultiVectorColumnInto1DView(equib.colDiagonalEntries, *rowNorms_colMap, 1);
946 if (!imp.is_null()) {
947 const LO numCols = 3;
956 mv_type colMapMV(G->getColMap(), numCols,
false);
958 copy1DViewIntoMultiVectorColumn(colMapMV, 0, equib.colNorms);
959 copy1DViewIntoMultiVectorColumn_mag(colMapMV, 1, equib.colDiagonalEntries);
960 copy1DViewIntoMultiVectorColumn(colMapMV, 2, equib.rowScaledColNorms);
962 mv_type domainMapMV(G->getDomainMap(), numCols,
true);
966 copyMultiVectorColumnInto1DView(equib.colNorms, colMapMV, 0);
967 copyMultiVectorColumnInto1DView(equib.colDiagonalEntries, colMapMV, 1);
968 copyMultiVectorColumnInto1DView(equib.rowScaledColNorms, colMapMV, 2);
975template <
class SC,
class LO,
class GO,
class NT>
976Details::EquilibrationInfo<typename KokkosKernels::ArithTraits<SC>::val_type,
977 typename NT::device_type>
980 "computeRowOneNorms: Input matrix A must be fillComplete.");
983 Details::globalizeRowOneNorms(
result,
A);
987template <
class SC,
class LO,
class GO,
class NT>
988Details::EquilibrationInfo<typename KokkosKernels::ArithTraits<SC>::val_type,
989 typename NT::device_type>
991 const bool assumeSymmetric) {
993 "computeRowAndColumnOneNorms: Input matrix A must be fillComplete.");
996 Details::globalizeRowOneNorms(
result,
A);
997 if (!assumeSymmetric) {
1001 Details::computeLocalRowScaledColumnNorms(
result,
A);
1003 Details::globalizeColumnOneNorms(
result,
A, assumeSymmetric);
1015#define TPETRA_COMPUTEROWANDCOLUMNONENORMS_INSTANT(SC, LO, GO, NT) \
1016 template Details::EquilibrationInfo<KokkosKernels::ArithTraits<SC>::val_type, NT::device_type> \
1017 computeRowOneNorms(const Tpetra::RowMatrix<SC, LO, GO, NT>& A); \
1019 template Details::EquilibrationInfo<KokkosKernels::ArithTraits<SC>::val_type, NT::device_type> \
1020 computeRowAndColumnOneNorms(const Tpetra::RowMatrix<SC, LO, GO, NT>& A, \
1021 const bool assumeSymmetric);
Declaration of Tpetra::Details::EquilibrationInfo.
Declare and define Tpetra::Details::copyConvert, an implementation detail of Tpetra (in particular,...
typename Node::device_type device_type
The Kokkos device type.
KokkosSparse::CrsMatrix< impl_scalar_type, local_ordinal_type, device_type, void, typename local_graph_device_type::size_type > local_matrix_device_type
The specialization of Kokkos::CrsMatrix that represents the part of the sparse matrix on each MPI pro...
Struct that holds views of the contents of a CrsMatrix.
Implementation details of Tpetra.
EquilibrationInfo< typename KokkosKernels::ArithTraits< SC >::val_type, typename NT::device_type > computeLocalRowOneNorms_CrsMatrix(const Tpetra::CrsMatrix< SC, LO, GO, NT > &A)
Implementation of computeLocalRowOneNorms for a Tpetra::CrsMatrix.
void computeLocalRowScaledColumnNorms_RowMatrix(EquilibrationInfo< typename KokkosKernels::ArithTraits< SC >::val_type, typename NT::device_type > &result, const Tpetra::RowMatrix< SC, LO, GO, NT > &A)
For a given Tpetra::RowMatrix that is not a Tpetra::CrsMatrix, assume that result....
EquilibrationInfo< typename KokkosKernels::ArithTraits< SC >::val_type, typename NT::device_type > computeLocalRowOneNorms_RowMatrix(const Tpetra::RowMatrix< SC, LO, GO, NT > &A)
Implementation of computeLocalRowOneNorms for a Tpetra::RowMatrix that is NOT a Tpetra::CrsMatrix.
EquilibrationInfo< typename KokkosKernels::ArithTraits< SC >::val_type, typename NT::device_type > computeLocalRowOneNorms(const Tpetra::RowMatrix< SC, LO, GO, NT > &A)
Compute LOCAL row one-norms ("row sums" etc.) of the input sparse matrix A.
EquilibrationInfo< typename KokkosKernels::ArithTraits< SC >::val_type, typename NT::device_type > computeLocalRowAndColumnOneNorms_CrsMatrix(const Tpetra::CrsMatrix< SC, LO, GO, NT > &A, const bool assumeSymmetric)
Implementation of computeLocalRowAndColumnOneNorms for a Tpetra::CrsMatrix.
void copyConvert(const OutputViewType &dst, const InputViewType &src)
Copy values from the 1-D Kokkos::View src, to the 1-D Kokkos::View dst, of the same length....
EquilibrationInfo< typename KokkosKernels::ArithTraits< SC >::val_type, typename NT::device_type > computeLocalRowAndColumnOneNorms(const Tpetra::RowMatrix< SC, LO, GO, NT > &A, const bool assumeSymmetric)
Compute LOCAL row and column one-norms ("row sums" etc.) of the input sparse matrix A....
EquilibrationInfo< typename KokkosKernels::ArithTraits< SC >::val_type, typename NT::device_type > computeLocalRowAndColumnOneNorms_RowMatrix(const Tpetra::RowMatrix< SC, LO, GO, NT > &A, const bool assumeSymmetric)
Implementation of computeLocalRowAndColumnOneNorms for a Tpetra::RowMatrix that is NOT a Tpetra::CrsM...
Namespace Tpetra contains the class and methods constituting the Tpetra library.
Details::EquilibrationInfo< typename KokkosKernels::ArithTraits< SC >::val_type, typename NT::device_type > computeRowOneNorms(const Tpetra::RowMatrix< SC, LO, GO, NT > &A)
Compute global row one-norms ("row sums") of the input sparse matrix A, in a way suitable for one-sid...
Details::EquilibrationInfo< typename KokkosKernels::ArithTraits< SC >::val_type, typename NT::device_type > computeRowAndColumnOneNorms(const Tpetra::RowMatrix< SC, LO, GO, NT > &A, const bool assumeSymmetric)
Compute global row and column one-norms ("row sums" and "column sums") of the input sparse matrix A,...
@ REPLACE
Replace existing values with new values.
Struct storing results of Tpetra::computeRowAndColumnOneNorms.