10#ifndef TPETRA_IMPORT_DEF_HPP
11#define TPETRA_IMPORT_DEF_HPP
13#include "Tpetra_Distributor.hpp"
14#include "Tpetra_Map.hpp"
15#include "Tpetra_ImportExportData.hpp"
18#include "Tpetra_Export.hpp"
20#include "Tpetra_Details_DualViewUtil.hpp"
23#include "Teuchos_as.hpp"
33std::string toString(
const std::vector<T>& x) {
34 std::ostringstream os;
36 const std::size_t N = x.size();
37 for (std::size_t k = 0; k < N; ++k) {
39 if (k + std::size_t(1) < N) {
47template <
class ElementType,
class DeviceType>
48std::string toString(
const Kokkos::View<const ElementType*, DeviceType>& x) {
49 std::ostringstream os;
51 const std::size_t N = std::size_t(x.extent(0));
52 for (std::size_t k = 0; k < N; ++k) {
54 if (k + std::size_t(1) < N) {
67template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
68void Import<LocalOrdinal, GlobalOrdinal, Node>::
69 init(
const Teuchos::RCP<const map_type>& source,
70 const Teuchos::RCP<const map_type>& ,
72 Teuchos::Array<int>& remotePIDs,
73 const Teuchos::RCP<Teuchos::ParameterList>& plist) {
79 using ::Tpetra::Details::ProfilingRegion;
80 ProfilingRegion regionImportInit(
"Tpetra::Import::init");
82 std::unique_ptr<std::string> verbPrefix;
83 if (this->verbose()) {
84 std::ostringstream os;
85 const int myRank = source->getComm()->getRank();
86 os <<
"Proc " << myRank <<
": Tpetra::Import::init: ";
87 verbPrefix = std::unique_ptr<std::string>(
new std::string(os.str()));
89 this->verboseOutputStream() << os.str();
92 Array<GlobalOrdinal> remoteGIDs;
96 if (this->verbose()) {
97 std::ostringstream os;
98 os << *verbPrefix <<
"Call setupSamePermuteRemote" << endl;
99 this->verboseOutputStream() << os.str();
101 setupSamePermuteRemote(remoteGIDs);
105 if (source->isDistributed()) {
106 if (this->verbose()) {
107 std::ostringstream os;
108 os << *verbPrefix <<
"Call setupExport" << endl;
109 this->verboseOutputStream() << os.str();
111 setupExport(remoteGIDs, useRemotePIDs, remotePIDs);
112 }
else if (this->verbose()) {
113 std::ostringstream os;
114 os << *verbPrefix <<
"Source Map not distributed; skip setupExport"
116 this->verboseOutputStream() << os.str();
120 TEUCHOS_ASSERT(!this->TransferData_->permuteFromLIDs_.need_sync_device());
121 TEUCHOS_ASSERT(!this->TransferData_->permuteFromLIDs_.need_sync_host());
122 TEUCHOS_ASSERT(!this->TransferData_->permuteToLIDs_.need_sync_device());
123 TEUCHOS_ASSERT(!this->TransferData_->permuteToLIDs_.need_sync_host());
124 TEUCHOS_ASSERT(!this->TransferData_->remoteLIDs_.need_sync_device());
125 TEUCHOS_ASSERT(!this->TransferData_->remoteLIDs_.need_sync_host());
126 TEUCHOS_ASSERT(!this->TransferData_->exportLIDs_.need_sync_device());
127 TEUCHOS_ASSERT(!this->TransferData_->exportLIDs_.need_sync_host());
129 this->detectRemoteExportLIDsContiguous();
131 if (this->verbose()) {
132 std::ostringstream os;
133 os << *verbPrefix <<
"Done!" << endl;
134 this->verboseOutputStream() << os.str();
138template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
141 const Teuchos::RCP<const map_type>&
target)
143 Teuchos::Array<int>
dummy;
147template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
150 const Teuchos::RCP<const map_type>&
target,
151 const Teuchos::RCP<Teuchos::FancyOStream>&
out)
153 Teuchos::Array<int>
dummy;
157template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
160 const Teuchos::RCP<const map_type>&
target,
161 const Teuchos::RCP<Teuchos::ParameterList>&
plist)
163 Teuchos::Array<int>
dummy;
167template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
170 const Teuchos::RCP<const map_type>&
target,
171 const Teuchos::RCP<Teuchos::FancyOStream>&
out,
172 const Teuchos::RCP<Teuchos::ParameterList>&
plist)
174 Teuchos::Array<int>
dummy;
178template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
181 const Teuchos::RCP<const map_type>&
target,
182 Teuchos::Array<int>& remotePIDs,
183 const Teuchos::RCP<Teuchos::ParameterList>&
plist)
188template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
193template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
201template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
208 const Teuchos::RCP<Teuchos::ParameterList>&
plist,
209 const Teuchos::RCP<Teuchos::FancyOStream>&
out)
213 using Teuchos::Array;
214 using Teuchos::ArrayRCP;
215 using Teuchos::ArrayView;
219 using ::Tpetra::Details::makeDualViewFromArrayView;
222 using size_type = Teuchos::Array<int>::size_type;
224 std::unique_ptr<std::string>
prefix;
226 auto comm =
source.is_null() ? Teuchos::null :
source->getComm();
227 const int myRank = comm.is_null() ? -1 : comm->getRank();
228 std::ostringstream
os;
229 os <<
"Proc " << myRank <<
": Tpetra::Import createExpert ctor: ";
230 prefix = std::unique_ptr<std::string>(
new std::string(
os.str()));
240 std::ostringstream
os;
247 std::ostringstream
os;
257 std::ostringstream
os;
258 os << *
prefix <<
"Target Map has remote LIDs but source Map is not "
259 "distributed. Importing to a submap of the target Map."
267 "::constructExpert: Target Map has remote LIDs but source Map "
268 "is not distributed. Importing to a submap of the target Map.");
272 "Import::Import createExpert version: "
273 "Size mismatch on userRemotePIDs, remoteGIDs, and remoteLIDs "
274 "Array's to sort3.");
293 if (indexIntoRemotePIDs -
cnt > 0) {
322 userExportLIDs,
"exportLIDs");
333 std::ostringstream
os;
334 os << *
prefix <<
"locallyComplete: "
336 <<
"; call createFromSendsAndRecvs" <<
endl;
345 this->detectRemoteExportLIDsContiguous();
357template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
360 const Teuchos::RCP<const map_type>&
target,
361 const size_t numSameIDs,
364 Teuchos::Array<LocalOrdinal>& remoteLIDs,
368 const Teuchos::RCP<Teuchos::FancyOStream>&
out,
369 const Teuchos::RCP<Teuchos::ParameterList>&
plist)
372 using ::Tpetra::Details::makeDualViewFromArrayView;
374 std::unique_ptr<std::string>
prefix;
376 auto comm =
source.is_null() ? Teuchos::null :
source->getComm();
377 const int myRank = comm.is_null() ? -1 : comm->getRank();
378 std::ostringstream
os;
379 os <<
"Proc " << myRank <<
": Tpetra::Import export ctor: ";
380 prefix = std::unique_ptr<std::string>(
new std::string(
os.str()));
385 bool locallyComplete =
true;
386 for (Teuchos::Array<int>::size_type i = 0; i < exportPIDs.size(); ++i) {
387 if (exportPIDs[i] == -1) {
388 locallyComplete =
false;
392 std::ostringstream os;
393 os << *prefix <<
"numSameIDs: " << numSameIDs <<
", locallyComplete: "
394 << (locallyComplete ?
"true" :
"false") << endl;
401 makeDualViewFromArrayView(this->
TransferData_->permuteToLIDs_,
402 permuteToLIDs().getConst(),
404 TEUCHOS_ASSERT(
size_t(this->
TransferData_->permuteToLIDs_.extent(0)) ==
405 size_t(permuteToLIDs.size()));
406 makeDualViewFromArrayView(this->
TransferData_->permuteFromLIDs_,
407 permuteFromLIDs().getConst(),
409 TEUCHOS_ASSERT(
size_t(this->
TransferData_->permuteFromLIDs_.extent(0)) ==
410 size_t(permuteFromLIDs.size()));
412 remoteLIDs().getConst(),
414 TEUCHOS_ASSERT(
size_t(this->
TransferData_->remoteLIDs_.extent(0)) ==
415 size_t(remoteLIDs.size()));
417 exportLIDs().getConst(),
419 TEUCHOS_ASSERT(
size_t(this->
TransferData_->exportLIDs_.extent(0)) ==
420 size_t(exportLIDs.size()));
424 this->detectRemoteExportLIDsContiguous();
426 TEUCHOS_ASSERT(!this->
TransferData_->permuteFromLIDs_.need_sync_device());
427 TEUCHOS_ASSERT(!this->
TransferData_->permuteFromLIDs_.need_sync_host());
428 TEUCHOS_ASSERT(!this->
TransferData_->permuteToLIDs_.need_sync_device());
429 TEUCHOS_ASSERT(!this->
TransferData_->permuteToLIDs_.need_sync_host());
430 TEUCHOS_ASSERT(!this->
TransferData_->remoteLIDs_.need_sync_device());
431 TEUCHOS_ASSERT(!this->
TransferData_->remoteLIDs_.need_sync_host());
432 TEUCHOS_ASSERT(!this->
TransferData_->exportLIDs_.need_sync_device());
433 TEUCHOS_ASSERT(!this->
TransferData_->exportLIDs_.need_sync_host());
438template <
class LO,
class GO,
class NT>
439struct ImportLocalSetupResult {
440 Teuchos::RCP<const ::Tpetra::Map<LO, GO, NT>> targetMap;
444 std::vector<GO> remoteGIDs;
445 std::vector<LO> remoteLIDs;
446 std::vector<int> remotePIDs;
451void printArray(std::ostream& out,
const T x[],
const std::size_t N) {
453 for (std::size_t k = 0; k < N; ++k) {
462template <
class LO,
class GO,
class NT>
463ImportLocalSetupResult<LO, GO, NT>
464setupSamePermuteRemoteFromUserGlobalIndexList(const ::Tpetra::Map<LO, GO, NT>& sourceMap,
465 const GO targetMapRemoteOrPermuteGlobalIndices[],
466 const int targetMapRemoteOrPermuteProcessRanks[],
467 const LO numTargetMapRemoteOrPermuteGlobalIndices,
468 const bool mayReorderTargetMapIndicesLocally,
469 Teuchos::FancyOStream* out,
470 const std::string* verboseHeader,
474 const int myRank = sourceMap.getComm()->getRank();
475 ImportLocalSetupResult<LO, GO, NT> result;
478 std::ostringstream os;
479 os << *verboseHeader <<
"- Import::setupSPR w/ remote GIDs & PIDs: " << endl
480 << *verboseHeader <<
" Input GIDs: ";
481 printArray(os, targetMapRemoteOrPermuteGlobalIndices, numTargetMapRemoteOrPermuteGlobalIndices);
484 printArray(os, targetMapRemoteOrPermuteProcessRanks, numTargetMapRemoteOrPermuteGlobalIndices);
494 std::vector<GO> badGIDs;
495 std::vector<int> badPIDs;
496 const Teuchos::Comm<int>& comm = *(sourceMap.getComm());
497 const int numProcs = comm.getSize();
499 for (LO k = 0; k < numTargetMapRemoteOrPermuteGlobalIndices; ++k) {
500 const GO tgtGID = targetMapRemoteOrPermuteGlobalIndices[k];
501 if (sourceMap.isNodeGlobalElement(tgtGID)) {
502 badGIDs.push_back(tgtGID);
504 const int tgtPID = targetMapRemoteOrPermuteProcessRanks[k];
505 if (tgtPID < 0 || tgtPID >= numProcs) {
506 badPIDs.push_back(tgtPID);
510 std::array<int, 2> lclStatus{{badGIDs.size() == 0 ? 1 : 0,
511 badPIDs.size() == 0 ? 1 : 0}};
512 std::array<int, 2> gblStatus{{0, 0}};
513 Teuchos::reduceAll<int, int>(comm, Teuchos::REDUCE_MIN, 2,
514 lclStatus.data(), gblStatus.data());
515 const bool good = gblStatus[0] == 1 && gblStatus[1] == 1;
518 if (verbose && gblStatus[0] != 1) {
519 std::ostringstream os;
520 os << *verboseHeader <<
"- Some input GIDs are already in the source Map: ";
521 printArray(os, badGIDs.data(), badGIDs.size());
525 if (verbose && gblStatus[0] != 1) {
526 std::ostringstream os;
527 os << *verboseHeader <<
"- Some input PIDs are invalid: ";
528 printArray(os, badPIDs.data(), badPIDs.size());
534 std::ostringstream os;
535 os <<
"Tpetra::Import constructor that takes remote GIDs and PIDs: ";
536 if (gblStatus[0] != 1) {
537 os <<
"Some input GIDs (global indices) are already in the source Map! ";
539 if (gblStatus[1] != 1) {
540 os <<
"Some input PIDs (process ranks) are invalid! ";
542 os <<
"Rerun with the environment variable TPETRA_VERBOSE=Tpetra::Import "
543 "to see what GIDs and/or PIDs are bad.";
544 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument, os.str());
551 const LO numLclSrcIDs =
static_cast<LO
>(sourceMap.getLocalNumElements());
552 const LO numLclTgtIDs = numLclSrcIDs + numTargetMapRemoteOrPermuteGlobalIndices;
554 std::ostringstream os;
555 os << *verboseHeader <<
"- Copy source Map GIDs into target Map GID list: "
558 <<
", numTargetMapRemoteOrPermuteGlobalIndices="
559 << numTargetMapRemoteOrPermuteGlobalIndices << endl;
562 std::vector<GO> tgtGIDs(numLclTgtIDs);
563 if (sourceMap.isContiguous()) {
564 GO curTgtGID = sourceMap.getMinGlobalIndex();
565 for (LO k = 0; k < numLclSrcIDs; ++k, ++curTgtGID) {
566 tgtGIDs[k] = curTgtGID;
569 auto srcGIDs = sourceMap.getLocalElementList();
570 for (LO k = 0; k < numLclSrcIDs; ++k) {
571 tgtGIDs[k] = srcGIDs[k];
574 std::copy(targetMapRemoteOrPermuteGlobalIndices,
575 targetMapRemoteOrPermuteGlobalIndices + numTargetMapRemoteOrPermuteGlobalIndices,
576 tgtGIDs.begin() + numLclSrcIDs);
589 std::ostringstream os;
590 os << *verboseHeader <<
"- Sort by PID? "
591 << (mayReorderTargetMapIndicesLocally ?
"true" :
"false") << endl;
594 std::vector<int> tgtPIDs(targetMapRemoteOrPermuteProcessRanks,
595 targetMapRemoteOrPermuteProcessRanks + numTargetMapRemoteOrPermuteGlobalIndices);
596 result.numPermutes = 0;
597 if (mayReorderTargetMapIndicesLocally) {
598 Tpetra::sort2(tgtPIDs.begin(), tgtPIDs.end(), tgtGIDs.begin() + numLclSrcIDs);
599 auto range = std::equal_range(tgtPIDs.begin(), tgtPIDs.end(), myRank);
600 if (range.second > range.first) {
601 result.numPermutes =
static_cast<LO
>(range.second - range.first);
604 result.numPermutes =
static_cast<LO
>(std::count(tgtPIDs.begin(), tgtPIDs.end(), myRank));
607 const LO numRemotes = numTargetMapRemoteOrPermuteGlobalIndices - result.numPermutes;
608 result.numSameIDs =
static_cast<LO
>(sourceMap.getLocalNumElements());
611 std::ostringstream os;
612 os << *verboseHeader <<
"- numSame=" << result.numSameIDs
613 <<
", numPermutes=" << result.numPermutes
614 <<
", numRemotes=" << numRemotes << endl;
618 if (result.numPermutes == 0) {
620 std::ostringstream os;
621 os << *verboseHeader <<
"- No permutes" << endl;
624 result.remoteGIDs = std::vector<GO>(tgtGIDs.begin() + numLclSrcIDs, tgtGIDs.end());
625 result.remotePIDs.swap(tgtPIDs);
626 result.remoteLIDs.resize(numRemotes);
627 for (LO k = 0; k < numRemotes; ++k) {
628 const LO tgtLid = result.numSameIDs + k;
629 result.remoteLIDs[k] = tgtLid;
632 std::ostringstream os;
633 os << *verboseHeader <<
"- Remote GIDs: "
634 << Teuchos::toString(result.remoteGIDs) << endl;
635 os << *verboseHeader <<
"- Remote PIDs: "
636 << Teuchos::toString(result.remotePIDs) << endl;
637 os << *verboseHeader <<
"- Remote LIDs: "
638 << Teuchos::toString(result.remoteLIDs) << endl;
645 result.remoteGIDs.reserve(numRemotes);
646 result.remoteLIDs.reserve(numRemotes);
647 result.remotePIDs.reserve(numRemotes);
648 for (LO k = 0; k < numTargetMapRemoteOrPermuteGlobalIndices; ++k) {
649 const LO tgtLid = result.numSameIDs + k;
650 const GO tgtGid = tgtGIDs[numLclSrcIDs + k];
651 const int tgtPid = tgtPIDs[k];
653 if (tgtPid != myRank) {
654 result.remoteGIDs.push_back(tgtGid);
655 result.remoteLIDs.push_back(tgtLid);
656 result.remotePIDs.push_back(tgtPid);
660 std::ostringstream os;
661 os << *verboseHeader <<
"- Some permutes" << endl;
666 if (sourceMap.isDistributed()) {
668 std::ostringstream os;
669 os << *verboseHeader <<
"- Sort remotes by PID, as Import always does"
671 << *verboseHeader <<
"-- remotePIDs before: "
672 << Teuchos::toString(result.remotePIDs) << endl
673 << *verboseHeader <<
"-- remoteGIDs before: "
674 << Teuchos::toString(result.remoteGIDs) << endl
675 << *verboseHeader <<
"-- remoteLIDs before: "
676 << Teuchos::toString(result.remoteLIDs) << endl;
680 sort3(result.remotePIDs.begin(),
681 result.remotePIDs.end(),
682 result.remoteGIDs.begin(),
683 result.remoteLIDs.begin());
685 std::ostringstream os;
686 os << *verboseHeader <<
"-- remotePIDs after: "
687 << Teuchos::toString(result.remotePIDs) << endl
688 << *verboseHeader <<
"-- remoteGIDs after: "
689 << Teuchos::toString(result.remoteGIDs) << endl
690 << *verboseHeader <<
"-- remoteLIDs after: "
691 << Teuchos::toString(result.remoteLIDs) << endl;
692 std::cerr << os.str();
697 std::ostringstream os;
698 os << *verboseHeader <<
"- Make target Map" << endl;
701 using ::Teuchos::rcp;
702 typedef ::Tpetra::Map<LO, GO, NT> map_type;
704 const GST MAP_COMPUTES_GLOBAL_COUNT = ::Teuchos::OrdinalTraits<GST>::invalid();
705 result.targetMap = rcp(
new map_type(MAP_COMPUTES_GLOBAL_COUNT,
708 sourceMap.getIndexBase(),
709 sourceMap.getComm()));
711 std::ostringstream os;
712 os << *verboseHeader <<
"- Done with sameSPR..." << endl;
719template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
726 const Teuchos::RCP<Teuchos::ParameterList>&
plist,
727 const Teuchos::RCP<Teuchos::FancyOStream>&
debugOutput)
733 using Teuchos::ArrayView;
734 using Teuchos::getFancyOStream;
737 using Teuchos::rcpFromRef;
738 using ::Tpetra::Details::Behavior;
739 using ::Tpetra::Details::makeDualViewFromOwningHostView;
740 using ::Tpetra::Details::makeDualViewFromVector;
741 using ::Tpetra::Details::printDualView;
742 using ::Tpetra::Details::view_alloc_no_init;
747 const bool debug = Behavior::debug(
"Import") ||
748 Behavior::debug(
"Tpetra::Import");
750 std::unique_ptr<std::string>
verbPfx;
752 std::ostringstream
os;
753 const int myRank =
sourceMap->getComm()->getRank();
754 os <<
"Proc " << myRank <<
": Tpetra::Import ctor from remotes: ";
755 verbPfx = std::unique_ptr<std::string>(
new std::string(
os.str()));
780 this->TransferData_->out_,
782 this->
TransferData_->numSameIDs_ = localSetupResult.numSameIDs;
786 localSetupResult.remoteLIDs,
800 std::ostringstream
os;
801 os << *
verbPfx <<
"Make Distributor (createFromRecvs)" <<
endl;
826 std::ostringstream
os;
830 using size_type =
typename Teuchos::Array<GO>::size_type;
839 makeDualViewFromOwningHostView(this->
TransferData_->exportLIDs_, exportLIDs);
843 std::ostringstream
os;
846 "ImportExportData::remoteLIDs_");
851 std::ostringstream
os;
857template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
860 const Teuchos::EVerbosityLevel
verbLevel)
const {
865template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
867 print(std::ostream&
os)
const {
868 auto out = Teuchos::getFancyOStream(Teuchos::rcpFromRef(
os));
870 this->describe(*
out, Teuchos::VERB_EXTREME);
873template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
877 using Teuchos::Array;
878 using Teuchos::ArrayRCP;
879 using Teuchos::ArrayView;
882 using ::Tpetra::Details::makeDualViewFromOwningHostView;
883 using ::Tpetra::Details::ProfilingRegion;
884 using ::Tpetra::Details::view_alloc_no_init;
888 ProfilingRegion
regionExport(
"Tpetra::Import::setupSamePermuteRemote");
890 const map_type&
source = *(this->getSourceMap());
891 const map_type&
target = *(this->getTargetMap());
895#ifdef HAVE_TPETRA_DEBUG
915 this->TransferData_->numSameIDs_ = numSameGids;
929 const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid();
930 const LO numTgtLids = as<LO>(numTgtGids);
933 for (LO tgtLid = numSameGids; tgtLid < numTgtLids; ++tgtLid) {
934 const GO curTargetGid = rawTgtGids[tgtLid];
938 const LO srcLid = source.getLocalElement(curTargetGid);
939 if (srcLid != LINVALID) {
943 const LO numRemotes = (numTgtLids - numSameGids) - numPermutes;
945 using host_perm_type =
946 typename decltype(this->TransferData_->permuteToLIDs_)::t_host;
949 typename decltype(this->TransferData_->remoteLIDs_)::t_host remoteLIDs(
view_alloc_no_init(
"permuteFromLIDs"), numRemotes);
954 for (LO tgtLid = numSameGids; tgtLid < numTgtLids; ++tgtLid) {
955 const GO curTargetGid = rawTgtGids[tgtLid];
956 const LO srcLid = source.getLocalElement(curTargetGid);
957 if (srcLid != LINVALID) {
958 permuteToLIDs[numPermutes2] = tgtLid;
959 permuteFromLIDs[numPermutes2] = srcLid;
962 remoteGIDs.push_back(curTargetGid);
963 remoteLIDs[numRemotes2] = tgtLid;
967 TEUCHOS_ASSERT(numPermutes == numPermutes2);
968 TEUCHOS_ASSERT(numRemotes == numRemotes2);
969 TEUCHOS_ASSERT(
size_t(numPermutes) + remoteGIDs.size() ==
size_t(numTgtLids - numSameGids));
975 if (remoteLIDs.extent(0) != 0 && !source.isDistributed()) {
981 this->TransferData_->isLocallyComplete_ =
false;
985 "::setupSamePermuteRemote(): Target has "
986 "remote LIDs but Source is not distributed globally. Importing to a "
987 "submap of the target map.");
991template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
992void Import<LocalOrdinal, GlobalOrdinal, Node>::
993 setupExport(Teuchos::Array<GlobalOrdinal>& remoteGIDs,
995 Teuchos::Array<int>& userRemotePIDs,
996 const Teuchos::RCP<Teuchos::ParameterList>& plist) {
998 using Teuchos::Array;
999 using Teuchos::ArrayView;
1000 using ::Tpetra::Details::makeDualViewFromOwningHostView;
1001 using ::Tpetra::Details::view_alloc_no_init;
1002 using GO = GlobalOrdinal;
1003 typedef typename Array<int>::difference_type size_type;
1004 const char tfecfFuncName[] =
"setupExport: ";
1005 const char suffix[] =
" Please report this bug to the Tpetra developers.";
1007 std::unique_ptr<std::string> prefix;
1008 if (this->verbose()) {
1009 auto srcMap = this->getSourceMap();
1010 auto comm = srcMap.is_null() ? Teuchos::null : srcMap->getComm();
1011 const int myRank = comm.is_null() ? -1 : comm->getRank();
1012 std::ostringstream os;
1013 os <<
"Proc " << myRank <<
": Tpetra::Import::setupExport: ";
1014 prefix = std::unique_ptr<std::string>(
new std::string(os.str()));
1015 os <<
"Start" << std::endl;
1016 this->verboseOutputStream() << os.str();
1019 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->getSourceMap().is_null(), std::logic_error,
1020 "Source Map is null. " << suffix);
1021 const map_type& source = *(this->getSourceMap());
1023 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!useRemotePIDs && (userRemotePIDs.size() > 0), std::invalid_argument,
1024 "remotePIDs are non-empty but their use has not been requested.");
1025 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(userRemotePIDs.size() > 0 && remoteGIDs.size() != userRemotePIDs.size(),
1026 std::invalid_argument,
1027 "remotePIDs must either be of size zero or match "
1028 "the size of remoteGIDs.");
1032 ArrayView<GO> remoteGIDsView = remoteGIDs();
1033 ArrayView<int> remoteProcIDsView;
1053 Array<int> newRemotePIDs;
1056 if (!useRemotePIDs) {
1057 newRemotePIDs.resize(remoteGIDsView.size());
1058 if (this->verbose()) {
1059 std::ostringstream os;
1060 os << *prefix <<
"Call sourceMap.getRemoteIndexList" << endl;
1061 this->verboseOutputStream() << os.str();
1063 lookup = source.getRemoteIndexList(remoteGIDsView, newRemotePIDs());
1065 Array<int>& remoteProcIDs = useRemotePIDs ? userRemotePIDs : newRemotePIDs;
1072 this->TransferData_->isLocallyComplete_ =
false;
1077 "::setupExport(): the source Map wasn't "
1078 "able to figure out which process owns one or more of the GIDs in the "
1079 "list of remote GIDs. This probably means that there is at least one "
1080 "GID owned by some process in the target Map which is not owned by any"
1081 " process in the source Map. (That is, the source and target Maps do "
1082 "not contain the same set of GIDs globally.)");
1088 const size_type numInvalidRemote =
1089 std::count_if(remoteProcIDs.begin(), remoteProcIDs.end(),
1090 std::bind(std::equal_to<int>(), -1, std::placeholders::_1));
1091 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numInvalidRemote == 0, std::logic_error,
1092 "Calling getRemoteIndexList "
1093 "on the source Map returned IDNotPresent, but none of the returned "
1094 "\"remote\" process ranks are -1. Please report this bug to the "
1095 "Tpetra developers.");
1098 const size_type totalNumRemote = this->getNumRemoteIDs();
1099 if (numInvalidRemote == totalNumRemote) {
1101 remoteProcIDs.clear();
1103 this->TransferData_->remoteLIDs_ =
1104 decltype(this->TransferData_->remoteLIDs_)();
1108 size_type numValidRemote = 0;
1109#ifdef HAVE_TPETRA_DEBUG
1110 ArrayView<GO> remoteGIDsPtr = remoteGIDsView;
1112 GO*
const remoteGIDsPtr = remoteGIDsView.getRawPtr();
1116 auto remoteLIDs = this->TransferData_->remoteLIDs_.view_host();
1118 for (size_type r = 0; r < totalNumRemote; ++r) {
1120 if (remoteProcIDs[r] != -1) {
1121 remoteProcIDs[numValidRemote] = remoteProcIDs[r];
1122 remoteGIDsPtr[numValidRemote] = remoteGIDsPtr[r];
1123 remoteLIDs[numValidRemote] = remoteLIDs[r];
1127 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numValidRemote != totalNumRemote - numInvalidRemote,
1129 "After removing invalid remote GIDs and packing "
1130 "the valid remote GIDs, numValidRemote = "
1132 <<
" != totalNumRemote - numInvalidRemote = "
1133 << totalNumRemote - numInvalidRemote
1134 <<
". Please report this bug to the Tpetra developers.");
1136 remoteProcIDs.resize(numValidRemote);
1137 remoteGIDs.resize(numValidRemote);
1139 Kokkos::resize(remoteLIDs, numValidRemote);
1140 this->TransferData_->remoteLIDs_ =
decltype(this->TransferData_->remoteLIDs_)();
1144 remoteGIDsView = remoteGIDs();
1153 this->TransferData_->remoteLIDs_.modify_host();
1154 auto remoteLIDs = this->TransferData_->remoteLIDs_.view_host();
1155 sort3(remoteProcIDs.begin(),
1156 remoteProcIDs.end(),
1157 remoteGIDsView.getRawPtr(),
1159 this->TransferData_->remoteLIDs_.sync_device();
1167 Array<GO> exportGIDs;
1171 if (this->verbose()) {
1172 std::ostringstream os;
1173 os << *prefix <<
"Call createFromRecvs" << endl;
1174 this->verboseOutputStream() << endl;
1176 this->TransferData_->distributor_.createFromRecvs(remoteGIDsView().getConst(),
1177 remoteProcIDs, exportGIDs,
1178 this->TransferData_->exportPIDs_);
1189 const size_type numExportIDs = exportGIDs.size();
1190 if (numExportIDs > 0) {
1191 typename decltype(this->TransferData_->exportLIDs_)::t_host
1193 ArrayView<const GO> expGIDs = exportGIDs();
1195 for (size_type k = 0; k < numExportIDs; ++k) {
1196 exportLIDs[k] = source.getLocalElement(expGIDs[k]);
1201 if (this->verbose()) {
1202 std::ostringstream os;
1203 os << *prefix <<
"Done!" << endl;
1204 this->verboseOutputStream() << os.str();
1208template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1211 Teuchos::Array<std::pair<int, GlobalOrdinal>>&
remotePGIDs,
1212 typename Teuchos::Array<GlobalOrdinal>::size_type&
numSameGIDs,
1213 typename Teuchos::Array<GlobalOrdinal>::size_type&
numPermuteGIDs,
1214 typename Teuchos::Array<GlobalOrdinal>::size_type&
numRemoteGIDs,
1215 const Teuchos::ArrayView<const GlobalOrdinal>&
sameGIDs1,
1216 const Teuchos::ArrayView<const GlobalOrdinal>&
sameGIDs2,
1224 typedef typename Teuchos::Array<GO>::size_type size_type;
1307template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1308Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node>>
1311 using Teuchos::Array;
1312 using Teuchos::ArrayView;
1314 using Teuchos::Comm;
1315 using Teuchos::outArg;
1318 using Teuchos::REDUCE_MIN;
1319 using Teuchos::reduceAll;
1320 using ::Tpetra::Details::Behavior;
1333 const bool debug = Behavior::debug(
"Import::setUnion") ||
1334 Behavior::debug(
"Tpetra::Import::setUnion");
1338 "Tpetra::Import::setUnion: The source Map of the input Import must be the "
1339 "same as (in the sense of Map::isSameAs) the source Map of this Import.");
1343 std::invalid_argument,
1344 "Tpetra::Import::setUnion: "
1345 "The target Maps must have congruent communicators.");
1352 return rcp(
new import_type(*
this));
1367 std::shared_ptr<Details::CommRequest>
req;
1403 Tpetra::Import_Util::getRemotePIDs(*
this,
remotePIDs1);
1484 std::iota(idx.begin(), idx.end(), 0);
1485 std::sort(idx.begin(), idx.end(), [&
exportPIDsUnion, &
exportLIDsUnion](
const LO
i1,
const LO
i2) { return (exportPIDsUnion[i1] == exportPIDsUnion[i2]) ? (exportLIDsUnion[i1] < exportLIDsUnion[i2]) : (exportPIDsUnion[i1] < exportPIDsUnion[i2]); });
1515 this->TransferData_->out_));
1520template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1521Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node>>
1524 using Teuchos::Array;
1525 using Teuchos::ArrayView;
1527 using Teuchos::Comm;
1528 using Teuchos::outArg;
1531 using Teuchos::REDUCE_MIN;
1532 using Teuchos::reduceAll;
1538 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node>>
unionImport;
1568 GO
GO_INVALID = Teuchos::OrdinalTraits<GO>::invalid();
1593template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1594Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node>>
1598 using Teuchos::outArg;
1600 using Teuchos::REDUCE_MIN;
1601 using Teuchos::reduceAll;
1602 using ::Tpetra::Details::Behavior;
1603 using ::Tpetra::Details::gathervPrint;
1608 const char funcPrefix[] =
"Tpetra::createRemoteOnlyImport: ";
1611 const bool debug = Behavior::debug();
1613 const size_t NumRemotes = this->getNumRemoteIDs();
1615 Teuchos::RCP<const Teuchos::Comm<int>> comm;
1618 std::ostringstream
os;
1620 if (comm.is_null()) {
1623 os << comm->getRank();
1626 procPrefix = std::unique_ptr<std::string>(
new std::string(
os.str()));
1630 std::ostringstream
lclErr;
1636 <<
" != remoteTarget->getLocalNumElements() = "
1640 if (comm.is_null()) {
1648 if (comm.is_null()) {
1651 std::ostringstream
gblErr;
1660 Teuchos::ArrayView<const LO>
oldRemoteLIDs = this->getRemoteLIDs();
1665 std::unique_ptr<std::vector<size_t>>
badIndices;
1667 badIndices = std::unique_ptr<std::vector<size_t>>(
new std::vector<size_t>);
1672 if (
oldLclInd == Teuchos::OrdinalTraits<LO>::invalid()) {
1680 if (
gblInd == Teuchos::OrdinalTraits<GO>::invalid()) {
1688 if (
newLclInd == Teuchos::OrdinalTraits<LO>::invalid()) {
1710 if (comm.is_null()) {
1715 std::ostringstream
lclErr;
1718 <<
", bad indices: [";
1722 const size_t badIndex = (*badIndices)[
k];
1733 std::ostringstream
gblErr;
1735 "indices on one or more processes. \"Bad\" means that the "
1736 "indices are invalid, they don't exist in the target Map, "
1737 "they don't exist in remoteTarget, or they are not in "
1738 "sorted order. In what follows, I will show the \"bad\" "
1739 "indices as (k, LID) pairs, where k is the zero-based "
1740 "index of the LID in this->getRemoteLIDs()."
1742 if (comm.is_null()) {
1760 Teuchos::Array<LO>
dummy;
1771#define TPETRA_IMPORT_CLASS_INSTANT(LO, GO, NODE) \
1772 template class Import<LO, GO, NODE>;
1781#define TPETRA_IMPORT_INSTANT(LO, GO, NODE) \
1782 TPETRA_IMPORT_CLASS_INSTANT(LO, GO, NODE)
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
Declaration of a function that prints strings from each process.
Declaration of Tpetra::Details::iallreduce.
Internal functions and macros designed for use with Tpetra::Import and Tpetra::Export objects.
Stand-alone utility functions and macros.
#define TPETRA_ABUSE_WARNING(throw_exception_test, Exception, msg)
Handle an abuse warning, according to HAVE_TPETRA_THROW_ABUSE_WARNINGS and HAVE_TPETRA_PRINT_ABUSE_WA...
Struct that holds views of the contents of a CrsMatrix.
size_t getNumRemoteIDs() const
Number of entries not on the calling process.
bool verbose() const
Whether to print verbose debugging output.
Teuchos::RCP< ImportExportData< LocalOrdinal, GlobalOrdinal, Node > > TransferData_
All the data needed for executing the Export communication plan.
Teuchos::FancyOStream & verboseOutputStream() const
Valid (nonnull) output stream for verbose output.
Sets up and executes a communication plan for a Tpetra DistObject.
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.
void createFromSendsAndRecvs(const Teuchos::ArrayView< const int > &exportProcIDs, const Teuchos::ArrayView< const int > &remoteProcIDs)
Set up Distributor using list of process ranks to which to send, and list of process ranks from which...
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
Teuchos::RCP< const Import< LocalOrdinal, GlobalOrdinal, Node > > setUnion() const
Return the union of this Import this->getSourceMap()
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Describe this object in a human-readable way to the given output stream.
Teuchos::RCP< const Import< LocalOrdinal, GlobalOrdinal, Node > > createRemoteOnlyImport(const Teuchos::RCP< const map_type > &remoteTarget) const
Returns an importer that contains only the remote entries of this.
Import(const Teuchos::RCP< const map_type > &source, const Teuchos::RCP< const map_type > &target)
Construct an Import from the source and target Maps.
void findUnionTargetGIDs(Teuchos::Array< GlobalOrdinal > &unionTgtGIDs, Teuchos::Array< std::pair< int, GlobalOrdinal > > &remotePGIDs, typename Teuchos::Array< GlobalOrdinal >::size_type &numSameGIDs, typename Teuchos::Array< GlobalOrdinal >::size_type &numPermuteGIDs, typename Teuchos::Array< GlobalOrdinal >::size_type &numRemoteGIDs, const Teuchos::ArrayView< const GlobalOrdinal > &sameGIDs1, const Teuchos::ArrayView< const GlobalOrdinal > &sameGIDs2, Teuchos::Array< GlobalOrdinal > &permuteGIDs1, Teuchos::Array< GlobalOrdinal > &permuteGIDs2, Teuchos::Array< GlobalOrdinal > &remoteGIDs1, Teuchos::Array< GlobalOrdinal > &remoteGIDs2, Teuchos::Array< int > &remotePIDs1, Teuchos::Array< int > &remotePIDs2) const
Find the union of the target IDs from two Import objects.
virtual void print(std::ostream &os) const
Print the Import's data to the given output stream.
A parallel distribution of indices over processes.
auto view_alloc_no_init(const std::string &label) -> decltype(Kokkos::view_alloc(label, Kokkos::WithoutInitializing))
Use in place of the string label as the first argument of Kokkos::View's constructor,...
void makeDualViewFromOwningHostView(Kokkos::DualView< ElementType *, DeviceType > &dv, const typename Kokkos::DualView< ElementType *, DeviceType >::t_host &hostView)
Initialize dv such that its host View is hostView.
bool congruent(const Teuchos::Comm< int > &comm1, const Teuchos::Comm< int > &comm2)
Whether the two communicators are congruent.
void gathervPrint(std::ostream &out, const std::string &s, const Teuchos::Comm< int > &comm)
On Process 0 in the given communicator, print strings from each process in that communicator,...
Namespace Tpetra contains the class and methods constituting the Tpetra library.
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()).
void sort3(const IT1 &first1, const IT1 &last1, const IT2 &first2, const IT3 &first3, const bool stableSort=false)
Sort the first array, and apply the same permutation to the second and third arrays.