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.
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.
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...
"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...
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.