|
Tpetra Matrix/Vector Services
Version of the Day
|
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
1.7.6.1