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 typename RowGraph<LO,GO,NT>::global_inds_host_view_type 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 GOView,
typename bitset_t>
500 struct GatherPresentEntries
502 using GO =
typename GOView::non_const_value_type;
504 GatherPresentEntries(GO minGID_,
const GOView& gids_,
const bitset_t& present_)
505 : minGID(minGID_), gids(gids_), present(present_)
508 KOKKOS_INLINE_FUNCTION
void operator()(
const GO i)
const 510 present.set(gids(i) - minGID);
518 template<
typename LO,
typename GO,
typename device_t,
typename LocalMapType,
typename const_bitset_t,
bool doingRemotes>
521 using mem_space =
typename device_t::memory_space;
522 using GOView = Kokkos::View<GO*, mem_space>;
523 using SingleView = Kokkos::View<GO, mem_space>;
525 ListGIDs(GO minGID_, GOView& gidList_, SingleView& numElems_, const_bitset_t& present_,
const LocalMapType& localDomainMap_)
526 : minGID(minGID_), gidList(gidList_), numElems(numElems_), present(present_), localDomainMap(localDomainMap_)
529 KOKKOS_INLINE_FUNCTION
void operator()(
const GO i, GO& lcount,
const bool finalPass)
const 531 bool isRemote = localDomainMap.getLocalElement(i + minGID) == ::Tpetra::Details::OrdinalTraits<LO>::invalid();
532 if(present.test(i) && doingRemotes == isRemote)
537 gidList(lcount) = minGID + i;
541 if((i == static_cast<GO>(present.size() - 1)) && finalPass)
551 const_bitset_t present;
552 const LocalMapType localDomainMap;
555 template<
typename GO,
typename mem_space>
556 struct MinMaxReduceFunctor
558 using MinMaxValue =
typename Kokkos::MinMax<GO>::value_type;
559 using GOView = Kokkos::View<GO*, mem_space>;
561 MinMaxReduceFunctor(
const GOView& gids_)
565 KOKKOS_INLINE_FUNCTION
void operator()(
const GO i, MinMaxValue& lminmax)
const 568 if(gid < lminmax.min_val)
569 lminmax.min_val = gid;
570 if(gid > lminmax.max_val)
571 lminmax.max_val = gid;
577 template <
class LO,
class GO,
class NT>
581 Kokkos::View<GO*, typename NT::memory_space> gids,
582 std::ostream* errStrm)
585 using Teuchos::Array;
586 using Kokkos::RangePolicy;
587 using device_t =
typename NT::device_type;
588 using exec_space =
typename device_t::execution_space;
589 using memory_space =
typename device_t::memory_space;
595 using bitset_t = Kokkos::Bitset<typename exec_space::memory_space>;
596 using const_bitset_t = Kokkos::ConstBitset<typename exec_space::memory_space>;
597 using GOView = Kokkos::View<GO*, memory_space>;
598 using SingleView = Kokkos::View<GO, memory_space>;
600 using LocalMap =
typename map_type::local_map_type;
601 GO nentries = gids.extent(0);
602 GO minGID = Teuchos::OrdinalTraits<GO>::max();
604 using MinMaxValue =
typename Kokkos::MinMax<GO>::value_type;
605 MinMaxValue minMaxGID = {minGID, maxGID};
606 Kokkos::parallel_reduce(RangePolicy<exec_space>(0, nentries),
607 MinMaxReduceFunctor<GO, memory_space>(gids),
608 Kokkos::MinMax<GO>(minMaxGID));
609 minGID = minMaxGID.min_val; maxGID = minMaxGID.max_val;
612 bitset_t presentGIDs(maxGID - minGID + 1);
613 Kokkos::parallel_for(RangePolicy<exec_space>(0, nentries), GatherPresentEntries<GOView, bitset_t>(minGID, gids, presentGIDs));
614 const_bitset_t constPresentGIDs(presentGIDs);
616 SingleView numLocals(
"Num local GIDs");
617 SingleView numRemotes(
"Num remote GIDs");
618 GOView localGIDView(Kokkos::ViewAllocateWithoutInitializing(
"Local GIDs"), constPresentGIDs.count());
619 GOView remoteGIDView(Kokkos::ViewAllocateWithoutInitializing(
"Remote GIDs"), constPresentGIDs.count());
620 LocalMap localDomMap = domMap->getLocalMap();
622 Kokkos::parallel_scan(RangePolicy<exec_space>(0, constPresentGIDs.size()),
623 ListGIDs<LO, GO, device_t, LocalMap, const_bitset_t, false>
624 (minGID, localGIDView, numLocals, constPresentGIDs, localDomMap));
626 Kokkos::parallel_scan(RangePolicy<exec_space>(0, constPresentGIDs.size()),
627 ListGIDs<LO, GO, device_t, LocalMap, const_bitset_t, true>
628 (minGID, remoteGIDView, numRemotes, constPresentGIDs, localDomMap));
630 GO numLocalColGIDs = 0;
631 GO numRemoteColGIDs = 0;
635 auto localsHost = Kokkos::create_mirror_view(localGIDView);
636 auto remotesHost = Kokkos::create_mirror_view(remoteGIDView);
640 std::set<GO> RemoteGIDSet;
641 std::vector<GO> RemoteGIDUnorderedVector;
642 std::vector<bool> GIDisLocal (domMap->getNodeNumElements (),
false);
643 for(GO i = 0; i < numLocalColGIDs; i++)
645 GO gid = localsHost(i);
648 GIDisLocal[domMap->getLocalElement(gid)] =
true;
650 RemoteGIDUnorderedVector.reserve(numRemoteColGIDs);
651 for(GO i = 0; i < numRemoteColGIDs; i++)
653 GO gid = remotesHost(i);
654 RemoteGIDSet.insert(gid);
655 RemoteGIDUnorderedVector.push_back(gid);
658 Array<int> remotePIDs;
660 return makeColMapImpl<LO, GO, NT>(
664 static_cast<size_t>(numLocalColGIDs),
665 static_cast<size_t>(numRemoteColGIDs),
667 RemoteGIDUnorderedVector,
681 #define TPETRA_DETAILS_MAKECOLMAP_INSTANT(LO,GO,NT) \ 682 namespace Details { \ 684 makeColMap (Teuchos::RCP<const Tpetra::Map<LO, GO, NT> >&, \ 685 Teuchos::Array<int>&, \ 686 const Teuchos::RCP<const Tpetra::Map<LO, GO, NT> >&, \ 687 const RowGraph<LO, GO, NT>&, \ 691 makeColMap (Teuchos::RCP<const Tpetra::Map<LO, GO, NT> >&, \ 692 const Teuchos::RCP<const Tpetra::Map<LO, GO, NT> >&, \ 693 Kokkos::View<GO*, typename NT::memory_space>, \ 697 #endif // TPETRA_DETAILS_MAKECOLMAP_DEF_HPP virtual bool hasColMap() const =0
Whether the graph has a well-defined column Map.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
An abstract interface for graphs accessed by rows.
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 getNodeNumElements() const
The number of elements belonging to the calling process.
Implementation details of Tpetra.
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.
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...
void sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2)
Sort the first array, and apply the resulting permutation to the second array.
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...
global_ordinal_type getGlobalElement(local_ordinal_type localIndex) const
The global index corresponding to the given local index.