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 if (this->verbose ()) {
178 std::ostringstream os;
179 os << *verbPrefix <<
"Done!" << endl;
180 this->verboseOutputStream () << os.str ();
184 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
186 Import (
const Teuchos::RCP<const map_type >& source,
187 const Teuchos::RCP<const map_type >& target) :
188 base_type (source, target, Teuchos::null, Teuchos::null,
"Import")
190 Teuchos::Array<int> dummy;
191 #ifdef HAVE_TPETRA_MMM_TIMINGS
192 Teuchos::RCP<Teuchos::ParameterList> mypars = rcp(
new Teuchos::ParameterList);
193 mypars->set(
"Timer Label",
"Naive_tAFC");
194 init(source, target,
false, dummy, mypars);
196 init (source, target,
false, dummy, Teuchos::null);
200 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
202 Import (
const Teuchos::RCP<const map_type>& source,
203 const Teuchos::RCP<const map_type>& target,
204 const Teuchos::RCP<Teuchos::FancyOStream>& out) :
205 base_type (source, target, out, Teuchos::null,
"Import")
207 Teuchos::Array<int> dummy;
208 init (source, target,
false, dummy, Teuchos::null);
211 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
213 Import (
const Teuchos::RCP<const map_type>& source,
214 const Teuchos::RCP<const map_type>& target,
215 const Teuchos::RCP<Teuchos::ParameterList>& plist) :
216 base_type (source, target, Teuchos::null, plist,
"Import")
218 Teuchos::Array<int> dummy;
219 init (source, target,
false, dummy, plist);
222 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
224 Import (
const Teuchos::RCP<const map_type>& source,
225 const Teuchos::RCP<const map_type>& target,
226 const Teuchos::RCP<Teuchos::FancyOStream>& out,
227 const Teuchos::RCP<Teuchos::ParameterList>& plist) :
228 base_type (source, target, out, plist,
"Import")
230 Teuchos::Array<int> dummy;
231 init (source, target,
false, dummy, plist);
234 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
236 Import (
const Teuchos::RCP<const map_type>& source,
237 const Teuchos::RCP<const map_type>& target,
238 Teuchos::Array<int>& remotePIDs,
239 const Teuchos::RCP<Teuchos::ParameterList>& plist) :
240 base_type (source, target, Teuchos::null, plist,
"Import")
242 init (source, target,
true, remotePIDs, plist);
245 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
251 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
260 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
264 const Teuchos::ArrayView<int> & userRemotePIDs,
265 const Teuchos::ArrayView<const LocalOrdinal> & userExportLIDs,
266 const Teuchos::ArrayView<const int> & userExportPIDs,
267 const Teuchos::RCP<Teuchos::ParameterList>& plist,
268 const Teuchos::RCP<Teuchos::FancyOStream>& out) :
269 base_type (source, target, out, plist,
"Import")
271 using ::Tpetra::Details::makeDualViewFromArrayView;
273 using Teuchos::Array;
274 using Teuchos::ArrayRCP;
275 using Teuchos::ArrayView;
280 using LO = LocalOrdinal;
281 using GO = GlobalOrdinal;
282 using size_type = Teuchos::Array<int>::size_type;
284 std::unique_ptr<std::string> prefix;
286 auto comm = source.is_null () ? Teuchos::null : source->getComm ();
287 const int myRank = comm.is_null () ? -1 : comm->getRank ();
288 std::ostringstream os;
289 os <<
"Proc " << myRank <<
": Tpetra::Import createExpert ctor: ";
290 prefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
291 os <<
"Start" << endl;
295 ArrayView<const GO> sourceGIDs = source->getNodeElementList ();
296 ArrayView<const GO> targetGIDs = target->getNodeElementList ();
298 Array<GO> tRemoteGIDs;
300 std::ostringstream os;
301 os << *prefix <<
"Call setupSamePermuteRemote" << endl;
304 setupSamePermuteRemote (tRemoteGIDs);
307 std::ostringstream os;
308 os << *prefix <<
"Sort & filter IDs" << endl;
312 auto tRemoteLIDs = this->
TransferData_->remoteLIDs_.view_host ();
314 Teuchos::Array<int> tRemotePIDs (userRemotePIDs);
317 std::ostringstream os;
318 os << *prefix <<
"Target Map has remote LIDs but source Map is not "
319 "distributed. Importing to a submap of the target Map." << endl;
327 "::constructExpert: Target Map has remote LIDs but source Map "
328 "is not distributed. Importing to a submap of the target Map.");
329 TEUCHOS_TEST_FOR_EXCEPTION
330 (tRemotePIDs.size () != tRemoteGIDs.size () ||
331 size_t (tRemoteGIDs.size ()) !=
size_t (tRemoteLIDs.extent (0)),
332 std::runtime_error,
"Import::Import createExpert version: "
333 "Size mismatch on userRemotePIDs, remoteGIDs, and remoteLIDs "
334 "Array's to sort3.");
336 sort3 (tRemotePIDs.begin (),
338 tRemoteGIDs.begin (),
339 tRemoteLIDs.data ());
343 size_type indexIntoRemotePIDs = tRemotePIDs.size ();
344 for (size_type i = 0; i < indexIntoRemotePIDs; ++i) {
345 if (tRemotePIDs[i] == -1) {
354 if (indexIntoRemotePIDs - cnt > 0) {
355 Array<GO> newRemoteGIDs(indexIntoRemotePIDs-cnt);
356 Array<LO> newRemoteLIDs(indexIntoRemotePIDs-cnt);
357 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 TEUCHOS_ASSERT( ! this->
TransferData_->permuteFromLIDs_.need_sync_device () );
415 TEUCHOS_ASSERT( ! this->
TransferData_->permuteFromLIDs_.need_sync_host () );
416 TEUCHOS_ASSERT( ! this->
TransferData_->permuteToLIDs_.need_sync_device () );
417 TEUCHOS_ASSERT( ! this->
TransferData_->permuteToLIDs_.need_sync_host () );
418 TEUCHOS_ASSERT( ! this->
TransferData_->remoteLIDs_.need_sync_device () );
419 TEUCHOS_ASSERT( ! this->
TransferData_->remoteLIDs_.need_sync_host () );
420 TEUCHOS_ASSERT( ! this->
TransferData_->exportLIDs_.need_sync_device () );
421 TEUCHOS_ASSERT( ! this->
TransferData_->exportLIDs_.need_sync_host () );
424 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
426 Import (
const Teuchos::RCP<const map_type>& source,
427 const Teuchos::RCP<const map_type>& target,
428 const size_t numSameIDs,
429 Teuchos::Array<LocalOrdinal>& permuteToLIDs,
430 Teuchos::Array<LocalOrdinal>& permuteFromLIDs,
431 Teuchos::Array<LocalOrdinal>& remoteLIDs,
432 Teuchos::Array<LocalOrdinal>& exportLIDs,
433 Teuchos::Array<int>& exportPIDs,
435 const Teuchos::RCP<Teuchos::FancyOStream>& out,
436 const Teuchos::RCP<Teuchos::ParameterList>& plist) :
437 base_type (source, target, out, plist,
"Import")
439 using ::Tpetra::Details::makeDualViewFromArrayView;
442 std::unique_ptr<std::string> prefix;
444 auto comm = source.is_null () ? Teuchos::null : source->getComm ();
445 const int myRank = comm.is_null () ? -1 : comm->getRank ();
446 std::ostringstream os;
447 os <<
"Proc " << myRank <<
": Tpetra::Import export ctor: ";
448 prefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
449 os <<
"Start" << endl;
453 bool locallyComplete =
true;
454 for (Teuchos::Array<int>::size_type i = 0; i < exportPIDs.size (); ++i) {
455 if (exportPIDs[i] == -1) {
456 locallyComplete =
false;
460 std::ostringstream os;
461 os << *prefix <<
"numSameIDs: " << numSameIDs <<
", locallyComplete: "
462 << (locallyComplete ?
"true" :
"false") << endl;
469 makeDualViewFromArrayView (this->
TransferData_->permuteToLIDs_,
470 permuteToLIDs ().getConst (),
472 TEUCHOS_ASSERT(
size_t (this->
TransferData_->permuteToLIDs_.extent (0)) ==
473 size_t (permuteToLIDs.size ()) );
474 makeDualViewFromArrayView (this->
TransferData_->permuteFromLIDs_,
475 permuteFromLIDs ().getConst (),
477 TEUCHOS_ASSERT(
size_t (this->
TransferData_->permuteFromLIDs_.extent (0)) ==
478 size_t (permuteFromLIDs.size ()) );
480 remoteLIDs ().getConst (),
482 TEUCHOS_ASSERT(
size_t (this->
TransferData_->remoteLIDs_.extent (0)) ==
483 size_t (remoteLIDs.size ()) );
485 exportLIDs ().getConst (),
487 TEUCHOS_ASSERT(
size_t (this->
TransferData_->exportLIDs_.extent (0)) ==
488 size_t (exportLIDs.size ()) );
492 TEUCHOS_ASSERT( ! this->
TransferData_->permuteFromLIDs_.need_sync_device () );
493 TEUCHOS_ASSERT( ! this->
TransferData_->permuteFromLIDs_.need_sync_host () );
494 TEUCHOS_ASSERT( ! this->
TransferData_->permuteToLIDs_.need_sync_device () );
495 TEUCHOS_ASSERT( ! this->
TransferData_->permuteToLIDs_.need_sync_host () );
496 TEUCHOS_ASSERT( ! this->
TransferData_->remoteLIDs_.need_sync_device () );
497 TEUCHOS_ASSERT( ! this->
TransferData_->remoteLIDs_.need_sync_host () );
498 TEUCHOS_ASSERT( ! this->
TransferData_->exportLIDs_.need_sync_device () );
499 TEUCHOS_ASSERT( ! this->
TransferData_->exportLIDs_.need_sync_host () );
504 template <
class LO,
class GO,
class NT>
505 struct ImportLocalSetupResult
507 Teuchos::RCP<const ::Tpetra::Map<LO, GO, NT> > targetMap;
511 std::vector<GO> remoteGIDs;
512 std::vector<LO> remoteLIDs;
513 std::vector<int> remotePIDs;
518 void printArray (std::ostream& out,
const T x[],
const std::size_t N)
521 for (std::size_t k = 0; k < N; ++k) {
530 template<
class LO,
class GO,
class NT>
531 ImportLocalSetupResult<LO, GO, NT>
532 setupSamePermuteRemoteFromUserGlobalIndexList (const ::Tpetra::Map<LO, GO, NT>& sourceMap,
533 const GO targetMapRemoteOrPermuteGlobalIndices[],
534 const int targetMapRemoteOrPermuteProcessRanks[],
535 const LO numTargetMapRemoteOrPermuteGlobalIndices,
536 const bool mayReorderTargetMapIndicesLocally,
537 Teuchos::FancyOStream* out,
538 const std::string* verboseHeader,
543 const int myRank = sourceMap.getComm ()->getRank ();
544 ImportLocalSetupResult<LO, GO, NT> result;
547 std::ostringstream os;
548 os << *verboseHeader <<
"- Import::setupSPR w/ remote GIDs & PIDs: " << endl
549 << *verboseHeader <<
" Input GIDs: ";
550 printArray (os, targetMapRemoteOrPermuteGlobalIndices, numTargetMapRemoteOrPermuteGlobalIndices);
551 os << endl <<
" Input PIDs: ";
552 printArray (os, targetMapRemoteOrPermuteProcessRanks, numTargetMapRemoteOrPermuteGlobalIndices);
562 std::vector<GO> badGIDs;
563 std::vector<int> badPIDs;
564 const Teuchos::Comm<int>& comm = * (sourceMap.getComm ());
565 const int numProcs = comm.getSize ();
567 for (LO k = 0; k < numTargetMapRemoteOrPermuteGlobalIndices; ++k) {
568 const GO tgtGID = targetMapRemoteOrPermuteGlobalIndices[k];
569 if (sourceMap.isNodeGlobalElement (tgtGID)) {
570 badGIDs.push_back (tgtGID);
572 const int tgtPID = targetMapRemoteOrPermuteProcessRanks[k];
573 if (tgtPID < 0 || tgtPID >= numProcs) {
574 badPIDs.push_back (tgtPID);
578 std::array<int, 2> lclStatus {{
579 badGIDs.size () == 0 ? 1 : 0,
580 badPIDs.size () == 0 ? 1 : 0
582 std::array<int, 2> gblStatus {{0, 0}};
583 Teuchos::reduceAll<int, int> (comm, Teuchos::REDUCE_MIN, 2,
584 lclStatus.data (), gblStatus.data ());
585 const bool good = gblStatus[0] == 1 && gblStatus[1] == 1;
588 if (verbose && gblStatus[0] != 1) {
589 std::ostringstream os;
590 os << *verboseHeader <<
"- Some input GIDs are already in the source Map: ";
591 printArray (os, badGIDs.data (), badGIDs.size ());
593 ::Tpetra::Details::gathervPrint (*out, os.str (), comm);
595 if (verbose && gblStatus[0] != 1) {
596 std::ostringstream os;
597 os << *verboseHeader <<
"- Some input PIDs are invalid: ";
598 printArray (os, badPIDs.data (), badPIDs.size ());
600 ::Tpetra::Details::gathervPrint (*out, os.str (), comm);
604 std::ostringstream os;
605 os <<
"Tpetra::Import constructor that takes remote GIDs and PIDs: ";
606 if (gblStatus[0] != 1) {
607 os <<
"Some input GIDs (global indices) are already in the source Map! ";
609 if (gblStatus[1] != 1) {
610 os <<
"Some input PIDs (process ranks) are invalid! ";
612 os <<
"Rerun with the environment variable TPETRA_VERBOSE=Tpetra::Import "
613 "to see what GIDs and/or PIDs are bad.";
614 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument, os.str ());
621 const LO numLclSrcIDs =
static_cast<LO
> (sourceMap.getNodeNumElements ());
622 const LO numLclTgtIDs = numLclSrcIDs + numTargetMapRemoteOrPermuteGlobalIndices;
624 std::ostringstream os;
625 os << *verboseHeader <<
"- Copy source Map GIDs into target Map GID list: "
626 "numLclSrcIDs=" << numLclSrcIDs
627 <<
", numTargetMapRemoteOrPermuteGlobalIndices="
628 << numTargetMapRemoteOrPermuteGlobalIndices << endl;
631 std::vector<GO> tgtGIDs (numLclTgtIDs);
632 if (sourceMap.isContiguous ()) {
633 GO curTgtGID = sourceMap.getMinGlobalIndex ();
634 for (LO k = 0; k < numLclSrcIDs; ++k, ++curTgtGID) {
635 tgtGIDs[k] = curTgtGID;
639 auto srcGIDs = sourceMap.getNodeElementList ();
640 for (LO k = 0; k < numLclSrcIDs; ++k) {
641 tgtGIDs[k] = srcGIDs[k];
644 std::copy (targetMapRemoteOrPermuteGlobalIndices,
645 targetMapRemoteOrPermuteGlobalIndices + numTargetMapRemoteOrPermuteGlobalIndices,
646 tgtGIDs.begin () + numLclSrcIDs);
659 std::ostringstream os;
660 os << *verboseHeader <<
"- Sort by PID? "
661 << (mayReorderTargetMapIndicesLocally ?
"true" :
"false") << endl;
664 std::vector<int> tgtPIDs (targetMapRemoteOrPermuteProcessRanks,
665 targetMapRemoteOrPermuteProcessRanks + numTargetMapRemoteOrPermuteGlobalIndices);
666 result.numPermutes = 0;
667 if (mayReorderTargetMapIndicesLocally) {
668 Tpetra::sort2 (tgtPIDs.begin (), tgtPIDs.end (), tgtGIDs.begin () + numLclSrcIDs);
669 auto range = std::equal_range (tgtPIDs.begin (), tgtPIDs.end (), myRank);
670 if (range.second > range.first) {
671 result.numPermutes =
static_cast<LO
> (range.second - range.first);
675 result.numPermutes =
static_cast<LO
> (std::count (tgtPIDs.begin (), tgtPIDs.end (), myRank));
678 const LO numRemotes = numTargetMapRemoteOrPermuteGlobalIndices - result.numPermutes;
679 result.numSameIDs =
static_cast<LO
> (sourceMap.getNodeNumElements ());
682 std::ostringstream os;
683 os << *verboseHeader <<
"- numSame=" << result.numSameIDs
684 <<
", numPermutes=" << result.numPermutes
685 <<
", numRemotes=" << numRemotes << endl;
689 if (result.numPermutes == 0) {
691 std::ostringstream os;
692 os << *verboseHeader <<
"- No permutes" << endl;
695 result.remoteGIDs = std::vector<GO> (tgtGIDs.begin () + numLclSrcIDs, tgtGIDs.end ());
696 result.remotePIDs.swap (tgtPIDs);
697 result.remoteLIDs.resize (numRemotes);
698 for (LO k = 0; k < numRemotes; ++k) {
699 const LO tgtLid = result.numSameIDs + k;
700 result.remoteLIDs[k] = tgtLid;
703 std::ostringstream os;
704 os << *verboseHeader <<
"- Remote GIDs: "
705 << Teuchos::toString (result.remoteGIDs) << endl;
706 os << *verboseHeader <<
"- Remote PIDs: "
707 << Teuchos::toString (result.remotePIDs) << endl;
708 os << *verboseHeader <<
"- Remote LIDs: "
709 << Teuchos::toString (result.remoteLIDs) << endl;
717 result.remoteGIDs.reserve (numRemotes);
718 result.remoteLIDs.reserve (numRemotes);
719 result.remotePIDs.reserve (numRemotes);
720 for (LO k = 0; k < numTargetMapRemoteOrPermuteGlobalIndices; ++k) {
721 const LO tgtLid = result.numSameIDs + k;
722 const GO tgtGid = tgtGIDs[numLclSrcIDs + k];
723 const int tgtPid = tgtPIDs[k];
725 if (tgtPid != myRank) {
726 result.remoteGIDs.push_back (tgtGid);
727 result.remoteLIDs.push_back (tgtLid);
728 result.remotePIDs.push_back (tgtPid);
732 std::ostringstream os;
733 os << *verboseHeader <<
"- Some permutes" << endl;
738 if (sourceMap.isDistributed ()) {
740 std::ostringstream os;
741 os << *verboseHeader <<
"- Sort remotes by PID, as Import always does"
743 << *verboseHeader <<
"-- remotePIDs before: "
744 << Teuchos::toString (result.remotePIDs) << endl
745 << *verboseHeader <<
"-- remoteGIDs before: "
746 << Teuchos::toString (result.remoteGIDs) << endl
747 << *verboseHeader <<
"-- remoteLIDs before: "
748 << Teuchos::toString (result.remoteLIDs) << endl;
752 sort3 (result.remotePIDs.begin (),
753 result.remotePIDs.end (),
754 result.remoteGIDs.begin (),
755 result.remoteLIDs.begin ());
757 std::ostringstream os;
758 os << *verboseHeader <<
"-- remotePIDs after: "
759 << Teuchos::toString (result.remotePIDs) << endl
760 << *verboseHeader <<
"-- remoteGIDs after: "
761 << Teuchos::toString (result.remoteGIDs) << endl
762 << *verboseHeader <<
"-- remoteLIDs after: "
763 << Teuchos::toString (result.remoteLIDs) << endl;
764 std::cerr << os.str ();
769 std::ostringstream os;
770 os << *verboseHeader <<
"- Make target Map" << endl;
773 using ::Teuchos::rcp;
774 typedef ::Tpetra::Map<LO, GO, NT> map_type;
775 typedef ::Tpetra::global_size_t GST;
776 const GST MAP_COMPUTES_GLOBAL_COUNT = ::Teuchos::OrdinalTraits<GST>::invalid ();
777 result.targetMap = rcp (
new map_type (MAP_COMPUTES_GLOBAL_COUNT,
780 sourceMap.getIndexBase (),
781 sourceMap.getComm ()));
783 std::ostringstream os;
784 os << *verboseHeader <<
"- Done with sameSPR..." << endl;
791 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
794 const GlobalOrdinal targetMapRemoteOrPermuteGlobalIndices[],
795 const int targetMapRemoteOrPermuteProcessRanks[],
796 const LocalOrdinal numTargetMapRemoteOrPermuteGlobalIndices,
797 const bool mayReorderTargetMapIndicesLocally,
798 const Teuchos::RCP<Teuchos::ParameterList>& plist,
799 const Teuchos::RCP<Teuchos::FancyOStream>& debugOutput) :
803 base_type (sourceMap, Teuchos::null, debugOutput, plist,
"Import")
805 using ::Tpetra::Details::Behavior;
806 using ::Tpetra::Details::makeDualViewFromOwningHostView;
807 using ::Tpetra::Details::makeDualViewFromVector;
808 using ::Tpetra::Details::printDualView;
809 using ::Tpetra::Details::view_alloc_no_init;
810 using Teuchos::ArrayView;
811 using Teuchos::getFancyOStream;
814 using Teuchos::rcpFromRef;
816 typedef LocalOrdinal LO;
817 typedef GlobalOrdinal GO;
820 const bool debug = Behavior::debug (
"Import") ||
821 Behavior::debug (
"Tpetra::Import");
823 std::unique_ptr<std::string> verbPfx;
824 if (this->verbose ()) {
825 std::ostringstream os;
826 const int myRank = sourceMap->getComm ()->getRank ();
827 os <<
"Proc " << myRank <<
": Tpetra::Import ctor from remotes: ";
828 verbPfx = std::unique_ptr<std::string> (
new std::string (os.str ()));
829 os <<
"mayReorder=" << (mayReorderTargetMapIndicesLocally ?
"true" :
"false")
835 ImportLocalSetupResult<LO, GO, NT> localSetupResult =
836 setupSamePermuteRemoteFromUserGlobalIndexList<LO, GO, NT>
838 targetMapRemoteOrPermuteGlobalIndices,
839 targetMapRemoteOrPermuteProcessRanks,
840 numTargetMapRemoteOrPermuteGlobalIndices,
841 mayReorderTargetMapIndicesLocally,
853 localSetupResult.targetMap,
854 this->TransferData_->out_,
856 this->TransferData_->numSameIDs_ = localSetupResult.numSameIDs;
859 makeDualViewFromVector (this->TransferData_->remoteLIDs_,
860 localSetupResult.remoteLIDs,
869 this->TransferData_->isLocallyComplete_ =
true;
871 Teuchos::Array<GO> exportGIDs;
872 if (sourceMap->isDistributed ()) {
873 if (this->verbose ()) {
874 std::ostringstream os;
875 os << *verbPfx <<
"Make Distributor (createFromRecvs)" << endl;
878 ArrayView<const GO> remoteGIDs (localSetupResult.remoteGIDs.data (),
879 localSetupResult.remoteGIDs.size ());
880 ArrayView<const int> remotePIDs (localSetupResult.remotePIDs.data (),
881 localSetupResult.remotePIDs.size ());
886 Distributor& distributor = this->TransferData_->distributor_;
890 this->TransferData_->exportPIDs_);
899 if (this->verbose ()) {
900 std::ostringstream os;
901 os << *verbPfx <<
"Compute exportLIDs" << endl;
904 using size_type =
typename Teuchos::Array<GO>::size_type;
905 const size_type numExportIDs = exportGIDs.size ();
907 typename decltype (this->TransferData_->exportLIDs_)::t_host
908 exportLIDs (view_alloc_no_init (
"exportLIDs"), numExportIDs);
912 for (size_type k = 0; k < numExportIDs; ++k) {
913 exportLIDs[k] = sourceMap->getLocalElement (exportGIDs[k]);
915 makeDualViewFromOwningHostView (this->TransferData_->exportLIDs_, exportLIDs);
918 if (this->verbose ()) {
919 std::ostringstream os;
921 printDualView (os, this->TransferData_->remoteLIDs_,
922 "ImportExportData::remoteLIDs_");
926 if (this->verbose ()) {
927 std::ostringstream os;
928 os << *verbPfx <<
"Done!" << endl;
933 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
937 const Teuchos::EVerbosityLevel verbLevel)
const
940 this->describeImpl (out,
"Tpetra::Import", verbLevel);
943 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
947 auto out = Teuchos::getFancyOStream (Teuchos::rcpFromRef (os));
949 this->describe (*out, Teuchos::VERB_EXTREME);
952 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
957 using ::Tpetra::Details::makeDualViewFromOwningHostView;
958 using ::Tpetra::Details::ProfilingRegion;
959 using ::Tpetra::Details::view_alloc_no_init;
961 using Teuchos::Array;
962 using Teuchos::ArrayRCP;
963 using Teuchos::ArrayView;
966 typedef LocalOrdinal LO;
967 typedef GlobalOrdinal GO;
968 typedef typename ArrayView<const GO>::size_type size_type;
969 ProfilingRegion regionExport (
"Tpetra::Import::setupSamePermuteRemote");
971 const map_type& source = * (this->getSourceMap ());
972 const map_type& target = * (this->getTargetMap ());
973 ArrayView<const GO> sourceGIDs = source.getNodeElementList ();
974 ArrayView<const GO> targetGIDs = target.getNodeElementList ();
976 #ifdef HAVE_TPETRA_DEBUG
977 ArrayView<const GO> rawSrcGids = sourceGIDs;
978 ArrayView<const GO> rawTgtGids = targetGIDs;
980 const GO*
const rawSrcGids = sourceGIDs.getRawPtr ();
981 const GO*
const rawTgtGids = targetGIDs.getRawPtr ();
982 #endif // HAVE_TPETRA_DEBUG
983 const size_type numSrcGids = sourceGIDs.size ();
984 const size_type numTgtGids = targetGIDs.size ();
985 const size_type numGids = std::min (numSrcGids, numTgtGids);
993 size_type numSameGids = 0;
994 for ( ; numSameGids < numGids && rawSrcGids[numSameGids] == rawTgtGids[numSameGids]; ++numSameGids)
996 this->TransferData_->numSameIDs_ = numSameGids;
1010 const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid ();
1011 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::bind1st (std::equal_to<int> (), -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 ();
1307 for (size_type k = 0; k < numExportIDs; ++k) {
1308 exportLIDs[k] = source.getLocalElement (expGIDs[k]);
1313 if (this->verbose ()) {
1314 std::ostringstream os;
1315 os << *prefix <<
"Done!" << endl;
1316 this->verboseOutputStream () << os.str ();
1320 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1324 Teuchos::Array<std::pair<int,GlobalOrdinal>>& remotePGIDs,
1325 typename Teuchos::Array<GlobalOrdinal>::size_type& numSameGIDs,
1326 typename Teuchos::Array<GlobalOrdinal>::size_type& numPermuteGIDs,
1327 typename Teuchos::Array<GlobalOrdinal>::size_type& numRemoteGIDs,
1328 const Teuchos::ArrayView<const GlobalOrdinal>& sameGIDs1,
1329 const Teuchos::ArrayView<const GlobalOrdinal>& sameGIDs2,
1330 Teuchos::Array<GlobalOrdinal>& permuteGIDs1,
1331 Teuchos::Array<GlobalOrdinal>& permuteGIDs2,
1332 Teuchos::Array<GlobalOrdinal>& remoteGIDs1,
1333 Teuchos::Array<GlobalOrdinal>& remoteGIDs2,
1334 Teuchos::Array<int>& remotePIDs1,
1335 Teuchos::Array<int>& remotePIDs2)
const
1338 typedef GlobalOrdinal GO;
1339 typedef typename Teuchos::Array<GO>::size_type size_type;
1341 const size_type numSameGIDs1 = sameGIDs1.size();
1342 const size_type numSameGIDs2 = sameGIDs2.size();
1345 std::sort(permuteGIDs1.begin(), permuteGIDs1.end());
1346 std::sort(permuteGIDs2.begin(), permuteGIDs2.end());
1351 unionTgtGIDs.reserve(numSameGIDs1 + numSameGIDs2 +
1352 permuteGIDs1.size() + permuteGIDs2.size() +
1353 remoteGIDs1.size() + remoteGIDs2.size());
1357 typename Teuchos::Array<GO>::iterator permuteGIDs1_end;
1358 typename Teuchos::Array<GO>::iterator permuteGIDs2_end;
1359 if (numSameGIDs2 > numSameGIDs1) {
1361 numSameGIDs = numSameGIDs2;
1362 permuteGIDs2_end = permuteGIDs2.end();
1365 std::copy(sameGIDs2.begin(), sameGIDs2.end(), std::back_inserter(unionTgtGIDs));
1369 permuteGIDs1_end = std::set_difference(permuteGIDs1.begin(), permuteGIDs1.end(),
1370 unionTgtGIDs.begin()+numSameGIDs1, unionTgtGIDs.end(),
1371 permuteGIDs1.begin());
1375 numSameGIDs = numSameGIDs1;
1376 permuteGIDs1_end = permuteGIDs1.end();
1379 std::copy(sameGIDs1.begin(), sameGIDs1.end(), std::back_inserter(unionTgtGIDs));
1383 permuteGIDs2_end = std::set_difference(permuteGIDs2.begin(), permuteGIDs2.end(),
1384 unionTgtGIDs.begin()+numSameGIDs2, unionTgtGIDs.end(),
1385 permuteGIDs2.begin());
1390 std::set_union(permuteGIDs1.begin(), permuteGIDs1_end,
1391 permuteGIDs2.begin(), permuteGIDs2_end,
1392 std::back_inserter(unionTgtGIDs));
1395 Teuchos::Array<std::pair<int,GO>> remotePGIDs1(remoteGIDs1.size());
1396 for (size_type k=0; k<remoteGIDs1.size(); k++)
1397 remotePGIDs1[k] = std::make_pair(remotePIDs1[k], remoteGIDs1[k]);
1398 std::sort(remotePGIDs1.begin(), remotePGIDs1.end());
1400 Teuchos::Array<std::pair<int,GO>> remotePGIDs2(remoteGIDs2.size());
1401 for (size_type k=0; k<remoteGIDs2.size(); k++)
1402 remotePGIDs2[k] = std::make_pair(remotePIDs2[k], remoteGIDs2[k]);
1403 std::sort(remotePGIDs2.begin(), remotePGIDs2.end());
1405 remotePGIDs.reserve(remotePGIDs1.size()+remotePGIDs2.size());
1406 std::merge(remotePGIDs1.begin(), remotePGIDs1.end(),
1407 remotePGIDs2.begin(), remotePGIDs2.end(),
1408 std::back_inserter(remotePGIDs));
1409 auto it = std::unique(remotePGIDs.begin(), remotePGIDs.end());
1410 remotePGIDs.resize(std::distance(remotePGIDs.begin(), it));
1413 const size_type oldSize = unionTgtGIDs.size();
1414 unionTgtGIDs.resize(oldSize+remotePGIDs.size());
1415 for (size_type start=oldSize, k=0; k<remotePGIDs.size(); k++)
1416 unionTgtGIDs[start+k] = remotePGIDs[k].second;
1419 numRemoteGIDs = remotePGIDs.size();
1420 numPermuteGIDs = unionTgtGIDs.size() - numSameGIDs - numRemoteGIDs;
1425 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1426 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
1430 using ::Tpetra::Details::Behavior;
1431 using Teuchos::Array;
1432 using Teuchos::ArrayView;
1434 using Teuchos::Comm;
1437 using Teuchos::outArg;
1438 using Teuchos::REDUCE_MIN;
1439 using Teuchos::reduceAll;
1441 using LO = LocalOrdinal;
1442 using GO = GlobalOrdinal;
1444 using size_type =
typename Array<GO>::size_type;
1446 #ifdef HAVE_TPETRA_MMM_TIMINGS
1447 using Teuchos::TimeMonitor;
1448 std::string label = std::string(
"Tpetra::Import::setUnion");
1449 TimeMonitor MM(*TimeMonitor::getNewTimer(label));
1452 RCP<const map_type> srcMap = this->getSourceMap ();
1453 RCP<const map_type> tgtMap1 = this->getTargetMap ();
1455 RCP<const Comm<int> > comm = srcMap->getComm ();
1457 const bool debug = Behavior::debug (
"Import::setUnion") ||
1458 Behavior::debug (
"Tpetra::Import::setUnion");
1461 TEUCHOS_TEST_FOR_EXCEPTION
1462 (! srcMap->isSameAs (* (rhs.
getSourceMap ())), std::invalid_argument,
1463 "Tpetra::Import::setUnion: The source Map of the input Import must be the "
1464 "same as (in the sense of Map::isSameAs) the source Map of this Import.");
1465 const Comm<int>& comm1 = * (tgtMap1->getComm ());
1466 const Comm<int>& comm2 = * (tgtMap2->getComm ());
1467 TEUCHOS_TEST_FOR_EXCEPTION
1469 std::invalid_argument,
"Tpetra::Import::setUnion: "
1470 "The target Maps must have congruent communicators.");
1476 if (tgtMap1->isSameAs (*tgtMap2)) {
1477 return rcp (
new import_type (*
this));
1485 const size_type numSameGIDs1 = this->getNumSameIDs();
1486 ArrayView<const GO> sameGIDs1 = (tgtMap1->getNodeElementList())(0,numSameGIDs1);
1489 ArrayView<const GO> sameGIDs2 = (tgtMap2->getNodeElementList())(0,numSameGIDs2);
1492 ArrayView<const LO> permuteToLIDs1 = this->getPermuteToLIDs();
1493 Array<GO> permuteGIDs1(permuteToLIDs1.size());
1494 for (size_type k=0; k<permuteGIDs1.size(); k++)
1495 permuteGIDs1[k] = tgtMap1->getGlobalElement(permuteToLIDs1[k]);
1498 Array<GO> permuteGIDs2(permuteToLIDs2.size());
1499 for (size_type k=0; k<permuteGIDs2.size(); k++)
1500 permuteGIDs2[k] = tgtMap2->getGlobalElement(permuteToLIDs2[k]);
1503 ArrayView<const LO> remoteLIDs1 = this->getRemoteLIDs();
1504 Array<GO> remoteGIDs1(remoteLIDs1.size());
1505 for (size_type k=0; k<remoteLIDs1.size(); k++)
1506 remoteGIDs1[k] = this->getTargetMap()->getGlobalElement(remoteLIDs1[k]);
1509 Array<GO> remoteGIDs2(remoteLIDs2.size());
1510 for (size_type k=0; k<remoteLIDs2.size(); k++)
1511 remoteGIDs2[k] = rhs.
getTargetMap()->getGlobalElement(remoteLIDs2[k]);
1514 Array<int> remotePIDs1;
1515 Tpetra::Import_Util::getRemotePIDs(*
this, remotePIDs1);
1517 Array<int> remotePIDs2;
1518 Tpetra::Import_Util::getRemotePIDs(rhs, remotePIDs2);
1521 Array<GO> unionTgtGIDs;
1522 Array<std::pair<int,GO>> remotePGIDs;
1523 size_type numSameIDsUnion, numPermuteIDsUnion, numRemoteIDsUnion;
1525 findUnionTargetGIDs(unionTgtGIDs, remotePGIDs,
1526 numSameIDsUnion, numPermuteIDsUnion, numRemoteIDsUnion,
1527 sameGIDs1, sameGIDs2, permuteGIDs1, permuteGIDs2,
1528 remoteGIDs1, remoteGIDs2, remotePIDs1, remotePIDs2);
1531 Array<LO> remoteLIDsUnion(numRemoteIDsUnion);
1532 Array<GO> remoteGIDsUnion(numRemoteIDsUnion);
1533 Array<int> remotePIDsUnion(numRemoteIDsUnion);
1534 const size_type unionRemoteIDsStart = numSameIDsUnion + numPermuteIDsUnion;
1535 for (size_type k = 0; k < numRemoteIDsUnion; ++k) {
1536 remoteLIDsUnion[k] = unionRemoteIDsStart + k;
1537 remotePIDsUnion[k] = remotePGIDs[k].first;
1538 remoteGIDsUnion[k] = remotePGIDs[k].second;
1543 Array<LO> permuteToLIDsUnion(numPermuteIDsUnion);
1544 Array<LO> permuteFromLIDsUnion(numPermuteIDsUnion);
1548 for (size_type k = 0; k < numPermuteIDsUnion; ++k) {
1549 size_type idx = numSameIDsUnion + k;
1550 permuteToLIDsUnion[k] =
static_cast<LO
>(idx);
1551 permuteFromLIDsUnion[k] = srcMap->getLocalElement(unionTgtGIDs[idx]);
1554 #ifdef HAVE_TPETRA_MMM_TIMINGS
1555 MM.disableTimer(label);
1556 label =
"Tpetra::Import::setUnion : Construct Target Map";
1557 TimeMonitor MM2(*TimeMonitor::getNewTimer(label));
1561 const GST INVALID = Teuchos::OrdinalTraits<GST>::invalid ();
1562 const GO indexBaseUnion = std::min(tgtMap1->getIndexBase(), tgtMap2->getIndexBase());
1563 RCP<const map_type> unionTgtMap =
1564 rcp(
new map_type(INVALID, unionTgtGIDs(), indexBaseUnion, comm));
1566 #ifdef HAVE_TPETRA_MMM_TIMINGS
1567 MM2.disableTimer(label);
1568 label =
"Tpetra::Import::setUnion : Export GIDs";
1569 TimeMonitor MM3(*TimeMonitor::getNewTimer(label));
1580 Array<GO> exportGIDsUnion;
1581 Array<LO> exportLIDsUnion;
1582 Array<int> exportPIDsUnion;
1583 Distributor distributor (comm, this->TransferData_->out_);
1585 #ifdef TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1593 ArrayView<const LO> exportLIDs1 = this->getExportLIDs ();
1594 ArrayView<const LO> exportPIDs1 = this->getExportPIDs ();
1607 Array<LO> exportLIDs1Copy (exportLIDs1.begin (), exportLIDs1.end ());
1608 Array<int> exportPIDs1Copy (exportLIDs1.begin (), exportLIDs1.end ());
1609 sort2 (exportLIDs1Copy.begin (), exportLIDs1Copy.end (),
1610 exportPIDs1Copy.begin ());
1611 typename ArrayView<LO>::iterator exportLIDs1_end = exportLIDs1Copy.end ();
1612 typename ArrayView<LO>::iterator exportPIDs1_end = exportPIDs1Copy.end ();
1613 merge2 (exportLIDs1_end, exportPIDs1_end,
1614 exportLIDs1Copy.begin (), exportLIDs1_end,
1615 exportPIDs1Copy.begin (), exportPIDs1_end,
1618 Array<LO> exportLIDs2Copy (exportLIDs2.begin (), exportLIDs2.end ());
1619 Array<int> exportPIDs2Copy (exportLIDs2.begin (), exportLIDs2.end ());
1620 sort2 (exportLIDs2Copy.begin (), exportLIDs2Copy.end (),
1621 exportPIDs2Copy.begin ());
1622 typename ArrayView<LO>::iterator exportLIDs2_end = exportLIDs2Copy.end ();
1623 typename ArrayView<LO>::iterator exportPIDs2_end = exportPIDs2Copy.end ();
1624 merge2 (exportLIDs2_end, exportPIDs2_end,
1625 exportLIDs2Copy.begin (), exportLIDs2_end,
1626 exportPIDs2Copy.begin (), exportPIDs2_end,
1633 keyValueMerge (exportLIDs1Copy.begin (), exportLIDs1Copy.end (),
1634 exportPIDs1Copy.begin (), exportPIDs1Copy.end (),
1635 exportLIDs2Copy.begin (), exportLIDs2Copy.end (),
1636 exportPIDs2Copy.begin (), exportPIDs2Copy.end (),
1637 std::back_inserter (exportLIDsUnion),
1638 std::back_inserter (exportPIDsUnion),
1642 sort2 (exportPIDsUnion.begin (), exportPIDsUnion.end (),
1643 exportLIDsUnion.begin ());
1649 #else // NOT TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1657 remotePIDsUnion().getConst(),
1658 exportGIDsUnion, exportPIDsUnion);
1661 const size_type numExportIDsUnion = exportGIDsUnion.size ();
1662 exportLIDsUnion.resize (numExportIDsUnion);
1663 for (size_type k = 0; k < numExportIDsUnion; ++k) {
1664 exportLIDsUnion[k] = srcMap->getLocalElement (exportGIDsUnion[k]);
1666 #endif // TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1669 #ifdef HAVE_TPETRA_MMM_TIMINGS
1670 MM3.disableTimer(label);
1671 label =
"Tpetra::Import::setUnion : Construct Import";
1672 TimeMonitor MM4(*TimeMonitor::getNewTimer(label));
1674 RCP<const import_type> unionImport =
1675 rcp (
new import_type (srcMap, unionTgtMap,
1676 as<size_t> (numSameIDsUnion),
1677 permuteToLIDsUnion, permuteFromLIDsUnion,
1678 remoteLIDsUnion, exportLIDsUnion,
1679 exportPIDsUnion, distributor,
1680 this->TransferData_->out_));
1684 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1685 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
1689 using Teuchos::Array;
1690 using Teuchos::ArrayView;
1692 using Teuchos::Comm;
1695 using Teuchos::outArg;
1696 using Teuchos::REDUCE_MIN;
1697 using Teuchos::reduceAll;
1698 typedef LocalOrdinal LO;
1699 typedef GlobalOrdinal GO;
1700 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> > unionImport;
1701 RCP<const map_type> srcMap = this->getSourceMap ();
1702 RCP<const map_type> tgtMap = this->getTargetMap ();
1703 RCP<const Comm<int> > comm = srcMap->getComm ();
1705 ArrayView<const GO> srcGIDs = srcMap->getNodeElementList ();
1706 ArrayView<const GO> tgtGIDs = tgtMap->getNodeElementList ();
1709 size_t numSameIDsNew = srcMap->getNodeNumElements ();
1710 size_t numRemoteIDsNew = this->getNumRemoteIDs ();
1711 Array<LO> permuteToLIDsNew, permuteFromLIDsNew;
1714 ArrayView<const LO> remoteLIDsOld = this->getRemoteLIDs ();
1715 ArrayView<const LO> exportLIDsOld = this->getExportLIDs ();
1718 Array<GO> GIDs(numSameIDsNew + numRemoteIDsNew);
1719 for(
size_t i=0; i<numSameIDsNew; i++)
1720 GIDs[i] = srcGIDs[i];
1723 Array<LO> remoteLIDsNew(numRemoteIDsNew);
1724 for(
size_t i=0; i<numRemoteIDsNew; i++) {
1725 GIDs[numSameIDsNew + i] = tgtGIDs[remoteLIDsOld[i]];
1726 remoteLIDsNew[i] = numSameIDsNew+i;
1730 GO GO_INVALID = Teuchos::OrdinalTraits<GO>::invalid();
1731 RCP<const map_type> targetMapNew =
1732 rcp (
new map_type (GO_INVALID, GIDs, tgtMap->getIndexBase (),
1733 tgtMap->getComm ()));
1736 Array<int> exportPIDsnew (this->getExportPIDs ());
1737 Array<LO> exportLIDsnew (this->getExportLIDs ());
1755 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1756 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
1760 using ::Tpetra::Details::Behavior;
1761 using ::Tpetra::Details::gathervPrint;
1762 using Teuchos::outArg;
1764 using Teuchos::REDUCE_MIN;
1765 using Teuchos::reduceAll;
1767 using LO = LocalOrdinal;
1768 using GO = GlobalOrdinal;
1771 const char funcPrefix[] =
"Tpetra::createRemoteOnlyImport: ";
1774 const bool debug = Behavior::debug ();
1776 const size_t NumRemotes = this->getNumRemoteIDs ();
1777 std::unique_ptr<std::string> procPrefix;
1778 Teuchos::RCP<const Teuchos::Comm<int>> comm;
1780 comm = remoteTarget.is_null () ? Teuchos::null :
1781 remoteTarget->getComm ();
1782 std::ostringstream os;
1784 if (comm.is_null ()) {
1788 os << comm->getRank ();
1791 procPrefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
1795 std::ostringstream lclErr;
1796 if (remoteTarget.is_null ()) {
1799 else if (NumRemotes != remoteTarget->getNodeNumElements ()) {
1801 lclErr << *procPrefix <<
"getNumRemoteIDs() = " << NumRemotes
1802 <<
" != remoteTarget->getNodeNumElements() = "
1803 << remoteTarget->getNodeNumElements () <<
"." << endl;
1806 if (comm.is_null ()) {
1807 lclSuccess = gblSuccess;
1810 reduceAll (*comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
1812 TEUCHOS_TEST_FOR_EXCEPTION
1813 (gblSuccess == -1, std::invalid_argument, funcPrefix
1814 <<
"Input target Map is null on at least one process.");
1816 if (gblSuccess != 1) {
1817 if (comm.is_null ()) {
1818 TEUCHOS_TEST_FOR_EXCEPTION
1819 (
true, std::runtime_error, lclErr.str ());
1822 std::ostringstream gblErr;
1823 gblErr << funcPrefix << endl;
1824 gathervPrint (gblErr, lclErr.str (), *comm);
1825 TEUCHOS_TEST_FOR_EXCEPTION
1826 (
true, std::runtime_error, gblErr.str ());
1832 Teuchos::ArrayView<const LO> oldRemoteLIDs = this->getRemoteLIDs ();
1833 Teuchos::Array<LO> newRemoteLIDs (NumRemotes);
1834 const map_type& tgtMap = * (this->getTargetMap ());
1835 size_t badCount = 0;
1837 std::unique_ptr<std::vector<size_t>> badIndices;
1839 badIndices = std::unique_ptr<std::vector<size_t>> (
new std::vector<size_t>);
1844 for (
size_t i = 0; i < NumRemotes; ++i) {
1845 const LO oldLclInd = oldRemoteLIDs[i];
1846 if (oldLclInd == Teuchos::OrdinalTraits<LO>::invalid ()) {
1848 if (debug) { badIndices->push_back (i); }
1852 if (gblInd == Teuchos::OrdinalTraits<GO>::invalid ()) {
1854 if (debug) { badIndices->push_back (i); }
1857 const LO newLclInd = remoteTarget->getLocalElement (gblInd);
1858 if (newLclInd == Teuchos::OrdinalTraits<LO>::invalid ()) {
1860 if (debug) { badIndices->push_back (i); }
1863 newRemoteLIDs[i] = newLclInd;
1865 if (i > 0 && newRemoteLIDs[i] < newRemoteLIDs[i-1]) {
1867 if (debug) { badIndices->push_back (i); }
1871 if (badCount != 0) {
1876 if (comm.is_null ()) {
1877 lclSuccess = gblSuccess;
1880 reduceAll (*comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
1882 std::ostringstream lclErr;
1883 if (lclSuccess != 1) {
1884 lclErr << *procPrefix <<
"Count of bad indices: " << badCount
1885 <<
", bad indices: [";
1888 for (
size_t k = 0; k < badCount; ++k) {
1889 const size_t badIndex = (*badIndices)[k];
1890 lclErr <<
"(" << badIndex <<
","
1891 << oldRemoteLIDs[badIndex] <<
")";
1892 if (k +
size_t (1) < badCount) {
1896 lclErr <<
"]" << endl;
1899 if (gblSuccess != 1) {
1900 std::ostringstream gblErr;
1901 gblErr << funcPrefix <<
"this->getRemoteLIDs() has \"bad\" "
1902 "indices on one or more processes. \"Bad\" means that the "
1903 "indices are invalid, they don't exist in the target Map, "
1904 "they don't exist in remoteTarget, or they are not in "
1905 "sorted order. In what follows, I will show the \"bad\" "
1906 "indices as (k, LID) pairs, where k is the zero-based "
1907 "index of the LID in this->getRemoteLIDs()." << endl;
1908 if (comm.is_null ()) {
1909 gblErr << lclErr.str ();
1912 gathervPrint (gblErr, lclErr.str (), *comm);
1914 TEUCHOS_TEST_FOR_EXCEPTION
1915 (
true, std::runtime_error, gblErr.str ());
1919 TEUCHOS_TEST_FOR_EXCEPTION
1920 (lclSuccess == 0, std::runtime_error, funcPrefix
1921 <<
"this->getRemoteLIDs() has " << badCount
1922 <<
"ind" << (badCount == 1 ?
"ex" :
"ices")
1923 <<
" \"bad\" indices on this process." << endl);
1931 Teuchos::Array<int> newExportPIDs (this->getExportPIDs ());
1932 Teuchos::Array<LO> newExportLIDs (this->getExportLIDs ());
1933 Teuchos::Array<LO> dummy;
1936 return rcp (
new import_type (this->getSourceMap (), remoteTarget,
1937 static_cast<size_t> (0), dummy, dummy,
1938 newRemoteLIDs, newExportLIDs,
1939 newExportPIDs, newDistor));
1944 #define TPETRA_IMPORT_CLASS_INSTANT(LO, GO, NODE) \
1945 template class Import< LO , GO , NODE >;
1954 #define TPETRA_IMPORT_INSTANT(LO, GO, NODE) \
1955 TPETRA_IMPORT_CLASS_INSTANT(LO, GO, NODE)
1957 #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.
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.
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.