10 #ifndef TPETRA_ROWMATRIX_DEF_HPP
11 #define TPETRA_ROWMATRIX_DEF_HPP
13 #include "Tpetra_CrsMatrix.hpp"
14 #include "Tpetra_Map.hpp"
15 #include "Tpetra_RowGraph.hpp"
19 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
22 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
23 Teuchos::RCP<RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> >
25 add(
const Scalar& alpha,
30 const Teuchos::RCP<Teuchos::ParameterList>& params)
const {
32 using Teuchos::ArrayView;
33 using Teuchos::ParameterList;
36 using Teuchos::rcp_implicit_cast;
37 using Teuchos::sublist;
38 typedef LocalOrdinal LO;
39 typedef GlobalOrdinal GO;
40 typedef Teuchos::ScalarTraits<Scalar> STS;
45 const this_type& B = *
this;
53 RCP<const map_type> B_domainMap = B.getDomainMap();
54 RCP<const map_type> B_rangeMap = B.getRangeMap();
56 RCP<const map_type> theDomainMap = domainMap;
57 RCP<const map_type> theRangeMap = rangeMap;
59 if (domainMap.is_null()) {
60 if (B_domainMap.is_null()) {
61 TEUCHOS_TEST_FOR_EXCEPTION(
62 A_domainMap.is_null(), std::invalid_argument,
63 "Tpetra::RowMatrix::add: If neither A nor B have a domain Map, "
64 "then you must supply a nonnull domain Map to this method.");
65 theDomainMap = A_domainMap;
67 theDomainMap = B_domainMap;
70 if (rangeMap.is_null()) {
71 if (B_rangeMap.is_null()) {
72 TEUCHOS_TEST_FOR_EXCEPTION(
73 A_rangeMap.is_null(), std::invalid_argument,
74 "Tpetra::RowMatrix::add: If neither A nor B have a range Map, "
75 "then you must supply a nonnull range Map to this method.");
76 theRangeMap = A_rangeMap;
78 theRangeMap = B_rangeMap;
82 #ifdef HAVE_TPETRA_DEBUG
86 if (!A_domainMap.is_null() && !A_rangeMap.is_null()) {
87 if (!B_domainMap.is_null() && !B_rangeMap.is_null()) {
88 TEUCHOS_TEST_FOR_EXCEPTION(
89 !B_domainMap->isSameAs(*A_domainMap), std::invalid_argument,
90 "Tpetra::RowMatrix::add: The input RowMatrix A must have a domain Map "
91 "which is the same as (isSameAs) this RowMatrix's domain Map.");
92 TEUCHOS_TEST_FOR_EXCEPTION(
93 !B_rangeMap->isSameAs(*A_rangeMap), std::invalid_argument,
94 "Tpetra::RowMatrix::add: The input RowMatrix A must have a range Map "
95 "which is the same as (isSameAs) this RowMatrix's range Map.");
96 TEUCHOS_TEST_FOR_EXCEPTION(
97 !domainMap.is_null() && !domainMap->isSameAs(*B_domainMap),
98 std::invalid_argument,
99 "Tpetra::RowMatrix::add: The input domain Map must be the same as "
100 "(isSameAs) this RowMatrix's domain Map.");
101 TEUCHOS_TEST_FOR_EXCEPTION(
102 !rangeMap.is_null() && !rangeMap->isSameAs(*B_rangeMap),
103 std::invalid_argument,
104 "Tpetra::RowMatrix::add: The input range Map must be the same as "
105 "(isSameAs) this RowMatrix's range Map.");
107 }
else if (!B_domainMap.is_null() && !B_rangeMap.is_null()) {
108 TEUCHOS_TEST_FOR_EXCEPTION(
109 !domainMap.is_null() && !domainMap->isSameAs(*B_domainMap),
110 std::invalid_argument,
111 "Tpetra::RowMatrix::add: The input domain Map must be the same as "
112 "(isSameAs) this RowMatrix's domain Map.");
113 TEUCHOS_TEST_FOR_EXCEPTION(
114 !rangeMap.is_null() && !rangeMap->isSameAs(*B_rangeMap),
115 std::invalid_argument,
116 "Tpetra::RowMatrix::add: The input range Map must be the same as "
117 "(isSameAs) this RowMatrix's range Map.");
119 TEUCHOS_TEST_FOR_EXCEPTION(
120 domainMap.is_null() || rangeMap.is_null(), std::invalid_argument,
121 "Tpetra::RowMatrix::add: If neither A nor B have a domain and range "
122 "Map, then you must supply a nonnull domain and range Map to this "
125 #endif // HAVE_TPETRA_DEBUG
130 bool callFillComplete =
true;
131 RCP<ParameterList> constructorSublist;
132 RCP<ParameterList> fillCompleteSublist;
133 if (!params.is_null()) {
134 callFillComplete = params->get(
"Call fillComplete", callFillComplete);
135 constructorSublist = sublist(params,
"Constructor parameters");
136 fillCompleteSublist = sublist(params,
"fillComplete parameters");
139 RCP<const map_type> A_rowMap = A.
getRowMap();
140 RCP<const map_type> B_rowMap = B.getRowMap();
141 RCP<const map_type> C_rowMap = B_rowMap;
142 RCP<crs_matrix_type> C;
149 if (A_rowMap->isSameAs(*B_rowMap)) {
150 const LO localNumRows =
static_cast<LO
>(A_rowMap->getLocalNumElements());
151 Array<size_t> C_maxNumEntriesPerRow(localNumRows, 0);
154 if (alpha != STS::zero()) {
155 for (LO localRow = 0; localRow < localNumRows; ++localRow) {
157 C_maxNumEntriesPerRow[localRow] += A_numEntries;
161 if (beta != STS::zero()) {
162 for (LO localRow = 0; localRow < localNumRows; ++localRow) {
163 const size_t B_numEntries = B.getNumEntriesInLocalRow(localRow);
164 C_maxNumEntriesPerRow[localRow] += B_numEntries;
168 if (constructorSublist.is_null()) {
169 C = rcp(
new crs_matrix_type(C_rowMap, C_maxNumEntriesPerRow()));
171 C = rcp(
new crs_matrix_type(C_rowMap, C_maxNumEntriesPerRow(),
172 constructorSublist));
182 TEUCHOS_TEST_FOR_EXCEPTION(
true,
183 std::invalid_argument,
184 "Tpetra::RowMatrix::add: The row maps must be the same for statically "
185 "allocated matrices in order to be sure that there is sufficient space "
186 "to do the addition");
189 #ifdef HAVE_TPETRA_DEBUG
190 TEUCHOS_TEST_FOR_EXCEPTION(C.is_null(), std::logic_error,
191 "Tpetra::RowMatrix::add: C should not be null at this point. "
192 "Please report this bug to the Tpetra developers.");
193 #endif // HAVE_TPETRA_DEBUG
197 using gids_type = nonconst_global_inds_host_view_type;
198 using vals_type = nonconst_values_host_view_type;
202 if (alpha != STS::zero()) {
203 const LO A_localNumRows =
static_cast<LO
>(A_rowMap->getLocalNumElements());
204 for (LO localRow = 0; localRow < A_localNumRows; ++localRow) {
206 const GO globalRow = A_rowMap->getGlobalElement(localRow);
207 if (A_numEntries > static_cast<size_t>(ind.size())) {
208 Kokkos::resize(ind, A_numEntries);
209 Kokkos::resize(val, A_numEntries);
211 gids_type indView = Kokkos::subview(ind, std::make_pair((
size_t)0, A_numEntries));
212 vals_type valView = Kokkos::subview(val, std::make_pair((
size_t)0, A_numEntries));
215 if (alpha != STS::one()) {
216 for (
size_t k = 0; k < A_numEntries; ++k) {
220 C->insertGlobalValues(globalRow, A_numEntries,
221 reinterpret_cast<const Scalar*>(valView.data()),
226 if (beta != STS::zero()) {
227 const LO B_localNumRows =
static_cast<LO
>(B_rowMap->getLocalNumElements());
228 for (LO localRow = 0; localRow < B_localNumRows; ++localRow) {
229 size_t B_numEntries = B.getNumEntriesInLocalRow(localRow);
230 const GO globalRow = B_rowMap->getGlobalElement(localRow);
231 if (B_numEntries > static_cast<size_t>(ind.size())) {
232 Kokkos::resize(ind, B_numEntries);
233 Kokkos::resize(val, B_numEntries);
235 gids_type indView = Kokkos::subview(ind, std::make_pair((
size_t)0, B_numEntries));
236 vals_type valView = Kokkos::subview(val, std::make_pair((
size_t)0, B_numEntries));
237 B.getGlobalRowCopy(globalRow, indView, valView, B_numEntries);
239 if (beta != STS::one()) {
240 for (
size_t k = 0; k < B_numEntries; ++k) {
244 C->insertGlobalValues(globalRow, B_numEntries,
245 reinterpret_cast<const Scalar*>(valView.data()),
250 if (callFillComplete) {
251 if (fillCompleteSublist.is_null()) {
252 C->fillComplete(theDomainMap, theRangeMap);
254 C->fillComplete(theDomainMap, theRangeMap, fillCompleteSublist);
258 return rcp_implicit_cast<this_type>(C);
261 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
263 pack(
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
264 Teuchos::Array<char>& exports,
265 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
266 size_t& constantNumPackets)
const {
267 #ifdef HAVE_TPETRA_DEBUG
268 const char tfecfFuncName[] =
"pack: ";
270 using Teuchos::reduceAll;
271 std::ostringstream msg;
274 this->packImpl(exportLIDs, exports, numPacketsPerLID,
276 }
catch (std::exception& e) {
281 const Teuchos::Comm<int>& comm = *(this->getComm());
282 reduceAll<int, int>(comm, Teuchos::REDUCE_MAX,
283 lclBad, Teuchos::outArg(gblBad));
285 const int myRank = comm.getRank();
286 const int numProcs = comm.getSize();
287 for (
int r = 0; r < numProcs; ++r) {
288 if (r == myRank && lclBad != 0) {
289 std::ostringstream os;
290 os <<
"Proc " << myRank <<
": " << msg.str() << std::endl;
291 std::cerr << os.str();
297 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
298 true, std::logic_error,
299 "packImpl() threw an exception on one or "
300 "more participating processes.");
304 this->packImpl(exportLIDs, exports, numPacketsPerLID,
306 #endif // HAVE_TPETRA_DEBUG
309 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
312 size_t& totalNumEntries,
313 const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs)
const {
314 typedef LocalOrdinal LO;
315 typedef GlobalOrdinal GO;
316 typedef typename Teuchos::ArrayView<const LO>::size_type size_type;
318 const size_type numExportLIDs = exportLIDs.size();
322 for (size_type i = 0; i < numExportLIDs; ++i) {
323 const LO lclRow = exportLIDs[i];
324 size_t curNumEntries = this->getNumEntriesInLocalRow(lclRow);
327 if (curNumEntries == Teuchos::OrdinalTraits<size_t>::invalid()) {
330 totalNumEntries += curNumEntries;
341 const size_t allocSize =
342 static_cast<size_t>(numExportLIDs) *
sizeof(LO) +
343 totalNumEntries * (
sizeof(Scalar) +
sizeof(GO));
344 if (static_cast<size_t>(exports.size()) < allocSize) {
345 exports.resize(allocSize);
349 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
350 bool RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
351 packRow(
char*
const numEntOut,
355 const LocalOrdinal lclRow)
const {
356 using Teuchos::Array;
357 using Teuchos::ArrayView;
358 typedef LocalOrdinal LO;
359 typedef GlobalOrdinal GO;
362 const LO numEntLO =
static_cast<LO
>(numEnt);
363 memcpy(numEntOut, &numEntLO,
sizeof(LO));
365 if (this->supportsRowViews()) {
366 if (this->isLocallyIndexed()) {
370 local_inds_host_view_type indIn;
371 values_host_view_type valIn;
372 this->getLocalRowView(lclRow, indIn, valIn);
373 const map_type& colMap = *(this->getColMap());
376 for (
size_t k = 0; k < numEnt; ++k) {
377 const GO gblIndIn = colMap.getGlobalElement(indIn[k]);
378 memcpy(indOut + k *
sizeof(GO), &gblIndIn,
sizeof(GO));
380 memcpy(valOut, valIn.data(), numEnt *
sizeof(Scalar));
381 }
else if (this->isGloballyIndexed()) {
387 global_inds_host_view_type indIn;
388 values_host_view_type valIn;
389 const map_type& rowMap = *(this->getRowMap());
390 const GO gblRow = rowMap.getGlobalElement(lclRow);
391 this->getGlobalRowView(gblRow, indIn, valIn);
392 memcpy(indOut, indIn.data(), numEnt *
sizeof(GO));
393 memcpy(valOut, valIn.data(), numEnt *
sizeof(Scalar));
402 if (this->isLocallyIndexed()) {
403 nonconst_local_inds_host_view_type indIn(
"indIn", numEnt);
404 nonconst_values_host_view_type valIn(
"valIn", numEnt);
405 size_t theNumEnt = 0;
406 this->getLocalRowCopy(lclRow, indIn, valIn, theNumEnt);
407 if (theNumEnt != numEnt) {
410 const map_type& colMap = *(this->getColMap());
413 for (
size_t k = 0; k < numEnt; ++k) {
414 const GO gblIndIn = colMap.getGlobalElement(indIn[k]);
415 memcpy(indOut + k *
sizeof(GO), &gblIndIn,
sizeof(GO));
417 memcpy(valOut, valIn.data(), numEnt *
sizeof(Scalar));
418 }
else if (this->isGloballyIndexed()) {
419 nonconst_global_inds_host_view_type indIn(
"indIn", numEnt);
420 nonconst_values_host_view_type valIn(
"valIn", numEnt);
421 const map_type& rowMap = *(this->getRowMap());
422 const GO gblRow = rowMap.getGlobalElement(lclRow);
423 size_t theNumEnt = 0;
424 this->getGlobalRowCopy(gblRow, indIn, valIn, theNumEnt);
425 if (theNumEnt != numEnt) {
428 memcpy(indOut, indIn.data(), numEnt *
sizeof(GO));
429 memcpy(valOut, valIn.data(), numEnt *
sizeof(Scalar));
439 template <
class Scalar,
class LocalOrdinal,
class GlobalOrdinal,
class Node>
440 void RowMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::
441 packImpl(
const Teuchos::ArrayView<const LocalOrdinal>& exportLIDs,
442 Teuchos::Array<char>& exports,
443 const Teuchos::ArrayView<size_t>& numPacketsPerLID,
444 size_t& constantNumPackets)
const {
445 using Teuchos::Array;
446 using Teuchos::ArrayView;
448 using Teuchos::av_reinterpret_cast;
450 typedef LocalOrdinal LO;
451 typedef GlobalOrdinal GO;
452 typedef typename ArrayView<const LO>::size_type size_type;
453 const char tfecfFuncName[] =
"packImpl: ";
455 const size_type numExportLIDs = exportLIDs.size();
456 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(
457 numExportLIDs != numPacketsPerLID.size(), std::invalid_argument,
458 "exportLIDs.size() = " << numExportLIDs <<
" != numPacketsPerLID.size()"
460 << numPacketsPerLID.size() <<
".");
465 constantNumPackets = 0;
470 size_t totalNumEntries = 0;
471 allocatePackSpace(exports, totalNumEntries, exportLIDs);
472 const size_t bufSize =
static_cast<size_t>(exports.size());
484 size_type firstBadIndex = 0;
485 size_t firstBadOffset = 0;
486 size_t firstBadNumBytes = 0;
488 bool packErr =
false;
490 char*
const exportsRawPtr = exports.getRawPtr();
492 for (size_type i = 0; i < numExportLIDs; ++i) {
493 const LO lclRow = exportLIDs[i];
494 const size_t numEnt = this->getNumEntriesInLocalRow(lclRow);
498 numPacketsPerLID[i] = 0;
500 char*
const numEntBeg = exportsRawPtr + offset;
501 char*
const numEntEnd = numEntBeg +
sizeof(LO);
502 char*
const valBeg = numEntEnd;
503 char*
const valEnd = valBeg + numEnt *
sizeof(Scalar);
504 char*
const indBeg = valEnd;
505 const size_t numBytes =
sizeof(LO) +
506 numEnt * (
sizeof(Scalar) +
sizeof(GO));
507 if (offset > bufSize || offset + numBytes > bufSize) {
509 firstBadOffset = offset;
510 firstBadNumBytes = numBytes;
514 packErr = !packRow(numEntBeg, valBeg, indBeg, numEnt, lclRow);
517 firstBadOffset = offset;
518 firstBadNumBytes = numBytes;
524 numPacketsPerLID[i] = numBytes;
535 TEUCHOS_TEST_FOR_EXCEPTION(
536 outOfBounds, std::logic_error,
537 "First invalid offset into 'exports' "
538 "pack buffer at index i = "
539 << firstBadIndex <<
". exportLIDs[i]: "
540 << exportLIDs[firstBadIndex] <<
", bufSize: " << bufSize <<
", offset: "
541 << firstBadOffset <<
", numBytes: " << firstBadNumBytes <<
".");
542 TEUCHOS_TEST_FOR_EXCEPTION(
543 packErr, std::logic_error,
"First error in packRow() at index i = " << firstBadIndex <<
". exportLIDs[i]: " << exportLIDs[firstBadIndex] <<
", bufSize: " << bufSize <<
", offset: " << firstBadOffset <<
", numBytes: " << firstBadNumBytes <<
".");
554 #define TPETRA_ROWMATRIX_INSTANT(SCALAR, LO, GO, NODE) \
555 template class RowMatrix<SCALAR, LO, GO, NODE>;
557 #endif // TPETRA_ROWMATRIX_DEF_HPP
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...
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 ~RowMatrix()
Destructor (virtual for memory safety of derived classes).
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 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's entries.
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's data for an Import or Export.
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getRowMap() const =0
The Map that describes the distribution of rows over processes.
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 > ¶ms=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.