Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Tpetra_RowMatrix_def.hpp
1 // @HEADER
2 // *****************************************************************************
3 // Tpetra: Templated Linear Algebra Services Package
4 //
5 // Copyright 2008 NTESS and the Tpetra contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #ifndef TPETRA_ROWMATRIX_DEF_HPP
11 #define TPETRA_ROWMATRIX_DEF_HPP
12 
13 #include "Tpetra_CrsMatrix.hpp"
14 #include "Tpetra_Map.hpp"
15 #include "Tpetra_RowGraph.hpp"
16 
17 namespace Tpetra {
18 
19  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
21 
22  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
23  Teuchos::RCP<RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
25  add (const Scalar& alpha,
27  const Scalar& beta,
28  const Teuchos::RCP<const Map<LocalOrdinal, GlobalOrdinal, Node> >& domainMap,
29  const Teuchos::RCP<const Map<LocalOrdinal, GlobalOrdinal, Node> >& rangeMap,
30  const Teuchos::RCP<Teuchos::ParameterList>& params) const
31  {
32  using Teuchos::Array;
33  using Teuchos::ArrayView;
34  using Teuchos::ParameterList;
35  using Teuchos::RCP;
36  using Teuchos::rcp;
37  using Teuchos::rcp_implicit_cast;
38  using Teuchos::sublist;
39  typedef LocalOrdinal LO;
40  typedef GlobalOrdinal GO;
41  typedef Teuchos::ScalarTraits<Scalar> STS;
42  typedef Map<LO, GO, Node> map_type;
45 
46  const this_type& B = *this; // a convenient abbreviation
47 
48  // If the user didn't supply a domain or range Map, then try to
49  // get one from B first (if it has them), then from A (if it has
50  // them). If we don't have any domain or range Maps, scold the
51  // user.
52  RCP<const map_type> A_domainMap = A.getDomainMap ();
53  RCP<const map_type> A_rangeMap = A.getRangeMap ();
54  RCP<const map_type> B_domainMap = B.getDomainMap ();
55  RCP<const map_type> B_rangeMap = B.getRangeMap ();
56 
57  RCP<const map_type> theDomainMap = domainMap;
58  RCP<const map_type> theRangeMap = rangeMap;
59 
60  if (domainMap.is_null ()) {
61  if (B_domainMap.is_null ()) {
62  TEUCHOS_TEST_FOR_EXCEPTION(
63  A_domainMap.is_null (), std::invalid_argument,
64  "Tpetra::RowMatrix::add: If neither A nor B have a domain Map, "
65  "then you must supply a nonnull domain Map to this method.");
66  theDomainMap = A_domainMap;
67  } else {
68  theDomainMap = B_domainMap;
69  }
70  }
71  if (rangeMap.is_null ()) {
72  if (B_rangeMap.is_null ()) {
73  TEUCHOS_TEST_FOR_EXCEPTION(
74  A_rangeMap.is_null (), std::invalid_argument,
75  "Tpetra::RowMatrix::add: If neither A nor B have a range Map, "
76  "then you must supply a nonnull range Map to this method.");
77  theRangeMap = A_rangeMap;
78  } else {
79  theRangeMap = B_rangeMap;
80  }
81  }
82 
83 #ifdef HAVE_TPETRA_DEBUG
84  // In a debug build, check that A and B have matching domain and
85  // range Maps, if they have domain and range Maps at all. (If
86  // they aren't fill complete, then they may not yet have them.)
87  if (! A_domainMap.is_null () && ! A_rangeMap.is_null ()) {
88  if (! B_domainMap.is_null () && ! B_rangeMap.is_null ()) {
89  TEUCHOS_TEST_FOR_EXCEPTION(
90  ! B_domainMap->isSameAs (*A_domainMap), std::invalid_argument,
91  "Tpetra::RowMatrix::add: The input RowMatrix A must have a domain Map "
92  "which is the same as (isSameAs) this RowMatrix's domain Map.");
93  TEUCHOS_TEST_FOR_EXCEPTION(
94  ! B_rangeMap->isSameAs (*A_rangeMap), std::invalid_argument,
95  "Tpetra::RowMatrix::add: The input RowMatrix A must have a range Map "
96  "which is the same as (isSameAs) this RowMatrix's range Map.");
97  TEUCHOS_TEST_FOR_EXCEPTION(
98  ! domainMap.is_null () && ! domainMap->isSameAs (*B_domainMap),
99  std::invalid_argument,
100  "Tpetra::RowMatrix::add: The input domain Map must be the same as "
101  "(isSameAs) this RowMatrix's domain Map.");
102  TEUCHOS_TEST_FOR_EXCEPTION(
103  ! rangeMap.is_null () && ! rangeMap->isSameAs (*B_rangeMap),
104  std::invalid_argument,
105  "Tpetra::RowMatrix::add: The input range Map must be the same as "
106  "(isSameAs) this RowMatrix's range Map.");
107  }
108  }
109  else if (! B_domainMap.is_null () && ! B_rangeMap.is_null ()) {
110  TEUCHOS_TEST_FOR_EXCEPTION(
111  ! domainMap.is_null () && ! domainMap->isSameAs (*B_domainMap),
112  std::invalid_argument,
113  "Tpetra::RowMatrix::add: The input domain Map must be the same as "
114  "(isSameAs) this RowMatrix's domain Map.");
115  TEUCHOS_TEST_FOR_EXCEPTION(
116  ! rangeMap.is_null () && ! rangeMap->isSameAs (*B_rangeMap),
117  std::invalid_argument,
118  "Tpetra::RowMatrix::add: The input range Map must be the same as "
119  "(isSameAs) this RowMatrix's range Map.");
120  }
121  else {
122  TEUCHOS_TEST_FOR_EXCEPTION(
123  domainMap.is_null () || rangeMap.is_null (), std::invalid_argument,
124  "Tpetra::RowMatrix::add: If neither A nor B have a domain and range "
125  "Map, then you must supply a nonnull domain and range Map to this "
126  "method.");
127  }
128 #endif // HAVE_TPETRA_DEBUG
129 
130  // What parameters do we pass to C's constructor? Do we call
131  // fillComplete on C after filling it? And if so, what parameters
132  // do we pass to C's fillComplete call?
133  bool callFillComplete = true;
134  RCP<ParameterList> constructorSublist;
135  RCP<ParameterList> fillCompleteSublist;
136  if (! params.is_null ()) {
137  callFillComplete = params->get ("Call fillComplete", callFillComplete);
138  constructorSublist = sublist (params, "Constructor parameters");
139  fillCompleteSublist = sublist (params, "fillComplete parameters");
140  }
141 
142  RCP<const map_type> A_rowMap = A.getRowMap ();
143  RCP<const map_type> B_rowMap = B.getRowMap ();
144  RCP<const map_type> C_rowMap = B_rowMap; // see discussion in documentation
145  RCP<crs_matrix_type> C; // The result matrix.
146 
147  // If A and B's row Maps are the same, we can compute an upper
148  // bound on the number of entries in each row of C, before
149  // actually computing the sum. A reasonable upper bound is the
150  // sum of the two entry counts in each row. If we choose this as
151  // the actual per-row upper bound, we can use static profile.
152  if (A_rowMap->isSameAs (*B_rowMap)) {
153  const LO localNumRows = static_cast<LO> (A_rowMap->getLocalNumElements ());
154  Array<size_t> C_maxNumEntriesPerRow (localNumRows, 0);
155 
156  // Get the number of entries in each row of A.
157  if (alpha != STS::zero ()) {
158  for (LO localRow = 0; localRow < localNumRows; ++localRow) {
159  const size_t A_numEntries = A.getNumEntriesInLocalRow (localRow);
160  C_maxNumEntriesPerRow[localRow] += A_numEntries;
161  }
162  }
163  // Get the number of entries in each row of B.
164  if (beta != STS::zero ()) {
165  for (LO localRow = 0; localRow < localNumRows; ++localRow) {
166  const size_t B_numEntries = B.getNumEntriesInLocalRow (localRow);
167  C_maxNumEntriesPerRow[localRow] += B_numEntries;
168  }
169  }
170  // Construct the result matrix C.
171  if (constructorSublist.is_null ()) {
172  C = rcp (new crs_matrix_type (C_rowMap, C_maxNumEntriesPerRow ()));
173  } else {
174  C = rcp (new crs_matrix_type (C_rowMap, C_maxNumEntriesPerRow (),
175  constructorSublist));
176  }
177  // Since A and B have the same row Maps, we could add them
178  // together all at once and merge values before we call
179  // insertGlobalValues. However, we don't really need to, since
180  // we've already allocated enough space in each row of C for C
181  // to do the merge itself.
182  }
183  else { // the row Maps of A and B are not the same
184  // Construct the result matrix C.
185  // true: !A_rowMap->isSameAs (*B_rowMap)
186  TEUCHOS_TEST_FOR_EXCEPTION(true,
187  std::invalid_argument,
188  "Tpetra::RowMatrix::add: The row maps must be the same for statically "
189  "allocated matrices in order to be sure that there is sufficient space "
190  "to do the addition");
191  }
192 
193 #ifdef HAVE_TPETRA_DEBUG
194  TEUCHOS_TEST_FOR_EXCEPTION(C.is_null (), std::logic_error,
195  "Tpetra::RowMatrix::add: C should not be null at this point. "
196  "Please report this bug to the Tpetra developers.");
197 #endif // HAVE_TPETRA_DEBUG
198  //
199  // Compute C = alpha*A + beta*B.
200  //
201  using gids_type = nonconst_global_inds_host_view_type;
202  using vals_type = nonconst_values_host_view_type;
203  gids_type ind;
204  vals_type val;
205 
206  if (alpha != STS::zero ()) {
207  const LO A_localNumRows = static_cast<LO> (A_rowMap->getLocalNumElements ());
208  for (LO localRow = 0; localRow < A_localNumRows; ++localRow) {
209  size_t A_numEntries = A.getNumEntriesInLocalRow (localRow);
210  const GO globalRow = A_rowMap->getGlobalElement (localRow);
211  if (A_numEntries > static_cast<size_t> (ind.size ())) {
212  Kokkos::resize(ind,A_numEntries);
213  Kokkos::resize(val,A_numEntries);
214  }
215  gids_type indView = Kokkos::subview(ind, std::make_pair((size_t)0, A_numEntries));
216  vals_type valView = Kokkos::subview(val, std::make_pair((size_t)0, A_numEntries));
217  A.getGlobalRowCopy (globalRow, indView, valView, A_numEntries);
218 
219  if (alpha != STS::one ()) {
220  for (size_t k = 0; k < A_numEntries; ++k) {
221  valView[k] *= alpha;
222  }
223  }
224  C->insertGlobalValues (globalRow, A_numEntries,
225  reinterpret_cast<const Scalar*>(valView.data()),
226  indView.data());
227  }
228  }
229 
230  if (beta != STS::zero ()) {
231  const LO B_localNumRows = static_cast<LO> (B_rowMap->getLocalNumElements ());
232  for (LO localRow = 0; localRow < B_localNumRows; ++localRow) {
233  size_t B_numEntries = B.getNumEntriesInLocalRow (localRow);
234  const GO globalRow = B_rowMap->getGlobalElement (localRow);
235  if (B_numEntries > static_cast<size_t> (ind.size ())) {
236  Kokkos::resize(ind,B_numEntries);
237  Kokkos::resize(val,B_numEntries);
238  }
239  gids_type indView = Kokkos::subview(ind, std::make_pair((size_t)0, B_numEntries));
240  vals_type valView = Kokkos::subview(val, std::make_pair((size_t)0, B_numEntries));
241  B.getGlobalRowCopy (globalRow, indView, valView, B_numEntries);
242 
243  if (beta != STS::one ()) {
244  for (size_t k = 0; k < B_numEntries; ++k) {
245  valView[k] *= beta;
246  }
247  }
248  C->insertGlobalValues (globalRow, B_numEntries,
249  reinterpret_cast<const Scalar*>(valView.data()),
250  indView.data());
251  }
252  }
253 
254  if (callFillComplete) {
255  if (fillCompleteSublist.is_null ()) {
256  C->fillComplete (theDomainMap, theRangeMap);
257  } else {
258  C->fillComplete (theDomainMap, theRangeMap, fillCompleteSublist);
259  }
260  }
261 
262  return rcp_implicit_cast<this_type> (C);
263  }
264 
265 
266  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
267  void
269  pack (const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
270  Teuchos::Array<char>& exports,
271  const Teuchos::ArrayView<size_t>& numPacketsPerLID,
272  size_t& constantNumPackets) const
273  {
274 #ifdef HAVE_TPETRA_DEBUG
275  const char tfecfFuncName[] = "pack: ";
276  {
277  using Teuchos::reduceAll;
278  std::ostringstream msg;
279  int lclBad = 0;
280  try {
281  this->packImpl (exportLIDs, exports, numPacketsPerLID,
282  constantNumPackets);
283  } catch (std::exception& e) {
284  lclBad = 1;
285  msg << e.what ();
286  }
287  int gblBad = 0;
288  const Teuchos::Comm<int>& comm = * (this->getComm ());
289  reduceAll<int, int> (comm, Teuchos::REDUCE_MAX,
290  lclBad, Teuchos::outArg (gblBad));
291  if (gblBad != 0) {
292  const int myRank = comm.getRank ();
293  const int numProcs = comm.getSize ();
294  for (int r = 0; r < numProcs; ++r) {
295  if (r == myRank && lclBad != 0) {
296  std::ostringstream os;
297  os << "Proc " << myRank << ": " << msg.str () << std::endl;
298  std::cerr << os.str ();
299  }
300  comm.barrier ();
301  comm.barrier ();
302  comm.barrier ();
303  }
304  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
305  true, std::logic_error, "packImpl() threw an exception on one or "
306  "more participating processes.");
307  }
308  }
309 #else
310  this->packImpl (exportLIDs, exports, numPacketsPerLID,
311  constantNumPackets);
312 #endif // HAVE_TPETRA_DEBUG
313  }
314 
315  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
316  void
318  allocatePackSpace (Teuchos::Array<char>& exports,
319  size_t& totalNumEntries,
320  const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs) const
321  {
322  typedef LocalOrdinal LO;
323  typedef GlobalOrdinal GO;
324  typedef typename Teuchos::ArrayView<const LO>::size_type size_type;
325  //const char tfecfFuncName[] = "allocatePackSpace: ";
326  const size_type numExportLIDs = exportLIDs.size ();
327 
328  // Count the total number of entries to send.
329  totalNumEntries = 0;
330  for (size_type i = 0; i < numExportLIDs; ++i) {
331  const LO lclRow = exportLIDs[i];
332  size_t curNumEntries = this->getNumEntriesInLocalRow (lclRow);
333  // FIXME (mfh 25 Jan 2015) We should actually report invalid row
334  // indices as an error. Just consider them nonowned for now.
335  if (curNumEntries == Teuchos::OrdinalTraits<size_t>::invalid ()) {
336  curNumEntries = 0;
337  }
338  totalNumEntries += curNumEntries;
339  }
340 
341  // FIXME (mfh 24 Feb 2013) This code is only correct if
342  // sizeof(Scalar) is a meaningful representation of the amount of
343  // data in a Scalar instance. (LO and GO are always built-in
344  // integer types.)
345  //
346  // Allocate the exports array. It does NOT need padding for
347  // alignment, since we use memcpy to write to / read from send /
348  // receive buffers.
349  const size_t allocSize =
350  static_cast<size_t> (numExportLIDs) * sizeof (LO) +
351  totalNumEntries * (sizeof (Scalar) + sizeof (GO));
352  if (static_cast<size_t> (exports.size ()) < allocSize) {
353  exports.resize (allocSize);
354  }
355  }
356 
357  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
358  bool
359  RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
360  packRow (char* const numEntOut,
361  char* const valOut,
362  char* const indOut,
363  const size_t numEnt,
364  const LocalOrdinal lclRow) const
365  {
366  using Teuchos::Array;
367  using Teuchos::ArrayView;
368  typedef LocalOrdinal LO;
369  typedef GlobalOrdinal GO;
370  typedef Tpetra::Map<LO, GO, Node> map_type;
371 
372  const LO numEntLO = static_cast<LO> (numEnt);
373  memcpy (numEntOut, &numEntLO, sizeof (LO));
374 
375  if (this->supportsRowViews ()) {
376  if (this->isLocallyIndexed ()) {
377  // If the matrix is locally indexed on the calling process, we
378  // have to use its column Map (which it _must_ have in this
379  // case) to convert to global indices.
380  local_inds_host_view_type indIn;
381  values_host_view_type valIn;
382  this->getLocalRowView (lclRow, indIn, valIn);
383  const map_type& colMap = * (this->getColMap ());
384  // Copy column indices one at a time, so that we don't need
385  // temporary storage.
386  for (size_t k = 0; k < numEnt; ++k) {
387  const GO gblIndIn = colMap.getGlobalElement (indIn[k]);
388  memcpy (indOut + k * sizeof (GO), &gblIndIn, sizeof (GO));
389  }
390  memcpy (valOut, valIn.data (), numEnt * sizeof (Scalar));
391  }
392  else if (this->isGloballyIndexed ()) {
393  // If the matrix is globally indexed on the calling process,
394  // then we can use the column indices directly. However, we
395  // have to get the global row index. The calling process must
396  // have a row Map, since otherwise it shouldn't be participating
397  // in packing operations.
398  global_inds_host_view_type indIn;
399  values_host_view_type valIn;
400  const map_type& rowMap = * (this->getRowMap ());
401  const GO gblRow = rowMap.getGlobalElement (lclRow);
402  this->getGlobalRowView (gblRow, indIn, valIn);
403  memcpy (indOut, indIn.data (), numEnt * sizeof (GO));
404  memcpy (valOut, valIn.data (), numEnt * sizeof (Scalar));
405  }
406  else {
407  if (numEnt != 0) {
408  return false;
409  }
410  }
411  }
412  else {
413  // FIXME (mfh 25 Jan 2015) Pass in valIn and indIn as scratch
414  // space, instead of allocating them on each call.
415  if (this->isLocallyIndexed ()) {
416  nonconst_local_inds_host_view_type indIn("indIn",numEnt);
417  nonconst_values_host_view_type valIn("valIn",numEnt);
418  size_t theNumEnt = 0;
419  this->getLocalRowCopy (lclRow, indIn, valIn, theNumEnt);
420  if (theNumEnt != numEnt) {
421  return false;
422  }
423  const map_type& colMap = * (this->getColMap ());
424  // Copy column indices one at a time, so that we don't need
425  // temporary storage.
426  for (size_t k = 0; k < numEnt; ++k) {
427  const GO gblIndIn = colMap.getGlobalElement (indIn[k]);
428  memcpy (indOut + k * sizeof (GO), &gblIndIn, sizeof (GO));
429  }
430  memcpy (valOut, valIn.data(), numEnt * sizeof (Scalar));
431  }
432  else if (this->isGloballyIndexed ()) {
433  nonconst_global_inds_host_view_type indIn("indIn",numEnt);
434  nonconst_values_host_view_type valIn("valIn",numEnt);
435  const map_type& rowMap = * (this->getRowMap ());
436  const GO gblRow = rowMap.getGlobalElement (lclRow);
437  size_t theNumEnt = 0;
438  this->getGlobalRowCopy (gblRow, indIn, valIn, theNumEnt);
439  if (theNumEnt != numEnt) {
440  return false;
441  }
442  memcpy (indOut, indIn.data(), numEnt * sizeof (GO));
443  memcpy (valOut, valIn.data(), numEnt * sizeof (Scalar));
444  }
445  else {
446  if (numEnt != 0) {
447  return false;
448  }
449  }
450  }
451  return true;
452  }
453 
454  template <class Scalar, class LocalOrdinal, class GlobalOrdinal, class Node>
455  void
456  RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
457  packImpl (const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
458  Teuchos::Array<char>& exports,
459  const Teuchos::ArrayView<size_t>& numPacketsPerLID,
460  size_t& constantNumPackets) const
461  {
462  using Teuchos::Array;
463  using Teuchos::ArrayView;
464  using Teuchos::as;
465  using Teuchos::av_reinterpret_cast;
466  using Teuchos::RCP;
467  typedef LocalOrdinal LO;
468  typedef GlobalOrdinal GO;
469  typedef typename ArrayView<const LO>::size_type size_type;
470  const char tfecfFuncName[] = "packImpl: ";
471 
472  const size_type numExportLIDs = exportLIDs.size ();
473  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
474  numExportLIDs != numPacketsPerLID.size (), std::invalid_argument,
475  "exportLIDs.size() = " << numExportLIDs << " != numPacketsPerLID.size()"
476  " = " << numPacketsPerLID.size () << ".");
477 
478  // Setting this to zero tells the caller to expect a possibly
479  // different ("nonconstant") number of packets per local index
480  // (i.e., a possibly different number of entries per row).
481  constantNumPackets = 0;
482 
483  // The pack buffer 'exports' enters this method possibly
484  // unallocated. Do the first two parts of "Count, allocate, fill,
485  // compute."
486  size_t totalNumEntries = 0;
487  allocatePackSpace (exports, totalNumEntries, exportLIDs);
488  const size_t bufSize = static_cast<size_t> (exports.size ());
489 
490  // Compute the number of "packets" (in this case, bytes) per
491  // export LID (in this case, local index of the row to send), and
492  // actually pack the data.
493  //
494  // FIXME (mfh 24 Feb 2013, 25 Jan 2015) This code is only correct
495  // if sizeof(Scalar) is a meaningful representation of the amount
496  // of data in a Scalar instance. (LO and GO are always built-in
497  // integer types.)
498 
499  // Variables for error reporting in the loop.
500  size_type firstBadIndex = 0; // only valid if outOfBounds == true.
501  size_t firstBadOffset = 0; // only valid if outOfBounds == true.
502  size_t firstBadNumBytes = 0; // only valid if outOfBounds == true.
503  bool outOfBounds = false;
504  bool packErr = false;
505 
506  char* const exportsRawPtr = exports.getRawPtr ();
507  size_t offset = 0; // current index into 'exports' array.
508  for (size_type i = 0; i < numExportLIDs; ++i) {
509  const LO lclRow = exportLIDs[i];
510  const size_t numEnt = this->getNumEntriesInLocalRow (lclRow);
511 
512  // Only pad this row if it has a nonzero number of entries.
513  if (numEnt == 0) {
514  numPacketsPerLID[i] = 0;
515  }
516  else {
517  char* const numEntBeg = exportsRawPtr + offset;
518  char* const numEntEnd = numEntBeg + sizeof (LO);
519  char* const valBeg = numEntEnd;
520  char* const valEnd = valBeg + numEnt * sizeof (Scalar);
521  char* const indBeg = valEnd;
522  const size_t numBytes = sizeof (LO) +
523  numEnt * (sizeof (Scalar) + sizeof (GO));
524  if (offset > bufSize || offset + numBytes > bufSize) {
525  firstBadIndex = i;
526  firstBadOffset = offset;
527  firstBadNumBytes = numBytes;
528  outOfBounds = true;
529  break;
530  }
531  packErr = ! packRow (numEntBeg, valBeg, indBeg, numEnt, lclRow);
532  if (packErr) {
533  firstBadIndex = i;
534  firstBadOffset = offset;
535  firstBadNumBytes = numBytes;
536  break;
537  }
538  // numPacketsPerLID[i] is the number of "packets" in the
539  // current local row i. Packet=char (really "byte") so use
540  // the number of bytes of the packed data for that row.
541  numPacketsPerLID[i] = numBytes;
542  offset += numBytes;
543  }
544  }
545 
546  // The point of these exceptions is to stop computation if the
547  // above checks found a bug. If HAVE_TPETRA_DEBUG is defined,
548  // Tpetra will do extra all-reduces to check for global
549  // consistency of the error state. Otherwise, throwing an
550  // exception here might cause deadlock, but we accept that as
551  // better than just continuing.
552  TEUCHOS_TEST_FOR_EXCEPTION(
553  outOfBounds, std::logic_error, "First invalid offset into 'exports' "
554  "pack buffer at index i = " << firstBadIndex << ". exportLIDs[i]: "
555  << exportLIDs[firstBadIndex] << ", bufSize: " << bufSize << ", offset: "
556  << firstBadOffset << ", numBytes: " << firstBadNumBytes << ".");
557  TEUCHOS_TEST_FOR_EXCEPTION(
558  packErr, std::logic_error, "First error in packRow() at index i = "
559  << firstBadIndex << ". exportLIDs[i]: " << exportLIDs[firstBadIndex]
560  << ", bufSize: " << bufSize << ", offset: " << firstBadOffset
561  << ", numBytes: " << firstBadNumBytes << ".");
562  }
563 
564 
565 } // namespace Tpetra
566 
567 //
568 // Explicit instantiation macro
569 //
570 // Must be expanded from within the Tpetra namespace!
571 //
572 
573 #define TPETRA_ROWMATRIX_INSTANT(SCALAR,LO,GO,NODE) \
574  template class RowMatrix< SCALAR , LO , GO , NODE >;
575 
576 
577 #endif // TPETRA_ROWMATRIX_DEF_HPP
578 
KOKKOS_INLINE_FUNCTION bool outOfBounds(const IntegerType x, const IntegerType exclusiveUpperBound)
Is x out of bounds? That is, is x less than zero, or greater than or equal to the given exclusive upp...
Sparse matrix that presents a row-oriented interface that lets users read or modify entries...
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 Map< LocalOrdinal, GlobalOrdinal, Node > > getRangeMap() const =0
The Map associated with the range of this operator, which must be compatible with Y...
virtual ~RowMatrix()
Destructor (virtual for memory safety of derived classes).
virtual void getGlobalRowCopy(GlobalOrdinal GlobalRow, nonconst_global_inds_host_view_type &Indices, nonconst_values_host_view_type &Values, size_t &NumEntries) const =0
Get a copy of the given global row&#39;s entries.
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getDomainMap() const =0
The Map associated with the domain of this operator, which must be compatible with X...
virtual void pack(const Teuchos::ArrayView< const LocalOrdinal > &exportLIDs, Teuchos::Array< char > &exports, const Teuchos::ArrayView< size_t > &numPacketsPerLID, size_t &constantNumPackets) const
Pack this object&#39;s data for an Import or Export.
virtual Teuchos::RCP< RowMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > > add(const Scalar &alpha, const RowMatrix< Scalar, LocalOrdinal, GlobalOrdinal, Node > &A, const Scalar &beta, const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &domainMap=Teuchos::null, const Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > &rangeMap=Teuchos::null, const Teuchos::RCP< Teuchos::ParameterList > &params=Teuchos::null) const
Return a new RowMatrix which is the result of beta*this + alpha*A.
A parallel distribution of indices over processes.
A read-only, row-oriented interface to a sparse matrix.
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getRowMap() const =0
The Map that describes the distribution of rows over processes.