Anasazi Version of the Day
Tsqr_TeuchosMessenger.hpp
00001 // @HEADER
00002 // ***********************************************************************
00003 //
00004 //                 Anasazi: Block Eigensolvers Package
00005 //                 Copyright (2010) 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 __TSQR_Trilinos_TeuchosMessenger_hpp
00030 #define __TSQR_Trilinos_TeuchosMessenger_hpp
00031 
00032 #include "Teuchos_CommHelpers.hpp"
00033 #include "Tsqr_MessengerBase.hpp"
00034 #include <algorithm>
00035 
00038 
00039 namespace TSQR { 
00040   namespace Trilinos {
00050     template< class Datum >
00051     class TeuchosMessenger : public MessengerBase< Datum > {
00052     public:
00053       typedef Teuchos::RCP< const Teuchos::Comm<int> > comm_ptr;
00054 
00055       TeuchosMessenger (const comm_ptr& pComm) : pComm_ (pComm) {}
00056 
00058       virtual void 
00059       send (const Datum sendData[], 
00060       const int sendCount, 
00061       const int destProc, 
00062       const int tag) 
00063       {
00067   Teuchos::send (*pComm_, sendCount, sendData, destProc);
00068       }
00069 
00071       virtual void 
00072       recv (Datum recvData[], 
00073       const int recvCount, 
00074       const int srcProc, 
00075       const int tag) 
00076       {
00080   Teuchos::receive (*pComm_, srcProc, recvCount, recvData);
00081       }
00082 
00086       virtual void 
00087       swapData (const Datum sendData[], 
00088     Datum recvData[], 
00089     const int sendRecvCount, 
00090     const int destProc, 
00091     const int tag)
00092       {
00093   if (destProc == rank())
00094     std::copy (sendData, sendData+sendRecvCount, recvData);
00095   else
00096     {
00097       using Teuchos::RCP;
00098       using Teuchos::ArrayRCP;
00099       using Teuchos::CommRequest;
00100 
00101       const int srcProc = Teuchos::rank (*pComm_);
00102 
00103       // FIXME (mfh 14 June 2010, 09 Jul 2010) It would be nice
00104       // if Teuchos had a sendRecv() routine... as it is, we
00105       // have to do a send and then a receive.  We could do an
00106       // isend and an ireceive in order to exploit potential
00107       // overlap of the two messages.  That works if sendData
00108       // and recvData don't alias one another.  We only do a
00109       // partial check for aliasing here (sendData == recvData).
00110       if (sendData == recvData)
00111         {
00112     // The smaller-rank process sends first, and the
00113     // larger-rank process receives first.
00114     //
00115     // Teuchos::send() and Teuchos::recv() are blocking,
00116     // so we may safely write to recvBuf even if it
00117     // aliases sendBuf.
00118     if (srcProc < destProc)
00119       {
00120         Teuchos::send (*pComm_, sendRecvCount, sendData, destProc);
00121         Teuchos::receive (*pComm_, destProc, sendRecvCount, recvData);
00122       }
00123     else 
00124       {
00125         Teuchos::receive (*pComm_, destProc, sendRecvCount, recvData);
00126         Teuchos::send (*pComm_, sendRecvCount, sendData, destProc);
00127       }
00128         }
00129       else
00130         {
00131     ArrayRCP< const Datum > sendBuf (sendData, 0, sendRecvCount, false);
00132     ArrayRCP< Datum > recvBuf (recvData, 0, sendRecvCount, false);
00133 
00134     RCP< CommRequest > sendReq, recvReq;
00135     if (srcProc < destProc)
00136       {
00137         sendReq = Teuchos::isend (*pComm_, sendBuf, destProc);
00138         recvReq = Teuchos::ireceive (*pComm_, recvBuf, destProc);
00139       }
00140     else
00141       {
00142         recvReq = Teuchos::ireceive (*pComm_, recvBuf, destProc);
00143         sendReq = Teuchos::isend (*pComm_, sendBuf, destProc);
00144       }
00145     // Wait on both the send and the receive to complete.  The
00146     // two can happen independently, because sendBuf and recvBuf
00147     // are different.  (We assert no aliasing of buffers here,
00148     // and we've also checked above that destProc != rank().)
00149     Teuchos::waitAll (*pComm_, Teuchos::tuple (sendReq, recvReq));
00150         }
00151     }
00152       }
00153 
00156       virtual Datum 
00157       globalSum (const Datum& inDatum) 
00158       {
00159   Datum outDatum;
00160   Teuchos::reduceAll (*pComm_, Teuchos::REDUCE_SUM, inDatum, 
00161           Teuchos::outArg(outDatum));
00162   return outDatum;
00163       }
00164 
00169       virtual Datum 
00170       globalMin (const Datum& inDatum)
00171       {
00172   Datum outDatum;
00173   Teuchos::reduceAll (*pComm_, Teuchos::REDUCE_MIN, inDatum, 
00174           Teuchos::outArg(outDatum));
00175   return outDatum;
00176       }
00177 
00182       virtual Datum 
00183       globalMax (const Datum& inDatum)
00184       {
00185   Datum outDatum;
00186   Teuchos::reduceAll (*pComm_, Teuchos::REDUCE_MAX, inDatum, 
00187           Teuchos::outArg(outDatum));
00188   return outDatum;
00189       }
00190 
00193       virtual void
00194       globalVectorSum (const Datum inData[], 
00195            Datum outData[], 
00196            const int count) 
00197       {
00198   Teuchos::reduceAll (*pComm_, Teuchos::REDUCE_SUM, count, 
00199           inData, outData);
00200       }
00201 
00202       virtual void
00203       broadcast (Datum data[], 
00204      const int count,
00205      const int root)
00206       {
00207   // Assumes that Datum has value semantics.
00208   Teuchos::broadcast (*pComm_, root, count, data);
00209       }
00210 
00214       virtual int rank () const { return Teuchos::rank (*pComm_); }
00215 
00219       virtual int size () const { return Teuchos::size (*pComm_); }
00220 
00224       virtual void barrier () const { Teuchos::barrier (*pComm_); }
00225 
00226     private:
00230       comm_ptr pComm_;
00231     };
00232   } // namespace Trilinos
00233 } // namespace TSQR
00234 
00235 #endif // __TSQR_Trilinos_TeuchosMessenger_hpp
00236 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends