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"
24#ifdef HAVE_TPETRA_MMM_TIMINGS
25#include "Teuchos_TimeMonitor.hpp"
32std::string toString(
const std::vector<T>& x) {
33 std::ostringstream os;
35 const std::size_t N = x.size();
36 for (std::size_t k = 0; k < N; ++k) {
38 if (k + std::size_t(1) < N) {
46template <
class ElementType,
class DeviceType>
47std::string toString(
const Kokkos::View<const ElementType*, DeviceType>& x) {
48 std::ostringstream os;
50 const std::size_t N = std::size_t(x.extent(0));
51 for (std::size_t k = 0; k < N; ++k) {
53 if (k + std::size_t(1) < N) {
66template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
67void Import<LocalOrdinal, GlobalOrdinal, Node>::
68 init(
const Teuchos::RCP<const map_type>& source,
69 const Teuchos::RCP<const map_type>& ,
71 Teuchos::Array<int>& remotePIDs,
72 const Teuchos::RCP<Teuchos::ParameterList>& plist) {
78 using ::Tpetra::Details::ProfilingRegion;
79 ProfilingRegion regionImportInit(
"Tpetra::Import::init");
81 std::unique_ptr<std::string> verbPrefix;
82 if (this->verbose()) {
83 std::ostringstream os;
84 const int myRank = source->getComm()->getRank();
85 os <<
"Proc " << myRank <<
": Tpetra::Import::init: ";
86 verbPrefix = std::unique_ptr<std::string>(
new std::string(os.str()));
88 this->verboseOutputStream() << os.str();
91 Array<GlobalOrdinal> remoteGIDs;
93#ifdef HAVE_TPETRA_MMM_TIMINGS
94 using Teuchos::TimeMonitor;
97 label = plist->get(
"Timer Label", label);
98 std::string prefix = std::string(
"Tpetra ") + label + std::string(
":iport_ctor:preIData: ");
103#ifdef HAVE_TPETRA_MMM_TIMINGS
104 auto MM(*TimeMonitor::getNewTimer(prefix));
106 if (this->verbose()) {
107 std::ostringstream os;
108 os << *verbPrefix <<
"Call setupSamePermuteRemote" << endl;
109 this->verboseOutputStream() << os.str();
111 setupSamePermuteRemote(remoteGIDs);
114#ifdef HAVE_TPETRA_MMM_TIMINGS
115 prefix = std::string(
"Tpetra ") + label + std::string(
":iport_ctor:preSetupExport: ");
116 auto MM2(*TimeMonitor::getNewTimer(prefix));
118 if (source->isDistributed()) {
119 if (this->verbose()) {
120 std::ostringstream os;
121 os << *verbPrefix <<
"Call setupExport" << endl;
122 this->verboseOutputStream() << os.str();
124 setupExport(remoteGIDs, useRemotePIDs, remotePIDs);
125 }
else if (this->verbose()) {
126 std::ostringstream os;
127 os << *verbPrefix <<
"Source Map not distributed; skip setupExport"
129 this->verboseOutputStream() << os.str();
133 TEUCHOS_ASSERT(!this->TransferData_->permuteFromLIDs_.need_sync_device());
134 TEUCHOS_ASSERT(!this->TransferData_->permuteFromLIDs_.need_sync_host());
135 TEUCHOS_ASSERT(!this->TransferData_->permuteToLIDs_.need_sync_device());
136 TEUCHOS_ASSERT(!this->TransferData_->permuteToLIDs_.need_sync_host());
137 TEUCHOS_ASSERT(!this->TransferData_->remoteLIDs_.need_sync_device());
138 TEUCHOS_ASSERT(!this->TransferData_->remoteLIDs_.need_sync_host());
139 TEUCHOS_ASSERT(!this->TransferData_->exportLIDs_.need_sync_device());
140 TEUCHOS_ASSERT(!this->TransferData_->exportLIDs_.need_sync_host());
142 this->detectRemoteExportLIDsContiguous();
144 if (this->verbose()) {
145 std::ostringstream os;
146 os << *verbPrefix <<
"Done!" << endl;
147 this->verboseOutputStream() << os.str();
151template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
154 const Teuchos::RCP<const map_type>&
target)
156 Teuchos::Array<int>
dummy;
157#ifdef HAVE_TPETRA_MMM_TIMINGS
158 Teuchos::RCP<Teuchos::ParameterList>
mypars =
rcp(
new Teuchos::ParameterList);
159 mypars->set(
"Timer Label",
"Naive_tAFC");
166template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
169 const Teuchos::RCP<const map_type>&
target,
170 const Teuchos::RCP<Teuchos::FancyOStream>&
out)
172 Teuchos::Array<int>
dummy;
176template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
179 const Teuchos::RCP<const map_type>&
target,
180 const Teuchos::RCP<Teuchos::ParameterList>&
plist)
182 Teuchos::Array<int>
dummy;
186template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
189 const Teuchos::RCP<const map_type>&
target,
190 const Teuchos::RCP<Teuchos::FancyOStream>&
out,
191 const Teuchos::RCP<Teuchos::ParameterList>&
plist)
193 Teuchos::Array<int>
dummy;
197template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
200 const Teuchos::RCP<const map_type>&
target,
201 Teuchos::Array<int>& remotePIDs,
202 const Teuchos::RCP<Teuchos::ParameterList>&
plist)
207template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
212template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
220template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
227 const Teuchos::RCP<Teuchos::ParameterList>&
plist,
228 const Teuchos::RCP<Teuchos::FancyOStream>&
out)
232 using Teuchos::Array;
233 using Teuchos::ArrayRCP;
234 using Teuchos::ArrayView;
238 using ::Tpetra::Details::makeDualViewFromArrayView;
241 using size_type = Teuchos::Array<int>::size_type;
243 std::unique_ptr<std::string>
prefix;
245 auto comm =
source.is_null() ? Teuchos::null :
source->getComm();
246 const int myRank = comm.is_null() ? -1 : comm->getRank();
247 std::ostringstream
os;
248 os <<
"Proc " <<
myRank <<
": Tpetra::Import createExpert ctor: ";
249 prefix = std::unique_ptr<std::string>(
new std::string(
os.str()));
259 std::ostringstream
os;
266 std::ostringstream
os;
276 std::ostringstream
os;
277 os << *
prefix <<
"Target Map has remote LIDs but source Map is not "
278 "distributed. Importing to a submap of the target Map."
286 "::constructExpert: Target Map has remote LIDs but source Map "
287 "is not distributed. Importing to a submap of the target Map.");
291 "Import::Import createExpert version: "
292 "Size mismatch on userRemotePIDs, remoteGIDs, and remoteLIDs "
293 "Array's to sort3.");
312 if (indexIntoRemotePIDs -
cnt > 0) {
341 userExportLIDs,
"exportLIDs");
352 std::ostringstream
os;
353 os << *
prefix <<
"locallyComplete: "
355 <<
"; call createFromSendsAndRecvs" <<
endl;
359#ifdef HAVE_TPETRA_MMM_TIMINGS
361 std::string(
"Tpetra ") + std::string(
":iport_ctor:cFSAR ");
369 this->detectRemoteExportLIDsContiguous();
381template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
384 const Teuchos::RCP<const map_type>&
target,
385 const size_t numSameIDs,
388 Teuchos::Array<LocalOrdinal>& remoteLIDs,
392 const Teuchos::RCP<Teuchos::FancyOStream>&
out,
393 const Teuchos::RCP<Teuchos::ParameterList>&
plist)
396 using ::Tpetra::Details::makeDualViewFromArrayView;
398 std::unique_ptr<std::string>
prefix;
400 auto comm =
source.is_null() ? Teuchos::null :
source->getComm();
401 const int myRank = comm.is_null() ? -1 : comm->getRank();
402 std::ostringstream
os;
403 os <<
"Proc " <<
myRank <<
": Tpetra::Import export ctor: ";
404 prefix = std::unique_ptr<std::string>(
new std::string(
os.str()));
409 bool locallyComplete =
true;
410 for (Teuchos::Array<int>::size_type i = 0; i < exportPIDs.size(); ++i) {
411 if (exportPIDs[i] == -1) {
412 locallyComplete =
false;
416 std::ostringstream os;
417 os << *prefix <<
"numSameIDs: " << numSameIDs <<
", locallyComplete: "
418 << (locallyComplete ?
"true" :
"false") << endl;
425 makeDualViewFromArrayView(this->
TransferData_->permuteToLIDs_,
426 permuteToLIDs().getConst(),
428 TEUCHOS_ASSERT(
size_t(this->
TransferData_->permuteToLIDs_.extent(0)) ==
429 size_t(permuteToLIDs.size()));
430 makeDualViewFromArrayView(this->
TransferData_->permuteFromLIDs_,
431 permuteFromLIDs().getConst(),
433 TEUCHOS_ASSERT(
size_t(this->
TransferData_->permuteFromLIDs_.extent(0)) ==
434 size_t(permuteFromLIDs.size()));
436 remoteLIDs().getConst(),
438 TEUCHOS_ASSERT(
size_t(this->
TransferData_->remoteLIDs_.extent(0)) ==
439 size_t(remoteLIDs.size()));
441 exportLIDs().getConst(),
443 TEUCHOS_ASSERT(
size_t(this->
TransferData_->exportLIDs_.extent(0)) ==
444 size_t(exportLIDs.size()));
448 this->detectRemoteExportLIDsContiguous();
450 TEUCHOS_ASSERT(!this->
TransferData_->permuteFromLIDs_.need_sync_device());
451 TEUCHOS_ASSERT(!this->
TransferData_->permuteFromLIDs_.need_sync_host());
452 TEUCHOS_ASSERT(!this->
TransferData_->permuteToLIDs_.need_sync_device());
453 TEUCHOS_ASSERT(!this->
TransferData_->permuteToLIDs_.need_sync_host());
454 TEUCHOS_ASSERT(!this->
TransferData_->remoteLIDs_.need_sync_device());
455 TEUCHOS_ASSERT(!this->
TransferData_->remoteLIDs_.need_sync_host());
456 TEUCHOS_ASSERT(!this->
TransferData_->exportLIDs_.need_sync_device());
457 TEUCHOS_ASSERT(!this->
TransferData_->exportLIDs_.need_sync_host());
462template <
class LO,
class GO,
class NT>
463struct ImportLocalSetupResult {
464 Teuchos::RCP<const ::Tpetra::Map<LO, GO, NT>> targetMap;
468 std::vector<GO> remoteGIDs;
469 std::vector<LO> remoteLIDs;
470 std::vector<int> remotePIDs;
475void printArray(std::ostream& out,
const T x[],
const std::size_t N) {
477 for (std::size_t k = 0; k < N; ++k) {
486template <
class LO,
class GO,
class NT>
487ImportLocalSetupResult<LO, GO, NT>
488setupSamePermuteRemoteFromUserGlobalIndexList(const ::Tpetra::Map<LO, GO, NT>& sourceMap,
489 const GO targetMapRemoteOrPermuteGlobalIndices[],
490 const int targetMapRemoteOrPermuteProcessRanks[],
491 const LO numTargetMapRemoteOrPermuteGlobalIndices,
492 const bool mayReorderTargetMapIndicesLocally,
493 Teuchos::FancyOStream* out,
494 const std::string* verboseHeader,
498 const int myRank = sourceMap.getComm()->getRank();
499 ImportLocalSetupResult<LO, GO, NT> result;
502 std::ostringstream os;
503 os << *verboseHeader <<
"- Import::setupSPR w/ remote GIDs & PIDs: " << endl
504 << *verboseHeader <<
" Input GIDs: ";
505 printArray(os, targetMapRemoteOrPermuteGlobalIndices, numTargetMapRemoteOrPermuteGlobalIndices);
508 printArray(os, targetMapRemoteOrPermuteProcessRanks, numTargetMapRemoteOrPermuteGlobalIndices);
518 std::vector<GO> badGIDs;
519 std::vector<int> badPIDs;
520 const Teuchos::Comm<int>& comm = *(sourceMap.getComm());
521 const int numProcs = comm.getSize();
523 for (LO k = 0; k < numTargetMapRemoteOrPermuteGlobalIndices; ++k) {
524 const GO tgtGID = targetMapRemoteOrPermuteGlobalIndices[k];
525 if (sourceMap.isNodeGlobalElement(tgtGID)) {
526 badGIDs.push_back(tgtGID);
528 const int tgtPID = targetMapRemoteOrPermuteProcessRanks[k];
529 if (tgtPID < 0 || tgtPID >= numProcs) {
530 badPIDs.push_back(tgtPID);
534 std::array<int, 2> lclStatus{{badGIDs.size() == 0 ? 1 : 0,
535 badPIDs.size() == 0 ? 1 : 0}};
536 std::array<int, 2> gblStatus{{0, 0}};
537 Teuchos::reduceAll<int, int>(comm, Teuchos::REDUCE_MIN, 2,
538 lclStatus.data(), gblStatus.data());
539 const bool good = gblStatus[0] == 1 && gblStatus[1] == 1;
542 if (verbose && gblStatus[0] != 1) {
543 std::ostringstream os;
544 os << *verboseHeader <<
"- Some input GIDs are already in the source Map: ";
545 printArray(os, badGIDs.data(), badGIDs.size());
549 if (verbose && gblStatus[0] != 1) {
550 std::ostringstream os;
551 os << *verboseHeader <<
"- Some input PIDs are invalid: ";
552 printArray(os, badPIDs.data(), badPIDs.size());
558 std::ostringstream os;
559 os <<
"Tpetra::Import constructor that takes remote GIDs and PIDs: ";
560 if (gblStatus[0] != 1) {
561 os <<
"Some input GIDs (global indices) are already in the source Map! ";
563 if (gblStatus[1] != 1) {
564 os <<
"Some input PIDs (process ranks) are invalid! ";
566 os <<
"Rerun with the environment variable TPETRA_VERBOSE=Tpetra::Import "
567 "to see what GIDs and/or PIDs are bad.";
568 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument, os.str());
575 const LO numLclSrcIDs =
static_cast<LO
>(sourceMap.getLocalNumElements());
576 const LO numLclTgtIDs = numLclSrcIDs + numTargetMapRemoteOrPermuteGlobalIndices;
578 std::ostringstream os;
579 os << *verboseHeader <<
"- Copy source Map GIDs into target Map GID list: "
582 <<
", numTargetMapRemoteOrPermuteGlobalIndices="
583 << numTargetMapRemoteOrPermuteGlobalIndices << endl;
586 std::vector<GO> tgtGIDs(numLclTgtIDs);
587 if (sourceMap.isContiguous()) {
588 GO curTgtGID = sourceMap.getMinGlobalIndex();
589 for (LO k = 0; k < numLclSrcIDs; ++k, ++curTgtGID) {
590 tgtGIDs[k] = curTgtGID;
593 auto srcGIDs = sourceMap.getLocalElementList();
594 for (LO k = 0; k < numLclSrcIDs; ++k) {
595 tgtGIDs[k] = srcGIDs[k];
598 std::copy(targetMapRemoteOrPermuteGlobalIndices,
599 targetMapRemoteOrPermuteGlobalIndices + numTargetMapRemoteOrPermuteGlobalIndices,
600 tgtGIDs.begin() + numLclSrcIDs);
613 std::ostringstream os;
614 os << *verboseHeader <<
"- Sort by PID? "
615 << (mayReorderTargetMapIndicesLocally ?
"true" :
"false") << endl;
618 std::vector<int> tgtPIDs(targetMapRemoteOrPermuteProcessRanks,
619 targetMapRemoteOrPermuteProcessRanks + numTargetMapRemoteOrPermuteGlobalIndices);
620 result.numPermutes = 0;
621 if (mayReorderTargetMapIndicesLocally) {
622 Tpetra::sort2(tgtPIDs.begin(), tgtPIDs.end(), tgtGIDs.begin() + numLclSrcIDs);
623 auto range = std::equal_range(tgtPIDs.begin(), tgtPIDs.end(), myRank);
624 if (range.second > range.first) {
625 result.numPermutes =
static_cast<LO
>(range.second - range.first);
628 result.numPermutes =
static_cast<LO
>(std::count(tgtPIDs.begin(), tgtPIDs.end(), myRank));
631 const LO numRemotes = numTargetMapRemoteOrPermuteGlobalIndices - result.numPermutes;
632 result.numSameIDs =
static_cast<LO
>(sourceMap.getLocalNumElements());
635 std::ostringstream os;
636 os << *verboseHeader <<
"- numSame=" << result.numSameIDs
637 <<
", numPermutes=" << result.numPermutes
638 <<
", numRemotes=" << numRemotes << endl;
642 if (result.numPermutes == 0) {
644 std::ostringstream os;
645 os << *verboseHeader <<
"- No permutes" << endl;
648 result.remoteGIDs = std::vector<GO>(tgtGIDs.begin() + numLclSrcIDs, tgtGIDs.end());
649 result.remotePIDs.swap(tgtPIDs);
650 result.remoteLIDs.resize(numRemotes);
651 for (LO k = 0; k < numRemotes; ++k) {
652 const LO tgtLid = result.numSameIDs + k;
653 result.remoteLIDs[k] = tgtLid;
656 std::ostringstream os;
657 os << *verboseHeader <<
"- Remote GIDs: "
658 << Teuchos::toString(result.remoteGIDs) << endl;
659 os << *verboseHeader <<
"- Remote PIDs: "
660 << Teuchos::toString(result.remotePIDs) << endl;
661 os << *verboseHeader <<
"- Remote LIDs: "
662 << Teuchos::toString(result.remoteLIDs) << endl;
669 result.remoteGIDs.reserve(numRemotes);
670 result.remoteLIDs.reserve(numRemotes);
671 result.remotePIDs.reserve(numRemotes);
672 for (LO k = 0; k < numTargetMapRemoteOrPermuteGlobalIndices; ++k) {
673 const LO tgtLid = result.numSameIDs + k;
674 const GO tgtGid = tgtGIDs[numLclSrcIDs + k];
675 const int tgtPid = tgtPIDs[k];
677 if (tgtPid != myRank) {
678 result.remoteGIDs.push_back(tgtGid);
679 result.remoteLIDs.push_back(tgtLid);
680 result.remotePIDs.push_back(tgtPid);
684 std::ostringstream os;
685 os << *verboseHeader <<
"- Some permutes" << endl;
690 if (sourceMap.isDistributed()) {
692 std::ostringstream os;
693 os << *verboseHeader <<
"- Sort remotes by PID, as Import always does"
695 << *verboseHeader <<
"-- remotePIDs before: "
696 << Teuchos::toString(result.remotePIDs) << endl
697 << *verboseHeader <<
"-- remoteGIDs before: "
698 << Teuchos::toString(result.remoteGIDs) << endl
699 << *verboseHeader <<
"-- remoteLIDs before: "
700 << Teuchos::toString(result.remoteLIDs) << endl;
704 sort3(result.remotePIDs.begin(),
705 result.remotePIDs.end(),
706 result.remoteGIDs.begin(),
707 result.remoteLIDs.begin());
709 std::ostringstream os;
710 os << *verboseHeader <<
"-- remotePIDs after: "
711 << Teuchos::toString(result.remotePIDs) << endl
712 << *verboseHeader <<
"-- remoteGIDs after: "
713 << Teuchos::toString(result.remoteGIDs) << endl
714 << *verboseHeader <<
"-- remoteLIDs after: "
715 << Teuchos::toString(result.remoteLIDs) << endl;
716 std::cerr << os.str();
721 std::ostringstream os;
722 os << *verboseHeader <<
"- Make target Map" << endl;
725 using ::Teuchos::rcp;
726 typedef ::Tpetra::Map<LO, GO, NT> map_type;
728 const GST MAP_COMPUTES_GLOBAL_COUNT = ::Teuchos::OrdinalTraits<GST>::invalid();
729 result.targetMap = rcp(
new map_type(MAP_COMPUTES_GLOBAL_COUNT,
732 sourceMap.getIndexBase(),
733 sourceMap.getComm()));
735 std::ostringstream os;
736 os << *verboseHeader <<
"- Done with sameSPR..." << endl;
743template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
750 const Teuchos::RCP<Teuchos::ParameterList>&
plist,
751 const Teuchos::RCP<Teuchos::FancyOStream>&
debugOutput)
757 using Teuchos::ArrayView;
758 using Teuchos::getFancyOStream;
761 using Teuchos::rcpFromRef;
762 using ::Tpetra::Details::Behavior;
763 using ::Tpetra::Details::makeDualViewFromOwningHostView;
764 using ::Tpetra::Details::makeDualViewFromVector;
765 using ::Tpetra::Details::printDualView;
766 using ::Tpetra::Details::view_alloc_no_init;
771 const bool debug = Behavior::debug(
"Import") ||
772 Behavior::debug(
"Tpetra::Import");
774 std::unique_ptr<std::string>
verbPfx;
776 std::ostringstream
os;
778 os <<
"Proc " <<
myRank <<
": Tpetra::Import ctor from remotes: ";
779 verbPfx = std::unique_ptr<std::string>(
new std::string(
os.str()));
804 this->TransferData_->out_,
806 this->
TransferData_->numSameIDs_ = localSetupResult.numSameIDs;
810 localSetupResult.remoteLIDs,
824 std::ostringstream
os;
825 os << *
verbPfx <<
"Make Distributor (createFromRecvs)" <<
endl;
850 std::ostringstream
os;
854 using size_type =
typename Teuchos::Array<GO>::size_type;
863 makeDualViewFromOwningHostView(this->
TransferData_->exportLIDs_, exportLIDs);
867 std::ostringstream
os;
870 "ImportExportData::remoteLIDs_");
875 std::ostringstream
os;
881template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
884 const Teuchos::EVerbosityLevel
verbLevel)
const {
889template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
891 print(std::ostream&
os)
const {
892 auto out = Teuchos::getFancyOStream(Teuchos::rcpFromRef(
os));
894 this->describe(*
out, Teuchos::VERB_EXTREME);
897template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
901 using Teuchos::Array;
902 using Teuchos::ArrayRCP;
903 using Teuchos::ArrayView;
906 using ::Tpetra::Details::makeDualViewFromOwningHostView;
907 using ::Tpetra::Details::ProfilingRegion;
908 using ::Tpetra::Details::view_alloc_no_init;
912 ProfilingRegion
regionExport(
"Tpetra::Import::setupSamePermuteRemote");
914 const map_type&
source = *(this->getSourceMap());
915 const map_type&
target = *(this->getTargetMap());
919#ifdef HAVE_TPETRA_DEBUG
939 this->TransferData_->numSameIDs_ = numSameGids;
953 const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid();
954 const LO numTgtLids = as<LO>(numTgtGids);
957 for (LO tgtLid = numSameGids; tgtLid < numTgtLids; ++tgtLid) {
958 const GO curTargetGid = rawTgtGids[tgtLid];
962 const LO srcLid = source.getLocalElement(curTargetGid);
963 if (srcLid != LINVALID) {
967 const LO numRemotes = (numTgtLids - numSameGids) - numPermutes;
969 using host_perm_type =
970 typename decltype(this->TransferData_->permuteToLIDs_)::t_host;
973 typename decltype(this->TransferData_->remoteLIDs_)::t_host remoteLIDs(
view_alloc_no_init(
"permuteFromLIDs"), numRemotes);
978 for (LO tgtLid = numSameGids; tgtLid < numTgtLids; ++tgtLid) {
979 const GO curTargetGid = rawTgtGids[tgtLid];
980 const LO srcLid = source.getLocalElement(curTargetGid);
981 if (srcLid != LINVALID) {
982 permuteToLIDs[numPermutes2] = tgtLid;
983 permuteFromLIDs[numPermutes2] = srcLid;
986 remoteGIDs.push_back(curTargetGid);
987 remoteLIDs[numRemotes2] = tgtLid;
991 TEUCHOS_ASSERT(numPermutes == numPermutes2);
992 TEUCHOS_ASSERT(numRemotes == numRemotes2);
993 TEUCHOS_ASSERT(
size_t(numPermutes) + remoteGIDs.size() ==
size_t(numTgtLids - numSameGids));
999 if (remoteLIDs.extent(0) != 0 && !source.isDistributed()) {
1005 this->TransferData_->isLocallyComplete_ =
false;
1009 "::setupSamePermuteRemote(): Target has "
1010 "remote LIDs but Source is not distributed globally. Importing to a "
1011 "submap of the target map.");
1015template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1016void Import<LocalOrdinal, GlobalOrdinal, Node>::
1017 setupExport(Teuchos::Array<GlobalOrdinal>& remoteGIDs,
1019 Teuchos::Array<int>& userRemotePIDs,
1020 const Teuchos::RCP<Teuchos::ParameterList>& plist) {
1022 using Teuchos::Array;
1023 using Teuchos::ArrayView;
1024 using ::Tpetra::Details::makeDualViewFromOwningHostView;
1025 using ::Tpetra::Details::view_alloc_no_init;
1026 using GO = GlobalOrdinal;
1027 typedef typename Array<int>::difference_type size_type;
1028 const char tfecfFuncName[] =
"setupExport: ";
1029 const char suffix[] =
" Please report this bug to the Tpetra developers.";
1031 std::unique_ptr<std::string> prefix;
1032 if (this->verbose()) {
1033 auto srcMap = this->getSourceMap();
1034 auto comm = srcMap.is_null() ? Teuchos::null : srcMap->getComm();
1035 const int myRank = comm.is_null() ? -1 : comm->getRank();
1036 std::ostringstream os;
1037 os <<
"Proc " << myRank <<
": Tpetra::Import::setupExport: ";
1038 prefix = std::unique_ptr<std::string>(
new std::string(os.str()));
1039 os <<
"Start" << std::endl;
1040 this->verboseOutputStream() << os.str();
1043 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(this->getSourceMap().is_null(), std::logic_error,
1044 "Source Map is null. " << suffix);
1045 const map_type& source = *(this->getSourceMap());
1047 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(!useRemotePIDs && (userRemotePIDs.size() > 0), std::invalid_argument,
1048 "remotePIDs are non-empty but their use has not been requested.");
1049 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(userRemotePIDs.size() > 0 && remoteGIDs.size() != userRemotePIDs.size(),
1050 std::invalid_argument,
1051 "remotePIDs must either be of size zero or match "
1052 "the size of remoteGIDs.");
1056 ArrayView<GO> remoteGIDsView = remoteGIDs();
1057 ArrayView<int> remoteProcIDsView;
1077 Array<int> newRemotePIDs;
1080 if (!useRemotePIDs) {
1081 newRemotePIDs.resize(remoteGIDsView.size());
1082 if (this->verbose()) {
1083 std::ostringstream os;
1084 os << *prefix <<
"Call sourceMap.getRemoteIndexList" << endl;
1085 this->verboseOutputStream() << os.str();
1087 lookup = source.getRemoteIndexList(remoteGIDsView, newRemotePIDs());
1089 Array<int>& remoteProcIDs = useRemotePIDs ? userRemotePIDs : newRemotePIDs;
1095 this->TransferData_->isLocallyComplete_ =
false;
1100 "::setupExport(): the source Map wasn't "
1101 "able to figure out which process owns one or more of the GIDs in the "
1102 "list of remote GIDs. This probably means that there is at least one "
1103 "GID owned by some process in the target Map which is not owned by any"
1104 " process in the source Map. (That is, the source and target Maps do "
1105 "not contain the same set of GIDs globally.)");
1111 const size_type numInvalidRemote =
1112 std::count_if(remoteProcIDs.begin(), remoteProcIDs.end(),
1113 std::bind(std::equal_to<int>(), -1, std::placeholders::_1));
1114 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numInvalidRemote == 0, std::logic_error,
1115 "Calling getRemoteIndexList "
1116 "on the source Map returned IDNotPresent, but none of the returned "
1117 "\"remote\" process ranks are -1. Please report this bug to the "
1118 "Tpetra developers.");
1120#ifdef HAVE_TPETRA_MMM_TIMINGS
1121 using Teuchos::TimeMonitor;
1123 if (!plist.is_null())
1124 label = plist->get(
"Timer Label", label);
1125 std::string prefix = std::string(
"Tpetra ") + label + std::string(
":iport_ctor:setupExport:1 ");
1126 auto MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix)));
1132 const size_type totalNumRemote = this->getNumRemoteIDs();
1133 if (numInvalidRemote == totalNumRemote) {
1135 remoteProcIDs.clear();
1137 this->TransferData_->remoteLIDs_ =
1138 decltype(this->TransferData_->remoteLIDs_)();
1142 size_type numValidRemote = 0;
1143#ifdef HAVE_TPETRA_DEBUG
1144 ArrayView<GO> remoteGIDsPtr = remoteGIDsView;
1146 GO*
const remoteGIDsPtr = remoteGIDsView.getRawPtr();
1150 auto remoteLIDs = this->TransferData_->remoteLIDs_.view_host();
1152 for (size_type r = 0; r < totalNumRemote; ++r) {
1154 if (remoteProcIDs[r] != -1) {
1155 remoteProcIDs[numValidRemote] = remoteProcIDs[r];
1156 remoteGIDsPtr[numValidRemote] = remoteGIDsPtr[r];
1157 remoteLIDs[numValidRemote] = remoteLIDs[r];
1161 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC(numValidRemote != totalNumRemote - numInvalidRemote,
1163 "After removing invalid remote GIDs and packing "
1164 "the valid remote GIDs, numValidRemote = "
1166 <<
" != totalNumRemote - numInvalidRemote = "
1167 << totalNumRemote - numInvalidRemote
1168 <<
". Please report this bug to the Tpetra developers.");
1170 remoteProcIDs.resize(numValidRemote);
1171 remoteGIDs.resize(numValidRemote);
1173 Kokkos::resize(remoteLIDs, numValidRemote);
1174 this->TransferData_->remoteLIDs_ =
decltype(this->TransferData_->remoteLIDs_)();
1178 remoteGIDsView = remoteGIDs();
1186 this->TransferData_->remoteLIDs_.modify_host();
1187 auto remoteLIDs = this->TransferData_->remoteLIDs_.view_host();
1188 sort3(remoteProcIDs.begin(),
1189 remoteProcIDs.end(),
1190 remoteGIDsView.getRawPtr(),
1192 this->TransferData_->remoteLIDs_.sync_device();
1200 Array<GO> exportGIDs;
1202#ifdef HAVE_TPETRA_MMM_TIMINGS
1203 using Teuchos::TimeMonitor;
1205 if (!plist.is_null())
1206 label = plist->get(
"Timer Label", label);
1207 std::string prefix2 = std::string(
"Tpetra ") + label + std::string(
":iport_ctor:setupExport:3 ");
1208 auto MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2)));
1211 if (this->verbose()) {
1212 std::ostringstream os;
1213 os << *prefix <<
"Call createFromRecvs" << endl;
1214 this->verboseOutputStream() << endl;
1216 this->TransferData_->distributor_.createFromRecvs(remoteGIDsView().getConst(),
1217 remoteProcIDs, exportGIDs,
1218 this->TransferData_->exportPIDs_);
1224#ifdef HAVE_TPETRA_MMM_TIMINGS
1225 prefix2 = std::string(
"Tpetra ") + label + std::string(
":iport_ctor:setupExport:4 ");
1227 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2)));
1233 const size_type numExportIDs = exportGIDs.size();
1234 if (numExportIDs > 0) {
1235 typename decltype(this->TransferData_->exportLIDs_)::t_host
1237 ArrayView<const GO> expGIDs = exportGIDs();
1239 for (size_type k = 0; k < numExportIDs; ++k) {
1240 exportLIDs[k] = source.getLocalElement(expGIDs[k]);
1245 if (this->verbose()) {
1246 std::ostringstream os;
1247 os << *prefix <<
"Done!" << endl;
1248 this->verboseOutputStream() << os.str();
1252template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1255 Teuchos::Array<std::pair<int, GlobalOrdinal>>&
remotePGIDs,
1256 typename Teuchos::Array<GlobalOrdinal>::size_type&
numSameGIDs,
1257 typename Teuchos::Array<GlobalOrdinal>::size_type&
numPermuteGIDs,
1258 typename Teuchos::Array<GlobalOrdinal>::size_type&
numRemoteGIDs,
1259 const Teuchos::ArrayView<const GlobalOrdinal>&
sameGIDs1,
1260 const Teuchos::ArrayView<const GlobalOrdinal>&
sameGIDs2,
1268 typedef typename Teuchos::Array<GO>::size_type size_type;
1351template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1352Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node>>
1355 using Teuchos::Array;
1356 using Teuchos::ArrayView;
1358 using Teuchos::Comm;
1359 using Teuchos::outArg;
1362 using Teuchos::REDUCE_MIN;
1363 using Teuchos::reduceAll;
1364 using ::Tpetra::Details::Behavior;
1371#ifdef HAVE_TPETRA_MMM_TIMINGS
1372 using Teuchos::TimeMonitor;
1373 std::string label = std::string(
"Tpetra::Import::setUnion");
1382 const bool debug = Behavior::debug(
"Import::setUnion") ||
1383 Behavior::debug(
"Tpetra::Import::setUnion");
1387 "Tpetra::Import::setUnion: The source Map of the input Import must be the "
1388 "same as (in the sense of Map::isSameAs) the source Map of this Import.");
1392 std::invalid_argument,
1393 "Tpetra::Import::setUnion: "
1394 "The target Maps must have congruent communicators.");
1401 return rcp(
new import_type(*
this));
1439 Tpetra::Import_Util::getRemotePIDs(*
this,
remotePIDs1);
1476#ifdef HAVE_TPETRA_MMM_TIMINGS
1477 MM.disableTimer(label);
1478 label =
"Tpetra::Import::setUnion : Construct Target Map";
1483 const GST INVALID = Teuchos::OrdinalTraits<GST>::invalid();
1488#ifdef HAVE_TPETRA_MMM_TIMINGS
1489 MM2.disableTimer(label);
1490 label =
"Tpetra::Import::setUnion : Export GIDs";
1507#ifdef TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1591#ifdef HAVE_TPETRA_MMM_TIMINGS
1592 MM3.disableTimer(label);
1593 label =
"Tpetra::Import::setUnion : Construct Import";
1602 this->TransferData_->out_));
1606template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1607Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node>>
1610 using Teuchos::Array;
1611 using Teuchos::ArrayView;
1613 using Teuchos::Comm;
1614 using Teuchos::outArg;
1617 using Teuchos::REDUCE_MIN;
1618 using Teuchos::reduceAll;
1621 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node>>
unionImport;
1651 GO
GO_INVALID = Teuchos::OrdinalTraits<GO>::invalid();
1676template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1677Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node>>
1681 using Teuchos::outArg;
1683 using Teuchos::REDUCE_MIN;
1684 using Teuchos::reduceAll;
1685 using ::Tpetra::Details::Behavior;
1686 using ::Tpetra::Details::gathervPrint;
1691 const char funcPrefix[] =
"Tpetra::createRemoteOnlyImport: ";
1694 const bool debug = Behavior::debug();
1696 const size_t NumRemotes = this->getNumRemoteIDs();
1698 Teuchos::RCP<const Teuchos::Comm<int>> comm;
1701 std::ostringstream
os;
1703 if (comm.is_null()) {
1706 os << comm->getRank();
1709 procPrefix = std::unique_ptr<std::string>(
new std::string(
os.str()));
1713 std::ostringstream
lclErr;
1719 <<
" != remoteTarget->getLocalNumElements() = "
1723 if (comm.is_null()) {
1731 if (comm.is_null()) {
1734 std::ostringstream
gblErr;
1743 Teuchos::ArrayView<const LO>
oldRemoteLIDs = this->getRemoteLIDs();
1748 std::unique_ptr<std::vector<size_t>>
badIndices;
1750 badIndices = std::unique_ptr<std::vector<size_t>>(
new std::vector<size_t>);
1755 if (
oldLclInd == Teuchos::OrdinalTraits<LO>::invalid()) {
1763 if (
gblInd == Teuchos::OrdinalTraits<GO>::invalid()) {
1771 if (
newLclInd == Teuchos::OrdinalTraits<LO>::invalid()) {
1793 if (comm.is_null()) {
1798 std::ostringstream
lclErr;
1801 <<
", bad indices: [";
1805 const size_t badIndex = (*badIndices)[
k];
1816 std::ostringstream
gblErr;
1818 "indices on one or more processes. \"Bad\" means that the "
1819 "indices are invalid, they don't exist in the target Map, "
1820 "they don't exist in remoteTarget, or they are not in "
1821 "sorted order. In what follows, I will show the \"bad\" "
1822 "indices as (k, LID) pairs, where k is the zero-based "
1823 "index of the LID in this->getRemoteLIDs()."
1825 if (comm.is_null()) {
1843 Teuchos::Array<LO>
dummy;
1854#define TPETRA_IMPORT_CLASS_INSTANT(LO, GO, NODE) \
1855 template class Import<LO, GO, NODE>;
1864#define TPETRA_IMPORT_INSTANT(LO, GO, NODE) \
1865 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.