531 typedef LO local_ordinal_type;
532 typedef GO global_ordinal_type;
533 typedef NT node_type;
534 typedef typename NT::device_type device_type;
536 typedef ::Tpetra::Map<local_ordinal_type, global_ordinal_type, node_type>
map_type;
541 global_ordinal_type, node_type>
554 : base_type(::Teuchos::null)
555 , localError_(new bool(false))
556 , errs_(new std::shared_ptr<std::ostringstream>())
568 , localError_(new bool(false))
569 , errs_(new std::shared_ptr<std::ostringstream>())
598 const GO gblColInds[],
600 const std::size_t numEnt) {
607 std::initializer_list<GO> gblColInds,
608 std::initializer_list<SC> vals,
609 const std::size_t numEnt) {
611 vals.begin(), numEnt);
620 template <
class OffsetType>
622 buildCrs(::Kokkos::View<OffsetType*, device_type>& rowOffsets,
623 ::Kokkos::View<GO*, device_type>& gblColInds,
624#
if KOKKOS_VERSION >= 40799
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;
642 gblColInds = View<GO*, device_type>(
"gblColInds", numEnt);
643 vals = View<ISC*, device_type>(
"vals", numEnt);
644 auto gblColInds_h = create_mirror_view(gblColInds);
645 auto vals_h = create_mirror_view(vals);
647 std::vector<std::size_t> rowOffsetsSV;
648 this->impl_.buildCrs(rowOffsetsSV,
652 View<OffsetType*, device_type>(
"rowOffsets", rowOffsetsSV.size());
653 typename View<OffsetType*, device_type>::host_mirror_type
654 rowOffsets_h(rowOffsetsSV.data(), rowOffsetsSV.size());
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);
690 TEUCHOS_TEST_FOR_EXCEPTION(this->
getMap().is_null(), std::runtime_error,
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\": {"
779 <<
"SC: " << TypeNameTraits<SC>::name()
780 <<
", LO: " << TypeNameTraits<LO>::name()
781 <<
", GO: " << TypeNameTraits<GO>::name()
782 <<
", NT: " << TypeNameTraits<NT>::name();
783 if (this->getObjectLabel() !=
"") {
784 os <<
", Label: \"" << this->getObjectLabel() <<
"\"";
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;
806 const auto vl = (verbLevel == VERB_DEFAULT) ? VERB_LOW : verbLevel;
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;
823 out <<
"SC: " << TypeNameTraits<SC>::name() << endl
824 <<
"LO: " << TypeNameTraits<LO>::name() << endl
825 <<
"GO: " << TypeNameTraits<GO>::name() << endl
826 <<
"NT: " << TypeNameTraits<NT>::name() << endl;
828 if (this->getObjectLabel() !=
"") {
829 out <<
"Label: \"" << this->getObjectLabel() <<
"\"" << endl;
831 out <<
"Has Map: " << (this->
map_.is_null() ?
"false" :
"true") << endl;
835 if (!this->
map_.is_null()) {
837 out <<
"Map:" << endl;
840 this->
map_->describe(out, vl);
845 std::ostringstream os;
846 os <<
"Process " << myRank <<
":" << endl;
850 os <<
" Local number of entries: " << numEnt << endl;
851 if (vl > VERB_MEDIUM) {
852 os <<
" Local entries:" << endl;
854 this->impl_.
forAllEntries([&os](
const GO row,
const GO col,
const SC& val) {
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;
898 std::vector<GO> rowInds;
902 GO gblMinGblRowInd = 0;
903 reduceAll<int, GO>(*comm, REDUCE_MIN, lclMinGblRowInd,
904 outArg(gblMinGblRowInd));
905 const GO indexBase = gblMinGblRowInd;
906 const GST INV = Tpetra::Details::OrdinalTraits<GST>::invalid();
907 return rcp(
new map_type(INV, rowInds.data(), rowInds.size(),
916 return static_cast<size_t>(0);
926 const char prefix[] =
"Tpetra::Details::CooMatrix::checkSizes: ";
928 const this_COO_type* src =
dynamic_cast<const this_COO_type*
>(&source);
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."
972 const this_COO_type* src =
dynamic_cast<const this_COO_type*
>(&sourceObject);
973 if (src ==
nullptr) {
974 std::ostream& err = this->markLocalErrorAndGetStream();
975 err << prefix <<
"Input argument 'sourceObject' is not a CooMatrix."
980 const size_t numPermuteIDs =
981 static_cast<size_t>(permuteToLIDs.extent(0));
982 if (numPermuteIDs !=
static_cast<size_t>(permuteFromLIDs.extent(0))) {
983 std::ostream& err = this->markLocalErrorAndGetStream();
984 err << prefix <<
"permuteToLIDs.extent(0) = "
985 << numPermuteIDs <<
" != permuteFromLIDs.extent(0) = "
986 << permuteFromLIDs.extent(0) <<
"." << endl;
989 if (
sizeof(
int) <=
sizeof(
size_t) &&
990 numPermuteIDs >
static_cast<size_t>(std::numeric_limits<int>::max())) {
991 std::ostream& err = this->markLocalErrorAndGetStream();
992 err << prefix <<
"numPermuteIDs = " << numPermuteIDs
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);
1016 LO numInvalidSameRows = 0;
1017 for (LO lclRow = 0; lclRow < numSame; ++lclRow) {
1021 const GO gblRow = this->
map_->getGlobalElement(lclRow);
1022 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1023 ++numInvalidSameRows;
1035 const LO numPermute =
static_cast<int>(numPermuteIDs);
1040 LO numInvalidRowsFrom = 0;
1045 LO numInvalidRowsTo = 0;
1047 TEUCHOS_ASSERT(!permuteFromLIDs.need_sync_host());
1048 TEUCHOS_ASSERT(!permuteToLIDs.need_sync_host());
1049 auto permuteFromLIDs_h = permuteFromLIDs.view_host();
1050 auto permuteToLIDs_h = permuteToLIDs.view_host();
1052 for (LO k = 0; k < numPermute; ++k) {
1053 const LO lclRowFrom = permuteFromLIDs_h[k];
1054 const LO lclRowTo = permuteToLIDs_h[k];
1055 const GO gblRowFrom = src->
map_->getGlobalElement(lclRowFrom);
1056 const GO gblRowTo = this->
map_->getGlobalElement(lclRowTo);
1058 bool bothConversionsValid =
true;
1059 if (gblRowFrom == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1060 ++numInvalidRowsFrom;
1061 bothConversionsValid =
false;
1063 if (gblRowTo == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1065 bothConversionsValid =
false;
1067 if (bothConversionsValid) {
1068 this->impl_.
mergeIntoRow(gblRowTo, src->impl_, gblRowFrom);
1073 if (numInvalidSameRows != 0 || numInvalidRowsFrom != 0 ||
1074 numInvalidRowsTo != 0) {
1077 std::vector<std::pair<LO, GO> > invalidSameRows;
1078 invalidSameRows.reserve(numInvalidSameRows);
1079 std::vector<std::pair<LO, GO> > invalidRowsFrom;
1080 invalidRowsFrom.reserve(numInvalidRowsFrom);
1081 std::vector<std::pair<LO, GO> > invalidRowsTo;
1082 invalidRowsTo.reserve(numInvalidRowsTo);
1084 for (LO lclRow = 0; lclRow < numSame; ++lclRow) {
1088 const GO gblRow = this->
map_->getGlobalElement(lclRow);
1089 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1090 invalidSameRows.push_back({lclRow, gblRow});
1094 for (LO k = 0; k < numPermute; ++k) {
1095 const LO lclRowFrom = permuteFromLIDs_h[k];
1096 const LO lclRowTo = permuteToLIDs_h[k];
1097 const GO gblRowFrom = src->
map_->getGlobalElement(lclRowFrom);
1098 const GO gblRowTo = this->
map_->getGlobalElement(lclRowTo);
1100 if (gblRowFrom == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1101 invalidRowsFrom.push_back({lclRowFrom, gblRowFrom});
1103 if (gblRowTo == ::Tpetra::Details::OrdinalTraits<GO>::invalid()) {
1104 invalidRowsTo.push_back({lclRowTo, gblRowTo});
1108 std::ostringstream os;
1109 if (numInvalidSameRows != 0) {
1110 os <<
"Invalid permute \"same\" (local, global) index pairs: [";
1111 for (std::size_t k = 0; k < invalidSameRows.size(); ++k) {
1112 const auto& p = invalidSameRows[k];
1113 os <<
"(" << p.first <<
"," << p.second <<
")";
1114 if (k + 1 < invalidSameRows.size()) {
1118 os <<
"]" << std::endl;
1120 if (numInvalidRowsFrom != 0) {
1121 os <<
"Invalid permute \"from\" (local, global) index pairs: [";
1122 for (std::size_t k = 0; k < invalidRowsFrom.size(); ++k) {
1123 const auto& p = invalidRowsFrom[k];
1124 os <<
"(" << p.first <<
"," << p.second <<
")";
1125 if (k + 1 < invalidRowsFrom.size()) {
1129 os <<
"]" << std::endl;
1131 if (numInvalidRowsTo != 0) {
1132 os <<
"Invalid permute \"to\" (local, global) index pairs: [";
1133 for (std::size_t k = 0; k < invalidRowsTo.size(); ++k) {
1134 const auto& p = invalidRowsTo[k];
1135 os <<
"(" << p.first <<
"," << p.second <<
")";
1136 if (k + 1 < invalidRowsTo.size()) {
1140 os <<
"]" << std::endl;
1143 std::ostream& err = this->markLocalErrorAndGetStream();
1144 err << prefix << os.str();
1150 packAndPrepare(const ::Tpetra::SrcDistObject& sourceObject,
1155 Kokkos::DualView<
size_t*,
1158 size_t& constantNumPackets) {
1160 using Teuchos::Comm;
1163 const char prefix[] =
"Tpetra::Details::CooMatrix::packAndPrepare: ";
1164 const char suffix[] =
1165 " This should never happen. "
1166 "Please report this bug to the Tpetra developers.";
1170 constantNumPackets = 0;
1172 const this_COO_type* src =
dynamic_cast<const this_COO_type*
>(&sourceObject);
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()) {