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" 54 #include "Teuchos_TypeNameTraits.hpp" 56 #include <initializer_list> 60 #include <type_traits> 73 template<
class IndexType>
83 template<
class IndexType>
89 return (x.row < y.row) || (x.row == y.row && x.col < y.col);
95 template<
class SC,
class GO>
105 typedef std::map<CooGraphEntry<GO>, SC,
110 entries_type entries_;
134 auto result = this->entries_.insert ({ij, val});
135 if (! result.second) {
136 result.first->second += val;
150 const GO gblColInds[],
152 const std::size_t numEnt)
154 for (std::size_t k = 0; k < numEnt; ++k) {
159 const SC val = vals[k];
160 auto result = this->entries_.insert ({ij, val});
161 if (! result.second) {
162 result.first->second += val;
171 return this->entries_.size ();
180 for (
auto iter = this->entries_.begin ();
181 iter != this->entries_.end (); ++iter) {
182 f (iter->first.row, iter->first.col, iter->second);
199 entries_type& tgtEntries = this->entries_;
200 const entries_type& srcEntries = src.entries_;
206 auto srcBeg = srcEntries.lower_bound ({srcGblRow, std::numeric_limits<GO>::min ()});
207 auto srcEnd = srcEntries.upper_bound ({srcGblRow+1, std::numeric_limits<GO>::min ()});
208 auto tgtBeg = tgtEntries.lower_bound ({tgtGblRow, std::numeric_limits<GO>::min ()});
209 auto tgtEnd = tgtEntries.upper_bound ({tgtGblRow+1, std::numeric_limits<GO>::min ()});
213 if (srcBeg != srcEnd) {
214 for (
auto tgtCur = tgtBeg; tgtCur != tgtEnd; ++tgtCur) {
215 auto srcCur = srcBeg;
216 while (srcCur != srcEnd && srcCur->first.col < tgtCur->first.col) {
228 if (srcCur != srcEnd) {
229 if (srcCur->first.col == tgtCur->first.col) {
230 tgtCur->second += srcCur->second;
237 (void) tgtEntries.insert (tgtCur, *srcCur);
256 const ::Teuchos::Comm<int>& comm,
257 std::ostream* errStrm = NULL)
const 259 using ::Tpetra::Details::countPackTriples;
260 using ::Tpetra::Details::countPackTriplesCount;
262 const char prefix[] =
"Tpetra::Details::Impl::CooMatrixImpl::countPackRow: ";
263 #ifdef HAVE_TPETRACORE_MPI 264 int errCode = MPI_SUCCESS;
267 #endif // HAVE_TPETRACORE_MPI 270 const GO minGO = std::numeric_limits<GO>::min ();
271 auto beg = this->entries_.lower_bound ({gblRow, minGO});
272 auto end = this->entries_.upper_bound ({gblRow+1, minGO});
274 for (
auto iter = beg; iter != end; ++iter) {
276 if (numEnt == std::numeric_limits<int>::max ()) {
277 if (errStrm != NULL) {
278 *errStrm << prefix <<
"In (global) row " << gblRow <<
", the number " 279 "of entries thus far, numEnt = " << numEnt <<
", has reached the " 280 "maximum int value. We need to store this count as int for MPI's " 287 int numPacketsForCount = 0;
292 if (errStrm != NULL) {
293 *errStrm << prefix <<
"countPackTriplesCount " 294 "returned errCode = " << errCode <<
" != 0." << endl;
298 if (numPacketsForCount < 0) {
299 if (errStrm != NULL) {
300 *errStrm << prefix <<
"countPackTriplesCount returned " 301 "numPacketsForCount = " << numPacketsForCount <<
" < 0." << endl;
307 int numPacketsForTriples = 0;
309 const int errCode = countPackTriples<SC, GO> (numEnt, comm, numPacketsForTriples);
310 TEUCHOS_TEST_FOR_EXCEPTION
311 (errCode != 0, std::runtime_error, prefix <<
"countPackTriples " 312 "returned errCode = " << errCode <<
" != 0.");
313 TEUCHOS_TEST_FOR_EXCEPTION
314 (numPacketsForTriples < 0, std::logic_error, prefix <<
"countPackTriples " 315 "returned numPacketsForTriples = " << numPacketsForTriples <<
" < 0.");
318 numPackets = numPacketsForCount + numPacketsForTriples;
338 const int outBufSize,
340 const ::Teuchos::Comm<int>& comm,
341 std::vector<GO>& gblRowInds,
342 std::vector<GO>& gblColInds,
343 std::vector<SC>& vals,
344 const GO gblRow)
const 346 using ::Tpetra::Details::packTriples;
347 using ::Tpetra::Details::packTriplesCount;
348 const char prefix[] =
"Tpetra::Details::Impl::CooMatrixImpl::packRow: ";
350 const GO minGO = std::numeric_limits<GO>::min ();
351 auto beg = this->entries_.lower_bound ({gblRow, minGO});
352 auto end = this->entries_.upper_bound ({gblRow+1, minGO});
356 gblRowInds.resize (0);
357 gblColInds.resize (0);
361 for (
auto iter = beg; iter != end; ++iter) {
362 gblRowInds.push_back (iter->first.row);
363 gblColInds.push_back (iter->first.col);
364 vals.push_back (iter->second);
366 TEUCHOS_TEST_FOR_EXCEPTION
367 (numEnt == std::numeric_limits<int>::max (), std::runtime_error, prefix
368 <<
"In (global) row " << gblRow <<
", the number of entries thus far, " 369 "numEnt = " << numEnt <<
", has reached the maximum int value. " 370 "We need to store this count as int for MPI's sake.");
376 TEUCHOS_TEST_FOR_EXCEPTION
377 (errCode != 0, std::runtime_error, prefix
378 <<
"In (global) row " << gblRow <<
", packTriplesCount returned " 379 "errCode = " << errCode <<
" != 0.");
391 TEUCHOS_TEST_FOR_EXCEPTION
392 (errCode != 0, std::runtime_error, prefix <<
"In (global) row " 393 << gblRow <<
", packTriples returned errCode = " << errCode
410 GO lclMinRowInd = std::numeric_limits<GO>::max ();
411 for (
typename entries_type::const_iterator iter = this->entries_.begin ();
412 iter != this->entries_.end (); ++iter) {
413 const GO rowInd = iter->first.row;
414 if (rowInd < lclMinRowInd) {
415 lclMinRowInd = rowInd;
417 if (rowInds.empty () || rowInds.back () != rowInd) {
418 rowInds.push_back (rowInd);
424 template<
class OffsetType>
426 buildCrs (std::vector<OffsetType>& rowOffsets,
430 static_assert (std::is_integral<OffsetType>::value,
431 "OffsetType must be a built-in integer type.");
437 const std::size_t numEnt = this->getLclNumEntries ();
439 rowOffsets.push_back (0);
442 typename entries_type::const_iterator iter = this->entries_.begin ();
443 GO prevGblRowInd = iter->first.row;
446 for ( ; iter != this->entries_.end (); ++iter, ++k) {
447 const GO gblRowInd = iter->first.row;
448 if (k == 0 || gblRowInd != prevGblRowInd) {
452 rowOffsets.push_back (k);
453 prevGblRowInd = gblRowInd;
455 gblColInds[k] = iter->first.col;
457 static_assert (std::is_same<
typename std::decay<decltype (iter->second)>::type, SC>::value,
458 "The type of iter->second != SC.");
459 vals[k] = iter->second;
461 rowOffsets.push_back (static_cast<OffsetType> (numEnt));
477 template<
class OffsetType,
class LO>
482 std::function<LO (
const GO)> gblToLcl)
const 484 static_assert (std::is_integral<OffsetType>::value,
485 "OffsetType must be a built-in integer type.");
486 static_assert (std::is_integral<LO>::value,
487 "LO must be a built-in integer type.");
493 const std::size_t numEnt = this->getLclNumEntries ();
495 rowOffsets.push_back (0);
498 typename entries_type::const_iterator iter = this->entries_.begin ();
499 GO prevGblRowInd = iter->first.row;
502 for ( ; iter != this->entries_.end (); ++iter, ++k) {
503 const GO gblRowInd = iter->first.row;
504 if (k == 0 || gblRowInd != prevGblRowInd) {
508 rowOffsets.push_back (k);
509 prevGblRowInd = gblRowInd;
511 lclColInds[k] = gblToLcl (iter->first.col);
512 vals[k] = iter->second;
514 rowOffsets.push_back (static_cast<OffsetType> (numEnt));
579 typedef LO local_ordinal_type;
580 typedef GO global_ordinal_type;
581 typedef NT node_type;
582 typedef typename NT::device_type device_type;
584 typedef ::Tpetra::Map<local_ordinal_type, global_ordinal_type, node_type>
map_type;
588 typedef ::Tpetra::DistObject<packet_type, local_ordinal_type,
589 global_ordinal_type, node_type>
base_type;
602 localError_ (new bool (false)),
603 errs_ (new std::shared_ptr<std::ostringstream> ())
615 localError_ (new bool (false)),
616 errs_ (new std::shared_ptr<std::ostringstream> ())
646 const GO gblColInds[],
648 const std::size_t numEnt)
656 std::initializer_list<GO> gblColInds,
657 std::initializer_list<SC> vals,
658 const std::size_t numEnt)
661 vals.begin (), numEnt);
671 template<
class OffsetType>
673 buildCrs (::Kokkos::View<OffsetType*, device_type>& rowOffsets,
674 ::Kokkos::View<GO*, device_type>& gblColInds,
675 ::Kokkos::View<typename ::Kokkos::Details::ArithTraits<SC>::val_type*, device_type>& vals)
677 static_assert (std::is_integral<OffsetType>::value,
678 "OffsetType must be a built-in integer type.");
679 using ::Kokkos::create_mirror_view;
681 using ::Kokkos::View;
682 typedef typename ::Kokkos::Details::ArithTraits<SC>::val_type ISC;
684 const std::size_t numEnt = this->getLclNumEntries ();
686 gblColInds = View<GO*, device_type> (
"gblColInds", numEnt);
687 vals = View<ISC*, device_type> (
"vals", numEnt);
688 auto gblColInds_h = create_mirror_view (gblColInds);
689 auto vals_h = create_mirror_view (vals);
691 std::vector<std::size_t> rowOffsetsSV;
692 this->impl_.buildCrs (rowOffsetsSV,
693 gblColInds_h.ptr_on_device (),
694 vals_h.ptr_on_device ());
696 View<OffsetType*, device_type> (
"rowOffsets", rowOffsetsSV.size ());
697 typename View<OffsetType*, device_type>::HostMirror
698 rowOffsets_h (rowOffsetsSV.data (), rowOffsetsSV.size ());
718 if (comm.is_null ()) {
719 this->map_ = ::Teuchos::null;
722 this->map_ = this->buildMap (comm);
737 TEUCHOS_TEST_FOR_EXCEPTION
738 (this->getMap ().is_null (), std::runtime_error,
"Tpetra::Details::" 739 "CooMatrix::fillComplete: This object does not yet have a Map. " 740 "You must call the version of fillComplete " 741 "that takes an input communicator.");
742 this->fillComplete (this->getMap ()->getComm ());
781 return ((*errs_).get () == NULL) ? std::string (
"") : (*errs_)->str ();
797 std::shared_ptr<bool> localError_;
806 std::shared_ptr<std::shared_ptr<std::ostringstream> > errs_;
810 markLocalErrorAndGetStream ()
812 * (this->localError_) =
true;
813 if ((*errs_).get () == NULL) {
814 *errs_ = std::shared_ptr<std::ostringstream> (
new std::ostringstream ());
823 using Teuchos::TypeNameTraits;
825 std::ostringstream os;
826 os <<
"\"Tpetra::Details::CooMatrix\": {" 827 <<
"SC: " << TypeNameTraits<SC>::name ()
828 <<
", LO: " << TypeNameTraits<LO>::name ()
829 <<
", GO: " << TypeNameTraits<GO>::name ()
830 <<
", NT: " << TypeNameTraits<NT>::name ();
831 if (this->getObjectLabel () !=
"") {
832 os <<
", Label: \"" << this->getObjectLabel () <<
"\"";
834 os <<
", Has Map: " << (this->map_.is_null () ?
"false" :
"true")
843 const Teuchos::EVerbosityLevel verbLevel =
844 Teuchos::Describable::verbLevel_default)
const 846 using ::Tpetra::Details::gathervPrint;
847 using ::Teuchos::EVerbosityLevel;
848 using ::Teuchos::OSTab;
849 using ::Teuchos::TypeNameTraits;
850 using ::Teuchos::VERB_DEFAULT;
851 using ::Teuchos::VERB_LOW;
852 using ::Teuchos::VERB_MEDIUM;
855 const auto vl = (verbLevel == VERB_DEFAULT) ? VERB_LOW : verbLevel;
857 auto comm = this->getMap ().is_null () ?
858 Teuchos::null : this->getMap ()->getComm ();
859 const int myRank = comm.is_null () ? 0 : comm->getRank ();
862 if (vl != Teuchos::VERB_NONE) {
866 out <<
"\"Tpetra::Details::CooMatrix\":" << endl;
870 out <<
"Template parameters:" << endl;
873 out <<
"SC: " << TypeNameTraits<SC>::name () << endl
874 <<
"LO: " << TypeNameTraits<LO>::name () << endl
875 <<
"GO: " << TypeNameTraits<GO>::name () << endl
876 <<
"NT: " << TypeNameTraits<NT>::name () << endl;
878 if (this->getObjectLabel () !=
"") {
879 out <<
"Label: \"" << this->getObjectLabel () <<
"\"" << endl;
881 out <<
"Has Map: " << (this->map_.is_null () ?
"false" :
"true") << endl;
885 if (! this->map_.is_null ()) {
887 out <<
"Map:" << endl;
890 this->map_->describe (out, vl);
895 std::ostringstream os;
896 os <<
"Process " << myRank <<
":" << endl;
900 os <<
" Local number of entries: " << numEnt << endl;
901 if (vl > VERB_MEDIUM) {
902 os <<
" Local entries:" << endl;
904 this->impl_.
forAllEntries ([&os] (
const GO row,
const GO col,
const SC& val) {
926 Teuchos::RCP<const map_type>
927 buildMap (const ::Teuchos::RCP<const ::Teuchos::Comm<int> >& comm)
929 using ::Teuchos::outArg;
930 using ::Teuchos::rcp;
931 using ::Teuchos::REDUCE_MIN;
932 using ::Teuchos::reduceAll;
933 typedef ::Tpetra::global_size_t GST;
937 if (comm.is_null ()) {
938 return ::Teuchos::null;
949 std::vector<GO> rowInds;
953 GO gblMinGblRowInd = 0;
954 reduceAll<int, GO> (*comm, REDUCE_MIN, lclMinGblRowInd,
955 outArg (gblMinGblRowInd));
956 const GO indexBase = gblMinGblRowInd;
957 const GST INV = Tpetra::Details::OrdinalTraits<GST>::invalid ();
958 return rcp (
new map_type (INV, rowInds.data (), rowInds.size (),
967 return static_cast<size_t> (0);
978 const char prefix[] =
"Tpetra::Details::CooMatrix::checkSizes: ";
980 const this_type* src =
dynamic_cast<const this_type*
> (&source);
983 std::ostream& err = markLocalErrorAndGetStream ();
984 err << prefix <<
"The source object of the Import or Export " 985 "must be a CooMatrix with the same template parameters as the " 986 "target object." << endl;
988 else if (this->map_.is_null ()) {
989 std::ostream& err = markLocalErrorAndGetStream ();
990 err << prefix <<
"The target object of the Import or Export " 991 "must be a CooMatrix with a nonnull Map." << endl;
993 return ! (* (this->localError_));
1005 const size_t numSameIDs,
1006 const ::Kokkos::DualView<const LO*, device_type>& permuteToLIDs,
1007 const ::Kokkos::DualView<const LO*, device_type>& permuteFromLIDs)
1011 const char prefix[] =
"Tpetra::Details::CooMatrix::copyAndPermuteNew: ";
1016 if (* (this->localError_)) {
1017 std::ostream& err = this->markLocalErrorAndGetStream ();
1018 err << prefix <<
"The target object of the Import or Export is " 1019 "already in an error state." << endl;
1023 const this_type* src =
dynamic_cast<const this_type*
> (&sourceObject);
1025 std::ostream& err = this->markLocalErrorAndGetStream ();
1026 err << prefix <<
"Input argument 'sourceObject' is not a CooMatrix." 1031 const size_t numPermuteIDs =
1032 static_cast<size_t> (permuteToLIDs.dimension_0 ());
1033 if (numPermuteIDs != static_cast<size_t> (permuteFromLIDs.dimension_0 ())) {
1034 std::ostream& err = this->markLocalErrorAndGetStream ();
1035 err << prefix <<
"permuteToLIDs.dimension_0() = " 1036 << numPermuteIDs <<
" != permuteFromLIDs.dimension_0() = " 1037 << permuteFromLIDs.dimension_0 () <<
"." << endl;
1040 if (
sizeof (
int) <=
sizeof (
size_t) &&
1041 numPermuteIDs > static_cast<size_t> (std::numeric_limits<int>::max ())) {
1042 std::ostream& err = this->markLocalErrorAndGetStream ();
1043 err << prefix <<
"numPermuteIDs = " << numPermuteIDs
1044 <<
", a size_t, overflows int." << endl;
1054 if (
sizeof (
int) <=
sizeof (
size_t) &&
1055 numSameIDs > static_cast<size_t> (std::numeric_limits<int>::max ())) {
1056 std::ostream& err = this->markLocalErrorAndGetStream ();
1057 err << prefix <<
"numSameIDs = " << numSameIDs
1058 <<
", a size_t, overflows int." << endl;
1065 const LO numSame =
static_cast<int> (numSameIDs);
1070 LO numInvalidSameRows = 0;
1071 for (LO lclRow = 0; lclRow < numSame; ++lclRow) {
1075 const GO gblRow = this->map_->getGlobalElement (lclRow);
1076 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1077 ++numInvalidSameRows;
1090 const LO numPermute =
static_cast<int> (numPermuteIDs);
1095 LO numInvalidRowsFrom = 0;
1100 LO numInvalidRowsTo = 0;
1101 for (LO k = 0; k < numPermute; ++k) {
1102 const LO lclRowFrom = permuteFromLIDs.h_view(k);
1103 const LO lclRowTo = permuteToLIDs.h_view(k);
1104 const GO gblRowFrom = src->
map_->getGlobalElement (lclRowFrom);
1105 const GO gblRowTo = this->map_->getGlobalElement (lclRowTo);
1107 bool bothConversionsValid =
true;
1108 if (gblRowFrom == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1109 ++numInvalidRowsFrom;
1110 bothConversionsValid =
false;
1112 if (gblRowTo == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1114 bothConversionsValid =
false;
1116 if (bothConversionsValid) {
1117 this->impl_.
mergeIntoRow (gblRowTo, src->impl_, gblRowFrom);
1122 if (numInvalidSameRows != 0 || numInvalidRowsFrom != 0 || numInvalidRowsTo != 0) {
1125 std::vector<std::pair<LO, GO> > invalidSameRows;
1126 invalidSameRows.reserve (numInvalidSameRows);
1127 std::vector<std::pair<LO, GO> > invalidRowsFrom;
1128 invalidRowsFrom.reserve (numInvalidRowsFrom);
1129 std::vector<std::pair<LO, GO> > invalidRowsTo;
1130 invalidRowsTo.reserve (numInvalidRowsTo);
1132 for (LO lclRow = 0; lclRow < numSame; ++lclRow) {
1136 const GO gblRow = this->map_->getGlobalElement (lclRow);
1137 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1138 invalidSameRows.push_back ({lclRow, gblRow});
1142 for (LO k = 0; k < numPermute; ++k) {
1143 const LO lclRowFrom = permuteFromLIDs.h_view(k);
1144 const LO lclRowTo = permuteToLIDs.h_view(k);
1145 const GO gblRowFrom = src->
map_->getGlobalElement (lclRowFrom);
1146 const GO gblRowTo = this->map_->getGlobalElement (lclRowTo);
1148 if (gblRowFrom == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1149 invalidRowsFrom.push_back ({lclRowFrom, gblRowFrom});
1151 if (gblRowTo == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1152 invalidRowsTo.push_back ({lclRowTo, gblRowTo});
1156 std::ostringstream os;
1157 if (numInvalidSameRows != 0) {
1158 os <<
"Invalid permute \"same\" (local, global) index pairs: [";
1159 for (std::size_t k = 0; k < invalidSameRows.size (); ++k) {
1160 const auto& p = invalidSameRows[k];
1161 os <<
"(" << p.first <<
"," << p.second <<
")";
1162 if (k + 1 < invalidSameRows.size ()) {
1166 os <<
"]" << std::endl;
1168 if (numInvalidRowsFrom != 0) {
1169 os <<
"Invalid permute \"from\" (local, global) index pairs: [";
1170 for (std::size_t k = 0; k < invalidRowsFrom.size (); ++k) {
1171 const auto& p = invalidRowsFrom[k];
1172 os <<
"(" << p.first <<
"," << p.second <<
")";
1173 if (k + 1 < invalidRowsFrom.size ()) {
1177 os <<
"]" << std::endl;
1179 if (numInvalidRowsTo != 0) {
1180 os <<
"Invalid permute \"to\" (local, global) index pairs: [";
1181 for (std::size_t k = 0; k < invalidRowsTo.size (); ++k) {
1182 const auto& p = invalidRowsTo[k];
1183 os <<
"(" << p.first <<
"," << p.second <<
")";
1184 if (k + 1 < invalidRowsTo.size ()) {
1188 os <<
"]" << std::endl;
1191 std::ostream& err = this->markLocalErrorAndGetStream ();
1192 err << prefix << os.str ();
1201 const ::Kokkos::DualView<const local_ordinal_type*, device_type>& exportLIDs,
1202 ::Kokkos::DualView<packet_type*, device_type>& exports,
1203 const ::Kokkos::DualView<size_t*, device_type>& numPacketsPerLID,
1204 size_t& constantNumPackets,
1207 using ::Teuchos::Comm;
1208 using ::Teuchos::RCP;
1211 typedef ::Kokkos::DualView<packet_type*, device_type> out_buf_dv_type;
1212 const char prefix[] =
"Tpetra::Details::CooMatrix::packAndPrepareNew: ";
1213 const char suffix[] =
" This should never happen. " 1214 "Please report this bug to the Tpetra developers.";
1218 constantNumPackets = 0;
1220 const this_type* src =
dynamic_cast<const this_type*
> (&sourceObject);
1222 std::ostream& err = this->markLocalErrorAndGetStream ();
1223 err << prefix <<
"Input argument 'sourceObject' is not a CooMatrix." 1226 else if (* (src->localError_)) {
1227 std::ostream& err = this->markLocalErrorAndGetStream ();
1228 err << prefix <<
"The source (input) object of the Import or Export " 1229 "is already in an error state on this process." 1232 else if (* (this->localError_)) {
1233 std::ostream& err = this->markLocalErrorAndGetStream ();
1234 err << prefix <<
"The target (output, \"this\") object of the Import " 1235 "or Export is already in an error state on this process." << endl;
1240 if (* (this->localError_)) {
1242 exports = out_buf_dv_type (
"CooMatrix exports", 0);
1245 using ::Kokkos::DualView;
1246 DualView<size_t*, device_type> numPacketsPerLID_tmp = numPacketsPerLID;
1247 numPacketsPerLID_tmp.template sync<Kokkos::HostSpace> ();
1248 numPacketsPerLID_tmp.template modify<Kokkos::HostSpace> ();
1257 const size_t numExports = exportLIDs.dimension_0 ();
1258 if (numExports == 0) {
1259 exports = out_buf_dv_type (exports.h_view.label (), 0);
1262 RCP<const Comm<int> > comm = src->
getMap ().is_null () ?
1263 Teuchos::null : src->
getMap ()->getComm ();
1264 if (comm.is_null () || comm->getSize () == 1) {
1265 if (numExports != static_cast<size_t> (0)) {
1266 std::ostream& err = this->markLocalErrorAndGetStream ();
1267 err << prefix <<
"The input communicator is either null or " 1268 "has only one process, but numExports = " << numExports <<
" != 0." 1281 using ::Kokkos::DualView;
1282 DualView<size_t*, device_type> numPacketsPerLID_tmp = numPacketsPerLID;
1283 numPacketsPerLID_tmp.template sync<Kokkos::HostSpace> ();
1284 numPacketsPerLID_tmp.template modify<Kokkos::HostSpace> ();
1287 int totalNumPackets = 0;
1288 size_t numInvalidRowInds = 0;
1289 std::ostringstream errStrm;
1290 for (
size_t k = 0; k < numExports; ++k) {
1291 const LO lclRow = exportLIDs.h_view[k];
1294 const GO gblRow = src->
map_->getGlobalElement (lclRow);
1295 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1297 ++numInvalidRowInds;
1298 numPacketsPerLID.h_view[k] = 0;
1306 src->impl_.countPackRow (numPackets, gblRow, *comm, &errStrm);
1308 std::ostream& err = this->markLocalErrorAndGetStream ();
1309 err << prefix << errStrm.str () << endl;
1310 numPacketsPerLID.h_view[k] = 0;
1316 const long long newTotalNumPackets =
1317 static_cast<long long> (totalNumPackets) +
1318 static_cast<long long> (numPackets);
1319 if (newTotalNumPackets >
1320 static_cast<long long> (std::numeric_limits<int>::max ())) {
1321 std::ostream& err = this->markLocalErrorAndGetStream ();
1322 err << prefix <<
"The new total number of packets " 1323 << newTotalNumPackets <<
" does not fit in int." << endl;
1327 for (
size_t k2 = k; k2 < numExports; ++k2) {
1328 numPacketsPerLID.h_view[k2] = 0;
1332 numPacketsPerLID.h_view[k] =
static_cast<size_t> (numPackets);
1333 totalNumPackets =
static_cast<int> (newTotalNumPackets);
1338 if (numInvalidRowInds != 0) {
1339 std::vector<std::pair<LO, GO> > invalidRowInds;
1340 for (
size_t k = 0; k < numExports; ++k) {
1341 const LO lclRow = exportLIDs.h_view[k];
1345 const GO gblRow = src->
map_->getGlobalElement (lclRow);
1346 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1347 invalidRowInds.push_back ({lclRow, gblRow});
1350 std::ostringstream os;
1351 os << prefix <<
"We found " << numInvalidRowInds <<
" invalid row ind" 1352 << (numInvalidRowInds !=
static_cast<size_t> (1) ?
"ices" :
"ex")
1353 <<
" out of " << numExports <<
" in exportLIDs. Here is the list " 1354 <<
" of invalid row indices: [";
1355 for (
size_t k = 0; k < invalidRowInds.size (); ++k) {
1356 os <<
"(LID: " << invalidRowInds[k].first <<
", GID: " 1357 << invalidRowInds[k].second <<
")";
1358 if (k + 1 < invalidRowInds.size ()) {
1364 std::ostream& err = this->markLocalErrorAndGetStream ();
1365 err << prefix << os.str () << std::endl;
1369 if (static_cast<int> (exports.dimension_0 ()) != totalNumPackets) {
1370 exports = out_buf_dv_type (
"CooMatrix exports", totalNumPackets);
1371 exports.template sync<Kokkos::HostSpace> ();
1373 exports.template modify<Kokkos::HostSpace> ();
1377 std::vector<GO> gblRowInds;
1378 std::vector<GO> gblColInds;
1379 std::vector<SC> vals;
1381 int outBufCurPos = 0;
1382 packet_type* outBuf = exports.h_view.ptr_on_device ();
1383 for (
size_t k = 0; k < numExports; ++k) {
1384 const LO lclRow = exportLIDs.h_view[k];
1387 const GO gblRow = src->
map_->getGlobalElement (lclRow);
1389 src->impl_.packRow (outBuf, totalNumPackets, outBufCurPos, *comm,
1390 gblRowInds, gblColInds, vals, gblRow);
1401 const ::Kokkos::DualView<const packet_type*, device_type>& imports,
1402 const ::Kokkos::DualView<const size_t*, device_type>& numPacketsPerLID,
1407 using ::Kokkos::DualView;
1408 using ::Teuchos::Comm;
1409 using ::Teuchos::RCP;
1412 typedef typename device_type::memory_space DMS;
1413 typedef ::Kokkos::HostSpace HMS;
1414 const char prefix[] =
"Tpetra::Details::CooMatrix::unpackAndCombineNew: ";
1415 const char suffix[] =
" This should never happen. " 1416 "Please report this bug to the Tpetra developers.";
1418 const std::size_t numImports = importLIDs.dimension_0 ();
1419 if (numImports == 0) {
1422 else if (imports.dimension_0 () == 0) {
1423 std::ostream& err = this->markLocalErrorAndGetStream ();
1424 typename DualView<const LO*, device_type>::t_host importLIDs_h;
1426 if (importLIDs.template need_sync<HMS> ()) {
1429 auto importLIDs_d = importLIDs.template view<DMS> ();
1430 typedef typename decltype (importLIDs_h)::non_const_type HVNC;
1431 HVNC importLIDs_h_nc (importLIDs_d.label (), importLIDs.dimension_0 ());
1433 importLIDs_h = importLIDs_h_nc;
1436 importLIDs_h = importLIDs.h_view;
1439 err << prefix <<
"importLIDs.dimension_0() = " << numImports <<
" != 0, " 1440 <<
"but imports.dimension_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_view[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.dimension_0 ()) >
1474 static_cast<size_t> (std::numeric_limits<int>::max ())) {
1475 std::ostream& err = this->markLocalErrorAndGetStream ();
1476 err << prefix <<
"imports.dimension_0() = " 1477 << imports.dimension_0 () <<
" does not fit in int." << endl;
1480 const int inBufSize =
static_cast<int> (imports.dimension_0 ());
1485 typename std::decay<decltype (importLIDs)>::type::t_host importLIDs_h;
1486 typename std::decay<decltype (imports)>::type::t_host imports_h;
1487 typename std::decay<decltype (numPacketsPerLID)>::type::t_host numPacketsPerLID_h;
1489 if (importLIDs.template need_sync<HMS> ()) {
1491 auto importLIDs_d = importLIDs.template view<DMS> ();
1492 typedef typename decltype (importLIDs_h)::non_const_type HVNC;
1493 HVNC importLIDs_h_nc (importLIDs_d.label (),
1494 importLIDs.dimension_0 ());
1496 importLIDs_h = importLIDs_h_nc;
1499 importLIDs_h = importLIDs.h_view;
1502 if (imports.template need_sync<HMS> ()) {
1504 auto imports_d = imports.template view<DMS> ();
1505 typedef typename decltype (imports_h)::non_const_type HVNC;
1506 HVNC imports_h_nc (imports_d.label (),
1507 imports.dimension_0 ());
1509 imports_h = imports_h_nc;
1512 imports_h = imports.h_view;
1515 if (numPacketsPerLID.template need_sync<HMS> ()) {
1517 auto numPacketsPerLID_d = numPacketsPerLID.template view<DMS> ();
1518 typedef typename decltype (numPacketsPerLID_h)::non_const_type HVNC;
1519 HVNC numPacketsPerLID_h_nc (numPacketsPerLID_d.label (),
1520 numPacketsPerLID.dimension_0 ());
1522 numPacketsPerLID_h = numPacketsPerLID_h_nc;
1525 numPacketsPerLID_h = numPacketsPerLID.h_view;
1531 std::vector<GO> gblRowInds;
1532 std::vector<GO> gblColInds;
1533 std::vector<SC> vals;
1535 const packet_type* inBuf = imports_h.ptr_on_device ();
1536 int inBufCurPos = 0;
1537 size_t numInvalidRowInds = 0;
1539 std::ostringstream errStrm;
1540 for (
size_t k = 0; k < numImports; ++k) {
1541 const LO lclRow = importLIDs_h(k);
1542 const GO gblRow = this->map_->getGlobalElement (lclRow);
1543 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1544 ++numInvalidRowInds;
1550 const int origInBufCurPos = inBufCurPos;
1554 numEnt, *comm, &errStrm);
1555 if (errCode != 0 || numEnt < 0 || inBufCurPos < origInBufCurPos) {
1556 std::ostream& err = this->markLocalErrorAndGetStream ();
1558 err << prefix <<
"In unpack loop, k=" << k <<
": ";
1560 err <<
" unpackTriplesCount returned errCode = " << errCode
1561 <<
" != 0." << endl;
1564 err <<
" unpackTriplesCount returned errCode = 0, but numEnt = " 1565 << numEnt <<
" < 0." << endl;
1567 if (inBufCurPos < origInBufCurPos) {
1568 err <<
" After unpackTriplesCount, inBufCurPos = " << inBufCurPos
1569 <<
" < origInBufCurPos = " << origInBufCurPos <<
"." << endl;
1571 err <<
" unpackTriplesCount report: " << errStrm.str () << endl;
1572 err << suffix << endl;
1579 #ifdef HAVE_TPETRA_DEBUG 1586 #endif // HAVE_TPETRA_DEBUG 1591 gblRowInds.resize (numEnt);
1592 gblColInds.resize (numEnt);
1593 vals.resize (numEnt);
1596 gblRowInds.data (), gblColInds.data (),
1597 vals.data (), numEnt, *comm, &errStrm);
1599 std::ostream& err = this->markLocalErrorAndGetStream ();
1600 err << prefix <<
"unpackTriples returned errCode = " 1601 << errCode <<
" != 0. It reports: " << errStrm.str ()
1608 #ifdef HAVE_TPETRA_DEBUG 1615 #endif // HAVE_TPETRA_DEBUG 1617 this->sumIntoGlobalValues (gblRowInds.data (), gblColInds.data (),
1618 vals.data (), numEnt);
1623 if (numInvalidRowInds != 0) {
1627 std::ostream& err = this->markLocalErrorAndGetStream ();
1629 std::vector<std::pair<LO, GO> > invalidRowInds;
1630 for (
size_t k = 0; k < numImports; ++k) {
1631 const LO lclRow = importLIDs_h(k);
1632 const GO gblRow = this->map_->getGlobalElement (lclRow);
1633 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1634 invalidRowInds.push_back ({lclRow, gblRow});
1638 err << prefix <<
"We found " << numInvalidRowInds <<
" invalid row ind" 1639 << (numInvalidRowInds !=
static_cast<size_t> (1) ?
"ices" :
"ex")
1640 <<
" out of " << numImports <<
" in importLIDs. Here is the list " 1641 <<
" of invalid row indices: [";
1642 for (
size_t k = 0; k < invalidRowInds.size (); ++k) {
1643 err <<
"(LID: " << invalidRowInds[k].first <<
", GID: " 1644 << invalidRowInds[k].second <<
")";
1645 if (k + 1 < invalidRowInds.size ()) {
1658 #endif // TPETRA_DETAILS_COOMATRIX_HPP char packet_type
Type for packing and unpacking data.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
int packTriplesCount(const int, char [], const int, int &, const ::Teuchos::Comm< int > &, std::ostream *errStrm)
Pack the count (number) of matrix triples.
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.
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 Kokkos Node type.
virtual std::string description() const
One-line descriptiion of this object; overrides Teuchos::Describable method.
virtual size_t constantNumberOfPackets() const
By returning 0, tell DistObject that this class may not necessarily have a constant number of "packet...
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.
void deep_copy(MultiVector< DS, DL, DG, DN, dstClassic > &dst, const MultiVector< SS, SL, SG, SN, srcClassic > &src)
Copy the contents of the MultiVector src into dst.
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.
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 fillComplete()
Special version of fillComplete that assumes that the matrix already has a Map, and reuses its commun...
virtual ~CooMatrix()
Destructor (virtual for memory safety of derived classes).
Implementation details of Tpetra.
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.
GlobalOrdinal global_ordinal_type
The type of global indices.
LocalOrdinal local_ordinal_type
The type of local indices.
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 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...
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.
std::size_t getLclNumEntries() const
Number of entries in the sparse matrix on the calling process.
Type of each (row index, column index) pair in the Tpetra::Details::CooMatrix (see below)...
SC scalar_type
Type of each entry (value) in the sparse matrix.
CooMatrix()
Default constructor.
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.
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)...
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.
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.
std::size_t getLclNumEntries() const
Number of entries in the sparse matrix on the calling process.
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")...
Teuchos::RCP< const map_type > map_
The Map over which this object is distributed.
virtual bool useNewInterface()
Whether the subclass implements the "old" or "new" (Kokkos-friendly) interface (it implements the "ne...
virtual Teuchos::RCP< const map_type > getMap() const
The Map describing the parallel distribution of this object.
::Tpetra::Map< local_ordinal_type, global_ordinal_type, node_type > map_type
Type of the Map specialization to give to the constructor.
std::string errorMessages() const
The current stream of error messages.
bool localError() const
Whether this object had an error on the calling process.
virtual void packAndPrepareNew(const ::Tpetra::SrcDistObject &sourceObject, const ::Kokkos::DualView< const local_ordinal_type *, device_type > &exportLIDs, ::Kokkos::DualView< packet_type *, device_type > &exports, const ::Kokkos::DualView< size_t *, device_type > &numPacketsPerLID, size_t &constantNumPackets, ::Tpetra::Distributor &)
While we do use the "new" Kokkos::DualView - based interface, we don't currently use device Views...
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...
virtual void copyAndPermuteNew(const ::Tpetra::SrcDistObject &sourceObject, const size_t numSameIDs, const ::Kokkos::DualView< const LO *, device_type > &permuteToLIDs, const ::Kokkos::DualView< const LO *, device_type > &permuteFromLIDs)
While we do use the "new" Kokkos::DualView - based interface, we don't currently use device Views...
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 void unpackAndCombineNew(const ::Kokkos::DualView< const local_ordinal_type *, device_type > &importLIDs, const ::Kokkos::DualView< const packet_type *, device_type > &imports, const ::Kokkos::DualView< const size_t *, device_type > &numPacketsPerLID, const size_t, ::Tpetra::Distributor &, const ::Tpetra::CombineMode)
While we do use the "new" Kokkos::DualView - based interface, we don't currently use device Views...
Base class for distributed Tpetra objects that support data redistribution.
Implementation detail of Tpetra::Details::CooMatrix (which see below).
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...