Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Tpetra_computeRowAndColumnOneNorms_def.hpp
Go to the documentation of this file.
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Tpetra: Templated Linear Algebra Services Package
5 // Copyright (2008) Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ************************************************************************
40 // @HEADER
41 
42 #ifndef TPETRA_COMPUTEROWANDCOLUMNONENORMS_DEF_HPP
43 #define TPETRA_COMPUTEROWANDCOLUMNONENORMS_DEF_HPP
44 
51 
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"
60 #include <memory>
61 
62 namespace Tpetra {
63 namespace Details {
64 
65 template<class SC, class LO, class GO, class NT>
66 std::size_t
67 lclMaxNumEntriesRowMatrix (const Tpetra::RowMatrix<SC, LO, GO, NT>& A)
68 {
69  const auto& rowMap = * (A.getRowMap ());
70  const LO lclNumRows = static_cast<LO> (rowMap.getLocalNumElements ());
71 
72  std::size_t maxNumEnt {0};
73  for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
74  const std::size_t numEnt = A.getNumEntriesInLocalRow (lclRow);
75  maxNumEnt = numEnt > maxNumEnt ? numEnt : maxNumEnt;
76  }
77  return maxNumEnt;
78 }
79 
80 template<class SC, class LO, class GO, class NT>
81 void
82 forEachLocalRowMatrixRow (
84  const LO lclNumRows,
85  const std::size_t maxNumEnt,
86  std::function<void (
87  const LO lclRow,
88  const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_local_inds_host_view_type& /*ind*/,
89  const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_values_host_view_type& /*val*/,
90  std::size_t /*numEnt*/ )> doForEachRow)
91 {
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);
96 
97  for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
98  std::size_t numEnt = A.getNumEntriesInLocalRow (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));
101  A.getLocalRowCopy (lclRow, ind, val, numEnt);
102  doForEachRow (lclRow, ind, val, numEnt);
103  }
104 }
105 
106 template<class SC, class LO, class GO, class NT>
107 void
108 forEachLocalRowMatrixRow (
110  std::function<void (
111  const LO lclRow,
112  const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_local_inds_host_view_type& /*ind*/,
113  const typename Tpetra::RowMatrix<SC, LO, GO, NT>::nonconst_values_host_view_type& /*val*/,
114  std::size_t /*numEnt*/ )> doForEachRow)
115 {
116  const auto& rowMap = * (A.getRowMap ());
117  const LO lclNumRows = static_cast<LO> (rowMap.getLocalNumElements ());
118  const std::size_t maxNumEnt = lclMaxNumEntriesRowMatrix (A);
119 
120  forEachLocalRowMatrixRow<SC, LO, GO, NT> (A, lclNumRows, maxNumEnt, doForEachRow);
121 }
122 
126 template<class SC, class LO, class GO, class NT>
127 void
128 computeLocalRowScaledColumnNorms_RowMatrix (EquilibrationInfo<typename Kokkos::ArithTraits<SC>::val_type,
129  typename NT::device_type>& result,
131 {
132  using KAT = Kokkos::ArithTraits<SC>;
133  using mag_type = typename KAT::mag_type;
134  using KAV = Kokkos::ArithTraits<typename KAT::val_type>;
135 
136  auto rowNorms_h = Kokkos::create_mirror_view (result.rowNorms);
137 
138  // DEEP_COPY REVIEW - NOT TESTED
139  Kokkos::deep_copy (rowNorms_h, result.rowNorms);
140  auto rowScaledColNorms_h = Kokkos::create_mirror_view (result.rowScaledColNorms);
141 
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];
151 
152  rowScaledColNorms_h[lclCol] += matrixAbsVal / rowNorm;
153  }
154  });
155 
156  // DEEP_COPY REVIEW - NOT TESTED
157  Kokkos::deep_copy (result.rowScaledColNorms, rowScaledColNorms_h);
158 }
159 
162 template<class SC, class LO, class GO, class NT>
163 EquilibrationInfo<typename Kokkos::ArithTraits<SC>::val_type, typename NT::device_type>
165 {
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;
172  using equib_info_type = EquilibrationInfo<val_type, device_type>;
173 
174  const auto& rowMap = * (A.getRowMap ());
175  const auto& colMap = * (A.getColMap ());
176  const LO lclNumRows = static_cast<LO> (rowMap.getLocalNumElements ());
177  const LO lclNumCols = 0; // don't allocate column-related Views
178  constexpr bool assumeSymmetric = false; // doesn't matter here
179  equib_info_type result (lclNumRows, lclNumCols, assumeSymmetric);
180  auto result_h = result.createMirrorView ();
181 
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);
190  // OK if invalid(); then we simply won't find the diagonal entry.
191  const GO lclDiagColInd = colMap.getLocalElement (gblRow);
192 
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;
197  }
198  if (KAV::isNan (matrixVal)) {
199  result_h.foundNan = true;
200  }
201  const mag_type matrixAbsVal = KAV::abs (matrixVal);
202  rowNorm += matrixAbsVal;
203  const LO lclCol = ind[k];
204  if (lclCol == lclDiagColInd) {
205  diagVal += val[k]; // repeats count additively
206  }
207  } // for each entry in row
208 
209  // This is a local result. If the matrix has an overlapping
210  // row Map, then the global result might differ.
211  if (diagVal == KAV::zero ()) {
212  result_h.foundZeroDiag = true;
213  }
214  if (rowNorm == KAM::zero ()) {
215  result_h.foundZeroRowNorm = true;
216  }
217  // NOTE (mfh 24 May 2018) We could actually compute local
218  // rowScaledColNorms in situ at this point, if ! assumeSymmetric
219  // and row Map is the same as range Map (so that the local row
220  // norms are the same as the global row norms).
221  result_h.rowDiagonalEntries[lclRow] += diagVal;
222  result_h.rowNorms[lclRow] = rowNorm;
223  });
224 
225  result.assign (result_h);
226  return result;
227 }
228 
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)
235 {
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;
242 
243  const auto& rowMap = * (A.getRowMap ());
244  const auto& colMap = * (A.getColMap ());
245  const LO lclNumRows = static_cast<LO> (rowMap.getLocalNumElements ());
246  const LO lclNumCols = static_cast<LO> (colMap.getLocalNumElements ());
247 
249  (lclNumRows, lclNumCols, assumeSymmetric);
250  auto result_h = result.createMirrorView ();
251 
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);
260  // OK if invalid(); then we simply won't find the diagonal entry.
261  const GO lclDiagColInd = colMap.getLocalElement (gblRow);
262 
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;
267  }
268  if (KAV::isNan (matrixVal)) {
269  result_h.foundNan = true;
270  }
271  const mag_type matrixAbsVal = KAV::abs (matrixVal);
272  rowNorm += matrixAbsVal;
273  const LO lclCol = ind[k];
274  if (lclCol == lclDiagColInd) {
275  diagVal += val[k]; // repeats count additively
276  }
277  if (! assumeSymmetric) {
278  result_h.colNorms[lclCol] += matrixAbsVal;
279  }
280  } // for each entry in row
281 
282  // This is a local result. If the matrix has an overlapping
283  // row Map, then the global result might differ.
284  if (diagVal == KAV::zero ()) {
285  result_h.foundZeroDiag = true;
286  }
287  if (rowNorm == KAM::zero ()) {
288  result_h.foundZeroRowNorm = true;
289  }
290  // NOTE (mfh 24 May 2018) We could actually compute local
291  // rowScaledColNorms in situ at this point, if ! assumeSymmetric
292  // and row Map is the same as range Map (so that the local row
293  // norms are the same as the global row norms).
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;
299  }
300  });
301 
302  result.assign (result_h);
303  return result;
304 }
305 
306 template<class SC, class LO, class GO, class NT>
307 class ComputeLocalRowScaledColumnNorms {
308 public:
309  using crs_matrix_type = ::Tpetra::CrsMatrix<SC, LO, GO, NT>;
310  using val_type = typename Kokkos::ArithTraits<SC>::val_type;
311  using mag_type = typename Kokkos::ArithTraits<val_type>::mag_type;
312  using device_type = typename crs_matrix_type::device_type;
313 
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 ())
320  {}
321 
322  KOKKOS_INLINE_FUNCTION void operator () (const LO lclRow) const {
323  using KAT = Kokkos::ArithTraits<val_type>;
324 
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);
331 
332  Kokkos::atomic_add (&rowScaledColNorms_[lclCol], matrixAbsVal / rowNorm);
333  }
334  }
335 
336  static void
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)
340  {
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>;
344 
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);
350  }
351 
352 private:
353  Kokkos::View<mag_type*, device_type> rowScaledColNorms_;
354  Kokkos::View<const mag_type*, device_type> rowNorms_;
355 
356  using local_matrix_device_type = typename crs_matrix_type::local_matrix_device_type;
357  local_matrix_device_type A_lcl_;
358 };
359 
360 template<class SC, class LO, class GO, class NT>
361 void
362 computeLocalRowScaledColumnNorms_CrsMatrix (EquilibrationInfo<typename Kokkos::ArithTraits<SC>::val_type,
363  typename NT::device_type>& result,
365 {
366  using impl_type = ComputeLocalRowScaledColumnNorms<SC, LO, GO, NT>;
367  impl_type::run (result.rowScaledColNorms, result.rowNorms, A);
368 }
369 
370 template<class SC, class LO, class GO, class NT>
371 void
372 computeLocalRowScaledColumnNorms (EquilibrationInfo<typename Kokkos::ArithTraits<SC>::val_type,
373  typename NT::device_type>& result,
375 {
376  using crs_matrix_type = Tpetra::CrsMatrix<SC, LO, GO, NT>;
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;
380 
381  auto colMapPtr = A.getColMap ();
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);
391  }
392 
393  const crs_matrix_type* A_crs = dynamic_cast<const crs_matrix_type*> (&A);
394  if (A_crs == nullptr) {
396  }
397  else {
398  computeLocalRowScaledColumnNorms_CrsMatrix (result, *A_crs);
399  }
400 }
401 
402 // Kokkos::parallel_reduce functor that is part of the implementation
403 // of computeLocalRowOneNorms_CrsMatrix.
404 template<class SC, class LO, class GO, class NT>
405 class ComputeLocalRowOneNorms {
406 public:
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;
412 
413  ComputeLocalRowOneNorms (const equib_info_type& equib, // in/out
414  const local_matrix_device_type& A_lcl, // in
415  const local_map_type& rowMap, // in
416  const local_map_type& colMap) : // in
417  equib_ (equib),
418  A_lcl_ (A_lcl),
419  rowMap_ (rowMap),
420  colMap_ (colMap)
421  {}
422 
423  // (result & 1) != 0 means "found Inf."
424  // (result & 2) != 0 means "found NaN."
425  // (result & 4) != 0 means "found zero diag."
426  // (result & 8) != 0 means "found zero row norm."
427  // Pack into a single int so the reduction is cheaper,
428  // esp. on GPU.
429  using value_type = int;
430 
431  KOKKOS_INLINE_FUNCTION void init (value_type& dst) const
432  {
433  dst = 0;
434  }
435 
436  KOKKOS_INLINE_FUNCTION void
437  join (value_type& dst,
438  const value_type& src) const
439  {
440  dst |= src;
441  }
442 
443  KOKKOS_INLINE_FUNCTION void
444  operator () (const LO lclRow, value_type& dst) const
445  {
446  using KAT = Kokkos::ArithTraits<val_type>;
447  using mag_type = typename KAT::mag_type;
448  using KAM = Kokkos::ArithTraits<mag_type>;
449 
450  const GO gblRow = rowMap_.getGlobalElement (lclRow);
451  // OK if invalid(); then we simply won't find the diagonal entry.
452  const GO lclDiagColInd = colMap_.getLocalElement (gblRow);
453 
454  const auto curRow = A_lcl_.rowConst (lclRow);
455  const LO numEnt = curRow.length;
456 
457  mag_type rowNorm {0.0};
458  val_type diagVal {0.0};
459 
460  for (LO k = 0; k < numEnt; ++k) {
461  const val_type matrixVal = curRow.value (k);
462  if (KAT::isInf (matrixVal)) {
463  dst |= 1;
464  }
465  if (KAT::isNan (matrixVal)) {
466  dst |= 2;
467  }
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); // assume no repeats
473  }
474  } // for each entry in row
475 
476  // This is a local result. If the matrix has an overlapping
477  // row Map, then the global result might differ.
478  if (diagVal == KAT::zero ()) {
479  dst |= 4;
480  }
481  if (rowNorm == KAM::zero ()) {
482  dst |= 8;
483  }
484  equib_.rowDiagonalEntries[lclRow] = diagVal;
485  equib_.rowNorms[lclRow] = rowNorm;
486  }
487 
488 private:
489  equib_info_type equib_;
490  local_matrix_device_type A_lcl_;
491  local_map_type rowMap_;
492  local_map_type colMap_;
493 };
494 
495 // Kokkos::parallel_reduce functor that is part of the implementation
496 // of computeLocalRowAndColumnOneNorms_CrsMatrix.
497 template<class SC, class LO, class GO, class NT>
498 class ComputeLocalRowAndColumnOneNorms {
499 public:
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;
504 
505 public:
506  ComputeLocalRowAndColumnOneNorms (const equib_info_type& equib, // in/out
507  const local_matrix_device_type& A_lcl, // in
508  const local_map_type& rowMap, // in
509  const local_map_type& colMap) : // in
510  equib_ (equib),
511  A_lcl_ (A_lcl),
512  rowMap_ (rowMap),
513  colMap_ (colMap)
514  {}
515 
516  // (result & 1) != 0 means "found Inf."
517  // (result & 2) != 0 means "found NaN."
518  // (result & 4) != 0 means "found zero diag."
519  // (result & 8) != 0 means "found zero row norm."
520  // Pack into a single int so the reduction is cheaper,
521  // esp. on GPU.
522  using value_type = int;
523 
524  KOKKOS_INLINE_FUNCTION void init (value_type& dst) const
525  {
526  dst = 0;
527  }
528 
529  KOKKOS_INLINE_FUNCTION void
530  join (value_type& dst,
531  const value_type& src) const
532  {
533  dst |= src;
534  }
535 
536  KOKKOS_INLINE_FUNCTION void
537  operator () (const LO lclRow, value_type& dst) const
538  {
539  using KAT = Kokkos::ArithTraits<val_type>;
540  using mag_type = typename KAT::mag_type;
541  using KAM = Kokkos::ArithTraits<mag_type>;
542 
543  const GO gblRow = rowMap_.getGlobalElement (lclRow);
544  // OK if invalid(); then we simply won't find the diagonal entry.
545  const GO lclDiagColInd = colMap_.getLocalElement (gblRow);
546 
547  const auto curRow = A_lcl_.rowConst (lclRow);
548  const LO numEnt = curRow.length;
549 
550  mag_type rowNorm {0.0};
551  val_type diagVal {0.0};
552 
553  for (LO k = 0; k < numEnt; ++k) {
554  const val_type matrixVal = curRow.value (k);
555  if (KAT::isInf (matrixVal)) {
556  dst |= 1;
557  }
558  if (KAT::isNan (matrixVal)) {
559  dst |= 2;
560  }
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); // assume no repeats
566  }
567  if (! equib_.assumeSymmetric) {
568  Kokkos::atomic_add (&(equib_.colNorms[lclCol]), matrixAbsVal);
569  }
570  } // for each entry in row
571 
572  // This is a local result. If the matrix has an overlapping
573  // row Map, then the global result might differ.
574  if (diagVal == KAT::zero ()) {
575  dst |= 4;
576  }
577  if (rowNorm == KAM::zero ()) {
578  dst |= 8;
579  }
580  // NOTE (mfh 24 May 2018) We could actually compute local
581  // rowScaledColNorms in situ at this point, if ! assumeSymmetric
582  // and row Map is the same as range Map (so that the local row
583  // norms are the same as the global row norms).
584  equib_.rowDiagonalEntries[lclRow] = diagVal;
585  equib_.rowNorms[lclRow] = rowNorm;
586  if (! equib_.assumeSymmetric &&
587  lclDiagColInd != Tpetra::Details::OrdinalTraits<LO>::invalid ()) {
588  // Don't need an atomic update here, since this lclDiagColInd is
589  // a one-to-one function of lclRow.
590  equib_.colDiagonalEntries[lclDiagColInd] += diagVal;
591  }
592  }
593 
594 private:
595  equib_info_type equib_;
596  local_matrix_device_type A_lcl_;
597  local_map_type rowMap_;
598  local_map_type colMap_;
599 };
600 
603 template<class SC, class LO, class GO, class NT>
604 EquilibrationInfo<typename Kokkos::ArithTraits<SC>::val_type, typename NT::device_type>
606 {
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;
612  using equib_info_type = EquilibrationInfo<val_type, device_type>;
613 
614  const LO lclNumRows = static_cast<LO> (A.getRowMap ()->getLocalNumElements ());
615  const LO lclNumCols = 0; // don't allocate column-related Views
616  constexpr bool assumeSymmetric = false; // doesn't matter here
617  equib_info_type equib (lclNumRows, lclNumCols, assumeSymmetric);
618 
619  functor_type functor (equib, A.getLocalMatrixDevice (),
620  A.getRowMap ()->getLocalMap (),
621  A.getColMap ()->getLocalMap ());
622  int result = 0;
623  Kokkos::parallel_reduce ("computeLocalRowOneNorms",
624  range_type (0, lclNumRows), functor,
625  result);
626  equib.foundInf = (result & 1) != 0;
627  equib.foundNan = (result & 2) != 0;
628  equib.foundZeroDiag = (result & 4) != 0;
629  equib.foundZeroRowNorm = (result & 8) != 0;
630  return equib;
631 }
632 
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)
639 {
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;
645  using equib_info_type = EquilibrationInfo<val_type, device_type>;
646 
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);
650 
651  functor_type functor (equib, A.getLocalMatrixDevice (),
652  A.getRowMap ()->getLocalMap (),
653  A.getColMap ()->getLocalMap ());
654  int result = 0;
655  Kokkos::parallel_reduce ("computeLocalRowAndColumnOneNorms",
656  range_type (0, lclNumRows), functor,
657  result);
658  equib.foundInf = (result & 1) != 0;
659  equib.foundNan = (result & 2) != 0;
660  equib.foundZeroDiag = (result & 4) != 0;
661  equib.foundZeroRowNorm = (result & 8) != 0;
662  return equib;
663 }
664 
669 template<class SC, class LO, class GO, class NT>
670 EquilibrationInfo<typename Kokkos::ArithTraits<SC>::val_type,
671  typename NT::device_type>
673 {
674  using crs_matrix_type = Tpetra::CrsMatrix<SC, LO, GO, NT>;
675  const crs_matrix_type* A_crs = dynamic_cast<const crs_matrix_type*> (&A);
676 
677  if (A_crs == nullptr) {
679  }
680  else {
681  return computeLocalRowOneNorms_CrsMatrix (*A_crs);
682  }
683 }
684 
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)
710 {
711  using crs_matrix_type = Tpetra::CrsMatrix<SC, LO, GO, NT>;
712  const crs_matrix_type* A_crs = dynamic_cast<const crs_matrix_type*> (&A);
713 
714  if (A_crs == nullptr) {
715  return computeLocalRowAndColumnOneNorms_RowMatrix (A, assumeSymmetric);
716  }
717  else {
718  return computeLocalRowAndColumnOneNorms_CrsMatrix (*A_crs, assumeSymmetric);
719  }
720 }
721 
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))
728 {
729  if (X.isConstantStride ()) {
730  return Kokkos::subview (X.getLocalViewDevice(Access::ReadOnly),
731  Kokkos::ALL (), whichColumn);
732  }
733  else {
734  auto X_whichColumn = X.getVector (whichColumn);
735  return Kokkos::subview (X_whichColumn->getLocalViewDevice(Access::ReadOnly),
736  Kokkos::ALL (), 0);
737  }
738 }
739 
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))
746 {
747  if (X.isConstantStride ()) {
748  return Kokkos::subview (X.getLocalViewDevice(Access::ReadWrite),
749  Kokkos::ALL (), whichColumn);
750  }
751  else {
752  auto X_whichColumn = X.getVectorNonConst (whichColumn);
753  return Kokkos::subview(X_whichColumn->getLocalViewDevice(Access::ReadWrite),
754  Kokkos::ALL (), 0);
755  }
756 }
757 
758 template<class SC, class LO, class GO, class NT, class ViewValueType>
759 void
760 copy1DViewIntoMultiVectorColumn (
762  const LO whichColumn,
763  const Kokkos::View<ViewValueType*, typename NT::device_type>& view)
764 {
765  auto X_lcl = getLocalView_1d_writeOnly (X, whichColumn);
766  Tpetra::Details::copyConvert (X_lcl, view);
767 }
768 
769 template<class SC, class LO, class GO, class NT, class ViewValueType>
770 void
771 copyMultiVectorColumnInto1DView (
772  const Kokkos::View<ViewValueType*, typename NT::device_type>& view,
774  const LO whichColumn)
775 {
776  auto X_lcl = getLocalView_1d_readOnly (X, whichColumn);
777  Tpetra::Details::copyConvert (view, X_lcl);
778 }
779 
780 template<class OneDViewType, class IndexType>
781 class FindZero {
782 public:
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) {}
788  // Kokkos historically didn't like bool reduction results on CUDA,
789  // so we use int as the reduction result type.
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;
794  }
795 private:
796  OneDViewType x_;
797 };
798 
799 template<class OneDViewType>
800 bool findZero (const OneDViewType& x)
801 {
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>;
806 
807  Kokkos::RangePolicy<execution_space, size_type> range (0, x.extent (0));
808  range.set_chunk_size (500); // adjust as needed
809 
810  int foundZero = 0;
811  Kokkos::parallel_reduce ("findZero", range, functor_type (x), foundZero);
812  return foundZero == 1;
813 }
814 
815 template<class SC, class LO, class GO, class NT>
816 void
817 globalizeRowOneNorms (EquilibrationInfo<typename Kokkos::ArithTraits<SC>::val_type,
818  typename NT::device_type>& equib,
820 {
821  using mv_type = Tpetra::MultiVector<SC, LO, GO, NT>;
822 
823  auto G = A.getGraph ();
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.");
831 
832  auto exp = G->getExporter ();
833  if (! exp.is_null ()) {
834  // If the matrix has an overlapping row Map, first Export the
835  // local row norms with ADD CombineMode to a range Map Vector to
836  // get the global row norms, then reverse them back with REPLACE
837  // CombineMode to the row Map Vector. Ditto for the local row
838  // diagonal entries. Use SC instead of mag_type, so we can
839  // communicate both row norms and row diagonal entries at once.
840 
841  // FIXME (mfh 16 May 2018) Clever DualView tricks could possibly
842  // avoid the local copy here.
843  mv_type rowMapMV (G->getRowMap (), 2, false);
844 
845  copy1DViewIntoMultiVectorColumn (rowMapMV, 0, equib.rowNorms);
846  copy1DViewIntoMultiVectorColumn (rowMapMV, 1, equib.rowDiagonalEntries);
847  {
848  mv_type rangeMapMV (G->getRangeMap (), 2, true);
849  rangeMapMV.doExport (rowMapMV, *exp, Tpetra::ADD); // forward mode
850  rowMapMV.doImport (rangeMapMV, *exp, Tpetra::REPLACE); // reverse mode
851  }
852  copyMultiVectorColumnInto1DView (equib.rowNorms, rowMapMV, 0);
853  copyMultiVectorColumnInto1DView (equib.rowDiagonalEntries, rowMapMV, 1);
854 
855  // It's not common for users to solve linear systems with a
856  // nontrival Export, so it's OK for this to cost an additional
857  // pass over rowDiagonalEntries.
858  equib.foundZeroDiag = findZero (equib.rowDiagonalEntries);
859  equib.foundZeroRowNorm = findZero (equib.rowNorms);
860  }
861 
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;
868 
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);
876 
877  equib.foundInf = gblNaughtyMatrix[0] == 1;
878  equib.foundNan = gblNaughtyMatrix[1] == 1;
879  equib.foundZeroDiag = gblNaughtyMatrix[2] == 1;
880  equib.foundZeroRowNorm = gblNaughtyMatrix[3] == 1;
881 }
882 
883 template<class SC, class LO, class GO, class NT>
884 void
885 globalizeColumnOneNorms (EquilibrationInfo<typename Kokkos::ArithTraits<SC>::val_type,
886  typename NT::device_type>& equib,
888  const bool assumeSymmetric) // if so, use row norms
889 {
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;
894 
895  auto G = A.getGraph ();
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.");
903 
904  auto imp = G->getImporter ();
905  if (assumeSymmetric) {
906  const LO numCols = 2;
907  // Redistribute local row info to global column info.
908 
909  // Get the data into a MultiVector on the domain Map.
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);
915  }
916  else {
917  // This is not a common case; it would normally arise when the
918  // matrix has an overlapping row Map.
919  Tpetra::Export<LO, GO, NT> rowToDom (G->getRowMap (), G->getDomainMap ());
920  mv_type rowNorms_rowMap (G->getRowMap (), numCols, true);
921  copy1DViewIntoMultiVectorColumn (rowNorms_rowMap, 0, equib.rowNorms);
922  copy1DViewIntoMultiVectorColumn (rowNorms_rowMap, 1, equib.rowDiagonalEntries);
923  rowNorms_domMap.doExport (rowNorms_rowMap, rowToDom, Tpetra::REPLACE);
924  }
925 
926  // Use the existing Import to redistribute the row norms from the
927  // domain Map to the column Map.
928  std::unique_ptr<mv_type> rowNorms_colMap;
929  if (imp.is_null ()) {
930  // Shallow copy of rowNorms_domMap.
931  rowNorms_colMap =
932  std::unique_ptr<mv_type> (new mv_type (rowNorms_domMap, * (G->getColMap ())));
933  }
934  else {
935  rowNorms_colMap =
936  std::unique_ptr<mv_type> (new mv_type (G->getColMap (), numCols, true));
937  rowNorms_colMap->doImport (rowNorms_domMap, *imp, Tpetra::REPLACE);
938  }
939 
940  // Make sure the result has allocations of the right size.
941  const LO lclNumCols =
942  static_cast<LO> (G->getColMap ()->getLocalNumElements ());
943  if (static_cast<LO> (equib.colNorms.extent (0)) != lclNumCols) {
944  equib.colNorms =
945  Kokkos::View<mag_type*, device_type> ("colNorms", lclNumCols);
946  }
947  if (static_cast<LO> (equib.colDiagonalEntries.extent (0)) != lclNumCols) {
948  equib.colDiagonalEntries =
949  Kokkos::View<val_type*, device_type> ("colDiagonalEntries", lclNumCols);
950  }
951 
952  // Copy row norms and diagonal entries, appropriately
953  // redistributed, into column norms resp. diagonal entries.
954  copyMultiVectorColumnInto1DView (equib.colNorms, *rowNorms_colMap, 0);
955  copyMultiVectorColumnInto1DView (equib.colDiagonalEntries, *rowNorms_colMap, 1);
956  }
957  else {
958  if (! imp.is_null ()) {
959  const LO numCols = 3;
960  // If the matrix has an overlapping column Map (this is usually
961  // the case), first Export (reverse-mode Import) the local info
962  // to a domain Map Vector to get the global info, then Import
963  // them back with REPLACE CombineMode to the column Map Vector.
964  // Ditto for the row-scaled column norms.
965 
966  // FIXME (mfh 16 May 2018) Clever DualView tricks could possibly
967  // avoid the local copy here.
968  mv_type colMapMV (G->getColMap (), numCols, false);
969 
970  copy1DViewIntoMultiVectorColumn (colMapMV, 0, equib.colNorms);
971  copy1DViewIntoMultiVectorColumn (colMapMV, 1, equib.colDiagonalEntries);
972  copy1DViewIntoMultiVectorColumn (colMapMV, 2, equib.rowScaledColNorms);
973  {
974  mv_type domainMapMV (G->getDomainMap (), numCols, true);
975  domainMapMV.doExport (colMapMV, *imp, Tpetra::ADD); // reverse mode
976  colMapMV.doImport (domainMapMV, *imp, Tpetra::REPLACE); // forward mode
977  }
978  copyMultiVectorColumnInto1DView (equib.colNorms, colMapMV, 0);
979  copyMultiVectorColumnInto1DView (equib.colDiagonalEntries, colMapMV, 1);
980  copyMultiVectorColumnInto1DView (equib.rowScaledColNorms, colMapMV, 2);
981  }
982  }
983 }
984 
985 } // namespace Details
986 
987 template<class SC, class LO, class GO, class NT>
988 Details::EquilibrationInfo<typename Kokkos::ArithTraits<SC>::val_type,
989  typename NT::device_type>
991 {
992  TEUCHOS_TEST_FOR_EXCEPTION
993  (! A.isFillComplete (), std::invalid_argument,
994  "computeRowOneNorms: Input matrix A must be fillComplete.");
995  auto result = Details::computeLocalRowOneNorms (A);
996 
997  Details::globalizeRowOneNorms (result, A);
998  return result;
999 }
1000 
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)
1006 {
1007  TEUCHOS_TEST_FOR_EXCEPTION
1008  (! A.isFillComplete (), std::invalid_argument,
1009  "computeRowAndColumnOneNorms: Input matrix A must be fillComplete.");
1010  auto result = Details::computeLocalRowAndColumnOneNorms (A, assumeSymmetric);
1011 
1012  Details::globalizeRowOneNorms (result, A);
1013  if (! assumeSymmetric) {
1014  // Row-norm-scaled column norms are trivial if the matrix is
1015  // symmetric, since the row norms and column norms are the same in
1016  // that case.
1017  Details::computeLocalRowScaledColumnNorms (result, A);
1018  }
1019  Details::globalizeColumnOneNorms (result, A, assumeSymmetric);
1020  return result;
1021 }
1022 
1023 } // namespace Tpetra
1024 
1025 //
1026 // Explicit instantiation macro
1027 //
1028 // Must be expanded from within the Tpetra namespace!
1029 //
1030 
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); \
1034  \
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);
1038 
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 (&quot;row sums&quot;) 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 (&quot;row sums&quot; 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 (&quot;row sums&quot; and &quot;column sums&quot;) 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 (&quot;row sums&quot; 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...
Sum new values.
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&#39;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.