Tpetra Matrix/Vector Services Version of the Day
Tpetra_Export.hpp
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //          Tpetra: Templated Linear Algebra Services Package
00005 //                 Copyright (2008) Sandia Corporation
00006 //
00007 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
00008 // the U.S. Government retains certain rights in this software.
00009 //
00010 // Redistribution and use in source and binary forms, with or without
00011 // modification, are permitted provided that the following conditions are
00012 // met:
00013 //
00014 // 1. Redistributions of source code must retain the above copyright
00015 // notice, this list of conditions and the following disclaimer.
00016 //
00017 // 2. Redistributions in binary form must reproduce the above copyright
00018 // notice, this list of conditions and the following disclaimer in the
00019 // documentation and/or other materials provided with the distribution.
00020 //
00021 // 3. Neither the name of the Corporation nor the names of the
00022 // contributors may be used to endorse or promote products derived from
00023 // this software without specific prior written permission.
00024 //
00025 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00026 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00027 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00028 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00029 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00030 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00031 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00032 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00033 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00034 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00035 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00036 //
00037 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00038 //
00039 // ************************************************************************
00040 // @HEADER
00041 
00042 #ifndef TPETRA_EXPORT_HPP
00043 #define TPETRA_EXPORT_HPP
00044 
00045 #include <Kokkos_DefaultNode.hpp>
00046 #include <Teuchos_Describable.hpp>
00047 #include <Teuchos_as.hpp>
00048 #include "Tpetra_Map.hpp"
00049 #include "Tpetra_Util.hpp"
00050 #include "Tpetra_ImportExportData.hpp"
00051 #include <iterator>
00052 
00053 namespace Tpetra {
00054 
00089   template <class LocalOrdinal, class GlobalOrdinal = LocalOrdinal, class Node = Kokkos::DefaultNode::DefaultNodeType>
00090   class Export: public Teuchos::Describable {
00091 
00092   public:
00094     typedef Map<LocalOrdinal,GlobalOrdinal,Node> map_type;
00095 
00097 
00098 
00106     Export (const Teuchos::RCP<const map_type>& source,
00107             const Teuchos::RCP<const map_type>& target);
00108 
00121     Export (const Teuchos::RCP<const map_type>& source,
00122             const Teuchos::RCP<const map_type>& target,
00123             const Teuchos::RCP<Teuchos::ParameterList>& plist);
00124 
00129     Export (const Export<LocalOrdinal,GlobalOrdinal,Node>& rhs);
00130 
00132     ~Export();
00133 
00135 
00137 
00138 
00139 
00144     inline size_t getNumSameIDs() const;
00145 
00152     inline size_t getNumPermuteIDs() const;
00153 
00155     inline ArrayView<const LocalOrdinal> getPermuteFromLIDs() const;
00156 
00158     inline ArrayView<const LocalOrdinal> getPermuteToLIDs() const;
00159 
00161     inline size_t getNumRemoteIDs() const;
00162 
00164     inline ArrayView<const LocalOrdinal> getRemoteLIDs() const;
00165 
00167     inline size_t getNumExportIDs() const;
00168 
00170     inline ArrayView<const LocalOrdinal> getExportLIDs() const;
00171 
00176     inline ArrayView<const int> getExportImageIDs() const;
00177 
00179     inline const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & getSourceMap() const;
00180 
00182     inline const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & getTargetMap() const;
00183 
00185     inline Distributor & getDistributor() const;
00186 
00188     Export<LocalOrdinal,GlobalOrdinal,Node>&
00189     operator= (const Export<LocalOrdinal,GlobalOrdinal,Node>& rhs);
00190 
00192 
00194 
00195 
00211     virtual void print (std::ostream& os) const;
00212 
00214 
00215   private:
00216 
00217     RCP<ImportExportData<LocalOrdinal,GlobalOrdinal,Node> > ExportData_;
00218 
00220 
00221 
00222     //==============================================================================
00223     // sets up numSameIDs_, numPermuteIDs_, and the export IDs
00224     // these variables are already initialized to 0 by the ImportExportData ctr.
00225     // also sets up permuteToLIDs_, permuteFromLIDs_, exportGIDs_, and exportLIDs_
00226     void setupSamePermuteExport();
00227     void setupRemote();
00228 
00230   };
00231 
00232 
00233   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00234   Export<LocalOrdinal,GlobalOrdinal,Node>::
00235   Export (const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& source,
00236           const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& target)
00237   {
00238     using Teuchos::rcp;
00239     typedef ImportExportData<LocalOrdinal,GlobalOrdinal,Node> data_type;
00240 
00241     ExportData_ = rcp (new data_type (source, target));
00242     setupSamePermuteExport();
00243     if (source->isDistributed()) {
00244       setupRemote();
00245     }
00246   }
00247 
00248   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00249   Export<LocalOrdinal,GlobalOrdinal,Node>::
00250   Export (const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& source,
00251           const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& target,
00252           const Teuchos::RCP<Teuchos::ParameterList>& plist)
00253   {
00254     using Teuchos::rcp;
00255     typedef ImportExportData<LocalOrdinal,GlobalOrdinal,Node> data_type;
00256 
00257     ExportData_ = rcp (new data_type (source, target, plist));
00258     setupSamePermuteExport();
00259     if (source->isDistributed()) {
00260       setupRemote();
00261     }
00262   }
00263 
00264   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00265   Export<LocalOrdinal,GlobalOrdinal,Node>::Export(const Export<LocalOrdinal,GlobalOrdinal,Node> & rhs)
00266   : ExportData_(rhs.ExportData_)
00267   {}
00268 
00269   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00270   Export<LocalOrdinal,GlobalOrdinal,Node>::~Export()
00271   {}
00272 
00273   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00274   size_t Export<LocalOrdinal,GlobalOrdinal,Node>::getNumSameIDs() const {
00275     return ExportData_->numSameIDs_;
00276   }
00277 
00278   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00279   size_t Export<LocalOrdinal,GlobalOrdinal,Node>::getNumPermuteIDs() const {
00280     return ExportData_->permuteFromLIDs_.size();
00281   }
00282 
00283   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00284   ArrayView<const LocalOrdinal>
00285   Export<LocalOrdinal,GlobalOrdinal,Node>::getPermuteFromLIDs() const {
00286     return ExportData_->permuteFromLIDs_();
00287   }
00288 
00289   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00290   ArrayView<const LocalOrdinal>
00291   Export<LocalOrdinal,GlobalOrdinal,Node>::getPermuteToLIDs() const {
00292     return ExportData_->permuteToLIDs_();
00293   }
00294 
00295   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00296   size_t Export<LocalOrdinal,GlobalOrdinal,Node>::getNumRemoteIDs() const {
00297     return ExportData_->remoteLIDs_.size();
00298   }
00299 
00300   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00301   ArrayView<const LocalOrdinal>
00302   Export<LocalOrdinal,GlobalOrdinal,Node>::getRemoteLIDs() const {
00303     return ExportData_->remoteLIDs_();
00304   }
00305 
00306   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00307   size_t Export<LocalOrdinal,GlobalOrdinal,Node>::getNumExportIDs() const {
00308     return ExportData_->exportLIDs_.size();
00309   }
00310 
00311   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00312   ArrayView<const LocalOrdinal>
00313   Export<LocalOrdinal,GlobalOrdinal,Node>::getExportLIDs() const {
00314     return ExportData_->exportLIDs_();
00315   }
00316 
00317   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00318   ArrayView<const int>
00319   Export<LocalOrdinal,GlobalOrdinal,Node>::getExportImageIDs() const {
00320     return ExportData_->exportImageIDs_();
00321   }
00322 
00323   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00324   const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &
00325   Export<LocalOrdinal,GlobalOrdinal,Node>::getSourceMap() const {
00326     return ExportData_->source_;
00327   }
00328 
00329   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00330   const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &
00331   Export<LocalOrdinal,GlobalOrdinal,Node>::getTargetMap() const {
00332     return ExportData_->target_;
00333   }
00334 
00335   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00336   Distributor &
00337   Export<LocalOrdinal,GlobalOrdinal,Node>::getDistributor() const {
00338     return ExportData_->distributor_;
00339   }
00340 
00341   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00342   Export<LocalOrdinal,GlobalOrdinal,Node>&
00343   Export<LocalOrdinal,GlobalOrdinal,Node>::operator=(const Export<LocalOrdinal,GlobalOrdinal,Node> & rhs) {
00344     if (&rhs != this) {
00345       // It's bad form to clobber your own data in a self-assignment.
00346       // This can result in dangling pointers if some member data are
00347       // raw pointers that the class deallocates in the constructor.
00348       // It doesn't matter in this case, because ExportData_ is an
00349       // RCP, which defines self-assignment sensibly.  Nevertheless,
00350       // we include the check for self-assignment, because it's good
00351       // form and not expensive (just a raw pointer comparison).
00352       ExportData_ = rhs.ExportData_;
00353     }
00354     return *this;
00355   }
00356 
00357   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00358   void Export<LocalOrdinal,GlobalOrdinal,Node>::print(std::ostream& os) const {
00359     using Teuchos::getFancyOStream;
00360     using Teuchos::rcpFromRef;
00361     using std::endl;
00362 
00363     ArrayView<const LocalOrdinal> av;
00364     ArrayView<const int> avi;
00365     const RCP<const Comm<int> > & comm = getSourceMap()->getComm();
00366     const int myImageID = comm->getRank();
00367     const int numImages = comm->getSize();
00368     for (int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
00369       if (myImageID == imageCtr) {
00370         os << endl;
00371         if (myImageID == 0) { // this is the root node (only output this info once)
00372           os << "Export Data Members:" << endl;
00373         }
00374         os << "Image ID       : " << myImageID << endl;
00375         os << "permuteFromLIDs: {"; av = getPermuteFromLIDs(); std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << " }" << endl;
00376         os << "permuteToLIDs  : {"; av = getPermuteToLIDs();   std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << " }" << endl;
00377         os << "remoteLIDs     : {"; av = getRemoteLIDs();      std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << " }" << endl;
00378         os << "exportLIDs     : {"; av = getExportLIDs();      std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << " }" << endl;
00379         os << "exportImageIDs : {"; avi = getExportImageIDs();  std::copy(avi.begin(),avi.end(),std::ostream_iterator<int>(os," ")); os << " }" << endl;
00380         os << "numSameIDs     : " << getNumSameIDs() << endl;
00381         os << "numPermuteIDs  : " << getNumPermuteIDs() << endl;
00382         os << "numRemoteIDs   : " << getNumRemoteIDs() << endl;
00383         os << "numExportIDs   : " << getNumExportIDs() << endl;
00384       }
00385       // Do a few global ops to give I/O a chance to complete
00386       comm->barrier();
00387       comm->barrier();
00388       comm->barrier();
00389     }
00390     if (myImageID == 0) {
00391       os << endl << endl << "Source Map:" << endl << std::flush;
00392     }
00393     comm->barrier();
00394     os << *getSourceMap();
00395     comm->barrier();
00396 
00397     if (myImageID == 0) {
00398       os << endl << endl << "Target Map:" << endl << std::flush;
00399     }
00400     comm->barrier();
00401     os << *getTargetMap();
00402     comm->barrier();
00403 
00404     // It's also helpful for debugging to print the Distributor
00405     // object.  Epetra_Import::Print() does this (or _should_ do this,
00406     // but doesn't, as of 05 Jan 2012), so we can do a side-by-side
00407     // comparison.
00408     if (myImageID == 0) {
00409       os << endl << endl << "Distributor:" << endl << std::flush;
00410     }
00411     comm->barrier();
00412     getDistributor().describe (*(getFancyOStream (rcpFromRef (os))),
00413                                Teuchos::VERB_EXTREME);
00414   }
00415 
00416 
00417   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00418   void
00419   Export<LocalOrdinal,GlobalOrdinal,Node>::setupSamePermuteExport()
00420   {
00421     const Map<LocalOrdinal,GlobalOrdinal,Node> & source = *getSourceMap();
00422     const Map<LocalOrdinal,GlobalOrdinal,Node> & target = *getTargetMap();
00423     ArrayView<const GlobalOrdinal> sourceGIDs = source.getNodeElementList();
00424     ArrayView<const GlobalOrdinal> targetGIDs = target.getNodeElementList();
00425 
00426     // Compute numSameIDs_:
00427     //
00428     // Iterate through the source and target GID lists.  If the i-th
00429     // GID of both is the same, increment numSameIDs_ and try the
00430     // next.  As soon as you come to a nonmatching pair, give up.
00431     //
00432     // The point of numSameIDs_ is for the common case of an Export
00433     // where all the overlapping GIDs are at the end of the target
00434     // Map, but otherwise the source and target Maps are the same.
00435     // This allows a fast contiguous copy for the initial "same IDs."
00436     typename ArrayView<const GlobalOrdinal>::iterator sourceIter = sourceGIDs.begin(),
00437                                                       targetIter = targetGIDs.begin();
00438     while (sourceIter != sourceGIDs.end() && targetIter != targetGIDs.end() && *sourceIter == *targetIter) {
00439       ++ExportData_->numSameIDs_;
00440       ++sourceIter;
00441       ++targetIter;
00442     }
00443     // sourceIter should now point either to the GID of the first
00444     // non-same entry in sourceGIDs, or to the end of sourceGIDs (if
00445     // all the entries were the same).
00446 
00447     // Compute IDs to be permuted, vs. IDs to be sent out ("exported";
00448     // called "export" IDs).
00449     //
00450     // IDs to permute are in both the source and target Maps, which
00451     // means we don't have to send or receive them, but we do have to
00452     // rearrange (permute) them in general.  (We've already identified
00453     // an initial stretch of IDs which can be copied without
00454     // rearrangement; the iterator sourceIter is past that point.)
00455     // IDs to send out are in the source Map, but not the target Map.
00456     for (; sourceIter != sourceGIDs.end(); ++sourceIter) {
00457       const GlobalOrdinal curSourceGID = *sourceIter;
00458       if (target.isNodeGlobalElement (curSourceGID)) {
00459         // The current process owns this GID, for both the source and
00460         // the target Maps.  Determine the LIDs for this GID on both
00461         // Maps and add them to the permutation lists.
00462         ExportData_->permuteToLIDs_.push_back (target.getLocalElement (curSourceGID));
00463         ExportData_->permuteFromLIDs_.push_back (source.getLocalElement (curSourceGID));
00464       }
00465       else {
00466         // The current GID is owned by this process in the source Map,
00467         // but is not owned by this process in the target Map.  That
00468         // means the Export operation has to send it to another
00469         // process.  Store such GIDs in the "export" (outgoing) list.
00470         //
00471         // QUESTION (mfh 18 Aug 2012) Import at this point computes
00472         // remoteLIDs_.  Would it makes sense to compute them here,
00473         // instead of passing over exportGIDs_ again below?  That
00474         // would make the implementations of Export and Import look
00475         // more alike.
00476         ExportData_->exportGIDs_.push_back (curSourceGID);
00477       }
00478     }
00479 
00480     // Above, we filled exportGIDs_ with all the "outgoing" GIDs (that
00481     // is, the GIDs which we own in the source Map, but not in the
00482     // target Map).  Now allocate exportLIDs_, and fill it with the
00483     // LIDs (from the source Map) corresponding to those GIDs.
00484     //
00485     // exportLIDs_ is the list of this process' LIDs that it has to
00486     // send out.  Since this is an Export, and therefore the target
00487     // Map is nonoverlapping, we know that each export LID only needs
00488     // to be sent to one process.  However, the source Map may be
00489     // overlapping, so multiple processes might send to the same LID
00490     // on a receiving process.
00491     if (ExportData_->exportGIDs_.size()) {
00492       ExportData_->exportLIDs_ = arcp<LocalOrdinal>(ExportData_->exportGIDs_.size());
00493     }
00494     {
00495       typename ArrayRCP<LocalOrdinal>::iterator liditer = ExportData_->exportLIDs_.begin();
00496       typename Array<GlobalOrdinal>::iterator   giditer = ExportData_->exportGIDs_.begin();
00497       for (; giditer != ExportData_->exportGIDs_.end(); ++liditer, ++giditer) {
00498         *liditer = source.getLocalElement(*giditer);
00499       }
00500     }
00501 
00502     TPETRA_ABUSE_WARNING(
00503       getNumExportIDs() > 0 && ! source.isDistributed(),
00504       std::runtime_error,
00505       "::setupSamePermuteExport(): Source has export LIDs but Source is not "
00506       "distributed globally." << std::endl
00507       << "Importing to a submap of the target map.");
00508 
00509     // Compute exportImageIDs_ ("outgoing" process IDs).
00510     //
00511     // For each GID in exportGIDs_ (GIDs to which this process must
00512     // send), find its corresponding owning process (a.k.a. "image")
00513     // ID in the target Map.  Store these process IDs in
00514     // exportImageIDs_.  These are the process IDs to which the Export
00515     // needs to send data.
00516     //
00517     // We only need to do this if the source Map is distributed;
00518     // otherwise, the Export doesn't have to perform any
00519     // communication.
00520     if (source.isDistributed()) {
00521       ExportData_->exportImageIDs_ = arcp<int>(ExportData_->exportGIDs_.size());
00522       // This call will assign any GID in the target Map with no
00523       // corresponding process ID a fake process ID of -1.  We'll use
00524       // this below to remove exports for processses that don't exist.
00525       const LookupStatus lookup = target.getRemoteIndexList(ExportData_->exportGIDs_(), ExportData_->exportImageIDs_());
00526       TPETRA_ABUSE_WARNING( lookup == IDNotPresent, std::runtime_error,
00527         "::setupSamePermuteExport(): The source Map has GIDs not found in the target Map.");
00528 
00529       // Get rid of process IDs not in the target Map.  This prevents
00530       // exporting to GIDs which don't belong to any process in the
00531       // target Map.
00532       typedef typename ArrayRCP<int>::difference_type size_type;
00533       if (lookup == IDNotPresent) {
00534         const size_type numInvalidExports =
00535           std::count_if (ExportData_->exportImageIDs_().begin(),
00536                          ExportData_->exportImageIDs_().end(),
00537                          std::bind1st (std::equal_to<int>(), -1));
00538 
00539         // count number of valid and total number of exports
00540         const size_type totalNumExports = ExportData_->exportImageIDs_.size();
00541         if (numInvalidExports == totalNumExports) {
00542           // all exports are invalid; we have no exports; we can delete all exports
00543           ExportData_->exportGIDs_.resize(0);
00544           ExportData_->exportLIDs_ = null;
00545           ExportData_->exportImageIDs_ = null;
00546         }
00547         else {
00548           // some exports are valid; we need to keep the valid exports
00549           // pack and resize
00550           size_type numValidExports = 0;
00551           for (size_type e = 0; e < totalNumExports; ++e) {
00552             if (ExportData_->exportImageIDs_[e] != -1) {
00553               ExportData_->exportGIDs_[numValidExports]     = ExportData_->exportGIDs_[e];
00554               ExportData_->exportLIDs_[numValidExports]     = ExportData_->exportLIDs_[e];
00555               ExportData_->exportImageIDs_[numValidExports] = ExportData_->exportImageIDs_[e];
00556               ++numValidExports;
00557             }
00558           }
00559           ExportData_->exportGIDs_.resize(numValidExports);
00560           ExportData_->exportLIDs_.resize(numValidExports);
00561           ExportData_->exportImageIDs_.resize(numValidExports);
00562         }
00563       }
00564     }
00565   } // setupSamePermuteExport()
00566 
00567 
00568   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00569   void
00570   Export<LocalOrdinal,GlobalOrdinal,Node>::setupRemote()
00571   {
00572     const Map<LocalOrdinal,GlobalOrdinal,Node>& target = *getTargetMap();
00573 
00574     // Sort exportImageIDs_ in ascending order, and apply the same
00575     // permutation to exportGIDs_ and exportLIDs_.  This ensures that
00576     // exportImageIDs_[i], exportGIDs_[i], and exportLIDs_[i] all
00577     // refer to the same thing.
00578     sort3 (ExportData_->exportImageIDs_.begin(),
00579            ExportData_->exportImageIDs_.end(),
00580            ExportData_->exportGIDs_.begin(),
00581            ExportData_->exportLIDs_.begin());
00582 
00583     // Construct the list of entries that calling image needs to send
00584     // as a result of everyone asking for what it needs to receive.
00585     //
00586     // mfh 05 Jan 2012: I understand the above comment as follows:
00587     // Construct the communication plan from the list of image IDs to
00588     // which we need to send.
00589     size_t numRemoteIDs;
00590     numRemoteIDs = ExportData_->distributor_.createFromSends (ExportData_->exportImageIDs_());
00591 
00592     // Use the communication plan with ExportGIDs to find out who is
00593     // sending to us and get the proper ordering of GIDs for incoming
00594     // remote entries (these will be converted to LIDs when done).
00595     Array<GlobalOrdinal> remoteGIDs(numRemoteIDs);
00596     ExportData_->distributor_.doPostsAndWaits (ExportData_->exportGIDs_().getConst(), 1, remoteGIDs());
00597 
00598     // Remote (incoming) IDs come in as GIDs; convert to LIDs.  LIDs
00599     // tell this process where to store the incoming remote data.
00600     ExportData_->remoteLIDs_.resize(numRemoteIDs);
00601     {
00602       typename Array<GlobalOrdinal>::const_iterator i = remoteGIDs.begin();
00603       typename Array<LocalOrdinal>::iterator        j = ExportData_->remoteLIDs_.begin();
00604       while (i != remoteGIDs.end()) {
00605         *j++ = target.getLocalElement(*i++);
00606       }
00607     }
00608   }
00609 
00619   template <class LO, class GO, class Node>
00620   RCP< const Export<LO,GO,Node> >
00621   createExport( const RCP<const Map<LO,GO,Node> > & src,
00622                 const RCP<const Map<LO,GO,Node> > & tgt )
00623   {
00624     if (src == tgt) return null;
00625 #ifdef HAVE_TPETRA_DEBUG
00626     TEUCHOS_TEST_FOR_EXCEPTION(src == null || tgt == null, std::runtime_error,
00627         "Tpetra::createExport(): neither source nor target map may be null:\nsource: " << src << "\ntarget: " << tgt << "\n");
00628 #endif
00629     return rcp(new Export<LO,GO,Node>(src,tgt));
00630   }
00631 
00632 } // namespace Tpetra
00633 
00634 #endif // TPETRA_EXPORT_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines