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