1 #ifndef TPETRA_DETAILS_MAKECOLMAP_DEF_HPP
2 #define TPETRA_DETAILS_MAKECOLMAP_DEF_HPP
56 #include "Tpetra_RowGraph.hpp"
58 #include "Teuchos_Array.hpp"
59 #include "Kokkos_Bitset.hpp"
66 template <
class LO,
class GO,
class NT>
69 Teuchos::Array<int>& remotePIDs,
71 size_t numLocalColGIDs,
72 size_t numRemoteColGIDs,
73 std::set<GO>& RemoteGIDSet,
74 std::vector<GO>& RemoteGIDUnorderedVector,
75 std::vector<bool>& GIDisLocal,
76 const bool sortEachProcsGids,
77 std::ostream* errStrm)
80 using Teuchos::ArrayView;
84 const char prefix[] =
"Tpetra::Details::makeColMapImpl: ";
85 typedef ::Tpetra::Map<LO, GO, NT> map_type;
115 if (domMap->getComm ()->getSize () == 1) {
116 if (numRemoteColGIDs != 0) {
118 if (errStrm != NULL) {
119 *errStrm << prefix <<
"The domain Map only has one process, but "
120 << numRemoteColGIDs <<
" column "
121 << (numRemoteColGIDs != 1 ?
"indices are" :
"index is")
122 <<
" not in the domain Map. Either these indices are "
123 "invalid or the domain Map is invalid. Remember that nonsquare "
124 "matrices, or matrices where the row and range Maps differ, "
125 "require calling the version of fillComplete that takes the "
126 "domain and range Maps as input." << endl;
129 if (numLocalColGIDs == domMap->getNodeNumElements ()) {
139 Array<GO> myColumns(numLocalColGIDs + numRemoteColGIDs);
141 ArrayView<GO> LocalColGIDs = myColumns (0, numLocalColGIDs);
142 ArrayView<GO> remoteColGIDs = myColumns (numLocalColGIDs, numRemoteColGIDs);
145 if (sortEachProcsGids) {
147 std::copy (RemoteGIDSet.begin(), RemoteGIDSet.end(),
148 remoteColGIDs.begin());
152 std::copy (RemoteGIDUnorderedVector.begin(),
153 RemoteGIDUnorderedVector.end(), remoteColGIDs.begin());
159 if (static_cast<size_t> (remotePIDs.size ()) != numRemoteColGIDs) {
160 remotePIDs.resize (numRemoteColGIDs);
165 domMap->getRemoteIndexList (remoteColGIDs, remotePIDs ());
175 if (errStrm != NULL) {
176 *errStrm << prefix <<
"Some column indices are not in the domain Map."
177 "Either these column indices are invalid or the domain Map is "
178 "invalid. Likely cause: For a nonsquare matrix, you must give the "
179 "domain and range Maps as input to fillComplete." << endl;
198 sort2 (remotePIDs.begin (), remotePIDs.end (), remoteColGIDs.begin ());
210 const size_t numDomainElts = domMap->getNodeNumElements ();
211 if (numLocalColGIDs == numDomainElts) {
215 if (domMap->isContiguous ()) {
220 GO curColMapGid = domMap->getMinGlobalIndex ();
221 for (
size_t k = 0; k < numLocalColGIDs; ++k, ++curColMapGid) {
222 LocalColGIDs[k] = curColMapGid;
226 ArrayView<const GO> domainElts = domMap->getNodeElementList ();
227 std::copy (domainElts.begin(), domainElts.end(), LocalColGIDs.begin());
233 size_t numLocalCount = 0;
234 if (domMap->isContiguous ()) {
239 GO curColMapGid = domMap->getMinGlobalIndex ();
240 for (
size_t i = 0; i < numDomainElts; ++i, ++curColMapGid) {
242 LocalColGIDs[numLocalCount++] = curColMapGid;
247 ArrayView<const GO> domainElts = domMap->getNodeElementList ();
248 for (
size_t i = 0; i < numDomainElts; ++i) {
250 LocalColGIDs[numLocalCount++] = domainElts[i];
254 if (numLocalCount != numLocalColGIDs) {
255 if (errStrm != NULL) {
256 *errStrm << prefix <<
"numLocalCount = " << numLocalCount
257 <<
" != numLocalColGIDs = " << numLocalColGIDs
258 <<
". This should never happen. "
259 "Please report this bug to the Tpetra developers." << endl;
315 Tpetra::Details::OrdinalTraits<global_size_t>::invalid ();
320 const GO indexBase = domMap->getIndexBase ();
321 colMap = rcp (
new map_type (INV, myColumns, indexBase, domMap->getComm ()));
325 template <
class LO,
class GO,
class NT>
328 Teuchos::Array<int>& remotePIDs,
331 const bool sortEachProcsGids,
332 std::ostream* errStrm)
334 using Teuchos::Array;
335 using Teuchos::ArrayView;
338 typedef ::Tpetra::Map<LO, GO, NT> map_type;
339 const char prefix[] =
"Tpetra::Details::makeColMap: ";
349 if (domMap.is_null () || domMap->getComm ().is_null ()) {
350 colMap = Teuchos::null;
359 if (colMap.is_null () || ! graph.
hasColMap ()) {
361 if (errStrm != NULL) {
362 *errStrm << prefix <<
"The graph is locally indexed on the calling "
363 "process, but has no column Map (either getColMap() returns null, "
364 "or hasColMap() returns false)." << endl;
376 if (colMap->isContiguous ()) {
378 const LO numCurGids =
static_cast<LO
> (colMap->getNodeNumElements ());
379 myColumns.resize (numCurGids);
380 const GO myFirstGblInd = colMap->getMinGlobalIndex ();
381 for (LO k = 0; k < numCurGids; ++k) {
382 myColumns[k] = myFirstGblInd +
static_cast<GO
> (k);
386 ArrayView<const GO> curGids = graph.
getColMap ()->getNodeElementList ();
388 const LO numCurGids =
static_cast<LO
> (curGids.size ());
389 myColumns.resize (numCurGids);
390 for (LO k = 0; k < numCurGids; ++k) {
391 myColumns[k] = curGids[k];
420 const LO LINV = Tpetra::Details::OrdinalTraits<LO>::invalid ();
421 size_t numLocalColGIDs = 0;
422 size_t numRemoteColGIDs = 0;
426 std::vector<bool> GIDisLocal (domMap->getNodeNumElements (),
false);
427 std::set<GO> RemoteGIDSet;
430 std::vector<GO> RemoteGIDUnorderedVector;
435 for (LO lclRow = 0; lclRow < lclNumRows; ++lclRow) {
437 Teuchos::ArrayView<const GO> rowGids;
440 const LO numEnt =
static_cast<LO
> (rowGids.size ());
442 for (LO k = 0; k < numEnt; ++k) {
443 const GO gid = rowGids[k];
444 const LO lid = domMap->getLocalElement (gid);
446 const bool alreadyFound = GIDisLocal[lid];
447 if (! alreadyFound) {
448 GIDisLocal[lid] =
true;
453 const bool notAlreadyFound = RemoteGIDSet.insert (gid).second;
454 if (notAlreadyFound) {
455 if (! sortEachProcsGids) {
462 RemoteGIDUnorderedVector.push_back (gid);
472 return makeColMapImpl<LO, GO, NT>(
475 numLocalColGIDs, numRemoteColGIDs,
476 RemoteGIDSet, RemoteGIDUnorderedVector, GIDisLocal,
477 sortEachProcsGids, errStrm);
489 Tpetra::Details::OrdinalTraits<global_size_t>::invalid ();
494 const GO indexBase = domMap->getIndexBase ();
495 colMap = rcp (
new map_type (INV, myColumns, indexBase, domMap->getComm ()));
499 template<
typename GO,
typename device_t>
500 struct GatherPresentEntries
502 using bitset_t = Kokkos::Bitset<device_t>;
503 using mem_space =
typename device_t::memory_space;
504 using GOView = Kokkos::View<GO*, mem_space>;
506 GatherPresentEntries(GO minGID_,
const GOView& gids_, bitset_t& present_)
507 : minGID(minGID_), gids(gids_), present(present_)
510 KOKKOS_INLINE_FUNCTION
void operator()(
const GO i)
const
512 present.set(gids(i) - minGID);
520 template<
typename LO,
typename GO,
typename device_t,
typename LocalMapType,
bool doingRemotes>
523 using const_bitset_t = Kokkos::ConstBitset<device_t>;
524 using mem_space =
typename device_t::memory_space;
525 using GOView = Kokkos::View<GO*, mem_space>;
526 using SingleView = Kokkos::View<GO, mem_space>;
528 ListGIDs(GO minGID_, GOView& gidList_, SingleView& numElems_, const_bitset_t& present_,
const LocalMapType& localDomainMap_)
529 : minGID(minGID_), gidList(gidList_), numElems(numElems_), present(present_), localDomainMap(localDomainMap_)
532 KOKKOS_INLINE_FUNCTION
void operator()(
const GO i, GO& lcount,
const bool finalPass)
const
534 bool isRemote = localDomainMap.getLocalElement(i + minGID) == ::Tpetra::Details::OrdinalTraits<LO>::invalid();
535 if(present.test(i) && doingRemotes == isRemote)
540 gidList(lcount) = minGID + i;
544 if((i == static_cast<GO>(present.size() - 1)) && finalPass)
554 const_bitset_t present;
555 const LocalMapType localDomainMap;
558 template<
typename GO,
typename mem_space>
559 struct MinMaxReduceFunctor
561 using MinMaxValue =
typename Kokkos::MinMax<GO>::value_type;
562 using GOView = Kokkos::View<GO*, mem_space>;
564 MinMaxReduceFunctor(
const GOView& gids_)
568 KOKKOS_INLINE_FUNCTION
void operator()(
const GO i, MinMaxValue& lminmax)
const
571 if(gid < lminmax.min_val)
572 lminmax.min_val = gid;
573 if(gid > lminmax.max_val)
574 lminmax.max_val = gid;
580 template <
class LO,
class GO,
class NT>
584 Kokkos::View<GO*, typename NT::memory_space> gids,
585 std::ostream* errStrm)
588 using Teuchos::Array;
589 using Kokkos::RangePolicy;
590 using device_t =
typename NT::device_type;
591 using exec_space =
typename device_t::execution_space;
592 using memory_space =
typename device_t::memory_space;
593 using bitset_t = Kokkos::Bitset<device_t>;
594 using const_bitset_t = Kokkos::ConstBitset<device_t>;
595 using GOView = Kokkos::View<GO*, memory_space>;
596 using SingleView = Kokkos::View<GO, memory_space>;
598 using LocalMap =
typename map_type::local_map_type;
599 GO nentries = gids.extent(0);
600 GO minGID = Teuchos::OrdinalTraits<GO>::max();
602 using MinMaxValue =
typename Kokkos::MinMax<GO>::value_type;
603 MinMaxValue minMaxGID = {minGID, maxGID};
604 Kokkos::parallel_reduce(RangePolicy<exec_space>(0, nentries),
605 MinMaxReduceFunctor<GO, memory_space>(gids),
606 Kokkos::MinMax<GO>(minMaxGID));
607 minGID = minMaxGID.min_val; maxGID = minMaxGID.max_val;
610 bitset_t presentGIDs(maxGID - minGID + 1);
611 Kokkos::parallel_for(RangePolicy<exec_space>(0, nentries), GatherPresentEntries<GO, device_t>(minGID, gids, presentGIDs));
612 const_bitset_t constPresentGIDs(presentGIDs);
614 SingleView numLocals(
"Num local GIDs");
615 SingleView numRemotes(
"Num remote GIDs");
616 GOView localGIDView(Kokkos::ViewAllocateWithoutInitializing(
"Local GIDs"), constPresentGIDs.count());
617 GOView remoteGIDView(Kokkos::ViewAllocateWithoutInitializing(
"Remote GIDs"), constPresentGIDs.count());
618 LocalMap localDomMap = domMap->getLocalMap();
620 Kokkos::parallel_scan(RangePolicy<exec_space>(0, constPresentGIDs.size()),
621 ListGIDs<LO, GO, device_t, LocalMap, false>
622 (minGID, localGIDView, numLocals, constPresentGIDs, localDomMap));
624 Kokkos::parallel_scan(RangePolicy<exec_space>(0, constPresentGIDs.size()),
625 ListGIDs<LO, GO, device_t, LocalMap, true>
626 (minGID, remoteGIDView, numRemotes, constPresentGIDs, localDomMap));
628 GO numLocalColGIDs = 0;
629 GO numRemoteColGIDs = 0;
633 auto localsHost = Kokkos::create_mirror_view(localGIDView);
634 auto remotesHost = Kokkos::create_mirror_view(remoteGIDView);
638 std::set<GO> RemoteGIDSet;
639 std::vector<GO> RemoteGIDUnorderedVector;
640 std::vector<bool> GIDisLocal (domMap->getNodeNumElements (),
false);
641 for(GO i = 0; i < numLocalColGIDs; i++)
643 GO gid = localsHost(i);
646 GIDisLocal[domMap->getLocalElement(gid)] =
true;
648 RemoteGIDUnorderedVector.reserve(numRemoteColGIDs);
649 for(GO i = 0; i < numRemoteColGIDs; i++)
651 GO gid = remotesHost(i);
652 RemoteGIDSet.insert(gid);
653 RemoteGIDUnorderedVector.push_back(gid);
656 Array<int> remotePIDs;
658 return makeColMapImpl<LO, GO, NT>(
662 static_cast<size_t>(numLocalColGIDs),
663 static_cast<size_t>(numRemoteColGIDs),
665 RemoteGIDUnorderedVector,
679 #define TPETRA_DETAILS_MAKECOLMAP_INSTANT(LO,GO,NT) \
680 namespace Details { \
682 makeColMap (Teuchos::RCP<const Tpetra::Map<LO, GO, NT> >&, \
683 Teuchos::Array<int>&, \
684 const Teuchos::RCP<const Tpetra::Map<LO, GO, NT> >&, \
685 const RowGraph<LO, GO, NT>&, \
689 makeColMap (Teuchos::RCP<const Tpetra::Map<LO, GO, NT> >&, \
690 const Teuchos::RCP<const Tpetra::Map<LO, GO, NT> >&, \
691 Kokkos::View<GO*, typename NT::memory_space>, \
695 #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.
virtual void getGlobalRowView(const GlobalOrdinal gblRow, Teuchos::ArrayView< const GlobalOrdinal > &gblColInds) const
Get a const, non-persisting view of the given global row's global column indices, as a Teuchos::Array...
LookupStatus
Return status of Map remote index lookup (getRemoteIndexList()).
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.
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...
void sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2)
Sort the first array, and apply the resulting permutation to the second array.
size_t getNodeNumElements() const
The number of elements belonging to the calling process.
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...