Tpetra Matrix/Vector Services Version of the Day
Tpetra_Export_def.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_DEF_HPP
00043 #define TPETRA_EXPORT_DEF_HPP
00044 
00045 #ifdef DOXYGEN_USE_ONLY
00046 #  include <Tpetra_Export_decl.hpp>
00047 #endif // DOXYGEN_USE_ONLY
00048 
00049 #include <Tpetra_Distributor.hpp>
00050 #include <Tpetra_Map.hpp>
00051 #include <Tpetra_ImportExportData.hpp>
00052 #include <Tpetra_Util.hpp>
00053 #include <Tpetra_Import.hpp>
00054 #include <Teuchos_as.hpp>
00055 
00056 namespace {
00057   // Default value of Export's "Debug" parameter.
00058   const bool tpetraExportDebugDefault = false;
00059 } // namespace (anonymous)
00060 
00061 namespace Tpetra {
00062   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00063   void
00064   Export<LocalOrdinal,GlobalOrdinal,Node>::
00065   setParameterList (const Teuchos::RCP<Teuchos::ParameterList>& plist)
00066   {
00067     bool debug = tpetraExportDebugDefault;
00068     if (! plist.is_null ()) {
00069       try {
00070         debug = plist->get<bool> ("Debug");
00071       } catch (Teuchos::Exceptions::InvalidParameter&) {}
00072     }
00073     debug_ = debug;
00074     ExportData_->distributor_.setParameterList (plist);
00075   }
00076 
00077   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00078   Export<LocalOrdinal,GlobalOrdinal,Node>::
00079   Export (const Teuchos::RCP<const map_type >& source,
00080           const Teuchos::RCP<const map_type >& target) :
00081     out_ (Teuchos::getFancyOStream (Teuchos::rcpFromRef (std::cerr))),
00082     debug_ (tpetraExportDebugDefault)
00083   {
00084     using Teuchos::rcp;
00085     using std::endl;
00086     typedef ImportExportData<LocalOrdinal,GlobalOrdinal,Node> data_type;
00087 
00088     if (! out_.is_null ()) {
00089       out_->pushTab ();
00090     }
00091     if (debug_) {
00092       std::ostringstream os;
00093       const int myRank = source->getComm ()->getRank ();
00094       os << myRank << ": Export ctor" << endl;
00095       *out_ << os.str ();
00096     }
00097     ExportData_ = rcp (new data_type (source, target, out_));
00098     Teuchos::Array<GlobalOrdinal> exportGIDs;
00099     setupSamePermuteExport (exportGIDs);
00100     if (debug_) {
00101       std::ostringstream os;
00102       const int myRank = source->getComm ()->getRank ();
00103       os << myRank << ": Export ctor: "
00104          << "setupSamePermuteExport done" << endl;
00105       *out_ << os.str ();
00106     }
00107     if (source->isDistributed ()) {
00108       setupRemote (exportGIDs);
00109     }
00110     if (debug_) {
00111       std::ostringstream os;
00112       const int myRank = source->getComm ()->getRank ();
00113       os << myRank << ": Export ctor: done" << endl;
00114       *out_ << os.str ();
00115     }
00116     if (! out_.is_null ()) {
00117       out_->popTab ();
00118     }
00119   }
00120 
00121   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00122   Export<LocalOrdinal,GlobalOrdinal,Node>::
00123   Export (const Teuchos::RCP<const map_type >& source,
00124           const Teuchos::RCP<const map_type >& target,
00125           const RCP<Teuchos::FancyOStream>& out) :
00126     out_ (out),
00127     debug_ (tpetraExportDebugDefault)
00128   {
00129     using Teuchos::rcp;
00130     using std::endl;
00131     typedef ImportExportData<LocalOrdinal,GlobalOrdinal,Node> data_type;
00132 
00133     if (! out_.is_null ()) {
00134       out_->pushTab ();
00135     }
00136     if (debug_) {
00137       std::ostringstream os;
00138       const int myRank = source->getComm ()->getRank ();
00139       os << myRank << ": Export ctor" << endl;
00140       *out_ << os.str ();
00141     }
00142     ExportData_ = rcp (new data_type (source, target, out));
00143     Teuchos::Array<GlobalOrdinal> exportGIDs;
00144     setupSamePermuteExport (exportGIDs);
00145     if (debug_) {
00146       std::ostringstream os;
00147       const int myRank = source->getComm ()->getRank ();
00148       os << myRank << ": Export ctor: "
00149          << "setupSamePermuteExport done" << endl;
00150       *out_ << os.str ();
00151     }
00152     if (source->isDistributed ()) {
00153       setupRemote (exportGIDs);
00154     }
00155     if (debug_) {
00156       std::ostringstream os;
00157       const int myRank = source->getComm ()->getRank ();
00158       os << myRank << ": Export ctor: done" << endl;
00159       *out_ << os.str ();
00160     }
00161     if (! out_.is_null ()) {
00162       out_->popTab ();
00163     }
00164   }
00165 
00166   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00167   Export<LocalOrdinal,GlobalOrdinal,Node>::
00168   Export (const Teuchos::RCP<const map_type >& source,
00169           const Teuchos::RCP<const map_type >& target,
00170           const Teuchos::RCP<Teuchos::ParameterList>& plist) :
00171     out_ (Teuchos::getFancyOStream (Teuchos::rcpFromRef (std::cerr))),
00172     debug_ (tpetraExportDebugDefault)
00173   {
00174     using Teuchos::rcp;
00175     using std::endl;
00176     typedef ImportExportData<LocalOrdinal,GlobalOrdinal,Node> data_type;
00177 
00178     // Read "Debug" parameter from the input ParameterList.
00179     bool debug = tpetraExportDebugDefault;
00180     if (! plist.is_null ()) {
00181       try {
00182         debug = plist->get<bool> ("Debug");
00183       } catch (Teuchos::Exceptions::InvalidParameter&) {}
00184     }
00185     debug_ = debug;
00186 
00187     if (! out_.is_null ()) {
00188       out_->pushTab ();
00189     }
00190     if (debug_) {
00191       std::ostringstream os;
00192       const int myRank = source->getComm ()->getRank ();
00193       os << myRank << ": Export ctor" << endl;
00194       *out_ << os.str ();
00195     }
00196     ExportData_ = rcp (new data_type (source, target, out_, plist));
00197     Teuchos::Array<GlobalOrdinal> exportGIDs;
00198     setupSamePermuteExport (exportGIDs);
00199     if (debug_) {
00200       std::ostringstream os;
00201       const int myRank = source->getComm ()->getRank ();
00202       os << myRank << ": Export ctor: "
00203          << "setupSamePermuteExport done" << endl;
00204       *out_ << os.str ();
00205     }
00206     if (source->isDistributed ()) {
00207       setupRemote (exportGIDs);
00208     }
00209     if (debug_) {
00210       std::ostringstream os;
00211       const int myRank = source->getComm ()->getRank ();
00212       os << myRank << ": Export ctor: done" << endl;
00213       *out_ << os.str ();
00214     }
00215     if (! out_.is_null ()) {
00216       out_->popTab ();
00217     }
00218   }
00219 
00220   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00221   Export<LocalOrdinal,GlobalOrdinal,Node>::
00222   Export (const Teuchos::RCP<const map_type >& source,
00223           const Teuchos::RCP<const map_type >& target,
00224           const RCP<Teuchos::FancyOStream>& out,
00225           const Teuchos::RCP<Teuchos::ParameterList>& plist) :
00226     out_ (Teuchos::getFancyOStream (Teuchos::rcpFromRef (std::cerr))),
00227     debug_ (tpetraExportDebugDefault)
00228   {
00229     using Teuchos::rcp;
00230     using std::endl;
00231     typedef ImportExportData<LocalOrdinal,GlobalOrdinal,Node> data_type;
00232 
00233     // Read "Debug" parameter from the input ParameterList.
00234     bool debug = tpetraExportDebugDefault;
00235     if (! plist.is_null ()) {
00236       try {
00237         debug = plist->get<bool> ("Debug");
00238       } catch (Teuchos::Exceptions::InvalidParameter&) {}
00239     }
00240     debug_ = debug;
00241 
00242     if (! out_.is_null ()) {
00243       out_->pushTab ();
00244     }
00245     if (debug_) {
00246       std::ostringstream os;
00247       const int myRank = source->getComm ()->getRank ();
00248       os << myRank << ": Export ctor" << endl;
00249       *out_ << os.str ();
00250     }
00251     ExportData_ = rcp (new data_type (source, target, out, plist));
00252     Teuchos::Array<GlobalOrdinal> exportGIDs;
00253     setupSamePermuteExport (exportGIDs);
00254     if (debug_) {
00255       std::ostringstream os;
00256       const int myRank = source->getComm ()->getRank ();
00257       os << myRank << ": Export ctor: "
00258          << "setupSamePermuteExport done" << endl;
00259       *out_ << os.str ();
00260     }
00261     if (source->isDistributed ()) {
00262       setupRemote (exportGIDs);
00263     }
00264     if (debug_) {
00265       std::ostringstream os;
00266       const int myRank = source->getComm ()->getRank ();
00267       os << myRank << ": Export ctor: done" << endl;
00268       *out_ << os.str ();
00269     }
00270     if (! out_.is_null ()) {
00271       out_->popTab ();
00272     }
00273   }
00274 
00275   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00276   Export<LocalOrdinal,GlobalOrdinal,Node>::
00277   Export (const Export<LocalOrdinal,GlobalOrdinal,Node>& rhs)
00278     : ExportData_ (rhs.ExportData_),
00279       out_ (rhs.out_),
00280       debug_ (rhs.debug_)
00281   {
00282     using std::endl;
00283 
00284     if (! out_.is_null ()) {
00285       out_->pushTab ();
00286     }
00287     if (debug_) {
00288       std::ostringstream os;
00289       const int myRank = getSourceMap ()->getComm ()->getRank ();
00290       os << myRank << ": Export copy ctor (done)" << endl;
00291       *out_ << os.str ();
00292     }
00293     if (! out_.is_null ()) {
00294       out_->popTab ();
00295     }
00296   }
00297 
00298   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00299   Export<LocalOrdinal,GlobalOrdinal,Node>::
00300   Export (const Import<LocalOrdinal,GlobalOrdinal,Node>& importer)
00301     : out_ (importer.out_)
00302     , debug_ (importer.debug_)
00303   {
00304     if(!importer.ImportData_.is_null())  ExportData_ = importer.ImportData_->reverseClone();
00305   }
00306 
00307   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00308   Export<LocalOrdinal,GlobalOrdinal,Node>::~Export()
00309   {}
00310 
00311   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00312   size_t Export<LocalOrdinal,GlobalOrdinal,Node>::getNumSameIDs() const {
00313     return ExportData_->numSameIDs_;
00314   }
00315 
00316   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00317   size_t Export<LocalOrdinal,GlobalOrdinal,Node>::getNumPermuteIDs() const {
00318     return ExportData_->permuteFromLIDs_.size();
00319   }
00320 
00321   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00322   ArrayView<const LocalOrdinal>
00323   Export<LocalOrdinal,GlobalOrdinal,Node>::getPermuteFromLIDs() const {
00324     return ExportData_->permuteFromLIDs_();
00325   }
00326 
00327   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00328   ArrayView<const LocalOrdinal>
00329   Export<LocalOrdinal,GlobalOrdinal,Node>::getPermuteToLIDs() const {
00330     return ExportData_->permuteToLIDs_();
00331   }
00332 
00333   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00334   size_t Export<LocalOrdinal,GlobalOrdinal,Node>::getNumRemoteIDs() const {
00335     return ExportData_->remoteLIDs_.size();
00336   }
00337 
00338   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00339   ArrayView<const LocalOrdinal>
00340   Export<LocalOrdinal,GlobalOrdinal,Node>::getRemoteLIDs() const {
00341     return ExportData_->remoteLIDs_();
00342   }
00343 
00344   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00345   size_t Export<LocalOrdinal,GlobalOrdinal,Node>::getNumExportIDs() const {
00346     return ExportData_->exportLIDs_.size();
00347   }
00348 
00349   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00350   ArrayView<const LocalOrdinal>
00351   Export<LocalOrdinal,GlobalOrdinal,Node>::getExportLIDs() const {
00352     return ExportData_->exportLIDs_();
00353   }
00354 
00355   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00356   ArrayView<const int>
00357   Export<LocalOrdinal,GlobalOrdinal,Node>::getExportPIDs() const {
00358     return ExportData_->exportPIDs_();
00359   }
00360 
00361   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00362   Teuchos::RCP<const typename Export<LocalOrdinal,GlobalOrdinal,Node>::map_type>
00363   Export<LocalOrdinal,GlobalOrdinal,Node>::getSourceMap() const {
00364     return ExportData_->source_;
00365   }
00366 
00367   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00368   Teuchos::RCP<const typename Export<LocalOrdinal,GlobalOrdinal,Node>::map_type>
00369   Export<LocalOrdinal,GlobalOrdinal,Node>::getTargetMap() const {
00370     return ExportData_->target_;
00371   }
00372 
00373   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00374   Distributor &
00375   Export<LocalOrdinal,GlobalOrdinal,Node>::getDistributor() const {
00376     return ExportData_->distributor_;
00377   }
00378 
00379   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00380   Export<LocalOrdinal,GlobalOrdinal,Node>&
00381   Export<LocalOrdinal,GlobalOrdinal,Node>::
00382   operator= (const Export<LocalOrdinal,GlobalOrdinal,Node>& rhs) {
00383     if (&rhs != this) {
00384       ExportData_ = rhs.ExportData_;
00385     }
00386     return *this;
00387   }
00388 
00389   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00390   void Export<LocalOrdinal,GlobalOrdinal,Node>::
00391   print (std::ostream& os) const
00392   {
00393     using Teuchos::Comm;
00394     using Teuchos::getFancyOStream;
00395     using Teuchos::RCP;
00396     using Teuchos::rcpFromRef;
00397     using Teuchos::toString;
00398     using std::endl;
00399 
00400     RCP<const Comm<int> > comm = getSourceMap ()->getComm ();
00401     const int myImageID = comm->getRank ();
00402     const int numImages = comm->getSize ();
00403     for (int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
00404       if (myImageID == imageCtr) {
00405         os << endl;
00406         if (myImageID == 0) { // I'm the root node (only output this info once)
00407           os << "Export Data Members:" << endl;
00408         }
00409         os << "Image ID       : " << myImageID << endl;
00410 
00411         os << "permuteFromLIDs: " << toString (getPermuteFromLIDs ()) << endl;
00412         os << "permuteToLIDs  : " << toString (getPermuteToLIDs ()) << endl;
00413         os << "remoteLIDs     : " << toString (getRemoteLIDs ()) << endl;
00414         os << "exportLIDs     : " << toString (getExportLIDs ()) << endl;
00415         os << "exportPIDs     : " << toString (getExportPIDs ()) << endl;
00416 
00417         os << "numSameIDs     : " << getNumSameIDs () << endl;
00418         os << "numPermuteIDs  : " << getNumPermuteIDs () << endl;
00419         os << "numRemoteIDs   : " << getNumRemoteIDs () << endl;
00420         os << "numExportIDs   : " << getNumExportIDs () << endl;
00421       }
00422       // A few global barriers give output a chance to complete.
00423       comm->barrier();
00424       comm->barrier();
00425       comm->barrier();
00426     }
00427     if (myImageID == 0) {
00428       os << endl << endl << "Source Map:" << endl << std::flush;
00429     }
00430     comm->barrier();
00431     os << *getSourceMap();
00432     comm->barrier();
00433 
00434     if (myImageID == 0) {
00435       os << endl << endl << "Target Map:" << endl << std::flush;
00436     }
00437     comm->barrier();
00438     os << *getTargetMap();
00439     comm->barrier();
00440 
00441     // It's also helpful for debugging to print the Distributor
00442     // object.  Epetra_Export::Print() does this, so we can do a
00443     // side-by-side comparison.
00444     if (myImageID == 0) {
00445       os << endl << endl << "Distributor:" << endl << std::flush;
00446     }
00447     comm->barrier();
00448     getDistributor().describe (*(getFancyOStream (rcpFromRef (os))),
00449                                Teuchos::VERB_EXTREME);
00450   }
00451 
00452 
00453   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00454   void
00455   Export<LocalOrdinal,GlobalOrdinal,Node>::
00456   setupSamePermuteExport (Teuchos::Array<GlobalOrdinal>& exportGIDs)
00457   {
00458     using Teuchos::arcp;
00459     using Teuchos::Array;
00460     using Teuchos::ArrayRCP;
00461     using Teuchos::ArrayView;
00462     using Teuchos::as;
00463     using Teuchos::null;
00464     typedef LocalOrdinal LO;
00465     typedef GlobalOrdinal GO;
00466     typedef typename ArrayView<const GO>::size_type size_type;
00467     const map_type& source = * (getSourceMap ());
00468     const map_type& target = * (getTargetMap ());
00469     ArrayView<const GO> sourceGIDs = source.getNodeElementList ();
00470     ArrayView<const GO> targetGIDs = target.getNodeElementList ();
00471 
00472 #ifdef HAVE_TPETRA_DEBUG
00473     ArrayView<const GO> rawSrcGids = sourceGIDs;
00474     ArrayView<const GO> rawTgtGids = targetGIDs;
00475 #else
00476     const GO* const rawSrcGids = sourceGIDs.getRawPtr ();
00477     const GO* const rawTgtGids = targetGIDs.getRawPtr ();
00478 #endif // HAVE_TPETRA_DEBUG
00479     const size_type numSrcGids = sourceGIDs.size ();
00480     const size_type numTgtGids = targetGIDs.size ();
00481     const size_type numGids = std::min (numSrcGids, numTgtGids);
00482 
00483     // Compute numSameIDs_: the number of initial GIDs that are the
00484     // same (and occur in the same order) in both Maps.  The point of
00485     // numSameIDs_ is for the common case of an Export where all the
00486     // overlapping GIDs are at the end of the source Map, but
00487     // otherwise the source and target Maps are the same.  This allows
00488     // a fast contiguous copy for the initial "same IDs."
00489     size_type numSameGids = 0;
00490     for ( ; numSameGids < numGids && rawSrcGids[numSameGids] == rawTgtGids[numSameGids]; ++numSameGids)
00491       {} // third clause of 'for' does everything
00492     ExportData_->numSameIDs_ = numSameGids;
00493 
00494     // Compute permuteToLIDs_, permuteFromLIDs_, exportGIDs, and
00495     // exportLIDs_.  The first two arrays are IDs to be permuted, and
00496     // the latter two arrays are IDs to sent out ("exported"), called
00497     // "export" 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.  IDs to send are in the
00502     // source Map, but not in the target Map.
00503 
00504     exportGIDs.resize (0);
00505     Array<LO>& permuteToLIDs = ExportData_->permuteToLIDs_;
00506     Array<LO>& permuteFromLIDs = ExportData_->permuteFromLIDs_;
00507     Array<LO>& exportLIDs = ExportData_->exportLIDs_;
00508     const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid ();
00509     const LO numSrcLids = as<LO> (numSrcGids);
00510     // Iterate over the source Map's LIDs, since we only need to do
00511     // GID -> LID lookups for the target Map.
00512     for (LO srcLid = numSameGids; srcLid < numSrcLids; ++srcLid) {
00513       const GO curSrcGid = rawSrcGids[srcLid];
00514       // getLocalElement() returns LINVALID if the GID isn't in the target Map.
00515       // This saves us a lookup (which isNodeGlobalElement() would do).
00516       const LO tgtLid = target.getLocalElement (curSrcGid);
00517       if (tgtLid != LINVALID) { // if target.isNodeGlobalElement (curSrcGid)
00518         permuteToLIDs.push_back (tgtLid);
00519         permuteFromLIDs.push_back (srcLid);
00520       } else {
00521         exportGIDs.push_back (curSrcGid);
00522         exportLIDs.push_back (srcLid);
00523       }
00524     }
00525 
00526     // exportLIDs_ is the list of this process' LIDs that it has to
00527     // send out.  Since this is an Export, and therefore the target
00528     // Map is nonoverlapping, we know that each export LID only needs
00529     // to be sent to one process.  However, the source Map may be
00530     // overlapping, so multiple processes might send to the same LID
00531     // on a receiving process.
00532 
00533     TPETRA_ABUSE_WARNING(
00534       getNumExportIDs() > 0 && ! source.isDistributed(),
00535       std::runtime_error,
00536       "::setupSamePermuteExport(): Source has export LIDs but Source is not "
00537       "distributed globally." << std::endl
00538       << "Exporting to a submap of the target map.");
00539 
00540     // Compute exportPIDs_ ("outgoing" process IDs).
00541     //
00542     // For each GID in exportGIDs (GIDs to which this process must
00543     // send), find its corresponding owning process (a.k.a. "image")
00544     // ID in the target Map.  Store these process IDs in
00545     // exportPIDs_.  These are the process IDs to which the Export
00546     // needs to send data.
00547     //
00548     // We only need to do this if the source Map is distributed;
00549     // otherwise, the Export doesn't have to perform any
00550     // communication.
00551     if (source.isDistributed ()) {
00552       ExportData_->exportPIDs_.resize(exportGIDs.size ());
00553       // This call will assign any GID in the target Map with no
00554       // corresponding process ID a fake process ID of -1.  We'll use
00555       // this below to remove exports for processses that don't exist.
00556       const LookupStatus lookup =
00557         target.getRemoteIndexList (exportGIDs(),
00558                                    ExportData_->exportPIDs_ ());
00559       TPETRA_ABUSE_WARNING( lookup == IDNotPresent, std::runtime_error,
00560         "::setupSamePermuteExport(): The source Map has GIDs not found "
00561         "in the target Map.");
00562 
00563       // Get rid of process IDs not in the target Map.  This prevents
00564       // exporting to GIDs which don't belong to any process in the
00565       // target Map.
00566       if (lookup == IDNotPresent) {
00567         const size_type numInvalidExports =
00568           std::count_if (ExportData_->exportPIDs_().begin(),
00569                          ExportData_->exportPIDs_().end(),
00570                          std::bind1st (std::equal_to<int>(), -1));
00571 
00572         // count number of valid and total number of exports
00573         const size_type totalNumExports = ExportData_->exportPIDs_.size();
00574         if (numInvalidExports == totalNumExports) {
00575           // all exports are invalid; we have no exports; we can delete all exports
00576           exportGIDs.resize(0);
00577           ExportData_->exportLIDs_.resize(0);
00578           ExportData_->exportPIDs_.resize(0);
00579         }
00580         else {
00581           // some exports are valid; we need to keep the valid exports
00582           // pack and resize
00583           size_type numValidExports = 0;
00584           for (size_type e = 0; e < totalNumExports; ++e) {
00585             if (ExportData_->exportPIDs_[e] != -1) {
00586               exportGIDs[numValidExports]               = exportGIDs[e];
00587               ExportData_->exportLIDs_[numValidExports] = ExportData_->exportLIDs_[e];
00588               ExportData_->exportPIDs_[numValidExports] = ExportData_->exportPIDs_[e];
00589               ++numValidExports;
00590             }
00591           }
00592           exportGIDs.resize (numValidExports);
00593           ExportData_->exportLIDs_.resize (numValidExports);
00594           ExportData_->exportPIDs_.resize (numValidExports);
00595         }
00596       }
00597     }
00598   } // setupSamePermuteExport()
00599 
00600   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00601   void
00602   Export<LocalOrdinal,GlobalOrdinal,Node>::setupRemote(Teuchos::Array<GlobalOrdinal> & exportGIDs)
00603   {
00604     using std::endl;
00605     const map_type& target = * (getTargetMap ());
00606     const int myRank = target.getComm ()->getRank ();
00607 
00608     if (! out_.is_null ()) {
00609       out_->pushTab ();
00610     }
00611     if (debug_) {
00612       std::ostringstream os;
00613       os << myRank << ": Export::setupRemote" << endl;
00614       *out_ << os.str ();
00615     }
00616     if (! out_.is_null ()) {
00617       out_->pushTab ();
00618     }
00619 
00620     // Sort exportPIDs_ in ascending order, and apply the same
00621     // permutation to exportGIDs_ and exportLIDs_.  This ensures that
00622     // exportPIDs_[i], exportGIDs_[i], and exportLIDs_[i] all
00623     // refer to the same thing.
00624     sort3 (ExportData_->exportPIDs_.begin(),
00625            ExportData_->exportPIDs_.end(),
00626            exportGIDs.begin(),
00627            ExportData_->exportLIDs_.begin());
00628 
00629     if (debug_) {
00630       std::ostringstream os;
00631       os << myRank << ": Export::setupRemote: Calling createFromSends" << endl;
00632       *out_ << os.str ();
00633     }
00634 
00635     // Construct the list of entries that calling image needs to send
00636     // as a result of everyone asking for what it needs to receive.
00637     //
00638     // mfh 05 Jan 2012: I understand the above comment as follows:
00639     // Construct the communication plan from the list of image IDs to
00640     // which we need to send.
00641     size_t numRemoteIDs;
00642     numRemoteIDs = ExportData_->distributor_.createFromSends (ExportData_->exportPIDs_ ());
00643 
00644     if (debug_) {
00645       std::ostringstream os;
00646       os << myRank << ": Export::setupRemote: Calling doPostsAndWaits" << endl;
00647       *out_ << os.str ();
00648     }
00649 
00650     // Use the communication plan with ExportGIDs to find out who is
00651     // sending to us and get the proper ordering of GIDs for incoming
00652     // remote entries (these will be converted to LIDs when done).
00653     Array<GlobalOrdinal> remoteGIDs (numRemoteIDs);
00654     ExportData_->distributor_.doPostsAndWaits (exportGIDs().getConst (), 1, remoteGIDs());
00655 
00656     // Remote (incoming) IDs come in as GIDs; convert to LIDs.  LIDs
00657     // tell this process where to store the incoming remote data.
00658     ExportData_->remoteLIDs_.resize (numRemoteIDs);
00659     {
00660       typename Array<GlobalOrdinal>::const_iterator i = remoteGIDs.begin();
00661       typename Array<LocalOrdinal>::iterator        j = ExportData_->remoteLIDs_.begin();
00662       while (i != remoteGIDs.end()) {
00663         *j++ = target.getLocalElement(*i++);
00664       }
00665     }
00666 
00667     if (! out_.is_null ()) {
00668       out_->popTab ();
00669     }
00670     if (debug_) {
00671       std::ostringstream os;
00672       os << myRank << ": Export::setupRemote: done" << endl;
00673       *out_ << os.str ();
00674     }
00675     if (! out_.is_null ()) {
00676       out_->popTab ();
00677     }
00678   }
00679 
00680 } // namespace Tpetra
00681 
00682 // Explicit instantiation macro.
00683 // Only invoke this when in the Tpetra namespace.
00684 // Most users do not need to use this.
00685 //
00686 // LO: The local ordinal type.
00687 // GO: The global ordinal type.
00688 // NODE: The Kokkos Node type.
00689 #define TPETRA_EXPORT_INSTANT(LO, GO, NODE) \
00690   \
00691   template class Export< LO , GO , NODE >;
00692 
00693 #endif // TPETRA_EXPORT_DEF_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines