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>
39 Teuchos::Array< std::pair<int,GlobalOrdinal> >& gpids,
40 bool use_minus_one_for_local);
43 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
46 Teuchos::Array<int>& pids,
47 bool use_minus_one_for_local);
51 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
54 Teuchos::ArrayView<int>& pids,
55 bool use_minus_one_for_local);
60 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
63 Teuchos::Array<int>& RemotePIDs);
69namespace Import_Util {
71template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
74 Teuchos::Array< std::pair<int,GlobalOrdinal> >&
gpids,
85 size_t N =
Importer.getTargetMap()->getLocalNumElements();
92 Teuchos::ArrayView<const int>
ProcsFrom =
D.getProcsFrom();
93 Teuchos::ArrayView<const size_t>
LengthsFrom =
D.getLengthsFrom();
116template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
119 Teuchos::Array<int>&
pids,
123 pids.resize(
Importer.getTargetMap()->getLocalNumElements());
129template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
132 Teuchos::ArrayView<int>&
pids,
140 size_t N =
Importer.getTargetMap()->getLocalNumElements();
141 if(
N!=(
size_t)
pids.size())
throw std::runtime_error(
"Tpetra::Import_Util::getPids(): Incorrect size for output array");
148 Teuchos::ArrayView<const int>
ProcsFrom =
D.getProcsFrom();
149 Teuchos::ArrayView<const size_t>
LengthsFrom =
D.getLengthsFrom();
169template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
181 Teuchos::ArrayView<const int>
ProcsFrom =
D.getProcsFrom();
182 Teuchos::ArrayView<const size_t>
LengthsFrom =
D.getLengthsFrom();
203template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
213 if (!
source->isDistributed())
return true;
221 const int MyPID = comm->getRank();
222 const int NumProcs = comm->getSize();
229 std::ostringstream
os;
236 Teuchos::ArrayView<const LocalOrdinal> remoteLIDs =
Importer.getRemoteLIDs();
239 Teuchos::Array<int> remotePIDs; getRemotePIDs(
Importer,remotePIDs);
242 Teuchos::Array<GlobalOrdinal> remoteGIDs(remoteLIDs.size());
243 for(
size_t i=0;
i<(
size_t)remoteLIDs.size();
i++) {
244 remoteGIDs[
i] =
target->getGlobalElement(remoteLIDs[
i]);
245 if(remoteGIDs[
i]<0) {
246 os<<
MyPID<<
"ERROR3: source->getGlobalElement(remoteLIDs[l]) is invalid GID="<<remoteGIDs[
i]<<
" LID= "<<remoteLIDs[
i]<<std::endl;
251 Teuchos::Array<GlobalOrdinal> exportGIDs(exportLIDs.size(),-1);
252 for(
size_t i=0; i<(size_t)exportLIDs.size(); i++) {
253 exportGIDs[i] = source->getGlobalElement(exportLIDs[i]);
254 exportGIDs[i]=source->getGlobalElement(exportLIDs[i]);
255 if(exportGIDs[i]<0) {
256 os<<MyPID<<
"ERROR3: source->getGlobalElement(exportLIDs[l]) is invalid GID="<<exportGIDs[i]<<
" LID= "<<exportLIDs[i]<<std::endl;
262 for(
auto &&rgid : remoteGIDs) {
263 if(std::find(exportGIDs.begin(),exportGIDs.end(),rgid) != exportGIDs.end()) {
265 os<<MyPID<<
"ERROR0: Overlap between remoteGIDs and exportGIDs "<<rgid<<std::endl;
269 int TempPID , OwningPID;
270 for(GlobalOrdinal i=minSourceGID; i<maxSourceGID; i++) {
274 LocalOrdinal slid = source->getLocalElement(i);
275 if(slid == LO_INVALID) TempPID = -1;
276 else TempPID = MyPID;
277 Teuchos::reduceAll<int, int> (*comm, Teuchos::REDUCE_MAX,TempPID, Teuchos::outArg(OwningPID));
280 LocalOrdinal tlid = target->getLocalElement(i);
282 if(tlid != LO_INVALID) {
287 if(OwningPID == -1)
continue;
289 if (OwningPID == MyPID) {
291 if((
size_t) tlid < Importer.getNumSameIDs()) {
297 for (
size_t j=0; j<(size_t)permuteTarget.size(); j++) {
298 if(tlid == permuteTarget[j]) {
307 bool already_hit =
false;
308 for(
size_t j=0; j<(size_t)remoteGIDs.size(); j++) {
309 if(i == remoteGIDs[j]) {
316 if(OwningPID == remotePIDs[j]) {
324 os<<MyPID<<
" ERROR1: GID "<<i<<
" should be remoted from PID "<<OwningPID<<
" but isn't."<<std::endl;
334 Teuchos::Array<int> local_proc_mask(NumProcs,0), global_proc_mask(NumProcs,0);
337 for(GlobalOrdinal i=minTargetGID; i<maxTargetGID; i++) {
340 LocalOrdinal tlid = target->getLocalElement(i);
341 LocalOrdinal slid = source->getLocalElement(i);
343 if(tlid==LO_INVALID) local_proc_mask[MyPID] = 0;
344 else local_proc_mask[MyPID] = 1;
346 Teuchos::reduceAll<int,int>(*comm,Teuchos::REDUCE_MAX,NumProcs, &local_proc_mask[0],&global_proc_mask[0]);
349 if(slid !=LO_INVALID) {
351 for(
int j=0; j<NumProcs; j++) {
352 if(j==MyPID)
continue;
353 if(global_proc_mask[j]==1) {
356 bool already_hit =
false;
357 for(
size_t k=0; k<(size_t)exportPIDs.size(); k++) {
358 if (exportPIDs[k] == j && source->getGlobalElement(exportLIDs[k]) == i) {
371 os<<MyPID<<
" ERROR2: GID "<<i<<
" should be sent to PID "<<j<<
" but isn't"<<std::endl;
381 Teuchos::Array<int> proc_num_exports_recv(NumProcs,0);
383 Teuchos::Array<int> remoteGIDcount(remoteGIDs.size(),0);
386 Teuchos::reduceAll<int,int>(*comm,Teuchos::REDUCE_MAX,exportGIDs.size(), Teuchos::outArg(allexpsiz));
388 for(
int i=0;i<allexpsiz;++i) {
389 Teuchos::Array<GlobalOrdinal> myexpgid(NumProcs,-2), yourexpgid(NumProcs,-2);
390 Teuchos::Array<int> myexppid(NumProcs,-2), yourexppid(NumProcs,-2);
391 if(i<exportGIDs.size()) {
392 myexpgid[MyPID] = exportGIDs[i];
393 myexppid[MyPID] = exportPIDs[i];
395 Teuchos::reduceAll<int,GlobalOrdinal>(*comm,Teuchos::REDUCE_MAX,NumProcs, &myexpgid[0],&yourexpgid[0]);
396 Teuchos::reduceAll<int,int>(*comm,Teuchos::REDUCE_MAX,NumProcs, &myexppid[0],&yourexppid[0]);
397 for(
int p=0;p<NumProcs;++p) {
398 GlobalOrdinal cgid = yourexpgid[p];
400 if(cgid == -2)
continue;
402 os<<MyPID<<
" ERROR4: received exportGID is invalid "<<cgid<<std::endl;
406 for(
size_t k=0;k<(size_t)remoteGIDs.size();++k) {
407 if(cgid == remoteGIDs[k] && yourexppid[p] == MyPID ) {
408 if(p != remotePIDs[k]) {
409 os<<MyPID<<
" ERROR5: receive export from wrong pid: got "<<p<<
" expected: "<<remotePIDs[k]<<std::endl;
414 os<<MyPID<<
" ERROR6: found multiple GIDs from correct pid: GID "<<remoteGIDs[k]<<std::endl;
420 if(!foundit && yourexppid[p] == MyPID ) {
421 os<<MyPID<<
" ERROR7: receive gid "<<cgid<<
" that is not in my remote gid list, from pid "<<p<<std::endl;
428 for(
size_t i = 0; i< (size_t) remoteGIDcount.size(); ++i) {
429 int rc = remoteGIDcount[i];
430 if(rc == 1)
continue;
431 os<<MyPID<<
" ERROR8: my remote at "<<i<<
" gid "<<remoteGIDs[i]<<
" has count "<<rc<<std::endl;
437 Teuchos::reduceAll<int,int> (*comm, Teuchos::REDUCE_MIN,(
int)is_valid, Teuchos::outArg(global_is_valid));
439 if(!global_is_valid) {
440 std::cerr<<os.str()<<std::flush;
441 Importer.print(std::cout);
444 return global_is_valid>0;
449template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
454 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > source = Importer.getSourceMap();
455 Teuchos::RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > target = Importer.getTargetMap();
458 Teuchos::Array<std::pair<int, GlobalOrdinal> > gpids;
462 bool is_local =
true;
464 GlobalOrdinal INVALID = Teuchos::OrdinalTraits<GlobalOrdinal>::invalid();
465 GlobalOrdinal last_GID = Teuchos::OrdinalTraits<GlobalOrdinal>::invalid();
467 for(
size_t i=0; i<(size_t) gpids.size(); i++) {
468 int pid = gpids[i].first;
469 GlobalOrdinal gid = gpids[i].second;
471 if(is_local ==
false && pid == -1) {
478 if(source->getGlobalElement(i) != target->getGlobalElement(i)) {
491 else if(pid < last_PID) {
496 else if(pid == last_PID) {
516template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
519 bool consistent_block =
true;
521 for (
size_t lid = 0; lid < map.getLocalNumElements (); lid += block_size) {
522 auto lbid = floor(
double(lid)/block_size);
523 auto gbid = floor(
double(map.getGlobalElement(lid))/block_size);
525 for (
size_t lid2 = 1; lid2 < block_size; ++lid2) {
526 auto lbid_n = floor(
double(lid+lid2)/block_size);
527 auto gbid_n = floor(
double(map.getGlobalElement(lid+lid2))/block_size);
528 if (consistent_block)
529 consistent_block = (lbid == lbid_n);
530 if (consistent_block)
531 consistent_block = (gbid == gbid_n);
535 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.