Tpetra_Import.hpp

00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //          Tpetra: Templated Linear Algebra Services Package
00005 //                 Copyright (2008) Sandia Corporation
00006 // 
00007 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00008 // license for use of this work by or on behalf of the U.S. Government.
00009 // 
00010 // This library is free software; you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as
00012 // published by the Free Software Foundation; either version 2.1 of the
00013 // License, or (at your option) any later version.
00014 //  
00015 // This library is distributed in the hope that it will be useful, but
00016 // WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018 // Lesser General Public License for more details.
00019 //  
00020 // You should have received a copy of the GNU Lesser General Public
00021 // License along with this library; if not, write to the Free Software
00022 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00023 // USA
00024 // Questions? Contact Michael A. Heroux (maherou@sandia.gov) 
00025 // 
00026 // ***********************************************************************
00027 // @HEADER
00028 
00029 #ifndef TPETRA_IMPORT_HPP
00030 #define TPETRA_IMPORT_HPP
00031 
00032 #include <Kokkos_DefaultNode.hpp>
00033 #include <Teuchos_Describable.hpp>
00034 #include <Teuchos_as.hpp>
00035 #include <Teuchos_OrdinalTraits.hpp>
00036 #include <Teuchos_RCP.hpp>
00037 #include <Teuchos_Array.hpp>
00038 #include <Teuchos_ArrayRCP.hpp>
00039 #include "Tpetra_Map.hpp"
00040 #include "Tpetra_Util.hpp"
00041 #include "Tpetra_ImportExportData.hpp"
00042 #include "Tpetra_Distributor.hpp"
00043 #include <iterator>
00044 
00045 namespace Tpetra {
00046 
00048 
00059   template <class LocalOrdinal, class GlobalOrdinal = LocalOrdinal, class Node = Kokkos::DefaultNode::DefaultNodeType>
00060   class Import: public Teuchos::Describable {
00061 
00062   public:
00063 
00065 
00066 
00068     Import(const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & source, 
00069            const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & target);
00070 
00072     Import(const Import<LocalOrdinal,GlobalOrdinal,Node> & import);
00073 
00075     ~Import();
00076 
00078 
00080 
00081 
00083     size_t getNumSameIDs() const;
00084 
00086     size_t getNumPermuteIDs() const;
00087 
00089     Teuchos::ArrayView<const LocalOrdinal> getPermuteFromLIDs() const;
00090 
00092     Teuchos::ArrayView<const LocalOrdinal> getPermuteToLIDs() const;
00093 
00095     size_t getNumRemoteIDs() const;
00096 
00098     Teuchos::ArrayView<const LocalOrdinal> getRemoteLIDs() const;
00099 
00101     size_t getNumExportIDs() const;
00102 
00104     Teuchos::ArrayView<const LocalOrdinal> getExportLIDs() const;
00105 
00107     Teuchos::ArrayView<const int> getExportImageIDs() const;
00108 
00110     const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & getSourceMap() const;
00111 
00113     const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & getTargetMap() const;
00114 
00115     Distributor & getDistributor() const;
00116 
00118     Import<LocalOrdinal,GlobalOrdinal,Node>& operator = (const Import<LocalOrdinal,GlobalOrdinal,Node> & Source);
00119 
00121 
00123 
00124 
00126     virtual void print(std::ostream& os) const;
00127 
00129 
00130   private:
00131 
00132     Teuchos::RCP<ImportExportData<LocalOrdinal,GlobalOrdinal,Node> > ImportData_;
00133     Teuchos::RCP<Teuchos::Array<GlobalOrdinal> > remoteGIDs_;
00134 
00135     // subfunctions used by constructor
00136     //==============================================================================
00137     // sets up numSameIDs_, numPermuteIDs_, and numRemoteIDs_
00138     // these variables are already initialized to 0 by the ImportExportData ctr.
00139     // also sets up permuteToLIDs_, permuteFromLIDs_, and remoteLIDs_
00140     void setupSamePermuteRemote();
00141     void setupExport();
00142   };
00143 
00144   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00145   Import<LocalOrdinal,GlobalOrdinal,Node>::Import(const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & source, 
00146                                                   const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & target) {
00147     ImportData_ = Teuchos::rcp(new ImportExportData<LocalOrdinal,GlobalOrdinal,Node>(source, target));
00148     // call subfunctions
00149     setupSamePermuteRemote();
00150     if( source->isDistributed()) {
00151       setupExport();
00152     }
00153     // don't need remoteGIDs_ anymore
00154     remoteGIDs_ = Teuchos::null;
00155   }
00156 
00157   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00158   Import<LocalOrdinal,GlobalOrdinal,Node>::Import(const Import<LocalOrdinal,GlobalOrdinal,Node> & import)
00159   : ImportData_(import.ImportData_)
00160   {}
00161 
00162   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00163   Import<LocalOrdinal,GlobalOrdinal,Node>::~Import() 
00164   {}
00165 
00166   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00167   size_t Import<LocalOrdinal,GlobalOrdinal,Node>::getNumSameIDs() const {
00168     return ImportData_->numSameIDs_;
00169   }
00170 
00171   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00172   size_t Import<LocalOrdinal,GlobalOrdinal,Node>::getNumPermuteIDs() const {
00173     return ImportData_->permuteFromLIDs_.size();
00174   }
00175 
00176   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00177   Teuchos::ArrayView<const LocalOrdinal> 
00178   Import<LocalOrdinal,GlobalOrdinal,Node>::getPermuteFromLIDs() const {
00179     return ImportData_->permuteFromLIDs_();
00180   }
00181 
00182   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00183   Teuchos::ArrayView<const LocalOrdinal>
00184   Import<LocalOrdinal,GlobalOrdinal,Node>::getPermuteToLIDs() const {
00185     return ImportData_->permuteToLIDs_();
00186   }
00187 
00188   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00189   size_t Import<LocalOrdinal,GlobalOrdinal,Node>::getNumRemoteIDs() const {
00190     return ImportData_->remoteLIDs_.size();
00191   }
00192 
00193   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00194   Teuchos::ArrayView<const LocalOrdinal> 
00195   Import<LocalOrdinal,GlobalOrdinal,Node>::getRemoteLIDs() const {
00196     return ImportData_->remoteLIDs_();
00197   }
00198 
00199   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00200   size_t Import<LocalOrdinal,GlobalOrdinal,Node>::getNumExportIDs() const {
00201     return ImportData_->exportLIDs_.size();
00202   }
00203 
00204   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00205   Teuchos::ArrayView<const LocalOrdinal> 
00206   Import<LocalOrdinal,GlobalOrdinal,Node>::getExportLIDs() const {
00207     return ImportData_->exportLIDs_();
00208   }
00209 
00210   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00211   Teuchos::ArrayView<const int> 
00212   Import<LocalOrdinal,GlobalOrdinal,Node>::getExportImageIDs() const {
00213     return ImportData_->exportImageIDs_();
00214   }
00215 
00216   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00217   const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & 
00218   Import<LocalOrdinal,GlobalOrdinal,Node>::getSourceMap() const {
00219     return ImportData_->source_;
00220   }
00221 
00222   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00223   const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & 
00224   Import<LocalOrdinal,GlobalOrdinal,Node>::getTargetMap() const {
00225     return ImportData_->target_;
00226   }
00227 
00228   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00229   Distributor & 
00230   Import<LocalOrdinal,GlobalOrdinal,Node>::getDistributor() const {
00231     return ImportData_->distributor_;
00232   }
00233 
00234   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00235   Import<LocalOrdinal,GlobalOrdinal,Node>& 
00236   Import<LocalOrdinal,GlobalOrdinal,Node>::operator=(const Import<LocalOrdinal,GlobalOrdinal,Node> & Source) {
00237     ImportData_ = Source.ImportData_;
00238     return *this;
00239   }
00240 
00241   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00242   void Import<LocalOrdinal,GlobalOrdinal,Node>::print(std::ostream& os) const {
00243     using std::endl;
00244     Teuchos::ArrayView<const LocalOrdinal> av;
00245     Teuchos::ArrayView<const int> avi;
00246     const Teuchos::RCP<const Teuchos::Comm<int> > & comm = getSourceMap()->getComm();
00247     int myImageID = comm->getRank();
00248     int numImages = comm->getSize();
00249     for (int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
00250       if(myImageID == imageCtr) {
00251         os << endl;
00252         if(myImageID == 0) { // this is the root node (only output this info once)
00253           os << "Import Data Members:" << endl;
00254         }
00255         os << "Image ID       : " << myImageID << endl;
00256         os << "permuteFromLIDs: {"; av = getPermuteFromLIDs(); std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << " }" << endl;
00257         os << "permuteToLIDs  : {"; av = getPermuteToLIDs();   std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << " }" << endl;
00258         os << "remoteLIDs     : {"; av = getRemoteLIDs();      std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << " }" << endl;
00259         os << "exportLIDs     : {"; av = getExportLIDs();      std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << " }" << endl;
00260         os << "exportImageIDs : {"; avi = getExportImageIDs();  std::copy(avi.begin(),avi.end(),std::ostream_iterator<int>(os," ")); os << " }" << endl;
00261         os << "numSameIDs     : " << getNumSameIDs() << endl;
00262         os << "numPermuteIDs  : " << getNumPermuteIDs() << endl;
00263         os << "numRemoteIDs   : " << getNumRemoteIDs() << endl;
00264         os << "numExportIDs   : " << getNumExportIDs() << endl;
00265       }
00266       // Do a few global ops to give I/O a chance to complete
00267       comm->barrier();
00268       comm->barrier();
00269       comm->barrier();
00270     }
00271     if (myImageID == 0) {
00272       os << "\nSource Map: " << endl; 
00273     }
00274     os << *getSourceMap();
00275     if (myImageID == 0) {
00276       os << "\nTarget Map: " << endl; 
00277     }
00278     os << *getTargetMap();
00279   }
00280 
00281 
00282   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00283   void Import<LocalOrdinal,GlobalOrdinal,Node>::setupSamePermuteRemote() {
00284     const Map<LocalOrdinal,GlobalOrdinal,Node> & source = *getSourceMap();
00285     const Map<LocalOrdinal,GlobalOrdinal,Node> & target = *getTargetMap();
00286     Teuchos::ArrayView<const GlobalOrdinal> sourceGIDs = source.getNodeElementList();
00287     Teuchos::ArrayView<const GlobalOrdinal> targetGIDs = target.getNodeElementList();
00288 
00289     // -- compute numSameIDs_ ---
00290     // go through GID lists of source and target. if the ith GID on both is the same, 
00291     // increment numSameIDs_ and try the next. as soon as you come to a pair that don't
00292     // match, give up.
00293     typename Teuchos::ArrayView<const GlobalOrdinal>::iterator sourceIter = sourceGIDs.begin(),
00294                                                          targetIter = targetGIDs.begin();
00295     while( sourceIter != sourceGIDs.end() && targetIter != targetGIDs.end() && *sourceIter == *targetIter )
00296     {
00297       ++ImportData_->numSameIDs_;
00298       ++sourceIter;
00299       ++targetIter;
00300     }
00301     // targetIter should now point to the GID of the first non-same entry or the end of targetGIDs
00302 
00303     // -- compute numPermuteIDs and numRemoteIDs --
00304     // -- fill permuteToLIDs_, permuteFromLIDs_, remoteGIDs_, and remoteLIDs_ --
00305     // go through remaining entries in targetGIDs. if source owns that GID, 
00306     // increment numPermuteIDs_, and add entries to permuteToLIDs_ and permuteFromLIDs_.
00307     // otherwise increment numRemoteIDs_ and add entries to remoteLIDs_ and remoteGIDs_.
00308     remoteGIDs_ = Teuchos::rcp( new Teuchos::Array<GlobalOrdinal>() );
00309     for (; targetIter != targetGIDs.end(); ++targetIter) {
00310       if (source.isNodeGlobalElement(*targetIter)) {
00311         // both source and target list this GID (*targetIter)
00312         // determine the LIDs for this GID on both Maps and add them to the permutation lists
00313         ImportData_->permuteToLIDs_.push_back(target.getLocalElement(*targetIter));
00314         ImportData_->permuteFromLIDs_.push_back(source.getLocalElement(*targetIter));
00315       }
00316       else {
00317         // this GID is on another processor; store it, along with its destination LID on this processor
00318         remoteGIDs_->push_back(*targetIter);
00319         ImportData_->remoteLIDs_.push_back(target.getLocalElement(*targetIter));
00320       }
00321     }
00322 
00323     TEST_FOR_EXCEPTION( (getNumRemoteIDs() > 0) && !source.isDistributed(), std::runtime_error, 
00324         Teuchos::typeName(*this) << "::setupSamePermuteRemote(): Target has remote LIDs but Source is not distributed globally.");
00325   }
00326 
00327 
00328   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00329   void Import<LocalOrdinal,GlobalOrdinal,Node>::setupExport() {
00330     const Map<LocalOrdinal,GlobalOrdinal,Node> & source = *getSourceMap();
00331 
00332     // create remoteImageID list: for each entry remoteGIDs[i],
00333     // remoteImageIDs[i] will contain the ImageID of the image that owns that GID.
00334     // check for GIDs that exist in target but not in source: we see this if getRemoteIndexList returns true
00335     Teuchos::ArrayView<GlobalOrdinal> remoteGIDs = (*remoteGIDs_)();
00336     Teuchos::Array<int> remoteImageIDs(remoteGIDs.size());
00337     TEST_FOR_EXCEPTION( source.getRemoteIndexList(remoteGIDs, remoteImageIDs()) == IDNotPresent, std::runtime_error,
00338         "Tpetra::Import::setupExport(): Target has GIDs not found in Source.");
00339 
00340     // sort remoteImageIDs in ascending order
00341     // apply same permutation to remoteGIDs_
00342     sort2(remoteImageIDs.begin(), remoteImageIDs.end(), remoteGIDs.begin());
00343 
00344     // call Distributor.createFromRecvs()
00345     // takes in remoteGIDs and remoteImageIDs_
00346     // returns exportLIDs_, exportImageIDs_ 
00347     Teuchos::ArrayRCP<GlobalOrdinal> exportGIDs;
00348     ImportData_->distributor_.createFromRecvs(remoteGIDs().getConst(), remoteImageIDs, exportGIDs, ImportData_->exportImageIDs_);
00349     // -- exportGIDs and exportImageIDs_ allocated by createFromRecvs (the former contains GIDs, we will convert to LIDs below) --
00350 
00351     // convert exportGIDs from GIDs to LIDs
00352     if (exportGIDs != Teuchos::null) {
00353       ImportData_->exportLIDs_ = Teuchos::arcp<LocalOrdinal>(exportGIDs.size());
00354     }
00355     typename Teuchos::ArrayRCP<LocalOrdinal>::iterator dst = ImportData_->exportLIDs_.begin();
00356     typename Teuchos::ArrayRCP<GlobalOrdinal>::const_iterator src = exportGIDs.begin();
00357     while (src != exportGIDs.end())
00358     {
00359       (*dst++) = source.getLocalElement(*src++);
00360     }
00361   }
00362 
00363 } // namespace Tpetra
00364 
00365 #endif // TPETRA_IMPORT_HPP
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
Generated on Wed Apr 13 10:21:41 2011 for Tpetra Matrix/Vector Services by  doxygen 1.6.3