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 "KokkosSparse_SortCrs.hpp"
61 #include <Teuchos_Array.hpp>
63 #include <Kokkos_UnorderedMap.hpp>
64 #include <unordered_map>
70 #include <Kokkos_Core.hpp>
71 #include <Kokkos_Sort.hpp>
74 namespace Import_Util {
78 template<
typename Scalar,
typename Ordinal>
80 sortCrsEntries (
const Teuchos::ArrayView<size_t>& CRS_rowptr,
81 const Teuchos::ArrayView<Ordinal>& CRS_colind,
82 const Teuchos::ArrayView<Scalar>&CRS_vals);
84 template<
typename Ordinal>
86 sortCrsEntries (
const Teuchos::ArrayView<size_t>& CRS_rowptr,
87 const Teuchos::ArrayView<Ordinal>& CRS_colind);
89 template<
typename rowptr_array_type,
typename colind_array_type,
typename vals_array_type>
91 sortCrsEntries (
const rowptr_array_type& CRS_rowptr,
92 const colind_array_type& CRS_colind,
93 const vals_array_type& CRS_vals);
95 template<
typename rowptr_array_type,
typename colind_array_type>
97 sortCrsEntries (
const rowptr_array_type& CRS_rowptr,
98 const colind_array_type& CRS_colind);
104 template<
typename Scalar,
typename Ordinal>
106 sortAndMergeCrsEntries (
const Teuchos::ArrayView<size_t>& CRS_rowptr,
107 const Teuchos::ArrayView<Ordinal>& CRS_colind,
108 const Teuchos::ArrayView<Scalar>& CRS_vals);
110 template<
typename Ordinal>
112 sortAndMergeCrsEntries (
const Teuchos::ArrayView<size_t>& CRS_rowptr,
113 const Teuchos::ArrayView<Ordinal>& CRS_colind);
115 template<
class rowptr_view_type,
class colind_view_type,
class vals_view_type>
117 sortAndMergeCrsEntries (
const rowptr_view_type& CRS_rowptr,
118 const colind_view_type& CRS_colind,
119 const vals_view_type& CRS_vals);
136 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
138 lowCommunicationMakeColMapAndReindex (
139 const Teuchos::ArrayView<const size_t> &rowptr,
140 const Teuchos::ArrayView<LocalOrdinal> &colind_LID,
141 const Teuchos::ArrayView<GlobalOrdinal> &colind_GID,
143 const Teuchos::ArrayView<const int> &owningPIDs,
144 Teuchos::Array<int> &remotePIDs,
151 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
153 lowCommunicationMakeColMapAndReindex (
154 const Kokkos::View<size_t*,typename Node::device_type> rowptr_view,
155 const Kokkos::View<LocalOrdinal*,typename Node::device_type> colind_LID_view,
156 const Kokkos::View<GlobalOrdinal*,typename Node::device_type> colind_GID_view,
158 const Teuchos::ArrayView<const int> &owningPIDs,
159 Teuchos::Array<int> &remotePIDs,
175 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
176 void getTwoTransferOwnershipVector(const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& transferThatDefinesOwnership,
177 bool useReverseModeForOwnership,
178 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& transferForMigratingData,
179 bool useReverseModeForMigration,
191 namespace Import_Util {
194 template<
typename PID,
typename GlobalOrdinal>
195 bool sort_PID_then_GID(
const std::pair<PID,GlobalOrdinal> &a,
196 const std::pair<PID,GlobalOrdinal> &b)
199 return (a.first < b.first);
200 return (a.second < b.second);
203 template<
typename PID,
204 typename GlobalOrdinal,
205 typename LocalOrdinal>
206 bool sort_PID_then_pair_GID_LID(
const std::pair<PID, std::pair< GlobalOrdinal, LocalOrdinal > > &a,
207 const std::pair<PID, std::pair< GlobalOrdinal, LocalOrdinal > > &b)
210 return a.first < b.first;
212 return (a.second.first < b.second.first);
215 template<
typename Scalar,
216 typename LocalOrdinal,
217 typename GlobalOrdinal,
220 reverseNeighborDiscovery(
const CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> & SourceMatrix,
221 const typename CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::row_ptrs_host_view_type & rowptr,
222 const typename CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_inds_host_view_type & colind,
226 Teuchos::ArrayRCP<int>& type3PIDs,
227 Teuchos::ArrayRCP<LocalOrdinal>& type3LIDs,
228 Teuchos::RCP<
const Teuchos::Comm<int> >& rcomm)
230 #ifdef HAVE_TPETRACORE_MPI
231 using Teuchos::TimeMonitor;
232 using ::Tpetra::Details::Behavior;
233 typedef LocalOrdinal LO;
234 typedef GlobalOrdinal GO;
235 typedef std::pair<GO,GO> pidgidpair_t;
237 const std::string prefix {
" Import_Util2::ReverseND:: "};
238 const std::string label (
"IU2::Neighbor");
241 if(MyImporter.is_null())
return;
243 std::ostringstream errstr;
245 auto const comm = MyDomainMap->getComm();
247 MPI_Comm rawComm = getRawMpiComm(*comm);
248 const int MyPID = rcomm->getRank ();
256 Distributor & Distor = MyImporter->getDistributor();
257 const size_t NumRecvs = Distor.getNumReceives();
258 const size_t NumSends = Distor.getNumSends();
259 auto RemoteLIDs = MyImporter->getRemoteLIDs();
260 auto const ProcsFrom = Distor.getProcsFrom();
261 auto const ProcsTo = Distor.getProcsTo();
263 auto LengthsFrom = Distor.getLengthsFrom();
264 auto MyColMap = SourceMatrix.getColMap();
265 const size_t numCols = MyColMap->getLocalNumElements ();
266 RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > target = MyImporter->getTargetMap();
270 Teuchos::Array<int> RemotePIDOrder(numCols,-1);
273 for (
size_t i = 0, j = 0; i < NumRecvs; ++i) {
274 for (
size_t k = 0; k < LengthsFrom[i]; ++k) {
275 const int pid = ProcsFrom[i];
277 RemotePIDOrder[RemoteLIDs[j]] = i;
289 Teuchos::Array<int> ReverseSendSizes(NumRecvs,0);
291 Teuchos::Array< Teuchos::ArrayRCP<pidgidpair_t > > RSB(NumRecvs);
294 #ifdef HAVE_TPETRA_MMM_TIMINGS
295 TimeMonitor set_all(*TimeMonitor::getNewTimer(prefix + std::string(
"isMMallSetRSB")));
308 Teuchos::Array<std::set<pidgidpair_t>> pidsets(NumRecvs);
310 #ifdef HAVE_TPETRA_MMM_TIMINGS
311 TimeMonitor set_insert(*TimeMonitor::getNewTimer(prefix + std::string(
"isMMallSetRSBinsert")));
313 for(
size_t i=0; i < NumExportLIDs; i++) {
314 LO lid = ExportLIDs[i];
315 GO exp_pid = ExportPIDs[i];
316 for(
auto j=rowptr[lid]; j<rowptr[lid+1]; j++){
317 int pid_order = RemotePIDOrder[colind[j]];
319 GO gid = MyColMap->getGlobalElement(colind[j]);
320 auto tpair = pidgidpair_t(exp_pid,gid);
321 pidsets[pid_order].insert(pidsets[pid_order].end(),tpair);
328 #ifdef HAVE_TPETRA_MMM_TIMINGS
329 TimeMonitor set_cpy(*TimeMonitor::getNewTimer(prefix + std::string(
"isMMallSetRSBcpy")));
332 for(
auto &&ps : pidsets) {
334 RSB[jj] = Teuchos::arcp(
new pidgidpair_t[ s ],0, s ,
true);
335 std::copy(ps.begin(),ps.end(),RSB[jj]);
336 ReverseSendSizes[jj]=s;
342 Teuchos::Array<int> ReverseRecvSizes(NumSends,-1);
343 Teuchos::Array<MPI_Request> rawBreq(ProcsFrom.size()+ProcsTo.size(), MPI_REQUEST_NULL);
345 const int mpi_tag_base_ = 3;
348 for(
int i=0;i<ProcsTo.size();++i) {
349 int Rec_Tag = mpi_tag_base_ + ProcsTo[i];
350 int * thisrecv = (
int *) (&ReverseRecvSizes[i]);
351 MPI_Request rawRequest = MPI_REQUEST_NULL;
352 MPI_Irecv(const_cast<int*>(thisrecv),
359 rawBreq[mpireq_idx++]=rawRequest;
361 for(
int i=0;i<ProcsFrom.size();++i) {
362 int Send_Tag = mpi_tag_base_ + MyPID;
363 int * mysend = (
int *)(&ReverseSendSizes[i]);
364 MPI_Request rawRequest = MPI_REQUEST_NULL;
372 rawBreq[mpireq_idx++]=rawRequest;
374 Teuchos::Array<MPI_Status> rawBstatus(rawBreq.size());
375 #ifdef HAVE_TPETRA_DEBUG
378 MPI_Waitall (rawBreq.size(), rawBreq.getRawPtr(),
379 rawBstatus.getRawPtr());
382 #ifdef HAVE_TPETRA_DEBUG
384 errstr <<MyPID<<
"sE1 reverseNeighborDiscovery Mpi_Waitall error on send ";
386 std::cerr<<errstr.str()<<std::flush;
390 int totalexportpairrecsize = 0;
391 for (
size_t i = 0; i < NumSends; ++i) {
392 totalexportpairrecsize += ReverseRecvSizes[i];
393 #ifdef HAVE_TPETRA_DEBUG
394 if(ReverseRecvSizes[i]<0) {
395 errstr << MyPID <<
"E4 reverseNeighborDiscovery: got < 0 for receive size "<<ReverseRecvSizes[i]<<std::endl;
400 Teuchos::ArrayRCP<pidgidpair_t >AllReverseRecv= Teuchos::arcp(
new pidgidpair_t[totalexportpairrecsize],0,totalexportpairrecsize,
true);
403 for(
int i=0;i<ProcsTo.size();++i) {
404 int recv_data_size = ReverseRecvSizes[i]*2;
405 int recvData_MPI_Tag = mpi_tag_base_*2 + ProcsTo[i];
406 MPI_Request rawRequest = MPI_REQUEST_NULL;
407 GO * rec_bptr = (GO*) (&AllReverseRecv[offset]);
408 offset+=ReverseRecvSizes[i];
411 ::Tpetra::Details::MpiTypeTraits<GO>::getType(rec_bptr[0]),
416 rawBreq[mpireq_idx++]=rawRequest;
418 for(
int ii=0;ii<ProcsFrom.size();++ii) {
419 GO * send_bptr = (GO*) (RSB[ii].getRawPtr());
420 MPI_Request rawSequest = MPI_REQUEST_NULL;
421 int send_data_size = ReverseSendSizes[ii]*2;
422 int sendData_MPI_Tag = mpi_tag_base_*2+MyPID;
425 ::Tpetra::Details::MpiTypeTraits<GO>::getType(send_bptr[0]),
431 rawBreq[mpireq_idx++]=rawSequest;
433 #ifdef HAVE_TPETRA_DEBUG
436 MPI_Waitall (rawBreq.size(),
438 rawBstatus.getRawPtr());
439 #ifdef HAVE_TPETRA_DEBUG
441 errstr <<MyPID<<
"E3.r reverseNeighborDiscovery Mpi_Waitall error on receive ";
443 std::cerr<<errstr.str()<<std::flush;
446 std::sort(AllReverseRecv.begin(), AllReverseRecv.end(), Tpetra::Import_Util::sort_PID_then_GID<GlobalOrdinal, GlobalOrdinal>);
448 auto newEndOfPairs = std::unique(AllReverseRecv.begin(), AllReverseRecv.end());
450 if(AllReverseRecv.begin() == newEndOfPairs)
return;
451 int ARRsize = std::distance(AllReverseRecv.begin(),newEndOfPairs);
452 auto rPIDs = Teuchos::arcp(
new int[ARRsize],0,ARRsize,
true);
453 auto rLIDs = Teuchos::arcp(
new LocalOrdinal[ARRsize],0,ARRsize,
true);
456 for(
auto itr = AllReverseRecv.begin(); itr!=newEndOfPairs; ++itr ) {
457 if((
int)(itr->first) != MyPID) {
458 rPIDs[tsize]=(int)itr->first;
459 LocalOrdinal lid = MyDomainMap->getLocalElement(itr->second);
465 type3PIDs=rPIDs.persistingView(0,tsize);
466 type3LIDs=rLIDs.persistingView(0,tsize);
469 std::cerr<<errstr.str()<<std::flush;
473 MPI_Abort (MPI_COMM_WORLD, -1);
479 template<
typename Scalar,
typename Ordinal>
481 sortCrsEntries (
const Teuchos::ArrayView<size_t> &CRS_rowptr,
482 const Teuchos::ArrayView<Ordinal> & CRS_colind,
483 const Teuchos::ArrayView<Scalar> &CRS_vals)
488 size_t NumRows = CRS_rowptr.size()-1;
489 size_t nnz = CRS_colind.size();
491 const bool permute_values_array = CRS_vals.size() > 0;
493 for(
size_t i = 0; i < NumRows; i++){
494 size_t start=CRS_rowptr[i];
495 if(start >= nnz)
continue;
497 size_t NumEntries = CRS_rowptr[i+1] -
start;
498 Teuchos::ArrayRCP<Scalar> locValues;
499 if (permute_values_array)
500 locValues = Teuchos::arcp<Scalar>(&CRS_vals[
start], 0, NumEntries,
false);
501 Teuchos::ArrayRCP<Ordinal> locIndices(&CRS_colind[start], 0, NumEntries,
false);
503 Ordinal n = NumEntries;
505 while (m<n) m = m*3+1;
510 for(Ordinal j = 0; j < max; j++) {
511 for(Ordinal k = j; k >= 0; k-=m) {
512 if(locIndices[k+m] >= locIndices[k])
514 if (permute_values_array) {
515 Scalar dtemp = locValues[k+m];
516 locValues[k+m] = locValues[k];
517 locValues[k] = dtemp;
519 Ordinal itemp = locIndices[k+m];
520 locIndices[k+m] = locIndices[k];
521 locIndices[k] = itemp;
529 template<
typename Ordinal>
531 sortCrsEntries (
const Teuchos::ArrayView<size_t> &CRS_rowptr,
532 const Teuchos::ArrayView<Ordinal> & CRS_colind)
535 Teuchos::ArrayView<Tpetra::Details::DefaultTypes::scalar_type> CRS_vals;
536 sortCrsEntries (CRS_rowptr, CRS_colind, CRS_vals);
541 template<
class RowOffsetsType,
class ColumnIndicesType,
class ValuesType>
542 class SortCrsEntries {
544 typedef typename ColumnIndicesType::non_const_value_type ordinal_type;
545 typedef typename ValuesType::non_const_value_type scalar_type;
548 SortCrsEntries (
const RowOffsetsType& ptr,
549 const ColumnIndicesType& ind,
550 const ValuesType& val) :
555 static_assert (std::is_signed<ordinal_type>::value,
"The type of each "
556 "column index -- that is, the type of each entry of ind "
557 "-- must be signed in order for this functor to work.");
560 KOKKOS_FUNCTION
void operator() (
const size_t i)
const
562 const size_t nnz = ind_.extent (0);
563 const size_t start = ptr_(i);
564 const bool permute_values_array = val_.extent(0) > 0;
567 const size_t NumEntries = ptr_(i+1) -
start;
569 const ordinal_type n =
static_cast<ordinal_type
> (NumEntries);
571 while (m<n) m = m*3+1;
575 ordinal_type max = n - m;
576 for (ordinal_type j = 0; j < max; j++) {
577 for (ordinal_type k = j; k >= 0; k -= m) {
578 const size_t sk = start+k;
579 if (ind_(sk+m) >= ind_(sk)) {
582 if (permute_values_array) {
583 const scalar_type dtemp = val_(sk+m);
584 val_(sk+m) = val_(sk);
587 const ordinal_type itemp = ind_(sk+m);
588 ind_(sk+m) = ind_(sk);
598 sortCrsEntries (
const RowOffsetsType& ptr,
599 const ColumnIndicesType& ind,
600 const ValuesType& val)
607 if (ptr.extent (0) == 0) {
610 const size_t NumRows = ptr.extent (0) - 1;
612 typedef size_t index_type;
613 typedef typename ValuesType::execution_space execution_space;
616 typedef Kokkos::RangePolicy<execution_space, index_type> range_type;
617 Kokkos::parallel_for (
"sortCrsEntries", range_type (0, NumRows),
618 SortCrsEntries (ptr, ind, val));
623 ColumnIndicesType ind_;
629 template<
typename rowptr_array_type,
typename colind_array_type,
typename vals_array_type>
631 sortCrsEntries (
const rowptr_array_type& CRS_rowptr,
632 const colind_array_type& CRS_colind,
633 const vals_array_type& CRS_vals)
635 Impl::SortCrsEntries<rowptr_array_type, colind_array_type,
636 vals_array_type>::sortCrsEntries (CRS_rowptr, CRS_colind, CRS_vals);
639 template<
typename rowptr_array_type,
typename colind_array_type>
641 sortCrsEntries (
const rowptr_array_type& CRS_rowptr,
642 const colind_array_type& CRS_colind)
645 typedef typename colind_array_type::execution_space execution_space;
646 typedef Tpetra::Details::DefaultTypes::scalar_type scalar_type;
647 typedef typename Kokkos::View<scalar_type*, execution_space> scalar_view_type;
648 scalar_view_type CRS_vals;
649 sortCrsEntries<rowptr_array_type, colind_array_type,
650 scalar_view_type>(CRS_rowptr, CRS_colind, CRS_vals);
654 template<
typename Scalar,
typename Ordinal>
656 sortAndMergeCrsEntries (
const Teuchos::ArrayView<size_t> &CRS_rowptr,
657 const Teuchos::ArrayView<Ordinal> & CRS_colind,
658 const Teuchos::ArrayView<Scalar> &CRS_vals)
665 if (CRS_rowptr.size () == 0) {
668 const size_t NumRows = CRS_rowptr.size () - 1;
669 const size_t nnz = CRS_colind.size ();
670 size_t new_curr = CRS_rowptr[0];
671 size_t old_curr = CRS_rowptr[0];
673 const bool permute_values_array = CRS_vals.size() > 0;
675 for(
size_t i = 0; i < NumRows; i++){
676 const size_t old_rowptr_i=CRS_rowptr[i];
677 CRS_rowptr[i] = old_curr;
678 if(old_rowptr_i >= nnz)
continue;
680 size_t NumEntries = CRS_rowptr[i+1] - old_rowptr_i;
681 Teuchos::ArrayRCP<Scalar> locValues;
682 if (permute_values_array)
683 locValues = Teuchos::arcp<Scalar>(&CRS_vals[old_rowptr_i], 0, NumEntries,
false);
684 Teuchos::ArrayRCP<Ordinal> locIndices(&CRS_colind[old_rowptr_i], 0, NumEntries,
false);
687 Ordinal n = NumEntries;
692 for(Ordinal j = 0; j < max; j++) {
693 for(Ordinal k = j; k >= 0; k-=m) {
694 if(locIndices[k+m] >= locIndices[k])
696 if (permute_values_array) {
697 Scalar dtemp = locValues[k+m];
698 locValues[k+m] = locValues[k];
699 locValues[k] = dtemp;
701 Ordinal itemp = locIndices[k+m];
702 locIndices[k+m] = locIndices[k];
703 locIndices[k] = itemp;
710 for(
size_t j=old_rowptr_i; j < CRS_rowptr[i+1]; j++) {
711 if(j > old_rowptr_i && CRS_colind[j]==CRS_colind[new_curr-1]) {
712 if (permute_values_array) CRS_vals[new_curr-1] += CRS_vals[j];
714 else if(new_curr==j) {
718 CRS_colind[new_curr] = CRS_colind[j];
719 if (permute_values_array) CRS_vals[new_curr] = CRS_vals[j];
726 CRS_rowptr[NumRows] = new_curr;
729 template<
typename Ordinal>
731 sortAndMergeCrsEntries (
const Teuchos::ArrayView<size_t> &CRS_rowptr,
732 const Teuchos::ArrayView<Ordinal> & CRS_colind)
734 Teuchos::ArrayView<Tpetra::Details::DefaultTypes::scalar_type> CRS_vals;
735 return sortAndMergeCrsEntries(CRS_rowptr, CRS_colind, CRS_vals);
738 template<
class rowptr_view_type,
class colind_view_type,
class vals_view_type>
740 sortAndMergeCrsEntries(rowptr_view_type& CRS_rowptr,
741 colind_view_type& CRS_colind,
742 vals_view_type& CRS_vals)
744 using execution_space =
typename vals_view_type::execution_space;
746 auto CRS_rowptr_in = CRS_rowptr;
747 auto CRS_colind_in = CRS_colind;
748 auto CRS_vals_in = CRS_vals;
750 KokkosSparse::sort_and_merge_matrix<execution_space, rowptr_view_type,
751 colind_view_type, vals_view_type>(CRS_rowptr_in, CRS_colind_in, CRS_vals_in,
752 CRS_rowptr, CRS_colind, CRS_vals);
756 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
758 lowCommunicationMakeColMapAndReindexSerial (
const Teuchos::ArrayView<const size_t> &rowptr,
759 const Teuchos::ArrayView<LocalOrdinal> &colind_LID,
760 const Teuchos::ArrayView<GlobalOrdinal> &colind_GID,
762 const Teuchos::ArrayView<const int> &owningPIDs,
763 Teuchos::Array<int> &remotePIDs,
767 typedef LocalOrdinal LO;
768 typedef GlobalOrdinal GO;
771 const char prefix[] =
"lowCommunicationMakeColMapAndReindexSerial: ";
775 const map_type& domainMap = *domainMapRCP;
781 Teuchos::Array<bool> LocalGIDs;
782 if (numDomainElements > 0) {
783 LocalGIDs.resize (numDomainElements,
false);
794 const size_t numMyRows = rowptr.size () - 1;
795 const int hashsize = std::max (static_cast<int> (numMyRows), 100);
798 Teuchos::Array<GO> RemoteGIDList;
799 RemoteGIDList.reserve (hashsize);
800 Teuchos::Array<int> PIDList;
801 PIDList.reserve (hashsize);
812 size_t NumLocalColGIDs = 0;
813 LO NumRemoteColGIDs = 0;
814 for (
size_t i = 0; i < numMyRows; ++i) {
815 for(
size_t j = rowptr[i]; j < rowptr[i+1]; ++j) {
816 const GO GID = colind_GID[j];
818 const LO LID = domainMap.getLocalElement (GID);
820 const bool alreadyFound = LocalGIDs[LID];
821 if (! alreadyFound) {
822 LocalGIDs[LID] =
true;
828 const LO hash_value = RemoteGIDs.get (GID);
829 if (hash_value == -1) {
830 const int PID = owningPIDs[j];
831 TEUCHOS_TEST_FOR_EXCEPTION(
832 PID == -1, std::invalid_argument, prefix <<
"Cannot figure out if "
834 colind_LID[j] =
static_cast<LO
> (numDomainElements + NumRemoteColGIDs);
835 RemoteGIDs.add (GID, NumRemoteColGIDs);
836 RemoteGIDList.push_back (GID);
837 PIDList.push_back (PID);
841 colind_LID[j] =
static_cast<LO
> (numDomainElements + hash_value);
849 if (domainMap.getComm ()->getSize () == 1) {
852 TEUCHOS_TEST_FOR_EXCEPTION(
853 NumRemoteColGIDs != 0, std::runtime_error, prefix <<
"There is only one "
854 "process in the domain Map's communicator, which means that there are no "
855 "\"remote\" indices. Nevertheless, some column indices are not in the "
857 if (static_cast<size_t> (NumLocalColGIDs) == numDomainElements) {
861 colMap = domainMapRCP;
868 const LO numMyCols = NumLocalColGIDs + NumRemoteColGIDs;
869 Teuchos::Array<GO> ColIndices;
870 GO* RemoteColIndices = NULL;
872 ColIndices.resize (numMyCols);
873 if (NumLocalColGIDs != static_cast<size_t> (numMyCols)) {
874 RemoteColIndices = &ColIndices[NumLocalColGIDs];
878 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
879 RemoteColIndices[i] = RemoteGIDList[i];
883 Teuchos::Array<LO> RemotePermuteIDs (NumRemoteColGIDs);
884 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
885 RemotePermuteIDs[i]=i;
892 ColIndices.begin () + NumLocalColGIDs,
893 RemotePermuteIDs.begin ());
899 remotePIDs = PIDList;
908 LO StartCurrent = 0, StartNext = 1;
909 while (StartNext < NumRemoteColGIDs) {
910 if (PIDList[StartNext]==PIDList[StartNext-1]) {
914 Tpetra::sort2 (ColIndices.begin () + NumLocalColGIDs + StartCurrent,
915 ColIndices.begin () + NumLocalColGIDs + StartNext,
916 RemotePermuteIDs.begin () + StartCurrent);
917 StartCurrent = StartNext;
921 Tpetra::sort2 (ColIndices.begin () + NumLocalColGIDs + StartCurrent,
922 ColIndices.begin () + NumLocalColGIDs + StartNext,
923 RemotePermuteIDs.begin () + StartCurrent);
926 Teuchos::Array<LO> ReverseRemotePermuteIDs (NumRemoteColGIDs);
927 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
928 ReverseRemotePermuteIDs[RemotePermuteIDs[i]] = i;
932 bool use_local_permute =
false;
933 Teuchos::Array<LO> LocalPermuteIDs (numDomainElements);
945 Teuchos::ArrayView<const GO> domainGlobalElements = domainMap.getLocalElementList();
946 if (static_cast<size_t> (NumLocalColGIDs) == numDomainElements) {
947 if (NumLocalColGIDs > 0) {
949 std::copy (domainGlobalElements.begin (), domainGlobalElements.end (),
950 ColIndices.begin ());
954 LO NumLocalAgain = 0;
955 use_local_permute =
true;
956 for (
size_t i = 0; i < numDomainElements; ++i) {
958 LocalPermuteIDs[i] = NumLocalAgain;
959 ColIndices[NumLocalAgain++] = domainGlobalElements[i];
962 TEUCHOS_TEST_FOR_EXCEPTION(
963 static_cast<size_t> (NumLocalAgain) != NumLocalColGIDs,
964 std::runtime_error, prefix <<
"Local ID count test failed.");
968 const GST minus_one = Teuchos::OrdinalTraits<GST>::invalid ();
969 colMap = rcp (
new map_type (minus_one, ColIndices, domainMap.getIndexBase (),
970 domainMap.getComm ()));
973 for (
size_t i = 0; i < numMyRows; ++i) {
974 for (
size_t j = rowptr[i]; j < rowptr[i+1]; ++j) {
975 const LO ID = colind_LID[j];
976 if (static_cast<size_t> (ID) < numDomainElements) {
977 if (use_local_permute) {
978 colind_LID[j] = LocalPermuteIDs[colind_LID[j]];
985 colind_LID[j] = NumLocalColGIDs + ReverseRemotePermuteIDs[colind_LID[j]-numDomainElements];
992 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
994 lowCommunicationMakeColMapAndReindex (
995 const Teuchos::ArrayView<const size_t> &rowptr,
996 const Teuchos::ArrayView<LocalOrdinal> &colind_LID,
997 const Teuchos::ArrayView<GlobalOrdinal> &colind_GID,
999 const Teuchos::ArrayView<const int> &owningPIDs,
1000 Teuchos::Array<int> &remotePIDs,
1004 typedef LocalOrdinal LO;
1005 typedef GlobalOrdinal GO;
1008 const char prefix[] =
"lowCommunicationMakeColMapAndReindex: ";
1010 typedef typename Node::device_type DT;
1011 using execution_space =
typename DT::execution_space;
1012 execution_space exec;
1013 using team_policy = Kokkos::TeamPolicy<execution_space, Kokkos::Schedule<Kokkos::Dynamic>>;
1014 typedef typename map_type::local_map_type local_map_type;
1023 typename decltype(colind_LID_view)::HostMirror colind_LID_host(colind_LID.getRawPtr(), colind_LID.size());
1024 typename decltype(colind_GID_view)::HostMirror colind_GID_host(colind_GID.getRawPtr(), colind_GID.size());
1031 const map_type& domainMap = *domainMapRCP;
1033 Kokkos::UnorderedMap<LO, bool, DT> LocalGIDs_view_map(colind_LID.size());
1034 Kokkos::UnorderedMap<GO, LO, DT> RemoteGIDs_view_map(colind_LID.size());
1036 const size_t numMyRows = rowptr.size () - 1;
1037 local_map_type domainMap_local = domainMap.getLocalMap();
1039 const size_t numDomainElements = domainMap.getLocalNumElements ();
1040 Kokkos::View<bool*, DT> LocalGIDs_view(
"LocalGIDs", numDomainElements);
1041 auto LocalGIDs_host = Kokkos::create_mirror_view(LocalGIDs_view);
1043 size_t NumLocalColGIDs = 0;
1049 Kokkos::parallel_reduce(team_policy(numMyRows, Kokkos::AUTO), KOKKOS_LAMBDA(
const typename team_policy::member_type &member,
size_t &update) {
1050 const int i = member.league_rank();
1051 size_t NumLocalColGIDs_temp = 0;
1052 size_t rowptr_start = rowptr_view[i];
1053 size_t rowptr_end = rowptr_view[i+1];
1054 Kokkos::parallel_reduce(Kokkos::TeamThreadRange(member, rowptr_start, rowptr_end), [&](
const size_t j,
size_t &innerUpdate) {
1055 const GO GID = colind_GID_view[j];
1057 const LO LID = domainMap_local.getLocalElement (GID);
1059 auto outcome = LocalGIDs_view_map.insert(LID);
1061 if(outcome.success()) {
1062 LocalGIDs_view[LID] =
true;
1067 const int PID = owningPIDs_view[j];
1068 auto outcome = RemoteGIDs_view_map.insert(GID, PID);
1069 if(outcome.success() && PID == -1) {
1070 Kokkos::abort(
"Cannot figure out if ID is owned.\n");
1073 }, NumLocalColGIDs_temp);
1074 if(member.team_rank() == 0) update += NumLocalColGIDs_temp;
1075 }, NumLocalColGIDs);
1077 LO NumRemoteColGIDs = RemoteGIDs_view_map.size();
1079 Kokkos::View<int*, DT> PIDList_view(
"PIDList", NumRemoteColGIDs);
1080 auto PIDList_host = Kokkos::create_mirror_view(PIDList_view);
1082 Kokkos::View<GO*, DT> RemoteGIDList_view(
"RemoteGIDList", NumRemoteColGIDs);
1083 auto RemoteGIDList_host = Kokkos::create_mirror_view(RemoteGIDList_view);
1087 Kokkos::parallel_scan(Kokkos::RangePolicy<execution_space>(0, RemoteGIDs_view_map.capacity()), KOKKOS_LAMBDA(
const int i, GO& update,
const bool final) {
1088 if(
final && RemoteGIDs_view_map.valid_at(i)) {
1089 RemoteGIDList_view[update] = RemoteGIDs_view_map.key_at(i);
1090 PIDList_view[update] = RemoteGIDs_view_map.value_at(i);
1092 if(RemoteGIDs_view_map.valid_at(i)) {
1099 if (domainMap.getComm ()->getSize () == 1) {
1102 TEUCHOS_TEST_FOR_EXCEPTION(
1103 NumRemoteColGIDs != 0, std::runtime_error, prefix <<
"There is only one "
1104 "process in the domain Map's communicator, which means that there are no "
1105 "\"remote\" indices. Nevertheless, some column indices are not in the "
1107 if (static_cast<size_t> (NumLocalColGIDs) == numDomainElements) {
1111 colMap = domainMapRCP;
1114 auto localColMap = colMap->getLocalMap();
1115 Kokkos::parallel_for(Kokkos::RangePolicy<execution_space>(0, colind_GID.size()), KOKKOS_LAMBDA(
const int i) {
1116 colind_LID_view[i] = localColMap.getLocalElement(colind_GID_view[i]);
1125 const LO numMyCols = NumLocalColGIDs + NumRemoteColGIDs;
1126 Kokkos::View<GO*, DT> ColIndices_view(
"ColIndices", numMyCols);
1129 if(NumRemoteColGIDs > 0) {
1130 if(NumLocalColGIDs != static_cast<size_t> (numMyCols)) {
1131 Kokkos::parallel_for(Kokkos::RangePolicy<execution_space>(0, NumRemoteColGIDs), KOKKOS_LAMBDA(
const int i) {
1132 ColIndices_view[NumLocalColGIDs+i] = RemoteGIDList_view[i];
1138 Kokkos::parallel_reduce(Kokkos::RangePolicy<execution_space>(0, PIDList_host.size()), KOKKOS_LAMBDA(
const int i,
int& max) {
1139 if(max < PIDList_view[i]) max = PIDList_view[i];
1140 }, Kokkos::Max<int>(PID_max));
1142 using KeyViewTypePID = decltype(PIDList_view);
1143 using BinSortOpPID = Kokkos::BinOp1D<KeyViewTypePID>;
1146 auto ColIndices_subview = Kokkos::subview(ColIndices_view, Kokkos::make_pair(NumLocalColGIDs, ColIndices_view.size()));
1149 BinSortOpPID binOp2(PID_max+1, 0, PID_max);
1154 Kokkos::BinSort<KeyViewTypePID, BinSortOpPID> bin_sort2(PIDList_view, 0, PIDList_view.size(), binOp2,
false);
1155 bin_sort2.create_permute_vector(exec);
1156 bin_sort2.sort(exec, PIDList_view);
1157 bin_sort2.sort(exec, ColIndices_subview);
1166 Teuchos::Array<int> PIDList(NumRemoteColGIDs);
1167 for(LO i = 0; i < NumRemoteColGIDs; ++i) {
1168 PIDList[i] = PIDList_host[i];
1171 remotePIDs = PIDList;
1178 LO StartCurrent = 0, StartNext = 1;
1179 while(StartNext < NumRemoteColGIDs) {
1180 if(PIDList_host[StartNext] == PIDList_host[StartNext-1]) {
1184 Kokkos::sort(ColIndices_view, NumLocalColGIDs + StartCurrent, NumLocalColGIDs + StartNext);
1185 StartCurrent = StartNext;
1190 Kokkos::sort(ColIndices_view, NumLocalColGIDs + StartCurrent, NumLocalColGIDs + StartNext);
1206 if (static_cast<size_t> (NumLocalColGIDs) == numDomainElements) {
1207 if (NumLocalColGIDs > 0) {
1209 Kokkos::parallel_for(Kokkos::RangePolicy<execution_space>(0, numDomainElements), KOKKOS_LAMBDA(
const int i) {
1210 ColIndices_view[i] = domainMap_local.getGlobalElement(i);
1216 LO NumLocalAgain = 0;
1217 Kokkos::parallel_scan(Kokkos::RangePolicy<execution_space>(0, numDomainElements), KOKKOS_LAMBDA(
const int i, LO& update,
const bool final) {
1218 if(
final && LocalGIDs_view[i]) {
1219 ColIndices_view[update] = domainMap_local.getGlobalElement(i);
1221 if(LocalGIDs_view[i]) {
1227 TEUCHOS_TEST_FOR_EXCEPTION(
1228 static_cast<size_t> (NumLocalAgain) != NumLocalColGIDs,
1229 std::runtime_error, prefix <<
"Local ID count test failed.");
1233 const GST minus_one = Teuchos::OrdinalTraits<GST>::invalid ();
1235 colMap = rcp (
new map_type (minus_one, ColIndices_view, domainMap.getIndexBase (),
1236 domainMap.getComm ()));
1239 auto localColMap = colMap->getLocalMap();
1240 Kokkos::parallel_for(Kokkos::RangePolicy<execution_space>(0, colind_GID.size()), KOKKOS_LAMBDA(
const int i) {
1241 colind_LID_view[i] = localColMap.getLocalElement(colind_GID_view[i]);
1249 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
1251 lowCommunicationMakeColMapAndReindex (
1252 const Kokkos::View<size_t*,typename Node::device_type> rowptr_view,
1253 const Kokkos::View<LocalOrdinal*,typename Node::device_type> colind_LID_view,
1254 const Kokkos::View<GlobalOrdinal*,typename Node::device_type> colind_GID_view,
1256 const Kokkos::View<int*,typename Node::device_type> owningPIDs_view,
1257 Teuchos::Array<int> &remotePIDs,
1261 typedef LocalOrdinal LO;
1262 typedef GlobalOrdinal GO;
1265 const char prefix[] =
"lowCommunicationMakeColMapAndReindex: ";
1267 typedef typename Node::device_type DT;
1268 using execution_space =
typename DT::execution_space;
1269 execution_space exec;
1270 using team_policy = Kokkos::TeamPolicy<execution_space, Kokkos::Schedule<Kokkos::Dynamic>>;
1271 typedef typename map_type::local_map_type local_map_type;
1275 const map_type& domainMap = *domainMapRCP;
1277 Kokkos::UnorderedMap<LO, bool, DT> LocalGIDs_view_map(colind_LID_view.size());
1278 Kokkos::UnorderedMap<GO, LO, DT> RemoteGIDs_view_map(colind_LID_view.size());
1280 const size_t numMyRows = rowptr_view.size () - 1;
1281 local_map_type domainMap_local = domainMap.
getLocalMap();
1284 Kokkos::View<bool*, DT> LocalGIDs_view(
"LocalGIDs", numDomainElements);
1285 auto LocalGIDs_host = Kokkos::create_mirror_view(LocalGIDs_view);
1287 size_t NumLocalColGIDs = 0;
1293 Kokkos::parallel_reduce(team_policy(numMyRows, Kokkos::AUTO), KOKKOS_LAMBDA(
const typename team_policy::member_type &member,
size_t &update) {
1294 const int i = member.league_rank();
1295 size_t NumLocalColGIDs_temp = 0;
1296 size_t rowptr_start = rowptr_view[i];
1297 size_t rowptr_end = rowptr_view[i+1];
1298 Kokkos::parallel_reduce(Kokkos::TeamThreadRange(member, rowptr_start, rowptr_end), [&](
const size_t j,
size_t &innerUpdate) {
1299 const GO GID = colind_GID_view[j];
1301 const LO LID = domainMap_local.getLocalElement (GID);
1303 auto outcome = LocalGIDs_view_map.insert(LID);
1305 if(outcome.success()) {
1306 LocalGIDs_view[LID] =
true;
1311 const int PID = owningPIDs_view[j];
1312 auto outcome = RemoteGIDs_view_map.insert(GID, PID);
1313 if(outcome.success() && PID == -1) {
1314 Kokkos::abort(
"Cannot figure out if ID is owned.\n");
1317 }, NumLocalColGIDs_temp);
1318 if(member.team_rank() == 0) update += NumLocalColGIDs_temp;
1319 }, NumLocalColGIDs);
1321 LO NumRemoteColGIDs = RemoteGIDs_view_map.size();
1323 Kokkos::View<int*, DT> PIDList_view(
"PIDList_d", NumRemoteColGIDs);
1325 Kokkos::View<GO*, DT> RemoteGIDList_view(
"RemoteGIDList", NumRemoteColGIDs);
1326 auto RemoteGIDList_host = Kokkos::create_mirror_view(RemoteGIDList_view);
1330 Kokkos::parallel_scan(Kokkos::RangePolicy<execution_space>(0, RemoteGIDs_view_map.capacity()), KOKKOS_LAMBDA(
const int i, GO& update,
const bool final) {
1331 if(
final && RemoteGIDs_view_map.valid_at(i)) {
1332 RemoteGIDList_view[update] = RemoteGIDs_view_map.key_at(i);
1333 PIDList_view[update] = RemoteGIDs_view_map.value_at(i);
1335 if(RemoteGIDs_view_map.valid_at(i)) {
1342 if (domainMap.getComm ()->getSize () == 1) {
1345 TEUCHOS_TEST_FOR_EXCEPTION(
1346 NumRemoteColGIDs != 0, std::runtime_error, prefix <<
"There is only one "
1347 "process in the domain Map's communicator, which means that there are no "
1348 "\"remote\" indices. Nevertheless, some column indices are not in the "
1350 if (static_cast<size_t> (NumLocalColGIDs) == numDomainElements) {
1354 colMap = domainMapRCP;
1357 auto localColMap = colMap->getLocalMap();
1358 Kokkos::parallel_for(Kokkos::RangePolicy<execution_space>(0, colind_GID_view.size()), KOKKOS_LAMBDA(
const int i) {
1359 colind_LID_view[i] = localColMap.getLocalElement(colind_GID_view[i]);
1367 const LO numMyCols = NumLocalColGIDs + NumRemoteColGIDs;
1368 Kokkos::View<GO*, DT> ColIndices_view(
"ColIndices", numMyCols);
1371 if(NumRemoteColGIDs > 0) {
1372 if(NumLocalColGIDs != static_cast<size_t> (numMyCols)) {
1373 Kokkos::parallel_for(Kokkos::RangePolicy<execution_space>(0, NumRemoteColGIDs), KOKKOS_LAMBDA(
const int i) {
1374 ColIndices_view[NumLocalColGIDs+i] = RemoteGIDList_view[i];
1380 Kokkos::parallel_reduce(Kokkos::RangePolicy<execution_space>(0, PIDList_view.size()), KOKKOS_LAMBDA(
const int i,
int& max) {
1381 if(max < PIDList_view[i]) max = PIDList_view[i];
1382 }, Kokkos::Max<int>(PID_max));
1384 using KeyViewTypePID = decltype(PIDList_view);
1385 using BinSortOpPID = Kokkos::BinOp1D<KeyViewTypePID>;
1388 auto ColIndices_subview = Kokkos::subview(ColIndices_view, Kokkos::make_pair(NumLocalColGIDs, ColIndices_view.size()));
1391 BinSortOpPID binOp2(PID_max+1, 0, PID_max);
1396 Kokkos::BinSort<KeyViewTypePID, BinSortOpPID> bin_sort2(PIDList_view, 0, PIDList_view.size(), binOp2,
false);
1397 bin_sort2.create_permute_vector(exec);
1398 bin_sort2.sort(exec, PIDList_view);
1399 bin_sort2.sort(exec, ColIndices_subview);
1403 Teuchos::Array<int> PIDList(NumRemoteColGIDs);
1404 Kokkos::View<int*, Kokkos::HostSpace> PIDList_host(PIDList.data(), PIDList.size());
1408 remotePIDs = PIDList;
1415 LO StartCurrent = 0, StartNext = 1;
1416 while(StartNext < NumRemoteColGIDs) {
1417 if(PIDList_host[StartNext] == PIDList_host[StartNext-1]) {
1421 Kokkos::sort(ColIndices_view, NumLocalColGIDs + StartCurrent, NumLocalColGIDs + StartNext);
1422 StartCurrent = StartNext;
1427 Kokkos::sort(ColIndices_view, NumLocalColGIDs + StartCurrent, NumLocalColGIDs + StartNext);
1443 if (static_cast<size_t> (NumLocalColGIDs) == numDomainElements) {
1444 if (NumLocalColGIDs > 0) {
1446 Kokkos::parallel_for(Kokkos::RangePolicy<execution_space>(0, numDomainElements), KOKKOS_LAMBDA(
const int i) {
1447 ColIndices_view[i] = domainMap_local.getGlobalElement(i);
1453 LO NumLocalAgain = 0;
1454 Kokkos::parallel_scan(Kokkos::RangePolicy<execution_space>(0, numDomainElements), KOKKOS_LAMBDA(
const int i, LO& update,
const bool final) {
1455 if(
final && LocalGIDs_view[i]) {
1456 ColIndices_view[update] = domainMap_local.getGlobalElement(i);
1458 if(LocalGIDs_view[i]) {
1464 TEUCHOS_TEST_FOR_EXCEPTION(
1465 static_cast<size_t> (NumLocalAgain) != NumLocalColGIDs,
1466 std::runtime_error, prefix <<
"Local ID count test failed.");
1470 const GST minus_one = Teuchos::OrdinalTraits<GST>::invalid ();
1472 colMap = rcp (
new map_type (minus_one, ColIndices_view, domainMap.getIndexBase (),
1473 domainMap.getComm ()));
1476 auto localColMap = colMap->getLocalMap();
1477 Kokkos::parallel_for(Kokkos::RangePolicy<execution_space>(0, colind_GID_view.size()), KOKKOS_LAMBDA(
const int i) {
1478 colind_LID_view[i] = localColMap.getLocalElement(colind_GID_view[i]);
1495 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
1496 void getTwoTransferOwnershipVector(const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& transferThatDefinesOwnership,
1497 bool useReverseModeForOwnership,
1498 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& transferThatDefinesMigration,
1499 bool useReverseModeForMigration,
1504 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > OwningMap = useReverseModeForOwnership ?
1506 transferThatDefinesOwnership.getSourceMap();
1507 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > MapAo = useReverseModeForOwnership ?
1508 transferThatDefinesOwnership.getSourceMap() :
1509 transferThatDefinesOwnership.getTargetMap();
1510 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > MapAm = useReverseModeForMigration ?
1511 transferThatDefinesMigration.getTargetMap() :
1512 transferThatDefinesMigration.getSourceMap();
1513 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > VectorMap = useReverseModeForMigration ?
1514 transferThatDefinesMigration.getSourceMap() :
1515 transferThatDefinesMigration.getTargetMap();
1517 TEUCHOS_TEST_FOR_EXCEPTION(!MapAo->isSameAs(*MapAm),std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector map mismatch between transfers");
1518 TEUCHOS_TEST_FOR_EXCEPTION(!VectorMap->isSameAs(*owningPIDs.
getMap()),std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector map mismatch transfer and vector");
1519 #ifdef HAVE_TPETRA_DEBUG
1520 TEUCHOS_TEST_FOR_EXCEPTION(!OwningMap->isOneToOne(),std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");
1523 int rank = OwningMap->getComm()->getRank();
1527 const import_type* ownAsImport =
dynamic_cast<const import_type*
> (&transferThatDefinesOwnership);
1528 const export_type* ownAsExport =
dynamic_cast<const export_type*
> (&transferThatDefinesOwnership);
1530 Teuchos::ArrayRCP<int> pids = temp.getDataNonConst();
1531 Teuchos::ArrayView<int> v_pids = pids();
1532 if(ownAsImport && useReverseModeForOwnership) {TEUCHOS_TEST_FOR_EXCEPTION(1,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");}
1533 else if(ownAsImport && !useReverseModeForOwnership) getPids(*ownAsImport,v_pids,
false);
1534 else if(ownAsExport && useReverseModeForMigration) {TEUCHOS_TEST_FOR_EXCEPTION(1,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector this option not yet implemented");}
1535 else {TEUCHOS_TEST_FOR_EXCEPTION(1,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");}
1537 const import_type* xferAsImport =
dynamic_cast<const import_type*
> (&transferThatDefinesMigration);
1538 const export_type* xferAsExport =
dynamic_cast<const export_type*
> (&transferThatDefinesMigration);
1539 TEUCHOS_TEST_FOR_EXCEPTION(!xferAsImport && !xferAsExport,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector transfer undefined");
1555 #endif // TPETRA_IMPORT_UTIL_HPP
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
Impl::CreateMirrorViewFromUnmanagedHostArray< ValueType, OutputDeviceType >::output_view_type create_mirror_view_from_raw_host_array(const OutputDeviceType &, ValueType *inPtr, const size_t inSize, const bool copy=true, const char label[]="")
Variant of Kokkos::create_mirror_view that takes a raw host 1-d array as input.
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.
size_t getLocalNumElements() const
The number of elements belonging to the calling process.
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.
void sort(View &view, const size_t &size)
Convenience wrapper for std::sort for host-accessible views.
size_t global_size_t
Global size_t object.
void deep_copy(MultiVector< DS, DL, DG, DN > &dst, const MultiVector< SS, SL, SG, SN > &src)
Copy the contents of the MultiVector src into dst.
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.
void start()
Start the deep_copy counter.
Teuchos::ArrayView< const LO > getExportLIDs() const
List of entries in the source Map that will be sent to other processes.
local_map_type getLocalMap() const
Get the local Map for Kokkos kernels.
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.
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").
KOKKOS_INLINE_FUNCTION LocalOrdinal getLocalNumElements() const
The number of indices that live on the calling process.
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.
Functions that wrap Kokkos::create_mirror_view, in order to avoid deep copies when not necessary...