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