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