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