40#ifndef TPETRA_IMPORT_DEF_HPP
41#define TPETRA_IMPORT_DEF_HPP
43#include "Tpetra_Distributor.hpp"
44#include "Tpetra_Map.hpp"
45#include "Tpetra_ImportExportData.hpp"
48#include "Tpetra_Export.hpp"
50#include "Tpetra_Details_DualViewUtil.hpp"
53#include "Teuchos_as.hpp"
54#ifdef HAVE_TPETRA_MMM_TIMINGS
55#include "Teuchos_TimeMonitor.hpp"
62 std::string toString (
const std::vector<T>& x)
64 std::ostringstream os;
66 const std::size_t N = x.size ();
67 for (std::size_t k = 0; k < N; ++k) {
69 if (k + std::size_t (1) < N) {
77 template<
class ElementType,
class DeviceType>
78 std::string toString (
const Kokkos::View<const ElementType*, DeviceType>& x)
80 std::ostringstream os;
82 const std::size_t N = std::size_t (x.extent (0));
83 for (std::size_t k = 0; k < N; ++k) {
85 if (k + std::size_t (1) < N) {
98 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
100 Import<LocalOrdinal,GlobalOrdinal,Node>::
101 init (
const Teuchos::RCP<const map_type>& source,
102 const Teuchos::RCP<const map_type>& ,
104 Teuchos::Array<int> & remotePIDs,
105 const Teuchos::RCP<Teuchos::ParameterList>& plist)
107 using ::Tpetra::Details::ProfilingRegion;
108 using Teuchos::Array;
113 ProfilingRegion regionImportInit (
"Tpetra::Import::init");
115 std::unique_ptr<std::string> verbPrefix;
116 if (this->verbose ()) {
117 std::ostringstream os;
118 const int myRank = source->getComm ()->getRank ();
119 os <<
"Proc " << myRank <<
": Tpetra::Import::init: ";
120 verbPrefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
122 this->verboseOutputStream () << os.str ();
125 Array<GlobalOrdinal> remoteGIDs;
127#ifdef HAVE_TPETRA_MMM_TIMINGS
128 using Teuchos::TimeMonitor;
131 label = plist->get(
"Timer Label",label);
132 std::string prefix = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:preIData: ");
137#ifdef HAVE_TPETRA_MMM_TIMINGS
138 auto MM(*TimeMonitor::getNewTimer(prefix));
140 if (this->verbose ()) {
141 std::ostringstream os;
142 os << *verbPrefix <<
"Call setupSamePermuteRemote" << endl;
143 this->verboseOutputStream () << os.str ();
145 setupSamePermuteRemote (remoteGIDs);
148#ifdef HAVE_TPETRA_MMM_TIMINGS
149 prefix = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:preSetupExport: ");
150 auto MM2(*TimeMonitor::getNewTimer(prefix));
152 if (source->isDistributed ()) {
153 if (this->verbose ()) {
154 std::ostringstream os;
155 os << *verbPrefix <<
"Call setupExport" << endl;
156 this->verboseOutputStream () << os.str ();
158 setupExport (remoteGIDs,useRemotePIDs,remotePIDs);
160 else if (this->verbose ()) {
161 std::ostringstream os;
162 os << *verbPrefix <<
"Source Map not distributed; skip setupExport"
164 this->verboseOutputStream () << os.str ();
168 TEUCHOS_ASSERT( ! this->TransferData_->permuteFromLIDs_.need_sync_device () );
169 TEUCHOS_ASSERT( ! this->TransferData_->permuteFromLIDs_.need_sync_host () );
170 TEUCHOS_ASSERT( ! this->TransferData_->permuteToLIDs_.need_sync_device () );
171 TEUCHOS_ASSERT( ! this->TransferData_->permuteToLIDs_.need_sync_host () );
172 TEUCHOS_ASSERT( ! this->TransferData_->remoteLIDs_.need_sync_device () );
173 TEUCHOS_ASSERT( ! this->TransferData_->remoteLIDs_.need_sync_host () );
174 TEUCHOS_ASSERT( ! this->TransferData_->exportLIDs_.need_sync_device () );
175 TEUCHOS_ASSERT( ! this->TransferData_->exportLIDs_.need_sync_host () );
177 this->detectRemoteExportLIDsContiguous();
179 if (this->verbose ()) {
180 std::ostringstream os;
181 os << *verbPrefix <<
"Done!" << endl;
182 this->verboseOutputStream () << os.str ();
186 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
189 const Teuchos::RCP<const map_type >&
target) :
192 Teuchos::Array<int>
dummy;
193#ifdef HAVE_TPETRA_MMM_TIMINGS
194 Teuchos::RCP<Teuchos::ParameterList>
mypars =
rcp(
new Teuchos::ParameterList);
195 mypars->set(
"Timer Label",
"Naive_tAFC");
202 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
205 const Teuchos::RCP<const map_type>&
target,
206 const Teuchos::RCP<Teuchos::FancyOStream>&
out) :
209 Teuchos::Array<int>
dummy;
213 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
216 const Teuchos::RCP<const map_type>&
target,
217 const Teuchos::RCP<Teuchos::ParameterList>&
plist) :
220 Teuchos::Array<int>
dummy;
224 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
227 const Teuchos::RCP<const map_type>&
target,
228 const Teuchos::RCP<Teuchos::FancyOStream>&
out,
229 const Teuchos::RCP<Teuchos::ParameterList>&
plist) :
232 Teuchos::Array<int>
dummy;
236 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
239 const Teuchos::RCP<const map_type>&
target,
240 Teuchos::Array<int>& remotePIDs,
241 const Teuchos::RCP<Teuchos::ParameterList>&
plist) :
247 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
253 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
262 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
269 const Teuchos::RCP<Teuchos::ParameterList>&
plist,
270 const Teuchos::RCP<Teuchos::FancyOStream>&
out) :
273 using ::Tpetra::Details::makeDualViewFromArrayView;
275 using Teuchos::Array;
276 using Teuchos::ArrayRCP;
277 using Teuchos::ArrayView;
284 using size_type = Teuchos::Array<int>::size_type;
286 std::unique_ptr<std::string>
prefix;
288 auto comm =
source.is_null () ? Teuchos::null :
source->getComm ();
289 const int myRank = comm.is_null () ? -1 : comm->getRank ();
290 std::ostringstream
os;
291 os <<
"Proc " <<
myRank <<
": Tpetra::Import createExpert ctor: ";
292 prefix = std::unique_ptr<std::string> (
new std::string (
os.str ()));
302 std::ostringstream
os;
309 std::ostringstream
os;
319 std::ostringstream
os;
320 os << *
prefix <<
"Target Map has remote LIDs but source Map is not "
321 "distributed. Importing to a submap of the target Map." <<
endl;
329 "::constructExpert: Target Map has remote LIDs but source Map "
330 "is not distributed. Importing to a submap of the target Map.");
334 std::runtime_error,
"Import::Import createExpert version: "
335 "Size mismatch on userRemotePIDs, remoteGIDs, and remoteLIDs "
336 "Array's to sort3.");
356 if (indexIntoRemotePIDs -
cnt > 0) {
386 userExportLIDs,
"exportLIDs");
397 std::ostringstream
os;
398 os << *
prefix <<
"locallyComplete: "
400 <<
"; call createFromSendsAndRecvs" <<
endl;
404#ifdef HAVE_TPETRA_MMM_TIMINGS
406 std::string(
"Tpetra ") + std::string(
":iport_ctor:cFSAR ");
414 this->detectRemoteExportLIDsContiguous();
426 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
429 const Teuchos::RCP<const map_type>&
target,
430 const size_t numSameIDs,
433 Teuchos::Array<LocalOrdinal>& remoteLIDs,
437 const Teuchos::RCP<Teuchos::FancyOStream>&
out,
438 const Teuchos::RCP<Teuchos::ParameterList>&
plist) :
441 using ::Tpetra::Details::makeDualViewFromArrayView;
444 std::unique_ptr<std::string>
prefix;
446 auto comm =
source.is_null () ? Teuchos::null :
source->getComm ();
447 const int myRank = comm.is_null () ? -1 : comm->getRank ();
448 std::ostringstream
os;
449 os <<
"Proc " <<
myRank <<
": Tpetra::Import export ctor: ";
450 prefix = std::unique_ptr<std::string> (
new std::string (
os.str ()));
455 bool locallyComplete =
true;
456 for (Teuchos::Array<int>::size_type i = 0; i < exportPIDs.size (); ++i) {
457 if (exportPIDs[i] == -1) {
458 locallyComplete =
false;
462 std::ostringstream os;
463 os << *prefix <<
"numSameIDs: " << numSameIDs <<
", locallyComplete: "
464 << (locallyComplete ?
"true" :
"false") << endl;
471 makeDualViewFromArrayView (this->
TransferData_->permuteToLIDs_,
472 permuteToLIDs ().getConst (),
474 TEUCHOS_ASSERT(
size_t (this->
TransferData_->permuteToLIDs_.extent (0)) ==
475 size_t (permuteToLIDs.size ()) );
476 makeDualViewFromArrayView (this->
TransferData_->permuteFromLIDs_,
477 permuteFromLIDs ().getConst (),
479 TEUCHOS_ASSERT(
size_t (this->
TransferData_->permuteFromLIDs_.extent (0)) ==
480 size_t (permuteFromLIDs.size ()) );
482 remoteLIDs ().getConst (),
484 TEUCHOS_ASSERT(
size_t (this->
TransferData_->remoteLIDs_.extent (0)) ==
485 size_t (remoteLIDs.size ()) );
487 exportLIDs ().getConst (),
489 TEUCHOS_ASSERT(
size_t (this->
TransferData_->exportLIDs_.extent (0)) ==
490 size_t (exportLIDs.size ()) );
494 this->detectRemoteExportLIDsContiguous();
496 TEUCHOS_ASSERT( ! this->
TransferData_->permuteFromLIDs_.need_sync_device () );
497 TEUCHOS_ASSERT( ! this->
TransferData_->permuteFromLIDs_.need_sync_host () );
498 TEUCHOS_ASSERT( ! this->
TransferData_->permuteToLIDs_.need_sync_device () );
499 TEUCHOS_ASSERT( ! this->
TransferData_->permuteToLIDs_.need_sync_host () );
500 TEUCHOS_ASSERT( ! this->
TransferData_->remoteLIDs_.need_sync_device () );
501 TEUCHOS_ASSERT( ! this->
TransferData_->remoteLIDs_.need_sync_host () );
502 TEUCHOS_ASSERT( ! this->
TransferData_->exportLIDs_.need_sync_device () );
503 TEUCHOS_ASSERT( ! this->
TransferData_->exportLIDs_.need_sync_host () );
508 template <
class LO,
class GO,
class NT>
509 struct ImportLocalSetupResult
511 Teuchos::RCP<const ::Tpetra::Map<LO, GO, NT> > targetMap;
515 std::vector<GO> remoteGIDs;
516 std::vector<LO> remoteLIDs;
517 std::vector<int> remotePIDs;
522 void printArray (std::ostream& out,
const T x[],
const std::size_t N)
525 for (std::size_t k = 0; k < N; ++k) {
534 template<
class LO,
class GO,
class NT>
535 ImportLocalSetupResult<LO, GO, NT>
536 setupSamePermuteRemoteFromUserGlobalIndexList (const ::Tpetra::Map<LO, GO, NT>& sourceMap,
537 const GO targetMapRemoteOrPermuteGlobalIndices[],
538 const int targetMapRemoteOrPermuteProcessRanks[],
539 const LO numTargetMapRemoteOrPermuteGlobalIndices,
540 const bool mayReorderTargetMapIndicesLocally,
541 Teuchos::FancyOStream* out,
542 const std::string* verboseHeader,
547 const int myRank = sourceMap.getComm ()->getRank ();
548 ImportLocalSetupResult<LO, GO, NT> result;
551 std::ostringstream os;
552 os << *verboseHeader <<
"- Import::setupSPR w/ remote GIDs & PIDs: " << endl
553 << *verboseHeader <<
" Input GIDs: ";
554 printArray (os, targetMapRemoteOrPermuteGlobalIndices, numTargetMapRemoteOrPermuteGlobalIndices);
555 os << endl <<
" Input PIDs: ";
556 printArray (os, targetMapRemoteOrPermuteProcessRanks, numTargetMapRemoteOrPermuteGlobalIndices);
566 std::vector<GO> badGIDs;
567 std::vector<int> badPIDs;
568 const Teuchos::Comm<int>& comm = * (sourceMap.getComm ());
569 const int numProcs = comm.getSize ();
571 for (LO k = 0; k < numTargetMapRemoteOrPermuteGlobalIndices; ++k) {
572 const GO tgtGID = targetMapRemoteOrPermuteGlobalIndices[k];
573 if (sourceMap.isNodeGlobalElement (tgtGID)) {
574 badGIDs.push_back (tgtGID);
576 const int tgtPID = targetMapRemoteOrPermuteProcessRanks[k];
577 if (tgtPID < 0 || tgtPID >= numProcs) {
578 badPIDs.push_back (tgtPID);
582 std::array<int, 2> lclStatus {{
583 badGIDs.size () == 0 ? 1 : 0,
584 badPIDs.size () == 0 ? 1 : 0
586 std::array<int, 2> gblStatus {{0, 0}};
587 Teuchos::reduceAll<int, int> (comm, Teuchos::REDUCE_MIN, 2,
588 lclStatus.data (), gblStatus.data ());
589 const bool good = gblStatus[0] == 1 && gblStatus[1] == 1;
592 if (verbose && gblStatus[0] != 1) {
593 std::ostringstream os;
594 os << *verboseHeader <<
"- Some input GIDs are already in the source Map: ";
595 printArray (os, badGIDs.data (), badGIDs.size ());
599 if (verbose && gblStatus[0] != 1) {
600 std::ostringstream os;
601 os << *verboseHeader <<
"- Some input PIDs are invalid: ";
602 printArray (os, badPIDs.data (), badPIDs.size ());
608 std::ostringstream os;
609 os <<
"Tpetra::Import constructor that takes remote GIDs and PIDs: ";
610 if (gblStatus[0] != 1) {
611 os <<
"Some input GIDs (global indices) are already in the source Map! ";
613 if (gblStatus[1] != 1) {
614 os <<
"Some input PIDs (process ranks) are invalid! ";
616 os <<
"Rerun with the environment variable TPETRA_VERBOSE=Tpetra::Import "
617 "to see what GIDs and/or PIDs are bad.";
618 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument, os.str ());
625 const LO numLclSrcIDs =
static_cast<LO
> (sourceMap.getLocalNumElements ());
626 const LO numLclTgtIDs = numLclSrcIDs + numTargetMapRemoteOrPermuteGlobalIndices;
628 std::ostringstream os;
629 os << *verboseHeader <<
"- Copy source Map GIDs into target Map GID list: "
630 "numLclSrcIDs=" << numLclSrcIDs
631 <<
", numTargetMapRemoteOrPermuteGlobalIndices="
632 << numTargetMapRemoteOrPermuteGlobalIndices << endl;
635 std::vector<GO> tgtGIDs (numLclTgtIDs);
636 if (sourceMap.isContiguous ()) {
637 GO curTgtGID = sourceMap.getMinGlobalIndex ();
638 for (LO k = 0; k < numLclSrcIDs; ++k, ++curTgtGID) {
639 tgtGIDs[k] = curTgtGID;
643 auto srcGIDs = sourceMap.getLocalElementList ();
644 for (LO k = 0; k < numLclSrcIDs; ++k) {
645 tgtGIDs[k] = srcGIDs[k];
648 std::copy (targetMapRemoteOrPermuteGlobalIndices,
649 targetMapRemoteOrPermuteGlobalIndices + numTargetMapRemoteOrPermuteGlobalIndices,
650 tgtGIDs.begin () + numLclSrcIDs);
663 std::ostringstream os;
664 os << *verboseHeader <<
"- Sort by PID? "
665 << (mayReorderTargetMapIndicesLocally ?
"true" :
"false") << endl;
668 std::vector<int> tgtPIDs (targetMapRemoteOrPermuteProcessRanks,
669 targetMapRemoteOrPermuteProcessRanks + numTargetMapRemoteOrPermuteGlobalIndices);
670 result.numPermutes = 0;
671 if (mayReorderTargetMapIndicesLocally) {
672 Tpetra::sort2 (tgtPIDs.begin (), tgtPIDs.end (), tgtGIDs.begin () + numLclSrcIDs);
673 auto range = std::equal_range (tgtPIDs.begin (), tgtPIDs.end (), myRank);
674 if (range.second > range.first) {
675 result.numPermutes =
static_cast<LO
> (range.second - range.first);
679 result.numPermutes =
static_cast<LO
> (std::count (tgtPIDs.begin (), tgtPIDs.end (), myRank));
682 const LO numRemotes = numTargetMapRemoteOrPermuteGlobalIndices - result.numPermutes;
683 result.numSameIDs =
static_cast<LO
> (sourceMap.getLocalNumElements ());
686 std::ostringstream os;
687 os << *verboseHeader <<
"- numSame=" << result.numSameIDs
688 <<
", numPermutes=" << result.numPermutes
689 <<
", numRemotes=" << numRemotes << endl;
693 if (result.numPermutes == 0) {
695 std::ostringstream os;
696 os << *verboseHeader <<
"- No permutes" << endl;
699 result.remoteGIDs = std::vector<GO> (tgtGIDs.begin () + numLclSrcIDs, tgtGIDs.end ());
700 result.remotePIDs.swap (tgtPIDs);
701 result.remoteLIDs.resize (numRemotes);
702 for (LO k = 0; k < numRemotes; ++k) {
703 const LO tgtLid = result.numSameIDs + k;
704 result.remoteLIDs[k] = tgtLid;
707 std::ostringstream os;
708 os << *verboseHeader <<
"- Remote GIDs: "
709 << Teuchos::toString (result.remoteGIDs) << endl;
710 os << *verboseHeader <<
"- Remote PIDs: "
711 << Teuchos::toString (result.remotePIDs) << endl;
712 os << *verboseHeader <<
"- Remote LIDs: "
713 << Teuchos::toString (result.remoteLIDs) << endl;
721 result.remoteGIDs.reserve (numRemotes);
722 result.remoteLIDs.reserve (numRemotes);
723 result.remotePIDs.reserve (numRemotes);
724 for (LO k = 0; k < numTargetMapRemoteOrPermuteGlobalIndices; ++k) {
725 const LO tgtLid = result.numSameIDs + k;
726 const GO tgtGid = tgtGIDs[numLclSrcIDs + k];
727 const int tgtPid = tgtPIDs[k];
729 if (tgtPid != myRank) {
730 result.remoteGIDs.push_back (tgtGid);
731 result.remoteLIDs.push_back (tgtLid);
732 result.remotePIDs.push_back (tgtPid);
736 std::ostringstream os;
737 os << *verboseHeader <<
"- Some permutes" << endl;
742 if (sourceMap.isDistributed ()) {
744 std::ostringstream os;
745 os << *verboseHeader <<
"- Sort remotes by PID, as Import always does"
747 << *verboseHeader <<
"-- remotePIDs before: "
748 << Teuchos::toString (result.remotePIDs) << endl
749 << *verboseHeader <<
"-- remoteGIDs before: "
750 << Teuchos::toString (result.remoteGIDs) << endl
751 << *verboseHeader <<
"-- remoteLIDs before: "
752 << Teuchos::toString (result.remoteLIDs) << endl;
756 sort3 (result.remotePIDs.begin (),
757 result.remotePIDs.end (),
758 result.remoteGIDs.begin (),
759 result.remoteLIDs.begin ());
761 std::ostringstream os;
762 os << *verboseHeader <<
"-- remotePIDs after: "
763 << Teuchos::toString (result.remotePIDs) << endl
764 << *verboseHeader <<
"-- remoteGIDs after: "
765 << Teuchos::toString (result.remoteGIDs) << endl
766 << *verboseHeader <<
"-- remoteLIDs after: "
767 << Teuchos::toString (result.remoteLIDs) << endl;
768 std::cerr << os.str ();
773 std::ostringstream os;
774 os << *verboseHeader <<
"- Make target Map" << endl;
777 using ::Teuchos::rcp;
778 typedef ::Tpetra::Map<LO, GO, NT> map_type;
780 const GST MAP_COMPUTES_GLOBAL_COUNT = ::Teuchos::OrdinalTraits<GST>::invalid ();
781 result.targetMap = rcp (
new map_type (MAP_COMPUTES_GLOBAL_COUNT,
784 sourceMap.getIndexBase (),
785 sourceMap.getComm ()));
787 std::ostringstream os;
788 os << *verboseHeader <<
"- Done with sameSPR..." << endl;
795 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
802 const Teuchos::RCP<Teuchos::ParameterList>&
plist,
803 const Teuchos::RCP<Teuchos::FancyOStream>&
debugOutput) :
809 using ::Tpetra::Details::Behavior;
810 using ::Tpetra::Details::makeDualViewFromOwningHostView;
811 using ::Tpetra::Details::makeDualViewFromVector;
812 using ::Tpetra::Details::printDualView;
813 using ::Tpetra::Details::view_alloc_no_init;
814 using Teuchos::ArrayView;
815 using Teuchos::getFancyOStream;
818 using Teuchos::rcpFromRef;
824 const bool debug = Behavior::debug (
"Import") ||
825 Behavior::debug (
"Tpetra::Import");
827 std::unique_ptr<std::string>
verbPfx;
828 if (this->verbose ()) {
829 std::ostringstream
os;
831 os <<
"Proc " <<
myRank <<
": Tpetra::Import ctor from remotes: ";
832 verbPfx = std::unique_ptr<std::string> (
new std::string (
os.str ()));
858 this->TransferData_->out_,
860 this->
TransferData_->numSameIDs_ = localSetupResult.numSameIDs;
864 localSetupResult.remoteLIDs,
877 if (this->verbose ()) {
878 std::ostringstream
os;
879 os << *
verbPfx <<
"Make Distributor (createFromRecvs)" <<
endl;
903 if (this->verbose ()) {
904 std::ostringstream
os;
908 using size_type =
typename Teuchos::Array<GO>::size_type;
917 makeDualViewFromOwningHostView (this->
TransferData_->exportLIDs_, exportLIDs);
920 if (this->verbose ()) {
921 std::ostringstream
os;
924 "ImportExportData::remoteLIDs_");
928 if (this->verbose ()) {
929 std::ostringstream
os;
935 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
939 const Teuchos::EVerbosityLevel
verbLevel)
const
945 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
949 auto out = Teuchos::getFancyOStream (Teuchos::rcpFromRef (
os));
951 this->describe (*
out, Teuchos::VERB_EXTREME);
954 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
959 using ::Tpetra::Details::makeDualViewFromOwningHostView;
960 using ::Tpetra::Details::ProfilingRegion;
961 using ::Tpetra::Details::view_alloc_no_init;
963 using Teuchos::Array;
964 using Teuchos::ArrayRCP;
965 using Teuchos::ArrayView;
971 ProfilingRegion
regionExport (
"Tpetra::Import::setupSamePermuteRemote");
973 const map_type&
source = * (this->getSourceMap ());
974 const map_type&
target = * (this->getTargetMap ());
978#ifdef HAVE_TPETRA_DEBUG
998 this->TransferData_->numSameIDs_ = numSameGids;
1012 const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid ();
1013 const LO numTgtLids = as<LO> (numTgtGids);
1016 for (LO tgtLid = numSameGids; tgtLid < numTgtLids; ++tgtLid) {
1017 const GO curTargetGid = rawTgtGids[tgtLid];
1021 const LO srcLid = source.getLocalElement (curTargetGid);
1022 if (srcLid != LINVALID) {
1026 const LO numRemotes = (numTgtLids - numSameGids) - numPermutes;
1028 using host_perm_type =
1029 typename decltype (this->TransferData_->permuteToLIDs_)::t_host;
1030 host_perm_type permuteToLIDs
1031 (view_alloc_no_init (
"permuteToLIDs"), numPermutes);
1032 host_perm_type permuteFromLIDs
1033 (view_alloc_no_init (
"permuteFromLIDs"), numPermutes);
1034 typename decltype (this->TransferData_->remoteLIDs_)::t_host remoteLIDs
1035 (view_alloc_no_init (
"permuteFromLIDs"), numRemotes);
1038 LO numPermutes2 = 0;
1040 for (LO tgtLid = numSameGids; tgtLid < numTgtLids; ++tgtLid) {
1041 const GO curTargetGid = rawTgtGids[tgtLid];
1042 const LO srcLid = source.getLocalElement (curTargetGid);
1043 if (srcLid != LINVALID) {
1044 permuteToLIDs[numPermutes2] = tgtLid;
1045 permuteFromLIDs[numPermutes2] = srcLid;
1049 remoteGIDs.push_back (curTargetGid);
1050 remoteLIDs[numRemotes2] = tgtLid;
1054 TEUCHOS_ASSERT( numPermutes == numPermutes2 );
1055 TEUCHOS_ASSERT( numRemotes == numRemotes2 );
1056 TEUCHOS_ASSERT(
size_t (numPermutes) + remoteGIDs.size () == size_t (numTgtLids - numSameGids) );
1062 if (remoteLIDs.extent (0) != 0 && ! source.isDistributed ()) {
1068 this->TransferData_->isLocallyComplete_ =
false;
1072 (
true, std::runtime_error,
"::setupSamePermuteRemote(): Target has "
1073 "remote LIDs but Source is not distributed globally. Importing to a "
1074 "submap of the target map.");
1079 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1080 void Import<LocalOrdinal,GlobalOrdinal,Node>::
1081 setupExport (Teuchos::Array<GlobalOrdinal>& remoteGIDs,
1083 Teuchos::Array<int>& userRemotePIDs,
1084 const Teuchos::RCP<Teuchos::ParameterList>& plist)
1086 using ::Tpetra::Details::makeDualViewFromOwningHostView;
1087 using ::Tpetra::Details::view_alloc_no_init;
1088 using Teuchos::Array;
1089 using Teuchos::ArrayView;
1091 using GO = GlobalOrdinal;
1092 typedef typename Array<int>::difference_type size_type;
1093 const char tfecfFuncName[] =
"setupExport: ";
1094 const char suffix[] =
" Please report this bug to the Tpetra developers.";
1096 std::unique_ptr<std::string> prefix;
1097 if (this->verbose ()) {
1098 auto srcMap = this->getSourceMap ();
1099 auto comm = srcMap.is_null () ? Teuchos::null : srcMap->getComm ();
1100 const int myRank = comm.is_null () ? -1 : comm->getRank ();
1101 std::ostringstream os;
1102 os <<
"Proc " << myRank <<
": Tpetra::Import::setupExport: ";
1103 prefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
1104 os <<
"Start" << std::endl;
1105 this->verboseOutputStream () << os.str ();
1108 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1109 (this->getSourceMap ().is_null (), std::logic_error,
1110 "Source Map is null. " << suffix);
1111 const map_type& source = * (this->getSourceMap ());
1113 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1114 (! useRemotePIDs && (userRemotePIDs.size() > 0), std::invalid_argument,
1115 "remotePIDs are non-empty but their use has not been requested.");
1116 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1117 (userRemotePIDs.size () > 0 && remoteGIDs.size () != userRemotePIDs.size (),
1118 std::invalid_argument,
"remotePIDs must either be of size zero or match "
1119 "the size of remoteGIDs.");
1123 ArrayView<GO> remoteGIDsView = remoteGIDs ();
1124 ArrayView<int> remoteProcIDsView;
1144 Array<int> newRemotePIDs;
1147 if (! useRemotePIDs) {
1148 newRemotePIDs.resize (remoteGIDsView.size ());
1149 if (this->verbose ()) {
1150 std::ostringstream os;
1151 os << *prefix <<
"Call sourceMap.getRemoteIndexList" << endl;
1152 this->verboseOutputStream () << os.str ();
1154 lookup = source.getRemoteIndexList (remoteGIDsView, newRemotePIDs ());
1156 Array<int>& remoteProcIDs = useRemotePIDs ? userRemotePIDs : newRemotePIDs;
1162 this->TransferData_->isLocallyComplete_ =
false;
1167 (
true, std::runtime_error,
"::setupExport(): the source Map wasn't "
1168 "able to figure out which process owns one or more of the GIDs in the "
1169 "list of remote GIDs. This probably means that there is at least one "
1170 "GID owned by some process in the target Map which is not owned by any"
1171 " process in the source Map. (That is, the source and target Maps do "
1172 "not contain the same set of GIDs globally.)");
1178 const size_type numInvalidRemote =
1179 std::count_if (remoteProcIDs.begin (), remoteProcIDs.end (),
1180 std::bind (std::equal_to<int> (), -1, std::placeholders::_1));
1181 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1182 (numInvalidRemote == 0, std::logic_error,
"Calling getRemoteIndexList "
1183 "on the source Map returned IDNotPresent, but none of the returned "
1184 "\"remote\" process ranks are -1. Please report this bug to the "
1185 "Tpetra developers.");
1187#ifdef HAVE_TPETRA_MMM_TIMINGS
1188 using Teuchos::TimeMonitor;
1190 if(!plist.is_null())
1191 label = plist->get(
"Timer Label",label);
1192 std::string prefix = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:setupExport:1 ");
1193 auto MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix)));
1199 const size_type totalNumRemote = this->getNumRemoteIDs ();
1200 if (numInvalidRemote == totalNumRemote) {
1202 remoteProcIDs.clear ();
1203 remoteGIDs.clear ();
1204 this->TransferData_->remoteLIDs_ =
1205 decltype (this->TransferData_->remoteLIDs_) ();
1210 size_type numValidRemote = 0;
1211#ifdef HAVE_TPETRA_DEBUG
1212 ArrayView<GO> remoteGIDsPtr = remoteGIDsView;
1214 GO*
const remoteGIDsPtr = remoteGIDsView.getRawPtr ();
1218 auto remoteLIDs = this->TransferData_->remoteLIDs_.view_host ();
1220 for (size_type r = 0; r < totalNumRemote; ++r) {
1222 if (remoteProcIDs[r] != -1) {
1223 remoteProcIDs[numValidRemote] = remoteProcIDs[r];
1224 remoteGIDsPtr[numValidRemote] = remoteGIDsPtr[r];
1225 remoteLIDs[numValidRemote] = remoteLIDs[r];
1229 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1230 (numValidRemote != totalNumRemote - numInvalidRemote,
1231 std::logic_error,
"After removing invalid remote GIDs and packing "
1232 "the valid remote GIDs, numValidRemote = " << numValidRemote
1233 <<
" != totalNumRemote - numInvalidRemote = "
1234 << totalNumRemote - numInvalidRemote
1235 <<
". Please report this bug to the Tpetra developers.");
1237 remoteProcIDs.resize (numValidRemote);
1238 remoteGIDs.resize (numValidRemote);
1240 Kokkos::resize (remoteLIDs, numValidRemote);
1241 this->TransferData_->remoteLIDs_ =
decltype (this->TransferData_->remoteLIDs_) ();
1245 remoteGIDsView = remoteGIDs ();
1253 this->TransferData_->remoteLIDs_.modify_host ();
1254 auto remoteLIDs = this->TransferData_->remoteLIDs_.view_host ();
1255 sort3 (remoteProcIDs.begin (),
1256 remoteProcIDs.end (),
1257 remoteGIDsView.getRawPtr (),
1258 remoteLIDs.data ());
1259 this->TransferData_->remoteLIDs_.sync_device ();
1267 Array<GO> exportGIDs;
1269#ifdef HAVE_TPETRA_MMM_TIMINGS
1270 using Teuchos::TimeMonitor;
1272 if(!plist.is_null())
1273 label = plist->get(
"Timer Label",label);
1274 std::string prefix2 = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:setupExport:3 ");
1275 auto MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2)));
1278 if (this->verbose ()) {
1279 std::ostringstream os;
1280 os << *prefix <<
"Call createFromRecvs" << endl;
1281 this->verboseOutputStream () << endl;
1283 this->TransferData_->distributor_.createFromRecvs (remoteGIDsView ().getConst (),
1284 remoteProcIDs, exportGIDs,
1285 this->TransferData_->exportPIDs_);
1291#ifdef HAVE_TPETRA_MMM_TIMINGS
1292 prefix2 = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:setupExport:4 ");
1293 MM = Teuchos::null; MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2)));
1299 const size_type numExportIDs = exportGIDs.size ();
1300 if (numExportIDs > 0) {
1301 typename decltype (this->TransferData_->exportLIDs_)::t_host
1302 exportLIDs (view_alloc_no_init (
"exportLIDs"), numExportIDs);
1303 ArrayView<const GO> expGIDs = exportGIDs ();
1305 for (size_type k = 0; k < numExportIDs; ++k) {
1306 exportLIDs[k] = source.getLocalElement (expGIDs[k]);
1311 if (this->verbose ()) {
1312 std::ostringstream os;
1313 os << *prefix <<
"Done!" << endl;
1314 this->verboseOutputStream () << os.str ();
1318 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1322 Teuchos::Array<std::pair<int,GlobalOrdinal>>&
remotePGIDs,
1323 typename Teuchos::Array<GlobalOrdinal>::size_type&
numSameGIDs,
1324 typename Teuchos::Array<GlobalOrdinal>::size_type&
numPermuteGIDs,
1325 typename Teuchos::Array<GlobalOrdinal>::size_type&
numRemoteGIDs,
1326 const Teuchos::ArrayView<const GlobalOrdinal>&
sameGIDs1,
1327 const Teuchos::ArrayView<const GlobalOrdinal>&
sameGIDs2,
1337 typedef typename Teuchos::Array<GO>::size_type size_type;
1423 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1424 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
1428 using ::Tpetra::Details::Behavior;
1429 using Teuchos::Array;
1430 using Teuchos::ArrayView;
1432 using Teuchos::Comm;
1435 using Teuchos::outArg;
1436 using Teuchos::REDUCE_MIN;
1437 using Teuchos::reduceAll;
1444#ifdef HAVE_TPETRA_MMM_TIMINGS
1445 using Teuchos::TimeMonitor;
1446 std::string label = std::string(
"Tpetra::Import::setUnion");
1455 const bool debug = Behavior::debug (
"Import::setUnion") ||
1456 Behavior::debug (
"Tpetra::Import::setUnion");
1460 (!
srcMap->isSameAs (* (
rhs.getSourceMap ())), std::invalid_argument,
1461 "Tpetra::Import::setUnion: The source Map of the input Import must be the "
1462 "same as (in the sense of Map::isSameAs) the source Map of this Import.");
1467 std::invalid_argument,
"Tpetra::Import::setUnion: "
1468 "The target Maps must have congruent communicators.");
1475 return rcp (
new import_type (*
this));
1513 Tpetra::Import_Util::getRemotePIDs(*
this,
remotePIDs1);
1550#ifdef HAVE_TPETRA_MMM_TIMINGS
1551 MM.disableTimer(label);
1552 label =
"Tpetra::Import::setUnion : Construct Target Map";
1557 const GST INVALID = Teuchos::OrdinalTraits<GST>::invalid ();
1562#ifdef HAVE_TPETRA_MMM_TIMINGS
1563 MM2.disableTimer(label);
1564 label =
"Tpetra::Import::setUnion : Export GIDs";
1581#ifdef TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1665#ifdef HAVE_TPETRA_MMM_TIMINGS
1666 MM3.disableTimer(label);
1667 label =
"Tpetra::Import::setUnion : Construct Import";
1676 this->TransferData_->out_));
1680 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1681 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
1685 using Teuchos::Array;
1686 using Teuchos::ArrayView;
1688 using Teuchos::Comm;
1691 using Teuchos::outArg;
1692 using Teuchos::REDUCE_MIN;
1693 using Teuchos::reduceAll;
1696 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
unionImport;
1726 GO
GO_INVALID = Teuchos::OrdinalTraits<GO>::invalid();
1751 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1752 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
1756 using ::Tpetra::Details::Behavior;
1757 using ::Tpetra::Details::gathervPrint;
1758 using Teuchos::outArg;
1760 using Teuchos::REDUCE_MIN;
1761 using Teuchos::reduceAll;
1767 const char funcPrefix[] =
"Tpetra::createRemoteOnlyImport: ";
1770 const bool debug = Behavior::debug ();
1772 const size_t NumRemotes = this->getNumRemoteIDs ();
1774 Teuchos::RCP<const Teuchos::Comm<int>> comm;
1778 std::ostringstream
os;
1780 if (comm.is_null ()) {
1784 os << comm->getRank ();
1787 procPrefix = std::unique_ptr<std::string> (
new std::string (
os.str ()));
1791 std::ostringstream
lclErr;
1798 <<
" != remoteTarget->getLocalNumElements() = "
1802 if (comm.is_null ()) {
1810 <<
"Input target Map is null on at least one process.");
1813 if (comm.is_null ()) {
1815 (
true, std::runtime_error,
lclErr.str ());
1818 std::ostringstream
gblErr;
1822 (
true, std::runtime_error,
gblErr.str ());
1828 Teuchos::ArrayView<const LO>
oldRemoteLIDs = this->getRemoteLIDs ();
1833 std::unique_ptr<std::vector<size_t>>
badIndices;
1835 badIndices = std::unique_ptr<std::vector<size_t>> (
new std::vector<size_t>);
1840 if (
oldLclInd == Teuchos::OrdinalTraits<LO>::invalid ()) {
1846 if (
gblInd == Teuchos::OrdinalTraits<GO>::invalid ()) {
1852 if (
newLclInd == Teuchos::OrdinalTraits<LO>::invalid ()) {
1870 if (comm.is_null ()) {
1876 std::ostringstream
lclErr;
1879 <<
", bad indices: [";
1883 const size_t badIndex = (*badIndices)[
k];
1894 std::ostringstream
gblErr;
1896 "indices on one or more processes. \"Bad\" means that the "
1897 "indices are invalid, they don't exist in the target Map, "
1898 "they don't exist in remoteTarget, or they are not in "
1899 "sorted order. In what follows, I will show the \"bad\" "
1900 "indices as (k, LID) pairs, where k is the zero-based "
1901 "index of the LID in this->getRemoteLIDs()." <<
endl;
1902 if (comm.is_null ()) {
1909 (
true, std::runtime_error,
gblErr.str ());
1915 <<
"this->getRemoteLIDs() has " <<
badCount
1916 <<
"ind" << (
badCount == 1 ?
"ex" :
"ices")
1917 <<
" \"bad\" indices on this process." <<
endl);
1927 Teuchos::Array<LO>
dummy;
1938#define TPETRA_IMPORT_CLASS_INSTANT(LO, GO, NODE) \
1939 template class Import< LO , GO , NODE >;
1948#define TPETRA_IMPORT_INSTANT(LO, GO, NODE) \
1949 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.
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 sort3(const IT1 &first1, const IT1 &last1, const IT2 &first2, const IT3 &first3)
Sort the first array, and apply the same permutation to the second and third arrays.
void sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2)
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.