10#ifndef TPETRA_DIRECTORYIMPL_DEF_HPP
11#define TPETRA_DIRECTORYIMPL_DEF_HPP
16#include "Teuchos_TestForException.hpp"
17#include "Tpetra_Distributor.hpp"
18#include "Tpetra_Map.hpp"
21#include "Tpetra_Details_FixedHashTable.hpp"
22#include "Teuchos_Comm.hpp"
27#ifdef HAVE_TPETRACORE_MPI
34template <
class LO,
class GO,
class NT>
38 const Teuchos::ArrayView<const GO>& globalIDs,
39 const Teuchos::ArrayView<int>& nodeIDs,
40 const Teuchos::ArrayView<LO>& localIDs,
41 const bool computeLIDs)
const {
44 TEUCHOS_TEST_FOR_EXCEPTION(nodeIDs.size() != globalIDs.size(),
45 std::invalid_argument, Teuchos::typeName(*
this) <<
"::getEntries(): "
46 "Output arrays do not have the right sizes. nodeIDs.size() = "
47 << nodeIDs.size() <<
" != globalIDs.size() = " << globalIDs.size() <<
".");
48 TEUCHOS_TEST_FOR_EXCEPTION(
49 computeLIDs && localIDs.size() != globalIDs.size(),
50 std::invalid_argument, Teuchos::typeName(*
this) <<
"::getEntries(): "
51 "Output array do not have the right sizes. localIDs.size() = "
52 << localIDs.size() <<
" != globalIDs.size() = " << globalIDs.size() <<
".");
59 std::fill(nodeIDs.begin(), nodeIDs.end(), -1);
61 std::fill(localIDs.begin(), localIDs.end(),
62 Teuchos::OrdinalTraits<LO>::invalid());
65 return this->
getEntriesImpl(map, globalIDs, nodeIDs, localIDs, computeLIDs);
68template <
class LO,
class GO,
class NT>
71 : numProcs_(map.getComm()->getSize()) {}
73template <
class LO,
class GO,
class NT>
79 return (numProcs_ == 1);
82template <
class LO,
class GO,
class NT>
85 std::ostringstream os;
86 os <<
"ReplicatedDirectory"
87 <<
"<" << Teuchos::TypeNameTraits<LO>::name()
88 <<
", " << Teuchos::TypeNameTraits<GO>::name()
89 <<
", " << Teuchos::TypeNameTraits<NT>::name() <<
">";
93template <
class LO,
class GO,
class NT>
96 TEUCHOS_TEST_FOR_EXCEPTION(!map.isContiguous(), std::invalid_argument,
97 Teuchos::typeName(*
this) <<
" constructor: Map is not contiguous.");
98 TEUCHOS_TEST_FOR_EXCEPTION(!map.isUniform(), std::invalid_argument,
99 Teuchos::typeName(*
this) <<
" constructor: Map is not uniform.");
102template <
class LO,
class GO,
class NT>
105 std::ostringstream os;
106 os <<
"ContiguousUniformDirectory"
107 <<
"<" << Teuchos::TypeNameTraits<LO>::name()
108 <<
", " << Teuchos::TypeNameTraits<GO>::name()
109 <<
", " << Teuchos::TypeNameTraits<NT>::name() <<
">";
113template <
class LO,
class GO,
class NT>
117 const Teuchos::ArrayView<const GO>& globalIDs,
118 const Teuchos::ArrayView<int>& nodeIDs,
119 const Teuchos::ArrayView<LO>& localIDs,
120 const bool computeLIDs)
const {
123 typedef typename Teuchos::ArrayView<const GO>::size_type size_type;
124 const LO invalidLid = Teuchos::OrdinalTraits<LO>::invalid();
127 RCP<const Comm<int> > comm = map.
getComm();
151 const size_type N_G =
153 const size_type P =
static_cast<size_type
>(comm->getSize());
154 const size_type N_L = N_G / P;
155 const size_type R = N_G - N_L * P;
156 const size_type N_R = R * (N_L +
static_cast<size_type
>(1));
158#ifdef HAVE_TPETRA_DEBUG
159 TEUCHOS_TEST_FOR_EXCEPTION(
160 N_G != P * N_L + R, std::logic_error,
161 "Tpetra::ContiguousUniformDirectory::getEntriesImpl: "
163 << N_G <<
" != P*N_L + R = " << P <<
"*" << N_L <<
" + " << R
164 <<
" = " << P * N_L + R <<
". "
165 "Please report this bug to the Tpetra developers.");
168 const size_type numGids = globalIDs.size();
171 const GO ONE =
static_cast<GO
>(1);
174 for (size_type k = 0; k < numGids; ++k) {
175 const GO g_0 = globalIDs[k] - g_min;
181 if (g_0 + ONE < ONE || g_0 >=
static_cast<GO
>(N_G)) {
183 localIDs[k] = invalidLid;
185 }
else if (g_0 <
static_cast<GO
>(N_R)) {
187 nodeIDs[k] =
static_cast<int>(g_0 /
static_cast<GO
>(N_L + 1));
188 localIDs[k] =
static_cast<LO
>(g_0 %
static_cast<GO
>(N_L + 1));
189 }
else if (g_0 >=
static_cast<GO
>(N_R)) {
191 const GO g_R = g_0 -
static_cast<GO
>(N_R);
192 nodeIDs[k] =
static_cast<int>(R + g_R / N_L);
193 localIDs[k] =
static_cast<int>(g_R % N_L);
195#ifdef HAVE_TPETRA_DEBUG
197 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
198 "Tpetra::ContiguousUniformDirectory::getEntriesImpl: "
199 "should never get here. "
200 "Please report this bug to the Tpetra developers.");
205 for (size_type k = 0; k < numGids; ++k) {
206 const GO g_0 = globalIDs[k] - g_min;
211 if (g_0 + ONE < ONE || g_0 >=
static_cast<GO
>(N_G)) {
214 }
else if (g_0 <
static_cast<GO
>(N_R)) {
216 nodeIDs[k] =
static_cast<int>(g_0 /
static_cast<GO
>(N_L + 1));
217 }
else if (g_0 >=
static_cast<GO
>(N_R)) {
219 const GO g_R = g_0 -
static_cast<GO
>(N_R);
220 nodeIDs[k] =
static_cast<int>(R + g_R / N_L);
222#ifdef HAVE_TPETRA_DEBUG
224 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::logic_error,
225 "Tpetra::ContiguousUniformDirectory::getEntriesImpl: "
226 "should never get here. "
227 "Please report this bug to the Tpetra developers.");
235template <
class LO,
class GO,
class NT>
239 using Teuchos::gatherAll;
242 RCP<const Teuchos::Comm<int> > comm = map.
getComm();
244 TEUCHOS_TEST_FOR_EXCEPTION(!map.
isDistributed(), std::invalid_argument,
245 Teuchos::typeName(*
this) <<
" constructor: Map is not distributed.");
246 TEUCHOS_TEST_FOR_EXCEPTION(!map.isContiguous(), std::invalid_argument,
247 Teuchos::typeName(*
this) <<
" constructor: Map is not contiguous.");
249 const int numProcs = comm->getSize();
253 allMinGIDs_ = arcp<GO>(numProcs + 1);
255 GO minMyGID = map.getMinGlobalIndex();
266#ifdef HAVE_TPETRACORE_MPI
267 MPI_Datatype rawMpiType = MPI_INT;
268 bool useRawMpi =
true;
269 if (
typeid(GO) ==
typeid(
int)) {
270 rawMpiType = MPI_INT;
271 }
else if (
typeid(GO) ==
typeid(
long)) {
272 rawMpiType = MPI_LONG;
277 using Teuchos::MpiComm;
278 using Teuchos::rcp_dynamic_cast;
279 RCP<const MpiComm<int> > mpiComm =
280 rcp_dynamic_cast<const MpiComm<int> >(comm);
283 if (!comm.is_null()) {
284 MPI_Comm rawMpiComm = *(mpiComm->getRawMpiComm());
286 MPI_Allgather(&minMyGID, 1, rawMpiType,
287 allMinGIDs_.getRawPtr(), 1, rawMpiType,
289 TEUCHOS_TEST_FOR_EXCEPTION(err != MPI_SUCCESS, std::runtime_error,
290 "Tpetra::DistributedContiguousDirectory: MPI_Allgather failed");
292 gatherAll<int, GO>(*comm, 1, &minMyGID, numProcs, allMinGIDs_.getRawPtr());
295 gatherAll<int, GO>(*comm, 1, &minMyGID, numProcs, allMinGIDs_.getRawPtr());
298 gatherAll<int, GO>(*comm, 1, &minMyGID, numProcs, allMinGIDs_.getRawPtr());
306 allMinGIDs_[numProcs] = map.getMaxAllGlobalIndex() + Teuchos::OrdinalTraits<GO>::one();
309template <
class LO,
class GO,
class NT>
312 std::ostringstream os;
313 os <<
"DistributedContiguousDirectory"
314 <<
"<" << Teuchos::TypeNameTraits<LO>::name()
315 <<
", " << Teuchos::TypeNameTraits<GO>::name()
316 <<
", " << Teuchos::TypeNameTraits<NT>::name() <<
">";
320template <
class LO,
class GO,
class NT>
324 const Teuchos::ArrayView<const GO>& globalIDs,
325 const Teuchos::ArrayView<int>& nodeIDs,
326 const Teuchos::ArrayView<LO>& localIDs,
327 const bool computeLIDs)
const {
328 using Teuchos::Array;
329 using Teuchos::ArrayRCP;
330 using Teuchos::ArrayView;
336 RCP<const Teuchos::Comm<int> > comm = map.
getComm();
337 const int myRank = comm->getRank();
340 typename ArrayView<int>::iterator procIter = nodeIDs.begin();
341 typename ArrayView<LO>::iterator lidIter = localIDs.begin();
342 typename ArrayView<const GO>::iterator gidIter;
343 for (gidIter = globalIDs.begin(); gidIter != globalIDs.end(); ++gidIter) {
345 *procIter++ = myRank;
361template <
class LO,
class GO,
class NT>
365 const Teuchos::ArrayView<const GO>& globalIDs,
366 const Teuchos::ArrayView<int>& nodeIDs,
367 const Teuchos::ArrayView<LO>& localIDs,
368 const bool computeLIDs)
const {
369 using Teuchos::Array;
370 using Teuchos::ArrayRCP;
371 using Teuchos::ArrayView;
376 RCP<const Teuchos::Comm<int> > comm = map.
getComm();
377 const int numProcs = comm->getSize();
378 const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid();
379 const GO noGIDsOnProc = std::numeric_limits<GO>::max();
383 int firstProcWithGIDs;
384 for (firstProcWithGIDs = 0; firstProcWithGIDs < numProcs;
385 firstProcWithGIDs++) {
386 if (allMinGIDs_[firstProcWithGIDs] != noGIDsOnProc)
break;
392 if (firstProcWithGIDs == numProcs) {
395 std::fill(nodeIDs.begin(), nodeIDs.end(), -1);
397 std::fill(localIDs.begin(), localIDs.end(), LINVALID);
401 const GO one = as<GO>(1);
402 const GO nOverP = as<GO>(map.
getGlobalNumElements() / as<global_size_t>(numProcs - firstProcWithGIDs));
405 typename ArrayView<int>::iterator procIter = nodeIDs.begin();
406 typename ArrayView<LO>::iterator lidIter = localIDs.begin();
407 typename ArrayView<const GO>::iterator gidIter;
408 for (gidIter = globalIDs.begin(); gidIter != globalIDs.end(); ++gidIter) {
417 const GO firstGuess = firstProcWithGIDs + GID / std::max(nOverP, one);
418 curRank = as<int>(std::min(firstGuess, as<GO>(numProcs - 1)));
422 while (allMinGIDs_[curRank] == noGIDsOnProc) curRank++;
425 while (curRank >= firstProcWithGIDs && GID < allMinGIDs_[curRank]) {
427 while (curRank >= firstProcWithGIDs &&
428 allMinGIDs_[curRank] == noGIDsOnProc) curRank--;
430 if (curRank < firstProcWithGIDs) {
433 }
else if (curRank == numProcs) {
438 int above = curRank + 1;
439 while (allMinGIDs_[above] == noGIDsOnProc) above++;
441 while (GID >= allMinGIDs_[above]) {
443 if (curRank == numProcs) {
449 while (allMinGIDs_[above] == noGIDsOnProc) above++;
455 LID = as<LO>(GID - allMinGIDs_[image]);
467template <
class LO,
class GO,
class NT>
470 : oneToOneResult_(ONE_TO_ONE_NOT_CALLED_YET)
472 locallyOneToOne_(true)
474 useHashTables_(false)
479template <
class LO,
class GO,
class NT>
480DistributedNoncontiguousDirectory<LO, GO, NT>::
481 DistributedNoncontiguousDirectory(
const map_type& map,
482 const tie_break_type& tie_break)
483 : oneToOneResult_(ONE_TO_ONE_NOT_CALLED_YET)
485 locallyOneToOne_(true)
487 useHashTables_(false)
489 initialize(map, Teuchos::ptrFromRef(tie_break));
492template <
class LO,
class GO,
class NT>
493void DistributedNoncontiguousDirectory<LO, GO, NT>::
494 initialize(
const map_type& map,
495 Teuchos::Ptr<const tie_break_type> tie_break) {
499 using Teuchos::Array;
500 using Teuchos::ArrayRCP;
501 using Teuchos::ArrayView;
505 using Teuchos::typeName;
506 using Teuchos::TypeNameTraits;
507 typedef Array<int>::size_type size_type;
517 TEUCHOS_TEST_FOR_EXCEPTION(
sizeof(
global_size_t) <
sizeof(GO),
518 std::logic_error, typeName(*
this) <<
": sizeof(Tpetra::"
522 << TypeNameTraits<LO>::name() <<
") = " <<
sizeof(GO) <<
".");
523 TEUCHOS_TEST_FOR_EXCEPTION(
sizeof(
global_size_t) <
sizeof(
int),
524 std::logic_error, typeName(*
this) <<
": sizeof(Tpetra::"
526 <<
sizeof(
global_size_t) <<
" < sizeof(int) = " <<
sizeof(
int) <<
".");
527 TEUCHOS_TEST_FOR_EXCEPTION(
sizeof(
global_size_t) <
sizeof(LO),
528 std::logic_error, typeName(*
this) <<
": sizeof(Tpetra::"
532 << TypeNameTraits<LO>::name() <<
") = " <<
sizeof(LO) <<
".");
533 TEUCHOS_TEST_FOR_EXCEPTION(!map.haveGlobalConstants(), std::logic_error,
"Map needs to have global constants.");
535 RCP<const Teuchos::Comm<int> > comm = map.getComm();
536 const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid();
537 const GO minAllGID = map.getMinAllGlobalIndex();
538 const GO maxAllGID = map.getMaxAllGlobalIndex();
545 const global_size_t numGlobalEntries = maxAllGID - minAllGID + 1;
555 directoryMap_ = rcp(
new map_type(numGlobalEntries, minAllGID, comm,
556 GloballyDistributed));
558 const size_t dir_numMyEntries = directoryMap_->getLocalNumElements();
582 const size_t inverseSparsityThreshold = 10;
584 (dir_numMyEntries >= inverseSparsityThreshold * map.getLocalNumElements());
589 const int myRank = comm->getRank();
590 const size_t numMyEntries = map.getLocalNumElements();
591 Array<int> sendImageIDs(numMyEntries);
592 ArrayView<const GO> myGlobalEntries = map.getLocalElementList();
597 directoryMap_->getRemoteIndexList(myGlobalEntries, sendImageIDs);
598 TEUCHOS_TEST_FOR_EXCEPTION(
599 lookupStatus ==
IDNotPresent, std::logic_error, Teuchos::typeName(*
this) <<
" constructor: the Directory Map could not find out where one or "
600 "more of my Map's indices should go. The input to getRemoteIndexList "
602 << Teuchos::toString(myGlobalEntries) <<
", and the output is " << Teuchos::toString(sendImageIDs()) <<
". The input Map itself has "
603 "the following entries on the calling process "
604 << map.getComm()->getRank() <<
": " << Teuchos::toString(map.getLocalElementList()) <<
", and has " << map.getGlobalNumElements() <<
" total global indices in [" << map.getMinAllGlobalIndex() <<
"," << map.getMaxAllGlobalIndex() <<
"]. The Directory Map has " << directoryMap_->getGlobalNumElements() <<
" total global indices in "
606 << directoryMap_->getMinAllGlobalIndex() <<
"," << directoryMap_->getMaxAllGlobalIndex() <<
"], and the calling process "
608 << directoryMap_->getMinGlobalIndex() <<
"," << directoryMap_->getMaxGlobalIndex() <<
"]. "
609 "This probably means there is a bug in Map or Directory. "
610 "Please report this bug to the Tpetra developers.");
617 Distributor distor(comm);
618 const size_t numReceives = distor.createFromSends(sendImageIDs);
632 const int packetSize = 3;
633 Kokkos::View<GO*, Kokkos::HostSpace> exportEntries(
"exportEntries", packetSize * numMyEntries);
635 size_t exportIndex = 0;
636 for (
size_t i = 0; i < numMyEntries; ++i) {
637 exportEntries[exportIndex++] = myGlobalEntries[i];
638 exportEntries[exportIndex++] = as<GO>(myRank);
639 exportEntries[exportIndex++] = as<GO>(i);
645 Kokkos::View<GO*, Kokkos::HostSpace> importElements(
"importElements", packetSize * distor.getTotalReceiveLength());
648 distor.doPostsAndWaits(exportEntries, packetSize, importElements);
655 if (useHashTables_) {
670 LO* tableKeysRaw = NULL;
671 LO* tableLidsRaw = NULL;
672 int* tablePidsRaw = NULL;
674 tableKeysRaw =
new LO[numReceives];
675 tableLidsRaw =
new LO[numReceives];
676 tablePidsRaw =
new int[numReceives];
678 if (tableKeysRaw != NULL) {
679 delete[] tableKeysRaw;
681 if (tableLidsRaw != NULL) {
682 delete[] tableLidsRaw;
684 if (tablePidsRaw != NULL) {
685 delete[] tablePidsRaw;
689 ArrayRCP<LO> tableKeys(tableKeysRaw, 0, numReceives,
true);
690 ArrayRCP<LO> tableLids(tableLidsRaw, 0, numReceives,
true);
691 ArrayRCP<int> tablePids(tablePidsRaw, 0, numReceives,
true);
693 if (tie_break.is_null()) {
695 size_type importIndex = 0;
696 for (size_type i = 0; i < static_cast<size_type>(numReceives); ++i) {
697 const GO curGID = importElements[importIndex++];
698 const LO curLID = directoryMap_->getLocalElement(curGID);
699 TEUCHOS_TEST_FOR_EXCEPTION(
700 curLID == LINVALID, std::logic_error,
701 Teuchos::typeName(*
this) <<
" constructor: Incoming global index "
702 << curGID <<
" does not have a corresponding local index in the "
703 "Directory Map. Please report this bug to the Tpetra developers.");
704 tableKeys[i] = curLID;
705 tablePids[i] = importElements[importIndex++];
706 tableLids[i] = importElements[importIndex++];
712 rcp(
new lidToPidTable_type(tableKeys(), tablePids()));
713 locallyOneToOne_ = !(lidToPidTable_->hasDuplicateKeys());
715 rcp(
new lidToLidTable_type(tableKeys(), tableLids()));
723 typedef std::map<LO, std::vector<std::pair<int, LO> > > pair_table_type;
724 pair_table_type ownedPidLidPairs;
728 size_type importIndex = 0;
729 for (size_type i = 0; i < static_cast<size_type>(numReceives); ++i) {
730 const GO curGID = importElements[importIndex++];
731 const LO dirMapLid = directoryMap_->getLocalElement(curGID);
732 TEUCHOS_TEST_FOR_EXCEPTION(
733 dirMapLid == LINVALID, std::logic_error,
734 Teuchos::typeName(*
this) <<
" constructor: Incoming global index "
735 << curGID <<
" does not have a corresponding local index in the "
736 "Directory Map. Please report this bug to the Tpetra developers.");
737 tableKeys[i] = dirMapLid;
738 const int PID = importElements[importIndex++];
739 const int LID = importElements[importIndex++];
749 ownedPidLidPairs[dirMapLid].push_back(std::make_pair(PID, LID));
762 for (size_type i = 0; i < static_cast<size_type>(numReceives); ++i) {
763 const LO dirMapLid = tableKeys[i];
764 const std::vector<std::pair<int, LO> >& pidLidList =
765 ownedPidLidPairs[dirMapLid];
766 const size_t listLen = pidLidList.size();
767 if (listLen == 0)
continue;
768 const GO dirMapGid = directoryMap_->getGlobalElement(dirMapLid);
770 locallyOneToOne_ =
false;
779 const size_type index =
780 static_cast<size_type
>(tie_break->selectedIndex(dirMapGid,
782 tablePids[i] = pidLidList[index].first;
783 tableLids[i] = pidLidList[index].second;
788 rcp(
new lidToPidTable_type(tableKeys(), tablePids()));
790 rcp(
new lidToLidTable_type(tableKeys(), tableLids()));
793 if (tie_break.is_null()) {
798 PIDs_ = arcp<int>(dir_numMyEntries);
799 std::fill(PIDs_.begin(), PIDs_.end(), -1);
800 LIDs_ = arcp<LO>(dir_numMyEntries);
801 std::fill(LIDs_.begin(), LIDs_.end(), LINVALID);
803 size_type importIndex = 0;
804 for (size_type i = 0; i < static_cast<size_type>(numReceives); ++i) {
805 const GO curGID = importElements[importIndex++];
806 const LO curLID = directoryMap_->getLocalElement(curGID);
807 TEUCHOS_TEST_FOR_EXCEPTION(curLID == LINVALID, std::logic_error,
808 Teuchos::typeName(*
this) <<
" constructor: Incoming global index "
809 << curGID <<
" does not have a corresponding local index in the "
810 "Directory Map. Please report this bug to the Tpetra developers.");
815 if (PIDs_[curLID] != -1) {
816 locallyOneToOne_ =
false;
818 PIDs_[curLID] = importElements[importIndex++];
819 LIDs_[curLID] = importElements[importIndex++];
822 PIDs_ = arcp<int>(dir_numMyEntries);
823 LIDs_ = arcp<LO>(dir_numMyEntries);
824 std::fill(PIDs_.begin(), PIDs_.end(), -1);
833 Array<std::vector<std::pair<int, LO> > > ownedPidLidPairs(dir_numMyEntries);
834 size_t importIndex = 0;
835 for (
size_t i = 0; i < numReceives; ++i) {
836 const GO GID = importElements[importIndex++];
837 const int PID = importElements[importIndex++];
838 const LO LID = importElements[importIndex++];
840 const LO dirMapLid = directoryMap_->getLocalElement(GID);
841 TEUCHOS_TEST_FOR_EXCEPTION(
842 dirMapLid == LINVALID, std::logic_error,
843 Teuchos::typeName(*
this) <<
" constructor: Incoming global index "
844 << GID <<
" does not have a corresponding local index in the "
845 "Directory Map. Please report this bug to the Tpetra developers.");
846 ownedPidLidPairs[dirMapLid].push_back(std::make_pair(PID, LID));
858 for (
size_t i = 0; i < dir_numMyEntries; ++i) {
859 const std::vector<std::pair<int, LO> >& pidLidList =
861 const size_t listLen = pidLidList.size();
862 if (listLen == 0)
continue;
864 const LO dirMapLid =
static_cast<LO
>(i);
865 const GO dirMapGid = directoryMap_->getGlobalElement(dirMapLid);
867 locallyOneToOne_ =
false;
876 const size_type index =
877 static_cast<size_type
>(tie_break->selectedIndex(dirMapGid,
879 PIDs_[i] = pidLidList[index].first;
880 LIDs_[i] = pidLidList[index].second;
886template <
class LO,
class GO,
class NT>
889 std::ostringstream os;
890 os <<
"DistributedNoncontiguousDirectory"
891 <<
"<" << Teuchos::TypeNameTraits<LO>::name()
892 <<
", " << Teuchos::TypeNameTraits<GO>::name()
893 <<
", " << Teuchos::TypeNameTraits<NT>::name() <<
">";
897template <
class LO,
class GO,
class NT>
901 const Teuchos::ArrayView<const GO>& globalIDs,
902 const Teuchos::ArrayView<int>& nodeIDs,
903 const Teuchos::ArrayView<LO>& localIDs,
904 const bool computeLIDs)
const {
909 using Teuchos::Array;
910 using Teuchos::ArrayRCP;
911 using Teuchos::ArrayView;
914 using Teuchos::toString;
915 using size_type =
typename Array<GO>::size_type;
916 const char funcPrefix[] =
918 "DistributedNoncontiguousDirectory::getEntriesImpl: ";
919 const char errSuffix[] =
920 " Please report this bug to the Tpetra developers.";
922 RCP<const Teuchos::Comm<int> > comm = map.getComm();
927 std::unique_ptr<std::string> procPrefix;
929 std::ostringstream os;
931 if (map.getComm().is_null()) {
934 os << map.getComm()->getRank();
937 procPrefix = std::unique_ptr<std::string>(
938 new std::string(os.str()));
939 os << funcPrefix <<
"{";
945 os <<
", computeLIDs: "
946 << (computeLIDs ?
"true" :
"false") <<
"}" << endl;
950 const size_t numEntries = globalIDs.size();
951 const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid();
960 const int packetSize = computeLIDs ? 3 : 2;
966 Array<int> dirImages(numEntries);
968 std::ostringstream os;
969 os << *procPrefix <<
"Call directoryMap_->getRemoteIndexList"
973 res = directoryMap_->getRemoteIndexList(globalIDs, dirImages());
975 std::ostringstream os;
976 os << *procPrefix <<
"Director Map getRemoteIndexList out ";
983 size_t numMissing = 0;
985 for (
size_t i = 0; i < numEntries; ++i) {
986 if (dirImages[i] == -1) {
989 localIDs[i] = LINVALID;
997 Array<int> sendImages;
999 std::ostringstream os;
1000 os << *procPrefix <<
"Call Distributor::createFromRecvs"
1006 std::ostringstream os;
1007 os << *procPrefix <<
"Distributor::createFromRecvs result: "
1015 const size_type numSends = sendGIDs.size();
1048 Kokkos::View<global_size_t*, Kokkos::HostSpace> exports(
"exports", packetSize * numSends);
1061 size_t exportsIndex = 0;
1063 if (useHashTables_) {
1065 std::ostringstream os;
1066 os << *procPrefix <<
"Pack exports (useHashTables_ true)"
1070 for (size_type gidIndex = 0; gidIndex < numSends; ++gidIndex) {
1071 const GO curGID = sendGIDs[gidIndex];
1073 exports[exportsIndex++] =
static_cast<global_size_t>(curGID);
1074 const LO curLID = directoryMap_->getLocalElement(curGID);
1075 TEUCHOS_TEST_FOR_EXCEPTION(curLID == LINVALID, std::logic_error, funcPrefix <<
"Directory Map's global index " << curGID <<
" lacks "
1076 "a corresponding local index."
1079 exports[exportsIndex++] =
1083 exports[exportsIndex++] =
1089 std::ostringstream os;
1090 os << *procPrefix <<
"Pack exports (useHashTables_ false)"
1094 for (size_type gidIndex = 0; gidIndex < numSends; ++gidIndex) {
1095 const GO curGID = sendGIDs[gidIndex];
1097 exports[exportsIndex++] =
static_cast<global_size_t>(curGID);
1098 const LO curLID = directoryMap_->getLocalElement(curGID);
1099 TEUCHOS_TEST_FOR_EXCEPTION(curLID == LINVALID, std::logic_error, funcPrefix <<
"Directory Map's global index " << curGID <<
" lacks "
1100 "a corresponding local index."
1103 exports[exportsIndex++] =
1107 exports[exportsIndex++] =
1113 TEUCHOS_TEST_FOR_EXCEPTION(exportsIndex > exports.size(), std::logic_error,
1114 funcPrefix <<
"On Process " << comm->getRank() <<
", "
1116 << exportsIndex <<
" > exports.size() = "
1117 << exports.size() <<
"." << errSuffix);
1120 TEUCHOS_TEST_FOR_EXCEPTION(numEntries < numMissing, std::logic_error, funcPrefix <<
"On Process " << comm->getRank() <<
", numEntries = " << numEntries <<
" < numMissing = " << numMissing <<
"." << errSuffix);
1126 const size_t numRecv = numEntries - numMissing;
1130 const size_t requiredImportLen = numRecv * packetSize;
1131 const int myRank = comm->getRank();
1132 TEUCHOS_TEST_FOR_EXCEPTION(
1133 importLen < requiredImportLen, std::logic_error,
1134 "Tpetra::Details::DistributedNoncontiguousDirectory::getEntriesImpl: "
1136 << myRank <<
": The 'imports' array must have length "
1138 << requiredImportLen <<
", but its actual length is " << importLen <<
". numRecv: " << numRecv <<
", packetSize: " << packetSize <<
", numEntries (# GIDs): " << numEntries <<
", numMissing: " << numMissing <<
": distor.getTotalReceiveLength(): "
1140 <<
"Distributor description: " << distor.
description() <<
". "
1142 <<
"Please report this bug to the Tpetra developers.");
1145 Kokkos::View<global_size_t*, Kokkos::HostSpace> imports(
"imports", packetSize * distor.
getTotalReceiveLength());
1150 std::ostringstream os;
1151 os << *procPrefix <<
"Call doPostsAndWaits: {"
1152 <<
"packetSize: " << packetSize <<
", ";
1159 std::ostringstream os;
1160 os << *procPrefix <<
"doPostsAndWaits result: ";
1166 Array<GO> sortedIDs(globalIDs);
1167 Array<GO> offset(numEntries);
1168 for (GO ii = 0; ii < static_cast<GO>(numEntries); ++ii) {
1171 sort2(sortedIDs.begin(), sortedIDs.begin() + numEntries, offset.begin());
1173 std::ostringstream os;
1182 size_t importsIndex = 0;
1187 for (
size_t i = 0; i < numRecv; ++i) {
1188 const GO curGID =
static_cast<GO
>(imports[importsIndex++]);
1189 auto p1 = std::equal_range(sortedIDs.begin(),
1190 sortedIDs.end(), curGID);
1191 if (p1.first != p1.second) {
1192 const size_t j = p1.first - sortedIDs.begin();
1193 nodeIDs[offset[j]] =
1194 static_cast<int>(imports[importsIndex++]);
1196 localIDs[offset[j]] =
1197 static_cast<LO
>(imports[importsIndex++]);
1199 if (nodeIDs[offset[j]] == -1) {
1205 TEUCHOS_TEST_FOR_EXCEPTION(
size_t(importsIndex) >
size_t(imports.size()),
1206 std::logic_error, funcPrefix <<
"On Process " << comm->getRank() <<
": importsIndex = " << importsIndex <<
" > imports.size() = " << imports.size() <<
". "
1208 << numRecv <<
", packetSize: " << packetSize <<
", "
1209 "numEntries (# GIDs): "
1210 << numEntries <<
", numMissing: " << numMissing <<
": distor.getTotalReceiveLength(): " << distor.
getTotalReceiveLength() <<
"." << errSuffix);
1212 std::ostringstream os;
1213 os << *procPrefix << funcPrefix <<
"Done!" << endl;
1219template <
class LO,
class GO,
class NT>
1221 isOneToOne(
const Teuchos::Comm<int>& comm)
const {
1222 if (oneToOneResult_ == ONE_TO_ONE_NOT_CALLED_YET) {
1223 const int lcl121 = isLocallyOneToOne() ? 1 : 0;
1225 Teuchos::reduceAll<int, int>(comm, Teuchos::REDUCE_MIN, lcl121,
1226 Teuchos::outArg(gbl121));
1227 oneToOneResult_ = (gbl121 == 1) ? ONE_TO_ONE_TRUE : ONE_TO_ONE_FALSE;
1229 return (oneToOneResult_ == ONE_TO_ONE_TRUE);
1239#define TPETRA_DIRECTORYIMPL_INSTANT(LO, GO, NODE) \
1240 namespace Details { \
1241 template class Directory<LO, GO, NODE>; \
1242 template class ReplicatedDirectory<LO, GO, NODE>; \
1243 template class ContiguousUniformDirectory<LO, GO, NODE>; \
1244 template class DistributedContiguousDirectory<LO, GO, NODE>; \
1245 template class DistributedNoncontiguousDirectory<LO, GO, NODE>; \
Interface for breaking ties in ownership.
Stand-alone utility functions and macros.
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const override
The communicator over which the matrix is distributed.
Description of Tpetra's behavior.
static bool verbose()
Whether Tpetra is in verbose mode.
static size_t verbosePrintCountThreshold()
Number of entries below which arrays, lists, etc. will be printed in debug mode.
LookupStatus getEntries(const map_type &map, const Teuchos::ArrayView< const GlobalOrdinal > &globalIDs, const Teuchos::ArrayView< int > &nodeIDs, const Teuchos::ArrayView< LocalOrdinal > &localIDs, const bool computeLIDs) const
virtual LookupStatus getEntriesImpl(const map_type &map, const Teuchos::ArrayView< const GlobalOrdinal > &globalIDs, const Teuchos::ArrayView< int > &nodeIDs, const Teuchos::ArrayView< LocalOrdinal > &localIDs, const bool computeLIDs) const =0
Actually do the work of getEntries(), with no input validation.
Implementation of Directory for a distributed contiguous Map.
LookupStatus getEntriesImpl(const map_type &map, const Teuchos::ArrayView< const GlobalOrdinal > &globalIDs, const Teuchos::ArrayView< int > &nodeIDs, const Teuchos::ArrayView< LocalOrdinal > &localIDs, const bool computeLIDs) const override
Find process IDs and (optionally) local IDs for the given global IDs.
std::string description() const override
A one-line human-readable description of this object.
Implementation of Directory for a distributed noncontiguous Map.
std::string description() const override
A one-line human-readable description of this object.
bool isOneToOne(const Teuchos::Comm< int > &comm) const override
Whether the Directory's input Map is (globally) one to one.
LookupStatus getEntriesImpl(const map_type &map, const Teuchos::ArrayView< const GlobalOrdinal > &globalIDs, const Teuchos::ArrayView< int > &nodeIDs, const Teuchos::ArrayView< LocalOrdinal > &localIDs, const bool computeLIDs) const override
Find process IDs and (optionally) local IDs for the given global IDs.
LookupStatus getEntriesImpl(const map_type &map, const Teuchos::ArrayView< const GlobalOrdinal > &globalIDs, const Teuchos::ArrayView< int > &nodeIDs, const Teuchos::ArrayView< LocalOrdinal > &localIDs, const bool computeLIDs) const override
Find process IDs and (optionally) local IDs for the given global IDs.
bool isOneToOne(const Teuchos::Comm< int > &comm) const override
Whether the Directory's input Map is (globally) one to one.
std::string description() const override
A one-line human-readable description of this object.
ReplicatedDirectory()=default
Constructor (that takes no arguments).
bool isDistributed() const
Sets up and executes a communication plan for a Tpetra DistObject.
std::enable_if<(Kokkos::is_view< ExpView >::value &&Kokkos::is_view< ImpView >::value)>::type doPostsAndWaits(const ExpView &exports, size_t numPackets, const ImpView &imports)
Execute the (forward) communication plan.
void createFromRecvs(const Teuchos::ArrayView< const Ordinal > &remoteIDs, const Teuchos::ArrayView< const int > &remoteProcIDs, Teuchos::Array< Ordinal > &exportIDs, Teuchos::Array< int > &exportProcIDs)
Set up Distributor using list of process ranks from which to receive.
size_t getTotalReceiveLength() const
Total number of values this process will receive from other processes.
std::string description() const
Return a one-line description of this object.
global_ordinal_type getMinAllGlobalIndex() const
The minimum global index over all processes in the communicator.
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const
Accessors for the Teuchos::Comm and Kokkos Node objects.
local_ordinal_type getLocalElement(global_ordinal_type globalIndex) const
The local index corresponding to the given global index.
global_size_t getGlobalNumElements() const
The number of elements in this Map.
bool isNodeGlobalElement(global_ordinal_type globalIndex) const
Whether the given global index is owned by this Map on the calling process.
Nonmember function that computes a residual Computes R = B - A * X.
void verbosePrintArray(std::ostream &out, const ArrayType &x, const char name[], const size_t maxNumToPrint)
Print min(x.size(), maxNumToPrint) entries of x.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
void initialize(int *argc, char ***argv)
Initialize Tpetra.
void sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2, const bool stableSort=false)
Sort the first array, and apply the resulting permutation to the second array.
LookupStatus
Return status of Map remote index lookup (getRemoteIndexList()).
size_t global_size_t
Global size_t object.