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"
29std::string toString(
const std::vector<T>& x) {
30 std::ostringstream os;
32 const std::size_t N = x.size();
33 for (std::size_t k = 0; k < N; ++k) {
35 if (k + std::size_t(1) < N) {
43template <
class ElementType,
class DeviceType>
44std::string toString(
const Kokkos::View<const ElementType*, DeviceType>& x) {
45 std::ostringstream os;
47 const std::size_t N = std::size_t(x.extent(0));
48 for (std::size_t k = 0; k < N; ++k) {
50 if (k + std::size_t(1) < N) {
63template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
64void Import<LocalOrdinal, GlobalOrdinal, Node>::
65 init(
const Teuchos::RCP<const map_type>& source,
66 const Teuchos::RCP<const map_type>& ,
68 Teuchos::Array<int>& remotePIDs,
69 const Teuchos::RCP<Teuchos::ParameterList>& plist) {
75 using ::Tpetra::Details::ProfilingRegion;
76 ProfilingRegion regionImportInit(
"Tpetra::Import::init");
78 std::unique_ptr<std::string> verbPrefix;
79 if (this->verbose()) {
80 std::ostringstream os;
81 const int myRank = source->getComm()->getRank();
82 os <<
"Proc " << myRank <<
": Tpetra::Import::init: ";
83 verbPrefix = std::unique_ptr<std::string>(
new std::string(os.str()));
85 this->verboseOutputStream() << os.str();
88 Array<GlobalOrdinal> remoteGIDs;
92 if (this->verbose()) {
93 std::ostringstream os;
94 os << *verbPrefix <<
"Call setupSamePermuteRemote" << endl;
95 this->verboseOutputStream() << os.str();
97 setupSamePermuteRemote(remoteGIDs);
101 if (source->isDistributed()) {
102 if (this->verbose()) {
103 std::ostringstream os;
104 os << *verbPrefix <<
"Call setupExport" << endl;
105 this->verboseOutputStream() << os.str();
107 setupExport(remoteGIDs, useRemotePIDs, remotePIDs);
108 }
else if (this->verbose()) {
109 std::ostringstream os;
110 os << *verbPrefix <<
"Source Map not distributed; skip setupExport"
112 this->verboseOutputStream() << os.str();
116 TEUCHOS_ASSERT(!this->TransferData_->permuteFromLIDs_.need_sync_device());
117 TEUCHOS_ASSERT(!this->TransferData_->permuteFromLIDs_.need_sync_host());
118 TEUCHOS_ASSERT(!this->TransferData_->permuteToLIDs_.need_sync_device());
119 TEUCHOS_ASSERT(!this->TransferData_->permuteToLIDs_.need_sync_host());
120 TEUCHOS_ASSERT(!this->TransferData_->remoteLIDs_.need_sync_device());
121 TEUCHOS_ASSERT(!this->TransferData_->remoteLIDs_.need_sync_host());
122 TEUCHOS_ASSERT(!this->TransferData_->exportLIDs_.need_sync_device());
123 TEUCHOS_ASSERT(!this->TransferData_->exportLIDs_.need_sync_host());
125 this->detectRemoteExportLIDsContiguous();
127 if (this->verbose()) {
128 std::ostringstream os;
129 os << *verbPrefix <<
"Done!" << endl;
130 this->verboseOutputStream() << os.str();
134template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
137 const Teuchos::RCP<const map_type>&
target)
139 Teuchos::Array<int>
dummy;
143template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
146 const Teuchos::RCP<const map_type>&
target,
147 const Teuchos::RCP<Teuchos::FancyOStream>&
out)
149 Teuchos::Array<int>
dummy;
153template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
156 const Teuchos::RCP<const map_type>&
target,
157 const Teuchos::RCP<Teuchos::ParameterList>&
plist)
159 Teuchos::Array<int>
dummy;
163template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
166 const Teuchos::RCP<const map_type>&
target,
167 const Teuchos::RCP<Teuchos::FancyOStream>&
out,
168 const Teuchos::RCP<Teuchos::ParameterList>&
plist)
170 Teuchos::Array<int>
dummy;
174template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
177 const Teuchos::RCP<const map_type>&
target,
178 Teuchos::Array<int>& remotePIDs,
179 const Teuchos::RCP<Teuchos::ParameterList>&
plist)
184template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
189template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
197template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
204 const Teuchos::RCP<Teuchos::ParameterList>&
plist,
205 const Teuchos::RCP<Teuchos::FancyOStream>&
out)
209 using Teuchos::Array;
210 using Teuchos::ArrayRCP;
211 using Teuchos::ArrayView;
215 using ::Tpetra::Details::makeDualViewFromArrayView;
218 using size_type = Teuchos::Array<int>::size_type;
220 std::unique_ptr<std::string>
prefix;
222 auto comm =
source.is_null() ? Teuchos::null :
source->getComm();
223 const int myRank = comm.is_null() ? -1 : comm->getRank();
224 std::ostringstream
os;
225 os <<
"Proc " <<
myRank <<
": Tpetra::Import createExpert ctor: ";
226 prefix = std::unique_ptr<std::string>(
new std::string(
os.str()));
236 std::ostringstream
os;
243 std::ostringstream
os;
253 std::ostringstream
os;
254 os << *
prefix <<
"Target Map has remote LIDs but source Map is not "
255 "distributed. Importing to a submap of the target Map."
263 "::constructExpert: Target Map has remote LIDs but source Map "
264 "is not distributed. Importing to a submap of the target Map.");
268 "Import::Import createExpert version: "
269 "Size mismatch on userRemotePIDs, remoteGIDs, and remoteLIDs "
270 "Array's to sort3.");
289 if (indexIntoRemotePIDs -
cnt > 0) {
318 userExportLIDs,
"exportLIDs");
329 std::ostringstream
os;
330 os << *
prefix <<
"locallyComplete: "
332 <<
"; call createFromSendsAndRecvs" <<
endl;
341 this->detectRemoteExportLIDsContiguous();
353template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
356 const Teuchos::RCP<const map_type>&
target,
357 const size_t numSameIDs,
360 Teuchos::Array<LocalOrdinal>& remoteLIDs,
364 const Teuchos::RCP<Teuchos::FancyOStream>&
out,
365 const Teuchos::RCP<Teuchos::ParameterList>&
plist)
368 using ::Tpetra::Details::makeDualViewFromArrayView;
370 std::unique_ptr<std::string>
prefix;
372 auto comm =
source.is_null() ? Teuchos::null :
source->getComm();
373 const int myRank = comm.is_null() ? -1 : comm->getRank();
374 std::ostringstream
os;
375 os <<
"Proc " <<
myRank <<
": Tpetra::Import export ctor: ";
376 prefix = std::unique_ptr<std::string>(
new std::string(
os.str()));
381 bool locallyComplete =
true;
382 for (Teuchos::Array<int>::size_type i = 0; i < exportPIDs.size(); ++i) {
383 if (exportPIDs[i] == -1) {
384 locallyComplete =
false;
388 std::ostringstream os;
389 os << *prefix <<
"numSameIDs: " << numSameIDs <<
", locallyComplete: "
390 << (locallyComplete ?
"true" :
"false") << endl;
397 makeDualViewFromArrayView(this->
TransferData_->permuteToLIDs_,
398 permuteToLIDs().getConst(),
400 TEUCHOS_ASSERT(
size_t(this->
TransferData_->permuteToLIDs_.extent(0)) ==
401 size_t(permuteToLIDs.size()));
402 makeDualViewFromArrayView(this->
TransferData_->permuteFromLIDs_,
403 permuteFromLIDs().getConst(),
405 TEUCHOS_ASSERT(
size_t(this->
TransferData_->permuteFromLIDs_.extent(0)) ==
406 size_t(permuteFromLIDs.size()));
408 remoteLIDs().getConst(),
410 TEUCHOS_ASSERT(
size_t(this->
TransferData_->remoteLIDs_.extent(0)) ==
411 size_t(remoteLIDs.size()));
413 exportLIDs().getConst(),
415 TEUCHOS_ASSERT(
size_t(this->
TransferData_->exportLIDs_.extent(0)) ==
416 size_t(exportLIDs.size()));
420 this->detectRemoteExportLIDsContiguous();
422 TEUCHOS_ASSERT(!this->
TransferData_->permuteFromLIDs_.need_sync_device());
423 TEUCHOS_ASSERT(!this->
TransferData_->permuteFromLIDs_.need_sync_host());
424 TEUCHOS_ASSERT(!this->
TransferData_->permuteToLIDs_.need_sync_device());
425 TEUCHOS_ASSERT(!this->
TransferData_->permuteToLIDs_.need_sync_host());
426 TEUCHOS_ASSERT(!this->
TransferData_->remoteLIDs_.need_sync_device());
427 TEUCHOS_ASSERT(!this->
TransferData_->remoteLIDs_.need_sync_host());
428 TEUCHOS_ASSERT(!this->
TransferData_->exportLIDs_.need_sync_device());
429 TEUCHOS_ASSERT(!this->
TransferData_->exportLIDs_.need_sync_host());
434template <
class LO,
class GO,
class NT>
435struct ImportLocalSetupResult {
436 Teuchos::RCP<const ::Tpetra::Map<LO, GO, NT>> targetMap;
440 std::vector<GO> remoteGIDs;
441 std::vector<LO> remoteLIDs;
442 std::vector<int> remotePIDs;
447void printArray(std::ostream& out,
const T x[],
const std::size_t N) {
449 for (std::size_t k = 0; k < N; ++k) {
458template <
class LO,
class GO,
class NT>
459ImportLocalSetupResult<LO, GO, NT>
460setupSamePermuteRemoteFromUserGlobalIndexList(const ::Tpetra::Map<LO, GO, NT>& sourceMap,
461 const GO targetMapRemoteOrPermuteGlobalIndices[],
462 const int targetMapRemoteOrPermuteProcessRanks[],
463 const LO numTargetMapRemoteOrPermuteGlobalIndices,
464 const bool mayReorderTargetMapIndicesLocally,
465 Teuchos::FancyOStream* out,
466 const std::string* verboseHeader,
470 const int myRank = sourceMap.getComm()->getRank();
471 ImportLocalSetupResult<LO, GO, NT> result;
474 std::ostringstream os;
475 os << *verboseHeader <<
"- Import::setupSPR w/ remote GIDs & PIDs: " << endl
476 << *verboseHeader <<
" Input GIDs: ";
477 printArray(os, targetMapRemoteOrPermuteGlobalIndices, numTargetMapRemoteOrPermuteGlobalIndices);
480 printArray(os, targetMapRemoteOrPermuteProcessRanks, numTargetMapRemoteOrPermuteGlobalIndices);
490 std::vector<GO> badGIDs;
491 std::vector<int> badPIDs;
492 const Teuchos::Comm<int>& comm = *(sourceMap.getComm());
493 const int numProcs = comm.getSize();
495 for (LO k = 0; k < numTargetMapRemoteOrPermuteGlobalIndices; ++k) {
496 const GO tgtGID = targetMapRemoteOrPermuteGlobalIndices[k];
497 if (sourceMap.isNodeGlobalElement(tgtGID)) {
498 badGIDs.push_back(tgtGID);
500 const int tgtPID = targetMapRemoteOrPermuteProcessRanks[k];
501 if (tgtPID < 0 || tgtPID >= numProcs) {
502 badPIDs.push_back(tgtPID);
506 std::array<int, 2> lclStatus{{badGIDs.size() == 0 ? 1 : 0,
507 badPIDs.size() == 0 ? 1 : 0}};
508 std::array<int, 2> gblStatus{{0, 0}};
509 Teuchos::reduceAll<int, int>(comm, Teuchos::REDUCE_MIN, 2,
510 lclStatus.data(), gblStatus.data());
511 const bool good = gblStatus[0] == 1 && gblStatus[1] == 1;
514 if (verbose && gblStatus[0] != 1) {
515 std::ostringstream os;
516 os << *verboseHeader <<
"- Some input GIDs are already in the source Map: ";
517 printArray(os, badGIDs.data(), badGIDs.size());
521 if (verbose && gblStatus[0] != 1) {
522 std::ostringstream os;
523 os << *verboseHeader <<
"- Some input PIDs are invalid: ";
524 printArray(os, badPIDs.data(), badPIDs.size());
530 std::ostringstream os;
531 os <<
"Tpetra::Import constructor that takes remote GIDs and PIDs: ";
532 if (gblStatus[0] != 1) {
533 os <<
"Some input GIDs (global indices) are already in the source Map! ";
535 if (gblStatus[1] != 1) {
536 os <<
"Some input PIDs (process ranks) are invalid! ";
538 os <<
"Rerun with the environment variable TPETRA_VERBOSE=Tpetra::Import "
539 "to see what GIDs and/or PIDs are bad.";
540 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument, os.str());
547 const LO numLclSrcIDs =
static_cast<LO
>(sourceMap.getLocalNumElements());
548 const LO numLclTgtIDs = numLclSrcIDs + numTargetMapRemoteOrPermuteGlobalIndices;
550 std::ostringstream os;
551 os << *verboseHeader <<
"- Copy source Map GIDs into target Map GID list: "
554 <<
", numTargetMapRemoteOrPermuteGlobalIndices="
555 << numTargetMapRemoteOrPermuteGlobalIndices << endl;
558 std::vector<GO> tgtGIDs(numLclTgtIDs);
559 if (sourceMap.isContiguous()) {
560 GO curTgtGID = sourceMap.getMinGlobalIndex();
561 for (LO k = 0; k < numLclSrcIDs; ++k, ++curTgtGID) {
562 tgtGIDs[k] = curTgtGID;
565 auto srcGIDs = sourceMap.getLocalElementList();
566 for (LO k = 0; k < numLclSrcIDs; ++k) {
567 tgtGIDs[k] = srcGIDs[k];
570 std::copy(targetMapRemoteOrPermuteGlobalIndices,
571 targetMapRemoteOrPermuteGlobalIndices + numTargetMapRemoteOrPermuteGlobalIndices,
572 tgtGIDs.begin() + numLclSrcIDs);
585 std::ostringstream os;
586 os << *verboseHeader <<
"- Sort by PID? "
587 << (mayReorderTargetMapIndicesLocally ?
"true" :
"false") << endl;
590 std::vector<int> tgtPIDs(targetMapRemoteOrPermuteProcessRanks,
591 targetMapRemoteOrPermuteProcessRanks + numTargetMapRemoteOrPermuteGlobalIndices);
592 result.numPermutes = 0;
593 if (mayReorderTargetMapIndicesLocally) {
594 Tpetra::sort2(tgtPIDs.begin(), tgtPIDs.end(), tgtGIDs.begin() + numLclSrcIDs);
595 auto range = std::equal_range(tgtPIDs.begin(), tgtPIDs.end(), myRank);
596 if (range.second > range.first) {
597 result.numPermutes =
static_cast<LO
>(range.second - range.first);
600 result.numPermutes =
static_cast<LO
>(std::count(tgtPIDs.begin(), tgtPIDs.end(), myRank));
603 const LO numRemotes = numTargetMapRemoteOrPermuteGlobalIndices - result.numPermutes;
604 result.numSameIDs =
static_cast<LO
>(sourceMap.getLocalNumElements());
607 std::ostringstream os;
608 os << *verboseHeader <<
"- numSame=" << result.numSameIDs
609 <<
", numPermutes=" << result.numPermutes
610 <<
", numRemotes=" << numRemotes << endl;
614 if (result.numPermutes == 0) {
616 std::ostringstream os;
617 os << *verboseHeader <<
"- No permutes" << endl;
620 result.remoteGIDs = std::vector<GO>(tgtGIDs.begin() + numLclSrcIDs, tgtGIDs.end());
621 result.remotePIDs.swap(tgtPIDs);
622 result.remoteLIDs.resize(numRemotes);
623 for (LO k = 0; k < numRemotes; ++k) {
624 const LO tgtLid = result.numSameIDs + k;
625 result.remoteLIDs[k] = tgtLid;
628 std::ostringstream os;
629 os << *verboseHeader <<
"- Remote GIDs: "
630 << Teuchos::toString(result.remoteGIDs) << endl;
631 os << *verboseHeader <<
"- Remote PIDs: "
632 << Teuchos::toString(result.remotePIDs) << endl;
633 os << *verboseHeader <<
"- Remote LIDs: "
634 << Teuchos::toString(result.remoteLIDs) << endl;
641 result.remoteGIDs.reserve(numRemotes);
642 result.remoteLIDs.reserve(numRemotes);
643 result.remotePIDs.reserve(numRemotes);
644 for (LO k = 0; k < numTargetMapRemoteOrPermuteGlobalIndices; ++k) {
645 const LO tgtLid = result.numSameIDs + k;
646 const GO tgtGid = tgtGIDs[numLclSrcIDs + k];
647 const int tgtPid = tgtPIDs[k];
649 if (tgtPid != myRank) {
650 result.remoteGIDs.push_back(tgtGid);
651 result.remoteLIDs.push_back(tgtLid);
652 result.remotePIDs.push_back(tgtPid);
656 std::ostringstream os;
657 os << *verboseHeader <<
"- Some permutes" << endl;
662 if (sourceMap.isDistributed()) {
664 std::ostringstream os;
665 os << *verboseHeader <<
"- Sort remotes by PID, as Import always does"
667 << *verboseHeader <<
"-- remotePIDs before: "
668 << Teuchos::toString(result.remotePIDs) << endl
669 << *verboseHeader <<
"-- remoteGIDs before: "
670 << Teuchos::toString(result.remoteGIDs) << endl
671 << *verboseHeader <<
"-- remoteLIDs before: "
672 << Teuchos::toString(result.remoteLIDs) << endl;
676 sort3(result.remotePIDs.begin(),
677 result.remotePIDs.end(),
678 result.remoteGIDs.begin(),
679 result.remoteLIDs.begin());
681 std::ostringstream os;
682 os << *verboseHeader <<
"-- remotePIDs after: "
683 << Teuchos::toString(result.remotePIDs) << endl
684 << *verboseHeader <<
"-- remoteGIDs after: "
685 << Teuchos::toString(result.remoteGIDs) << endl
686 << *verboseHeader <<
"-- remoteLIDs after: "
687 << Teuchos::toString(result.remoteLIDs) << endl;
688 std::cerr << os.str();
693 std::ostringstream os;
694 os << *verboseHeader <<
"- Make target Map" << endl;
697 using ::Teuchos::rcp;
698 typedef ::Tpetra::Map<LO, GO, NT> map_type;
700 const GST MAP_COMPUTES_GLOBAL_COUNT = ::Teuchos::OrdinalTraits<GST>::invalid();
701 result.targetMap = rcp(
new map_type(MAP_COMPUTES_GLOBAL_COUNT,
704 sourceMap.getIndexBase(),
705 sourceMap.getComm()));
707 std::ostringstream os;
708 os << *verboseHeader <<
"- Done with sameSPR..." << endl;
715template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
722 const Teuchos::RCP<Teuchos::ParameterList>&
plist,
723 const Teuchos::RCP<Teuchos::FancyOStream>&
debugOutput)
729 using Teuchos::ArrayView;
730 using Teuchos::getFancyOStream;
733 using Teuchos::rcpFromRef;
734 using ::Tpetra::Details::Behavior;
735 using ::Tpetra::Details::makeDualViewFromOwningHostView;
736 using ::Tpetra::Details::makeDualViewFromVector;
737 using ::Tpetra::Details::printDualView;
738 using ::Tpetra::Details::view_alloc_no_init;
743 const bool debug = Behavior::debug(
"Import") ||
744 Behavior::debug(
"Tpetra::Import");
746 std::unique_ptr<std::string>
verbPfx;
748 std::ostringstream
os;
750 os <<
"Proc " <<
myRank <<
": Tpetra::Import ctor from remotes: ";
751 verbPfx = std::unique_ptr<std::string>(
new std::string(
os.str()));
776 this->TransferData_->out_,
778 this->
TransferData_->numSameIDs_ = localSetupResult.numSameIDs;
782 localSetupResult.remoteLIDs,
796 std::ostringstream
os;
797 os << *
verbPfx <<
"Make Distributor (createFromRecvs)" <<
endl;
822 std::ostringstream
os;
826 using size_type =
typename Teuchos::Array<GO>::size_type;
835 makeDualViewFromOwningHostView(this->
TransferData_->exportLIDs_, exportLIDs);
839 std::ostringstream
os;
842 "ImportExportData::remoteLIDs_");
847 std::ostringstream
os;
853template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
856 const Teuchos::EVerbosityLevel
verbLevel)
const {
861template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
863 print(std::ostream&
os)
const {
864 auto out = Teuchos::getFancyOStream(Teuchos::rcpFromRef(
os));
866 this->describe(*
out, Teuchos::VERB_EXTREME);
869template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
873 using Teuchos::Array;
874 using Teuchos::ArrayRCP;
875 using Teuchos::ArrayView;
878 using ::Tpetra::Details::makeDualViewFromOwningHostView;
879 using ::Tpetra::Details::ProfilingRegion;
880 using ::Tpetra::Details::view_alloc_no_init;
884 ProfilingRegion
regionExport(
"Tpetra::Import::setupSamePermuteRemote");
886 const map_type&
source = *(this->getSourceMap());
887 const map_type&
target = *(this->getTargetMap());
891#ifdef HAVE_TPETRA_DEBUG
911 this->TransferData_->numSameIDs_ = numSameGids;
925 const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid();
926 const LO numTgtLids = as<LO>(numTgtGids);
929 for (LO tgtLid = numSameGids; tgtLid < numTgtLids; ++tgtLid) {
930 const GO curTargetGid = rawTgtGids[tgtLid];
934 const LO srcLid = source.getLocalElement(curTargetGid);
935 if (srcLid != LINVALID) {
939 const LO numRemotes = (numTgtLids - numSameGids) - numPermutes;
941 using host_perm_type =
942 typename decltype(this->TransferData_->permuteToLIDs_)::t_host;
945 typename decltype(this->TransferData_->remoteLIDs_)::t_host remoteLIDs(
view_alloc_no_init(
"permuteFromLIDs"), numRemotes);
950 for (LO tgtLid = numSameGids; tgtLid < numTgtLids; ++tgtLid) {
951 const GO curTargetGid = rawTgtGids[tgtLid];
952 const LO srcLid = source.getLocalElement(curTargetGid);
953 if (srcLid != LINVALID) {
954 permuteToLIDs[numPermutes2] = tgtLid;
955 permuteFromLIDs[numPermutes2] = srcLid;
958 remoteGIDs.push_back(curTargetGid);
959 remoteLIDs[numRemotes2] = tgtLid;
963 TEUCHOS_ASSERT(numPermutes == numPermutes2);
964 TEUCHOS_ASSERT(numRemotes == numRemotes2);
965 TEUCHOS_ASSERT(
size_t(numPermutes) + remoteGIDs.size() ==
size_t(numTgtLids - numSameGids));
971 if (remoteLIDs.extent(0) != 0 && !source.isDistributed()) {
977 this->TransferData_->isLocallyComplete_ =
false;
981 "::setupSamePermuteRemote(): Target has "
982 "remote LIDs but Source is not distributed globally. Importing to a "
983 "submap of the target map.");
987template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
988void Import<LocalOrdinal, GlobalOrdinal, Node>::
989 setupExport(Teuchos::Array<GlobalOrdinal>& remoteGIDs,
991 Teuchos::Array<int>& userRemotePIDs,
992 const Teuchos::RCP<Teuchos::ParameterList>& plist) {
994 using Teuchos::Array;
995 using Teuchos::ArrayView;
996 using ::Tpetra::Details::makeDualViewFromOwningHostView;
997 using ::Tpetra::Details::view_alloc_no_init;
998 using GO = GlobalOrdinal;
999 typedef typename Array<int>::difference_type size_type;
1000 const char tfecfFuncName[] =
"setupExport: ";
1001 const char suffix[] =
" Please report this bug to the Tpetra developers.";
1003 std::unique_ptr<std::string> prefix;
1004 if (this->verbose()) {
1005 auto srcMap = this->getSourceMap();
1006 auto comm = srcMap.is_null() ? Teuchos::null : srcMap->getComm();
1007 const int myRank = comm.is_null() ? -1 : comm->getRank();
1008 std::ostringstream os;
1009 os <<
"Proc " << myRank <<
": Tpetra::Import::setupExport: ";
1010 prefix = std::unique_ptr<std::string>(
new std::string(os.str()));
1011 os <<
"Start" << std::endl;
1012 this->verboseOutputStream() << os.str();
1015 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->getSourceMap().is_null(), std::logic_error,
1016 "Source Map is null. " << suffix);
1017 const map_type& source = *(this->getSourceMap());
1019 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!useRemotePIDs && (userRemotePIDs.size() > 0), std::invalid_argument,
1020 "remotePIDs are non-empty but their use has not been requested.");
1021 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(userRemotePIDs.size() > 0 && remoteGIDs.size() != userRemotePIDs.size(),
1022 std::invalid_argument,
1023 "remotePIDs must either be of size zero or match "
1024 "the size of remoteGIDs.");
1028 ArrayView<GO> remoteGIDsView = remoteGIDs();
1029 ArrayView<int> remoteProcIDsView;
1049 Array<int> newRemotePIDs;
1052 if (!useRemotePIDs) {
1053 newRemotePIDs.resize(remoteGIDsView.size());
1054 if (this->verbose()) {
1055 std::ostringstream os;
1056 os << *prefix <<
"Call sourceMap.getRemoteIndexList" << endl;
1057 this->verboseOutputStream() << os.str();
1059 lookup = source.getRemoteIndexList(remoteGIDsView, newRemotePIDs());
1061 Array<int>& remoteProcIDs = useRemotePIDs ? userRemotePIDs : newRemotePIDs;
1067 this->TransferData_->isLocallyComplete_ =
false;
1072 "::setupExport(): the source Map wasn't "
1073 "able to figure out which process owns one or more of the GIDs in the "
1074 "list of remote GIDs. This probably means that there is at least one "
1075 "GID owned by some process in the target Map which is not owned by any"
1076 " process in the source Map. (That is, the source and target Maps do "
1077 "not contain the same set of GIDs globally.)");
1083 const size_type numInvalidRemote =
1084 std::count_if(remoteProcIDs.begin(), remoteProcIDs.end(),
1085 std::bind(std::equal_to<int>(), -1, std::placeholders::_1));
1086 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numInvalidRemote == 0, std::logic_error,
1087 "Calling getRemoteIndexList "
1088 "on the source Map returned IDNotPresent, but none of the returned "
1089 "\"remote\" process ranks are -1. Please report this bug to the "
1090 "Tpetra developers.");
1095 const size_type totalNumRemote = this->getNumRemoteIDs();
1096 if (numInvalidRemote == totalNumRemote) {
1098 remoteProcIDs.clear();
1100 this->TransferData_->remoteLIDs_ =
1101 decltype(this->TransferData_->remoteLIDs_)();
1105 size_type numValidRemote = 0;
1106#ifdef HAVE_TPETRA_DEBUG
1107 ArrayView<GO> remoteGIDsPtr = remoteGIDsView;
1109 GO*
const remoteGIDsPtr = remoteGIDsView.getRawPtr();
1113 auto remoteLIDs = this->TransferData_->remoteLIDs_.view_host();
1115 for (size_type r = 0; r < totalNumRemote; ++r) {
1117 if (remoteProcIDs[r] != -1) {
1118 remoteProcIDs[numValidRemote] = remoteProcIDs[r];
1119 remoteGIDsPtr[numValidRemote] = remoteGIDsPtr[r];
1120 remoteLIDs[numValidRemote] = remoteLIDs[r];
1124 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numValidRemote != totalNumRemote - numInvalidRemote,
1126 "After removing invalid remote GIDs and packing "
1127 "the valid remote GIDs, numValidRemote = "
1129 <<
" != totalNumRemote - numInvalidRemote = "
1130 << totalNumRemote - numInvalidRemote
1131 <<
". Please report this bug to the Tpetra developers.");
1133 remoteProcIDs.resize(numValidRemote);
1134 remoteGIDs.resize(numValidRemote);
1136 Kokkos::resize(remoteLIDs, numValidRemote);
1137 this->TransferData_->remoteLIDs_ =
decltype(this->TransferData_->remoteLIDs_)();
1141 remoteGIDsView = remoteGIDs();
1149 this->TransferData_->remoteLIDs_.modify_host();
1150 auto remoteLIDs = this->TransferData_->remoteLIDs_.view_host();
1151 sort3(remoteProcIDs.begin(),
1152 remoteProcIDs.end(),
1153 remoteGIDsView.getRawPtr(),
1155 this->TransferData_->remoteLIDs_.sync_device();
1163 Array<GO> exportGIDs;
1167 if (this->verbose()) {
1168 std::ostringstream os;
1169 os << *prefix <<
"Call createFromRecvs" << endl;
1170 this->verboseOutputStream() << endl;
1172 this->TransferData_->distributor_.createFromRecvs(remoteGIDsView().getConst(),
1173 remoteProcIDs, exportGIDs,
1174 this->TransferData_->exportPIDs_);
1186 const size_type numExportIDs = exportGIDs.size();
1187 if (numExportIDs > 0) {
1188 typename decltype(this->TransferData_->exportLIDs_)::t_host
1190 ArrayView<const GO> expGIDs = exportGIDs();
1192 for (size_type k = 0; k < numExportIDs; ++k) {
1193 exportLIDs[k] = source.getLocalElement(expGIDs[k]);
1198 if (this->verbose()) {
1199 std::ostringstream os;
1200 os << *prefix <<
"Done!" << endl;
1201 this->verboseOutputStream() << os.str();
1205template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1208 Teuchos::Array<std::pair<int, GlobalOrdinal>>&
remotePGIDs,
1209 typename Teuchos::Array<GlobalOrdinal>::size_type&
numSameGIDs,
1210 typename Teuchos::Array<GlobalOrdinal>::size_type&
numPermuteGIDs,
1211 typename Teuchos::Array<GlobalOrdinal>::size_type&
numRemoteGIDs,
1212 const Teuchos::ArrayView<const GlobalOrdinal>&
sameGIDs1,
1213 const Teuchos::ArrayView<const GlobalOrdinal>&
sameGIDs2,
1221 typedef typename Teuchos::Array<GO>::size_type size_type;
1304template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1305Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node>>
1308 using Teuchos::Array;
1309 using Teuchos::ArrayView;
1311 using Teuchos::Comm;
1312 using Teuchos::outArg;
1315 using Teuchos::REDUCE_MIN;
1316 using Teuchos::reduceAll;
1317 using ::Tpetra::Details::Behavior;
1331 const bool debug = Behavior::debug(
"Import::setUnion") ||
1332 Behavior::debug(
"Tpetra::Import::setUnion");
1336 "Tpetra::Import::setUnion: The source Map of the input Import must be the "
1337 "same as (in the sense of Map::isSameAs) the source Map of this Import.");
1341 std::invalid_argument,
1342 "Tpetra::Import::setUnion: "
1343 "The target Maps must have congruent communicators.");
1350 return rcp(
new import_type(*
this));
1388 Tpetra::Import_Util::getRemotePIDs(*
this,
remotePIDs1);
1429 const GST INVALID = Teuchos::OrdinalTraits<GST>::invalid();
1434 MM2 = Teuchos::null;
1450#ifdef TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1534 MM3 = Teuchos::null;
1542 this->TransferData_->out_));
1546template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1547Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node>>
1550 using Teuchos::Array;
1551 using Teuchos::ArrayView;
1553 using Teuchos::Comm;
1554 using Teuchos::outArg;
1557 using Teuchos::REDUCE_MIN;
1558 using Teuchos::reduceAll;
1561 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node>>
unionImport;
1591 GO
GO_INVALID = Teuchos::OrdinalTraits<GO>::invalid();
1616template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1617Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node>>
1621 using Teuchos::outArg;
1623 using Teuchos::REDUCE_MIN;
1624 using Teuchos::reduceAll;
1625 using ::Tpetra::Details::Behavior;
1626 using ::Tpetra::Details::gathervPrint;
1631 const char funcPrefix[] =
"Tpetra::createRemoteOnlyImport: ";
1634 const bool debug = Behavior::debug();
1636 const size_t NumRemotes = this->getNumRemoteIDs();
1638 Teuchos::RCP<const Teuchos::Comm<int>> comm;
1641 std::ostringstream
os;
1643 if (comm.is_null()) {
1646 os << comm->getRank();
1649 procPrefix = std::unique_ptr<std::string>(
new std::string(
os.str()));
1653 std::ostringstream
lclErr;
1659 <<
" != remoteTarget->getLocalNumElements() = "
1663 if (comm.is_null()) {
1671 if (comm.is_null()) {
1674 std::ostringstream
gblErr;
1683 Teuchos::ArrayView<const LO>
oldRemoteLIDs = this->getRemoteLIDs();
1688 std::unique_ptr<std::vector<size_t>>
badIndices;
1690 badIndices = std::unique_ptr<std::vector<size_t>>(
new std::vector<size_t>);
1695 if (
oldLclInd == Teuchos::OrdinalTraits<LO>::invalid()) {
1703 if (
gblInd == Teuchos::OrdinalTraits<GO>::invalid()) {
1711 if (
newLclInd == Teuchos::OrdinalTraits<LO>::invalid()) {
1733 if (comm.is_null()) {
1738 std::ostringstream
lclErr;
1741 <<
", bad indices: [";
1745 const size_t badIndex = (*badIndices)[
k];
1756 std::ostringstream
gblErr;
1758 "indices on one or more processes. \"Bad\" means that the "
1759 "indices are invalid, they don't exist in the target Map, "
1760 "they don't exist in remoteTarget, or they are not in "
1761 "sorted order. In what follows, I will show the \"bad\" "
1762 "indices as (k, LID) pairs, where k is the zero-based "
1763 "index of the LID in this->getRemoteLIDs()."
1765 if (comm.is_null()) {
1783 Teuchos::Array<LO>
dummy;
1794#define TPETRA_IMPORT_CLASS_INSTANT(LO, GO, NODE) \
1795 template class Import<LO, GO, NODE>;
1804#define TPETRA_IMPORT_INSTANT(LO, GO, NODE) \
1805 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.
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()).
size_t global_size_t
Global size_t object.
void merge2(IT1 &indResultOut, IT2 &valResultOut, IT1 indBeg, IT1 indEnd, IT2 valBeg, IT2)
Merge values in place, additively, with the same index.
void keyValueMerge(KeyInputIterType keyBeg1, KeyInputIterType keyEnd1, ValueInputIterType valBeg1, ValueInputIterType valEnd1, KeyInputIterType keyBeg2, KeyInputIterType keyEnd2, ValueInputIterType valBeg2, ValueInputIterType valEnd2, KeyOutputIterType keyOut, ValueOutputIterType valOut, BinaryFunction f)
Merge two sorted (by keys) sequences of unique (key,value) pairs by combining pairs with equal keys.
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.