532 typedef LO local_ordinal_type;
533 typedef GO global_ordinal_type;
535 typedef typename NT::device_type device_type;
537 typedef ::Tpetra::Map<local_ordinal_type, global_ordinal_type, node_type>
map_type;
601 const std::size_t
numEnt) {
609 std::initializer_list<SC>
vals,
610 const std::size_t
numEnt) {
621 template <
class OffsetType>
623 buildCrs(::Kokkos::View<OffsetType*, device_type>&
rowOffsets,
625 ::Kokkos::View<typename ::KokkosKernels::ArithTraits<SC>::val_type*, device_type>&
vals) {
626 static_assert(std::is_integral<OffsetType>::value,
627 "OffsetType must be a built-in integer type.");
628 using ::Kokkos::create_mirror_view;
629 using ::Kokkos::deep_copy;
630 using ::Kokkos::View;
631 typedef typename ::KokkosKernels::ArithTraits<SC>::val_type
ISC;
665 fillComplete(const ::Teuchos::RCP<const ::Teuchos::Comm<int> >& comm) {
666 if (comm.is_null()) {
667 this->
map_ = ::Teuchos::null;
669 this->
map_ = this->buildMap(comm);
685 "CooMatrix::fillComplete: This object does not yet have a Map. "
686 "You must call the version of fillComplete "
687 "that takes an input communicator.");
727 return ((*errs_).get() ==
NULL) ? std::string(
"") : (*errs_)->str();
743 std::shared_ptr<bool> localError_;
752 std::shared_ptr<std::shared_ptr<std::ostringstream> > errs_;
756 markLocalErrorAndGetStream() {
757 *(this->localError_) =
true;
758 if ((*errs_).get() ==
NULL) {
759 *errs_ = std::shared_ptr<std::ostringstream>(
new std::ostringstream());
768 using Teuchos::TypeNameTraits;
770 std::ostringstream
os;
771 os <<
"\"Tpetra::Details::CooMatrix\": {"
779 os <<
", Has Map: " << (this->
map_.is_null() ?
"false" :
"true")
788 const Teuchos::EVerbosityLevel
verbLevel =
789 Teuchos::Describable::verbLevel_default)
const {
791 using ::Teuchos::EVerbosityLevel;
792 using ::Teuchos::OSTab;
793 using ::Teuchos::TypeNameTraits;
794 using ::Teuchos::VERB_DEFAULT;
795 using ::Teuchos::VERB_LOW;
796 using ::Teuchos::VERB_MEDIUM;
797 using ::Tpetra::Details::gathervPrint;
801 auto comm = this->
getMap().is_null() ? Teuchos::null : this->
getMap()->getComm();
802 const int myRank = comm.is_null() ? 0 : comm->getRank();
805 if (
vl != Teuchos::VERB_NONE) {
809 out <<
"\"Tpetra::Details::CooMatrix\":" <<
endl;
813 out <<
"Template parameters:" <<
endl;
824 out <<
"Has Map: " << (this->
map_.is_null() ?
"false" :
"true") << endl;
828 if (!this->
map_.is_null()) {
833 this->
map_->describe(out,
vl);
838 std::ostringstream
os;
839 os <<
"Process " << myRank <<
":" <<
endl;
845 os <<
" Local entries:" <<
endl;
869 Teuchos::RCP<const map_type>
870 buildMap(const ::Teuchos::RCP<const ::Teuchos::Comm<int> >& comm) {
871 using ::Teuchos::outArg;
872 using ::Teuchos::rcp;
873 using ::Teuchos::REDUCE_MIN;
874 using ::Teuchos::reduceAll;
879 if (comm.is_null()) {
880 return ::Teuchos::null;
899 const GST INV = Tpetra::Details::OrdinalTraits<GST>::invalid();
909 return static_cast<size_t>(0);
919 const char prefix[] =
"Tpetra::Details::CooMatrix::checkSizes: ";
924 std::ostream&
err = markLocalErrorAndGetStream();
925 err <<
prefix <<
"The source object of the Import or Export "
926 "must be a CooMatrix with the same template parameters as the "
929 }
else if (this->
map_.is_null()) {
930 std::ostream&
err = markLocalErrorAndGetStream();
931 err <<
prefix <<
"The target object of the Import or Export "
932 "must be a CooMatrix with a nonnull Map."
935 return !(*(this->localError_));
940 typename ::Tpetra::DistObject<char, LO, GO, NT>::buffer_device_type;
943 copyAndPermute(const ::Tpetra::SrcDistObject&
sourceObject,
944 const size_t numSameIDs,
945 const Kokkos::DualView<
const LO*,
947 const Kokkos::DualView<
const LO*,
952 const char prefix[] =
"Tpetra::Details::CooMatrix::copyAndPermute: ";
957 if (*(this->localError_)) {
958 std::ostream&
err = this->markLocalErrorAndGetStream();
959 err <<
prefix <<
"The target object of the Import or Export is "
960 "already in an error state."
966 if (src ==
nullptr) {
967 std::ostream&
err = this->markLocalErrorAndGetStream();
968 err <<
prefix <<
"Input argument 'sourceObject' is not a CooMatrix."
976 std::ostream&
err = this->markLocalErrorAndGetStream();
977 err <<
prefix <<
"permuteToLIDs.extent(0) = "
982 if (
sizeof(
int) <=
sizeof(
size_t) &&
983 numPermuteIDs >
static_cast<size_t>(std::numeric_limits<int>::max())) {
984 std::ostream&
err = this->markLocalErrorAndGetStream();
986 <<
", a size_t, overflows int." <<
endl;
993 if (
sizeof(
int) <=
sizeof(
size_t) &&
994 numSameIDs >
static_cast<size_t>(std::numeric_limits<int>::max())) {
995 std::ostream&
err = this->markLocalErrorAndGetStream();
996 err <<
prefix <<
"numSameIDs = " << numSameIDs
997 <<
", a size_t, overflows int." <<
endl;
1004 const LO
numSame =
static_cast<int>(numSameIDs);
1015 if (
gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1049 const GO
gblRowTo = this->
map_->getGlobalElement(lclRowTo);
1052 if (
gblRowFrom == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1056 if (
gblRowTo == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1082 if (
gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1091 const GO
gblRowTo = this->
map_->getGlobalElement(lclRowTo);
1093 if (
gblRowFrom == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1096 if (
gblRowTo == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1101 std::ostringstream
os;
1103 os <<
"Invalid permute \"same\" (local, global) index pairs: [";
1106 os <<
"(" <<
p.first <<
"," <<
p.second <<
")";
1111 os <<
"]" << std::endl;
1114 os <<
"Invalid permute \"from\" (local, global) index pairs: [";
1117 os <<
"(" <<
p.first <<
"," <<
p.second <<
")";
1122 os <<
"]" << std::endl;
1125 os <<
"Invalid permute \"to\" (local, global) index pairs: [";
1128 os <<
"(" <<
p.first <<
"," <<
p.second <<
")";
1133 os <<
"]" << std::endl;
1136 std::ostream&
err = this->markLocalErrorAndGetStream();
1143 packAndPrepare(const ::Tpetra::SrcDistObject&
sourceObject,
1144 const Kokkos::DualView<
const local_ordinal_type*,
1148 Kokkos::DualView<
size_t*,
1153 using Teuchos::Comm;
1156 const char prefix[] =
"Tpetra::Details::CooMatrix::packAndPrepare: ";
1158 " This should never happen. "
1159 "Please report this bug to the Tpetra developers.";
1166 if (src ==
nullptr) {
1167 std::ostream&
err = this->markLocalErrorAndGetStream();
1168 err <<
prefix <<
"Input argument 'sourceObject' is not a CooMatrix."
1170 }
else if (*(src->localError_)) {
1171 std::ostream&
err = this->markLocalErrorAndGetStream();
1172 err <<
prefix <<
"The source (input) object of the Import or Export "
1173 "is already in an error state on this process."
1175 }
else if (*(this->localError_)) {
1176 std::ostream& err = this->markLocalErrorAndGetStream();
1177 err << prefix <<
"The target (output, \"this\") object of the Import "
1178 "or Export is already in an error state on this process."
1184 if (*(this->localError_)) {
1189 auto numPacketsPerLID_tmp = numPacketsPerLID;
1190 numPacketsPerLID_tmp.sync_host();
1191 numPacketsPerLID_tmp.modify_host();
1194 Kokkos::deep_copy(numPacketsPerLID.view_host(),
static_cast<size_t>(0));
1198 const size_t numExports = exportLIDs.extent(0);
1199 if (numExports == 0) {
1203 RCP<const Comm<int> > comm = src->getMap().is_null() ? Teuchos::null : src->getMap()->getComm();
1204 if (comm.is_null() || comm->getSize() == 1) {
1205 if (numExports !=
static_cast<size_t>(0)) {
1206 std::ostream& err = this->markLocalErrorAndGetStream();
1207 err << prefix <<
"The input communicator is either null or "
1208 "has only one process, but numExports = "
1209 << numExports <<
" != 0."
1220 numPacketsPerLID.sync_host();
1221 numPacketsPerLID.modify_host();
1223 TEUCHOS_ASSERT(!exportLIDs.need_sync_host());
1224 auto exportLIDs_h = exportLIDs.view_host();
1226 int totalNumPackets = 0;
1227 size_t numInvalidRowInds = 0;
1228 std::ostringstream errStrm;
1229 for (
size_t k = 0; k < numExports; ++k) {
1230 const LO lclRow = exportLIDs_h[k];
1233 const GO gblRow = src->map_->getGlobalElement(lclRow);
1234 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1236 ++numInvalidRowInds;
1237 numPacketsPerLID.view_host()[k] = 0;
1245 src->impl_.countPackRow(numPackets, gblRow, *comm, &errStrm);
1247 std::ostream& err = this->markLocalErrorAndGetStream();
1248 err << prefix << errStrm.str() << endl;
1249 numPacketsPerLID.view_host()[k] = 0;
1255 const long long newTotalNumPackets =
1256 static_cast<long long>(totalNumPackets) +
1257 static_cast<long long>(numPackets);
1258 if (newTotalNumPackets >
1259 static_cast<long long>(std::numeric_limits<int>::max())) {
1260 std::ostream& err = this->markLocalErrorAndGetStream();
1261 err << prefix <<
"The new total number of packets "
1262 << newTotalNumPackets <<
" does not fit in int." << endl;
1266 for (
size_t k2 = k; k2 < numExports; ++k2) {
1267 numPacketsPerLID.view_host()[k2] = 0;
1271 numPacketsPerLID.view_host()[k] =
static_cast<size_t>(numPackets);
1272 totalNumPackets =
static_cast<int>(newTotalNumPackets);
1277 if (numInvalidRowInds != 0) {
1278 std::vector<std::pair<LO, GO> > invalidRowInds;
1279 for (
size_t k = 0; k < numExports; ++k) {
1280 const LO lclRow = exportLIDs_h[k];
1284 const GO gblRow = src->map_->getGlobalElement(lclRow);
1285 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1286 invalidRowInds.push_back({lclRow, gblRow});
1289 std::ostringstream os;
1290 os << prefix <<
"We found " << numInvalidRowInds <<
" invalid row ind"
1291 << (numInvalidRowInds !=
static_cast<size_t>(1) ?
"ices" :
"ex")
1292 <<
" out of " << numExports <<
" in exportLIDs. Here is the list "
1293 <<
" of invalid row indices: [";
1294 for (
size_t k = 0; k < invalidRowInds.size(); ++k) {
1295 os <<
"(LID: " << invalidRowInds[k].first <<
", GID: "
1296 << invalidRowInds[k].second <<
")";
1297 if (k + 1 < invalidRowInds.size()) {
1303 std::ostream& err = this->markLocalErrorAndGetStream();
1304 err << prefix << os.str() << std::endl;
1309 const bool reallocated =
1311 "CooMatrix exports");
1313 exports.sync_host();
1316 exports.modify_host();
1320 std::vector<GO> gblRowInds;
1321 std::vector<GO> gblColInds;
1322 std::vector<SC> vals;
1324 int outBufCurPos = 0;
1326 for (
size_t k = 0; k < numExports; ++k) {
1327 const LO lclRow = exportLIDs.view_host()[k];
1330 const GO gblRow = src->map_->getGlobalElement(lclRow);
1332 src->impl_.packRow(outBuf, totalNumPackets, outBufCurPos, *comm,
1333 gblRowInds, gblColInds, vals, gblRow);
1338 unpackAndCombine(
const Kokkos::DualView<
const local_ordinal_type*,
1343 Kokkos::DualView<
size_t*,
1347 const ::Tpetra::CombineMode ) {
1349 using Teuchos::Comm;
1351 const char prefix[] =
"Tpetra::Details::CooMatrix::unpackAndCombine: ";
1352 const char suffix[] =
1353 " This should never happen. "
1354 "Please report this bug to the Tpetra developers.";
1356 TEUCHOS_ASSERT(!importLIDs.need_sync_host());
1357 auto importLIDs_h = importLIDs.view_host();
1359 const std::size_t numImports = importLIDs.extent(0);
1360 if (numImports == 0) {
1362 }
else if (imports.extent(0) == 0) {
1363 std::ostream& err = this->markLocalErrorAndGetStream();
1364 err << prefix <<
"importLIDs.extent(0) = " << numImports <<
" != 0, "
1365 <<
"but imports.extent(0) = 0. This doesn't make sense, because "
1366 <<
"for every incoming LID, CooMatrix packs at least the count of "
1367 <<
"triples associated with that LID, even if the count is zero. "
1368 <<
"importLIDs = [";
1369 for (std::size_t k = 0; k < numImports; ++k) {
1370 err << importLIDs_h[k];
1371 if (k + 1 < numImports) {
1375 err <<
"]. " << suffix << endl;
1379 RCP<const Comm<int> > comm = this->
getMap().is_null() ? Teuchos::null : this->
getMap()->getComm();
1380 if (comm.is_null() || comm->getSize() == 1) {
1381 if (numImports !=
static_cast<size_t>(0)) {
1382 std::ostream& err = this->markLocalErrorAndGetStream();
1383 err << prefix <<
"The input communicator is either null or "
1384 "has only one process, but numImports = "
1385 << numImports <<
" != 0."
1398 if (
static_cast<size_t>(imports.extent(0)) >
1399 static_cast<size_t>(std::numeric_limits<int>::max())) {
1400 std::ostream& err = this->markLocalErrorAndGetStream();
1401 err << prefix <<
"imports.extent(0) = "
1402 << imports.extent(0) <<
" does not fit in int." << endl;
1405 const int inBufSize =
static_cast<int>(imports.extent(0));
1407 if (imports.need_sync_host()) {
1408 imports.sync_host();
1410 if (numPacketsPerLID.need_sync_host()) {
1411 numPacketsPerLID.sync_host();
1413 auto imports_h = imports.view_host();
1414 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
1418 std::vector<GO> gblRowInds;
1419 std::vector<GO> gblColInds;
1420 std::vector<SC> vals;
1423 int inBufCurPos = 0;
1424 size_t numInvalidRowInds = 0;
1426 std::ostringstream errStrm;
1427 for (
size_t k = 0; k < numImports; ++k) {
1428 const LO lclRow = importLIDs_h(k);
1429 const GO gblRow = this->
map_->getGlobalElement(lclRow);
1430 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1431 ++numInvalidRowInds;
1437 const int origInBufCurPos = inBufCurPos;
1441 numEnt, *comm, &errStrm);
1442 if (errCode != 0 || numEnt < 0 || inBufCurPos < origInBufCurPos) {
1443 std::ostream& err = this->markLocalErrorAndGetStream();
1445 err << prefix <<
"In unpack loop, k=" << k <<
": ";
1447 err <<
" unpackTriplesCount returned errCode = " << errCode
1448 <<
" != 0." << endl;
1451 err <<
" unpackTriplesCount returned errCode = 0, but numEnt = "
1452 << numEnt <<
" < 0." << endl;
1454 if (inBufCurPos < origInBufCurPos) {
1455 err <<
" After unpackTriplesCount, inBufCurPos = " << inBufCurPos
1456 <<
" < origInBufCurPos = " << origInBufCurPos <<
"." << endl;
1458 err <<
" unpackTriplesCount report: " << errStrm.str() << endl;
1459 err << suffix << endl;
1466#ifdef HAVE_TPETRA_DEBUG
1478 gblRowInds.resize(numEnt);
1479 gblColInds.resize(numEnt);
1480 vals.resize(numEnt);
1483 gblRowInds.data(), gblColInds.data(),
1484 vals.data(), numEnt, *comm, &errStrm);
1486 std::ostream& err = this->markLocalErrorAndGetStream();
1487 err << prefix <<
"unpackTriples returned errCode = "
1488 << errCode <<
" != 0. It reports: " << errStrm.str()
1495#ifdef HAVE_TPETRA_DEBUG
1505 vals.data(), numEnt);
1510 if (numInvalidRowInds != 0) {
1514 std::ostream& err = this->markLocalErrorAndGetStream();
1516 std::vector<std::pair<LO, GO> > invalidRowInds;
1517 for (
size_t k = 0; k < numImports; ++k) {
1518 const LO lclRow = importLIDs_h(k);
1519 const GO gblRow = this->
map_->getGlobalElement(lclRow);
1520 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1521 invalidRowInds.push_back({lclRow, gblRow});
1525 err << prefix <<
"We found " << numInvalidRowInds <<
" invalid row ind"
1526 << (numInvalidRowInds !=
static_cast<size_t>(1) ?
"ices" :
"ex")
1527 <<
" out of " << numImports <<
" in importLIDs. Here is the list "
1528 <<
" of invalid row indices: [";
1529 for (
size_t k = 0; k < invalidRowInds.size(); ++k) {
1530 err <<
"(LID: " << invalidRowInds[k].first <<
", GID: "
1531 << invalidRowInds[k].second <<
")";
1532 if (k + 1 < invalidRowInds.size()) {