Tpetra_Export.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_EXPORT_HPP
00030 #define TPETRA_EXPORT_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 <iterator>
00043 
00044 namespace Tpetra {
00045 
00047 
00059   template <class LocalOrdinal, class GlobalOrdinal = LocalOrdinal, class Node = Kokkos::DefaultNode::DefaultNodeType>
00060   class Export: public Teuchos::Describable {
00061 
00062   public:
00063 
00065 
00066 
00068     Export(const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & source,  
00069            const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & target);
00070 
00072     Export(const Export<LocalOrdinal,GlobalOrdinal,Node> & rhs);
00073 
00075     ~Export();
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     Export<LocalOrdinal,GlobalOrdinal,Node>& operator = (const Export<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> > ExportData_;
00133 
00134     // subfunctions used by constructor
00135     //==============================================================================
00136     // sets up numSameIDs_, numPermuteIDs_, and numExportIDs_
00137     // these variables are already initialized to 0 by the ImportExportData ctr.
00138     // also sets up permuteToLIDs_, permuteFromLIDs_, exportGIDs_, and exportLIDs_
00139     void setupSamePermuteExport();
00140     void setupRemote();
00141   };
00142 
00143   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00144   Export<LocalOrdinal,GlobalOrdinal,Node>::Export(const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & source,   
00145                                                   const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & target) {
00146     ExportData_ = Teuchos::rcp(new ImportExportData<LocalOrdinal,GlobalOrdinal,Node>(source, target));
00147     // call subfunctions
00148     setupSamePermuteExport();
00149     if (source->isDistributed()) {
00150       setupRemote();
00151     }
00152   }
00153 
00154   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00155   Export<LocalOrdinal,GlobalOrdinal,Node>::Export(const Export<LocalOrdinal,GlobalOrdinal,Node> & rhs)
00156   : ExportData_(rhs.ExportData_)
00157   {}
00158 
00159   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00160   Export<LocalOrdinal,GlobalOrdinal,Node>::~Export() 
00161   {}
00162 
00163   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00164   size_t Export<LocalOrdinal,GlobalOrdinal,Node>::getNumSameIDs() const {
00165     return ExportData_->numSameIDs_;
00166   }
00167 
00168   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00169   size_t Export<LocalOrdinal,GlobalOrdinal,Node>::getNumPermuteIDs() const {
00170     return ExportData_->permuteFromLIDs_.size();
00171   }
00172 
00173   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00174   Teuchos::ArrayView<const LocalOrdinal> 
00175   Export<LocalOrdinal,GlobalOrdinal,Node>::getPermuteFromLIDs() const {
00176     return ExportData_->permuteFromLIDs_();
00177   }
00178 
00179   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00180   Teuchos::ArrayView<const LocalOrdinal>
00181   Export<LocalOrdinal,GlobalOrdinal,Node>::getPermuteToLIDs() const {
00182     return ExportData_->permuteToLIDs_();
00183   }
00184 
00185   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00186   size_t Export<LocalOrdinal,GlobalOrdinal,Node>::getNumRemoteIDs() const {
00187     return ExportData_->remoteLIDs_.size();
00188   }
00189 
00190   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00191   Teuchos::ArrayView<const LocalOrdinal> 
00192   Export<LocalOrdinal,GlobalOrdinal,Node>::getRemoteLIDs() const {
00193     return ExportData_->remoteLIDs_();
00194   }
00195 
00196   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00197   size_t Export<LocalOrdinal,GlobalOrdinal,Node>::getNumExportIDs() const {
00198     return ExportData_->exportLIDs_.size();
00199   }
00200 
00201   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00202   Teuchos::ArrayView<const LocalOrdinal> 
00203   Export<LocalOrdinal,GlobalOrdinal,Node>::getExportLIDs() const {
00204     return ExportData_->exportLIDs_();
00205   }
00206 
00207   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00208   Teuchos::ArrayView<const int> 
00209   Export<LocalOrdinal,GlobalOrdinal,Node>::getExportImageIDs() const {
00210     return ExportData_->exportImageIDs_();
00211   }
00212 
00213   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00214   const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & 
00215   Export<LocalOrdinal,GlobalOrdinal,Node>::getSourceMap() const {
00216     return ExportData_->source_;
00217   }
00218 
00219   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00220   const Teuchos::RCP<const Map<LocalOrdinal,GlobalOrdinal,Node> > & 
00221   Export<LocalOrdinal,GlobalOrdinal,Node>::getTargetMap() const {
00222     return ExportData_->target_;
00223   }
00224 
00225   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00226   Distributor & 
00227   Export<LocalOrdinal,GlobalOrdinal,Node>::getDistributor() const { return ExportData_->distributor_;
00228   }
00229 
00230   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00231   Export<LocalOrdinal,GlobalOrdinal,Node>& 
00232   Export<LocalOrdinal,GlobalOrdinal,Node>::operator=(const Export<LocalOrdinal,GlobalOrdinal,Node> & source) {
00233     ExportData_ = source.ExportData_;
00234     return *this;
00235   }
00236 
00237   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00238   void Export<LocalOrdinal,GlobalOrdinal,Node>::print(std::ostream& os) const {
00239     using std::endl;
00240     Teuchos::ArrayView<const LocalOrdinal> av;
00241     Teuchos::ArrayView<const int> avi;
00242     const Teuchos::RCP<const Teuchos::Comm<int> > & comm = getSourceMap()->getComm();
00243     const int myImageID = comm->getRank();
00244     const int numImages = comm->getSize();
00245     for (int imageCtr = 0; imageCtr < numImages; ++imageCtr) {
00246       if(myImageID == imageCtr) {
00247         os << endl;
00248         if(myImageID == 0) { // this is the root node (only output this info once)
00249           os << "Export Data Members:" << endl;
00250         }
00251         os << "Image ID       : " << myImageID << endl;
00252         os << "permuteFromLIDs: {"; av = getPermuteFromLIDs(); std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << " }" << endl;
00253         os << "permuteToLIDs  : {"; av = getPermuteToLIDs();   std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << " }" << endl;
00254         os << "remoteLIDs     : {"; av = getRemoteLIDs();      std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << " }" << endl;
00255         os << "exportLIDs     : {"; av = getExportLIDs();      std::copy(av.begin(),av.end(),std::ostream_iterator<LocalOrdinal>(os," ")); os << " }" << endl;
00256         os << "exportImageIDs : {"; avi = getExportImageIDs();  std::copy(avi.begin(),avi.end(),std::ostream_iterator<int>(os," ")); os << " }" << endl;
00257         os << "numSameIDs     : " << getNumSameIDs() << endl;
00258         os << "numPermuteIDs  : " << getNumPermuteIDs() << endl;
00259         os << "numRemoteIDs   : " << getNumRemoteIDs() << endl;
00260         os << "numExportIDs   : " << getNumExportIDs() << endl;
00261       }
00262       // Do a few global ops to give I/O a chance to complete
00263       comm->barrier();
00264       comm->barrier();
00265       comm->barrier();
00266     }
00267     if (myImageID == 0) {
00268       os << "\nSource Map: " << endl; 
00269     }
00270     os << *getSourceMap();
00271     if (myImageID == 0) {
00272       os << "\nTarget Map: " << endl; 
00273     }
00274     os << *getTargetMap();
00275   }
00276 
00277 
00278   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00279   void Export<LocalOrdinal,GlobalOrdinal,Node>::setupSamePermuteExport() {
00280     const Map<LocalOrdinal,GlobalOrdinal,Node> & source = *getSourceMap();
00281     const Map<LocalOrdinal,GlobalOrdinal,Node> & target = *getTargetMap();
00282     Teuchos::ArrayView<const GlobalOrdinal> sourceGIDs = source.getNodeElementList();
00283     Teuchos::ArrayView<const GlobalOrdinal> targetGIDs = target.getNodeElementList();
00284 
00285     // -- compute numSameIDs_ ---
00286     // go through GID lists of source and target. if the ith GID on both is the same, 
00287     // increment numSameIDs_ and try the next. as soon as you come to a pair that don't
00288     // match, give up.
00289     typename Teuchos::ArrayView<const GlobalOrdinal>::iterator sourceIter = sourceGIDs.begin(),
00290                                                                targetIter = targetGIDs.begin();
00291     while( sourceIter != sourceGIDs.end() && targetIter != targetGIDs.end() && *sourceIter == *targetIter ) {
00292       ++ExportData_->numSameIDs_;
00293       ++sourceIter;
00294       ++targetIter;
00295     }
00296     // sourceIter should now point to the GID of the first non-same entry or at the end of targetGIDs
00297 
00298     // -- compute numPermuteIDs --
00299     // -- fill permuteToLIDs_, permuteFromLIDs_ --
00300     // go through remaining entries in sourceGIDs. if target owns that GID, 
00301     // increment numPermuteIDs_, and add entries to permuteToLIDs_ and permuteFromLIDs_.
00302     // otherwise increment numExportIDs_ and add entries to exportLIDs_ and exportGIDs_.
00303     for(; sourceIter != sourceGIDs.end(); ++sourceIter) {
00304       if(target.isNodeGlobalElement(*sourceIter)) {
00305         // both source and target list this GID (*targetIter)
00306         // determine the LIDs for this GID on both Maps and add them to the permutation lists
00307         ExportData_->permuteToLIDs_.push_back(  target.getLocalElement(*sourceIter));
00308         ExportData_->permuteFromLIDs_.push_back(source.getLocalElement(*sourceIter));
00309       }
00310       else {
00311         ExportData_->exportGIDs_.push_back(*sourceIter);
00312       }
00313     }
00314 
00315     TEST_FOR_EXCEPTION( (getNumExportIDs() > 0) && (!source.isDistributed()), std::runtime_error, 
00316         Teuchos::typeName(*this) << "::setupSamePermuteExport(): Source has export LIDs but Source is not distributed globally.");
00317 
00318     // -- compute exportImageIDs_ --
00319     // get list of images that own the GIDs in exportGIDs_ (in the target Map)
00320     ExportData_->exportImageIDs_ = Teuchos::arcp<int>(ExportData_->exportGIDs_.size());
00321     ExportData_->exportLIDs_     = Teuchos::arcp<LocalOrdinal>(ExportData_->exportGIDs_.size());
00322     {
00323       typename Teuchos::ArrayRCP<LocalOrdinal>::iterator liditer = ExportData_->exportLIDs_.begin();
00324       typename Teuchos::Array<GlobalOrdinal>::iterator    giditer = ExportData_->exportGIDs_.begin();
00325       for (; giditer != ExportData_->exportGIDs_.end(); ++liditer, ++giditer) {
00326         *liditer = source.getLocalElement(*giditer);
00327       }
00328     }
00329     TEST_FOR_EXCEPTION( target.getRemoteIndexList(ExportData_->exportGIDs_(), ExportData_->exportImageIDs_()) == IDNotPresent,
00330         std::runtime_error, "Tpetra::Export::setupSamePermuteExport(): Source has GIDs not found in Target.");
00331   }
00332 
00333 
00334   template <class LocalOrdinal, class GlobalOrdinal, class Node>
00335   void Export<LocalOrdinal,GlobalOrdinal,Node>::setupRemote() {
00336     const Map<LocalOrdinal,GlobalOrdinal,Node> & target = *getTargetMap();
00337 
00338     // make sure export IDs are ordered by image
00339     // sort exportImageIDs_ in ascending order,
00340     // and apply the same permutation to exportGIDs_ and exportLIDs_.
00341     sort3(ExportData_->exportImageIDs_.begin(), ExportData_->exportImageIDs_.end(), ExportData_->exportGIDs_.begin(), ExportData_->exportLIDs_.begin());
00342 
00343     // Construct list of entries that calling image needs to send as a result
00344     // of everyone asking for what it needs to receive.
00345     size_t numRemoteIDs;
00346     numRemoteIDs = ExportData_->distributor_.createFromSends(ExportData_->exportImageIDs_());
00347 
00348     // Use comm plan with ExportGIDs to find out who is sending to us and
00349     // get proper ordering of GIDs for remote entries 
00350     // (these will be converted to LIDs when done).
00351     Teuchos::Array<GlobalOrdinal> remoteGIDs(numRemoteIDs);
00352     ExportData_->distributor_.doPostsAndWaits(ExportData_->exportGIDs_().getConst(),1,remoteGIDs());
00353 
00354     // Remote IDs come in as GIDs, convert to LIDs
00355     ExportData_->remoteLIDs_.resize(numRemoteIDs);
00356     {
00357       typename Teuchos::Array<GlobalOrdinal>::const_iterator i = remoteGIDs.begin();
00358       typename Teuchos::Array<LocalOrdinal>::iterator       j = ExportData_->remoteLIDs_.begin();
00359       while (i != remoteGIDs.end()) 
00360       {
00361         *j++ = target.getLocalElement(*i++);
00362       }
00363     }
00364   }
00365 
00366 } // namespace Tpetra
00367 
00368 #endif // TPETRA_EXPORT_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