10 #ifndef TPETRA_IMPORT_DEF_HPP
11 #define TPETRA_IMPORT_DEF_HPP
13 #include "Tpetra_Distributor.hpp"
14 #include "Tpetra_Map.hpp"
15 #include "Tpetra_ImportExportData.hpp"
18 #include "Tpetra_Export.hpp"
20 #include "Tpetra_Details_DualViewUtil.hpp"
23 #include "Teuchos_as.hpp"
24 #ifdef HAVE_TPETRA_MMM_TIMINGS
25 #include "Teuchos_TimeMonitor.hpp"
32 std::string toString (
const std::vector<T>& x)
34 std::ostringstream os;
36 const std::size_t N = x.size ();
37 for (std::size_t k = 0; k < N; ++k) {
39 if (k + std::size_t (1) < N) {
47 template<
class ElementType,
class DeviceType>
48 std::string toString (
const Kokkos::View<const ElementType*, DeviceType>& x)
50 std::ostringstream os;
52 const std::size_t N = std::size_t (x.extent (0));
53 for (std::size_t k = 0; k < N; ++k) {
55 if (k + std::size_t (1) < N) {
68 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
70 Import<LocalOrdinal,GlobalOrdinal,Node>::
71 init (
const Teuchos::RCP<const map_type>& source,
72 const Teuchos::RCP<const map_type>& ,
74 Teuchos::Array<int> & remotePIDs,
75 const Teuchos::RCP<Teuchos::ParameterList>& plist)
77 using ::Tpetra::Details::ProfilingRegion;
83 ProfilingRegion regionImportInit (
"Tpetra::Import::init");
85 std::unique_ptr<std::string> verbPrefix;
86 if (this->verbose ()) {
87 std::ostringstream os;
88 const int myRank = source->getComm ()->getRank ();
89 os <<
"Proc " << myRank <<
": Tpetra::Import::init: ";
90 verbPrefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
92 this->verboseOutputStream () << os.str ();
95 Array<GlobalOrdinal> remoteGIDs;
97 #ifdef HAVE_TPETRA_MMM_TIMINGS
98 using Teuchos::TimeMonitor;
101 label = plist->get(
"Timer Label",label);
102 std::string prefix = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:preIData: ");
107 #ifdef HAVE_TPETRA_MMM_TIMINGS
108 auto MM(*TimeMonitor::getNewTimer(prefix));
110 if (this->verbose ()) {
111 std::ostringstream os;
112 os << *verbPrefix <<
"Call setupSamePermuteRemote" << endl;
113 this->verboseOutputStream () << os.str ();
115 setupSamePermuteRemote (remoteGIDs);
118 #ifdef HAVE_TPETRA_MMM_TIMINGS
119 prefix = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:preSetupExport: ");
120 auto MM2(*TimeMonitor::getNewTimer(prefix));
122 if (source->isDistributed ()) {
123 if (this->verbose ()) {
124 std::ostringstream os;
125 os << *verbPrefix <<
"Call setupExport" << endl;
126 this->verboseOutputStream () << os.str ();
128 setupExport (remoteGIDs,useRemotePIDs,remotePIDs);
130 else if (this->verbose ()) {
131 std::ostringstream os;
132 os << *verbPrefix <<
"Source Map not distributed; skip setupExport"
134 this->verboseOutputStream () << os.str ();
138 TEUCHOS_ASSERT( ! this->TransferData_->permuteFromLIDs_.need_sync_device () );
139 TEUCHOS_ASSERT( ! this->TransferData_->permuteFromLIDs_.need_sync_host () );
140 TEUCHOS_ASSERT( ! this->TransferData_->permuteToLIDs_.need_sync_device () );
141 TEUCHOS_ASSERT( ! this->TransferData_->permuteToLIDs_.need_sync_host () );
142 TEUCHOS_ASSERT( ! this->TransferData_->remoteLIDs_.need_sync_device () );
143 TEUCHOS_ASSERT( ! this->TransferData_->remoteLIDs_.need_sync_host () );
144 TEUCHOS_ASSERT( ! this->TransferData_->exportLIDs_.need_sync_device () );
145 TEUCHOS_ASSERT( ! this->TransferData_->exportLIDs_.need_sync_host () );
147 this->detectRemoteExportLIDsContiguous();
149 if (this->verbose ()) {
150 std::ostringstream os;
151 os << *verbPrefix <<
"Done!" << endl;
152 this->verboseOutputStream () << os.str ();
156 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
158 Import (
const Teuchos::RCP<const map_type >& source,
159 const Teuchos::RCP<const map_type >& target) :
160 base_type (source, target, Teuchos::null, Teuchos::null,
"Import")
162 Teuchos::Array<int> dummy;
163 #ifdef HAVE_TPETRA_MMM_TIMINGS
164 Teuchos::RCP<Teuchos::ParameterList> mypars = rcp(
new Teuchos::ParameterList);
165 mypars->set(
"Timer Label",
"Naive_tAFC");
166 init(source, target,
false, dummy, mypars);
168 init (source, target,
false, dummy, Teuchos::null);
172 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
174 Import (
const Teuchos::RCP<const map_type>& source,
175 const Teuchos::RCP<const map_type>& target,
176 const Teuchos::RCP<Teuchos::FancyOStream>& out) :
177 base_type (source, target, out, Teuchos::null,
"Import")
179 Teuchos::Array<int> dummy;
180 init (source, target,
false, dummy, Teuchos::null);
183 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
185 Import (
const Teuchos::RCP<const map_type>& source,
186 const Teuchos::RCP<const map_type>& target,
187 const Teuchos::RCP<Teuchos::ParameterList>& plist) :
188 base_type (source, target, Teuchos::null, plist,
"Import")
190 Teuchos::Array<int> dummy;
191 init (source, target,
false, dummy, plist);
194 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
196 Import (
const Teuchos::RCP<const map_type>& source,
197 const Teuchos::RCP<const map_type>& target,
198 const Teuchos::RCP<Teuchos::FancyOStream>& out,
199 const Teuchos::RCP<Teuchos::ParameterList>& plist) :
200 base_type (source, target, out, plist,
"Import")
202 Teuchos::Array<int> dummy;
203 init (source, target,
false, dummy, plist);
206 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
208 Import (
const Teuchos::RCP<const map_type>& source,
209 const Teuchos::RCP<const map_type>& target,
210 Teuchos::Array<int>& remotePIDs,
211 const Teuchos::RCP<Teuchos::ParameterList>& plist) :
212 base_type (source, target, Teuchos::null, plist,
"Import")
214 init (source, target,
true, remotePIDs, plist);
217 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
223 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
232 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
236 const Teuchos::ArrayView<int> & userRemotePIDs,
237 const Teuchos::ArrayView<const LocalOrdinal> & userExportLIDs,
238 const Teuchos::ArrayView<const int> & userExportPIDs,
239 const Teuchos::RCP<Teuchos::ParameterList>& plist,
240 const Teuchos::RCP<Teuchos::FancyOStream>& out) :
241 base_type (source, target, out, plist,
"Import")
243 using ::Tpetra::Details::makeDualViewFromArrayView;
245 using Teuchos::Array;
246 using Teuchos::ArrayRCP;
247 using Teuchos::ArrayView;
252 using LO = LocalOrdinal;
253 using GO = GlobalOrdinal;
254 using size_type = Teuchos::Array<int>::size_type;
256 std::unique_ptr<std::string> prefix;
258 auto comm = source.is_null () ? Teuchos::null : source->getComm ();
259 const int myRank = comm.is_null () ? -1 : comm->getRank ();
260 std::ostringstream os;
261 os <<
"Proc " << myRank <<
": Tpetra::Import createExpert ctor: ";
262 prefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
263 os <<
"Start" << endl;
267 ArrayView<const GO> sourceGIDs = source->getLocalElementList ();
268 ArrayView<const GO> targetGIDs = target->getLocalElementList ();
270 Array<GO> tRemoteGIDs;
272 std::ostringstream os;
273 os << *prefix <<
"Call setupSamePermuteRemote" << endl;
276 setupSamePermuteRemote (tRemoteGIDs);
279 std::ostringstream os;
280 os << *prefix <<
"Sort & filter IDs" << endl;
284 auto tRemoteLIDs = this->
TransferData_->remoteLIDs_.view_host ();
286 Teuchos::Array<int> tRemotePIDs (userRemotePIDs);
289 std::ostringstream os;
290 os << *prefix <<
"Target Map has remote LIDs but source Map is not "
291 "distributed. Importing to a submap of the target Map." << endl;
299 "::constructExpert: Target Map has remote LIDs but source Map "
300 "is not distributed. Importing to a submap of the target Map.");
301 TEUCHOS_TEST_FOR_EXCEPTION
302 (tRemotePIDs.size () != tRemoteGIDs.size () ||
303 size_t (tRemoteGIDs.size ()) !=
size_t (tRemoteLIDs.extent (0)),
304 std::runtime_error,
"Import::Import createExpert version: "
305 "Size mismatch on userRemotePIDs, remoteGIDs, and remoteLIDs "
306 "Array's to sort3.");
308 sort3 (tRemotePIDs.begin (),
310 tRemoteGIDs.begin (),
311 tRemoteLIDs.data ());
315 size_type indexIntoRemotePIDs = tRemotePIDs.size ();
316 for (size_type i = 0; i < indexIntoRemotePIDs; ++i) {
317 if (tRemotePIDs[i] == -1) {
326 if (indexIntoRemotePIDs - cnt > 0) {
327 Array<GO> newRemoteGIDs(indexIntoRemotePIDs-cnt);
328 Array<LO> newRemoteLIDs(indexIntoRemotePIDs-cnt);
329 Array<int> newRemotePIDs(indexIntoRemotePIDs-cnt);
332 for (size_type j = 0; j < indexIntoRemotePIDs; ++j)
333 if(tRemotePIDs[j] != -1) {
334 newRemoteGIDs[cnt] = tRemoteGIDs[j];
335 newRemotePIDs[cnt] = tRemotePIDs[j];
336 newRemoteLIDs[cnt] = target->getLocalElement(tRemoteGIDs[j]);
339 indexIntoRemotePIDs = cnt;
340 tRemoteGIDs = newRemoteGIDs;
341 tRemotePIDs = newRemotePIDs;
343 newRemoteLIDs ().getConst (),
347 indexIntoRemotePIDs = 0;
354 this->
TransferData_->exportPIDs_ = Teuchos::Array<int> (userExportPIDs);
356 userExportLIDs,
"exportLIDs");
358 bool locallyComplete =
true;
359 for (size_type i = 0; i < userExportPIDs.size () && locallyComplete; ++i) {
360 if (userExportPIDs[i] == -1) {
361 locallyComplete =
false;
367 std::ostringstream os;
368 os << *prefix <<
"locallyComplete: "
369 << (locallyComplete ?
"true" :
"false")
370 <<
"; call createFromSendsAndRecvs" << endl;
374 #ifdef HAVE_TPETRA_MMM_TIMINGS
375 std::string mmm_prefix =
376 std::string(
"Tpetra ") + std::string(
":iport_ctor:cFSAR ");
378 auto MM3(*Teuchos::TimeMonitor::getNewTimer(mmm_prefix));
384 this->detectRemoteExportLIDsContiguous();
386 TEUCHOS_ASSERT( ! this->
TransferData_->permuteFromLIDs_.need_sync_device () );
387 TEUCHOS_ASSERT( ! this->
TransferData_->permuteFromLIDs_.need_sync_host () );
388 TEUCHOS_ASSERT( ! this->
TransferData_->permuteToLIDs_.need_sync_device () );
389 TEUCHOS_ASSERT( ! this->
TransferData_->permuteToLIDs_.need_sync_host () );
390 TEUCHOS_ASSERT( ! this->
TransferData_->remoteLIDs_.need_sync_device () );
391 TEUCHOS_ASSERT( ! this->
TransferData_->remoteLIDs_.need_sync_host () );
392 TEUCHOS_ASSERT( ! this->
TransferData_->exportLIDs_.need_sync_device () );
393 TEUCHOS_ASSERT( ! this->
TransferData_->exportLIDs_.need_sync_host () );
396 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
398 Import (
const Teuchos::RCP<const map_type>& source,
399 const Teuchos::RCP<const map_type>& target,
400 const size_t numSameIDs,
401 Teuchos::Array<LocalOrdinal>& permuteToLIDs,
402 Teuchos::Array<LocalOrdinal>& permuteFromLIDs,
403 Teuchos::Array<LocalOrdinal>& remoteLIDs,
404 Teuchos::Array<LocalOrdinal>& exportLIDs,
405 Teuchos::Array<int>& exportPIDs,
407 const Teuchos::RCP<Teuchos::FancyOStream>& out,
408 const Teuchos::RCP<Teuchos::ParameterList>& plist) :
409 base_type (source, target, out, plist,
"Import")
411 using ::Tpetra::Details::makeDualViewFromArrayView;
414 std::unique_ptr<std::string> prefix;
416 auto comm = source.is_null () ? Teuchos::null : source->getComm ();
417 const int myRank = comm.is_null () ? -1 : comm->getRank ();
418 std::ostringstream os;
419 os <<
"Proc " << myRank <<
": Tpetra::Import export ctor: ";
420 prefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
421 os <<
"Start" << endl;
425 bool locallyComplete =
true;
426 for (Teuchos::Array<int>::size_type i = 0; i < exportPIDs.size (); ++i) {
427 if (exportPIDs[i] == -1) {
428 locallyComplete =
false;
432 std::ostringstream os;
433 os << *prefix <<
"numSameIDs: " << numSameIDs <<
", locallyComplete: "
434 << (locallyComplete ?
"true" :
"false") << endl;
441 makeDualViewFromArrayView (this->
TransferData_->permuteToLIDs_,
442 permuteToLIDs ().getConst (),
444 TEUCHOS_ASSERT(
size_t (this->
TransferData_->permuteToLIDs_.extent (0)) ==
445 size_t (permuteToLIDs.size ()) );
446 makeDualViewFromArrayView (this->
TransferData_->permuteFromLIDs_,
447 permuteFromLIDs ().getConst (),
449 TEUCHOS_ASSERT(
size_t (this->
TransferData_->permuteFromLIDs_.extent (0)) ==
450 size_t (permuteFromLIDs.size ()) );
452 remoteLIDs ().getConst (),
454 TEUCHOS_ASSERT(
size_t (this->
TransferData_->remoteLIDs_.extent (0)) ==
455 size_t (remoteLIDs.size ()) );
457 exportLIDs ().getConst (),
459 TEUCHOS_ASSERT(
size_t (this->
TransferData_->exportLIDs_.extent (0)) ==
460 size_t (exportLIDs.size ()) );
464 this->detectRemoteExportLIDsContiguous();
466 TEUCHOS_ASSERT( ! this->
TransferData_->permuteFromLIDs_.need_sync_device () );
467 TEUCHOS_ASSERT( ! this->
TransferData_->permuteFromLIDs_.need_sync_host () );
468 TEUCHOS_ASSERT( ! this->
TransferData_->permuteToLIDs_.need_sync_device () );
469 TEUCHOS_ASSERT( ! this->
TransferData_->permuteToLIDs_.need_sync_host () );
470 TEUCHOS_ASSERT( ! this->
TransferData_->remoteLIDs_.need_sync_device () );
471 TEUCHOS_ASSERT( ! this->
TransferData_->remoteLIDs_.need_sync_host () );
472 TEUCHOS_ASSERT( ! this->
TransferData_->exportLIDs_.need_sync_device () );
473 TEUCHOS_ASSERT( ! this->
TransferData_->exportLIDs_.need_sync_host () );
478 template <
class LO,
class GO,
class NT>
479 struct ImportLocalSetupResult
481 Teuchos::RCP<const ::Tpetra::Map<LO, GO, NT> > targetMap;
485 std::vector<GO> remoteGIDs;
486 std::vector<LO> remoteLIDs;
487 std::vector<int> remotePIDs;
492 void printArray (std::ostream& out,
const T x[],
const std::size_t N)
495 for (std::size_t k = 0; k < N; ++k) {
504 template<
class LO,
class GO,
class NT>
505 ImportLocalSetupResult<LO, GO, NT>
506 setupSamePermuteRemoteFromUserGlobalIndexList (const ::Tpetra::Map<LO, GO, NT>& sourceMap,
507 const GO targetMapRemoteOrPermuteGlobalIndices[],
508 const int targetMapRemoteOrPermuteProcessRanks[],
509 const LO numTargetMapRemoteOrPermuteGlobalIndices,
510 const bool mayReorderTargetMapIndicesLocally,
511 Teuchos::FancyOStream* out,
512 const std::string* verboseHeader,
517 const int myRank = sourceMap.getComm ()->getRank ();
518 ImportLocalSetupResult<LO, GO, NT> result;
521 std::ostringstream os;
522 os << *verboseHeader <<
"- Import::setupSPR w/ remote GIDs & PIDs: " << endl
523 << *verboseHeader <<
" Input GIDs: ";
524 printArray (os, targetMapRemoteOrPermuteGlobalIndices, numTargetMapRemoteOrPermuteGlobalIndices);
525 os << endl <<
" Input PIDs: ";
526 printArray (os, targetMapRemoteOrPermuteProcessRanks, numTargetMapRemoteOrPermuteGlobalIndices);
536 std::vector<GO> badGIDs;
537 std::vector<int> badPIDs;
538 const Teuchos::Comm<int>& comm = * (sourceMap.getComm ());
539 const int numProcs = comm.getSize ();
541 for (LO k = 0; k < numTargetMapRemoteOrPermuteGlobalIndices; ++k) {
542 const GO tgtGID = targetMapRemoteOrPermuteGlobalIndices[k];
543 if (sourceMap.isNodeGlobalElement (tgtGID)) {
544 badGIDs.push_back (tgtGID);
546 const int tgtPID = targetMapRemoteOrPermuteProcessRanks[k];
547 if (tgtPID < 0 || tgtPID >= numProcs) {
548 badPIDs.push_back (tgtPID);
552 std::array<int, 2> lclStatus {{
553 badGIDs.size () == 0 ? 1 : 0,
554 badPIDs.size () == 0 ? 1 : 0
556 std::array<int, 2> gblStatus {{0, 0}};
557 Teuchos::reduceAll<int, int> (comm, Teuchos::REDUCE_MIN, 2,
558 lclStatus.data (), gblStatus.data ());
559 const bool good = gblStatus[0] == 1 && gblStatus[1] == 1;
562 if (verbose && gblStatus[0] != 1) {
563 std::ostringstream os;
564 os << *verboseHeader <<
"- Some input GIDs are already in the source Map: ";
565 printArray (os, badGIDs.data (), badGIDs.size ());
567 ::Tpetra::Details::gathervPrint (*out, os.str (), comm);
569 if (verbose && gblStatus[0] != 1) {
570 std::ostringstream os;
571 os << *verboseHeader <<
"- Some input PIDs are invalid: ";
572 printArray (os, badPIDs.data (), badPIDs.size ());
574 ::Tpetra::Details::gathervPrint (*out, os.str (), comm);
578 std::ostringstream os;
579 os <<
"Tpetra::Import constructor that takes remote GIDs and PIDs: ";
580 if (gblStatus[0] != 1) {
581 os <<
"Some input GIDs (global indices) are already in the source Map! ";
583 if (gblStatus[1] != 1) {
584 os <<
"Some input PIDs (process ranks) are invalid! ";
586 os <<
"Rerun with the environment variable TPETRA_VERBOSE=Tpetra::Import "
587 "to see what GIDs and/or PIDs are bad.";
588 TEUCHOS_TEST_FOR_EXCEPTION(
true, std::invalid_argument, os.str ());
595 const LO numLclSrcIDs =
static_cast<LO
> (sourceMap.getLocalNumElements ());
596 const LO numLclTgtIDs = numLclSrcIDs + numTargetMapRemoteOrPermuteGlobalIndices;
598 std::ostringstream os;
599 os << *verboseHeader <<
"- Copy source Map GIDs into target Map GID list: "
600 "numLclSrcIDs=" << numLclSrcIDs
601 <<
", numTargetMapRemoteOrPermuteGlobalIndices="
602 << numTargetMapRemoteOrPermuteGlobalIndices << endl;
605 std::vector<GO> tgtGIDs (numLclTgtIDs);
606 if (sourceMap.isContiguous ()) {
607 GO curTgtGID = sourceMap.getMinGlobalIndex ();
608 for (LO k = 0; k < numLclSrcIDs; ++k, ++curTgtGID) {
609 tgtGIDs[k] = curTgtGID;
613 auto srcGIDs = sourceMap.getLocalElementList ();
614 for (LO k = 0; k < numLclSrcIDs; ++k) {
615 tgtGIDs[k] = srcGIDs[k];
618 std::copy (targetMapRemoteOrPermuteGlobalIndices,
619 targetMapRemoteOrPermuteGlobalIndices + numTargetMapRemoteOrPermuteGlobalIndices,
620 tgtGIDs.begin () + numLclSrcIDs);
633 std::ostringstream os;
634 os << *verboseHeader <<
"- Sort by PID? "
635 << (mayReorderTargetMapIndicesLocally ?
"true" :
"false") << endl;
638 std::vector<int> tgtPIDs (targetMapRemoteOrPermuteProcessRanks,
639 targetMapRemoteOrPermuteProcessRanks + numTargetMapRemoteOrPermuteGlobalIndices);
640 result.numPermutes = 0;
641 if (mayReorderTargetMapIndicesLocally) {
642 Tpetra::sort2 (tgtPIDs.begin (), tgtPIDs.end (), tgtGIDs.begin () + numLclSrcIDs);
643 auto range = std::equal_range (tgtPIDs.begin (), tgtPIDs.end (), myRank);
644 if (range.second > range.first) {
645 result.numPermutes =
static_cast<LO
> (range.second - range.first);
649 result.numPermutes =
static_cast<LO
> (std::count (tgtPIDs.begin (), tgtPIDs.end (), myRank));
652 const LO numRemotes = numTargetMapRemoteOrPermuteGlobalIndices - result.numPermutes;
653 result.numSameIDs =
static_cast<LO
> (sourceMap.getLocalNumElements ());
656 std::ostringstream os;
657 os << *verboseHeader <<
"- numSame=" << result.numSameIDs
658 <<
", numPermutes=" << result.numPermutes
659 <<
", numRemotes=" << numRemotes << endl;
663 if (result.numPermutes == 0) {
665 std::ostringstream os;
666 os << *verboseHeader <<
"- No permutes" << endl;
669 result.remoteGIDs = std::vector<GO> (tgtGIDs.begin () + numLclSrcIDs, tgtGIDs.end ());
670 result.remotePIDs.swap (tgtPIDs);
671 result.remoteLIDs.resize (numRemotes);
672 for (LO k = 0; k < numRemotes; ++k) {
673 const LO tgtLid = result.numSameIDs + k;
674 result.remoteLIDs[k] = tgtLid;
677 std::ostringstream os;
678 os << *verboseHeader <<
"- Remote GIDs: "
679 << Teuchos::toString (result.remoteGIDs) << endl;
680 os << *verboseHeader <<
"- Remote PIDs: "
681 << Teuchos::toString (result.remotePIDs) << endl;
682 os << *verboseHeader <<
"- Remote LIDs: "
683 << Teuchos::toString (result.remoteLIDs) << endl;
691 result.remoteGIDs.reserve (numRemotes);
692 result.remoteLIDs.reserve (numRemotes);
693 result.remotePIDs.reserve (numRemotes);
694 for (LO k = 0; k < numTargetMapRemoteOrPermuteGlobalIndices; ++k) {
695 const LO tgtLid = result.numSameIDs + k;
696 const GO tgtGid = tgtGIDs[numLclSrcIDs + k];
697 const int tgtPid = tgtPIDs[k];
699 if (tgtPid != myRank) {
700 result.remoteGIDs.push_back (tgtGid);
701 result.remoteLIDs.push_back (tgtLid);
702 result.remotePIDs.push_back (tgtPid);
706 std::ostringstream os;
707 os << *verboseHeader <<
"- Some permutes" << endl;
712 if (sourceMap.isDistributed ()) {
714 std::ostringstream os;
715 os << *verboseHeader <<
"- Sort remotes by PID, as Import always does"
717 << *verboseHeader <<
"-- remotePIDs before: "
718 << Teuchos::toString (result.remotePIDs) << endl
719 << *verboseHeader <<
"-- remoteGIDs before: "
720 << Teuchos::toString (result.remoteGIDs) << endl
721 << *verboseHeader <<
"-- remoteLIDs before: "
722 << Teuchos::toString (result.remoteLIDs) << endl;
726 sort3 (result.remotePIDs.begin (),
727 result.remotePIDs.end (),
728 result.remoteGIDs.begin (),
729 result.remoteLIDs.begin ());
731 std::ostringstream os;
732 os << *verboseHeader <<
"-- remotePIDs after: "
733 << Teuchos::toString (result.remotePIDs) << endl
734 << *verboseHeader <<
"-- remoteGIDs after: "
735 << Teuchos::toString (result.remoteGIDs) << endl
736 << *verboseHeader <<
"-- remoteLIDs after: "
737 << Teuchos::toString (result.remoteLIDs) << endl;
738 std::cerr << os.str ();
743 std::ostringstream os;
744 os << *verboseHeader <<
"- Make target Map" << endl;
747 using ::Teuchos::rcp;
748 typedef ::Tpetra::Map<LO, GO, NT> map_type;
749 typedef ::Tpetra::global_size_t GST;
750 const GST MAP_COMPUTES_GLOBAL_COUNT = ::Teuchos::OrdinalTraits<GST>::invalid ();
751 result.targetMap = rcp (
new map_type (MAP_COMPUTES_GLOBAL_COUNT,
754 sourceMap.getIndexBase (),
755 sourceMap.getComm ()));
757 std::ostringstream os;
758 os << *verboseHeader <<
"- Done with sameSPR..." << endl;
765 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
768 const GlobalOrdinal targetMapRemoteOrPermuteGlobalIndices[],
769 const int targetMapRemoteOrPermuteProcessRanks[],
770 const LocalOrdinal numTargetMapRemoteOrPermuteGlobalIndices,
771 const bool mayReorderTargetMapIndicesLocally,
772 const Teuchos::RCP<Teuchos::ParameterList>& plist,
773 const Teuchos::RCP<Teuchos::FancyOStream>& debugOutput) :
777 base_type (sourceMap, Teuchos::null, debugOutput, plist,
"Import")
779 using ::Tpetra::Details::Behavior;
780 using ::Tpetra::Details::makeDualViewFromOwningHostView;
781 using ::Tpetra::Details::makeDualViewFromVector;
782 using ::Tpetra::Details::printDualView;
783 using ::Tpetra::Details::view_alloc_no_init;
784 using Teuchos::ArrayView;
785 using Teuchos::getFancyOStream;
788 using Teuchos::rcpFromRef;
790 typedef LocalOrdinal LO;
791 typedef GlobalOrdinal GO;
794 const bool debug = Behavior::debug (
"Import") ||
795 Behavior::debug (
"Tpetra::Import");
797 std::unique_ptr<std::string> verbPfx;
798 if (this->verbose ()) {
799 std::ostringstream os;
800 const int myRank = sourceMap->getComm ()->getRank ();
801 os <<
"Proc " << myRank <<
": Tpetra::Import ctor from remotes: ";
802 verbPfx = std::unique_ptr<std::string> (
new std::string (os.str ()));
803 os <<
"mayReorder=" << (mayReorderTargetMapIndicesLocally ?
"true" :
"false")
809 ImportLocalSetupResult<LO, GO, NT> localSetupResult =
810 setupSamePermuteRemoteFromUserGlobalIndexList<LO, GO, NT>
812 targetMapRemoteOrPermuteGlobalIndices,
813 targetMapRemoteOrPermuteProcessRanks,
814 numTargetMapRemoteOrPermuteGlobalIndices,
815 mayReorderTargetMapIndicesLocally,
827 localSetupResult.targetMap,
828 this->TransferData_->out_,
830 this->TransferData_->numSameIDs_ = localSetupResult.numSameIDs;
833 makeDualViewFromVector (this->TransferData_->remoteLIDs_,
834 localSetupResult.remoteLIDs,
843 this->TransferData_->isLocallyComplete_ =
true;
845 Teuchos::Array<GO> exportGIDs;
846 if (sourceMap->isDistributed ()) {
847 if (this->verbose ()) {
848 std::ostringstream os;
849 os << *verbPfx <<
"Make Distributor (createFromRecvs)" << endl;
852 ArrayView<const GO> remoteGIDs (localSetupResult.remoteGIDs.data (),
853 localSetupResult.remoteGIDs.size ());
854 ArrayView<const int> remotePIDs (localSetupResult.remotePIDs.data (),
855 localSetupResult.remotePIDs.size ());
860 Distributor& distributor = this->TransferData_->distributor_;
864 this->TransferData_->exportPIDs_);
873 if (this->verbose ()) {
874 std::ostringstream os;
875 os << *verbPfx <<
"Compute exportLIDs" << endl;
878 using size_type =
typename Teuchos::Array<GO>::size_type;
879 const size_type numExportIDs = exportGIDs.size ();
881 typename decltype (this->TransferData_->exportLIDs_)::t_host
882 exportLIDs (view_alloc_no_init (
"exportLIDs"), numExportIDs);
884 for (size_type k = 0; k < numExportIDs; ++k) {
885 exportLIDs[k] = sourceMap->getLocalElement (exportGIDs[k]);
887 makeDualViewFromOwningHostView (this->TransferData_->exportLIDs_, exportLIDs);
890 if (this->verbose ()) {
891 std::ostringstream os;
893 printDualView (os, this->TransferData_->remoteLIDs_,
894 "ImportExportData::remoteLIDs_");
898 if (this->verbose ()) {
899 std::ostringstream os;
900 os << *verbPfx <<
"Done!" << endl;
905 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
909 const Teuchos::EVerbosityLevel verbLevel)
const
912 this->describeImpl (out,
"Tpetra::Import", verbLevel);
915 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
919 auto out = Teuchos::getFancyOStream (Teuchos::rcpFromRef (os));
921 this->describe (*out, Teuchos::VERB_EXTREME);
924 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
929 using ::Tpetra::Details::makeDualViewFromOwningHostView;
930 using ::Tpetra::Details::ProfilingRegion;
931 using ::Tpetra::Details::view_alloc_no_init;
933 using Teuchos::Array;
934 using Teuchos::ArrayRCP;
935 using Teuchos::ArrayView;
938 typedef LocalOrdinal LO;
939 typedef GlobalOrdinal GO;
940 typedef typename ArrayView<const GO>::size_type size_type;
941 ProfilingRegion regionExport (
"Tpetra::Import::setupSamePermuteRemote");
943 const map_type& source = * (this->getSourceMap ());
944 const map_type& target = * (this->getTargetMap ());
945 ArrayView<const GO> sourceGIDs = source.getLocalElementList ();
946 ArrayView<const GO> targetGIDs = target.getLocalElementList ();
948 #ifdef HAVE_TPETRA_DEBUG
949 ArrayView<const GO> rawSrcGids = sourceGIDs;
950 ArrayView<const GO> rawTgtGids = targetGIDs;
952 const GO*
const rawSrcGids = sourceGIDs.getRawPtr ();
953 const GO*
const rawTgtGids = targetGIDs.getRawPtr ();
954 #endif // HAVE_TPETRA_DEBUG
955 const size_type numSrcGids = sourceGIDs.size ();
956 const size_type numTgtGids = targetGIDs.size ();
957 const size_type numGids = std::min (numSrcGids, numTgtGids);
965 size_type numSameGids = 0;
966 for ( ; numSameGids < numGids && rawSrcGids[numSameGids] == rawTgtGids[numSameGids]; ++numSameGids)
968 this->TransferData_->numSameIDs_ = numSameGids;
982 const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid ();
983 const LO numTgtLids = as<LO> (numTgtGids);
986 for (LO tgtLid = numSameGids; tgtLid < numTgtLids; ++tgtLid) {
987 const GO curTargetGid = rawTgtGids[tgtLid];
991 const LO srcLid = source.getLocalElement (curTargetGid);
992 if (srcLid != LINVALID) {
996 const LO numRemotes = (numTgtLids - numSameGids) - numPermutes;
998 using host_perm_type =
999 typename decltype (this->TransferData_->permuteToLIDs_)::t_host;
1000 host_perm_type permuteToLIDs
1001 (view_alloc_no_init (
"permuteToLIDs"), numPermutes);
1002 host_perm_type permuteFromLIDs
1003 (view_alloc_no_init (
"permuteFromLIDs"), numPermutes);
1004 typename decltype (this->TransferData_->remoteLIDs_)::t_host remoteLIDs
1008 LO numPermutes2 = 0;
1010 for (LO tgtLid = numSameGids; tgtLid < numTgtLids; ++tgtLid) {
1011 const GO curTargetGid = rawTgtGids[tgtLid];
1012 const LO srcLid = source.getLocalElement (curTargetGid);
1013 if (srcLid != LINVALID) {
1014 permuteToLIDs[numPermutes2] = tgtLid;
1015 permuteFromLIDs[numPermutes2] = srcLid;
1019 remoteGIDs.push_back (curTargetGid);
1020 remoteLIDs[numRemotes2] = tgtLid;
1024 TEUCHOS_ASSERT( numPermutes == numPermutes2 );
1025 TEUCHOS_ASSERT( numRemotes == numRemotes2 );
1026 TEUCHOS_ASSERT(
size_t (numPermutes) + remoteGIDs.size () == size_t (numTgtLids - numSameGids) );
1032 if (remoteLIDs.extent (0) != 0 && ! source.isDistributed ()) {
1038 this->TransferData_->isLocallyComplete_ =
false;
1042 (
true, std::runtime_error,
"::setupSamePermuteRemote(): Target has "
1043 "remote LIDs but Source is not distributed globally. Importing to a "
1044 "submap of the target map.");
1049 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1050 void Import<LocalOrdinal,GlobalOrdinal,Node>::
1051 setupExport (Teuchos::Array<GlobalOrdinal>& remoteGIDs,
1053 Teuchos::Array<int>& userRemotePIDs,
1054 const Teuchos::RCP<Teuchos::ParameterList>& plist)
1056 using ::Tpetra::Details::makeDualViewFromOwningHostView;
1057 using ::Tpetra::Details::view_alloc_no_init;
1058 using Teuchos::Array;
1059 using Teuchos::ArrayView;
1061 using GO = GlobalOrdinal;
1062 typedef typename Array<int>::difference_type size_type;
1063 const char tfecfFuncName[] =
"setupExport: ";
1064 const char suffix[] =
" Please report this bug to the Tpetra developers.";
1066 std::unique_ptr<std::string> prefix;
1067 if (this->verbose ()) {
1068 auto srcMap = this->getSourceMap ();
1069 auto comm = srcMap.is_null () ? Teuchos::null : srcMap->getComm ();
1070 const int myRank = comm.is_null () ? -1 : comm->getRank ();
1071 std::ostringstream os;
1072 os <<
"Proc " << myRank <<
": Tpetra::Import::setupExport: ";
1073 prefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
1074 os <<
"Start" << std::endl;
1075 this->verboseOutputStream () << os.str ();
1078 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1079 (this->getSourceMap ().is_null (), std::logic_error,
1080 "Source Map is null. " << suffix);
1081 const map_type& source = * (this->getSourceMap ());
1083 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1084 (! useRemotePIDs && (userRemotePIDs.size() > 0), std::invalid_argument,
1085 "remotePIDs are non-empty but their use has not been requested.");
1086 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1087 (userRemotePIDs.size () > 0 && remoteGIDs.size () != userRemotePIDs.size (),
1088 std::invalid_argument,
"remotePIDs must either be of size zero or match "
1089 "the size of remoteGIDs.");
1093 ArrayView<GO> remoteGIDsView = remoteGIDs ();
1094 ArrayView<int> remoteProcIDsView;
1114 Array<int> newRemotePIDs;
1117 if (! useRemotePIDs) {
1118 newRemotePIDs.resize (remoteGIDsView.size ());
1119 if (this->verbose ()) {
1120 std::ostringstream os;
1121 os << *prefix <<
"Call sourceMap.getRemoteIndexList" << endl;
1122 this->verboseOutputStream () << os.str ();
1124 lookup = source.getRemoteIndexList (remoteGIDsView, newRemotePIDs ());
1126 Array<int>& remoteProcIDs = useRemotePIDs ? userRemotePIDs : newRemotePIDs;
1132 this->TransferData_->isLocallyComplete_ =
false;
1137 (
true, std::runtime_error,
"::setupExport(): the source Map wasn't "
1138 "able to figure out which process owns one or more of the GIDs in the "
1139 "list of remote GIDs. This probably means that there is at least one "
1140 "GID owned by some process in the target Map which is not owned by any"
1141 " process in the source Map. (That is, the source and target Maps do "
1142 "not contain the same set of GIDs globally.)");
1148 const size_type numInvalidRemote =
1149 std::count_if (remoteProcIDs.begin (), remoteProcIDs.end (),
1150 std::bind (std::equal_to<int> (), -1, std::placeholders::_1));
1151 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1152 (numInvalidRemote == 0, std::logic_error,
"Calling getRemoteIndexList "
1153 "on the source Map returned IDNotPresent, but none of the returned "
1154 "\"remote\" process ranks are -1. Please report this bug to the "
1155 "Tpetra developers.");
1157 #ifdef HAVE_TPETRA_MMM_TIMINGS
1158 using Teuchos::TimeMonitor;
1160 if(!plist.is_null())
1161 label = plist->get(
"Timer Label",label);
1162 std::string prefix = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:setupExport:1 ");
1163 auto MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix)));
1169 const size_type totalNumRemote = this->getNumRemoteIDs ();
1170 if (numInvalidRemote == totalNumRemote) {
1172 remoteProcIDs.clear ();
1173 remoteGIDs.clear ();
1174 this->TransferData_->remoteLIDs_ =
1175 decltype (this->TransferData_->remoteLIDs_) ();
1180 size_type numValidRemote = 0;
1181 #ifdef HAVE_TPETRA_DEBUG
1182 ArrayView<GO> remoteGIDsPtr = remoteGIDsView;
1184 GO*
const remoteGIDsPtr = remoteGIDsView.getRawPtr ();
1185 #endif // HAVE_TPETRA_DEBUG
1188 auto remoteLIDs = this->TransferData_->remoteLIDs_.view_host ();
1190 for (size_type r = 0; r < totalNumRemote; ++r) {
1192 if (remoteProcIDs[r] != -1) {
1193 remoteProcIDs[numValidRemote] = remoteProcIDs[r];
1194 remoteGIDsPtr[numValidRemote] = remoteGIDsPtr[r];
1195 remoteLIDs[numValidRemote] = remoteLIDs[r];
1199 TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
1200 (numValidRemote != totalNumRemote - numInvalidRemote,
1201 std::logic_error,
"After removing invalid remote GIDs and packing "
1202 "the valid remote GIDs, numValidRemote = " << numValidRemote
1203 <<
" != totalNumRemote - numInvalidRemote = "
1204 << totalNumRemote - numInvalidRemote
1205 <<
". Please report this bug to the Tpetra developers.");
1207 remoteProcIDs.resize (numValidRemote);
1208 remoteGIDs.resize (numValidRemote);
1210 Kokkos::resize (remoteLIDs, numValidRemote);
1211 this->TransferData_->remoteLIDs_ = decltype (this->TransferData_->remoteLIDs_) ();
1215 remoteGIDsView = remoteGIDs ();
1223 this->TransferData_->remoteLIDs_.modify_host ();
1224 auto remoteLIDs = this->TransferData_->remoteLIDs_.view_host ();
1225 sort3 (remoteProcIDs.begin (),
1226 remoteProcIDs.end (),
1227 remoteGIDsView.getRawPtr (),
1228 remoteLIDs.data ());
1229 this->TransferData_->remoteLIDs_.sync_device ();
1237 Array<GO> exportGIDs;
1239 #ifdef HAVE_TPETRA_MMM_TIMINGS
1240 using Teuchos::TimeMonitor;
1242 if(!plist.is_null())
1243 label = plist->get(
"Timer Label",label);
1244 std::string prefix2 = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:setupExport:3 ");
1245 auto MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2)));
1248 if (this->verbose ()) {
1249 std::ostringstream os;
1250 os << *prefix <<
"Call createFromRecvs" << endl;
1251 this->verboseOutputStream () << endl;
1253 this->TransferData_->distributor_.createFromRecvs (remoteGIDsView ().getConst (),
1254 remoteProcIDs, exportGIDs,
1255 this->TransferData_->exportPIDs_);
1261 #ifdef HAVE_TPETRA_MMM_TIMINGS
1262 prefix2 = std::string(
"Tpetra ")+ label + std::string(
":iport_ctor:setupExport:4 ");
1263 MM = Teuchos::null; MM = rcp(
new TimeMonitor(*TimeMonitor::getNewTimer(prefix2)));
1269 const size_type numExportIDs = exportGIDs.size ();
1270 if (numExportIDs > 0) {
1271 typename decltype (this->TransferData_->exportLIDs_)::t_host
1273 ArrayView<const GO> expGIDs = exportGIDs ();
1275 for (size_type k = 0; k < numExportIDs; ++k) {
1276 exportLIDs[k] = source.getLocalElement (expGIDs[k]);
1281 if (this->verbose ()) {
1282 std::ostringstream os;
1283 os << *prefix <<
"Done!" << endl;
1284 this->verboseOutputStream () << os.str ();
1288 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1292 Teuchos::Array<std::pair<int,GlobalOrdinal>>& remotePGIDs,
1293 typename Teuchos::Array<GlobalOrdinal>::size_type& numSameGIDs,
1294 typename Teuchos::Array<GlobalOrdinal>::size_type& numPermuteGIDs,
1295 typename Teuchos::Array<GlobalOrdinal>::size_type& numRemoteGIDs,
1296 const Teuchos::ArrayView<const GlobalOrdinal>& sameGIDs1,
1297 const Teuchos::ArrayView<const GlobalOrdinal>& sameGIDs2,
1298 Teuchos::Array<GlobalOrdinal>& permuteGIDs1,
1299 Teuchos::Array<GlobalOrdinal>& permuteGIDs2,
1300 Teuchos::Array<GlobalOrdinal>& remoteGIDs1,
1301 Teuchos::Array<GlobalOrdinal>& remoteGIDs2,
1302 Teuchos::Array<int>& remotePIDs1,
1303 Teuchos::Array<int>& remotePIDs2)
const
1306 typedef GlobalOrdinal GO;
1307 typedef typename Teuchos::Array<GO>::size_type size_type;
1309 const size_type numSameGIDs1 = sameGIDs1.size();
1310 const size_type numSameGIDs2 = sameGIDs2.size();
1313 std::sort(permuteGIDs1.begin(), permuteGIDs1.end());
1314 std::sort(permuteGIDs2.begin(), permuteGIDs2.end());
1319 unionTgtGIDs.reserve(numSameGIDs1 + numSameGIDs2 +
1320 permuteGIDs1.size() + permuteGIDs2.size() +
1321 remoteGIDs1.size() + remoteGIDs2.size());
1325 typename Teuchos::Array<GO>::iterator permuteGIDs1_end;
1326 typename Teuchos::Array<GO>::iterator permuteGIDs2_end;
1327 if (numSameGIDs2 > numSameGIDs1) {
1329 numSameGIDs = numSameGIDs2;
1330 permuteGIDs2_end = permuteGIDs2.end();
1333 std::copy(sameGIDs2.begin(), sameGIDs2.end(), std::back_inserter(unionTgtGIDs));
1337 permuteGIDs1_end = std::set_difference(permuteGIDs1.begin(), permuteGIDs1.end(),
1338 unionTgtGIDs.begin()+numSameGIDs1, unionTgtGIDs.end(),
1339 permuteGIDs1.begin());
1343 numSameGIDs = numSameGIDs1;
1344 permuteGIDs1_end = permuteGIDs1.end();
1347 std::copy(sameGIDs1.begin(), sameGIDs1.end(), std::back_inserter(unionTgtGIDs));
1351 permuteGIDs2_end = std::set_difference(permuteGIDs2.begin(), permuteGIDs2.end(),
1352 unionTgtGIDs.begin()+numSameGIDs2, unionTgtGIDs.end(),
1353 permuteGIDs2.begin());
1358 std::set_union(permuteGIDs1.begin(), permuteGIDs1_end,
1359 permuteGIDs2.begin(), permuteGIDs2_end,
1360 std::back_inserter(unionTgtGIDs));
1363 Teuchos::Array<std::pair<int,GO>> remotePGIDs1(remoteGIDs1.size());
1364 for (size_type k=0; k<remoteGIDs1.size(); k++)
1365 remotePGIDs1[k] = std::make_pair(remotePIDs1[k], remoteGIDs1[k]);
1366 std::sort(remotePGIDs1.begin(), remotePGIDs1.end());
1368 Teuchos::Array<std::pair<int,GO>> remotePGIDs2(remoteGIDs2.size());
1369 for (size_type k=0; k<remoteGIDs2.size(); k++)
1370 remotePGIDs2[k] = std::make_pair(remotePIDs2[k], remoteGIDs2[k]);
1371 std::sort(remotePGIDs2.begin(), remotePGIDs2.end());
1373 remotePGIDs.reserve(remotePGIDs1.size()+remotePGIDs2.size());
1374 std::merge(remotePGIDs1.begin(), remotePGIDs1.end(),
1375 remotePGIDs2.begin(), remotePGIDs2.end(),
1376 std::back_inserter(remotePGIDs));
1377 auto it = std::unique(remotePGIDs.begin(), remotePGIDs.end());
1378 remotePGIDs.resize(std::distance(remotePGIDs.begin(), it));
1381 const size_type oldSize = unionTgtGIDs.size();
1382 unionTgtGIDs.resize(oldSize+remotePGIDs.size());
1383 for (size_type
start=oldSize, k=0; k<remotePGIDs.size(); k++)
1384 unionTgtGIDs[
start+k] = remotePGIDs[k].second;
1387 numRemoteGIDs = remotePGIDs.size();
1388 numPermuteGIDs = unionTgtGIDs.size() - numSameGIDs - numRemoteGIDs;
1393 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1394 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
1398 using ::Tpetra::Details::Behavior;
1399 using Teuchos::Array;
1400 using Teuchos::ArrayView;
1402 using Teuchos::Comm;
1405 using Teuchos::outArg;
1406 using Teuchos::REDUCE_MIN;
1407 using Teuchos::reduceAll;
1409 using LO = LocalOrdinal;
1410 using GO = GlobalOrdinal;
1412 using size_type =
typename Array<GO>::size_type;
1414 #ifdef HAVE_TPETRA_MMM_TIMINGS
1415 using Teuchos::TimeMonitor;
1416 std::string label = std::string(
"Tpetra::Import::setUnion");
1417 TimeMonitor MM(*TimeMonitor::getNewTimer(label));
1420 RCP<const map_type> srcMap = this->getSourceMap ();
1421 RCP<const map_type> tgtMap1 = this->getTargetMap ();
1423 RCP<const Comm<int> > comm = srcMap->getComm ();
1425 const bool debug = Behavior::debug (
"Import::setUnion") ||
1426 Behavior::debug (
"Tpetra::Import::setUnion");
1429 TEUCHOS_TEST_FOR_EXCEPTION
1430 (! srcMap->isSameAs (* (rhs.
getSourceMap ())), std::invalid_argument,
1431 "Tpetra::Import::setUnion: The source Map of the input Import must be the "
1432 "same as (in the sense of Map::isSameAs) the source Map of this Import.");
1433 const Comm<int>& comm1 = * (tgtMap1->getComm ());
1434 const Comm<int>& comm2 = * (tgtMap2->getComm ());
1435 TEUCHOS_TEST_FOR_EXCEPTION
1437 std::invalid_argument,
"Tpetra::Import::setUnion: "
1438 "The target Maps must have congruent communicators.");
1444 if (tgtMap1->isSameAs (*tgtMap2)) {
1445 return rcp (
new import_type (*
this));
1453 const size_type numSameGIDs1 = this->getNumSameIDs();
1454 ArrayView<const GO> sameGIDs1 = (tgtMap1->getLocalElementList())(0,numSameGIDs1);
1457 ArrayView<const GO> sameGIDs2 = (tgtMap2->getLocalElementList())(0,numSameGIDs2);
1460 ArrayView<const LO> permuteToLIDs1 = this->getPermuteToLIDs();
1461 Array<GO> permuteGIDs1(permuteToLIDs1.size());
1462 for (size_type k=0; k<permuteGIDs1.size(); k++)
1463 permuteGIDs1[k] = tgtMap1->getGlobalElement(permuteToLIDs1[k]);
1466 Array<GO> permuteGIDs2(permuteToLIDs2.size());
1467 for (size_type k=0; k<permuteGIDs2.size(); k++)
1468 permuteGIDs2[k] = tgtMap2->getGlobalElement(permuteToLIDs2[k]);
1471 ArrayView<const LO> remoteLIDs1 = this->getRemoteLIDs();
1472 Array<GO> remoteGIDs1(remoteLIDs1.size());
1473 for (size_type k=0; k<remoteLIDs1.size(); k++)
1474 remoteGIDs1[k] = this->getTargetMap()->getGlobalElement(remoteLIDs1[k]);
1477 Array<GO> remoteGIDs2(remoteLIDs2.size());
1478 for (size_type k=0; k<remoteLIDs2.size(); k++)
1479 remoteGIDs2[k] = rhs.
getTargetMap()->getGlobalElement(remoteLIDs2[k]);
1482 Array<int> remotePIDs1;
1483 Tpetra::Import_Util::getRemotePIDs(*
this, remotePIDs1);
1485 Array<int> remotePIDs2;
1486 Tpetra::Import_Util::getRemotePIDs(rhs, remotePIDs2);
1489 Array<GO> unionTgtGIDs;
1490 Array<std::pair<int,GO>> remotePGIDs;
1491 size_type numSameIDsUnion, numPermuteIDsUnion, numRemoteIDsUnion;
1493 findUnionTargetGIDs(unionTgtGIDs, remotePGIDs,
1494 numSameIDsUnion, numPermuteIDsUnion, numRemoteIDsUnion,
1495 sameGIDs1, sameGIDs2, permuteGIDs1, permuteGIDs2,
1496 remoteGIDs1, remoteGIDs2, remotePIDs1, remotePIDs2);
1499 Array<LO> remoteLIDsUnion(numRemoteIDsUnion);
1500 Array<GO> remoteGIDsUnion(numRemoteIDsUnion);
1501 Array<int> remotePIDsUnion(numRemoteIDsUnion);
1502 const size_type unionRemoteIDsStart = numSameIDsUnion + numPermuteIDsUnion;
1503 for (size_type k = 0; k < numRemoteIDsUnion; ++k) {
1504 remoteLIDsUnion[k] = unionRemoteIDsStart + k;
1505 remotePIDsUnion[k] = remotePGIDs[k].first;
1506 remoteGIDsUnion[k] = remotePGIDs[k].second;
1511 Array<LO> permuteToLIDsUnion(numPermuteIDsUnion);
1512 Array<LO> permuteFromLIDsUnion(numPermuteIDsUnion);
1514 for (size_type k = 0; k < numPermuteIDsUnion; ++k) {
1515 size_type idx = numSameIDsUnion + k;
1516 permuteToLIDsUnion[k] =
static_cast<LO
>(idx);
1517 permuteFromLIDsUnion[k] = srcMap->getLocalElement(unionTgtGIDs[idx]);
1520 #ifdef HAVE_TPETRA_MMM_TIMINGS
1521 MM.disableTimer(label);
1522 label =
"Tpetra::Import::setUnion : Construct Target Map";
1523 TimeMonitor MM2(*TimeMonitor::getNewTimer(label));
1527 const GST INVALID = Teuchos::OrdinalTraits<GST>::invalid ();
1528 const GO indexBaseUnion = std::min(tgtMap1->getIndexBase(), tgtMap2->getIndexBase());
1529 RCP<const map_type> unionTgtMap =
1530 rcp(
new map_type(INVALID, unionTgtGIDs(), indexBaseUnion, comm));
1532 #ifdef HAVE_TPETRA_MMM_TIMINGS
1533 MM2.disableTimer(label);
1534 label =
"Tpetra::Import::setUnion : Export GIDs";
1535 TimeMonitor MM3(*TimeMonitor::getNewTimer(label));
1546 Array<GO> exportGIDsUnion;
1547 Array<LO> exportLIDsUnion;
1548 Array<int> exportPIDsUnion;
1549 Distributor distributor (comm, this->TransferData_->out_);
1551 #ifdef TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1559 ArrayView<const LO> exportLIDs1 = this->getExportLIDs ();
1560 ArrayView<const LO> exportPIDs1 = this->getExportPIDs ();
1573 Array<LO> exportLIDs1Copy (exportLIDs1.begin (), exportLIDs1.end ());
1574 Array<int> exportPIDs1Copy (exportLIDs1.begin (), exportLIDs1.end ());
1575 sort2 (exportLIDs1Copy.begin (), exportLIDs1Copy.end (),
1576 exportPIDs1Copy.begin ());
1577 typename ArrayView<LO>::iterator exportLIDs1_end = exportLIDs1Copy.end ();
1578 typename ArrayView<LO>::iterator exportPIDs1_end = exportPIDs1Copy.end ();
1579 merge2 (exportLIDs1_end, exportPIDs1_end,
1580 exportLIDs1Copy.begin (), exportLIDs1_end,
1581 exportPIDs1Copy.begin (), exportPIDs1_end,
1584 Array<LO> exportLIDs2Copy (exportLIDs2.begin (), exportLIDs2.end ());
1585 Array<int> exportPIDs2Copy (exportLIDs2.begin (), exportLIDs2.end ());
1586 sort2 (exportLIDs2Copy.begin (), exportLIDs2Copy.end (),
1587 exportPIDs2Copy.begin ());
1588 typename ArrayView<LO>::iterator exportLIDs2_end = exportLIDs2Copy.end ();
1589 typename ArrayView<LO>::iterator exportPIDs2_end = exportPIDs2Copy.end ();
1590 merge2 (exportLIDs2_end, exportPIDs2_end,
1591 exportLIDs2Copy.begin (), exportLIDs2_end,
1592 exportPIDs2Copy.begin (), exportPIDs2_end,
1599 keyValueMerge (exportLIDs1Copy.begin (), exportLIDs1Copy.end (),
1600 exportPIDs1Copy.begin (), exportPIDs1Copy.end (),
1601 exportLIDs2Copy.begin (), exportLIDs2Copy.end (),
1602 exportPIDs2Copy.begin (), exportPIDs2Copy.end (),
1603 std::back_inserter (exportLIDsUnion),
1604 std::back_inserter (exportPIDsUnion),
1608 sort2 (exportPIDsUnion.begin (), exportPIDsUnion.end (),
1609 exportLIDsUnion.begin ());
1615 #else // NOT TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1623 remotePIDsUnion().getConst(),
1624 exportGIDsUnion, exportPIDsUnion);
1627 const size_type numExportIDsUnion = exportGIDsUnion.size ();
1628 exportLIDsUnion.resize (numExportIDsUnion);
1629 for (size_type k = 0; k < numExportIDsUnion; ++k) {
1630 exportLIDsUnion[k] = srcMap->getLocalElement (exportGIDsUnion[k]);
1632 #endif // TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1635 #ifdef HAVE_TPETRA_MMM_TIMINGS
1636 MM3.disableTimer(label);
1637 label =
"Tpetra::Import::setUnion : Construct Import";
1638 TimeMonitor MM4(*TimeMonitor::getNewTimer(label));
1640 RCP<const import_type> unionImport =
1641 rcp (
new import_type (srcMap, unionTgtMap,
1642 as<size_t> (numSameIDsUnion),
1643 permuteToLIDsUnion, permuteFromLIDsUnion,
1644 remoteLIDsUnion, exportLIDsUnion,
1645 exportPIDsUnion, distributor,
1646 this->TransferData_->out_));
1650 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1651 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
1655 using Teuchos::Array;
1656 using Teuchos::ArrayView;
1658 using Teuchos::Comm;
1661 using Teuchos::outArg;
1662 using Teuchos::REDUCE_MIN;
1663 using Teuchos::reduceAll;
1664 typedef LocalOrdinal LO;
1665 typedef GlobalOrdinal GO;
1666 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> > unionImport;
1667 RCP<const map_type> srcMap = this->getSourceMap ();
1668 RCP<const map_type> tgtMap = this->getTargetMap ();
1669 RCP<const Comm<int> > comm = srcMap->getComm ();
1671 ArrayView<const GO> srcGIDs = srcMap->getLocalElementList ();
1672 ArrayView<const GO> tgtGIDs = tgtMap->getLocalElementList ();
1675 size_t numSameIDsNew = srcMap->getLocalNumElements ();
1676 size_t numRemoteIDsNew = this->getNumRemoteIDs ();
1677 Array<LO> permuteToLIDsNew, permuteFromLIDsNew;
1680 ArrayView<const LO> remoteLIDsOld = this->getRemoteLIDs ();
1681 ArrayView<const LO> exportLIDsOld = this->getExportLIDs ();
1684 Array<GO> GIDs(numSameIDsNew + numRemoteIDsNew);
1685 for(
size_t i=0; i<numSameIDsNew; i++)
1686 GIDs[i] = srcGIDs[i];
1689 Array<LO> remoteLIDsNew(numRemoteIDsNew);
1690 for(
size_t i=0; i<numRemoteIDsNew; i++) {
1691 GIDs[numSameIDsNew + i] = tgtGIDs[remoteLIDsOld[i]];
1692 remoteLIDsNew[i] = numSameIDsNew+i;
1696 GO GO_INVALID = Teuchos::OrdinalTraits<GO>::invalid();
1697 RCP<const map_type> targetMapNew =
1698 rcp (
new map_type (GO_INVALID, GIDs, tgtMap->getIndexBase (),
1699 tgtMap->getComm ()));
1702 Array<int> exportPIDsnew (this->getExportPIDs ());
1703 Array<LO> exportLIDsnew (this->getExportLIDs ());
1721 template <
class LocalOrdinal,
class GlobalOrdinal,
class Node>
1722 Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
1726 using ::Tpetra::Details::Behavior;
1727 using ::Tpetra::Details::gathervPrint;
1728 using Teuchos::outArg;
1730 using Teuchos::REDUCE_MIN;
1731 using Teuchos::reduceAll;
1733 using LO = LocalOrdinal;
1734 using GO = GlobalOrdinal;
1737 const char funcPrefix[] =
"Tpetra::createRemoteOnlyImport: ";
1740 const bool debug = Behavior::debug ();
1742 const size_t NumRemotes = this->getNumRemoteIDs ();
1743 std::unique_ptr<std::string> procPrefix;
1744 Teuchos::RCP<const Teuchos::Comm<int>> comm;
1746 comm = remoteTarget.is_null () ? Teuchos::null :
1747 remoteTarget->getComm ();
1748 std::ostringstream os;
1750 if (comm.is_null ()) {
1754 os << comm->getRank ();
1757 procPrefix = std::unique_ptr<std::string> (
new std::string (os.str ()));
1761 std::ostringstream lclErr;
1762 if (remoteTarget.is_null ()) {
1765 else if (NumRemotes != remoteTarget->getLocalNumElements ()) {
1767 lclErr << *procPrefix <<
"getNumRemoteIDs() = " << NumRemotes
1768 <<
" != remoteTarget->getLocalNumElements() = "
1769 << remoteTarget->getLocalNumElements () <<
"." << endl;
1772 if (comm.is_null ()) {
1773 lclSuccess = gblSuccess;
1776 reduceAll (*comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
1778 TEUCHOS_TEST_FOR_EXCEPTION
1779 (gblSuccess == -1, std::invalid_argument, funcPrefix
1780 <<
"Input target Map is null on at least one process.");
1782 if (gblSuccess != 1) {
1783 if (comm.is_null ()) {
1784 TEUCHOS_TEST_FOR_EXCEPTION
1785 (
true, std::runtime_error, lclErr.str ());
1788 std::ostringstream gblErr;
1789 gblErr << funcPrefix << endl;
1790 gathervPrint (gblErr, lclErr.str (), *comm);
1791 TEUCHOS_TEST_FOR_EXCEPTION
1792 (
true, std::runtime_error, gblErr.str ());
1798 Teuchos::ArrayView<const LO> oldRemoteLIDs = this->getRemoteLIDs ();
1799 Teuchos::Array<LO> newRemoteLIDs (NumRemotes);
1800 const map_type& tgtMap = * (this->getTargetMap ());
1801 size_t badCount = 0;
1803 std::unique_ptr<std::vector<size_t>> badIndices;
1805 badIndices = std::unique_ptr<std::vector<size_t>> (
new std::vector<size_t>);
1808 for (
size_t i = 0; i < NumRemotes; ++i) {
1809 const LO oldLclInd = oldRemoteLIDs[i];
1810 if (oldLclInd == Teuchos::OrdinalTraits<LO>::invalid ()) {
1812 if (debug) { badIndices->push_back (i); }
1816 if (gblInd == Teuchos::OrdinalTraits<GO>::invalid ()) {
1818 if (debug) { badIndices->push_back (i); }
1821 const LO newLclInd = remoteTarget->getLocalElement (gblInd);
1822 if (newLclInd == Teuchos::OrdinalTraits<LO>::invalid ()) {
1824 if (debug) { badIndices->push_back (i); }
1827 newRemoteLIDs[i] = newLclInd;
1829 if (i > 0 && newRemoteLIDs[i] < newRemoteLIDs[i-1]) {
1831 if (debug) { badIndices->push_back (i); }
1835 if (badCount != 0) {
1840 if (comm.is_null ()) {
1841 lclSuccess = gblSuccess;
1844 reduceAll (*comm, REDUCE_MIN, lclSuccess, outArg (gblSuccess));
1846 std::ostringstream lclErr;
1847 if (lclSuccess != 1) {
1848 lclErr << *procPrefix <<
"Count of bad indices: " << badCount
1849 <<
", bad indices: [";
1852 for (
size_t k = 0; k < badCount; ++k) {
1853 const size_t badIndex = (*badIndices)[k];
1854 lclErr <<
"(" << badIndex <<
","
1855 << oldRemoteLIDs[badIndex] <<
")";
1856 if (k +
size_t (1) < badCount) {
1860 lclErr <<
"]" << endl;
1863 if (gblSuccess != 1) {
1864 std::ostringstream gblErr;
1865 gblErr << funcPrefix <<
"this->getRemoteLIDs() has \"bad\" "
1866 "indices on one or more processes. \"Bad\" means that the "
1867 "indices are invalid, they don't exist in the target Map, "
1868 "they don't exist in remoteTarget, or they are not in "
1869 "sorted order. In what follows, I will show the \"bad\" "
1870 "indices as (k, LID) pairs, where k is the zero-based "
1871 "index of the LID in this->getRemoteLIDs()." << endl;
1872 if (comm.is_null ()) {
1873 gblErr << lclErr.str ();
1876 gathervPrint (gblErr, lclErr.str (), *comm);
1878 TEUCHOS_TEST_FOR_EXCEPTION
1879 (
true, std::runtime_error, gblErr.str ());
1883 TEUCHOS_TEST_FOR_EXCEPTION
1884 (lclSuccess == 0, std::runtime_error, funcPrefix
1885 <<
"this->getRemoteLIDs() has " << badCount
1886 <<
"ind" << (badCount == 1 ?
"ex" :
"ices")
1887 <<
" \"bad\" indices on this process." << endl);
1895 Teuchos::Array<int> newExportPIDs (this->getExportPIDs ());
1896 Teuchos::Array<LO> newExportLIDs (this->getExportLIDs ());
1897 Teuchos::Array<LO> dummy;
1900 return rcp (
new import_type (this->getSourceMap (), remoteTarget,
1901 static_cast<size_t> (0), dummy, dummy,
1902 newRemoteLIDs, newExportLIDs,
1903 newExportPIDs, newDistor));
1908 #define TPETRA_IMPORT_CLASS_INSTANT(LO, GO, NODE) \
1909 template class Import< LO , GO , NODE >;
1918 #define TPETRA_IMPORT_INSTANT(LO, GO, NODE) \
1919 TPETRA_IMPORT_CLASS_INSTANT(LO, GO, NODE)
1921 #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.
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.
void sort3(const IT1 &first1, const IT1 &last1, const IT2 &first2, const IT3 &first3, const bool stableSort=false)
Sort the first array, and apply the same permutation to the second and third arrays.
Teuchos::ArrayView< const int > getExportPIDs() const
List of processes to which entries will be sent.
Teuchos::ArrayView< const LocalOrdinal > getPermuteToLIDs() const
List of local IDs in the target Map that are permuted.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Describe this object in a human-readable way to the given output stream.
Teuchos::RCP< const map_type > getTargetMap() const
The target Map used to construct this Export or Import.
size_t getNumSameIDs() const
Number of initial identical IDs.
void sort(View &view, const size_t &size)
Convenience wrapper for std::sort for host-accessible views.
size_t getNumRemoteIDs() const
Number of entries not on the calling process.
size_t createFromSends(const Teuchos::ArrayView< const int > &exportProcIDs)
Set up Distributor using list of process ranks to which this process will send.
Teuchos::RCP< const Import< LocalOrdinal, GlobalOrdinal, Node > > setUnion() const
Return the union of this Import this->getSourceMap()
size_t global_size_t
Global size_t object.
Import(const Teuchos::RCP< const map_type > &source, const Teuchos::RCP< const map_type > &target)
Construct an Import from the source and target Maps.
Teuchos::ArrayView< const LocalOrdinal > getRemoteLIDs() const
List of entries in the target Map to receive from other processes.
global_ordinal_type getGlobalElement(local_ordinal_type localIndex) const
The global index corresponding to the given local index.
void keyValueMerge(KeyInputIterType keyBeg1, KeyInputIterType keyEnd1, ValueInputIterType valBeg1, ValueInputIterType valEnd1, KeyInputIterType keyBeg2, KeyInputIterType keyEnd2, ValueInputIterType valBeg2, ValueInputIterType valEnd2, KeyOutputIterType keyOut, ValueOutputIterType valOut, BinaryFunction f)
Merge two sorted (by keys) sequences of unique (key,value) pairs by combining pairs with equal keys...
void createFromSendsAndRecvs(const Teuchos::ArrayView< const int > &exportProcIDs, const Teuchos::ArrayView< const int > &remoteProcIDs)
Set up Distributor using list of process ranks to which to send, and list of process ranks from which...
auto view_alloc_no_init(const std::string &label) ->
Use in place of the string label as the first argument of Kokkos::View's constructor, in case you want to allocate without initializing.
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
void sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2, const bool stableSort=false)
Sort the first array, and apply the resulting permutation to the second array.
#define TPETRA_ABUSE_WARNING(throw_exception_test, Exception, msg)
Handle an abuse warning, according to HAVE_TPETRA_THROW_ABUSE_WARNINGS and HAVE_TPETRA_PRINT_ABUSE_WA...
Implementation detail of Import and Export.
Sets up and executes a communication plan for a Tpetra DistObject.
Teuchos::RCP< ImportExportData< LocalOrdinal, GlobalOrdinal, Node > > TransferData_
All the data needed for executing the Export communication plan.
Teuchos::RCP< const map_type > getSourceMap() const
The source Map used to construct this Export or Import.
void findUnionTargetGIDs(Teuchos::Array< GlobalOrdinal > &unionTgtGIDs, Teuchos::Array< std::pair< int, GlobalOrdinal >> &remotePGIDs, typename Teuchos::Array< GlobalOrdinal >::size_type &numSameGIDs, typename Teuchos::Array< GlobalOrdinal >::size_type &numPermuteGIDs, typename Teuchos::Array< GlobalOrdinal >::size_type &numRemoteGIDs, const Teuchos::ArrayView< const GlobalOrdinal > &sameGIDs1, const Teuchos::ArrayView< const GlobalOrdinal > &sameGIDs2, Teuchos::Array< GlobalOrdinal > &permuteGIDs1, Teuchos::Array< GlobalOrdinal > &permuteGIDs2, Teuchos::Array< GlobalOrdinal > &remoteGIDs1, Teuchos::Array< GlobalOrdinal > &remoteGIDs2, Teuchos::Array< int > &remotePIDs1, Teuchos::Array< int > &remotePIDs2) const
Find the union of the target IDs from two Import objects.
void start()
Start the deep_copy counter.
Teuchos::ArrayView< const LocalOrdinal > getExportLIDs() const
List of entries in the source Map that will be sent to other processes.
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.