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>
42namespace Import_Util {
46template <
typename Scalar,
typename Ordinal>
48 const Teuchos::ArrayView<Ordinal>& CRS_colind,
49 const Teuchos::ArrayView<Scalar>& CRS_vals);
51template <
typename Ordinal>
53 const Teuchos::ArrayView<Ordinal>& CRS_colind);
55template <
typename rowptr_array_type,
typename colind_array_type,
typename vals_array_type>
57 const colind_array_type& CRS_colind,
58 const vals_array_type& CRS_vals);
60template <
typename rowptr_array_type,
typename colind_array_type>
62 const colind_array_type& CRS_colind);
68template <
typename Scalar,
typename Ordinal>
70 const Teuchos::ArrayView<Ordinal>& CRS_colind,
71 const Teuchos::ArrayView<Scalar>& CRS_vals);
73template <
typename Ordinal>
75 const Teuchos::ArrayView<Ordinal>& CRS_colind);
77template <
class rowptr_view_type,
class colind_view_type,
class vals_view_type>
79 const colind_view_type& CRS_colind,
80 const vals_view_type& CRS_vals);
97template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
99 const Teuchos::ArrayView<const size_t>& rowptr,
100 const Teuchos::ArrayView<LocalOrdinal>& colind_LID,
101 const Teuchos::ArrayView<GlobalOrdinal>& colind_GID,
103 const Teuchos::ArrayView<const int>& owningPIDs,
104 Teuchos::Array<int>& remotePIDs,
111template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
113 const Kokkos::View<size_t*, typename Node::device_type>
rowptr_view,
114 const Kokkos::View<LocalOrdinal*, typename Node::device_type>
colind_LID_view,
115 const Kokkos::View<GlobalOrdinal*, typename Node::device_type>
colind_GID_view,
117 const Teuchos::ArrayView<const int>&
owningPIDs,
118 Teuchos::Array<int>& remotePIDs,
134template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
149namespace Import_Util {
151template <
typename PID,
typename GlobalOrdinal>
152bool sort_PID_then_GID(
const std::pair<PID, GlobalOrdinal>& a,
153 const std::pair<PID, GlobalOrdinal>& b) {
154 if (a.first != b.first)
155 return (a.first < b.first);
156 return (a.second < b.second);
159template <
typename PID,
160 typename GlobalOrdinal,
161 typename LocalOrdinal>
162bool sort_PID_then_pair_GID_LID(
const std::pair<PID, std::pair<GlobalOrdinal, LocalOrdinal>>& a,
163 const std::pair<PID, std::pair<GlobalOrdinal, LocalOrdinal>>& b) {
164 if (a.first != b.first)
165 return a.first < b.first;
167 return (a.second.first < b.second.first);
170template <
typename Scalar,
171 typename LocalOrdinal,
172 typename GlobalOrdinal,
174void reverseNeighborDiscovery(
const CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>& SourceMatrix,
175 const typename CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::row_ptrs_host_view_type& rowptr,
176 const typename CrsMatrix<Scalar, LocalOrdinal, GlobalOrdinal, Node>::local_inds_host_view_type& colind,
180 Teuchos::ArrayRCP<int>& type3PIDs,
181 Teuchos::ArrayRCP<LocalOrdinal>& type3LIDs,
182 Teuchos::RCP<
const Teuchos::Comm<int>>& rcomm) {
183#ifdef HAVE_TPETRACORE_MPI
184 using ::Tpetra::Details::Behavior;
185 typedef LocalOrdinal LO;
186 typedef GlobalOrdinal GO;
187 typedef std::pair<GO, GO> pidgidpair_t;
189 const std::string prefix{
" Import_Util2::ReverseND:: "};
190 const std::string label(
"IU2::Neighbor");
193 if (MyImporter.is_null())
return;
195 std::ostringstream errstr;
197 auto const comm = MyDomainMap->getComm();
199 MPI_Comm rawComm = getRawMpiComm(*comm);
200 const int MyPID = rcomm->getRank();
208 Distributor& Distor = MyImporter->getDistributor();
209 const size_t NumRecvs = Distor.getNumReceives();
210 const size_t NumSends = Distor.getNumSends();
211 auto RemoteLIDs = MyImporter->getRemoteLIDs();
212 auto const ProcsFrom = Distor.getProcsFrom();
213 auto const ProcsTo = Distor.getProcsTo();
215 auto LengthsFrom = Distor.getLengthsFrom();
216 auto MyColMap = SourceMatrix.getColMap();
217 const size_t numCols = MyColMap->getLocalNumElements();
218 RCP<const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> target = MyImporter->getTargetMap();
222 Teuchos::Array<int> RemotePIDOrder(numCols, -1);
225 for (
size_t i = 0, j = 0; i < NumRecvs; ++i) {
226 for (
size_t k = 0; k < LengthsFrom[i]; ++k) {
227 const int pid = ProcsFrom[i];
229 RemotePIDOrder[RemoteLIDs[j]] = i;
241 Teuchos::Array<int> ReverseSendSizes(NumRecvs, 0);
243 Teuchos::Array<Teuchos::ArrayRCP<pidgidpair_t>> RSB(NumRecvs);
258 Teuchos::Array<std::set<pidgidpair_t>> pidsets(NumRecvs);
261 for (
size_t i = 0; i < NumExportLIDs; i++) {
262 LO lid = ExportLIDs[i];
263 GO exp_pid = ExportPIDs[i];
264 for (
auto j = rowptr[lid]; j < rowptr[lid + 1]; j++) {
265 int pid_order = RemotePIDOrder[colind[j]];
266 if (pid_order != -1) {
267 GO gid = MyColMap->getGlobalElement(colind[j]);
268 auto tpair = pidgidpair_t(exp_pid, gid);
269 pidsets[pid_order].insert(pidsets[pid_order].end(), tpair);
278 for (
auto&& ps : pidsets) {
280 RSB[jj] = Teuchos::arcp(
new pidgidpair_t[s], 0, s,
true);
281 std::copy(ps.begin(), ps.end(), RSB[jj]);
282 ReverseSendSizes[jj] = s;
288 Teuchos::Array<int> ReverseRecvSizes(NumSends, -1);
289 Teuchos::Array<MPI_Request> rawBreq(ProcsFrom.size() + ProcsTo.size(), MPI_REQUEST_NULL);
291 const int mpi_tag_base_ = 3;
294 for (
int i = 0; i < ProcsTo.size(); ++i) {
295 int Rec_Tag = mpi_tag_base_ + ProcsTo[i];
296 int* thisrecv = (
int*)(&ReverseRecvSizes[i]);
297 MPI_Request rawRequest = MPI_REQUEST_NULL;
298 MPI_Irecv(
const_cast<int*
>(thisrecv),
305 rawBreq[mpireq_idx++] = rawRequest;
307 for (
int i = 0; i < ProcsFrom.size(); ++i) {
308 int Send_Tag = mpi_tag_base_ + MyPID;
309 int* mysend = (
int*)(&ReverseSendSizes[i]);
310 MPI_Request rawRequest = MPI_REQUEST_NULL;
318 rawBreq[mpireq_idx++] = rawRequest;
320 Teuchos::Array<MPI_Status> rawBstatus(rawBreq.size());
321#ifdef HAVE_TPETRA_DEBUG
324 MPI_Waitall(rawBreq.size(), rawBreq.getRawPtr(),
325 rawBstatus.getRawPtr());
327#ifdef HAVE_TPETRA_DEBUG
329 errstr << MyPID <<
"sE1 reverseNeighborDiscovery Mpi_Waitall error on send ";
331 std::cerr << errstr.str() << std::flush;
335 int totalexportpairrecsize = 0;
336 for (
size_t i = 0; i < NumSends; ++i) {
337 totalexportpairrecsize += ReverseRecvSizes[i];
338#ifdef HAVE_TPETRA_DEBUG
339 if (ReverseRecvSizes[i] < 0) {
340 errstr << MyPID <<
"E4 reverseNeighborDiscovery: got < 0 for receive size " << ReverseRecvSizes[i] << std::endl;
345 Teuchos::ArrayRCP<pidgidpair_t> AllReverseRecv = Teuchos::arcp(
new pidgidpair_t[totalexportpairrecsize], 0, totalexportpairrecsize,
true);
348 for (
int i = 0; i < ProcsTo.size(); ++i) {
349 int recv_data_size = ReverseRecvSizes[i] * 2;
350 int recvData_MPI_Tag = mpi_tag_base_ * 2 + ProcsTo[i];
351 MPI_Request rawRequest = MPI_REQUEST_NULL;
352 GO* rec_bptr = (GO*)(&AllReverseRecv[offset]);
353 offset += ReverseRecvSizes[i];
356 ::Tpetra::Details::MpiTypeTraits<GO>::getType(rec_bptr[0]),
361 rawBreq[mpireq_idx++] = rawRequest;
363 for (
int ii = 0; ii < ProcsFrom.size(); ++ii) {
364 GO* send_bptr = (GO*)(RSB[ii].getRawPtr());
365 MPI_Request rawSequest = MPI_REQUEST_NULL;
366 int send_data_size = ReverseSendSizes[ii] * 2;
367 int sendData_MPI_Tag = mpi_tag_base_ * 2 + MyPID;
370 ::Tpetra::Details::MpiTypeTraits<GO>::getType(send_bptr[0]),
376 rawBreq[mpireq_idx++] = rawSequest;
378#ifdef HAVE_TPETRA_DEBUG
381 MPI_Waitall(rawBreq.size(),
383 rawBstatus.getRawPtr());
384#ifdef HAVE_TPETRA_DEBUG
386 errstr << MyPID <<
"E3.r reverseNeighborDiscovery Mpi_Waitall error on receive ";
388 std::cerr << errstr.str() << std::flush;
391 std::sort(AllReverseRecv.begin(), AllReverseRecv.end(), Tpetra::Import_Util::sort_PID_then_GID<GlobalOrdinal, GlobalOrdinal>);
393 auto newEndOfPairs = std::unique(AllReverseRecv.begin(), AllReverseRecv.end());
395 if (AllReverseRecv.begin() == newEndOfPairs)
return;
396 int ARRsize = std::distance(AllReverseRecv.begin(), newEndOfPairs);
397 auto rPIDs = Teuchos::arcp(
new int[ARRsize], 0, ARRsize,
true);
398 auto rLIDs = Teuchos::arcp(
new LocalOrdinal[ARRsize], 0, ARRsize,
true);
401 for (
auto itr = AllReverseRecv.begin(); itr != newEndOfPairs; ++itr) {
402 if ((
int)(itr->first) != MyPID) {
403 rPIDs[tsize] = (int)itr->first;
404 LocalOrdinal lid = MyDomainMap->getLocalElement(itr->second);
410 type3PIDs = rPIDs.persistingView(0, tsize);
411 type3LIDs = rLIDs.persistingView(0, tsize);
414 std::cerr << errstr.str() << std::flush;
418 MPI_Abort(MPI_COMM_WORLD, -1);
424template <
typename Scalar,
typename Ordinal>
426 const Teuchos::ArrayView<Ordinal>&
CRS_colind,
427 const Teuchos::ArrayView<Scalar>&
CRS_vals) {
430 auto vals_k = Kokkos::View<Scalar*, Kokkos::HostSpace, Kokkos::MemoryUnmanaged>(
CRS_vals.data(),
CRS_vals.size());
434template <
typename Ordinal>
435void sortCrsEntries(
const Teuchos::ArrayView<size_t>&
CRS_rowptr,
436 const Teuchos::ArrayView<Ordinal>&
CRS_colind) {
442template <
typename rowptr_array_type,
typename colind_array_type,
typename vals_array_type>
443void sortCrsEntries(
const rowptr_array_type& CRS_rowptr,
444 const colind_array_type& CRS_colind,
445 const vals_array_type& CRS_vals) {
446 KokkosSparse::sort_crs_matrix(CRS_rowptr, CRS_colind, CRS_vals);
449template <
typename rowptr_array_type,
typename colind_array_type>
451 const colind_array_type& CRS_colind) {
452 KokkosSparse::sort_crs_graph(CRS_rowptr, CRS_colind);
456template <
typename Scalar,
typename Ordinal>
458 const Teuchos::ArrayView<Ordinal>&
CRS_colind,
459 const Teuchos::ArrayView<Scalar>&
CRS_vals) {
527template <
typename Ordinal>
528void sortAndMergeCrsEntries(
const Teuchos::ArrayView<size_t>&
CRS_rowptr,
529 const Teuchos::ArrayView<Ordinal>&
CRS_colind) {
530 Teuchos::ArrayView<Tpetra::Details::DefaultTypes::scalar_type>
CRS_vals;
534template <
class rowptr_view_type,
class colind_view_type,
class vals_view_type>
535void sortAndMergeCrsEntries(rowptr_view_type& CRS_rowptr,
536 colind_view_type& CRS_colind,
537 vals_view_type& CRS_vals) {
538 using execution_space =
typename vals_view_type::execution_space;
540 auto CRS_rowptr_in = CRS_rowptr;
541 auto CRS_colind_in = CRS_colind;
542 auto CRS_vals_in = CRS_vals;
544 KokkosSparse::sort_and_merge_matrix<execution_space, rowptr_view_type,
545 colind_view_type, vals_view_type>(CRS_rowptr_in, CRS_colind_in, CRS_vals_in,
546 CRS_rowptr, CRS_colind, CRS_vals);
549template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
550void lowCommunicationMakeColMapAndReindexSerial(
const Teuchos::ArrayView<const size_t>& rowptr,
551 const Teuchos::ArrayView<LocalOrdinal>& colind_LID,
552 const Teuchos::ArrayView<GlobalOrdinal>& colind_GID,
554 const Teuchos::ArrayView<const int>& owningPIDs,
555 Teuchos::Array<int>& remotePIDs,
558 typedef LocalOrdinal LO;
559 typedef GlobalOrdinal GO;
562 const char prefix[] =
"lowCommunicationMakeColMapAndReindexSerial: ";
566 const map_type& domainMap = *domainMapRCP;
571 const size_t numDomainElements = domainMap.getLocalNumElements();
572 Teuchos::Array<bool> LocalGIDs;
573 if (numDomainElements > 0) {
574 LocalGIDs.resize(numDomainElements,
false);
585 const size_t numMyRows = rowptr.size() - 1;
586 const int hashsize = std::max(
static_cast<int>(numMyRows), 100);
589 Teuchos::Array<GO> RemoteGIDList;
590 RemoteGIDList.reserve(hashsize);
591 Teuchos::Array<int> PIDList;
592 PIDList.reserve(hashsize);
603 size_t NumLocalColGIDs = 0;
604 LO NumRemoteColGIDs = 0;
605 for (
size_t i = 0; i < numMyRows; ++i) {
606 for (
size_t j = rowptr[i]; j < rowptr[i + 1]; ++j) {
607 const GO GID = colind_GID[j];
609 const LO LID = domainMap.getLocalElement(GID);
611 const bool alreadyFound = LocalGIDs[LID];
613 LocalGIDs[LID] =
true;
618 const LO hash_value = RemoteGIDs.get(GID);
619 if (hash_value == -1) {
620 const int PID = owningPIDs[j];
621 TEUCHOS_TEST_FOR_EXCEPTION(
622 PID == -1, std::invalid_argument, prefix <<
"Cannot figure out if "
624 colind_LID[j] =
static_cast<LO
>(numDomainElements + NumRemoteColGIDs);
625 RemoteGIDs.add(GID, NumRemoteColGIDs);
626 RemoteGIDList.push_back(GID);
627 PIDList.push_back(PID);
630 colind_LID[j] =
static_cast<LO
>(numDomainElements + hash_value);
638 if (domainMap.getComm()->getSize() == 1) {
641 TEUCHOS_TEST_FOR_EXCEPTION(
642 NumRemoteColGIDs != 0, std::runtime_error, prefix <<
"There is only one "
643 "process in the domain Map's communicator, which means that there are no "
644 "\"remote\" indices. Nevertheless, some column indices are not in the "
646 if (
static_cast<size_t>(NumLocalColGIDs) == numDomainElements) {
650 colMap = domainMapRCP;
657 const LO numMyCols = NumLocalColGIDs + NumRemoteColGIDs;
658 Teuchos::Array<GO> ColIndices;
659 GO* RemoteColIndices = NULL;
661 ColIndices.resize(numMyCols);
662 if (NumLocalColGIDs !=
static_cast<size_t>(numMyCols)) {
663 RemoteColIndices = &ColIndices[NumLocalColGIDs];
667 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
668 RemoteColIndices[i] = RemoteGIDList[i];
672 Teuchos::Array<LO> RemotePermuteIDs(NumRemoteColGIDs);
673 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
674 RemotePermuteIDs[i] = i;
681 ColIndices.begin() + NumLocalColGIDs,
682 RemotePermuteIDs.begin());
688 remotePIDs = PIDList;
697 LO StartCurrent = 0, StartNext = 1;
698 while (StartNext < NumRemoteColGIDs) {
699 if (PIDList[StartNext] == PIDList[StartNext - 1]) {
702 Tpetra::sort2(ColIndices.begin() + NumLocalColGIDs + StartCurrent,
703 ColIndices.begin() + NumLocalColGIDs + StartNext,
704 RemotePermuteIDs.begin() + StartCurrent);
705 StartCurrent = StartNext;
709 Tpetra::sort2(ColIndices.begin() + NumLocalColGIDs + StartCurrent,
710 ColIndices.begin() + NumLocalColGIDs + StartNext,
711 RemotePermuteIDs.begin() + StartCurrent);
714 Teuchos::Array<LO> ReverseRemotePermuteIDs(NumRemoteColGIDs);
715 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
716 ReverseRemotePermuteIDs[RemotePermuteIDs[i]] = i;
720 bool use_local_permute =
false;
721 Teuchos::Array<LO> LocalPermuteIDs(numDomainElements);
733 Teuchos::ArrayView<const GO> domainGlobalElements = domainMap.getLocalElementList();
734 if (
static_cast<size_t>(NumLocalColGIDs) == numDomainElements) {
735 if (NumLocalColGIDs > 0) {
737 std::copy(domainGlobalElements.begin(), domainGlobalElements.end(),
741 LO NumLocalAgain = 0;
742 use_local_permute =
true;
743 for (
size_t i = 0; i < numDomainElements; ++i) {
745 LocalPermuteIDs[i] = NumLocalAgain;
746 ColIndices[NumLocalAgain++] = domainGlobalElements[i];
749 TEUCHOS_TEST_FOR_EXCEPTION(
750 static_cast<size_t>(NumLocalAgain) != NumLocalColGIDs,
751 std::runtime_error, prefix <<
"Local ID count test failed.");
755 const GST minus_one = Teuchos::OrdinalTraits<GST>::invalid();
756 colMap = rcp(
new map_type(minus_one, ColIndices, domainMap.getIndexBase(),
757 domainMap.getComm()));
760 for (
size_t i = 0; i < numMyRows; ++i) {
761 for (
size_t j = rowptr[i]; j < rowptr[i + 1]; ++j) {
762 const LO ID = colind_LID[j];
763 if (
static_cast<size_t>(ID) < numDomainElements) {
764 if (use_local_permute) {
765 colind_LID[j] = LocalPermuteIDs[colind_LID[j]];
771 colind_LID[j] = NumLocalColGIDs + ReverseRemotePermuteIDs[colind_LID[j] - numDomainElements];
777template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
779 const Teuchos::ArrayView<const size_t>&
rowptr,
780 const Teuchos::ArrayView<LocalOrdinal>&
colind_LID,
781 const Teuchos::ArrayView<GlobalOrdinal>&
colind_GID,
783 const Teuchos::ArrayView<const int>&
owningPIDs,
784 Teuchos::Array<int>& remotePIDs,
791 const char prefix[] =
"lowCommunicationMakeColMapAndReindex: ";
793 typedef typename Node::device_type DT;
794 using execution_space =
typename DT::execution_space;
795 execution_space
exec;
796 using team_policy = Kokkos::TeamPolicy<execution_space, Kokkos::Schedule<Kokkos::Dynamic>>;
797 typedef typename map_type::local_map_type local_map_type;
832 Kokkos::parallel_reduce(
834 const int i =
member.league_rank();
838 Kokkos::parallel_reduce(
847 LocalGIDs_view[LID] = true;
853 if (
outcome.success() && PID == -1) {
854 Kokkos::abort(
"Cannot figure out if ID is owned.\n");
873 Kokkos::parallel_scan(
876 RemoteGIDList_view[update] = RemoteGIDs_view_map.key_at(i);
877 PIDList_view[update] = RemoteGIDs_view_map.value_at(i);
886 if (domainMap.getComm()->getSize() == 1) {
891 "process in the domain Map's communicator, which means that there are no "
892 "\"remote\" indices. Nevertheless, some column indices are not in the "
901 auto localColMap = colMap->getLocalMap();
902 Kokkos::parallel_for(
919 Kokkos::parallel_for(
927 Kokkos::parallel_reduce(
957 exec.fence(
"fence before setting PIDList");
999 Kokkos::parallel_for(
1007 Kokkos::parallel_scan(
1020 std::runtime_error,
prefix <<
"Local ID count test failed.");
1024 const GST minus_one = Teuchos::OrdinalTraits<GST>::invalid();
1027 domainMap.getComm()));
1030 auto localColMap = colMap->getLocalMap();
1031 Kokkos::parallel_for(
1041template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
1042void lowCommunicationMakeColMapAndReindex(
1043 const Kokkos::View<size_t*, typename Node::device_type>
rowptr_view,
1044 const Kokkos::View<LocalOrdinal*, typename Node::device_type>
colind_LID_view,
1045 const Kokkos::View<GlobalOrdinal*, typename Node::device_type>
colind_GID_view,
1048 Teuchos::Array<int>& remotePIDs,
1055 const char prefix[] =
"lowCommunicationMakeColMapAndReindex: ";
1057 typedef typename Node::device_type DT;
1058 using execution_space =
typename DT::execution_space;
1059 execution_space
exec;
1060 using team_policy = Kokkos::TeamPolicy<execution_space, Kokkos::Schedule<Kokkos::Dynamic>>;
1061 typedef typename map_type::local_map_type local_map_type;
1083 Kokkos::parallel_reduce(
1085 const int i =
member.league_rank();
1089 Kokkos::parallel_reduce(
1098 LocalGIDs_view[LID] = true;
1102 const int PID = owningPIDs_view[j];
1103 auto outcome = RemoteGIDs_view_map.insert(GID, PID);
1104 if (outcome.success() && PID == -1) {
1105 Kokkos::abort(
"Cannot figure out if ID is owned.\n");
1109 NumLocalColGIDs_temp);
1110 if (member.team_rank() == 0) update += NumLocalColGIDs_temp;
1114 LO NumRemoteColGIDs = RemoteGIDs_view_map.size();
1116 Kokkos::View<int*, DT> PIDList_view(
"PIDList_d", NumRemoteColGIDs);
1118 Kokkos::View<GO*, DT> RemoteGIDList_view(
"RemoteGIDList", NumRemoteColGIDs);
1119 auto RemoteGIDList_host = Kokkos::create_mirror_view(RemoteGIDList_view);
1123 Kokkos::parallel_scan(
1124 Kokkos::RangePolicy<execution_space>(0, RemoteGIDs_view_map.capacity()), KOKKOS_LAMBDA(
const int i, GO& update,
const bool final) {
1125 if (
final && RemoteGIDs_view_map.valid_at(i)) {
1126 RemoteGIDList_view[update] = RemoteGIDs_view_map.key_at(i);
1127 PIDList_view[update] = RemoteGIDs_view_map.value_at(i);
1129 if (RemoteGIDs_view_map.valid_at(i)) {
1136 if (domainMap.getComm()->getSize() == 1) {
1139 TEUCHOS_TEST_FOR_EXCEPTION(
1140 NumRemoteColGIDs != 0, std::runtime_error, prefix <<
"There is only one "
1141 "process in the domain Map's communicator, which means that there are no "
1142 "\"remote\" indices. Nevertheless, some column indices are not in the "
1144 if (
static_cast<size_t>(NumLocalColGIDs) == numDomainElements) {
1148 colMap = domainMapRCP;
1151 auto localColMap = colMap->getLocalMap();
1152 Kokkos::parallel_for(
1153 Kokkos::RangePolicy<execution_space>(0, colind_GID_view.size()), KOKKOS_LAMBDA(
const int i) {
1154 colind_LID_view[i] = localColMap.getLocalElement(colind_GID_view[i]);
1162 const LO numMyCols = NumLocalColGIDs + NumRemoteColGIDs;
1163 Kokkos::View<GO*, DT> ColIndices_view(
"ColIndices", numMyCols);
1166 if (NumRemoteColGIDs > 0) {
1167 if (NumLocalColGIDs !=
static_cast<size_t>(numMyCols)) {
1168 Kokkos::parallel_for(
1169 Kokkos::RangePolicy<execution_space>(0, NumRemoteColGIDs), KOKKOS_LAMBDA(
const int i) {
1170 ColIndices_view[NumLocalColGIDs + i] = RemoteGIDList_view[i];
1176 Kokkos::parallel_reduce(
1177 Kokkos::RangePolicy<execution_space>(0, PIDList_view.size()), KOKKOS_LAMBDA(
const int i,
int& max) {
1178 if (max < PIDList_view[i]) max = PIDList_view[i];
1180 Kokkos::Max<int>(PID_max));
1182 using KeyViewTypePID =
decltype(PIDList_view);
1183 using BinSortOpPID = Kokkos::BinOp1D<KeyViewTypePID>;
1186 auto ColIndices_subview = Kokkos::subview(ColIndices_view, Kokkos::make_pair(NumLocalColGIDs, ColIndices_view.size()));
1189 BinSortOpPID binOp2(PID_max + 1, 0, PID_max);
1194 Kokkos::BinSort<KeyViewTypePID, BinSortOpPID> bin_sort2(PIDList_view, 0, PIDList_view.size(), binOp2,
false);
1195 bin_sort2.create_permute_vector(exec);
1196 bin_sort2.sort(exec, PIDList_view);
1197 bin_sort2.sort(exec, ColIndices_subview);
1201 Teuchos::Array<int> PIDList(NumRemoteColGIDs);
1202 Kokkos::View<int*, Kokkos::HostSpace> PIDList_host(PIDList.data(), PIDList.size());
1203 Kokkos::deep_copy(exec, PIDList_host, PIDList_view);
1206 remotePIDs = PIDList;
1213 LO StartCurrent = 0, StartNext = 1;
1214 while (StartNext < NumRemoteColGIDs) {
1215 if (PIDList_host[StartNext] == PIDList_host[StartNext - 1]) {
1218 Kokkos::sort(ColIndices_view, NumLocalColGIDs + StartCurrent, NumLocalColGIDs + StartNext);
1219 StartCurrent = StartNext;
1224 Kokkos::sort(ColIndices_view, NumLocalColGIDs + StartCurrent, NumLocalColGIDs + StartNext);
1239 if (
static_cast<size_t>(NumLocalColGIDs) == numDomainElements) {
1240 if (NumLocalColGIDs > 0) {
1242 Kokkos::parallel_for(
1243 Kokkos::RangePolicy<execution_space>(0, numDomainElements), KOKKOS_LAMBDA(
const int i) {
1244 ColIndices_view[i] = domainMap_local.getGlobalElement(i);
1249 LO NumLocalAgain = 0;
1250 Kokkos::parallel_scan(
1251 Kokkos::RangePolicy<execution_space>(0, numDomainElements), KOKKOS_LAMBDA(
const int i, LO& update,
const bool final) {
1252 if (
final && LocalGIDs_view[i]) {
1253 ColIndices_view[update] = domainMap_local.getGlobalElement(i);
1255 if (LocalGIDs_view[i]) {
1261 TEUCHOS_TEST_FOR_EXCEPTION(
1262 static_cast<size_t>(NumLocalAgain) != NumLocalColGIDs,
1263 std::runtime_error, prefix <<
"Local ID count test failed.");
1267 const GST minus_one = Teuchos::OrdinalTraits<GST>::invalid();
1269 colMap = rcp(
new map_type(minus_one, ColIndices_view, domainMap.getIndexBase(),
1270 domainMap.getComm()));
1273 auto localColMap = colMap->getLocalMap();
1274 Kokkos::parallel_for(
1275 Kokkos::RangePolicy<execution_space>(0, colind_GID_view.size()), KOKKOS_LAMBDA(
const int i) {
1276 colind_LID_view[i] = localColMap.getLocalElement(colind_GID_view[i]);
1293template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
1309#ifdef HAVE_TPETRA_DEBUG
1320 Teuchos::ArrayRCP<int>
pids =
temp.getDataNonConst();
1323 TEUCHOS_TEST_FOR_EXCEPTION(1, std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");
1327 TEUCHOS_TEST_FOR_EXCEPTION(1, std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector this option not yet implemented");
1329 TEUCHOS_TEST_FOR_EXCEPTION(1, std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");
Declaration of the Tpetra::CrsMatrix class.
Add specializations of Teuchos::Details::MpiTypeTraits for Kokkos::complex<float> and Kokkos::complex...
Functions that wrap Kokkos::create_mirror_view, in order to avoid deep copies when not necessary,...
Declaration and definition of Tpetra::Details::reallocDualViewIfNeeded, an implementation detail of T...
void lowCommunicationMakeColMapAndReindex(const Teuchos::ArrayView< const size_t > &rowptr, const Teuchos::ArrayView< LocalOrdinal > &colind_LID, const Teuchos::ArrayView< GlobalOrdinal > &colind_GID, const Teuchos::RCP< const Tpetra::Map< LocalOrdinal, GlobalOrdinal, Node > > &domainMapRCP, 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.
Struct that holds views of the contents of a CrsMatrix.
Common base class of Import and Export.
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.
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.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
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 global_size_t
Global size_t object.
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.
@ REPLACE
Replace existing values with new values.