Teuchos Package Browser (Single Doxygen Collection) Version of the Day
DefaultMpiComm_UnitTests.cpp
Go to the documentation of this file.
00001 /*
00002 // @HEADER
00003 // ***********************************************************************
00004 //
00005 //                    Teuchos: Common Tools Package
00006 //                 Copyright (2004) Sandia Corporation
00007 //
00008 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
00009 // license for use of this work by or on behalf of the U.S. Government.
00010 //
00011 // Redistribution and use in source and binary forms, with or without
00012 // modification, are permitted provided that the following conditions are
00013 // met:
00014 //
00015 // 1. Redistributions of source code must retain the above copyright
00016 // notice, this list of conditions and the following disclaimer.
00017 //
00018 // 2. Redistributions in binary form must reproduce the above copyright
00019 // notice, this list of conditions and the following disclaimer in the
00020 // documentation and/or other materials provided with the distribution.
00021 //
00022 // 3. Neither the name of the Corporation nor the names of the
00023 // contributors may be used to endorse or promote products derived from
00024 // this software without specific prior written permission.
00025 //
00026 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
00027 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00028 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00029 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
00030 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00031 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00032 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00033 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00034 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00035 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00036 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00037 //
00038 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
00039 //
00040 // ***********************************************************************
00041 // @HEADER
00042 */
00043 
00044 #include "Teuchos_UnitTestHarness.hpp"
00045 
00046 
00047 #include "Teuchos_DefaultSerialComm.hpp"
00048 #include "Teuchos_CommHelpers.hpp"
00049 #include "Teuchos_DefaultComm.hpp"
00050 #include "Teuchos_DefaultSerialComm.hpp"
00051 #include "Teuchos_getConst.hpp"
00052 #include "Teuchos_as.hpp"
00053 
00054 #ifdef HAVE_TEUCHOS_QD
00055 #include <qd/dd_real.h>
00056 #endif
00057 
00058 namespace std { 
00059 
00060 
00061 template <typename Packet>
00062 ostream & operator<< ( ostream& os, const pair<Packet, Packet>& arg)
00063 {
00064   os << "(" << arg.first << "," << arg.second << ")";
00065   return os;
00066 }
00067 
00068 
00069 } // namespace std
00070 
00071 
00072 namespace Teuchos {
00073 
00074 
00075 template<typename Packet>
00076 struct ScalarTraits<std::pair<Packet,Packet> >
00077 {
00078   typedef ScalarTraits<Packet> PST;
00079       typedef  std::pair<typename PST::magnitudeType, typename PST::magnitudeType> magnitudeType;
00080   static const bool isComplex = PST::isComplex;
00081   static const bool isComparable = PST::isComparable;
00082   static const bool hasMachineParameters = PST::hasMachineParameters;
00083   // Not defined: eps(), sfmin(), base(), prec(), t(), rnd(), emin(), rmin(), emax(), rmax()
00084   static inline magnitudeType magnitude(std::pair<Packet,Packet> a) { return std::pair<Packet,Packet>( PST::magnitude(a.first), PST::magnitude(a.second) ); }
00085   static inline std::pair<Packet,Packet> zero()  { return std::pair<Packet,Packet>(PST::zero(),PST::zero()); }
00086   static inline std::pair<Packet,Packet> one()   { return std::pair<Packet,Packet>(PST::one(), PST::one()); }
00087   static inline std::pair<Packet,Packet> conjugate(std::pair<Packet,Packet> x) { return std::pair<Packet,Packet>(PST::conjugate(x.first), PST::conjugate(x.second) ); }
00088   static inline std::pair<Packet,Packet> real(std::pair<Packet,Packet> x) { return std::pair<Packet,Packet>(PST::real(x.first), PST::real(x.second) ); }
00089   static inline std::pair<Packet,Packet> imag(std::pair<Packet,Packet> x) { return std::pair<Packet,Packet>(PST::imag(x.first), PST::imag(x.second) ); }
00090   static inline bool isnaninf(std::pair<Packet,Packet> x) { return PST::isnaninf(x.first) || PST::isnaninf(x.second); }
00091   static inline void seedrandom(unsigned int s) { PST::seedrandom(s); }
00092   static inline std::pair<Packet,Packet> random() { return std::pair<Packet,Packet>( PST::random(), PST::random() ); }
00093   static inline std::string name() { return "std::pair<" + Teuchos::TypeNameTraits<Packet>::name() + "," + Teuchos::TypeNameTraits<Packet>::name() + ">"; }
00094   static inline std::pair<Packet,Packet> squareroot(std::pair<Packet,Packet> x) { return std::pair<Packet,Packet>(PST::squareroot(x.first), PST::squareroot(x.second)); }
00095   static inline std::pair<Packet,Packet> pow(std::pair<Packet,Packet> x, std::pair<Packet,Packet> y) { return std::pair<Packet,Packet>( PST::pow(x.first,y.first), PST::pow(x.second,y.second) ); }
00096 };
00097 
00098 template<class Packet, class ConvertToPacket>
00099 class ValueTypeConversionTraits<std::pair<Packet,Packet>, ConvertToPacket> {
00100 public:
00101   static std::pair<Packet,Packet> convert( const ConvertToPacket t )
00102     {
00103       return std::pair<Packet,Packet>(t,t);
00104     }
00105   static std::pair<Packet,Packet> safeConvert( const ConvertToPacket t )
00106     {
00107       return std::pair<Packet,Packet>(t,t);
00108     }
00109 };
00110 
00111 
00112 } // namespace Teuchos
00113 
00114 
00115 namespace {
00116 
00117 
00118 using Teuchos::as;
00119 using Teuchos::RCP;
00120 using Teuchos::rcp;
00121 using Teuchos::Array;
00122 using Teuchos::Comm;
00123 using Teuchos::DefaultComm;
00124 using Teuchos::GlobalMPISession;
00125 using Teuchos::defaultSmallNumber;
00126 using Teuchos::outArg;
00127 
00128 
00129 bool testMpi = true;
00130 
00131 
00132 double errorTolSlack = 1e+1;
00133 
00134 
00135 
00136 TEUCHOS_STATIC_SETUP()
00137 {
00138 
00139   Teuchos::CommandLineProcessor &clp = Teuchos::UnitTestRepository::getCLP();
00140 
00141   clp.addOutputSetupOptions(true);
00142 
00143   clp.setOption(
00144     "test-mpi", "test-serial", &testMpi,
00145     "Test MPI (if available) or force test of serial.  In a serial build,"
00146     " this option is ignord and a serial comm is always used." );
00147 
00148   clp.setOption(
00149     "error-tol-slack", &errorTolSlack,
00150     "Slack off of machine epsilon used to check test results" );
00151 
00152 }
00153 
00154 
00155 template<class Ordinal>
00156 RCP<const Comm<Ordinal> > getDefaultComm()
00157 {
00158   if (testMpi) {
00159     return DefaultComm<Ordinal>::getComm();
00160   }
00161   return rcp(new Teuchos::SerialComm<Ordinal>);
00162 }
00163 
00164 
00165 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL( DefaultMpiComm, basic, Ordinal )
00166 {
00167   RCP<const Comm<Ordinal> > comm = getDefaultComm<Ordinal>();
00168   out << "comm = " << Teuchos::describe(*comm);
00169   TEST_EQUALITY( size(*comm), GlobalMPISession::getNProc() );
00170 }
00171 
00172 
00173 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( DefaultMpiComm, reduceAllAndScatter_1, Ordinal, Packet )
00174 {
00175 
00176   typedef Teuchos::ScalarTraits<Packet> PT;
00177   typedef typename PT::magnitudeType PacketMag;
00178   typedef Teuchos::ScalarTraits<PacketMag> PMT;
00179 
00180   RCP<const Comm<Ordinal> > comm = getDefaultComm<Ordinal>();
00181   const Ordinal numProcs = size(*comm);
00182 
00183 #ifdef TEUCHOS_MPI_COMM_DUMP
00184   Teuchos::MpiComm<Ordinal>::show_dump = true;
00185 #endif
00186 
00187   Array<Packet> sendBuffer(as<Ordinal>(numProcs));
00188   for (Ordinal k = 0; k < numProcs; ++k) {
00189     sendBuffer[k] = as<Packet>(1);
00190   }
00191 
00192   Array<Ordinal> recvCounts(as<Ordinal>(numProcs), as<Ordinal>(1));
00193 
00194   Array<Packet> myGlobalReducts(1);
00195 
00196   Teuchos::reduceAllAndScatter<Ordinal,Packet>(
00197     *comm, Teuchos::REDUCE_SUM,
00198     as<Ordinal>(sendBuffer.size()), &sendBuffer[0],
00199     &recvCounts[0], &myGlobalReducts[0]
00200     );
00201 
00202   if (std::numeric_limits<Packet>::is_integer) {
00203     TEST_EQUALITY( myGlobalReducts[0], as<Packet>(numProcs) );
00204   }
00205   else {
00206     const PacketMag local_errorTolSlack = static_cast<PacketMag>(errorTolSlack);
00207     TEST_FLOATING_EQUALITY( myGlobalReducts[0], as<Packet>(numProcs),
00208       as<PacketMag>(defaultSmallNumber<PacketMag>() * local_errorTolSlack / numProcs)
00209       );
00210   }
00211   
00212 }
00213 
00214 
00215 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( DefaultMpiComm, reduceAllAndScatter_2, Ordinal, Packet )
00216 {
00217 
00218   typedef Teuchos::ScalarTraits<Packet> PT;
00219   typedef typename PT::magnitudeType PacketMag;
00220   typedef Teuchos::ScalarTraits<PacketMag> PMT;
00221 
00222   RCP<const Comm<Ordinal> > comm = getDefaultComm<Ordinal>();
00223   const Ordinal numProcs = size(*comm);
00224   const Ordinal procRank = rank(*comm);
00225 
00226   Array<Packet> sendBuffer(as<Ordinal>(numProcs));
00227   for (Ordinal k = 0; k < numProcs; ++k) {
00228     sendBuffer[k] = as<Packet>(procRank + k);
00229   }
00230 
00231   Array<Ordinal> recvCounts(as<Ordinal>(numProcs), as<Ordinal>(1));
00232 
00233   Array<Packet> myGlobalReducts(1);
00234 
00235   Teuchos::reduceAllAndScatter<Ordinal,Packet>(
00236     *comm, Teuchos::REDUCE_SUM,
00237     as<Ordinal>(sendBuffer.size()), &sendBuffer[0],
00238     &recvCounts[0], &myGlobalReducts[0]
00239     );
00240 
00241   const Packet expectedMyGlobalReduct = as<Packet>(
00242     numProcs * procRank + ((numProcs - 1) * numProcs)/2 
00243     );
00244 
00245   if (std::numeric_limits<Packet>::is_integer) {
00246     TEST_EQUALITY( myGlobalReducts[0], expectedMyGlobalReduct );
00247   }
00248   else {
00249     const PacketMag local_errorTolSlack = static_cast<PacketMag>(errorTolSlack);
00250     TEST_FLOATING_EQUALITY( myGlobalReducts[0], expectedMyGlobalReduct,
00251       as<PacketMag>(defaultSmallNumber<PacketMag>() * local_errorTolSlack / numProcs)
00252       );
00253   }
00254 
00255 }
00256 
00257 
00258 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( DefaultMpiComm, ReadySend1, Ordinal, Packet )
00259 {
00260 
00261   using Teuchos::broadcast;
00262   using Teuchos::readySend;
00263   using Teuchos::wait;
00264   using Teuchos::as;
00265   using Teuchos::rcpFromRef;
00266   using Teuchos::outArg;
00267   using Teuchos::isend;
00268   using Teuchos::ireceive;
00269   using Teuchos::wait;
00270   using Teuchos::SerialComm;
00271   using Teuchos::is_null;
00272   using Teuchos::arcp;
00273   using Teuchos::arcpClone;
00274   using Teuchos::rcp_dynamic_cast;
00275   using Teuchos::ArrayRCP;
00276   using Teuchos::ptr;
00277   typedef Teuchos::ScalarTraits<Packet> PT;
00278   typedef typename PT::magnitudeType PacketMag;
00279   typedef Teuchos::ScalarTraits<PacketMag> PMT;
00280 
00281   RCP<const Comm<Ordinal> > comm = getDefaultComm<Ordinal>();
00282   const Ordinal numProcs = size(*comm);
00283   const Ordinal procRank = rank(*comm);
00284 
00285   if (
00286     numProcs == 1
00287     &&
00288     !is_null(rcp_dynamic_cast<const SerialComm<Ordinal> >(comm))
00289     )
00290   {
00291     out << "\nThis is Teuchos::SerialComm which does not support readySend!\n";
00292     return; // Pass!
00293   }
00294 
00295   PT::seedrandom(as<unsigned int>(procRank));
00296   Packet origSendData = PT::random();
00297   Packet origRecvData = PT::random();
00298   broadcast<Ordinal, Packet>( *comm, 0, outArg(origSendData) );
00299 
00300   Packet sendData = origSendData;
00301   Packet recvData = origRecvData;
00302 
00303   RCP<Teuchos::CommRequest> recvRequest;
00304 
00305   // Post non-block receive on proc 0
00306   if (procRank == 0) {
00307     // Post non-blocking receive from proc n-1
00308     recvRequest = ireceive<Ordinal, Packet>(
00309         *comm,
00310         rcp(&recvData,false),
00311         numProcs-1
00312         );
00313   }
00314   barrier(*comm);
00315 
00316   if (procRank == numProcs-1) {
00317     // ready send from proc n-1 to proc 0
00318     // send data in sendData
00319     readySend<Ordinal, Packet>(
00320         *comm,
00321         sendData,
00322         0
00323         );
00324   }
00325   barrier(*comm);
00326 
00327   if (procRank == 0) {
00328     // wait for request on 0
00329     wait( *comm, outArg(recvRequest) );
00330   }
00331   barrier(*comm);
00332 
00333   // test that all procs have recvRequest == Teuchos::null
00334   TEST_EQUALITY_CONST( recvRequest, Teuchos::null );
00335 
00336   // proc 0 should have recvData == sendData
00337   if (procRank == 0) {
00338     TEST_EQUALITY( recvData, sendData );
00339   }
00340   // other procs should have recvData == origRecvData (i.e., unchanged)
00341   else {
00342     TEST_EQUALITY( recvData, origRecvData );
00343   }
00344   // all procs should have sendData == origSendData
00345   TEST_EQUALITY( sendData, origSendData );
00346 
00347   // All procs fail if any proc fails
00348   int globalSuccess_int = -1;
00349   reduceAll( *comm, Teuchos::REDUCE_SUM, success ? 0 : 1, outArg(globalSuccess_int) );
00350   TEST_EQUALITY_CONST( globalSuccess_int, 0 );
00351 }
00352 
00353 
00354 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( DefaultMpiComm, ReadySend, Ordinal, Packet )
00355 {
00356 
00357   using Teuchos::broadcast;
00358   using Teuchos::readySend;
00359   using Teuchos::wait;
00360   using Teuchos::as;
00361   using Teuchos::rcpFromRef;
00362   using Teuchos::outArg;
00363   using Teuchos::isend;
00364   using Teuchos::ireceive;
00365   using Teuchos::wait;
00366   using Teuchos::SerialComm;
00367   using Teuchos::is_null;
00368   using Teuchos::arcp;
00369   using Teuchos::arcpClone;
00370   using Teuchos::rcp_dynamic_cast;
00371   using Teuchos::ArrayRCP;
00372   typedef Teuchos::ScalarTraits<Packet> PT;
00373   typedef typename PT::magnitudeType PacketMag;
00374   typedef Teuchos::ScalarTraits<PacketMag> PMT;
00375 
00376   RCP<const Comm<Ordinal> > comm = getDefaultComm<Ordinal>();
00377   const Ordinal numProcs = size(*comm);
00378   const Ordinal procRank = rank(*comm);
00379 
00380   if (
00381     numProcs == 1
00382     &&
00383     !is_null(rcp_dynamic_cast<const SerialComm<Ordinal> >(comm))
00384     )
00385   {
00386     out << "\nThis is Teuchos::SerialComm which does not support readySend!\n";
00387     return; // Pass!
00388   }
00389 
00390   const int dataLen = 3;
00391 
00392   const ArrayRCP<Packet> origSendData = arcp<Packet>(dataLen);
00393   const ArrayRCP<Packet> origRecvData = arcp<Packet>(dataLen);
00394   PT::seedrandom(as<unsigned int>(procRank));
00395   for (int j = 0; j < dataLen; ++j) {
00396     origSendData[j] = PT::random();
00397     origRecvData[j] = PT::random();
00398   }
00399   broadcast<Ordinal, Packet>( *comm, 0, origSendData() );
00400 
00401   const ArrayRCP<Packet> sendData = arcpClone<Packet>(origSendData());
00402   const ArrayRCP<Packet> recvData = arcpClone<Packet>(origRecvData());
00403 
00404   RCP<Teuchos::CommRequest> recvRequest;
00405 
00406   // both proc 0 and proc n-1 will post non-block receives, into recvData
00407   // then proc 0 will initiate a ready-send to proc n-1; the latter will initiate a wait
00408   // a barrier
00409   // then proc n-1 will initiate a ready-send to proc 0 of the data from recvData; the latter will initiate a wait
00410   // a barrier
00411   // now both of these procs should have matching data in sendData and recvData
00412 
00413   // Post non-block receive on both procs
00414   if (procRank == 0) {
00415     // Post non-blocking receive from proc n-1
00416     recvRequest = ireceive<Ordinal, Packet>(
00417         *comm,
00418         recvData.persistingView(0, dataLen),
00419         numProcs-1
00420         );
00421   }
00422   else if (procRank == numProcs-1) {
00423     // Post non-blocking receive from proc 0
00424     recvRequest = ireceive<Ordinal, Packet>(
00425         *comm,
00426         recvData.persistingView(0, dataLen),
00427         0
00428         );
00429   }
00430   barrier(*comm);
00431 
00432   if (procRank == 0) {
00433     // ready send from proc 0 to proc n-1
00434     // send data in sendData
00435     readySend<Ordinal, Packet>(
00436         *comm,
00437         sendData(),
00438         numProcs-1
00439         );
00440   }
00441   else if (procRank == numProcs-1) {
00442     // wait for request on proc n-1
00443     wait( *comm, outArg(recvRequest) );
00444   }
00445   barrier(*comm);
00446 
00447   if (procRank == 0) {
00448     // wait for request on 0
00449     wait( *comm, outArg(recvRequest) );
00450   }
00451   else if (procRank == numProcs-1) {
00452     // ready send from proc n-1 to proc 0
00453     // send data in recvData: THIS IS IMPORTANT: SEE ABOVE
00454     readySend<Ordinal, Packet>(
00455         *comm,
00456         recvData(),
00457         0
00458         );
00459   }
00460   barrier(*comm);
00461 
00462   // test that all procs (even non-participating) have recvRequest == Teuchos::null
00463   TEST_EQUALITY_CONST( recvRequest, Teuchos::null );
00464 
00465   // participating procs should have recvData == sendData
00466   if (procRank == 0 || procRank == numProcs-1) {
00467     TEST_COMPARE_ARRAYS( recvData, sendData );
00468   }
00469   // non-participating procs should have recvData == origRecvData (i.e., unchanged)
00470   else {
00471     TEST_COMPARE_ARRAYS( recvData, origRecvData );
00472   }
00473   // all procs should have sendData == origSendData
00474   TEST_COMPARE_ARRAYS( sendData, origSendData );
00475 
00476   // All procs fail if any proc fails
00477   int globalSuccess_int = -1;
00478   reduceAll( *comm, Teuchos::REDUCE_SUM, success ? 0 : 1, outArg(globalSuccess_int) );
00479   TEST_EQUALITY_CONST( globalSuccess_int, 0 );
00480 }
00481 
00482 
00483 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( DefaultMpiComm, NonblockingSendReceive, Ordinal, Packet )
00484 {
00485 
00486   using Teuchos::as;
00487   using Teuchos::rcpFromRef;
00488   using Teuchos::outArg;
00489   using Teuchos::isend;
00490   using Teuchos::ireceive;
00491   using Teuchos::wait;
00492   using Teuchos::SerialComm;
00493   using Teuchos::rcp_dynamic_cast;
00494   typedef Teuchos::ScalarTraits<Packet> PT;
00495   typedef typename PT::magnitudeType PacketMag;
00496   typedef Teuchos::ScalarTraits<PacketMag> PMT;
00497 
00498   RCP<const Comm<Ordinal> > comm = getDefaultComm<Ordinal>();
00499   const Ordinal numProcs = size(*comm);
00500   const Ordinal procRank = rank(*comm);
00501 
00502   if (
00503     numProcs == 1
00504     &&
00505     !is_null(rcp_dynamic_cast<const SerialComm<Ordinal> >(comm))
00506     )
00507   {
00508     out << "\nThis is Teuchos::SerialComm which does not yet support isend/ireceive!\n";
00509     return; // Pass!
00510   }
00511 
00512   // Only use randomize on one proc and then broacast
00513   Packet orig_input_data = PT::random();
00514   broadcast( *comm, 0, &orig_input_data );
00515 
00516   const Packet orig_output_data = as<Packet>(-1);
00517 
00518   const Packet input_data = orig_input_data;
00519   Packet output_data = orig_output_data;
00520 
00521   RCP<Teuchos::CommRequest> recvRequest;
00522   RCP<Teuchos::CommRequest> sendRequest;
00523 
00524   if (procRank == 0) {
00525     // Create copy of data to make sure that persisting relationship is
00526     // maintained!
00527     sendRequest = isend<Ordinal, Packet>(
00528       *comm, Teuchos::rcp(new Packet(input_data)), numProcs-1);
00529   }
00530   if (procRank == numProcs-1) {
00531     // We will need to read output_data after wait(...) below
00532     recvRequest = ireceive<Ordinal, Packet>(
00533       *comm, rcpFromRef(output_data), 0);
00534   }
00535 
00536   if (procRank == 0) {
00537     wait( *comm, outArg(sendRequest) );
00538   }
00539   if (procRank == numProcs-1) {
00540     wait( *comm, outArg(recvRequest) );
00541   }
00542   
00543   TEST_EQUALITY_CONST( sendRequest, Teuchos::null );
00544   TEST_EQUALITY_CONST( recvRequest, Teuchos::null );
00545 
00546   if (procRank == numProcs-1) {
00547     TEST_EQUALITY( output_data, input_data );
00548   }
00549   else {
00550     TEST_EQUALITY( output_data, orig_output_data );
00551   }
00552   TEST_EQUALITY( input_data, orig_input_data );
00553 
00554   // All procs fail if any proc fails
00555   int globalSuccess_int = -1;
00556   reduceAll( *comm, Teuchos::REDUCE_SUM, success ? 0 : 1, outArg(globalSuccess_int) );
00557   TEST_EQUALITY_CONST( globalSuccess_int, 0 );
00558 
00559 }
00560 
00561 
00562 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( DefaultMpiComm, NonblockingSendReceiveSet, Ordinal, Packet )
00563 {
00564 
00565   using Teuchos::as;
00566   using Teuchos::rcpFromRef;
00567   using Teuchos::outArg;
00568   using Teuchos::arcp;
00569   using Teuchos::arcpClone;
00570   using Teuchos::ArrayRCP;
00571   using Teuchos::isend;
00572   using Teuchos::ireceive;
00573   using Teuchos::wait;
00574   using Teuchos::broadcast;
00575   using Teuchos::SerialComm;
00576   using Teuchos::rcp_dynamic_cast;
00577   typedef Teuchos::ScalarTraits<Packet> PT;
00578   typedef typename PT::magnitudeType PacketMag;
00579   typedef Teuchos::ScalarTraits<PacketMag> PMT;
00580 
00581   RCP<const Comm<Ordinal> > comm = getDefaultComm<Ordinal>();
00582   const Ordinal numProcs = size(*comm);
00583   const Ordinal procRank = rank(*comm);
00584 
00585   if (
00586     numProcs == 1
00587     &&
00588     !is_null(rcp_dynamic_cast<const SerialComm<Ordinal> >(comm))
00589     )
00590   {
00591     out << "\nThis is Teuchos::SerialComm which does not yet support isend/ireceive!\n";
00592     return; // Pass!
00593   }
00594 
00595   const int numSendRecv = 4;
00596   const int sendLen = 3;
00597 
00598   const ArrayRCP<Packet> origInputData = arcp<Packet>(numSendRecv*sendLen);
00599   const ArrayRCP<Packet> origOutputData = arcp<Packet>(numSendRecv*sendLen);
00600   {
00601     int offset = 0;
00602     for (int i = 0; i < numSendRecv; ++i, offset += sendLen) {
00603       const ArrayRCP<Packet> origInputData_i =
00604         origInputData.persistingView(offset, sendLen); 
00605       const ArrayRCP<Packet> origOutputData_i =
00606         origOutputData.persistingView(offset, sendLen); 
00607       for (int j = 0; j < sendLen; ++j) {
00608         origInputData_i[j] = PT::random();
00609         origOutputData_i[j] = PT::random();
00610       }
00611     }
00612   }
00613   broadcast<Ordinal, Packet>( *comm, 0, origInputData() );
00614 
00615   const ArrayRCP<Packet> inputData = arcpClone<Packet>(origInputData());
00616   const ArrayRCP<Packet> outputData = arcpClone<Packet>(origOutputData());
00617 
00618   Array<RCP<Teuchos::CommRequest> > recvRequests;
00619   Array<RCP<Teuchos::CommRequest> > sendRequests;
00620 
00621   // Send from proc 0 to proc numProcs-1
00622   if (procRank == 0) {
00623     // Create copy of data to make sure that persisting relationship is
00624     // maintained!
00625     int offset = 0;
00626     for (int i = 0; i < numSendRecv; ++i, offset += sendLen) {
00627       sendRequests.push_back(
00628         isend<Ordinal, Packet>(
00629           *comm,
00630           arcpClone<Packet>(inputData(offset, sendLen)),
00631           numProcs-1
00632           )
00633         );
00634     }
00635   }
00636 
00637   // Receive from proc 0 on proc numProcs-1
00638   if (procRank == numProcs-1) {
00639     // We will need to read output_data after wait(...) below
00640     int offset = 0;
00641     for (int i = 0; i < numSendRecv; ++i, offset += sendLen) {
00642       recvRequests.push_back(
00643         ireceive<Ordinal, Packet>(
00644           *comm, outputData.persistingView(offset, sendLen), 0
00645           )
00646         );
00647     }
00648   }
00649 
00650   if (procRank == 0) {
00651     waitAll( *comm, sendRequests );
00652   }
00653   if (procRank == numProcs-1) {
00654     waitAll( *comm, recvRequests );
00655   }
00656 
00657   if (!sendRequests.empty()) {
00658     for (int i = 0; i < numSendRecv; ++i) {
00659       TEST_EQUALITY_CONST( sendRequests[i], Teuchos::null );
00660     }
00661   }
00662 
00663   if (!recvRequests.empty()) {
00664     for (int i = 0; i < numSendRecv; ++i) {
00665       TEST_EQUALITY_CONST( recvRequests[i], Teuchos::null );
00666     }
00667   }
00668   // ToDo: Write a test macro for this in one shot!
00669 
00670   if (procRank == numProcs-1) {
00671     TEST_COMPARE_ARRAYS( outputData, inputData );
00672   }
00673   else {
00674     TEST_COMPARE_ARRAYS( outputData, origOutputData );
00675   }
00676   TEST_COMPARE_ARRAYS( inputData, origInputData );
00677 
00678   // All procs fail if any proc fails
00679   int globalSuccess_int = -1;
00680   reduceAll( *comm, Teuchos::REDUCE_SUM, success ? 0 : 1, outArg(globalSuccess_int) );
00681   TEST_EQUALITY_CONST( globalSuccess_int, 0 );
00682 
00683 }
00684 
00685 
00686 //
00687 // Instantiations
00688 //
00689 
00690 
00691 #ifdef HAVE_TEUCHOS_COMPLEX
00692 #  define UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(TEST_GROUP, TEST_NAME, ORDINAL)\
00693      typedef std::complex<float> ComplexFloat; \
00694      TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT(TEST_GROUP, TEST_NAME, ORDINAL, ComplexFloat)
00695 #  define UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(TEST_GROUP, TEST_NAME, ORDINAL)\
00696      typedef std::complex<double> ComplexDouble; \
00697      TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT(TEST_GROUP, TEST_NAME, ORDINAL, ComplexDouble)
00698 #else
00699 #  define UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(TEST_GROUP, TEST_NAME, ORDINAL)
00700 #  define UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(TEST_GROUP, TEST_NAME, ORDINAL)
00701 #endif
00702 
00703 
00704 #define UNIT_TEST_GROUP_ORDINAL_PACKET( ORDINAL, PACKET ) \
00705   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, reduceAllAndScatter_1, ORDINAL, PACKET ) \
00706   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, reduceAllAndScatter_2, ORDINAL, PACKET ) \
00707   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, NonblockingSendReceive, ORDINAL, PACKET ) \
00708   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, NonblockingSendReceiveSet, ORDINAL, PACKET ) \
00709   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, ReadySend1, ORDINAL, PACKET ) \
00710   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, ReadySend, ORDINAL, PACKET )
00711 
00712 #ifdef HAVE_TEUCHOS_QD
00713 #  define UNIT_TEST_GROUP_ORDINAL_QD(ORDINAL) \
00714      UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, dd_real) \
00715      UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, qd_real)
00716 #else
00717 #  define UNIT_TEST_GROUP_ORDINAL_QD(ORDINAL)
00718 #endif
00719 
00720 #define UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS( ORDINAL, PAIROFPACKETS ) \
00721   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, NonblockingSendReceive, ORDINAL, PAIROFPACKETS ) \
00722   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, NonblockingSendReceiveSet, ORDINAL, PAIROFPACKETS ) \
00723   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, ReadySend1, ORDINAL, PAIROFPACKETS ) \
00724   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, ReadySend, ORDINAL, PAIROFPACKETS )
00725 
00726 
00727 typedef std::pair<short, short> PairOfShorts;
00728 typedef std::pair<int,int> PairOfInts;
00729 typedef std::pair<float,float> PairOfFloats;
00730 typedef std::pair<double,double> PairOfDoubles;
00731 
00732 
00733 // Uncomment this for really fast development cycles but make sure to comment
00734 // it back again before checking in so that we can test all the types.
00735 // #define FAST_DEVELOPMENT_UNIT_TEST_BUILD
00736 
00737 
00738 #ifdef FAST_DEVELOPMENT_UNIT_TEST_BUILD
00739 
00740 #  define UNIT_TEST_GROUP_ORDINAL( ORDINAL ) \
00741     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, double) \
00742     UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfDoubles) \
00743 
00744   UNIT_TEST_GROUP_ORDINAL(int)
00745 
00746 #else // FAST_DEVELOPMENT_UNIT_TEST_BUILD
00747 
00748 #  define UNIT_TEST_GROUP_ORDINAL( ORDINAL ) \
00749     TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DefaultMpiComm, basic, ORDINAL ) \
00750     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, short) \
00751     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, int) \
00752     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, float) \
00753     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, double) \
00754     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, reduceAllAndScatter_1, ORDINAL) \
00755     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, reduceAllAndScatter_2, ORDINAL) \
00756     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, NonblockingSendReceive, ORDINAL) \
00757     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, ReadySend1, ORDINAL) \
00758     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, ReadySend, ORDINAL) \
00759     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, reduceAllAndScatter_1, ORDINAL) \
00760     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, reduceAllAndScatter_2, ORDINAL) \
00761     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, NonblockingSendReceive, ORDINAL) \
00762     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, ReadySend1, ORDINAL) \
00763     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, ReadySend, ORDINAL)
00764 
00765 #  define UNIT_TEST_GROUP_ORDINAL_WITH_PAIRS_AND_QD( ORDINAL ) \
00766     TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DefaultMpiComm, basic, ORDINAL ) \
00767     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, short)      \
00768     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, int) \
00769     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, float) \
00770     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, double) \
00771     UNIT_TEST_GROUP_ORDINAL_QD(ORDINAL) \
00772     UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfShorts) \
00773     UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfInts) \
00774     UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfFloats) \
00775     UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfDoubles) \
00776     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, reduceAllAndScatter_1, ORDINAL) \
00777     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, reduceAllAndScatter_2, ORDINAL) \
00778     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, NonblockingSendReceive, ORDINAL) \
00779     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, ReadySend1, ORDINAL) \
00780     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, ReadySend, ORDINAL) \
00781     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, reduceAllAndScatter_1, ORDINAL) \
00782     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, reduceAllAndScatter_2, ORDINAL) \
00783     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, NonblockingSendReceive, ORDINAL) \
00784     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, ReadySend1, ORDINAL) \
00785     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, ReadySend, ORDINAL)
00786 
00787   typedef short int ShortInt;
00788   UNIT_TEST_GROUP_ORDINAL(ShortInt)
00789   UNIT_TEST_GROUP_ORDINAL_WITH_PAIRS_AND_QD(int)
00790   typedef long int LongInt;
00791   UNIT_TEST_GROUP_ORDINAL(LongInt) // can't do QD with LongInt, one of the tests complains
00792   
00793 #  ifdef HAVE_TEUCHOS_LONG_LONG_INT
00794   typedef long long int LongLongInt;
00795   UNIT_TEST_GROUP_ORDINAL(LongLongInt)
00796 #  endif
00797 
00798 #endif // FAST_DEVELOPMENT_UNIT_TEST_BUILD
00799 
00800 
00801 } // namespace
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines