42 #ifndef TPETRA_IMPORT_UTIL2_HPP
43 #define TPETRA_IMPORT_UTIL2_HPP
50 #include "Tpetra_ConfigDefs.hpp"
51 #include "Tpetra_Import.hpp"
52 #include "Tpetra_HashTable.hpp"
53 #include "Tpetra_Map.hpp"
55 #include "Tpetra_Distributor.hpp"
58 #include "Tpetra_Vector.hpp"
59 #include "Kokkos_DualView.hpp"
60 #include <Teuchos_Array.hpp>
67 namespace Import_Util {
71 template<
typename Scalar,
typename Ordinal>
73 sortCrsEntries (
const Teuchos::ArrayView<size_t>& CRS_rowptr,
74 const Teuchos::ArrayView<Ordinal>& CRS_colind,
75 const Teuchos::ArrayView<Scalar>&CRS_vals);
77 template<
typename Ordinal>
79 sortCrsEntries (
const Teuchos::ArrayView<size_t>& CRS_rowptr,
80 const Teuchos::ArrayView<Ordinal>& CRS_colind);
82 template<
typename rowptr_array_type,
typename colind_array_type,
typename vals_array_type>
84 sortCrsEntries (
const rowptr_array_type& CRS_rowptr,
85 const colind_array_type& CRS_colind,
86 const vals_array_type& CRS_vals);
88 template<
typename rowptr_array_type,
typename colind_array_type>
90 sortCrsEntries (
const rowptr_array_type& CRS_rowptr,
91 const colind_array_type& CRS_colind);
97 template<
typename Scalar,
typename Ordinal>
99 sortAndMergeCrsEntries (
const Teuchos::ArrayView<size_t>& CRS_rowptr,
100 const Teuchos::ArrayView<Ordinal>& CRS_colind,
101 const Teuchos::ArrayView<Scalar>& CRS_vals);
103 template<
typename Ordinal>
105 sortAndMergeCrsEntries (
const Teuchos::ArrayView<size_t>& CRS_rowptr,
106 const Teuchos::ArrayView<Ordinal>& CRS_colind);
123 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
125 lowCommunicationMakeColMapAndReindex (
const Teuchos::ArrayView<const size_t> &rowPointers,
126 const Teuchos::ArrayView<LocalOrdinal> &columnIndices_LID,
127 const Teuchos::ArrayView<GlobalOrdinal> &columnIndices_GID,
129 const Teuchos::ArrayView<const int> &owningPids,
130 Teuchos::Array<int> &remotePids,
149 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
150 void getTwoTransferOwnershipVector(const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& transferThatDefinesOwnership,
151 bool useReverseModeForOwnership,
152 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& transferForMigratingData,
153 bool useReverseModeForMigration,
165 namespace Import_Util {
168 template<
typename PID,
typename GlobalOrdinal>
169 bool sort_PID_then_GID(
const std::pair<PID,GlobalOrdinal> &a,
170 const std::pair<PID,GlobalOrdinal> &b)
173 return (a.first < b.first);
174 return (a.second < b.second);
177 template<
typename PID,
178 typename GlobalOrdinal,
179 typename LocalOrdinal>
180 bool sort_PID_then_pair_GID_LID(
const std::pair<PID, std::pair< GlobalOrdinal, LocalOrdinal > > &a,
181 const std::pair<PID, std::pair< GlobalOrdinal, LocalOrdinal > > &b)
184 return a.first < b.first;
186 return (a.second.first < b.second.first);
189 template<
typename Scalar,
190 typename LocalOrdinal,
191 typename GlobalOrdinal,
194 reverseNeighborDiscovery(
const CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> & SourceMatrix,
195 const Teuchos::ArrayRCP<const size_t> & rowptr,
196 const Teuchos::ArrayRCP<const LocalOrdinal> & colind,
200 Teuchos::ArrayRCP<int>& type3PIDs,
201 Teuchos::ArrayRCP<LocalOrdinal>& type3LIDs,
202 Teuchos::RCP<
const Teuchos::Comm<int> >& rcomm)
204 #ifdef HAVE_TPETRACORE_MPI
205 using Teuchos::TimeMonitor;
206 using ::Tpetra::Details::Behavior;
207 using Kokkos::AllowPadding;
208 using Kokkos::view_alloc;
209 using Kokkos::WithoutInitializing;
210 typedef LocalOrdinal LO;
211 typedef GlobalOrdinal GO;
212 typedef std::pair<GO,GO> pidgidpair_t;
214 const std::string prefix {
" Import_Util2::ReverseND:: "};
215 const std::string label (
"IU2::Neighbor");
218 if(MyImporter.is_null())
return;
220 std::ostringstream errstr;
222 auto const comm = MyDomainMap->getComm();
224 MPI_Comm rawComm = getRawMpiComm(*comm);
225 const int MyPID = rcomm->getRank ();
233 Distributor & Distor = MyImporter->getDistributor();
234 const size_t NumRecvs = Distor.getNumReceives();
235 const size_t NumSends = Distor.getNumSends();
236 auto RemoteLIDs = MyImporter->getRemoteLIDs();
237 auto const ProcsFrom = Distor.getProcsFrom();
238 auto const ProcsTo = Distor.getProcsTo();
240 auto LengthsFrom = Distor.getLengthsFrom();
241 auto MyColMap = SourceMatrix.getColMap();
242 const size_t numCols = MyColMap->getNodeNumElements ();
243 RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > target = MyImporter->getTargetMap();
247 Teuchos::Array<int> RemotePIDOrder(numCols,-1);
250 for (
size_t i = 0, j = 0; i < NumRecvs; ++i) {
251 for (
size_t k = 0; k < LengthsFrom[i]; ++k) {
252 const int pid = ProcsFrom[i];
254 RemotePIDOrder[RemoteLIDs[j]] = i;
266 Teuchos::Array<int> ReverseSendSizes(NumRecvs,0);
268 Teuchos::Array< Teuchos::ArrayRCP<pidgidpair_t > > RSB(NumRecvs);
271 #ifdef HAVE_TPETRA_MMM_TIMINGS
272 TimeMonitor set_all(*TimeMonitor::getNewTimer(prefix + std::string(
"isMMallSetRSB")));
285 Teuchos::Array<std::set<pidgidpair_t>> pidsets(NumRecvs);
287 #ifdef HAVE_TPETRA_MMM_TIMINGS
288 TimeMonitor set_insert(*TimeMonitor::getNewTimer(prefix + std::string(
"isMMallSetRSBinsert")));
290 for(
size_t i=0; i < NumExportLIDs; i++) {
291 LO lid = ExportLIDs[i];
292 GO exp_pid = ExportPIDs[i];
293 for(
auto j=rowptr[lid]; j<rowptr[lid+1]; j++){
294 int pid_order = RemotePIDOrder[colind[j]];
296 GO gid = MyColMap->getGlobalElement(colind[j]);
297 auto tpair = pidgidpair_t(exp_pid,gid);
298 pidsets[pid_order].insert(pidsets[pid_order].end(),tpair);
305 #ifdef HAVE_TPETRA_MMM_TIMINGS
306 TimeMonitor set_cpy(*TimeMonitor::getNewTimer(prefix + std::string(
"isMMallSetRSBcpy")));
309 for(
auto &&ps : pidsets) {
311 RSB[jj] = Teuchos::arcp(
new pidgidpair_t[ s ],0, s ,
true);
312 std::copy(ps.begin(),ps.end(),RSB[jj]);
313 ReverseSendSizes[jj]=s;
319 Teuchos::Array<int> ReverseRecvSizes(NumSends,-1);
320 Teuchos::Array<MPI_Request> rawBreq(ProcsFrom.size()+ProcsTo.size(), MPI_REQUEST_NULL);
322 const int mpi_tag_base_ = 3;
325 for(
int i=0;i<ProcsTo.size();++i) {
326 int Rec_Tag = mpi_tag_base_ + ProcsTo[i];
327 int * thisrecv = (
int *) (&ReverseRecvSizes[i]);
328 MPI_Request rawRequest = MPI_REQUEST_NULL;
329 MPI_Irecv(const_cast<int*>(thisrecv),
336 rawBreq[mpireq_idx++]=rawRequest;
338 for(
int i=0;i<ProcsFrom.size();++i) {
339 int Send_Tag = mpi_tag_base_ + MyPID;
340 int * mysend = (
int *)(&ReverseSendSizes[i]);
341 MPI_Request rawRequest = MPI_REQUEST_NULL;
349 rawBreq[mpireq_idx++]=rawRequest;
351 Teuchos::Array<MPI_Status> rawBstatus(rawBreq.size());
352 #ifdef HAVE_TPETRA_DEBUG
355 MPI_Waitall (rawBreq.size(), rawBreq.getRawPtr(),
356 rawBstatus.getRawPtr());
359 #ifdef HAVE_TPETRA_DEBUG
361 errstr <<MyPID<<
"sE1 reverseNeighborDiscovery Mpi_Waitall error on send ";
363 std::cerr<<errstr.str()<<std::flush;
367 int totalexportpairrecsize = 0;
368 for (
size_t i = 0; i < NumSends; ++i) {
369 totalexportpairrecsize += ReverseRecvSizes[i];
370 #ifdef HAVE_TPETRA_DEBUG
371 if(ReverseRecvSizes[i]<0) {
372 errstr << MyPID <<
"E4 reverseNeighborDiscovery: got < 0 for receive size "<<ReverseRecvSizes[i]<<std::endl;
377 Teuchos::ArrayRCP<pidgidpair_t >AllReverseRecv= Teuchos::arcp(
new pidgidpair_t[totalexportpairrecsize],0,totalexportpairrecsize,
true);
380 for(
int i=0;i<ProcsTo.size();++i) {
381 int recv_data_size = ReverseRecvSizes[i]*2;
382 int recvData_MPI_Tag = mpi_tag_base_*2 + ProcsTo[i];
383 MPI_Request rawRequest = MPI_REQUEST_NULL;
384 GO * rec_bptr = (GO*) (&AllReverseRecv[offset]);
385 offset+=ReverseRecvSizes[i];
388 ::Tpetra::Details::MpiTypeTraits<GO>::getType(rec_bptr[0]),
393 rawBreq[mpireq_idx++]=rawRequest;
395 for(
int ii=0;ii<ProcsFrom.size();++ii) {
396 GO * send_bptr = (GO*) (RSB[ii].getRawPtr());
397 MPI_Request rawSequest = MPI_REQUEST_NULL;
398 int send_data_size = ReverseSendSizes[ii]*2;
399 int sendData_MPI_Tag = mpi_tag_base_*2+MyPID;
402 ::Tpetra::Details::MpiTypeTraits<GO>::getType(send_bptr[0]),
408 rawBreq[mpireq_idx++]=rawSequest;
410 #ifdef HAVE_TPETRA_DEBUG
413 MPI_Waitall (rawBreq.size(),
415 rawBstatus.getRawPtr());
416 #ifdef HAVE_TPETRA_DEBUG
418 errstr <<MyPID<<
"E3.r reverseNeighborDiscovery Mpi_Waitall error on receive ";
420 std::cerr<<errstr.str()<<std::flush;
423 std::sort(AllReverseRecv.begin(), AllReverseRecv.end(), Tpetra::Import_Util::sort_PID_then_GID<GlobalOrdinal, GlobalOrdinal>);
425 auto newEndOfPairs = std::unique(AllReverseRecv.begin(), AllReverseRecv.end());
427 if(AllReverseRecv.begin() == newEndOfPairs)
return;
428 int ARRsize = std::distance(AllReverseRecv.begin(),newEndOfPairs);
429 auto rPIDs = Teuchos::arcp(
new int[ARRsize],0,ARRsize,
true);
430 auto rLIDs = Teuchos::arcp(
new LocalOrdinal[ARRsize],0,ARRsize,
true);
433 for(
auto itr = AllReverseRecv.begin(); itr!=newEndOfPairs; ++itr ) {
434 if((
int)(itr->first) != MyPID) {
435 rPIDs[tsize]=(int)itr->first;
436 LocalOrdinal lid = MyDomainMap->getLocalElement(itr->second);
442 type3PIDs=rPIDs.persistingView(0,tsize);
443 type3LIDs=rLIDs.persistingView(0,tsize);
446 std::cerr<<errstr.str()<<std::flush;
450 MPI_Abort (MPI_COMM_WORLD, -1);
456 template<
typename Scalar,
typename Ordinal>
458 sortCrsEntries (
const Teuchos::ArrayView<size_t> &CRS_rowptr,
459 const Teuchos::ArrayView<Ordinal> & CRS_colind,
460 const Teuchos::ArrayView<Scalar> &CRS_vals)
465 size_t NumRows = CRS_rowptr.size()-1;
466 size_t nnz = CRS_colind.size();
468 const bool permute_values_array = CRS_vals.size() > 0;
470 for(
size_t i = 0; i < NumRows; i++){
471 size_t start=CRS_rowptr[i];
472 if(start >= nnz)
continue;
474 size_t NumEntries = CRS_rowptr[i+1] - start;
475 Teuchos::ArrayRCP<Scalar> locValues;
476 if (permute_values_array)
477 locValues = Teuchos::arcp<Scalar>(&CRS_vals[start], 0, NumEntries,
false);
478 Teuchos::ArrayRCP<Ordinal> locIndices(&CRS_colind[start], 0, NumEntries,
false);
480 Ordinal n = NumEntries;
482 while (m<n) m = m*3+1;
487 for(Ordinal j = 0; j < max; j++) {
488 for(Ordinal k = j; k >= 0; k-=m) {
489 if(locIndices[k+m] >= locIndices[k])
491 if (permute_values_array) {
492 Scalar dtemp = locValues[k+m];
493 locValues[k+m] = locValues[k];
494 locValues[k] = dtemp;
496 Ordinal itemp = locIndices[k+m];
497 locIndices[k+m] = locIndices[k];
498 locIndices[k] = itemp;
506 template<
typename Ordinal>
508 sortCrsEntries (
const Teuchos::ArrayView<size_t> &CRS_rowptr,
509 const Teuchos::ArrayView<Ordinal> & CRS_colind)
512 Teuchos::ArrayView<Tpetra::Details::DefaultTypes::scalar_type> CRS_vals;
513 sortCrsEntries (CRS_rowptr, CRS_colind, CRS_vals);
518 template<
class RowOffsetsType,
class ColumnIndicesType,
class ValuesType>
519 class SortCrsEntries {
521 typedef typename ColumnIndicesType::non_const_value_type ordinal_type;
522 typedef typename ValuesType::non_const_value_type scalar_type;
525 SortCrsEntries (
const RowOffsetsType& ptr,
526 const ColumnIndicesType& ind,
527 const ValuesType& val) :
532 static_assert (std::is_signed<ordinal_type>::value,
"The type of each "
533 "column index -- that is, the type of each entry of ind "
534 "-- must be signed in order for this functor to work.");
537 KOKKOS_FUNCTION
void operator() (
const size_t i)
const
539 const size_t nnz = ind_.extent (0);
540 const size_t start = ptr_(i);
541 const bool permute_values_array = val_.extent(0) > 0;
544 const size_t NumEntries = ptr_(i+1) - start;
546 const ordinal_type n =
static_cast<ordinal_type
> (NumEntries);
548 while (m<n) m = m*3+1;
552 ordinal_type max = n - m;
553 for (ordinal_type j = 0; j < max; j++) {
554 for (ordinal_type k = j; k >= 0; k -= m) {
555 const size_t sk = start+k;
556 if (ind_(sk+m) >= ind_(sk)) {
559 if (permute_values_array) {
560 const scalar_type dtemp = val_(sk+m);
561 val_(sk+m) = val_(sk);
564 const ordinal_type itemp = ind_(sk+m);
565 ind_(sk+m) = ind_(sk);
575 sortCrsEntries (
const RowOffsetsType& ptr,
576 const ColumnIndicesType& ind,
577 const ValuesType& val)
584 if (ptr.extent (0) == 0) {
587 const size_t NumRows = ptr.extent (0) - 1;
589 typedef size_t index_type;
590 typedef typename ValuesType::execution_space execution_space;
593 typedef Kokkos::RangePolicy<execution_space, index_type> range_type;
594 Kokkos::parallel_for (
"sortCrsEntries", range_type (0, NumRows),
595 SortCrsEntries (ptr, ind, val));
600 ColumnIndicesType ind_;
606 template<
typename rowptr_array_type,
typename colind_array_type,
typename vals_array_type>
608 sortCrsEntries (
const rowptr_array_type& CRS_rowptr,
609 const colind_array_type& CRS_colind,
610 const vals_array_type& CRS_vals)
612 Impl::SortCrsEntries<rowptr_array_type, colind_array_type,
613 vals_array_type>::sortCrsEntries (CRS_rowptr, CRS_colind, CRS_vals);
616 template<
typename rowptr_array_type,
typename colind_array_type>
618 sortCrsEntries (
const rowptr_array_type& CRS_rowptr,
619 const colind_array_type& CRS_colind)
622 typedef typename colind_array_type::execution_space execution_space;
623 typedef Tpetra::Details::DefaultTypes::scalar_type scalar_type;
624 typedef typename Kokkos::View<scalar_type*, execution_space> scalar_view_type;
625 scalar_view_type CRS_vals;
626 sortCrsEntries<rowptr_array_type, colind_array_type,
627 scalar_view_type>(CRS_rowptr, CRS_colind, CRS_vals);
631 template<
typename Scalar,
typename Ordinal>
633 sortAndMergeCrsEntries (
const Teuchos::ArrayView<size_t> &CRS_rowptr,
634 const Teuchos::ArrayView<Ordinal> & CRS_colind,
635 const Teuchos::ArrayView<Scalar> &CRS_vals)
642 if (CRS_rowptr.size () == 0) {
645 const size_t NumRows = CRS_rowptr.size () - 1;
646 const size_t nnz = CRS_colind.size ();
647 size_t new_curr = CRS_rowptr[0];
648 size_t old_curr = CRS_rowptr[0];
650 const bool permute_values_array = CRS_vals.size() > 0;
652 for(
size_t i = 0; i < NumRows; i++){
653 const size_t old_rowptr_i=CRS_rowptr[i];
654 CRS_rowptr[i] = old_curr;
655 if(old_rowptr_i >= nnz)
continue;
657 size_t NumEntries = CRS_rowptr[i+1] - old_rowptr_i;
658 Teuchos::ArrayRCP<Scalar> locValues;
659 if (permute_values_array)
660 locValues = Teuchos::arcp<Scalar>(&CRS_vals[old_rowptr_i], 0, NumEntries,
false);
661 Teuchos::ArrayRCP<Ordinal> locIndices(&CRS_colind[old_rowptr_i], 0, NumEntries,
false);
664 Ordinal n = NumEntries;
669 for(Ordinal j = 0; j < max; j++) {
670 for(Ordinal k = j; k >= 0; k-=m) {
671 if(locIndices[k+m] >= locIndices[k])
673 if (permute_values_array) {
674 Scalar dtemp = locValues[k+m];
675 locValues[k+m] = locValues[k];
676 locValues[k] = dtemp;
678 Ordinal itemp = locIndices[k+m];
679 locIndices[k+m] = locIndices[k];
680 locIndices[k] = itemp;
687 for(
size_t j=old_rowptr_i; j < CRS_rowptr[i+1]; j++) {
688 if(j > old_rowptr_i && CRS_colind[j]==CRS_colind[new_curr-1]) {
689 if (permute_values_array) CRS_vals[new_curr-1] += CRS_vals[j];
691 else if(new_curr==j) {
695 CRS_colind[new_curr] = CRS_colind[j];
696 if (permute_values_array) CRS_vals[new_curr] = CRS_vals[j];
703 CRS_rowptr[NumRows] = new_curr;
706 template<
typename Ordinal>
708 sortAndMergeCrsEntries (
const Teuchos::ArrayView<size_t> &CRS_rowptr,
709 const Teuchos::ArrayView<Ordinal> & CRS_colind)
711 Teuchos::ArrayView<Tpetra::Details::DefaultTypes::scalar_type> CRS_vals;
712 return sortAndMergeCrsEntries(CRS_rowptr, CRS_colind, CRS_vals);
716 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
718 lowCommunicationMakeColMapAndReindex (
const Teuchos::ArrayView<const size_t> &rowptr,
719 const Teuchos::ArrayView<LocalOrdinal> &colind_LID,
720 const Teuchos::ArrayView<GlobalOrdinal> &colind_GID,
722 const Teuchos::ArrayView<const int> &owningPIDs,
723 Teuchos::Array<int> &remotePIDs,
727 typedef LocalOrdinal LO;
728 typedef GlobalOrdinal GO;
731 const char prefix[] =
"lowCommunicationMakeColMapAndReindex: ";
735 const map_type& domainMap = *domainMapRCP;
741 Teuchos::Array<bool> LocalGIDs;
742 if (numDomainElements > 0) {
743 LocalGIDs.resize (numDomainElements,
false);
754 const size_t numMyRows = rowptr.size () - 1;
755 const int hashsize = std::max (static_cast<int> (numMyRows), 100);
758 Teuchos::Array<GO> RemoteGIDList;
759 RemoteGIDList.reserve (hashsize);
760 Teuchos::Array<int> PIDList;
761 PIDList.reserve (hashsize);
772 size_t NumLocalColGIDs = 0;
773 LO NumRemoteColGIDs = 0;
774 for (
size_t i = 0; i < numMyRows; ++i) {
775 for(
size_t j = rowptr[i]; j < rowptr[i+1]; ++j) {
776 const GO GID = colind_GID[j];
778 const LO LID = domainMap.getLocalElement (GID);
780 const bool alreadyFound = LocalGIDs[LID];
781 if (! alreadyFound) {
782 LocalGIDs[LID] =
true;
788 const LO hash_value = RemoteGIDs.get (GID);
789 if (hash_value == -1) {
790 const int PID = owningPIDs[j];
791 TEUCHOS_TEST_FOR_EXCEPTION(
792 PID == -1, std::invalid_argument, prefix <<
"Cannot figure out if "
794 colind_LID[j] =
static_cast<LO
> (numDomainElements + NumRemoteColGIDs);
795 RemoteGIDs.add (GID, NumRemoteColGIDs);
796 RemoteGIDList.push_back (GID);
797 PIDList.push_back (PID);
801 colind_LID[j] =
static_cast<LO
> (numDomainElements + hash_value);
809 if (domainMap.getComm ()->getSize () == 1) {
812 TEUCHOS_TEST_FOR_EXCEPTION(
813 NumRemoteColGIDs != 0, std::runtime_error, prefix <<
"There is only one "
814 "process in the domain Map's communicator, which means that there are no "
815 "\"remote\" indices. Nevertheless, some column indices are not in the "
817 if (static_cast<size_t> (NumLocalColGIDs) == numDomainElements) {
821 colMap = domainMapRCP;
828 const LO numMyCols = NumLocalColGIDs + NumRemoteColGIDs;
829 Teuchos::Array<GO> ColIndices;
830 GO* RemoteColIndices = NULL;
832 ColIndices.resize (numMyCols);
833 if (NumLocalColGIDs != static_cast<size_t> (numMyCols)) {
834 RemoteColIndices = &ColIndices[NumLocalColGIDs];
838 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
839 RemoteColIndices[i] = RemoteGIDList[i];
843 Teuchos::Array<LO> RemotePermuteIDs (NumRemoteColGIDs);
844 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
845 RemotePermuteIDs[i]=i;
852 ColIndices.begin () + NumLocalColGIDs,
853 RemotePermuteIDs.begin ());
859 remotePIDs = PIDList;
868 LO StartCurrent = 0, StartNext = 1;
869 while (StartNext < NumRemoteColGIDs) {
870 if (PIDList[StartNext]==PIDList[StartNext-1]) {
874 Tpetra::sort2 (ColIndices.begin () + NumLocalColGIDs + StartCurrent,
875 ColIndices.begin () + NumLocalColGIDs + StartNext,
876 RemotePermuteIDs.begin () + StartCurrent);
877 StartCurrent = StartNext;
881 Tpetra::sort2 (ColIndices.begin () + NumLocalColGIDs + StartCurrent,
882 ColIndices.begin () + NumLocalColGIDs + StartNext,
883 RemotePermuteIDs.begin () + StartCurrent);
886 Teuchos::Array<LO> ReverseRemotePermuteIDs (NumRemoteColGIDs);
887 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
888 ReverseRemotePermuteIDs[RemotePermuteIDs[i]] = i;
892 bool use_local_permute =
false;
893 Teuchos::Array<LO> LocalPermuteIDs (numDomainElements);
905 Teuchos::ArrayView<const GO> domainGlobalElements = domainMap.getNodeElementList();
906 if (static_cast<size_t> (NumLocalColGIDs) == numDomainElements) {
907 if (NumLocalColGIDs > 0) {
909 std::copy (domainGlobalElements.begin (), domainGlobalElements.end (),
910 ColIndices.begin ());
914 LO NumLocalAgain = 0;
915 use_local_permute =
true;
916 for (
size_t i = 0; i < numDomainElements; ++i) {
918 LocalPermuteIDs[i] = NumLocalAgain;
919 ColIndices[NumLocalAgain++] = domainGlobalElements[i];
922 TEUCHOS_TEST_FOR_EXCEPTION(
923 static_cast<size_t> (NumLocalAgain) != NumLocalColGIDs,
924 std::runtime_error, prefix <<
"Local ID count test failed.");
928 const GST minus_one = Teuchos::OrdinalTraits<GST>::invalid ();
929 colMap = rcp (
new map_type (minus_one, ColIndices, domainMap.getIndexBase (),
930 domainMap.getComm ()));
933 for (
size_t i = 0; i < numMyRows; ++i) {
934 for (
size_t j = rowptr[i]; j < rowptr[i+1]; ++j) {
935 const LO ID = colind_LID[j];
936 if (static_cast<size_t> (ID) < numDomainElements) {
937 if (use_local_permute) {
938 colind_LID[j] = LocalPermuteIDs[colind_LID[j]];
945 colind_LID[j] = NumLocalColGIDs + ReverseRemotePermuteIDs[colind_LID[j]-numDomainElements];
967 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
968 void getTwoTransferOwnershipVector(const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& transferThatDefinesOwnership,
969 bool useReverseModeForOwnership,
970 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& transferThatDefinesMigration,
971 bool useReverseModeForMigration,
976 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > OwningMap = useReverseModeForOwnership ?
978 transferThatDefinesOwnership.getSourceMap();
979 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > MapAo = useReverseModeForOwnership ?
980 transferThatDefinesOwnership.getSourceMap() :
981 transferThatDefinesOwnership.getTargetMap();
982 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > MapAm = useReverseModeForMigration ?
983 transferThatDefinesMigration.getTargetMap() :
984 transferThatDefinesMigration.getSourceMap();
985 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > VectorMap = useReverseModeForMigration ?
986 transferThatDefinesMigration.getSourceMap() :
987 transferThatDefinesMigration.getTargetMap();
989 TEUCHOS_TEST_FOR_EXCEPTION(!MapAo->isSameAs(*MapAm),std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector map mismatch between transfers");
990 TEUCHOS_TEST_FOR_EXCEPTION(!VectorMap->isSameAs(*owningPIDs.
getMap()),std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector map mismatch transfer and vector");
991 #ifdef HAVE_TPETRA_DEBUG
992 TEUCHOS_TEST_FOR_EXCEPTION(!OwningMap->isOneToOne(),std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");
995 int rank = OwningMap->getComm()->getRank();
999 const import_type* ownAsImport =
dynamic_cast<const import_type*
> (&transferThatDefinesOwnership);
1000 const export_type* ownAsExport =
dynamic_cast<const export_type*
> (&transferThatDefinesOwnership);
1002 Teuchos::ArrayRCP<int> pids = temp.getDataNonConst();
1003 Teuchos::ArrayView<int> v_pids = pids();
1004 if(ownAsImport && useReverseModeForOwnership) {TEUCHOS_TEST_FOR_EXCEPTION(1,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");}
1005 else if(ownAsImport && !useReverseModeForOwnership) getPids(*ownAsImport,v_pids,
false);
1006 else if(ownAsExport && useReverseModeForMigration) {TEUCHOS_TEST_FOR_EXCEPTION(1,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector this option not yet implemented");}
1007 else {TEUCHOS_TEST_FOR_EXCEPTION(1,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");}
1009 const import_type* xferAsImport =
dynamic_cast<const import_type*
> (&transferThatDefinesMigration);
1010 const export_type* xferAsExport =
dynamic_cast<const export_type*
> (&transferThatDefinesMigration);
1011 TEUCHOS_TEST_FOR_EXCEPTION(!xferAsImport && !xferAsExport,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector transfer undefined");
1027 #endif // TPETRA_IMPORT_UTIL_HPP
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
Add specializations of Teuchos::Details::MpiTypeTraits for Kokkos::complex<float> and Kokkos::complex...
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.
void doImport(const SrcDistObject &source, const Import< LocalOrdinal, GlobalOrdinal, Node > &importer, const CombineMode CM, const bool restrictedMode=false)
Import data into this object using an Import object ("forward mode").
void putScalar(const Scalar &value)
Set all values in the multivector with the given value.
Declaration of the Tpetra::CrsMatrix class.
Teuchos::ArrayView< const int > getExportPIDs() const
List of processes to which entries will be sent.
Teuchos::RCP< const map_type > getTargetMap() const
The target Map used to construct this Export or Import.
size_t global_size_t
Global size_t object.
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
size_t getNumExportIDs() const
Number of entries that must be sent by the calling process to other processes.
Declaration and definition of Tpetra::Details::reallocDualViewIfNeeded, an implementation detail of T...
Replace existing values with new values.
Teuchos::ArrayView< const LO > 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.
size_t getNodeNumElements() const
The number of elements belonging to the calling process.
A parallel distribution of indices over processes.
void doExport(const SrcDistObject &source, const Export< LocalOrdinal, GlobalOrdinal, Node > &exporter, const CombineMode CM, const bool restrictedMode=false)
Export data into this object using an Export object ("forward mode").
A distributed dense vector.
Stand-alone utility functions and macros.
virtual Teuchos::RCP< const map_type > getMap() const
The Map describing the parallel distribution of this object.