10 #ifndef TPETRA_IMPORT_UTIL2_HPP
11 #define TPETRA_IMPORT_UTIL2_HPP
18 #include "Tpetra_ConfigDefs.hpp"
19 #include "Tpetra_Import.hpp"
20 #include "Tpetra_HashTable.hpp"
21 #include "Tpetra_Map.hpp"
23 #include "Tpetra_Distributor.hpp"
26 #include "Tpetra_Vector.hpp"
27 #include "Kokkos_DualView.hpp"
28 #include "KokkosSparse_SortCrs.hpp"
29 #include <Teuchos_Array.hpp>
31 #include <Kokkos_UnorderedMap.hpp>
32 #include <unordered_map>
38 #include <Kokkos_Core.hpp>
39 #include <Kokkos_Sort.hpp>
42 namespace Import_Util {
46 template<
typename Scalar,
typename Ordinal>
48 sortCrsEntries (
const Teuchos::ArrayView<size_t>& CRS_rowptr,
49 const Teuchos::ArrayView<Ordinal>& CRS_colind,
50 const Teuchos::ArrayView<Scalar>&CRS_vals);
52 template<
typename Ordinal>
54 sortCrsEntries (
const Teuchos::ArrayView<size_t>& CRS_rowptr,
55 const Teuchos::ArrayView<Ordinal>& CRS_colind);
57 template<
typename rowptr_array_type,
typename colind_array_type,
typename vals_array_type>
59 sortCrsEntries (
const rowptr_array_type& CRS_rowptr,
60 const colind_array_type& CRS_colind,
61 const vals_array_type& CRS_vals);
63 template<
typename rowptr_array_type,
typename colind_array_type>
65 sortCrsEntries (
const rowptr_array_type& CRS_rowptr,
66 const colind_array_type& CRS_colind);
72 template<
typename Scalar,
typename Ordinal>
74 sortAndMergeCrsEntries (
const Teuchos::ArrayView<size_t>& CRS_rowptr,
75 const Teuchos::ArrayView<Ordinal>& CRS_colind,
76 const Teuchos::ArrayView<Scalar>& CRS_vals);
78 template<
typename Ordinal>
80 sortAndMergeCrsEntries (
const Teuchos::ArrayView<size_t>& CRS_rowptr,
81 const Teuchos::ArrayView<Ordinal>& CRS_colind);
83 template<
class rowptr_view_type,
class colind_view_type,
class vals_view_type>
85 sortAndMergeCrsEntries (
const rowptr_view_type& CRS_rowptr,
86 const colind_view_type& CRS_colind,
87 const vals_view_type& CRS_vals);
104 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
106 lowCommunicationMakeColMapAndReindex (
107 const Teuchos::ArrayView<const size_t> &rowptr,
108 const Teuchos::ArrayView<LocalOrdinal> &colind_LID,
109 const Teuchos::ArrayView<GlobalOrdinal> &colind_GID,
111 const Teuchos::ArrayView<const int> &owningPIDs,
112 Teuchos::Array<int> &remotePIDs,
119 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
121 lowCommunicationMakeColMapAndReindex (
122 const Kokkos::View<size_t*,typename Node::device_type> rowptr_view,
123 const Kokkos::View<LocalOrdinal*,typename Node::device_type> colind_LID_view,
124 const Kokkos::View<GlobalOrdinal*,typename Node::device_type> colind_GID_view,
126 const Teuchos::ArrayView<const int> &owningPIDs,
127 Teuchos::Array<int> &remotePIDs,
143 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
144 void getTwoTransferOwnershipVector(const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& transferThatDefinesOwnership,
145 bool useReverseModeForOwnership,
146 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& transferForMigratingData,
147 bool useReverseModeForMigration,
159 namespace Import_Util {
162 template<
typename PID,
typename GlobalOrdinal>
163 bool sort_PID_then_GID(
const std::pair<PID,GlobalOrdinal> &a,
164 const std::pair<PID,GlobalOrdinal> &b)
167 return (a.first < b.first);
168 return (a.second < b.second);
171 template<
typename PID,
172 typename GlobalOrdinal,
173 typename LocalOrdinal>
174 bool sort_PID_then_pair_GID_LID(
const std::pair<PID, std::pair< GlobalOrdinal, LocalOrdinal > > &a,
175 const std::pair<PID, std::pair< GlobalOrdinal, LocalOrdinal > > &b)
178 return a.first < b.first;
180 return (a.second.first < b.second.first);
183 template<
typename Scalar,
184 typename LocalOrdinal,
185 typename GlobalOrdinal,
188 reverseNeighborDiscovery(
const CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> & SourceMatrix,
189 const typename CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::row_ptrs_host_view_type & rowptr,
190 const typename CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_inds_host_view_type & colind,
194 Teuchos::ArrayRCP<int>& type3PIDs,
195 Teuchos::ArrayRCP<LocalOrdinal>& type3LIDs,
196 Teuchos::RCP<
const Teuchos::Comm<int> >& rcomm)
198 #ifdef HAVE_TPETRACORE_MPI
199 using Teuchos::TimeMonitor;
200 using ::Tpetra::Details::Behavior;
201 typedef LocalOrdinal LO;
202 typedef GlobalOrdinal GO;
203 typedef std::pair<GO,GO> pidgidpair_t;
205 const std::string prefix {
" Import_Util2::ReverseND:: "};
206 const std::string label (
"IU2::Neighbor");
209 if(MyImporter.is_null())
return;
211 std::ostringstream errstr;
213 auto const comm = MyDomainMap->getComm();
215 MPI_Comm rawComm = getRawMpiComm(*comm);
216 const int MyPID = rcomm->getRank ();
224 Distributor & Distor = MyImporter->getDistributor();
225 const size_t NumRecvs = Distor.getNumReceives();
226 const size_t NumSends = Distor.getNumSends();
227 auto RemoteLIDs = MyImporter->getRemoteLIDs();
228 auto const ProcsFrom = Distor.getProcsFrom();
229 auto const ProcsTo = Distor.getProcsTo();
231 auto LengthsFrom = Distor.getLengthsFrom();
232 auto MyColMap = SourceMatrix.getColMap();
233 const size_t numCols = MyColMap->getLocalNumElements ();
234 RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > target = MyImporter->getTargetMap();
238 Teuchos::Array<int> RemotePIDOrder(numCols,-1);
241 for (
size_t i = 0, j = 0; i < NumRecvs; ++i) {
242 for (
size_t k = 0; k < LengthsFrom[i]; ++k) {
243 const int pid = ProcsFrom[i];
245 RemotePIDOrder[RemoteLIDs[j]] = i;
257 Teuchos::Array<int> ReverseSendSizes(NumRecvs,0);
259 Teuchos::Array< Teuchos::ArrayRCP<pidgidpair_t > > RSB(NumRecvs);
262 #ifdef HAVE_TPETRA_MMM_TIMINGS
263 TimeMonitor set_all(*TimeMonitor::getNewTimer(prefix + std::string(
"isMMallSetRSB")));
276 Teuchos::Array<std::set<pidgidpair_t>> pidsets(NumRecvs);
278 #ifdef HAVE_TPETRA_MMM_TIMINGS
279 TimeMonitor set_insert(*TimeMonitor::getNewTimer(prefix + std::string(
"isMMallSetRSBinsert")));
281 for(
size_t i=0; i < NumExportLIDs; i++) {
282 LO lid = ExportLIDs[i];
283 GO exp_pid = ExportPIDs[i];
284 for(
auto j=rowptr[lid]; j<rowptr[lid+1]; j++){
285 int pid_order = RemotePIDOrder[colind[j]];
287 GO gid = MyColMap->getGlobalElement(colind[j]);
288 auto tpair = pidgidpair_t(exp_pid,gid);
289 pidsets[pid_order].insert(pidsets[pid_order].end(),tpair);
296 #ifdef HAVE_TPETRA_MMM_TIMINGS
297 TimeMonitor set_cpy(*TimeMonitor::getNewTimer(prefix + std::string(
"isMMallSetRSBcpy")));
300 for(
auto &&ps : pidsets) {
302 RSB[jj] = Teuchos::arcp(
new pidgidpair_t[ s ],0, s ,
true);
303 std::copy(ps.begin(),ps.end(),RSB[jj]);
304 ReverseSendSizes[jj]=s;
310 Teuchos::Array<int> ReverseRecvSizes(NumSends,-1);
311 Teuchos::Array<MPI_Request> rawBreq(ProcsFrom.size()+ProcsTo.size(), MPI_REQUEST_NULL);
313 const int mpi_tag_base_ = 3;
316 for(
int i=0;i<ProcsTo.size();++i) {
317 int Rec_Tag = mpi_tag_base_ + ProcsTo[i];
318 int * thisrecv = (
int *) (&ReverseRecvSizes[i]);
319 MPI_Request rawRequest = MPI_REQUEST_NULL;
320 MPI_Irecv(const_cast<int*>(thisrecv),
327 rawBreq[mpireq_idx++]=rawRequest;
329 for(
int i=0;i<ProcsFrom.size();++i) {
330 int Send_Tag = mpi_tag_base_ + MyPID;
331 int * mysend = (
int *)(&ReverseSendSizes[i]);
332 MPI_Request rawRequest = MPI_REQUEST_NULL;
340 rawBreq[mpireq_idx++]=rawRequest;
342 Teuchos::Array<MPI_Status> rawBstatus(rawBreq.size());
343 #ifdef HAVE_TPETRA_DEBUG
346 MPI_Waitall (rawBreq.size(), rawBreq.getRawPtr(),
347 rawBstatus.getRawPtr());
350 #ifdef HAVE_TPETRA_DEBUG
352 errstr <<MyPID<<
"sE1 reverseNeighborDiscovery Mpi_Waitall error on send ";
354 std::cerr<<errstr.str()<<std::flush;
358 int totalexportpairrecsize = 0;
359 for (
size_t i = 0; i < NumSends; ++i) {
360 totalexportpairrecsize += ReverseRecvSizes[i];
361 #ifdef HAVE_TPETRA_DEBUG
362 if(ReverseRecvSizes[i]<0) {
363 errstr << MyPID <<
"E4 reverseNeighborDiscovery: got < 0 for receive size "<<ReverseRecvSizes[i]<<std::endl;
368 Teuchos::ArrayRCP<pidgidpair_t >AllReverseRecv= Teuchos::arcp(
new pidgidpair_t[totalexportpairrecsize],0,totalexportpairrecsize,
true);
371 for(
int i=0;i<ProcsTo.size();++i) {
372 int recv_data_size = ReverseRecvSizes[i]*2;
373 int recvData_MPI_Tag = mpi_tag_base_*2 + ProcsTo[i];
374 MPI_Request rawRequest = MPI_REQUEST_NULL;
375 GO * rec_bptr = (GO*) (&AllReverseRecv[offset]);
376 offset+=ReverseRecvSizes[i];
379 ::Tpetra::Details::MpiTypeTraits<GO>::getType(rec_bptr[0]),
384 rawBreq[mpireq_idx++]=rawRequest;
386 for(
int ii=0;ii<ProcsFrom.size();++ii) {
387 GO * send_bptr = (GO*) (RSB[ii].getRawPtr());
388 MPI_Request rawSequest = MPI_REQUEST_NULL;
389 int send_data_size = ReverseSendSizes[ii]*2;
390 int sendData_MPI_Tag = mpi_tag_base_*2+MyPID;
393 ::Tpetra::Details::MpiTypeTraits<GO>::getType(send_bptr[0]),
399 rawBreq[mpireq_idx++]=rawSequest;
401 #ifdef HAVE_TPETRA_DEBUG
404 MPI_Waitall (rawBreq.size(),
406 rawBstatus.getRawPtr());
407 #ifdef HAVE_TPETRA_DEBUG
409 errstr <<MyPID<<
"E3.r reverseNeighborDiscovery Mpi_Waitall error on receive ";
411 std::cerr<<errstr.str()<<std::flush;
414 std::sort(AllReverseRecv.begin(), AllReverseRecv.end(), Tpetra::Import_Util::sort_PID_then_GID<GlobalOrdinal, GlobalOrdinal>);
416 auto newEndOfPairs = std::unique(AllReverseRecv.begin(), AllReverseRecv.end());
418 if(AllReverseRecv.begin() == newEndOfPairs)
return;
419 int ARRsize = std::distance(AllReverseRecv.begin(),newEndOfPairs);
420 auto rPIDs = Teuchos::arcp(
new int[ARRsize],0,ARRsize,
true);
421 auto rLIDs = Teuchos::arcp(
new LocalOrdinal[ARRsize],0,ARRsize,
true);
424 for(
auto itr = AllReverseRecv.begin(); itr!=newEndOfPairs; ++itr ) {
425 if((
int)(itr->first) != MyPID) {
426 rPIDs[tsize]=(int)itr->first;
427 LocalOrdinal lid = MyDomainMap->getLocalElement(itr->second);
433 type3PIDs=rPIDs.persistingView(0,tsize);
434 type3LIDs=rLIDs.persistingView(0,tsize);
437 std::cerr<<errstr.str()<<std::flush;
441 MPI_Abort (MPI_COMM_WORLD, -1);
447 template<
typename Scalar,
typename Ordinal>
449 sortCrsEntries (
const Teuchos::ArrayView<size_t> &CRS_rowptr,
450 const Teuchos::ArrayView<Ordinal> & CRS_colind,
451 const Teuchos::ArrayView<Scalar> &CRS_vals)
456 size_t NumRows = CRS_rowptr.size()-1;
457 size_t nnz = CRS_colind.size();
459 const bool permute_values_array = CRS_vals.size() > 0;
461 for(
size_t i = 0; i < NumRows; i++){
462 size_t start=CRS_rowptr[i];
463 if(start >= nnz)
continue;
465 size_t NumEntries = CRS_rowptr[i+1] -
start;
466 Teuchos::ArrayRCP<Scalar> locValues;
467 if (permute_values_array)
468 locValues = Teuchos::arcp<Scalar>(&CRS_vals[
start], 0, NumEntries,
false);
469 Teuchos::ArrayRCP<Ordinal> locIndices(&CRS_colind[start], 0, NumEntries,
false);
471 Ordinal n = NumEntries;
473 while (m<n) m = m*3+1;
478 for(Ordinal j = 0; j < max; j++) {
479 for(Ordinal k = j; k >= 0; k-=m) {
480 if(locIndices[k+m] >= locIndices[k])
482 if (permute_values_array) {
483 Scalar dtemp = locValues[k+m];
484 locValues[k+m] = locValues[k];
485 locValues[k] = dtemp;
487 Ordinal itemp = locIndices[k+m];
488 locIndices[k+m] = locIndices[k];
489 locIndices[k] = itemp;
497 template<
typename Ordinal>
499 sortCrsEntries (
const Teuchos::ArrayView<size_t> &CRS_rowptr,
500 const Teuchos::ArrayView<Ordinal> & CRS_colind)
503 Teuchos::ArrayView<Tpetra::Details::DefaultTypes::scalar_type> CRS_vals;
504 sortCrsEntries (CRS_rowptr, CRS_colind, CRS_vals);
509 template<
class RowOffsetsType,
class ColumnIndicesType,
class ValuesType>
510 class SortCrsEntries {
512 typedef typename ColumnIndicesType::non_const_value_type ordinal_type;
513 typedef typename ValuesType::non_const_value_type scalar_type;
516 SortCrsEntries (
const RowOffsetsType& ptr,
517 const ColumnIndicesType& ind,
518 const ValuesType& val) :
523 static_assert (std::is_signed<ordinal_type>::value,
"The type of each "
524 "column index -- that is, the type of each entry of ind "
525 "-- must be signed in order for this functor to work.");
528 KOKKOS_FUNCTION
void operator() (
const size_t i)
const
530 const size_t nnz = ind_.extent (0);
531 const size_t start = ptr_(i);
532 const bool permute_values_array = val_.extent(0) > 0;
535 const size_t NumEntries = ptr_(i+1) -
start;
537 const ordinal_type n =
static_cast<ordinal_type
> (NumEntries);
539 while (m<n) m = m*3+1;
543 ordinal_type max = n - m;
544 for (ordinal_type j = 0; j < max; j++) {
545 for (ordinal_type k = j; k >= 0; k -= m) {
546 const size_t sk = start+k;
547 if (ind_(sk+m) >= ind_(sk)) {
550 if (permute_values_array) {
551 const scalar_type dtemp = val_(sk+m);
552 val_(sk+m) = val_(sk);
555 const ordinal_type itemp = ind_(sk+m);
556 ind_(sk+m) = ind_(sk);
566 sortCrsEntries (
const RowOffsetsType& ptr,
567 const ColumnIndicesType& ind,
568 const ValuesType& val)
575 if (ptr.extent (0) == 0) {
578 const size_t NumRows = ptr.extent (0) - 1;
580 typedef size_t index_type;
581 typedef typename ValuesType::execution_space execution_space;
584 typedef Kokkos::RangePolicy<execution_space, index_type> range_type;
585 Kokkos::parallel_for (
"sortCrsEntries", range_type (0, NumRows),
586 SortCrsEntries (ptr, ind, val));
591 ColumnIndicesType ind_;
597 template<
typename rowptr_array_type,
typename colind_array_type,
typename vals_array_type>
599 sortCrsEntries (
const rowptr_array_type& CRS_rowptr,
600 const colind_array_type& CRS_colind,
601 const vals_array_type& CRS_vals)
603 Impl::SortCrsEntries<rowptr_array_type, colind_array_type,
604 vals_array_type>::sortCrsEntries (CRS_rowptr, CRS_colind, CRS_vals);
607 template<
typename rowptr_array_type,
typename colind_array_type>
609 sortCrsEntries (
const rowptr_array_type& CRS_rowptr,
610 const colind_array_type& CRS_colind)
613 typedef typename colind_array_type::execution_space execution_space;
614 typedef Tpetra::Details::DefaultTypes::scalar_type scalar_type;
615 typedef typename Kokkos::View<scalar_type*, execution_space> scalar_view_type;
616 scalar_view_type CRS_vals;
617 sortCrsEntries<rowptr_array_type, colind_array_type,
618 scalar_view_type>(CRS_rowptr, CRS_colind, CRS_vals);
622 template<
typename Scalar,
typename Ordinal>
624 sortAndMergeCrsEntries (
const Teuchos::ArrayView<size_t> &CRS_rowptr,
625 const Teuchos::ArrayView<Ordinal> & CRS_colind,
626 const Teuchos::ArrayView<Scalar> &CRS_vals)
633 if (CRS_rowptr.size () == 0) {
636 const size_t NumRows = CRS_rowptr.size () - 1;
637 const size_t nnz = CRS_colind.size ();
638 size_t new_curr = CRS_rowptr[0];
639 size_t old_curr = CRS_rowptr[0];
641 const bool permute_values_array = CRS_vals.size() > 0;
643 for(
size_t i = 0; i < NumRows; i++){
644 const size_t old_rowptr_i=CRS_rowptr[i];
645 CRS_rowptr[i] = old_curr;
646 if(old_rowptr_i >= nnz)
continue;
648 size_t NumEntries = CRS_rowptr[i+1] - old_rowptr_i;
649 Teuchos::ArrayRCP<Scalar> locValues;
650 if (permute_values_array)
651 locValues = Teuchos::arcp<Scalar>(&CRS_vals[old_rowptr_i], 0, NumEntries,
false);
652 Teuchos::ArrayRCP<Ordinal> locIndices(&CRS_colind[old_rowptr_i], 0, NumEntries,
false);
655 Ordinal n = NumEntries;
660 for(Ordinal j = 0; j < max; j++) {
661 for(Ordinal k = j; k >= 0; k-=m) {
662 if(locIndices[k+m] >= locIndices[k])
664 if (permute_values_array) {
665 Scalar dtemp = locValues[k+m];
666 locValues[k+m] = locValues[k];
667 locValues[k] = dtemp;
669 Ordinal itemp = locIndices[k+m];
670 locIndices[k+m] = locIndices[k];
671 locIndices[k] = itemp;
678 for(
size_t j=old_rowptr_i; j < CRS_rowptr[i+1]; j++) {
679 if(j > old_rowptr_i && CRS_colind[j]==CRS_colind[new_curr-1]) {
680 if (permute_values_array) CRS_vals[new_curr-1] += CRS_vals[j];
682 else if(new_curr==j) {
686 CRS_colind[new_curr] = CRS_colind[j];
687 if (permute_values_array) CRS_vals[new_curr] = CRS_vals[j];
694 CRS_rowptr[NumRows] = new_curr;
697 template<
typename Ordinal>
699 sortAndMergeCrsEntries (
const Teuchos::ArrayView<size_t> &CRS_rowptr,
700 const Teuchos::ArrayView<Ordinal> & CRS_colind)
702 Teuchos::ArrayView<Tpetra::Details::DefaultTypes::scalar_type> CRS_vals;
703 return sortAndMergeCrsEntries(CRS_rowptr, CRS_colind, CRS_vals);
706 template<
class rowptr_view_type,
class colind_view_type,
class vals_view_type>
708 sortAndMergeCrsEntries(rowptr_view_type& CRS_rowptr,
709 colind_view_type& CRS_colind,
710 vals_view_type& CRS_vals)
712 using execution_space =
typename vals_view_type::execution_space;
714 auto CRS_rowptr_in = CRS_rowptr;
715 auto CRS_colind_in = CRS_colind;
716 auto CRS_vals_in = CRS_vals;
718 KokkosSparse::sort_and_merge_matrix<execution_space, rowptr_view_type,
719 colind_view_type, vals_view_type>(CRS_rowptr_in, CRS_colind_in, CRS_vals_in,
720 CRS_rowptr, CRS_colind, CRS_vals);
724 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
726 lowCommunicationMakeColMapAndReindexSerial (
const Teuchos::ArrayView<const size_t> &rowptr,
727 const Teuchos::ArrayView<LocalOrdinal> &colind_LID,
728 const Teuchos::ArrayView<GlobalOrdinal> &colind_GID,
730 const Teuchos::ArrayView<const int> &owningPIDs,
731 Teuchos::Array<int> &remotePIDs,
735 typedef LocalOrdinal LO;
736 typedef GlobalOrdinal GO;
739 const char prefix[] =
"lowCommunicationMakeColMapAndReindexSerial: ";
743 const map_type& domainMap = *domainMapRCP;
749 Teuchos::Array<bool> LocalGIDs;
750 if (numDomainElements > 0) {
751 LocalGIDs.resize (numDomainElements,
false);
762 const size_t numMyRows = rowptr.size () - 1;
763 const int hashsize = std::max (static_cast<int> (numMyRows), 100);
766 Teuchos::Array<GO> RemoteGIDList;
767 RemoteGIDList.reserve (hashsize);
768 Teuchos::Array<int> PIDList;
769 PIDList.reserve (hashsize);
780 size_t NumLocalColGIDs = 0;
781 LO NumRemoteColGIDs = 0;
782 for (
size_t i = 0; i < numMyRows; ++i) {
783 for(
size_t j = rowptr[i]; j < rowptr[i+1]; ++j) {
784 const GO GID = colind_GID[j];
786 const LO LID = domainMap.getLocalElement (GID);
788 const bool alreadyFound = LocalGIDs[LID];
789 if (! alreadyFound) {
790 LocalGIDs[LID] =
true;
796 const LO hash_value = RemoteGIDs.get (GID);
797 if (hash_value == -1) {
798 const int PID = owningPIDs[j];
799 TEUCHOS_TEST_FOR_EXCEPTION(
800 PID == -1, std::invalid_argument, prefix <<
"Cannot figure out if "
802 colind_LID[j] =
static_cast<LO
> (numDomainElements + NumRemoteColGIDs);
803 RemoteGIDs.add (GID, NumRemoteColGIDs);
804 RemoteGIDList.push_back (GID);
805 PIDList.push_back (PID);
809 colind_LID[j] =
static_cast<LO
> (numDomainElements + hash_value);
817 if (domainMap.getComm ()->getSize () == 1) {
820 TEUCHOS_TEST_FOR_EXCEPTION(
821 NumRemoteColGIDs != 0, std::runtime_error, prefix <<
"There is only one "
822 "process in the domain Map's communicator, which means that there are no "
823 "\"remote\" indices. Nevertheless, some column indices are not in the "
825 if (static_cast<size_t> (NumLocalColGIDs) == numDomainElements) {
829 colMap = domainMapRCP;
836 const LO numMyCols = NumLocalColGIDs + NumRemoteColGIDs;
837 Teuchos::Array<GO> ColIndices;
838 GO* RemoteColIndices = NULL;
840 ColIndices.resize (numMyCols);
841 if (NumLocalColGIDs != static_cast<size_t> (numMyCols)) {
842 RemoteColIndices = &ColIndices[NumLocalColGIDs];
846 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
847 RemoteColIndices[i] = RemoteGIDList[i];
851 Teuchos::Array<LO> RemotePermuteIDs (NumRemoteColGIDs);
852 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
853 RemotePermuteIDs[i]=i;
860 ColIndices.begin () + NumLocalColGIDs,
861 RemotePermuteIDs.begin ());
867 remotePIDs = PIDList;
876 LO StartCurrent = 0, StartNext = 1;
877 while (StartNext < NumRemoteColGIDs) {
878 if (PIDList[StartNext]==PIDList[StartNext-1]) {
882 Tpetra::sort2 (ColIndices.begin () + NumLocalColGIDs + StartCurrent,
883 ColIndices.begin () + NumLocalColGIDs + StartNext,
884 RemotePermuteIDs.begin () + StartCurrent);
885 StartCurrent = StartNext;
889 Tpetra::sort2 (ColIndices.begin () + NumLocalColGIDs + StartCurrent,
890 ColIndices.begin () + NumLocalColGIDs + StartNext,
891 RemotePermuteIDs.begin () + StartCurrent);
894 Teuchos::Array<LO> ReverseRemotePermuteIDs (NumRemoteColGIDs);
895 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
896 ReverseRemotePermuteIDs[RemotePermuteIDs[i]] = i;
900 bool use_local_permute =
false;
901 Teuchos::Array<LO> LocalPermuteIDs (numDomainElements);
913 Teuchos::ArrayView<const GO> domainGlobalElements = domainMap.getLocalElementList();
914 if (static_cast<size_t> (NumLocalColGIDs) == numDomainElements) {
915 if (NumLocalColGIDs > 0) {
917 std::copy (domainGlobalElements.begin (), domainGlobalElements.end (),
918 ColIndices.begin ());
922 LO NumLocalAgain = 0;
923 use_local_permute =
true;
924 for (
size_t i = 0; i < numDomainElements; ++i) {
926 LocalPermuteIDs[i] = NumLocalAgain;
927 ColIndices[NumLocalAgain++] = domainGlobalElements[i];
930 TEUCHOS_TEST_FOR_EXCEPTION(
931 static_cast<size_t> (NumLocalAgain) != NumLocalColGIDs,
932 std::runtime_error, prefix <<
"Local ID count test failed.");
936 const GST minus_one = Teuchos::OrdinalTraits<GST>::invalid ();
937 colMap = rcp (
new map_type (minus_one, ColIndices, domainMap.getIndexBase (),
938 domainMap.getComm ()));
941 for (
size_t i = 0; i < numMyRows; ++i) {
942 for (
size_t j = rowptr[i]; j < rowptr[i+1]; ++j) {
943 const LO ID = colind_LID[j];
944 if (static_cast<size_t> (ID) < numDomainElements) {
945 if (use_local_permute) {
946 colind_LID[j] = LocalPermuteIDs[colind_LID[j]];
953 colind_LID[j] = NumLocalColGIDs + ReverseRemotePermuteIDs[colind_LID[j]-numDomainElements];
960 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
962 lowCommunicationMakeColMapAndReindex (
963 const Teuchos::ArrayView<const size_t> &rowptr,
964 const Teuchos::ArrayView<LocalOrdinal> &colind_LID,
965 const Teuchos::ArrayView<GlobalOrdinal> &colind_GID,
967 const Teuchos::ArrayView<const int> &owningPIDs,
968 Teuchos::Array<int> &remotePIDs,
972 typedef LocalOrdinal LO;
973 typedef GlobalOrdinal GO;
976 const char prefix[] =
"lowCommunicationMakeColMapAndReindex: ";
978 typedef typename Node::device_type DT;
979 using execution_space =
typename DT::execution_space;
980 execution_space exec;
981 using team_policy = Kokkos::TeamPolicy<execution_space, Kokkos::Schedule<Kokkos::Dynamic>>;
982 typedef typename map_type::local_map_type local_map_type;
991 typename decltype(colind_LID_view)::HostMirror colind_LID_host(colind_LID.getRawPtr(), colind_LID.size());
992 typename decltype(colind_GID_view)::HostMirror colind_GID_host(colind_GID.getRawPtr(), colind_GID.size());
999 const map_type& domainMap = *domainMapRCP;
1001 Kokkos::UnorderedMap<LO, bool, DT> LocalGIDs_view_map(colind_LID.size());
1002 Kokkos::UnorderedMap<GO, LO, DT> RemoteGIDs_view_map(colind_LID.size());
1004 const size_t numMyRows = rowptr.size () - 1;
1005 local_map_type domainMap_local = domainMap.getLocalMap();
1007 const size_t numDomainElements = domainMap.getLocalNumElements ();
1008 Kokkos::View<bool*, DT> LocalGIDs_view(
"LocalGIDs", numDomainElements);
1009 auto LocalGIDs_host = Kokkos::create_mirror_view(LocalGIDs_view);
1011 size_t NumLocalColGIDs = 0;
1017 Kokkos::parallel_reduce(team_policy(numMyRows, Kokkos::AUTO), KOKKOS_LAMBDA(
const typename team_policy::member_type &member,
size_t &update) {
1018 const int i = member.league_rank();
1019 size_t NumLocalColGIDs_temp = 0;
1020 size_t rowptr_start = rowptr_view[i];
1021 size_t rowptr_end = rowptr_view[i+1];
1022 Kokkos::parallel_reduce(Kokkos::TeamThreadRange(member, rowptr_start, rowptr_end), [&](
const size_t j,
size_t &innerUpdate) {
1023 const GO GID = colind_GID_view[j];
1025 const LO LID = domainMap_local.getLocalElement (GID);
1027 auto outcome = LocalGIDs_view_map.insert(LID);
1029 if(outcome.success()) {
1030 LocalGIDs_view[LID] =
true;
1035 const int PID = owningPIDs_view[j];
1036 auto outcome = RemoteGIDs_view_map.insert(GID, PID);
1037 if(outcome.success() && PID == -1) {
1038 Kokkos::abort(
"Cannot figure out if ID is owned.\n");
1041 }, NumLocalColGIDs_temp);
1042 if(member.team_rank() == 0) update += NumLocalColGIDs_temp;
1043 }, NumLocalColGIDs);
1045 LO NumRemoteColGIDs = RemoteGIDs_view_map.size();
1047 Kokkos::View<int*, DT> PIDList_view(
"PIDList", NumRemoteColGIDs);
1048 auto PIDList_host = Kokkos::create_mirror_view(PIDList_view);
1050 Kokkos::View<GO*, DT> RemoteGIDList_view(
"RemoteGIDList", NumRemoteColGIDs);
1051 auto RemoteGIDList_host = Kokkos::create_mirror_view(RemoteGIDList_view);
1055 Kokkos::parallel_scan(Kokkos::RangePolicy<execution_space>(0, RemoteGIDs_view_map.capacity()), KOKKOS_LAMBDA(
const int i, GO& update,
const bool final) {
1056 if(
final && RemoteGIDs_view_map.valid_at(i)) {
1057 RemoteGIDList_view[update] = RemoteGIDs_view_map.key_at(i);
1058 PIDList_view[update] = RemoteGIDs_view_map.value_at(i);
1060 if(RemoteGIDs_view_map.valid_at(i)) {
1067 if (domainMap.getComm ()->getSize () == 1) {
1070 TEUCHOS_TEST_FOR_EXCEPTION(
1071 NumRemoteColGIDs != 0, std::runtime_error, prefix <<
"There is only one "
1072 "process in the domain Map's communicator, which means that there are no "
1073 "\"remote\" indices. Nevertheless, some column indices are not in the "
1075 if (static_cast<size_t> (NumLocalColGIDs) == numDomainElements) {
1079 colMap = domainMapRCP;
1082 auto localColMap = colMap->getLocalMap();
1083 Kokkos::parallel_for(Kokkos::RangePolicy<execution_space>(0, colind_GID.size()), KOKKOS_LAMBDA(
const int i) {
1084 colind_LID_view[i] = localColMap.getLocalElement(colind_GID_view[i]);
1093 const LO numMyCols = NumLocalColGIDs + NumRemoteColGIDs;
1094 Kokkos::View<GO*, DT> ColIndices_view(
"ColIndices", numMyCols);
1097 if(NumRemoteColGIDs > 0) {
1098 if(NumLocalColGIDs != static_cast<size_t> (numMyCols)) {
1099 Kokkos::parallel_for(Kokkos::RangePolicy<execution_space>(0, NumRemoteColGIDs), KOKKOS_LAMBDA(
const int i) {
1100 ColIndices_view[NumLocalColGIDs+i] = RemoteGIDList_view[i];
1106 Kokkos::parallel_reduce(Kokkos::RangePolicy<execution_space>(0, PIDList_host.size()), KOKKOS_LAMBDA(
const int i,
int& max) {
1107 if(max < PIDList_view[i]) max = PIDList_view[i];
1108 }, Kokkos::Max<int>(PID_max));
1110 using KeyViewTypePID = decltype(PIDList_view);
1111 using BinSortOpPID = Kokkos::BinOp1D<KeyViewTypePID>;
1114 auto ColIndices_subview = Kokkos::subview(ColIndices_view, Kokkos::make_pair(NumLocalColGIDs, ColIndices_view.size()));
1117 BinSortOpPID binOp2(PID_max+1, 0, PID_max);
1122 Kokkos::BinSort<KeyViewTypePID, BinSortOpPID> bin_sort2(PIDList_view, 0, PIDList_view.size(), binOp2,
false);
1123 bin_sort2.create_permute_vector(exec);
1124 bin_sort2.sort(exec, PIDList_view);
1125 bin_sort2.sort(exec, ColIndices_subview);
1134 exec.fence(
"fence before setting PIDList");
1135 Teuchos::Array<int> PIDList(NumRemoteColGIDs);
1136 for(LO i = 0; i < NumRemoteColGIDs; ++i) {
1137 PIDList[i] = PIDList_host[i];
1140 remotePIDs = PIDList;
1147 LO StartCurrent = 0, StartNext = 1;
1148 while(StartNext < NumRemoteColGIDs) {
1149 if(PIDList_host[StartNext] == PIDList_host[StartNext-1]) {
1153 Kokkos::sort(ColIndices_view, NumLocalColGIDs + StartCurrent, NumLocalColGIDs + StartNext);
1154 StartCurrent = StartNext;
1159 Kokkos::sort(ColIndices_view, NumLocalColGIDs + StartCurrent, NumLocalColGIDs + StartNext);
1175 if (static_cast<size_t> (NumLocalColGIDs) == numDomainElements) {
1176 if (NumLocalColGIDs > 0) {
1178 Kokkos::parallel_for(Kokkos::RangePolicy<execution_space>(0, numDomainElements), KOKKOS_LAMBDA(
const int i) {
1179 ColIndices_view[i] = domainMap_local.getGlobalElement(i);
1185 LO NumLocalAgain = 0;
1186 Kokkos::parallel_scan(Kokkos::RangePolicy<execution_space>(0, numDomainElements), KOKKOS_LAMBDA(
const int i, LO& update,
const bool final) {
1187 if(
final && LocalGIDs_view[i]) {
1188 ColIndices_view[update] = domainMap_local.getGlobalElement(i);
1190 if(LocalGIDs_view[i]) {
1196 TEUCHOS_TEST_FOR_EXCEPTION(
1197 static_cast<size_t> (NumLocalAgain) != NumLocalColGIDs,
1198 std::runtime_error, prefix <<
"Local ID count test failed.");
1202 const GST minus_one = Teuchos::OrdinalTraits<GST>::invalid ();
1204 colMap = rcp (
new map_type (minus_one, ColIndices_view, domainMap.getIndexBase (),
1205 domainMap.getComm ()));
1208 auto localColMap = colMap->getLocalMap();
1209 Kokkos::parallel_for(Kokkos::RangePolicy<execution_space>(0, colind_GID.size()), KOKKOS_LAMBDA(
const int i) {
1210 colind_LID_view[i] = localColMap.getLocalElement(colind_GID_view[i]);
1218 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
1220 lowCommunicationMakeColMapAndReindex (
1221 const Kokkos::View<size_t*,typename Node::device_type> rowptr_view,
1222 const Kokkos::View<LocalOrdinal*,typename Node::device_type> colind_LID_view,
1223 const Kokkos::View<GlobalOrdinal*,typename Node::device_type> colind_GID_view,
1225 const Kokkos::View<int*,typename Node::device_type> owningPIDs_view,
1226 Teuchos::Array<int> &remotePIDs,
1230 typedef LocalOrdinal LO;
1231 typedef GlobalOrdinal GO;
1234 const char prefix[] =
"lowCommunicationMakeColMapAndReindex: ";
1236 typedef typename Node::device_type DT;
1237 using execution_space =
typename DT::execution_space;
1238 execution_space exec;
1239 using team_policy = Kokkos::TeamPolicy<execution_space, Kokkos::Schedule<Kokkos::Dynamic>>;
1240 typedef typename map_type::local_map_type local_map_type;
1244 const map_type& domainMap = *domainMapRCP;
1246 Kokkos::UnorderedMap<LO, bool, DT> LocalGIDs_view_map(colind_LID_view.size());
1247 Kokkos::UnorderedMap<GO, LO, DT> RemoteGIDs_view_map(colind_LID_view.size());
1249 const size_t numMyRows = rowptr_view.size () - 1;
1250 local_map_type domainMap_local = domainMap.
getLocalMap();
1253 Kokkos::View<bool*, DT> LocalGIDs_view(
"LocalGIDs", numDomainElements);
1254 auto LocalGIDs_host = Kokkos::create_mirror_view(LocalGIDs_view);
1256 size_t NumLocalColGIDs = 0;
1262 Kokkos::parallel_reduce(team_policy(numMyRows, Kokkos::AUTO), KOKKOS_LAMBDA(
const typename team_policy::member_type &member,
size_t &update) {
1263 const int i = member.league_rank();
1264 size_t NumLocalColGIDs_temp = 0;
1265 size_t rowptr_start = rowptr_view[i];
1266 size_t rowptr_end = rowptr_view[i+1];
1267 Kokkos::parallel_reduce(Kokkos::TeamThreadRange(member, rowptr_start, rowptr_end), [&](
const size_t j,
size_t &innerUpdate) {
1268 const GO GID = colind_GID_view[j];
1270 const LO LID = domainMap_local.getLocalElement (GID);
1272 auto outcome = LocalGIDs_view_map.insert(LID);
1274 if(outcome.success()) {
1275 LocalGIDs_view[LID] =
true;
1280 const int PID = owningPIDs_view[j];
1281 auto outcome = RemoteGIDs_view_map.insert(GID, PID);
1282 if(outcome.success() && PID == -1) {
1283 Kokkos::abort(
"Cannot figure out if ID is owned.\n");
1286 }, NumLocalColGIDs_temp);
1287 if(member.team_rank() == 0) update += NumLocalColGIDs_temp;
1288 }, NumLocalColGIDs);
1290 LO NumRemoteColGIDs = RemoteGIDs_view_map.size();
1292 Kokkos::View<int*, DT> PIDList_view(
"PIDList_d", NumRemoteColGIDs);
1294 Kokkos::View<GO*, DT> RemoteGIDList_view(
"RemoteGIDList", NumRemoteColGIDs);
1295 auto RemoteGIDList_host = Kokkos::create_mirror_view(RemoteGIDList_view);
1299 Kokkos::parallel_scan(Kokkos::RangePolicy<execution_space>(0, RemoteGIDs_view_map.capacity()), KOKKOS_LAMBDA(
const int i, GO& update,
const bool final) {
1300 if(
final && RemoteGIDs_view_map.valid_at(i)) {
1301 RemoteGIDList_view[update] = RemoteGIDs_view_map.key_at(i);
1302 PIDList_view[update] = RemoteGIDs_view_map.value_at(i);
1304 if(RemoteGIDs_view_map.valid_at(i)) {
1311 if (domainMap.getComm ()->getSize () == 1) {
1314 TEUCHOS_TEST_FOR_EXCEPTION(
1315 NumRemoteColGIDs != 0, std::runtime_error, prefix <<
"There is only one "
1316 "process in the domain Map's communicator, which means that there are no "
1317 "\"remote\" indices. Nevertheless, some column indices are not in the "
1319 if (static_cast<size_t> (NumLocalColGIDs) == numDomainElements) {
1323 colMap = domainMapRCP;
1326 auto localColMap = colMap->getLocalMap();
1327 Kokkos::parallel_for(Kokkos::RangePolicy<execution_space>(0, colind_GID_view.size()), KOKKOS_LAMBDA(
const int i) {
1328 colind_LID_view[i] = localColMap.getLocalElement(colind_GID_view[i]);
1336 const LO numMyCols = NumLocalColGIDs + NumRemoteColGIDs;
1337 Kokkos::View<GO*, DT> ColIndices_view(
"ColIndices", numMyCols);
1340 if(NumRemoteColGIDs > 0) {
1341 if(NumLocalColGIDs != static_cast<size_t> (numMyCols)) {
1342 Kokkos::parallel_for(Kokkos::RangePolicy<execution_space>(0, NumRemoteColGIDs), KOKKOS_LAMBDA(
const int i) {
1343 ColIndices_view[NumLocalColGIDs+i] = RemoteGIDList_view[i];
1349 Kokkos::parallel_reduce(Kokkos::RangePolicy<execution_space>(0, PIDList_view.size()), KOKKOS_LAMBDA(
const int i,
int& max) {
1350 if(max < PIDList_view[i]) max = PIDList_view[i];
1351 }, Kokkos::Max<int>(PID_max));
1353 using KeyViewTypePID = decltype(PIDList_view);
1354 using BinSortOpPID = Kokkos::BinOp1D<KeyViewTypePID>;
1357 auto ColIndices_subview = Kokkos::subview(ColIndices_view, Kokkos::make_pair(NumLocalColGIDs, ColIndices_view.size()));
1360 BinSortOpPID binOp2(PID_max+1, 0, PID_max);
1365 Kokkos::BinSort<KeyViewTypePID, BinSortOpPID> bin_sort2(PIDList_view, 0, PIDList_view.size(), binOp2,
false);
1366 bin_sort2.create_permute_vector(exec);
1367 bin_sort2.sort(exec, PIDList_view);
1368 bin_sort2.sort(exec, ColIndices_subview);
1372 Teuchos::Array<int> PIDList(NumRemoteColGIDs);
1373 Kokkos::View<int*, Kokkos::HostSpace> PIDList_host(PIDList.data(), PIDList.size());
1377 remotePIDs = PIDList;
1384 LO StartCurrent = 0, StartNext = 1;
1385 while(StartNext < NumRemoteColGIDs) {
1386 if(PIDList_host[StartNext] == PIDList_host[StartNext-1]) {
1390 Kokkos::sort(ColIndices_view, NumLocalColGIDs + StartCurrent, NumLocalColGIDs + StartNext);
1391 StartCurrent = StartNext;
1396 Kokkos::sort(ColIndices_view, NumLocalColGIDs + StartCurrent, NumLocalColGIDs + StartNext);
1412 if (static_cast<size_t> (NumLocalColGIDs) == numDomainElements) {
1413 if (NumLocalColGIDs > 0) {
1415 Kokkos::parallel_for(Kokkos::RangePolicy<execution_space>(0, numDomainElements), KOKKOS_LAMBDA(
const int i) {
1416 ColIndices_view[i] = domainMap_local.getGlobalElement(i);
1422 LO NumLocalAgain = 0;
1423 Kokkos::parallel_scan(Kokkos::RangePolicy<execution_space>(0, numDomainElements), KOKKOS_LAMBDA(
const int i, LO& update,
const bool final) {
1424 if(
final && LocalGIDs_view[i]) {
1425 ColIndices_view[update] = domainMap_local.getGlobalElement(i);
1427 if(LocalGIDs_view[i]) {
1433 TEUCHOS_TEST_FOR_EXCEPTION(
1434 static_cast<size_t> (NumLocalAgain) != NumLocalColGIDs,
1435 std::runtime_error, prefix <<
"Local ID count test failed.");
1439 const GST minus_one = Teuchos::OrdinalTraits<GST>::invalid ();
1441 colMap = rcp (
new map_type (minus_one, ColIndices_view, domainMap.getIndexBase (),
1442 domainMap.getComm ()));
1445 auto localColMap = colMap->getLocalMap();
1446 Kokkos::parallel_for(Kokkos::RangePolicy<execution_space>(0, colind_GID_view.size()), KOKKOS_LAMBDA(
const int i) {
1447 colind_LID_view[i] = localColMap.getLocalElement(colind_GID_view[i]);
1464 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
1465 void getTwoTransferOwnershipVector(const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& transferThatDefinesOwnership,
1466 bool useReverseModeForOwnership,
1467 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& transferThatDefinesMigration,
1468 bool useReverseModeForMigration,
1473 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > OwningMap = useReverseModeForOwnership ?
1475 transferThatDefinesOwnership.getSourceMap();
1476 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > MapAo = useReverseModeForOwnership ?
1477 transferThatDefinesOwnership.getSourceMap() :
1478 transferThatDefinesOwnership.getTargetMap();
1479 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > MapAm = useReverseModeForMigration ?
1480 transferThatDefinesMigration.getTargetMap() :
1481 transferThatDefinesMigration.getSourceMap();
1482 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > VectorMap = useReverseModeForMigration ?
1483 transferThatDefinesMigration.getSourceMap() :
1484 transferThatDefinesMigration.getTargetMap();
1486 TEUCHOS_TEST_FOR_EXCEPTION(!MapAo->isSameAs(*MapAm),std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector map mismatch between transfers");
1487 TEUCHOS_TEST_FOR_EXCEPTION(!VectorMap->isSameAs(*owningPIDs.
getMap()),std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector map mismatch transfer and vector");
1488 #ifdef HAVE_TPETRA_DEBUG
1489 TEUCHOS_TEST_FOR_EXCEPTION(!OwningMap->isOneToOne(),std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");
1492 int rank = OwningMap->getComm()->getRank();
1496 const import_type* ownAsImport =
dynamic_cast<const import_type*
> (&transferThatDefinesOwnership);
1497 const export_type* ownAsExport =
dynamic_cast<const export_type*
> (&transferThatDefinesOwnership);
1499 Teuchos::ArrayRCP<int> pids = temp.getDataNonConst();
1500 Teuchos::ArrayView<int> v_pids = pids();
1501 if(ownAsImport && useReverseModeForOwnership) {TEUCHOS_TEST_FOR_EXCEPTION(1,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");}
1502 else if(ownAsImport && !useReverseModeForOwnership) getPids(*ownAsImport,v_pids,
false);
1503 else if(ownAsExport && useReverseModeForMigration) {TEUCHOS_TEST_FOR_EXCEPTION(1,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector this option not yet implemented");}
1504 else {TEUCHOS_TEST_FOR_EXCEPTION(1,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");}
1506 const import_type* xferAsImport =
dynamic_cast<const import_type*
> (&transferThatDefinesMigration);
1507 const export_type* xferAsExport =
dynamic_cast<const export_type*
> (&transferThatDefinesMigration);
1508 TEUCHOS_TEST_FOR_EXCEPTION(!xferAsImport && !xferAsExport,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector transfer undefined");
1524 #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 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.
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.
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...
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.
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 LocalMap for Kokkos-Kernels.
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...