Tpetra parallel linear algebra  Version of the Day
Tpetra_Import_def.hpp
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Tpetra: Templated Linear Algebra Services Package
5 // Copyright (2008) Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ************************************************************************
40 // @HEADER
41 
42 #ifndef TPETRA_IMPORT_DEF_HPP
43 #define TPETRA_IMPORT_DEF_HPP
44 
45 #include <Tpetra_Import_decl.hpp>
46 #include <Tpetra_Distributor.hpp>
47 #include <Tpetra_Map.hpp>
48 #include <Tpetra_ImportExportData.hpp>
49 #include <Tpetra_Util.hpp>
50 #include <Tpetra_Import_Util.hpp>
51 #include <Tpetra_Export.hpp>
52 #include <Teuchos_as.hpp>
53 
54 
55 namespace {
56  // Default value of Import's "Debug" parameter.
57  const bool tpetraImportDebugDefault = false;
58 } // namespace (anonymous)
59 
60 namespace Tpetra {
61 
62  template <class LocalOrdinal, class GlobalOrdinal, class Node>
63  void
65  setParameterList (const Teuchos::RCP<Teuchos::ParameterList>& plist)
66  {
67  bool debug = tpetraImportDebugDefault;
68  if (! plist.is_null ()) {
69  try {
70  debug = plist->get<bool> ("Debug");
71  } catch (Teuchos::Exceptions::InvalidParameter&) {}
72  }
73  debug_ = debug;
74  ImportData_->distributor_.setParameterList (plist);
75  }
76 
77  template <class LocalOrdinal, class GlobalOrdinal, class Node>
78  void
80  init (const Teuchos::RCP<const map_type>& source,
81  const Teuchos::RCP<const map_type>& target,
82  bool useRemotePIDs,
83  Teuchos::Array<int> & remotePIDs,
84  const Teuchos::RCP<Teuchos::ParameterList>& plist)
85  {
86  using Teuchos::Array;
87  using Teuchos::null;
88  using Teuchos::Ptr;
89  using Teuchos::rcp;
90  using std::endl;
92 
93  // Read "Debug" parameter from the input ParameterList.
94  bool debug = tpetraImportDebugDefault;
95  if (! plist.is_null ()) {
96  try {
97  debug = plist->get<bool> ("Debug");
98  } catch (Teuchos::Exceptions::InvalidParameter&) {}
99  }
100  debug_ = debug;
101 
102  if (! out_.is_null ()) {
103  out_->pushTab ();
104  }
105  if (debug_) {
106  std::ostringstream os;
107  const int myRank = source->getComm ()->getRank ();
108  os << myRank << ": Import ctor" << endl;
109  *out_ << os.str ();
110  }
111  ImportData_ = rcp (new data_type (source, target, out_, plist));
112 
113  Array<GlobalOrdinal> remoteGIDs;
114  setupSamePermuteRemote (remoteGIDs);
115  if (debug_) {
116  std::ostringstream os;
117  const int myRank = source->getComm ()->getRank ();
118  os << myRank << ": Import ctor: "
119  << "setupSamePermuteRemote done" << endl;
120  *out_ << os.str ();
121  }
122  if (source->isDistributed ()) {
123  setupExport (remoteGIDs,useRemotePIDs,remotePIDs);
124  }
125  if (debug_) {
126  std::ostringstream os;
127  const int myRank = source->getComm ()->getRank ();
128  os << myRank << ": Import ctor: done" << endl;
129  *out_ << os.str ();
130  }
131  if (! out_.is_null ()) {
132  out_->popTab ();
133  }
134  }
135 
136  template <class LocalOrdinal, class GlobalOrdinal, class Node>
138  Import (const Teuchos::RCP<const map_type >& source,
139  const Teuchos::RCP<const map_type >& target) :
140  out_ (Teuchos::getFancyOStream (Teuchos::rcpFromRef (std::cerr))),
141  debug_ (tpetraImportDebugDefault)
142  {
143  Teuchos::Array<int> dummy;
144  init (source, target, false, dummy, Teuchos::null);
145  }
146 
147  template <class LocalOrdinal, class GlobalOrdinal, class Node>
149  Import (const Teuchos::RCP<const map_type >& source,
150  const Teuchos::RCP<const map_type >& target,
151  const Teuchos::RCP<Teuchos::FancyOStream>& out) :
152  out_ (out),
153  debug_ (tpetraImportDebugDefault)
154  {
155  Teuchos::Array<int> dummy;
156  init (source, target, false, dummy, Teuchos::null);
157  }
158 
159  template <class LocalOrdinal, class GlobalOrdinal, class Node>
161  Import (const Teuchos::RCP<const map_type >& source,
162  const Teuchos::RCP<const map_type >& target,
163  const Teuchos::RCP<Teuchos::ParameterList>& plist) :
164  out_ (Teuchos::getFancyOStream (Teuchos::rcpFromRef (std::cerr))),
165  debug_ (tpetraImportDebugDefault)
166  {
167  Teuchos::Array<int> dummy;
168  init (source, target, false, dummy, plist);
169  }
170 
171  template <class LocalOrdinal, class GlobalOrdinal, class Node>
173  Import (const Teuchos::RCP<const map_type >& source,
174  const Teuchos::RCP<const map_type >& target,
175  const Teuchos::RCP<Teuchos::FancyOStream>& out,
176  const Teuchos::RCP<Teuchos::ParameterList>& plist) :
177  out_ (out),
178  debug_ (tpetraImportDebugDefault)
179  {
180  Teuchos::Array<int> dummy;
181  init (source, target, false, dummy, plist);
182  }
183 
184  template <class LocalOrdinal, class GlobalOrdinal, class Node>
186  Import (const Teuchos::RCP<const map_type >& source,
187  const Teuchos::RCP<const map_type >& target,
188  Teuchos::Array<int> & remotePIDs) :
189  debug_ (tpetraImportDebugDefault)
190  {
191  init (source, target, true, remotePIDs, Teuchos::null);
192  }
193 
194 
195  template <class LocalOrdinal, class GlobalOrdinal, class Node>
198  : ImportData_ (rhs.ImportData_)
199  , out_ (rhs.out_)
200  , debug_ (rhs.debug_)
201  {}
202 
203  template <class LocalOrdinal, class GlobalOrdinal, class Node>
206  : out_ (exporter.out_)
207  , debug_ (exporter.debug_)
208  {
209  if (! exporter.ExportData_.is_null ()) {
210  ImportData_ = exporter.ExportData_->reverseClone ();
211  }
212  }
213 
214  // This is the "createExpert" version of the constructor
215 
216  template <class LocalOrdinal, class GlobalOrdinal, class Node>
218  Import(const Teuchos::RCP<const Map<LocalOrdinal, GlobalOrdinal, Node> >& source,
219  const Teuchos::RCP<const Map<LocalOrdinal, GlobalOrdinal, Node> >& target,
220  Teuchos::Array<int>& userRemotePIDs,
221  Teuchos::Array<GlobalOrdinal>& remoteGIDs,
222  const Teuchos::ArrayView<const LocalOrdinal> & userExportLIDs,
223  const Teuchos::ArrayView<const int> & userExportPIDs,
224  const bool useRemotePIDGID,
225  const Teuchos::RCP<Teuchos::ParameterList>& plist,
226  const Teuchos::RCP<Teuchos::FancyOStream>& out) :
227  out_ (out.is_null () ?
228  Teuchos::getFancyOStream (Teuchos::rcpFromRef (std::cerr)) : out)
229  {
230  using Teuchos::arcp;
231  using Teuchos::Array;
232  using Teuchos::ArrayRCP;
233  using Teuchos::ArrayView;
234  using Teuchos::as;
235  using Teuchos::null;
236  using Teuchos::rcp;
237  typedef LocalOrdinal LO;
238  typedef GlobalOrdinal GO;
239  typedef Teuchos::Array<int>::size_type size_type;
241 
242  out_->pushTab ();
243 
244  ArrayView<const GO> sourceGIDs = source->getNodeElementList ();
245  ArrayView<const GO> targetGIDs = target->getNodeElementList ();
246  const size_type numSrcGids = sourceGIDs.size ();
247  const size_type numTgtGids = targetGIDs.size ();
248  const size_type numGids = std::min (numSrcGids, numTgtGids);
249 
250  size_type numSameGids = 0;
251  for ( ; numSameGids < numGids && sourceGIDs[numSameGids] == targetGIDs[numSameGids]; ++numSameGids)
252  {}
253 
254  // Read "Debug" parameter from the input ParameterList.
255  bool debug = tpetraImportDebugDefault;
256  if (! plist.is_null ()) {
257  try {
258  debug = plist->get<bool> ("Debug");
259  } catch (Teuchos::Exceptions::InvalidParameter&) {}
260  }
261  debug_ = debug;
262 
263  if (debug_ && ! out_.is_null ()) {
264  std::ostringstream os;
265  const int myRank = source->getComm ()->getRank ();
266  os << myRank << ": constructExpert " << std::endl;
267  *out_ << os.str ();
268  }
269  ImportData_ = rcp (new data_type (source, target, out_, plist));
270  ImportData_->numSameIDs_ = numSameGids;
271 
272  Array<LO>& permuteToLIDs = ImportData_->permuteToLIDs_;
273  Array<LO>& permuteFromLIDs = ImportData_->permuteFromLIDs_;
274  Array<LO>& remoteLIDs = ImportData_->remoteLIDs_;
275  const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid ();
276  const LO numTgtLids = as<LO> (numTgtGids);
277 
278  if(!useRemotePIDGID) {
279  remoteGIDs.clear();
280  remoteLIDs.clear();
281  }
282 
283  for (LO tgtLid = numSameGids; tgtLid < numTgtLids; ++tgtLid) {
284  const GO curTargetGid = targetGIDs[tgtLid];
285  // getLocalElement() returns LINVALID if the GID isn't in the source Map.
286  const LO srcLid = source->getLocalElement (curTargetGid);
287  if (srcLid != LINVALID) {
288  permuteToLIDs.push_back (tgtLid);
289  permuteFromLIDs.push_back (srcLid);
290  } else {
291  if(!useRemotePIDGID) {
292  remoteGIDs.push_back (curTargetGid);
293  remoteLIDs.push_back (tgtLid);
294  }
295  }
296  }
297 
299  getNumRemoteIDs() > 0 && ! source->isDistributed(),
300  std::runtime_error,
301  "::constructExpert(): Target has remote LIDs but Source is not "
302  "distributed globally." << std::endl
303  << "Importing to a submap of the target map.");
304 
305  Array<int> remotePIDs;
306  remotePIDs.resize (remoteGIDs.size (),0);
307  LookupStatus lookup = AllIDsPresent;
308 
309  ArrayView<GO> remoteGIDsView = remoteGIDs ();
310  lookup = source->getRemoteIndexList (remoteGIDsView, remotePIDs ());
311  remoteGIDsView = remoteGIDs ();
312 
313  Array<int>& remoteProcIDs = (useRemotePIDGID) ? userRemotePIDs : remotePIDs;
314 
315  TEUCHOS_TEST_FOR_EXCEPTION( lookup == IDNotPresent, std::runtime_error,
316  "Import::Import createExpert: the source Map wasn't able to figure out which process "
317  "owns one or more of the GIDs in the list of remote GIDs. This probably "
318  "means that there is at least one GID owned by some process in the target"
319  " Map which is not owned by any process in the source Map. (That is, the"
320  " source and target Maps do not contain the same set of GIDs globally.)");
321 
322  // Sort remoteProcIDs in ascending order, and apply the resulting
323  // permutation to remoteGIDs and remoteLIDs_. This ensures that
324  // remoteProcIDs[i], remoteGIDs[i], and remoteLIDs_[i] all refer
325  // to the same thing.
326 
327  TEUCHOS_TEST_FOR_EXCEPTION( !(remoteProcIDs.size() == remoteGIDsView.size() &&remoteGIDsView.size() == remoteLIDs.size()), std::runtime_error,
328  "Import::Import createExpert version: Size miss match on RemoteProcIDs, remoteGIDsView and remoteLIDs Array's to sort3. This will produce produce an error, aborting ");
329 
330  sort3 (remoteProcIDs.begin (),
331  remoteProcIDs.end (),
332  remoteGIDsView.begin (),
333  remoteLIDs.begin ());
334 
335  ImportData_->remoteLIDs_ = remoteLIDs;
336  ImportData_->distributor_ = Distributor (source->getComm(),this->out_);
337  ImportData_->exportPIDs_ = Teuchos::Array<int>(userExportPIDs.size(),0);
338  ImportData_->exportLIDs_ = Teuchos::Array<int>(userExportPIDs.size(),0);
339 
340  bool locallyComplete = true;
341  for(size_type i=0; i<userExportPIDs.size(); i++) {
342  if (userExportPIDs[i] == -1) {
343  locallyComplete = false;
344  }
345  ImportData_->exportPIDs_[i] = userExportPIDs[i];
346  ImportData_->exportLIDs_[i] = userExportLIDs[i];
347  }
348  ImportData_->isLocallyComplete_ = locallyComplete;
349 
350  ImportData_->distributor_.createFromSendsAndRecvs(ImportData_->exportPIDs_,remoteProcIDs);
351 
352  }
353 
354 
355  template <class LocalOrdinal, class GlobalOrdinal, class Node>
357  Import (const Teuchos::RCP<const map_type>& source,
358  const Teuchos::RCP<const map_type>& target,
359  const size_t numSameIDs,
360  Teuchos::Array<LocalOrdinal>& permuteToLIDs,
361  Teuchos::Array<LocalOrdinal>& permuteFromLIDs,
362  Teuchos::Array<LocalOrdinal>& remoteLIDs,
363  Teuchos::Array<LocalOrdinal>& exportLIDs,
364  Teuchos::Array<int>& exportPIDs,
365  Distributor& distributor,
366  const Teuchos::RCP<Teuchos::FancyOStream>& out,
367  const Teuchos::RCP<Teuchos::ParameterList>& plist) :
368  out_ (out.is_null () ? Teuchos::getFancyOStream (Teuchos::rcpFromRef (std::cerr)) : out),
369  debug_ (tpetraImportDebugDefault)
370  {
371  using Teuchos::null;
372  using Teuchos::Ptr;
373  using Teuchos::rcp;
374  using std::cerr;
375  using std::endl;
377 
378  // Read "Debug" parameter from the input ParameterList.
379  bool debug = tpetraImportDebugDefault;
380  if (! plist.is_null ()) {
381  try {
382  debug = plist->get<bool> ("Debug");
383  } catch (Teuchos::Exceptions::InvalidParameter&) {}
384  }
385  debug_ = debug;
386 
387  if (! out_.is_null ()) {
388  out_->pushTab ();
389  }
390  if (debug_ && ! out_.is_null ()) {
391  std::ostringstream os;
392  const int myRank = source->getComm ()->getRank ();
393  os << myRank << ": Import expert ctor" << endl;
394  *out_ << os.str ();
395  }
396  ImportData_ = rcp (new data_type (source, target, out_, plist));
397 
398  bool locallyComplete = true;
399  for (Teuchos::Array<int>::size_type i = 0; i < exportPIDs.size (); ++i) {
400  if (exportPIDs[i] == -1) {
401  locallyComplete = false;
402  }
403  }
404  ImportData_->isLocallyComplete_ = locallyComplete;
405 
406  ImportData_->numSameIDs_ = numSameIDs;
407  ImportData_->permuteToLIDs_.swap (permuteToLIDs);
408  ImportData_->permuteFromLIDs_.swap (permuteFromLIDs);
409  ImportData_->remoteLIDs_.swap (remoteLIDs);
410  ImportData_->distributor_.swap (distributor);
411  ImportData_->exportLIDs_.swap (exportLIDs);
412  ImportData_->exportPIDs_.swap (exportPIDs);
413  }
414 
415  template <class LocalOrdinal, class GlobalOrdinal, class Node>
417  {}
418 
419  template <class LocalOrdinal, class GlobalOrdinal, class Node>
421  return ImportData_->numSameIDs_;
422  }
423 
424  template <class LocalOrdinal, class GlobalOrdinal, class Node>
426  return ImportData_->permuteFromLIDs_.size();
427  }
428 
429  template <class LocalOrdinal, class GlobalOrdinal, class Node>
430  Teuchos::ArrayView<const LocalOrdinal>
432  return ImportData_->permuteFromLIDs_();
433  }
434 
435  template <class LocalOrdinal, class GlobalOrdinal, class Node>
436  Teuchos::ArrayView<const LocalOrdinal>
438  return ImportData_->permuteToLIDs_();
439  }
440 
441  template <class LocalOrdinal, class GlobalOrdinal, class Node>
443  return ImportData_->remoteLIDs_.size();
444  }
445 
446  template <class LocalOrdinal, class GlobalOrdinal, class Node>
447  Teuchos::ArrayView<const LocalOrdinal>
449  return ImportData_->remoteLIDs_();
450  }
451 
452  template <class LocalOrdinal, class GlobalOrdinal, class Node>
454  return ImportData_->exportLIDs_.size();
455  }
456 
457  template <class LocalOrdinal, class GlobalOrdinal, class Node>
458  Teuchos::ArrayView<const LocalOrdinal>
460  return ImportData_->exportLIDs_();
461  }
462 
463  template <class LocalOrdinal, class GlobalOrdinal, class Node>
464  Teuchos::ArrayView<const int>
466  return ImportData_->exportPIDs_();
467  }
468 
469  template <class LocalOrdinal, class GlobalOrdinal, class Node>
470  Teuchos::RCP<const typename Import<LocalOrdinal,GlobalOrdinal,Node>::map_type>
472  return ImportData_->source_;
473  }
474 
475  template <class LocalOrdinal, class GlobalOrdinal, class Node>
476  Teuchos::RCP<const typename Import<LocalOrdinal,GlobalOrdinal,Node>::map_type>
478  return ImportData_->target_;
479  }
480 
481  template <class LocalOrdinal, class GlobalOrdinal, class Node>
482  Distributor &
484  return ImportData_->distributor_;
485  }
486 
487  template <class LocalOrdinal, class GlobalOrdinal, class Node>
488  bool
490  return ImportData_->isLocallyComplete_;
491  }
492 
493  template <class LocalOrdinal, class GlobalOrdinal, class Node>
497  if (&rhs != this) {
498  ImportData_ = rhs.ImportData_;
499  }
500  return *this;
501  }
502 
503  template <class LocalOrdinal, class GlobalOrdinal, class Node>
504  void
506  describe (Teuchos::FancyOStream& out,
507  const Teuchos::EVerbosityLevel verbLevel) const
508  {
509  // Call the base class' method. It does all the work.
510  this->describeImpl (out, "Tpetra::Import", verbLevel);
511  }
512 
513  template <class LocalOrdinal, class GlobalOrdinal, class Node>
515  print (std::ostream& os) const
516  {
517  auto out = Teuchos::getFancyOStream (Teuchos::rcpFromRef (os));
518  // "Print" traditionally meant "everything."
519  this->describe (*out, Teuchos::VERB_EXTREME);
520  }
521 
522  template <class LocalOrdinal, class GlobalOrdinal, class Node>
523  void
525  setupSamePermuteRemote (Teuchos::Array<GlobalOrdinal>& remoteGIDs)
526  {
527  using Teuchos::arcp;
528  using Teuchos::Array;
529  using Teuchos::ArrayRCP;
530  using Teuchos::ArrayView;
531  using Teuchos::as;
532  using Teuchos::null;
533  typedef LocalOrdinal LO;
534  typedef GlobalOrdinal GO;
535  typedef typename ArrayView<const GO>::size_type size_type;
536  const map_type& source = * (getSourceMap ());
537  const map_type& target = * (getTargetMap ());
538  ArrayView<const GO> sourceGIDs = source.getNodeElementList ();
539  ArrayView<const GO> targetGIDs = target.getNodeElementList ();
540 
541 #ifdef HAVE_TPETRA_DEBUG
542  ArrayView<const GO> rawSrcGids = sourceGIDs;
543  ArrayView<const GO> rawTgtGids = targetGIDs;
544 #else
545  const GO* const rawSrcGids = sourceGIDs.getRawPtr ();
546  const GO* const rawTgtGids = targetGIDs.getRawPtr ();
547 #endif // HAVE_TPETRA_DEBUG
548  const size_type numSrcGids = sourceGIDs.size ();
549  const size_type numTgtGids = targetGIDs.size ();
550  const size_type numGids = std::min (numSrcGids, numTgtGids);
551 
552  // Compute numSameIDs_: the number of initial GIDs that are the
553  // same (and occur in the same order) in both Maps. The point of
554  // numSameIDs_ is for the common case of an Import where all the
555  // overlapping GIDs are at the end of the target Map, but
556  // otherwise the source and target Maps are the same. This allows
557  // a fast contiguous copy for the initial "same IDs."
558  size_type numSameGids = 0;
559  for ( ; numSameGids < numGids && rawSrcGids[numSameGids] == rawTgtGids[numSameGids]; ++numSameGids)
560  {} // third clause of 'for' does everything
561  ImportData_->numSameIDs_ = numSameGids;
562 
563  // Compute permuteToLIDs_, permuteFromLIDs_, remoteGIDs, and
564  // remoteLIDs_. The first two arrays are IDs to be permuted, and
565  // the latter two arrays are IDs to be received ("imported"),
566  // called "remote" IDs.
567  //
568  // IDs to permute are in both the source and target Maps, which
569  // means we don't have to send or receive them, but we do have to
570  // rearrange (permute) them in general. IDs to receive are in the
571  // target Map, but not the source Map.
572 
573  Array<LO>& permuteToLIDs = ImportData_->permuteToLIDs_;
574  Array<LO>& permuteFromLIDs = ImportData_->permuteFromLIDs_;
575  Array<LO>& remoteLIDs = ImportData_->remoteLIDs_;
576  const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid ();
577  const LO numTgtLids = as<LO> (numTgtGids);
578  // Iterate over the target Map's LIDs, since we only need to do
579  // GID -> LID lookups for the source Map.
580  for (LO tgtLid = numSameGids; tgtLid < numTgtLids; ++tgtLid) {
581  const GO curTargetGid = rawTgtGids[tgtLid];
582  // getLocalElement() returns LINVALID if the GID isn't in the source Map.
583  // This saves us a lookup (which isNodeGlobalElement() would do).
584  const LO srcLid = source.getLocalElement (curTargetGid);
585  if (srcLid != LINVALID) { // if source.isNodeGlobalElement (curTargetGid)
586  permuteToLIDs.push_back (tgtLid);
587  permuteFromLIDs.push_back (srcLid);
588  } else {
589  remoteGIDs.push_back (curTargetGid);
590  remoteLIDs.push_back (tgtLid);
591  }
592  }
593 
594  if (remoteLIDs.size () != 0 && ! source.isDistributed ()) {
595  // This Import has remote LIDs, meaning that the target Map has
596  // entries on this process that are not in the source Map on
597  // this process. However, the source Map is not distributed
598  // globally. This implies that this Import is not locally
599  // complete on this process.
600  ImportData_->isLocallyComplete_ = false;
601  // mfh 12 Sep 2016: I disagree that this is "abuse"; it may be
602  // correct behavior, depending on the circumstances.
604  (true, std::runtime_error, "::setupSamePermuteRemote(): Target has "
605  "remote LIDs but Source is not distributed globally. Importing to a "
606  "submap of the target map.");
607  }
608  }
609 
610 
611  template <class LocalOrdinal, class GlobalOrdinal, class Node>
612  void Import<LocalOrdinal,GlobalOrdinal,Node>::
613  setupExport (Teuchos::Array<GlobalOrdinal>& remoteGIDs,
614  bool useRemotePIDs,
615  Teuchos::Array<int>& userRemotePIDs)
616  {
617  using Teuchos::arcp;
618  using Teuchos::Array;
619  using Teuchos::ArrayRCP;
620  using Teuchos::ArrayView;
621  using Teuchos::null;
622  using std::endl;
623  typedef LocalOrdinal LO;
624  typedef GlobalOrdinal GO;
625  typedef typename Array<int>::difference_type size_type;
626  const char tfecfFuncName[] = "setupExport: ";
627 
628  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
629  (getSourceMap ().is_null (), std::logic_error, "Source Map is null. "
630  "Please report this bug to the Tpetra developers.");
631  const map_type& source = * (getSourceMap ());
632 
633  Teuchos::OSTab tab (out_);
634 
635  // if (debug_ && ! out_.is_null ()) {
636  // std::ostringstream os;
637  // const int myRank = source.getComm ()->getRank ();
638  // os << myRank << ": Import::setupExport:" << endl;
639  // }
640 
641  // Sanity checks
642  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
643  (! useRemotePIDs && (userRemotePIDs.size() > 0), std::invalid_argument,
644  "remotePIDs are non-empty but their use has not been requested.");
645  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
646  (userRemotePIDs.size () > 0 && remoteGIDs.size () != userRemotePIDs.size (),
647  std::invalid_argument, "remotePIDs must either be of size zero or match "
648  "the size of remoteGIDs.");
649 
650  // For each entry remoteGIDs[i], remoteProcIDs[i] will contain
651  // the process ID of the process that owns that GID.
652  ArrayView<GO> remoteGIDsView = remoteGIDs ();
653  ArrayView<int> remoteProcIDsView;
654 
655  // lookup == IDNotPresent means that the source Map wasn't able to
656  // figure out to which processes one or more of the GIDs in the
657  // given list of remote GIDs belong.
658  //
659  // The previous abuse warning said "The target Map has GIDs not
660  // found in the source Map." This statement could be confusing,
661  // because it doesn't refer to ownership by the current process,
662  // but rather to ownership by _any_ process participating in the
663  // Map. (It could not possibly refer to ownership by the current
664  // process, since remoteGIDs is exactly the list of GIDs owned by
665  // the target Map but not owned by the source Map. It was
666  // constructed that way by setupSamePermuteRemote().)
667  //
668  // What this statement means is that the source and target Maps
669  // don't contain the same set of GIDs globally (over all
670  // processes). That is, there is at least one GID owned by some
671  // process in the target Map, which is not owned by _any_ process
672  // in the source Map.
673  Array<int> newRemotePIDs;
674  LookupStatus lookup = AllIDsPresent;
675 
676  if (! useRemotePIDs) {
677  newRemotePIDs.resize (remoteGIDsView.size ());
678  if (debug_ && ! out_.is_null ()) {
679  std::ostringstream os;
680  const int myRank = source.getComm ()->getRank ();
681  os << myRank << ": Import::setupExport: about to call "
682  "getRemoteIndexList on source Map" << endl;
683  *out_ << os.str ();
684  }
685  lookup = source.getRemoteIndexList (remoteGIDsView, newRemotePIDs ());
686  }
687  Array<int>& remoteProcIDs = useRemotePIDs ? userRemotePIDs : newRemotePIDs;
688 
689  if (lookup == IDNotPresent) {
690  // There is at least one GID owned by the calling process in the
691  // target Map, which is not owned by any process in the source
692  // Map.
693  ImportData_->isLocallyComplete_ = false;
694 
695  // mfh 12 Sep 2016: I disagree that this is "abuse"; it may be
696  // correct behavior, depending on the circumstances.
698  (true, std::runtime_error, "::setupExport(): the source Map wasn't "
699  "able to figure out which process owns one or more of the GIDs in the "
700  "list of remote GIDs. This probably means that there is at least one "
701  "GID owned by some process in the target Map which is not owned by any"
702  " process in the source Map. (That is, the source and target Maps do "
703  "not contain the same set of GIDs globally.)");
704 
705  // Ignore remote GIDs that aren't owned by any process in the
706  // source Map. getRemoteIndexList() gives each of these a
707  // process ID of -1.
708 
709  const size_type numInvalidRemote =
710  std::count_if (remoteProcIDs.begin (), remoteProcIDs.end (),
711  std::bind1st (std::equal_to<int> (), -1));
712  TEUCHOS_TEST_FOR_EXCEPTION_CLASS_FUNC
713  (numInvalidRemote == 0, std::logic_error, "Calling getRemoteIndexList "
714  "on the source Map returned IDNotPresent, but none of the returned "
715  "\"remote\" process ranks are -1. Please report this bug to the "
716  "Tpetra developers.");
717 
718  // If all of them are invalid, we can delete the whole array.
719  const size_type totalNumRemote = getNumRemoteIDs ();
720  if (numInvalidRemote == totalNumRemote) {
721  // all remotes are invalid; we have no remotes; we can delete the remotes
722  remoteProcIDs.clear ();
723  remoteGIDs.clear (); // This invalidates the view remoteGIDsView
724  ImportData_->remoteLIDs_.clear();
725  }
726  else {
727  // Some remotes are valid; we need to keep the valid ones.
728  // Pack and resize remoteProcIDs, remoteGIDs, and remoteLIDs_.
729  size_type numValidRemote = 0;
730 #ifdef HAVE_TPETRA_DEBUG
731  ArrayView<GlobalOrdinal> remoteGIDsPtr = remoteGIDsView;
732 #else
733  GlobalOrdinal* const remoteGIDsPtr = remoteGIDsView.getRawPtr ();
734 #endif // HAVE_TPETRA_DEBUG
735  for (size_type r = 0; r < totalNumRemote; ++r) {
736  // Pack in all the valid remote PIDs and GIDs.
737  if (remoteProcIDs[r] != -1) {
738  remoteProcIDs[numValidRemote] = remoteProcIDs[r];
739  remoteGIDsPtr[numValidRemote] = remoteGIDsPtr[r];
740  ImportData_->remoteLIDs_[numValidRemote] = ImportData_->remoteLIDs_[r];
741  ++numValidRemote;
742  }
743  }
744  TEUCHOS_TEST_FOR_EXCEPTION(
745  numValidRemote != totalNumRemote - numInvalidRemote, std::logic_error,
746  "Tpetra::Import::setupExport(): After removing invalid remote GIDs and"
747  " packing the valid remote GIDs, numValidRemote = " << numValidRemote
748  << " != totalNumRemote - numInvalidRemote = "
749  << totalNumRemote - numInvalidRemote
750  << ". Please report this bug to the Tpetra developers.");
751 
752  remoteProcIDs.resize (numValidRemote);
753  remoteGIDs.resize (numValidRemote);
754  ImportData_->remoteLIDs_.resize (numValidRemote);
755  }
756  // Revalidate the view after clear or resize.
757  remoteGIDsView = remoteGIDs ();
758  }
759 
760  // Sort remoteProcIDs in ascending order, and apply the resulting
761  // permutation to remoteGIDs and remoteLIDs_. This ensures that
762  // remoteProcIDs[i], remoteGIDs[i], and remoteLIDs_[i] all refer
763  // to the same thing.
764 
765  sort3 (remoteProcIDs.begin (),
766  remoteProcIDs.end (),
767  remoteGIDsView.begin (),
768  ImportData_->remoteLIDs_.begin ());
769 
770  // Call the Distributor's createFromRecvs() method to turn the
771  // remote GIDs and their owning processes into a send-and-receive
772  // communication plan. remoteGIDs and remoteProcIDs_ are input;
773  // exportGIDs and exportProcIDs_ are output arrays which are
774  // allocated by createFromRecvs().
775  Array<GO> exportGIDs;
776  ImportData_->distributor_.createFromRecvs (remoteGIDsView ().getConst (),
777  remoteProcIDs, exportGIDs,
778  ImportData_->exportPIDs_);
779  // if (debug_ && ! out_.is_null ()) {
780  // std::ostringstream os;
781  // const int myRank = source.getComm ()->getRank ();
782  // os << myRank << ": Import::setupExport: Getting LIDs" << endl;
783  // *out_ << os.str ();
784  // }
785 
786  // Find the LIDs corresponding to the (outgoing) GIDs in
787  // exportGIDs. For sparse matrix-vector multiply, this tells the
788  // calling process how to index into the source vector to get the
789  // elements which it needs to send.
790  //
791  // NOTE (mfh 03 Mar 2014) This is now a candidate for a
792  // thread-parallel kernel, but only if using the new thread-safe
793  // Map implementation.
794  const size_type numExportIDs = exportGIDs.size ();
795  if (numExportIDs > 0) {
796  ImportData_->exportLIDs_.resize (numExportIDs);
797  ArrayView<const GO> expGIDs = exportGIDs ();
798  ArrayView<LO> expLIDs = ImportData_->exportLIDs_ ();
799  for (size_type k = 0; k < numExportIDs; ++k) {
800  expLIDs[k] = source.getLocalElement (expGIDs[k]);
801  }
802  }
803 
804  if (debug_ && ! out_.is_null ()) {
805  std::ostringstream os;
806  const int myRank = source.getComm ()->getRank ();
807  os << myRank << ": Import::setupExport: done" << endl;
808  *out_ << os.str ();
809  }
810  }
811 
812 
813  template <class LocalOrdinal, class GlobalOrdinal, class Node>
814  Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
817  {
818  typedef Tpetra::global_size_t GST;
819  using Teuchos::Array;
820  using Teuchos::ArrayView;
821  using Teuchos::as;
822  using Teuchos::Comm;
823  using Teuchos::RCP;
824  using Teuchos::rcp;
825  using Teuchos::outArg;
826  using Teuchos::REDUCE_MIN;
827  using Teuchos::reduceAll;
828  typedef LocalOrdinal LO;
829  typedef GlobalOrdinal GO;
830  typedef Import<LO, GO, Node> import_type;
831  typedef typename Array<GO>::size_type size_type;
832 
833 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
834  using Teuchos::toString;
835  using std::cerr;
836  using std::endl;
837 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
838 
839  RCP<const map_type> srcMap = this->getSourceMap ();
840  RCP<const map_type> tgtMap1 = this->getTargetMap ();
841  RCP<const map_type> tgtMap2 = rhs.getTargetMap ();
842  RCP<const Comm<int> > comm = srcMap->getComm ();
843 
844 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
845  const int myRank = comm->getRank ();
846 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
847 
848 #ifdef HAVE_TPETRA_DEBUG
849  TEUCHOS_TEST_FOR_EXCEPTION(
850  ! srcMap->isSameAs (* (rhs.getSourceMap ())), std::invalid_argument,
851  "Tpetra::Import::setUnion: The source Map of the input Import must be the "
852  "same as (in the sense of Map::isSameAs) the source Map of this Import.");
853  TEUCHOS_TEST_FOR_EXCEPTION(
854  ! Details::congruent (* (tgtMap1->getComm ()), * (tgtMap2->getComm ())),
855  std::invalid_argument, "Tpetra::Import::setUnion: "
856  "The target Maps must have congruent communicators.");
857 #endif // HAVE_TPETRA_DEBUG
858 
859  // It's probably worth the one all-reduce to check whether the two
860  // Maps are the same. If so, we can just return a copy of *this.
861  // isSameAs() bypasses the all-reduce if the pointers are equal.
862  if (tgtMap1->isSameAs (*tgtMap2)) {
863  return rcp (new import_type (*this));
864  }
865  // Alas, the two target Maps are not the same. That means we have
866  // to compute their union, and the union Import object.
867 
868  ArrayView<const GO> srcGIDs = srcMap->getNodeElementList ();
869  ArrayView<const GO> tgtGIDs1 = tgtMap1->getNodeElementList ();
870  ArrayView<const GO> tgtGIDs2 = tgtMap2->getNodeElementList ();
871 
872 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
873  comm->barrier ();
874  {
875  std::ostringstream os;
876  os << myRank << ": srcGIDs: " << toString (srcGIDs) << endl;
877  os << myRank << ": tgtGIDs1: " << toString (tgtGIDs1) << endl;
878  os << myRank << ": tgtGIDs2: " << toString (tgtGIDs2) << endl;
879  cerr << os.str ();
880  }
881  comm->barrier ();
882 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
883 
884 
885  // Fill this as we go with the union target Map's GIDs, in the
886  // desired order. We'll need them for the Map constructor.
887  Array<GO> unionTgtGIDs;
888  // Upper bound on the number of union target Map GIDs. This
889  // happens to be strict, but doesn't have to be. Setting some
890  // reasonable upper bound avoids reallocation in loops that do
891  // push_back operations.
892  unionTgtGIDs.reserve (tgtGIDs1.size () + tgtGIDs2.size ());
893 
894 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
895  if (myRank == 0) {
896  cerr << endl;
897  }
898  comm->barrier ();
899  comm->barrier ();
900  comm->barrier ();
901  cerr << myRank << ": Computing \"same\" GIDs" << endl;
902 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
903 
904  // Compute the initial sequence of "same" GIDs in the union
905  // import. The number of "same" GIDs in the union is the maximum
906  // of the lengths of this in the two inputs.
907 
908  const size_type numSameGIDs1 = this->getNumSameIDs ();
909  const size_type numSameGIDs2 = rhs.getNumSameIDs ();
910  ArrayView<const GO> sameGIDs1 = tgtGIDs1 (0, numSameGIDs1);
911  ArrayView<const GO> sameGIDs2 = tgtGIDs2 (0, numSameGIDs2);
912 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
913  {
914  std::ostringstream os;
915  os << myRank << ": same IDs for target Map 1: " << toString (sameGIDs1) << endl;
916  os << myRank << ": same IDs for target Map 2: " << toString (sameGIDs2) << endl;
917  cerr << os.str ();
918  }
919 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
920  // For the input target Map with fewer "same" GIDs, that Map's
921  // permute IDs could include some of the other input target Map's
922  // "same" GIDs. We have to make sure not to include them twice.
923  // To do so, keep a view of them for now, and remove them (via set
924  // intersection) from the permute ID list. Keeping track of which
925  // GID set had the max number of "same" IDs avoids unnecessary set
926  // intersection operations later.
927  ArrayView<const GO> doubleCountedSameGIDs;
928  size_type numSameIDsUnion;
929  bool tgtMap1HadMaxSameGIDs;
930  if (numSameGIDs1 >= numSameGIDs2) {
931  tgtMap1HadMaxSameGIDs = true;
932  numSameIDsUnion = numSameGIDs1;
933  std::copy (sameGIDs1.begin (), sameGIDs1.end (), std::back_inserter (unionTgtGIDs));
934  // There could be GIDs in target Map 2 that are not included in
935  // the "same" IDs, but are included in Import 2's permute IDs.
936  // Keep track of them so we don't double-count them when
937  // building the list of permute IDs.
938  doubleCountedSameGIDs = tgtGIDs1 (numSameGIDs2, numSameGIDs1 - numSameGIDs2);
939  } else {
940  tgtMap1HadMaxSameGIDs = false;
941  numSameIDsUnion = numSameGIDs2;
942  std::copy (sameGIDs2.begin (), sameGIDs2.end (), std::back_inserter (unionTgtGIDs));
943  // There could be GIDs in target Map 1 that are not included in
944  // the "same" IDs, but are included in Import 1's permute IDs.
945  // Keep track of them so we don't double-count them when
946  // building the list of permute IDs.
947  doubleCountedSameGIDs = tgtGIDs2 (numSameGIDs1, numSameGIDs2 - numSameGIDs1);
948  }
949 
950 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
951  {
952  std::ostringstream os;
953  os << myRank << ": union Map's same GIDs: " << toString (unionTgtGIDs ()) << endl;
954  os << myRank << ": doubleCountedSameGIDs: " << toString (doubleCountedSameGIDs) << endl;
955  cerr << os.str ();
956  }
957  if (myRank == 0) {
958  cerr << endl;
959  }
960  comm->barrier ();
961  comm->barrier ();
962  comm->barrier ();
963  cerr << myRank << ": Computing permute IDs" << endl;
964 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
965 
966  // Each input Import knows its permute-from LIDs (in the source
967  // Map) and permute-to LIDs (in its target Map). We will have to
968  // reassign LIDs in the union target Map, but we can use these
969  // permute-to LIDs to construct the union Import's permute-to IDs.
970  Array<LO> permuteFromLIDsUnion;
971  Array<LO> permuteToLIDsUnion;
972  LO curTgtLid = as<LO> (numSameIDsUnion);
973  {
974  // Permute-to LIDs in the two input target Maps.
975  ArrayView<const LO> permuteToLIDs1 = this->getPermuteToLIDs ();
976  ArrayView<const LO> permuteToLIDs2 = rhs.getPermuteToLIDs ();
977  const size_type numPermuteIDs1 = this->getNumPermuteIDs ();
978  const size_type numPermuteIDs2 = rhs.getNumPermuteIDs ();
979 
980 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
981  cerr << myRank << ": Converting permute-to LIDs to GIDs" << endl;
982 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
983 
984  // Convert the permute-to LID lists to GIDs, so that we can
985  // later reassign LIDs for the (output) union target Map.
986  Array<GO> permuteGIDs1 (numPermuteIDs1);
987  for (size_type k = 0; k < numPermuteIDs1; ++k) {
988  permuteGIDs1[k] = tgtMap1->getGlobalElement (permuteToLIDs1[k]);
989  }
990  Array<GO> permuteGIDs2 (numPermuteIDs2);
991  for (size_type k = 0; k < numPermuteIDs2; ++k) {
992  permuteGIDs2[k] = tgtMap2->getGlobalElement (permuteToLIDs2[k]);
993  }
994 
995 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
996  {
997  std::ostringstream os;
998  os << myRank << ": permuteGIDs1: " << toString (permuteGIDs1) << endl;
999  os << myRank << ": permuteGIDs2: " << toString (permuteGIDs2) << endl;
1000  cerr << os.str ();
1001  }
1002  cerr << myRank << ": Sorting and merging permute GID lists" << endl;
1003 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1004 
1005  // Sort the two permute GID lists, remove the GIDs that we don't
1006  // want to double-count, and merge the result into the global
1007  // list of GIDs in the target union Map.
1008  std::sort (permuteGIDs1.begin (), permuteGIDs1.end ());
1009  std::sort (permuteGIDs2.begin (), permuteGIDs2.end ());
1010 
1011  typename Array<GO>::iterator permuteGIDs1_beg = permuteGIDs1.begin ();
1012  typename Array<GO>::iterator permuteGIDs1_end = permuteGIDs1.end ();
1013  typename Array<GO>::iterator permuteGIDs2_beg = permuteGIDs2.begin ();
1014  typename Array<GO>::iterator permuteGIDs2_end = permuteGIDs2.end ();
1015  if (tgtMap1HadMaxSameGIDs) {
1016  // This operation allows the last (output) argument to alias the first.
1017  permuteGIDs2_end =
1018  std::set_difference(permuteGIDs2_beg,
1019  permuteGIDs2_end,
1020  doubleCountedSameGIDs.begin (),
1021  doubleCountedSameGIDs.end (),
1022  permuteGIDs2_beg);
1023 
1024 
1025  } else {
1026  // This operation allows the last (output) argument to alias the first.
1027  permuteGIDs1_end =
1028  std::set_difference(permuteGIDs1_beg,
1029  permuteGIDs1_end,
1030  doubleCountedSameGIDs.begin (),
1031  doubleCountedSameGIDs.end (),
1032  permuteGIDs1_beg);
1033 
1034  }
1035  std::set_union (permuteGIDs1_beg, permuteGIDs1_end,
1036  permuteGIDs2_beg, permuteGIDs2_end,
1037  std::back_inserter (unionTgtGIDs));
1038 
1039 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1040  {
1041  std::ostringstream os;
1042  if(tgtMap1HadMaxSameGIDs) os << myRank << ": tgtMap1HadMaxSameGIDs == true"<<endl;
1043  else os << myRank << ": tgtMap1HadMaxSameGIDs == false"<<endl;
1044 
1045  os << myRank << ": reduced permuteGIDs1: {";
1046  for(typename Array<GO>::iterator k = permuteGIDs1_beg; k != permuteGIDs1_end; k++)
1047  os<<*k<<", ";
1048  os<<"}"<<endl;
1049  os << myRank << ": reduced permuteGIDs2: {";
1050  for(typename Array<GO>::iterator k = permuteGIDs2_beg; k != permuteGIDs2_end; k++)
1051  os<<*k<<", ";
1052  os<<"}"<<endl;
1053  cerr << os.str ();
1054  }
1055 #endif
1056  const size_type numPermuteIDsUnion =
1057  unionTgtGIDs.size () - numSameIDsUnion;
1058  ArrayView<const GO> permuteGIDsUnion =
1059  unionTgtGIDs (numSameIDsUnion, numPermuteIDsUnion).getConst ();
1060 
1061 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1062  {
1063  std::ostringstream os;
1064  os << myRank << ": permuteGIDsUnion: " << toString (permuteGIDsUnion) << endl;
1065  cerr << os.str ();
1066  }
1067 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1068 
1069 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1070  comm->barrier ();
1071  cerr << myRank << ": Computing permute-to LIDs" << endl;
1072 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1073 
1074  // Compute the permute-to LIDs (in the union target Map).
1075  permuteToLIDsUnion.resize (numPermuteIDsUnion);
1076  for (size_type k = 0; k < numPermuteIDsUnion; ++k) {
1077  permuteToLIDsUnion[k] = curTgtLid++;
1078  }
1079 
1080 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1081  {
1082  std::ostringstream os;
1083  os << myRank << ": permuteToLIDsUnion: " << toString (permuteToLIDsUnion) << endl;
1084  cerr << os.str ();
1085  }
1086 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1087 
1088 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1089  comm->barrier ();
1090  cerr << myRank << ": Computing permute-from LIDs" << endl;
1091 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1092 
1093  // Convert the permute GIDs to permute-from LIDs in the source Map.
1094  permuteFromLIDsUnion.resize (numPermuteIDsUnion);
1095  for (size_type k = 0; k < numPermuteIDsUnion; ++k) {
1096  permuteFromLIDsUnion[k] = srcMap->getLocalElement (permuteGIDsUnion[k]);
1097  }
1098 
1099 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1100  {
1101  std::ostringstream os;
1102  os << myRank << ": permuteFromLIDsUnion: " << toString (permuteFromLIDsUnion) << endl;
1103  cerr << os.str ();
1104  }
1105 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1106  }// end permutes
1107 
1108 
1109 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1110  {
1111  std::ostringstream os;
1112  os << myRank << ": unionTgtGIDs after permutes: "
1113  << toString (unionTgtGIDs ()) << endl;
1114  cerr << os.str ();
1115  }
1116 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1117 
1118  // Thus far, we have computed the following in the union Import:
1119  // - getNumSameIDs()
1120  // - getNumPermuteIDs()
1121  // - getPermuteFromLIDs ()
1122  // - getPermuteToLIDs ()
1123  //
1124  // Now it's time to compute the remote IDs. By definition, none
1125  // of these IDs are in the source Map (on the calling process), so
1126  // they can't possibly overlap with any of the "same" or permute
1127  // IDs in either target Map.
1128  //
1129  // After the first numSameIDsUnion IDs, we get to control the
1130  // order of GIDs in the union target Map. We'll put the permute
1131  // IDs first (which we already did above) and the remote IDs last
1132  // (which we are about to do). We'll sort the remote IDs by
1133  // process rank, so that Distributor doesn't have to pack buffers.
1134  // (That way, doPosts() will always take the "fast path" on all
1135  // processes.)
1136 
1137 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1138  if (myRank == 0) {
1139  cerr << endl;
1140  }
1141  comm->barrier ();
1142  comm->barrier ();
1143  comm->barrier ();
1144  cerr << myRank << ": Computing remote IDs" << endl;
1145 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1146 
1147  Array<GO> remoteGIDsUnion;
1148  Array<int> remotePIDsUnion;
1149  Array<LO> remoteLIDsUnion;
1150  size_type numRemoteIDsUnion = 0;
1151  {
1152  // Distributor::createFromRecvs takes remote IDs and PIDs as
1153  // input, and computes exportIDs and exportPIDs. The easiest
1154  // way to get the remote PIDs is to imitate setupExport by using
1155  // getRemoteIndexList(). We could try to get them out of the
1156  // Distributor via getImagesFrom(), but Distributor reorders
1157  // them in some not entirely transparent way.
1158 
1159  // Grab the remoteLIDs
1160  ArrayView<const LO> remoteLIDs1 = this->getRemoteLIDs();
1161  ArrayView<const LO> remoteLIDs2 = rhs.getRemoteLIDs();
1162 
1163  // Grab the remotePIDs
1164  Array<int> remotePIDs1, remotePIDs2;
1165  Tpetra::Import_Util::getRemotePIDs(*this,remotePIDs1);
1166  Tpetra::Import_Util::getRemotePIDs(rhs,remotePIDs2);
1167 
1168  // Put the (PID,GID) into std:pairs to make for easier sorting
1169  Array<std::pair<int,GO> > remotePGIDs1, remotePGIDs2,remotePGUnion;
1170  remotePGIDs1.resize(remotePIDs1.size());
1171  remotePGIDs2.resize(remotePIDs2.size());
1172 
1173  for(size_type k=0; k < remotePIDs1.size(); k++)
1174  remotePGIDs1[k] = std::pair<int,GO>(remotePIDs1[k],this->getTargetMap()->getGlobalElement(remoteLIDs1[k]));
1175 
1176  for(size_type k=0; k < remotePIDs2.size(); k++)
1177  remotePGIDs2[k] = std::pair<int,GO>(remotePIDs2[k],rhs.getTargetMap()->getGlobalElement(remoteLIDs2[k]));
1178 
1179 
1180  // Sort and merge the (PID,GID) pairs (with the LIDs along for the ride at least for the sort)
1181  std::sort(remotePGIDs1.begin(), remotePGIDs1.end());
1182  std::sort(remotePGIDs2.begin(), remotePGIDs2.end());
1183  std::merge(remotePGIDs1.begin(), remotePGIDs1.end(),
1184  remotePGIDs2.begin(), remotePGIDs2.end(),
1185  std::back_inserter(remotePGUnion));
1186  typename Array<std::pair<int,GO> >::iterator it = std::unique(remotePGUnion.begin(),remotePGUnion.end());
1187  remotePGUnion.resize(std::distance(remotePGUnion.begin(),it));
1188 
1189  // Assign the remote LIDs in order; copy out
1190  numRemoteIDsUnion = remotePGUnion.size();
1191  remoteLIDsUnion.resize(numRemoteIDsUnion);
1192  remotePIDsUnion.resize(numRemoteIDsUnion);
1193  remoteGIDsUnion.resize(numRemoteIDsUnion);
1194 
1195  for (size_type k = 0; k < numRemoteIDsUnion; ++k) {
1196  remoteLIDsUnion[k] = curTgtLid++;
1197  remotePIDsUnion[k] = remotePGUnion[k].first;
1198  remoteGIDsUnion[k] = remotePGUnion[k].second;
1199  }
1200 
1201  // Update the unionTgtGIDs
1202  const size_type oldSize = unionTgtGIDs.size();
1203  unionTgtGIDs.resize(oldSize + numRemoteIDsUnion);
1204  for(size_type k=0; k<numRemoteIDsUnion; k++)
1205  unionTgtGIDs[oldSize+k] = remoteGIDsUnion[k];
1206 
1207 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1208  {
1209  // For debugging purposes only
1210  Array<GO> remoteGIDs1(remotePIDs1.size());
1211  Array<GO> remoteGIDs2(remotePIDs2.size());
1212  for(size_type k=0; k < remotePIDs1.size(); k++)
1213  remoteGIDs1[k] = this->getTargetMap()->getGlobalElement(remoteLIDs1[k]);
1214  for(size_type k=0; k < remotePIDs2.size(); k++)
1215  remoteGIDs2[k] = rhs.getTargetMap()->getGlobalElement(remoteLIDs2[k]);
1216 
1217  std::ostringstream os;
1218  os << myRank << ": remoteGIDs1 : " << toString (remoteGIDs1 ()) << endl;
1219  os << myRank << ": remotePIDs1 : " << toString (remotePIDs1 ()) << endl;
1220  os << myRank << ": remoteGIDs2 : " << toString (remoteGIDs2 ()) << endl;
1221  os << myRank << ": remotePIDs2 : " << toString (remotePIDs2 ()) << endl;
1222  cerr << os.str ();
1223  }
1224 #endif
1225  }//end remotes
1226 
1227 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1228  {
1229  std::ostringstream os;
1230  os << myRank << ": remoteGIDsUnion sorted: " << toString (remoteGIDsUnion ()) << endl;
1231  os << myRank << ": remotePIDsUnion sorted: " << toString (remotePIDsUnion ()) << endl;
1232  os << myRank << ": remoteLIDsUnion sorted: " << toString (remoteLIDsUnion ()) << endl;
1233  cerr << os.str ();
1234  }
1235 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1236 
1237 
1238 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1239  {
1240  std::ostringstream os;
1241  os << myRank << ": unionTgtGIDs after remotes: "
1242  << toString (unionTgtGIDs ()) << endl;
1243  cerr << os.str ();
1244  }
1245 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1246 
1247  // Find the union target Map's index base, which must also be the
1248  // union target Map's global min GID. Thus, by definition, it
1249  // must be the minimum of the two input target Maps' index bases.
1250  // We already know these, so we don't have to do another
1251  // all-reduce to find it.
1252  const GO indexBaseUnion =
1253  std::min (tgtMap1->getIndexBase (), tgtMap2->getIndexBase ());
1254 
1255 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1256  cerr << myRank << "Creating union target Map" << endl;
1257 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1258 
1259  // Create the union target Map.
1260  //
1261  // mfh 01 May 2013, 28 Feb 2014: It might be handy to have a Map
1262  // constructor that takes the global min and max GIDs; that would
1263  // obviate the need for Map to compute them. On the other hand,
1264  // for signed GlobalOrdinal, this version of Map's constructor
1265  // already computes as few all-reduces as possible (not including
1266  // optimizations that might be possible if one were to fold in
1267  // Directory construction). The constructor must do two
1268  // all-reduces:
1269  //
1270  // 1. Get the global number of GIDs (since the first argument is
1271  // INVALID, we're asking Map to compute this for us)
1272  //
1273  // 2. Figure out three things: global min and max GID, and
1274  // whether the Map is distributed or locally replicated.
1275  //
1276  // #2 above happens in one all-reduce (of three integers).
1277  // #Figuring out whether the Map is distributed or locally
1278  // #replicated requires knowing the global number of GIDs.
1279  const GST INVALID = Teuchos::OrdinalTraits<GST>::invalid ();
1280  RCP<const map_type> unionTgtMap =
1281  rcp (new map_type (INVALID, unionTgtGIDs (), indexBaseUnion,
1282  comm, srcMap->getNode ()));
1283 
1284 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1285  if (myRank == 0) {
1286  cerr << endl;
1287  }
1288  comm->barrier ();
1289  comm->barrier ();
1290  comm->barrier ();
1291  cerr << myRank << ": Computing export IDs and Distributor" << endl;
1292 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1293 
1294  // Thus far, we have computed the following in the union Import:
1295  // - numSameIDs
1296  // - numPermuteIDs and permuteFromLIDs
1297  // - numRemoteIDs, remoteGIDs, remoteLIDs, and remotePIDs
1298  //
1299  // Now it's time to compute the export IDs and initialize the
1300  // Distributor.
1301 
1302  Array<GO> exportGIDsUnion;
1303  Array<LO> exportLIDsUnion;
1304  Array<int> exportPIDsUnion;
1305  Distributor distributor (comm, this->out_);
1306 
1307 #ifdef TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1308  // Compute the export IDs without communication, by merging the
1309  // lists of (export LID, export PID) pairs from the two input
1310  // Import objects. The export LIDs in both input Import objects
1311  // are LIDs in the source Map. Then, use the export PIDs to
1312  // initialize the Distributor via createFromSends.
1313 
1314  // const size_type numExportIDs1 = this->getNumExportIDs ();
1315  ArrayView<const LO> exportLIDs1 = this->getExportLIDs ();
1316  ArrayView<const LO> exportPIDs1 = this->getExportPIDs ();
1317 
1318  // const size_type numExportIDs2 = rhs.getNumExportIDs ();
1319  ArrayView<const LO> exportLIDs2 = rhs.getExportLIDs ();
1320  ArrayView<const LO> exportPIDs2 = rhs.getExportPIDs ();
1321 
1322  // We have to keep the export LIDs in PID-sorted order, then merge
1323  // them. So, first key-value merge (LID,PID) pairs, treating PIDs
1324  // as values, merging values by replacement. Then, sort the
1325  // (LID,PID) pairs again by PID.
1326 
1327  // Sort (LID,PID) pairs by LID for the later merge, and make
1328  // each sequence unique by LID.
1329  Array<LO> exportLIDs1Copy (exportLIDs1.begin (), exportLIDs1.end ());
1330  Array<int> exportPIDs1Copy (exportLIDs1.begin (), exportLIDs1.end ());
1331  sort2 (exportLIDs1Copy.begin (), exportLIDs1Copy.end (),
1332  exportPIDs1Copy.begin ());
1333  typename ArrayView<LO>::iterator exportLIDs1_end = exportLIDs1Copy.end ();
1334  typename ArrayView<LO>::iterator exportPIDs1_end = exportPIDs1Copy.end ();
1335  merge2 (exportLIDs1_end, exportPIDs1_end,
1336  exportLIDs1Copy.begin (), exportLIDs1_end,
1337  exportPIDs1Copy.begin (), exportPIDs1_end,
1338  project1st<LO, LO> ());
1339 
1340  Array<LO> exportLIDs2Copy (exportLIDs2.begin (), exportLIDs2.end ());
1341  Array<int> exportPIDs2Copy (exportLIDs2.begin (), exportLIDs2.end ());
1342  sort2 (exportLIDs2Copy.begin (), exportLIDs2Copy.end (),
1343  exportPIDs2Copy.begin ());
1344  typename ArrayView<LO>::iterator exportLIDs2_end = exportLIDs2Copy.end ();
1345  typename ArrayView<LO>::iterator exportPIDs2_end = exportPIDs2Copy.end ();
1346  merge2 (exportLIDs2_end, exportPIDs2_end,
1347  exportLIDs2Copy.begin (), exportLIDs2_end,
1348  exportPIDs2Copy.begin (), exportPIDs2_end,
1349  project1st<LO, LO> ());
1350 
1351  // Merge export (LID,PID) pairs. In this merge operation, the
1352  // LIDs are the "keys" and the PIDs their "values." We combine
1353  // the "values" (PIDs) in the pairs by replacement, rather than
1354  // by adding them together.
1355  keyValueMerge (exportLIDs1Copy.begin (), exportLIDs1Copy.end (),
1356  exportPIDs1Copy.begin (), exportPIDs1Copy.end (),
1357  exportLIDs2Copy.begin (), exportLIDs2Copy.end (),
1358  exportPIDs2Copy.begin (), exportPIDs2Copy.end (),
1359  std::back_inserter (exportLIDsUnion),
1360  std::back_inserter (exportPIDsUnion),
1362 
1363  // Resort the merged (LID,PID) pairs by PID.
1364  sort2 (exportPIDsUnion.begin (), exportPIDsUnion.end (),
1365  exportLIDsUnion.begin ());
1366 
1367  // Initialize the Distributor. Using createFromSends instead of
1368  // createFromRecvs avoids the initialization and use of a
1369  // temporary Distributor object.
1370  (void) distributor.createFromSends (exportPIDsUnion ().getConst ());
1371 #else // NOT TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1372 
1373  // Call the Distributor's createFromRecvs() method to turn the
1374  // remote GIDs and their owning processes into a send-and-receive
1375  // communication plan. remoteGIDsUnion and remotePIDsUnion are
1376  // input; exportGIDsUnion and exportPIDsUnion are output arrays
1377  // which are allocated by createFromRecvs().
1378  distributor.createFromRecvs (remoteGIDsUnion().getConst (),
1379  remotePIDsUnion ().getConst (),
1380  exportGIDsUnion, exportPIDsUnion);
1381 
1382  // Find the (source Map) LIDs corresponding to the export GIDs.
1383  const size_type numExportIDsUnion = exportGIDsUnion.size ();
1384  exportLIDsUnion.resize (numExportIDsUnion);
1385  for (size_type k = 0; k < numExportIDsUnion; ++k) {
1386  exportLIDsUnion[k] = srcMap->getLocalElement (exportGIDsUnion[k]);
1387  }
1388 #endif // TPETRA_IMPORT_SETUNION_USE_CREATE_FROM_SENDS
1389 
1390 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1391  {
1392  std::ostringstream os;
1393  os << myRank << ": exportGIDsUnion: " << toString (exportGIDsUnion ()) << endl;
1394  os << myRank << ": exportPIDsUnion: " << toString (exportPIDsUnion ()) << endl;
1395  os << myRank << ": exportLIDsUnion: " << toString (exportLIDsUnion ()) << endl;
1396  cerr << os.str ();
1397  }
1398  comm->barrier ();
1399  cerr << "Creating union Import" << endl;
1400 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1401 
1402  // Create and return the union Import. This uses the "expert" constructor
1403  RCP<const import_type> unionImport =
1404  rcp (new import_type (srcMap, unionTgtMap,
1405  as<size_t> (numSameIDsUnion),
1406  permuteToLIDsUnion, permuteFromLIDsUnion,
1407  remoteLIDsUnion, exportLIDsUnion,
1408  exportPIDsUnion, distributor, this->out_));
1409 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1410  comm->barrier ();
1411  cerr << "Created union Import; done!" << endl;
1412 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1413 
1414  return unionImport;
1415  }
1416 
1417 
1418 
1419  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1420  Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
1422  setUnion () const
1423  {
1424  using Teuchos::Array;
1425  using Teuchos::ArrayView;
1426  using Teuchos::as;
1427  using Teuchos::Comm;
1428  using Teuchos::RCP;
1429  using Teuchos::rcp;
1430  using Teuchos::outArg;
1431  using Teuchos::REDUCE_MIN;
1432  using Teuchos::reduceAll;
1433  typedef LocalOrdinal LO;
1434  typedef GlobalOrdinal GO;
1435  Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> > unionImport;
1436  RCP<const map_type> srcMap = this->getSourceMap ();
1437  RCP<const map_type> tgtMap = this->getTargetMap ();
1438  RCP<const Comm<int> > comm = srcMap->getComm ();
1439 
1440 #ifdef HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1441  const int myRank = comm->getRank ();
1442 #endif // HAVE_TPETRA_IMPORT_SETUNION_EXTRA_DEBUG_OUTPUT
1443 
1444  ArrayView<const GO> srcGIDs = srcMap->getNodeElementList ();
1445  ArrayView<const GO> tgtGIDs = tgtMap->getNodeElementList ();
1446 
1447  // All elements in srcMap will be in the "new" target map, so...
1448  size_t numSameIDsNew = srcMap->getNodeNumElements();
1449  size_t numRemoteIDsNew = getNumRemoteIDs();
1450  Array<LO> permuteToLIDsNew, permuteFromLIDsNew; // empty on purpose
1451 
1452  // Grab some old data
1453  ArrayView<const LO> remoteLIDsOld = getRemoteLIDs();
1454  ArrayView<const LO> exportLIDsOld = getExportLIDs();
1455 
1456  // Build up the new map (same part)
1457  Array<GO> GIDs(numSameIDsNew + numRemoteIDsNew);
1458  for(size_t i=0; i<numSameIDsNew; i++)
1459  GIDs[i] = srcGIDs[i];
1460 
1461  // Build up the new map (remote part) and remotes list
1462  Array<LO> remoteLIDsNew(numRemoteIDsNew);
1463  for(size_t i=0; i<numRemoteIDsNew; i++) {
1464  GIDs[numSameIDsNew + i] = tgtGIDs[remoteLIDsOld[i]];
1465  remoteLIDsNew[i] = numSameIDsNew+i;
1466  }
1467 
1468  // Build the new target map
1469  GO GO_INVALID = Teuchos::OrdinalTraits<GO>::invalid();
1470  RCP<const map_type> targetMapNew = rcp(new map_type(GO_INVALID,GIDs,tgtMap->getIndexBase(),tgtMap->getComm(),tgtMap->getNode()));
1471 
1472  // Exports are trivial (since the sourcemap doesn't change)
1473  Array<int> exportPIDsnew(getExportPIDs());
1474  Array<LO> exportLIDsnew(getExportLIDs());
1475 
1476  // Copy the Distributor (due to how the Import constructor works)
1477  Distributor D(getDistributor());
1478 
1479  // Build the importer using the "expert" constructor
1480  unionImport = rcp(new Import<LocalOrdinal, GlobalOrdinal, Node>(srcMap,
1481  targetMapNew,
1482  numSameIDsNew,
1483  permuteToLIDsNew,
1484  permuteFromLIDsNew,
1485  remoteLIDsNew,
1486  exportLIDsnew,
1487  exportPIDsnew,D));
1488 
1489  return unionImport;
1490  }
1491 
1492 
1493 
1494 
1495  template <class LocalOrdinal, class GlobalOrdinal, class Node>
1496  Teuchos::RCP<const Import<LocalOrdinal, GlobalOrdinal, Node> >
1498  createRemoteOnlyImport(const Teuchos::RCP<const map_type>& remoteTarget) const
1499  {
1500  using Teuchos::rcp;
1501  typedef Import<LocalOrdinal,GlobalOrdinal,Node> import_type;
1502 
1503  const size_t NumRemotes = getNumRemoteIDs ();
1504  TEUCHOS_TEST_FOR_EXCEPTION(
1505  NumRemotes != remoteTarget->getNodeNumElements (),
1506  std::runtime_error, "Tpetra::createRemoteOnlyImport: "
1507  "remoteTarget map ID count doesn't match.");
1508 
1509  // Compute the new Remote LIDs
1510  Teuchos::ArrayView<const LocalOrdinal> oldRemoteLIDs = getRemoteLIDs ();
1511  Teuchos::Array<LocalOrdinal> newRemoteLIDs (NumRemotes);
1512  for (size_t i = 0; i < NumRemotes; ++i) {
1513  newRemoteLIDs[i] = remoteTarget->getLocalElement (getTargetMap ()->getGlobalElement (oldRemoteLIDs[i]));
1514  // Now we make sure these guys are in sorted order (AztecOO-ML ordering)
1515  TEUCHOS_TEST_FOR_EXCEPTION(
1516  i > 0 && newRemoteLIDs[i] < newRemoteLIDs[i-1],
1517  std::runtime_error, "Tpetra::createRemoteOnlyImport: "
1518  "this and remoteTarget order don't match.");
1519  }
1520 
1521  // Copy ExportPIDs and such
1522  // NOTE: Be careful: The "Expert" Import constructor we use does a "swap"
1523  // for most of the LID/PID lists and the Distributor, meaning it
1524  // ruins the existing object if we pass things in directly. Hence
1525  // we copy them first.
1526  Teuchos::Array<int> newExportPIDs (getExportPIDs ());
1527  Teuchos::Array<LocalOrdinal> newExportLIDs (getExportLIDs ());
1528  Teuchos::Array<LocalOrdinal> dummy;
1529  Distributor newDistor (getDistributor ());
1530 
1531  return rcp (new import_type (getSourceMap (), remoteTarget,
1532  static_cast<size_t> (0), dummy, dummy,
1533  newRemoteLIDs, newExportLIDs,
1534  newExportPIDs, newDistor));
1535  }
1536 
1537 } // namespace Tpetra
1538 
1539 #define TPETRA_IMPORT_CLASS_INSTANT(LO, GO, NODE) \
1540  \
1541  template class Import< LO , GO , NODE >;
1542 
1543 // Explicit instantiation macro.
1544 // Only invoke this when in the Tpetra namespace.
1545 // Most users do not need to use this.
1546 //
1547 // LO: The local ordinal type.
1548 // GO: The global ordinal type.
1549 // NODE: The Kokkos Node type.
1550 #define TPETRA_IMPORT_INSTANT(LO, GO, NODE) \
1551  TPETRA_IMPORT_CLASS_INSTANT(LO, GO, NODE)
1552 
1553 #endif // TPETRA_IMPORT_DEF_HPP
bool congruent(const Teuchos::Comm< int > &comm1, const Teuchos::Comm< int > &comm2)
Whether the two communicators are congruent.
Definition: Tpetra_Util.cpp:65
Communication plan for data redistribution from a uniquely-owned to a (possibly) multiply-owned distr...
Namespace Tpetra contains the class and methods constituting the Tpetra library.
Teuchos::ArrayView< const int > getExportPIDs() const
List of processes to which entries will be sent.
Teuchos::ArrayView< const LocalOrdinal > getExportLIDs() const
List of entries in the source Map that will be sent to other processes.
Teuchos::RCP< const map_type > getSourceMap() const
The Source Map used to construct this Import object.
void sort3(const IT1 &first1, const IT1 &last1, const IT2 &first2, const IT3 &first3)
Sort the first array, and apply the same permutation to the second and third arrays.
LookupStatus
Return status of Map remote index lookup (getRemoteIndexList()).
Teuchos::ArrayView< const LocalOrdinal > getPermuteToLIDs() const
List of local IDs in the target Map that are permuted.
virtual ~Import()
Destructor.
Teuchos::RCP< const Import< LocalOrdinal, GlobalOrdinal, Node > > setUnion() const
Return the union of this Import this->getSourceMap()
bool isLocallyComplete() const
Do all target Map indices on the calling process exist on at least one process (not necessarily this ...
size_t createFromSends(const Teuchos::ArrayView< const int > &exportProcIDs)
Set up Distributor using list of process ranks to which this process will send.
size_t global_size_t
Global size_t object.
void merge2(IT1 &indResultOut, IT2 &valResultOut, IT1 indBeg, IT1 indEnd, IT2 valBeg, IT2 valEnd)
Merge values in place, additively, with the same index.
Import(const Teuchos::RCP< const map_type > &source, const Teuchos::RCP< const map_type > &target)
Construct an Import from the source and target Maps.
Teuchos::ArrayView< const LocalOrdinal > getPermuteFromLIDs() const
List of local IDs in the source Map that are permuted.
size_t getNumPermuteIDs() const
Number of IDs to permute but not to communicate.
Teuchos::ArrayView< const LocalOrdinal > getRemoteLIDs() const
List of entries in the target Map to receive from other processes.
void keyValueMerge(KeyInputIterType keyBeg1, KeyInputIterType keyEnd1, ValueInputIterType valBeg1, ValueInputIterType valEnd1, KeyInputIterType keyBeg2, KeyInputIterType keyEnd2, ValueInputIterType valBeg2, ValueInputIterType valEnd2, KeyOutputIterType keyOut, ValueOutputIterType valOut, BinaryFunction f)
Merge two sorted (by keys) sequences of unique (key,value) pairs by combining pairs with equal keys...
Communication plan for data redistribution from a (possibly) multiply-owned to a uniquely-owned distr...
Teuchos::RCP< const map_type > getTargetMap() const
The Target Map used to construct this Import object.
#define TPETRA_ABUSE_WARNING(throw_exception_test, Exception, msg)
Handle an abuse warning, according to HAVE_TPETRA_THROW_ABUSE_WARNINGS and HAVE_TPETRA_PRINT_ABUSE_WA...
Import< LocalOrdinal, GlobalOrdinal, Node > & operator=(const Import< LocalOrdinal, GlobalOrdinal, Node > &Source)
Assignment operator.
Implementation detail of Import and Export.
Sets up and executes a communication plan for a Tpetra DistObject.
size_t getNumRemoteIDs() const
Number of entries not on the calling process.
void setParameterList(const Teuchos::RCP< Teuchos::ParameterList > &plist)
Set parameters.
virtual void describe(Teuchos::FancyOStream &out, const Teuchos::EVerbosityLevel verbLevel=Teuchos::Describable::verbLevel_default) const
Describe this object in a human-readable way to the given output stream.
size_t getNumExportIDs() const
Number of entries that must be sent by the calling process to other processes.
virtual void print(std::ostream &os) const
Print the Import&#39;s data to the given output stream.
void sort2(const IT1 &first1, const IT1 &last1, const IT2 &first2)
Sort the first array, and apply the resulting permutation to the second array.
Describes a parallel distribution of objects over processes.
Internal functions and macros designed for use with Tpetra::Import and Tpetra::Export objects...
Stand-alone utility functions and macros.
size_t getNumSameIDs() const
Number of initial identical IDs.
Distributor & getDistributor() const
The Distributor that this Import object uses to move data.
Teuchos::RCP< const Import< LocalOrdinal, GlobalOrdinal, Node > > createRemoteOnlyImport(const Teuchos::RCP< const map_type > &remoteTarget) const
Returns an importer that contains only the remote entries of this.
void createFromRecvs(const Teuchos::ArrayView< const Ordinal > &remoteIDs, const Teuchos::ArrayView< const int > &remoteProcIDs, Teuchos::Array< Ordinal > &exportIDs, Teuchos::Array< int > &exportProcIDs)
Set up Distributor using list of process ranks from which to receive.
Binary function that returns its first argument.