1 #ifndef TPETRA_DETAILS_MAKECOLMAP_DEF_HPP
2 #define TPETRA_DETAILS_MAKECOLMAP_DEF_HPP
24 #include "Tpetra_RowGraph.hpp"
26 #include "Teuchos_Array.hpp"
27 #include "Kokkos_Bitset.hpp"
34 template <
class LO,
class GO,
class NT>
37 Teuchos::Array<int>& remotePIDs,
39 size_t numLocalColGIDs,
40 size_t numRemoteColGIDs,
41 std::set<GO>& RemoteGIDSet,
42 std::vector<GO>& RemoteGIDUnorderedVector,
43 std::vector<bool>& GIDisLocal,
44 const bool sortEachProcsGids,
45 std::ostream* errStrm)
48 using Teuchos::ArrayView;
52 const char prefix[] =
"Tpetra::Details::makeColMapImpl: ";
53 typedef ::Tpetra::Map<LO, GO, NT> map_type;
83 if (domMap->getComm ()->getSize () == 1) {
84 if (numRemoteColGIDs != 0) {
86 if (errStrm != NULL) {
87 *errStrm << prefix <<
"The domain Map only has one process, but "
88 << numRemoteColGIDs <<
" column "
89 << (numRemoteColGIDs != 1 ?
"indices are" :
"index is")
90 <<
" not in the domain Map. Either these indices are "
91 "invalid or the domain Map is invalid. Remember that nonsquare "
92 "matrices, or matrices where the row and range Maps differ, "
93 "require calling the version of fillComplete that takes the "
94 "domain and range Maps as input." << endl;
97 if (numLocalColGIDs == domMap->getLocalNumElements ()) {
107 Array<GO> myColumns(numLocalColGIDs + numRemoteColGIDs);
109 ArrayView<GO> LocalColGIDs = myColumns (0, numLocalColGIDs);
110 ArrayView<GO> remoteColGIDs = myColumns (numLocalColGIDs, numRemoteColGIDs);
113 if (sortEachProcsGids) {
115 std::copy (RemoteGIDSet.begin(), RemoteGIDSet.end(),
116 remoteColGIDs.begin());
120 std::copy (RemoteGIDUnorderedVector.begin(),
121 RemoteGIDUnorderedVector.end(), remoteColGIDs.begin());
127 if (static_cast<size_t> (remotePIDs.size ()) != numRemoteColGIDs) {
128 remotePIDs.resize (numRemoteColGIDs);
133 domMap->getRemoteIndexList (remoteColGIDs, remotePIDs ());
143 if (errStrm != NULL) {
144 *errStrm << prefix <<
"Some column indices are not in the domain Map."
145 "Either these column indices are invalid or the domain Map is "
146 "invalid. Likely cause: For a nonsquare matrix, you must give the "
147 "domain and range Maps as input to fillComplete." << endl;
166 sort2 (remotePIDs.begin (), remotePIDs.end (), remoteColGIDs.begin (),
true);
178 const size_t numDomainElts = domMap->getLocalNumElements ();
179 if (numLocalColGIDs == numDomainElts) {
183 if (domMap->isContiguous ()) {
188 GO curColMapGid = domMap->getMinGlobalIndex ();
189 for (
size_t k = 0; k < numLocalColGIDs; ++k, ++curColMapGid) {
190 LocalColGIDs[k] = curColMapGid;
194 ArrayView<const GO> domainElts = domMap->getLocalElementList ();
195 std::copy (domainElts.begin(), domainElts.end(), LocalColGIDs.begin());
201 size_t numLocalCount = 0;
202 if (domMap->isContiguous ()) {
207 GO curColMapGid = domMap->getMinGlobalIndex ();
208 for (
size_t i = 0; i < numDomainElts; ++i, ++curColMapGid) {
210 LocalColGIDs[numLocalCount++] = curColMapGid;
215 ArrayView<const GO> domainElts = domMap->getLocalElementList ();
216 for (
size_t i = 0; i < numDomainElts; ++i) {
218 LocalColGIDs[numLocalCount++] = domainElts[i];
222 if (numLocalCount != numLocalColGIDs) {
223 if (errStrm != NULL) {
224 *errStrm << prefix <<
"numLocalCount = " << numLocalCount
225 <<
" != numLocalColGIDs = " << numLocalColGIDs
226 <<
". This should never happen. "
227 "Please report this bug to the Tpetra developers." << endl;
283 Tpetra::Details::OrdinalTraits<global_size_t>::invalid ();
288 const GO indexBase = domMap->getIndexBase ();
289 colMap = rcp (
new map_type (INV, myColumns, indexBase, domMap->getComm ()));
293 template <
class LO,
class GO,
class NT>
296 Teuchos::Array<int>& remotePIDs,
299 const bool sortEachProcsGids,
300 std::ostream* errStrm)
302 using Teuchos::Array;
303 using Teuchos::ArrayView;
306 typedef ::Tpetra::Map<LO, GO, NT> map_type;
307 const char prefix[] =
"Tpetra::Details::makeColMap: ";
317 if (domMap.is_null () || domMap->getComm ().is_null ()) {
318 colMap = Teuchos::null;
327 if (colMap.is_null () || ! graph.
hasColMap ()) {
329 if (errStrm != NULL) {
330 *errStrm << prefix <<
"The graph is locally indexed on the calling "
331 "process, but has no column Map (either getColMap() returns null, "
332 "or hasColMap() returns false)." << endl;
344 if (colMap->isContiguous ()) {
346 const LO numCurGids =
static_cast<LO
> (colMap->getLocalNumElements ());
347 myColumns.resize (numCurGids);
348 const GO myFirstGblInd = colMap->getMinGlobalIndex ();
349 for (LO k = 0; k < numCurGids; ++k) {
350 myColumns[k] = myFirstGblInd +
static_cast<GO
> (k);
354 ArrayView<const GO> curGids = graph.
getColMap ()->getLocalElementList ();
356 const LO numCurGids =
static_cast<LO
> (curGids.size ());
357 myColumns.resize (numCurGids);
358 for (LO k = 0; k < numCurGids; ++k) {
359 myColumns[k] = curGids[k];
388 const LO LINV = Tpetra::Details::OrdinalTraits<LO>::invalid ();
389 size_t numLocalColGIDs = 0;
390 size_t numRemoteColGIDs = 0;
394 std::vector<bool> GIDisLocal (domMap->getLocalNumElements (),
false);
395 std::set<GO> RemoteGIDSet;
398 std::vector<GO> RemoteGIDUnorderedVector;
403 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
405 typename RowGraph<LO,GO,NT>::global_inds_host_view_type rowGids;
408 const LO numEnt =
static_cast<LO
> (rowGids.size ());
410 for (LO k = 0; k < numEnt; ++k) {
411 const GO gid = rowGids[k];
412 const LO lid = domMap->getLocalElement (gid);
414 const bool alreadyFound = GIDisLocal[lid];
415 if (! alreadyFound) {
416 GIDisLocal[lid] =
true;
421 const bool notAlreadyFound = RemoteGIDSet.insert (gid).second;
422 if (notAlreadyFound) {
423 if (! sortEachProcsGids) {
430 RemoteGIDUnorderedVector.push_back (gid);
440 return makeColMapImpl<LO, GO, NT>(
443 numLocalColGIDs, numRemoteColGIDs,
444 RemoteGIDSet, RemoteGIDUnorderedVector, GIDisLocal,
445 sortEachProcsGids, errStrm);
457 Tpetra::Details::OrdinalTraits<global_size_t>::invalid ();
462 const GO indexBase = domMap->getIndexBase ();
463 colMap = rcp (
new map_type (INV, myColumns, indexBase, domMap->getComm ()));
467 template<
typename GOView,
typename bitset_t>
468 struct GatherPresentEntries
470 using GO =
typename GOView::non_const_value_type;
472 GatherPresentEntries(GO minGID_,
const GOView& gids_,
const bitset_t& present_)
473 : minGID(minGID_), gids(gids_), present(present_)
476 KOKKOS_INLINE_FUNCTION
void operator()(
const GO i)
const
478 present.set(gids(i) - minGID);
486 template<
typename LO,
typename GO,
typename device_t,
typename LocalMapType,
typename const_bitset_t,
bool doingRemotes>
489 using mem_space =
typename device_t::memory_space;
490 using GOView = Kokkos::View<GO*, mem_space>;
491 using SingleView = Kokkos::View<GO, mem_space>;
493 ListGIDs(GO minGID_, GOView& gidList_, SingleView& numElems_, const_bitset_t& present_,
const LocalMapType& localDomainMap_)
494 : minGID(minGID_), gidList(gidList_), numElems(numElems_), present(present_), localDomainMap(localDomainMap_)
497 KOKKOS_INLINE_FUNCTION
void operator()(
const GO i, GO& lcount,
const bool finalPass)
const
499 bool isRemote = localDomainMap.getLocalElement(i + minGID) == ::Tpetra::Details::OrdinalTraits<LO>::invalid();
500 if(present.test(i) && doingRemotes == isRemote)
505 gidList(lcount) = minGID + i;
509 if((i == static_cast<GO>(present.size() - 1)) && finalPass)
519 const_bitset_t present;
520 const LocalMapType localDomainMap;
523 template<
typename GO,
typename mem_space>
524 struct MinMaxReduceFunctor
526 using MinMaxValue =
typename Kokkos::MinMax<GO>::value_type;
527 using GOView = Kokkos::View<GO*, mem_space>;
529 MinMaxReduceFunctor(
const GOView& gids_)
533 KOKKOS_INLINE_FUNCTION
void operator()(
const GO i, MinMaxValue& lminmax)
const
536 if(gid < lminmax.min_val)
537 lminmax.min_val = gid;
538 if(gid > lminmax.max_val)
539 lminmax.max_val = gid;
545 template <
class LO,
class GO,
class NT>
549 Kokkos::View<GO*, typename NT::memory_space> gids,
550 std::ostream* errStrm)
553 using Teuchos::Array;
554 using Kokkos::RangePolicy;
555 using device_t =
typename NT::device_type;
556 using exec_space =
typename device_t::execution_space;
557 using memory_space =
typename device_t::memory_space;
563 using bitset_t = Kokkos::Bitset<typename exec_space::memory_space>;
564 using const_bitset_t = Kokkos::ConstBitset<typename exec_space::memory_space>;
565 using GOView = Kokkos::View<GO*, memory_space>;
566 using SingleView = Kokkos::View<GO, memory_space>;
568 using LocalMap =
typename map_type::local_map_type;
569 GO nentries = gids.extent(0);
570 GO minGID = Teuchos::OrdinalTraits<GO>::max();
572 using MinMaxValue =
typename Kokkos::MinMax<GO>::value_type;
573 MinMaxValue minMaxGID = {minGID, maxGID};
574 Kokkos::parallel_reduce(RangePolicy<exec_space>(0, nentries),
575 MinMaxReduceFunctor<GO, memory_space>(gids),
576 Kokkos::MinMax<GO>(minMaxGID));
577 minGID = minMaxGID.min_val; maxGID = minMaxGID.max_val;
580 bitset_t presentGIDs(maxGID - minGID + 1);
581 Kokkos::parallel_for(RangePolicy<exec_space>(0, nentries), GatherPresentEntries<GOView, bitset_t>(minGID, gids, presentGIDs));
582 const_bitset_t constPresentGIDs(presentGIDs);
584 SingleView numLocals(
"Num local GIDs");
585 SingleView numRemotes(
"Num remote GIDs");
586 GOView localGIDView(Kokkos::ViewAllocateWithoutInitializing(
"Local GIDs"), constPresentGIDs.count());
587 GOView remoteGIDView(Kokkos::ViewAllocateWithoutInitializing(
"Remote GIDs"), constPresentGIDs.count());
588 LocalMap localDomMap = domMap->getLocalMap();
590 Kokkos::parallel_scan(RangePolicy<exec_space>(0, constPresentGIDs.size()),
591 ListGIDs<LO, GO, device_t, LocalMap, const_bitset_t, false>
592 (minGID, localGIDView, numLocals, constPresentGIDs, localDomMap));
594 Kokkos::parallel_scan(RangePolicy<exec_space>(0, constPresentGIDs.size()),
595 ListGIDs<LO, GO, device_t, LocalMap, const_bitset_t, true>
596 (minGID, remoteGIDView, numRemotes, constPresentGIDs, localDomMap));
598 GO numLocalColGIDs = 0;
599 GO numRemoteColGIDs = 0;
605 auto localsHost = Kokkos::create_mirror_view(localGIDView);
606 auto remotesHost = Kokkos::create_mirror_view(remoteGIDView);
612 Kokkos::fence(
"Tpetra::makeColMap");
614 std::set<GO> RemoteGIDSet;
615 std::vector<GO> RemoteGIDUnorderedVector;
616 std::vector<bool> GIDisLocal (domMap->getLocalNumElements (),
false);
617 for(GO i = 0; i < numLocalColGIDs; i++)
619 GO gid = localsHost(i);
622 GIDisLocal[domMap->getLocalElement(gid)] =
true;
624 RemoteGIDUnorderedVector.reserve(numRemoteColGIDs);
625 for(GO i = 0; i < numRemoteColGIDs; i++)
627 GO gid = remotesHost(i);
628 RemoteGIDSet.insert(gid);
629 RemoteGIDUnorderedVector.push_back(gid);
632 Array<int> remotePIDs;
634 return makeColMapImpl<LO, GO, NT>(
638 static_cast<size_t>(numLocalColGIDs),
639 static_cast<size_t>(numRemoteColGIDs),
641 RemoteGIDUnorderedVector,
655 #define TPETRA_DETAILS_MAKECOLMAP_INSTANT(LO,GO,NT) \
656 namespace Details { \
658 makeColMap (Teuchos::RCP<const Tpetra::Map<LO, GO, NT> >&, \
659 Teuchos::Array<int>&, \
660 const Teuchos::RCP<const Tpetra::Map<LO, GO, NT> >&, \
661 const RowGraph<LO, GO, NT>&, \
665 makeColMap (Teuchos::RCP<const Tpetra::Map<LO, GO, NT> >&, \
666 const Teuchos::RCP<const Tpetra::Map<LO, GO, NT> >&, \
667 Kokkos::View<GO*, typename NT::memory_space>, \
671 #endif // TPETRA_DETAILS_MAKECOLMAP_DEF_HPP
virtual bool hasColMap() const =0
Whether the graph has a well-defined column Map.
An abstract interface for graphs accessed by rows.
LookupStatus
Return status of Map remote index lookup (getRemoteIndexList()).
size_t getLocalNumElements() const
The number of elements belonging to the calling process.
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getColMap() const =0
The Map that describes this graph's distribution of columns over processes.
"Local" part of Map suitable for Kokkos kernels.
size_t global_size_t
Global size_t object.
void deep_copy(MultiVector< DS, DL, DG, DN > &dst, const MultiVector< SS, SL, SG, SN > &src)
Copy the contents of the MultiVector src into dst.
global_ordinal_type getGlobalElement(local_ordinal_type localIndex) const
The global index corresponding to the given local index.
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.
virtual Teuchos::RCP< const Map< LocalOrdinal, GlobalOrdinal, Node > > getRowMap() const =0
The Map that describes this graph's distribution of rows over processes.
virtual bool isGloballyIndexed() const =0
If graph indices are in the global range, this function returns true. Otherwise, this function return...
virtual void getGlobalRowView(const GlobalOrdinal gblRow, global_inds_host_view_type &gblColInds) const =0
Get a const, non-persisting view of the given global row's global column indices, as a Teuchos::Array...
A parallel distribution of indices over processes.
int makeColMap(Teuchos::RCP< const Tpetra::Map< LO, GO, NT > > &colMap, Teuchos::Array< int > &remotePIDs, const Teuchos::RCP< const Tpetra::Map< LO, GO, NT > > &domMap, const RowGraph< LO, GO, NT > &graph, const bool sortEachProcsGids=true, std::ostream *errStrm=NULL)
Make the graph's column Map.
Stand-alone utility functions and macros.
virtual bool isLocallyIndexed() const =0
If graph indices are in the local range, this function returns true. Otherwise, this function returns...