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" 57 #include "Tpetra_Vector.hpp" 58 #include "Kokkos_DualView.hpp" 59 #include <Teuchos_Array.hpp> 63 namespace Import_Util {
67 template<
typename Scalar,
typename Ordinal>
70 const Teuchos::ArrayView<Ordinal>& CRS_colind,
71 const Teuchos::ArrayView<Scalar>&CRS_vals);
73 template<
typename Ordinal>
76 const Teuchos::ArrayView<Ordinal>& CRS_colind);
78 template<
typename rowptr_array_type,
typename colind_array_type,
typename vals_array_type>
81 const colind_array_type& CRS_colind,
82 const vals_array_type& CRS_vals);
84 template<
typename rowptr_array_type,
typename colind_array_type>
87 const colind_array_type& CRS_colind);
93 template<
typename Scalar,
typename Ordinal>
96 const Teuchos::ArrayView<Ordinal>& CRS_colind,
97 const Teuchos::ArrayView<Scalar>& CRS_vals);
99 template<
typename Ordinal>
102 const Teuchos::ArrayView<Ordinal>& CRS_colind);
119 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
122 const Teuchos::ArrayView<LocalOrdinal> &columnIndices_LID,
123 const Teuchos::ArrayView<GlobalOrdinal> &columnIndices_GID,
125 const Teuchos::ArrayView<const int> &owningPids,
126 Teuchos::Array<int> &remotePids,
145 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
147 bool useReverseModeForOwnership,
148 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& transferForMigratingData,
149 bool useReverseModeForMigration,
161 namespace Import_Util {
164 template<
typename Scalar,
typename Ordinal>
167 const Teuchos::ArrayView<Ordinal> & CRS_colind,
168 const Teuchos::ArrayView<Scalar> &CRS_vals)
173 size_t NumRows = CRS_rowptr.size()-1;
174 size_t nnz = CRS_colind.size();
176 const bool permute_values_array = CRS_vals.size() > 0;
178 for(
size_t i = 0; i < NumRows; i++){
179 size_t start=CRS_rowptr[i];
180 if(start >= nnz)
continue;
182 size_t NumEntries = CRS_rowptr[i+1] - start;
183 Teuchos::ArrayRCP<Scalar> locValues;
184 if (permute_values_array)
185 locValues = Teuchos::arcp<Scalar>(&CRS_vals[start], 0, NumEntries,
false);
186 Teuchos::ArrayRCP<Ordinal> locIndices(&CRS_colind[start], 0, NumEntries,
false);
188 Ordinal n = NumEntries;
190 while (m<n) m = m*3+1;
195 for(Ordinal j = 0; j < max; j++) {
196 for(Ordinal k = j; k >= 0; k-=m) {
197 if(locIndices[k+m] >= locIndices[k])
199 if (permute_values_array) {
200 Scalar dtemp = locValues[k+m];
201 locValues[k+m] = locValues[k];
202 locValues[k] = dtemp;
204 Ordinal itemp = locIndices[k+m];
205 locIndices[k+m] = locIndices[k];
206 locIndices[k] = itemp;
214 template<
typename Ordinal>
217 const Teuchos::ArrayView<Ordinal> & CRS_colind)
220 Teuchos::ArrayView<Tpetra::Details::DefaultTypes::scalar_type> CRS_vals;
226 template<
class RowOffsetsType,
class ColumnIndicesType,
class ValuesType>
227 class SortCrsEntries {
229 typedef typename ColumnIndicesType::non_const_value_type ordinal_type;
230 typedef typename ValuesType::non_const_value_type scalar_type;
233 SortCrsEntries (
const RowOffsetsType& ptr,
234 const ColumnIndicesType& ind,
235 const ValuesType& val) :
240 static_assert (std::is_signed<ordinal_type>::value,
"The type of each " 241 "column index -- that is, the type of each entry of ind " 242 "-- must be signed in order for this functor to work.");
245 KOKKOS_FUNCTION
void operator() (
const size_t i)
const 247 const size_t nnz = ind_.extent (0);
248 const size_t start = ptr_(i);
249 const bool permute_values_array = val_.extent(0) > 0;
252 const size_t NumEntries = ptr_(i+1) - start;
254 const ordinal_type n =
static_cast<ordinal_type
> (NumEntries);
256 while (m<n) m = m*3+1;
260 ordinal_type max = n - m;
261 for (ordinal_type j = 0; j < max; j++) {
262 for (ordinal_type k = j; k >= 0; k -= m) {
263 const size_t sk = start+k;
264 if (ind_(sk+m) >= ind_(sk)) {
267 if (permute_values_array) {
268 const scalar_type dtemp = val_(sk+m);
269 val_(sk+m) = val_(sk);
272 const ordinal_type itemp = ind_(sk+m);
273 ind_(sk+m) = ind_(sk);
284 const ColumnIndicesType& ind,
285 const ValuesType& val)
292 if (ptr.extent (0) == 0) {
295 const size_t NumRows = ptr.extent (0) - 1;
297 typedef size_t index_type;
298 typedef typename ValuesType::execution_space execution_space;
301 typedef Kokkos::RangePolicy<execution_space, index_type> range_type;
302 Kokkos::parallel_for (
"sortCrsEntries", range_type (0, NumRows),
303 SortCrsEntries (ptr, ind, val));
308 ColumnIndicesType ind_;
314 template<
typename rowptr_array_type,
typename colind_array_type,
typename vals_array_type>
317 const colind_array_type& CRS_colind,
318 const vals_array_type& CRS_vals)
320 Impl::SortCrsEntries<rowptr_array_type, colind_array_type,
321 vals_array_type>::sortCrsEntries (CRS_rowptr, CRS_colind, CRS_vals);
324 template<
typename rowptr_array_type,
typename colind_array_type>
327 const colind_array_type& CRS_colind)
330 typedef typename colind_array_type::execution_space execution_space;
331 typedef Tpetra::Details::DefaultTypes::scalar_type scalar_type;
332 typedef typename Kokkos::View<scalar_type*, execution_space> scalar_view_type;
333 scalar_view_type CRS_vals;
335 scalar_view_type>(CRS_rowptr, CRS_colind, CRS_vals);
339 template<
typename Scalar,
typename Ordinal>
342 const Teuchos::ArrayView<Ordinal> & CRS_colind,
343 const Teuchos::ArrayView<Scalar> &CRS_vals)
350 if (CRS_rowptr.size () == 0) {
353 const size_t NumRows = CRS_rowptr.size () - 1;
354 const size_t nnz = CRS_colind.size ();
355 size_t new_curr = CRS_rowptr[0];
356 size_t old_curr = CRS_rowptr[0];
358 const bool permute_values_array = CRS_vals.size() > 0;
360 for(
size_t i = 0; i < NumRows; i++){
361 const size_t old_rowptr_i=CRS_rowptr[i];
362 CRS_rowptr[i] = old_curr;
363 if(old_rowptr_i >= nnz)
continue;
365 size_t NumEntries = CRS_rowptr[i+1] - old_rowptr_i;
366 Teuchos::ArrayRCP<Scalar> locValues;
367 if (permute_values_array)
368 locValues = Teuchos::arcp<Scalar>(&CRS_vals[old_rowptr_i], 0, NumEntries,
false);
369 Teuchos::ArrayRCP<Ordinal> locIndices(&CRS_colind[old_rowptr_i], 0, NumEntries,
false);
372 Ordinal n = NumEntries;
377 for(Ordinal j = 0; j < max; j++) {
378 for(Ordinal k = j; k >= 0; k-=m) {
379 if(locIndices[k+m] >= locIndices[k])
381 if (permute_values_array) {
382 Scalar dtemp = locValues[k+m];
383 locValues[k+m] = locValues[k];
384 locValues[k] = dtemp;
386 Ordinal itemp = locIndices[k+m];
387 locIndices[k+m] = locIndices[k];
388 locIndices[k] = itemp;
395 for(
size_t j=old_rowptr_i; j < CRS_rowptr[i+1]; j++) {
396 if(j > old_rowptr_i && CRS_colind[j]==CRS_colind[new_curr-1]) {
397 if (permute_values_array) CRS_vals[new_curr-1] += CRS_vals[j];
399 else if(new_curr==j) {
403 CRS_colind[new_curr] = CRS_colind[j];
404 if (permute_values_array) CRS_vals[new_curr] = CRS_vals[j];
411 CRS_rowptr[NumRows] = new_curr;
414 template<
typename Ordinal>
417 const Teuchos::ArrayView<Ordinal> & CRS_colind)
419 Teuchos::ArrayView<Tpetra::Details::DefaultTypes::scalar_type> CRS_vals;
424 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
427 const Teuchos::ArrayView<LocalOrdinal> &colind_LID,
428 const Teuchos::ArrayView<GlobalOrdinal> &colind_GID,
430 const Teuchos::ArrayView<const int> &owningPIDs,
431 Teuchos::Array<int> &remotePIDs,
435 typedef LocalOrdinal LO;
436 typedef GlobalOrdinal GO;
439 const char prefix[] =
"lowCommunicationMakeColMapAndReindex: ";
443 const map_type& domainMap = *domainMapRCP;
449 Teuchos::Array<bool> LocalGIDs;
450 if (numDomainElements > 0) {
451 LocalGIDs.resize (numDomainElements,
false);
462 const size_t numMyRows = rowptr.size () - 1;
463 const int hashsize = std::max (static_cast<int> (numMyRows), 100);
466 Teuchos::Array<GO> RemoteGIDList;
467 RemoteGIDList.reserve (hashsize);
468 Teuchos::Array<int> PIDList;
469 PIDList.reserve (hashsize);
480 size_t NumLocalColGIDs = 0;
481 LO NumRemoteColGIDs = 0;
482 for (
size_t i = 0; i < numMyRows; ++i) {
483 for(
size_t j = rowptr[i]; j < rowptr[i+1]; ++j) {
484 const GO GID = colind_GID[j];
486 const LO LID = domainMap.getLocalElement (GID);
488 const bool alreadyFound = LocalGIDs[LID];
489 if (! alreadyFound) {
490 LocalGIDs[LID] =
true;
496 const LO hash_value = RemoteGIDs.
get (GID);
497 if (hash_value == -1) {
498 const int PID = owningPIDs[j];
499 TEUCHOS_TEST_FOR_EXCEPTION(
500 PID == -1, std::invalid_argument, prefix <<
"Cannot figure out if " 502 colind_LID[j] =
static_cast<LO
> (numDomainElements + NumRemoteColGIDs);
503 RemoteGIDs.
add (GID, NumRemoteColGIDs);
504 RemoteGIDList.push_back (GID);
505 PIDList.push_back (PID);
509 colind_LID[j] =
static_cast<LO
> (numDomainElements + hash_value);
517 if (domainMap.getComm ()->getSize () == 1) {
520 TEUCHOS_TEST_FOR_EXCEPTION(
521 NumRemoteColGIDs != 0, std::runtime_error, prefix <<
"There is only one " 522 "process in the domain Map's communicator, which means that there are no " 523 "\"remote\" indices. Nevertheless, some column indices are not in the " 525 if (static_cast<size_t> (NumLocalColGIDs) == numDomainElements) {
529 colMap = domainMapRCP;
536 const LO numMyCols = NumLocalColGIDs + NumRemoteColGIDs;
537 Teuchos::Array<GO> ColIndices;
538 GO* RemoteColIndices = NULL;
540 ColIndices.resize (numMyCols);
541 if (NumLocalColGIDs != static_cast<size_t> (numMyCols)) {
542 RemoteColIndices = &ColIndices[NumLocalColGIDs];
546 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
547 RemoteColIndices[i] = RemoteGIDList[i];
551 Teuchos::Array<LO> RemotePermuteIDs (NumRemoteColGIDs);
552 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
553 RemotePermuteIDs[i]=i;
560 ColIndices.begin () + NumLocalColGIDs,
561 RemotePermuteIDs.begin ());
567 remotePIDs = PIDList;
576 LO StartCurrent = 0, StartNext = 1;
577 while (StartNext < NumRemoteColGIDs) {
578 if (PIDList[StartNext]==PIDList[StartNext-1]) {
582 Tpetra::sort2 (ColIndices.begin () + NumLocalColGIDs + StartCurrent,
583 ColIndices.begin () + NumLocalColGIDs + StartNext,
584 RemotePermuteIDs.begin () + StartCurrent);
585 StartCurrent = StartNext;
589 Tpetra::sort2 (ColIndices.begin () + NumLocalColGIDs + StartCurrent,
590 ColIndices.begin () + NumLocalColGIDs + StartNext,
591 RemotePermuteIDs.begin () + StartCurrent);
594 Teuchos::Array<LO> ReverseRemotePermuteIDs (NumRemoteColGIDs);
595 for (LO i = 0; i < NumRemoteColGIDs; ++i) {
596 ReverseRemotePermuteIDs[RemotePermuteIDs[i]] = i;
600 bool use_local_permute =
false;
601 Teuchos::Array<LO> LocalPermuteIDs (numDomainElements);
613 Teuchos::ArrayView<const GO> domainGlobalElements = domainMap.getNodeElementList();
614 if (static_cast<size_t> (NumLocalColGIDs) == numDomainElements) {
615 if (NumLocalColGIDs > 0) {
617 std::copy (domainGlobalElements.begin (), domainGlobalElements.end (),
618 ColIndices.begin ());
622 LO NumLocalAgain = 0;
623 use_local_permute =
true;
624 for (
size_t i = 0; i < numDomainElements; ++i) {
626 LocalPermuteIDs[i] = NumLocalAgain;
627 ColIndices[NumLocalAgain++] = domainGlobalElements[i];
630 TEUCHOS_TEST_FOR_EXCEPTION(
631 static_cast<size_t> (NumLocalAgain) != NumLocalColGIDs,
632 std::runtime_error, prefix <<
"Local ID count test failed.");
636 const GST minus_one = Teuchos::OrdinalTraits<GST>::invalid ();
637 colMap = rcp (
new map_type (minus_one, ColIndices, domainMap.getIndexBase (),
638 domainMap.getComm (), domainMap.getNode ()));
641 for (
size_t i = 0; i < numMyRows; ++i) {
642 for (
size_t j = rowptr[i]; j < rowptr[i+1]; ++j) {
643 const LO ID = colind_LID[j];
644 if (static_cast<size_t> (ID) < numDomainElements) {
645 if (use_local_permute) {
646 colind_LID[j] = LocalPermuteIDs[colind_LID[j]];
653 colind_LID[j] = NumLocalColGIDs + ReverseRemotePermuteIDs[colind_LID[j]-numDomainElements];
675 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
677 bool useReverseModeForOwnership,
678 const ::Tpetra::Details::Transfer<LocalOrdinal, GlobalOrdinal, Node>& transferThatDefinesMigration,
679 bool useReverseModeForMigration,
684 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > OwningMap = useReverseModeForOwnership ? transferThatDefinesOwnership.
getTargetMap() : transferThatDefinesOwnership.getSourceMap();
685 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > MapAo = useReverseModeForOwnership ? transferThatDefinesOwnership.getSourceMap() : transferThatDefinesOwnership.getTargetMap();
686 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > MapAm = useReverseModeForMigration ? transferThatDefinesMigration.getTargetMap() : transferThatDefinesMigration.getSourceMap();
687 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > VectorMap = useReverseModeForMigration ? transferThatDefinesMigration.getSourceMap() : transferThatDefinesMigration.getTargetMap();
689 TEUCHOS_TEST_FOR_EXCEPTION(!MapAo->isSameAs(*MapAm),std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector map mismatch between transfers");
690 TEUCHOS_TEST_FOR_EXCEPTION(!VectorMap->isSameAs(*owningPIDs.
getMap()),std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector map mismatch transfer and vector");
691 #ifdef HAVE_TPETRA_DEBUG 692 TEUCHOS_TEST_FOR_EXCEPTION(!OwningMap->isOneToOne(),std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");
695 int rank = OwningMap->getComm()->getRank();
699 const import_type* ownAsImport =
dynamic_cast<const import_type*
> (&transferThatDefinesOwnership);
700 const export_type* ownAsExport =
dynamic_cast<const export_type*
> (&transferThatDefinesOwnership);
703 Teuchos::ArrayView<int> v_pids = pids();
704 if(ownAsImport && useReverseModeForOwnership) {TEUCHOS_TEST_FOR_EXCEPTION(1,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");}
705 else if(ownAsImport && !useReverseModeForOwnership)
getPids(*ownAsImport,v_pids,
false);
706 else if(ownAsExport && useReverseModeForMigration) {TEUCHOS_TEST_FOR_EXCEPTION(1,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector this option not yet implemented");}
707 else {TEUCHOS_TEST_FOR_EXCEPTION(1,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector owner must be 1-to-1");}
709 const import_type* xferAsImport =
dynamic_cast<const import_type*
> (&transferThatDefinesMigration);
710 const export_type* xferAsExport =
dynamic_cast<const export_type*
> (&transferThatDefinesMigration);
711 TEUCHOS_TEST_FOR_EXCEPTION(!xferAsImport && !xferAsExport,std::runtime_error,
"Tpetra::Import_Util::getTwoTransferOwnershipVector transfer undefined");
727 #endif // TPETRA_IMPORT_UTIL_HPP 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.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
void doExport(const SrcDistObject &source, const Export< LocalOrdinal, GlobalOrdinal, Node > &exporter, CombineMode CM)
Export data into this object using an Export object ("forward mode").
A distributed dense vector.
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.
size_t getNodeNumElements() const
The number of elements belonging to the calling process.
virtual Teuchos::RCP< const map_type > getMap() const
The Map describing the parallel distribution of this object.
void doImport(const SrcDistObject &source, const Import< LocalOrdinal, GlobalOrdinal, Node > &importer, CombineMode CM)
Import data into this object using an Import object ("forward mode").
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 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
size_t global_size_t
Global size_t object.
Teuchos::RCP< const map_type > getTargetMap() const
The target Map used to construct this Export.
void putScalar(const Scalar &value)
Set all values in the multivector with the given value.
Declaration and definition of Tpetra::Details::reallocDualViewIfNeeded, an implementation detail of T...
Replace existing values with new values.
Teuchos::ArrayRCP< Scalar > getDataNonConst()
View of the local values of this vector.
void sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2)
Sort the first array, and apply the resulting permutation to the second array.
ValueType get(const KeyType key)
Get the value corresponding to the given key.
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
void add(const KeyType key, const ValueType value)
Add a key and its value to the hash table.
Stand-alone utility functions and macros.
A parallel distribution of indices over processes.
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.