Tpetra Matrix/Vector Services Version of the Day
Tpetra_Import.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_IMPORT_HPP
00043 #define TPETRA_IMPORT_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 "Tpetra_Distributor.hpp"
00052 #include <iterator>
00053 
00054 namespace Tpetra {
00055 
00089   template <class LocalOrdinal, class GlobalOrdinal = LocalOrdinal, class Node = Kokkos::DefaultNode::DefaultNodeType>
00090   class Import: public Teuchos::Describable {
00091 
00092   public:
00094     typedef Map<LocalOrdinal,GlobalOrdinal,Node> map_type;
00095 
00097 
00098 
00106     Import (const Teuchos::RCP<const map_type>& source,
00107             const Teuchos::RCP<const map_type>& target);
00108 
00119     Import (const Teuchos::RCP<const map_type>& source,
00120             const Teuchos::RCP<const map_type>& target,
00121             const Teuchos::RCP<Teuchos::ParameterList>& plist);
00122 
00127     Import(const Import<LocalOrdinal,GlobalOrdinal,Node> & import);
00128 
00130     ~Import();
00131 
00133 
00135 
00136 
00141     inline size_t getNumSameIDs() const;
00142 
00149     inline size_t getNumPermuteIDs() const;
00150 
00152     inline ArrayView<const LocalOrdinal> getPermuteFromLIDs() const;
00153 
00155     inline ArrayView<const LocalOrdinal> getPermuteToLIDs() const;
00156 
00158     inline size_t getNumRemoteIDs() const;
00159 
00161     inline ArrayView<const LocalOrdinal> getRemoteLIDs() const;
00162 
00164     inline size_t getNumExportIDs() const;
00165 
00167     inline ArrayView<const LocalOrdinal> getExportLIDs() const;
00168 
00173     inline ArrayView<const int> getExportImageIDs() const;
00174 
00176     inline const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& getSourceMap() const;
00177 
00179     inline const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& getTargetMap() const;
00180 
00182     inline Distributor & getDistributor() const;
00183 
00185     Import<LocalOrdinal,GlobalOrdinal,Node>&
00186     operator= (const Import<LocalOrdinal,GlobalOrdinal,Node>& Source);
00187 
00189 
00191 
00192 
00194     virtual void print(std::ostream& os) const;
00195 
00197 
00198   private:
00199 
00200     RCP<ImportExportData<LocalOrdinal,GlobalOrdinal,Node> > ImportData_;
00201     RCP<Array<GlobalOrdinal> > remoteGIDs_;
00202 
00204 
00205 
00206     //==============================================================================
00207     // sets up numSameIDs_, numPermuteIDs_, and numRemoteIDs_
00208     // these variables are already initialized to 0 by the ImportExportData ctr.
00209     // also sets up permuteToLIDs_, permuteFromLIDs_, and remoteLIDs_
00210 
00241     void setupSamePermuteRemote();
00242 
00268     void setupExport();
00269 
00271   };
00272 
00273   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00274   Import<LocalOrdinal,GlobalOrdinal,Node>::Import(const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & source,
00275                                                   const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & target) {
00276     ImportData_ = rcp(new ImportExportData<LocalOrdinal,GlobalOrdinal,Node>(source, target));
00277     // call subfunctions
00278     setupSamePermuteRemote();
00279     if (source->isDistributed()) {
00280       setupExport();
00281     }
00282     // don't need remoteGIDs_ anymore
00283     remoteGIDs_ = null;
00284   }
00285 
00286 
00287   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00288   Import<LocalOrdinal,GlobalOrdinal,Node>::
00289   Import (const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & source,
00290           const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & target,
00291           const Teuchos::RCP<Teuchos::ParameterList>& plist)
00292   {
00293     using Teuchos::rcp;
00294     typedef ImportExportData<LocalOrdinal,GlobalOrdinal,Node> data_type;
00295 
00296     ImportData_ = rcp (new data_type (source, target, plist));
00297     setupSamePermuteRemote();
00298     if (source->isDistributed()) {
00299       setupExport();
00300     }
00301     remoteGIDs_ = null; // Don't need this anymore
00302   }
00303 
00304 
00305   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00306   Import<LocalOrdinal,GlobalOrdinal,Node>::Import(const Import<LocalOrdinal,GlobalOrdinal,Node> & import)
00307   : ImportData_(import.ImportData_)
00308   {}
00309 
00310   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00311   Import<LocalOrdinal,GlobalOrdinal,Node>::~Import()
00312   {}
00313 
00314   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00315   size_t Import<LocalOrdinal,GlobalOrdinal,Node>::getNumSameIDs() const {
00316     return ImportData_->numSameIDs_;
00317   }
00318 
00319   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00320   size_t Import<LocalOrdinal,GlobalOrdinal,Node>::getNumPermuteIDs() const {
00321     return ImportData_->permuteFromLIDs_.size();
00322   }
00323 
00324   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00325   ArrayView<const LocalOrdinal>
00326   Import<LocalOrdinal,GlobalOrdinal,Node>::getPermuteFromLIDs() const {
00327     return ImportData_->permuteFromLIDs_();
00328   }
00329 
00330   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00331   ArrayView<const LocalOrdinal>
00332   Import<LocalOrdinal,GlobalOrdinal,Node>::getPermuteToLIDs() const {
00333     return ImportData_->permuteToLIDs_();
00334   }
00335 
00336   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00337   size_t Import<LocalOrdinal,GlobalOrdinal,Node>::getNumRemoteIDs() const {
00338     return ImportData_->remoteLIDs_.size();
00339   }
00340 
00341   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00342   ArrayView<const LocalOrdinal>
00343   Import<LocalOrdinal,GlobalOrdinal,Node>::getRemoteLIDs() const {
00344     return ImportData_->remoteLIDs_();
00345   }
00346 
00347   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00348   size_t Import<LocalOrdinal,GlobalOrdinal,Node>::getNumExportIDs() const {
00349     return ImportData_->exportLIDs_.size();
00350   }
00351 
00352   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00353   ArrayView<const LocalOrdinal>
00354   Import<LocalOrdinal,GlobalOrdinal,Node>::getExportLIDs() const {
00355     return ImportData_->exportLIDs_();
00356   }
00357 
00358   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00359   ArrayView<const int>
00360   Import<LocalOrdinal,GlobalOrdinal,Node>::getExportImageIDs() const {
00361     return ImportData_->exportImageIDs_();
00362   }
00363 
00364   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00365   const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &
00366   Import<LocalOrdinal,GlobalOrdinal,Node>::getSourceMap() const {
00367     return ImportData_->source_;
00368   }
00369 
00370   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00371   const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > &
00372   Import<LocalOrdinal,GlobalOrdinal,Node>::getTargetMap() const {
00373     return ImportData_->target_;
00374   }
00375 
00376   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00377   Distributor &
00378   Import<LocalOrdinal,GlobalOrdinal,Node>::getDistributor() const {
00379     return ImportData_->distributor_;
00380   }
00381 
00382   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00383   Import<LocalOrdinal,GlobalOrdinal,Node>&
00384   Import<LocalOrdinal,GlobalOrdinal,Node>::operator=(const Import<LocalOrdinal,GlobalOrdinal,Node> & source) {
00385     ImportData_ = source.ImportData_;
00386     return *this;
00387   }
00388 
00389   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00390   void Import<LocalOrdinal,GlobalOrdinal,Node>::print(std::ostream& os) const {
00391     using Teuchos::getFancyOStream;
00392     using Teuchos::rcpFromRef;
00393     using std::endl;
00394 
00395     ArrayView<const LocalOrdinal> av;
00396     ArrayView<const int> avi;
00397     const RCP<const Comm<int> > & comm = getSourceMap()->getComm();
00398     const int myImageID = comm->getRank();
00399     const int numImages = comm->getSize();
00400     for (int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
00401       if (myImageID == imageCtr) {
00402         os << endl;
00403         if (myImageID == 0) { // this is the root node (only output this info once)
00404           os << "Import Data Members:" << endl;
00405         }
00406         os << "Image ID       : " << myImageID << endl;
00407 
00408         os << "permuteFromLIDs: "; os << toString (getPermuteFromLIDs()) << endl;
00409         //av = getPermuteFromLIDs(); std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << "}" << endl;
00410 
00411         os << "permuteToLIDs  : ";
00412         os << toString (getPermuteToLIDs()) << endl;
00413         //av = getPermuteToLIDs();   std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << "}" << endl;
00414 
00415         os << "remoteLIDs     : ";
00416         os << toString (getRemoteLIDs()) << endl;
00417         //av = getRemoteLIDs();      std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << "}" << endl;
00418 
00419         os << "exportLIDs     : ";
00420         os << toString (getExportLIDs()) << endl;
00421         //av = getExportLIDs();      std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << "}" << endl;
00422 
00423         os << "exportImageIDs : ";
00424         os << toString (getExportImageIDs()) << endl;
00425         //avi = getExportImageIDs();  std::copy(avi.begin(),avi.end(),std::ostream_iterator<int>(os," ")); os << "}" << endl;
00426 
00427         os << "numSameIDs     : " << getNumSameIDs() << endl;
00428         os << "numPermuteIDs  : " << getNumPermuteIDs() << endl;
00429         os << "numRemoteIDs   : " << getNumRemoteIDs() << endl;
00430         os << "numExportIDs   : " << getNumExportIDs() << endl;
00431       }
00432 
00433       // A few global barriers give I/O a chance to complete.
00434       comm->barrier();
00435       comm->barrier();
00436       comm->barrier();
00437     }
00438 
00439     const bool printMaps = false;
00440     if (printMaps) {
00441       if (myImageID == 0) {
00442         os << endl << endl << "Source Map:" << endl << std::flush;
00443       }
00444       comm->barrier();
00445       os << *getSourceMap();
00446       comm->barrier();
00447 
00448       if (myImageID == 0) {
00449         os << endl << endl << "Target Map:" << endl << std::flush;
00450       }
00451       comm->barrier();
00452       os << *getTargetMap();
00453       comm->barrier();
00454     }
00455 
00456     // It's also helpful for debugging to print the Distributor
00457     // object.  Epetra_Import::Print() does this, so we can do a
00458     // side-by-side comparison.
00459     if (myImageID == 0) {
00460       os << endl << endl << "Distributor:" << endl << std::flush;
00461     }
00462     comm->barrier();
00463     getDistributor().describe (*(getFancyOStream (rcpFromRef (os))),
00464                                Teuchos::VERB_EXTREME);
00465   }
00466 
00467 
00468   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00469   void Import<LocalOrdinal,GlobalOrdinal,Node>::setupSamePermuteRemote() {
00470     const Map<LocalOrdinal,GlobalOrdinal,Node> & source = *getSourceMap();
00471     const Map<LocalOrdinal,GlobalOrdinal,Node> & target = *getTargetMap();
00472     ArrayView<const GlobalOrdinal> sourceGIDs = source.getNodeElementList();
00473     ArrayView<const GlobalOrdinal> targetGIDs = target.getNodeElementList();
00474 
00475     // Compute numSameIDs_:
00476     //
00477     // Iterate through the source and target GID lists.  If the i-th
00478     // GID of both is the same, increment numSameIDs_ and try the
00479     // next.  As soon as you come to a nonmatching pair, give up.
00480     //
00481     // The point of numSameIDs_ is for the common case of an Import
00482     // where all the overlapping GIDs are at the end of the source
00483     // Map, but otherwise the source and target Maps are the same.
00484     // This allows a fast contiguous copy for the initial "same IDs."
00485     typename ArrayView<const GlobalOrdinal>::iterator sourceIter = sourceGIDs.begin(),
00486                                                       targetIter = targetGIDs.begin();
00487     while (sourceIter != sourceGIDs.end() && targetIter != targetGIDs.end() && *sourceIter == *targetIter) {
00488       ++ImportData_->numSameIDs_;
00489       ++sourceIter;
00490       ++targetIter;
00491     }
00492     // targetIter should now point either to the GID of the first
00493     // non-same entry in targetGIDs, or to the end of targetGIDs (if
00494     // all the entries were the same).
00495 
00496     // Compute IDs to be permuted, vs. IDs to be received ("imported";
00497     // called "remote" IDs).
00498     //
00499     // IDs to permute are in both the source and target Maps, which
00500     // means we don't have to send or receive them, but we do have to
00501     // rearrange (permute) them in general.  (We've already identified
00502     // an initial stretch of IDs which can be copied without
00503     // rearrangement; the iterator targetIter is past that point.)
00504     // IDs to receive are in the target Map, but not the source Map.
00505     //
00506     // How do the following code and its equivalent in Export differ?
00507     //
00508     // 1. Export uses sourceIter, whereas Import uses targetIter.
00509     //
00510     // 2. Import collects remoteGIDs_ (target Map GIDs that are not in
00511     //    the source Map), which is a separate array.  Export can use
00512     //    exportGIDs_, which is an array belonging to its
00513     //    ImportExportData object.
00514     remoteGIDs_ = rcp( new Array<GlobalOrdinal>() );
00515     for (; targetIter != targetGIDs.end(); ++targetIter) {
00516       const GlobalOrdinal curTargetGID = *targetIter;
00517       if (source.isNodeGlobalElement (curTargetGID)) {
00518         // The current process owns this GID, for both the source and
00519         // the target Maps.  Determine the LIDs for this GID on both
00520         // Maps and add them to the permutation lists.
00521         ImportData_->permuteToLIDs_.push_back (target.getLocalElement (curTargetGID));
00522         ImportData_->permuteFromLIDs_.push_back (source.getLocalElement (curTargetGID));
00523       }
00524       else {
00525         // The current GID is owned by this process in the target Map,
00526         // but is not owned by this process in the source Map.  That
00527         // means the Import operation has to receive it from another
00528         // process.  Store it in the "remote" (incoming) list, along
00529         // with its destination LID on this process.
00530         //
00531         // remoteLIDs_ is the list of this process' LIDs that it has
00532         // to receive from other processes.  Since this is an Import,
00533         // and therefore the source Map is nonoverlapping, we know
00534         // that each remote LID can receive from only one process.
00535         remoteGIDs_->push_back (curTargetGID);
00536         ImportData_->remoteLIDs_.push_back (target.getLocalElement (curTargetGID));
00537       }
00538     }
00539 
00540     TPETRA_ABUSE_WARNING(
00541       getNumRemoteIDs() > 0 && ! source.isDistributed(),
00542       std::runtime_error,
00543       "::setupSamePermuteRemote(): Target has remote LIDs but Source is not "
00544       "distributed globally." << std::endl
00545       << "Importing to a submap of the target map.");
00546   }
00547 
00548 
00549   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00550   void Import<LocalOrdinal,GlobalOrdinal,Node>::setupExport() {
00551     typedef typename Array<int>::difference_type size_type;
00552     const Map<LocalOrdinal,GlobalOrdinal,Node> & source = *getSourceMap();
00553 
00554     // For each entry remoteGIDs[i], remoteImageIDs[i] will contain
00555     // the process ID of the process that owns that GID.
00556     ArrayView<GlobalOrdinal> remoteGIDs = (*remoteGIDs_)();
00557     Array<int> remoteImageIDs(remoteGIDs.size());
00558     // lookup == IDNotPresent means that the source Map wasn't able to
00559     // figure out to which processes one or more of the GIDs in the
00560     // given list of remoteGIDs belong.
00561     //
00562     // The previous abuse warning said "The target Map has GIDs not
00563     // found in the source Map."  This statement could be confusing,
00564     // because it doesn't refer to ownership by the current process,
00565     // but rather to ownership by _any_ process participating in the
00566     // Map.  (It could not possibly refer to ownership by the current
00567     // process, since remoteGIDs is exactly the list of GIDs owned by
00568     // the target Map but not owned by the source Map.  It was
00569     // constructed that way by setupSamePermuteRemote().)
00570     //
00571     // What this statement means is that the source and target Maps
00572     // don't contain the same set of GIDs globally (over all
00573     // processes).  That is, there is at least one GID owned by some
00574     // process in the target Map, which is not owned by _any_ process
00575     // in the source Map.
00576     const LookupStatus lookup = source.getRemoteIndexList(remoteGIDs, remoteImageIDs());
00577     TPETRA_ABUSE_WARNING( lookup == IDNotPresent, std::runtime_error,
00578       "::setupExport(): the source Map wasn't able to figure out which process "
00579       "owns one or more of the GIDs in the list of remote GIDs.  This probably "
00580       "means that there is at least one GID owned by some process in the target"
00581       " Map which is not owned by any process in the source Map.  (That is, the"
00582       " source and target Maps do not contain the same set of GIDs globally.)");
00583 
00584     // Ignore remote GIDs that aren't owned by any process in the
00585     // source Map.  getRemoteIndexList() gives each of these a process
00586     // ID of -1.
00587     if ( lookup == IDNotPresent ) {
00588       const size_type numInvalidRemote = std::count_if( remoteImageIDs.begin(), remoteImageIDs.end(), std::bind1st(std::equal_to<int>(),-1) );
00589       // if all of them are invalid, we can delete the whole array
00590       const size_type totalNumRemote = getNumRemoteIDs();
00591       if (numInvalidRemote == totalNumRemote) {
00592         // all remotes are invalid; we have no remotes; we can delete the remotes
00593         remoteImageIDs.clear();
00594         (*remoteGIDs_).clear();
00595         ImportData_->remoteLIDs_.clear();
00596       }
00597       else {
00598         // Some remotes are valid; we need to keep the valid ones.
00599         // Pack and resize remoteImageIDs, remoteGIDs_, and
00600         // remoteLIDs_.
00601         size_type numValidRemote = 0;
00602         for (size_type r = 0; r < totalNumRemote; ++r) {
00603           if (remoteImageIDs[r] != -1) {
00604             remoteImageIDs[numValidRemote] = remoteImageIDs[r];
00605             (*remoteGIDs_)[numValidRemote] = (*remoteGIDs_)[r];
00606             ImportData_->remoteLIDs_[numValidRemote] = ImportData_->remoteLIDs_[r];
00607             ++numValidRemote;
00608           }
00609         }
00610         TEUCHOS_TEST_FOR_EXCEPTION(
00611           numValidRemote != totalNumRemote - numInvalidRemote, std::logic_error,
00612           "Tpetra::Import::setupExport(): After removing invalid remote GIDs and"
00613           " packing the valid remote GIDs, numValidRemote = " << numValidRemote
00614           << " != totalNumRemote - numInvalidRemote = "
00615           << totalNumRemote - numInvalidRemote
00616           << ".  Please report this bug to the Tpetra developers.");
00617 
00618         remoteImageIDs.resize(numValidRemote);
00619         (*remoteGIDs_).resize(numValidRemote);
00620         ImportData_->remoteLIDs_.resize(numValidRemote);
00621       }
00622       remoteGIDs = (*remoteGIDs_)();
00623     }
00624 
00625     // Sort remoteImageIDs in ascending order, and apply the resulting
00626     // permutation to remoteGIDs_ and remoteLIDs_.  This ensures that
00627     // remoteImageIDs[i], remoteGIDs_[i], and remoteLIDs_[i] all refer
00628     // to the same thing.
00629     sort3 (remoteImageIDs.begin(),
00630            remoteImageIDs.end(),
00631            remoteGIDs.begin(),
00632            ImportData_->remoteLIDs_.begin());
00633 
00634     // Call the Distributor's createFromRecvs() method to turn the
00635     // remote GIDs and their owning processes into a send-and-receive
00636     // communication plan.  remoteGIDs and remoteImageIDs_ are input;
00637     // exportGIDs and exportImageIDs_ are output arrays which are
00638     // allocated by createFromRecvs().
00639     ArrayRCP<GlobalOrdinal> exportGIDs;
00640     ImportData_->distributor_.createFromRecvs(remoteGIDs().getConst(), remoteImageIDs, exportGIDs, ImportData_->exportImageIDs_);
00641 
00642     // Find the LIDs corresponding to the (outgoing) GIDs in
00643     // exportGIDs.  For sparse matrix-vector multiply, this tells the
00644     // calling process how to index into the source vector to get the
00645     // elements which it needs to send.
00646     if (exportGIDs != null) {
00647       ImportData_->exportLIDs_ = arcp<LocalOrdinal>(exportGIDs.size());
00648     }
00649     typename ArrayRCP<LocalOrdinal>::iterator dst = ImportData_->exportLIDs_.begin();
00650     typename ArrayRCP<GlobalOrdinal>::const_iterator src = exportGIDs.begin();
00651     while (src != exportGIDs.end()) {
00652       (*dst++) = source.getLocalElement(*src++);
00653     }
00654   }
00655 
00665   template <class LO, class GO, class Node>
00666   RCP< const Import<LO,GO,Node> >
00667   createImport( const RCP<const Map<LO,GO,Node> > & src,
00668                 const RCP<const Map<LO,GO,Node> > & tgt )
00669   {
00670     if (src == tgt) return null;
00671 #ifdef HAVE_TPETRA_DEBUG
00672     TEUCHOS_TEST_FOR_EXCEPTION(src == null || tgt == null, std::runtime_error,
00673         "Tpetra::createImport(): neither source nor target map may be null:\nsource: " << src << "\ntarget: " << tgt << "\n");
00674 #endif
00675     return rcp(new Import<LO,GO,Node>(src,tgt));
00676   }
00677 
00678 } // namespace Tpetra
00679 
00680 #endif // TPETRA_IMPORT_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines