580 typedef LO local_ordinal_type;
581 typedef GO global_ordinal_type;
583 typedef typename NT::device_type device_type;
585 typedef ::Tpetra::Map<local_ordinal_type, global_ordinal_type, node_type>
map_type;
658 std::initializer_list<SC>
vals,
672 template<
class OffsetType>
674 buildCrs (::Kokkos::View<OffsetType*, device_type>&
rowOffsets,
676 ::Kokkos::View<typename ::Kokkos::Details::ArithTraits<SC>::val_type*, device_type>&
vals)
678 static_assert (std::is_integral<OffsetType>::value,
679 "OffsetType must be a built-in integer type.");
680 using ::Kokkos::create_mirror_view;
681 using ::Kokkos::deep_copy;
682 using ::Kokkos::View;
683 typedef typename ::Kokkos::Details::ArithTraits<SC>::val_type
ISC;
719 if (comm.is_null ()) {
720 this->
map_ = ::Teuchos::null;
723 this->
map_ = this->buildMap (comm);
739 (this->
getMap ().
is_null (), std::runtime_error,
"Tpetra::Details::"
740 "CooMatrix::fillComplete: This object does not yet have a Map. "
741 "You must call the version of fillComplete "
742 "that takes an input communicator.");
782 return ((*errs_).get () ==
NULL) ? std::string (
"") : (*errs_)->str ();
798 std::shared_ptr<bool> localError_;
807 std::shared_ptr<std::shared_ptr<std::ostringstream> > errs_;
811 markLocalErrorAndGetStream ()
813 * (this->localError_) =
true;
814 if ((*errs_).get () ==
NULL) {
815 *errs_ = std::shared_ptr<std::ostringstream> (
new std::ostringstream ());
824 using Teuchos::TypeNameTraits;
826 std::ostringstream
os;
827 os <<
"\"Tpetra::Details::CooMatrix\": {"
835 os <<
", Has Map: " << (this->
map_.is_null () ?
"false" :
"true")
844 const Teuchos::EVerbosityLevel
verbLevel =
845 Teuchos::Describable::verbLevel_default)
const
847 using ::Tpetra::Details::gathervPrint;
848 using ::Teuchos::EVerbosityLevel;
849 using ::Teuchos::OSTab;
850 using ::Teuchos::TypeNameTraits;
851 using ::Teuchos::VERB_DEFAULT;
852 using ::Teuchos::VERB_LOW;
853 using ::Teuchos::VERB_MEDIUM;
858 auto comm = this->
getMap ().is_null () ?
859 Teuchos::null : this->
getMap ()->getComm ();
860 const int myRank = comm.is_null () ? 0 : comm->getRank ();
863 if (
vl != Teuchos::VERB_NONE) {
867 out <<
"\"Tpetra::Details::CooMatrix\":" <<
endl;
871 out <<
"Template parameters:" <<
endl;
882 out <<
"Has Map: " << (this->
map_.is_null () ?
"false" :
"true") << endl;
886 if (! this->
map_.is_null ()) {
891 this->
map_->describe (out,
vl);
896 std::ostringstream
os;
903 os <<
" Local entries:" <<
endl;
927 Teuchos::RCP<const map_type>
928 buildMap (const ::Teuchos::RCP<const ::Teuchos::Comm<int> >& comm)
930 using ::Teuchos::outArg;
931 using ::Teuchos::rcp;
932 using ::Teuchos::REDUCE_MIN;
933 using ::Teuchos::reduceAll;
938 if (comm.is_null ()) {
939 return ::Teuchos::null;
958 const GST INV = Tpetra::Details::OrdinalTraits<GST>::invalid ();
968 return static_cast<size_t> (0);
979 const char prefix[] =
"Tpetra::Details::CooMatrix::checkSizes: ";
984 std::ostream&
err = markLocalErrorAndGetStream ();
985 err <<
prefix <<
"The source object of the Import or Export "
986 "must be a CooMatrix with the same template parameters as the "
987 "target object." <<
endl;
989 else if (this->
map_.is_null ()) {
990 std::ostream&
err = markLocalErrorAndGetStream ();
991 err <<
prefix <<
"The target object of the Import or Export "
992 "must be a CooMatrix with a nonnull Map." <<
endl;
994 return ! (* (this->localError_));
999 typename ::Tpetra::DistObject<char, LO, GO, NT>::buffer_device_type;
1004 const size_t numSameIDs,
1005 const Kokkos::DualView<
const LO*,
1007 const Kokkos::DualView<
const LO*,
1013 const char prefix[] =
"Tpetra::Details::CooMatrix::copyAndPermute: ";
1018 if (* (this->localError_)) {
1019 std::ostream&
err = this->markLocalErrorAndGetStream ();
1020 err <<
prefix <<
"The target object of the Import or Export is "
1021 "already in an error state." <<
endl;
1026 if (src ==
nullptr) {
1027 std::ostream&
err = this->markLocalErrorAndGetStream ();
1028 err <<
prefix <<
"Input argument 'sourceObject' is not a CooMatrix."
1036 std::ostream&
err = this->markLocalErrorAndGetStream ();
1037 err <<
prefix <<
"permuteToLIDs.extent(0) = "
1042 if (
sizeof (
int) <=
sizeof (
size_t) &&
1043 numPermuteIDs >
static_cast<size_t> (std::numeric_limits<int>::max ())) {
1044 std::ostream&
err = this->markLocalErrorAndGetStream ();
1046 <<
", a size_t, overflows int." <<
endl;
1053 if (
sizeof (
int) <=
sizeof (
size_t) &&
1054 numSameIDs >
static_cast<size_t> (std::numeric_limits<int>::max ())) {
1055 std::ostream&
err = this->markLocalErrorAndGetStream ();
1056 err <<
prefix <<
"numSameIDs = " << numSameIDs
1057 <<
", a size_t, overflows int." <<
endl;
1064 const LO
numSame =
static_cast<int> (numSameIDs);
1075 if (
gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1110 const GO
gblRowTo = this->
map_->getGlobalElement (lclRowTo);
1113 if (
gblRowFrom == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1117 if (
gblRowTo == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1143 if (
gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1152 const GO
gblRowTo = this->
map_->getGlobalElement (lclRowTo);
1154 if (
gblRowFrom == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1157 if (
gblRowTo == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1162 std::ostringstream
os;
1164 os <<
"Invalid permute \"same\" (local, global) index pairs: [";
1167 os <<
"(" <<
p.first <<
"," <<
p.second <<
")";
1172 os <<
"]" << std::endl;
1175 os <<
"Invalid permute \"from\" (local, global) index pairs: [";
1178 os <<
"(" <<
p.first <<
"," <<
p.second <<
")";
1183 os <<
"]" << std::endl;
1186 os <<
"Invalid permute \"to\" (local, global) index pairs: [";
1189 os <<
"(" <<
p.first <<
"," <<
p.second <<
")";
1194 os <<
"]" << std::endl;
1197 std::ostream&
err = this->markLocalErrorAndGetStream ();
1206 const Kokkos::DualView<
const local_ordinal_type*,
1210 Kokkos::DualView<
size_t*,
1214 using Teuchos::Comm;
1218 const char prefix[] =
"Tpetra::Details::CooMatrix::packAndPrepare: ";
1219 const char suffix[] =
" This should never happen. "
1220 "Please report this bug to the Tpetra developers.";
1227 if (src ==
nullptr) {
1228 std::ostream&
err = this->markLocalErrorAndGetStream ();
1229 err <<
prefix <<
"Input argument 'sourceObject' is not a CooMatrix."
1232 else if (* (src->localError_)) {
1233 std::ostream&
err = this->markLocalErrorAndGetStream ();
1234 err <<
prefix <<
"The source (input) object of the Import or Export "
1235 "is already in an error state on this process."
1238 else if (* (this->localError_)) {
1239 std::ostream& err = this->markLocalErrorAndGetStream ();
1240 err << prefix <<
"The target (output, \"this\") object of the Import "
1241 "or Export is already in an error state on this process." << endl;
1246 if (* (this->localError_)) {
1251 auto numPacketsPerLID_tmp = numPacketsPerLID;
1252 numPacketsPerLID_tmp.sync_host ();
1253 numPacketsPerLID_tmp.modify_host ();
1256 Kokkos::deep_copy (numPacketsPerLID.h_view,
static_cast<size_t> (0));
1260 const size_t numExports = exportLIDs.extent (0);
1261 if (numExports == 0) {
1265 RCP<const Comm<int> > comm = src->getMap ().is_null () ?
1266 Teuchos::null : src->getMap ()->getComm ();
1267 if (comm.is_null () || comm->getSize () == 1) {
1268 if (numExports !=
static_cast<size_t> (0)) {
1269 std::ostream& err = this->markLocalErrorAndGetStream ();
1270 err << prefix <<
"The input communicator is either null or "
1271 "has only one process, but numExports = " << numExports <<
" != 0."
1282 numPacketsPerLID.sync_host ();
1283 numPacketsPerLID.modify_host ();
1285 TEUCHOS_ASSERT( ! exportLIDs.need_sync_host () );
1286 auto exportLIDs_h = exportLIDs.view_host ();
1288 int totalNumPackets = 0;
1289 size_t numInvalidRowInds = 0;
1290 std::ostringstream errStrm;
1291 for (
size_t k = 0; k < numExports; ++k) {
1292 const LO lclRow = exportLIDs_h[k];
1295 const GO gblRow = src->map_->getGlobalElement (lclRow);
1296 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1298 ++numInvalidRowInds;
1299 numPacketsPerLID.h_view[k] = 0;
1307 src->impl_.countPackRow (numPackets, gblRow, *comm, &errStrm);
1309 std::ostream& err = this->markLocalErrorAndGetStream ();
1310 err << prefix << errStrm.str () << endl;
1311 numPacketsPerLID.h_view[k] = 0;
1317 const long long newTotalNumPackets =
1318 static_cast<long long> (totalNumPackets) +
1319 static_cast<long long> (numPackets);
1320 if (newTotalNumPackets >
1321 static_cast<long long> (std::numeric_limits<int>::max ())) {
1322 std::ostream& err = this->markLocalErrorAndGetStream ();
1323 err << prefix <<
"The new total number of packets "
1324 << newTotalNumPackets <<
" does not fit in int." << endl;
1328 for (
size_t k2 = k; k2 < numExports; ++k2) {
1329 numPacketsPerLID.h_view[k2] = 0;
1333 numPacketsPerLID.h_view[k] =
static_cast<size_t> (numPackets);
1334 totalNumPackets =
static_cast<int> (newTotalNumPackets);
1339 if (numInvalidRowInds != 0) {
1340 std::vector<std::pair<LO, GO> > invalidRowInds;
1341 for (
size_t k = 0; k < numExports; ++k) {
1342 const LO lclRow = exportLIDs_h[k];
1346 const GO gblRow = src->map_->getGlobalElement (lclRow);
1347 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1348 invalidRowInds.push_back ({lclRow, gblRow});
1351 std::ostringstream os;
1352 os << prefix <<
"We found " << numInvalidRowInds <<
" invalid row ind"
1353 << (numInvalidRowInds !=
static_cast<size_t> (1) ?
"ices" :
"ex")
1354 <<
" out of " << numExports <<
" in exportLIDs. Here is the list "
1355 <<
" of invalid row indices: [";
1356 for (
size_t k = 0; k < invalidRowInds.size (); ++k) {
1357 os <<
"(LID: " << invalidRowInds[k].first <<
", GID: "
1358 << invalidRowInds[k].second <<
")";
1359 if (k + 1 < invalidRowInds.size ()) {
1365 std::ostream& err = this->markLocalErrorAndGetStream ();
1366 err << prefix << os.str () << std::endl;
1371 const bool reallocated =
1373 "CooMatrix exports");
1375 exports.sync_host ();
1378 exports.modify_host ();
1382 std::vector<GO> gblRowInds;
1383 std::vector<GO> gblColInds;
1384 std::vector<SC> vals;
1386 int outBufCurPos = 0;
1388 for (
size_t k = 0; k < numExports; ++k) {
1389 const LO lclRow = exportLIDs.h_view[k];
1392 const GO gblRow = src->map_->getGlobalElement (lclRow);
1394 src->impl_.packRow (outBuf, totalNumPackets, outBufCurPos, *comm,
1395 gblRowInds, gblColInds, vals, gblRow);
1401 (
const Kokkos::DualView<
const local_ordinal_type*,
1405 Kokkos::DualView<
size_t*,
1408 const ::Tpetra::CombineMode )
1410 using Teuchos::Comm;
1413 const char prefix[] =
"Tpetra::Details::CooMatrix::unpackAndCombine: ";
1414 const char suffix[] =
" This should never happen. "
1415 "Please report this bug to the Tpetra developers.";
1417 TEUCHOS_ASSERT( ! importLIDs.need_sync_host () );
1418 auto importLIDs_h = importLIDs.view_host ();
1420 const std::size_t numImports = importLIDs.extent (0);
1421 if (numImports == 0) {
1424 else if (imports.extent (0) == 0) {
1425 std::ostream& err = this->markLocalErrorAndGetStream ();
1426 err << prefix <<
"importLIDs.extent(0) = " << numImports <<
" != 0, "
1427 <<
"but imports.extent(0) = 0. This doesn't make sense, because "
1428 <<
"for every incoming LID, CooMatrix packs at least the count of "
1429 <<
"triples associated with that LID, even if the count is zero. "
1430 <<
"importLIDs = [";
1431 for (std::size_t k = 0; k < numImports; ++k) {
1432 err << importLIDs_h[k];
1433 if (k + 1 < numImports) {
1437 err <<
"]. " << suffix << endl;
1441 RCP<const Comm<int> > comm = this->
getMap ().is_null () ?
1442 Teuchos::null : this->
getMap ()->getComm ();
1443 if (comm.is_null () || comm->getSize () == 1) {
1444 if (numImports !=
static_cast<size_t> (0)) {
1445 std::ostream& err = this->markLocalErrorAndGetStream ();
1446 err << prefix <<
"The input communicator is either null or "
1447 "has only one process, but numImports = " << numImports <<
" != 0."
1460 if (
static_cast<size_t> (imports.extent (0)) >
1461 static_cast<size_t> (std::numeric_limits<int>::max ())) {
1462 std::ostream& err = this->markLocalErrorAndGetStream ();
1463 err << prefix <<
"imports.extent(0) = "
1464 << imports.extent (0) <<
" does not fit in int." << endl;
1467 const int inBufSize =
static_cast<int> (imports.extent (0));
1469 if (imports.need_sync_host ()) {
1470 imports.sync_host ();
1472 if (numPacketsPerLID.need_sync_host ()) {
1473 numPacketsPerLID.sync_host ();
1475 auto imports_h = imports.view_host ();
1476 auto numPacketsPerLID_h = numPacketsPerLID.view_host ();
1480 std::vector<GO> gblRowInds;
1481 std::vector<GO> gblColInds;
1482 std::vector<SC> vals;
1485 int inBufCurPos = 0;
1486 size_t numInvalidRowInds = 0;
1488 std::ostringstream errStrm;
1489 for (
size_t k = 0; k < numImports; ++k) {
1490 const LO lclRow = importLIDs_h(k);
1491 const GO gblRow = this->
map_->getGlobalElement (lclRow);
1492 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1493 ++numInvalidRowInds;
1499 const int origInBufCurPos = inBufCurPos;
1503 numEnt, *comm, &errStrm);
1504 if (errCode != 0 || numEnt < 0 || inBufCurPos < origInBufCurPos) {
1505 std::ostream& err = this->markLocalErrorAndGetStream ();
1507 err << prefix <<
"In unpack loop, k=" << k <<
": ";
1509 err <<
" unpackTriplesCount returned errCode = " << errCode
1510 <<
" != 0." << endl;
1513 err <<
" unpackTriplesCount returned errCode = 0, but numEnt = "
1514 << numEnt <<
" < 0." << endl;
1516 if (inBufCurPos < origInBufCurPos) {
1517 err <<
" After unpackTriplesCount, inBufCurPos = " << inBufCurPos
1518 <<
" < origInBufCurPos = " << origInBufCurPos <<
"." << endl;
1520 err <<
" unpackTriplesCount report: " << errStrm.str () << endl;
1521 err << suffix << endl;
1528#ifdef HAVE_TPETRA_DEBUG
1540 gblRowInds.resize (numEnt);
1541 gblColInds.resize (numEnt);
1542 vals.resize (numEnt);
1545 gblRowInds.data (), gblColInds.data (),
1546 vals.data (), numEnt, *comm, &errStrm);
1548 std::ostream& err = this->markLocalErrorAndGetStream ();
1549 err << prefix <<
"unpackTriples returned errCode = "
1550 << errCode <<
" != 0. It reports: " << errStrm.str ()
1557#ifdef HAVE_TPETRA_DEBUG
1567 vals.data (), numEnt);
1572 if (numInvalidRowInds != 0) {
1576 std::ostream& err = this->markLocalErrorAndGetStream ();
1578 std::vector<std::pair<LO, GO> > invalidRowInds;
1579 for (
size_t k = 0; k < numImports; ++k) {
1580 const LO lclRow = importLIDs_h(k);
1581 const GO gblRow = this->
map_->getGlobalElement (lclRow);
1582 if (gblRow == ::Tpetra::Details::OrdinalTraits<GO>::invalid ()) {
1583 invalidRowInds.push_back ({lclRow, gblRow});
1587 err << prefix <<
"We found " << numInvalidRowInds <<
" invalid row ind"
1588 << (numInvalidRowInds !=
static_cast<size_t> (1) ?
"ices" :
"ex")
1589 <<
" out of " << numImports <<
" in importLIDs. Here is the list "
1590 <<
" of invalid row indices: [";
1591 for (
size_t k = 0; k < invalidRowInds.size (); ++k) {
1592 err <<
"(LID: " << invalidRowInds[k].first <<
", GID: "
1593 << invalidRowInds[k].second <<
")";
1594 if (k + 1 < invalidRowInds.size ()) {