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>
29namespace Import_Util {
36template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
38 Teuchos::Array<std::pair<int, GlobalOrdinal> >& gpids,
39 bool use_minus_one_for_local);
42template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
44 Teuchos::Array<int>& pids,
45 bool use_minus_one_for_local);
49template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
51 Teuchos::ArrayView<int>& pids,
52 bool use_minus_one_for_local);
56template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
58 Teuchos::Array<int>& RemotePIDs);
64namespace Import_Util {
66template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
68 Teuchos::Array<std::pair<int, GlobalOrdinal> >&
gpids,
78 size_t N =
Importer.getTargetMap()->getLocalNumElements();
85 Teuchos::ArrayView<const int>
ProcsFrom =
D.getProcsFrom();
86 Teuchos::ArrayView<const size_t>
LengthsFrom =
D.getLengthsFrom();
109template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
111 Teuchos::Array<int>&
pids,
114 pids.resize(
Importer.getTargetMap()->getLocalNumElements());
119template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
121 Teuchos::ArrayView<int>&
pids,
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");
136 Teuchos::ArrayView<const int>
ProcsFrom =
D.getProcsFrom();
137 Teuchos::ArrayView<const size_t>
LengthsFrom =
D.getLengthsFrom();
157template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
167 Teuchos::ArrayView<const int>
ProcsFrom =
D.getProcsFrom();
168 Teuchos::ArrayView<const size_t>
LengthsFrom =
D.getLengthsFrom();
188template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
196 if (!
source->isDistributed())
return true;
204 const int MyPID = comm->getRank();
205 const int NumProcs = comm->getSize();
212 std::ostringstream
os;
219 Teuchos::ArrayView<const LocalOrdinal> remoteLIDs =
Importer.getRemoteLIDs();
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) {
277 if ((
size_t)tlid < Importer.getNumSameIDs()) {
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;
428template <
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;
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) {
486template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
488 bool consistent_block =
true;
490 for (
size_t lid = 0; lid < map.getLocalNumElements(); lid += block_size) {
491 auto lbid = floor(
double(lid) / block_size);
492 auto gbid = floor(
double(map.getGlobalElement(lid)) / block_size);
494 for (
size_t lid2 = 1; lid2 < block_size; ++lid2) {
495 auto lbid_n = floor(
double(lid + lid2) / block_size);
496 auto gbid_n = floor(
double(map.getGlobalElement(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;
void getPids(const Tpetra::Import< LocalOrdinal, GlobalOrdinal, Node > &Importer, Teuchos::Array< int > &pids, bool use_minus_one_for_local)
Like getPidGidPairs, but just gets the PIDs, ordered by the column Map.
void getRemotePIDs(const Tpetra::Import< LocalOrdinal, GlobalOrdinal, Node > &Importer, Teuchos::Array< int > &RemotePIDs)
Get a list of remote PIDs from an importer in the order corresponding to the remote LIDs.
void getPidGidPairs(const Tpetra::Import< LocalOrdinal, GlobalOrdinal, Node > &Importer, Teuchos::Array< std::pair< int, GlobalOrdinal > > &gpids, bool use_minus_one_for_local)
For each GID in the TargetMap, find who owns the GID in the SourceMap.
Stand-alone utility functions and macros.
Struct that holds views of the contents of a CrsMatrix.
Sets up and executes a communication plan for a Tpetra DistObject.
Namespace Tpetra contains the class and methods constituting the Tpetra library.