|
Teuchos Package Browser (Single Doxygen Collection)
Version of the Day
|
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 / (double)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 / (double)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
1.7.6.1