10 #ifndef TPETRA_IMPORT_UTIL_HPP
11 #define TPETRA_IMPORT_UTIL_HPP
19 #include "Tpetra_ConfigDefs.hpp"
20 #include "Tpetra_Import.hpp"
21 #include "Tpetra_HashTable.hpp"
22 #include "Tpetra_Map.hpp"
24 #include "Tpetra_Distributor.hpp"
25 #include <Teuchos_Array.hpp>
29 namespace Import_Util {
36 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
38 Teuchos::Array<std::pair<int, GlobalOrdinal> >& gpids,
39 bool use_minus_one_for_local);
42 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
44 Teuchos::Array<int>& pids,
45 bool use_minus_one_for_local);
49 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
51 Teuchos::ArrayView<int>& pids,
52 bool use_minus_one_for_local);
56 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
58 Teuchos::Array<int>& RemotePIDs);
64 namespace Import_Util {
66 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
68 Teuchos::Array<std::pair<int, GlobalOrdinal> >& gpids,
69 bool use_minus_one_for_local) {
77 int mypid = Importer.
getTargetMap()->getComm()->getRank();
78 size_t N = Importer.
getTargetMap()->getLocalNumElements();
81 Teuchos::ArrayView<const LocalOrdinal> RemoteLIDs = Importer.
getRemoteLIDs();
85 Teuchos::ArrayView<const int> ProcsFrom = D.
getProcsFrom();
92 LocalOrdinal lzero = Teuchos::ScalarTraits<LocalOrdinal>::zero();
93 if (use_minus_one_for_local)
94 for (ii = lzero; Teuchos::as<size_t>(ii) < N; ii++) gpids[ii] = std::make_pair(-1, Importer.
getTargetMap()->getGlobalElement(ii));
96 for (ii = lzero; Teuchos::as<size_t>(ii) < N; ii++) gpids[ii] = std::make_pair(mypid, Importer.
getTargetMap()->getGlobalElement(ii));
100 for (i = 0, j = 0; i < NumReceives; i++) {
101 int pid = ProcsFrom[i];
102 for (k = 0; k < LengthsFrom[i]; k++) {
103 if (pid != mypid) gpids[RemoteLIDs[j]].first = pid;
109 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
111 Teuchos::Array<int>& pids,
112 bool use_minus_one_for_local) {
114 pids.resize(Importer.
getTargetMap()->getLocalNumElements());
115 Teuchos::ArrayView<int> v_pids = pids();
116 getPids(Importer, v_pids, use_minus_one_for_local);
119 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
121 Teuchos::ArrayView<int>& pids,
122 bool use_minus_one_for_local) {
127 int mypid = Importer.
getTargetMap()->getComm()->getRank();
128 size_t N = Importer.
getTargetMap()->getLocalNumElements();
129 if (N != (
size_t)pids.size())
throw std::runtime_error(
"Tpetra::Import_Util::getPids(): Incorrect size for output array");
132 Teuchos::ArrayView<const LocalOrdinal> RemoteLIDs = Importer.
getRemoteLIDs();
136 Teuchos::ArrayView<const int> ProcsFrom = D.
getProcsFrom();
137 Teuchos::ArrayView<const size_t> LengthsFrom = D.
getLengthsFrom();
140 LocalOrdinal lzero = Teuchos::ScalarTraits<LocalOrdinal>::zero();
141 if (use_minus_one_for_local)
142 for (ii = lzero; Teuchos::as<size_t>(ii) < N; ii++) pids[ii] = -1;
144 for (ii = lzero; Teuchos::as<size_t>(ii) < N; ii++) pids[ii] = mypid;
148 for (i = 0, j = 0; i < NumReceives; i++) {
149 int pid = ProcsFrom[i];
150 for (k = 0; k < LengthsFrom[i]; k++) {
151 if (pid != mypid) pids[RemoteLIDs[j]] = pid;
157 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
159 Teuchos::Array<int>& RemotePIDs) {
163 Teuchos::ArrayView<const LocalOrdinal> RemoteLIDs = Importer.
getRemoteLIDs();
167 Teuchos::ArrayView<const int> ProcsFrom = D.
getProcsFrom();
168 Teuchos::ArrayView<const size_t> LengthsFrom = D.
getLengthsFrom();
177 for (i = 0, j = 0; i < NumReceives; ++i) {
178 const int pid = ProcsFrom[i];
179 for (k = 0; k < LengthsFrom[i]; ++k) {
188 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
191 RCP<const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > source = Importer.
getSourceMap();
192 RCP<const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > target = Importer.
getTargetMap();
193 RCP<const Teuchos::Comm<int> > comm = source->getComm();
196 if (!source->isDistributed())
return true;
198 int global_is_valid = 0;
199 bool is_valid =
true;
203 LocalOrdinal LO_INVALID = Teuchos::OrdinalTraits<LocalOrdinal>::invalid();
204 const int MyPID = comm->getRank();
205 const int NumProcs = comm->getSize();
207 GlobalOrdinal minSourceGID = source->getMinAllGlobalIndex();
208 GlobalOrdinal maxSourceGID = source->getMaxAllGlobalIndex();
209 GlobalOrdinal minTargetGID = target->getMinAllGlobalIndex();
210 GlobalOrdinal maxTargetGID = target->getMaxAllGlobalIndex();
212 std::ostringstream os;
218 Teuchos::ArrayView<const LocalOrdinal> permuteTarget = Importer.
getPermuteToLIDs();
219 Teuchos::ArrayView<const LocalOrdinal> remoteLIDs = Importer.
getRemoteLIDs();
220 Teuchos::ArrayView<const LocalOrdinal> exportLIDs = Importer.
getExportLIDs();
221 Teuchos::ArrayView<const LocalOrdinal> exportPIDs = Importer.
getExportPIDs();
222 Teuchos::Array<int> remotePIDs;
223 getRemotePIDs(Importer, remotePIDs);
226 Teuchos::Array<GlobalOrdinal> remoteGIDs(remoteLIDs.size());
227 for (
size_t i = 0; i < (size_t)remoteLIDs.size(); i++) {
228 remoteGIDs[i] = target->getGlobalElement(remoteLIDs[i]);
229 if (remoteGIDs[i] < 0) {
230 os << MyPID <<
"ERROR3: source->getGlobalElement(remoteLIDs[l]) is invalid GID=" << remoteGIDs[i] <<
" LID= " << remoteLIDs[i] << std::endl;
235 Teuchos::Array<GlobalOrdinal> exportGIDs(exportLIDs.size(), -1);
236 for (
size_t i = 0; i < (size_t)exportLIDs.size(); i++) {
237 exportGIDs[i] = source->getGlobalElement(exportLIDs[i]);
238 exportGIDs[i] = source->getGlobalElement(exportLIDs[i]);
239 if (exportGIDs[i] < 0) {
240 os << MyPID <<
"ERROR3: source->getGlobalElement(exportLIDs[l]) is invalid GID=" << exportGIDs[i] <<
" LID= " << exportLIDs[i] << std::endl;
246 for (
auto&& rgid : remoteGIDs) {
247 if (std::find(exportGIDs.begin(), exportGIDs.end(), rgid) != exportGIDs.end()) {
249 os << MyPID <<
"ERROR0: Overlap between remoteGIDs and exportGIDs " << rgid << std::endl;
253 int TempPID, OwningPID;
254 for (GlobalOrdinal i = minSourceGID; i < maxSourceGID; i++) {
258 LocalOrdinal slid = source->getLocalElement(i);
259 if (slid == LO_INVALID)
263 Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_MAX, TempPID, Teuchos::outArg(OwningPID));
266 LocalOrdinal tlid = target->getLocalElement(i);
268 if (tlid != LO_INVALID) {
273 if (OwningPID == -1)
continue;
275 if (OwningPID == MyPID) {
282 for (
size_t j = 0; j < (size_t)permuteTarget.size(); j++) {
283 if (tlid == permuteTarget[j]) {
291 bool already_hit =
false;
292 for (
size_t j = 0; j < (size_t)remoteGIDs.size(); j++) {
293 if (i == remoteGIDs[j]) {
300 if (OwningPID == remotePIDs[j]) {
308 os << MyPID <<
" ERROR1: GID " << i <<
" should be remoted from PID " << OwningPID <<
" but isn't." << std::endl;
318 Teuchos::Array<int> local_proc_mask(NumProcs, 0), global_proc_mask(NumProcs, 0);
320 for (GlobalOrdinal i = minTargetGID; i < maxTargetGID; i++) {
322 LocalOrdinal tlid = target->getLocalElement(i);
323 LocalOrdinal slid = source->getLocalElement(i);
325 if (tlid == LO_INVALID)
326 local_proc_mask[MyPID] = 0;
328 local_proc_mask[MyPID] = 1;
330 Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_MAX, NumProcs, &local_proc_mask[0], &global_proc_mask[0]);
332 if (slid != LO_INVALID) {
334 for (
int j = 0; j < NumProcs; j++) {
335 if (j == MyPID)
continue;
336 if (global_proc_mask[j] == 1) {
339 bool already_hit =
false;
340 for (
size_t k = 0; k < (size_t)exportPIDs.size(); k++) {
341 if (exportPIDs[k] == j && source->getGlobalElement(exportLIDs[k]) == i) {
353 os << MyPID <<
" ERROR2: GID " << i <<
" should be sent to PID " << j <<
" but isn't" << std::endl;
363 Teuchos::Array<int> proc_num_exports_recv(NumProcs, 0);
365 Teuchos::Array<int> remoteGIDcount(remoteGIDs.size(), 0);
368 Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_MAX, exportGIDs.size(), Teuchos::outArg(allexpsiz));
370 for (
int i = 0; i < allexpsiz; ++i) {
371 Teuchos::Array<GlobalOrdinal> myexpgid(NumProcs, -2), yourexpgid(NumProcs, -2);
372 Teuchos::Array<int> myexppid(NumProcs, -2), yourexppid(NumProcs, -2);
373 if (i < exportGIDs.size()) {
374 myexpgid[MyPID] = exportGIDs[i];
375 myexppid[MyPID] = exportPIDs[i];
377 Teuchos::reduceAll<int, GlobalOrdinal>(*comm, Teuchos::REDUCE_MAX, NumProcs, &myexpgid[0], &yourexpgid[0]);
378 Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_MAX, NumProcs, &myexppid[0], &yourexppid[0]);
379 for (
int p = 0; p < NumProcs; ++p) {
380 GlobalOrdinal cgid = yourexpgid[p];
382 if (cgid == -2)
continue;
384 os << MyPID <<
" ERROR4: received exportGID is invalid " << cgid << std::endl;
387 bool foundit =
false;
388 for (
size_t k = 0; k < (size_t)remoteGIDs.size(); ++k) {
389 if (cgid == remoteGIDs[k] && yourexppid[p] == MyPID) {
390 if (p != remotePIDs[k]) {
391 os << MyPID <<
" ERROR5: receive export from wrong pid: got " << p <<
" expected: " << remotePIDs[k] << std::endl;
396 os << MyPID <<
" ERROR6: found multiple GIDs from correct pid: GID " << remoteGIDs[k] << std::endl;
402 if (!foundit && yourexppid[p] == MyPID) {
403 os << MyPID <<
" ERROR7: receive gid " << cgid <<
" that is not in my remote gid list, from pid " << p << std::endl;
409 for (
size_t i = 0; i < (size_t)remoteGIDcount.size(); ++i) {
410 int rc = remoteGIDcount[i];
411 if (rc == 1)
continue;
412 os << MyPID <<
" ERROR8: my remote at " << i <<
" gid " << remoteGIDs[i] <<
" has count " << rc << std::endl;
417 Teuchos::reduceAll<int, int>(*comm, Teuchos::REDUCE_MIN, (int)is_valid, Teuchos::outArg(global_is_valid));
419 if (!global_is_valid) {
420 std::cerr << os.str() << std::flush;
421 Importer.
print(std::cout);
424 return global_is_valid > 0;
428 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
430 Teuchos::RCP<const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > source = Importer.
getSourceMap();
431 Teuchos::RCP<const Tpetra::Map<LocalOrdinal, GlobalOrdinal, Node> > target = Importer.
getTargetMap();
434 Teuchos::Array<std::pair<int, GlobalOrdinal> > gpids;
435 getPidGidPairs(Importer, gpids,
true);
438 bool is_local =
true;
440 GlobalOrdinal INVALID = Teuchos::OrdinalTraits<GlobalOrdinal>::invalid();
441 GlobalOrdinal last_GID = Teuchos::OrdinalTraits<GlobalOrdinal>::invalid();
443 for (
size_t i = 0; i < (size_t)gpids.size(); i++) {
444 int pid = gpids[i].first;
445 GlobalOrdinal gid = gpids[i].second;
447 if (is_local ==
false && pid == -1) {
451 }
else if (pid == -1) {
453 if (source->getGlobalElement(i) != target->getGlobalElement(i)) {
461 if (last_PID == -1) {
464 }
else if (pid < last_PID) {
468 }
else if (pid == last_PID) {
469 if (gid < last_GID) {
486 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
488 bool consistent_block =
true;
491 auto lbid = floor(
double(lid) / block_size);
494 for (
size_t lid2 = 1; lid2 < block_size; ++lid2) {
495 auto lbid_n = floor(
double(lid + lid2) / block_size);
497 if (consistent_block)
498 consistent_block = (lbid == lbid_n);
499 if (consistent_block)
500 consistent_block = (gbid == gbid_n);
504 return consistent_block;
510 #endif // TPETRA_IMPORT_UTIL_HPP
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
size_t getNumReceives() const
The number of processes from which we will receive data.
size_t getLocalNumElements() const
The number of elements belonging to the calling process.
Teuchos::ArrayView< const int > getExportPIDs() const
List of processes to which entries will be sent.
Teuchos::ArrayView< const LocalOrdinal > getPermuteToLIDs() const
List of local IDs in the target Map that are permuted.
Teuchos::RCP< const map_type > getTargetMap() const
The target Map used to construct this Export or Import.
size_t getNumSameIDs() const
Number of initial identical IDs.
Teuchos::ArrayView< const size_t > getLengthsFrom() const
Number of values this process will receive from each process.
Teuchos::ArrayView< const int > getProcsFrom() const
Ranks of the processes sending values to this process.
size_t getNumRemoteIDs() const
Number of entries not on the calling process.
Teuchos::ArrayView< const LocalOrdinal > getRemoteLIDs() const
List of entries in the target Map to receive from other processes.
global_ordinal_type getGlobalElement(local_ordinal_type localIndex) const
The global index corresponding to the given local index.
Sets up and executes a communication plan for a Tpetra DistObject.
Teuchos::RCP< const map_type > getSourceMap() const
The source Map used to construct this Export or Import.
Teuchos::ArrayView< const LocalOrdinal > getExportLIDs() const
List of entries in the source Map that will be sent to other processes.
A parallel distribution of indices over processes.
::Tpetra::Distributor & getDistributor() const
The Distributor that this Export or Import object uses to move data.
Stand-alone utility functions and macros.
virtual void print(std::ostream &os) const
Print the Import's data to the given output stream.