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 ());
599 if (verbose && gblStatus[0] != 1) {
600 std::ostringstream os;
601 os << *verboseHeader <<
"- Some input PIDs are invalid: ";
602 printArray (os, badPIDs.data (), badPIDs.size ());
608 std::ostringstream os;
609 os <<
"Tpetra::Import constructor that takes remote GIDs and PIDs: ";
610 if (gblStatus[0] != 1) {
611 os <<
"Some input GIDs (global indices) are already in the source Map! ";
613 if (gblStatus[1] != 1) {
614 os <<
"Some input PIDs (process ranks) are invalid! ";
616 os <<
"Rerun with the environment variable TPETRA_VERBOSE=Tpetra::Import "
617 "to see what GIDs and/or PIDs are bad.";
618 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument, os.str ());
625 const LO numLclSrcIDs =
static_cast<LO
> (sourceMap.getLocalNumElements ());
626 const LO numLclTgtIDs = numLclSrcIDs + numTargetMapRemoteOrPermuteGlobalIndices;
628 std::ostringstream os;
629 os << *verboseHeader <<
"- Copy source Map GIDs into target Map GID list: "
630 "numLclSrcIDs=" << numLclSrcIDs
631 <<
", numTargetMapRemoteOrPermuteGlobalIndices="
632 << numTargetMapRemoteOrPermuteGlobalIndices << endl;
635 std::vector<GO> tgtGIDs (numLclTgtIDs);
636 if (sourceMap.isContiguous ()) {
637 GO curTgtGID = sourceMap.getMinGlobalIndex ();
638 for (LO k = 0; k < numLclSrcIDs; ++k, ++curTgtGID) {
639 tgtGIDs[k] = curTgtGID;
643 auto srcGIDs = sourceMap.getLocalElementList ();
644 for (LO k = 0; k < numLclSrcIDs; ++k) {
645 tgtGIDs[k] = srcGIDs[k];
648 std::copy (targetMapRemoteOrPermuteGlobalIndices,
649 targetMapRemoteOrPermuteGlobalIndices + numTargetMapRemoteOrPermuteGlobalIndices,
650 tgtGIDs.begin () + numLclSrcIDs);
663 std::ostringstream os;
664 os << *verboseHeader <<
"- Sort by PID? "
665 << (mayReorderTargetMapIndicesLocally ?
"true" :
"false") << endl;
668 std::vector<int> tgtPIDs (targetMapRemoteOrPermuteProcessRanks,
669 targetMapRemoteOrPermuteProcessRanks + numTargetMapRemoteOrPermuteGlobalIndices);
670 result.numPermutes = 0;
671 if (mayReorderTargetMapIndicesLocally) {
672 Tpetra::sort2 (tgtPIDs.begin (), tgtPIDs.end (), tgtGIDs.begin () + numLclSrcIDs);
673 auto range = std::equal_range (tgtPIDs.begin (), tgtPIDs.end (), myRank);
674 if (range.second > range.first) {
675 result.numPermutes =
static_cast<LO
> (range.second - range.first);
679 result.numPermutes =
static_cast<LO
> (std::count (tgtPIDs.begin (), tgtPIDs.end (), myRank));
682 const LO numRemotes = numTargetMapRemoteOrPermuteGlobalIndices - result.numPermutes;
683 result.numSameIDs =
static_cast<LO
> (sourceMap.getLocalNumElements ());
686 std::ostringstream os;
687 os << *verboseHeader <<
"- numSame=" << result.numSameIDs
688 <<
", numPermutes=" << result.numPermutes
689 <<
", numRemotes=" << numRemotes << endl;
693 if (result.numPermutes == 0) {
695 std::ostringstream os;
696 os << *verboseHeader <<
"- No permutes" << endl;
699 result.remoteGIDs = std::vector<GO> (tgtGIDs.begin () + numLclSrcIDs, tgtGIDs.end ());
700 result.remotePIDs.swap (tgtPIDs);
701 result.remoteLIDs.resize (numRemotes);
702 for (LO k = 0; k < numRemotes; ++k) {
703 const LO tgtLid = result.numSameIDs + k;
704 result.remoteLIDs[k] = tgtLid;
707 std::ostringstream os;
708 os << *verboseHeader <<
"- Remote GIDs: "
709 << Teuchos::toString (result.remoteGIDs) << endl;
710 os << *verboseHeader <<
"- Remote PIDs: "
711 << Teuchos::toString (result.remotePIDs) << endl;
712 os << *verboseHeader <<
"- Remote LIDs: "
713 << Teuchos::toString (result.remoteLIDs) << endl;
721 result.remoteGIDs.reserve (numRemotes);
722 result.remoteLIDs.reserve (numRemotes);
723 result.remotePIDs.reserve (numRemotes);
724 for (LO k = 0; k < numTargetMapRemoteOrPermuteGlobalIndices; ++k) {
725 const LO tgtLid = result.numSameIDs + k;
726 const GO tgtGid = tgtGIDs[numLclSrcIDs + k];
727 const int tgtPid = tgtPIDs[k];
729 if (tgtPid != myRank) {
730 result.remoteGIDs.push_back (tgtGid);
731 result.remoteLIDs.push_back (tgtLid);
732 result.remotePIDs.push_back (tgtPid);
736 std::ostringstream os;
737 os << *verboseHeader <<
"- Some permutes" << endl;
742 if (sourceMap.isDistributed ()) {
744 std::ostringstream os;
745 os << *verboseHeader <<
"- Sort remotes by PID, as Import always does"
747 << *verboseHeader <<
"-- remotePIDs before: "
748 << Teuchos::toString (result.remotePIDs) << endl
749 << *verboseHeader <<
"-- remoteGIDs before: "
750 << Teuchos::toString (result.remoteGIDs) << endl
751 << *verboseHeader <<
"-- remoteLIDs before: "
752 << Teuchos::toString (result.remoteLIDs) << endl;
756 sort3 (result.remotePIDs.begin (),
757 result.remotePIDs.end (),
758 result.remoteGIDs.begin (),
759 result.remoteLIDs.begin ());
761 std::ostringstream os;
762 os << *verboseHeader <<
"-- remotePIDs after: "
763 << Teuchos::toString (result.remotePIDs) << endl
764 << *verboseHeader <<
"-- remoteGIDs after: "
765 << Teuchos::toString (result.remoteGIDs) << endl
766 << *verboseHeader <<
"-- remoteLIDs after: "
767 << Teuchos::toString (result.remoteLIDs) << endl;
768 std::cerr << os.str ();
773 std::ostringstream os;
774 os << *verboseHeader <<
"- Make target Map" << endl;
777 using ::Teuchos::rcp;
778 typedef ::Tpetra::Map<LO, GO, NT>
map_type;
780 const GST MAP_COMPUTES_GLOBAL_COUNT = ::Teuchos::OrdinalTraits<GST>::invalid ();
781 result.targetMap = rcp (
new map_type (MAP_COMPUTES_GLOBAL_COUNT,
784 sourceMap.getIndexBase (),
785 sourceMap.getComm ()));
787 std::ostringstream os;
788 os << *verboseHeader <<
"- Done with sameSPR..." << endl;
795 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
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")
811 using ::Tpetra::Details::makeDualViewFromVector;
812 using ::Tpetra::Details::printDualView;
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;
864 localSetupResult.remoteLIDs,
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 ());
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 ();
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;
924 "ImportExportData::remoteLIDs_");
928 if (this->verbose ()) {
929 std::ostringstream os;
930 os << *verbPfx <<
"Done!" << endl;
935 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
938 describe (Teuchos::FancyOStream& out,
939 const Teuchos::EVerbosityLevel verbLevel)
const
945 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
947 print (std::ostream& os)
const
949 auto out = Teuchos::getFancyOStream (Teuchos::rcpFromRef (os));
951 this->
describe (*out, Teuchos::VERB_EXTREME);
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;
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));
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)) {
1484 ArrayView<const GO> sameGIDs1 = (tgtMap1->getLocalElementList())(0,numSameGIDs1);
1487 ArrayView<const GO> sameGIDs2 = (tgtMap2->getLocalElementList())(0,numSameGIDs2);
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]);
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;
1515 Array<int> remotePIDs2;
1519 Array<GO> unionTgtGIDs;
1520 Array<std::pair<int,GO>> remotePGIDs;
1521 size_type numSameIDsUnion, numPermuteIDsUnion, numRemoteIDsUnion;
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;
1581#ifdef TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
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 ());
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]);
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 =
1672 as<size_t> (numSameIDsUnion),
1673 permuteToLIDsUnion, permuteFromLIDsUnion,
1674 remoteLIDsUnion, exportLIDsUnion,
1675 exportPIDsUnion, distributor,
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 ();
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);
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);
1927 Teuchos::Array<LO> dummy;
1931 static_cast<size_t> (0), dummy, dummy,
1932 newRemoteLIDs, newExportLIDs,
1933 newExportPIDs, newDistor));