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>
67namespace Import_Util {
71template<
typename Scalar,
typename Ordinal>
74 const Teuchos::ArrayView<Ordinal>& CRS_colind,
75 const Teuchos::ArrayView<Scalar>&CRS_vals);
77template<
typename Ordinal>
80 const Teuchos::ArrayView<Ordinal>& CRS_colind);
82template<
typename rowptr_array_type,
typename colind_array_type,
typename vals_array_type>
85 const colind_array_type& CRS_colind,
86 const vals_array_type& CRS_vals);
88template<
typename rowptr_array_type,
typename colind_array_type>
91 const colind_array_type& CRS_colind);
97template<
typename Scalar,
typename Ordinal>
100 const Teuchos::ArrayView<Ordinal>& CRS_colind,
101 const Teuchos::ArrayView<Scalar>& CRS_vals);
103template<
typename Ordinal>
106 const Teuchos::ArrayView<Ordinal>& CRS_colind);
123template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
126 const Teuchos::ArrayView<LocalOrdinal> &columnIndices_LID,
127 const Teuchos::ArrayView<GlobalOrdinal> &columnIndices_GID,
128 const Teuchos::RCP<
const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > & domainMap,
129 const Teuchos::ArrayView<const int> &owningPids,
130 Teuchos::Array<int> &remotePids,
131 Teuchos::RCP<
const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > & colMap);
149 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
151 bool useReverseModeForOwnership,
152 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& transferForMigratingData,
153 bool useReverseModeForMigration,
154 Tpetra::Vector<int,LocalOrdinal,GlobalOrdinal,Node> & owningPIDs);
165namespace Import_Util {
168template<
typename PID,
typename GlobalOrdinal>
169bool 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);
177template<
typename PID,
178 typename GlobalOrdinal,
179 typename LocalOrdinal>
180bool 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);
189template<
typename Scalar,
190 typename LocalOrdinal,
191 typename GlobalOrdinal,
194reverseNeighborDiscovery(
const CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node> & SourceMatrix,
195 const typename CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::row_ptrs_host_view_type & rowptr,
196 const typename CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_inds_host_view_type & colind,
197 const Tpetra::Details::Transfer<LocalOrdinal,GlobalOrdinal,Node>& RowTransfer,
198 Teuchos::RCP<
const Tpetra::Import<LocalOrdinal,GlobalOrdinal,Node> > MyImporter,
199 Teuchos::RCP<
const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > MyDomainMap,
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 typedef LocalOrdinal LO;
208 typedef GlobalOrdinal GO;
209 typedef std::pair<GO,GO> pidgidpair_t;
211 const std::string prefix {
" Import_Util2::ReverseND:: "};
212 const std::string label (
"IU2::Neighbor");
215 if(MyImporter.is_null())
return;
217 std::ostringstream errstr;
219 auto const comm = MyDomainMap->getComm();
221 MPI_Comm rawComm = getRawMpiComm(*comm);
222 const int MyPID = rcomm->getRank ();
230 Distributor & Distor = MyImporter->getDistributor();
231 const size_t NumRecvs = Distor.getNumReceives();
232 const size_t NumSends = Distor.getNumSends();
233 auto RemoteLIDs = MyImporter->getRemoteLIDs();
234 auto const ProcsFrom = Distor.getProcsFrom();
235 auto const ProcsTo = Distor.getProcsTo();
237 auto LengthsFrom = Distor.getLengthsFrom();
238 auto MyColMap = SourceMatrix.getColMap();
239 const size_t numCols = MyColMap->getLocalNumElements ();
240 RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > target = MyImporter->getTargetMap();
244 Teuchos::Array<int> RemotePIDOrder(numCols,-1);
247 for (
size_t i = 0, j = 0; i < NumRecvs; ++i) {
248 for (
size_t k = 0; k < LengthsFrom[i]; ++k) {
249 const int pid = ProcsFrom[i];
251 RemotePIDOrder[RemoteLIDs[j]] = i;
263 Teuchos::Array<int> ReverseSendSizes(NumRecvs,0);
265 Teuchos::Array< Teuchos::ArrayRCP<pidgidpair_t > > RSB(NumRecvs);
268#ifdef HAVE_TPETRA_MMM_TIMINGS
269 TimeMonitor set_all(*TimeMonitor::getNewTimer(prefix + std::string(
"isMMallSetRSB")));
282 Teuchos::Array<std::set<pidgidpair_t>> pidsets(NumRecvs);
284#ifdef HAVE_TPETRA_MMM_TIMINGS
285 TimeMonitor set_insert(*TimeMonitor::getNewTimer(prefix + std::string(
"isMMallSetRSBinsert")));
287 for(
size_t i=0; i < NumExportLIDs; i++) {
288 LO lid = ExportLIDs[i];
289 GO exp_pid = ExportPIDs[i];
290 for(
auto j=rowptr[lid]; j<rowptr[lid+1]; j++){
291 int pid_order = RemotePIDOrder[colind[j]];
293 GO gid = MyColMap->getGlobalElement(colind[j]);
294 auto tpair = pidgidpair_t(exp_pid,gid);
295 pidsets[pid_order].insert(pidsets[pid_order].end(),tpair);
302#ifdef HAVE_TPETRA_MMM_TIMINGS
303 TimeMonitor set_cpy(*TimeMonitor::getNewTimer(prefix + std::string(
"isMMallSetRSBcpy")));
306 for(
auto &&ps : pidsets) {
308 RSB[jj] = Teuchos::arcp(
new pidgidpair_t[ s ],0, s ,
true);
309 std::copy(ps.begin(),ps.end(),RSB[jj]);
310 ReverseSendSizes[jj]=s;
316 Teuchos::Array<int> ReverseRecvSizes(NumSends,-1);
317 Teuchos::Array<MPI_Request> rawBreq(ProcsFrom.size()+ProcsTo.size(), MPI_REQUEST_NULL);
319 const int mpi_tag_base_ = 3;
322 for(
int i=0;i<ProcsTo.size();++i) {
323 int Rec_Tag = mpi_tag_base_ + ProcsTo[i];
324 int * thisrecv = (
int *) (&ReverseRecvSizes[i]);
325 MPI_Request rawRequest = MPI_REQUEST_NULL;
326 MPI_Irecv(
const_cast<int*
>(thisrecv),
333 rawBreq[mpireq_idx++]=rawRequest;
335 for(
int i=0;i<ProcsFrom.size();++i) {
336 int Send_Tag = mpi_tag_base_ + MyPID;
337 int * mysend = (
int *)(&ReverseSendSizes[i]);
338 MPI_Request rawRequest = MPI_REQUEST_NULL;
346 rawBreq[mpireq_idx++]=rawRequest;
348 Teuchos::Array<MPI_Status> rawBstatus(rawBreq.size());
349#ifdef HAVE_TPETRA_DEBUG
352 MPI_Waitall (rawBreq.size(), rawBreq.getRawPtr(),
353 rawBstatus.getRawPtr());
356#ifdef HAVE_TPETRA_DEBUG
358 errstr <<MyPID<<
"sE1 reverseNeighborDiscovery Mpi_Waitall error on send ";
360 std::cerr<<errstr.str()<<std::flush;
364 int totalexportpairrecsize = 0;
365 for (
size_t i = 0; i < NumSends; ++i) {
366 totalexportpairrecsize += ReverseRecvSizes[i];
367#ifdef HAVE_TPETRA_DEBUG
368 if(ReverseRecvSizes[i]<0) {
369 errstr << MyPID <<
"E4 reverseNeighborDiscovery: got < 0 for receive size "<<ReverseRecvSizes[i]<<std::endl;
374 Teuchos::ArrayRCP<pidgidpair_t >AllReverseRecv= Teuchos::arcp(
new pidgidpair_t[totalexportpairrecsize],0,totalexportpairrecsize,
true);
377 for(
int i=0;i<ProcsTo.size();++i) {
378 int recv_data_size = ReverseRecvSizes[i]*2;
379 int recvData_MPI_Tag = mpi_tag_base_*2 + ProcsTo[i];
380 MPI_Request rawRequest = MPI_REQUEST_NULL;
381 GO * rec_bptr = (GO*) (&AllReverseRecv[offset]);
382 offset+=ReverseRecvSizes[i];
385 ::Tpetra::Details::MpiTypeTraits<GO>::getType(rec_bptr[0]),
390 rawBreq[mpireq_idx++]=rawRequest;
392 for(
int ii=0;ii<ProcsFrom.size();++ii) {
393 GO * send_bptr = (GO*) (RSB[ii].getRawPtr());
394 MPI_Request rawSequest = MPI_REQUEST_NULL;
395 int send_data_size = ReverseSendSizes[ii]*2;
396 int sendData_MPI_Tag = mpi_tag_base_*2+MyPID;
399 ::Tpetra::Details::MpiTypeTraits<GO>::getType(send_bptr[0]),
405 rawBreq[mpireq_idx++]=rawSequest;
407#ifdef HAVE_TPETRA_DEBUG
410 MPI_Waitall (rawBreq.size(),
412 rawBstatus.getRawPtr());
413#ifdef HAVE_TPETRA_DEBUG
415 errstr <<MyPID<<
"E3.r reverseNeighborDiscovery Mpi_Waitall error on receive ";
417 std::cerr<<errstr.str()<<std::flush;
420 std::sort(AllReverseRecv.begin(), AllReverseRecv.end(), Tpetra::Import_Util::sort_PID_then_GID<GlobalOrdinal, GlobalOrdinal>);
422 auto newEndOfPairs = std::unique(AllReverseRecv.begin(), AllReverseRecv.end());
424 if(AllReverseRecv.begin() == newEndOfPairs)
return;
425 int ARRsize = std::distance(AllReverseRecv.begin(),newEndOfPairs);
426 auto rPIDs = Teuchos::arcp(
new int[ARRsize],0,ARRsize,
true);
427 auto rLIDs = Teuchos::arcp(
new LocalOrdinal[ARRsize],0,ARRsize,
true);
430 for(
auto itr = AllReverseRecv.begin(); itr!=newEndOfPairs; ++itr ) {
431 if((
int)(itr->first) != MyPID) {
432 rPIDs[tsize]=(int)itr->first;
433 LocalOrdinal lid = MyDomainMap->getLocalElement(itr->second);
439 type3PIDs=rPIDs.persistingView(0,tsize);
440 type3LIDs=rLIDs.persistingView(0,tsize);
443 std::cerr<<errstr.str()<<std::flush;
447 MPI_Abort (MPI_COMM_WORLD, -1);
453template<
typename Scalar,
typename Ordinal>
456 const Teuchos::ArrayView<Ordinal> & CRS_colind,
457 const Teuchos::ArrayView<Scalar> &CRS_vals)
462 size_t NumRows = CRS_rowptr.size()-1;
463 size_t nnz = CRS_colind.size();
465 const bool permute_values_array = CRS_vals.size() > 0;
467 for(
size_t i = 0; i < NumRows; i++){
468 size_t start=CRS_rowptr[i];
469 if(start >= nnz)
continue;
471 size_t NumEntries = CRS_rowptr[i+1] - start;
472 Teuchos::ArrayRCP<Scalar> locValues;
473 if (permute_values_array)
474 locValues = Teuchos::arcp<Scalar>(&CRS_vals[start], 0, NumEntries,
false);
475 Teuchos::ArrayRCP<Ordinal> locIndices(&CRS_colind[start], 0, NumEntries,
false);
477 Ordinal n = NumEntries;
479 while (m<n) m = m*3+1;
484 for(Ordinal j = 0; j < max; j++) {
485 for(Ordinal k = j; k >= 0; k-=m) {
486 if(locIndices[k+m] >= locIndices[k])
488 if (permute_values_array) {
489 Scalar dtemp = locValues[k+m];
490 locValues[k+m] = locValues[k];
491 locValues[k] = dtemp;
493 Ordinal itemp = locIndices[k+m];
494 locIndices[k+m] = locIndices[k];
495 locIndices[k] = itemp;
503template<
typename Ordinal>
505sortCrsEntries (
const Teuchos::ArrayView<size_t> &CRS_rowptr,
506 const Teuchos::ArrayView<Ordinal> & CRS_colind)
509 Teuchos::ArrayView<Tpetra::Details::DefaultTypes::scalar_type> CRS_vals;
510 sortCrsEntries (CRS_rowptr, CRS_colind, CRS_vals);
515template<
class RowOffsetsType,
class ColumnIndicesType,
class ValuesType>
516class SortCrsEntries {
518 typedef typename ColumnIndicesType::non_const_value_type ordinal_type;
519 typedef typename ValuesType::non_const_value_type scalar_type;
522 SortCrsEntries (
const RowOffsetsType& ptr,
523 const ColumnIndicesType& ind,
524 const ValuesType& val) :
529 static_assert (std::is_signed<ordinal_type>::value,
"The type of each "
530 "column index -- that is, the type of each entry of ind "
531 "-- must be signed in order for this functor to work.");
534 KOKKOS_FUNCTION
void operator() (
const size_t i)
const
536 const size_t nnz = ind_.extent (0);
537 const size_t start = ptr_(i);
538 const bool permute_values_array = val_.extent(0) > 0;
541 const size_t NumEntries = ptr_(i+1) - start;
543 const ordinal_type n =
static_cast<ordinal_type
> (NumEntries);
545 while (m<n) m = m*3+1;
549 ordinal_type max = n - m;
550 for (ordinal_type j = 0; j < max; j++) {
551 for (ordinal_type k = j; k >= 0; k -= m) {
552 const size_t sk = start+k;
553 if (ind_(sk+m) >= ind_(sk)) {
556 if (permute_values_array) {
557 const scalar_type dtemp = val_(sk+m);
558 val_(sk+m) = val_(sk);
561 const ordinal_type itemp = ind_(sk+m);
562 ind_(sk+m) = ind_(sk);
572 sortCrsEntries (
const RowOffsetsType& ptr,
573 const ColumnIndicesType& ind,
574 const ValuesType& val)
581 if (ptr.extent (0) == 0) {
584 const size_t NumRows = ptr.extent (0) - 1;
586 typedef size_t index_type;
587 typedef typename ValuesType::execution_space execution_space;
590 typedef Kokkos::RangePolicy<execution_space, index_type> range_type;
591 Kokkos::parallel_for (
"sortCrsEntries", range_type (0, NumRows),
592 SortCrsEntries (ptr, ind, val));
597 ColumnIndicesType ind_;
603template<
typename rowptr_array_type,
typename colind_array_type,
typename vals_array_type>
606 const colind_array_type& CRS_colind,
607 const vals_array_type& CRS_vals)
609 Impl::SortCrsEntries<rowptr_array_type, colind_array_type,
610 vals_array_type>::sortCrsEntries (CRS_rowptr, CRS_colind, CRS_vals);
613template<
typename rowptr_array_type,
typename colind_array_type>
616 const colind_array_type& CRS_colind)
619 typedef typename colind_array_type::execution_space execution_space;
620 typedef Tpetra::Details::DefaultTypes::scalar_type scalar_type;
621 typedef typename Kokkos::View<scalar_type*, execution_space> scalar_view_type;
622 scalar_view_type CRS_vals;
624 scalar_view_type>(CRS_rowptr, CRS_colind, CRS_vals);
628template<
typename Scalar,
typename Ordinal>
631 const Teuchos::ArrayView<Ordinal> & CRS_colind,
632 const Teuchos::ArrayView<Scalar> &CRS_vals)
639 if (CRS_rowptr.size () == 0) {
642 const size_t NumRows = CRS_rowptr.size () - 1;
643 const size_t nnz = CRS_colind.size ();
644 size_t new_curr = CRS_rowptr[0];
645 size_t old_curr = CRS_rowptr[0];
647 const bool permute_values_array = CRS_vals.size() > 0;
649 for(
size_t i = 0; i < NumRows; i++){
650 const size_t old_rowptr_i=CRS_rowptr[i];
651 CRS_rowptr[i] = old_curr;
652 if(old_rowptr_i >= nnz)
continue;
654 size_t NumEntries = CRS_rowptr[i+1] - old_rowptr_i;
655 Teuchos::ArrayRCP<Scalar> locValues;
656 if (permute_values_array)
657 locValues = Teuchos::arcp<Scalar>(&CRS_vals[old_rowptr_i], 0, NumEntries,
false);
658 Teuchos::ArrayRCP<Ordinal> locIndices(&CRS_colind[old_rowptr_i], 0, NumEntries,
false);
661 Ordinal n = NumEntries;
666 for(Ordinal j = 0; j < max; j++) {
667 for(Ordinal k = j; k >= 0; k-=m) {
668 if(locIndices[k+m] >= locIndices[k])
670 if (permute_values_array) {
671 Scalar dtemp = locValues[k+m];
672 locValues[k+m] = locValues[k];
673 locValues[k] = dtemp;
675 Ordinal itemp = locIndices[k+m];
676 locIndices[k+m] = locIndices[k];
677 locIndices[k] = itemp;
684 for(
size_t j=old_rowptr_i; j < CRS_rowptr[i+1]; j++) {
685 if(j > old_rowptr_i && CRS_colind[j]==CRS_colind[new_curr-1]) {
686 if (permute_values_array) CRS_vals[new_curr-1] += CRS_vals[j];
688 else if(new_curr==j) {
692 CRS_colind[new_curr] = CRS_colind[j];
693 if (permute_values_array) CRS_vals[new_curr] = CRS_vals[j];
700 CRS_rowptr[NumRows] = new_curr;
703template<
typename Ordinal>
705sortAndMergeCrsEntries (
const Teuchos::ArrayView<size_t> &CRS_rowptr,
706 const Teuchos::ArrayView<Ordinal> & CRS_colind)
708 Teuchos::ArrayView<Tpetra::Details::DefaultTypes::scalar_type> CRS_vals;
709 return sortAndMergeCrsEntries(CRS_rowptr, CRS_colind, CRS_vals);
713template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
716 const Teuchos::ArrayView<LocalOrdinal> &colind_LID,
717 const Teuchos::ArrayView<GlobalOrdinal> &colind_GID,
719 const Teuchos::ArrayView<const int> &owningPIDs,
720 Teuchos::Array<int> &remotePIDs,
724 typedef LocalOrdinal LO;
725 typedef GlobalOrdinal GO;
728 const char prefix[] =
"lowCommunicationMakeColMapAndReindex: ";
732 const map_type& domainMap = *domainMapRCP;
737 const size_t numDomainElements = domainMap.getLocalNumElements ();
738 Teuchos::Array<bool> LocalGIDs;
739 if (numDomainElements > 0) {
740 LocalGIDs.resize (numDomainElements,
false);
751 const size_t numMyRows = rowptr.size () - 1;
752 const int hashsize = std::max (
static_cast<int> (numMyRows), 100);
755 Teuchos::Array<GO> RemoteGIDList;
756 RemoteGIDList.reserve (hashsize);
757 Teuchos::Array<int> PIDList;
758 PIDList.reserve (hashsize);
769 size_t NumLocalColGIDs = 0;
770 LO NumRemoteColGIDs = 0;
771 for (
size_t i = 0; i < numMyRows; ++i) {
772 for(
size_t j = rowptr[i]; j < rowptr[i+1]; ++j) {
773 const GO GID = colind_GID[j];
775 const LO LID = domainMap.getLocalElement (GID);
777 const bool alreadyFound = LocalGIDs[LID];
778 if (! alreadyFound) {
779 LocalGIDs[LID] =
true;
785 const LO hash_value = RemoteGIDs.
get (GID);
786 if (hash_value == -1) {
787 const int PID = owningPIDs[j];
788 TEUCHOS_TEST_FOR_EXCEPTION(
789 PID == -1, std::invalid_argument, prefix <<
"Cannot figure out if "
791 colind_LID[j] =
static_cast<LO
> (numDomainElements + NumRemoteColGIDs);
792 RemoteGIDs.
add (GID, NumRemoteColGIDs);
793 RemoteGIDList.push_back (GID);
794 PIDList.push_back (PID);
798 colind_LID[j] =
static_cast<LO
> (numDomainElements + hash_value);
806 if (domainMap.
getComm ()->getSize () == 1) {
809 TEUCHOS_TEST_FOR_EXCEPTION(
810 NumRemoteColGIDs != 0, std::runtime_error, prefix <<
"There is only one "
811 "process in the domain Map's communicator, which means that there are no "
812 "\"remote\" indices. Nevertheless, some column indices are not in the "
814 if (
static_cast<size_t> (NumLocalColGIDs) == numDomainElements) {
818 colMap = domainMapRCP;
825 const LO numMyCols = NumLocalColGIDs + NumRemoteColGIDs;
826 Teuchos::Array<GO> ColIndices;
827 GO* RemoteColIndices = NULL;
829 ColIndices.resize (numMyCols);
830 if (NumLocalColGIDs !=
static_cast<size_t> (numMyCols)) {
831 RemoteColIndices = &ColIndices[NumLocalColGIDs];
835 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
836 RemoteColIndices[i] = RemoteGIDList[i];
840 Teuchos::Array<LO> RemotePermuteIDs (NumRemoteColGIDs);
841 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
842 RemotePermuteIDs[i]=i;
849 ColIndices.begin () + NumLocalColGIDs,
850 RemotePermuteIDs.begin ());
856 remotePIDs = PIDList;
865 LO StartCurrent = 0, StartNext = 1;
866 while (StartNext < NumRemoteColGIDs) {
867 if (PIDList[StartNext]==PIDList[StartNext-1]) {
871 Tpetra::sort2 (ColIndices.begin () + NumLocalColGIDs + StartCurrent,
872 ColIndices.begin () + NumLocalColGIDs + StartNext,
873 RemotePermuteIDs.begin () + StartCurrent);
874 StartCurrent = StartNext;
878 Tpetra::sort2 (ColIndices.begin () + NumLocalColGIDs + StartCurrent,
879 ColIndices.begin () + NumLocalColGIDs + StartNext,
880 RemotePermuteIDs.begin () + StartCurrent);
883 Teuchos::Array<LO> ReverseRemotePermuteIDs (NumRemoteColGIDs);
884 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
885 ReverseRemotePermuteIDs[RemotePermuteIDs[i]] = i;
889 bool use_local_permute =
false;
890 Teuchos::Array<LO> LocalPermuteIDs (numDomainElements);
902 Teuchos::ArrayView<const GO> domainGlobalElements = domainMap.getLocalElementList();
903 if (
static_cast<size_t> (NumLocalColGIDs) == numDomainElements) {
904 if (NumLocalColGIDs > 0) {
906 std::copy (domainGlobalElements.begin (), domainGlobalElements.end (),
907 ColIndices.begin ());
911 LO NumLocalAgain = 0;
912 use_local_permute =
true;
913 for (
size_t i = 0; i < numDomainElements; ++i) {
915 LocalPermuteIDs[i] = NumLocalAgain;
916 ColIndices[NumLocalAgain++] = domainGlobalElements[i];
919 TEUCHOS_TEST_FOR_EXCEPTION(
920 static_cast<size_t> (NumLocalAgain) != NumLocalColGIDs,
921 std::runtime_error, prefix <<
"Local ID count test failed.");
925 const GST minus_one = Teuchos::OrdinalTraits<GST>::invalid ();
930 for (
size_t i = 0; i < numMyRows; ++i) {
931 for (
size_t j = rowptr[i]; j < rowptr[i+1]; ++j) {
932 const LO ID = colind_LID[j];
933 if (
static_cast<size_t> (ID) < numDomainElements) {
934 if (use_local_permute) {
935 colind_LID[j] = LocalPermuteIDs[colind_LID[j]];
942 colind_LID[j] = NumLocalColGIDs + ReverseRemotePermuteIDs[colind_LID[j]-numDomainElements];
964template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
966 bool useReverseModeForOwnership,
967 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& transferThatDefinesMigration,
968 bool useReverseModeForMigration,
973 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > OwningMap = useReverseModeForOwnership ?
974 transferThatDefinesOwnership.getTargetMap() :
975 transferThatDefinesOwnership.getSourceMap();
976 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > MapAo = useReverseModeForOwnership ?
977 transferThatDefinesOwnership.getSourceMap() :
978 transferThatDefinesOwnership.getTargetMap();
979 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > MapAm = useReverseModeForMigration ?
980 transferThatDefinesMigration.getTargetMap() :
981 transferThatDefinesMigration.getSourceMap();
982 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > VectorMap = useReverseModeForMigration ?
983 transferThatDefinesMigration.getSourceMap() :
984 transferThatDefinesMigration.getTargetMap();
986 TEUCHOS_TEST_FOR_EXCEPTION(!MapAo->isSameAs(*MapAm),std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector map mismatch between transfers");
987 TEUCHOS_TEST_FOR_EXCEPTION(!VectorMap->isSameAs(*owningPIDs.
getMap()),std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector map mismatch transfer and vector");
988#ifdef HAVE_TPETRA_DEBUG
989 TEUCHOS_TEST_FOR_EXCEPTION(!OwningMap->isOneToOne(),std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");
992 int rank = OwningMap->getComm()->getRank();
1000 Teuchos::ArrayView<int> v_pids = pids();
1001 if(ownAsImport && useReverseModeForOwnership) {TEUCHOS_TEST_FOR_EXCEPTION(1,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");}
1002 else if(ownAsImport && !useReverseModeForOwnership)
getPids(*ownAsImport,v_pids,
false);
1003 else if(ownAsExport && useReverseModeForMigration) {TEUCHOS_TEST_FOR_EXCEPTION(1,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector this option not yet implemented");}
1004 else {TEUCHOS_TEST_FOR_EXCEPTION(1,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");}
1008 TEUCHOS_TEST_FOR_EXCEPTION(!xferAsImport && !xferAsExport,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector transfer undefined");
Declaration of the Tpetra::CrsMatrix class.
Add specializations of Teuchos::Details::MpiTypeTraits for Kokkos::complex<float> and Kokkos::complex...
Declaration and definition of Tpetra::Details::reallocDualViewIfNeeded, an implementation detail of T...
void lowCommunicationMakeColMapAndReindex(const Teuchos::ArrayView< const size_t > &rowPointers, const Teuchos::ArrayView< LocalOrdinal > &columnIndices_LID, const Teuchos::ArrayView< GlobalOrdinal > &columnIndices_GID, const Teuchos::RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > &domainMap, const Teuchos::ArrayView< const int > &owningPids, Teuchos::Array< int > &remotePids, Teuchos::RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > &colMap)
lowCommunicationMakeColMapAndReindex
void getTwoTransferOwnershipVector(const ::Tpetra::Details::Transfer< LocalOrdinal, GlobalOrdinal, Node > &transferThatDefinesOwnership, bool useReverseModeForOwnership, const ::Tpetra::Details::Transfer< LocalOrdinal, GlobalOrdinal, Node > &transferForMigratingData, bool useReverseModeForMigration, Tpetra::Vector< int, LocalOrdinal, GlobalOrdinal, Node > &owningPIDs)
Generates an list of owning PIDs based on two transfer (aka import/export objects) Let: OwningMap = u...
void sortAndMergeCrsEntries(const Teuchos::ArrayView< size_t > &CRS_rowptr, const Teuchos::ArrayView< Ordinal > &CRS_colind, const Teuchos::ArrayView< Scalar > &CRS_vals)
Sort and merge the entries of the (raw CSR) matrix by column index within each row.
void sortCrsEntries(const Teuchos::ArrayView< size_t > &CRS_rowptr, const Teuchos::ArrayView< Ordinal > &CRS_colind, const Teuchos::ArrayView< Scalar > &CRS_vals)
Sort the entries of the (raw CSR) matrix by column index within each row.
void getPids(const Tpetra::Import< LocalOrdinal, GlobalOrdinal, Node > &Importer, Teuchos::Array< int > &pids, bool use_minus_one_for_local)
Like getPidGidPairs, but just gets the PIDs, ordered by the column Map.
Stand-alone utility functions and macros.
Teuchos::RCP< const Teuchos::Comm< int > > getComm() const override
The communicator over which the matrix is distributed.
GlobalOrdinal getIndexBase() const override
The index base for global indices for this matrix.
ValueType get(const KeyType key)
Get the value corresponding to the given key.
void add(const KeyType key, const ValueType value)
Add a key and its value to the hash table.
Teuchos::ArrayView< const LO > getExportLIDs() const
List of entries in the source Map that will be sent to other processes.
size_t getNumExportIDs() const
Number of entries that must be sent by the calling process to other processes.
Teuchos::ArrayView< const int > getExportPIDs() const
List of processes to which entries will be sent.
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 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").
virtual Teuchos::RCP< const map_type > getMap() const
The Map describing the parallel distribution of this object.
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
A parallel distribution of indices over processes.
void putScalar(const Scalar &value)
Set all values in the multivector with the given value.
A distributed dense vector.
Teuchos::ArrayRCP< Scalar > getDataNonConst()
View of the local values of this vector.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
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 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 global_size_t
Global size_t object.
@ REPLACE
Replace existing values with new values.