531 typedef LO local_ordinal_type;
532 typedef GO global_ordinal_type;
534 typedef typename NT::device_type device_type;
536 typedef ::Tpetra::Map<local_ordinal_type, global_ordinal_type, node_type>
map_type;
600 const std::size_t
numEnt) {
608 std::initializer_list<SC>
vals,
609 const std::size_t
numEnt) {
620 template <
class OffsetType>
622 buildCrs(::Kokkos::View<OffsetType*, device_type>&
rowOffsets,
624 ::Kokkos::View<typename ::KokkosKernels::ArithTraits<SC>::val_type*, device_type>&
vals) {
625 static_assert(std::is_integral<OffsetType>::value,
626 "OffsetType must be a built-in integer type.");
627 using ::Kokkos::create_mirror_view;
628 using ::Kokkos::deep_copy;
629 using ::Kokkos::View;
630 typedef typename ::KokkosKernels::ArithTraits<SC>::val_type
ISC;
664 fillComplete(const ::Teuchos::RCP<const ::Teuchos::Comm<int> >& comm) {
665 if (comm.is_null()) {
666 this->
map_ = ::Teuchos::null;
668 this->
map_ = this->buildMap(comm);
684 "CooMatrix::fillComplete: This object does not yet have a Map. "
685 "You must call the version of fillComplete "
686 "that takes an input communicator.");
726 return ((*errs_).get() ==
NULL) ? std::string(
"") : (*errs_)->str();
742 std::shared_ptr<bool> localError_;
751 std::shared_ptr<std::shared_ptr<std::ostringstream> > errs_;
755 markLocalErrorAndGetStream() {
756 *(this->localError_) =
true;
757 if ((*errs_).get() ==
NULL) {
758 *errs_ = std::shared_ptr<std::ostringstream>(
new std::ostringstream());
767 using Teuchos::TypeNameTraits;
769 std::ostringstream
os;
770 os <<
"\"Tpetra::Details::CooMatrix\": {"
778 os <<
", Has Map: " << (this->
map_.is_null() ?
"false" :
"true")
787 const Teuchos::EVerbosityLevel
verbLevel =
788 Teuchos::Describable::verbLevel_default)
const {
790 using ::Teuchos::EVerbosityLevel;
791 using ::Teuchos::OSTab;
792 using ::Teuchos::TypeNameTraits;
793 using ::Teuchos::VERB_DEFAULT;
794 using ::Teuchos::VERB_LOW;
795 using ::Teuchos::VERB_MEDIUM;
796 using ::Tpetra::Details::gathervPrint;
800 auto comm = this->
getMap().is_null() ? Teuchos::null : this->
getMap()->getComm();
801 const int myRank = comm.is_null() ? 0 : comm->getRank();
804 if (
vl != Teuchos::VERB_NONE) {
808 out <<
"\"Tpetra::Details::CooMatrix\":" <<
endl;
812 out <<
"Template parameters:" <<
endl;
823 out <<
"Has Map: " << (this->
map_.is_null() ?
"false" :
"true") << endl;
827 if (!this->
map_.is_null()) {
832 this->
map_->describe(out,
vl);
837 std::ostringstream
os;
844 os <<
" Local entries:" <<
endl;
868 Teuchos::RCP<const map_type>
869 buildMap(const ::Teuchos::RCP<const ::Teuchos::Comm<int> >& comm) {
870 using ::Teuchos::outArg;
871 using ::Teuchos::rcp;
872 using ::Teuchos::REDUCE_MIN;
873 using ::Teuchos::reduceAll;
878 if (comm.is_null()) {
879 return ::Teuchos::null;
898 const GST INV = Tpetra::Details::OrdinalTraits<GST>::invalid();
908 return static_cast<size_t>(0);
918 const char prefix[] =
"Tpetra::Details::CooMatrix::checkSizes: ";
923 std::ostream&
err = markLocalErrorAndGetStream();
924 err <<
prefix <<
"The source object of the Import or Export "
925 "must be a CooMatrix with the same template parameters as the "
928 }
else if (this->
map_.is_null()) {
929 std::ostream&
err = markLocalErrorAndGetStream();
930 err <<
prefix <<
"The target object of the Import or Export "
931 "must be a CooMatrix with a nonnull Map."
934 return !(*(this->localError_));
939 typename ::Tpetra::DistObject<char, LO, GO, NT>::buffer_device_type;
942 copyAndPermute(const ::Tpetra::SrcDistObject&
sourceObject,
943 const size_t numSameIDs,
944 const Kokkos::DualView<
const LO*,
946 const Kokkos::DualView<
const LO*,
951 const char prefix[] =
"Tpetra::Details::CooMatrix::copyAndPermute: ";
956 if (*(this->localError_)) {
957 std::ostream&
err = this->markLocalErrorAndGetStream();
958 err <<
prefix <<
"The target object of the Import or Export is "
959 "already in an error state."
965 if (src ==
nullptr) {
966 std::ostream&
err = this->markLocalErrorAndGetStream();
967 err <<
prefix <<
"Input argument 'sourceObject' is not a CooMatrix."
975 std::ostream&
err = this->markLocalErrorAndGetStream();
976 err <<
prefix <<
"permuteToLIDs.extent(0) = "
981 if (
sizeof(
int) <=
sizeof(
size_t) &&
982 numPermuteIDs >
static_cast<size_t>(std::numeric_limits<int>::max())) {
983 std::ostream&
err = this->markLocalErrorAndGetStream();
985 <<
", a size_t, overflows int." <<
endl;
992 if (
sizeof(
int) <=
sizeof(
size_t) &&
993 numSameIDs >
static_cast<size_t>(std::numeric_limits<int>::max())) {
994 std::ostream&
err = this->markLocalErrorAndGetStream();
995 err <<
prefix <<
"numSameIDs = " << numSameIDs
996 <<
", a size_t, overflows int." <<
endl;
1003 const LO
numSame =
static_cast<int>(numSameIDs);
1014 if (
gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1048 const GO
gblRowTo = this->
map_->getGlobalElement(lclRowTo);
1051 if (
gblRowFrom == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1055 if (
gblRowTo == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1081 if (
gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1090 const GO
gblRowTo = this->
map_->getGlobalElement(lclRowTo);
1092 if (
gblRowFrom == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1095 if (
gblRowTo == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1100 std::ostringstream
os;
1102 os <<
"Invalid permute \"same\" (local, global) index pairs: [";
1105 os <<
"(" <<
p.first <<
"," <<
p.second <<
")";
1110 os <<
"]" << std::endl;
1113 os <<
"Invalid permute \"from\" (local, global) index pairs: [";
1116 os <<
"(" <<
p.first <<
"," <<
p.second <<
")";
1121 os <<
"]" << std::endl;
1124 os <<
"Invalid permute \"to\" (local, global) index pairs: [";
1127 os <<
"(" <<
p.first <<
"," <<
p.second <<
")";
1132 os <<
"]" << std::endl;
1135 std::ostream&
err = this->markLocalErrorAndGetStream();
1142 packAndPrepare(const ::Tpetra::SrcDistObject&
sourceObject,
1143 const Kokkos::DualView<
const local_ordinal_type*,
1147 Kokkos::DualView<
size_t*,
1152 using Teuchos::Comm;
1155 const char prefix[] =
"Tpetra::Details::CooMatrix::packAndPrepare: ";
1157 " This should never happen. "
1158 "Please report this bug to the Tpetra developers.";
1165 if (src ==
nullptr) {
1166 std::ostream&
err = this->markLocalErrorAndGetStream();
1167 err <<
prefix <<
"Input argument 'sourceObject' is not a CooMatrix."
1169 }
else if (*(src->localError_)) {
1170 std::ostream&
err = this->markLocalErrorAndGetStream();
1171 err <<
prefix <<
"The source (input) object of the Import or Export "
1172 "is already in an error state on this process."
1174 }
else if (*(this->localError_)) {
1175 std::ostream& err = this->markLocalErrorAndGetStream();
1176 err << prefix <<
"The target (output, \"this\") object of the Import "
1177 "or Export is already in an error state on this process."
1183 if (*(this->localError_)) {
1188 auto numPacketsPerLID_tmp = numPacketsPerLID;
1189 numPacketsPerLID_tmp.sync_host();
1190 numPacketsPerLID_tmp.modify_host();
1193 Kokkos::deep_copy(numPacketsPerLID.view_host(),
static_cast<size_t>(0));
1197 const size_t numExports = exportLIDs.extent(0);
1198 if (numExports == 0) {
1202 RCP<const Comm<int> > comm = src->getMap().is_null() ? Teuchos::null : src->getMap()->getComm();
1203 if (comm.is_null() || comm->getSize() == 1) {
1204 if (numExports !=
static_cast<size_t>(0)) {
1205 std::ostream& err = this->markLocalErrorAndGetStream();
1206 err << prefix <<
"The input communicator is either null or "
1207 "has only one process, but numExports = "
1208 << numExports <<
" != 0."
1219 numPacketsPerLID.sync_host();
1220 numPacketsPerLID.modify_host();
1222 TEUCHOS_ASSERT(!exportLIDs.need_sync_host());
1223 auto exportLIDs_h = exportLIDs.view_host();
1225 int totalNumPackets = 0;
1226 size_t numInvalidRowInds = 0;
1227 std::ostringstream errStrm;
1228 for (
size_t k = 0; k < numExports; ++k) {
1229 const LO lclRow = exportLIDs_h[k];
1232 const GO gblRow = src->map_->getGlobalElement(lclRow);
1233 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1235 ++numInvalidRowInds;
1236 numPacketsPerLID.view_host()[k] = 0;
1244 src->impl_.countPackRow(numPackets, gblRow, *comm, &errStrm);
1246 std::ostream& err = this->markLocalErrorAndGetStream();
1247 err << prefix << errStrm.str() << endl;
1248 numPacketsPerLID.view_host()[k] = 0;
1254 const long long newTotalNumPackets =
1255 static_cast<long long>(totalNumPackets) +
1256 static_cast<long long>(numPackets);
1257 if (newTotalNumPackets >
1258 static_cast<long long>(std::numeric_limits<int>::max())) {
1259 std::ostream& err = this->markLocalErrorAndGetStream();
1260 err << prefix <<
"The new total number of packets "
1261 << newTotalNumPackets <<
" does not fit in int." << endl;
1265 for (
size_t k2 = k; k2 < numExports; ++k2) {
1266 numPacketsPerLID.view_host()[k2] = 0;
1270 numPacketsPerLID.view_host()[k] =
static_cast<size_t>(numPackets);
1271 totalNumPackets =
static_cast<int>(newTotalNumPackets);
1276 if (numInvalidRowInds != 0) {
1277 std::vector<std::pair<LO, GO> > invalidRowInds;
1278 for (
size_t k = 0; k < numExports; ++k) {
1279 const LO lclRow = exportLIDs_h[k];
1283 const GO gblRow = src->map_->getGlobalElement(lclRow);
1284 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1285 invalidRowInds.push_back({lclRow, gblRow});
1288 std::ostringstream os;
1289 os << prefix <<
"We found " << numInvalidRowInds <<
" invalid row ind"
1290 << (numInvalidRowInds !=
static_cast<size_t>(1) ?
"ices" :
"ex")
1291 <<
" out of " << numExports <<
" in exportLIDs. Here is the list "
1292 <<
" of invalid row indices: [";
1293 for (
size_t k = 0; k < invalidRowInds.size(); ++k) {
1294 os <<
"(LID: " << invalidRowInds[k].first <<
", GID: "
1295 << invalidRowInds[k].second <<
")";
1296 if (k + 1 < invalidRowInds.size()) {
1302 std::ostream& err = this->markLocalErrorAndGetStream();
1303 err << prefix << os.str() << std::endl;
1308 const bool reallocated =
1310 "CooMatrix exports");
1312 exports.sync_host();
1315 exports.modify_host();
1319 std::vector<GO> gblRowInds;
1320 std::vector<GO> gblColInds;
1321 std::vector<SC> vals;
1323 int outBufCurPos = 0;
1325 for (
size_t k = 0; k < numExports; ++k) {
1326 const LO lclRow = exportLIDs.view_host()[k];
1329 const GO gblRow = src->map_->getGlobalElement(lclRow);
1331 src->impl_.packRow(outBuf, totalNumPackets, outBufCurPos, *comm,
1332 gblRowInds, gblColInds, vals, gblRow);
1337 unpackAndCombine(
const Kokkos::DualView<
const local_ordinal_type*,
1342 Kokkos::DualView<
size_t*,
1346 const ::Tpetra::CombineMode ) {
1348 using Teuchos::Comm;
1350 const char prefix[] =
"Tpetra::Details::CooMatrix::unpackAndCombine: ";
1351 const char suffix[] =
1352 " This should never happen. "
1353 "Please report this bug to the Tpetra developers.";
1355 TEUCHOS_ASSERT(!importLIDs.need_sync_host());
1356 auto importLIDs_h = importLIDs.view_host();
1358 const std::size_t numImports = importLIDs.extent(0);
1359 if (numImports == 0) {
1361 }
else if (imports.extent(0) == 0) {
1362 std::ostream& err = this->markLocalErrorAndGetStream();
1363 err << prefix <<
"importLIDs.extent(0) = " << numImports <<
" != 0, "
1364 <<
"but imports.extent(0) = 0. This doesn't make sense, because "
1365 <<
"for every incoming LID, CooMatrix packs at least the count of "
1366 <<
"triples associated with that LID, even if the count is zero. "
1367 <<
"importLIDs = [";
1368 for (std::size_t k = 0; k < numImports; ++k) {
1369 err << importLIDs_h[k];
1370 if (k + 1 < numImports) {
1374 err <<
"]. " << suffix << endl;
1378 RCP<const Comm<int> > comm = this->
getMap().is_null() ? Teuchos::null : this->
getMap()->getComm();
1379 if (comm.is_null() || comm->getSize() == 1) {
1380 if (numImports !=
static_cast<size_t>(0)) {
1381 std::ostream& err = this->markLocalErrorAndGetStream();
1382 err << prefix <<
"The input communicator is either null or "
1383 "has only one process, but numImports = "
1384 << numImports <<
" != 0."
1397 if (
static_cast<size_t>(imports.extent(0)) >
1398 static_cast<size_t>(std::numeric_limits<int>::max())) {
1399 std::ostream& err = this->markLocalErrorAndGetStream();
1400 err << prefix <<
"imports.extent(0) = "
1401 << imports.extent(0) <<
" does not fit in int." << endl;
1404 const int inBufSize =
static_cast<int>(imports.extent(0));
1406 if (imports.need_sync_host()) {
1407 imports.sync_host();
1409 if (numPacketsPerLID.need_sync_host()) {
1410 numPacketsPerLID.sync_host();
1412 auto imports_h = imports.view_host();
1413 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
1417 std::vector<GO> gblRowInds;
1418 std::vector<GO> gblColInds;
1419 std::vector<SC> vals;
1422 int inBufCurPos = 0;
1423 size_t numInvalidRowInds = 0;
1425 std::ostringstream errStrm;
1426 for (
size_t k = 0; k < numImports; ++k) {
1427 const LO lclRow = importLIDs_h(k);
1428 const GO gblRow = this->
map_->getGlobalElement(lclRow);
1429 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1430 ++numInvalidRowInds;
1436 const int origInBufCurPos = inBufCurPos;
1440 numEnt, *comm, &errStrm);
1441 if (errCode != 0 || numEnt < 0 || inBufCurPos < origInBufCurPos) {
1442 std::ostream& err = this->markLocalErrorAndGetStream();
1444 err << prefix <<
"In unpack loop, k=" << k <<
": ";
1446 err <<
" unpackTriplesCount returned errCode = " << errCode
1447 <<
" != 0." << endl;
1450 err <<
" unpackTriplesCount returned errCode = 0, but numEnt = "
1451 << numEnt <<
" < 0." << endl;
1453 if (inBufCurPos < origInBufCurPos) {
1454 err <<
" After unpackTriplesCount, inBufCurPos = " << inBufCurPos
1455 <<
" < origInBufCurPos = " << origInBufCurPos <<
"." << endl;
1457 err <<
" unpackTriplesCount report: " << errStrm.str() << endl;
1458 err << suffix << endl;
1465#ifdef HAVE_TPETRA_DEBUG
1477 gblRowInds.resize(numEnt);
1478 gblColInds.resize(numEnt);
1479 vals.resize(numEnt);
1482 gblRowInds.data(), gblColInds.data(),
1483 vals.data(), numEnt, *comm, &errStrm);
1485 std::ostream& err = this->markLocalErrorAndGetStream();
1486 err << prefix <<
"unpackTriples returned errCode = "
1487 << errCode <<
" != 0. It reports: " << errStrm.str()
1494#ifdef HAVE_TPETRA_DEBUG
1504 vals.data(), numEnt);
1509 if (numInvalidRowInds != 0) {
1513 std::ostream& err = this->markLocalErrorAndGetStream();
1515 std::vector<std::pair<LO, GO> > invalidRowInds;
1516 for (
size_t k = 0; k < numImports; ++k) {
1517 const LO lclRow = importLIDs_h(k);
1518 const GO gblRow = this->
map_->getGlobalElement(lclRow);
1519 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1520 invalidRowInds.push_back({lclRow, gblRow});
1524 err << prefix <<
"We found " << numInvalidRowInds <<
" invalid row ind"
1525 << (numInvalidRowInds !=
static_cast<size_t>(1) ?
"ices" :
"ex")
1526 <<
" out of " << numImports <<
" in importLIDs. Here is the list "
1527 <<
" of invalid row indices: [";
1528 for (
size_t k = 0; k < invalidRowInds.size(); ++k) {
1529 err <<
"(LID: " << invalidRowInds[k].first <<
", GID: "
1530 << invalidRowInds[k].second <<
")";
1531 if (k + 1 < invalidRowInds.size()) {