42 #ifndef TPETRA_IMPORT_DEF_HPP
43 #define TPETRA_IMPORT_DEF_HPP
45 #include "Tpetra_Distributor.hpp"
46 #include "Tpetra_Map.hpp"
47 #include "Tpetra_ImportExportData.hpp"
50 #include "Tpetra_Export.hpp"
52 #include "Tpetra_Details_DualViewUtil.hpp"
53 #include "Tpetra_Details_gathervPrint.hpp"
55 #include "Teuchos_as.hpp"
56 #ifdef HAVE_TPETRA_MMM_TIMINGS
57 #include "Teuchos_TimeMonitor.hpp"
64 std::string toString (
const std::vector<T>& x)
66 std::ostringstream os;
68 const std::size_t N = x.size ();
69 for (std::size_t k = 0; k < N; ++k) {
71 if (k + std::size_t (1) < N) {
79 template<
class ElementType,
class DeviceType>
80 std::string toString (
const Kokkos::View<const ElementType*, DeviceType>& x)
82 std::ostringstream os;
84 const std::size_t N = std::size_t (x.extent (0));
85 for (std::size_t k = 0; k < N; ++k) {
87 if (k + std::size_t (1) < N) {
100 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
102 Import<LocalOrdinal,GlobalOrdinal,Node>::
103 init (
const Teuchos::RCP<const map_type>& source,
104 const Teuchos::RCP<const map_type>& ,
106 Teuchos::Array<int> & remotePIDs,
107 const Teuchos::RCP<Teuchos::ParameterList>& plist)
109 using ::Tpetra::Details::ProfilingRegion;
110 using Teuchos::Array;
115 ProfilingRegion regionImportInit (
"Tpetra::Import::init");
117 std::unique_ptr<std::string> verbPrefix;
118 if (this->verbose ()) {
119 std::ostringstream os;
120 const int myRank = source->getComm ()->getRank ();
121 os <<
"Proc " << myRank <<
": Tpetra::Import::init: ";
122 verbPrefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
124 this->verboseOutputStream () << os.str ();
127 Array<GlobalOrdinal> remoteGIDs;
129 #ifdef HAVE_TPETRA_MMM_TIMINGS
130 using Teuchos::TimeMonitor;
133 label = plist->get(
"Timer Label",label);
134 std::string prefix = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:preIData: ");
139 #ifdef HAVE_TPETRA_MMM_TIMINGS
140 auto MM(*TimeMonitor::getNewTimer(prefix));
142 if (this->verbose ()) {
143 std::ostringstream os;
144 os << *verbPrefix <<
"Call setupSamePermuteRemote" << endl;
145 this->verboseOutputStream () << os.str ();
147 setupSamePermuteRemote (remoteGIDs);
150 #ifdef HAVE_TPETRA_MMM_TIMINGS
151 prefix = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:preSetupExport: ");
152 auto MM2(*TimeMonitor::getNewTimer(prefix));
154 if (source->isDistributed ()) {
155 if (this->verbose ()) {
156 std::ostringstream os;
157 os << *verbPrefix <<
"Call setupExport" << endl;
158 this->verboseOutputStream () << os.str ();
160 setupExport (remoteGIDs,useRemotePIDs,remotePIDs);
162 else if (this->verbose ()) {
163 std::ostringstream os;
164 os << *verbPrefix <<
"Source Map not distributed; skip setupExport"
166 this->verboseOutputStream () << os.str ();
170 TEUCHOS_ASSERT( ! this->TransferData_->permuteFromLIDs_.need_sync_device () );
171 TEUCHOS_ASSERT( ! this->TransferData_->permuteFromLIDs_.need_sync_host () );
172 TEUCHOS_ASSERT( ! this->TransferData_->permuteToLIDs_.need_sync_device () );
173 TEUCHOS_ASSERT( ! this->TransferData_->permuteToLIDs_.need_sync_host () );
174 TEUCHOS_ASSERT( ! this->TransferData_->remoteLIDs_.need_sync_device () );
175 TEUCHOS_ASSERT( ! this->TransferData_->remoteLIDs_.need_sync_host () );
176 TEUCHOS_ASSERT( ! this->TransferData_->exportLIDs_.need_sync_device () );
177 TEUCHOS_ASSERT( ! this->TransferData_->exportLIDs_.need_sync_host () );
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->getNodeElementList ();
298 ArrayView<const GO> targetGIDs = target->getNodeElementList ();
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);
361 for (size_type j = 0; j < indexIntoRemotePIDs; ++j)
362 if(tRemotePIDs[j] != -1) {
363 newRemoteGIDs[cnt] = tRemoteGIDs[j];
364 newRemotePIDs[cnt] = tRemotePIDs[j];
365 newRemoteLIDs[cnt] = target->getLocalElement(tRemoteGIDs[j]);
368 indexIntoRemotePIDs = cnt;
369 tRemoteGIDs = newRemoteGIDs;
370 tRemotePIDs = newRemotePIDs;
372 newRemoteLIDs ().getConst (),
376 indexIntoRemotePIDs = 0;
383 this->
TransferData_->exportPIDs_ = Teuchos::Array<int> (userExportPIDs);
385 userExportLIDs,
"exportLIDs");
387 bool locallyComplete =
true;
388 for (size_type i = 0; i < userExportPIDs.size () && locallyComplete; ++i) {
389 if (userExportPIDs[i] == -1) {
390 locallyComplete =
false;
396 std::ostringstream os;
397 os << *prefix <<
"locallyComplete: "
398 << (locallyComplete ?
"true" :
"false")
399 <<
"; call createFromSendsAndRecvs" << endl;
403 #ifdef HAVE_TPETRA_MMM_TIMINGS
404 std::string mmm_prefix =
405 std::string(
"Tpetra ") + std::string(
":iport_ctor:cFSAR ");
407 auto MM3(*Teuchos::TimeMonitor::getNewTimer(mmm_prefix));
413 TEUCHOS_ASSERT( ! this->
TransferData_->permuteFromLIDs_.need_sync_device () );
414 TEUCHOS_ASSERT( ! this->
TransferData_->permuteFromLIDs_.need_sync_host () );
415 TEUCHOS_ASSERT( ! this->
TransferData_->permuteToLIDs_.need_sync_device () );
416 TEUCHOS_ASSERT( ! this->
TransferData_->permuteToLIDs_.need_sync_host () );
417 TEUCHOS_ASSERT( ! this->
TransferData_->remoteLIDs_.need_sync_device () );
418 TEUCHOS_ASSERT( ! this->
TransferData_->remoteLIDs_.need_sync_host () );
419 TEUCHOS_ASSERT( ! this->
TransferData_->exportLIDs_.need_sync_device () );
420 TEUCHOS_ASSERT( ! this->
TransferData_->exportLIDs_.need_sync_host () );
423 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
425 Import (
const Teuchos::RCP<const map_type>& source,
426 const Teuchos::RCP<const map_type>& target,
427 const size_t numSameIDs,
428 Teuchos::Array<LocalOrdinal>& permuteToLIDs,
429 Teuchos::Array<LocalOrdinal>& permuteFromLIDs,
430 Teuchos::Array<LocalOrdinal>& remoteLIDs,
431 Teuchos::Array<LocalOrdinal>& exportLIDs,
432 Teuchos::Array<int>& exportPIDs,
434 const Teuchos::RCP<Teuchos::FancyOStream>& out,
435 const Teuchos::RCP<Teuchos::ParameterList>& plist) :
436 base_type (source, target, out, plist,
"Import")
438 using ::Tpetra::Details::makeDualViewFromArrayView;
441 std::unique_ptr<std::string> prefix;
443 auto comm = source.is_null () ? Teuchos::null : source->getComm ();
444 const int myRank = comm.is_null () ? -1 : comm->getRank ();
445 std::ostringstream os;
446 os <<
"Proc " << myRank <<
": Tpetra::Import export ctor: ";
447 prefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
448 os <<
"Start" << endl;
452 bool locallyComplete =
true;
453 for (Teuchos::Array<int>::size_type i = 0; i < exportPIDs.size (); ++i) {
454 if (exportPIDs[i] == -1) {
455 locallyComplete =
false;
459 std::ostringstream os;
460 os << *prefix <<
"numSameIDs: " << numSameIDs <<
", locallyComplete: "
461 << (locallyComplete ?
"true" :
"false") << endl;
468 makeDualViewFromArrayView (this->
TransferData_->permuteToLIDs_,
469 permuteToLIDs ().getConst (),
471 TEUCHOS_ASSERT(
size_t (this->
TransferData_->permuteToLIDs_.extent (0)) ==
472 size_t (permuteToLIDs.size ()) );
473 makeDualViewFromArrayView (this->
TransferData_->permuteFromLIDs_,
474 permuteFromLIDs ().getConst (),
476 TEUCHOS_ASSERT(
size_t (this->
TransferData_->permuteFromLIDs_.extent (0)) ==
477 size_t (permuteFromLIDs.size ()) );
479 remoteLIDs ().getConst (),
481 TEUCHOS_ASSERT(
size_t (this->
TransferData_->remoteLIDs_.extent (0)) ==
482 size_t (remoteLIDs.size ()) );
484 exportLIDs ().getConst (),
486 TEUCHOS_ASSERT(
size_t (this->
TransferData_->exportLIDs_.extent (0)) ==
487 size_t (exportLIDs.size ()) );
491 TEUCHOS_ASSERT( ! this->
TransferData_->permuteFromLIDs_.need_sync_device () );
492 TEUCHOS_ASSERT( ! this->
TransferData_->permuteFromLIDs_.need_sync_host () );
493 TEUCHOS_ASSERT( ! this->
TransferData_->permuteToLIDs_.need_sync_device () );
494 TEUCHOS_ASSERT( ! this->
TransferData_->permuteToLIDs_.need_sync_host () );
495 TEUCHOS_ASSERT( ! this->
TransferData_->remoteLIDs_.need_sync_device () );
496 TEUCHOS_ASSERT( ! this->
TransferData_->remoteLIDs_.need_sync_host () );
497 TEUCHOS_ASSERT( ! this->
TransferData_->exportLIDs_.need_sync_device () );
498 TEUCHOS_ASSERT( ! this->
TransferData_->exportLIDs_.need_sync_host () );
503 template <
class LO,
class GO,
class NT>
504 struct ImportLocalSetupResult
506 Teuchos::RCP<const ::Tpetra::Map<LO, GO, NT> > targetMap;
510 std::vector<GO> remoteGIDs;
511 std::vector<LO> remoteLIDs;
512 std::vector<int> remotePIDs;
517 void printArray (std::ostream& out,
const T x[],
const std::size_t N)
520 for (std::size_t k = 0; k < N; ++k) {
529 template<
class LO,
class GO,
class NT>
530 ImportLocalSetupResult<LO, GO, NT>
531 setupSamePermuteRemoteFromUserGlobalIndexList (const ::Tpetra::Map<LO, GO, NT>& sourceMap,
532 const GO targetMapRemoteOrPermuteGlobalIndices[],
533 const int targetMapRemoteOrPermuteProcessRanks[],
534 const LO numTargetMapRemoteOrPermuteGlobalIndices,
535 const bool mayReorderTargetMapIndicesLocally,
536 Teuchos::FancyOStream* out,
537 const std::string* verboseHeader,
542 const int myRank = sourceMap.getComm ()->getRank ();
543 ImportLocalSetupResult<LO, GO, NT> result;
546 std::ostringstream os;
547 os << *verboseHeader <<
"- Import::setupSPR w/ remote GIDs & PIDs: " << endl
548 << *verboseHeader <<
" Input GIDs: ";
549 printArray (os, targetMapRemoteOrPermuteGlobalIndices, numTargetMapRemoteOrPermuteGlobalIndices);
550 os << endl <<
" Input PIDs: ";
551 printArray (os, targetMapRemoteOrPermuteProcessRanks, numTargetMapRemoteOrPermuteGlobalIndices);
561 std::vector<GO> badGIDs;
562 std::vector<int> badPIDs;
563 const Teuchos::Comm<int>& comm = * (sourceMap.getComm ());
564 const int numProcs = comm.getSize ();
566 for (LO k = 0; k < numTargetMapRemoteOrPermuteGlobalIndices; ++k) {
567 const GO tgtGID = targetMapRemoteOrPermuteGlobalIndices[k];
568 if (sourceMap.isNodeGlobalElement (tgtGID)) {
569 badGIDs.push_back (tgtGID);
571 const int tgtPID = targetMapRemoteOrPermuteProcessRanks[k];
572 if (tgtPID < 0 || tgtPID >= numProcs) {
573 badPIDs.push_back (tgtPID);
577 std::array<int, 2> lclStatus {{
578 badGIDs.size () == 0 ? 1 : 0,
579 badPIDs.size () == 0 ? 1 : 0
581 std::array<int, 2> gblStatus {{0, 0}};
582 Teuchos::reduceAll<int, int> (comm, Teuchos::REDUCE_MIN, 2,
583 lclStatus.data (), gblStatus.data ());
584 const bool good = gblStatus[0] == 1 && gblStatus[1] == 1;
587 if (verbose && gblStatus[0] != 1) {
588 std::ostringstream os;
589 os << *verboseHeader <<
"- Some input GIDs are already in the source Map: ";
590 printArray (os, badGIDs.data (), badGIDs.size ());
592 ::Tpetra::Details::gathervPrint (*out, os.str (), comm);
594 if (verbose && gblStatus[0] != 1) {
595 std::ostringstream os;
596 os << *verboseHeader <<
"- Some input PIDs are invalid: ";
597 printArray (os, badPIDs.data (), badPIDs.size ());
599 ::Tpetra::Details::gathervPrint (*out, os.str (), comm);
603 std::ostringstream os;
604 os <<
"Tpetra::Import constructor that takes remote GIDs and PIDs: ";
605 if (gblStatus[0] != 1) {
606 os <<
"Some input GIDs (global indices) are already in the source Map! ";
608 if (gblStatus[1] != 1) {
609 os <<
"Some input PIDs (process ranks) are invalid! ";
611 os <<
"Rerun with the environment variable TPETRA_VERBOSE=Tpetra::Import "
612 "to see what GIDs and/or PIDs are bad.";
613 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument, os.str ());
620 const LO numLclSrcIDs =
static_cast<LO
> (sourceMap.getNodeNumElements ());
621 const LO numLclTgtIDs = numLclSrcIDs + numTargetMapRemoteOrPermuteGlobalIndices;
623 std::ostringstream os;
624 os << *verboseHeader <<
"- Copy source Map GIDs into target Map GID list: "
625 "numLclSrcIDs=" << numLclSrcIDs
626 <<
", numTargetMapRemoteOrPermuteGlobalIndices="
627 << numTargetMapRemoteOrPermuteGlobalIndices << endl;
630 std::vector<GO> tgtGIDs (numLclTgtIDs);
631 if (sourceMap.isContiguous ()) {
632 GO curTgtGID = sourceMap.getMinGlobalIndex ();
633 for (LO k = 0; k < numLclSrcIDs; ++k, ++curTgtGID) {
634 tgtGIDs[k] = curTgtGID;
638 auto srcGIDs = sourceMap.getNodeElementList ();
639 for (LO k = 0; k < numLclSrcIDs; ++k) {
640 tgtGIDs[k] = srcGIDs[k];
643 std::copy (targetMapRemoteOrPermuteGlobalIndices,
644 targetMapRemoteOrPermuteGlobalIndices + numTargetMapRemoteOrPermuteGlobalIndices,
645 tgtGIDs.begin () + numLclSrcIDs);
658 std::ostringstream os;
659 os << *verboseHeader <<
"- Sort by PID? "
660 << (mayReorderTargetMapIndicesLocally ?
"true" :
"false") << endl;
663 std::vector<int> tgtPIDs (targetMapRemoteOrPermuteProcessRanks,
664 targetMapRemoteOrPermuteProcessRanks + numTargetMapRemoteOrPermuteGlobalIndices);
665 result.numPermutes = 0;
666 if (mayReorderTargetMapIndicesLocally) {
667 Tpetra::sort2 (tgtPIDs.begin (), tgtPIDs.end (), tgtGIDs.begin () + numLclSrcIDs);
668 auto range = std::equal_range (tgtPIDs.begin (), tgtPIDs.end (), myRank);
669 if (range.second > range.first) {
670 result.numPermutes =
static_cast<LO
> (range.second - range.first);
674 result.numPermutes =
static_cast<LO
> (std::count (tgtPIDs.begin (), tgtPIDs.end (), myRank));
677 const LO numRemotes = numTargetMapRemoteOrPermuteGlobalIndices - result.numPermutes;
678 result.numSameIDs =
static_cast<LO
> (sourceMap.getNodeNumElements ());
681 std::ostringstream os;
682 os << *verboseHeader <<
"- numSame=" << result.numSameIDs
683 <<
", numPermutes=" << result.numPermutes
684 <<
", numRemotes=" << numRemotes << endl;
688 if (result.numPermutes == 0) {
690 std::ostringstream os;
691 os << *verboseHeader <<
"- No permutes" << endl;
694 result.remoteGIDs = std::vector<GO> (tgtGIDs.begin () + numLclSrcIDs, tgtGIDs.end ());
695 result.remotePIDs.swap (tgtPIDs);
696 result.remoteLIDs.resize (numRemotes);
697 for (LO k = 0; k < numRemotes; ++k) {
698 const LO tgtLid = result.numSameIDs + k;
699 result.remoteLIDs[k] = tgtLid;
702 std::ostringstream os;
703 os << *verboseHeader <<
"- Remote GIDs: "
704 << Teuchos::toString (result.remoteGIDs) << endl;
705 os << *verboseHeader <<
"- Remote PIDs: "
706 << Teuchos::toString (result.remotePIDs) << endl;
707 os << *verboseHeader <<
"- Remote LIDs: "
708 << Teuchos::toString (result.remoteLIDs) << endl;
716 result.remoteGIDs.reserve (numRemotes);
717 result.remoteLIDs.reserve (numRemotes);
718 result.remotePIDs.reserve (numRemotes);
719 for (LO k = 0; k < numTargetMapRemoteOrPermuteGlobalIndices; ++k) {
720 const LO tgtLid = result.numSameIDs + k;
721 const GO tgtGid = tgtGIDs[numLclSrcIDs + k];
722 const int tgtPid = tgtPIDs[k];
724 if (tgtPid != myRank) {
725 result.remoteGIDs.push_back (tgtGid);
726 result.remoteLIDs.push_back (tgtLid);
727 result.remotePIDs.push_back (tgtPid);
731 std::ostringstream os;
732 os << *verboseHeader <<
"- Some permutes" << endl;
737 if (sourceMap.isDistributed ()) {
739 std::ostringstream os;
740 os << *verboseHeader <<
"- Sort remotes by PID, as Import always does"
742 << *verboseHeader <<
"-- remotePIDs before: "
743 << Teuchos::toString (result.remotePIDs) << endl
744 << *verboseHeader <<
"-- remoteGIDs before: "
745 << Teuchos::toString (result.remoteGIDs) << endl
746 << *verboseHeader <<
"-- remoteLIDs before: "
747 << Teuchos::toString (result.remoteLIDs) << endl;
751 sort3 (result.remotePIDs.begin (),
752 result.remotePIDs.end (),
753 result.remoteGIDs.begin (),
754 result.remoteLIDs.begin ());
756 std::ostringstream os;
757 os << *verboseHeader <<
"-- remotePIDs after: "
758 << Teuchos::toString (result.remotePIDs) << endl
759 << *verboseHeader <<
"-- remoteGIDs after: "
760 << Teuchos::toString (result.remoteGIDs) << endl
761 << *verboseHeader <<
"-- remoteLIDs after: "
762 << Teuchos::toString (result.remoteLIDs) << endl;
763 std::cerr << os.str ();
768 std::ostringstream os;
769 os << *verboseHeader <<
"- Make target Map" << endl;
772 using ::Teuchos::rcp;
773 typedef ::Tpetra::Map<LO, GO, NT> map_type;
774 typedef ::Tpetra::global_size_t GST;
775 const GST MAP_COMPUTES_GLOBAL_COUNT = ::Teuchos::OrdinalTraits<GST>::invalid ();
776 result.targetMap = rcp (
new map_type (MAP_COMPUTES_GLOBAL_COUNT,
779 sourceMap.getIndexBase (),
780 sourceMap.getComm ()));
782 std::ostringstream os;
783 os << *verboseHeader <<
"- Done with sameSPR..." << endl;
790 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
793 const GlobalOrdinal targetMapRemoteOrPermuteGlobalIndices[],
794 const int targetMapRemoteOrPermuteProcessRanks[],
795 const LocalOrdinal numTargetMapRemoteOrPermuteGlobalIndices,
796 const bool mayReorderTargetMapIndicesLocally,
797 const Teuchos::RCP<Teuchos::ParameterList>& plist,
798 const Teuchos::RCP<Teuchos::FancyOStream>& debugOutput) :
802 base_type (sourceMap, Teuchos::null, debugOutput, plist,
"Import")
804 using ::Tpetra::Details::Behavior;
805 using ::Tpetra::Details::makeDualViewFromOwningHostView;
806 using ::Tpetra::Details::makeDualViewFromVector;
807 using ::Tpetra::Details::printDualView;
808 using ::Tpetra::Details::view_alloc_no_init;
809 using Teuchos::ArrayView;
810 using Teuchos::getFancyOStream;
813 using Teuchos::rcpFromRef;
815 typedef LocalOrdinal LO;
816 typedef GlobalOrdinal GO;
819 const bool debug = Behavior::debug (
"Import") ||
820 Behavior::debug (
"Tpetra::Import");
822 std::unique_ptr<std::string> verbPfx;
823 if (this->verbose ()) {
824 std::ostringstream os;
825 const int myRank = sourceMap->getComm ()->getRank ();
826 os <<
"Proc " << myRank <<
": Tpetra::Import ctor from remotes: ";
827 verbPfx = std::unique_ptr<std::string> (
new std::string (os.str ()));
828 os <<
"mayReorder=" << (mayReorderTargetMapIndicesLocally ?
"true" :
"false")
834 ImportLocalSetupResult<LO, GO, NT> localSetupResult =
835 setupSamePermuteRemoteFromUserGlobalIndexList<LO, GO, NT>
837 targetMapRemoteOrPermuteGlobalIndices,
838 targetMapRemoteOrPermuteProcessRanks,
839 numTargetMapRemoteOrPermuteGlobalIndices,
840 mayReorderTargetMapIndicesLocally,
852 localSetupResult.targetMap,
853 this->TransferData_->out_,
855 this->TransferData_->numSameIDs_ = localSetupResult.numSameIDs;
858 makeDualViewFromVector (this->TransferData_->remoteLIDs_,
859 localSetupResult.remoteLIDs,
868 this->TransferData_->isLocallyComplete_ =
true;
870 Teuchos::Array<GO> exportGIDs;
871 if (sourceMap->isDistributed ()) {
872 if (this->verbose ()) {
873 std::ostringstream os;
874 os << *verbPfx <<
"Make Distributor (createFromRecvs)" << endl;
877 ArrayView<const GO> remoteGIDs (localSetupResult.remoteGIDs.data (),
878 localSetupResult.remoteGIDs.size ());
879 ArrayView<const int> remotePIDs (localSetupResult.remotePIDs.data (),
880 localSetupResult.remotePIDs.size ());
885 Distributor& distributor = this->TransferData_->distributor_;
889 this->TransferData_->exportPIDs_);
898 if (this->verbose ()) {
899 std::ostringstream os;
900 os << *verbPfx <<
"Compute exportLIDs" << endl;
903 using size_type =
typename Teuchos::Array<GO>::size_type;
904 const size_type numExportIDs = exportGIDs.size ();
906 typename decltype (this->TransferData_->exportLIDs_)::t_host
907 exportLIDs (view_alloc_no_init (
"exportLIDs"), numExportIDs);
908 for (size_type k = 0; k < numExportIDs; ++k) {
909 exportLIDs[k] = sourceMap->getLocalElement (exportGIDs[k]);
911 makeDualViewFromOwningHostView (this->TransferData_->exportLIDs_, exportLIDs);
914 if (this->verbose ()) {
915 std::ostringstream os;
917 printDualView (os, this->TransferData_->remoteLIDs_,
918 "ImportExportData::remoteLIDs_");
922 if (this->verbose ()) {
923 std::ostringstream os;
924 os << *verbPfx <<
"Done!" << endl;
929 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
933 const Teuchos::EVerbosityLevel verbLevel)
const
936 this->describeImpl (out,
"Tpetra::Import", verbLevel);
939 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
943 auto out = Teuchos::getFancyOStream (Teuchos::rcpFromRef (os));
945 this->describe (*out, Teuchos::VERB_EXTREME);
948 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
953 using ::Tpetra::Details::makeDualViewFromOwningHostView;
954 using ::Tpetra::Details::ProfilingRegion;
955 using ::Tpetra::Details::view_alloc_no_init;
957 using Teuchos::Array;
958 using Teuchos::ArrayRCP;
959 using Teuchos::ArrayView;
962 typedef LocalOrdinal LO;
963 typedef GlobalOrdinal GO;
964 typedef typename ArrayView<const GO>::size_type size_type;
965 ProfilingRegion regionExport (
"Tpetra::Import::setupSamePermuteRemote");
967 const map_type& source = * (this->getSourceMap ());
968 const map_type& target = * (this->getTargetMap ());
969 ArrayView<const GO> sourceGIDs = source.getNodeElementList ();
970 ArrayView<const GO> targetGIDs = target.getNodeElementList ();
972 #ifdef HAVE_TPETRA_DEBUG
973 ArrayView<const GO> rawSrcGids = sourceGIDs;
974 ArrayView<const GO> rawTgtGids = targetGIDs;
976 const GO*
const rawSrcGids = sourceGIDs.getRawPtr ();
977 const GO*
const rawTgtGids = targetGIDs.getRawPtr ();
978 #endif // HAVE_TPETRA_DEBUG
979 const size_type numSrcGids = sourceGIDs.size ();
980 const size_type numTgtGids = targetGIDs.size ();
981 const size_type numGids = std::min (numSrcGids, numTgtGids);
989 size_type numSameGids = 0;
990 for ( ; numSameGids < numGids && rawSrcGids[numSameGids] == rawTgtGids[numSameGids]; ++numSameGids)
992 this->TransferData_->numSameIDs_ = numSameGids;
1006 const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid ();
1007 const LO numTgtLids = as<LO> (numTgtGids);
1009 for (LO tgtLid = numSameGids; tgtLid < numTgtLids; ++tgtLid) {
1010 const GO curTargetGid = rawTgtGids[tgtLid];
1014 const LO srcLid = source.getLocalElement (curTargetGid);
1015 if (srcLid != LINVALID) {
1019 const LO numRemotes = (numTgtLids - numSameGids) - numPermutes;
1021 using host_perm_type =
1022 typename decltype (this->TransferData_->permuteToLIDs_)::t_host;
1023 host_perm_type permuteToLIDs
1024 (view_alloc_no_init (
"permuteToLIDs"), numPermutes);
1025 host_perm_type permuteFromLIDs
1026 (view_alloc_no_init (
"permuteFromLIDs"), numPermutes);
1027 typename decltype (this->TransferData_->remoteLIDs_)::t_host remoteLIDs
1031 LO numPermutes2 = 0;
1033 for (LO tgtLid = numSameGids; tgtLid < numTgtLids; ++tgtLid) {
1034 const GO curTargetGid = rawTgtGids[tgtLid];
1035 const LO srcLid = source.getLocalElement (curTargetGid);
1036 if (srcLid != LINVALID) {
1037 permuteToLIDs[numPermutes2] = tgtLid;
1038 permuteFromLIDs[numPermutes2] = srcLid;
1042 remoteGIDs.push_back (curTargetGid);
1043 remoteLIDs[numRemotes2] = tgtLid;
1047 TEUCHOS_ASSERT( numPermutes == numPermutes2 );
1048 TEUCHOS_ASSERT( numRemotes == numRemotes2 );
1049 TEUCHOS_ASSERT(
size_t (numPermutes) + remoteGIDs.size () == size_t (numTgtLids - numSameGids) );
1055 if (remoteLIDs.extent (0) != 0 && ! source.isDistributed ()) {
1061 this->TransferData_->isLocallyComplete_ =
false;
1065 (
true, std::runtime_error,
"::setupSamePermuteRemote(): Target has "
1066 "remote LIDs but Source is not distributed globally. Importing to a "
1067 "submap of the target map.");
1072 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1073 void Import<LocalOrdinal,GlobalOrdinal,Node>::
1074 setupExport (Teuchos::Array<GlobalOrdinal>& remoteGIDs,
1076 Teuchos::Array<int>& userRemotePIDs,
1077 const Teuchos::RCP<Teuchos::ParameterList>& plist)
1079 using ::Tpetra::Details::makeDualViewFromOwningHostView;
1080 using ::Tpetra::Details::view_alloc_no_init;
1081 using Teuchos::Array;
1082 using Teuchos::ArrayView;
1084 using GO = GlobalOrdinal;
1085 typedef typename Array<int>::difference_type size_type;
1086 const char tfecfFuncName[] =
"setupExport: ";
1087 const char suffix[] =
" Please report this bug to the Tpetra developers.";
1089 std::unique_ptr<std::string> prefix;
1090 if (this->verbose ()) {
1091 auto srcMap = this->getSourceMap ();
1092 auto comm = srcMap.is_null () ? Teuchos::null : srcMap->getComm ();
1093 const int myRank = comm.is_null () ? -1 : comm->getRank ();
1094 std::ostringstream os;
1095 os <<
"Proc " << myRank <<
": Tpetra::Import::setupExport: ";
1096 prefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
1097 os <<
"Start" << std::endl;
1098 this->verboseOutputStream () << os.str ();
1101 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1102 (this->getSourceMap ().is_null (), std::logic_error,
1103 "Source Map is null. " << suffix);
1104 const map_type& source = * (this->getSourceMap ());
1106 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1107 (! useRemotePIDs && (userRemotePIDs.size() > 0), std::invalid_argument,
1108 "remotePIDs are non-empty but their use has not been requested.");
1109 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1110 (userRemotePIDs.size () > 0 && remoteGIDs.size () != userRemotePIDs.size (),
1111 std::invalid_argument,
"remotePIDs must either be of size zero or match "
1112 "the size of remoteGIDs.");
1116 ArrayView<GO> remoteGIDsView = remoteGIDs ();
1117 ArrayView<int> remoteProcIDsView;
1137 Array<int> newRemotePIDs;
1140 if (! useRemotePIDs) {
1141 newRemotePIDs.resize (remoteGIDsView.size ());
1142 if (this->verbose ()) {
1143 std::ostringstream os;
1144 os << *prefix <<
"Call sourceMap.getRemoteIndexList" << endl;
1145 this->verboseOutputStream () << os.str ();
1147 lookup = source.getRemoteIndexList (remoteGIDsView, newRemotePIDs ());
1149 Array<int>& remoteProcIDs = useRemotePIDs ? userRemotePIDs : newRemotePIDs;
1155 this->TransferData_->isLocallyComplete_ =
false;
1160 (
true, std::runtime_error,
"::setupExport(): the source Map wasn't "
1161 "able to figure out which process owns one or more of the GIDs in the "
1162 "list of remote GIDs. This probably means that there is at least one "
1163 "GID owned by some process in the target Map which is not owned by any"
1164 " process in the source Map. (That is, the source and target Maps do "
1165 "not contain the same set of GIDs globally.)");
1171 const size_type numInvalidRemote =
1172 std::count_if (remoteProcIDs.begin (), remoteProcIDs.end (),
1173 std::bind1st (std::equal_to<int> (), -1));
1174 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1175 (numInvalidRemote == 0, std::logic_error,
"Calling getRemoteIndexList "
1176 "on the source Map returned IDNotPresent, but none of the returned "
1177 "\"remote\" process ranks are -1. Please report this bug to the "
1178 "Tpetra developers.");
1180 #ifdef HAVE_TPETRA_MMM_TIMINGS
1181 using Teuchos::TimeMonitor;
1183 if(!plist.is_null())
1184 label = plist->get(
"Timer Label",label);
1185 std::string prefix = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:setupExport:1 ");
1186 auto MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix)));
1192 const size_type totalNumRemote = this->getNumRemoteIDs ();
1193 if (numInvalidRemote == totalNumRemote) {
1195 remoteProcIDs.clear ();
1196 remoteGIDs.clear ();
1197 this->TransferData_->remoteLIDs_ =
1198 decltype (this->TransferData_->remoteLIDs_) ();
1203 size_type numValidRemote = 0;
1204 #ifdef HAVE_TPETRA_DEBUG
1205 ArrayView<GO> remoteGIDsPtr = remoteGIDsView;
1207 GO*
const remoteGIDsPtr = remoteGIDsView.getRawPtr ();
1208 #endif // HAVE_TPETRA_DEBUG
1211 auto remoteLIDs = this->TransferData_->remoteLIDs_.view_host ();
1213 for (size_type r = 0; r < totalNumRemote; ++r) {
1215 if (remoteProcIDs[r] != -1) {
1216 remoteProcIDs[numValidRemote] = remoteProcIDs[r];
1217 remoteGIDsPtr[numValidRemote] = remoteGIDsPtr[r];
1218 remoteLIDs[numValidRemote] = remoteLIDs[r];
1222 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1223 (numValidRemote != totalNumRemote - numInvalidRemote,
1224 std::logic_error,
"After removing invalid remote GIDs and packing "
1225 "the valid remote GIDs, numValidRemote = " << numValidRemote
1226 <<
" != totalNumRemote - numInvalidRemote = "
1227 << totalNumRemote - numInvalidRemote
1228 <<
". Please report this bug to the Tpetra developers.");
1230 remoteProcIDs.resize (numValidRemote);
1231 remoteGIDs.resize (numValidRemote);
1233 Kokkos::resize (remoteLIDs, numValidRemote);
1234 this->TransferData_->remoteLIDs_ = decltype (this->TransferData_->remoteLIDs_) ();
1238 remoteGIDsView = remoteGIDs ();
1246 this->TransferData_->remoteLIDs_.modify_host ();
1247 auto remoteLIDs = this->TransferData_->remoteLIDs_.view_host ();
1248 sort3 (remoteProcIDs.begin (),
1249 remoteProcIDs.end (),
1250 remoteGIDsView.getRawPtr (),
1251 remoteLIDs.data ());
1252 this->TransferData_->remoteLIDs_.sync_device ();
1260 Array<GO> exportGIDs;
1262 #ifdef HAVE_TPETRA_MMM_TIMINGS
1263 using Teuchos::TimeMonitor;
1265 if(!plist.is_null())
1266 label = plist->get(
"Timer Label",label);
1267 std::string prefix2 = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:setupExport:3 ");
1268 auto MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2)));
1271 if (this->verbose ()) {
1272 std::ostringstream os;
1273 os << *prefix <<
"Call createFromRecvs" << endl;
1274 this->verboseOutputStream () << endl;
1276 this->TransferData_->distributor_.createFromRecvs (remoteGIDsView ().getConst (),
1277 remoteProcIDs, exportGIDs,
1278 this->TransferData_->exportPIDs_);
1284 #ifdef HAVE_TPETRA_MMM_TIMINGS
1285 prefix2 = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:setupExport:4 ");
1287 MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2)));
1293 const size_type numExportIDs = exportGIDs.size ();
1294 if (numExportIDs > 0) {
1295 typename decltype (this->TransferData_->exportLIDs_)::t_host
1297 ArrayView<const GO> expGIDs = exportGIDs ();
1298 for (size_type k = 0; k < numExportIDs; ++k) {
1299 exportLIDs[k] = source.getLocalElement (expGIDs[k]);
1304 if (this->verbose ()) {
1305 std::ostringstream os;
1306 os << *prefix <<
"Done!" << endl;
1307 this->verboseOutputStream () << os.str ();
1311 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1315 Teuchos::Array<std::pair<int,GlobalOrdinal>>& remotePGIDs,
1316 typename Teuchos::Array<GlobalOrdinal>::size_type& numSameGIDs,
1317 typename Teuchos::Array<GlobalOrdinal>::size_type& numPermuteGIDs,
1318 typename Teuchos::Array<GlobalOrdinal>::size_type& numRemoteGIDs,
1319 const Teuchos::ArrayView<const GlobalOrdinal>& sameGIDs1,
1320 const Teuchos::ArrayView<const GlobalOrdinal>& sameGIDs2,
1321 Teuchos::Array<GlobalOrdinal>& permuteGIDs1,
1322 Teuchos::Array<GlobalOrdinal>& permuteGIDs2,
1323 Teuchos::Array<GlobalOrdinal>& remoteGIDs1,
1324 Teuchos::Array<GlobalOrdinal>& remoteGIDs2,
1325 Teuchos::Array<int>& remotePIDs1,
1326 Teuchos::Array<int>& remotePIDs2)
const
1329 typedef GlobalOrdinal GO;
1330 typedef typename Teuchos::Array<GO>::size_type size_type;
1332 const size_type numSameGIDs1 = sameGIDs1.size();
1333 const size_type numSameGIDs2 = sameGIDs2.size();
1336 std::sort(permuteGIDs1.begin(), permuteGIDs1.end());
1337 std::sort(permuteGIDs2.begin(), permuteGIDs2.end());
1342 unionTgtGIDs.reserve(numSameGIDs1 + numSameGIDs2 +
1343 permuteGIDs1.size() + permuteGIDs2.size() +
1344 remoteGIDs1.size() + remoteGIDs2.size());
1348 typename Teuchos::Array<GO>::iterator permuteGIDs1_end;
1349 typename Teuchos::Array<GO>::iterator permuteGIDs2_end;
1350 if (numSameGIDs2 > numSameGIDs1) {
1352 numSameGIDs = numSameGIDs2;
1353 permuteGIDs2_end = permuteGIDs2.end();
1356 std::copy(sameGIDs2.begin(), sameGIDs2.end(), std::back_inserter(unionTgtGIDs));
1360 permuteGIDs1_end = std::set_difference(permuteGIDs1.begin(), permuteGIDs1.end(),
1361 unionTgtGIDs.begin()+numSameGIDs1, unionTgtGIDs.end(),
1362 permuteGIDs1.begin());
1366 numSameGIDs = numSameGIDs1;
1367 permuteGIDs1_end = permuteGIDs1.end();
1370 std::copy(sameGIDs1.begin(), sameGIDs1.end(), std::back_inserter(unionTgtGIDs));
1374 permuteGIDs2_end = std::set_difference(permuteGIDs2.begin(), permuteGIDs2.end(),
1375 unionTgtGIDs.begin()+numSameGIDs2, unionTgtGIDs.end(),
1376 permuteGIDs2.begin());
1381 std::set_union(permuteGIDs1.begin(), permuteGIDs1_end,
1382 permuteGIDs2.begin(), permuteGIDs2_end,
1383 std::back_inserter(unionTgtGIDs));
1386 Teuchos::Array<std::pair<int,GO>> remotePGIDs1(remoteGIDs1.size());
1387 for (size_type k=0; k<remoteGIDs1.size(); k++)
1388 remotePGIDs1[k] = std::make_pair(remotePIDs1[k], remoteGIDs1[k]);
1389 std::sort(remotePGIDs1.begin(), remotePGIDs1.end());
1391 Teuchos::Array<std::pair<int,GO>> remotePGIDs2(remoteGIDs2.size());
1392 for (size_type k=0; k<remoteGIDs2.size(); k++)
1393 remotePGIDs2[k] = std::make_pair(remotePIDs2[k], remoteGIDs2[k]);
1394 std::sort(remotePGIDs2.begin(), remotePGIDs2.end());
1396 remotePGIDs.reserve(remotePGIDs1.size()+remotePGIDs2.size());
1397 std::merge(remotePGIDs1.begin(), remotePGIDs1.end(),
1398 remotePGIDs2.begin(), remotePGIDs2.end(),
1399 std::back_inserter(remotePGIDs));
1400 auto it = std::unique(remotePGIDs.begin(), remotePGIDs.end());
1401 remotePGIDs.resize(std::distance(remotePGIDs.begin(), it));
1404 const size_type oldSize = unionTgtGIDs.size();
1405 unionTgtGIDs.resize(oldSize+remotePGIDs.size());
1406 for (size_type start=oldSize, k=0; k<remotePGIDs.size(); k++)
1407 unionTgtGIDs[start+k] = remotePGIDs[k].second;
1410 numRemoteGIDs = remotePGIDs.size();
1411 numPermuteGIDs = unionTgtGIDs.size() - numSameGIDs - numRemoteGIDs;
1416 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1417 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
1421 using ::Tpetra::Details::Behavior;
1422 using Teuchos::Array;
1423 using Teuchos::ArrayView;
1425 using Teuchos::Comm;
1428 using Teuchos::outArg;
1429 using Teuchos::REDUCE_MIN;
1430 using Teuchos::reduceAll;
1432 using LO = LocalOrdinal;
1433 using GO = GlobalOrdinal;
1435 using size_type =
typename Array<GO>::size_type;
1437 #ifdef HAVE_TPETRA_MMM_TIMINGS
1438 using Teuchos::TimeMonitor;
1439 std::string label = std::string(
"Tpetra::Import::setUnion");
1440 TimeMonitor MM(*TimeMonitor::getNewTimer(label));
1443 RCP<const map_type> srcMap = this->getSourceMap ();
1444 RCP<const map_type> tgtMap1 = this->getTargetMap ();
1446 RCP<const Comm<int> > comm = srcMap->getComm ();
1448 const bool debug = Behavior::debug (
"Import::setUnion") ||
1449 Behavior::debug (
"Tpetra::Import::setUnion");
1452 TEUCHOS_TEST_FOR_EXCEPTION
1453 (! srcMap->isSameAs (* (rhs.
getSourceMap ())), std::invalid_argument,
1454 "Tpetra::Import::setUnion: The source Map of the input Import must be the "
1455 "same as (in the sense of Map::isSameAs) the source Map of this Import.");
1456 const Comm<int>& comm1 = * (tgtMap1->getComm ());
1457 const Comm<int>& comm2 = * (tgtMap2->getComm ());
1458 TEUCHOS_TEST_FOR_EXCEPTION
1460 std::invalid_argument,
"Tpetra::Import::setUnion: "
1461 "The target Maps must have congruent communicators.");
1467 if (tgtMap1->isSameAs (*tgtMap2)) {
1468 return rcp (
new import_type (*
this));
1476 const size_type numSameGIDs1 = this->getNumSameIDs();
1477 ArrayView<const GO> sameGIDs1 = (tgtMap1->getNodeElementList())(0,numSameGIDs1);
1480 ArrayView<const GO> sameGIDs2 = (tgtMap2->getNodeElementList())(0,numSameGIDs2);
1483 ArrayView<const LO> permuteToLIDs1 = this->getPermuteToLIDs();
1484 Array<GO> permuteGIDs1(permuteToLIDs1.size());
1485 for (size_type k=0; k<permuteGIDs1.size(); k++)
1486 permuteGIDs1[k] = tgtMap1->getGlobalElement(permuteToLIDs1[k]);
1489 Array<GO> permuteGIDs2(permuteToLIDs2.size());
1490 for (size_type k=0; k<permuteGIDs2.size(); k++)
1491 permuteGIDs2[k] = tgtMap2->getGlobalElement(permuteToLIDs2[k]);
1494 ArrayView<const LO> remoteLIDs1 = this->getRemoteLIDs();
1495 Array<GO> remoteGIDs1(remoteLIDs1.size());
1496 for (size_type k=0; k<remoteLIDs1.size(); k++)
1497 remoteGIDs1[k] = this->getTargetMap()->getGlobalElement(remoteLIDs1[k]);
1500 Array<GO> remoteGIDs2(remoteLIDs2.size());
1501 for (size_type k=0; k<remoteLIDs2.size(); k++)
1502 remoteGIDs2[k] = rhs.
getTargetMap()->getGlobalElement(remoteLIDs2[k]);
1505 Array<int> remotePIDs1;
1506 Tpetra::Import_Util::getRemotePIDs(*
this, remotePIDs1);
1508 Array<int> remotePIDs2;
1509 Tpetra::Import_Util::getRemotePIDs(rhs, remotePIDs2);
1512 Array<GO> unionTgtGIDs;
1513 Array<std::pair<int,GO>> remotePGIDs;
1514 size_type numSameIDsUnion, numPermuteIDsUnion, numRemoteIDsUnion;
1516 findUnionTargetGIDs(unionTgtGIDs, remotePGIDs,
1517 numSameIDsUnion, numPermuteIDsUnion, numRemoteIDsUnion,
1518 sameGIDs1, sameGIDs2, permuteGIDs1, permuteGIDs2,
1519 remoteGIDs1, remoteGIDs2, remotePIDs1, remotePIDs2);
1522 Array<LO> remoteLIDsUnion(numRemoteIDsUnion);
1523 Array<GO> remoteGIDsUnion(numRemoteIDsUnion);
1524 Array<int> remotePIDsUnion(numRemoteIDsUnion);
1525 const size_type unionRemoteIDsStart = numSameIDsUnion + numPermuteIDsUnion;
1526 for (size_type k = 0; k < numRemoteIDsUnion; ++k) {
1527 remoteLIDsUnion[k] = unionRemoteIDsStart + k;
1528 remotePIDsUnion[k] = remotePGIDs[k].first;
1529 remoteGIDsUnion[k] = remotePGIDs[k].second;
1534 Array<LO> permuteToLIDsUnion(numPermuteIDsUnion);
1535 Array<LO> permuteFromLIDsUnion(numPermuteIDsUnion);
1536 for (size_type k = 0; k < numPermuteIDsUnion; ++k) {
1537 size_type idx = numSameIDsUnion + k;
1538 permuteToLIDsUnion[k] =
static_cast<LO
>(idx);
1539 permuteFromLIDsUnion[k] = srcMap->getLocalElement(unionTgtGIDs[idx]);
1542 #ifdef HAVE_TPETRA_MMM_TIMINGS
1543 MM.disableTimer(label);
1544 label =
"Tpetra::Import::setUnion : Construct Target Map";
1545 TimeMonitor MM2(*TimeMonitor::getNewTimer(label));
1549 const GST INVALID = Teuchos::OrdinalTraits<GST>::invalid ();
1550 const GO indexBaseUnion = std::min(tgtMap1->getIndexBase(), tgtMap2->getIndexBase());
1551 RCP<const map_type> unionTgtMap =
1552 rcp(
new map_type(INVALID, unionTgtGIDs(), indexBaseUnion, comm));
1554 #ifdef HAVE_TPETRA_MMM_TIMINGS
1555 MM2.disableTimer(label);
1556 label =
"Tpetra::Import::setUnion : Export GIDs";
1557 TimeMonitor MM3(*TimeMonitor::getNewTimer(label));
1568 Array<GO> exportGIDsUnion;
1569 Array<LO> exportLIDsUnion;
1570 Array<int> exportPIDsUnion;
1571 Distributor distributor (comm, this->TransferData_->out_);
1573 #ifdef TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1581 ArrayView<const LO> exportLIDs1 = this->getExportLIDs ();
1582 ArrayView<const LO> exportPIDs1 = this->getExportPIDs ();
1595 Array<LO> exportLIDs1Copy (exportLIDs1.begin (), exportLIDs1.end ());
1596 Array<int> exportPIDs1Copy (exportLIDs1.begin (), exportLIDs1.end ());
1597 sort2 (exportLIDs1Copy.begin (), exportLIDs1Copy.end (),
1598 exportPIDs1Copy.begin ());
1599 typename ArrayView<LO>::iterator exportLIDs1_end = exportLIDs1Copy.end ();
1600 typename ArrayView<LO>::iterator exportPIDs1_end = exportPIDs1Copy.end ();
1601 merge2 (exportLIDs1_end, exportPIDs1_end,
1602 exportLIDs1Copy.begin (), exportLIDs1_end,
1603 exportPIDs1Copy.begin (), exportPIDs1_end,
1606 Array<LO> exportLIDs2Copy (exportLIDs2.begin (), exportLIDs2.end ());
1607 Array<int> exportPIDs2Copy (exportLIDs2.begin (), exportLIDs2.end ());
1608 sort2 (exportLIDs2Copy.begin (), exportLIDs2Copy.end (),
1609 exportPIDs2Copy.begin ());
1610 typename ArrayView<LO>::iterator exportLIDs2_end = exportLIDs2Copy.end ();
1611 typename ArrayView<LO>::iterator exportPIDs2_end = exportPIDs2Copy.end ();
1612 merge2 (exportLIDs2_end, exportPIDs2_end,
1613 exportLIDs2Copy.begin (), exportLIDs2_end,
1614 exportPIDs2Copy.begin (), exportPIDs2_end,
1621 keyValueMerge (exportLIDs1Copy.begin (), exportLIDs1Copy.end (),
1622 exportPIDs1Copy.begin (), exportPIDs1Copy.end (),
1623 exportLIDs2Copy.begin (), exportLIDs2Copy.end (),
1624 exportPIDs2Copy.begin (), exportPIDs2Copy.end (),
1625 std::back_inserter (exportLIDsUnion),
1626 std::back_inserter (exportPIDsUnion),
1630 sort2 (exportPIDsUnion.begin (), exportPIDsUnion.end (),
1631 exportLIDsUnion.begin ());
1637 #else // NOT TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1645 remotePIDsUnion().getConst(),
1646 exportGIDsUnion, exportPIDsUnion);
1649 const size_type numExportIDsUnion = exportGIDsUnion.size ();
1650 exportLIDsUnion.resize (numExportIDsUnion);
1651 for (size_type k = 0; k < numExportIDsUnion; ++k) {
1652 exportLIDsUnion[k] = srcMap->getLocalElement (exportGIDsUnion[k]);
1654 #endif // TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1657 #ifdef HAVE_TPETRA_MMM_TIMINGS
1658 MM3.disableTimer(label);
1659 label =
"Tpetra::Import::setUnion : Construct Import";
1660 TimeMonitor MM4(*TimeMonitor::getNewTimer(label));
1662 RCP<const import_type> unionImport =
1663 rcp (
new import_type (srcMap, unionTgtMap,
1664 as<size_t> (numSameIDsUnion),
1665 permuteToLIDsUnion, permuteFromLIDsUnion,
1666 remoteLIDsUnion, exportLIDsUnion,
1667 exportPIDsUnion, distributor,
1668 this->TransferData_->out_));
1672 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1673 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
1677 using Teuchos::Array;
1678 using Teuchos::ArrayView;
1680 using Teuchos::Comm;
1683 using Teuchos::outArg;
1684 using Teuchos::REDUCE_MIN;
1685 using Teuchos::reduceAll;
1686 typedef LocalOrdinal LO;
1687 typedef GlobalOrdinal GO;
1688 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> > unionImport;
1689 RCP<const map_type> srcMap = this->getSourceMap ();
1690 RCP<const map_type> tgtMap = this->getTargetMap ();
1691 RCP<const Comm<int> > comm = srcMap->getComm ();
1693 ArrayView<const GO> srcGIDs = srcMap->getNodeElementList ();
1694 ArrayView<const GO> tgtGIDs = tgtMap->getNodeElementList ();
1697 size_t numSameIDsNew = srcMap->getNodeNumElements ();
1698 size_t numRemoteIDsNew = this->getNumRemoteIDs ();
1699 Array<LO> permuteToLIDsNew, permuteFromLIDsNew;
1702 ArrayView<const LO> remoteLIDsOld = this->getRemoteLIDs ();
1703 ArrayView<const LO> exportLIDsOld = this->getExportLIDs ();
1706 Array<GO> GIDs(numSameIDsNew + numRemoteIDsNew);
1707 for(
size_t i=0; i<numSameIDsNew; i++)
1708 GIDs[i] = srcGIDs[i];
1711 Array<LO> remoteLIDsNew(numRemoteIDsNew);
1712 for(
size_t i=0; i<numRemoteIDsNew; i++) {
1713 GIDs[numSameIDsNew + i] = tgtGIDs[remoteLIDsOld[i]];
1714 remoteLIDsNew[i] = numSameIDsNew+i;
1718 GO GO_INVALID = Teuchos::OrdinalTraits<GO>::invalid();
1719 RCP<const map_type> targetMapNew =
1720 rcp (
new map_type (GO_INVALID, GIDs, tgtMap->getIndexBase (),
1721 tgtMap->getComm ()));
1724 Array<int> exportPIDsnew (this->getExportPIDs ());
1725 Array<LO> exportLIDsnew (this->getExportLIDs ());
1746 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1747 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
1753 using LO = LocalOrdinal;
1755 const size_t NumRemotes = this->getNumRemoteIDs ();
1756 TEUCHOS_TEST_FOR_EXCEPTION(
1757 NumRemotes != remoteTarget->getNodeNumElements (),
1758 std::runtime_error,
"Tpetra::createRemoteOnlyImport: "
1759 "remoteTarget map ID count doesn't match.");
1762 Teuchos::ArrayView<const LO> oldRemoteLIDs = this->getRemoteLIDs ();
1763 Teuchos::Array<LO> newRemoteLIDs (NumRemotes);
1764 const map_type& tgtMap = * (this->getTargetMap ());
1765 for (
size_t i = 0; i < NumRemotes; ++i) {
1766 newRemoteLIDs[i] = remoteTarget->getLocalElement (tgtMap.
getGlobalElement (oldRemoteLIDs[i]));
1768 TEUCHOS_TEST_FOR_EXCEPTION(
1769 i > 0 && newRemoteLIDs[i] < newRemoteLIDs[i-1],
1770 std::runtime_error,
"Tpetra::createRemoteOnlyImport: "
1771 "this and remoteTarget order don't match.");
1779 Teuchos::Array<int> newExportPIDs (this->getExportPIDs ());
1780 Teuchos::Array<LO> newExportLIDs (this->getExportLIDs ());
1781 Teuchos::Array<LO> dummy;
1784 return rcp (
new import_type (this->getSourceMap (), remoteTarget,
1785 static_cast<size_t> (0), dummy, dummy,
1786 newRemoteLIDs, newExportLIDs,
1787 newExportPIDs, newDistor));
1792 #define TPETRA_IMPORT_CLASS_INSTANT(LO, GO, NODE) \
1793 template class Import< LO , GO , NODE >;
1802 #define TPETRA_IMPORT_INSTANT(LO, GO, NODE) \
1803 TPETRA_IMPORT_CLASS_INSTANT(LO, GO, NODE)
1805 #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()).
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.
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.
GlobalOrdinal getGlobalElement(LocalOrdinal localIndex) const
The global index corresponding to the given local index.
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.