Tpetra parallel linear algebra Version of the Day
Loading...
Searching...
No Matches
Tpetra_Details_makeOptimizedColMap.hpp
Go to the documentation of this file.
1// @HEADER
2// *****************************************************************************
3// Tpetra: Templated Linear Algebra Services Package
4//
5// Copyright 2008 NTESS and the Tpetra contributors.
6// SPDX-License-Identifier: BSD-3-Clause
7// *****************************************************************************
8// @HEADER
9
27
28#include "Tpetra_Map.hpp"
29#include "Tpetra_Import.hpp"
30#include "Tpetra_Util.hpp"
32#include "Teuchos_FancyOStream.hpp"
33#include <memory>
34
35namespace Tpetra {
36namespace Details {
37
44template <class MapType>
45class OptColMap {
46 public:
47 using local_ordinal_type = typename MapType::local_ordinal_type;
48 using global_ordinal_type = typename MapType::global_ordinal_type;
49 using node_type = typename MapType::node_type;
52
53 static Teuchos::RCP<const map_type>
54 makeOptColMap(std::ostream& errStream,
55 bool& lclErr,
56 const map_type& domMap,
57 const map_type& colMap,
58 const import_type* /* oldImport */) {
59 using std::endl;
60 using Teuchos::Array;
61 using Teuchos::ArrayView;
62 using Teuchos::FancyOStream;
63 using Teuchos::getFancyOStream;
64 using Teuchos::RCP;
65 using Teuchos::rcp;
66 using Teuchos::rcpFromRef;
67 using ::Tpetra::Details::Behavior;
68 using LO = local_ordinal_type;
69 using GO = global_ordinal_type;
70 const char prefix[] = "Tpetra::Details::makeOptimizedColMap: ";
71
72 RCP<const Teuchos::Comm<int> > comm = colMap.getComm();
73 std::ostream& err = errStream;
74
75 const bool verbose = Behavior::verbose("Tpetra::Details::makeOptimizedColMap");
76
78 TEUCHOS_TEST_FOR_EXCEPTION(outPtr.is_null(), std::logic_error,
79 "outPtr is null; this should never happen!");
81 Teuchos::OSTab tab1(out);
82
83 std::unique_ptr<std::string> verboseHeader;
84 if (verbose) {
85 std::ostringstream os;
86 const int myRank = comm->getRank();
87 os << "Proc " << myRank << ": ";
88 verboseHeader = std::unique_ptr<std::string>(new std::string(os.str()));
89 }
90 if (verbose) {
91 std::ostringstream os;
92 os << *verboseHeader << "Tpetra::Details::makeOptimizedColMap" << endl;
93 out << os.str();
94 }
95
96 if (verbose) {
97 std::ostringstream os;
98 os << *verboseHeader << "Domain Map GIDs: [";
99 const LO domMapLclNumInds = static_cast<LO>(domMap.getLocalNumElements());
100 for (LO lid = 0; lid < domMapLclNumInds; ++lid) {
101 const GO gid = domMap.getGlobalElement(lid);
102 os << gid;
103 if (lid + LO(1) < domMapLclNumInds) {
104 os << ", ";
105 }
106 }
107 os << "]" << endl;
108 out << os.str();
109 }
110
111 const LO colMapLclNumInds = static_cast<LO>(colMap.getLocalNumElements());
112
113 if (verbose) {
114 std::ostringstream os;
115 os << *verboseHeader << "Column Map GIDs: [";
116 for (LO lid = 0; lid < colMapLclNumInds; ++lid) {
117 const GO gid = colMap.getGlobalElement(lid);
118 os << gid;
119 if (lid + LO(1) < colMapLclNumInds) {
120 os << ", ";
121 }
122 }
123 os << "]" << endl;
124 out << os.str();
125 }
126
127 // Count remote GIDs.
128 LO numOwnedGids = 0;
129 LO numRemoteGids = 0;
130 for (LO colMapLid = 0; colMapLid < colMapLclNumInds; ++colMapLid) {
131 const GO colMapGid = colMap.getGlobalElement(colMapLid);
132 if (domMap.isNodeGlobalElement(colMapGid)) {
133 ++numOwnedGids;
134 } else {
136 }
137 }
138
139 if (verbose) {
140 std::ostringstream os;
141 os << *verboseHeader << "- numOwnedGids: " << numOwnedGids << endl
142 << *verboseHeader << "- numRemoteGids: " << numRemoteGids << endl;
143 out << os.str();
144 }
145
146 // Put all colMap GIDs on the calling process in a single array.
147 // Owned GIDs go in front, and remote GIDs at the end.
151
152 // Fill ownedGids and remoteGids (and therefore allGids). We use
153 // two loops, one to count (above) and one to fill (here), in
154 // order to avoid dynamic memory allocation during the loop (in
155 // this case, lots of calls to push_back()). That will simplify
156 // use of Kokkos to parallelize these loops later.
157 LO ownedPos = 0;
158 LO remotePos = 0;
159 for (LO colMapLid = 0; colMapLid < colMapLclNumInds; ++colMapLid) {
160 const GO colMapGid = colMap.getGlobalElement(colMapLid);
161 if (domMap.isNodeGlobalElement(colMapGid)) {
163 } else {
165 }
166 }
167
168 // If, for some reason, the running count doesn't match the
169 // orignal count, fill in any remaining GID spots with an
170 // obviously invalid value. We don't want to stop yet, because
171 // other processes might not have noticed this error; Map
172 // construction is a collective, so we can't stop now.
173 if (ownedPos != numOwnedGids) {
174 lclErr = true;
175 err << prefix << "On Process " << comm->getRank() << ", ownedPos = "
176 << ownedPos << " != numOwnedGids = " << numOwnedGids << endl;
178 ownedGids[colMapLid] = Teuchos::OrdinalTraits<GO>::invalid();
179 }
180 }
181 if (remotePos != numRemoteGids) {
182 lclErr = true;
183 err << prefix << "On Process " << comm->getRank() << ", remotePos = "
184 << remotePos << " != numRemoteGids = " << numRemoteGids << endl;
186 remoteGids[colMapLid] = Teuchos::OrdinalTraits<GO>::invalid();
187 }
188 }
189
190 // Figure out what processes own what GIDs in the domain Map.
191 // Initialize the output array of remote PIDs with the "invalid
192 // process rank" -1, to help us test whether getRemoteIndexList
193 // did its job.
196 domMap.getRemoteIndexList(remoteGids, remotePids());
197
198 // If any process returns IDNotPresent, then at least one of the
199 // remote indices was not present in the domain Map. This means
200 // that the Import object cannot be constructed, because of
201 // incongruity between the column Map and domain Map. This
202 // means that either the column Map or domain Map, or both, is
203 // incorrect.
206 lclErr = true;
207 err << prefix << "On Process " << comm->getRank() << ", some indices "
208 "in the input colMap (the original column Map) are not in domMap (the "
209 "domain Map). Either these indices or the domain Map is invalid. "
210 "Likely cause: For a nonsquare matrix, you must give the domain and "
211 "range Maps as input to fillComplete."
212 << endl;
213 }
214
215 // Check that getRemoteIndexList actually worked, by making sure
216 // that none of the remote PIDs are -1.
217 for (LO k = 0; k < numRemoteGids; ++k) {
218 bool foundInvalidPid = false;
219 if (remotePids[k] == -1) {
220 foundInvalidPid = true;
221 break;
222 }
223 if (foundInvalidPid) {
224 lclErr = true;
225 err << prefix << "On Process " << comm->getRank() << ", "
226 "getRemoteIndexList returned -1 for the process ranks of "
227 "one or more GIDs on this process."
228 << endl;
229 }
230 }
231
232 if (verbose) {
233 std::ostringstream os;
234 os << *verboseHeader << "- Before sort2:" << endl
235 << *verboseHeader << "-- ownedGids: " << Teuchos::toString(ownedGids) << endl
236 << *verboseHeader << "-- remoteGids: " << Teuchos::toString(remoteGids) << endl
237 << *verboseHeader << "-- allGids: " << Teuchos::toString(allGids()) << endl;
238 out << os.str();
239 }
240 using Tpetra::sort2;
241 sort2(remotePids.begin(), remotePids.end(), remoteGids.begin(), true);
242 if (verbose) {
243 std::ostringstream os;
244 os << *verboseHeader << "- After sort2:" << endl
245 << *verboseHeader << "-- ownedGids: " << Teuchos::toString(ownedGids) << endl
246 << *verboseHeader << "-- remoteGids: " << Teuchos::toString(remoteGids) << endl
247 << *verboseHeader << "-- allGids: " << Teuchos::toString(allGids()) << endl;
248 out << os.str();
249 }
250
251 auto optColMap = rcp(new map_type(colMap.getGlobalNumElements(),
252 allGids(),
253 colMap.getIndexBase(),
254 comm));
255 if (verbose) {
256 std::ostringstream os;
257 os << *verboseHeader << "Tpetra::Details::makeOptimizedColMap: Done" << endl;
258 out << os.str();
259 }
260 return optColMap;
261 }
262
293 static std::pair<Teuchos::RCP<const map_type>,
294 Teuchos::RCP<import_type> >
296 bool& lclErr,
297 const map_type& domMap,
298 const map_type& colMap,
299 const import_type* oldImport) {
300 using Teuchos::RCP;
301 using Teuchos::rcp;
302
303 // mfh 15 May 2018: For now, just call makeOptColMap, and use
304 // the conventional two-Map (source and target) Import
305 // constructor.
307 makeOptColMap(errStream, lclErr, domMap, colMap, oldImport);
309
310 // FIXME (mfh 06 Jul 2014) This constructor throws a runtime
311 // error, so I'm not using it for now.
312 //
313 // imp = rcp (new import_type (domMap, newColMap, remoteGids,
314 // remotePids (), remoteLids (),
315 // Teuchos::null, Teuchos::null));
316 return std::make_pair(newColMap, imp);
317 }
318};
319
344template <class MapType>
345Teuchos::RCP<const MapType>
347 bool& lclErr,
348 const MapType& domMap,
349 const MapType& colMap,
350 const Tpetra::Import<
351 typename MapType::local_ordinal_type,
352 typename MapType::global_ordinal_type,
353 typename MapType::node_type>* oldImport = nullptr) {
354 using map_type = ::Tpetra::Map<
355 typename MapType::local_ordinal_type,
356 typename MapType::global_ordinal_type,
357 typename MapType::node_type>;
359 auto mapPtr = impl_type::makeOptColMap(errStream, lclErr,
360 domMap, colMap, oldImport);
361 return mapPtr;
362}
363
420template <class MapType>
421std::pair<Teuchos::RCP<const MapType>,
422 Teuchos::RCP<typename OptColMap<MapType>::import_type> >
424 bool& lclErr,
425 const MapType& domMap,
426 const MapType& colMap,
427 const typename OptColMap<MapType>::import_type* oldImport = nullptr) {
428 using local_ordinal_type = typename MapType::local_ordinal_type;
429 using global_ordinal_type = typename MapType::global_ordinal_type;
430 using node_type = typename MapType::node_type;
433
434 auto mapAndImp = impl_type::makeOptColMapAndImport(errStream, lclErr, domMap, colMap, oldImport);
435 return std::make_pair(mapAndImp.first, mapAndImp.second);
436}
437
438} // namespace Details
439} // namespace Tpetra
Declaration of Tpetra::Details::Behavior, a class that describes Tpetra's behavior.
Stand-alone utility functions and macros.
Struct that holds views of the contents of a CrsMatrix.
static bool verbose()
Whether Tpetra is in verbose mode.
Implementation detail of makeOptimizedColMap, and makeOptimizedColMapAndImport.
static std::pair< Teuchos::RCP< const map_type >, Teuchos::RCP< import_type > > makeOptColMapAndImport(std::ostream &errStream, bool &lclErr, const map_type &domMap, const map_type &colMap, const import_type *oldImport)
Return an optimized reordering of the given column Map. Optionally, recompute an Import from the inpu...
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
A parallel distribution of indices over processes.
Implementation details of Tpetra.
std::pair< Teuchos::RCP< const MapType >, Teuchos::RCP< typename OptColMap< MapType >::import_type > > makeOptimizedColMapAndImport(std::ostream &errStream, bool &lclErr, const MapType &domMap, const MapType &colMap, const typename OptColMap< MapType >::import_type *oldImport=nullptr)
Return an optimized reordering of the given column Map. Optionally, recompute an Import from the inpu...
Teuchos::RCP< const MapType > makeOptimizedColMap(std::ostream &errStream, bool &lclErr, const MapType &domMap, const MapType &colMap, const Tpetra::Import< typename MapType::local_ordinal_type, typename MapType::global_ordinal_type, typename MapType::node_type > *oldImport=nullptr)
Return an optimized reordering of the given column Map.
Namespace Tpetra contains the class and methods constituting the Tpetra library.
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.
LookupStatus
Return status of Map remote index lookup (getRemoteIndexList()).