42 #ifndef TPETRA_COMPUTEROWANDCOLUMNONENORMS_DEF_HPP
43 #define TPETRA_COMPUTEROWANDCOLUMNONENORMS_DEF_HPP
53 #include "Tpetra_CrsMatrix.hpp"
54 #include "Tpetra_Export.hpp"
55 #include "Tpetra_Map.hpp"
56 #include "Tpetra_MultiVector.hpp"
57 #include "Tpetra_RowMatrix.hpp"
58 #include "Kokkos_Core.hpp"
59 #include "Teuchos_CommHelpers.hpp"
65 template<
class SC,
class LO,
class GO,
class NT>
70 const LO lclNumRows =
static_cast<LO
> (rowMap.getLocalNumElements ());
72 std::size_t maxNumEnt {0};
73 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
75 maxNumEnt = numEnt > maxNumEnt ? numEnt : maxNumEnt;
80 template<
class SC,
class LO,
class GO,
class NT>
82 forEachLocalRowMatrixRow (
85 const std::size_t maxNumEnt,
88 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_local_inds_host_view_type& ,
89 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_values_host_view_type& ,
90 std::size_t )> doForEachRow)
92 using lids_type =
typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_local_inds_host_view_type;
93 using vals_type =
typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_values_host_view_type;
94 lids_type indBuf(
"indices",maxNumEnt);
95 vals_type valBuf(
"values",maxNumEnt);
97 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
99 lids_type ind = Kokkos::subview(indBuf,std::make_pair((
size_t)0, numEnt));
100 vals_type val = Kokkos::subview(valBuf,std::make_pair((
size_t)0, numEnt));
102 doForEachRow (lclRow, ind, val, numEnt);
106 template<
class SC,
class LO,
class GO,
class NT>
108 forEachLocalRowMatrixRow (
112 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_local_inds_host_view_type& ,
113 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_values_host_view_type& ,
114 std::size_t )> doForEachRow)
117 const LO lclNumRows =
static_cast<LO
> (rowMap.getLocalNumElements ());
118 const std::size_t maxNumEnt = lclMaxNumEntriesRowMatrix (A);
120 forEachLocalRowMatrixRow<SC, LO, GO, NT> (A, lclNumRows, maxNumEnt, doForEachRow);
126 template<
class SC,
class LO,
class GO,
class NT>
129 typename NT::device_type>& result,
132 using KAT = Kokkos::ArithTraits<SC>;
133 using mag_type =
typename KAT::mag_type;
134 using KAV = Kokkos::ArithTraits<typename KAT::val_type>;
136 auto rowNorms_h = Kokkos::create_mirror_view (result.rowNorms);
140 auto rowScaledColNorms_h = Kokkos::create_mirror_view (result.rowScaledColNorms);
142 forEachLocalRowMatrixRow<SC, LO, GO, NT> (A,
143 [&] (
const LO lclRow,
144 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_local_inds_host_view_type& ind,
145 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_values_host_view_type& val,
146 std::size_t numEnt) {
147 const mag_type rowNorm = rowNorms_h[lclRow];
148 for (std::size_t k = 0; k < numEnt; ++k) {
149 const mag_type matrixAbsVal = KAV::abs (val[k]);
150 const LO lclCol = ind[k];
152 rowScaledColNorms_h[lclCol] += matrixAbsVal / rowNorm;
162 template<
class SC,
class LO,
class GO,
class NT>
163 EquilibrationInfo<typename Kokkos::ArithTraits<SC>::val_type,
typename NT::device_type>
166 using KAT = Kokkos::ArithTraits<SC>;
167 using val_type =
typename KAT::val_type;
168 using KAV = Kokkos::ArithTraits<val_type>;
169 using mag_type =
typename KAT::mag_type;
170 using KAM = Kokkos::ArithTraits<mag_type>;
171 using device_type =
typename NT::device_type;
176 const LO lclNumRows =
static_cast<LO
> (rowMap.getLocalNumElements ());
177 const LO lclNumCols = 0;
178 constexpr
bool assumeSymmetric =
false;
179 equib_info_type result (lclNumRows, lclNumCols, assumeSymmetric);
180 auto result_h = result.createMirrorView ();
182 forEachLocalRowMatrixRow<SC, LO, GO, NT> (A,
183 [&] (
const LO lclRow,
184 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_local_inds_host_view_type& ind,
185 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_values_host_view_type& val,
186 std::size_t numEnt) {
187 mag_type rowNorm {0.0};
188 val_type diagVal {0.0};
189 const GO gblRow = rowMap.getGlobalElement (lclRow);
191 const GO lclDiagColInd = colMap.getLocalElement (gblRow);
193 for (std::size_t k = 0; k < numEnt; ++k) {
194 const val_type matrixVal = val[k];
195 if (KAV::isInf (matrixVal)) {
196 result_h.foundInf =
true;
198 if (KAV::isNan (matrixVal)) {
199 result_h.foundNan =
true;
201 const mag_type matrixAbsVal = KAV::abs (matrixVal);
202 rowNorm += matrixAbsVal;
203 const LO lclCol = ind[k];
204 if (lclCol == lclDiagColInd) {
211 if (diagVal == KAV::zero ()) {
212 result_h.foundZeroDiag =
true;
214 if (rowNorm == KAM::zero ()) {
215 result_h.foundZeroRowNorm =
true;
221 result_h.rowDiagonalEntries[lclRow] += diagVal;
222 result_h.rowNorms[lclRow] = rowNorm;
225 result.assign (result_h);
231 template<
class SC,
class LO,
class GO,
class NT>
232 EquilibrationInfo<typename Kokkos::ArithTraits<SC>::val_type,
typename NT::device_type>
234 const bool assumeSymmetric)
236 using KAT = Kokkos::ArithTraits<SC>;
237 using val_type =
typename KAT::val_type;
238 using KAV = Kokkos::ArithTraits<val_type>;
239 using mag_type =
typename KAT::mag_type;
240 using KAM = Kokkos::ArithTraits<mag_type>;
241 using device_type =
typename NT::device_type;
245 const LO lclNumRows =
static_cast<LO
> (rowMap.getLocalNumElements ());
246 const LO lclNumCols =
static_cast<LO
> (colMap.getLocalNumElements ());
249 (lclNumRows, lclNumCols, assumeSymmetric);
250 auto result_h = result.createMirrorView ();
252 forEachLocalRowMatrixRow<SC, LO, GO, NT> (A,
253 [&] (
const LO lclRow,
254 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_local_inds_host_view_type& ind,
255 const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_values_host_view_type& val,
256 std::size_t numEnt) {
257 mag_type rowNorm {0.0};
258 val_type diagVal {0.0};
259 const GO gblRow = rowMap.getGlobalElement (lclRow);
261 const GO lclDiagColInd = colMap.getLocalElement (gblRow);
263 for (std::size_t k = 0; k < numEnt; ++k) {
264 const val_type matrixVal = val[k];
265 if (KAV::isInf (matrixVal)) {
266 result_h.foundInf =
true;
268 if (KAV::isNan (matrixVal)) {
269 result_h.foundNan =
true;
271 const mag_type matrixAbsVal = KAV::abs (matrixVal);
272 rowNorm += matrixAbsVal;
273 const LO lclCol = ind[k];
274 if (lclCol == lclDiagColInd) {
277 if (! assumeSymmetric) {
278 result_h.colNorms[lclCol] += matrixAbsVal;
284 if (diagVal == KAV::zero ()) {
285 result_h.foundZeroDiag =
true;
287 if (rowNorm == KAM::zero ()) {
288 result_h.foundZeroRowNorm =
true;
294 result_h.rowDiagonalEntries[lclRow] += diagVal;
295 result_h.rowNorms[lclRow] = rowNorm;
296 if (! assumeSymmetric &&
297 lclDiagColInd != Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
298 result_h.colDiagonalEntries[lclDiagColInd] += diagVal;
306 template<
class SC,
class LO,
class GO,
class NT>
307 class ComputeLocalRowScaledColumnNorms {
310 using val_type =
typename Kokkos::ArithTraits<SC>::val_type;
311 using mag_type =
typename Kokkos::ArithTraits<val_type>::mag_type;
314 ComputeLocalRowScaledColumnNorms (
const Kokkos::View<mag_type*, device_type>& rowScaledColNorms,
315 const Kokkos::View<const mag_type*, device_type>& rowNorms,
316 const crs_matrix_type& A) :
317 rowScaledColNorms_ (rowScaledColNorms),
318 rowNorms_ (rowNorms),
319 A_lcl_ (A.getLocalMatrixDevice ())
322 KOKKOS_INLINE_FUNCTION
void operator () (
const LO lclRow)
const {
323 using KAT = Kokkos::ArithTraits<val_type>;
325 const auto curRow = A_lcl_.rowConst (lclRow);
326 const mag_type rowNorm = rowNorms_[lclRow];
327 const LO numEnt = curRow.length;
328 for (LO k = 0; k < numEnt; ++k) {
329 const mag_type matrixAbsVal = KAT::abs (curRow.value(k));
330 const LO lclCol = curRow.colidx(k);
332 Kokkos::atomic_add (&rowScaledColNorms_[lclCol], matrixAbsVal / rowNorm);
337 run (
const Kokkos::View<mag_type*, device_type>& rowScaledColNorms,
338 const Kokkos::View<const mag_type*, device_type>& rowNorms,
339 const crs_matrix_type& A)
341 using execution_space =
typename device_type::execution_space;
342 using range_type = Kokkos::RangePolicy<execution_space, LO>;
343 using functor_type = ComputeLocalRowScaledColumnNorms<SC, LO, GO, NT>;
345 functor_type functor (rowScaledColNorms, rowNorms, A);
346 const LO lclNumRows =
347 static_cast<LO
> (A.getRowMap ()->getLocalNumElements ());
348 Kokkos::parallel_for (
"computeLocalRowScaledColumnNorms",
349 range_type (0, lclNumRows), functor);
353 Kokkos::View<mag_type*, device_type> rowScaledColNorms_;
354 Kokkos::View<const mag_type*, device_type> rowNorms_;
357 local_matrix_device_type A_lcl_;
360 template<
class SC,
class LO,
class GO,
class NT>
362 computeLocalRowScaledColumnNorms_CrsMatrix (EquilibrationInfo<
typename Kokkos::ArithTraits<SC>::val_type,
363 typename NT::device_type>& result,
366 using impl_type = ComputeLocalRowScaledColumnNorms<SC, LO, GO, NT>;
367 impl_type::run (result.rowScaledColNorms, result.rowNorms, A);
370 template<
class SC,
class LO,
class GO,
class NT>
372 computeLocalRowScaledColumnNorms (EquilibrationInfo<
typename Kokkos::ArithTraits<SC>::val_type,
373 typename NT::device_type>& result,
377 using val_type =
typename Kokkos::ArithTraits<SC>::val_type;
378 using mag_type =
typename Kokkos::ArithTraits<val_type>::mag_type;
379 using device_type =
typename NT::device_type;
382 TEUCHOS_TEST_FOR_EXCEPTION
383 (colMapPtr.get () ==
nullptr, std::invalid_argument,
384 "computeLocalRowScaledColumnNorms: "
385 "Input matrix A must have a nonnull column Map.");
386 const LO lclNumCols =
static_cast<LO
> (colMapPtr->getLocalNumElements ());
387 if (static_cast<std::size_t> (result.rowScaledColNorms.extent (0)) !=
388 static_cast<std::size_t> (lclNumCols)) {
389 result.rowScaledColNorms =
390 Kokkos::View<mag_type*, device_type> (
"rowScaledColNorms", lclNumCols);
393 const crs_matrix_type* A_crs =
dynamic_cast<const crs_matrix_type*
> (&A);
394 if (A_crs ==
nullptr) {
398 computeLocalRowScaledColumnNorms_CrsMatrix (result, *A_crs);
404 template<
class SC,
class LO,
class GO,
class NT>
405 class ComputeLocalRowOneNorms {
407 using val_type =
typename Kokkos::ArithTraits<SC>::val_type;
408 using equib_info_type = EquilibrationInfo<val_type, typename NT::device_type>;
409 using local_matrix_device_type =
410 typename ::Tpetra::CrsMatrix<SC, LO, GO, NT>::local_matrix_device_type;
411 using local_map_type = typename ::Tpetra::Map<LO, GO, NT>::local_map_type;
413 ComputeLocalRowOneNorms (
const equib_info_type& equib,
414 const local_matrix_device_type& A_lcl,
415 const local_map_type& rowMap,
416 const local_map_type& colMap) :
429 using value_type = int;
431 KOKKOS_INLINE_FUNCTION
void init (value_type& dst)
const
436 KOKKOS_INLINE_FUNCTION
void
437 join (value_type& dst,
438 const value_type& src)
const
443 KOKKOS_INLINE_FUNCTION
void
444 operator () (
const LO lclRow, value_type& dst)
const
446 using KAT = Kokkos::ArithTraits<val_type>;
447 using mag_type =
typename KAT::mag_type;
448 using KAM = Kokkos::ArithTraits<mag_type>;
450 const GO gblRow = rowMap_.getGlobalElement (lclRow);
452 const GO lclDiagColInd = colMap_.getLocalElement (gblRow);
454 const auto curRow = A_lcl_.rowConst (lclRow);
455 const LO numEnt = curRow.length;
457 mag_type rowNorm {0.0};
458 val_type diagVal {0.0};
460 for (LO k = 0; k < numEnt; ++k) {
461 const val_type matrixVal = curRow.value (k);
462 if (KAT::isInf (matrixVal)) {
465 if (KAT::isNan (matrixVal)) {
468 const mag_type matrixAbsVal = KAT::abs (matrixVal);
469 rowNorm += matrixAbsVal;
470 const LO lclCol = curRow.colidx (k);
471 if (lclCol == lclDiagColInd) {
472 diagVal = curRow.value (k);
478 if (diagVal == KAT::zero ()) {
481 if (rowNorm == KAM::zero ()) {
484 equib_.rowDiagonalEntries[lclRow] = diagVal;
485 equib_.rowNorms[lclRow] = rowNorm;
489 equib_info_type equib_;
490 local_matrix_device_type A_lcl_;
491 local_map_type rowMap_;
492 local_map_type colMap_;
497 template<
class SC,
class LO,
class GO,
class NT>
498 class ComputeLocalRowAndColumnOneNorms {
500 using val_type =
typename Kokkos::ArithTraits<SC>::val_type;
501 using equib_info_type = EquilibrationInfo<val_type, typename NT::device_type>;
502 using local_matrix_device_type = typename ::Tpetra::CrsMatrix<SC, LO, GO, NT>::local_matrix_device_type;
503 using local_map_type = typename ::Tpetra::Map<LO, GO, NT>::local_map_type;
506 ComputeLocalRowAndColumnOneNorms (
const equib_info_type& equib,
507 const local_matrix_device_type& A_lcl,
508 const local_map_type& rowMap,
509 const local_map_type& colMap) :
522 using value_type = int;
524 KOKKOS_INLINE_FUNCTION
void init (value_type& dst)
const
529 KOKKOS_INLINE_FUNCTION
void
530 join (value_type& dst,
531 const value_type& src)
const
536 KOKKOS_INLINE_FUNCTION
void
537 operator () (
const LO lclRow, value_type& dst)
const
539 using KAT = Kokkos::ArithTraits<val_type>;
540 using mag_type =
typename KAT::mag_type;
541 using KAM = Kokkos::ArithTraits<mag_type>;
543 const GO gblRow = rowMap_.getGlobalElement (lclRow);
545 const GO lclDiagColInd = colMap_.getLocalElement (gblRow);
547 const auto curRow = A_lcl_.rowConst (lclRow);
548 const LO numEnt = curRow.length;
550 mag_type rowNorm {0.0};
551 val_type diagVal {0.0};
553 for (LO k = 0; k < numEnt; ++k) {
554 const val_type matrixVal = curRow.value (k);
555 if (KAT::isInf (matrixVal)) {
558 if (KAT::isNan (matrixVal)) {
561 const mag_type matrixAbsVal = KAT::abs (matrixVal);
562 rowNorm += matrixAbsVal;
563 const LO lclCol = curRow.colidx (k);
564 if (lclCol == lclDiagColInd) {
565 diagVal = curRow.value (k);
567 if (! equib_.assumeSymmetric) {
568 Kokkos::atomic_add (&(equib_.colNorms[lclCol]), matrixAbsVal);
574 if (diagVal == KAT::zero ()) {
577 if (rowNorm == KAM::zero ()) {
584 equib_.rowDiagonalEntries[lclRow] = diagVal;
585 equib_.rowNorms[lclRow] = rowNorm;
586 if (! equib_.assumeSymmetric &&
587 lclDiagColInd != Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
590 equib_.colDiagonalEntries[lclDiagColInd] += diagVal;
595 equib_info_type equib_;
596 local_matrix_device_type A_lcl_;
597 local_map_type rowMap_;
598 local_map_type colMap_;
603 template<
class SC,
class LO,
class GO,
class NT>
604 EquilibrationInfo<typename Kokkos::ArithTraits<SC>::val_type,
typename NT::device_type>
607 using execution_space =
typename NT::device_type::execution_space;
608 using range_type = Kokkos::RangePolicy<execution_space, LO>;
609 using functor_type = ComputeLocalRowOneNorms<SC, LO, GO, NT>;
610 using val_type =
typename Kokkos::ArithTraits<SC>::val_type;
611 using device_type =
typename NT::device_type;
614 const LO lclNumRows =
static_cast<LO
> (A.
getRowMap ()->getLocalNumElements ());
615 const LO lclNumCols = 0;
616 constexpr
bool assumeSymmetric =
false;
617 equib_info_type equib (lclNumRows, lclNumCols, assumeSymmetric);
623 Kokkos::parallel_reduce (
"computeLocalRowOneNorms",
624 range_type (0, lclNumRows), functor,
626 equib.foundInf = (result & 1) != 0;
627 equib.foundNan = (result & 2) != 0;
628 equib.foundZeroDiag = (result & 4) != 0;
629 equib.foundZeroRowNorm = (result & 8) != 0;
635 template<
class SC,
class LO,
class GO,
class NT>
636 EquilibrationInfo<typename Kokkos::ArithTraits<SC>::val_type,
typename NT::device_type>
638 const bool assumeSymmetric)
640 using execution_space =
typename NT::device_type::execution_space;
641 using range_type = Kokkos::RangePolicy<execution_space, LO>;
642 using functor_type = ComputeLocalRowAndColumnOneNorms<SC, LO, GO, NT>;
643 using val_type =
typename Kokkos::ArithTraits<SC>::val_type;
644 using device_type =
typename NT::device_type;
647 const LO lclNumRows =
static_cast<LO
> (A.
getRowMap ()->getLocalNumElements ());
648 const LO lclNumCols =
static_cast<LO
> (A.
getColMap ()->getLocalNumElements ());
649 equib_info_type equib (lclNumRows, lclNumCols, assumeSymmetric);
655 Kokkos::parallel_reduce (
"computeLocalRowAndColumnOneNorms",
656 range_type (0, lclNumRows), functor,
658 equib.foundInf = (result & 1) != 0;
659 equib.foundNan = (result & 2) != 0;
660 equib.foundZeroDiag = (result & 4) != 0;
661 equib.foundZeroRowNorm = (result & 8) != 0;
669 template<
class SC,
class LO,
class GO,
class NT>
670 EquilibrationInfo<typename Kokkos::ArithTraits<SC>::val_type,
671 typename NT::device_type>
675 const crs_matrix_type* A_crs =
dynamic_cast<const crs_matrix_type*
> (&A);
677 if (A_crs ==
nullptr) {
706 template<
class SC,
class LO,
class GO,
class NT>
707 EquilibrationInfo<typename Kokkos::ArithTraits<SC>::val_type,
typename NT::device_type>
709 const bool assumeSymmetric)
712 const crs_matrix_type* A_crs =
dynamic_cast<const crs_matrix_type*
> (&A);
714 if (A_crs ==
nullptr) {
722 template<
class SC,
class LO,
class GO,
class NT>
723 auto getLocalView_1d_readOnly (
725 const LO whichColumn)
726 -> decltype (Kokkos::subview (X.getLocalViewDevice(Access::ReadOnly),
727 Kokkos::ALL (), whichColumn))
729 if (X.isConstantStride ()) {
730 return Kokkos::subview (X.getLocalViewDevice(Access::ReadOnly),
731 Kokkos::ALL (), whichColumn);
734 auto X_whichColumn = X.getVector (whichColumn);
735 return Kokkos::subview (X_whichColumn->getLocalViewDevice(Access::ReadOnly),
740 template<
class SC,
class LO,
class GO,
class NT>
741 auto getLocalView_1d_writeOnly (
743 const LO whichColumn)
744 -> decltype (Kokkos::subview (X.getLocalViewDevice(Access::ReadWrite),
745 Kokkos::ALL (), whichColumn))
747 if (X.isConstantStride ()) {
748 return Kokkos::subview (X.getLocalViewDevice(Access::ReadWrite),
749 Kokkos::ALL (), whichColumn);
752 auto X_whichColumn = X.getVectorNonConst (whichColumn);
753 return Kokkos::subview(X_whichColumn->getLocalViewDevice(Access::ReadWrite),
758 template<
class SC,
class LO,
class GO,
class NT,
class ViewValueType>
760 copy1DViewIntoMultiVectorColumn (
762 const LO whichColumn,
763 const Kokkos::View<ViewValueType*, typename NT::device_type>& view)
765 auto X_lcl = getLocalView_1d_writeOnly (X, whichColumn);
769 template<
class SC,
class LO,
class GO,
class NT,
class ViewValueType>
771 copyMultiVectorColumnInto1DView (
772 const Kokkos::View<ViewValueType*, typename NT::device_type>& view,
774 const LO whichColumn)
776 auto X_lcl = getLocalView_1d_readOnly (X, whichColumn);
780 template<
class OneDViewType,
class IndexType>
783 static_assert (OneDViewType::rank == 1,
784 "OneDViewType must be a rank-1 Kokkos::View.");
785 static_assert (std::is_integral<IndexType>::value,
786 "IndexType must be a built-in integer type.");
787 FindZero (
const OneDViewType& x) : x_ (x) {}
790 KOKKOS_INLINE_FUNCTION
void
791 operator () (
const IndexType i,
int& result)
const {
792 using val_type =
typename OneDViewType::non_const_value_type;
793 result = (x_(i) == Kokkos::ArithTraits<val_type>::zero ()) ? 1 : result;
799 template<
class OneDViewType>
800 bool findZero (
const OneDViewType& x)
802 using view_type =
typename OneDViewType::const_type;
803 using execution_space =
typename view_type::execution_space;
804 using size_type =
typename view_type::size_type;
805 using functor_type = FindZero<view_type, size_type>;
807 Kokkos::RangePolicy<execution_space, size_type> range (0, x.extent (0));
808 range.set_chunk_size (500);
811 Kokkos::parallel_reduce (
"findZero", range, functor_type (x), foundZero);
812 return foundZero == 1;
815 template<
class SC,
class LO,
class GO,
class NT>
817 globalizeRowOneNorms (EquilibrationInfo<
typename Kokkos::ArithTraits<SC>::val_type,
818 typename NT::device_type>& equib,
824 TEUCHOS_TEST_FOR_EXCEPTION
825 (G.get () ==
nullptr, std::invalid_argument,
826 "globalizeRowOneNorms: Input RowMatrix A must have a nonnull graph "
827 "(that is, getGraph() must return nonnull).");
828 TEUCHOS_TEST_FOR_EXCEPTION
829 (! G->isFillComplete (), std::invalid_argument,
830 "globalizeRowOneNorms: Input CrsGraph G must be fillComplete.");
832 auto exp = G->getExporter ();
833 if (! exp.is_null ()) {
843 mv_type rowMapMV (G->getRowMap (), 2,
false);
845 copy1DViewIntoMultiVectorColumn (rowMapMV, 0, equib.rowNorms);
846 copy1DViewIntoMultiVectorColumn (rowMapMV, 1, equib.rowDiagonalEntries);
848 mv_type rangeMapMV (G->getRangeMap (), 2,
true);
852 copyMultiVectorColumnInto1DView (equib.rowNorms, rowMapMV, 0);
853 copyMultiVectorColumnInto1DView (equib.rowDiagonalEntries, rowMapMV, 1);
858 equib.foundZeroDiag = findZero (equib.rowDiagonalEntries);
859 equib.foundZeroRowNorm = findZero (equib.rowNorms);
862 constexpr
int allReduceCount = 4;
863 int lclNaughtyMatrix[allReduceCount];
864 lclNaughtyMatrix[0] = equib.foundInf ? 1 : 0;
865 lclNaughtyMatrix[1] = equib.foundNan ? 1 : 0;
866 lclNaughtyMatrix[2] = equib.foundZeroDiag ? 1 : 0;
867 lclNaughtyMatrix[3] = equib.foundZeroRowNorm ? 1 : 0;
869 using Teuchos::outArg;
870 using Teuchos::REDUCE_MAX;
871 using Teuchos::reduceAll;
872 auto comm = G->getComm ();
873 int gblNaughtyMatrix[allReduceCount];
874 reduceAll<int, int> (*comm, REDUCE_MAX, allReduceCount,
875 lclNaughtyMatrix, gblNaughtyMatrix);
877 equib.foundInf = gblNaughtyMatrix[0] == 1;
878 equib.foundNan = gblNaughtyMatrix[1] == 1;
879 equib.foundZeroDiag = gblNaughtyMatrix[2] == 1;
880 equib.foundZeroRowNorm = gblNaughtyMatrix[3] == 1;
883 template<
class SC,
class LO,
class GO,
class NT>
885 globalizeColumnOneNorms (EquilibrationInfo<
typename Kokkos::ArithTraits<SC>::val_type,
886 typename NT::device_type>& equib,
888 const bool assumeSymmetric)
890 using val_type =
typename Kokkos::ArithTraits<SC>::val_type;
891 using mag_type =
typename Kokkos::ArithTraits<val_type>::mag_type;
893 using device_type =
typename NT::device_type;
896 TEUCHOS_TEST_FOR_EXCEPTION
897 (G.get () ==
nullptr, std::invalid_argument,
898 "globalizeColumnOneNorms: Input RowMatrix A must have a nonnull graph "
899 "(that is, getGraph() must return nonnull).");
900 TEUCHOS_TEST_FOR_EXCEPTION
901 (! G->isFillComplete (), std::invalid_argument,
902 "globalizeColumnOneNorms: Input CrsGraph G must be fillComplete.");
904 auto imp = G->getImporter ();
905 if (assumeSymmetric) {
906 const LO numCols = 2;
910 mv_type rowNorms_domMap (G->getDomainMap (), numCols,
false);
911 const bool rowMapSameAsDomainMap = G->getRowMap ()->isSameAs (* (G->getDomainMap ()));
912 if (rowMapSameAsDomainMap) {
913 copy1DViewIntoMultiVectorColumn (rowNorms_domMap, 0, equib.rowNorms);
914 copy1DViewIntoMultiVectorColumn (rowNorms_domMap, 1, equib.rowDiagonalEntries);
920 mv_type rowNorms_rowMap (G->getRowMap (), numCols,
true);
921 copy1DViewIntoMultiVectorColumn (rowNorms_rowMap, 0, equib.rowNorms);
922 copy1DViewIntoMultiVectorColumn (rowNorms_rowMap, 1, equib.rowDiagonalEntries);
928 std::unique_ptr<mv_type> rowNorms_colMap;
929 if (imp.is_null ()) {
932 std::unique_ptr<mv_type> (
new mv_type (rowNorms_domMap, * (G->getColMap ())));
936 std::unique_ptr<mv_type> (
new mv_type (G->getColMap (), numCols,
true));
941 const LO lclNumCols =
942 static_cast<LO
> (G->getColMap ()->getLocalNumElements ());
943 if (static_cast<LO> (equib.colNorms.extent (0)) != lclNumCols) {
945 Kokkos::View<mag_type*, device_type> (
"colNorms", lclNumCols);
947 if (static_cast<LO> (equib.colDiagonalEntries.extent (0)) != lclNumCols) {
948 equib.colDiagonalEntries =
949 Kokkos::View<val_type*, device_type> (
"colDiagonalEntries", lclNumCols);
954 copyMultiVectorColumnInto1DView (equib.colNorms, *rowNorms_colMap, 0);
955 copyMultiVectorColumnInto1DView (equib.colDiagonalEntries, *rowNorms_colMap, 1);
958 if (! imp.is_null ()) {
959 const LO numCols = 3;
968 mv_type colMapMV (G->getColMap (), numCols,
false);
970 copy1DViewIntoMultiVectorColumn (colMapMV, 0, equib.colNorms);
971 copy1DViewIntoMultiVectorColumn (colMapMV, 1, equib.colDiagonalEntries);
972 copy1DViewIntoMultiVectorColumn (colMapMV, 2, equib.rowScaledColNorms);
974 mv_type domainMapMV (G->getDomainMap (), numCols,
true);
975 domainMapMV.doExport (colMapMV, *imp,
Tpetra::ADD);
978 copyMultiVectorColumnInto1DView (equib.colNorms, colMapMV, 0);
979 copyMultiVectorColumnInto1DView (equib.colDiagonalEntries, colMapMV, 1);
980 copyMultiVectorColumnInto1DView (equib.rowScaledColNorms, colMapMV, 2);
987 template<
class SC,
class LO,
class GO,
class NT>
988 Details::EquilibrationInfo<typename Kokkos::ArithTraits<SC>::val_type,
989 typename NT::device_type>
992 TEUCHOS_TEST_FOR_EXCEPTION
994 "computeRowOneNorms: Input matrix A must be fillComplete.");
997 Details::globalizeRowOneNorms (result, A);
1001 template<
class SC,
class LO,
class GO,
class NT>
1002 Details::EquilibrationInfo<typename Kokkos::ArithTraits<SC>::val_type,
1003 typename NT::device_type>
1005 const bool assumeSymmetric)
1007 TEUCHOS_TEST_FOR_EXCEPTION
1009 "computeRowAndColumnOneNorms: Input matrix A must be fillComplete.");
1012 Details::globalizeRowOneNorms (result, A);
1013 if (! assumeSymmetric) {
1017 Details::computeLocalRowScaledColumnNorms (result, A);
1019 Details::globalizeColumnOneNorms (result, A, assumeSymmetric);
1031 #define TPETRA_COMPUTEROWANDCOLUMNONENORMS_INSTANT(SC,LO,GO,NT) \
1032 template Details::EquilibrationInfo<Kokkos::ArithTraits<SC>::val_type, NT::device_type> \
1033 computeRowOneNorms (const Tpetra::RowMatrix<SC, LO, GO, NT>& A); \
1035 template Details::EquilibrationInfo<Kokkos::ArithTraits<SC>::val_type, NT::device_type> \
1036 computeRowAndColumnOneNorms (const Tpetra::RowMatrix<SC, LO, GO, NT>& A, \
1037 const bool assumeSymmetric);
1039 #endif // TPETRA_COMPUTEROWANDCOLUMNONENORMS_DEF_HPP
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getColMap() const =0
The Map that describes the distribution of columns over processes.
Sparse matrix that presents a row-oriented interface that lets users read or modify entries...
EquilibrationInfo< typename Kokkos::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 Kokkos::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...
One or more distributed dense vectors.
virtual size_t getNumEntriesInLocalRow(LocalOrdinal localRow) const =0
The current number of entries on the calling process in the specified local row.
virtual Teuchos::RCP< const RowGraph< LocalOrdinal, GlobalOrdinal, Node > > getGraph() const =0
The RowGraph associated with this matrix.
Details::EquilibrationInfo< typename Kokkos::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...
EquilibrationInfo< typename Kokkos::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 Kokkos::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.
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...
Details::EquilibrationInfo< typename Kokkos::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...
Declare and define Tpetra::Details::copyConvert, an implementation detail of Tpetra (in particular...
Struct storing results of Tpetra::computeRowAndColumnOneNorms.
void deep_copy(MultiVector< DS, DL, DG, DN > &dst, const MultiVector< SS, SL, SG, SN > &src)
Copy the contents of the MultiVector src into dst.
void computeLocalRowScaledColumnNorms_RowMatrix(EquilibrationInfo< typename Kokkos::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.rowNorms has been computed (and globalized), and compute result.rowScaledColNorms.
EquilibrationInfo< typename Kokkos::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.
EquilibrationInfo< typename Kokkos::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.
local_matrix_device_type getLocalMatrixDevice() const
The local sparse matrix.
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
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...
typename Node::device_type device_type
The Kokkos device type.
Replace existing values with new values.
void assign(const EquilibrationInfo< ScalarType, SrcDeviceType > &src)
Deep-copy src into *this.
virtual bool isFillComplete() const =0
Whether fillComplete() has been called.
A read-only, row-oriented interface to a sparse matrix.
virtual void getLocalRowCopy(LocalOrdinal LocalRow, nonconst_local_inds_host_view_type &Indices, nonconst_values_host_view_type &Values, size_t &NumEntries) const =0
Get a copy of the given local row's entries.
Teuchos::RCP< const map_type > getColMap() const override
The Map that describes the column distribution in this matrix.
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getRowMap() const =0
The Map that describes the distribution of rows over processes.
Teuchos::RCP< const map_type > getRowMap() const override
The Map that describes the row distribution in this matrix.