125 "Map, then you must supply a nonnull domain and range Map to this "
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");
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;
145 RCP<crs_matrix_type> C;
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);
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;
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;
171 if (constructorSublist.is_null ()) {
172 C = rcp (
new crs_matrix_type (C_rowMap, C_maxNumEntriesPerRow ()));
174 C = rcp (
new crs_matrix_type (C_rowMap, C_maxNumEntriesPerRow (),
175 constructorSublist));
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");
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.");
201 using gids_type = nonconst_global_inds_host_view_type;
202 using vals_type = nonconst_values_host_view_type;
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);
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);
219 if (alpha != STS::one ()) {
220 for (
size_t k = 0; k < A_numEntries; ++k) {
224 C->insertGlobalValues (globalRow, A_numEntries,
225 reinterpret_cast<const Scalar*
>(valView.data()),
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);
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);
243 if (beta != STS::one ()) {
244 for (
size_t k = 0; k < B_numEntries; ++k) {
248 C->insertGlobalValues (globalRow, B_numEntries,
249 reinterpret_cast<const Scalar*
>(valView.data()),
254 if (callFillComplete) {
255 if (fillCompleteSublist.is_null ()) {
256 C->fillComplete (theDomainMap, theRangeMap);
258 C->fillComplete (theDomainMap, theRangeMap, fillCompleteSublist);
262 return rcp_implicit_cast<this_type> (C);
266 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
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
274#ifdef HAVE_TPETRA_DEBUG
275 const char tfecfFuncName[] =
"pack: ";
277 using Teuchos::reduceAll;
278 std::ostringstream msg;
281 this->packImpl (exportLIDs, exports, numPacketsPerLID,
283 }
catch (std::exception& e) {
288 const Teuchos::Comm<int>& comm = * (this->
getComm ());
289 reduceAll<int, int> (comm, Teuchos::REDUCE_MAX,
290 lclBad, Teuchos::outArg (gblBad));
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 ();
304 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
305 true, std::logic_error,
"packImpl() threw an exception on one or "
306 "more participating processes.");
310 this->packImpl (exportLIDs, exports, numPacketsPerLID,
315 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
319 size_t& totalNumEntries,
320 const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs)
const
322 typedef LocalOrdinal LO;
323 typedef GlobalOrdinal GO;
324 typedef typename Teuchos::ArrayView<const LO>::size_type size_type;
326 const size_type numExportLIDs = exportLIDs.size ();
330 for (size_type i = 0; i < numExportLIDs; ++i) {
331 const LO lclRow = exportLIDs[i];
332 size_t curNumEntries = this->getNumEntriesInLocalRow (lclRow);
335 if (curNumEntries == Teuchos::OrdinalTraits<size_t>::invalid ()) {
338 totalNumEntries += curNumEntries;
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);
357 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
360 packRow (
char*
const numEntOut,
364 const LocalOrdinal lclRow)
const
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;
372 const LO numEntLO =
static_cast<LO
> (numEnt);
373 memcpy (numEntOut, &numEntLO,
sizeof (LO));
375 if (this->supportsRowViews ()) {
376 if (this->isLocallyIndexed ()) {
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 ());
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));
390 memcpy (valOut, valIn.data (), numEnt * sizeof (Scalar));
392 else if (this->isGloballyIndexed ()) {
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));
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) {
423 const map_type& colMap = * (this->getColMap ());
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));
430 memcpy (valOut, valIn.data(), numEnt * sizeof (Scalar));
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) {
442 memcpy (indOut, indIn.data(), numEnt * sizeof (GO));
443 memcpy (valOut, valIn.data(), numEnt * sizeof (Scalar));
454 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class 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
462 using Teuchos::Array;
463 using Teuchos::ArrayView;
465 using Teuchos::av_reinterpret_cast;
467 typedef LocalOrdinal LO;
468 typedef GlobalOrdinal GO;
469 typedef typename ArrayView<const LO>::size_type size_type;
470 const char tfecfFuncName[] =
"packImpl: ";
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 () <<
".");
481 constantNumPackets = 0;
486 size_t totalNumEntries = 0;
487 allocatePackSpace (exports, totalNumEntries, exportLIDs);
488 const size_t bufSize =
static_cast<size_t> (exports.size ());
500 size_type firstBadIndex = 0;
501 size_t firstBadOffset = 0;
502 size_t firstBadNumBytes = 0;
503 bool outOfBounds =
false;
504 bool packErr =
false;
506 char*
const exportsRawPtr = exports.getRawPtr ();
508 for (size_type i = 0; i < numExportLIDs; ++i) {
509 const LO lclRow = exportLIDs[i];
514 numPacketsPerLID[i] = 0;
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) {
526 firstBadOffset = offset;
527 firstBadNumBytes = numBytes;
531 packErr = ! packRow (numEntBeg, valBeg, indBeg, numEnt, lclRow);
534 firstBadOffset = offset;
535 firstBadNumBytes = numBytes;
541 numPacketsPerLID[i] = numBytes;
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 <<
".");
573#define TPETRA_ROWMATRIX_INSTANT(SCALAR,LO,GO,NODE) \
574 template class RowMatrix< SCALAR , LO , GO , NODE >;