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 ignored 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 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(DefaultMpiComm, duplicate, Ordinal)
00686 {
00687   RCP< const Comm<Ordinal> > comm = getDefaultComm<Ordinal>();
00688   int initialRank = comm->getRank();
00689   int initialSize = comm->getSize();
00690 
00691   RCP< const Comm<Ordinal> > newComm = comm->duplicate();
00692   TEST_EQUALITY(newComm->getSize(), initialSize);
00693   TEST_EQUALITY(newComm->getRank(), initialRank);
00694 
00695   // TODO Make sure the communication space is distinct.
00696 }
00697 
00698 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(DefaultMpiComm, split, Ordinal) {
00699   RCP< const Comm<Ordinal> > comm = getDefaultComm<Ordinal>();
00700   int initialRank = comm->getRank();
00701   int initialSize = comm->getSize();
00702 
00703   // Partition this communicator into two: one with the odd ranks and one with
00704   // the even ones. Pass a common key for everyone to maintain the same
00705   // ordering as in the initial communicator.
00706   RCP< const Comm<Ordinal> > newComm = comm->split(initialRank % 2, 0);
00707 
00708   // Check the size of the new communicator and my rank within it.
00709   int halfSize = initialSize / 2;
00710   int newSize = newComm->getSize();
00711   int newRank = newComm->getRank();
00712   if (initialSize % 2 == 0) {
00713     TEST_EQUALITY(newSize, halfSize);
00714   }
00715   else {
00716     TEST_EQUALITY(newSize, initialRank % 2 == 0 ? halfSize + 1 : halfSize);
00717   }
00718   TEST_EQUALITY(newRank, initialRank / 2);
00719 
00720   // Negative color values get a null communicator.
00721   RCP< const Comm<Ordinal> > shouldBeNull = comm->split(-1, 0);
00722   TEST_ASSERT(shouldBeNull.is_null());
00723 }
00724 
00725 namespace {
00726 
00727 template<typename ValueType>
00728 class MonotoneSequence
00729 {
00730   ValueType currentValue_;
00731 public:
00732   typedef ValueType value_type;
00733 
00734   MonotoneSequence(const value_type& initialValue) : currentValue_(initialValue)
00735   {}
00736 
00737   value_type operator()()
00738   {
00739     return currentValue_++;
00740   }
00741 };
00742 
00743 } // namepsace
00744 
00745 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(DefaultMpiComm, createSubcommunicator, Ordinal) {
00746   RCP< const Comm<Ordinal> > comm = getDefaultComm<Ordinal>();
00747   int initialRank = comm->getRank();
00748   int initialSize = comm->getSize();
00749 
00750   // Create a new communicator that reverses all of the ranks.
00751   std::vector< int > ranks(initialSize);
00752   std::generate(ranks.begin(), ranks.end(), MonotoneSequence<int>(0));
00753   std::reverse(ranks.begin(), ranks.end());
00754   RCP< const Comm<Ordinal> > newComm = comm->createSubcommunicator(ranks);
00755   TEST_EQUALITY(newComm->getSize(), initialSize);
00756   int expectedNewRank = initialSize - initialRank - 1;
00757   TEST_EQUALITY(newComm->getRank(), expectedNewRank);
00758 
00759   // Processes that aren't in the group get a null communicator.
00760   std::vector<int> rank0Only(1, 0);
00761   RCP< const Comm<Ordinal> > rank0Comm = comm->createSubcommunicator(rank0Only);
00762   // Original rank 0 should be valid, all others should be null.
00763   if (initialRank == 0) {
00764     TEST_ASSERT(rank0Comm.is_valid_ptr());
00765   } else {
00766     TEST_ASSERT(rank0Comm.is_null());
00767   }
00768 }
00769 
00770 //
00771 // Instantiations
00772 //
00773 
00774 
00775 #ifdef HAVE_TEUCHOS_COMPLEX
00776 #  define UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(TEST_GROUP, TEST_NAME, ORDINAL)\
00777      typedef std::complex<float> ComplexFloat; \
00778      TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT(TEST_GROUP, TEST_NAME, ORDINAL, ComplexFloat)
00779 #  define UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(TEST_GROUP, TEST_NAME, ORDINAL)\
00780      typedef std::complex<double> ComplexDouble; \
00781      TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT(TEST_GROUP, TEST_NAME, ORDINAL, ComplexDouble)
00782 #else
00783 #  define UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(TEST_GROUP, TEST_NAME, ORDINAL)
00784 #  define UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(TEST_GROUP, TEST_NAME, ORDINAL)
00785 #endif
00786 
00787 
00788 #define UNIT_TEST_GROUP_ORDINAL_PACKET( ORDINAL, PACKET ) \
00789   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, reduceAllAndScatter_1, ORDINAL, PACKET ) \
00790   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, reduceAllAndScatter_2, ORDINAL, PACKET ) \
00791   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, NonblockingSendReceive, ORDINAL, PACKET ) \
00792   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, NonblockingSendReceiveSet, ORDINAL, PACKET ) \
00793   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, ReadySend1, ORDINAL, PACKET ) \
00794   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, ReadySend, ORDINAL, PACKET )
00795 
00796 #ifdef HAVE_TEUCHOS_QD
00797 #  define UNIT_TEST_GROUP_ORDINAL_QD(ORDINAL) \
00798      UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, dd_real) \
00799      UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, qd_real)
00800 #else
00801 #  define UNIT_TEST_GROUP_ORDINAL_QD(ORDINAL)
00802 #endif
00803 
00804 #define UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS( ORDINAL, PAIROFPACKETS ) \
00805   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, NonblockingSendReceive, ORDINAL, PAIROFPACKETS ) \
00806   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, NonblockingSendReceiveSet, ORDINAL, PAIROFPACKETS ) \
00807   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, ReadySend1, ORDINAL, PAIROFPACKETS ) \
00808   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, ReadySend, ORDINAL, PAIROFPACKETS )
00809 
00810 #define UNIT_TEST_GROUP_ORDINAL_SUBCOMMUNICATORS( ORDINAL ) \
00811   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DefaultMpiComm, duplicate, ORDINAL ) \
00812   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DefaultMpiComm, split, ORDINAL ) \
00813   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DefaultMpiComm, createSubcommunicator, ORDINAL )
00814 
00815 
00816 typedef std::pair<short, short> PairOfShorts;
00817 typedef std::pair<int,int> PairOfInts;
00818 typedef std::pair<float,float> PairOfFloats;
00819 typedef std::pair<double,double> PairOfDoubles;
00820 
00821 
00822 // Uncomment this for really fast development cycles but make sure to comment
00823 // it back again before checking in so that we can test all the types.
00824 // #define FAST_DEVELOPMENT_UNIT_TEST_BUILD
00825 
00826 
00827 #ifdef FAST_DEVELOPMENT_UNIT_TEST_BUILD
00828 
00829 #  define UNIT_TEST_GROUP_ORDINAL( ORDINAL ) \
00830     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, double) \
00831     UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfDoubles) \
00832 
00833   UNIT_TEST_GROUP_ORDINAL(int)
00834 
00835 #else // FAST_DEVELOPMENT_UNIT_TEST_BUILD
00836 
00837 #  define UNIT_TEST_GROUP_ORDINAL( ORDINAL ) \
00838     TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DefaultMpiComm, basic, ORDINAL ) \
00839     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, short) \
00840     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, int) \
00841     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, float) \
00842     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, double) \
00843     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, reduceAllAndScatter_1, ORDINAL) \
00844     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, reduceAllAndScatter_2, ORDINAL) \
00845     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, NonblockingSendReceive, ORDINAL) \
00846     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, ReadySend1, ORDINAL) \
00847     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, ReadySend, ORDINAL) \
00848     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, reduceAllAndScatter_1, ORDINAL) \
00849     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, reduceAllAndScatter_2, ORDINAL) \
00850     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, NonblockingSendReceive, ORDINAL) \
00851     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, ReadySend1, ORDINAL) \
00852     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, ReadySend, ORDINAL) \
00853     UNIT_TEST_GROUP_ORDINAL_SUBCOMMUNICATORS(ORDINAL)
00854 
00855 #  define UNIT_TEST_GROUP_ORDINAL_WITH_PAIRS_AND_QD( ORDINAL ) \
00856     TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DefaultMpiComm, basic, ORDINAL ) \
00857     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, short)      \
00858     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, int) \
00859     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, float) \
00860     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, double) \
00861     UNIT_TEST_GROUP_ORDINAL_QD(ORDINAL) \
00862     UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfShorts) \
00863     UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfInts) \
00864     UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfFloats) \
00865     UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfDoubles) \
00866     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, reduceAllAndScatter_1, ORDINAL) \
00867     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, reduceAllAndScatter_2, ORDINAL) \
00868     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, NonblockingSendReceive, ORDINAL) \
00869     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, ReadySend1, ORDINAL) \
00870     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, ReadySend, ORDINAL) \
00871     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, reduceAllAndScatter_1, ORDINAL) \
00872     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, reduceAllAndScatter_2, ORDINAL) \
00873     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, NonblockingSendReceive, ORDINAL) \
00874     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, ReadySend1, ORDINAL) \
00875     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, ReadySend, ORDINAL)
00876 
00877   typedef short int ShortInt;
00878   UNIT_TEST_GROUP_ORDINAL(ShortInt)
00879   UNIT_TEST_GROUP_ORDINAL_WITH_PAIRS_AND_QD(int)
00880   typedef long int LongInt;
00881   UNIT_TEST_GROUP_ORDINAL(LongInt) // can't do QD with LongInt, one of the tests complains
00882   
00883 #  ifdef HAVE_TEUCHOS_LONG_LONG_INT
00884   typedef long long int LongLongInt;
00885   UNIT_TEST_GROUP_ORDINAL(LongLongInt)
00886 #  endif
00887 
00888 #endif // FAST_DEVELOPMENT_UNIT_TEST_BUILD
00889 
00890 
00891 } // namespace
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines