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"
32 std::string toString (
const std::vector<T>& x)
34 std::ostringstream os;
36 const std::size_t N = x.size ();
37 for (std::size_t k = 0; k < N; ++k) {
39 if (k + std::size_t (1) < N) {
47 template<
class ElementType,
class DeviceType>
48 std::string toString (
const Kokkos::View<const ElementType*, DeviceType>& x)
50 std::ostringstream os;
52 const std::size_t N = std::size_t (x.extent (0));
53 for (std::size_t k = 0; k < N; ++k) {
55 if (k + std::size_t (1) < N) {
68 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
70 Import<LocalOrdinal,GlobalOrdinal,Node>::
71 init (
const Teuchos::RCP<const map_type>& source,
72 const Teuchos::RCP<const map_type>& ,
74 Teuchos::Array<int> & remotePIDs,
75 const Teuchos::RCP<Teuchos::ParameterList>& plist)
77 using ::Tpetra::Details::ProfilingRegion;
83 ProfilingRegion regionImportInit (
"Tpetra::Import::init");
85 std::unique_ptr<std::string> verbPrefix;
86 if (this->verbose ()) {
87 std::ostringstream os;
88 const int myRank = source->getComm ()->getRank ();
89 os <<
"Proc " << myRank <<
": Tpetra::Import::init: ";
90 verbPrefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
92 this->verboseOutputStream () << os.str ();
95 Array<GlobalOrdinal> remoteGIDs;
97#ifdef HAVE_TPETRA_MMM_TIMINGS
98 using Teuchos::TimeMonitor;
101 label = plist->get(
"Timer Label",label);
102 std::string prefix = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:preIData: ");
107#ifdef HAVE_TPETRA_MMM_TIMINGS
108 auto MM(*TimeMonitor::getNewTimer(prefix));
110 if (this->verbose ()) {
111 std::ostringstream os;
112 os << *verbPrefix <<
"Call setupSamePermuteRemote" << endl;
113 this->verboseOutputStream () << os.str ();
115 setupSamePermuteRemote (remoteGIDs);
118#ifdef HAVE_TPETRA_MMM_TIMINGS
119 prefix = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:preSetupExport: ");
120 auto MM2(*TimeMonitor::getNewTimer(prefix));
122 if (source->isDistributed ()) {
123 if (this->verbose ()) {
124 std::ostringstream os;
125 os << *verbPrefix <<
"Call setupExport" << endl;
126 this->verboseOutputStream () << os.str ();
128 setupExport (remoteGIDs,useRemotePIDs,remotePIDs);
130 else if (this->verbose ()) {
131 std::ostringstream os;
132 os << *verbPrefix <<
"Source Map not distributed; skip setupExport"
134 this->verboseOutputStream () << os.str ();
138 TEUCHOS_ASSERT( ! this->TransferData_->permuteFromLIDs_.need_sync_device () );
139 TEUCHOS_ASSERT( ! this->TransferData_->permuteFromLIDs_.need_sync_host () );
140 TEUCHOS_ASSERT( ! this->TransferData_->permuteToLIDs_.need_sync_device () );
141 TEUCHOS_ASSERT( ! this->TransferData_->permuteToLIDs_.need_sync_host () );
142 TEUCHOS_ASSERT( ! this->TransferData_->remoteLIDs_.need_sync_device () );
143 TEUCHOS_ASSERT( ! this->TransferData_->remoteLIDs_.need_sync_host () );
144 TEUCHOS_ASSERT( ! this->TransferData_->exportLIDs_.need_sync_device () );
145 TEUCHOS_ASSERT( ! this->TransferData_->exportLIDs_.need_sync_host () );
147 this->detectRemoteExportLIDsContiguous();
149 if (this->verbose ()) {
150 std::ostringstream os;
151 os << *verbPrefix <<
"Done!" << endl;
152 this->verboseOutputStream () << os.str ();
156 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
159 const Teuchos::RCP<const map_type >&
target) :
162 Teuchos::Array<int>
dummy;
163#ifdef HAVE_TPETRA_MMM_TIMINGS
164 Teuchos::RCP<Teuchos::ParameterList>
mypars =
rcp(
new Teuchos::ParameterList);
165 mypars->set(
"Timer Label",
"Naive_tAFC");
172 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
175 const Teuchos::RCP<const map_type>&
target,
176 const Teuchos::RCP<Teuchos::FancyOStream>&
out) :
179 Teuchos::Array<int>
dummy;
183 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
186 const Teuchos::RCP<const map_type>&
target,
187 const Teuchos::RCP<Teuchos::ParameterList>&
plist) :
190 Teuchos::Array<int>
dummy;
194 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
197 const Teuchos::RCP<const map_type>&
target,
198 const Teuchos::RCP<Teuchos::FancyOStream>&
out,
199 const Teuchos::RCP<Teuchos::ParameterList>&
plist) :
202 Teuchos::Array<int>
dummy;
206 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
209 const Teuchos::RCP<const map_type>&
target,
210 Teuchos::Array<int>& remotePIDs,
211 const Teuchos::RCP<Teuchos::ParameterList>&
plist) :
217 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
223 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
232 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
239 const Teuchos::RCP<Teuchos::ParameterList>&
plist,
240 const Teuchos::RCP<Teuchos::FancyOStream>&
out) :
243 using ::Tpetra::Details::makeDualViewFromArrayView;
245 using Teuchos::Array;
246 using Teuchos::ArrayRCP;
247 using Teuchos::ArrayView;
254 using size_type = Teuchos::Array<int>::size_type;
256 std::unique_ptr<std::string>
prefix;
258 auto comm =
source.is_null () ? Teuchos::null :
source->getComm ();
259 const int myRank = comm.is_null () ? -1 : comm->getRank ();
260 std::ostringstream
os;
261 os <<
"Proc " <<
myRank <<
": Tpetra::Import createExpert ctor: ";
262 prefix = std::unique_ptr<std::string> (
new std::string (
os.str ()));
272 std::ostringstream
os;
279 std::ostringstream
os;
289 std::ostringstream
os;
290 os << *
prefix <<
"Target Map has remote LIDs but source Map is not "
291 "distributed. Importing to a submap of the target Map." <<
endl;
299 "::constructExpert: Target Map has remote LIDs but source Map "
300 "is not distributed. Importing to a submap of the target Map.");
304 std::runtime_error,
"Import::Import createExpert version: "
305 "Size mismatch on userRemotePIDs, remoteGIDs, and remoteLIDs "
306 "Array's to sort3.");
326 if (indexIntoRemotePIDs -
cnt > 0) {
356 userExportLIDs,
"exportLIDs");
367 std::ostringstream
os;
368 os << *
prefix <<
"locallyComplete: "
370 <<
"; call createFromSendsAndRecvs" <<
endl;
374#ifdef HAVE_TPETRA_MMM_TIMINGS
376 std::string(
"Tpetra ") + std::string(
":iport_ctor:cFSAR ");
384 this->detectRemoteExportLIDsContiguous();
396 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
399 const Teuchos::RCP<const map_type>&
target,
400 const size_t numSameIDs,
403 Teuchos::Array<LocalOrdinal>& remoteLIDs,
407 const Teuchos::RCP<Teuchos::FancyOStream>&
out,
408 const Teuchos::RCP<Teuchos::ParameterList>&
plist) :
411 using ::Tpetra::Details::makeDualViewFromArrayView;
414 std::unique_ptr<std::string>
prefix;
416 auto comm =
source.is_null () ? Teuchos::null :
source->getComm ();
417 const int myRank = comm.is_null () ? -1 : comm->getRank ();
418 std::ostringstream
os;
419 os <<
"Proc " <<
myRank <<
": Tpetra::Import export ctor: ";
420 prefix = std::unique_ptr<std::string> (
new std::string (
os.str ()));
425 bool locallyComplete =
true;
426 for (Teuchos::Array<int>::size_type i = 0; i < exportPIDs.size (); ++i) {
427 if (exportPIDs[i] == -1) {
428 locallyComplete =
false;
432 std::ostringstream os;
433 os << *prefix <<
"numSameIDs: " << numSameIDs <<
", locallyComplete: "
434 << (locallyComplete ?
"true" :
"false") << endl;
441 makeDualViewFromArrayView (this->
TransferData_->permuteToLIDs_,
442 permuteToLIDs ().getConst (),
444 TEUCHOS_ASSERT(
size_t (this->
TransferData_->permuteToLIDs_.extent (0)) ==
445 size_t (permuteToLIDs.size ()) );
446 makeDualViewFromArrayView (this->
TransferData_->permuteFromLIDs_,
447 permuteFromLIDs ().getConst (),
449 TEUCHOS_ASSERT(
size_t (this->
TransferData_->permuteFromLIDs_.extent (0)) ==
450 size_t (permuteFromLIDs.size ()) );
452 remoteLIDs ().getConst (),
454 TEUCHOS_ASSERT(
size_t (this->
TransferData_->remoteLIDs_.extent (0)) ==
455 size_t (remoteLIDs.size ()) );
457 exportLIDs ().getConst (),
459 TEUCHOS_ASSERT(
size_t (this->
TransferData_->exportLIDs_.extent (0)) ==
460 size_t (exportLIDs.size ()) );
464 this->detectRemoteExportLIDsContiguous();
466 TEUCHOS_ASSERT( ! this->
TransferData_->permuteFromLIDs_.need_sync_device () );
467 TEUCHOS_ASSERT( ! this->
TransferData_->permuteFromLIDs_.need_sync_host () );
468 TEUCHOS_ASSERT( ! this->
TransferData_->permuteToLIDs_.need_sync_device () );
469 TEUCHOS_ASSERT( ! this->
TransferData_->permuteToLIDs_.need_sync_host () );
470 TEUCHOS_ASSERT( ! this->
TransferData_->remoteLIDs_.need_sync_device () );
471 TEUCHOS_ASSERT( ! this->
TransferData_->remoteLIDs_.need_sync_host () );
472 TEUCHOS_ASSERT( ! this->
TransferData_->exportLIDs_.need_sync_device () );
473 TEUCHOS_ASSERT( ! this->
TransferData_->exportLIDs_.need_sync_host () );
478 template <
class LO,
class GO,
class NT>
479 struct ImportLocalSetupResult
481 Teuchos::RCP<const ::Tpetra::Map<LO, GO, NT> > targetMap;
485 std::vector<GO> remoteGIDs;
486 std::vector<LO> remoteLIDs;
487 std::vector<int> remotePIDs;
492 void printArray (std::ostream& out,
const T x[],
const std::size_t N)
495 for (std::size_t k = 0; k < N; ++k) {
504 template<
class LO,
class GO,
class NT>
505 ImportLocalSetupResult<LO, GO, NT>
506 setupSamePermuteRemoteFromUserGlobalIndexList (const ::Tpetra::Map<LO, GO, NT>& sourceMap,
507 const GO targetMapRemoteOrPermuteGlobalIndices[],
508 const int targetMapRemoteOrPermuteProcessRanks[],
509 const LO numTargetMapRemoteOrPermuteGlobalIndices,
510 const bool mayReorderTargetMapIndicesLocally,
511 Teuchos::FancyOStream* out,
512 const std::string* verboseHeader,
517 const int myRank = sourceMap.getComm ()->getRank ();
518 ImportLocalSetupResult<LO, GO, NT> result;
521 std::ostringstream os;
522 os << *verboseHeader <<
"- Import::setupSPR w/ remote GIDs & PIDs: " << endl
523 << *verboseHeader <<
" Input GIDs: ";
524 printArray (os, targetMapRemoteOrPermuteGlobalIndices, numTargetMapRemoteOrPermuteGlobalIndices);
525 os << endl <<
" Input PIDs: ";
526 printArray (os, targetMapRemoteOrPermuteProcessRanks, numTargetMapRemoteOrPermuteGlobalIndices);
536 std::vector<GO> badGIDs;
537 std::vector<int> badPIDs;
538 const Teuchos::Comm<int>& comm = * (sourceMap.getComm ());
539 const int numProcs = comm.getSize ();
541 for (LO k = 0; k < numTargetMapRemoteOrPermuteGlobalIndices; ++k) {
542 const GO tgtGID = targetMapRemoteOrPermuteGlobalIndices[k];
543 if (sourceMap.isNodeGlobalElement (tgtGID)) {
544 badGIDs.push_back (tgtGID);
546 const int tgtPID = targetMapRemoteOrPermuteProcessRanks[k];
547 if (tgtPID < 0 || tgtPID >= numProcs) {
548 badPIDs.push_back (tgtPID);
552 std::array<int, 2> lclStatus {{
553 badGIDs.size () == 0 ? 1 : 0,
554 badPIDs.size () == 0 ? 1 : 0
556 std::array<int, 2> gblStatus {{0, 0}};
557 Teuchos::reduceAll<int, int> (comm, Teuchos::REDUCE_MIN, 2,
558 lclStatus.data (), gblStatus.data ());
559 const bool good = gblStatus[0] == 1 && gblStatus[1] == 1;
562 if (verbose && gblStatus[0] != 1) {
563 std::ostringstream os;
564 os << *verboseHeader <<
"- Some input GIDs are already in the source Map: ";
565 printArray (os, badGIDs.data (), badGIDs.size ());
569 if (verbose && gblStatus[0] != 1) {
570 std::ostringstream os;
571 os << *verboseHeader <<
"- Some input PIDs are invalid: ";
572 printArray (os, badPIDs.data (), badPIDs.size ());
578 std::ostringstream os;
579 os <<
"Tpetra::Import constructor that takes remote GIDs and PIDs: ";
580 if (gblStatus[0] != 1) {
581 os <<
"Some input GIDs (global indices) are already in the source Map! ";
583 if (gblStatus[1] != 1) {
584 os <<
"Some input PIDs (process ranks) are invalid! ";
586 os <<
"Rerun with the environment variable TPETRA_VERBOSE=Tpetra::Import "
587 "to see what GIDs and/or PIDs are bad.";
588 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument, os.str ());
595 const LO numLclSrcIDs =
static_cast<LO
> (sourceMap.getLocalNumElements ());
596 const LO numLclTgtIDs = numLclSrcIDs + numTargetMapRemoteOrPermuteGlobalIndices;
598 std::ostringstream os;
599 os << *verboseHeader <<
"- Copy source Map GIDs into target Map GID list: "
600 "numLclSrcIDs=" << numLclSrcIDs
601 <<
", numTargetMapRemoteOrPermuteGlobalIndices="
602 << numTargetMapRemoteOrPermuteGlobalIndices << endl;
605 std::vector<GO> tgtGIDs (numLclTgtIDs);
606 if (sourceMap.isContiguous ()) {
607 GO curTgtGID = sourceMap.getMinGlobalIndex ();
608 for (LO k = 0; k < numLclSrcIDs; ++k, ++curTgtGID) {
609 tgtGIDs[k] = curTgtGID;
613 auto srcGIDs = sourceMap.getLocalElementList ();
614 for (LO k = 0; k < numLclSrcIDs; ++k) {
615 tgtGIDs[k] = srcGIDs[k];
618 std::copy (targetMapRemoteOrPermuteGlobalIndices,
619 targetMapRemoteOrPermuteGlobalIndices + numTargetMapRemoteOrPermuteGlobalIndices,
620 tgtGIDs.begin () + numLclSrcIDs);
633 std::ostringstream os;
634 os << *verboseHeader <<
"- Sort by PID? "
635 << (mayReorderTargetMapIndicesLocally ?
"true" :
"false") << endl;
638 std::vector<int> tgtPIDs (targetMapRemoteOrPermuteProcessRanks,
639 targetMapRemoteOrPermuteProcessRanks + numTargetMapRemoteOrPermuteGlobalIndices);
640 result.numPermutes = 0;
641 if (mayReorderTargetMapIndicesLocally) {
642 Tpetra::sort2 (tgtPIDs.begin (), tgtPIDs.end (), tgtGIDs.begin () + numLclSrcIDs);
643 auto range = std::equal_range (tgtPIDs.begin (), tgtPIDs.end (), myRank);
644 if (range.second > range.first) {
645 result.numPermutes =
static_cast<LO
> (range.second - range.first);
649 result.numPermutes =
static_cast<LO
> (std::count (tgtPIDs.begin (), tgtPIDs.end (), myRank));
652 const LO numRemotes = numTargetMapRemoteOrPermuteGlobalIndices - result.numPermutes;
653 result.numSameIDs =
static_cast<LO
> (sourceMap.getLocalNumElements ());
656 std::ostringstream os;
657 os << *verboseHeader <<
"- numSame=" << result.numSameIDs
658 <<
", numPermutes=" << result.numPermutes
659 <<
", numRemotes=" << numRemotes << endl;
663 if (result.numPermutes == 0) {
665 std::ostringstream os;
666 os << *verboseHeader <<
"- No permutes" << endl;
669 result.remoteGIDs = std::vector<GO> (tgtGIDs.begin () + numLclSrcIDs, tgtGIDs.end ());
670 result.remotePIDs.swap (tgtPIDs);
671 result.remoteLIDs.resize (numRemotes);
672 for (LO k = 0; k < numRemotes; ++k) {
673 const LO tgtLid = result.numSameIDs + k;
674 result.remoteLIDs[k] = tgtLid;
677 std::ostringstream os;
678 os << *verboseHeader <<
"- Remote GIDs: "
679 << Teuchos::toString (result.remoteGIDs) << endl;
680 os << *verboseHeader <<
"- Remote PIDs: "
681 << Teuchos::toString (result.remotePIDs) << endl;
682 os << *verboseHeader <<
"- Remote LIDs: "
683 << Teuchos::toString (result.remoteLIDs) << endl;
691 result.remoteGIDs.reserve (numRemotes);
692 result.remoteLIDs.reserve (numRemotes);
693 result.remotePIDs.reserve (numRemotes);
694 for (LO k = 0; k < numTargetMapRemoteOrPermuteGlobalIndices; ++k) {
695 const LO tgtLid = result.numSameIDs + k;
696 const GO tgtGid = tgtGIDs[numLclSrcIDs + k];
697 const int tgtPid = tgtPIDs[k];
699 if (tgtPid != myRank) {
700 result.remoteGIDs.push_back (tgtGid);
701 result.remoteLIDs.push_back (tgtLid);
702 result.remotePIDs.push_back (tgtPid);
706 std::ostringstream os;
707 os << *verboseHeader <<
"- Some permutes" << endl;
712 if (sourceMap.isDistributed ()) {
714 std::ostringstream os;
715 os << *verboseHeader <<
"- Sort remotes by PID, as Import always does"
717 << *verboseHeader <<
"-- remotePIDs before: "
718 << Teuchos::toString (result.remotePIDs) << endl
719 << *verboseHeader <<
"-- remoteGIDs before: "
720 << Teuchos::toString (result.remoteGIDs) << endl
721 << *verboseHeader <<
"-- remoteLIDs before: "
722 << Teuchos::toString (result.remoteLIDs) << endl;
726 sort3 (result.remotePIDs.begin (),
727 result.remotePIDs.end (),
728 result.remoteGIDs.begin (),
729 result.remoteLIDs.begin ());
731 std::ostringstream os;
732 os << *verboseHeader <<
"-- remotePIDs after: "
733 << Teuchos::toString (result.remotePIDs) << endl
734 << *verboseHeader <<
"-- remoteGIDs after: "
735 << Teuchos::toString (result.remoteGIDs) << endl
736 << *verboseHeader <<
"-- remoteLIDs after: "
737 << Teuchos::toString (result.remoteLIDs) << endl;
738 std::cerr << os.str ();
743 std::ostringstream os;
744 os << *verboseHeader <<
"- Make target Map" << endl;
747 using ::Teuchos::rcp;
748 typedef ::Tpetra::Map<LO, GO, NT> map_type;
750 const GST MAP_COMPUTES_GLOBAL_COUNT = ::Teuchos::OrdinalTraits<GST>::invalid ();
751 result.targetMap = rcp (
new map_type (MAP_COMPUTES_GLOBAL_COUNT,
754 sourceMap.getIndexBase (),
755 sourceMap.getComm ()));
757 std::ostringstream os;
758 os << *verboseHeader <<
"- Done with sameSPR..." << endl;
765 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
772 const Teuchos::RCP<Teuchos::ParameterList>&
plist,
773 const Teuchos::RCP<Teuchos::FancyOStream>&
debugOutput) :
779 using ::Tpetra::Details::Behavior;
780 using ::Tpetra::Details::makeDualViewFromOwningHostView;
781 using ::Tpetra::Details::makeDualViewFromVector;
782 using ::Tpetra::Details::printDualView;
783 using ::Tpetra::Details::view_alloc_no_init;
784 using Teuchos::ArrayView;
785 using Teuchos::getFancyOStream;
788 using Teuchos::rcpFromRef;
794 const bool debug = Behavior::debug (
"Import") ||
795 Behavior::debug (
"Tpetra::Import");
797 std::unique_ptr<std::string>
verbPfx;
798 if (this->verbose ()) {
799 std::ostringstream
os;
801 os <<
"Proc " <<
myRank <<
": Tpetra::Import ctor from remotes: ";
802 verbPfx = std::unique_ptr<std::string> (
new std::string (
os.str ()));
828 this->TransferData_->out_,
830 this->
TransferData_->numSameIDs_ = localSetupResult.numSameIDs;
834 localSetupResult.remoteLIDs,
847 if (this->verbose ()) {
848 std::ostringstream
os;
849 os << *
verbPfx <<
"Make Distributor (createFromRecvs)" <<
endl;
873 if (this->verbose ()) {
874 std::ostringstream
os;
878 using size_type =
typename Teuchos::Array<GO>::size_type;
887 makeDualViewFromOwningHostView (this->
TransferData_->exportLIDs_, exportLIDs);
890 if (this->verbose ()) {
891 std::ostringstream
os;
894 "ImportExportData::remoteLIDs_");
898 if (this->verbose ()) {
899 std::ostringstream
os;
905 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
909 const Teuchos::EVerbosityLevel
verbLevel)
const
915 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
919 auto out = Teuchos::getFancyOStream (Teuchos::rcpFromRef (
os));
921 this->describe (*
out, Teuchos::VERB_EXTREME);
924 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
929 using ::Tpetra::Details::makeDualViewFromOwningHostView;
930 using ::Tpetra::Details::ProfilingRegion;
931 using ::Tpetra::Details::view_alloc_no_init;
933 using Teuchos::Array;
934 using Teuchos::ArrayRCP;
935 using Teuchos::ArrayView;
941 ProfilingRegion
regionExport (
"Tpetra::Import::setupSamePermuteRemote");
943 const map_type&
source = * (this->getSourceMap ());
944 const map_type&
target = * (this->getTargetMap ());
948#ifdef HAVE_TPETRA_DEBUG
968 this->TransferData_->numSameIDs_ = numSameGids;
982 const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid ();
983 const LO numTgtLids = as<LO> (numTgtGids);
986 for (LO tgtLid = numSameGids; tgtLid < numTgtLids; ++tgtLid) {
987 const GO curTargetGid = rawTgtGids[tgtLid];
991 const LO srcLid = source.getLocalElement (curTargetGid);
992 if (srcLid != LINVALID) {
996 const LO numRemotes = (numTgtLids - numSameGids) - numPermutes;
998 using host_perm_type =
999 typename decltype (this->TransferData_->permuteToLIDs_)::t_host;
1000 host_perm_type permuteToLIDs
1001 (view_alloc_no_init (
"permuteToLIDs"), numPermutes);
1002 host_perm_type permuteFromLIDs
1003 (view_alloc_no_init (
"permuteFromLIDs"), numPermutes);
1004 typename decltype (this->TransferData_->remoteLIDs_)::t_host remoteLIDs
1005 (view_alloc_no_init (
"permuteFromLIDs"), numRemotes);
1008 LO numPermutes2 = 0;
1010 for (LO tgtLid = numSameGids; tgtLid < numTgtLids; ++tgtLid) {
1011 const GO curTargetGid = rawTgtGids[tgtLid];
1012 const LO srcLid = source.getLocalElement (curTargetGid);
1013 if (srcLid != LINVALID) {
1014 permuteToLIDs[numPermutes2] = tgtLid;
1015 permuteFromLIDs[numPermutes2] = srcLid;
1019 remoteGIDs.push_back (curTargetGid);
1020 remoteLIDs[numRemotes2] = tgtLid;
1024 TEUCHOS_ASSERT( numPermutes == numPermutes2 );
1025 TEUCHOS_ASSERT( numRemotes == numRemotes2 );
1026 TEUCHOS_ASSERT(
size_t (numPermutes) + remoteGIDs.size () == size_t (numTgtLids - numSameGids) );
1032 if (remoteLIDs.extent (0) != 0 && ! source.isDistributed ()) {
1038 this->TransferData_->isLocallyComplete_ =
false;
1042 (
true, std::runtime_error,
"::setupSamePermuteRemote(): Target has "
1043 "remote LIDs but Source is not distributed globally. Importing to a "
1044 "submap of the target map.");
1049 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1050 void Import<LocalOrdinal,GlobalOrdinal,Node>::
1051 setupExport (Teuchos::Array<GlobalOrdinal>& remoteGIDs,
1053 Teuchos::Array<int>& userRemotePIDs,
1054 const Teuchos::RCP<Teuchos::ParameterList>& plist)
1056 using ::Tpetra::Details::makeDualViewFromOwningHostView;
1057 using ::Tpetra::Details::view_alloc_no_init;
1058 using Teuchos::Array;
1059 using Teuchos::ArrayView;
1061 using GO = GlobalOrdinal;
1062 typedef typename Array<int>::difference_type size_type;
1063 const char tfecfFuncName[] =
"setupExport: ";
1064 const char suffix[] =
" Please report this bug to the Tpetra developers.";
1066 std::unique_ptr<std::string> prefix;
1067 if (this->verbose ()) {
1068 auto srcMap = this->getSourceMap ();
1069 auto comm = srcMap.is_null () ? Teuchos::null : srcMap->getComm ();
1070 const int myRank = comm.is_null () ? -1 : comm->getRank ();
1071 std::ostringstream os;
1072 os <<
"Proc " << myRank <<
": Tpetra::Import::setupExport: ";
1073 prefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
1074 os <<
"Start" << std::endl;
1075 this->verboseOutputStream () << os.str ();
1078 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1079 (this->getSourceMap ().is_null (), std::logic_error,
1080 "Source Map is null. " << suffix);
1081 const map_type& source = * (this->getSourceMap ());
1083 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1084 (! useRemotePIDs && (userRemotePIDs.size() > 0), std::invalid_argument,
1085 "remotePIDs are non-empty but their use has not been requested.");
1086 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1087 (userRemotePIDs.size () > 0 && remoteGIDs.size () != userRemotePIDs.size (),
1088 std::invalid_argument,
"remotePIDs must either be of size zero or match "
1089 "the size of remoteGIDs.");
1093 ArrayView<GO> remoteGIDsView = remoteGIDs ();
1094 ArrayView<int> remoteProcIDsView;
1114 Array<int> newRemotePIDs;
1117 if (! useRemotePIDs) {
1118 newRemotePIDs.resize (remoteGIDsView.size ());
1119 if (this->verbose ()) {
1120 std::ostringstream os;
1121 os << *prefix <<
"Call sourceMap.getRemoteIndexList" << endl;
1122 this->verboseOutputStream () << os.str ();
1124 lookup = source.getRemoteIndexList (remoteGIDsView, newRemotePIDs ());
1126 Array<int>& remoteProcIDs = useRemotePIDs ? userRemotePIDs : newRemotePIDs;
1132 this->TransferData_->isLocallyComplete_ =
false;
1137 (
true, std::runtime_error,
"::setupExport(): the source Map wasn't "
1138 "able to figure out which process owns one or more of the GIDs in the "
1139 "list of remote GIDs. This probably means that there is at least one "
1140 "GID owned by some process in the target Map which is not owned by any"
1141 " process in the source Map. (That is, the source and target Maps do "
1142 "not contain the same set of GIDs globally.)");
1148 const size_type numInvalidRemote =
1149 std::count_if (remoteProcIDs.begin (), remoteProcIDs.end (),
1150 std::bind (std::equal_to<int> (), -1, std::placeholders::_1));
1151 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1152 (numInvalidRemote == 0, std::logic_error,
"Calling getRemoteIndexList "
1153 "on the source Map returned IDNotPresent, but none of the returned "
1154 "\"remote\" process ranks are -1. Please report this bug to the "
1155 "Tpetra developers.");
1157#ifdef HAVE_TPETRA_MMM_TIMINGS
1158 using Teuchos::TimeMonitor;
1160 if(!plist.is_null())
1161 label = plist->get(
"Timer Label",label);
1162 std::string prefix = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:setupExport:1 ");
1163 auto MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix)));
1169 const size_type totalNumRemote = this->getNumRemoteIDs ();
1170 if (numInvalidRemote == totalNumRemote) {
1172 remoteProcIDs.clear ();
1173 remoteGIDs.clear ();
1174 this->TransferData_->remoteLIDs_ =
1175 decltype (this->TransferData_->remoteLIDs_) ();
1180 size_type numValidRemote = 0;
1181#ifdef HAVE_TPETRA_DEBUG
1182 ArrayView<GO> remoteGIDsPtr = remoteGIDsView;
1184 GO*
const remoteGIDsPtr = remoteGIDsView.getRawPtr ();
1188 auto remoteLIDs = this->TransferData_->remoteLIDs_.view_host ();
1190 for (size_type r = 0; r < totalNumRemote; ++r) {
1192 if (remoteProcIDs[r] != -1) {
1193 remoteProcIDs[numValidRemote] = remoteProcIDs[r];
1194 remoteGIDsPtr[numValidRemote] = remoteGIDsPtr[r];
1195 remoteLIDs[numValidRemote] = remoteLIDs[r];
1199 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1200 (numValidRemote != totalNumRemote - numInvalidRemote,
1201 std::logic_error,
"After removing invalid remote GIDs and packing "
1202 "the valid remote GIDs, numValidRemote = " << numValidRemote
1203 <<
" != totalNumRemote - numInvalidRemote = "
1204 << totalNumRemote - numInvalidRemote
1205 <<
". Please report this bug to the Tpetra developers.");
1207 remoteProcIDs.resize (numValidRemote);
1208 remoteGIDs.resize (numValidRemote);
1210 Kokkos::resize (remoteLIDs, numValidRemote);
1211 this->TransferData_->remoteLIDs_ =
decltype (this->TransferData_->remoteLIDs_) ();
1215 remoteGIDsView = remoteGIDs ();
1223 this->TransferData_->remoteLIDs_.modify_host ();
1224 auto remoteLIDs = this->TransferData_->remoteLIDs_.view_host ();
1225 sort3 (remoteProcIDs.begin (),
1226 remoteProcIDs.end (),
1227 remoteGIDsView.getRawPtr (),
1228 remoteLIDs.data ());
1229 this->TransferData_->remoteLIDs_.sync_device ();
1237 Array<GO> exportGIDs;
1239#ifdef HAVE_TPETRA_MMM_TIMINGS
1240 using Teuchos::TimeMonitor;
1242 if(!plist.is_null())
1243 label = plist->get(
"Timer Label",label);
1244 std::string prefix2 = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:setupExport:3 ");
1245 auto MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2)));
1248 if (this->verbose ()) {
1249 std::ostringstream os;
1250 os << *prefix <<
"Call createFromRecvs" << endl;
1251 this->verboseOutputStream () << endl;
1253 this->TransferData_->distributor_.createFromRecvs (remoteGIDsView ().getConst (),
1254 remoteProcIDs, exportGIDs,
1255 this->TransferData_->exportPIDs_);
1261#ifdef HAVE_TPETRA_MMM_TIMINGS
1262 prefix2 = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:setupExport:4 ");
1263 MM = Teuchos::null; MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2)));
1269 const size_type numExportIDs = exportGIDs.size ();
1270 if (numExportIDs > 0) {
1271 typename decltype (this->TransferData_->exportLIDs_)::t_host
1272 exportLIDs (view_alloc_no_init (
"exportLIDs"), numExportIDs);
1273 ArrayView<const GO> expGIDs = exportGIDs ();
1275 for (size_type k = 0; k < numExportIDs; ++k) {
1276 exportLIDs[k] = source.getLocalElement (expGIDs[k]);
1281 if (this->verbose ()) {
1282 std::ostringstream os;
1283 os << *prefix <<
"Done!" << endl;
1284 this->verboseOutputStream () << os.str ();
1288 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1292 Teuchos::Array<std::pair<int,GlobalOrdinal>>&
remotePGIDs,
1293 typename Teuchos::Array<GlobalOrdinal>::size_type&
numSameGIDs,
1294 typename Teuchos::Array<GlobalOrdinal>::size_type&
numPermuteGIDs,
1295 typename Teuchos::Array<GlobalOrdinal>::size_type&
numRemoteGIDs,
1296 const Teuchos::ArrayView<const GlobalOrdinal>&
sameGIDs1,
1297 const Teuchos::ArrayView<const GlobalOrdinal>&
sameGIDs2,
1307 typedef typename Teuchos::Array<GO>::size_type size_type;
1393 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1394 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
1398 using ::Tpetra::Details::Behavior;
1399 using Teuchos::Array;
1400 using Teuchos::ArrayView;
1402 using Teuchos::Comm;
1405 using Teuchos::outArg;
1406 using Teuchos::REDUCE_MIN;
1407 using Teuchos::reduceAll;
1414#ifdef HAVE_TPETRA_MMM_TIMINGS
1415 using Teuchos::TimeMonitor;
1416 std::string label = std::string(
"Tpetra::Import::setUnion");
1425 const bool debug = Behavior::debug (
"Import::setUnion") ||
1426 Behavior::debug (
"Tpetra::Import::setUnion");
1430 (!
srcMap->isSameAs (* (
rhs.getSourceMap ())), std::invalid_argument,
1431 "Tpetra::Import::setUnion: The source Map of the input Import must be the "
1432 "same as (in the sense of Map::isSameAs) the source Map of this Import.");
1437 std::invalid_argument,
"Tpetra::Import::setUnion: "
1438 "The target Maps must have congruent communicators.");
1445 return rcp (
new import_type (*
this));
1483 Tpetra::Import_Util::getRemotePIDs(*
this,
remotePIDs1);
1520#ifdef HAVE_TPETRA_MMM_TIMINGS
1521 MM.disableTimer(label);
1522 label =
"Tpetra::Import::setUnion : Construct Target Map";
1527 const GST INVALID = Teuchos::OrdinalTraits<GST>::invalid ();
1532#ifdef HAVE_TPETRA_MMM_TIMINGS
1533 MM2.disableTimer(label);
1534 label =
"Tpetra::Import::setUnion : Export GIDs";
1551#ifdef TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1635#ifdef HAVE_TPETRA_MMM_TIMINGS
1636 MM3.disableTimer(label);
1637 label =
"Tpetra::Import::setUnion : Construct Import";
1646 this->TransferData_->out_));
1650 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1651 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
1655 using Teuchos::Array;
1656 using Teuchos::ArrayView;
1658 using Teuchos::Comm;
1661 using Teuchos::outArg;
1662 using Teuchos::REDUCE_MIN;
1663 using Teuchos::reduceAll;
1666 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
unionImport;
1696 GO
GO_INVALID = Teuchos::OrdinalTraits<GO>::invalid();
1721 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1722 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
1726 using ::Tpetra::Details::Behavior;
1727 using ::Tpetra::Details::gathervPrint;
1728 using Teuchos::outArg;
1730 using Teuchos::REDUCE_MIN;
1731 using Teuchos::reduceAll;
1737 const char funcPrefix[] =
"Tpetra::createRemoteOnlyImport: ";
1740 const bool debug = Behavior::debug ();
1742 const size_t NumRemotes = this->getNumRemoteIDs ();
1744 Teuchos::RCP<const Teuchos::Comm<int>> comm;
1748 std::ostringstream
os;
1750 if (comm.is_null ()) {
1754 os << comm->getRank ();
1757 procPrefix = std::unique_ptr<std::string> (
new std::string (
os.str ()));
1761 std::ostringstream
lclErr;
1768 <<
" != remoteTarget->getLocalNumElements() = "
1772 if (comm.is_null ()) {
1780 <<
"Input target Map is null on at least one process.");
1783 if (comm.is_null ()) {
1785 (
true, std::runtime_error,
lclErr.str ());
1788 std::ostringstream
gblErr;
1792 (
true, std::runtime_error,
gblErr.str ());
1798 Teuchos::ArrayView<const LO>
oldRemoteLIDs = this->getRemoteLIDs ();
1803 std::unique_ptr<std::vector<size_t>>
badIndices;
1805 badIndices = std::unique_ptr<std::vector<size_t>> (
new std::vector<size_t>);
1810 if (
oldLclInd == Teuchos::OrdinalTraits<LO>::invalid ()) {
1816 if (
gblInd == Teuchos::OrdinalTraits<GO>::invalid ()) {
1822 if (
newLclInd == Teuchos::OrdinalTraits<LO>::invalid ()) {
1840 if (comm.is_null ()) {
1846 std::ostringstream
lclErr;
1849 <<
", bad indices: [";
1853 const size_t badIndex = (*badIndices)[
k];
1864 std::ostringstream
gblErr;
1866 "indices on one or more processes. \"Bad\" means that the "
1867 "indices are invalid, they don't exist in the target Map, "
1868 "they don't exist in remoteTarget, or they are not in "
1869 "sorted order. In what follows, I will show the \"bad\" "
1870 "indices as (k, LID) pairs, where k is the zero-based "
1871 "index of the LID in this->getRemoteLIDs()." <<
endl;
1872 if (comm.is_null ()) {
1879 (
true, std::runtime_error,
gblErr.str ());
1885 <<
"this->getRemoteLIDs() has " <<
badCount
1886 <<
"ind" << (
badCount == 1 ?
"ex" :
"ices")
1887 <<
" \"bad\" indices on this process." <<
endl);
1897 Teuchos::Array<LO>
dummy;
1908#define TPETRA_IMPORT_CLASS_INSTANT(LO, GO, NODE) \
1909 template class Import< LO , GO , NODE >;
1918#define TPETRA_IMPORT_INSTANT(LO, GO, NODE) \
1919 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 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.