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,
625 ::Kokkos::View<typename ::KokkosKernels::ArithTraits<SC>::val_type*, device_type>&
vals) {
627 ::Kokkos::View<typename ::Kokkos::ArithTraits<SC>::val_type*, device_type>&
vals) {
629 static_assert(std::is_integral<OffsetType>::value,
630 "OffsetType must be a built-in integer type.");
631 using ::Kokkos::create_mirror_view;
632 using ::Kokkos::deep_copy;
633 using ::Kokkos::View;
634#if KOKKOS_VERSION >= 40799
635 typedef typename ::KokkosKernels::ArithTraits<SC>::val_type
ISC;
637 typedef typename ::Kokkos::ArithTraits<SC>::val_type
ISC;
672 fillComplete(const ::Teuchos::RCP<const ::Teuchos::Comm<int> >& comm) {
673 if (comm.is_null()) {
674 this->
map_ = ::Teuchos::null;
676 this->
map_ = this->buildMap(comm);
692 "CooMatrix::fillComplete: This object does not yet have a Map. "
693 "You must call the version of fillComplete "
694 "that takes an input communicator.");
734 return ((*errs_).get() ==
NULL) ? std::string(
"") : (*errs_)->str();
750 std::shared_ptr<bool> localError_;
759 std::shared_ptr<std::shared_ptr<std::ostringstream> > errs_;
763 markLocalErrorAndGetStream() {
764 *(this->localError_) =
true;
765 if ((*errs_).get() ==
NULL) {
766 *errs_ = std::shared_ptr<std::ostringstream>(
new std::ostringstream());
775 using Teuchos::TypeNameTraits;
777 std::ostringstream
os;
778 os <<
"\"Tpetra::Details::CooMatrix\": {"
786 os <<
", Has Map: " << (this->
map_.is_null() ?
"false" :
"true")
795 const Teuchos::EVerbosityLevel
verbLevel =
796 Teuchos::Describable::verbLevel_default)
const {
798 using ::Teuchos::EVerbosityLevel;
799 using ::Teuchos::OSTab;
800 using ::Teuchos::TypeNameTraits;
801 using ::Teuchos::VERB_DEFAULT;
802 using ::Teuchos::VERB_LOW;
803 using ::Teuchos::VERB_MEDIUM;
804 using ::Tpetra::Details::gathervPrint;
808 auto comm = this->
getMap().is_null() ? Teuchos::null : this->
getMap()->getComm();
809 const int myRank = comm.is_null() ? 0 : comm->getRank();
812 if (
vl != Teuchos::VERB_NONE) {
816 out <<
"\"Tpetra::Details::CooMatrix\":" <<
endl;
820 out <<
"Template parameters:" <<
endl;
831 out <<
"Has Map: " << (this->
map_.is_null() ?
"false" :
"true") << endl;
835 if (!this->
map_.is_null()) {
840 this->
map_->describe(out,
vl);
845 std::ostringstream
os;
852 os <<
" Local entries:" <<
endl;
876 Teuchos::RCP<const map_type>
877 buildMap(const ::Teuchos::RCP<const ::Teuchos::Comm<int> >& comm) {
878 using ::Teuchos::outArg;
879 using ::Teuchos::rcp;
880 using ::Teuchos::REDUCE_MIN;
881 using ::Teuchos::reduceAll;
886 if (comm.is_null()) {
887 return ::Teuchos::null;
906 const GST INV = Tpetra::Details::OrdinalTraits<GST>::invalid();
916 return static_cast<size_t>(0);
926 const char prefix[] =
"Tpetra::Details::CooMatrix::checkSizes: ";
931 std::ostream&
err = markLocalErrorAndGetStream();
932 err <<
prefix <<
"The source object of the Import or Export "
933 "must be a CooMatrix with the same template parameters as the "
936 }
else if (this->
map_.is_null()) {
937 std::ostream&
err = markLocalErrorAndGetStream();
938 err <<
prefix <<
"The target object of the Import or Export "
939 "must be a CooMatrix with a nonnull Map."
942 return !(*(this->localError_));
947 typename ::Tpetra::DistObject<char, LO, GO, NT>::buffer_device_type;
950 copyAndPermute(const ::Tpetra::SrcDistObject&
sourceObject,
951 const size_t numSameIDs,
952 const Kokkos::DualView<
const LO*,
954 const Kokkos::DualView<
const LO*,
959 const char prefix[] =
"Tpetra::Details::CooMatrix::copyAndPermute: ";
964 if (*(this->localError_)) {
965 std::ostream&
err = this->markLocalErrorAndGetStream();
966 err <<
prefix <<
"The target object of the Import or Export is "
967 "already in an error state."
973 if (src ==
nullptr) {
974 std::ostream&
err = this->markLocalErrorAndGetStream();
975 err <<
prefix <<
"Input argument 'sourceObject' is not a CooMatrix."
983 std::ostream&
err = this->markLocalErrorAndGetStream();
984 err <<
prefix <<
"permuteToLIDs.extent(0) = "
989 if (
sizeof(
int) <=
sizeof(
size_t) &&
990 numPermuteIDs >
static_cast<size_t>(std::numeric_limits<int>::max())) {
991 std::ostream&
err = this->markLocalErrorAndGetStream();
993 <<
", a size_t, overflows int." <<
endl;
1000 if (
sizeof(
int) <=
sizeof(
size_t) &&
1001 numSameIDs >
static_cast<size_t>(std::numeric_limits<int>::max())) {
1002 std::ostream&
err = this->markLocalErrorAndGetStream();
1003 err <<
prefix <<
"numSameIDs = " << numSameIDs
1004 <<
", a size_t, overflows int." <<
endl;
1011 const LO
numSame =
static_cast<int>(numSameIDs);
1022 if (
gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1056 const GO
gblRowTo = this->
map_->getGlobalElement(lclRowTo);
1059 if (
gblRowFrom == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1063 if (
gblRowTo == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1089 if (
gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1098 const GO
gblRowTo = this->
map_->getGlobalElement(lclRowTo);
1100 if (
gblRowFrom == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1103 if (
gblRowTo == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1108 std::ostringstream
os;
1110 os <<
"Invalid permute \"same\" (local, global) index pairs: [";
1113 os <<
"(" <<
p.first <<
"," <<
p.second <<
")";
1118 os <<
"]" << std::endl;
1121 os <<
"Invalid permute \"from\" (local, global) index pairs: [";
1124 os <<
"(" <<
p.first <<
"," <<
p.second <<
")";
1129 os <<
"]" << std::endl;
1132 os <<
"Invalid permute \"to\" (local, global) index pairs: [";
1135 os <<
"(" <<
p.first <<
"," <<
p.second <<
")";
1140 os <<
"]" << std::endl;
1143 std::ostream&
err = this->markLocalErrorAndGetStream();
1150 packAndPrepare(const ::Tpetra::SrcDistObject&
sourceObject,
1151 const Kokkos::DualView<
const local_ordinal_type*,
1155 Kokkos::DualView<
size_t*,
1160 using Teuchos::Comm;
1163 const char prefix[] =
"Tpetra::Details::CooMatrix::packAndPrepare: ";
1165 " This should never happen. "
1166 "Please report this bug to the Tpetra developers.";
1173 if (src ==
nullptr) {
1174 std::ostream&
err = this->markLocalErrorAndGetStream();
1175 err <<
prefix <<
"Input argument 'sourceObject' is not a CooMatrix."
1177 }
else if (*(src->localError_)) {
1178 std::ostream&
err = this->markLocalErrorAndGetStream();
1179 err <<
prefix <<
"The source (input) object of the Import or Export "
1180 "is already in an error state on this process."
1182 }
else if (*(this->localError_)) {
1183 std::ostream& err = this->markLocalErrorAndGetStream();
1184 err << prefix <<
"The target (output, \"this\") object of the Import "
1185 "or Export is already in an error state on this process."
1191 if (*(this->localError_)) {
1196 auto numPacketsPerLID_tmp = numPacketsPerLID;
1197 numPacketsPerLID_tmp.sync_host();
1198 numPacketsPerLID_tmp.modify_host();
1201 Kokkos::deep_copy(numPacketsPerLID.view_host(),
static_cast<size_t>(0));
1205 const size_t numExports = exportLIDs.extent(0);
1206 if (numExports == 0) {
1210 RCP<const Comm<int> > comm = src->getMap().is_null() ? Teuchos::null : src->getMap()->getComm();
1211 if (comm.is_null() || comm->getSize() == 1) {
1212 if (numExports !=
static_cast<size_t>(0)) {
1213 std::ostream& err = this->markLocalErrorAndGetStream();
1214 err << prefix <<
"The input communicator is either null or "
1215 "has only one process, but numExports = "
1216 << numExports <<
" != 0."
1227 numPacketsPerLID.sync_host();
1228 numPacketsPerLID.modify_host();
1230 TEUCHOS_ASSERT(!exportLIDs.need_sync_host());
1231 auto exportLIDs_h = exportLIDs.view_host();
1233 int totalNumPackets = 0;
1234 size_t numInvalidRowInds = 0;
1235 std::ostringstream errStrm;
1236 for (
size_t k = 0; k < numExports; ++k) {
1237 const LO lclRow = exportLIDs_h[k];
1240 const GO gblRow = src->map_->getGlobalElement(lclRow);
1241 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1243 ++numInvalidRowInds;
1244 numPacketsPerLID.view_host()[k] = 0;
1252 src->impl_.countPackRow(numPackets, gblRow, *comm, &errStrm);
1254 std::ostream& err = this->markLocalErrorAndGetStream();
1255 err << prefix << errStrm.str() << endl;
1256 numPacketsPerLID.view_host()[k] = 0;
1262 const long long newTotalNumPackets =
1263 static_cast<long long>(totalNumPackets) +
1264 static_cast<long long>(numPackets);
1265 if (newTotalNumPackets >
1266 static_cast<long long>(std::numeric_limits<int>::max())) {
1267 std::ostream& err = this->markLocalErrorAndGetStream();
1268 err << prefix <<
"The new total number of packets "
1269 << newTotalNumPackets <<
" does not fit in int." << endl;
1273 for (
size_t k2 = k; k2 < numExports; ++k2) {
1274 numPacketsPerLID.view_host()[k2] = 0;
1278 numPacketsPerLID.view_host()[k] =
static_cast<size_t>(numPackets);
1279 totalNumPackets =
static_cast<int>(newTotalNumPackets);
1284 if (numInvalidRowInds != 0) {
1285 std::vector<std::pair<LO, GO> > invalidRowInds;
1286 for (
size_t k = 0; k < numExports; ++k) {
1287 const LO lclRow = exportLIDs_h[k];
1291 const GO gblRow = src->map_->getGlobalElement(lclRow);
1292 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1293 invalidRowInds.push_back({lclRow, gblRow});
1296 std::ostringstream os;
1297 os << prefix <<
"We found " << numInvalidRowInds <<
" invalid row ind"
1298 << (numInvalidRowInds !=
static_cast<size_t>(1) ?
"ices" :
"ex")
1299 <<
" out of " << numExports <<
" in exportLIDs. Here is the list "
1300 <<
" of invalid row indices: [";
1301 for (
size_t k = 0; k < invalidRowInds.size(); ++k) {
1302 os <<
"(LID: " << invalidRowInds[k].first <<
", GID: "
1303 << invalidRowInds[k].second <<
")";
1304 if (k + 1 < invalidRowInds.size()) {
1310 std::ostream& err = this->markLocalErrorAndGetStream();
1311 err << prefix << os.str() << std::endl;
1316 const bool reallocated =
1318 "CooMatrix exports");
1320 exports.sync_host();
1323 exports.modify_host();
1327 std::vector<GO> gblRowInds;
1328 std::vector<GO> gblColInds;
1329 std::vector<SC> vals;
1331 int outBufCurPos = 0;
1333 for (
size_t k = 0; k < numExports; ++k) {
1334 const LO lclRow = exportLIDs.view_host()[k];
1337 const GO gblRow = src->map_->getGlobalElement(lclRow);
1339 src->impl_.packRow(outBuf, totalNumPackets, outBufCurPos, *comm,
1340 gblRowInds, gblColInds, vals, gblRow);
1345 unpackAndCombine(
const Kokkos::DualView<
const local_ordinal_type*,
1350 Kokkos::DualView<
size_t*,
1354 const ::Tpetra::CombineMode ) {
1356 using Teuchos::Comm;
1358 const char prefix[] =
"Tpetra::Details::CooMatrix::unpackAndCombine: ";
1359 const char suffix[] =
1360 " This should never happen. "
1361 "Please report this bug to the Tpetra developers.";
1363 TEUCHOS_ASSERT(!importLIDs.need_sync_host());
1364 auto importLIDs_h = importLIDs.view_host();
1366 const std::size_t numImports = importLIDs.extent(0);
1367 if (numImports == 0) {
1369 }
else if (imports.extent(0) == 0) {
1370 std::ostream& err = this->markLocalErrorAndGetStream();
1371 err << prefix <<
"importLIDs.extent(0) = " << numImports <<
" != 0, "
1372 <<
"but imports.extent(0) = 0. This doesn't make sense, because "
1373 <<
"for every incoming LID, CooMatrix packs at least the count of "
1374 <<
"triples associated with that LID, even if the count is zero. "
1375 <<
"importLIDs = [";
1376 for (std::size_t k = 0; k < numImports; ++k) {
1377 err << importLIDs_h[k];
1378 if (k + 1 < numImports) {
1382 err <<
"]. " << suffix << endl;
1386 RCP<const Comm<int> > comm = this->
getMap().is_null() ? Teuchos::null : this->
getMap()->getComm();
1387 if (comm.is_null() || comm->getSize() == 1) {
1388 if (numImports !=
static_cast<size_t>(0)) {
1389 std::ostream& err = this->markLocalErrorAndGetStream();
1390 err << prefix <<
"The input communicator is either null or "
1391 "has only one process, but numImports = "
1392 << numImports <<
" != 0."
1405 if (
static_cast<size_t>(imports.extent(0)) >
1406 static_cast<size_t>(std::numeric_limits<int>::max())) {
1407 std::ostream& err = this->markLocalErrorAndGetStream();
1408 err << prefix <<
"imports.extent(0) = "
1409 << imports.extent(0) <<
" does not fit in int." << endl;
1412 const int inBufSize =
static_cast<int>(imports.extent(0));
1414 if (imports.need_sync_host()) {
1415 imports.sync_host();
1417 if (numPacketsPerLID.need_sync_host()) {
1418 numPacketsPerLID.sync_host();
1420 auto imports_h = imports.view_host();
1421 auto numPacketsPerLID_h = numPacketsPerLID.view_host();
1425 std::vector<GO> gblRowInds;
1426 std::vector<GO> gblColInds;
1427 std::vector<SC> vals;
1430 int inBufCurPos = 0;
1431 size_t numInvalidRowInds = 0;
1433 std::ostringstream errStrm;
1434 for (
size_t k = 0; k < numImports; ++k) {
1435 const LO lclRow = importLIDs_h(k);
1436 const GO gblRow = this->
map_->getGlobalElement(lclRow);
1437 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1438 ++numInvalidRowInds;
1444 const int origInBufCurPos = inBufCurPos;
1448 numEnt, *comm, &errStrm);
1449 if (errCode != 0 || numEnt < 0 || inBufCurPos < origInBufCurPos) {
1450 std::ostream& err = this->markLocalErrorAndGetStream();
1452 err << prefix <<
"In unpack loop, k=" << k <<
": ";
1454 err <<
" unpackTriplesCount returned errCode = " << errCode
1455 <<
" != 0." << endl;
1458 err <<
" unpackTriplesCount returned errCode = 0, but numEnt = "
1459 << numEnt <<
" < 0." << endl;
1461 if (inBufCurPos < origInBufCurPos) {
1462 err <<
" After unpackTriplesCount, inBufCurPos = " << inBufCurPos
1463 <<
" < origInBufCurPos = " << origInBufCurPos <<
"." << endl;
1465 err <<
" unpackTriplesCount report: " << errStrm.str() << endl;
1466 err << suffix << endl;
1473#ifdef HAVE_TPETRA_DEBUG
1485 gblRowInds.resize(numEnt);
1486 gblColInds.resize(numEnt);
1487 vals.resize(numEnt);
1490 gblRowInds.data(), gblColInds.data(),
1491 vals.data(), numEnt, *comm, &errStrm);
1493 std::ostream& err = this->markLocalErrorAndGetStream();
1494 err << prefix <<
"unpackTriples returned errCode = "
1495 << errCode <<
" != 0. It reports: " << errStrm.str()
1502#ifdef HAVE_TPETRA_DEBUG
1512 vals.data(), numEnt);
1517 if (numInvalidRowInds != 0) {
1521 std::ostream& err = this->markLocalErrorAndGetStream();
1523 std::vector<std::pair<LO, GO> > invalidRowInds;
1524 for (
size_t k = 0; k < numImports; ++k) {
1525 const LO lclRow = importLIDs_h(k);
1526 const GO gblRow = this->
map_->getGlobalElement(lclRow);
1527 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1528 invalidRowInds.push_back({lclRow, gblRow});
1532 err << prefix <<
"We found " << numInvalidRowInds <<
" invalid row ind"
1533 << (numInvalidRowInds !=
static_cast<size_t>(1) ?
"ices" :
"ex")
1534 <<
" out of " << numImports <<
" in importLIDs. Here is the list "
1535 <<
" of invalid row indices: [";
1536 for (
size_t k = 0; k < invalidRowInds.size(); ++k) {
1537 err <<
"(LID: " << invalidRowInds[k].first <<
", GID: "
1538 << invalidRowInds[k].second <<
")";
1539 if (k + 1 < invalidRowInds.size()) {