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; // unused
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; // unused
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; // unused
00279   //typedef Teuchos::ScalarTraits<PacketMag> PMT; // unused
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<Ordinal> > 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; // unused
00374   //typedef Teuchos::ScalarTraits<PacketMag> PMT; // unused
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<Ordinal> > 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   using Teuchos::as;
00486   using Teuchos::rcpFromRef;
00487   using Teuchos::outArg;
00488   using Teuchos::isend;
00489   using Teuchos::ireceive;
00490   using Teuchos::wait;
00491   using Teuchos::SerialComm;
00492   using Teuchos::rcp_dynamic_cast;
00493   using std::endl;
00494   typedef Teuchos::ScalarTraits<Packet> PT;
00495   //typedef typename PT::magnitudeType PacketMag; // unused
00496   //typedef Teuchos::ScalarTraits<PacketMag> PMT; // unused
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<Ordinal> > recvRequest;
00522   RCP<Teuchos::CommRequest<Ordinal> > sendRequest;
00523 
00524   out << "Exchanging messages" << endl;
00525 
00526   if (procRank == 0) {
00527     // Create copy of data to make sure that persisting relationship is
00528     // maintained!
00529     sendRequest = isend<Ordinal, Packet>(
00530       *comm, Teuchos::rcp(new Packet(input_data)), numProcs-1);
00531   }
00532   if (procRank == numProcs-1) {
00533     // We will need to read output_data after wait(...) below
00534     recvRequest = ireceive<Ordinal, Packet>(
00535       *comm, rcpFromRef(output_data), 0);
00536   }
00537 
00538   out << "Waiting for messages" << endl;
00539 
00540   if (procRank == 0) {
00541     wait( *comm, outArg(sendRequest) );
00542   }
00543   if (procRank == numProcs-1) {
00544     wait( *comm, outArg(recvRequest) );
00545   }
00546 
00547   TEST_EQUALITY_CONST( sendRequest, Teuchos::null );
00548   TEST_EQUALITY_CONST( recvRequest, Teuchos::null );
00549 
00550   out << "Testing message correctness" << endl;
00551 
00552   if (procRank == numProcs-1) {
00553     TEST_EQUALITY( output_data, input_data );
00554   }
00555   else {
00556     TEST_EQUALITY( output_data, orig_output_data );
00557   }
00558   TEST_EQUALITY( input_data, orig_input_data );
00559 
00560   // All procs fail if any proc fails
00561   int globalSuccess_int = -1;
00562   reduceAll( *comm, Teuchos::REDUCE_SUM, success ? 0 : 1, outArg(globalSuccess_int) );
00563   TEST_EQUALITY_CONST( globalSuccess_int, 0 );
00564 }
00565 
00566 
00567 TEUCHOS_UNIT_TEST_TEMPLATE_2_DECL( DefaultMpiComm, NonblockingSendReceiveSet, Ordinal, Packet )
00568 {
00569   using Teuchos::as;
00570   using Teuchos::rcpFromRef;
00571   using Teuchos::outArg;
00572   using Teuchos::arcp;
00573   using Teuchos::arcpClone;
00574   using Teuchos::ArrayRCP;
00575   using Teuchos::isend;
00576   using Teuchos::ireceive;
00577   using Teuchos::wait;
00578   using Teuchos::broadcast;
00579   using Teuchos::SerialComm;
00580   using Teuchos::rcp_dynamic_cast;
00581   using std::cerr;
00582   using std::endl;
00583   typedef Teuchos::ScalarTraits<Packet> PT;
00584   //typedef typename PT::magnitudeType PacketMag; // unused
00585   //typedef Teuchos::ScalarTraits<PacketMag> PMT; // unused
00586 
00587   RCP<const Comm<Ordinal> > comm = getDefaultComm<Ordinal>();
00588   const Ordinal numProcs = size(*comm);
00589   const Ordinal procRank = rank(*comm);
00590 
00591   if (
00592     numProcs == 1
00593     &&
00594     !is_null(rcp_dynamic_cast<const SerialComm<Ordinal> >(comm))
00595     )
00596   {
00597     out << "\nThis is Teuchos::SerialComm which does not yet support isend/ireceive!\n";
00598     return; // Pass!
00599   }
00600 
00601   const int numSendRecv = 4;
00602   const int sendLen = 3;
00603 
00604   cerr << "Creating data" << endl;
00605 
00606   const ArrayRCP<Packet> origInputData = arcp<Packet>(numSendRecv*sendLen);
00607   const ArrayRCP<Packet> origOutputData = arcp<Packet>(numSendRecv*sendLen);
00608   {
00609     int offset = 0;
00610     for (int i = 0; i < numSendRecv; ++i, offset += sendLen) {
00611       const ArrayRCP<Packet> origInputData_i =
00612         origInputData.persistingView(offset, sendLen);
00613       const ArrayRCP<Packet> origOutputData_i =
00614         origOutputData.persistingView(offset, sendLen);
00615       for (int j = 0; j < sendLen; ++j) {
00616         origInputData_i[j] = PT::random();
00617         origOutputData_i[j] = PT::random();
00618       }
00619     }
00620   }
00621   cerr << "Broadcasting data" << endl;
00622   broadcast<Ordinal, Packet>( *comm, 0, origInputData() );
00623 
00624   const ArrayRCP<Packet> inputData = arcpClone<Packet>(origInputData());
00625   const ArrayRCP<Packet> outputData = arcpClone<Packet>(origOutputData());
00626 
00627   Array<RCP<Teuchos::CommRequest<Ordinal> > > recvRequests;
00628   Array<RCP<Teuchos::CommRequest<Ordinal> > > sendRequests;
00629 
00630   cerr << "Exchanging data" << endl;
00631 
00632   // Send from proc 0 to proc numProcs-1
00633   if (procRank == 0) {
00634     // Create copy of data to make sure that persisting relationship is
00635     // maintained!
00636     int offset = 0;
00637     for (int i = 0; i < numSendRecv; ++i, offset += sendLen) {
00638       sendRequests.push_back(
00639         isend<Ordinal, Packet>(
00640           *comm,
00641           arcpClone<Packet>(inputData(offset, sendLen)),
00642           numProcs-1
00643           )
00644         );
00645     }
00646   }
00647 
00648   // Receive from proc 0 on proc numProcs-1
00649   if (procRank == numProcs-1) {
00650     // We will need to read output_data after wait(...) below
00651     int offset = 0;
00652     for (int i = 0; i < numSendRecv; ++i, offset += sendLen) {
00653       recvRequests.push_back(
00654         ireceive<Ordinal, Packet>(
00655           *comm, outputData.persistingView(offset, sendLen), 0
00656           )
00657         );
00658     }
00659   }
00660 
00661   cerr << "Waiting on messages" << endl;
00662 
00663   if (procRank == 0) {
00664     waitAll( *comm, sendRequests() );
00665   }
00666   if (procRank == numProcs-1) {
00667     waitAll( *comm, recvRequests() );
00668   }
00669 
00670   cerr << "Testing received data" << endl;
00671 
00672   if (!sendRequests.empty()) {
00673     for (int i = 0; i < numSendRecv; ++i) {
00674       TEST_EQUALITY_CONST( sendRequests[i], Teuchos::null );
00675     }
00676   }
00677 
00678   if (!recvRequests.empty()) {
00679     for (int i = 0; i < numSendRecv; ++i) {
00680       TEST_EQUALITY_CONST( recvRequests[i], Teuchos::null );
00681     }
00682   }
00683   // ToDo: Write a test macro for this in one shot!
00684 
00685   if (procRank == numProcs-1) {
00686     TEST_COMPARE_ARRAYS( outputData, inputData );
00687   }
00688   else {
00689     TEST_COMPARE_ARRAYS( outputData, origOutputData );
00690   }
00691   TEST_COMPARE_ARRAYS( inputData, origInputData );
00692 
00693   // All procs fail if any proc fails
00694   int globalSuccess_int = -1;
00695   reduceAll( *comm, Teuchos::REDUCE_SUM, success ? 0 : 1, outArg(globalSuccess_int) );
00696   TEST_EQUALITY_CONST( globalSuccess_int, 0 );
00697 
00698 }
00699 
00700 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(DefaultMpiComm, duplicate, Ordinal)
00701 {
00702   RCP< const Comm<Ordinal> > comm = getDefaultComm<Ordinal>();
00703   int initialRank = comm->getRank();
00704   int initialSize = comm->getSize();
00705 
00706   RCP< const Comm<Ordinal> > newComm = comm->duplicate();
00707   TEST_EQUALITY(newComm->getSize(), initialSize);
00708   TEST_EQUALITY(newComm->getRank(), initialRank);
00709 
00710   // TODO Make sure the communication space is distinct.
00711 }
00712 
00713 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(DefaultMpiComm, split, Ordinal) {
00714   RCP< const Comm<Ordinal> > comm = getDefaultComm<Ordinal>();
00715   int initialRank = comm->getRank();
00716   int initialSize = comm->getSize();
00717 
00718   // Partition this communicator into two: one with the odd ranks and one with
00719   // the even ones. Pass a common key for everyone to maintain the same
00720   // ordering as in the initial communicator.
00721   RCP< const Comm<Ordinal> > newComm = comm->split(initialRank % 2, 0);
00722 
00723   // Check the size of the new communicator and my rank within it.
00724   int halfSize = initialSize / 2;
00725   int newSize = newComm->getSize();
00726   int newRank = newComm->getRank();
00727   if (initialSize % 2 == 0) {
00728     TEST_EQUALITY(newSize, halfSize);
00729   }
00730   else {
00731     TEST_EQUALITY(newSize, initialRank % 2 == 0 ? halfSize + 1 : halfSize);
00732   }
00733   TEST_EQUALITY(newRank, initialRank / 2);
00734 
00735   // Negative color values get a null communicator.
00736   RCP< const Comm<Ordinal> > shouldBeNull = comm->split(-1, 0);
00737   TEST_ASSERT(shouldBeNull.is_null());
00738 }
00739 
00740 
00741 namespace {
00742 
00743 
00744 template<typename ValueType>
00745 class MonotoneSequence
00746 {
00747   ValueType currentValue_;
00748 public:
00749   typedef ValueType value_type;
00750 
00751   MonotoneSequence(const value_type& initialValue) : currentValue_(initialValue)
00752   {}
00753 
00754   value_type operator()()
00755   {
00756     return currentValue_++;
00757   }
00758 };
00759 
00760 
00761 } // namepsace
00762 
00763 
00764 TEUCHOS_UNIT_TEST_TEMPLATE_1_DECL(DefaultMpiComm, createSubcommunicator, Ordinal) {
00765   RCP< const Comm<Ordinal> > comm = getDefaultComm<Ordinal>();
00766   int initialRank = comm->getRank();
00767   int initialSize = comm->getSize();
00768 
00769   // Create a new communicator that reverses all of the ranks.
00770   std::vector< int > ranks(initialSize);
00771   std::generate(ranks.begin(), ranks.end(), MonotoneSequence<int>(0));
00772   std::reverse(ranks.begin(), ranks.end());
00773   RCP< const Comm<Ordinal> > newComm = comm->createSubcommunicator(ranks);
00774   TEST_EQUALITY(newComm->getSize(), initialSize);
00775   int expectedNewRank = initialSize - initialRank - 1;
00776   TEST_EQUALITY(newComm->getRank(), expectedNewRank);
00777 
00778   // Processes that aren't in the group get a null communicator.
00779   std::vector<int> rank0Only(1, 0);
00780   RCP< const Comm<Ordinal> > rank0Comm = comm->createSubcommunicator(rank0Only);
00781   // Original rank 0 should be valid, all others should be null.
00782   if (initialRank == 0) {
00783     TEST_ASSERT(rank0Comm.is_valid_ptr());
00784   } else {
00785     TEST_ASSERT(rank0Comm.is_null());
00786   }
00787 }
00788 
00789 
00790 #ifdef HAVE_TEUCHOS_MPI
00791 
00792 
00793 TEUCHOS_UNIT_TEST(DefaultMpiComm, TagConsistency )
00794 {
00795   using Teuchos::tuple; using Teuchos::inoutArg;
00796 
00797   const Teuchos::RCP<const Teuchos::Comm<int> > defaultComm =
00798     Teuchos::DefaultComm<int>::getComm();
00799   const int comm_size = defaultComm->getSize();
00800   const int comm_rank = defaultComm->getRank();
00801 
00802   // Must have at least two processes to run this test!
00803   if (comm_size < 2) {
00804     return;
00805   }
00806 
00807   // Create a subcomm that contains just two processes
00808   const Teuchos::RCP<const Teuchos::Comm<int> > masterComm =
00809     defaultComm->createSubcommunicator(tuple<int>(0, 1)());
00810 
00811   if (comm_rank <= 1) {
00812 
00813     const int masterComm_size = masterComm->getSize();
00814     (void) masterComm_size; // Forestall "unused variable" warning.
00815     const int masterComm_rank = masterComm->getRank();
00816 
00817     // Split the main communicator into 2 overlapping groups
00818     Teuchos::RCP<const Teuchos::Comm<int> > comm_1 =
00819       masterComm->createSubcommunicator(tuple<int>(0, 1)());
00820     Teuchos::RCP<const Teuchos::Comm<int> > comm_2 =
00821       masterComm->createSubcommunicator(tuple<int>(0)());
00822 
00823     // Create another communicator.
00824     Teuchos::RCP<const Teuchos::Comm<int> > comm_3 =
00825       masterComm->createSubcommunicator(tuple<int>(0, 1)());
00826 
00827     // Get my mpi tag for comm 3.
00828     int my_tag = Teuchos::rcp_dynamic_cast<const Teuchos::MpiComm<int> >(
00829       comm_3 )->getTag();
00830 
00831     // Collect the tags for comm 3.
00832     int tag1 = 0;
00833     if (masterComm_rank == 0) { tag1 = my_tag; }
00834     masterComm->barrier();
00835     Teuchos::broadcast( *masterComm, 0, inoutArg(tag1) );
00836 
00837     int tag2 = 0;
00838     if (masterComm_rank == 1) { tag2 = my_tag; }
00839     masterComm->barrier();
00840     Teuchos::broadcast( *masterComm, 1, inoutArg(tag2) );
00841 
00842     // This currently fails.
00843     TEST_EQUALITY( tag1, tag2 );
00844 
00845   }
00846 
00847 }
00848 
00849 
00850 #endif // HAVE_TEUCHOS_MPI
00851 
00852 
00853 //
00854 // Instantiations
00855 //
00856 
00857 
00858 #ifdef HAVE_TEUCHOS_COMPLEX
00859 #  define UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(TEST_GROUP, TEST_NAME, ORDINAL)\
00860      typedef std::complex<float> ComplexFloat; \
00861      TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT(TEST_GROUP, TEST_NAME, ORDINAL, ComplexFloat)
00862 #  define UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(TEST_GROUP, TEST_NAME, ORDINAL)\
00863      typedef std::complex<double> ComplexDouble; \
00864      TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT(TEST_GROUP, TEST_NAME, ORDINAL, ComplexDouble)
00865 #else
00866 #  define UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(TEST_GROUP, TEST_NAME, ORDINAL)
00867 #  define UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(TEST_GROUP, TEST_NAME, ORDINAL)
00868 #endif
00869 
00870 
00871 #define UNIT_TEST_GROUP_ORDINAL_PACKET( ORDINAL, PACKET ) \
00872   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, reduceAllAndScatter_1, ORDINAL, PACKET ) \
00873   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, reduceAllAndScatter_2, ORDINAL, PACKET ) \
00874   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, NonblockingSendReceive, ORDINAL, PACKET ) \
00875   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, NonblockingSendReceiveSet, ORDINAL, PACKET ) \
00876   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, ReadySend1, ORDINAL, PACKET ) \
00877   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, ReadySend, ORDINAL, PACKET )
00878 
00879 #ifdef HAVE_TEUCHOS_QD
00880 #  define UNIT_TEST_GROUP_ORDINAL_QD(ORDINAL) \
00881      UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, dd_real) \
00882      UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, qd_real)
00883 #else
00884 #  define UNIT_TEST_GROUP_ORDINAL_QD(ORDINAL)
00885 #endif
00886 
00887 #define UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS( ORDINAL, PAIROFPACKETS ) \
00888   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, NonblockingSendReceive, ORDINAL, PAIROFPACKETS ) \
00889   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, NonblockingSendReceiveSet, ORDINAL, PAIROFPACKETS ) \
00890   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, ReadySend1, ORDINAL, PAIROFPACKETS ) \
00891   TEUCHOS_UNIT_TEST_TEMPLATE_2_INSTANT( DefaultMpiComm, ReadySend, ORDINAL, PAIROFPACKETS )
00892 
00893 #define UNIT_TEST_GROUP_ORDINAL_SUBCOMMUNICATORS( ORDINAL ) \
00894   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DefaultMpiComm, duplicate, ORDINAL ) \
00895   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DefaultMpiComm, split, ORDINAL ) \
00896   TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DefaultMpiComm, createSubcommunicator, ORDINAL )
00897 
00898 
00899 typedef std::pair<short, short> PairOfShorts;
00900 typedef std::pair<int,int> PairOfInts;
00901 typedef std::pair<float,float> PairOfFloats;
00902 typedef std::pair<double,double> PairOfDoubles;
00903 
00904 
00905 // Uncomment this for really fast development cycles but make sure to comment
00906 // it back again before checking in so that we can test all the types.
00907 // #define FAST_DEVELOPMENT_UNIT_TEST_BUILD
00908 
00909 
00910 #ifdef FAST_DEVELOPMENT_UNIT_TEST_BUILD
00911 
00912 #  define UNIT_TEST_GROUP_ORDINAL( ORDINAL ) \
00913     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, double) \
00914     UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfDoubles) \
00915 
00916   UNIT_TEST_GROUP_ORDINAL(int)
00917 
00918 #else // FAST_DEVELOPMENT_UNIT_TEST_BUILD
00919 
00920 #  define UNIT_TEST_GROUP_ORDINAL( ORDINAL ) \
00921     TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DefaultMpiComm, basic, ORDINAL ) \
00922     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, short) \
00923     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, int) \
00924     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, float) \
00925     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, double) \
00926     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, reduceAllAndScatter_1, ORDINAL) \
00927     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, reduceAllAndScatter_2, ORDINAL) \
00928     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, NonblockingSendReceive, ORDINAL) \
00929     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, ReadySend1, ORDINAL) \
00930     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, ReadySend, ORDINAL) \
00931     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, reduceAllAndScatter_1, ORDINAL) \
00932     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, reduceAllAndScatter_2, ORDINAL) \
00933     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, NonblockingSendReceive, ORDINAL) \
00934     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, ReadySend1, ORDINAL) \
00935     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, ReadySend, ORDINAL) \
00936     UNIT_TEST_GROUP_ORDINAL_SUBCOMMUNICATORS(ORDINAL)
00937 
00938 #  define UNIT_TEST_GROUP_ORDINAL_WITH_PAIRS_AND_QD( ORDINAL ) \
00939     TEUCHOS_UNIT_TEST_TEMPLATE_1_INSTANT( DefaultMpiComm, basic, ORDINAL ) \
00940     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, short)                      \
00941     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, int) \
00942     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, float) \
00943     UNIT_TEST_GROUP_ORDINAL_PACKET(ORDINAL, double) \
00944     UNIT_TEST_GROUP_ORDINAL_QD(ORDINAL) \
00945     UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfShorts) \
00946     UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfInts) \
00947     UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfFloats) \
00948     UNIT_TEST_GROUP_ORDINAL_PAIROFPACKETS(ORDINAL, PairOfDoubles) \
00949     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, reduceAllAndScatter_1, ORDINAL) \
00950     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, reduceAllAndScatter_2, ORDINAL) \
00951     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, NonblockingSendReceive, ORDINAL) \
00952     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, ReadySend1, ORDINAL) \
00953     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_FLOAT(DefaultMpiComm, ReadySend, ORDINAL) \
00954     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, reduceAllAndScatter_1, ORDINAL) \
00955     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, reduceAllAndScatter_2, ORDINAL) \
00956     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, NonblockingSendReceive, ORDINAL) \
00957     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, ReadySend1, ORDINAL) \
00958     UNIT_TEST_TEMPLATE_2_INSTANT_COMPLEX_DOUBLE(DefaultMpiComm, ReadySend, ORDINAL)
00959 
00960   typedef short int ShortInt;
00961   UNIT_TEST_GROUP_ORDINAL(ShortInt)
00962   UNIT_TEST_GROUP_ORDINAL_WITH_PAIRS_AND_QD(int)
00963   typedef long int LongInt;
00964   UNIT_TEST_GROUP_ORDINAL(LongInt) // can't do QD with LongInt, one of the tests complains
00965 
00966 #  ifdef HAVE_TEUCHOS_LONG_LONG_INT
00967   typedef long long int LongLongInt;
00968   UNIT_TEST_GROUP_ORDINAL(LongLongInt)
00969 #  endif
00970 
00971 #endif // FAST_DEVELOPMENT_UNIT_TEST_BUILD
00972 
00973 
00974 } // namespace
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines