|
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 00087 template <class LocalOrdinal, class GlobalOrdinal = LocalOrdinal, class Node = Kokkos::DefaultNode::DefaultNodeType> 00088 class Import: public Teuchos::Describable { 00089 00090 public: 00092 typedef Map<LocalOrdinal,GlobalOrdinal,Node> map_type; 00093 00095 00096 00104 Import (const Teuchos::RCP<const map_type>& source, 00105 const Teuchos::RCP<const map_type>& target); 00106 00117 Import (const Teuchos::RCP<const map_type>& source, 00118 const Teuchos::RCP<const map_type>& target, 00119 const Teuchos::RCP<Teuchos::ParameterList>& plist); 00120 00125 Import(const Import<LocalOrdinal,GlobalOrdinal,Node> & import); 00126 00128 ~Import(); 00129 00131 00133 00134 00139 inline size_t getNumSameIDs() const; 00140 00147 inline size_t getNumPermuteIDs() const; 00148 00150 inline ArrayView<const LocalOrdinal> getPermuteFromLIDs() const; 00151 00153 inline ArrayView<const LocalOrdinal> getPermuteToLIDs() const; 00154 00156 inline size_t getNumRemoteIDs() const; 00157 00159 inline ArrayView<const LocalOrdinal> getRemoteLIDs() const; 00160 00162 inline size_t getNumExportIDs() const; 00163 00165 inline ArrayView<const LocalOrdinal> getExportLIDs() const; 00166 00171 inline ArrayView<const int> getExportImageIDs() const; 00172 00174 inline const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& getSourceMap() const; 00175 00177 inline const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> >& getTargetMap() const; 00178 00180 inline Distributor & getDistributor() const; 00181 00183 Import<LocalOrdinal,GlobalOrdinal,Node>& 00184 operator= (const Import<LocalOrdinal,GlobalOrdinal,Node>& Source); 00185 00187 00189 00190 00192 virtual void print(std::ostream& os) const; 00193 00195 00196 private: 00197 00198 RCP<ImportExportData<LocalOrdinal,GlobalOrdinal,Node> > ImportData_; 00199 RCP<Array<GlobalOrdinal> > remoteGIDs_; 00200 00202 00203 00204 //============================================================================== 00205 // sets up numSameIDs_, numPermuteIDs_, and numRemoteIDs_ 00206 // these variables are already initialized to 0 by the ImportExportData ctr. 00207 // also sets up permuteToLIDs_, permuteFromLIDs_, and remoteLIDs_ 00208 00239 void setupSamePermuteRemote(); 00240 00266 void setupExport(); 00267 00269 }; 00270 00271 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00272 Import<LocalOrdinal,GlobalOrdinal,Node>::Import(const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & source, 00273 const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & target) { 00274 ImportData_ = rcp(new ImportExportData<LocalOrdinal,GlobalOrdinal,Node>(source, target)); 00275 // call subfunctions 00276 setupSamePermuteRemote(); 00277 if (source->isDistributed()) { 00278 setupExport(); 00279 } 00280 // don't need remoteGIDs_ anymore 00281 remoteGIDs_ = null; 00282 } 00283 00284 00285 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00286 Import<LocalOrdinal,GlobalOrdinal,Node>:: 00287 Import (const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & source, 00288 const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & target, 00289 const Teuchos::RCP<Teuchos::ParameterList>& plist) 00290 { 00291 using Teuchos::rcp; 00292 typedef ImportExportData<LocalOrdinal,GlobalOrdinal,Node> data_type; 00293 00294 ImportData_ = rcp (new data_type (source, target, plist)); 00295 setupSamePermuteRemote(); 00296 if (source->isDistributed()) { 00297 setupExport(); 00298 } 00299 remoteGIDs_ = null; // Don't need this anymore 00300 } 00301 00302 00303 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00304 Import<LocalOrdinal,GlobalOrdinal,Node>::Import(const Import<LocalOrdinal,GlobalOrdinal,Node> & import) 00305 : ImportData_(import.ImportData_) 00306 {} 00307 00308 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00309 Import<LocalOrdinal,GlobalOrdinal,Node>::~Import() 00310 {} 00311 00312 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00313 size_t Import<LocalOrdinal,GlobalOrdinal,Node>::getNumSameIDs() const { 00314 return ImportData_->numSameIDs_; 00315 } 00316 00317 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00318 size_t Import<LocalOrdinal,GlobalOrdinal,Node>::getNumPermuteIDs() const { 00319 return ImportData_->permuteFromLIDs_.size(); 00320 } 00321 00322 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00323 ArrayView<const LocalOrdinal> 00324 Import<LocalOrdinal,GlobalOrdinal,Node>::getPermuteFromLIDs() const { 00325 return ImportData_->permuteFromLIDs_(); 00326 } 00327 00328 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00329 ArrayView<const LocalOrdinal> 00330 Import<LocalOrdinal,GlobalOrdinal,Node>::getPermuteToLIDs() const { 00331 return ImportData_->permuteToLIDs_(); 00332 } 00333 00334 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00335 size_t Import<LocalOrdinal,GlobalOrdinal,Node>::getNumRemoteIDs() const { 00336 return ImportData_->remoteLIDs_.size(); 00337 } 00338 00339 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00340 ArrayView<const LocalOrdinal> 00341 Import<LocalOrdinal,GlobalOrdinal,Node>::getRemoteLIDs() const { 00342 return ImportData_->remoteLIDs_(); 00343 } 00344 00345 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00346 size_t Import<LocalOrdinal,GlobalOrdinal,Node>::getNumExportIDs() const { 00347 return ImportData_->exportLIDs_.size(); 00348 } 00349 00350 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00351 ArrayView<const LocalOrdinal> 00352 Import<LocalOrdinal,GlobalOrdinal,Node>::getExportLIDs() const { 00353 return ImportData_->exportLIDs_(); 00354 } 00355 00356 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00357 ArrayView<const int> 00358 Import<LocalOrdinal,GlobalOrdinal,Node>::getExportImageIDs() const { 00359 return ImportData_->exportImageIDs_(); 00360 } 00361 00362 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00363 const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & 00364 Import<LocalOrdinal,GlobalOrdinal,Node>::getSourceMap() const { 00365 return ImportData_->source_; 00366 } 00367 00368 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00369 const RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & 00370 Import<LocalOrdinal,GlobalOrdinal,Node>::getTargetMap() const { 00371 return ImportData_->target_; 00372 } 00373 00374 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00375 Distributor & 00376 Import<LocalOrdinal,GlobalOrdinal,Node>::getDistributor() const { 00377 return ImportData_->distributor_; 00378 } 00379 00380 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00381 Import<LocalOrdinal,GlobalOrdinal,Node>& 00382 Import<LocalOrdinal,GlobalOrdinal,Node>::operator=(const Import<LocalOrdinal,GlobalOrdinal,Node> & source) { 00383 ImportData_ = source.ImportData_; 00384 return *this; 00385 } 00386 00387 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00388 void Import<LocalOrdinal,GlobalOrdinal,Node>::print(std::ostream& os) const { 00389 using Teuchos::getFancyOStream; 00390 using Teuchos::rcpFromRef; 00391 using std::endl; 00392 00393 ArrayView<const LocalOrdinal> av; 00394 ArrayView<const int> avi; 00395 const RCP<const Comm<int> > & comm = getSourceMap()->getComm(); 00396 const int myImageID = comm->getRank(); 00397 const int numImages = comm->getSize(); 00398 for (int imageCtr = 0; imageCtr < numImages; ++imageCtr) { 00399 if (myImageID == imageCtr) { 00400 os << endl; 00401 if (myImageID == 0) { // this is the root node (only output this info once) 00402 os << "Import Data Members:" << endl; 00403 } 00404 os << "Image ID : " << myImageID << endl; 00405 00406 os << "permuteFromLIDs: "; os << toString (getPermuteFromLIDs()) << endl; 00407 //av = getPermuteFromLIDs(); std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << "}" << endl; 00408 00409 os << "permuteToLIDs : "; 00410 os << toString (getPermuteToLIDs()) << endl; 00411 //av = getPermuteToLIDs(); std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << "}" << endl; 00412 00413 os << "remoteLIDs : "; 00414 os << toString (getRemoteLIDs()) << endl; 00415 //av = getRemoteLIDs(); std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << "}" << endl; 00416 00417 os << "exportLIDs : "; 00418 os << toString (getExportLIDs()) << endl; 00419 //av = getExportLIDs(); std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << "}" << endl; 00420 00421 os << "exportImageIDs : "; 00422 os << toString (getExportImageIDs()) << endl; 00423 //avi = getExportImageIDs(); std::copy(avi.begin(),avi.end(),std::ostream_iterator<int>(os," ")); os << "}" << endl; 00424 00425 os << "numSameIDs : " << getNumSameIDs() << endl; 00426 os << "numPermuteIDs : " << getNumPermuteIDs() << endl; 00427 os << "numRemoteIDs : " << getNumRemoteIDs() << endl; 00428 os << "numExportIDs : " << getNumExportIDs() << endl; 00429 } 00430 00431 // A few global barriers give I/O a chance to complete. 00432 comm->barrier(); 00433 comm->barrier(); 00434 comm->barrier(); 00435 } 00436 00437 const bool printMaps = false; 00438 if (printMaps) { 00439 if (myImageID == 0) { 00440 os << endl << endl << "Source Map:" << endl << std::flush; 00441 } 00442 comm->barrier(); 00443 os << *getSourceMap(); 00444 comm->barrier(); 00445 00446 if (myImageID == 0) { 00447 os << endl << endl << "Target Map:" << endl << std::flush; 00448 } 00449 comm->barrier(); 00450 os << *getTargetMap(); 00451 comm->barrier(); 00452 } 00453 00454 // It's also helpful for debugging to print the Distributor 00455 // object. Epetra_Import::Print() does this, so we can do a 00456 // side-by-side comparison. 00457 if (myImageID == 0) { 00458 os << endl << endl << "Distributor:" << endl << std::flush; 00459 } 00460 comm->barrier(); 00461 getDistributor().describe (*(getFancyOStream (rcpFromRef (os))), 00462 Teuchos::VERB_EXTREME); 00463 } 00464 00465 00466 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00467 void Import<LocalOrdinal,GlobalOrdinal,Node>::setupSamePermuteRemote() { 00468 const Map<LocalOrdinal,GlobalOrdinal,Node> & source = *getSourceMap(); 00469 const Map<LocalOrdinal,GlobalOrdinal,Node> & target = *getTargetMap(); 00470 ArrayView<const GlobalOrdinal> sourceGIDs = source.getNodeElementList(); 00471 ArrayView<const GlobalOrdinal> targetGIDs = target.getNodeElementList(); 00472 00473 // -- compute numSameIDs_ --- 00474 // go through GID lists of source and target. if the ith GID on both is the same, 00475 // increment numSameIDs_ and try the next. as soon as you come to a pair that don't 00476 // match, give up. 00477 typename ArrayView<const GlobalOrdinal>::iterator sourceIter = sourceGIDs.begin(), 00478 targetIter = targetGIDs.begin(); 00479 while( sourceIter != sourceGIDs.end() && targetIter != targetGIDs.end() && *sourceIter == *targetIter ) 00480 { 00481 ++ImportData_->numSameIDs_; 00482 ++sourceIter; 00483 ++targetIter; 00484 } 00485 // targetIter should now point to the GID of the first non-same entry or the end of targetGIDs 00486 00487 // -- compute numPermuteIDs and numRemoteIDs -- 00488 // -- fill permuteToLIDs_, permuteFromLIDs_, remoteGIDs_, and remoteLIDs_ -- 00489 // go through remaining entries in targetGIDs. if source owns that GID, 00490 // increment numPermuteIDs_, and add entries to permuteToLIDs_ and permuteFromLIDs_. 00491 // otherwise increment numRemoteIDs_ and add entries to remoteLIDs_ and remoteGIDs_. 00492 remoteGIDs_ = rcp( new Array<GlobalOrdinal>() ); 00493 for (; targetIter != targetGIDs.end(); ++targetIter) { 00494 if (source.isNodeGlobalElement(*targetIter)) { 00495 // both source and target list this GID (*targetIter) 00496 // determine the LIDs for this GID on both Maps and add them to the permutation lists 00497 ImportData_->permuteToLIDs_.push_back(target.getLocalElement(*targetIter)); 00498 ImportData_->permuteFromLIDs_.push_back(source.getLocalElement(*targetIter)); 00499 } 00500 else { 00501 // this GID is on another processor; store it, along with its destination LID on this processor 00502 remoteGIDs_->push_back(*targetIter); 00503 ImportData_->remoteLIDs_.push_back(target.getLocalElement(*targetIter)); 00504 } 00505 } 00506 00507 TPETRA_ABUSE_WARNING((getNumRemoteIDs() > 0) && !source.isDistributed(),std::runtime_error, 00508 "::setupSamePermuteRemote(): Target has remote LIDs but Source is not distributed globally." 00509 << std::endl << "Importing to a submap of the target map."); 00510 } 00511 00512 00513 template <class LocalOrdinal, class GlobalOrdinal, class Node> 00514 void Import<LocalOrdinal,GlobalOrdinal,Node>::setupExport() { 00515 typedef typename Array<int>::difference_type size_type; 00516 const Map<LocalOrdinal,GlobalOrdinal,Node> & source = *getSourceMap(); 00517 00518 // For each entry remoteGIDs[i], remoteImageIDs[i] will contain 00519 // the process ID of the process that owns that GID. 00520 ArrayView<GlobalOrdinal> remoteGIDs = (*remoteGIDs_)(); 00521 Array<int> remoteImageIDs(remoteGIDs.size()); 00522 // lookup == IDNotPresent means that the source Map wasn't able to 00523 // figure out to which processes one or more of the GIDs in the 00524 // given list of remoteGIDs belong. 00525 // 00526 // The previous abuse warning said "The target Map has GIDs not 00527 // found in the source Map." This statement could be confusing, 00528 // because it doesn't refer to ownership by the current process, 00529 // but rather to ownership by _any_ process participating in the 00530 // Map. (It could not possibly refer to ownership by the current 00531 // process, since remoteGIDs is exactly the list of GIDs owned by 00532 // the target Map but not owned by the source Map. It was 00533 // constructed that way by setupSamePermuteRemote().) 00534 // 00535 // What this statement means is that the source and target Maps 00536 // don't contain the same set of GIDs globally (over all 00537 // processes). That is, there is at least one GID owned by some 00538 // process in the target Map, which is not owned by _any_ process 00539 // in the source Map. 00540 const LookupStatus lookup = source.getRemoteIndexList(remoteGIDs, remoteImageIDs()); 00541 TPETRA_ABUSE_WARNING( lookup == IDNotPresent, std::runtime_error, 00542 "::setupExport(): the source Map wasn't able to figure out which process " 00543 "owns one or more of the GIDs in the list of remote GIDs. This probably " 00544 "means that there is at least one GID owned by some process in the target" 00545 " Map which is not owned by any process in the source Map. (That is, the" 00546 " source and target Maps do not contain the same set of GIDs globally.)"); 00547 00548 // Ignore remote GIDs that aren't owned by any process in the 00549 // source Map. getRemoteIndexList() gives each of these a process 00550 // ID of -1. 00551 if ( lookup == IDNotPresent ) { 00552 const size_type numInvalidRemote = std::count_if( remoteImageIDs.begin(), remoteImageIDs.end(), std::bind1st(std::equal_to<int>(),-1) ); 00553 // if all of them are invalid, we can delete the whole array 00554 const size_type totalNumRemote = getNumRemoteIDs(); 00555 if (numInvalidRemote == totalNumRemote) { 00556 // all remotes are invalid; we have no remotes; we can delete the remotes 00557 remoteImageIDs.clear(); 00558 (*remoteGIDs_).clear(); 00559 ImportData_->remoteLIDs_.clear(); 00560 } 00561 else { 00562 // Some remotes are valid; we need to keep the valid ones. 00563 // Pack and resize remoteImageIDs, remoteGIDs_, and 00564 // remoteLIDs_. 00565 size_type numValidRemote = 0; 00566 for (size_type r = 0; r < totalNumRemote; ++r) { 00567 if (remoteImageIDs[r] != -1) { 00568 remoteImageIDs[numValidRemote] = remoteImageIDs[r]; 00569 (*remoteGIDs_)[numValidRemote] = (*remoteGIDs_)[r]; 00570 ImportData_->remoteLIDs_[numValidRemote] = ImportData_->remoteLIDs_[r]; 00571 ++numValidRemote; 00572 } 00573 } 00574 TEUCHOS_TEST_FOR_EXCEPTION( numValidRemote != totalNumRemote - numInvalidRemote, std::logic_error, 00575 "Tpetra::Import::setupExport(): After removing invalid remote GIDs and packing the valid remote " 00576 "GIDs, numValidRemote = " << numValidRemote << " != totalNumRemote - numInvalidRemote = " 00577 << totalNumRemote - numInvalidRemote << ". Please report this bug to the Tpetra developers."); 00578 00579 remoteImageIDs.resize(numValidRemote); 00580 (*remoteGIDs_).resize(numValidRemote); 00581 ImportData_->remoteLIDs_.resize(numValidRemote); 00582 } 00583 remoteGIDs = (*remoteGIDs_)(); 00584 } 00585 00586 // Sort remoteImageIDs in ascending order. Apply the resulting 00587 // permutation to remoteGIDs_ and remoteLIDs_, so that 00588 // remoteImageIDs[i], remoteGIDs_[i], and remoteLIDs_[i] refer to 00589 // the same thing. 00590 sort3(remoteImageIDs.begin(), remoteImageIDs.end(), remoteGIDs.begin(), ImportData_->remoteLIDs_.begin()); 00591 00592 // Call the Distributor's createFromRecvs() method to turn the 00593 // remote GIDs and their owning processes into a send-and-receive 00594 // communication plan. remoteGIDs and remoteImageIDs_ are input; 00595 // exportGIDs and exportImageIDs_ are output arrays which are 00596 // allocated by createFromRecvs(). 00597 ArrayRCP<GlobalOrdinal> exportGIDs; 00598 ImportData_->distributor_.createFromRecvs(remoteGIDs().getConst(), remoteImageIDs, exportGIDs, ImportData_->exportImageIDs_); 00599 00600 // Find the LIDs corresponding to the GIDs in exportGIDs. For 00601 // sparse matrix-vector multiply, this tells the calling process 00602 // how to index into the source vector to get the elements which 00603 // it needs to send. 00604 if (exportGIDs != null) { 00605 ImportData_->exportLIDs_ = arcp<LocalOrdinal>(exportGIDs.size()); 00606 } 00607 typename ArrayRCP<LocalOrdinal>::iterator dst = ImportData_->exportLIDs_.begin(); 00608 typename ArrayRCP<GlobalOrdinal>::const_iterator src = exportGIDs.begin(); 00609 while (src != exportGIDs.end()) 00610 { 00611 (*dst++) = source.getLocalElement(*src++); 00612 } 00613 } 00614 00624 template <class LO, class GO, class Node> 00625 RCP< const Import<LO,GO,Node> > 00626 createImport( const RCP<const Map<LO,GO,Node> > & src, 00627 const RCP<const Map<LO,GO,Node> > & tgt ) 00628 { 00629 if (src == tgt) return null; 00630 #ifdef HAVE_TPETRA_DEBUG 00631 TEUCHOS_TEST_FOR_EXCEPTION(src == null || tgt == null, std::runtime_error, 00632 "Tpetra::createImport(): neither source nor target map may be null:\nsource: " << src << "\ntarget: " << tgt << "\n"); 00633 #endif 00634 return rcp(new Import<LO,GO,Node>(src,tgt)); 00635 } 00636 00639 template <class LO, class GO, class Node> 00640 RCP< const Import<LO,GO,Node> > 00641 TPETRA_DEPRECATED makeImport( const RCP<const Map<LO,GO,Node> > & src, 00642 const RCP<const Map<LO,GO,Node> > & tgt ) 00643 { 00644 return createImport<LO,GO,Node>(src,tgt); 00645 } 00646 00647 } // namespace Tpetra 00648 00649 #endif // TPETRA_IMPORT_HPP
1.7.4