Tpetra_Import.hpp

00001 // @HEADER
00002 // ***********************************************************************
00003 // 
00004 //          Tpetra: Templated Linear Algebra Services Package
00005 //                 Copyright (2004) 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 <Teuchos_Object.hpp>
00033 #include <Teuchos_as.hpp>
00034 #include <Teuchos_OrdinalTraits.hpp>
00035 #include <Teuchos_RCP.hpp>
00036 #include <Teuchos_Array.hpp>
00037 #include <Teuchos_ArrayRCP.hpp>
00038 #include "Tpetra_Map.hpp"
00039 #include "Tpetra_Util.hpp"
00040 #include "Tpetra_ImportExportData.hpp"
00041 
00042 namespace Tpetra {
00043 
00045 
00058   template <typename Ordinal>
00059   class Import: public Teuchos::Object {
00060 
00061   public:
00062 
00064 
00065 
00067     Import(const Map<Ordinal> & source, const Map<Ordinal> & target);
00068 
00070     Import(const Import<Ordinal> & import);
00071 
00073     ~Import();
00074 
00076 
00078 
00079 
00081     Ordinal getNumSameIDs() const;
00082 
00084     Ordinal getNumPermuteIDs() const;
00085 
00087     Teuchos::ArrayView<const Ordinal> getPermuteFromLIDs() const;
00088 
00090     Teuchos::ArrayView<const Ordinal> getPermuteToLIDs() const;
00091 
00093     Ordinal getNumRemoteIDs() const;
00094 
00096     Teuchos::ArrayView<const Ordinal> getRemoteLIDs() const;
00097 
00099     Ordinal getNumExportIDs() const;
00100 
00102     Teuchos::ArrayView<const Ordinal> getExportLIDs() const;
00103 
00105     Teuchos::ArrayView<const Ordinal> getExportImageIDs() const;
00106 
00108     const Map<Ordinal> & getSourceMap() const;
00109 
00111     const Map<Ordinal> & getTargetMap() const;
00112 
00113     Distributor<Ordinal> & getDistributor() const;
00114 
00116     Import<Ordinal>& operator = (const Import<Ordinal> & Source);
00117 
00119 
00121 
00122 
00124     virtual void print(std::ostream& os) const;
00125 
00127 
00128   private:
00129 
00130     Teuchos::RCP<ImportExportData<Ordinal> > ImportData_;
00131 
00132     // subfunctions used by constructor
00133     //==============================================================================
00134     // sets up numSameIDs_, numPermuteIDs_, and numRemoteIDs_
00135     // these variables are already initialized to 0 by the ImportExportData ctr.
00136     // also sets up permuteToLIDs_, permuteFromLIDs_, and remoteLIDs_
00137     void setupSamePermuteRemote();
00138     void setupExport();
00139   };
00140 
00141   template <typename Ordinal>
00142   Import<Ordinal>::Import(const Map<Ordinal> & source, const Map<Ordinal> & target)
00143   : Teuchos::Object("Tpetra::Import")
00144   , ImportData_()
00145   {
00146     ImportData_ = Teuchos::rcp(new ImportExportData<Ordinal>(source, target));
00147     // call subfunctions
00148     setupSamePermuteRemote();
00149     if(source.isDistributed()) {
00150       setupExport();
00151     }
00152   }
00153 
00154   template <typename Ordinal>
00155   Import<Ordinal>::Import(const Import<Ordinal> & import)
00156   : Teuchos::Object(import.label())
00157   , ImportData_(import.ImportData_)
00158   {}
00159 
00160   template <typename Ordinal>
00161   Import<Ordinal>::~Import() 
00162   {}
00163 
00164   template <typename Ordinal>
00165   Ordinal Import<Ordinal>::getNumSameIDs() const {
00166     return ImportData_->numSameIDs_;
00167   }
00168 
00169   template <typename Ordinal>
00170   Ordinal Import<Ordinal>::getNumPermuteIDs() const {
00171     return ImportData_->numPermuteIDs_;
00172   }
00173 
00174   template <typename Ordinal>
00175   Teuchos::ArrayView<const Ordinal> 
00176   Import<Ordinal>::getPermuteFromLIDs() const {
00177     return ImportData_->permuteFromLIDs_();
00178   }
00179 
00180   template <typename Ordinal>
00181   Teuchos::ArrayView<const Ordinal>
00182   Import<Ordinal>::getPermuteToLIDs() const {
00183     return ImportData_->permuteToLIDs_();
00184   }
00185 
00186   template <typename Ordinal>
00187   Ordinal Import<Ordinal>::getNumRemoteIDs() const {
00188     return ImportData_->numRemoteIDs_;
00189   }
00190 
00191   template <typename Ordinal>
00192   Teuchos::ArrayView<const Ordinal> 
00193   Import<Ordinal>::getRemoteLIDs() const {
00194     return ImportData_->remoteLIDs_();
00195   }
00196 
00197   template <typename Ordinal>
00198   Ordinal Import<Ordinal>::getNumExportIDs() const {
00199     return ImportData_->numExportIDs_;
00200   }
00201 
00202   template <typename Ordinal>
00203   Teuchos::ArrayView<const Ordinal> 
00204   Import<Ordinal>::getExportLIDs() const {
00205     return ImportData_->exportLIDs_();
00206   }
00207 
00208   template <typename Ordinal>
00209   Teuchos::ArrayView<const Ordinal> 
00210   Import<Ordinal>::getExportImageIDs() const {
00211     return ImportData_->exportImageIDs_();
00212   }
00213 
00214   template <typename Ordinal>
00215   const Map<Ordinal> & 
00216   Import<Ordinal>::getSourceMap() const {
00217     return ImportData_->source_;
00218   }
00219 
00220   template <typename Ordinal>
00221   const Map<Ordinal> & 
00222   Import<Ordinal>::getTargetMap() const {
00223     return ImportData_->target_;
00224   }
00225 
00226   template <typename Ordinal>
00227   Distributor<Ordinal>& 
00228   Import<Ordinal>::getDistributor() const {
00229     return ImportData_->distributor_;
00230   }
00231 
00232   template <typename Ordinal>
00233   Import<Ordinal>& 
00234   Import<Ordinal>::operator=(const Import<Ordinal> & Source) 
00235   {
00236     ImportData_ = Source.ImportData_;
00237     return *this;
00238   }
00239 
00240   template <typename Ordinal>
00241   void Import<Ordinal>::print(std::ostream& os) const 
00242   {
00243     using std::endl;
00244     os << "Import Data Members:" << endl;
00245     os << "permuteToLIDs:   {"; std::copy(getPermuteToLIDs().begin()  ,getPermuteToLIDs().end()  ,std::ostream_iterator<Ordinal>(os," ")); os << " }" << endl;
00246     os << "permuteFromLIDs: {"; std::copy(getPermuteFromLIDs().begin(),getPermuteFromLIDs().end(),std::ostream_iterator<Ordinal>(os," ")); os << " }" << endl;
00247     os << "remoteLIDs:      {"; std::copy(getRemoteLIDs().begin()     ,getRemoteLIDs().end()     ,std::ostream_iterator<Ordinal>(os," ")); os << " }" << endl;
00248     os << "exportLIDs:      {"; std::copy(getExportLIDs().begin()     ,getExportLIDs().end()     ,std::ostream_iterator<Ordinal>(os," ")); os << " }" << endl;
00249     os << "exportImageIDs:  {"; std::copy(getExportImageIDs().begin() ,getExportImageIDs().end() ,std::ostream_iterator<Ordinal>(os," ")); os << " }" << endl;
00250     os << "numSameIDs   : " << getNumSameIDs() << endl;
00251     os << "numPermuteIDs: " << getNumPermuteIDs() << endl;
00252     os << "numRemoteIDs : " << getNumRemoteIDs() << endl;
00253     os << "numExportIDs : " << getNumExportIDs() << endl;
00254     os << "\nsource: " << endl << getSourceMap();
00255     os << "\ntarget: " << endl << getTargetMap();
00256   }
00257 
00258 
00259   template <typename Ordinal>
00260   void Import<Ordinal>::setupSamePermuteRemote() 
00261   {
00262     const Map<Ordinal> & source = getSourceMap();
00263     const Map<Ordinal> & target = getTargetMap();
00264     Teuchos::ArrayView<const Ordinal> sourceGIDs = source.getMyGlobalEntries();
00265     Teuchos::ArrayView<const Ordinal> targetGIDs = target.getMyGlobalEntries();
00266 
00267     // -- compute numSameIDs_ ---
00268     // go through GID lists of source and target. if the ith GID on both is the same, 
00269     // increment numSameIDs_ and try the next. as soon as you come to a pair that don't
00270     // match, give up.
00271     typename Teuchos::ArrayView<const Ordinal>::iterator sourceIter = sourceGIDs.begin(),
00272                                                          targetIter = targetGIDs.begin();
00273     while( sourceIter != sourceGIDs.end() && targetIter != targetGIDs.end() && *sourceIter == *targetIter )
00274     {
00275       ++ImportData_->numSameIDs_;
00276       ++sourceIter;
00277       ++targetIter;
00278     }
00279     // targetIter should now point to the GID of the first non-same entry or the end of targetGIDs
00280 
00281     // -- compute numPermuteIDs and numRemoteIDs --
00282     // -- fill permuteToLIDs_, permuteFromLIDs_, remoteGIDs_, and remoteLIDs_ --
00283     // go through remaining entries in targetGIDs. if source owns that GID, 
00284     // increment numPermuteIDs_, and add entries to permuteToLIDs_ and permuteFromLIDs_.
00285     // otherwise increment numRemoteIDs_ and add entries to remoteLIDs_ and remoteGIDs_.
00286     for (; targetIter != targetGIDs.end(); ++targetIter) {
00287       if (source.isMyGlobalIndex(*targetIter)) {
00288         // both source and target list this GID (*targetIter)
00289         // determine the LIDs for this GID on both Maps and add them to the permutation lists
00290         ImportData_->permuteToLIDs_.push_back(target.getLocalIndex(*targetIter));
00291         ImportData_->permuteFromLIDs_.push_back(source.getLocalIndex(*targetIter));
00292       }
00293       else {
00294         ImportData_->remoteLIDs_.push_back(target.getLocalIndex(*targetIter));
00295         ImportData_->remoteGIDs_.push_back(*targetIter);
00296       }
00297     }
00298     ImportData_->numPermuteIDs_ = Teuchos::as<Ordinal>(ImportData_->permuteToLIDs_.size());
00299     ImportData_->numRemoteIDs_  = Teuchos::as<Ordinal>(ImportData_->remoteLIDs_.size());
00300 
00301     TEST_FOR_EXCEPTION( (ImportData_->numRemoteIDs_ > 0) && !source.isDistributed(), std::runtime_error, 
00302         "Tpetra::Import<" << Teuchos::OrdinalTraits<Ordinal>::name() 
00303         << ">::setupSamePermuteRemote(): Target has remote LIDs but Source is not distributed globally.");
00304   }
00305 
00306 
00307   template <typename Ordinal>
00308   void Import<Ordinal>::setupExport()
00309   {
00310     const Map<Ordinal> & source = getSourceMap();
00311 
00312     // create remoteImageID list: for each entry remoteGIDs[i],
00313     // remoteImageIDs[i] will contain the ImageID of the image that owns that GID.
00314     // check for GIDs that exist in target but not in source: we see this if getRemoteIndexList returns true
00315     Teuchos::Array<Ordinal> remoteImageIDs(ImportData_->remoteGIDs_.size());
00316     TEST_FOR_EXCEPTION( source.getRemoteIndexList(ImportData_->remoteGIDs_(), remoteImageIDs()) == true, std::runtime_error,
00317         "Tpetra::Import::setupExport(): Target has GIDs not found in Source.");
00318 
00319     // sort remoteImageIDs in ascending order
00320     // apply same permutation to remoteGIDs_
00321     sortArrays(remoteImageIDs(), ImportData_->remoteGIDs_());
00322 
00323     // call Distributor.createFromRecvs()
00324     // takes in numRemoteIDs_, remoteGIDs_, and remoteImageIDs_
00325     // returns numExportIDs_, exportLIDs_, and exportImageIDs_
00326     TEST_FOR_EXCEPT(ImportData_->remoteGIDs_.size() != (typename std::vector<Ordinal>::size_type)ImportData_->numRemoteIDs_);      // FINISH: remove this
00327     TEST_FOR_EXCEPT(ImportData_->exportLIDs_.size() != (typename Teuchos::ArrayRCP<Ordinal>::Ordinal)ImportData_->numExportIDs_ ); // FINISH: remove this
00328     ImportData_->distributor_.createFromRecvs(ImportData_->remoteGIDs_, remoteImageIDs, ImportData_->exportLIDs_, ImportData_->exportImageIDs_);
00329 
00330     // convert exportLIDs_ from GIDs to their LIDs in target
00331     for(typename Teuchos::ArrayRCP<Ordinal>::const_iterator i = ImportData_->exportLIDs_.begin(); 
00332         i != ImportData_->exportLIDs_.end(); ++i) 
00333     {
00334       *i = source.getLocalIndex(*i);
00335     }
00336   }
00337 
00338 } // namespace Tpetra
00339 
00340 #endif // TPETRA_IMPORT_HPP

Generated on Wed May 12 21:59:41 2010 for Tpetra Matrix/Vector Services by  doxygen 1.4.7