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);
69 namespace Import_Util {
71 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
74 Teuchos::Array< std::pair<int,GlobalOrdinal> >& gpids,
75 bool use_minus_one_for_local)
84 int mypid = Importer.
getTargetMap()->getComm()->getRank();
85 size_t N = Importer.
getTargetMap()->getLocalNumElements();
88 Teuchos::ArrayView<const LocalOrdinal> RemoteLIDs = Importer.
getRemoteLIDs();
92 Teuchos::ArrayView<const int> ProcsFrom = D.
getProcsFrom();
99 LocalOrdinal lzero = Teuchos::ScalarTraits<LocalOrdinal>::zero();
100 if(use_minus_one_for_local)
101 for(ii=lzero; Teuchos::as<size_t>(ii)<N; ii++) gpids[ii]=std::make_pair(-1,Importer.
getTargetMap()->getGlobalElement(ii));
103 for(ii=lzero; Teuchos::as<size_t>(ii)<N; ii++) gpids[ii]=std::make_pair(mypid,Importer.
getTargetMap()->getGlobalElement(ii));
107 for(i=0,j=0; i<NumReceives; i++){
108 int pid=ProcsFrom[i];
109 for(k=0; k<LengthsFrom[i]; k++){
110 if(pid!=mypid) gpids[RemoteLIDs[j]].first=pid;
116 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
119 Teuchos::Array<int>& pids,
120 bool use_minus_one_for_local)
123 pids.resize(Importer.
getTargetMap()->getLocalNumElements());
124 Teuchos::ArrayView<int> v_pids = pids();
125 getPids(Importer,v_pids,use_minus_one_for_local);
129 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
132 Teuchos::ArrayView<int>& pids,
133 bool use_minus_one_for_local)
139 int mypid = Importer.
getTargetMap()->getComm()->getRank();
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");
144 Teuchos::ArrayView<const LocalOrdinal> RemoteLIDs = Importer.
getRemoteLIDs();
148 Teuchos::ArrayView<const int> ProcsFrom = D.
getProcsFrom();
149 Teuchos::ArrayView<const size_t> LengthsFrom = D.
getLengthsFrom();
152 LocalOrdinal lzero = Teuchos::ScalarTraits<LocalOrdinal>::zero();
153 if(use_minus_one_for_local)
154 for(ii=lzero; Teuchos::as<size_t>(ii)<N; ii++) pids[ii]=-1;
156 for(ii=lzero; Teuchos::as<size_t>(ii)<N; ii++) pids[ii]=mypid;
160 for(i=0,j=0; i<NumReceives; i++){
161 int pid=ProcsFrom[i];
162 for(k=0; k<LengthsFrom[i]; k++){
163 if(pid!=mypid) pids[RemoteLIDs[j]]=pid;
169 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
172 Teuchos::Array<int>& RemotePIDs)
177 Teuchos::ArrayView<const LocalOrdinal> RemoteLIDs = Importer.
getRemoteLIDs();
181 Teuchos::ArrayView<const int> ProcsFrom = D.
getProcsFrom();
182 Teuchos::ArrayView<const size_t> LengthsFrom = D.
getLengthsFrom();
191 for (i = 0, j = 0; i < NumReceives; ++i) {
192 const int pid = ProcsFrom[i];
193 for (k = 0; k < LengthsFrom[i]; ++k) {
203 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
208 RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > source = Importer.
getSourceMap();
209 RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > target = Importer.
getTargetMap();
210 RCP<const Teuchos::Comm<int> > comm = source->getComm();
213 if (!source->isDistributed())
return true;
215 int global_is_valid=0;
220 LocalOrdinal LO_INVALID = Teuchos::OrdinalTraits<LocalOrdinal>::invalid();
221 const int MyPID = comm->getRank();
222 const int NumProcs = comm->getSize();
224 GlobalOrdinal minSourceGID = source->getMinAllGlobalIndex();
225 GlobalOrdinal maxSourceGID = source->getMaxAllGlobalIndex();
226 GlobalOrdinal minTargetGID = target->getMinAllGlobalIndex();
227 GlobalOrdinal maxTargetGID = target->getMaxAllGlobalIndex();
229 std::ostringstream os;
235 Teuchos::ArrayView<const LocalOrdinal> permuteTarget = Importer.
getPermuteToLIDs();
236 Teuchos::ArrayView<const LocalOrdinal> remoteLIDs = Importer.
getRemoteLIDs();
237 Teuchos::ArrayView<const LocalOrdinal> exportLIDs = Importer.
getExportLIDs();
238 Teuchos::ArrayView<const LocalOrdinal> exportPIDs = Importer.
getExportPIDs();
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) {
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;
449 template <
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;
459 getPidGidPairs (Importer, gpids,
true);
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) {
516 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
519 bool consistent_block =
true;
522 auto lbid = floor(
double(lid)/block_size);
525 for (
size_t lid2 = 1; lid2 < block_size; ++lid2) {
526 auto lbid_n = floor(
double(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;
542 #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.