Teuchos - Trilinos Tools Package  Version of the Day
Teuchos_CommHelpers.cpp
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Teuchos: Common Tools Package
5 // Copyright (2004) Sandia Corporation
6 //
7 // Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8 // license for use of this work by or on behalf of the U.S. Government.
9 //
10 // Redistribution and use in source and binary forms, with or without
11 // modification, are permitted provided that the following conditions are
12 // met:
13 //
14 // 1. Redistributions of source code must retain the above copyright
15 // notice, this list of conditions and the following disclaimer.
16 //
17 // 2. Redistributions in binary form must reproduce the above copyright
18 // notice, this list of conditions and the following disclaimer in the
19 // documentation and/or other materials provided with the distribution.
20 //
21 // 3. Neither the name of the Corporation nor the names of the
22 // contributors may be used to endorse or promote products derived from
23 // this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38 //
39 // ***********************************************************************
40 // @HEADER
41 
42 #include "Teuchos_CommHelpers.hpp"
43 #ifdef HAVE_MPI
44 # include "Teuchos_Details_MpiCommRequest.hpp"
45 #endif // HAVE_MPI
46 
47 namespace Teuchos {
48 namespace { // (anonymous)
49 
50 #ifdef HAVE_MPI
51 MPI_Op getMpiOpForEReductionType (const enum EReductionType reductionType) {
53  switch (reductionType) {
54  case REDUCE_SUM: return MPI_SUM;
55  case REDUCE_MIN: return MPI_MIN;
56  case REDUCE_MAX: return MPI_MAX;
57  case REDUCE_AND: return MPI_LAND; // logical AND, not bitwise AND
58  default:
59  TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument,
60  "The given EReductionType value is invalid.");
61  }
62 }
63 
67 std::string getMpiErrorString (const int errCode) {
68  // Space for storing the error string returned by MPI.
69  // Leave room for null termination, since I don't know if MPI does this.
70  char errString [MPI_MAX_ERROR_STRING+1];
71  int errStringLen = MPI_MAX_ERROR_STRING; // output argument
72  (void) MPI_Error_string (errCode, errString, &errStringLen);
73  // errStringLen on output is the number of characters written.
74  // I'm not sure (the MPI 3.0 Standard doesn't say) if this
75  // includes the '\0', so I'll make sure. We reserved space for
76  // the extra '\0' if needed.
77  if (errString[errStringLen-1] != '\0') {
78  errString[errStringLen] = '\0';
79  }
80  return std::string (errString); // This copies the original string.
81 }
82 
90 template<class T>
91 class MpiTypeTraits {
92 public:
98  static MPI_Datatype getType (const T&);
99 };
100 
101 // amb See note in .hpp file.
102 #if 0
103 #ifdef HAVE_TEUCHOS_COMPLEX
104 template<>
105 class MpiTypeTraits<std::complex<double> > {
106 public:
107  static MPI_Datatype getType (const std::complex<double>&) {
108  return MPI_C_DOUBLE_COMPLEX;
109  }
110 };
111 
112 template<>
113 class MpiTypeTraits<std::complex<float> > {
114 public:
115  static MPI_Datatype getType (const std::complex<float>&) {
116  return MPI_C_FLOAT_COMPLEX;
117  }
118 };
119 #endif // HAVE_TEUCHOS_COMPLEX
120 #endif // if 0
121 
122 template<>
123 class MpiTypeTraits<double> {
124 public:
125  static MPI_Datatype getType (const double&) {
126  return MPI_DOUBLE;
127  }
128 };
129 
130 template<>
131 class MpiTypeTraits<float> {
132 public:
133  static MPI_Datatype getType (const float&) {
134  return MPI_FLOAT;
135  }
136 };
137 
138 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
139 template<>
140 class MpiTypeTraits<long long> {
141 public:
142  static MPI_Datatype getType (const long long&) {
143  return MPI_LONG_LONG;
144  }
145 };
146 
147 template<>
148 class MpiTypeTraits<unsigned long long> {
149 public:
150  static MPI_Datatype getType (const unsigned long long&) {
151  return MPI_UNSIGNED_LONG_LONG;
152  }
153 };
154 #endif // HAVE_TEUCHOS_LONG_LONG_INT
155 
156 template<>
157 class MpiTypeTraits<long> {
158 public:
159  static MPI_Datatype getType (const long&) {
160  return MPI_LONG;
161  }
162 };
163 
164 template<>
165 class MpiTypeTraits<unsigned long> {
166 public:
167  static MPI_Datatype getType (const unsigned long&) {
168  return MPI_UNSIGNED_LONG;
169  }
170 };
171 
172 template<>
173 class MpiTypeTraits<int> {
174 public:
175  static MPI_Datatype getType (const int&) {
176  return MPI_INT;
177  }
178 };
179 
180 template<>
181 class MpiTypeTraits<unsigned int> {
182 public:
183  static MPI_Datatype getType (const unsigned int&) {
184  return MPI_UNSIGNED;
185  }
186 };
187 
188 template<>
189 class MpiTypeTraits<short> {
190 public:
191  static MPI_Datatype getType (const short&) {
192  return MPI_SHORT;
193  }
194 };
195 
196 template<>
197 class MpiTypeTraits<unsigned short> {
198 public:
199  static MPI_Datatype getType (const unsigned short&) {
200  return MPI_UNSIGNED_SHORT;
201  }
202 };
203 #endif // HAVE_MPI
204 
205 
213 template<class T>
214 void
215 reduceAllImpl (const Comm<int>& comm,
216  const EReductionType reductType,
217  const int count,
218  const T sendBuffer[],
219  T globalReducts[])
220 {
221 #ifdef HAVE_MPI
222  // mfh 17 Oct 2012: Even in an MPI build, Comm might be either a
223  // SerialComm or an MpiComm. If it's something else, we fall back
224  // to the most general implementation.
225  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
226  if (mpiComm == NULL) {
227  // Is it a SerialComm?
228  const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
229  if (serialComm == NULL) {
230  // We don't know what kind of Comm we have, so fall back to the
231  // most general implementation.
232  std::auto_ptr<ValueTypeReductionOp<int, T> > reductOp (createOp<int, T> (reductType));
233  reduceAll (comm, *reductOp, count, sendBuffer, globalReducts);
234  }
235  else { // It's a SerialComm; there is only 1 process, so just copy.
236  std::copy (sendBuffer, sendBuffer + count, globalReducts);
237  }
238  } else { // It's an MpiComm. Invoke MPI directly.
239  MPI_Op rawMpiOp = getMpiOpForEReductionType (reductType);
240  MPI_Comm rawMpiComm = * (mpiComm->getRawMpiComm ());
241  T t;
242  MPI_Datatype rawMpiType = MpiTypeTraits<T>::getType (t);
243  const int err = MPI_Allreduce (const_cast<T*> (sendBuffer),
244  globalReducts, count, rawMpiType, rawMpiOp, rawMpiComm);
246  err != MPI_SUCCESS,
247  std::runtime_error,
248  "MPI_Allreduce failed with the following error: "
249  << getMpiErrorString (err));
250  }
251 #else
252  // We've built without MPI, so just assume it's a SerialComm and copy the data.
253  std::copy (sendBuffer, sendBuffer + count, globalReducts);
254 #endif // HAVE_MPI
255 }
256 
257 
265 template<class T>
266 void
267 gatherImpl (const T sendBuf[],
268  const int sendCount,
269  T recvBuf[],
270  const int recvCount,
271  const int root,
272  const Comm<int>& comm)
273 {
274 #ifdef HAVE_MPI
275  // mfh 17 Oct 2012: Even in an MPI build, Comm might be either a
276  // SerialComm or an MpiComm. If it's something else, we fall back
277  // to the most general implementation.
278  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
279  if (mpiComm == NULL) {
280  // Is it a SerialComm?
281  const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
282  if (serialComm == NULL) {
283  // We don't know what kind of Comm we have, so fall back to the
284  // most general implementation.
285  gather<int, T> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
286  }
287  else { // It's a SerialComm; there is only 1 process, so just copy.
288  std::copy (sendBuf, sendBuf + sendCount, recvBuf);
289  }
290  } else { // It's an MpiComm. Invoke MPI directly.
291  MPI_Comm rawMpiComm = * (mpiComm->getRawMpiComm ());
292  T t;
293  MPI_Datatype rawMpiType = MpiTypeTraits<T>::getType (t);
294  const int err = MPI_Gather (const_cast<T*> (sendBuf), sendCount, rawMpiType,
295  recvBuf, recvCount, rawMpiType,
296  root, rawMpiComm);
298  err != MPI_SUCCESS,
299  std::runtime_error,
300  "MPI_Gather failed with the following error: "
301  << getMpiErrorString (err));
302  }
303 #else
304  // We've built without MPI, so just assume it's a SerialComm and copy the data.
305  std::copy (sendBuf, sendBuf + sendCount, recvBuf);
306 #endif // HAVE_MPI
307 }
308 
309 
317 template<class T>
318 void
319 scatterImpl (const T sendBuf[],
320  const int sendCount,
321  T recvBuf[],
322  const int recvCount,
323  const int root,
324  const Comm<int>& comm)
325 {
326 #ifdef HAVE_MPI
327  // mfh 17 Oct 2012: Even in an MPI build, Comm might be either a
328  // SerialComm or an MpiComm. If it's something else, we fall back
329  // to the most general implementation.
330  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
331  if (mpiComm == NULL) {
332  // Is it a SerialComm?
333  const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
334  if (serialComm == NULL) {
335  // We don't know what kind of Comm we have, so fall back to the
336  // most general implementation.
337  scatter<int, T> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
338  }
339  else { // It's a SerialComm; there is only 1 process, so just copy.
340  std::copy (sendBuf, sendBuf + sendCount, recvBuf);
341  }
342  } else { // It's an MpiComm. Invoke MPI directly.
343  MPI_Comm rawMpiComm = * (mpiComm->getRawMpiComm ());
344  T t;
345  MPI_Datatype rawMpiType = MpiTypeTraits<T>::getType (t);
346  const int err =
347  MPI_Scatter (const_cast<T*> (sendBuf), sendCount, rawMpiType,
348  recvBuf, recvCount, rawMpiType,
349  root, rawMpiComm);
351  (err != MPI_SUCCESS, std::runtime_error,
352  "MPI_Scatter failed with the following error: "
353  << getMpiErrorString (err));
354  }
355 #else
356  // We've built without MPI, so just assume it's a SerialComm and
357  // copy the data.
358  std::copy (sendBuf, sendBuf + sendCount, recvBuf);
359 #endif // HAVE_MPI
360 }
361 
362 
370 template<class T>
371 void
372 reduceImpl (const T sendBuf[],
373  T recvBuf[],
374  const int count,
375  const EReductionType reductType,
376  const int root,
377  const Comm<int>& comm)
378 {
379 #ifdef HAVE_MPI
380  // mfh 17 Oct 2012: Even in an MPI build, Comm might be either a
381  // SerialComm or an MpiComm. If it's something else, we fall back
382  // to the most general implementation.
383  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
384  if (mpiComm == NULL) {
385  // Is it a SerialComm?
386  const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
387  if (serialComm == NULL) {
388  // We don't know what kind of Comm we have, so fall back to the
389  // most general implementation.
390  reduce<int, T> (sendBuf, recvBuf, count, reductType, root, comm);
391  }
392  else { // It's a SerialComm; there is only 1 process, so just copy.
393  std::copy (sendBuf, sendBuf + count, recvBuf);
394  }
395  } else { // It's an MpiComm. Invoke MPI directly.
396  MPI_Op rawMpiOp = getMpiOpForEReductionType (reductType);
397  MPI_Comm rawMpiComm = * (mpiComm->getRawMpiComm ());
398  T t;
399  MPI_Datatype rawMpiType = MpiTypeTraits<T>::getType (t);
400  const int err = MPI_Reduce (const_cast<T*> (sendBuf), recvBuf, count,
401  rawMpiType, rawMpiOp, root, rawMpiComm);
403  (err != MPI_SUCCESS, std::runtime_error, "MPI_Reduce failed with the "
404  "following error: " << getMpiErrorString (err));
405  }
406 #else
407  // We've built without MPI, so just assume it's a SerialComm and copy the data.
408  std::copy (sendBuf, sendBuf + count, recvBuf);
409 #endif // HAVE_MPI
410 }
411 
412 
420 template<class T>
421 void
422 gathervImpl (const T sendBuf[],
423  const int sendCount,
424  T recvBuf[],
425  const int recvCounts[],
426  const int displs[],
427  const int root,
428  const Comm<int>& comm)
429 {
430 #ifdef HAVE_MPI
431  // mfh 17 Oct 2012: Even in an MPI build, Comm might be either a
432  // SerialComm or an MpiComm. If it's something else, we fall back
433  // to the most general implementation.
434  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
435  if (mpiComm == NULL) {
436  // Is it a SerialComm?
437  const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
438  if (serialComm == NULL) {
439  // We don't know what kind of Comm we have, so fall back to the
440  // most general implementation.
441  gatherv<int, T> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
442  }
443  else { // It's a SerialComm; there is only 1 process, so just copy.
445  recvCounts[0] > sendCount, std::invalid_argument,
446  "Teuchos::gatherv: If the input communicator contains only one "
447  "process, then you cannot receive more entries than you send. "
448  "You aim to receive " << recvCounts[0] << " entries, but to send "
449  << sendCount << " entries.");
450  // Serial communicator case: just copy. recvCounts[0] is the
451  // amount to receive, so it's the amount to copy. Start writing
452  // to recvbuf at the offset displs[0].
453  std::copy (sendBuf, sendBuf + recvCounts[0], recvBuf + displs[0]);
454  }
455  } else { // It's an MpiComm. Invoke MPI directly.
456  MPI_Comm rawMpiComm = * (mpiComm->getRawMpiComm ());
457  T t;
458  MPI_Datatype rawMpiType = MpiTypeTraits<T>::getType (t);
459  const int err = MPI_Gatherv (const_cast<T*> (sendBuf),
460  sendCount,
461  rawMpiType,
462  recvBuf,
463  const_cast<int*> (recvCounts),
464  const_cast<int*> (displs),
465  rawMpiType,
466  root,
467  rawMpiComm);
469  err != MPI_SUCCESS,
470  std::runtime_error,
471  "MPI_Gatherv failed with the following error: "
472  << getMpiErrorString (err));
473  }
474 #else
475  // We've built without MPI, so just assume it's a SerialComm and copy the data.
477  recvCounts[0] > sendCount, std::invalid_argument,
478  "Teuchos::gatherv: If the input communicator contains only one "
479  "process, then you cannot receive more entries than you send. "
480  "You aim to receive " << recvCounts[0] << " entries, but to send "
481  << sendCount << " entries.");
482  // Serial communicator case: just copy. recvCounts[0] is the
483  // amount to receive, so it's the amount to copy. Start writing
484  // to recvbuf at the offset displs[0].
485  std::copy (sendBuf, sendBuf + recvCounts[0], recvBuf + displs[0]);
486 #endif // HAVE_MPI
487 }
488 
494 template<typename Packet>
495 RCP<Teuchos::CommRequest<int> >
496 ireceiveGeneral(const Comm<int>& comm,
497  const ArrayRCP<Packet> &recvBuffer,
498  const int sourceRank)
499 {
500  TEUCHOS_COMM_TIME_MONITOR(
501  "Teuchos::ireceive<int, " << "," << TypeNameTraits<Packet>::name ()
502  << "> ( value type )"
503  );
504  ValueTypeSerializationBuffer<int, Packet>
505  charRecvBuffer (recvBuffer.size (), recvBuffer.getRawPtr ());
506  RCP<CommRequest<int> > commRequest =
507  comm.ireceive (charRecvBuffer.getCharBufferView (), sourceRank);
508  set_extra_data (recvBuffer, "buffer", inOutArg (commRequest));
509  return commRequest;
510 }
511 
514 template<typename Packet>
515 RCP<Teuchos::CommRequest<int> >
516 ireceiveGeneral (const ArrayRCP<Packet> &recvBuffer,
517  const int sourceRank,
518  const int tag,
519  const Comm<int>& comm)
520 {
521  TEUCHOS_COMM_TIME_MONITOR(
522  "Teuchos::ireceive<int, " << "," << TypeNameTraits<Packet>::name ()
523  << "> ( value type )"
524  );
525  ValueTypeSerializationBuffer<int, Packet>
526  charRecvBuffer (recvBuffer.size (), recvBuffer.getRawPtr ());
527  RCP<CommRequest<int> > commRequest =
528  comm.ireceive (charRecvBuffer.getCharBufferView (), sourceRank, tag);
529  set_extra_data (recvBuffer, "buffer", inOutArg (commRequest));
530  return commRequest;
531 }
532 
545 template<class T>
546 RCP<CommRequest<int> >
547 ireceiveImpl (const Comm<int>& comm,
548  const ArrayRCP<T>& recvBuffer,
549  const int sourceRank)
550 {
551 #ifdef HAVE_MPI
552  // Even in an MPI build, Comm might be either a SerialComm or an
553  // MpiComm. If it's something else, we fall back to the most
554  // general implementation.
555  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
556  if (mpiComm == NULL) {
557  // Is it a SerialComm?
558  const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
559  if (serialComm == NULL) {
560  // We don't know what kind of Comm we have, so fall back to the
561  // most general implementation.
562  return ireceiveGeneral<T> (comm, recvBuffer, sourceRank);
563  }
564  else { // SerialComm doesn't implement ireceive anyway.
566  true,
567  std::logic_error,
568  "ireceiveImpl: Not implemented for a serial communicator.");
569  }
570  }
571  else { // It's an MpiComm. Invoke MPI directly.
572  MPI_Comm rawComm = * (mpiComm->getRawMpiComm ());
573  T t;
574  MPI_Datatype rawType = MpiTypeTraits<T>::getType (t);
575  T* rawRecvBuf = recvBuffer.getRawPtr ();
576  const int count = as<int> (recvBuffer.size ());
577  const int tag = mpiComm->getTag ();
578  MPI_Request rawRequest = MPI_REQUEST_NULL;
579  const int err = MPI_Irecv (rawRecvBuf, count, rawType, sourceRank, tag,
580  rawComm, &rawRequest);
582  err != MPI_SUCCESS, std::runtime_error,
583  "MPI_Irecv failed with the following error: "
584  << getMpiErrorString (err));
585 
586  ArrayRCP<const char> buf =
587  arcp_const_cast<const char> (arcp_reinterpret_cast<char> (recvBuffer));
588  RCP<Details::MpiCommRequest> req (new Details::MpiCommRequest (rawRequest, buf));
589  return rcp_implicit_cast<CommRequest<int> > (req);
590  }
591 #else
593  true,
594  std::logic_error,
595  "ireceiveImpl: Not implemented for a serial communicator.");
596 
597  // NOTE (mfh 15 Sep 2014): Most compilers have figured out that the
598  // return statement below is unreachable. Some older compilers
599  // might not realize this. That's why the return statement was put
600  // there, so that those compilers don't warn that this function
601  // doesn't return a value. If it's a choice between one warning and
602  // another, I would prefer the choice that produces less code and
603  // doesn't have unreachable code (which never gets tested).
604 
605  //return null; // Guard to avoid compiler warning about not returning a value.
606 #endif // HAVE_MPI
607 }
608 
611 template<class T>
612 RCP<CommRequest<int> >
613 ireceiveImpl (const ArrayRCP<T>& recvBuffer,
614  const int sourceRank,
615  const int tag,
616  const Comm<int>& comm)
617 {
618 #ifdef HAVE_MPI
619  // Even in an MPI build, Comm might be either a SerialComm or an
620  // MpiComm. If it's something else, we fall back to the most
621  // general implementation.
622  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
623  if (mpiComm == NULL) {
624  // Is it a SerialComm?
625  const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
626  if (serialComm == NULL) {
627  // We don't know what kind of Comm we have, so fall back to the
628  // most general implementation.
629  return ireceiveGeneral<T> (recvBuffer, sourceRank, tag, comm);
630  }
631  else { // SerialComm doesn't implement ireceive anyway.
633  true,
634  std::logic_error,
635  "ireceiveImpl: Not implemented for a serial communicator.");
636  }
637  }
638  else { // It's an MpiComm. Invoke MPI directly.
639  MPI_Comm rawComm = * (mpiComm->getRawMpiComm ());
640  T t;
641  MPI_Datatype rawType = MpiTypeTraits<T>::getType (t);
642  T* rawRecvBuf = recvBuffer.getRawPtr ();
643  const int count = as<int> (recvBuffer.size ());
644  MPI_Request rawRequest = MPI_REQUEST_NULL;
645  const int err = MPI_Irecv (rawRecvBuf, count, rawType, sourceRank, tag,
646  rawComm, &rawRequest);
648  err != MPI_SUCCESS, std::runtime_error,
649  "MPI_Irecv failed with the following error: "
650  << getMpiErrorString (err));
651 
652  ArrayRCP<const char> buf =
653  arcp_const_cast<const char> (arcp_reinterpret_cast<char> (recvBuffer));
654  RCP<Details::MpiCommRequest> req (new Details::MpiCommRequest (rawRequest, buf));
655  return rcp_implicit_cast<CommRequest<int> > (req);
656  }
657 #else
659  true,
660  std::logic_error,
661  "ireceiveImpl: Not implemented for a serial communicator.");
662 
663  return null; // Guard to avoid compiler warning about not returning a value.
664 #endif // HAVE_MPI
665 }
666 
672 template<class T>
673 void
674 sendGeneral (const Comm<int>& comm,
675  const int count,
676  const T sendBuffer[],
677  const int destRank)
678 {
679  TEUCHOS_COMM_TIME_MONITOR(
680  "Teuchos::send<int, " << TypeNameTraits<T>::name () << ">");
681  ConstValueTypeSerializationBuffer<int,T> charSendBuffer (count, sendBuffer);
682  comm.send (charSendBuffer.getBytes (),
683  charSendBuffer.getCharBuffer (),
684  destRank);
685 }
686 
689 template<class T>
690 void
691 sendGeneral (const T sendBuffer[],
692  const int count,
693  const int destRank,
694  const int tag,
695  const Comm<int>& comm)
696 {
697  TEUCHOS_COMM_TIME_MONITOR(
698  "Teuchos::send<int, " << TypeNameTraits<T>::name () << ">");
699  ConstValueTypeSerializationBuffer<int,T> charSendBuffer (count, sendBuffer);
700  comm.send (charSendBuffer.getBytes (),
701  charSendBuffer.getCharBuffer (),
702  destRank, tag);
703 }
704 
717 template<class T>
718 void
719 sendImpl (const Comm<int>& comm,
720  const int count,
721  const T sendBuffer[],
722  const int destRank)
723 {
724 #ifdef HAVE_MPI
725  // Even in an MPI build, Comm might be either a SerialComm or an
726  // MpiComm. If it's something else, we fall back to the most
727  // general implementation.
728  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
729  if (mpiComm == NULL) {
730  // Is it a SerialComm?
731  const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
732  if (serialComm == NULL) {
733  // We don't know what kind of Comm we have, so fall back to the
734  // most general implementation.
735  sendGeneral<T> (comm, count, sendBuffer, destRank);
736  }
737  else { // SerialComm doesn't implement send correctly anyway.
739  true,
740  std::logic_error,
741  "sendImpl: Not implemented for a serial communicator.");
742  }
743  }
744  else { // It's an MpiComm. Invoke MPI directly.
745  MPI_Comm rawComm = * (mpiComm->getRawMpiComm ());
746  T t;
747  MPI_Datatype rawType = MpiTypeTraits<T>::getType (t);
748  T* rawBuf = const_cast<T*> (sendBuffer);
749  const int tag = mpiComm->getTag ();
750  const int err = MPI_Send (rawBuf, count, rawType, destRank, tag, rawComm);
752  err != MPI_SUCCESS,
753  std::runtime_error,
754  "MPI_Send failed with the following error: "
755  << getMpiErrorString (err));
756  }
757 #else
759  true,
760  std::logic_error,
761  "sendImpl: Not implemented for a serial communicator.");
762 #endif // HAVE_MPI
763 }
764 
767 template<class T>
768 void
769 sendImpl (const T sendBuffer[],
770  const int count,
771  const int destRank,
772  const int tag,
773  const Comm<int>& comm)
774 {
775 #ifdef HAVE_MPI
776  // Even in an MPI build, Comm might be either a SerialComm or an
777  // MpiComm. If it's something else, we fall back to the most
778  // general implementation.
779  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
780  if (mpiComm == NULL) {
781  // Is it a SerialComm?
782  const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
783  if (serialComm == NULL) {
784  // We don't know what kind of Comm we have, so fall back to the
785  // most general implementation.
786  sendGeneral<T> (sendBuffer, count, destRank, tag, comm);
787  }
788  else { // SerialComm doesn't implement send correctly anyway.
790  true,
791  std::logic_error,
792  "sendImpl: Not implemented for a serial communicator.");
793  }
794  }
795  else { // It's an MpiComm. Invoke MPI directly.
796  MPI_Comm rawComm = * (mpiComm->getRawMpiComm ());
797  T t;
798  MPI_Datatype rawType = MpiTypeTraits<T>::getType (t);
799  T* rawBuf = const_cast<T*> (sendBuffer);
800  const int err = MPI_Send (rawBuf, count, rawType, destRank, tag, rawComm);
802  err != MPI_SUCCESS,
803  std::runtime_error,
804  "MPI_Send failed with the following error: "
805  << getMpiErrorString (err));
806  }
807 #else
809  true,
810  std::logic_error,
811  "sendImpl: Not implemented for a serial communicator.");
812 #endif // HAVE_MPI
813 }
814 
820 template<class T>
821 RCP<CommRequest<int> >
822 isendGeneral (const Comm<int>& comm,
823  const ArrayRCP<const T>& sendBuffer,
824  const int destRank)
825 {
826  TEUCHOS_COMM_TIME_MONITOR(
827  "Teuchos::isend<int," << TypeNameTraits<T>::name () << ">");
828  ConstValueTypeSerializationBuffer<int, T>
829  charSendBuffer (sendBuffer.size (), sendBuffer.getRawPtr ());
830  RCP<CommRequest<int> > commRequest =
831  comm.isend (charSendBuffer.getCharBufferView (), destRank);
832  set_extra_data (sendBuffer, "buffer", inOutArg (commRequest));
833  return commRequest;
834 }
835 
842 template<class T>
843 RCP<CommRequest<int> >
844 isendGeneral (const ArrayRCP<const T>& sendBuffer,
845  const int destRank,
846  const int tag,
847  const Comm<int>& comm)
848 {
849  TEUCHOS_COMM_TIME_MONITOR(
850  "Teuchos::isend<int," << TypeNameTraits<T>::name () << ">");
851  ConstValueTypeSerializationBuffer<int, T>
852  charSendBuffer (sendBuffer.size (), sendBuffer.getRawPtr ());
853  RCP<CommRequest<int> > commRequest =
854  comm.isend (charSendBuffer.getCharBufferView (), destRank, tag);
855  set_extra_data (sendBuffer, "buffer", inOutArg (commRequest));
856  return commRequest;
857 }
858 
861 template<class T>
862 RCP<Teuchos::CommRequest<int> >
863 isendImpl (const ArrayRCP<const T>& sendBuffer,
864  const int destRank,
865  const int tag,
866  const Comm<int>& comm)
867 {
868 #ifdef HAVE_MPI
869  // Even in an MPI build, Comm might be either a SerialComm or an
870  // MpiComm. If it's something else, we fall back to the most
871  // general implementation.
872  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
873  if (mpiComm == NULL) {
874  // Is it a SerialComm?
875  const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
876  if (serialComm == NULL) {
877  // We don't know what kind of Comm we have, so fall back to the
878  // most general implementation.
879  return isendGeneral<T> (sendBuffer, destRank, tag, comm);
880  }
881  else { // SerialComm doesn't implement send correctly anyway.
883  true, std::logic_error,
884  "isendImpl: Not implemented for a serial communicator.");
885  }
886  }
887  else { // It's an MpiComm. Invoke MPI directly.
888  MPI_Comm rawComm = * (mpiComm->getRawMpiComm ());
889  T t;
890  MPI_Datatype rawType = MpiTypeTraits<T>::getType (t);
891  // MPI promises not to modify the send buffer; the const_cast
892  // merely ensures compatibilty with C89, which does not have a
893  // "const" keyword.
894  T* rawSendBuf = const_cast<T*> (sendBuffer.getRawPtr ());
895  const int count = as<int> (sendBuffer.size ());
896  MPI_Request rawRequest = MPI_REQUEST_NULL;
897  const int err = MPI_Isend (rawSendBuf, count, rawType, destRank, tag,
898  rawComm, &rawRequest);
900  err != MPI_SUCCESS,
901  std::runtime_error,
902  "MPI_Isend failed with the following error: "
903  << getMpiErrorString (err));
904 
905  ArrayRCP<const char> buf = arcp_reinterpret_cast<const char> (sendBuffer);
906  RCP<Details::MpiCommRequest> req (new Details::MpiCommRequest (rawRequest, buf));
907  return rcp_implicit_cast<CommRequest<int> > (req);
908  }
909 #else
911  true,
912  std::logic_error,
913  "isendImpl: Not implemented for a serial communicator.");
914 #endif // HAVE_MPI
915 }
916 
917 } // namespace (anonymous)
918 
919 
920 const char*
921 toString (const EReductionType reductType)
922 {
923  switch (reductType) {
924  case REDUCE_SUM: return "REDUCE_SUM";
925  case REDUCE_MIN: return "REDUCE_MIN";
926  case REDUCE_MAX: return "REDUCE_MAX";
927  case REDUCE_AND: return "REDUCE_AND";
928  default:
930  true, std::invalid_argument, "Teuchos::toString(EReductionType): "
931  "Invalid EReductionType value " << reductType << ". Valid values "
932  "include REDUCE_SUM = " << REDUCE_SUM << ", REDUCE_MIN = " << REDUCE_MIN
933  << ", REDUCE_MAX = " << REDUCE_MIN << ", and REDUCE_AND = " << REDUCE_AND
934  << ".");
935  }
936 }
937 
938 
939 // mfh 18 Oct 2012: Note on full template specializations
940 //
941 // To make Windows builds happy, declarations of full template
942 // specializations (as found in Teuchos_CommHelpers.hpp) must use the
943 // TEUCHOSCOMM_LIB_DLL_EXPORT macro. However, _definitions_ of the
944 // specializations (as found in this file) must _not_ use the macro.
945 // That's why we don't use that macro here.
946 
947 // amb See note in .hpp file.
948 #if 0
949 #ifdef HAVE_TEUCHOS_COMPLEX
950 // Specialization for Ordinal=int and Packet=std::complex<double>.
951 template<>
952 void
953 reduceAll<int, std::complex<double> > (const Comm<int>& comm,
954  const EReductionType reductType,
955  const int count,
956  const std::complex<double> sendBuffer[],
957  std::complex<double> globalReducts[])
958 {
959  TEUCHOS_COMM_TIME_MONITOR(
960  "Teuchos::reduceAll<int, std::complex<double> > (" << count << ", "
961  << toString (reductType) << ")"
962  );
963  reduceAllImpl<std::complex<double> > (comm, reductType, count, sendBuffer, globalReducts);
964 }
965 
966 template<>
967 RCP<Teuchos::CommRequest<int> >
968 ireceive<int, std::complex<double> > (const Comm<int>& comm,
969  const ArrayRCP<std::complex<double> >& recvBuffer,
970  const int sourceRank)
971 {
972  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, std::complex<double> >");
973  return ireceiveImpl<std::complex<double> > (comm, recvBuffer, sourceRank);
974 }
975 
976 template<>
977 RCP<Teuchos::CommRequest<int> >
978 ireceive<int, std::complex<double> > (const ArrayRCP<std::complex<double> >& recvBuffer,
979  const int sourceRank,
980  const int tag,
981  const Comm<int>& comm)
982 {
983  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, std::complex<double> >");
984  return ireceiveImpl<std::complex<double> > (recvBuffer, sourceRank, tag, comm);
985 }
986 
987 template<>
988 void
989 send<int, std::complex<double> > (const Comm<int>& comm,
990  const int count,
991  const std::complex<double> sendBuffer[],
992  const int destRank)
993 {
994  sendImpl<std::complex<double> > (comm, count, sendBuffer, destRank);
995 }
996 
997 template<>
998 void
999 send<int, std::complex<double> > (const std::complex<double> sendBuffer[],
1000  const int count,
1001  const int destRank,
1002  const int tag,
1003  const Comm<int>& comm)
1004 {
1005  sendImpl<std::complex<double> > (sendBuffer, count, destRank, tag, comm);
1006 }
1007 
1008 template<>
1009 RCP<Teuchos::CommRequest<int> >
1010 isend (const ArrayRCP<const std::complex<double> >& sendBuffer,
1011  const int destRank,
1012  const int tag,
1013  const Comm<int>& comm)
1014 {
1015  return isendImpl<std::complex<double> > (sendBuffer, destRank, tag, comm);
1016 }
1017 
1018 // Specialization for Ordinal=int and Packet=std::complex<float>.
1019 template<>
1020 void
1021 reduceAll<int, std::complex<float> > (const Comm<int>& comm,
1022  const EReductionType reductType,
1023  const int count,
1024  const std::complex<float> sendBuffer[],
1025  std::complex<float> globalReducts[])
1026 {
1027  TEUCHOS_COMM_TIME_MONITOR(
1028  "Teuchos::reduceAll<int, std::complex<float> > (" << count << ", "
1029  << toString (reductType) << ")"
1030  );
1031  reduceAllImpl<std::complex<float> > (comm, reductType, count, sendBuffer, globalReducts);
1032 }
1033 
1034 template<>
1035 RCP<Teuchos::CommRequest<int> >
1036 ireceive<int, std::complex<float> > (const Comm<int>& comm,
1037  const ArrayRCP<std::complex<float> >& recvBuffer,
1038  const int sourceRank)
1039 {
1040  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, std::complex<float> >");
1041  return ireceiveImpl<std::complex<float> > (comm, recvBuffer, sourceRank);
1042 }
1043 
1044 template<>
1045 RCP<Teuchos::CommRequest<int> >
1046 ireceive<int, std::complex<float> > (const ArrayRCP<std::complex<float> >& recvBuffer,
1047  const int sourceRank,
1048  const int tag,
1049  const Comm<int>& comm)
1050 {
1051  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, std::complex<float> >");
1052  return ireceiveImpl<std::complex<float> > (recvBuffer, sourceRank, tag, comm);
1053 }
1054 
1055 template<>
1056 void
1057 send<int, std::complex<float> > (const Comm<int>& comm,
1058  const int count,
1059  const std::complex<float> sendBuffer[],
1060  const int destRank)
1061 {
1062  return sendImpl<std::complex<float> > (comm, count, sendBuffer, destRank);
1063 }
1064 
1065 template<>
1066 void
1067 send<int, std::complex<float> > (const std::complex<float> sendBuffer[],
1068  const int count,
1069  const int destRank,
1070  const int tag,
1071  const Comm<int>& comm)
1072 {
1073  return sendImpl<std::complex<float> > (sendBuffer, count, destRank, tag, comm);
1074 }
1075 
1076 template<>
1077 RCP<Teuchos::CommRequest<int> >
1078 isend (const ArrayRCP<const std::complex<float> >& sendBuffer,
1079  const int destRank,
1080  const int tag,
1081  const Comm<int>& comm)
1082 {
1083  return isendImpl<std::complex<float> > (sendBuffer, destRank, tag, comm);
1084 }
1085 #endif // HAVE_TEUCHOS_COMPLEX
1086 #endif // if 0
1087 
1088 
1089 // Specialization for Ordinal=int and Packet=double.
1090 template<>
1091 void
1092 reduceAll<int, double> (const Comm<int>& comm,
1093  const EReductionType reductType,
1094  const int count,
1095  const double sendBuffer[],
1096  double globalReducts[])
1097 {
1098  TEUCHOS_COMM_TIME_MONITOR(
1099  "Teuchos::reduceAll<int, double> (" << count << ", "
1100  << toString (reductType) << ")"
1101  );
1102  reduceAllImpl<double> (comm, reductType, count, sendBuffer, globalReducts);
1103 }
1104 
1105 template<>
1106 RCP<Teuchos::CommRequest<int> >
1107 ireceive<int, double> (const Comm<int>& comm,
1108  const ArrayRCP<double>& recvBuffer,
1109  const int sourceRank)
1110 {
1111  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, double>");
1112  return ireceiveImpl<double> (comm, recvBuffer, sourceRank);
1113 }
1114 
1115 template<>
1116 RCP<Teuchos::CommRequest<int> >
1117 ireceive<int, double> (const ArrayRCP<double>& recvBuffer,
1118  const int sourceRank,
1119  const int tag,
1120  const Comm<int>& comm)
1121 {
1122  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, double>");
1123  return ireceiveImpl<double> (recvBuffer, sourceRank, tag, comm);
1124 }
1125 
1126 template<>
1127 void
1128 send<int, double> (const Comm<int>& comm,
1129  const int count,
1130  const double sendBuffer[],
1131  const int destRank)
1132 {
1133  return sendImpl<double> (comm, count, sendBuffer, destRank);
1134 }
1135 
1136 template<>
1137 void
1138 send<int, double> (const double sendBuffer[],
1139  const int count,
1140  const int destRank,
1141  const int tag,
1142  const Comm<int>& comm)
1143 {
1144  return sendImpl<double> (sendBuffer, count, destRank, tag, comm);
1145 }
1146 
1147 template<>
1148 RCP<Teuchos::CommRequest<int> >
1149 isend (const ArrayRCP<const double>& sendBuffer,
1150  const int destRank,
1151  const int tag,
1152  const Comm<int>& comm)
1153 {
1154  return isendImpl<double> (sendBuffer, destRank, tag, comm);
1155 }
1156 
1157 // Specialization for Ordinal=int and Packet=float.
1158 template<>
1159 void
1160 reduceAll<int, float> (const Comm<int>& comm,
1161  const EReductionType reductType,
1162  const int count,
1163  const float sendBuffer[],
1164  float globalReducts[])
1165 {
1166  TEUCHOS_COMM_TIME_MONITOR(
1167  "Teuchos::reduceAll<int, float> (" << count << ", "
1168  << toString (reductType) << ")"
1169  );
1170  reduceAllImpl<float> (comm, reductType, count, sendBuffer, globalReducts);
1171 }
1172 
1173 template<>
1174 RCP<Teuchos::CommRequest<int> >
1175 ireceive<int, float> (const Comm<int>& comm,
1176  const ArrayRCP<float>& recvBuffer,
1177  const int sourceRank)
1178 {
1179  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, float>");
1180  return ireceiveImpl<float> (comm, recvBuffer, sourceRank);
1181 }
1182 
1183 template<>
1184 RCP<Teuchos::CommRequest<int> >
1185 ireceive<int, float> (const ArrayRCP<float>& recvBuffer,
1186  const int sourceRank,
1187  const int tag,
1188  const Comm<int>& comm)
1189 {
1190  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, float>");
1191  return ireceiveImpl<float> (recvBuffer, sourceRank, tag, comm);
1192 }
1193 
1194 template<>
1195 void
1196 send<int, float> (const Comm<int>& comm,
1197  const int count,
1198  const float sendBuffer[],
1199  const int destRank)
1200 {
1201  return sendImpl<float> (comm, count, sendBuffer, destRank);
1202 }
1203 
1204 template<>
1205 void
1206 send<int, float> (const float sendBuffer[],
1207  const int count,
1208  const int destRank,
1209  const int tag,
1210  const Comm<int>& comm)
1211 {
1212  return sendImpl<float> (sendBuffer, count, destRank, tag, comm);
1213 }
1214 
1215 template<>
1216 RCP<Teuchos::CommRequest<int> >
1217 isend (const ArrayRCP<const float>& sendBuffer,
1218  const int destRank,
1219  const int tag,
1220  const Comm<int>& comm)
1221 {
1222  return isendImpl<float> (sendBuffer, destRank, tag, comm);
1223 }
1224 
1225 
1226 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
1227 // Specialization for Ordinal=int and Packet=long long.
1228 template<>
1229 void
1230 gather<int, long long> (const long long sendBuf[],
1231  const int sendCount,
1232  long long recvBuf[],
1233  const int recvCount,
1234  const int root,
1235  const Comm<int>& comm)
1236 {
1237  gatherImpl<long long> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1238 }
1239 
1240 template<>
1241 void
1242 gatherv<int, long long> (const long long sendBuf[],
1243  const int sendCount,
1244  long long recvBuf[],
1245  const int recvCounts[],
1246  const int displs[],
1247  const int root,
1248  const Comm<int>& comm)
1249 {
1250  gathervImpl<long long> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1251 }
1252 
1253 template<>
1254 void
1255 reduceAll<int, long long> (const Comm<int>& comm,
1256  const EReductionType reductType,
1257  const int count,
1258  const long long sendBuffer[],
1259  long long globalReducts[])
1260 {
1261  TEUCHOS_COMM_TIME_MONITOR(
1262  "Teuchos::reduceAll<int, long long> (" << count << ", "
1263  << toString (reductType) << ")"
1264  );
1265  reduceAllImpl<long long> (comm, reductType, count, sendBuffer, globalReducts);
1266 }
1267 
1268 template<>
1269 RCP<Teuchos::CommRequest<int> >
1270 ireceive<int, long long> (const Comm<int>& comm,
1271  const ArrayRCP<long long>& recvBuffer,
1272  const int sourceRank)
1273 {
1274  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, long long>");
1275  return ireceiveImpl<long long> (comm, recvBuffer, sourceRank);
1276 }
1277 
1278 template<>
1279 RCP<Teuchos::CommRequest<int> >
1280 ireceive<int, long long> (const ArrayRCP<long long>& recvBuffer,
1281  const int sourceRank,
1282  const int tag,
1283  const Comm<int>& comm)
1284 {
1285  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, long long>");
1286  return ireceiveImpl<long long> (recvBuffer, sourceRank, tag, comm);
1287 }
1288 
1289 template<>
1290 void
1291 send<int, long long> (const Comm<int>& comm,
1292  const int count,
1293  const long long sendBuffer[],
1294  const int destRank)
1295 {
1296  return sendImpl<long long> (comm, count, sendBuffer, destRank);
1297 }
1298 
1299 template<>
1300 void
1301 send<int, long long> (const long long sendBuffer[],
1302  const int count,
1303  const int destRank,
1304  const int tag,
1305  const Comm<int>& comm)
1306 {
1307  return sendImpl<long long> (sendBuffer, count, destRank, tag, comm);
1308 }
1309 
1310 template<>
1311 RCP<Teuchos::CommRequest<int> >
1312 isend (const ArrayRCP<const long long>& sendBuffer,
1313  const int destRank,
1314  const int tag,
1315  const Comm<int>& comm)
1316 {
1317  return isendImpl<long long> (sendBuffer, destRank, tag, comm);
1318 }
1319 
1320 // Specialization for Ordinal=int and Packet=unsigned long long.
1321 template<>
1322 void
1323 gather<int, unsigned long long> (const unsigned long long sendBuf[],
1324  const int sendCount,
1325  unsigned long long recvBuf[],
1326  const int recvCount,
1327  const int root,
1328  const Comm<int>& comm)
1329 {
1330  gatherImpl<unsigned long long> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1331 }
1332 
1333 template<>
1334 void
1335 gatherv<int, unsigned long long> (const unsigned long long sendBuf[],
1336  const int sendCount,
1337  unsigned long long recvBuf[],
1338  const int recvCounts[],
1339  const int displs[],
1340  const int root,
1341  const Comm<int>& comm)
1342 {
1343  gathervImpl<unsigned long long> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1344 }
1345 
1346 template<>
1347 void
1348 reduceAll<int, unsigned long long> (const Comm<int>& comm,
1349  const EReductionType reductType,
1350  const int count,
1351  const unsigned long long sendBuffer[],
1352  unsigned long long globalReducts[])
1353 {
1354  TEUCHOS_COMM_TIME_MONITOR(
1355  "Teuchos::reduceAll<int, unsigned long long> (" << count << ", "
1356  << toString (reductType) << ")"
1357  );
1358  reduceAllImpl<unsigned long long> (comm, reductType, count, sendBuffer, globalReducts);
1359 }
1360 
1361 template<>
1362 RCP<Teuchos::CommRequest<int> >
1363 ireceive<int, unsigned long long> (const Comm<int>& comm,
1364  const ArrayRCP<unsigned long long>& recvBuffer,
1365  const int sourceRank)
1366 {
1367  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned long long>");
1368  return ireceiveImpl<unsigned long long> (comm, recvBuffer, sourceRank);
1369 }
1370 
1371 template<>
1372 RCP<Teuchos::CommRequest<int> >
1373 ireceive<int, unsigned long long> (const ArrayRCP<unsigned long long>& recvBuffer,
1374  const int sourceRank,
1375  const int tag,
1376  const Comm<int>& comm)
1377 {
1378  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned long long>");
1379  return ireceiveImpl<unsigned long long> (recvBuffer, sourceRank, tag, comm);
1380 }
1381 
1382 template<>
1383 void
1384 send<int, unsigned long long> (const Comm<int>& comm,
1385  const int count,
1386  const unsigned long long sendBuffer[],
1387  const int destRank)
1388 {
1389  return sendImpl<unsigned long long> (comm, count, sendBuffer, destRank);
1390 }
1391 
1392 template<>
1393 void
1394 send<int, unsigned long long> (const unsigned long long sendBuffer[],
1395  const int count,
1396  const int destRank,
1397  const int tag,
1398  const Comm<int>& comm)
1399 {
1400  return sendImpl<unsigned long long> (sendBuffer, count, destRank, tag, comm);
1401 }
1402 
1403 template<>
1404 RCP<Teuchos::CommRequest<int> >
1405 isend (const ArrayRCP<const unsigned long long>& sendBuffer,
1406  const int destRank,
1407  const int tag,
1408  const Comm<int>& comm)
1409 {
1410  return isendImpl<unsigned long long> (sendBuffer, destRank, tag, comm);
1411 }
1412 
1413 #endif // HAVE_TEUCHOS_LONG_LONG_INT
1414 
1415 
1416 // Specialization for Ordinal=int and Packet=long.
1417 template<>
1418 void
1419 gather<int, long> (const long sendBuf[],
1420  const int sendCount,
1421  long recvBuf[],
1422  const int recvCount,
1423  const int root,
1424  const Comm<int>& comm)
1425 {
1426  gatherImpl<long> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1427 }
1428 
1429 template<>
1430 void
1431 gatherv<int, long> (const long sendBuf[],
1432  const int sendCount,
1433  long recvBuf[],
1434  const int recvCounts[],
1435  const int displs[],
1436  const int root,
1437  const Comm<int>& comm)
1438 {
1439  gathervImpl<long> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1440 }
1441 
1442 template<>
1443 void
1444 reduceAll<int, long> (const Comm<int>& comm,
1445  const EReductionType reductType,
1446  const int count,
1447  const long sendBuffer[],
1448  long globalReducts[])
1449 {
1450  TEUCHOS_COMM_TIME_MONITOR(
1451  "Teuchos::reduceAll<int, long> (" << count << ", "
1452  << toString (reductType) << ")"
1453  );
1454  reduceAllImpl<long> (comm, reductType, count, sendBuffer, globalReducts);
1455 }
1456 
1457 template<>
1458 RCP<Teuchos::CommRequest<int> >
1459 ireceive<int, long> (const Comm<int>& comm,
1460  const ArrayRCP<long>& recvBuffer,
1461  const int sourceRank)
1462 {
1463  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, long>");
1464  return ireceiveImpl<long> (comm, recvBuffer, sourceRank);
1465 }
1466 
1467 template<>
1468 RCP<Teuchos::CommRequest<int> >
1469 ireceive<int, long> (const ArrayRCP<long>& recvBuffer,
1470  const int sourceRank,
1471  const int tag,
1472  const Comm<int>& comm)
1473 {
1474  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, long>");
1475  return ireceiveImpl<long> (recvBuffer, sourceRank, tag, comm);
1476 }
1477 
1478 template<>
1479 void
1480 send<int, long> (const Comm<int>& comm,
1481  const int count,
1482  const long sendBuffer[],
1483  const int destRank)
1484 {
1485  return sendImpl<long> (comm, count, sendBuffer, destRank);
1486 }
1487 
1488 template<>
1489 void
1490 send<int, long> (const long sendBuffer[],
1491  const int count,
1492  const int destRank,
1493  const int tag,
1494  const Comm<int>& comm)
1495 {
1496  return sendImpl<long> (sendBuffer, count, destRank, tag, comm);
1497 }
1498 
1499 template<>
1500 RCP<Teuchos::CommRequest<int> >
1501 isend (const ArrayRCP<const long>& sendBuffer,
1502  const int destRank,
1503  const int tag,
1504  const Comm<int>& comm)
1505 {
1506  return isendImpl<long> (sendBuffer, destRank, tag, comm);
1507 }
1508 
1509 
1510 // Specialization for Ordinal=int and Packet=unsigned long.
1511 template<>
1512 void
1513 gather<int, unsigned long> (const unsigned long sendBuf[],
1514  const int sendCount,
1515  unsigned long recvBuf[],
1516  const int recvCount,
1517  const int root,
1518  const Comm<int>& comm)
1519 {
1520  gatherImpl<unsigned long> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1521 }
1522 
1523 template<>
1524 void
1525 gatherv<int, unsigned long> (const unsigned long sendBuf[],
1526  const int sendCount,
1527  unsigned long recvBuf[],
1528  const int recvCounts[],
1529  const int displs[],
1530  const int root,
1531  const Comm<int>& comm)
1532 {
1533  gathervImpl<unsigned long> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1534 }
1535 
1536 template<>
1537 void
1538 reduceAll<int, unsigned long> (const Comm<int>& comm,
1539  const EReductionType reductType,
1540  const int count,
1541  const unsigned long sendBuffer[],
1542  unsigned long globalReducts[])
1543 {
1544  TEUCHOS_COMM_TIME_MONITOR(
1545  "Teuchos::reduceAll<int, unsigned long> (" << count << ", "
1546  << toString (reductType) << ")"
1547  );
1548  reduceAllImpl<unsigned long> (comm, reductType, count, sendBuffer, globalReducts);
1549 }
1550 
1551 template<>
1552 RCP<Teuchos::CommRequest<int> >
1553 ireceive<int, unsigned long> (const Comm<int>& comm,
1554  const ArrayRCP<unsigned long>& recvBuffer,
1555  const int sourceRank)
1556 {
1557  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned long>");
1558  return ireceiveImpl<unsigned long> (comm, recvBuffer, sourceRank);
1559 }
1560 
1561 template<>
1562 RCP<Teuchos::CommRequest<int> >
1563 ireceive<int, unsigned long> (const ArrayRCP<unsigned long>& recvBuffer,
1564  const int sourceRank,
1565  const int tag,
1566  const Comm<int>& comm)
1567 {
1568  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned long>");
1569  return ireceiveImpl<unsigned long> (recvBuffer, sourceRank, tag, comm);
1570 }
1571 
1572 template<>
1573 void
1574 send<int, unsigned long> (const Comm<int>& comm,
1575  const int count,
1576  const unsigned long sendBuffer[],
1577  const int destRank)
1578 {
1579  return sendImpl<unsigned long> (comm, count, sendBuffer, destRank);
1580 }
1581 
1582 template<>
1583 void
1584 send<int, unsigned long> (const unsigned long sendBuffer[],
1585  const int count,
1586  const int destRank,
1587  const int tag,
1588  const Comm<int>& comm)
1589 {
1590  return sendImpl<unsigned long> (sendBuffer, count, destRank, tag, comm);
1591 }
1592 
1593 template<>
1594 RCP<Teuchos::CommRequest<int> >
1595 isend (const ArrayRCP<const unsigned long>& sendBuffer,
1596  const int destRank,
1597  const int tag,
1598  const Comm<int>& comm)
1599 {
1600  return isendImpl<unsigned long> (sendBuffer, destRank, tag, comm);
1601 }
1602 
1603 // Specialization for Ordinal=int and Packet=int.
1604 template<>
1605 void
1606 gather<int, int> (const int sendBuf[],
1607  const int sendCount,
1608  int recvBuf[],
1609  const int recvCount,
1610  const int root,
1611  const Comm<int>& comm)
1612 {
1613  gatherImpl<int> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1614 }
1615 
1616 template<>
1617 void
1618 gatherv<int, int> (const int sendBuf[],
1619  const int sendCount,
1620  int recvBuf[],
1621  const int recvCounts[],
1622  const int displs[],
1623  const int root,
1624  const Comm<int>& comm)
1625 {
1626  gathervImpl<int> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1627 }
1628 
1629 template<>
1630 void
1631 scatter<int, int> (const int sendBuf[],
1632  const int sendCount,
1633  int recvBuf[],
1634  const int recvCount,
1635  const int root,
1636  const Comm<int>& comm)
1637 {
1638  scatterImpl<int> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1639 }
1640 
1641 template<>
1642 void
1643 reduce<int, int> (const int sendBuf[],
1644  int recvBuf[],
1645  const int count,
1646  const EReductionType reductType,
1647  const int root,
1648  const Comm<int>& comm)
1649 {
1650  TEUCHOS_COMM_TIME_MONITOR
1651  ("Teuchos::reduce<int, int> (" << count << ", " << toString (reductType)
1652  << ")");
1653  reduceImpl<int> (sendBuf, recvBuf, count, reductType, root, comm);
1654 }
1655 
1656 template<>
1657 void
1658 reduceAll<int, int> (const Comm<int>& comm,
1659  const EReductionType reductType,
1660  const int count,
1661  const int sendBuffer[],
1662  int globalReducts[])
1663 {
1664  TEUCHOS_COMM_TIME_MONITOR(
1665  "Teuchos::reduceAll<int, int> (" << count << ", "
1666  << toString (reductType) << ")"
1667  );
1668  reduceAllImpl<int> (comm, reductType, count, sendBuffer, globalReducts);
1669 }
1670 
1671 template<>
1672 RCP<Teuchos::CommRequest<int> >
1673 ireceive<int, int> (const Comm<int>& comm,
1674  const ArrayRCP<int>& recvBuffer,
1675  const int sourceRank)
1676 {
1677  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, int>");
1678  return ireceiveImpl<int> (comm, recvBuffer, sourceRank);
1679 }
1680 
1681 template<>
1682 RCP<Teuchos::CommRequest<int> >
1683 ireceive<int, int> (const ArrayRCP<int>& recvBuffer,
1684  const int sourceRank,
1685  const int tag,
1686  const Comm<int>& comm)
1687 {
1688  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, int>");
1689  return ireceiveImpl<int> (recvBuffer, sourceRank, tag, comm);
1690 }
1691 
1692 template<>
1693 void
1694 send<int, int> (const Comm<int>& comm,
1695  const int count,
1696  const int sendBuffer[],
1697  const int destRank)
1698 {
1699  return sendImpl<int> (comm, count, sendBuffer, destRank);
1700 }
1701 
1702 template<>
1703 void
1704 send<int, int> (const int sendBuffer[],
1705  const int count,
1706  const int destRank,
1707  const int tag,
1708  const Comm<int>& comm)
1709 {
1710  return sendImpl<int> (sendBuffer, count, destRank, tag, comm);
1711 }
1712 
1713 template<>
1714 RCP<Teuchos::CommRequest<int> >
1715 isend (const ArrayRCP<const int>& sendBuffer,
1716  const int destRank,
1717  const int tag,
1718  const Comm<int>& comm)
1719 {
1720  return isendImpl<int> (sendBuffer, destRank, tag, comm);
1721 }
1722 
1723 // Specialization for Ordinal=int and Packet=unsigned int.
1724 template<>
1725 void
1726 gather<int, unsigned int> (const unsigned int sendBuf[],
1727  const int sendCount,
1728  unsigned int recvBuf[],
1729  const int recvCount,
1730  const int root,
1731  const Comm<int>& comm)
1732 {
1733  gatherImpl<unsigned int> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1734 }
1735 
1736 template<>
1737 void
1738 gatherv<int, unsigned int> (const unsigned int sendBuf[],
1739  const int sendCount,
1740  unsigned int recvBuf[],
1741  const int recvCounts[],
1742  const int displs[],
1743  const int root,
1744  const Comm<int>& comm)
1745 {
1746  gathervImpl<unsigned int> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1747 }
1748 
1749 template<>
1750 void
1751 reduceAll<int, unsigned int> (const Comm<int>& comm,
1752  const EReductionType reductType,
1753  const int count,
1754  const unsigned int sendBuffer[],
1755  unsigned int globalReducts[])
1756 {
1757  TEUCHOS_COMM_TIME_MONITOR(
1758  "Teuchos::reduceAll<int, unsigned int> (" << count << ", "
1759  << toString (reductType) << ")"
1760  );
1761  reduceAllImpl<unsigned int> (comm, reductType, count, sendBuffer, globalReducts);
1762 }
1763 
1764 template<>
1765 RCP<Teuchos::CommRequest<int> >
1766 ireceive<int, unsigned int> (const Comm<int>& comm,
1767  const ArrayRCP<unsigned int>& recvBuffer,
1768  const int sourceRank)
1769 {
1770  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned int>");
1771  return ireceiveImpl<unsigned int> (comm, recvBuffer, sourceRank);
1772 }
1773 
1774 template<>
1775 RCP<Teuchos::CommRequest<int> >
1776 ireceive<int, unsigned int> (const ArrayRCP<unsigned int>& recvBuffer,
1777  const int sourceRank,
1778  const int tag,
1779  const Comm<int>& comm)
1780 {
1781  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned int>");
1782  return ireceiveImpl<unsigned int> (recvBuffer, sourceRank, tag, comm);
1783 }
1784 
1785 template<>
1786 void
1787 send<int, unsigned int> (const Comm<int>& comm,
1788  const int count,
1789  const unsigned int sendBuffer[],
1790  const int destRank)
1791 {
1792  return sendImpl<unsigned int> (comm, count, sendBuffer, destRank);
1793 }
1794 
1795 template<>
1796 void
1797 send<int, unsigned int> (const unsigned int sendBuffer[],
1798  const int count,
1799  const int destRank,
1800  const int tag,
1801  const Comm<int>& comm)
1802 {
1803  return sendImpl<unsigned int> (sendBuffer, count, destRank, tag, comm);
1804 }
1805 
1806 template<>
1807 RCP<Teuchos::CommRequest<int> >
1808 isend (const ArrayRCP<const unsigned int>& sendBuffer,
1809  const int destRank,
1810  const int tag,
1811  const Comm<int>& comm)
1812 {
1813  return isendImpl<unsigned int> (sendBuffer, destRank, tag, comm);
1814 }
1815 
1816 
1817 // Specialization for Ordinal=int and Packet=short.
1818 template<>
1819 void
1820 gather<int, short> (const short sendBuf[],
1821  const int sendCount,
1822  short recvBuf[],
1823  const int recvCount,
1824  const int root,
1825  const Comm<int>& comm)
1826 {
1827  gatherImpl<short> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1828 }
1829 
1830 template<>
1831 void
1832 gatherv<int, short> (const short sendBuf[],
1833  const int sendCount,
1834  short recvBuf[],
1835  const int recvCounts[],
1836  const int displs[],
1837  const int root,
1838  const Comm<int>& comm)
1839 {
1840  gathervImpl<short> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1841 }
1842 
1843 template<>
1844 void
1845 reduceAll<int, short> (const Comm<int>& comm,
1846  const EReductionType reductType,
1847  const int count,
1848  const short sendBuffer[],
1849  short globalReducts[])
1850 {
1851  TEUCHOS_COMM_TIME_MONITOR(
1852  "Teuchos::reduceAll<int, short> (" << count << ", "
1853  << toString (reductType) << ")"
1854  );
1855  reduceAllImpl<short> (comm, reductType, count, sendBuffer, globalReducts);
1856 }
1857 
1858 template<>
1859 RCP<Teuchos::CommRequest<int> >
1860 ireceive<int, short> (const Comm<int>& comm,
1861  const ArrayRCP<short>& recvBuffer,
1862  const int sourceRank)
1863 {
1864  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, short>");
1865  return ireceiveImpl<short> (comm, recvBuffer, sourceRank);
1866 }
1867 
1868 template<>
1869 RCP<Teuchos::CommRequest<int> >
1870 ireceive<int, short> (const ArrayRCP<short>& recvBuffer,
1871  const int sourceRank,
1872  const int tag,
1873  const Comm<int>& comm)
1874 {
1875  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, short>");
1876  return ireceiveImpl<short> (recvBuffer, sourceRank, tag, comm);
1877 }
1878 
1879 template<>
1880 void
1881 send<int, short> (const Comm<int>& comm,
1882  const int count,
1883  const short sendBuffer[],
1884  const int destRank)
1885 {
1886  return sendImpl<short> (comm, count, sendBuffer, destRank);
1887 }
1888 
1889 template<>
1890 void
1891 send<int, short> (const short sendBuffer[],
1892  const int count,
1893  const int destRank,
1894  const int tag,
1895  const Comm<int>& comm)
1896 {
1897  return sendImpl<short> (sendBuffer, count, destRank, tag, comm);
1898 }
1899 
1900 template<>
1901 RCP<Teuchos::CommRequest<int> >
1902 isend (const ArrayRCP<const short>& sendBuffer,
1903  const int destRank,
1904  const int tag,
1905  const Comm<int>& comm)
1906 {
1907  return isendImpl<short> (sendBuffer, destRank, tag, comm);
1908 }
1909 
1910 // mfh 18 Oct 2012: The specialization for Packet=char seems to be
1911 // causing problems such as the following:
1912 //
1913 // http://testing.sandia.gov/cdash/testDetails.php?test=9909246&build=747699
1914 //
1915 // I am disabling it for now. This should revert back to the old
1916 // behavior for Packet=char. That should fix the Tpetra errors, since
1917 // many Tpetra objects inherit from DistObject<char, ...>.
1918 #if 0
1919 // Specialization for Ordinal=int and Packet=char.
1920 template<>
1921 void
1922 reduceAll<int, char> (const Comm<int>& comm,
1923  const EReductionType reductType,
1924  const int count,
1925  const char sendBuffer[],
1926  char globalReducts[])
1927 {
1928  TEUCHOS_COMM_TIME_MONITOR(
1929  "Teuchos::reduceAll<int, char> (" << count << ", "
1930  << toString (reductType) << ")"
1931  );
1932  reduceAllImpl<char> (comm, reductType, count, sendBuffer, globalReducts);
1933 }
1934 #endif // 0
1935 
1936 } // namespace Teuchos
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
TEUCHOS_DEPRECATED void reduceAll(const Comm< Ordinal > &comm, const EReductionType reductType, const Packet &send, Packet *globalReduct)
Deprecated .
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos, as well as a number of utility routines.