Tpetra_Export.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_EXPORT_HPP
00030 #define TPETRA_EXPORT_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 // FINISH: this class is not finished yet
00043 
00044 namespace Tpetra {
00045 
00047 
00060   template <typename Ordinal>
00061   class Export: public Teuchos::Object {
00062 
00063   public:
00064 
00066 
00067 
00069     Export(const Map<Ordinal> & source, const Map<Ordinal> & target);
00070 
00072     Export(Export<Ordinal> const& rhs);
00073 
00075     ~Export();
00076 
00078 
00080 
00081 
00083     Ordinal getNumSameIDs() const;
00084 
00086     Ordinal getNumPermuteIDs() const;
00087 
00089     Teuchos::ArrayView<const Ordinal> getPermuteFromLIDs() const;
00090 
00092     Teuchos::ArrayView<const Ordinal> getPermuteToLIDs() const;
00093 
00095     Ordinal getNumRemoteIDs() const;
00096 
00098     Teuchos::ArrayView<const Ordinal> getRemoteLIDs() const;
00099 
00101     Ordinal getNumExportIDs() const;
00102 
00104     Teuchos::ArrayView<const Ordinal> getExportLIDs() const;
00105 
00107     Teuchos::ArrayView<const Ordinal> getExportImageIDs() const;
00108 
00110     const Map<Ordinal> & getSourceMap() const;
00111 
00113     const Map<Ordinal> & getTargetMap() const;
00114 
00115     Distributor<Ordinal>& getDistributor() const;
00116 
00118     Export<Ordinal>& operator = (const Export<Ordinal> & Source);
00119 
00121 
00123 
00124 
00126     virtual void print(std::ostream& os) const;
00127 
00129 
00130   private:
00131 
00132     Teuchos::RCP<ImportExportData<Ordinal> > 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 <typename Ordinal>
00144     Export<Ordinal>::Export(const Map<Ordinal> & source, const Map<Ordinal> & target)
00145     : Teuchos::Object("Tpetra::Export")
00146     , ExportData_()
00147   {
00148     TEST_FOR_EXCEPT(true); // not yet supported
00149     ExportData_ = Teuchos::rcp(new ImportExportData<Ordinal>(source, target));
00150     // call subfunctions
00151     setupSamePermuteExport();
00152     if(source.isDistributed()) {
00153       setupRemote();
00154     }
00155   }
00156 
00157   template <typename Ordinal>
00158   Export<Ordinal>::Export(const Export<Ordinal> & rhs)
00159   : Teuchos::Object(rhs.label())
00160   , ExportData_(rhs.ExportData_)
00161   {
00162     TEST_FOR_EXCEPT(true); // not yet supported
00163   }
00164 
00165   template <typename Ordinal>
00166   Export<Ordinal>::~Export() 
00167   {}
00168 
00169   template <typename Ordinal>
00170   Ordinal Export<Ordinal>::getNumSameIDs() const {
00171     return ExportData_->numSameIDs_;
00172   }
00173 
00174   template <typename Ordinal>
00175   Ordinal Export<Ordinal>::getNumPermuteIDs() const {
00176     return ExportData_->numPermuteIDs_;
00177   }
00178 
00179   template <typename Ordinal>
00180   Teuchos::ArrayView<const Ordinal> 
00181   Export<Ordinal>::getPermuteFromLIDs() const {
00182     return ExportData_->permuteFromLIDs_();
00183   }
00184 
00185   template <typename Ordinal>
00186   Teuchos::ArrayView<const Ordinal>
00187   Export<Ordinal>::getPermuteToLIDs() const {
00188     return ExportData_->permuteToLIDs_();
00189   }
00190 
00191   template <typename Ordinal>
00192   Ordinal Export<Ordinal>::getNumRemoteIDs() const {
00193     return ExportData_->numRemoteIDs_;
00194   }
00195 
00196   template <typename Ordinal>
00197   Teuchos::ArrayView<const Ordinal> 
00198   Export<Ordinal>::getRemoteLIDs() const {
00199     return ExportData_->remoteLIDs_();
00200   }
00201 
00202   template <typename Ordinal>
00203   Ordinal Export<Ordinal>::getNumExportIDs() const {
00204     return ExportData_->numExportIDs_;
00205   }
00206 
00207   template <typename Ordinal>
00208   Teuchos::ArrayView<const Ordinal> 
00209   Export<Ordinal>::getExportLIDs() const {
00210     return ExportData_->exportLIDs_();
00211   }
00212 
00213   template <typename Ordinal>
00214   Teuchos::ArrayView<const Ordinal> 
00215   Export<Ordinal>::getExportImageIDs() const {
00216     return ExportData_->exportImageIDs_();
00217   }
00218 
00219   template <typename Ordinal>
00220   const Map<Ordinal> & 
00221   Export<Ordinal>::getSourceMap() const {
00222     return ExportData_->source_;
00223   }
00224 
00225   template <typename Ordinal>
00226   const Map<Ordinal> & 
00227   Export<Ordinal>::getTargetMap() const {
00228     return ExportData_->target_;
00229   }
00230 
00231   template <typename Ordinal>
00232   Distributor<Ordinal>& 
00233   Export<Ordinal>::getDistributor() const {
00234     return ExportData_->distributor_;
00235   }
00236 
00237   template <typename Ordinal>
00238   Export<Ordinal>& 
00239   Export<Ordinal>::operator=(const Export<Ordinal> & Source) 
00240   {
00241     ExportData_ = Source.ExportData_;
00242     return *this;
00243   }
00244 
00245   template <typename Ordinal>
00246   void Export<Ordinal>::print(std::ostream& os) const 
00247   {
00248     using std::endl;
00249     os << "Export Data Members:" << endl;
00250     os << "permuteToLIDs:   {"; std::copy(getPermuteToLIDs().begin()  ,getPermuteToLIDs().end()  ,std::ostream_iterator<Ordinal>(os," ")); os << " }" << endl;
00251     os << "permuteFromLIDs: {"; std::copy(getPermuteFromLIDs().begin(),getPermuteFromLIDs().end(),std::ostream_iterator<Ordinal>(os," ")); os << " }" << endl;
00252     os << "remoteLIDs:      {"; std::copy(getRemoteLIDs().begin()     ,getRemoteLIDs().end()     ,std::ostream_iterator<Ordinal>(os," ")); os << " }" << endl;
00253     os << "exportLIDs:      {"; std::copy(getExportLIDs().begin()     ,getExportLIDs().end()     ,std::ostream_iterator<Ordinal>(os," ")); os << " }" << endl;
00254     os << "exportImageIDs:  {"; std::copy(getExportImageIDs().begin() ,getExportImageIDs().end() ,std::ostream_iterator<Ordinal>(os," ")); os << " }" << endl;
00255     os << "numSameIDs   : " << getNumSameIDs() << endl;
00256     os << "numPermuteIDs: " << getNumPermuteIDs() << endl;
00257     os << "numRemoteIDs : " << getNumRemoteIDs() << endl;
00258     os << "numExportIDs : " << getNumExportIDs() << endl;
00259     os << "\nsource: " << endl << getSourceMap();
00260     os << "\ntarget: " << endl << getTargetMap();
00261   }
00262 
00263 
00264   template <typename Ordinal>
00265   void Export<Ordinal>::setupSamePermuteExport() 
00266   {
00267     const Map<Ordinal> & source = getSourceMap();
00268     const Map<Ordinal> & target = getTargetMap();
00269     Teuchos::ArrayView<const Ordinal> sourceGIDs = source.getMyGlobalEntries();
00270     Teuchos::ArrayView<const Ordinal> targetGIDs = target.getMyGlobalEntries();
00271 
00272     // -- compute numSameIDs_ ---
00273     // go through GID lists of source and target. if the ith GID on both is the same, 
00274     // increment numSameIDs_ and try the next. as soon as you come to a pair that don't
00275     // match, give up.
00276     typename Teuchos::ArrayView<const Ordinal>::iterator sourceIter = sourceGIDs.begin(),
00277                                                          targetIter = targetGIDs.begin();
00278     while( sourceIter != sourceGIDs.end() && targetIter != targetGIDs.end() && *sourceIter == *targetIter )
00279     {
00280       ++ExportData_->numSameIDs_;
00281       ++sourceIter;
00282       ++targetIter;
00283     }
00284     // sourceIter should now point to the GID of the first non-same entry or at the end of targetGIDs
00285 
00286     // -- compute numPermuteIDs and numRemoteIDs --
00287     // -- fill permuteToLIDs_, permuteFromLIDs_, remoteGIDs_, and remoteLIDs_ --
00288     // go through remaining entries in sourceGIDs. if target owns that GID, 
00289     // increment numPermuteIDs_, and add entries to permuteToLIDs_ and permuteFromLIDs_.
00290     // otherwise increment numExportIDs_ and add entries to exportLIDs_ and exportGIDs_.
00291     for(; sourceIter != sourceGIDs.end(); ++sourceIter) {
00292       if(target.isMyGlobalIndex(*sourceIter)) {
00293         // both source and target list this GID (*targetIter)
00294         // determine the LIDs for this GID on both Maps and add them to the permutation lists
00295         ExportData_->permuteToLIDs_.push_back(  target.getLocalIndex(*sourceIter));
00296         ExportData_->permuteFromLIDs_.push_back(source.getLocalIndex(*sourceIter));
00297       }
00298       else {
00299         ExportData_->exportLIDs_.push_back(source.getLocalIndex(*sourceIter));
00300         ExportData_->exportGIDs_.push_back(*sourceIter);
00301       }
00302     }
00303     ExportData_->numPermuteIDs_ = Teuchos::as<Ordinal>(ExportData_->permuteToLIDs.size());
00304     ExportData_->numExportIDs_  = Teuchos::as<Ordinal>(ExportData_->exportLIDs_.size());
00305 
00306     /* FINISH
00307     TEST_FOR_EXCEPTION( (ExportData_->numExportIDs_ > zero) && (!source.isDistributed()), std::runtime_error, 
00308         "Tpetra::Export<" << Teuchos::OrdinalTraits<Ordinal>::name() 
00309         << ">::setupSamePermuteExport(): Source has export LIDs but Source is not distributed globally.");
00310 
00311     // -- compute exportImageIDs_ --
00312     // get list of images that own the GIDs in exportGIDs_ (in the target Map)
00313     // check exportImageIDs_ for any -1 entries (nobody owns that GID in the target Map)
00314     target.getRemoteIDList(ExportData_->exportGIDs_, ExportData_->exportImageIDs_);
00315     Ordinal count = std::count(ExportData_->exportImageIDs_.begin(), ExportData_->exportImageIDs_.end(), negOne);
00316     if(count > zero) {
00317       throw reportError("Source has GIDs not found in Target.", 2);
00318     }
00319     */
00320   }
00321 
00322   template <typename Ordinal>
00323   void Export<Ordinal>::setupRemote() 
00324   {
00325     Ordinal const zero = Teuchos::OrdinalTraits<Ordinal>::zero();
00326     Ordinal const one = Teuchos::OrdinalTraits<Ordinal>::one();
00327     Map<Ordinal> const& target = getTargetMap();
00328 
00329     // make sure export IDs are ordered by image
00330     // sort exportImageIDs_ in ascending order,
00331     // and apply the same permutation to exportGIDs_ and exportLIDs_.
00332     sortArrays(ExportData_->exportImageIDs_, ExportData_->exportGIDs_, ExportData_->exportLIDs_);
00333 
00334     // Construct list of entries that calling image needs to send as a result
00335     // of everyone asking for what it needs to receive.
00336     ExportData_->distributor_.createFromSends(ExportData_->numExportIDs_, ExportData_->exportImageIDs_, true, ExportData_->numRemoteIDs_);
00337     // -- numRemoteIDs_ is now defined --
00338 
00339     // Use comm plan with ExportGIDs to find out who is sending to us and
00340     // get proper ordering of GIDs for remote entries 
00341     // (that we will convert to LIDs when done).
00342     Teuchos::RCP< Teuchos::Comm<Ordinal> > comm = ExportData_->platform_->createOrdinalComm();
00343     comm->doPostsAndWaits(ExportData_->distributor_, ExportData_->exportGIDs_, one, ExportData_->remoteGIDs_);
00344     // -- remoteGIDs_ is now defined --
00345 
00346     // Remote IDs come in as GIDs, convert to LIDs
00347     for(Ordinal i = zero; i < ExportData_->numRemoteIDs_; i++) {
00348       ExportData_->remoteLIDs_.push_back(target.getLID(ExportData_->remoteGIDs_[i]));
00349     }
00350   }
00351 
00352 } // namespace Tpetra
00353 
00354 #endif // TPETRA_EXPORT_HPP

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