Tpetra Matrix/Vector Services Version of the Day
Tpetra_DirectoryImpl_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_DirectoryImpl_def_hpp
00043 #define __Tpetra_DirectoryImpl_def_hpp
00044 
00045 #ifdef DOXYGEN_USE_ONLY
00046 #  include <Tpetra_DirectoryImpl_decl.hpp>
00047 #endif
00048 #include <Tpetra_Distributor.hpp>
00049 
00050 namespace Tpetra {
00051   namespace Details {
00052     template<class LO, class GO, class NT>
00053     Directory<LO, GO, NT>::
00054     Directory (const Teuchos::RCP<const typename Directory<LO, GO, NT>::map_type>& map) :
00055       map_ (map)
00056     {}
00057 
00058     template<class LO, class GO, class NT>
00059     LookupStatus
00060     Directory<LO, GO, NT>::
00061     getEntries (const Teuchos::ArrayView<const GO> &globalIDs,
00062                 const Teuchos::ArrayView<int> &nodeIDs,
00063                 const Teuchos::ArrayView<LO> &localIDs,
00064                 const bool computeLIDs) const
00065     {
00066       // Ensure that globalIDs, nodeIDs, and localIDs (if applicable)
00067       // all have the same size, before modifying any output arguments.
00068       TEUCHOS_TEST_FOR_EXCEPTION(nodeIDs.size() != globalIDs.size(),
00069         std::invalid_argument, Teuchos::typeName(*this) << "::getEntries(): "
00070         "Output arrays do not have the right sizes.  nodeIDs.size() = "
00071         << nodeIDs.size() << " != globalIDs.size() = " << globalIDs.size()
00072         << ".");
00073       TEUCHOS_TEST_FOR_EXCEPTION(
00074         computeLIDs && localIDs.size() != globalIDs.size(),
00075         std::invalid_argument, Teuchos::typeName(*this) << "::getEntries(): "
00076         "Output array do not have the right sizes.  localIDs.size() = "
00077         << localIDs.size() << " != globalIDs.size() = " << globalIDs.size()
00078         << ".");
00079 
00080       // Initially, fill nodeIDs and localIDs (if applicable) with
00081       // invalid values.  The "invalid" process ID is -1 (this means
00082       // the same thing as MPI_ANY_SOURCE to Teuchos, so it's an
00083       // "invalid" process ID); the invalid local ID comes from
00084       // OrdinalTraits.
00085       std::fill (nodeIDs.begin(), nodeIDs.end(), -1);
00086       if (computeLIDs) {
00087         std::fill (localIDs.begin(), localIDs.end(),
00088                    Teuchos::OrdinalTraits<LO>::invalid ());
00089       }
00090       // Actually do the work.
00091       return this->getEntriesImpl (globalIDs, nodeIDs, localIDs, computeLIDs);
00092     }
00093 
00094     template<class LO, class GO, class NT>
00095     ReplicatedDirectory<LO, GO, NT>::
00096     ReplicatedDirectory (const Teuchos::RCP<const typename ReplicatedDirectory<LO, GO, NT>::map_type>& map) :
00097       Directory<LO, GO, NT> (map)
00098     {}
00099 
00100     template<class LO, class GO, class NT>
00101     std::string
00102     ReplicatedDirectory<LO, GO, NT>::description () const
00103     {
00104       std::ostringstream os;
00105       os << "ReplicatedDirectory"
00106          << "<" << Teuchos::TypeNameTraits<LO>::name ()
00107          << ", " << Teuchos::TypeNameTraits<GO>::name ()
00108          << ", " << Teuchos::TypeNameTraits<NT>::name () << ">";
00109       return os.str ();
00110     }
00111 
00112     template<class LO, class GO, class NT>
00113     DistributedContiguousDirectory<LO, GO, NT>::
00114     DistributedContiguousDirectory (const Teuchos::RCP<const typename DistributedContiguousDirectory<LO, GO, NT>::map_type>& map) :
00115       Directory<LO, GO, NT> (map)
00116     {
00117       using Teuchos::gatherAll;
00118       using Teuchos::RCP;
00119 
00120       RCP<const Teuchos::Comm<int> > comm = map->getComm ();
00121 
00122       TEUCHOS_TEST_FOR_EXCEPTION(! map->isDistributed (), std::invalid_argument,
00123         Teuchos::typeName (*this) << " constructor: Map is not distributed.");
00124       TEUCHOS_TEST_FOR_EXCEPTION(! map->isContiguous (), std::invalid_argument,
00125         Teuchos::typeName (*this) << " constructor: Map is not contiguous.");
00126 
00127       // Make room for the min global ID on each proc, plus one
00128       // entry at the end for the max cap.
00129       allMinGIDs_.resize (comm->getSize () + 1);
00130       // Get my process' min global ID.
00131       GO minMyGID = map->getMinGlobalIndex ();
00132       // Gather all of the min global IDs into the first getSize()
00133       // entries of allMinGIDs_.
00134       Teuchos::gatherAll<int, GO> (*comm, 1, &minMyGID, comm->getSize (),
00135                                    allMinGIDs_.getRawPtr ());
00136       // Put the max cap at the end.  Adding one lets us write loops
00137       // over the global IDs with the usual strict less-than bound.
00138       allMinGIDs_.back() = map->getMaxAllGlobalIndex() +
00139         Teuchos::OrdinalTraits<GO>::one();
00140     }
00141 
00142     template<class LO, class GO, class NT>
00143     std::string
00144     DistributedContiguousDirectory<LO, GO, NT>::description () const
00145     {
00146       std::ostringstream os;
00147       os << "DistributedContiguousDirectory"
00148          << "<" << Teuchos::TypeNameTraits<LO>::name ()
00149          << ", " << Teuchos::TypeNameTraits<GO>::name ()
00150          << ", " << Teuchos::TypeNameTraits<NT>::name () << ">";
00151       return os.str ();
00152     }
00153 
00154     template<class LO, class GO, class NT>
00155     LookupStatus
00156     ReplicatedDirectory<LO, GO, NT>::
00157     getEntriesImpl (const Teuchos::ArrayView<const GO> &globalIDs,
00158                     const Teuchos::ArrayView<int> &nodeIDs,
00159                     const Teuchos::ArrayView<LO> &localIDs,
00160                     const bool computeLIDs) const
00161     {
00162       using Teuchos::Array;
00163       using Teuchos::ArrayRCP;
00164       using Teuchos::ArrayView;
00165       using Teuchos::as;
00166       using Teuchos::Comm;
00167       using Teuchos::RCP;
00168 
00169       LookupStatus res = AllIDsPresent;
00170       RCP<const map_type> map = this->getMap ();
00171       RCP<const Teuchos::Comm<int> > comm = map->getComm ();
00172       const int myRank = comm->getRank ();
00173 
00174       // Map is on one process or is locally replicated.
00175       typename ArrayView<int>::iterator procIter = nodeIDs.begin();
00176       typename ArrayView<LO>::iterator lidIter = localIDs.begin();
00177       typename ArrayView<const GO>::iterator gidIter;
00178       for (gidIter = globalIDs.begin(); gidIter != globalIDs.end(); ++gidIter) {
00179         if (map->isNodeGlobalElement (*gidIter)) {
00180           *procIter++ = myRank;
00181           if (computeLIDs) {
00182             *lidIter++ = map->getLocalElement (*gidIter);
00183           }
00184         }
00185         else {
00186           // Advance the pointers, leaving these values set to invalid
00187           procIter++;
00188           if (computeLIDs) {
00189             lidIter++;
00190           }
00191           res = IDNotPresent;
00192         }
00193       }
00194       return res;
00195     }
00196 
00197     template<class LO, class GO, class NT>
00198     LookupStatus
00199     DistributedContiguousDirectory<LO, GO, NT>::
00200     getEntriesImpl (const Teuchos::ArrayView<const GO> &globalIDs,
00201                     const Teuchos::ArrayView<int> &nodeIDs,
00202                     const Teuchos::ArrayView<LO> &localIDs,
00203                     const bool computeLIDs) const
00204     {
00205       using Teuchos::Array;
00206       using Teuchos::ArrayRCP;
00207       using Teuchos::ArrayView;
00208       using Teuchos::as;
00209       using Teuchos::Comm;
00210       using Teuchos::RCP;
00211 
00212       const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid();
00213       LookupStatus res = AllIDsPresent;
00214 
00215       RCP<const map_type> map  = this->getMap ();
00216       RCP<const Teuchos::Comm<int> > comm = map->getComm ();
00217       const int numProcs = comm->getSize ();
00218       const global_size_t nOverP = map->getGlobalNumElements () / numProcs;
00219 
00220       // Map is distributed but contiguous.
00221       typename ArrayView<int>::iterator procIter = nodeIDs.begin();
00222       typename ArrayView<LO>::iterator lidIter = localIDs.begin();
00223       typename ArrayView<const GO>::iterator gidIter;
00224       for (gidIter = globalIDs.begin(); gidIter != globalIDs.end(); ++gidIter) {
00225         LO LID = LINVALID; // Assume not found until proven otherwise
00226         int image = -1;
00227         GO GID = *gidIter;
00228         // Guess uniform distribution and start a little above it
00229         // TODO: replace by a binary search
00230         int curRank;
00231         { // We go through all this trouble to avoid overflow and
00232           // signed / unsigned casting mistakes (that were made in
00233           // previous versions of this code).
00234           const GO one = Teuchos::OrdinalTraits<GO>::one();
00235           const GO two = one + one;
00236           const GO nOverP_GID = static_cast<GO> (nOverP);
00237           const GO lowerBound = GID / std::max(nOverP_GID, one) + two;
00238           // It's probably not OK to cast this to int in general.  It
00239           // works as long as |GID| <= the global number of entries
00240           // and nOverP is appropriately sized for int.  Trouble may
00241           // ensue if the index base has an exotic value.
00242           const int lowerBound_int = static_cast<int> (lowerBound);
00243           curRank = std::min (lowerBound_int, numProcs - 1);
00244         }
00245         bool found = false;
00246         while (curRank >= 0 && curRank < numProcs) {
00247           if (allMinGIDs_[curRank] <= GID) {
00248             if (GID < allMinGIDs_[curRank + 1]) {
00249               found = true;
00250               break;
00251             }
00252             else {
00253               curRank++;
00254             }
00255           }
00256           else {
00257             curRank--;
00258           }
00259         }
00260         if (found) {
00261           image = curRank;
00262           LID = as<LO> (GID - allMinGIDs_[image]);
00263         }
00264         else {
00265           res = IDNotPresent;
00266         }
00267         *procIter++ = image;
00268         if (computeLIDs) {
00269           *lidIter++ = LID;
00270         }
00271       }
00272       return res;
00273     }
00274 
00275     template<class LO, class GO, class NT>
00276     DistributedNoncontiguousDirectory<LO, GO, NT>::
00277     DistributedNoncontiguousDirectory (const Teuchos::RCP<const typename DistributedNoncontiguousDirectory<LO, GO, NT>::map_type>& map) :
00278       Directory<LO, GO, NT> (map)
00279     {
00280       using Teuchos::Array;
00281       using Teuchos::ArrayView;
00282       using Teuchos::as;
00283       using Teuchos::RCP;
00284       using Teuchos::rcp;
00285       using Teuchos::typeName;
00286       using Teuchos::TypeNameTraits;
00287 
00288       // This class' implementation of getEntriesImpl() currently
00289       // encodes the following assumptions:
00290       //
00291       // 1. global_size_t >= GO
00292       // 2. global_size_t >= int
00293       // 3. global_size_t >= LO
00294       //
00295       // We check these assumptions here.
00296       TEUCHOS_TEST_FOR_EXCEPTION(sizeof(global_size_t) < sizeof(GO),
00297         std::logic_error, typeName (*this) << ": sizeof(Tpetra::"
00298         "global_size_t) = " << sizeof(global_size_t) << " < sizeof(Global"
00299         "Ordinal = " << TypeNameTraits<LO>::name () << ") = " << sizeof(GO)
00300         << ".");
00301       TEUCHOS_TEST_FOR_EXCEPTION(sizeof(global_size_t) < sizeof(int),
00302         std::logic_error, typeName (*this) << ": sizeof(Tpetra::"
00303         "global_size_t) = " << sizeof(global_size_t) << " < sizeof(int) = "
00304         << sizeof(int) << ".");
00305       TEUCHOS_TEST_FOR_EXCEPTION(sizeof(global_size_t) < sizeof(LO),
00306         std::logic_error, typeName (*this) << ": sizeof(Tpetra::"
00307         "global_size_t) = " << sizeof(global_size_t) << " < sizeof(Local"
00308         "Ordinal = " << TypeNameTraits<LO>::name () << ") = " << sizeof(LO)
00309         << ".");
00310 
00311       RCP<const Teuchos::Comm<int> > comm = map->getComm ();
00312       const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid ();
00313       const GO minAllGID = map->getMinAllGlobalIndex ();
00314       const GO maxAllGID = map->getMaxAllGlobalIndex ();
00315 
00316       // The "Directory Map" (see below) will have a range of elements
00317       // from the minimum to the maximum GID of the user Map, and a
00318       // minimum GID of minAllGID from the user Map.
00319       const global_size_t numGlobalEntries = maxAllGID - minAllGID + 1;
00320 
00321       // We can't afford to replicate the whole directory on each
00322       // process, so create the "Directory Map", a uniform contiguous
00323       // Map that describes how we will distribute the directory over
00324       // processes.
00325       //
00326       // FIXME (mfh 08 May 2012) Here we're setting minAllGID to be
00327       // the index base.  The index base should be separate from the
00328       // minimum GID.
00329       directoryMap_ = rcp (new map_type (numGlobalEntries, minAllGID, comm, GloballyDistributed, map->getNode ()));
00330 
00331       // The number of Directory elements that my process owns.
00332       const size_t dir_numMyEntries = directoryMap_->getNodeNumElements ();
00333 
00334       // NOTE (mfh 21 Mar 2012): I rephrased the comment below so that
00335       // it made a little more sense, but I don't fully understand what
00336       // it means yet.
00337       //
00338       // Allocate process ID List and LID list.  Initialize to
00339       // invalid values, in case the user global element list does
00340       // fill all IDs from minAllGID to maxAllGID (e.g., allows
00341       // global indices to be all even integers).
00342       nodeIDs_.resize (dir_numMyEntries, -1);
00343       LIDs_.resize (dir_numMyEntries, LINVALID);
00344 
00345       // Get list of process IDs that own the directory entries for the
00346       // Map GIDs.  These will be the targets of the sends that the
00347       // Distributor will do.
00348       const int myRank = comm->getRank ();
00349       const size_t numMyEntries = map->getNodeNumElements ();
00350       Array<int> sendImageIDs (numMyEntries);
00351       ArrayView<const GO> myGlobalEntries = map->getNodeElementList ();
00352       // An ID not present in this lookup indicates that it lies outside
00353       // of the range [minAllGID,maxAllGID] (from map_).  this means
00354       // something is wrong with map_, our fault.
00355       TEUCHOS_TEST_FOR_EXCEPTION(
00356         directoryMap_->getRemoteIndexList (myGlobalEntries, sendImageIDs) == IDNotPresent,
00357         std::logic_error, Teuchos::typeName(*this) << " constructor: the "
00358         "Directory Map could not find out where one or more of my Map's "
00359         "elements should go.  This probably means there is a bug in Map or "
00360         "Directory.  Please report this bug to the Tpetra developers.");
00361 
00362       // Initialize the distributor using the list of process IDs to
00363       // which to send.  We'll use the distributor to send out triples
00364       // of (GID, process ID, LID).  We're sending the entries to the
00365       // processes that the Directory Map says should own them, which is
00366       // why we called directoryMap_->getRemoteIndexList() above.
00367       Distributor distor (comm);
00368       const size_t numReceives = distor.createFromSends (sendImageIDs);
00369 
00370       // NOTE (mfh 21 Mar 2012) The following code assumes that
00371       // sizeof(GO) >= sizeof(int) and sizeof(GO) >= sizeof(LO).
00372       //
00373       // Create and fill buffer of (GID, process ID, LID) triples to
00374       // send out.  We pack the (GID, process ID, LID) triples into a
00375       // single Array of GO, casting the process ID from int to GO and
00376       // the LID from LO to GO as we do so.
00377       const int packetSize = 3; // We're sending triples, so packet size is 3.
00378       Array<GO> exportEntries (packetSize * numMyEntries); // data to send out
00379       {
00380         typename Array<GO>::iterator iter = exportEntries.begin();
00381         for (size_t i=0; i < numMyEntries; ++i) {
00382           *iter++ = myGlobalEntries[i];
00383           *iter++ = as<GO> (myRank);
00384           *iter++ = as<GO> (i);
00385         }
00386       }
00387       // Buffer of data to receive.  The Distributor figured out for
00388       // us how many packets we're receiving, when we called its
00389       // createFromSends() method to set up the distribution plan.
00390       Array<GO> importElements (packetSize * distor.getTotalReceiveLength ());
00391 
00392       // Distribute the triples of (GID, process ID, LID).
00393       distor.doPostsAndWaits (exportEntries ().getConst (), packetSize, importElements ());
00394 
00395       // Unpack the redistributed data.
00396       {
00397         typename Array<GO>::iterator iter = importElements.begin();
00398         for (size_t i = 0; i < numReceives; ++i) {
00399           // Each "packet" (contiguous chunk of importElements) contains
00400           // a triple: (GID, process ID, LID).
00401           //
00402           // Convert incoming GID to Directory LID.
00403           const GO currGID = *iter++;
00404           const LO currLID = directoryMap_->getLocalElement (currGID);
00405           TEUCHOS_TEST_FOR_EXCEPTION(currLID == LINVALID, std::logic_error,
00406             Teuchos::typeName(*this) << " constructor: Incoming global ID "
00407             << currGID << " does not have a corresponding local ID in the "
00408             "Directory Map.  Please report this bug to the Tpetra developers.");
00409           nodeIDs_[currLID] = *iter++;
00410           LIDs_[currLID]    = *iter++;
00411         }
00412       }
00413     }
00414 
00415     template<class LO, class GO, class NT>
00416     std::string
00417     DistributedNoncontiguousDirectory<LO, GO, NT>::description () const
00418     {
00419       std::ostringstream os;
00420       os << "DistributedNoncontiguousDirectory"
00421          << "<" << Teuchos::TypeNameTraits<LO>::name ()
00422          << ", " << Teuchos::TypeNameTraits<GO>::name ()
00423          << ", " << Teuchos::TypeNameTraits<NT>::name () << ">";
00424       return os.str ();
00425     }
00426 
00427     template<class LO, class GO, class NT>
00428     LookupStatus
00429     DistributedNoncontiguousDirectory<LO, GO, NT>::
00430     getEntriesImpl (const Teuchos::ArrayView<const GO> &globalIDs,
00431                     const Teuchos::ArrayView<int> &nodeIDs,
00432                     const Teuchos::ArrayView<LO> &localIDs,
00433                     const bool computeLIDs) const
00434     {
00435       using Teuchos::Array;
00436       using Teuchos::ArrayRCP;
00437       using Teuchos::ArrayView;
00438       using Teuchos::as;
00439       using Teuchos::RCP;
00440 
00441       const LO LINVALID = Teuchos::OrdinalTraits<LO>::invalid();
00442       LookupStatus res = AllIDsPresent;
00443 
00444       RCP<const map_type> map = this->getMap ();
00445       RCP<const Teuchos::Comm<int> > comm = map->getComm ();
00446       const size_t numEntries = globalIDs.size ();
00447 
00448       //
00449       // Set up directory structure.
00450       //
00451 
00452       // If we're computing LIDs, we also have to include them in each
00453       // packet, along with the GID and process ID.
00454       const int packetSize = computeLIDs ? 3 : 2;
00455 
00456       // For data distribution, we use: Surprise!  A Distributor!
00457       Distributor distor (comm);
00458 
00459       // Get directory locations for the requested list of entries.
00460       Array<int> dirImages (numEntries);
00461       res = directoryMap_->getRemoteIndexList (globalIDs, dirImages ());
00462       // Check for unfound globalIDs and set corresponding nodeIDs to -1
00463       size_t numMissing = 0;
00464       if (res == IDNotPresent) {
00465         for (size_t i=0; i < numEntries; ++i) {
00466           if (dirImages[i] == -1) {
00467             nodeIDs[i] = -1;
00468             if (computeLIDs) {
00469               localIDs[i] = LINVALID;
00470             }
00471             numMissing++;
00472           }
00473         }
00474       }
00475 
00476       ArrayRCP<GO> sendGIDs;
00477       ArrayRCP<int> sendImages;
00478       distor.createFromRecvs (globalIDs, dirImages (), sendGIDs, sendImages);
00479       const size_t numSends = sendGIDs.size ();
00480 
00481       //    global_size_t >= GO
00482       //    global_size_t >= size_t >= int
00483       //    global_size_t >= size_t >= LO
00484       // Therefore, we can safely store all of these in a global_size_t
00485       Array<global_size_t> exports (packetSize * numSends);
00486       {
00487         LO curLID;
00488         typename Array<global_size_t>::iterator exportsIter = exports.begin();
00489         typename ArrayRCP<GO>::const_iterator gidIter = sendGIDs.begin();
00490         for ( ; gidIter != sendGIDs.end(); ++gidIter) {
00491           *exportsIter++ = as<global_size_t> (*gidIter);
00492           curLID = directoryMap_->getLocalElement (*gidIter);
00493           TEUCHOS_TEST_FOR_EXCEPTION(curLID == LINVALID, std::logic_error,
00494             Teuchos::typeName (*this) << "::getEntriesImpl(): The Directory "
00495             "Map's global ID " << *gidIter << " does not have a corresponding "
00496             "local ID.  Please report this bug to the Tpetra developers.");
00497           *exportsIter++ = as<global_size_t> (nodeIDs_[curLID]);
00498           if (computeLIDs) {
00499             *exportsIter++ = as<global_size_t> (LIDs_[curLID]);
00500           }
00501         }
00502       }
00503 
00504       Array<global_size_t> imports (packetSize * distor.getTotalReceiveLength ());
00505       distor.doPostsAndWaits (exports ().getConst (), packetSize, imports ());
00506 
00507       typename Array<global_size_t>::iterator ptr = imports.begin();
00508       const size_t numRecv = numEntries - numMissing;
00509 
00510       Array<GO> sortedIDs (globalIDs);
00511       ArrayRCP<GO> offset = arcp<GO> (numEntries);
00512       GO ii=0;
00513       for (typename ArrayRCP<GO>::iterator oo = offset.begin(); oo != offset.end(); ++oo, ++ii) {
00514         *oo = ii;
00515       }
00516       sort2 (sortedIDs.begin(), sortedIDs.begin() + numEntries, offset.begin());
00517 
00518       typedef typename Array<GO>::iterator IT;
00519       // we know these conversions are in range, because we loaded this data
00520       for (size_t i = 0; i < numRecv; ++i) {
00521         GO curGID = as<GO> (*ptr++);
00522         std::pair<IT, IT> p1 = std::equal_range (sortedIDs.begin(), sortedIDs.end(), curGID);
00523         if (p1.first != p1.second) {
00524           //found it
00525           size_t j = p1.first - sortedIDs.begin();
00526           nodeIDs[offset[j]] = as<int>(*ptr++);
00527           if (computeLIDs) {
00528             localIDs[offset[j]] = as<LO>(*ptr++);
00529           }
00530           if (nodeIDs[offset[j]] == -1) {
00531             res = IDNotPresent;
00532           }
00533         }
00534       }
00535       return res;
00536     }
00537   } // namespace Details
00538 } // namespace Tpetra
00539 
00540 //
00541 // Explicit instantiation macro
00542 //
00543 // Must be expanded from within the Tpetra::Details namespace!
00544 //
00545 #define TPETRA_DIRECTORY_IMPL_INSTANT(LO,GO,NODE)                     \
00546   template<> class Directory< LO , GO , NODE >;                       \
00547   template<> class ReplicatedDirectory< LO , GO , NODE >;             \
00548   template<> class DistributedContiguousDirectory< LO , GO , NODE >;  \
00549   template<> class DistributedNoncontiguousDirectory< LO , GO , NODE >;
00550 
00551 #endif // __Tpetra_DirectoryImpl_def_hpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines