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,
102 const Teuchos::RCP<
const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node>>& domainMapRCP,
103 const Teuchos::ArrayView<const int>& owningPIDs,
104 Teuchos::Array<int>& remotePIDs,
105 Teuchos::RCP<
const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node>>& colMap);
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>
136 bool useReverseModeForOwnership,
137 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& transferForMigratingData,
138 bool useReverseModeForMigration,
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,
177 const Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& RowTransfer,
178 Teuchos::RCP<
const Tpetra::Import<LocalOrdinal, GlobalOrdinal, Node>> MyImporter,
179 Teuchos::RCP<
const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> MyDomainMap,
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 Teuchos::TimeMonitor;
185 using ::Tpetra::Details::Behavior;
186 typedef LocalOrdinal LO;
187 typedef GlobalOrdinal GO;
188 typedef std::pair<GO, GO> pidgidpair_t;
190 const std::string prefix{
" Import_Util2::ReverseND:: "};
191 const std::string label(
"IU2::Neighbor");
194 if (MyImporter.is_null())
return;
196 std::ostringstream errstr;
198 auto const comm = MyDomainMap->getComm();
200 MPI_Comm rawComm = getRawMpiComm(*comm);
201 const int MyPID = rcomm->getRank();
209 Distributor& Distor = MyImporter->getDistributor();
210 const size_t NumRecvs = Distor.getNumReceives();
211 const size_t NumSends = Distor.getNumSends();
212 auto RemoteLIDs = MyImporter->getRemoteLIDs();
213 auto const ProcsFrom = Distor.getProcsFrom();
214 auto const ProcsTo = Distor.getProcsTo();
216 auto LengthsFrom = Distor.getLengthsFrom();
217 auto MyColMap = SourceMatrix.getColMap();
218 const size_t numCols = MyColMap->getLocalNumElements();
219 RCP<const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> target = MyImporter->getTargetMap();
223 Teuchos::Array<int> RemotePIDOrder(numCols, -1);
226 for (
size_t i = 0, j = 0; i < NumRecvs; ++i) {
227 for (
size_t k = 0; k < LengthsFrom[i]; ++k) {
228 const int pid = ProcsFrom[i];
230 RemotePIDOrder[RemoteLIDs[j]] = i;
242 Teuchos::Array<int> ReverseSendSizes(NumRecvs, 0);
244 Teuchos::Array<Teuchos::ArrayRCP<pidgidpair_t>> RSB(NumRecvs);
247#ifdef HAVE_TPETRA_MMM_TIMINGS
248 TimeMonitor set_all(*TimeMonitor::getNewTimer(prefix + std::string(
"isMMallSetRSB")));
261 Teuchos::Array<std::set<pidgidpair_t>> pidsets(NumRecvs);
263#ifdef HAVE_TPETRA_MMM_TIMINGS
264 TimeMonitor set_insert(*TimeMonitor::getNewTimer(prefix + std::string(
"isMMallSetRSBinsert")));
266 for (
size_t i = 0; i < NumExportLIDs; i++) {
267 LO lid = ExportLIDs[i];
268 GO exp_pid = ExportPIDs[i];
269 for (
auto j = rowptr[lid]; j < rowptr[lid + 1]; j++) {
270 int pid_order = RemotePIDOrder[colind[j]];
271 if (pid_order != -1) {
272 GO gid = MyColMap->getGlobalElement(colind[j]);
273 auto tpair = pidgidpair_t(exp_pid, gid);
274 pidsets[pid_order].insert(pidsets[pid_order].end(), tpair);
281#ifdef HAVE_TPETRA_MMM_TIMINGS
282 TimeMonitor set_cpy(*TimeMonitor::getNewTimer(prefix + std::string(
"isMMallSetRSBcpy")));
285 for (
auto&& ps : pidsets) {
287 RSB[jj] = Teuchos::arcp(
new pidgidpair_t[s], 0, s,
true);
288 std::copy(ps.begin(), ps.end(), RSB[jj]);
289 ReverseSendSizes[jj] = s;
295 Teuchos::Array<int> ReverseRecvSizes(NumSends, -1);
296 Teuchos::Array<MPI_Request> rawBreq(ProcsFrom.size() + ProcsTo.size(), MPI_REQUEST_NULL);
298 const int mpi_tag_base_ = 3;
301 for (
int i = 0; i < ProcsTo.size(); ++i) {
302 int Rec_Tag = mpi_tag_base_ + ProcsTo[i];
303 int* thisrecv = (
int*)(&ReverseRecvSizes[i]);
304 MPI_Request rawRequest = MPI_REQUEST_NULL;
305 MPI_Irecv(
const_cast<int*
>(thisrecv),
312 rawBreq[mpireq_idx++] = rawRequest;
314 for (
int i = 0; i < ProcsFrom.size(); ++i) {
315 int Send_Tag = mpi_tag_base_ + MyPID;
316 int* mysend = (
int*)(&ReverseSendSizes[i]);
317 MPI_Request rawRequest = MPI_REQUEST_NULL;
325 rawBreq[mpireq_idx++] = rawRequest;
327 Teuchos::Array<MPI_Status> rawBstatus(rawBreq.size());
328#ifdef HAVE_TPETRA_DEBUG
331 MPI_Waitall(rawBreq.size(), rawBreq.getRawPtr(),
332 rawBstatus.getRawPtr());
334#ifdef HAVE_TPETRA_DEBUG
336 errstr << MyPID <<
"sE1 reverseNeighborDiscovery Mpi_Waitall error on send ";
338 std::cerr << errstr.str() << std::flush;
342 int totalexportpairrecsize = 0;
343 for (
size_t i = 0; i < NumSends; ++i) {
344 totalexportpairrecsize += ReverseRecvSizes[i];
345#ifdef HAVE_TPETRA_DEBUG
346 if (ReverseRecvSizes[i] < 0) {
347 errstr << MyPID <<
"E4 reverseNeighborDiscovery: got < 0 for receive size " << ReverseRecvSizes[i] << std::endl;
352 Teuchos::ArrayRCP<pidgidpair_t> AllReverseRecv = Teuchos::arcp(
new pidgidpair_t[totalexportpairrecsize], 0, totalexportpairrecsize,
true);
355 for (
int i = 0; i < ProcsTo.size(); ++i) {
356 int recv_data_size = ReverseRecvSizes[i] * 2;
357 int recvData_MPI_Tag = mpi_tag_base_ * 2 + ProcsTo[i];
358 MPI_Request rawRequest = MPI_REQUEST_NULL;
359 GO* rec_bptr = (GO*)(&AllReverseRecv[offset]);
360 offset += ReverseRecvSizes[i];
363 ::Tpetra::Details::MpiTypeTraits<GO>::getType(rec_bptr[0]),
368 rawBreq[mpireq_idx++] = rawRequest;
370 for (
int ii = 0; ii < ProcsFrom.size(); ++ii) {
371 GO* send_bptr = (GO*)(RSB[ii].getRawPtr());
372 MPI_Request rawSequest = MPI_REQUEST_NULL;
373 int send_data_size = ReverseSendSizes[ii] * 2;
374 int sendData_MPI_Tag = mpi_tag_base_ * 2 + MyPID;
377 ::Tpetra::Details::MpiTypeTraits<GO>::getType(send_bptr[0]),
383 rawBreq[mpireq_idx++] = rawSequest;
385#ifdef HAVE_TPETRA_DEBUG
388 MPI_Waitall(rawBreq.size(),
390 rawBstatus.getRawPtr());
391#ifdef HAVE_TPETRA_DEBUG
393 errstr << MyPID <<
"E3.r reverseNeighborDiscovery Mpi_Waitall error on receive ";
395 std::cerr << errstr.str() << std::flush;
398 std::sort(AllReverseRecv.begin(), AllReverseRecv.end(), Tpetra::Import_Util::sort_PID_then_GID<GlobalOrdinal, GlobalOrdinal>);
400 auto newEndOfPairs = std::unique(AllReverseRecv.begin(), AllReverseRecv.end());
402 if (AllReverseRecv.begin() == newEndOfPairs)
return;
403 int ARRsize = std::distance(AllReverseRecv.begin(), newEndOfPairs);
404 auto rPIDs = Teuchos::arcp(
new int[ARRsize], 0, ARRsize,
true);
405 auto rLIDs = Teuchos::arcp(
new LocalOrdinal[ARRsize], 0, ARRsize,
true);
408 for (
auto itr = AllReverseRecv.begin(); itr != newEndOfPairs; ++itr) {
409 if ((
int)(itr->first) != MyPID) {
410 rPIDs[tsize] = (int)itr->first;
411 LocalOrdinal lid = MyDomainMap->getLocalElement(itr->second);
417 type3PIDs = rPIDs.persistingView(0, tsize);
418 type3LIDs = rLIDs.persistingView(0, tsize);
421 std::cerr << errstr.str() << std::flush;
425 MPI_Abort(MPI_COMM_WORLD, -1);
431template <
typename Scalar,
typename Ordinal>
433 const Teuchos::ArrayView<Ordinal>& CRS_colind,
434 const Teuchos::ArrayView<Scalar>& CRS_vals) {
435 auto rowptr_k = Kokkos::View<size_t*, Kokkos::HostSpace, Kokkos::MemoryUnmanaged>(CRS_rowptr.data(), CRS_rowptr.size());
436 auto colind_k = Kokkos::View<Ordinal*, Kokkos::HostSpace, Kokkos::MemoryUnmanaged>(CRS_colind.data(), CRS_colind.size());
437 auto vals_k = Kokkos::View<Scalar*, Kokkos::HostSpace, Kokkos::MemoryUnmanaged>(CRS_vals.data(), CRS_vals.size());
441template <
typename Ordinal>
442void sortCrsEntries(
const Teuchos::ArrayView<size_t>& CRS_rowptr,
443 const Teuchos::ArrayView<Ordinal>& CRS_colind) {
444 auto rowptr_k = Kokkos::View<size_t*, Kokkos::HostSpace, Kokkos::MemoryUnmanaged>(CRS_rowptr.data(), CRS_rowptr.size());
445 auto colind_k = Kokkos::View<Ordinal*, Kokkos::HostSpace, Kokkos::MemoryUnmanaged>(CRS_colind.data(), CRS_colind.size());
446 sortCrsEntries(rowptr_k, colind_k);
449template <
typename rowptr_array_type,
typename colind_array_type,
typename vals_array_type>
450void sortCrsEntries(
const rowptr_array_type& CRS_rowptr,
451 const colind_array_type& CRS_colind,
452 const vals_array_type& CRS_vals) {
453 KokkosSparse::sort_crs_matrix(CRS_rowptr, CRS_colind, CRS_vals);
456template <
typename rowptr_array_type,
typename colind_array_type>
458 const colind_array_type& CRS_colind) {
459 KokkosSparse::sort_crs_graph(CRS_rowptr, CRS_colind);
463template <
typename Scalar,
typename Ordinal>
465 const Teuchos::ArrayView<Ordinal>& CRS_colind,
466 const Teuchos::ArrayView<Scalar>& CRS_vals) {
472 if (CRS_rowptr.size() == 0) {
475 const size_t NumRows = CRS_rowptr.size() - 1;
476 const size_t nnz = CRS_colind.size();
477 size_t new_curr = CRS_rowptr[0];
478 size_t old_curr = CRS_rowptr[0];
480 const bool permute_values_array = CRS_vals.size() > 0;
482 for (
size_t i = 0; i < NumRows; i++) {
483 const size_t old_rowptr_i = CRS_rowptr[i];
484 CRS_rowptr[i] = old_curr;
485 if (old_rowptr_i >= nnz)
continue;
487 size_t NumEntries = CRS_rowptr[i + 1] - old_rowptr_i;
488 Teuchos::ArrayRCP<Scalar> locValues;
489 if (permute_values_array)
490 locValues = Teuchos::arcp<Scalar>(&CRS_vals[old_rowptr_i], 0, NumEntries,
false);
491 Teuchos::ArrayRCP<Ordinal> locIndices(&CRS_colind[old_rowptr_i], 0, NumEntries,
false);
494 Ordinal n = NumEntries;
499 for (Ordinal j = 0; j < max; j++) {
500 for (Ordinal k = j; k >= 0; k -= m) {
501 if (locIndices[k + m] >= locIndices[k])
503 if (permute_values_array) {
504 Scalar dtemp = locValues[k + m];
505 locValues[k + m] = locValues[k];
506 locValues[k] = dtemp;
508 Ordinal itemp = locIndices[k + m];
509 locIndices[k + m] = locIndices[k];
510 locIndices[k] = itemp;
517 for (
size_t j = old_rowptr_i; j < CRS_rowptr[i + 1]; j++) {
518 if (j > old_rowptr_i && CRS_colind[j] == CRS_colind[new_curr - 1]) {
519 if (permute_values_array) CRS_vals[new_curr - 1] += CRS_vals[j];
520 }
else if (new_curr == j) {
523 CRS_colind[new_curr] = CRS_colind[j];
524 if (permute_values_array) CRS_vals[new_curr] = CRS_vals[j];
531 CRS_rowptr[NumRows] = new_curr;
534template <
typename Ordinal>
535void sortAndMergeCrsEntries(
const Teuchos::ArrayView<size_t>& CRS_rowptr,
536 const Teuchos::ArrayView<Ordinal>& CRS_colind) {
537 Teuchos::ArrayView<Tpetra::Details::DefaultTypes::scalar_type> CRS_vals;
538 return sortAndMergeCrsEntries<Tpetra::Details::DefaultTypes::scalar_type, Ordinal>(CRS_rowptr, CRS_colind, CRS_vals);
541template <
class rowptr_view_type,
class colind_view_type,
class vals_view_type>
542void sortAndMergeCrsEntries(rowptr_view_type& CRS_rowptr,
543 colind_view_type& CRS_colind,
544 vals_view_type& CRS_vals) {
545 using execution_space =
typename vals_view_type::execution_space;
547 auto CRS_rowptr_in = CRS_rowptr;
548 auto CRS_colind_in = CRS_colind;
549 auto CRS_vals_in = CRS_vals;
551 KokkosSparse::sort_and_merge_matrix<execution_space, rowptr_view_type,
552 colind_view_type, vals_view_type>(CRS_rowptr_in, CRS_colind_in, CRS_vals_in,
553 CRS_rowptr, CRS_colind, CRS_vals);
556template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
557void lowCommunicationMakeColMapAndReindexSerial(
const Teuchos::ArrayView<const size_t>& rowptr,
558 const Teuchos::ArrayView<LocalOrdinal>& colind_LID,
559 const Teuchos::ArrayView<GlobalOrdinal>& colind_GID,
560 const Teuchos::RCP<
const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node>>& domainMapRCP,
561 const Teuchos::ArrayView<const int>& owningPIDs,
562 Teuchos::Array<int>& remotePIDs,
563 Teuchos::RCP<
const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node>>& colMap) {
565 typedef LocalOrdinal LO;
566 typedef GlobalOrdinal GO;
568 typedef Tpetra::Map<LO, GO, Node> map_type;
569 const char prefix[] =
"lowCommunicationMakeColMapAndReindexSerial: ";
573 const map_type& domainMap = *domainMapRCP;
578 const size_t numDomainElements = domainMap.getLocalNumElements();
579 Teuchos::Array<bool> LocalGIDs;
580 if (numDomainElements > 0) {
581 LocalGIDs.resize(numDomainElements,
false);
592 const size_t numMyRows = rowptr.size() - 1;
593 const int hashsize = std::max(
static_cast<int>(numMyRows), 100);
595 Tpetra::Details::HashTable<GO, LO> RemoteGIDs(hashsize);
596 Teuchos::Array<GO> RemoteGIDList;
597 RemoteGIDList.reserve(hashsize);
598 Teuchos::Array<int> PIDList;
599 PIDList.reserve(hashsize);
610 size_t NumLocalColGIDs = 0;
611 LO NumRemoteColGIDs = 0;
612 for (
size_t i = 0; i < numMyRows; ++i) {
613 for (
size_t j = rowptr[i]; j < rowptr[i + 1]; ++j) {
614 const GO GID = colind_GID[j];
616 const LO LID = domainMap.getLocalElement(GID);
618 const bool alreadyFound = LocalGIDs[LID];
620 LocalGIDs[LID] =
true;
625 const LO hash_value = RemoteGIDs.get(GID);
626 if (hash_value == -1) {
627 const int PID = owningPIDs[j];
628 TEUCHOS_TEST_FOR_EXCEPTION(
629 PID == -1, std::invalid_argument, prefix <<
"Cannot figure out if "
631 colind_LID[j] =
static_cast<LO
>(numDomainElements + NumRemoteColGIDs);
632 RemoteGIDs.add(GID, NumRemoteColGIDs);
633 RemoteGIDList.push_back(GID);
634 PIDList.push_back(PID);
637 colind_LID[j] =
static_cast<LO
>(numDomainElements + hash_value);
645 if (domainMap.getComm()->getSize() == 1) {
648 TEUCHOS_TEST_FOR_EXCEPTION(
649 NumRemoteColGIDs != 0, std::runtime_error, prefix <<
"There is only one "
650 "process in the domain Map's communicator, which means that there are no "
651 "\"remote\" indices. Nevertheless, some column indices are not in the "
653 if (
static_cast<size_t>(NumLocalColGIDs) == numDomainElements) {
657 colMap = domainMapRCP;
664 const LO numMyCols = NumLocalColGIDs + NumRemoteColGIDs;
665 Teuchos::Array<GO> ColIndices;
666 GO* RemoteColIndices = NULL;
668 ColIndices.resize(numMyCols);
669 if (NumLocalColGIDs !=
static_cast<size_t>(numMyCols)) {
670 RemoteColIndices = &ColIndices[NumLocalColGIDs];
674 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
675 RemoteColIndices[i] = RemoteGIDList[i];
679 Teuchos::Array<LO> RemotePermuteIDs(NumRemoteColGIDs);
680 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
681 RemotePermuteIDs[i] = i;
688 ColIndices.begin() + NumLocalColGIDs,
689 RemotePermuteIDs.begin());
695 remotePIDs = PIDList;
704 LO StartCurrent = 0, StartNext = 1;
705 while (StartNext < NumRemoteColGIDs) {
706 if (PIDList[StartNext] == PIDList[StartNext - 1]) {
709 Tpetra::sort2(ColIndices.begin() + NumLocalColGIDs + StartCurrent,
710 ColIndices.begin() + NumLocalColGIDs + StartNext,
711 RemotePermuteIDs.begin() + StartCurrent);
712 StartCurrent = StartNext;
716 Tpetra::sort2(ColIndices.begin() + NumLocalColGIDs + StartCurrent,
717 ColIndices.begin() + NumLocalColGIDs + StartNext,
718 RemotePermuteIDs.begin() + StartCurrent);
721 Teuchos::Array<LO> ReverseRemotePermuteIDs(NumRemoteColGIDs);
722 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
723 ReverseRemotePermuteIDs[RemotePermuteIDs[i]] = i;
727 bool use_local_permute =
false;
728 Teuchos::Array<LO> LocalPermuteIDs(numDomainElements);
740 Teuchos::ArrayView<const GO> domainGlobalElements = domainMap.getLocalElementList();
741 if (
static_cast<size_t>(NumLocalColGIDs) == numDomainElements) {
742 if (NumLocalColGIDs > 0) {
744 std::copy(domainGlobalElements.begin(), domainGlobalElements.end(),
748 LO NumLocalAgain = 0;
749 use_local_permute =
true;
750 for (
size_t i = 0; i < numDomainElements; ++i) {
752 LocalPermuteIDs[i] = NumLocalAgain;
753 ColIndices[NumLocalAgain++] = domainGlobalElements[i];
756 TEUCHOS_TEST_FOR_EXCEPTION(
757 static_cast<size_t>(NumLocalAgain) != NumLocalColGIDs,
758 std::runtime_error, prefix <<
"Local ID count test failed.");
762 const GST minus_one = Teuchos::OrdinalTraits<GST>::invalid();
763 colMap = rcp(
new map_type(minus_one, ColIndices, domainMap.getIndexBase(),
764 domainMap.getComm()));
767 for (
size_t i = 0; i < numMyRows; ++i) {
768 for (
size_t j = rowptr[i]; j < rowptr[i + 1]; ++j) {
769 const LO ID = colind_LID[j];
770 if (
static_cast<size_t>(ID) < numDomainElements) {
771 if (use_local_permute) {
772 colind_LID[j] = LocalPermuteIDs[colind_LID[j]];
778 colind_LID[j] = NumLocalColGIDs + ReverseRemotePermuteIDs[colind_LID[j] - numDomainElements];
784template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
786 const Teuchos::ArrayView<const size_t>& rowptr,
787 const Teuchos::ArrayView<LocalOrdinal>& colind_LID,
788 const Teuchos::ArrayView<GlobalOrdinal>& colind_GID,
790 const Teuchos::ArrayView<const int>& owningPIDs,
791 Teuchos::Array<int>& remotePIDs,
794 typedef LocalOrdinal LO;
795 typedef GlobalOrdinal GO;
798 const char prefix[] =
"lowCommunicationMakeColMapAndReindex: ";
800 typedef typename Node::device_type DT;
803 using team_policy = Kokkos::TeamPolicy<execution_space, Kokkos::Schedule<Kokkos::Dynamic>>;
804 typedef typename map_type::local_map_type local_map_type;
813 typename decltype(colind_LID_view)::host_mirror_type colind_LID_host(colind_LID.getRawPtr(), colind_LID.size());
814 typename decltype(colind_GID_view)::host_mirror_type colind_GID_host(colind_GID.getRawPtr(), colind_GID.size());
816 Kokkos::deep_copy(colind_LID_view, colind_LID_host);
817 Kokkos::deep_copy(colind_GID_view, colind_GID_host);
821 const map_type& domainMap = *domainMapRCP;
823 Kokkos::UnorderedMap<LO, bool, DT> LocalGIDs_view_map(colind_LID.size());
824 Kokkos::UnorderedMap<GO, LO, DT> RemoteGIDs_view_map(colind_LID.size());
826 const size_t numMyRows = rowptr.size() - 1;
827 local_map_type domainMap_local = domainMap.getLocalMap();
829 const size_t numDomainElements = domainMap.getLocalNumElements();
830 Kokkos::View<bool*, DT> LocalGIDs_view(
"LocalGIDs", numDomainElements);
831 auto LocalGIDs_host = Kokkos::create_mirror_view(LocalGIDs_view);
833 size_t NumLocalColGIDs = 0;
839 Kokkos::parallel_reduce(
840 team_policy(numMyRows, Kokkos::AUTO), KOKKOS_LAMBDA(
const typename team_policy::member_type& member,
size_t& update) {
841 const int i = member.league_rank();
842 size_t NumLocalColGIDs_temp = 0;
843 size_t rowptr_start = rowptr_view[i];
844 size_t rowptr_end = rowptr_view[i + 1];
845 Kokkos::parallel_reduce(
846 Kokkos::TeamThreadRange(member, rowptr_start, rowptr_end), [&](
const size_t j,
size_t& innerUpdate) {
847 const GO GID = colind_GID_view[j];
849 const LO LID = domainMap_local.getLocalElement(GID);
851 auto outcome = LocalGIDs_view_map.insert(LID);
853 if (outcome.success()) {
854 LocalGIDs_view[LID] =
true;
858 const int PID = owningPIDs_view[j];
859 auto outcome = RemoteGIDs_view_map.insert(GID, PID);
860 if (outcome.success() && PID == -1) {
861 Kokkos::abort(
"Cannot figure out if ID is owned.\n");
865 NumLocalColGIDs_temp);
866 if (member.team_rank() == 0) update += NumLocalColGIDs_temp;
870 LO NumRemoteColGIDs = RemoteGIDs_view_map.size();
872 Kokkos::View<int*, DT> PIDList_view(
"PIDList", NumRemoteColGIDs);
873 auto PIDList_host = Kokkos::create_mirror_view(PIDList_view);
875 Kokkos::View<GO*, DT> RemoteGIDList_view(
"RemoteGIDList", NumRemoteColGIDs);
876 auto RemoteGIDList_host = Kokkos::create_mirror_view(RemoteGIDList_view);
880 Kokkos::parallel_scan(
881 Kokkos::RangePolicy<execution_space>(0, RemoteGIDs_view_map.capacity()), KOKKOS_LAMBDA(
const int i, GO& update,
const bool final) {
882 if (
final && RemoteGIDs_view_map.valid_at(i)) {
883 RemoteGIDList_view[update] = RemoteGIDs_view_map.key_at(i);
884 PIDList_view[update] = RemoteGIDs_view_map.value_at(i);
886 if (RemoteGIDs_view_map.valid_at(i)) {
893 if (domainMap.
getComm()->getSize() == 1) {
896 TEUCHOS_TEST_FOR_EXCEPTION(
897 NumRemoteColGIDs != 0, std::runtime_error, prefix <<
"There is only one "
898 "process in the domain Map's communicator, which means that there are no "
899 "\"remote\" indices. Nevertheless, some column indices are not in the "
901 if (
static_cast<size_t>(NumLocalColGIDs) == numDomainElements) {
905 colMap = domainMapRCP;
908 auto localColMap = colMap->getLocalMap();
909 Kokkos::parallel_for(
910 Kokkos::RangePolicy<execution_space>(0, colind_GID.size()), KOKKOS_LAMBDA(
const int i) {
911 colind_LID_view[i] = localColMap.getLocalElement(colind_GID_view[i]);
913 Kokkos::deep_copy(
execution_space(), colind_LID_host, colind_LID_view);
920 const LO numMyCols = NumLocalColGIDs + NumRemoteColGIDs;
921 Kokkos::View<GO*, DT> ColIndices_view(
"ColIndices", numMyCols);
924 if (NumRemoteColGIDs > 0) {
925 if (NumLocalColGIDs !=
static_cast<size_t>(numMyCols)) {
926 Kokkos::parallel_for(
927 Kokkos::RangePolicy<execution_space>(0, NumRemoteColGIDs), KOKKOS_LAMBDA(
const int i) {
928 ColIndices_view[NumLocalColGIDs + i] = RemoteGIDList_view[i];
934 Kokkos::parallel_reduce(
935 Kokkos::RangePolicy<execution_space>(0, PIDList_host.size()), KOKKOS_LAMBDA(
const int i,
int& max) {
936 if (max < PIDList_view[i]) max = PIDList_view[i];
938 Kokkos::Max<int>(PID_max));
940 using KeyViewTypePID =
decltype(PIDList_view);
941 using BinSortOpPID = Kokkos::BinOp1D<KeyViewTypePID>;
944 auto ColIndices_subview = Kokkos::subview(ColIndices_view, Kokkos::make_pair(NumLocalColGIDs, ColIndices_view.size()));
947 BinSortOpPID binOp2(PID_max + 1, 0, PID_max);
952 Kokkos::BinSort<KeyViewTypePID, BinSortOpPID> bin_sort2(PIDList_view, 0, PIDList_view.size(), binOp2,
false);
953 bin_sort2.create_permute_vector(exec);
954 bin_sort2.sort(exec, PIDList_view);
955 bin_sort2.sort(exec, ColIndices_subview);
958 Kokkos::deep_copy(exec, PIDList_host, PIDList_view);
964 exec.fence(
"fence before setting PIDList");
965 Teuchos::Array<int> PIDList(NumRemoteColGIDs);
966 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
967 PIDList[i] = PIDList_host[i];
970 remotePIDs = PIDList;
977 LO StartCurrent = 0, StartNext = 1;
978 while (StartNext < NumRemoteColGIDs) {
979 if (PIDList_host[StartNext] == PIDList_host[StartNext - 1]) {
982 Kokkos::sort(ColIndices_view, NumLocalColGIDs + StartCurrent, NumLocalColGIDs + StartNext);
983 StartCurrent = StartNext;
988 Kokkos::sort(ColIndices_view, NumLocalColGIDs + StartCurrent, NumLocalColGIDs + StartNext);
1003 if (
static_cast<size_t>(NumLocalColGIDs) == numDomainElements) {
1004 if (NumLocalColGIDs > 0) {
1006 Kokkos::parallel_for(
1007 Kokkos::RangePolicy<execution_space>(0, numDomainElements), KOKKOS_LAMBDA(
const int i) {
1008 ColIndices_view[i] = domainMap_local.getGlobalElement(i);
1013 LO NumLocalAgain = 0;
1014 Kokkos::parallel_scan(
1015 Kokkos::RangePolicy<execution_space>(0, numDomainElements), KOKKOS_LAMBDA(
const int i, LO& update,
const bool final) {
1016 if (
final && LocalGIDs_view[i]) {
1017 ColIndices_view[update] = domainMap_local.getGlobalElement(i);
1019 if (LocalGIDs_view[i]) {
1025 TEUCHOS_TEST_FOR_EXCEPTION(
1026 static_cast<size_t>(NumLocalAgain) != NumLocalColGIDs,
1027 std::runtime_error, prefix <<
"Local ID count test failed.");
1031 const GST minus_one = Teuchos::OrdinalTraits<GST>::invalid();
1037 auto localColMap = colMap->getLocalMap();
1038 Kokkos::parallel_for(
1039 Kokkos::RangePolicy<execution_space>(0, colind_GID.size()), KOKKOS_LAMBDA(
const int i) {
1040 colind_LID_view[i] = localColMap.getLocalElement(colind_GID_view[i]);
1045 Kokkos::deep_copy(exec, colind_LID_host, colind_LID_view);
1048template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
1049void lowCommunicationMakeColMapAndReindex(
1050 const Kokkos::View<size_t*, typename Node::device_type> rowptr_view,
1051 const Kokkos::View<LocalOrdinal*, typename Node::device_type> colind_LID_view,
1052 const Kokkos::View<GlobalOrdinal*, typename Node::device_type> colind_GID_view,
1054 const Kokkos::View<int*, typename Node::device_type> owningPIDs_view,
1055 Teuchos::Array<int>& remotePIDs,
1058 typedef LocalOrdinal LO;
1059 typedef GlobalOrdinal GO;
1062 const char prefix[] =
"lowCommunicationMakeColMapAndReindex: ";
1064 typedef typename Node::device_type DT;
1067 using team_policy = Kokkos::TeamPolicy<execution_space, Kokkos::Schedule<Kokkos::Dynamic>>;
1068 typedef typename map_type::local_map_type local_map_type;
1072 const map_type& domainMap = *domainMapRCP;
1074 Kokkos::UnorderedMap<LO, bool, DT> LocalGIDs_view_map(colind_LID_view.size());
1075 Kokkos::UnorderedMap<GO, LO, DT> RemoteGIDs_view_map(colind_LID_view.size());
1077 const size_t numMyRows = rowptr_view.size() - 1;
1078 local_map_type domainMap_local = domainMap.getLocalMap();
1080 const size_t numDomainElements = domainMap.getLocalNumElements();
1081 Kokkos::View<bool*, DT> LocalGIDs_view(
"LocalGIDs", numDomainElements);
1082 auto LocalGIDs_host = Kokkos::create_mirror_view(LocalGIDs_view);
1084 size_t NumLocalColGIDs = 0;
1090 Kokkos::parallel_reduce(
1091 team_policy(numMyRows, Kokkos::AUTO), KOKKOS_LAMBDA(
const typename team_policy::member_type& member,
size_t& update) {
1092 const int i = member.league_rank();
1093 size_t NumLocalColGIDs_temp = 0;
1094 size_t rowptr_start = rowptr_view[i];
1095 size_t rowptr_end = rowptr_view[i + 1];
1096 Kokkos::parallel_reduce(
1097 Kokkos::TeamThreadRange(member, rowptr_start, rowptr_end), [&](
const size_t j,
size_t& innerUpdate) {
1098 const GO GID = colind_GID_view[j];
1100 const LO LID = domainMap_local.getLocalElement(GID);
1102 auto outcome = LocalGIDs_view_map.insert(LID);
1104 if (outcome.success()) {
1105 LocalGIDs_view[LID] =
true;
1109 const int PID = owningPIDs_view[j];
1110 auto outcome = RemoteGIDs_view_map.insert(GID, PID);
1111 if (outcome.success() && PID == -1) {
1112 Kokkos::abort(
"Cannot figure out if ID is owned.\n");
1116 NumLocalColGIDs_temp);
1117 if (member.team_rank() == 0) update += NumLocalColGIDs_temp;
1121 LO NumRemoteColGIDs = RemoteGIDs_view_map.size();
1123 Kokkos::View<int*, DT> PIDList_view(
"PIDList_d", NumRemoteColGIDs);
1125 Kokkos::View<GO*, DT> RemoteGIDList_view(
"RemoteGIDList", NumRemoteColGIDs);
1126 auto RemoteGIDList_host = Kokkos::create_mirror_view(RemoteGIDList_view);
1130 Kokkos::parallel_scan(
1131 Kokkos::RangePolicy<execution_space>(0, RemoteGIDs_view_map.capacity()), KOKKOS_LAMBDA(
const int i, GO& update,
const bool final) {
1132 if (
final && RemoteGIDs_view_map.valid_at(i)) {
1133 RemoteGIDList_view[update] = RemoteGIDs_view_map.key_at(i);
1134 PIDList_view[update] = RemoteGIDs_view_map.value_at(i);
1136 if (RemoteGIDs_view_map.valid_at(i)) {
1143 if (domainMap.
getComm()->getSize() == 1) {
1146 TEUCHOS_TEST_FOR_EXCEPTION(
1147 NumRemoteColGIDs != 0, std::runtime_error, prefix <<
"There is only one "
1148 "process in the domain Map's communicator, which means that there are no "
1149 "\"remote\" indices. Nevertheless, some column indices are not in the "
1151 if (
static_cast<size_t>(NumLocalColGIDs) == numDomainElements) {
1155 colMap = domainMapRCP;
1158 auto localColMap = colMap->getLocalMap();
1159 Kokkos::parallel_for(
1160 Kokkos::RangePolicy<execution_space>(0, colind_GID_view.size()), KOKKOS_LAMBDA(
const int i) {
1161 colind_LID_view[i] = localColMap.getLocalElement(colind_GID_view[i]);
1169 const LO numMyCols = NumLocalColGIDs + NumRemoteColGIDs;
1170 Kokkos::View<GO*, DT> ColIndices_view(
"ColIndices", numMyCols);
1173 if (NumRemoteColGIDs > 0) {
1174 if (NumLocalColGIDs !=
static_cast<size_t>(numMyCols)) {
1175 Kokkos::parallel_for(
1176 Kokkos::RangePolicy<execution_space>(0, NumRemoteColGIDs), KOKKOS_LAMBDA(
const int i) {
1177 ColIndices_view[NumLocalColGIDs + i] = RemoteGIDList_view[i];
1183 Kokkos::parallel_reduce(
1184 Kokkos::RangePolicy<execution_space>(0, PIDList_view.size()), KOKKOS_LAMBDA(
const int i,
int& max) {
1185 if (max < PIDList_view[i]) max = PIDList_view[i];
1187 Kokkos::Max<int>(PID_max));
1189 using KeyViewTypePID =
decltype(PIDList_view);
1190 using BinSortOpPID = Kokkos::BinOp1D<KeyViewTypePID>;
1193 auto ColIndices_subview = Kokkos::subview(ColIndices_view, Kokkos::make_pair(NumLocalColGIDs, ColIndices_view.size()));
1196 BinSortOpPID binOp2(PID_max + 1, 0, PID_max);
1201 Kokkos::BinSort<KeyViewTypePID, BinSortOpPID> bin_sort2(PIDList_view, 0, PIDList_view.size(), binOp2,
false);
1202 bin_sort2.create_permute_vector(exec);
1203 bin_sort2.sort(exec, PIDList_view);
1204 bin_sort2.sort(exec, ColIndices_subview);
1208 Teuchos::Array<int> PIDList(NumRemoteColGIDs);
1209 Kokkos::View<int*, Kokkos::HostSpace> PIDList_host(PIDList.data(), PIDList.size());
1210 Kokkos::deep_copy(exec, PIDList_host, PIDList_view);
1213 remotePIDs = PIDList;
1220 LO StartCurrent = 0, StartNext = 1;
1221 while (StartNext < NumRemoteColGIDs) {
1222 if (PIDList_host[StartNext] == PIDList_host[StartNext - 1]) {
1225 Kokkos::sort(ColIndices_view, NumLocalColGIDs + StartCurrent, NumLocalColGIDs + StartNext);
1226 StartCurrent = StartNext;
1231 Kokkos::sort(ColIndices_view, NumLocalColGIDs + StartCurrent, NumLocalColGIDs + StartNext);
1246 if (
static_cast<size_t>(NumLocalColGIDs) == numDomainElements) {
1247 if (NumLocalColGIDs > 0) {
1249 Kokkos::parallel_for(
1250 Kokkos::RangePolicy<execution_space>(0, numDomainElements), KOKKOS_LAMBDA(
const int i) {
1251 ColIndices_view[i] = domainMap_local.getGlobalElement(i);
1256 LO NumLocalAgain = 0;
1257 Kokkos::parallel_scan(
1258 Kokkos::RangePolicy<execution_space>(0, numDomainElements), KOKKOS_LAMBDA(
const int i, LO& update,
const bool final) {
1259 if (
final && LocalGIDs_view[i]) {
1260 ColIndices_view[update] = domainMap_local.getGlobalElement(i);
1262 if (LocalGIDs_view[i]) {
1268 TEUCHOS_TEST_FOR_EXCEPTION(
1269 static_cast<size_t>(NumLocalAgain) != NumLocalColGIDs,
1270 std::runtime_error, prefix <<
"Local ID count test failed.");
1274 const GST minus_one = Teuchos::OrdinalTraits<GST>::invalid();
1276 colMap = rcp(
new map_type(minus_one, ColIndices_view, domainMap.
getIndexBase(),
1280 auto localColMap = colMap->getLocalMap();
1281 Kokkos::parallel_for(
1282 Kokkos::RangePolicy<execution_space>(0, colind_GID_view.size()), KOKKOS_LAMBDA(
const int i) {
1283 colind_LID_view[i] = localColMap.getLocalElement(colind_GID_view[i]);
1300template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
1302 bool useReverseModeForOwnership,
1303 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& transferThatDefinesMigration,
1304 bool useReverseModeForMigration,
1309 Teuchos::RCP<const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> OwningMap = useReverseModeForOwnership ? transferThatDefinesOwnership.getTargetMap() : transferThatDefinesOwnership.getSourceMap();
1310 Teuchos::RCP<const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> MapAo = useReverseModeForOwnership ? transferThatDefinesOwnership.getSourceMap() : transferThatDefinesOwnership.getTargetMap();
1311 Teuchos::RCP<const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> MapAm = useReverseModeForMigration ? transferThatDefinesMigration.getTargetMap() : transferThatDefinesMigration.getSourceMap();
1312 Teuchos::RCP<const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node>> VectorMap = useReverseModeForMigration ? transferThatDefinesMigration.getSourceMap() : transferThatDefinesMigration.getTargetMap();
1314 TEUCHOS_TEST_FOR_EXCEPTION(!MapAo->isSameAs(*MapAm), std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector map mismatch between transfers");
1315 TEUCHOS_TEST_FOR_EXCEPTION(!VectorMap->isSameAs(*owningPIDs.
getMap()), std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector map mismatch transfer and vector");
1316#ifdef HAVE_TPETRA_DEBUG
1317 TEUCHOS_TEST_FOR_EXCEPTION(!OwningMap->isOneToOne(), std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");
1320 int rank = OwningMap->getComm()->getRank();
1328 Teuchos::ArrayView<int> v_pids = pids();
1329 if (ownAsImport && useReverseModeForOwnership) {
1330 TEUCHOS_TEST_FOR_EXCEPTION(1, std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");
1331 }
else if (ownAsImport && !useReverseModeForOwnership)
1332 getPids(*ownAsImport, v_pids,
false);
1333 else if (ownAsExport && useReverseModeForMigration) {
1334 TEUCHOS_TEST_FOR_EXCEPTION(1, std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector this option not yet implemented");
1336 TEUCHOS_TEST_FOR_EXCEPTION(1, std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");
1341 TEUCHOS_TEST_FOR_EXCEPTION(!xferAsImport && !xferAsExport, std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector transfer undefined");
1345 if (xferAsImport && useReverseModeForMigration)
1347 else if (xferAsImport && !useReverseModeForMigration)
1349 else if (xferAsExport && useReverseModeForMigration)
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.
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.
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.
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.