42 #ifndef TPETRA_DETAILS_COOMATRIX_HPP
43 #define TPETRA_DETAILS_COOMATRIX_HPP
50 #include "TpetraCore_config.h"
51 #include "Tpetra_Details_PackTriples.hpp"
52 #include "Tpetra_DistObject.hpp"
53 #include "Tpetra_Details_gathervPrint.hpp"
55 #include "Teuchos_TypeNameTraits.hpp"
57 #include <initializer_list>
61 #include <type_traits>
74 template<
class IndexType>
84 template<
class IndexType>
90 return (x.row < y.row) || (x.row == y.row && x.col < y.col);
96 template<
class SC,
class GO>
106 typedef std::map<CooGraphEntry<GO>, SC,
111 entries_type entries_;
135 auto result = this->entries_.insert ({ij, val});
136 if (! result.second) {
137 result.first->second += val;
151 const GO gblColInds[],
153 const std::size_t numEnt)
155 for (std::size_t k = 0; k < numEnt; ++k) {
160 const SC val = vals[k];
161 auto result = this->entries_.insert ({ij, val});
162 if (! result.second) {
163 result.first->second += val;
172 return this->entries_.size ();
181 for (
auto iter = this->entries_.begin ();
182 iter != this->entries_.end (); ++iter) {
183 f (iter->first.row, iter->first.col, iter->second);
200 entries_type& tgtEntries = this->entries_;
201 const entries_type& srcEntries = src.entries_;
207 auto srcBeg = srcEntries.lower_bound ({srcGblRow, std::numeric_limits<GO>::min ()});
208 auto srcEnd = srcEntries.upper_bound ({srcGblRow+1, std::numeric_limits<GO>::min ()});
209 auto tgtBeg = tgtEntries.lower_bound ({tgtGblRow, std::numeric_limits<GO>::min ()});
210 auto tgtEnd = tgtEntries.upper_bound ({tgtGblRow+1, std::numeric_limits<GO>::min ()});
214 if (srcBeg != srcEnd) {
215 for (
auto tgtCur = tgtBeg; tgtCur != tgtEnd; ++tgtCur) {
216 auto srcCur = srcBeg;
217 while (srcCur != srcEnd && srcCur->first.col < tgtCur->first.col) {
229 if (srcCur != srcEnd) {
230 if (srcCur->first.col == tgtCur->first.col) {
231 tgtCur->second += srcCur->second;
238 (void) tgtEntries.insert (tgtCur, *srcCur);
257 const ::Teuchos::Comm<int>& comm,
258 std::ostream* errStrm = NULL)
const
260 using ::Tpetra::Details::countPackTriples;
261 using ::Tpetra::Details::countPackTriplesCount;
263 const char prefix[] =
"Tpetra::Details::Impl::CooMatrixImpl::countPackRow: ";
264 #ifdef HAVE_TPETRACORE_MPI
265 int errCode = MPI_SUCCESS;
268 #endif // HAVE_TPETRACORE_MPI
271 const GO minGO = std::numeric_limits<GO>::min ();
272 auto beg = this->entries_.lower_bound ({gblRow, minGO});
273 auto end = this->entries_.upper_bound ({gblRow+1, minGO});
275 for (
auto iter = beg; iter != end; ++iter) {
277 if (numEnt == std::numeric_limits<int>::max ()) {
278 if (errStrm != NULL) {
279 *errStrm << prefix <<
"In (global) row " << gblRow <<
", the number "
280 "of entries thus far, numEnt = " << numEnt <<
", has reached the "
281 "maximum int value. We need to store this count as int for MPI's "
288 int numPacketsForCount = 0;
293 if (errStrm != NULL) {
294 *errStrm << prefix <<
"countPackTriplesCount "
295 "returned errCode = " << errCode <<
" != 0." << endl;
299 if (numPacketsForCount < 0) {
300 if (errStrm != NULL) {
301 *errStrm << prefix <<
"countPackTriplesCount returned "
302 "numPacketsForCount = " << numPacketsForCount <<
" < 0." << endl;
308 int numPacketsForTriples = 0;
310 errCode = countPackTriples<SC, GO> (numEnt, comm, numPacketsForTriples);
311 TEUCHOS_TEST_FOR_EXCEPTION
312 (errCode != 0, std::runtime_error, prefix <<
"countPackTriples "
313 "returned errCode = " << errCode <<
" != 0.");
314 TEUCHOS_TEST_FOR_EXCEPTION
315 (numPacketsForTriples < 0, std::logic_error, prefix <<
"countPackTriples "
316 "returned numPacketsForTriples = " << numPacketsForTriples <<
" < 0.");
319 numPackets = numPacketsForCount + numPacketsForTriples;
339 const int outBufSize,
341 const ::Teuchos::Comm<int>& comm,
342 std::vector<GO>& gblRowInds,
343 std::vector<GO>& gblColInds,
344 std::vector<SC>& vals,
345 const GO gblRow)
const
347 using ::Tpetra::Details::packTriples;
348 using ::Tpetra::Details::packTriplesCount;
349 const char prefix[] =
"Tpetra::Details::Impl::CooMatrixImpl::packRow: ";
351 const GO minGO = std::numeric_limits<GO>::min ();
352 auto beg = this->entries_.lower_bound ({gblRow, minGO});
353 auto end = this->entries_.upper_bound ({gblRow+1, minGO});
357 gblRowInds.resize (0);
358 gblColInds.resize (0);
362 for (
auto iter = beg; iter != end; ++iter) {
363 gblRowInds.push_back (iter->first.row);
364 gblColInds.push_back (iter->first.col);
365 vals.push_back (iter->second);
367 TEUCHOS_TEST_FOR_EXCEPTION
368 (numEnt == std::numeric_limits<int>::max (), std::runtime_error, prefix
369 <<
"In (global) row " << gblRow <<
", the number of entries thus far, "
370 "numEnt = " << numEnt <<
", has reached the maximum int value. "
371 "We need to store this count as int for MPI's sake.");
377 TEUCHOS_TEST_FOR_EXCEPTION
378 (errCode != 0, std::runtime_error, prefix
379 <<
"In (global) row " << gblRow <<
", packTriplesCount returned "
380 "errCode = " << errCode <<
" != 0.");
392 TEUCHOS_TEST_FOR_EXCEPTION
393 (errCode != 0, std::runtime_error, prefix <<
"In (global) row "
394 << gblRow <<
", packTriples returned errCode = " << errCode
411 GO lclMinRowInd = std::numeric_limits<GO>::max ();
412 for (
typename entries_type::const_iterator iter = this->entries_.begin ();
413 iter != this->entries_.end (); ++iter) {
414 const GO rowInd = iter->first.row;
415 if (rowInd < lclMinRowInd) {
416 lclMinRowInd = rowInd;
418 if (rowInds.empty () || rowInds.back () != rowInd) {
419 rowInds.push_back (rowInd);
425 template<
class OffsetType>
427 buildCrs (std::vector<OffsetType>& rowOffsets,
431 static_assert (std::is_integral<OffsetType>::value,
432 "OffsetType must be a built-in integer type.");
440 rowOffsets.push_back (0);
443 typename entries_type::const_iterator iter = this->entries_.begin ();
444 GO prevGblRowInd = iter->first.row;
447 for ( ; iter != this->entries_.end (); ++iter, ++k) {
448 const GO gblRowInd = iter->first.row;
449 if (k == 0 || gblRowInd != prevGblRowInd) {
453 rowOffsets.push_back (k);
454 prevGblRowInd = gblRowInd;
456 gblColInds[k] = iter->first.col;
458 static_assert (std::is_same<
typename std::decay<decltype (iter->second)>::type, SC>::value,
459 "The type of iter->second != SC.");
460 vals[k] = iter->second;
462 rowOffsets.push_back (static_cast<OffsetType> (numEnt));
478 template<
class OffsetType,
class LO>
483 std::function<LO (
const GO)> gblToLcl)
const
485 static_assert (std::is_integral<OffsetType>::value,
486 "OffsetType must be a built-in integer type.");
487 static_assert (std::is_integral<LO>::value,
488 "LO must be a built-in integer type.");
496 rowOffsets.push_back (0);
499 typename entries_type::const_iterator iter = this->entries_.begin ();
500 GO prevGblRowInd = iter->first.row;
503 for ( ; iter != this->entries_.end (); ++iter, ++k) {
504 const GO gblRowInd = iter->first.row;
505 if (k == 0 || gblRowInd != prevGblRowInd) {
509 rowOffsets.push_back (k);
510 prevGblRowInd = gblRowInd;
512 lclColInds[k] = gblToLcl (iter->first.col);
513 vals[k] = iter->second;
515 rowOffsets.push_back (static_cast<OffsetType> (numEnt));
585 typedef ::Tpetra::Map<local_ordinal_type, global_ordinal_type, node_type>
map_type;
603 localError_ (new bool (false)),
604 errs_ (new std::shared_ptr<std::ostringstream> ())
616 localError_ (new bool (false)),
617 errs_ (new std::shared_ptr<std::ostringstream> ())
647 const GO gblColInds[],
649 const std::size_t numEnt)
657 std::initializer_list<GO> gblColInds,
658 std::initializer_list<SC> vals,
659 const std::size_t numEnt)
662 vals.begin (), numEnt);
672 template<
class OffsetType>
674 buildCrs (::Kokkos::View<OffsetType*, device_type>& rowOffsets,
675 ::Kokkos::View<GO*, device_type>& gblColInds,
676 ::Kokkos::View<typename ::Kokkos::Details::ArithTraits<SC>::val_type*, device_type>& vals)
678 static_assert (std::is_integral<OffsetType>::value,
679 "OffsetType must be a built-in integer type.");
680 using ::Kokkos::create_mirror_view;
682 using ::Kokkos::View;
683 typedef typename ::Kokkos::Details::ArithTraits<SC>::val_type ISC;
687 gblColInds = View<GO*, device_type> (
"gblColInds", numEnt);
688 vals = View<ISC*, device_type> (
"vals", numEnt);
689 auto gblColInds_h = create_mirror_view (gblColInds);
690 auto vals_h = create_mirror_view (vals);
692 std::vector<std::size_t> rowOffsetsSV;
693 this->impl_.buildCrs (rowOffsetsSV,
694 gblColInds_h.data (),
697 View<OffsetType*, device_type> (
"rowOffsets", rowOffsetsSV.size ());
698 typename View<OffsetType*, device_type>::HostMirror
699 rowOffsets_h (rowOffsetsSV.data (), rowOffsetsSV.size ());
719 if (comm.is_null ()) {
720 this->
map_ = ::Teuchos::null;
723 this->
map_ = this->buildMap (comm);
738 TEUCHOS_TEST_FOR_EXCEPTION
739 (this->
getMap ().is_null (), std::runtime_error,
"Tpetra::Details::"
740 "CooMatrix::fillComplete: This object does not yet have a Map. "
741 "You must call the version of fillComplete "
742 "that takes an input communicator.");
782 return ((*errs_).get () == NULL) ? std::string (
"") : (*errs_)->str ();
798 std::shared_ptr<bool> localError_;
807 std::shared_ptr<std::shared_ptr<std::ostringstream> > errs_;
811 markLocalErrorAndGetStream ()
813 * (this->localError_) =
true;
814 if ((*errs_).get () == NULL) {
815 *errs_ = std::shared_ptr<std::ostringstream> (
new std::ostringstream ());
824 using Teuchos::TypeNameTraits;
826 std::ostringstream os;
827 os <<
"\"Tpetra::Details::CooMatrix\": {"
828 <<
"SC: " << TypeNameTraits<SC>::name ()
829 <<
", LO: " << TypeNameTraits<LO>::name ()
830 <<
", GO: " << TypeNameTraits<GO>::name ()
831 <<
", NT: " << TypeNameTraits<NT>::name ();
832 if (this->getObjectLabel () !=
"") {
833 os <<
", Label: \"" << this->getObjectLabel () <<
"\"";
835 os <<
", Has Map: " << (this->
map_.is_null () ?
"false" :
"true")
844 const Teuchos::EVerbosityLevel verbLevel =
845 Teuchos::Describable::verbLevel_default)
const
847 using ::Tpetra::Details::gathervPrint;
848 using ::Teuchos::EVerbosityLevel;
849 using ::Teuchos::OSTab;
850 using ::Teuchos::TypeNameTraits;
851 using ::Teuchos::VERB_DEFAULT;
852 using ::Teuchos::VERB_LOW;
853 using ::Teuchos::VERB_MEDIUM;
856 const auto vl = (verbLevel == VERB_DEFAULT) ? VERB_LOW : verbLevel;
858 auto comm = this->
getMap ().is_null () ?
859 Teuchos::null : this->
getMap ()->getComm ();
860 const int myRank = comm.is_null () ? 0 : comm->getRank ();
863 if (vl != Teuchos::VERB_NONE) {
867 out <<
"\"Tpetra::Details::CooMatrix\":" << endl;
871 out <<
"Template parameters:" << endl;
874 out <<
"SC: " << TypeNameTraits<SC>::name () << endl
875 <<
"LO: " << TypeNameTraits<LO>::name () << endl
876 <<
"GO: " << TypeNameTraits<GO>::name () << endl
877 <<
"NT: " << TypeNameTraits<NT>::name () << endl;
879 if (this->getObjectLabel () !=
"") {
880 out <<
"Label: \"" << this->getObjectLabel () <<
"\"" << endl;
882 out <<
"Has Map: " << (this->
map_.is_null () ?
"false" :
"true") << endl;
886 if (! this->
map_.is_null ()) {
888 out <<
"Map:" << endl;
891 this->
map_->describe (out, vl);
896 std::ostringstream os;
897 os <<
"Process " << myRank <<
":" << endl;
901 os <<
" Local number of entries: " << numEnt << endl;
902 if (vl > VERB_MEDIUM) {
903 os <<
" Local entries:" << endl;
905 this->impl_.
forAllEntries ([&os] (
const GO row,
const GO col,
const SC& val) {
927 Teuchos::RCP<const map_type>
928 buildMap (const ::Teuchos::RCP<const ::Teuchos::Comm<int> >& comm)
930 using ::Teuchos::outArg;
931 using ::Teuchos::rcp;
932 using ::Teuchos::REDUCE_MIN;
933 using ::Teuchos::reduceAll;
934 typedef ::Tpetra::global_size_t GST;
938 if (comm.is_null ()) {
939 return ::Teuchos::null;
950 std::vector<GO> rowInds;
954 GO gblMinGblRowInd = 0;
955 reduceAll<int, GO> (*comm, REDUCE_MIN, lclMinGblRowInd,
956 outArg (gblMinGblRowInd));
957 const GO indexBase = gblMinGblRowInd;
958 const GST INV = Tpetra::Details::OrdinalTraits<GST>::invalid ();
959 return rcp (
new map_type (INV, rowInds.data (), rowInds.size (),
968 return static_cast<size_t> (0);
979 const char prefix[] =
"Tpetra::Details::CooMatrix::checkSizes: ";
981 const this_type* src = dynamic_cast<const this_type* > (&source);
984 std::ostream& err = markLocalErrorAndGetStream ();
985 err << prefix <<
"The source object of the Import or Export "
986 "must be a CooMatrix with the same template parameters as the "
987 "target object." << endl;
989 else if (this->
map_.is_null ()) {
990 std::ostream& err = markLocalErrorAndGetStream ();
991 err << prefix <<
"The target object of the Import or Export "
992 "must be a CooMatrix with a nonnull Map." << endl;
994 return ! (* (this->localError_));
1006 const size_t numSameIDs,
1007 const ::Kokkos::DualView<const LO*, device_type>& permuteToLIDs,
1008 const ::Kokkos::DualView<const LO*, device_type>& permuteFromLIDs)
1012 const char prefix[] =
"Tpetra::Details::CooMatrix::copyAndPermuteNew: ";
1017 if (* (this->localError_)) {
1018 std::ostream& err = this->markLocalErrorAndGetStream ();
1019 err << prefix <<
"The target object of the Import or Export is "
1020 "already in an error state." << endl;
1024 const this_type* src = dynamic_cast<const this_type*> (&sourceObject);
1026 std::ostream& err = this->markLocalErrorAndGetStream ();
1027 err << prefix <<
"Input argument 'sourceObject' is not a CooMatrix."
1032 const size_t numPermuteIDs =
1033 static_cast<size_t> (permuteToLIDs.extent (0));
1034 if (numPermuteIDs != static_cast<size_t> (permuteFromLIDs.extent (0))) {
1035 std::ostream& err = this->markLocalErrorAndGetStream ();
1036 err << prefix <<
"permuteToLIDs.extent(0) = "
1037 << numPermuteIDs <<
" != permuteFromLIDs.extent(0) = "
1038 << permuteFromLIDs.extent (0) <<
"." << endl;
1041 if (
sizeof (
int) <=
sizeof (
size_t) &&
1042 numPermuteIDs > static_cast<size_t> (std::numeric_limits<int>::max ())) {
1043 std::ostream& err = this->markLocalErrorAndGetStream ();
1044 err << prefix <<
"numPermuteIDs = " << numPermuteIDs
1045 <<
", a size_t, overflows int." << endl;
1055 if (
sizeof (
int) <=
sizeof (
size_t) &&
1056 numSameIDs > static_cast<size_t> (std::numeric_limits<int>::max ())) {
1057 std::ostream& err = this->markLocalErrorAndGetStream ();
1058 err << prefix <<
"numSameIDs = " << numSameIDs
1059 <<
", a size_t, overflows int." << endl;
1066 const LO numSame = static_cast<int> (numSameIDs);
1071 LO numInvalidSameRows = 0;
1072 for (LO lclRow = 0; lclRow < numSame; ++lclRow) {
1076 const GO gblRow = this->
map_->getGlobalElement (lclRow);
1077 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1078 ++numInvalidSameRows;
1091 const LO numPermute = static_cast<int> (numPermuteIDs);
1096 LO numInvalidRowsFrom = 0;
1101 LO numInvalidRowsTo = 0;
1102 for (LO k = 0; k < numPermute; ++k) {
1103 const LO lclRowFrom = permuteFromLIDs.h_view(k);
1104 const LO lclRowTo = permuteToLIDs.h_view(k);
1105 const GO gblRowFrom = src->
map_->getGlobalElement (lclRowFrom);
1106 const GO gblRowTo = this->
map_->getGlobalElement (lclRowTo);
1108 bool bothConversionsValid =
true;
1109 if (gblRowFrom == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1110 ++numInvalidRowsFrom;
1111 bothConversionsValid =
false;
1113 if (gblRowTo == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1115 bothConversionsValid =
false;
1117 if (bothConversionsValid) {
1118 this->impl_.
mergeIntoRow (gblRowTo, src->impl_, gblRowFrom);
1123 if (numInvalidSameRows != 0 || numInvalidRowsFrom != 0 || numInvalidRowsTo != 0) {
1126 std::vector<std::pair<LO, GO> > invalidSameRows;
1127 invalidSameRows.reserve (numInvalidSameRows);
1128 std::vector<std::pair<LO, GO> > invalidRowsFrom;
1129 invalidRowsFrom.reserve (numInvalidRowsFrom);
1130 std::vector<std::pair<LO, GO> > invalidRowsTo;
1131 invalidRowsTo.reserve (numInvalidRowsTo);
1133 for (LO lclRow = 0; lclRow < numSame; ++lclRow) {
1137 const GO gblRow = this->
map_->getGlobalElement (lclRow);
1138 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1139 invalidSameRows.push_back ({lclRow, gblRow});
1143 for (LO k = 0; k < numPermute; ++k) {
1144 const LO lclRowFrom = permuteFromLIDs.h_view(k);
1145 const LO lclRowTo = permuteToLIDs.h_view(k);
1146 const GO gblRowFrom = src->
map_->getGlobalElement (lclRowFrom);
1147 const GO gblRowTo = this->
map_->getGlobalElement (lclRowTo);
1149 if (gblRowFrom == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1150 invalidRowsFrom.push_back ({lclRowFrom, gblRowFrom});
1152 if (gblRowTo == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1153 invalidRowsTo.push_back ({lclRowTo, gblRowTo});
1157 std::ostringstream os;
1158 if (numInvalidSameRows != 0) {
1159 os <<
"Invalid permute \"same\" (local, global) index pairs: [";
1160 for (std::size_t k = 0; k < invalidSameRows.size (); ++k) {
1161 const auto& p = invalidSameRows[k];
1162 os <<
"(" << p.first <<
"," << p.second <<
")";
1163 if (k + 1 < invalidSameRows.size ()) {
1167 os <<
"]" << std::endl;
1169 if (numInvalidRowsFrom != 0) {
1170 os <<
"Invalid permute \"from\" (local, global) index pairs: [";
1171 for (std::size_t k = 0; k < invalidRowsFrom.size (); ++k) {
1172 const auto& p = invalidRowsFrom[k];
1173 os <<
"(" << p.first <<
"," << p.second <<
")";
1174 if (k + 1 < invalidRowsFrom.size ()) {
1178 os <<
"]" << std::endl;
1180 if (numInvalidRowsTo != 0) {
1181 os <<
"Invalid permute \"to\" (local, global) index pairs: [";
1182 for (std::size_t k = 0; k < invalidRowsTo.size (); ++k) {
1183 const auto& p = invalidRowsTo[k];
1184 os <<
"(" << p.first <<
"," << p.second <<
")";
1185 if (k + 1 < invalidRowsTo.size ()) {
1189 os <<
"]" << std::endl;
1192 std::ostream& err = this->markLocalErrorAndGetStream ();
1193 err << prefix << os.str ();
1205 const ::Kokkos::DualView<const local_ordinal_type*, device_type>& exportLIDs,
1206 ::Kokkos::DualView<packet_type*, buffer_device_type>& exports,
1207 const ::Kokkos::DualView<size_t*, buffer_device_type>& numPacketsPerLID,
1208 size_t& constantNumPackets,
1211 using ::Teuchos::Comm;
1212 using ::Teuchos::RCP;
1215 const char prefix[] =
"Tpetra::Details::CooMatrix::packAndPrepareNew: ";
1216 const char suffix[] =
" This should never happen. "
1217 "Please report this bug to the Tpetra developers.";
1221 constantNumPackets = 0;
1223 const this_type* src = dynamic_cast<const this_type*> (&sourceObject);
1225 std::ostream& err = this->markLocalErrorAndGetStream ();
1226 err << prefix <<
"Input argument 'sourceObject' is not a CooMatrix."
1229 else if (* (src->localError_)) {
1230 std::ostream& err = this->markLocalErrorAndGetStream ();
1231 err << prefix <<
"The source (input) object of the Import or Export "
1232 "is already in an error state on this process."
1235 else if (* (this->localError_)) {
1236 std::ostream& err = this->markLocalErrorAndGetStream ();
1237 err << prefix <<
"The target (output, \"this\") object of the Import "
1238 "or Export is already in an error state on this process." << endl;
1243 if (* (this->localError_)) {
1248 auto numPacketsPerLID_tmp = numPacketsPerLID;
1249 numPacketsPerLID_tmp.template sync<Kokkos::HostSpace> ();
1250 numPacketsPerLID_tmp.template modify<Kokkos::HostSpace> ();
1259 const size_t numExports = exportLIDs.extent (0);
1260 if (numExports == 0) {
1264 RCP<const Comm<int> > comm = src->
getMap ().is_null () ?
1265 Teuchos::null : src->
getMap ()->getComm ();
1266 if (comm.is_null () || comm->getSize () == 1) {
1267 if (numExports != static_cast<size_t> (0)) {
1268 std::ostream& err = this->markLocalErrorAndGetStream ();
1269 err << prefix <<
"The input communicator is either null or "
1270 "has only one process, but numExports = " << numExports <<
" != 0."
1283 auto numPacketsPerLID_tmp = numPacketsPerLID;
1284 numPacketsPerLID_tmp.template sync<Kokkos::HostSpace> ();
1285 numPacketsPerLID_tmp.template modify<Kokkos::HostSpace> ();
1288 int totalNumPackets = 0;
1289 size_t numInvalidRowInds = 0;
1290 std::ostringstream errStrm;
1291 for (
size_t k = 0; k < numExports; ++k) {
1292 const LO lclRow = exportLIDs.h_view[k];
1295 const GO gblRow = src->
map_->getGlobalElement (lclRow);
1296 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1298 ++numInvalidRowInds;
1299 numPacketsPerLID.h_view[k] = 0;
1307 src->impl_.countPackRow (numPackets, gblRow, *comm, &errStrm);
1309 std::ostream& err = this->markLocalErrorAndGetStream ();
1310 err << prefix << errStrm.str () << endl;
1311 numPacketsPerLID.h_view[k] = 0;
1317 const long long newTotalNumPackets =
1318 static_cast<long long> (totalNumPackets) +
1319 static_cast<long long> (numPackets);
1320 if (newTotalNumPackets >
1321 static_cast<long long> (std::numeric_limits<int>::max ())) {
1322 std::ostream& err = this->markLocalErrorAndGetStream ();
1323 err << prefix <<
"The new total number of packets "
1324 << newTotalNumPackets <<
" does not fit in int." << endl;
1328 for (
size_t k2 = k; k2 < numExports; ++k2) {
1329 numPacketsPerLID.h_view[k2] = 0;
1333 numPacketsPerLID.h_view[k] = static_cast<size_t> (numPackets);
1334 totalNumPackets = static_cast<int> (newTotalNumPackets);
1339 if (numInvalidRowInds != 0) {
1340 std::vector<std::pair<LO, GO> > invalidRowInds;
1341 for (
size_t k = 0; k < numExports; ++k) {
1342 const LO lclRow = exportLIDs.h_view[k];
1346 const GO gblRow = src->
map_->getGlobalElement (lclRow);
1347 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1348 invalidRowInds.push_back ({lclRow, gblRow});
1351 std::ostringstream os;
1352 os << prefix <<
"We found " << numInvalidRowInds <<
" invalid row ind"
1353 << (numInvalidRowInds != static_cast<size_t> (1) ?
"ices" :
"ex")
1354 <<
" out of " << numExports <<
" in exportLIDs. Here is the list "
1355 <<
" of invalid row indices: [";
1356 for (
size_t k = 0; k < invalidRowInds.size (); ++k) {
1357 os <<
"(LID: " << invalidRowInds[k].first <<
", GID: "
1358 << invalidRowInds[k].second <<
")";
1359 if (k + 1 < invalidRowInds.size ()) {
1365 std::ostream& err = this->markLocalErrorAndGetStream ();
1366 err << prefix << os.str () << std::endl;
1371 const bool reallocated =
1373 "CooMatrix exports");
1375 exports.template sync<Kokkos::HostSpace> ();
1378 exports.template modify<Kokkos::HostSpace> ();
1382 std::vector<GO> gblRowInds;
1383 std::vector<GO> gblColInds;
1384 std::vector<SC> vals;
1386 int outBufCurPos = 0;
1388 for (
size_t k = 0; k < numExports; ++k) {
1389 const LO lclRow = exportLIDs.h_view[k];
1392 const GO gblRow = src->
map_->getGlobalElement (lclRow);
1394 src->impl_.packRow (outBuf, totalNumPackets, outBufCurPos, *comm,
1395 gblRowInds, gblColInds, vals, gblRow);
1406 const ::Kokkos::DualView<const packet_type*, buffer_device_type>& imports,
1407 const ::Kokkos::DualView<const size_t*, buffer_device_type>& numPacketsPerLID,
1412 using ::Teuchos::Comm;
1413 using ::Teuchos::RCP;
1420 typedef typename Kokkos::DualView<const size_t*, buffer_device_type>::t_dev::memory_space CDMS;
1421 typedef typename Kokkos::DualView<const size_t*, buffer_device_type>::t_host::memory_space CHMS;
1422 typedef typename Kokkos::DualView<const LO*, device_type>::t_dev::memory_space DMS;
1423 typedef typename Kokkos::DualView<const LO*, device_type>::t_host::memory_space HMS;
1425 const char prefix[] =
"Tpetra::Details::CooMatrix::unpackAndCombineNew: ";
1426 const char suffix[] =
" This should never happen. "
1427 "Please report this bug to the Tpetra developers.";
1429 const std::size_t numImports = importLIDs.extent (0);
1430 if (numImports == 0) {
1433 else if (imports.extent (0) == 0) {
1434 std::ostream& err = this->markLocalErrorAndGetStream ();
1435 typename Kokkos::DualView<const LO*, device_type>::t_host importLIDs_h;
1437 if (importLIDs.template need_sync<HMS> ()) {
1440 auto importLIDs_d = importLIDs.template view<DMS> ();
1441 typedef typename decltype (importLIDs_h)::non_const_type HVNC;
1442 HVNC importLIDs_h_nc (importLIDs_d.label (), importLIDs.extent (0));
1444 importLIDs_h = importLIDs_h_nc;
1447 importLIDs_h = importLIDs.h_view;
1450 err << prefix <<
"importLIDs.extent(0) = " << numImports <<
" != 0, "
1451 <<
"but imports.extent(0) = 0. This doesn't make sense, because "
1452 <<
"for every incoming LID, CooMatrix packs at least the count of "
1453 <<
"triples associated with that LID, even if the count is zero. "
1454 <<
"importLIDs = [";
1455 for (std::size_t k = 0; k < numImports; ++k) {
1456 err << importLIDs.h_view[k];
1457 if (k + 1 < numImports) {
1461 err <<
"]. " << suffix << endl;
1465 RCP<const Comm<int> > comm = this->
getMap ().is_null () ?
1466 Teuchos::null : this->
getMap ()->getComm ();
1467 if (comm.is_null () || comm->getSize () == 1) {
1468 if (numImports != static_cast<size_t> (0)) {
1469 std::ostream& err = this->markLocalErrorAndGetStream ();
1470 err << prefix <<
"The input communicator is either null or "
1471 "has only one process, but numImports = " << numImports <<
" != 0."
1484 if (static_cast<size_t> (imports.extent (0)) >
1485 static_cast<size_t> (std::numeric_limits<int>::max ())) {
1486 std::ostream& err = this->markLocalErrorAndGetStream ();
1487 err << prefix <<
"imports.extent(0) = "
1488 << imports.extent (0) <<
" does not fit in int." << endl;
1491 const int inBufSize = static_cast<int> (imports.extent (0));
1496 typename Kokkos::DualView<const LO*, device_type>::t_host importLIDs_h;
1497 typename Kokkos::DualView<const packet_type*, buffer_device_type>::t_host imports_h;
1498 typename Kokkos::DualView<const size_t*, buffer_device_type>::t_host numPacketsPerLID_h;
1500 if (importLIDs.template need_sync<HMS> ()) {
1502 auto importLIDs_d = importLIDs.template view<DMS> ();
1503 typedef typename decltype (importLIDs_h)::non_const_type HVNC;
1504 HVNC importLIDs_h_nc (importLIDs_d.label (),
1505 importLIDs.extent (0));
1507 importLIDs_h = importLIDs_h_nc;
1510 importLIDs_h = importLIDs.h_view;
1513 if (imports.template need_sync<CHMS> ()) {
1515 auto imports_d = imports.template view<CDMS> ();
1516 typedef typename decltype (imports_h)::non_const_type HVNC;
1517 HVNC imports_h_nc (imports_d.label (),
1518 imports.extent (0));
1520 imports_h = imports_h_nc;
1523 imports_h = imports.h_view;
1526 if (numPacketsPerLID.template need_sync<CHMS> ()) {
1528 auto numPacketsPerLID_d = numPacketsPerLID.template view<CDMS> ();
1529 typedef typename decltype (numPacketsPerLID_h)::non_const_type HVNC;
1530 HVNC numPacketsPerLID_h_nc (numPacketsPerLID_d.label (),
1531 numPacketsPerLID.extent (0));
1533 numPacketsPerLID_h = numPacketsPerLID_h_nc;
1536 numPacketsPerLID_h = numPacketsPerLID.h_view;
1542 std::vector<GO> gblRowInds;
1543 std::vector<GO> gblColInds;
1544 std::vector<SC> vals;
1547 int inBufCurPos = 0;
1548 size_t numInvalidRowInds = 0;
1550 std::ostringstream errStrm;
1551 for (
size_t k = 0; k < numImports; ++k) {
1552 const LO lclRow = importLIDs_h(k);
1553 const GO gblRow = this->
map_->getGlobalElement (lclRow);
1554 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1555 ++numInvalidRowInds;
1561 const int origInBufCurPos = inBufCurPos;
1565 numEnt, *comm, &errStrm);
1566 if (errCode != 0 || numEnt < 0 || inBufCurPos < origInBufCurPos) {
1567 std::ostream& err = this->markLocalErrorAndGetStream ();
1569 err << prefix <<
"In unpack loop, k=" << k <<
": ";
1571 err <<
" unpackTriplesCount returned errCode = " << errCode
1572 <<
" != 0." << endl;
1575 err <<
" unpackTriplesCount returned errCode = 0, but numEnt = "
1576 << numEnt <<
" < 0." << endl;
1578 if (inBufCurPos < origInBufCurPos) {
1579 err <<
" After unpackTriplesCount, inBufCurPos = " << inBufCurPos
1580 <<
" < origInBufCurPos = " << origInBufCurPos <<
"." << endl;
1582 err <<
" unpackTriplesCount report: " << errStrm.str () << endl;
1583 err << suffix << endl;
1590 #ifdef HAVE_TPETRA_DEBUG
1597 #endif // HAVE_TPETRA_DEBUG
1602 gblRowInds.resize (numEnt);
1603 gblColInds.resize (numEnt);
1604 vals.resize (numEnt);
1607 gblRowInds.data (), gblColInds.data (),
1608 vals.data (), numEnt, *comm, &errStrm);
1610 std::ostream& err = this->markLocalErrorAndGetStream ();
1611 err << prefix <<
"unpackTriples returned errCode = "
1612 << errCode <<
" != 0. It reports: " << errStrm.str ()
1619 #ifdef HAVE_TPETRA_DEBUG
1626 #endif // HAVE_TPETRA_DEBUG
1629 vals.data (), numEnt);
1634 if (numInvalidRowInds != 0) {
1638 std::ostream& err = this->markLocalErrorAndGetStream ();
1640 std::vector<std::pair<LO, GO> > invalidRowInds;
1641 for (
size_t k = 0; k < numImports; ++k) {
1642 const LO lclRow = importLIDs_h(k);
1643 const GO gblRow = this->
map_->getGlobalElement (lclRow);
1644 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1645 invalidRowInds.push_back ({lclRow, gblRow});
1649 err << prefix <<
"We found " << numInvalidRowInds <<
" invalid row ind"
1650 << (numInvalidRowInds != static_cast<size_t> (1) ?
"ices" :
"ex")
1651 <<
" out of " << numImports <<
" in importLIDs. Here is the list "
1652 <<
" of invalid row indices: [";
1653 for (
size_t k = 0; k < invalidRowInds.size (); ++k) {
1654 err <<
"(LID: " << invalidRowInds[k].first <<
", GID: "
1655 << invalidRowInds[k].second <<
")";
1656 if (k + 1 < invalidRowInds.size ()) {
1669 #endif // TPETRA_DETAILS_COOMATRIX_HPP