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 
489 
497 template<class T>
498 void
499 reduceAllAndScatterImpl (const Comm<int>& comm,
500  const EReductionType reductType,
501  const int sendCount,
502  const T sendBuffer[],
503  const int recvCounts[],
504  T myGlobalReducts[])
505 {
506 #ifdef HAVE_MPI
507  // mfh 17 Oct 2012: Even in an MPI build, Comm might be either a
508  // SerialComm or an MpiComm. If it's something else, we fall back
509  // to the most general implementation.
510  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
511  if (mpiComm == NULL) {
512  // Is it a SerialComm?
513  const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
514  if (serialComm == NULL) {
515  TEUCHOS_TEST_FOR_EXCEPTION(true, std::logic_error, "reduceAllAndScatter: "
516  "Not implemented for Comm not MpiComm or SerialComm.");
517  }
518  else { // It's a SerialComm; there is only 1 process, so just copy.
519  //
520  // FIXME (mfh 09 Apr 2013) Is this right? This is what
521  // SerialComm does.
522  //
523  std::copy (sendBuffer, sendBuffer + sendCount, myGlobalReducts);
524  }
525  } else { // It's an MpiComm. Invoke MPI directly.
526  MPI_Op rawMpiOp = getMpiOpForEReductionType (reductType);
527  MPI_Comm rawMpiComm = * (mpiComm->getRawMpiComm ());
528  T t;
529  MPI_Datatype rawMpiType = MpiTypeTraits<T>::getType (t);
530  const int err = MPI_Reduce_scatter (const_cast<T*> (sendBuffer),
531  myGlobalReducts,
532  const_cast<int*> (recvCounts),
533  rawMpiType,
534  rawMpiOp,
535  rawMpiComm);
537  err != MPI_SUCCESS,
538  std::runtime_error,
539  "MPI_Reduce_scatter failed with the following error: "
540  << getMpiErrorString (err));
541  }
542 #else
543  // We've built without MPI, so just assume it's a SerialComm and copy the data.
544  //
545  // FIXME (mfh 09 Apr 2013) Is this right? This is what SerialComm does.
546  //
547  std::copy (sendBuffer, sendBuffer + sendCount, myGlobalReducts);
548 #endif // HAVE_MPI
549 }
550 
551 
557 template<typename Packet>
558 RCP<Teuchos::CommRequest<int> >
559 ireceiveGeneral(const Comm<int>& comm,
560  const ArrayRCP<Packet> &recvBuffer,
561  const int sourceRank)
562 {
563  TEUCHOS_COMM_TIME_MONITOR(
564  "Teuchos::ireceive<int, " << "," << TypeNameTraits<Packet>::name ()
565  << "> ( value type )"
566  );
567  ValueTypeSerializationBuffer<int, Packet>
568  charRecvBuffer (recvBuffer.size (), recvBuffer.getRawPtr ());
569  RCP<CommRequest<int> > commRequest =
570  comm.ireceive (charRecvBuffer.getCharBufferView (), sourceRank);
571  set_extra_data (recvBuffer, "buffer", inOutArg (commRequest));
572  return commRequest;
573 }
574 
577 template<typename Packet>
578 RCP<Teuchos::CommRequest<int> >
579 ireceiveGeneral (const ArrayRCP<Packet> &recvBuffer,
580  const int sourceRank,
581  const int tag,
582  const Comm<int>& comm)
583 {
584  TEUCHOS_COMM_TIME_MONITOR(
585  "Teuchos::ireceive<int, " << "," << TypeNameTraits<Packet>::name ()
586  << "> ( value type )"
587  );
588  ValueTypeSerializationBuffer<int, Packet>
589  charRecvBuffer (recvBuffer.size (), recvBuffer.getRawPtr ());
590  RCP<CommRequest<int> > commRequest =
591  comm.ireceive (charRecvBuffer.getCharBufferView (), sourceRank, tag);
592  set_extra_data (recvBuffer, "buffer", inOutArg (commRequest));
593  return commRequest;
594 }
595 
608 template<class T>
609 RCP<CommRequest<int> >
610 ireceiveImpl (const Comm<int>& comm,
611  const ArrayRCP<T>& recvBuffer,
612  const int sourceRank)
613 {
614 #ifdef HAVE_MPI
615  // Even in an MPI build, Comm might be either a SerialComm or an
616  // MpiComm. If it's something else, we fall back to the most
617  // general implementation.
618  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
619  if (mpiComm == NULL) {
620  // Is it a SerialComm?
621  const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
622  if (serialComm == NULL) {
623  // We don't know what kind of Comm we have, so fall back to the
624  // most general implementation.
625  return ireceiveGeneral<T> (comm, recvBuffer, sourceRank);
626  }
627  else { // SerialComm doesn't implement ireceive anyway.
629  true,
630  std::logic_error,
631  "ireceiveImpl: Not implemented for a serial communicator.");
632  }
633  }
634  else { // It's an MpiComm. Invoke MPI directly.
635  MPI_Comm rawComm = * (mpiComm->getRawMpiComm ());
636  T t;
637  MPI_Datatype rawType = MpiTypeTraits<T>::getType (t);
638  T* rawRecvBuf = recvBuffer.getRawPtr ();
639  const int count = as<int> (recvBuffer.size ());
640  const int tag = mpiComm->getTag ();
641  MPI_Request rawRequest = MPI_REQUEST_NULL;
642  const int err = MPI_Irecv (rawRecvBuf, count, rawType, sourceRank, tag,
643  rawComm, &rawRequest);
645  err != MPI_SUCCESS, std::runtime_error,
646  "MPI_Irecv failed with the following error: "
647  << getMpiErrorString (err));
648 
649  ArrayRCP<const char> buf =
650  arcp_const_cast<const char> (arcp_reinterpret_cast<char> (recvBuffer));
651  RCP<Details::MpiCommRequest> req (new Details::MpiCommRequest (rawRequest, buf));
652  return rcp_implicit_cast<CommRequest<int> > (req);
653  }
654 #else
656  true,
657  std::logic_error,
658  "ireceiveImpl: Not implemented for a serial communicator.");
659 
660  // NOTE (mfh 15 Sep 2014): Most compilers have figured out that the
661  // return statement below is unreachable. Some older compilers
662  // might not realize this. That's why the return statement was put
663  // there, so that those compilers don't warn that this function
664  // doesn't return a value. If it's a choice between one warning and
665  // another, I would prefer the choice that produces less code and
666  // doesn't have unreachable code (which never gets tested).
667 
668  //return null; // Guard to avoid compiler warning about not returning a value.
669 #endif // HAVE_MPI
670 }
671 
674 template<class T>
675 RCP<CommRequest<int> >
676 ireceiveImpl (const ArrayRCP<T>& recvBuffer,
677  const int sourceRank,
678  const int tag,
679  const Comm<int>& comm)
680 {
681 #ifdef HAVE_MPI
682  // Even in an MPI build, Comm might be either a SerialComm or an
683  // MpiComm. If it's something else, we fall back to the most
684  // general implementation.
685  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
686  if (mpiComm == NULL) {
687  // Is it a SerialComm?
688  const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
689  if (serialComm == NULL) {
690  // We don't know what kind of Comm we have, so fall back to the
691  // most general implementation.
692  return ireceiveGeneral<T> (recvBuffer, sourceRank, tag, comm);
693  }
694  else { // SerialComm doesn't implement ireceive anyway.
696  true,
697  std::logic_error,
698  "ireceiveImpl: Not implemented for a serial communicator.");
699  }
700  }
701  else { // It's an MpiComm. Invoke MPI directly.
702  MPI_Comm rawComm = * (mpiComm->getRawMpiComm ());
703  T t;
704  MPI_Datatype rawType = MpiTypeTraits<T>::getType (t);
705  T* rawRecvBuf = recvBuffer.getRawPtr ();
706  const int count = as<int> (recvBuffer.size ());
707  MPI_Request rawRequest = MPI_REQUEST_NULL;
708  const int err = MPI_Irecv (rawRecvBuf, count, rawType, sourceRank, tag,
709  rawComm, &rawRequest);
711  err != MPI_SUCCESS, std::runtime_error,
712  "MPI_Irecv failed with the following error: "
713  << getMpiErrorString (err));
714 
715  ArrayRCP<const char> buf =
716  arcp_const_cast<const char> (arcp_reinterpret_cast<char> (recvBuffer));
717  RCP<Details::MpiCommRequest> req (new Details::MpiCommRequest (rawRequest, buf));
718  return rcp_implicit_cast<CommRequest<int> > (req);
719  }
720 #else
722  true,
723  std::logic_error,
724  "ireceiveImpl: Not implemented for a serial communicator.");
725 
726  return null; // Guard to avoid compiler warning about not returning a value.
727 #endif // HAVE_MPI
728 }
729 
735 template<class T>
736 void
737 sendGeneral (const Comm<int>& comm,
738  const int count,
739  const T sendBuffer[],
740  const int destRank)
741 {
742  TEUCHOS_COMM_TIME_MONITOR(
743  "Teuchos::send<int, " << TypeNameTraits<T>::name () << ">");
744  ConstValueTypeSerializationBuffer<int,T> charSendBuffer (count, sendBuffer);
745  comm.send (charSendBuffer.getBytes (),
746  charSendBuffer.getCharBuffer (),
747  destRank);
748 }
749 
752 template<class T>
753 void
754 sendGeneral (const T sendBuffer[],
755  const int count,
756  const int destRank,
757  const int tag,
758  const Comm<int>& comm)
759 {
760  TEUCHOS_COMM_TIME_MONITOR(
761  "Teuchos::send<int, " << TypeNameTraits<T>::name () << ">");
762  ConstValueTypeSerializationBuffer<int,T> charSendBuffer (count, sendBuffer);
763  comm.send (charSendBuffer.getBytes (),
764  charSendBuffer.getCharBuffer (),
765  destRank, tag);
766 }
767 
780 template<class T>
781 void
782 sendImpl (const Comm<int>& comm,
783  const int count,
784  const T sendBuffer[],
785  const int destRank)
786 {
787 #ifdef HAVE_MPI
788  // Even in an MPI build, Comm might be either a SerialComm or an
789  // MpiComm. If it's something else, we fall back to the most
790  // general implementation.
791  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
792  if (mpiComm == NULL) {
793  // Is it a SerialComm?
794  const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
795  if (serialComm == NULL) {
796  // We don't know what kind of Comm we have, so fall back to the
797  // most general implementation.
798  sendGeneral<T> (comm, count, sendBuffer, destRank);
799  }
800  else { // SerialComm doesn't implement send correctly anyway.
802  true,
803  std::logic_error,
804  "sendImpl: Not implemented for a serial communicator.");
805  }
806  }
807  else { // It's an MpiComm. Invoke MPI directly.
808  MPI_Comm rawComm = * (mpiComm->getRawMpiComm ());
809  T t;
810  MPI_Datatype rawType = MpiTypeTraits<T>::getType (t);
811  T* rawBuf = const_cast<T*> (sendBuffer);
812  const int tag = mpiComm->getTag ();
813  const int err = MPI_Send (rawBuf, count, rawType, destRank, tag, rawComm);
815  err != MPI_SUCCESS,
816  std::runtime_error,
817  "MPI_Send failed with the following error: "
818  << getMpiErrorString (err));
819  }
820 #else
822  true,
823  std::logic_error,
824  "sendImpl: Not implemented for a serial communicator.");
825 #endif // HAVE_MPI
826 }
827 
830 template<class T>
831 void
832 sendImpl (const T sendBuffer[],
833  const int count,
834  const int destRank,
835  const int tag,
836  const Comm<int>& comm)
837 {
838 #ifdef HAVE_MPI
839  // Even in an MPI build, Comm might be either a SerialComm or an
840  // MpiComm. If it's something else, we fall back to the most
841  // general implementation.
842  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
843  if (mpiComm == NULL) {
844  // Is it a SerialComm?
845  const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
846  if (serialComm == NULL) {
847  // We don't know what kind of Comm we have, so fall back to the
848  // most general implementation.
849  sendGeneral<T> (sendBuffer, count, destRank, tag, comm);
850  }
851  else { // SerialComm doesn't implement send correctly anyway.
853  true,
854  std::logic_error,
855  "sendImpl: Not implemented for a serial communicator.");
856  }
857  }
858  else { // It's an MpiComm. Invoke MPI directly.
859  MPI_Comm rawComm = * (mpiComm->getRawMpiComm ());
860  T t;
861  MPI_Datatype rawType = MpiTypeTraits<T>::getType (t);
862  T* rawBuf = const_cast<T*> (sendBuffer);
863  const int err = MPI_Send (rawBuf, count, rawType, destRank, tag, rawComm);
865  err != MPI_SUCCESS,
866  std::runtime_error,
867  "MPI_Send failed with the following error: "
868  << getMpiErrorString (err));
869  }
870 #else
872  true,
873  std::logic_error,
874  "sendImpl: Not implemented for a serial communicator.");
875 #endif // HAVE_MPI
876 }
877 
883 template<class T>
884 RCP<CommRequest<int> >
885 isendGeneral (const Comm<int>& comm,
886  const ArrayRCP<const T>& sendBuffer,
887  const int destRank)
888 {
889  TEUCHOS_COMM_TIME_MONITOR(
890  "Teuchos::isend<int," << TypeNameTraits<T>::name () << ">");
891  ConstValueTypeSerializationBuffer<int, T>
892  charSendBuffer (sendBuffer.size (), sendBuffer.getRawPtr ());
893  RCP<CommRequest<int> > commRequest =
894  comm.isend (charSendBuffer.getCharBufferView (), destRank);
895  set_extra_data (sendBuffer, "buffer", inOutArg (commRequest));
896  return commRequest;
897 }
898 
905 template<class T>
906 RCP<CommRequest<int> >
907 isendGeneral (const ArrayRCP<const T>& sendBuffer,
908  const int destRank,
909  const int tag,
910  const Comm<int>& comm)
911 {
912  TEUCHOS_COMM_TIME_MONITOR(
913  "Teuchos::isend<int," << TypeNameTraits<T>::name () << ">");
914  ConstValueTypeSerializationBuffer<int, T>
915  charSendBuffer (sendBuffer.size (), sendBuffer.getRawPtr ());
916  RCP<CommRequest<int> > commRequest =
917  comm.isend (charSendBuffer.getCharBufferView (), destRank, tag);
918  set_extra_data (sendBuffer, "buffer", inOutArg (commRequest));
919  return commRequest;
920 }
921 
924 template<class T>
925 RCP<Teuchos::CommRequest<int> >
926 isendImpl (const ArrayRCP<const T>& sendBuffer,
927  const int destRank,
928  const int tag,
929  const Comm<int>& comm)
930 {
931 #ifdef HAVE_MPI
932  // Even in an MPI build, Comm might be either a SerialComm or an
933  // MpiComm. If it's something else, we fall back to the most
934  // general implementation.
935  const MpiComm<int>* mpiComm = dynamic_cast<const MpiComm<int>* > (&comm);
936  if (mpiComm == NULL) {
937  // Is it a SerialComm?
938  const SerialComm<int>* serialComm = dynamic_cast<const SerialComm<int>* > (&comm);
939  if (serialComm == NULL) {
940  // We don't know what kind of Comm we have, so fall back to the
941  // most general implementation.
942  return isendGeneral<T> (sendBuffer, destRank, tag, comm);
943  }
944  else { // SerialComm doesn't implement send correctly anyway.
946  true, std::logic_error,
947  "isendImpl: Not implemented for a serial communicator.");
948  }
949  }
950  else { // It's an MpiComm. Invoke MPI directly.
951  MPI_Comm rawComm = * (mpiComm->getRawMpiComm ());
952  T t;
953  MPI_Datatype rawType = MpiTypeTraits<T>::getType (t);
954  // MPI promises not to modify the send buffer; the const_cast
955  // merely ensures compatibilty with C89, which does not have a
956  // "const" keyword.
957  T* rawSendBuf = const_cast<T*> (sendBuffer.getRawPtr ());
958  const int count = as<int> (sendBuffer.size ());
959  MPI_Request rawRequest = MPI_REQUEST_NULL;
960  const int err = MPI_Isend (rawSendBuf, count, rawType, destRank, tag,
961  rawComm, &rawRequest);
963  err != MPI_SUCCESS,
964  std::runtime_error,
965  "MPI_Isend failed with the following error: "
966  << getMpiErrorString (err));
967 
968  ArrayRCP<const char> buf = arcp_reinterpret_cast<const char> (sendBuffer);
969  RCP<Details::MpiCommRequest> req (new Details::MpiCommRequest (rawRequest, buf));
970  return rcp_implicit_cast<CommRequest<int> > (req);
971  }
972 #else
974  true,
975  std::logic_error,
976  "isendImpl: Not implemented for a serial communicator.");
977 #endif // HAVE_MPI
978 }
979 
980 } // namespace (anonymous)
981 
982 
983 const char*
984 toString (const EReductionType reductType)
985 {
986  switch (reductType) {
987  case REDUCE_SUM: return "REDUCE_SUM";
988  case REDUCE_MIN: return "REDUCE_MIN";
989  case REDUCE_MAX: return "REDUCE_MAX";
990  case REDUCE_AND: return "REDUCE_AND";
991  default:
993  true, std::invalid_argument, "Teuchos::toString(EReductionType): "
994  "Invalid EReductionType value " << reductType << ". Valid values "
995  "include REDUCE_SUM = " << REDUCE_SUM << ", REDUCE_MIN = " << REDUCE_MIN
996  << ", REDUCE_MAX = " << REDUCE_MIN << ", and REDUCE_AND = " << REDUCE_AND
997  << ".");
998  }
999 }
1000 
1001 
1002 // mfh 18 Oct 2012: Note on full template specializations
1003 //
1004 // To make Windows builds happy, declarations of full template
1005 // specializations (as found in Teuchos_CommHelpers.hpp) must use the
1006 // TEUCHOSCOMM_LIB_DLL_EXPORT macro. However, _definitions_ of the
1007 // specializations (as found in this file) must _not_ use the macro.
1008 // That's why we don't use that macro here.
1009 
1010 // amb See note in .hpp file.
1011 #if 0
1012 #ifdef HAVE_TEUCHOS_COMPLEX
1013 // Specialization for Ordinal=int and Packet=std::complex<double>.
1014 template<>
1015 void
1016 reduceAll<int, std::complex<double> > (const Comm<int>& comm,
1017  const EReductionType reductType,
1018  const int count,
1019  const std::complex<double> sendBuffer[],
1020  std::complex<double> globalReducts[])
1021 {
1022  TEUCHOS_COMM_TIME_MONITOR(
1023  "Teuchos::reduceAll<int, std::complex<double> > (" << count << ", "
1024  << toString (reductType) << ")"
1025  );
1026  reduceAllImpl<std::complex<double> > (comm, reductType, count, sendBuffer, globalReducts);
1027 }
1028 
1029 template<>
1030 RCP<Teuchos::CommRequest<int> >
1031 ireceive<int, std::complex<double> > (const Comm<int>& comm,
1032  const ArrayRCP<std::complex<double> >& recvBuffer,
1033  const int sourceRank)
1034 {
1035  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, std::complex<double> >");
1036  return ireceiveImpl<std::complex<double> > (comm, recvBuffer, sourceRank);
1037 }
1038 
1039 template<>
1040 RCP<Teuchos::CommRequest<int> >
1041 ireceive<int, std::complex<double> > (const ArrayRCP<std::complex<double> >& recvBuffer,
1042  const int sourceRank,
1043  const int tag,
1044  const Comm<int>& comm)
1045 {
1046  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, std::complex<double> >");
1047  return ireceiveImpl<std::complex<double> > (recvBuffer, sourceRank, tag, comm);
1048 }
1049 
1050 template<>
1051 void
1052 send<int, std::complex<double> > (const Comm<int>& comm,
1053  const int count,
1054  const std::complex<double> sendBuffer[],
1055  const int destRank)
1056 {
1057  sendImpl<std::complex<double> > (comm, count, sendBuffer, destRank);
1058 }
1059 
1060 template<>
1061 void
1062 send<int, std::complex<double> > (const std::complex<double> sendBuffer[],
1063  const int count,
1064  const int destRank,
1065  const int tag,
1066  const Comm<int>& comm)
1067 {
1068  sendImpl<std::complex<double> > (sendBuffer, count, destRank, tag, comm);
1069 }
1070 
1071 template<>
1072 RCP<Teuchos::CommRequest<int> >
1073 isend (const ArrayRCP<const std::complex<double> >& sendBuffer,
1074  const int destRank,
1075  const int tag,
1076  const Comm<int>& comm)
1077 {
1078  return isendImpl<std::complex<double> > (sendBuffer, destRank, tag, comm);
1079 }
1080 
1081 // Specialization for Ordinal=int and Packet=std::complex<float>.
1082 template<>
1083 void
1084 reduceAll<int, std::complex<float> > (const Comm<int>& comm,
1085  const EReductionType reductType,
1086  const int count,
1087  const std::complex<float> sendBuffer[],
1088  std::complex<float> globalReducts[])
1089 {
1090  TEUCHOS_COMM_TIME_MONITOR(
1091  "Teuchos::reduceAll<int, std::complex<float> > (" << count << ", "
1092  << toString (reductType) << ")"
1093  );
1094  reduceAllImpl<std::complex<float> > (comm, reductType, count, sendBuffer, globalReducts);
1095 }
1096 
1097 template<>
1098 RCP<Teuchos::CommRequest<int> >
1099 ireceive<int, std::complex<float> > (const Comm<int>& comm,
1100  const ArrayRCP<std::complex<float> >& recvBuffer,
1101  const int sourceRank)
1102 {
1103  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, std::complex<float> >");
1104  return ireceiveImpl<std::complex<float> > (comm, recvBuffer, sourceRank);
1105 }
1106 
1107 template<>
1108 RCP<Teuchos::CommRequest<int> >
1109 ireceive<int, std::complex<float> > (const ArrayRCP<std::complex<float> >& recvBuffer,
1110  const int sourceRank,
1111  const int tag,
1112  const Comm<int>& comm)
1113 {
1114  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, std::complex<float> >");
1115  return ireceiveImpl<std::complex<float> > (recvBuffer, sourceRank, tag, comm);
1116 }
1117 
1118 template<>
1119 void
1120 send<int, std::complex<float> > (const Comm<int>& comm,
1121  const int count,
1122  const std::complex<float> sendBuffer[],
1123  const int destRank)
1124 {
1125  return sendImpl<std::complex<float> > (comm, count, sendBuffer, destRank);
1126 }
1127 
1128 template<>
1129 void
1130 send<int, std::complex<float> > (const std::complex<float> sendBuffer[],
1131  const int count,
1132  const int destRank,
1133  const int tag,
1134  const Comm<int>& comm)
1135 {
1136  return sendImpl<std::complex<float> > (sendBuffer, count, destRank, tag, comm);
1137 }
1138 
1139 template<>
1140 RCP<Teuchos::CommRequest<int> >
1141 isend (const ArrayRCP<const std::complex<float> >& sendBuffer,
1142  const int destRank,
1143  const int tag,
1144  const Comm<int>& comm)
1145 {
1146  return isendImpl<std::complex<float> > (sendBuffer, destRank, tag, comm);
1147 }
1148 #endif // HAVE_TEUCHOS_COMPLEX
1149 #endif // if 0
1150 
1151 
1152 // Specialization for Ordinal=int and Packet=double.
1153 template<>
1154 void
1155 reduceAll<int, double> (const Comm<int>& comm,
1156  const EReductionType reductType,
1157  const int count,
1158  const double sendBuffer[],
1159  double globalReducts[])
1160 {
1161  TEUCHOS_COMM_TIME_MONITOR(
1162  "Teuchos::reduceAll<int, double> (" << count << ", "
1163  << toString (reductType) << ")"
1164  );
1165  reduceAllImpl<double> (comm, reductType, count, sendBuffer, globalReducts);
1166 }
1167 
1168 template<>
1169 RCP<Teuchos::CommRequest<int> >
1170 ireceive<int, double> (const Comm<int>& comm,
1171  const ArrayRCP<double>& recvBuffer,
1172  const int sourceRank)
1173 {
1174  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, double>");
1175  return ireceiveImpl<double> (comm, recvBuffer, sourceRank);
1176 }
1177 
1178 template<>
1179 RCP<Teuchos::CommRequest<int> >
1180 ireceive<int, double> (const ArrayRCP<double>& recvBuffer,
1181  const int sourceRank,
1182  const int tag,
1183  const Comm<int>& comm)
1184 {
1185  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, double>");
1186  return ireceiveImpl<double> (recvBuffer, sourceRank, tag, comm);
1187 }
1188 
1189 template<>
1190 void
1191 send<int, double> (const Comm<int>& comm,
1192  const int count,
1193  const double sendBuffer[],
1194  const int destRank)
1195 {
1196  return sendImpl<double> (comm, count, sendBuffer, destRank);
1197 }
1198 
1199 template<>
1200 void
1201 send<int, double> (const double sendBuffer[],
1202  const int count,
1203  const int destRank,
1204  const int tag,
1205  const Comm<int>& comm)
1206 {
1207  return sendImpl<double> (sendBuffer, count, destRank, tag, comm);
1208 }
1209 
1210 template<>
1211 RCP<Teuchos::CommRequest<int> >
1212 isend (const ArrayRCP<const double>& sendBuffer,
1213  const int destRank,
1214  const int tag,
1215  const Comm<int>& comm)
1216 {
1217  return isendImpl<double> (sendBuffer, destRank, tag, comm);
1218 }
1219 
1220 // Specialization for Ordinal=int and Packet=float.
1221 template<>
1222 void
1223 reduceAll<int, float> (const Comm<int>& comm,
1224  const EReductionType reductType,
1225  const int count,
1226  const float sendBuffer[],
1227  float globalReducts[])
1228 {
1229  TEUCHOS_COMM_TIME_MONITOR(
1230  "Teuchos::reduceAll<int, float> (" << count << ", "
1231  << toString (reductType) << ")"
1232  );
1233  reduceAllImpl<float> (comm, reductType, count, sendBuffer, globalReducts);
1234 }
1235 
1236 template<>
1237 RCP<Teuchos::CommRequest<int> >
1238 ireceive<int, float> (const Comm<int>& comm,
1239  const ArrayRCP<float>& recvBuffer,
1240  const int sourceRank)
1241 {
1242  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, float>");
1243  return ireceiveImpl<float> (comm, recvBuffer, sourceRank);
1244 }
1245 
1246 template<>
1247 RCP<Teuchos::CommRequest<int> >
1248 ireceive<int, float> (const ArrayRCP<float>& recvBuffer,
1249  const int sourceRank,
1250  const int tag,
1251  const Comm<int>& comm)
1252 {
1253  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, float>");
1254  return ireceiveImpl<float> (recvBuffer, sourceRank, tag, comm);
1255 }
1256 
1257 template<>
1258 void
1259 send<int, float> (const Comm<int>& comm,
1260  const int count,
1261  const float sendBuffer[],
1262  const int destRank)
1263 {
1264  return sendImpl<float> (comm, count, sendBuffer, destRank);
1265 }
1266 
1267 template<>
1268 void
1269 send<int, float> (const float sendBuffer[],
1270  const int count,
1271  const int destRank,
1272  const int tag,
1273  const Comm<int>& comm)
1274 {
1275  return sendImpl<float> (sendBuffer, count, destRank, tag, comm);
1276 }
1277 
1278 template<>
1279 RCP<Teuchos::CommRequest<int> >
1280 isend (const ArrayRCP<const float>& sendBuffer,
1281  const int destRank,
1282  const int tag,
1283  const Comm<int>& comm)
1284 {
1285  return isendImpl<float> (sendBuffer, destRank, tag, comm);
1286 }
1287 
1288 
1289 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
1290 // Specialization for Ordinal=int and Packet=long long.
1291 template<>
1292 void
1293 gather<int, long long> (const long long sendBuf[],
1294  const int sendCount,
1295  long long recvBuf[],
1296  const int recvCount,
1297  const int root,
1298  const Comm<int>& comm)
1299 {
1300  gatherImpl<long long> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1301 }
1302 
1303 template<>
1304 void
1305 gatherv<int, long long> (const long long sendBuf[],
1306  const int sendCount,
1307  long long recvBuf[],
1308  const int recvCounts[],
1309  const int displs[],
1310  const int root,
1311  const Comm<int>& comm)
1312 {
1313  gathervImpl<long long> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1314 }
1315 
1316 template<>
1317 void
1318 reduceAll<int, long long> (const Comm<int>& comm,
1319  const EReductionType reductType,
1320  const int count,
1321  const long long sendBuffer[],
1322  long long globalReducts[])
1323 {
1324  TEUCHOS_COMM_TIME_MONITOR(
1325  "Teuchos::reduceAll<int, long long> (" << count << ", "
1326  << toString (reductType) << ")"
1327  );
1328  reduceAllImpl<long long> (comm, reductType, count, sendBuffer, globalReducts);
1329 }
1330 
1331 template<>
1332 RCP<Teuchos::CommRequest<int> >
1333 ireceive<int, long long> (const Comm<int>& comm,
1334  const ArrayRCP<long long>& recvBuffer,
1335  const int sourceRank)
1336 {
1337  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, long long>");
1338  return ireceiveImpl<long long> (comm, recvBuffer, sourceRank);
1339 }
1340 
1341 template<>
1342 RCP<Teuchos::CommRequest<int> >
1343 ireceive<int, long long> (const ArrayRCP<long long>& recvBuffer,
1344  const int sourceRank,
1345  const int tag,
1346  const Comm<int>& comm)
1347 {
1348  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, long long>");
1349  return ireceiveImpl<long long> (recvBuffer, sourceRank, tag, comm);
1350 }
1351 
1352 template<>
1353 void
1354 send<int, long long> (const Comm<int>& comm,
1355  const int count,
1356  const long long sendBuffer[],
1357  const int destRank)
1358 {
1359  return sendImpl<long long> (comm, count, sendBuffer, destRank);
1360 }
1361 
1362 template<>
1363 void
1364 send<int, long long> (const long long sendBuffer[],
1365  const int count,
1366  const int destRank,
1367  const int tag,
1368  const Comm<int>& comm)
1369 {
1370  return sendImpl<long long> (sendBuffer, count, destRank, tag, comm);
1371 }
1372 
1373 template<>
1374 RCP<Teuchos::CommRequest<int> >
1375 isend (const ArrayRCP<const long long>& sendBuffer,
1376  const int destRank,
1377  const int tag,
1378  const Comm<int>& comm)
1379 {
1380  return isendImpl<long long> (sendBuffer, destRank, tag, comm);
1381 }
1382 
1383 // Specialization for Ordinal=int and Packet=unsigned long long.
1384 template<>
1385 void
1386 gather<int, unsigned long long> (const unsigned long long sendBuf[],
1387  const int sendCount,
1388  unsigned long long recvBuf[],
1389  const int recvCount,
1390  const int root,
1391  const Comm<int>& comm)
1392 {
1393  gatherImpl<unsigned long long> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1394 }
1395 
1396 template<>
1397 void
1398 gatherv<int, unsigned long long> (const unsigned long long sendBuf[],
1399  const int sendCount,
1400  unsigned long long recvBuf[],
1401  const int recvCounts[],
1402  const int displs[],
1403  const int root,
1404  const Comm<int>& comm)
1405 {
1406  gathervImpl<unsigned long long> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1407 }
1408 
1409 template<>
1410 void
1411 reduceAll<int, unsigned long long> (const Comm<int>& comm,
1412  const EReductionType reductType,
1413  const int count,
1414  const unsigned long long sendBuffer[],
1415  unsigned long long globalReducts[])
1416 {
1417  TEUCHOS_COMM_TIME_MONITOR(
1418  "Teuchos::reduceAll<int, unsigned long long> (" << count << ", "
1419  << toString (reductType) << ")"
1420  );
1421  reduceAllImpl<unsigned long long> (comm, reductType, count, sendBuffer, globalReducts);
1422 }
1423 
1424 template<>
1425 RCP<Teuchos::CommRequest<int> >
1426 ireceive<int, unsigned long long> (const Comm<int>& comm,
1427  const ArrayRCP<unsigned long long>& recvBuffer,
1428  const int sourceRank)
1429 {
1430  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned long long>");
1431  return ireceiveImpl<unsigned long long> (comm, recvBuffer, sourceRank);
1432 }
1433 
1434 template<>
1435 RCP<Teuchos::CommRequest<int> >
1436 ireceive<int, unsigned long long> (const ArrayRCP<unsigned long long>& recvBuffer,
1437  const int sourceRank,
1438  const int tag,
1439  const Comm<int>& comm)
1440 {
1441  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned long long>");
1442  return ireceiveImpl<unsigned long long> (recvBuffer, sourceRank, tag, comm);
1443 }
1444 
1445 template<>
1446 void
1447 send<int, unsigned long long> (const Comm<int>& comm,
1448  const int count,
1449  const unsigned long long sendBuffer[],
1450  const int destRank)
1451 {
1452  return sendImpl<unsigned long long> (comm, count, sendBuffer, destRank);
1453 }
1454 
1455 template<>
1456 void
1457 send<int, unsigned long long> (const unsigned long long sendBuffer[],
1458  const int count,
1459  const int destRank,
1460  const int tag,
1461  const Comm<int>& comm)
1462 {
1463  return sendImpl<unsigned long long> (sendBuffer, count, destRank, tag, comm);
1464 }
1465 
1466 template<>
1467 RCP<Teuchos::CommRequest<int> >
1468 isend (const ArrayRCP<const unsigned long long>& sendBuffer,
1469  const int destRank,
1470  const int tag,
1471  const Comm<int>& comm)
1472 {
1473  return isendImpl<unsigned long long> (sendBuffer, destRank, tag, comm);
1474 }
1475 
1476 #endif // HAVE_TEUCHOS_LONG_LONG_INT
1477 
1478 
1479 // Specialization for Ordinal=int and Packet=long.
1480 template<>
1481 void
1482 gather<int, long> (const long sendBuf[],
1483  const int sendCount,
1484  long recvBuf[],
1485  const int recvCount,
1486  const int root,
1487  const Comm<int>& comm)
1488 {
1489  gatherImpl<long> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1490 }
1491 
1492 template<>
1493 void
1494 gatherv<int, long> (const long sendBuf[],
1495  const int sendCount,
1496  long recvBuf[],
1497  const int recvCounts[],
1498  const int displs[],
1499  const int root,
1500  const Comm<int>& comm)
1501 {
1502  gathervImpl<long> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1503 }
1504 
1505 template<>
1506 void
1507 reduceAll<int, long> (const Comm<int>& comm,
1508  const EReductionType reductType,
1509  const int count,
1510  const long sendBuffer[],
1511  long globalReducts[])
1512 {
1513  TEUCHOS_COMM_TIME_MONITOR(
1514  "Teuchos::reduceAll<int, long> (" << count << ", "
1515  << toString (reductType) << ")"
1516  );
1517  reduceAllImpl<long> (comm, reductType, count, sendBuffer, globalReducts);
1518 }
1519 
1520 template<>
1521 RCP<Teuchos::CommRequest<int> >
1522 ireceive<int, long> (const Comm<int>& comm,
1523  const ArrayRCP<long>& recvBuffer,
1524  const int sourceRank)
1525 {
1526  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, long>");
1527  return ireceiveImpl<long> (comm, recvBuffer, sourceRank);
1528 }
1529 
1530 template<>
1531 RCP<Teuchos::CommRequest<int> >
1532 ireceive<int, long> (const ArrayRCP<long>& recvBuffer,
1533  const int sourceRank,
1534  const int tag,
1535  const Comm<int>& comm)
1536 {
1537  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, long>");
1538  return ireceiveImpl<long> (recvBuffer, sourceRank, tag, comm);
1539 }
1540 
1541 template<>
1542 void
1543 send<int, long> (const Comm<int>& comm,
1544  const int count,
1545  const long sendBuffer[],
1546  const int destRank)
1547 {
1548  return sendImpl<long> (comm, count, sendBuffer, destRank);
1549 }
1550 
1551 template<>
1552 void
1553 send<int, long> (const long sendBuffer[],
1554  const int count,
1555  const int destRank,
1556  const int tag,
1557  const Comm<int>& comm)
1558 {
1559  return sendImpl<long> (sendBuffer, count, destRank, tag, comm);
1560 }
1561 
1562 template<>
1563 RCP<Teuchos::CommRequest<int> >
1564 isend (const ArrayRCP<const long>& sendBuffer,
1565  const int destRank,
1566  const int tag,
1567  const Comm<int>& comm)
1568 {
1569  return isendImpl<long> (sendBuffer, destRank, tag, comm);
1570 }
1571 
1572 
1573 // Specialization for Ordinal=int and Packet=unsigned long.
1574 template<>
1575 void
1576 gather<int, unsigned long> (const unsigned long sendBuf[],
1577  const int sendCount,
1578  unsigned long recvBuf[],
1579  const int recvCount,
1580  const int root,
1581  const Comm<int>& comm)
1582 {
1583  gatherImpl<unsigned long> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1584 }
1585 
1586 template<>
1587 void
1588 gatherv<int, unsigned long> (const unsigned long sendBuf[],
1589  const int sendCount,
1590  unsigned long recvBuf[],
1591  const int recvCounts[],
1592  const int displs[],
1593  const int root,
1594  const Comm<int>& comm)
1595 {
1596  gathervImpl<unsigned long> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1597 }
1598 
1599 template<>
1600 void
1601 reduceAll<int, unsigned long> (const Comm<int>& comm,
1602  const EReductionType reductType,
1603  const int count,
1604  const unsigned long sendBuffer[],
1605  unsigned long globalReducts[])
1606 {
1607  TEUCHOS_COMM_TIME_MONITOR(
1608  "Teuchos::reduceAll<int, unsigned long> (" << count << ", "
1609  << toString (reductType) << ")"
1610  );
1611  reduceAllImpl<unsigned long> (comm, reductType, count, sendBuffer, globalReducts);
1612 }
1613 
1614 template<>
1615 RCP<Teuchos::CommRequest<int> >
1616 ireceive<int, unsigned long> (const Comm<int>& comm,
1617  const ArrayRCP<unsigned long>& recvBuffer,
1618  const int sourceRank)
1619 {
1620  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned long>");
1621  return ireceiveImpl<unsigned long> (comm, recvBuffer, sourceRank);
1622 }
1623 
1624 template<>
1625 RCP<Teuchos::CommRequest<int> >
1626 ireceive<int, unsigned long> (const ArrayRCP<unsigned long>& recvBuffer,
1627  const int sourceRank,
1628  const int tag,
1629  const Comm<int>& comm)
1630 {
1631  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned long>");
1632  return ireceiveImpl<unsigned long> (recvBuffer, sourceRank, tag, comm);
1633 }
1634 
1635 template<>
1636 void
1637 send<int, unsigned long> (const Comm<int>& comm,
1638  const int count,
1639  const unsigned long sendBuffer[],
1640  const int destRank)
1641 {
1642  return sendImpl<unsigned long> (comm, count, sendBuffer, destRank);
1643 }
1644 
1645 template<>
1646 void
1647 send<int, unsigned long> (const unsigned long sendBuffer[],
1648  const int count,
1649  const int destRank,
1650  const int tag,
1651  const Comm<int>& comm)
1652 {
1653  return sendImpl<unsigned long> (sendBuffer, count, destRank, tag, comm);
1654 }
1655 
1656 template<>
1657 RCP<Teuchos::CommRequest<int> >
1658 isend (const ArrayRCP<const unsigned long>& sendBuffer,
1659  const int destRank,
1660  const int tag,
1661  const Comm<int>& comm)
1662 {
1663  return isendImpl<unsigned long> (sendBuffer, destRank, tag, comm);
1664 }
1665 
1666 // Specialization for Ordinal=int and Packet=int.
1667 template<>
1668 void
1669 gather<int, int> (const int sendBuf[],
1670  const int sendCount,
1671  int recvBuf[],
1672  const int recvCount,
1673  const int root,
1674  const Comm<int>& comm)
1675 {
1676  gatherImpl<int> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1677 }
1678 
1679 template<>
1680 void
1681 gatherv<int, int> (const int sendBuf[],
1682  const int sendCount,
1683  int recvBuf[],
1684  const int recvCounts[],
1685  const int displs[],
1686  const int root,
1687  const Comm<int>& comm)
1688 {
1689  gathervImpl<int> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1690 }
1691 
1692 template<>
1693 void
1694 scatter<int, int> (const int sendBuf[],
1695  const int sendCount,
1696  int recvBuf[],
1697  const int recvCount,
1698  const int root,
1699  const Comm<int>& comm)
1700 {
1701  scatterImpl<int> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1702 }
1703 
1704 template<>
1705 void
1706 reduce<int, int> (const int sendBuf[],
1707  int recvBuf[],
1708  const int count,
1709  const EReductionType reductType,
1710  const int root,
1711  const Comm<int>& comm)
1712 {
1713  TEUCHOS_COMM_TIME_MONITOR
1714  ("Teuchos::reduce<int, int> (" << count << ", " << toString (reductType)
1715  << ")");
1716  reduceImpl<int> (sendBuf, recvBuf, count, reductType, root, comm);
1717 }
1718 
1719 template<>
1720 void
1721 reduceAll<int, int> (const Comm<int>& comm,
1722  const EReductionType reductType,
1723  const int count,
1724  const int sendBuffer[],
1725  int globalReducts[])
1726 {
1727  TEUCHOS_COMM_TIME_MONITOR(
1728  "Teuchos::reduceAll<int, int> (" << count << ", "
1729  << toString (reductType) << ")"
1730  );
1731  reduceAllImpl<int> (comm, reductType, count, sendBuffer, globalReducts);
1732 }
1733 
1734 template<>
1735 TEUCHOS_DEPRECATED void
1736 reduceAllAndScatter<int, int> (const Comm<int>& comm,
1737  const EReductionType reductType,
1738  const int sendCount,
1739  const int sendBuffer[],
1740  const int recvCounts[],
1741  int myGlobalReducts[])
1742 {
1743  reduceAllAndScatterImpl<int> (comm, reductType, sendCount, sendBuffer,
1744  recvCounts, myGlobalReducts);
1745 }
1746 
1747 template<>
1748 RCP<Teuchos::CommRequest<int> >
1749 ireceive<int, int> (const Comm<int>& comm,
1750  const ArrayRCP<int>& recvBuffer,
1751  const int sourceRank)
1752 {
1753  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, int>");
1754  return ireceiveImpl<int> (comm, recvBuffer, sourceRank);
1755 }
1756 
1757 template<>
1758 RCP<Teuchos::CommRequest<int> >
1759 ireceive<int, int> (const ArrayRCP<int>& recvBuffer,
1760  const int sourceRank,
1761  const int tag,
1762  const Comm<int>& comm)
1763 {
1764  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, int>");
1765  return ireceiveImpl<int> (recvBuffer, sourceRank, tag, comm);
1766 }
1767 
1768 template<>
1769 void
1770 send<int, int> (const Comm<int>& comm,
1771  const int count,
1772  const int sendBuffer[],
1773  const int destRank)
1774 {
1775  return sendImpl<int> (comm, count, sendBuffer, destRank);
1776 }
1777 
1778 template<>
1779 void
1780 send<int, int> (const int sendBuffer[],
1781  const int count,
1782  const int destRank,
1783  const int tag,
1784  const Comm<int>& comm)
1785 {
1786  return sendImpl<int> (sendBuffer, count, destRank, tag, comm);
1787 }
1788 
1789 template<>
1790 RCP<Teuchos::CommRequest<int> >
1791 isend (const ArrayRCP<const int>& sendBuffer,
1792  const int destRank,
1793  const int tag,
1794  const Comm<int>& comm)
1795 {
1796  return isendImpl<int> (sendBuffer, destRank, tag, comm);
1797 }
1798 
1799 // Specialization for Ordinal=int and Packet=unsigned int.
1800 template<>
1801 void
1802 gather<int, unsigned int> (const unsigned int sendBuf[],
1803  const int sendCount,
1804  unsigned int recvBuf[],
1805  const int recvCount,
1806  const int root,
1807  const Comm<int>& comm)
1808 {
1809  gatherImpl<unsigned int> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1810 }
1811 
1812 template<>
1813 void
1814 gatherv<int, unsigned int> (const unsigned int sendBuf[],
1815  const int sendCount,
1816  unsigned int recvBuf[],
1817  const int recvCounts[],
1818  const int displs[],
1819  const int root,
1820  const Comm<int>& comm)
1821 {
1822  gathervImpl<unsigned int> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1823 }
1824 
1825 template<>
1826 void
1827 reduceAll<int, unsigned int> (const Comm<int>& comm,
1828  const EReductionType reductType,
1829  const int count,
1830  const unsigned int sendBuffer[],
1831  unsigned int globalReducts[])
1832 {
1833  TEUCHOS_COMM_TIME_MONITOR(
1834  "Teuchos::reduceAll<int, unsigned int> (" << count << ", "
1835  << toString (reductType) << ")"
1836  );
1837  reduceAllImpl<unsigned int> (comm, reductType, count, sendBuffer, globalReducts);
1838 }
1839 
1840 template<>
1841 RCP<Teuchos::CommRequest<int> >
1842 ireceive<int, unsigned int> (const Comm<int>& comm,
1843  const ArrayRCP<unsigned int>& recvBuffer,
1844  const int sourceRank)
1845 {
1846  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned int>");
1847  return ireceiveImpl<unsigned int> (comm, recvBuffer, sourceRank);
1848 }
1849 
1850 template<>
1851 RCP<Teuchos::CommRequest<int> >
1852 ireceive<int, unsigned int> (const ArrayRCP<unsigned int>& recvBuffer,
1853  const int sourceRank,
1854  const int tag,
1855  const Comm<int>& comm)
1856 {
1857  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned int>");
1858  return ireceiveImpl<unsigned int> (recvBuffer, sourceRank, tag, comm);
1859 }
1860 
1861 template<>
1862 void
1863 send<int, unsigned int> (const Comm<int>& comm,
1864  const int count,
1865  const unsigned int sendBuffer[],
1866  const int destRank)
1867 {
1868  return sendImpl<unsigned int> (comm, count, sendBuffer, destRank);
1869 }
1870 
1871 template<>
1872 void
1873 send<int, unsigned int> (const unsigned int sendBuffer[],
1874  const int count,
1875  const int destRank,
1876  const int tag,
1877  const Comm<int>& comm)
1878 {
1879  return sendImpl<unsigned int> (sendBuffer, count, destRank, tag, comm);
1880 }
1881 
1882 template<>
1883 RCP<Teuchos::CommRequest<int> >
1884 isend (const ArrayRCP<const unsigned int>& sendBuffer,
1885  const int destRank,
1886  const int tag,
1887  const Comm<int>& comm)
1888 {
1889  return isendImpl<unsigned int> (sendBuffer, destRank, tag, comm);
1890 }
1891 
1892 
1893 // Specialization for Ordinal=int and Packet=short.
1894 template<>
1895 void
1896 gather<int, short> (const short sendBuf[],
1897  const int sendCount,
1898  short recvBuf[],
1899  const int recvCount,
1900  const int root,
1901  const Comm<int>& comm)
1902 {
1903  gatherImpl<short> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1904 }
1905 
1906 template<>
1907 void
1908 gatherv<int, short> (const short sendBuf[],
1909  const int sendCount,
1910  short recvBuf[],
1911  const int recvCounts[],
1912  const int displs[],
1913  const int root,
1914  const Comm<int>& comm)
1915 {
1916  gathervImpl<short> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1917 }
1918 
1919 template<>
1920 void
1921 reduceAll<int, short> (const Comm<int>& comm,
1922  const EReductionType reductType,
1923  const int count,
1924  const short sendBuffer[],
1925  short globalReducts[])
1926 {
1927  TEUCHOS_COMM_TIME_MONITOR(
1928  "Teuchos::reduceAll<int, short> (" << count << ", "
1929  << toString (reductType) << ")"
1930  );
1931  reduceAllImpl<short> (comm, reductType, count, sendBuffer, globalReducts);
1932 }
1933 
1934 template<>
1935 RCP<Teuchos::CommRequest<int> >
1936 ireceive<int, short> (const Comm<int>& comm,
1937  const ArrayRCP<short>& recvBuffer,
1938  const int sourceRank)
1939 {
1940  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, short>");
1941  return ireceiveImpl<short> (comm, recvBuffer, sourceRank);
1942 }
1943 
1944 template<>
1945 RCP<Teuchos::CommRequest<int> >
1946 ireceive<int, short> (const ArrayRCP<short>& recvBuffer,
1947  const int sourceRank,
1948  const int tag,
1949  const Comm<int>& comm)
1950 {
1951  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, short>");
1952  return ireceiveImpl<short> (recvBuffer, sourceRank, tag, comm);
1953 }
1954 
1955 template<>
1956 void
1957 send<int, short> (const Comm<int>& comm,
1958  const int count,
1959  const short sendBuffer[],
1960  const int destRank)
1961 {
1962  return sendImpl<short> (comm, count, sendBuffer, destRank);
1963 }
1964 
1965 template<>
1966 void
1967 send<int, short> (const short sendBuffer[],
1968  const int count,
1969  const int destRank,
1970  const int tag,
1971  const Comm<int>& comm)
1972 {
1973  return sendImpl<short> (sendBuffer, count, destRank, tag, comm);
1974 }
1975 
1976 template<>
1977 RCP<Teuchos::CommRequest<int> >
1978 isend (const ArrayRCP<const short>& sendBuffer,
1979  const int destRank,
1980  const int tag,
1981  const Comm<int>& comm)
1982 {
1983  return isendImpl<short> (sendBuffer, destRank, tag, comm);
1984 }
1985 
1986 // mfh 18 Oct 2012: The specialization for Packet=char seems to be
1987 // causing problems such as the following:
1988 //
1989 // http://testing.sandia.gov/cdash/testDetails.php?test=9909246&build=747699
1990 //
1991 // I am disabling it for now. This should revert back to the old
1992 // behavior for Packet=char. That should fix the Tpetra errors, since
1993 // many Tpetra objects inherit from DistObject<char, ...>.
1994 #if 0
1995 // Specialization for Ordinal=int and Packet=char.
1996 template<>
1997 void
1998 reduceAll<int, char> (const Comm<int>& comm,
1999  const EReductionType reductType,
2000  const int count,
2001  const char sendBuffer[],
2002  char globalReducts[])
2003 {
2004  TEUCHOS_COMM_TIME_MONITOR(
2005  "Teuchos::reduceAll<int, char> (" << count << ", "
2006  << toString (reductType) << ")"
2007  );
2008  reduceAllImpl<char> (comm, reductType, count, sendBuffer, globalReducts);
2009 }
2010 #endif // 0
2011 
2012 } // 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.