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>
188 Import (
const Teuchos::RCP<const map_type >& source,
189 const Teuchos::RCP<const map_type >& target) :
190 base_type (source, target, Teuchos::null, Teuchos::null,
"Import")
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");
196 init(source, target,
false, dummy, mypars);
198 init (source, target,
false, dummy, Teuchos::null);
202 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
204 Import (
const Teuchos::RCP<const map_type>& source,
205 const Teuchos::RCP<const map_type>& target,
206 const Teuchos::RCP<Teuchos::FancyOStream>& out) :
207 base_type (source, target, out, Teuchos::null,
"Import")
209 Teuchos::Array<int> dummy;
210 init (source, target,
false, dummy, Teuchos::null);
213 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
215 Import (
const Teuchos::RCP<const map_type>& source,
216 const Teuchos::RCP<const map_type>& target,
217 const Teuchos::RCP<Teuchos::ParameterList>& plist) :
218 base_type (source, target, Teuchos::null, plist,
"Import")
220 Teuchos::Array<int> dummy;
221 init (source, target,
false, dummy, plist);
224 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
226 Import (
const Teuchos::RCP<const map_type>& source,
227 const Teuchos::RCP<const map_type>& target,
228 const Teuchos::RCP<Teuchos::FancyOStream>& out,
229 const Teuchos::RCP<Teuchos::ParameterList>& plist) :
230 base_type (source, target, out, plist,
"Import")
232 Teuchos::Array<int> dummy;
233 init (source, target,
false, dummy, plist);
236 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
238 Import (
const Teuchos::RCP<const map_type>& source,
239 const Teuchos::RCP<const map_type>& target,
240 Teuchos::Array<int>& remotePIDs,
241 const Teuchos::RCP<Teuchos::ParameterList>& plist) :
242 base_type (source, target, Teuchos::null, plist,
"Import")
244 init (source, target,
true, remotePIDs, 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>
266 const Teuchos::ArrayView<int> & userRemotePIDs,
267 const Teuchos::ArrayView<const LocalOrdinal> & userExportLIDs,
268 const Teuchos::ArrayView<const int> & userExportPIDs,
269 const Teuchos::RCP<Teuchos::ParameterList>& plist,
270 const Teuchos::RCP<Teuchos::FancyOStream>& out) :
271 base_type (source, target, out, plist,
"Import")
273 using ::Tpetra::Details::makeDualViewFromArrayView;
275 using Teuchos::Array;
276 using Teuchos::ArrayRCP;
277 using Teuchos::ArrayView;
282 using LO = LocalOrdinal;
283 using GO = GlobalOrdinal;
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 ()));
293 os <<
"Start" << endl;
297 ArrayView<const GO> sourceGIDs = source->getLocalElementList ();
298 ArrayView<const GO> targetGIDs = target->getLocalElementList ();
300 Array<GO> tRemoteGIDs;
302 std::ostringstream os;
303 os << *prefix <<
"Call setupSamePermuteRemote" << endl;
306 setupSamePermuteRemote (tRemoteGIDs);
309 std::ostringstream os;
310 os << *prefix <<
"Sort & filter IDs" << endl;
314 auto tRemoteLIDs = this->
TransferData_->remoteLIDs_.view_host ();
316 Teuchos::Array<int> tRemotePIDs (userRemotePIDs);
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.");
331 TEUCHOS_TEST_FOR_EXCEPTION
332 (tRemotePIDs.size () != tRemoteGIDs.size () ||
333 size_t (tRemoteGIDs.size ()) !=
size_t (tRemoteLIDs.extent (0)),
334 std::runtime_error,
"Import::Import createExpert version: "
335 "Size mismatch on userRemotePIDs, remoteGIDs, and remoteLIDs "
336 "Array's to sort3.");
338 sort3 (tRemotePIDs.begin (),
340 tRemoteGIDs.begin (),
341 tRemoteLIDs.data ());
345 size_type indexIntoRemotePIDs = tRemotePIDs.size ();
346 for (size_type i = 0; i < indexIntoRemotePIDs; ++i) {
347 if (tRemotePIDs[i] == -1) {
356 if (indexIntoRemotePIDs - cnt > 0) {
357 Array<GO> newRemoteGIDs(indexIntoRemotePIDs-cnt);
358 Array<LO> newRemoteLIDs(indexIntoRemotePIDs-cnt);
359 Array<int> newRemotePIDs(indexIntoRemotePIDs-cnt);
362 for (size_type j = 0; j < indexIntoRemotePIDs; ++j)
363 if(tRemotePIDs[j] != -1) {
364 newRemoteGIDs[cnt] = tRemoteGIDs[j];
365 newRemotePIDs[cnt] = tRemotePIDs[j];
366 newRemoteLIDs[cnt] = target->getLocalElement(tRemoteGIDs[j]);
369 indexIntoRemotePIDs = cnt;
370 tRemoteGIDs = newRemoteGIDs;
371 tRemotePIDs = newRemotePIDs;
373 newRemoteLIDs ().getConst (),
377 indexIntoRemotePIDs = 0;
384 this->
TransferData_->exportPIDs_ = Teuchos::Array<int> (userExportPIDs);
386 userExportLIDs,
"exportLIDs");
388 bool locallyComplete =
true;
389 for (size_type i = 0; i < userExportPIDs.size () && locallyComplete; ++i) {
390 if (userExportPIDs[i] == -1) {
391 locallyComplete =
false;
397 std::ostringstream os;
398 os << *prefix <<
"locallyComplete: "
399 << (locallyComplete ?
"true" :
"false")
400 <<
"; call createFromSendsAndRecvs" << endl;
404 #ifdef HAVE_TPETRA_MMM_TIMINGS
405 std::string mmm_prefix =
406 std::string(
"Tpetra ") + std::string(
":iport_ctor:cFSAR ");
408 auto MM3(*Teuchos::TimeMonitor::getNewTimer(mmm_prefix));
414 this->detectRemoteExportLIDsContiguous();
416 TEUCHOS_ASSERT( ! this->
TransferData_->permuteFromLIDs_.need_sync_device () );
417 TEUCHOS_ASSERT( ! this->
TransferData_->permuteFromLIDs_.need_sync_host () );
418 TEUCHOS_ASSERT( ! this->
TransferData_->permuteToLIDs_.need_sync_device () );
419 TEUCHOS_ASSERT( ! this->
TransferData_->permuteToLIDs_.need_sync_host () );
420 TEUCHOS_ASSERT( ! this->
TransferData_->remoteLIDs_.need_sync_device () );
421 TEUCHOS_ASSERT( ! this->
TransferData_->remoteLIDs_.need_sync_host () );
422 TEUCHOS_ASSERT( ! this->
TransferData_->exportLIDs_.need_sync_device () );
423 TEUCHOS_ASSERT( ! this->
TransferData_->exportLIDs_.need_sync_host () );
426 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
428 Import (
const Teuchos::RCP<const map_type>& source,
429 const Teuchos::RCP<const map_type>& target,
430 const size_t numSameIDs,
431 Teuchos::Array<LocalOrdinal>& permuteToLIDs,
432 Teuchos::Array<LocalOrdinal>& permuteFromLIDs,
433 Teuchos::Array<LocalOrdinal>& remoteLIDs,
434 Teuchos::Array<LocalOrdinal>& exportLIDs,
435 Teuchos::Array<int>& exportPIDs,
437 const Teuchos::RCP<Teuchos::FancyOStream>& out,
438 const Teuchos::RCP<Teuchos::ParameterList>& plist) :
439 base_type (source, target, out, plist,
"Import")
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 ()));
451 os <<
"Start" << endl;
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 ());
597 ::Tpetra::Details::gathervPrint (*out, os.str (), comm);
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 ());
604 ::Tpetra::Details::gathervPrint (*out, os.str (), comm);
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;
779 typedef ::Tpetra::global_size_t GST;
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>
798 const GlobalOrdinal targetMapRemoteOrPermuteGlobalIndices[],
799 const int targetMapRemoteOrPermuteProcessRanks[],
800 const LocalOrdinal numTargetMapRemoteOrPermuteGlobalIndices,
801 const bool mayReorderTargetMapIndicesLocally,
802 const Teuchos::RCP<Teuchos::ParameterList>& plist,
803 const Teuchos::RCP<Teuchos::FancyOStream>& debugOutput) :
807 base_type (sourceMap, Teuchos::null, debugOutput, plist,
"Import")
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;
820 typedef LocalOrdinal LO;
821 typedef GlobalOrdinal GO;
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;
830 const int myRank = sourceMap->getComm ()->getRank ();
831 os <<
"Proc " << myRank <<
": Tpetra::Import ctor from remotes: ";
832 verbPfx = std::unique_ptr<std::string> (
new std::string (os.str ()));
833 os <<
"mayReorder=" << (mayReorderTargetMapIndicesLocally ?
"true" :
"false")
839 ImportLocalSetupResult<LO, GO, NT> localSetupResult =
840 setupSamePermuteRemoteFromUserGlobalIndexList<LO, GO, NT>
842 targetMapRemoteOrPermuteGlobalIndices,
843 targetMapRemoteOrPermuteProcessRanks,
844 numTargetMapRemoteOrPermuteGlobalIndices,
845 mayReorderTargetMapIndicesLocally,
857 localSetupResult.targetMap,
858 this->TransferData_->out_,
860 this->TransferData_->numSameIDs_ = localSetupResult.numSameIDs;
863 makeDualViewFromVector (this->TransferData_->remoteLIDs_,
864 localSetupResult.remoteLIDs,
873 this->TransferData_->isLocallyComplete_ =
true;
875 Teuchos::Array<GO> exportGIDs;
876 if (sourceMap->isDistributed ()) {
877 if (this->verbose ()) {
878 std::ostringstream os;
879 os << *verbPfx <<
"Make Distributor (createFromRecvs)" << endl;
882 ArrayView<const GO> remoteGIDs (localSetupResult.remoteGIDs.data (),
883 localSetupResult.remoteGIDs.size ());
884 ArrayView<const int> remotePIDs (localSetupResult.remotePIDs.data (),
885 localSetupResult.remotePIDs.size ());
890 Distributor& distributor = this->TransferData_->distributor_;
894 this->TransferData_->exportPIDs_);
903 if (this->verbose ()) {
904 std::ostringstream os;
905 os << *verbPfx <<
"Compute exportLIDs" << endl;
908 using size_type =
typename Teuchos::Array<GO>::size_type;
909 const size_type numExportIDs = exportGIDs.size ();
911 typename decltype (this->TransferData_->exportLIDs_)::t_host
912 exportLIDs (view_alloc_no_init (
"exportLIDs"), numExportIDs);
914 for (size_type k = 0; k < numExportIDs; ++k) {
915 exportLIDs[k] = sourceMap->getLocalElement (exportGIDs[k]);
917 makeDualViewFromOwningHostView (this->TransferData_->exportLIDs_, exportLIDs);
920 if (this->verbose ()) {
921 std::ostringstream os;
923 printDualView (os, this->TransferData_->remoteLIDs_,
924 "ImportExportData::remoteLIDs_");
928 if (this->verbose ()) {
929 std::ostringstream os;
930 os << *verbPfx <<
"Done!" << endl;
935 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
939 const Teuchos::EVerbosityLevel verbLevel)
const
942 this->describeImpl (out,
"Tpetra::Import", verbLevel);
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;
968 typedef LocalOrdinal LO;
969 typedef GlobalOrdinal GO;
970 typedef typename ArrayView<const GO>::size_type size_type;
971 ProfilingRegion regionExport (
"Tpetra::Import::setupSamePermuteRemote");
973 const map_type& source = * (this->getSourceMap ());
974 const map_type& target = * (this->getTargetMap ());
975 ArrayView<const GO> sourceGIDs = source.getLocalElementList ();
976 ArrayView<const GO> targetGIDs = target.getLocalElementList ();
978 #ifdef HAVE_TPETRA_DEBUG
979 ArrayView<const GO> rawSrcGids = sourceGIDs;
980 ArrayView<const GO> rawTgtGids = targetGIDs;
982 const GO*
const rawSrcGids = sourceGIDs.getRawPtr ();
983 const GO*
const rawTgtGids = targetGIDs.getRawPtr ();
984 #endif // HAVE_TPETRA_DEBUG
985 const size_type numSrcGids = sourceGIDs.size ();
986 const size_type numTgtGids = targetGIDs.size ();
987 const size_type numGids = std::min (numSrcGids, numTgtGids);
995 size_type numSameGids = 0;
996 for ( ; numSameGids < numGids && rawSrcGids[numSameGids] == rawTgtGids[numSameGids]; ++numSameGids)
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
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 ();
1215 #endif // HAVE_TPETRA_DEBUG
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
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,
1328 Teuchos::Array<GlobalOrdinal>& permuteGIDs1,
1329 Teuchos::Array<GlobalOrdinal>& permuteGIDs2,
1330 Teuchos::Array<GlobalOrdinal>& remoteGIDs1,
1331 Teuchos::Array<GlobalOrdinal>& remoteGIDs2,
1332 Teuchos::Array<int>& remotePIDs1,
1333 Teuchos::Array<int>& remotePIDs2)
const
1336 typedef GlobalOrdinal GO;
1337 typedef typename Teuchos::Array<GO>::size_type size_type;
1339 const size_type numSameGIDs1 = sameGIDs1.size();
1340 const size_type numSameGIDs2 = sameGIDs2.size();
1343 std::sort(permuteGIDs1.begin(), permuteGIDs1.end());
1344 std::sort(permuteGIDs2.begin(), permuteGIDs2.end());
1349 unionTgtGIDs.reserve(numSameGIDs1 + numSameGIDs2 +
1350 permuteGIDs1.size() + permuteGIDs2.size() +
1351 remoteGIDs1.size() + remoteGIDs2.size());
1355 typename Teuchos::Array<GO>::iterator permuteGIDs1_end;
1356 typename Teuchos::Array<GO>::iterator permuteGIDs2_end;
1357 if (numSameGIDs2 > numSameGIDs1) {
1359 numSameGIDs = numSameGIDs2;
1360 permuteGIDs2_end = permuteGIDs2.end();
1363 std::copy(sameGIDs2.begin(), sameGIDs2.end(), std::back_inserter(unionTgtGIDs));
1367 permuteGIDs1_end = std::set_difference(permuteGIDs1.begin(), permuteGIDs1.end(),
1368 unionTgtGIDs.begin()+numSameGIDs1, unionTgtGIDs.end(),
1369 permuteGIDs1.begin());
1373 numSameGIDs = numSameGIDs1;
1374 permuteGIDs1_end = permuteGIDs1.end();
1377 std::copy(sameGIDs1.begin(), sameGIDs1.end(), std::back_inserter(unionTgtGIDs));
1381 permuteGIDs2_end = std::set_difference(permuteGIDs2.begin(), permuteGIDs2.end(),
1382 unionTgtGIDs.begin()+numSameGIDs2, unionTgtGIDs.end(),
1383 permuteGIDs2.begin());
1388 std::set_union(permuteGIDs1.begin(), permuteGIDs1_end,
1389 permuteGIDs2.begin(), permuteGIDs2_end,
1390 std::back_inserter(unionTgtGIDs));
1393 Teuchos::Array<std::pair<int,GO>> remotePGIDs1(remoteGIDs1.size());
1394 for (size_type k=0; k<remoteGIDs1.size(); k++)
1395 remotePGIDs1[k] = std::make_pair(remotePIDs1[k], remoteGIDs1[k]);
1396 std::sort(remotePGIDs1.begin(), remotePGIDs1.end());
1398 Teuchos::Array<std::pair<int,GO>> remotePGIDs2(remoteGIDs2.size());
1399 for (size_type k=0; k<remoteGIDs2.size(); k++)
1400 remotePGIDs2[k] = std::make_pair(remotePIDs2[k], remoteGIDs2[k]);
1401 std::sort(remotePGIDs2.begin(), remotePGIDs2.end());
1403 remotePGIDs.reserve(remotePGIDs1.size()+remotePGIDs2.size());
1404 std::merge(remotePGIDs1.begin(), remotePGIDs1.end(),
1405 remotePGIDs2.begin(), remotePGIDs2.end(),
1406 std::back_inserter(remotePGIDs));
1407 auto it = std::unique(remotePGIDs.begin(), remotePGIDs.end());
1408 remotePGIDs.resize(std::distance(remotePGIDs.begin(), it));
1411 const size_type oldSize = unionTgtGIDs.size();
1412 unionTgtGIDs.resize(oldSize+remotePGIDs.size());
1413 for (size_type
start=oldSize, k=0; k<remotePGIDs.size(); k++)
1414 unionTgtGIDs[
start+k] = remotePGIDs[k].second;
1417 numRemoteGIDs = remotePGIDs.size();
1418 numPermuteGIDs = unionTgtGIDs.size() - numSameGIDs - numRemoteGIDs;
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;
1439 using LO = LocalOrdinal;
1440 using GO = GlobalOrdinal;
1442 using size_type =
typename Array<GO>::size_type;
1444 #ifdef HAVE_TPETRA_MMM_TIMINGS
1445 using Teuchos::TimeMonitor;
1446 std::string label = std::string(
"Tpetra::Import::setUnion");
1447 TimeMonitor MM(*TimeMonitor::getNewTimer(label));
1450 RCP<const map_type> srcMap = this->getSourceMap ();
1451 RCP<const map_type> tgtMap1 = this->getTargetMap ();
1453 RCP<const Comm<int> > comm = srcMap->getComm ();
1455 const bool debug = Behavior::debug (
"Import::setUnion") ||
1456 Behavior::debug (
"Tpetra::Import::setUnion");
1459 TEUCHOS_TEST_FOR_EXCEPTION
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.");
1463 const Comm<int>& comm1 = * (tgtMap1->getComm ());
1464 const Comm<int>& comm2 = * (tgtMap2->getComm ());
1465 TEUCHOS_TEST_FOR_EXCEPTION
1467 std::invalid_argument,
"Tpetra::Import::setUnion: "
1468 "The target Maps must have congruent communicators.");
1474 if (tgtMap1->isSameAs (*tgtMap2)) {
1475 return rcp (
new import_type (*
this));
1483 const size_type numSameGIDs1 = this->getNumSameIDs();
1484 ArrayView<const GO> sameGIDs1 = (tgtMap1->getLocalElementList())(0,numSameGIDs1);
1487 ArrayView<const GO> sameGIDs2 = (tgtMap2->getLocalElementList())(0,numSameGIDs2);
1490 ArrayView<const LO> permuteToLIDs1 = this->getPermuteToLIDs();
1491 Array<GO> permuteGIDs1(permuteToLIDs1.size());
1492 for (size_type k=0; k<permuteGIDs1.size(); k++)
1493 permuteGIDs1[k] = tgtMap1->getGlobalElement(permuteToLIDs1[k]);
1496 Array<GO> permuteGIDs2(permuteToLIDs2.size());
1497 for (size_type k=0; k<permuteGIDs2.size(); k++)
1498 permuteGIDs2[k] = tgtMap2->getGlobalElement(permuteToLIDs2[k]);
1501 ArrayView<const LO> remoteLIDs1 = this->getRemoteLIDs();
1502 Array<GO> remoteGIDs1(remoteLIDs1.size());
1503 for (size_type k=0; k<remoteLIDs1.size(); k++)
1504 remoteGIDs1[k] = this->getTargetMap()->getGlobalElement(remoteLIDs1[k]);
1507 Array<GO> remoteGIDs2(remoteLIDs2.size());
1508 for (size_type k=0; k<remoteLIDs2.size(); k++)
1509 remoteGIDs2[k] = rhs.
getTargetMap()->getGlobalElement(remoteLIDs2[k]);
1512 Array<int> remotePIDs1;
1513 Tpetra::Import_Util::getRemotePIDs(*
this, remotePIDs1);
1515 Array<int> remotePIDs2;
1516 Tpetra::Import_Util::getRemotePIDs(rhs, remotePIDs2);
1519 Array<GO> unionTgtGIDs;
1520 Array<std::pair<int,GO>> remotePGIDs;
1521 size_type numSameIDsUnion, numPermuteIDsUnion, numRemoteIDsUnion;
1523 findUnionTargetGIDs(unionTgtGIDs, remotePGIDs,
1524 numSameIDsUnion, numPermuteIDsUnion, numRemoteIDsUnion,
1525 sameGIDs1, sameGIDs2, permuteGIDs1, permuteGIDs2,
1526 remoteGIDs1, remoteGIDs2, remotePIDs1, remotePIDs2);
1529 Array<LO> remoteLIDsUnion(numRemoteIDsUnion);
1530 Array<GO> remoteGIDsUnion(numRemoteIDsUnion);
1531 Array<int> remotePIDsUnion(numRemoteIDsUnion);
1532 const size_type unionRemoteIDsStart = numSameIDsUnion + numPermuteIDsUnion;
1533 for (size_type k = 0; k < numRemoteIDsUnion; ++k) {
1534 remoteLIDsUnion[k] = unionRemoteIDsStart + k;
1535 remotePIDsUnion[k] = remotePGIDs[k].first;
1536 remoteGIDsUnion[k] = remotePGIDs[k].second;
1541 Array<LO> permuteToLIDsUnion(numPermuteIDsUnion);
1542 Array<LO> permuteFromLIDsUnion(numPermuteIDsUnion);
1544 for (size_type k = 0; k < numPermuteIDsUnion; ++k) {
1545 size_type idx = numSameIDsUnion + k;
1546 permuteToLIDsUnion[k] =
static_cast<LO
>(idx);
1547 permuteFromLIDsUnion[k] = srcMap->getLocalElement(unionTgtGIDs[idx]);
1550 #ifdef HAVE_TPETRA_MMM_TIMINGS
1551 MM.disableTimer(label);
1552 label =
"Tpetra::Import::setUnion : Construct Target Map";
1553 TimeMonitor MM2(*TimeMonitor::getNewTimer(label));
1557 const GST INVALID = Teuchos::OrdinalTraits<GST>::invalid ();
1558 const GO indexBaseUnion = std::min(tgtMap1->getIndexBase(), tgtMap2->getIndexBase());
1559 RCP<const map_type> unionTgtMap =
1560 rcp(
new map_type(INVALID, unionTgtGIDs(), indexBaseUnion, comm));
1562 #ifdef HAVE_TPETRA_MMM_TIMINGS
1563 MM2.disableTimer(label);
1564 label =
"Tpetra::Import::setUnion : Export GIDs";
1565 TimeMonitor MM3(*TimeMonitor::getNewTimer(label));
1576 Array<GO> exportGIDsUnion;
1577 Array<LO> exportLIDsUnion;
1578 Array<int> exportPIDsUnion;
1579 Distributor distributor (comm, this->TransferData_->out_);
1581 #ifdef TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1589 ArrayView<const LO> exportLIDs1 = this->getExportLIDs ();
1590 ArrayView<const LO> exportPIDs1 = this->getExportPIDs ();
1603 Array<LO> exportLIDs1Copy (exportLIDs1.begin (), exportLIDs1.end ());
1604 Array<int> exportPIDs1Copy (exportLIDs1.begin (), exportLIDs1.end ());
1605 sort2 (exportLIDs1Copy.begin (), exportLIDs1Copy.end (),
1606 exportPIDs1Copy.begin ());
1607 typename ArrayView<LO>::iterator exportLIDs1_end = exportLIDs1Copy.end ();
1608 typename ArrayView<LO>::iterator exportPIDs1_end = exportPIDs1Copy.end ();
1609 merge2 (exportLIDs1_end, exportPIDs1_end,
1610 exportLIDs1Copy.begin (), exportLIDs1_end,
1611 exportPIDs1Copy.begin (), exportPIDs1_end,
1614 Array<LO> exportLIDs2Copy (exportLIDs2.begin (), exportLIDs2.end ());
1615 Array<int> exportPIDs2Copy (exportLIDs2.begin (), exportLIDs2.end ());
1616 sort2 (exportLIDs2Copy.begin (), exportLIDs2Copy.end (),
1617 exportPIDs2Copy.begin ());
1618 typename ArrayView<LO>::iterator exportLIDs2_end = exportLIDs2Copy.end ();
1619 typename ArrayView<LO>::iterator exportPIDs2_end = exportPIDs2Copy.end ();
1620 merge2 (exportLIDs2_end, exportPIDs2_end,
1621 exportLIDs2Copy.begin (), exportLIDs2_end,
1622 exportPIDs2Copy.begin (), exportPIDs2_end,
1629 keyValueMerge (exportLIDs1Copy.begin (), exportLIDs1Copy.end (),
1630 exportPIDs1Copy.begin (), exportPIDs1Copy.end (),
1631 exportLIDs2Copy.begin (), exportLIDs2Copy.end (),
1632 exportPIDs2Copy.begin (), exportPIDs2Copy.end (),
1633 std::back_inserter (exportLIDsUnion),
1634 std::back_inserter (exportPIDsUnion),
1638 sort2 (exportPIDsUnion.begin (), exportPIDsUnion.end (),
1639 exportLIDsUnion.begin ());
1645 #else // NOT TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1653 remotePIDsUnion().getConst(),
1654 exportGIDsUnion, exportPIDsUnion);
1657 const size_type numExportIDsUnion = exportGIDsUnion.size ();
1658 exportLIDsUnion.resize (numExportIDsUnion);
1659 for (size_type k = 0; k < numExportIDsUnion; ++k) {
1660 exportLIDsUnion[k] = srcMap->getLocalElement (exportGIDsUnion[k]);
1662 #endif // TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1665 #ifdef HAVE_TPETRA_MMM_TIMINGS
1666 MM3.disableTimer(label);
1667 label =
"Tpetra::Import::setUnion : Construct Import";
1668 TimeMonitor MM4(*TimeMonitor::getNewTimer(label));
1670 RCP<const import_type> unionImport =
1671 rcp (
new import_type (srcMap, unionTgtMap,
1672 as<size_t> (numSameIDsUnion),
1673 permuteToLIDsUnion, permuteFromLIDsUnion,
1674 remoteLIDsUnion, exportLIDsUnion,
1675 exportPIDsUnion, distributor,
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;
1694 typedef LocalOrdinal LO;
1695 typedef GlobalOrdinal GO;
1696 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> > unionImport;
1697 RCP<const map_type> srcMap = this->getSourceMap ();
1698 RCP<const map_type> tgtMap = this->getTargetMap ();
1699 RCP<const Comm<int> > comm = srcMap->getComm ();
1701 ArrayView<const GO> srcGIDs = srcMap->getLocalElementList ();
1702 ArrayView<const GO> tgtGIDs = tgtMap->getLocalElementList ();
1705 size_t numSameIDsNew = srcMap->getLocalNumElements ();
1706 size_t numRemoteIDsNew = this->getNumRemoteIDs ();
1707 Array<LO> permuteToLIDsNew, permuteFromLIDsNew;
1710 ArrayView<const LO> remoteLIDsOld = this->getRemoteLIDs ();
1711 ArrayView<const LO> exportLIDsOld = this->getExportLIDs ();
1714 Array<GO> GIDs(numSameIDsNew + numRemoteIDsNew);
1715 for(
size_t i=0; i<numSameIDsNew; i++)
1716 GIDs[i] = srcGIDs[i];
1719 Array<LO> remoteLIDsNew(numRemoteIDsNew);
1720 for(
size_t i=0; i<numRemoteIDsNew; i++) {
1721 GIDs[numSameIDsNew + i] = tgtGIDs[remoteLIDsOld[i]];
1722 remoteLIDsNew[i] = numSameIDsNew+i;
1726 GO GO_INVALID = Teuchos::OrdinalTraits<GO>::invalid();
1727 RCP<const map_type> targetMapNew =
1728 rcp (
new map_type (GO_INVALID, GIDs, tgtMap->getIndexBase (),
1729 tgtMap->getComm ()));
1732 Array<int> exportPIDsnew (this->getExportPIDs ());
1733 Array<LO> exportLIDsnew (this->getExportLIDs ());
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;
1763 using LO = LocalOrdinal;
1764 using GO = GlobalOrdinal;
1767 const char funcPrefix[] =
"Tpetra::createRemoteOnlyImport: ";
1770 const bool debug = Behavior::debug ();
1772 const size_t NumRemotes = this->getNumRemoteIDs ();
1773 std::unique_ptr<std::string> procPrefix;
1774 Teuchos::RCP<const Teuchos::Comm<int>> comm;
1776 comm = remoteTarget.is_null () ? Teuchos::null :
1777 remoteTarget->getComm ();
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;
1792 if (remoteTarget.is_null ()) {
1795 else if (NumRemotes != remoteTarget->getLocalNumElements ()) {
1797 lclErr << *procPrefix <<
"getNumRemoteIDs() = " << NumRemotes
1798 <<
" != remoteTarget->getLocalNumElements() = "
1799 << remoteTarget->getLocalNumElements () <<
"." << endl;
1802 if (comm.is_null ()) {
1803 lclSuccess = gblSuccess;
1806 reduceAll (*comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
1808 TEUCHOS_TEST_FOR_EXCEPTION
1809 (gblSuccess == -1, std::invalid_argument, funcPrefix
1810 <<
"Input target Map is null on at least one process.");
1812 if (gblSuccess != 1) {
1813 if (comm.is_null ()) {
1814 TEUCHOS_TEST_FOR_EXCEPTION
1815 (
true, std::runtime_error, lclErr.str ());
1818 std::ostringstream gblErr;
1819 gblErr << funcPrefix << endl;
1820 gathervPrint (gblErr, lclErr.str (), *comm);
1821 TEUCHOS_TEST_FOR_EXCEPTION
1822 (
true, std::runtime_error, gblErr.str ());
1828 Teuchos::ArrayView<const LO> oldRemoteLIDs = this->getRemoteLIDs ();
1829 Teuchos::Array<LO> newRemoteLIDs (NumRemotes);
1830 const map_type& tgtMap = * (this->getTargetMap ());
1831 size_t badCount = 0;
1833 std::unique_ptr<std::vector<size_t>> badIndices;
1835 badIndices = std::unique_ptr<std::vector<size_t>> (
new std::vector<size_t>);
1838 for (
size_t i = 0; i < NumRemotes; ++i) {
1839 const LO oldLclInd = oldRemoteLIDs[i];
1840 if (oldLclInd == Teuchos::OrdinalTraits<LO>::invalid ()) {
1842 if (debug) { badIndices->push_back (i); }
1846 if (gblInd == Teuchos::OrdinalTraits<GO>::invalid ()) {
1848 if (debug) { badIndices->push_back (i); }
1851 const LO newLclInd = remoteTarget->getLocalElement (gblInd);
1852 if (newLclInd == Teuchos::OrdinalTraits<LO>::invalid ()) {
1854 if (debug) { badIndices->push_back (i); }
1857 newRemoteLIDs[i] = newLclInd;
1859 if (i > 0 && newRemoteLIDs[i] < newRemoteLIDs[i-1]) {
1861 if (debug) { badIndices->push_back (i); }
1865 if (badCount != 0) {
1870 if (comm.is_null ()) {
1871 lclSuccess = gblSuccess;
1874 reduceAll (*comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
1876 std::ostringstream lclErr;
1877 if (lclSuccess != 1) {
1878 lclErr << *procPrefix <<
"Count of bad indices: " << badCount
1879 <<
", bad indices: [";
1882 for (
size_t k = 0; k < badCount; ++k) {
1883 const size_t badIndex = (*badIndices)[k];
1884 lclErr <<
"(" << badIndex <<
","
1885 << oldRemoteLIDs[badIndex] <<
")";
1886 if (k +
size_t (1) < badCount) {
1890 lclErr <<
"]" << endl;
1893 if (gblSuccess != 1) {
1894 std::ostringstream gblErr;
1895 gblErr << funcPrefix <<
"this->getRemoteLIDs() has \"bad\" "
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 ()) {
1903 gblErr << lclErr.str ();
1906 gathervPrint (gblErr, lclErr.str (), *comm);
1908 TEUCHOS_TEST_FOR_EXCEPTION
1909 (
true, std::runtime_error, gblErr.str ());
1913 TEUCHOS_TEST_FOR_EXCEPTION
1914 (lclSuccess == 0, std::runtime_error, funcPrefix
1915 <<
"this->getRemoteLIDs() has " << badCount
1916 <<
"ind" << (badCount == 1 ?
"ex" :
"ices")
1917 <<
" \"bad\" indices on this process." << endl);
1925 Teuchos::Array<int> newExportPIDs (this->getExportPIDs ());
1926 Teuchos::Array<LO> newExportLIDs (this->getExportLIDs ());
1927 Teuchos::Array<LO> dummy;
1930 return rcp (
new import_type (this->getSourceMap (), remoteTarget,
1931 static_cast<size_t> (0), dummy, dummy,
1932 newRemoteLIDs, newExportLIDs,
1933 newExportPIDs, newDistor));
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)
1951 #endif // TPETRA_IMPORT_DEF_HPP
bool congruent(const Teuchos::Comm< int > &comm1, const Teuchos::Comm< int > &comm2)
Whether the two communicators are congruent.
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
void merge2(IT1 &indResultOut, IT2 &valResultOut, IT1 indBeg, IT1 indEnd, IT2 valBeg, IT2)
Merge values in place, additively, with the same index.
Teuchos::FancyOStream & verboseOutputStream() const
Valid (nonnull) output stream for verbose output.
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.
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.
Declaration of Tpetra::Details::Profiling, a scope guard for Kokkos Profiling.
LookupStatus
Return status of Map remote index lookup (getRemoteIndexList()).
Declaration of a function that prints strings from each process.
Teuchos::ArrayView< const int > getExportPIDs() const
List of processes to which entries will be sent.
Teuchos::ArrayView< const LocalOrdinal > getPermuteToLIDs() const
List of local IDs in the target Map that are permuted.
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 map_type > getTargetMap() const
The target Map used to construct this Export or Import.
size_t getNumSameIDs() const
Number of initial identical IDs.
void sort(View &view, const size_t &size)
Convenience wrapper for std::sort for host-accessible views.
size_t getNumRemoteIDs() const
Number of entries not on the calling process.
size_t createFromSends(const Teuchos::ArrayView< const int > &exportProcIDs)
Set up Distributor using list of process ranks to which this process will send.
Teuchos::RCP< const Import< LocalOrdinal, GlobalOrdinal, Node > > setUnion() const
Return the union of this Import this->getSourceMap()
size_t global_size_t
Global size_t object.
Import(const Teuchos::RCP< const map_type > &source, const Teuchos::RCP< const map_type > &target)
Construct an Import from the source and target Maps.
Teuchos::ArrayView< const LocalOrdinal > getRemoteLIDs() const
List of entries in the target Map to receive from other processes.
global_ordinal_type getGlobalElement(local_ordinal_type localIndex) const
The global index corresponding to the given local 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 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...
auto view_alloc_no_init(const std::string &label) ->
Use in place of the string label as the first argument of Kokkos::View's constructor, in case you want to allocate without initializing.
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
#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...
Implementation detail of Import and Export.
Sets up and executes a communication plan for a Tpetra DistObject.
Teuchos::RCP< ImportExportData< LocalOrdinal, GlobalOrdinal, Node > > TransferData_
All the data needed for executing the Export communication plan.
Teuchos::RCP< const map_type > getSourceMap() const
The source Map used to construct this Export or Import.
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.
void start()
Start the deep_copy counter.
Teuchos::ArrayView< const LocalOrdinal > getExportLIDs() const
List of entries in the source Map that will be sent to other processes.
void sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2)
Sort the first array, and apply the resulting permutation to the second array.
A parallel distribution of indices over processes.
Internal functions and macros designed for use with Tpetra::Import and Tpetra::Export objects...
Stand-alone utility functions and macros.
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 verbose() const
Whether to print verbose debugging output.
virtual void print(std::ostream &os) const
Print the Import's data to the given output stream.
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.
Binary function that returns its first argument.
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.