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