42 #ifndef TPETRA_IMPORT_UTIL_HPP
43 #define TPETRA_IMPORT_UTIL_HPP
51 #include "Tpetra_ConfigDefs.hpp"
52 #include "Tpetra_Import.hpp"
53 #include "Tpetra_HashTable.hpp"
54 #include "Tpetra_Map.hpp"
56 #include "Tpetra_Distributor.hpp"
57 #include <Teuchos_Array.hpp>
61 namespace Import_Util {
68 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
71 Teuchos::Array< std::pair<int,GlobalOrdinal> >& gpids,
72 bool use_minus_one_for_local);
75 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
78 Teuchos::Array<int>& pids,
79 bool use_minus_one_for_local);
83 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
86 Teuchos::ArrayView<int>& pids,
87 bool use_minus_one_for_local);
92 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
95 Teuchos::Array<int>& RemotePIDs);
101 namespace Import_Util {
103 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
106 Teuchos::Array< std::pair<int,GlobalOrdinal> >& gpids,
107 bool use_minus_one_for_local)
116 int mypid = Importer.
getTargetMap()->getComm()->getRank();
117 size_t N = Importer.
getTargetMap()->getNodeNumElements();
120 Teuchos::ArrayView<const LocalOrdinal> RemoteLIDs = Importer.
getRemoteLIDs();
124 Teuchos::ArrayView<const int> ProcsFrom = D.
getProcsFrom();
125 Teuchos::ArrayView<const size_t> LengthsFrom = D.
getLengthsFrom();
131 LocalOrdinal lzero = Teuchos::ScalarTraits<LocalOrdinal>::zero();
132 if(use_minus_one_for_local)
133 for(ii=lzero; Teuchos::as<size_t>(ii)<N; ii++) gpids[ii]=std::make_pair(-1,Importer.
getTargetMap()->getGlobalElement(ii));
135 for(ii=lzero; Teuchos::as<size_t>(ii)<N; ii++) gpids[ii]=std::make_pair(mypid,Importer.
getTargetMap()->getGlobalElement(ii));
139 for(i=0,j=0; i<NumReceives; i++){
140 int pid=ProcsFrom[i];
141 for(k=0; k<LengthsFrom[i]; k++){
142 if(pid!=mypid) gpids[RemoteLIDs[j]].first=pid;
148 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
151 Teuchos::Array<int>& pids,
152 bool use_minus_one_for_local)
155 pids.resize(Importer.
getTargetMap()->getNodeNumElements());
156 Teuchos::ArrayView<int> v_pids = pids();
157 getPids(Importer,v_pids,use_minus_one_for_local);
161 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
164 Teuchos::ArrayView<int>& pids,
165 bool use_minus_one_for_local)
171 int mypid = Importer.
getTargetMap()->getComm()->getRank();
172 size_t N = Importer.
getTargetMap()->getNodeNumElements();
173 if(N!=(
size_t)pids.size())
throw std::runtime_error(
"Tpetra::Import_Util::getPids(): Incorrect size for output array");
176 Teuchos::ArrayView<const LocalOrdinal> RemoteLIDs = Importer.
getRemoteLIDs();
180 Teuchos::ArrayView<const int> ProcsFrom = D.
getProcsFrom();
181 Teuchos::ArrayView<const size_t> LengthsFrom = D.
getLengthsFrom();
184 LocalOrdinal lzero = Teuchos::ScalarTraits<LocalOrdinal>::zero();
185 if(use_minus_one_for_local)
186 for(ii=lzero; Teuchos::as<size_t>(ii)<N; ii++) pids[ii]=-1;
188 for(ii=lzero; Teuchos::as<size_t>(ii)<N; ii++) pids[ii]=mypid;
192 for(i=0,j=0; i<NumReceives; i++){
193 int pid=ProcsFrom[i];
194 for(k=0; k<LengthsFrom[i]; k++){
195 if(pid!=mypid) pids[RemoteLIDs[j]]=pid;
201 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
204 Teuchos::Array<int>& RemotePIDs)
209 Teuchos::ArrayView<const LocalOrdinal> RemoteLIDs = Importer.
getRemoteLIDs();
213 Teuchos::ArrayView<const int> ProcsFrom = D.
getProcsFrom();
214 Teuchos::ArrayView<const size_t> LengthsFrom = D.
getLengthsFrom();
223 for (i = 0, j = 0; i < NumReceives; ++i) {
224 const int pid = ProcsFrom[i];
225 for (k = 0; k < LengthsFrom[i]; ++k) {
235 template <
typename LocalOrdinal,
typename GlobalOrdinal,
typename Node>
240 RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > source = Importer.
getSourceMap();
241 RCP<const Tpetra::Map<LocalOrdinal,GlobalOrdinal,Node> > target = Importer.
getTargetMap();
242 RCP<const Teuchos::Comm<int> > comm = source->getComm();
245 if (!source->isDistributed())
return true;
247 int global_is_valid=0;
252 LocalOrdinal LO_INVALID = Teuchos::OrdinalTraits<LocalOrdinal>::invalid();
253 const int MyPID = comm->getRank();
254 const int NumProcs = comm->getSize();
256 GlobalOrdinal minSourceGID = source->getMinAllGlobalIndex();
257 GlobalOrdinal maxSourceGID = source->getMaxAllGlobalIndex();
258 GlobalOrdinal minTargetGID = target->getMinAllGlobalIndex();
259 GlobalOrdinal maxTargetGID = target->getMaxAllGlobalIndex();
261 std::ostringstream os;
267 Teuchos::ArrayView<const LocalOrdinal> permuteTarget = Importer.
getPermuteToLIDs();
268 Teuchos::ArrayView<const LocalOrdinal> remoteLIDs = Importer.
getRemoteLIDs();
269 Teuchos::ArrayView<const LocalOrdinal> exportLIDs = Importer.
getExportLIDs();
270 Teuchos::ArrayView<const LocalOrdinal> exportPIDs = Importer.
getExportPIDs();
271 Teuchos::Array<int> remotePIDs; getRemotePIDs(Importer,remotePIDs);
274 Teuchos::Array<GlobalOrdinal> remoteGIDs(remoteLIDs.size());
275 for(
size_t i=0; i<(size_t)remoteLIDs.size(); i++) {
276 remoteGIDs[i] = target->getGlobalElement(remoteLIDs[i]);
277 if(remoteGIDs[i]<0) {
278 os<<MyPID<<
"ERROR3: source->getGlobalElement(remoteLIDs[l]) is invalid GID="<<remoteGIDs[i]<<
" LID= "<<remoteLIDs[i]<<std::endl;
283 Teuchos::Array<GlobalOrdinal> exportGIDs(exportLIDs.size(),-1);
284 for(
size_t i=0; i<(size_t)exportLIDs.size(); i++) {
285 exportGIDs[i] = source->getGlobalElement(exportLIDs[i]);
286 exportGIDs[i]=source->getGlobalElement(exportLIDs[i]);
287 if(exportGIDs[i]<0) {
288 os<<MyPID<<
"ERROR3: source->getGlobalElement(exportLIDs[l]) is invalid GID="<<exportGIDs[i]<<
" LID= "<<exportLIDs[i]<<std::endl;
294 for(
auto &&rgid : remoteGIDs) {
295 if(std::find(exportGIDs.begin(),exportGIDs.end(),rgid) != exportGIDs.end()) {
297 os<<MyPID<<
"ERROR0: Overlap between remoteGIDs and exportGIDs "<<rgid<<std::endl;
301 int TempPID , OwningPID;
302 for(GlobalOrdinal i=minSourceGID; i<maxSourceGID; i++) {
306 LocalOrdinal slid = source->getLocalElement(i);
307 if(slid == LO_INVALID) TempPID = -1;
308 else TempPID = MyPID;
309 Teuchos::reduceAll<int, int> (*comm, Teuchos::REDUCE_MAX,TempPID, Teuchos::outArg(OwningPID));
312 LocalOrdinal tlid = target->getLocalElement(i);
314 if(tlid != LO_INVALID) {
319 if(OwningPID == -1)
continue;
321 if (OwningPID == MyPID) {
329 for (
size_t j=0; j<(size_t)permuteTarget.size(); j++) {
330 if(tlid == permuteTarget[j]) {
339 bool already_hit =
false;
340 for(
size_t j=0; j<(size_t)remoteGIDs.size(); j++) {
341 if(i == remoteGIDs[j]) {
348 if(OwningPID == remotePIDs[j]) {
356 os<<MyPID<<
" ERROR1: GID "<<i<<
" should be remoted from PID "<<OwningPID<<
" but isn't."<<std::endl;
366 Teuchos::Array<int> local_proc_mask(NumProcs,0), global_proc_mask(NumProcs,0);
369 for(GlobalOrdinal i=minTargetGID; i<maxTargetGID; i++) {
372 LocalOrdinal tlid = target->getLocalElement(i);
373 LocalOrdinal slid = source->getLocalElement(i);
375 if(tlid==LO_INVALID) local_proc_mask[MyPID] = 0;
376 else local_proc_mask[MyPID] = 1;
378 Teuchos::reduceAll<int,int>(*comm,Teuchos::REDUCE_MAX,NumProcs, &local_proc_mask[0],&global_proc_mask[0]);
381 if(slid !=LO_INVALID) {
383 for(
int j=0; j<NumProcs; j++) {
384 if(j==MyPID)
continue;
385 if(global_proc_mask[j]==1) {
388 bool already_hit =
false;
389 for(
size_t k=0; k<(size_t)exportPIDs.size(); k++) {
390 if (exportPIDs[k] == j && source->getGlobalElement(exportLIDs[k]) == i) {
403 os<<MyPID<<
" ERROR2: GID "<<i<<
" should be sent to PID "<<j<<
" but isn't"<<std::endl;
413 Teuchos::Array<int> proc_num_exports_recv(NumProcs,0);
415 Teuchos::Array<int> remoteGIDcount(remoteGIDs.size(),0);
418 Teuchos::reduceAll<int,int>(*comm,Teuchos::REDUCE_MAX,exportGIDs.size(), Teuchos::outArg(allexpsiz));
420 for(
int i=0;i<allexpsiz;++i) {
421 Teuchos::Array<GlobalOrdinal> myexpgid(NumProcs,-2), yourexpgid(NumProcs,-2);
422 Teuchos::Array<int> myexppid(NumProcs,-2), yourexppid(NumProcs,-2);
423 if(i<exportGIDs.size()) {
424 myexpgid[MyPID] = exportGIDs[i];
425 myexppid[MyPID] = exportPIDs[i];
427 Teuchos::reduceAll<int,GlobalOrdinal>(*comm,Teuchos::REDUCE_MAX,NumProcs, &myexpgid[0],&yourexpgid[0]);
428 Teuchos::reduceAll<int,int>(*comm,Teuchos::REDUCE_MAX,NumProcs, &myexppid[0],&yourexppid[0]);
429 for(
int p=0;p<NumProcs;++p) {
430 GlobalOrdinal cgid = yourexpgid[p];
432 if(cgid == -2)
continue;
434 os<<MyPID<<
" ERROR4: received exportGID is invalid "<<cgid<<std::endl;
438 for(
size_t k=0;k<(size_t)remoteGIDs.size();++k) {
439 if(cgid == remoteGIDs[k] && yourexppid[p] == MyPID ) {
440 if(p != remotePIDs[k]) {
441 os<<MyPID<<
" ERROR5: receive export from wrong pid: got "<<p<<
" expected: "<<remotePIDs[k]<<std::endl;
446 os<<MyPID<<
" ERROR6: found multiple GIDs from correct pid: GID "<<remoteGIDs[k]<<std::endl;
452 if(!foundit && yourexppid[p] == MyPID ) {
453 os<<MyPID<<
" ERROR7: receive gid "<<cgid<<
" that is not in my remote gid list, from pid "<<p<<std::endl;
460 for(
size_t i = 0; i< (size_t) remoteGIDcount.size(); ++i) {
461 int rc = remoteGIDcount[i];
462 if(rc == 1)
continue;
463 os<<MyPID<<
" ERROR8: my remote at "<<i<<
" gid "<<remoteGIDs[i]<<
" has count "<<rc<<std::endl;
469 Teuchos::reduceAll<int,int> (*comm, Teuchos::REDUCE_MIN,(int)is_valid, Teuchos::outArg(global_is_valid));
471 if(!global_is_valid) {
472 std::cerr<<os.str()<<std::flush;
473 Importer.
print(std::cout);
476 return global_is_valid>0;
484 #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.
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.
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.
::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.