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));
580 typedef LO local_ordinal_type;
581 typedef GO global_ordinal_type;
582 typedef NT node_type;
583 typedef typename NT::device_type device_type;
585 typedef ::Tpetra::Map<local_ordinal_type, global_ordinal_type, node_type>
map_type;
589 typedef ::Tpetra::DistObject<
packet_type, local_ordinal_type,
590 global_ordinal_type, node_type>
base_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> ())
634 this->impl_.sumIntoGlobalValue (gblRowInd, gblColInd, val);
647 const GO gblColInds[],
649 const std::size_t numEnt)
651 this->impl_.sumIntoGlobalValues (gblRowInds, gblColInds, vals, numEnt);
657 std::initializer_list<GO> gblColInds,
658 std::initializer_list<SC> vals,
659 const std::size_t numEnt)
661 this->impl_.sumIntoGlobalValues (gblRowInds.begin (), gblColInds.begin (),
662 vals.begin (), numEnt);
669 return this->impl_.getLclNumEntries ();
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;
900 const std::size_t numEnt = this->impl_.getLclNumEntries ();
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;
951 const GO lclMinGblRowInd = this->impl_.getMyGlobalRowIndices (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_));
999 typename ::Tpetra::DistObject<char, LO, GO, NT>::buffer_device_type;
1002 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
1004 #else // TPETRA_ENABLE_DEPRECATED_CODE
1006 #endif // TPETRA_ENABLE_DEPRECATED_CODE
1007 (const ::Tpetra::SrcDistObject& sourceObject,
1008 const size_t numSameIDs,
1009 const Kokkos::DualView<
const LO*,
1011 const Kokkos::DualView<
const LO*,
1016 const char prefix[] =
"Tpetra::Details::CooMatrix::copyAndPermute: ";
1021 if (* (this->localError_)) {
1022 std::ostream& err = this->markLocalErrorAndGetStream ();
1023 err << prefix <<
"The target object of the Import or Export is "
1024 "already in an error state." << endl;
1029 if (src ==
nullptr) {
1030 std::ostream& err = this->markLocalErrorAndGetStream ();
1031 err << prefix <<
"Input argument 'sourceObject' is not a CooMatrix."
1036 const size_t numPermuteIDs =
1037 static_cast<size_t> (permuteToLIDs.extent (0));
1038 if (numPermuteIDs != static_cast<size_t> (permuteFromLIDs.extent (0))) {
1039 std::ostream& err = this->markLocalErrorAndGetStream ();
1040 err << prefix <<
"permuteToLIDs.extent(0) = "
1041 << numPermuteIDs <<
" != permuteFromLIDs.extent(0) = "
1042 << permuteFromLIDs.extent (0) <<
"." << endl;
1045 if (
sizeof (
int) <=
sizeof (
size_t) &&
1046 numPermuteIDs > static_cast<size_t> (std::numeric_limits<int>::max ())) {
1047 std::ostream& err = this->markLocalErrorAndGetStream ();
1048 err << prefix <<
"numPermuteIDs = " << numPermuteIDs
1049 <<
", a size_t, overflows int." << endl;
1056 if (
sizeof (
int) <=
sizeof (
size_t) &&
1057 numSameIDs > static_cast<size_t> (std::numeric_limits<int>::max ())) {
1058 std::ostream& err = this->markLocalErrorAndGetStream ();
1059 err << prefix <<
"numSameIDs = " << numSameIDs
1060 <<
", a size_t, overflows int." << endl;
1067 const LO numSame =
static_cast<int> (numSameIDs);
1072 LO numInvalidSameRows = 0;
1073 for (LO lclRow = 0; lclRow < numSame; ++lclRow) {
1077 const GO gblRow = this->
map_->getGlobalElement (lclRow);
1078 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1079 ++numInvalidSameRows;
1083 this->impl_.mergeIntoRow (gblRow, src->impl_, gblRow);
1092 const LO numPermute =
static_cast<int> (numPermuteIDs);
1097 LO numInvalidRowsFrom = 0;
1102 LO numInvalidRowsTo = 0;
1104 TEUCHOS_ASSERT( ! permuteFromLIDs.need_sync_host () );
1105 TEUCHOS_ASSERT( ! permuteToLIDs.need_sync_host () );
1106 auto permuteFromLIDs_h = permuteFromLIDs.view_host ();
1107 auto permuteToLIDs_h = permuteToLIDs.view_host ();
1109 for (LO k = 0; k < numPermute; ++k) {
1110 const LO lclRowFrom = permuteFromLIDs_h[k];
1111 const LO lclRowTo = permuteToLIDs_h[k];
1112 const GO gblRowFrom = src->
map_->getGlobalElement (lclRowFrom);
1113 const GO gblRowTo = this->
map_->getGlobalElement (lclRowTo);
1115 bool bothConversionsValid =
true;
1116 if (gblRowFrom == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1117 ++numInvalidRowsFrom;
1118 bothConversionsValid =
false;
1120 if (gblRowTo == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1122 bothConversionsValid =
false;
1124 if (bothConversionsValid) {
1125 this->impl_.mergeIntoRow (gblRowTo, src->impl_, gblRowFrom);
1130 if (numInvalidSameRows != 0 || numInvalidRowsFrom != 0 ||
1131 numInvalidRowsTo != 0) {
1134 std::vector<std::pair<LO, GO> > invalidSameRows;
1135 invalidSameRows.reserve (numInvalidSameRows);
1136 std::vector<std::pair<LO, GO> > invalidRowsFrom;
1137 invalidRowsFrom.reserve (numInvalidRowsFrom);
1138 std::vector<std::pair<LO, GO> > invalidRowsTo;
1139 invalidRowsTo.reserve (numInvalidRowsTo);
1141 for (LO lclRow = 0; lclRow < numSame; ++lclRow) {
1145 const GO gblRow = this->
map_->getGlobalElement (lclRow);
1146 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1147 invalidSameRows.push_back ({lclRow, gblRow});
1151 for (LO k = 0; k < numPermute; ++k) {
1152 const LO lclRowFrom = permuteFromLIDs_h[k];
1153 const LO lclRowTo = permuteToLIDs_h[k];
1154 const GO gblRowFrom = src->
map_->getGlobalElement (lclRowFrom);
1155 const GO gblRowTo = this->
map_->getGlobalElement (lclRowTo);
1157 if (gblRowFrom == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1158 invalidRowsFrom.push_back ({lclRowFrom, gblRowFrom});
1160 if (gblRowTo == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1161 invalidRowsTo.push_back ({lclRowTo, gblRowTo});
1165 std::ostringstream os;
1166 if (numInvalidSameRows != 0) {
1167 os <<
"Invalid permute \"same\" (local, global) index pairs: [";
1168 for (std::size_t k = 0; k < invalidSameRows.size (); ++k) {
1169 const auto& p = invalidSameRows[k];
1170 os <<
"(" << p.first <<
"," << p.second <<
")";
1171 if (k + 1 < invalidSameRows.size ()) {
1175 os <<
"]" << std::endl;
1177 if (numInvalidRowsFrom != 0) {
1178 os <<
"Invalid permute \"from\" (local, global) index pairs: [";
1179 for (std::size_t k = 0; k < invalidRowsFrom.size (); ++k) {
1180 const auto& p = invalidRowsFrom[k];
1181 os <<
"(" << p.first <<
"," << p.second <<
")";
1182 if (k + 1 < invalidRowsFrom.size ()) {
1186 os <<
"]" << std::endl;
1188 if (numInvalidRowsTo != 0) {
1189 os <<
"Invalid permute \"to\" (local, global) index pairs: [";
1190 for (std::size_t k = 0; k < invalidRowsTo.size (); ++k) {
1191 const auto& p = invalidRowsTo[k];
1192 os <<
"(" << p.first <<
"," << p.second <<
")";
1193 if (k + 1 < invalidRowsTo.size ()) {
1197 os <<
"]" << std::endl;
1200 std::ostream& err = this->markLocalErrorAndGetStream ();
1201 err << prefix << os.str ();
1207 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
1209 #else // TPETRA_ENABLE_DEPRECATED_CODE
1211 #endif // TPETRA_ENABLE_DEPRECATED_CODE
1212 (const ::Tpetra::SrcDistObject& sourceObject,
1213 const Kokkos::DualView<
const local_ordinal_type*,
1217 Kokkos::DualView<
size_t*,
1219 size_t& constantNumPackets,
1222 using Teuchos::Comm;
1226 const char prefix[] =
"Tpetra::Details::CooMatrix::packAndPrepare: ";
1227 const char suffix[] =
" This should never happen. "
1228 "Please report this bug to the Tpetra developers.";
1232 constantNumPackets = 0;
1234 const this_type* src =
dynamic_cast<const this_type*
> (&sourceObject);
1235 if (src ==
nullptr) {
1236 std::ostream& err = this->markLocalErrorAndGetStream ();
1237 err << prefix <<
"Input argument 'sourceObject' is not a CooMatrix."
1240 else if (* (src->localError_)) {
1241 std::ostream& err = this->markLocalErrorAndGetStream ();
1242 err << prefix <<
"The source (input) object of the Import or Export "
1243 "is already in an error state on this process."
1246 else if (* (this->localError_)) {
1247 std::ostream& err = this->markLocalErrorAndGetStream ();
1248 err << prefix <<
"The target (output, \"this\") object of the Import "
1249 "or Export is already in an error state on this process." << endl;
1254 if (* (this->localError_)) {
1259 auto numPacketsPerLID_tmp = numPacketsPerLID;
1260 numPacketsPerLID_tmp.sync_host ();
1261 numPacketsPerLID_tmp.modify_host ();
1268 const size_t numExports = exportLIDs.extent (0);
1269 if (numExports == 0) {
1273 RCP<const Comm<int> > comm = src->getMap ().is_null () ?
1274 Teuchos::null : src->getMap ()->getComm ();
1275 if (comm.is_null () || comm->getSize () == 1) {
1276 if (numExports != static_cast<size_t> (0)) {
1277 std::ostream& err = this->markLocalErrorAndGetStream ();
1278 err << prefix <<
"The input communicator is either null or "
1279 "has only one process, but numExports = " << numExports <<
" != 0."
1290 numPacketsPerLID.sync_host ();
1291 numPacketsPerLID.modify_host ();
1293 TEUCHOS_ASSERT( ! exportLIDs.need_sync_host () );
1294 auto exportLIDs_h = exportLIDs.view_host ();
1296 int totalNumPackets = 0;
1297 size_t numInvalidRowInds = 0;
1298 std::ostringstream errStrm;
1299 for (
size_t k = 0; k < numExports; ++k) {
1300 const LO lclRow = exportLIDs_h[k];
1303 const GO gblRow = src->map_->getGlobalElement (lclRow);
1304 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1306 ++numInvalidRowInds;
1307 numPacketsPerLID.h_view[k] = 0;
1315 src->impl_.countPackRow (numPackets, gblRow, *comm, &errStrm);
1317 std::ostream& err = this->markLocalErrorAndGetStream ();
1318 err << prefix << errStrm.str () << endl;
1319 numPacketsPerLID.h_view[k] = 0;
1325 const long long newTotalNumPackets =
1326 static_cast<long long> (totalNumPackets) +
1327 static_cast<long long> (numPackets);
1328 if (newTotalNumPackets >
1329 static_cast<long long> (std::numeric_limits<int>::max ())) {
1330 std::ostream& err = this->markLocalErrorAndGetStream ();
1331 err << prefix <<
"The new total number of packets "
1332 << newTotalNumPackets <<
" does not fit in int." << endl;
1336 for (
size_t k2 = k; k2 < numExports; ++k2) {
1337 numPacketsPerLID.h_view[k2] = 0;
1341 numPacketsPerLID.h_view[k] =
static_cast<size_t> (numPackets);
1342 totalNumPackets =
static_cast<int> (newTotalNumPackets);
1347 if (numInvalidRowInds != 0) {
1348 std::vector<std::pair<LO, GO> > invalidRowInds;
1349 for (
size_t k = 0; k < numExports; ++k) {
1350 const LO lclRow = exportLIDs_h[k];
1354 const GO gblRow = src->map_->getGlobalElement (lclRow);
1355 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1356 invalidRowInds.push_back ({lclRow, gblRow});
1359 std::ostringstream os;
1360 os << prefix <<
"We found " << numInvalidRowInds <<
" invalid row ind"
1361 << (numInvalidRowInds !=
static_cast<size_t> (1) ?
"ices" :
"ex")
1362 <<
" out of " << numExports <<
" in exportLIDs. Here is the list "
1363 <<
" of invalid row indices: [";
1364 for (
size_t k = 0; k < invalidRowInds.size (); ++k) {
1365 os <<
"(LID: " << invalidRowInds[k].first <<
", GID: "
1366 << invalidRowInds[k].second <<
")";
1367 if (k + 1 < invalidRowInds.size ()) {
1373 std::ostream& err = this->markLocalErrorAndGetStream ();
1374 err << prefix << os.str () << std::endl;
1379 const bool reallocated =
1381 "CooMatrix exports");
1383 exports.sync_host ();
1386 exports.modify_host ();
1390 std::vector<GO> gblRowInds;
1391 std::vector<GO> gblColInds;
1392 std::vector<SC> vals;
1394 int outBufCurPos = 0;
1396 for (
size_t k = 0; k < numExports; ++k) {
1397 const LO lclRow = exportLIDs.h_view[k];
1400 const GO gblRow = src->map_->getGlobalElement (lclRow);
1402 src->impl_.packRow (outBuf, totalNumPackets, outBufCurPos, *comm,
1403 gblRowInds, gblColInds, vals, gblRow);
1408 #ifdef TPETRA_ENABLE_DEPRECATED_CODE
1410 #else // TPETRA_ENABLE_DEPRECATED_CODE
1412 #endif // TPETRA_ENABLE_DEPRECATED_CODE
1413 (
const Kokkos::DualView<
const local_ordinal_type*,
1417 Kokkos::DualView<
size_t*,
1423 using Teuchos::Comm;
1426 const char prefix[] =
"Tpetra::Details::CooMatrix::unpackAndCombine: ";
1427 const char suffix[] =
" This should never happen. "
1428 "Please report this bug to the Tpetra developers.";
1430 TEUCHOS_ASSERT( ! importLIDs.need_sync_host () );
1431 auto importLIDs_h = importLIDs.view_host ();
1433 const std::size_t numImports = importLIDs.extent (0);
1434 if (numImports == 0) {
1437 else if (imports.extent (0) == 0) {
1438 std::ostream& err = this->markLocalErrorAndGetStream ();
1439 err << prefix <<
"importLIDs.extent(0) = " << numImports <<
" != 0, "
1440 <<
"but imports.extent(0) = 0. This doesn't make sense, because "
1441 <<
"for every incoming LID, CooMatrix packs at least the count of "
1442 <<
"triples associated with that LID, even if the count is zero. "
1443 <<
"importLIDs = [";
1444 for (std::size_t k = 0; k < numImports; ++k) {
1445 err << importLIDs_h[k];
1446 if (k + 1 < numImports) {
1450 err <<
"]. " << suffix << endl;
1454 RCP<const Comm<int> > comm = this->
getMap ().is_null () ?
1455 Teuchos::null : this->
getMap ()->getComm ();
1456 if (comm.is_null () || comm->getSize () == 1) {
1457 if (numImports != static_cast<size_t> (0)) {
1458 std::ostream& err = this->markLocalErrorAndGetStream ();
1459 err << prefix <<
"The input communicator is either null or "
1460 "has only one process, but numImports = " << numImports <<
" != 0."
1473 if (static_cast<size_t> (imports.extent (0)) >
1474 static_cast<size_t> (std::numeric_limits<int>::max ())) {
1475 std::ostream& err = this->markLocalErrorAndGetStream ();
1476 err << prefix <<
"imports.extent(0) = "
1477 << imports.extent (0) <<
" does not fit in int." << endl;
1480 const int inBufSize =
static_cast<int> (imports.extent (0));
1482 if (imports.need_sync_host ()) {
1483 imports.sync_host ();
1485 if (numPacketsPerLID.need_sync_host ()) {
1486 numPacketsPerLID.sync_host ();
1488 auto imports_h = imports.view_host ();
1489 auto numPacketsPerLID_h = numPacketsPerLID.view_host ();
1493 std::vector<GO> gblRowInds;
1494 std::vector<GO> gblColInds;
1495 std::vector<SC> vals;
1498 int inBufCurPos = 0;
1499 size_t numInvalidRowInds = 0;
1501 std::ostringstream errStrm;
1502 for (
size_t k = 0; k < numImports; ++k) {
1503 const LO lclRow = importLIDs_h(k);
1504 const GO gblRow = this->
map_->getGlobalElement (lclRow);
1505 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1506 ++numInvalidRowInds;
1512 const int origInBufCurPos = inBufCurPos;
1516 numEnt, *comm, &errStrm);
1517 if (errCode != 0 || numEnt < 0 || inBufCurPos < origInBufCurPos) {
1518 std::ostream& err = this->markLocalErrorAndGetStream ();
1520 err << prefix <<
"In unpack loop, k=" << k <<
": ";
1522 err <<
" unpackTriplesCount returned errCode = " << errCode
1523 <<
" != 0." << endl;
1526 err <<
" unpackTriplesCount returned errCode = 0, but numEnt = "
1527 << numEnt <<
" < 0." << endl;
1529 if (inBufCurPos < origInBufCurPos) {
1530 err <<
" After unpackTriplesCount, inBufCurPos = " << inBufCurPos
1531 <<
" < origInBufCurPos = " << origInBufCurPos <<
"." << endl;
1533 err <<
" unpackTriplesCount report: " << errStrm.str () << endl;
1534 err << suffix << endl;
1541 #ifdef HAVE_TPETRA_DEBUG
1548 #endif // HAVE_TPETRA_DEBUG
1553 gblRowInds.resize (numEnt);
1554 gblColInds.resize (numEnt);
1555 vals.resize (numEnt);
1558 gblRowInds.data (), gblColInds.data (),
1559 vals.data (), numEnt, *comm, &errStrm);
1561 std::ostream& err = this->markLocalErrorAndGetStream ();
1562 err << prefix <<
"unpackTriples returned errCode = "
1563 << errCode <<
" != 0. It reports: " << errStrm.str ()
1570 #ifdef HAVE_TPETRA_DEBUG
1577 #endif // HAVE_TPETRA_DEBUG
1580 vals.data (), numEnt);
1585 if (numInvalidRowInds != 0) {
1589 std::ostream& err = this->markLocalErrorAndGetStream ();
1591 std::vector<std::pair<LO, GO> > invalidRowInds;
1592 for (
size_t k = 0; k < numImports; ++k) {
1593 const LO lclRow = importLIDs_h(k);
1594 const GO gblRow = this->
map_->getGlobalElement (lclRow);
1595 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1596 invalidRowInds.push_back ({lclRow, gblRow});
1600 err << prefix <<
"We found " << numInvalidRowInds <<
" invalid row ind"
1601 << (numInvalidRowInds !=
static_cast<size_t> (1) ?
"ices" :
"ex")
1602 <<
" out of " << numImports <<
" in importLIDs. Here is the list "
1603 <<
" of invalid row indices: [";
1604 for (
size_t k = 0; k < invalidRowInds.size (); ++k) {
1605 err <<
"(LID: " << invalidRowInds[k].first <<
", GID: "
1606 << invalidRowInds[k].second <<
")";
1607 if (k + 1 < invalidRowInds.size ()) {
1620 #endif // TPETRA_DETAILS_COOMATRIX_HPP
char packet_type
Type for packing and unpacking data.
int packTriplesCount(const int, char[], const int, int &, const ::Teuchos::Comm< int > &, std::ostream *errStrm)
Pack the count (number) of matrix triples.
void sumIntoGlobalValues(std::initializer_list< GO > gblRowInds, std::initializer_list< GO > gblColInds, std::initializer_list< SC > vals, const std::size_t numEnt)
Initializer-list overload of the above method (which see).
Node node_type
The Node type. If you don't know what this is, don't use it.
CooMatrixImpl()=default
Default constructor.
std::string errorMessages() const
The current stream of error messages.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Print a descriptiion of this object to the given output stream; overrides Teuchos::Describable method...
void packRow(packet_type outBuf[], const int outBufSize, int &outBufCurPos, const ::Teuchos::Comm< int > &comm, std::vector< GO > &gblRowInds, std::vector< GO > &gblColInds, std::vector< SC > &vals, const GO gblRow) const
Pack the given row of the matrix.
Function comparing two CooGraphEntry structs, lexicographically, first by row index, then by column index.
void sumIntoGlobalValue(const GO gblRowInd, const GO gblColInd, const SC &val)
Insert one entry locally into the sparse matrix, if it does not exist there yet. If it does exist...
Sparse matrix used only for file input / output.
void buildLocallyIndexedCrs(std::vector< OffsetType > &rowOffsets, LO lclColInds[], SC vals[], std::function< LO(const GO)> gblToLcl) const
Build a locally indexed version of CRS storage.
void fillComplete()
Special version of fillComplete that assumes that the matrix already has a Map, and reuses its commun...
GlobalOrdinal global_ordinal_type
The type of global indices.
virtual ~CooMatrix()
Destructor (virtual for memory safety of derived classes).
void gathervPrint(std::ostream &out, const std::string &s, const Teuchos::Comm< int > &comm)
On Process 0 in the given communicator, print strings from each process in that communicator, in rank order.
void fillComplete(const ::Teuchos::RCP< const ::Teuchos::Comm< int > > &comm)
Tell the matrix that you are done inserting entries locally, and that the matrix should build its Map...
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.
std::size_t getLclNumEntries() const
Number of entries in the sparse matrix on the calling process.
void sumIntoGlobalValue(const GO gblRowInd, const GO gblColInd, const SC &val)
Insert one entry locally into the sparse matrix, if it does not exist there yet. If it does exist...
Type of each (row index, column index) pair in the Tpetra::Details::CooMatrix (see below)...
bool localError() const
Whether this object had an error on the calling process.
int unpackTriplesCount(const char[], const int, int &, int &, const ::Teuchos::Comm< int > &, std::ostream *errStrm)
Unpack just the count of triples from the given input buffer.
SC scalar_type
Type of each entry (value) in the sparse matrix.
CooMatrix()
Default constructor.
virtual size_t constantNumberOfPackets() const
By returning 0, tell DistObject that this class may not necessarily have a constant number of "packet...
void sumIntoGlobalValues(const GO gblRowInds[], const GO gblColInds[], const SC vals[], const std::size_t numEnt)
Insert multiple entries locally into the sparse matrix.
CooMatrix(const ::Teuchos::RCP< const map_type > &map)
Constructor that takes a Map.
virtual bool checkSizes(const ::Tpetra::SrcDistObject &source)
Compare the source and target (this) objects for compatibility.
Sets up and executes a communication plan for a Tpetra DistObject.
void sumIntoGlobalValues(const GO gblRowInds[], const GO gblColInds[], const SC vals[], const std::size_t numEnt)
Insert multiple entries locally into the sparse matrix.
CombineMode
Rule for combining data in an Import or Export.
Teuchos::RCP< const map_type > map_
The Map over which this object is distributed.
bool reallocDualViewIfNeeded(Kokkos::DualView< ValueType *, DeviceType > &dv, const size_t newSize, const char newLabel[], const size_t tooBigFactor=2, const bool needFenceBeforeRealloc=true)
Reallocate the DualView in/out argument, if needed.
int countPackTriplesCount(const ::Teuchos::Comm< int > &, int &size, std::ostream *errStrm)
Compute the buffer size required by packTriples for packing the number of matrix entries ("triples")...
::Tpetra::Map< local_ordinal_type, global_ordinal_type, node_type > map_type
Type of the Map specialization to give to the constructor.
Declaration and definition of Tpetra::Details::reallocDualViewIfNeeded, an implementation detail of T...
void forAllEntries(std::function< void(const GO, const GO, const SC &)> f) const
Execute the given function for all entries of the sparse matrix, sequentially (no thread parallelism)...
LocalOrdinal local_ordinal_type
The type of local indices.
int countPackRow(int &numPackets, const GO gblRow, const ::Teuchos::Comm< int > &comm, std::ostream *errStrm=NULL) const
Count the number of packets (bytes, in this case) needed to pack the given row of the matrix...
std::size_t getLclNumEntries() const
Number of entries in the sparse matrix on the calling process.
GO getMyGlobalRowIndices(std::vector< GO > &rowInds) const
Get the global row indices on this process, sorted and made unique, and return the minimum global row...
typename::Tpetra::DistObject< char, LO, GO, NT >::buffer_device_type buffer_device_type
Kokkos::Device specialization for DistObject communication buffers.
void mergeIntoRow(const GO tgtGblRow, const CooMatrixImpl< SC, GO > &src, const GO srcGblRow)
Into global row tgtGblRow of *this, merge global row srcGblRow of src.
char packet_type
This class transfers data as bytes (MPI_BYTE).
virtual std::string description() const
One-line descriptiion of this object; overrides Teuchos::Describable method.
virtual Teuchos::RCP< const map_type > getMap() const
The Map describing the parallel distribution of this object.
int unpackTriples(const char[], const int, int &, OrdinalType[], OrdinalType[], ScalarType[], const int, const ::Teuchos::Comm< int > &, std::ostream *errStrm=NULL)
Unpack matrix entries ("triples" (i, j, A(i,j))) from the given input buffer.
Base class for distributed Tpetra objects that support data redistribution.
Implementation detail of Tpetra::Details::CooMatrix (which see below).
int packTriples(const OrdinalType[], const OrdinalType[], const ScalarType[], const int, char[], const int, int &, const ::Teuchos::Comm< int > &, std::ostream *errStrm=NULL)
Pack matrix entries ("triples" (i, j, A(i,j))) into the given output buffer.