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 #ifdef HAVE_TEUCHOS_LONG_LONG_INT
1115 // Specialization for Ordinal=int and Packet=long long.
1116 template<>
1117 void
1118 gather<int, long long> (const long long sendBuf[],
1119  const int sendCount,
1120  long long recvBuf[],
1121  const int recvCount,
1122  const int root,
1123  const Comm<int>& comm)
1124 {
1125  gatherImpl<long long> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1126 }
1127 
1128 template<>
1129 void
1130 gatherv<int, long long> (const long long sendBuf[],
1131  const int sendCount,
1132  long long recvBuf[],
1133  const int recvCounts[],
1134  const int displs[],
1135  const int root,
1136  const Comm<int>& comm)
1137 {
1138  gathervImpl<long long> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1139 }
1140 
1141 template<>
1142 void
1143 reduceAll<int, long long> (const Comm<int>& comm,
1144  const EReductionType reductType,
1145  const int count,
1146  const long long sendBuffer[],
1147  long long globalReducts[])
1148 {
1149  TEUCHOS_COMM_TIME_MONITOR(
1150  "Teuchos::reduceAll<int, long long> (" << count << ", "
1151  << toString (reductType) << ")"
1152  );
1153  reduceAllImpl<long long> (comm, reductType, count, sendBuffer, globalReducts);
1154 }
1155 
1156 template<>
1157 RCP<Teuchos::CommRequest<int> >
1158 ireceive<int, long long> (const Comm<int>& comm,
1159  const ArrayRCP<long long>& recvBuffer,
1160  const int sourceRank)
1161 {
1162  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, long long>");
1163  return ireceiveImpl<long long> (comm, recvBuffer, sourceRank);
1164 }
1165 
1166 template<>
1167 RCP<Teuchos::CommRequest<int> >
1168 ireceive<int, long long> (const ArrayRCP<long long>& recvBuffer,
1169  const int sourceRank,
1170  const int tag,
1171  const Comm<int>& comm)
1172 {
1173  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, long long>");
1174  return ireceiveImpl<long long> (recvBuffer, sourceRank, tag, comm);
1175 }
1176 
1177 template<>
1178 void
1179 send<int, long long> (const Comm<int>& comm,
1180  const int count,
1181  const long long sendBuffer[],
1182  const int destRank)
1183 {
1184  return sendImpl<long long> (comm, count, sendBuffer, destRank);
1185 }
1186 
1187 template<>
1188 void
1189 send<int, long long> (const long long sendBuffer[],
1190  const int count,
1191  const int destRank,
1192  const int tag,
1193  const Comm<int>& comm)
1194 {
1195  return sendImpl<long long> (sendBuffer, count, destRank, tag, comm);
1196 }
1197 
1198 template<>
1199 RCP<Teuchos::CommRequest<int> >
1200 isend (const ArrayRCP<const long long>& sendBuffer,
1201  const int destRank,
1202  const int tag,
1203  const Comm<int>& comm)
1204 {
1205  return isendImpl<long long> (sendBuffer, destRank, tag, comm);
1206 }
1207 
1208 // Specialization for Ordinal=int and Packet=unsigned long long.
1209 template<>
1210 void
1211 gather<int, unsigned long long> (const unsigned long long sendBuf[],
1212  const int sendCount,
1213  unsigned long long recvBuf[],
1214  const int recvCount,
1215  const int root,
1216  const Comm<int>& comm)
1217 {
1218  gatherImpl<unsigned long long> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1219 }
1220 
1221 template<>
1222 void
1223 gatherv<int, unsigned long long> (const unsigned long long sendBuf[],
1224  const int sendCount,
1225  unsigned long long recvBuf[],
1226  const int recvCounts[],
1227  const int displs[],
1228  const int root,
1229  const Comm<int>& comm)
1230 {
1231  gathervImpl<unsigned long long> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1232 }
1233 
1234 template<>
1235 void
1236 reduceAll<int, unsigned long long> (const Comm<int>& comm,
1237  const EReductionType reductType,
1238  const int count,
1239  const unsigned long long sendBuffer[],
1240  unsigned long long globalReducts[])
1241 {
1242  TEUCHOS_COMM_TIME_MONITOR(
1243  "Teuchos::reduceAll<int, unsigned long long> (" << count << ", "
1244  << toString (reductType) << ")"
1245  );
1246  reduceAllImpl<unsigned long long> (comm, reductType, count, sendBuffer, globalReducts);
1247 }
1248 
1249 template<>
1250 RCP<Teuchos::CommRequest<int> >
1251 ireceive<int, unsigned long long> (const Comm<int>& comm,
1252  const ArrayRCP<unsigned long long>& recvBuffer,
1253  const int sourceRank)
1254 {
1255  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned long long>");
1256  return ireceiveImpl<unsigned long long> (comm, recvBuffer, sourceRank);
1257 }
1258 
1259 template<>
1260 RCP<Teuchos::CommRequest<int> >
1261 ireceive<int, unsigned long long> (const ArrayRCP<unsigned long long>& recvBuffer,
1262  const int sourceRank,
1263  const int tag,
1264  const Comm<int>& comm)
1265 {
1266  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned long long>");
1267  return ireceiveImpl<unsigned long long> (recvBuffer, sourceRank, tag, comm);
1268 }
1269 
1270 template<>
1271 void
1272 send<int, unsigned long long> (const Comm<int>& comm,
1273  const int count,
1274  const unsigned long long sendBuffer[],
1275  const int destRank)
1276 {
1277  return sendImpl<unsigned long long> (comm, count, sendBuffer, destRank);
1278 }
1279 
1280 template<>
1281 void
1282 send<int, unsigned long long> (const unsigned long long sendBuffer[],
1283  const int count,
1284  const int destRank,
1285  const int tag,
1286  const Comm<int>& comm)
1287 {
1288  return sendImpl<unsigned long long> (sendBuffer, count, destRank, tag, comm);
1289 }
1290 
1291 template<>
1292 RCP<Teuchos::CommRequest<int> >
1293 isend (const ArrayRCP<const unsigned long long>& sendBuffer,
1294  const int destRank,
1295  const int tag,
1296  const Comm<int>& comm)
1297 {
1298  return isendImpl<unsigned long long> (sendBuffer, destRank, tag, comm);
1299 }
1300 
1301 #endif // HAVE_TEUCHOS_LONG_LONG_INT
1302 
1303 
1304 // Specialization for Ordinal=int and Packet=long.
1305 template<>
1306 void
1307 gather<int, long> (const long sendBuf[],
1308  const int sendCount,
1309  long recvBuf[],
1310  const int recvCount,
1311  const int root,
1312  const Comm<int>& comm)
1313 {
1314  gatherImpl<long> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1315 }
1316 
1317 template<>
1318 void
1319 gatherv<int, long> (const long sendBuf[],
1320  const int sendCount,
1321  long recvBuf[],
1322  const int recvCounts[],
1323  const int displs[],
1324  const int root,
1325  const Comm<int>& comm)
1326 {
1327  gathervImpl<long> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1328 }
1329 
1330 template<>
1331 void
1332 reduceAll<int, long> (const Comm<int>& comm,
1333  const EReductionType reductType,
1334  const int count,
1335  const long sendBuffer[],
1336  long globalReducts[])
1337 {
1338  TEUCHOS_COMM_TIME_MONITOR(
1339  "Teuchos::reduceAll<int, long> (" << count << ", "
1340  << toString (reductType) << ")"
1341  );
1342  reduceAllImpl<long> (comm, reductType, count, sendBuffer, globalReducts);
1343 }
1344 
1345 template<>
1346 RCP<Teuchos::CommRequest<int> >
1347 ireceive<int, long> (const Comm<int>& comm,
1348  const ArrayRCP<long>& recvBuffer,
1349  const int sourceRank)
1350 {
1351  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, long>");
1352  return ireceiveImpl<long> (comm, recvBuffer, sourceRank);
1353 }
1354 
1355 template<>
1356 RCP<Teuchos::CommRequest<int> >
1357 ireceive<int, long> (const ArrayRCP<long>& recvBuffer,
1358  const int sourceRank,
1359  const int tag,
1360  const Comm<int>& comm)
1361 {
1362  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, long>");
1363  return ireceiveImpl<long> (recvBuffer, sourceRank, tag, comm);
1364 }
1365 
1366 template<>
1367 void
1368 send<int, long> (const Comm<int>& comm,
1369  const int count,
1370  const long sendBuffer[],
1371  const int destRank)
1372 {
1373  return sendImpl<long> (comm, count, sendBuffer, destRank);
1374 }
1375 
1376 template<>
1377 void
1378 send<int, long> (const long sendBuffer[],
1379  const int count,
1380  const int destRank,
1381  const int tag,
1382  const Comm<int>& comm)
1383 {
1384  return sendImpl<long> (sendBuffer, count, destRank, tag, comm);
1385 }
1386 
1387 template<>
1388 RCP<Teuchos::CommRequest<int> >
1389 isend (const ArrayRCP<const long>& sendBuffer,
1390  const int destRank,
1391  const int tag,
1392  const Comm<int>& comm)
1393 {
1394  return isendImpl<long> (sendBuffer, destRank, tag, comm);
1395 }
1396 
1397 
1398 // Specialization for Ordinal=int and Packet=unsigned long.
1399 template<>
1400 void
1401 gather<int, unsigned long> (const unsigned long sendBuf[],
1402  const int sendCount,
1403  unsigned long recvBuf[],
1404  const int recvCount,
1405  const int root,
1406  const Comm<int>& comm)
1407 {
1408  gatherImpl<unsigned long> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1409 }
1410 
1411 template<>
1412 void
1413 gatherv<int, unsigned long> (const unsigned long sendBuf[],
1414  const int sendCount,
1415  unsigned long recvBuf[],
1416  const int recvCounts[],
1417  const int displs[],
1418  const int root,
1419  const Comm<int>& comm)
1420 {
1421  gathervImpl<unsigned long> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1422 }
1423 
1424 template<>
1425 void
1426 reduceAll<int, unsigned long> (const Comm<int>& comm,
1427  const EReductionType reductType,
1428  const int count,
1429  const unsigned long sendBuffer[],
1430  unsigned long globalReducts[])
1431 {
1432  TEUCHOS_COMM_TIME_MONITOR(
1433  "Teuchos::reduceAll<int, unsigned long> (" << count << ", "
1434  << toString (reductType) << ")"
1435  );
1436  reduceAllImpl<unsigned long> (comm, reductType, count, sendBuffer, globalReducts);
1437 }
1438 
1439 template<>
1440 RCP<Teuchos::CommRequest<int> >
1441 ireceive<int, unsigned long> (const Comm<int>& comm,
1442  const ArrayRCP<unsigned long>& recvBuffer,
1443  const int sourceRank)
1444 {
1445  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned long>");
1446  return ireceiveImpl<unsigned long> (comm, recvBuffer, sourceRank);
1447 }
1448 
1449 template<>
1450 RCP<Teuchos::CommRequest<int> >
1451 ireceive<int, unsigned long> (const ArrayRCP<unsigned long>& recvBuffer,
1452  const int sourceRank,
1453  const int tag,
1454  const Comm<int>& comm)
1455 {
1456  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned long>");
1457  return ireceiveImpl<unsigned long> (recvBuffer, sourceRank, tag, comm);
1458 }
1459 
1460 template<>
1461 void
1462 send<int, unsigned long> (const Comm<int>& comm,
1463  const int count,
1464  const unsigned long sendBuffer[],
1465  const int destRank)
1466 {
1467  return sendImpl<unsigned long> (comm, count, sendBuffer, destRank);
1468 }
1469 
1470 template<>
1471 void
1472 send<int, unsigned long> (const unsigned long sendBuffer[],
1473  const int count,
1474  const int destRank,
1475  const int tag,
1476  const Comm<int>& comm)
1477 {
1478  return sendImpl<unsigned long> (sendBuffer, count, destRank, tag, comm);
1479 }
1480 
1481 template<>
1482 RCP<Teuchos::CommRequest<int> >
1483 isend (const ArrayRCP<const unsigned long>& sendBuffer,
1484  const int destRank,
1485  const int tag,
1486  const Comm<int>& comm)
1487 {
1488  return isendImpl<unsigned long> (sendBuffer, destRank, tag, comm);
1489 }
1490 
1491 // Specialization for Ordinal=int and Packet=int.
1492 template<>
1493 void
1494 gather<int, int> (const int sendBuf[],
1495  const int sendCount,
1496  int recvBuf[],
1497  const int recvCount,
1498  const int root,
1499  const Comm<int>& comm)
1500 {
1501  gatherImpl<int> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1502 }
1503 
1504 template<>
1505 void
1506 gatherv<int, int> (const int sendBuf[],
1507  const int sendCount,
1508  int recvBuf[],
1509  const int recvCounts[],
1510  const int displs[],
1511  const int root,
1512  const Comm<int>& comm)
1513 {
1514  gathervImpl<int> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1515 }
1516 
1517 template<>
1518 void
1519 scatter<int, int> (const int sendBuf[],
1520  const int sendCount,
1521  int recvBuf[],
1522  const int recvCount,
1523  const int root,
1524  const Comm<int>& comm)
1525 {
1526  scatterImpl<int> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1527 }
1528 
1529 template<>
1530 void
1531 reduce<int, int> (const int sendBuf[],
1532  int recvBuf[],
1533  const int count,
1534  const EReductionType reductType,
1535  const int root,
1536  const Comm<int>& comm)
1537 {
1538  TEUCHOS_COMM_TIME_MONITOR
1539  ("Teuchos::reduce<int, int> (" << count << ", " << toString (reductType)
1540  << ")");
1541  reduceImpl<int> (sendBuf, recvBuf, count, reductType, root, comm);
1542 }
1543 
1544 template<>
1545 void
1546 reduceAll<int, int> (const Comm<int>& comm,
1547  const EReductionType reductType,
1548  const int count,
1549  const int sendBuffer[],
1550  int globalReducts[])
1551 {
1552  TEUCHOS_COMM_TIME_MONITOR(
1553  "Teuchos::reduceAll<int, int> (" << count << ", "
1554  << toString (reductType) << ")"
1555  );
1556  reduceAllImpl<int> (comm, reductType, count, sendBuffer, globalReducts);
1557 }
1558 
1559 template<>
1560 RCP<Teuchos::CommRequest<int> >
1561 ireceive<int, int> (const Comm<int>& comm,
1562  const ArrayRCP<int>& recvBuffer,
1563  const int sourceRank)
1564 {
1565  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, int>");
1566  return ireceiveImpl<int> (comm, recvBuffer, sourceRank);
1567 }
1568 
1569 template<>
1570 RCP<Teuchos::CommRequest<int> >
1571 ireceive<int, int> (const ArrayRCP<int>& recvBuffer,
1572  const int sourceRank,
1573  const int tag,
1574  const Comm<int>& comm)
1575 {
1576  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, int>");
1577  return ireceiveImpl<int> (recvBuffer, sourceRank, tag, comm);
1578 }
1579 
1580 template<>
1581 void
1582 send<int, int> (const Comm<int>& comm,
1583  const int count,
1584  const int sendBuffer[],
1585  const int destRank)
1586 {
1587  return sendImpl<int> (comm, count, sendBuffer, destRank);
1588 }
1589 
1590 template<>
1591 void
1592 send<int, int> (const int sendBuffer[],
1593  const int count,
1594  const int destRank,
1595  const int tag,
1596  const Comm<int>& comm)
1597 {
1598  return sendImpl<int> (sendBuffer, count, destRank, tag, comm);
1599 }
1600 
1601 template<>
1602 RCP<Teuchos::CommRequest<int> >
1603 isend (const ArrayRCP<const int>& sendBuffer,
1604  const int destRank,
1605  const int tag,
1606  const Comm<int>& comm)
1607 {
1608  return isendImpl<int> (sendBuffer, destRank, tag, comm);
1609 }
1610 
1611 // Specialization for Ordinal=int and Packet=unsigned int.
1612 template<>
1613 void
1614 gather<int, unsigned int> (const unsigned int sendBuf[],
1615  const int sendCount,
1616  unsigned int recvBuf[],
1617  const int recvCount,
1618  const int root,
1619  const Comm<int>& comm)
1620 {
1621  gatherImpl<unsigned int> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1622 }
1623 
1624 template<>
1625 void
1626 gatherv<int, unsigned int> (const unsigned int sendBuf[],
1627  const int sendCount,
1628  unsigned int recvBuf[],
1629  const int recvCounts[],
1630  const int displs[],
1631  const int root,
1632  const Comm<int>& comm)
1633 {
1634  gathervImpl<unsigned int> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1635 }
1636 
1637 template<>
1638 void
1639 reduceAll<int, unsigned int> (const Comm<int>& comm,
1640  const EReductionType reductType,
1641  const int count,
1642  const unsigned int sendBuffer[],
1643  unsigned int globalReducts[])
1644 {
1645  TEUCHOS_COMM_TIME_MONITOR(
1646  "Teuchos::reduceAll<int, unsigned int> (" << count << ", "
1647  << toString (reductType) << ")"
1648  );
1649  reduceAllImpl<unsigned int> (comm, reductType, count, sendBuffer, globalReducts);
1650 }
1651 
1652 template<>
1653 RCP<Teuchos::CommRequest<int> >
1654 ireceive<int, unsigned int> (const Comm<int>& comm,
1655  const ArrayRCP<unsigned int>& recvBuffer,
1656  const int sourceRank)
1657 {
1658  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned int>");
1659  return ireceiveImpl<unsigned int> (comm, recvBuffer, sourceRank);
1660 }
1661 
1662 template<>
1663 RCP<Teuchos::CommRequest<int> >
1664 ireceive<int, unsigned int> (const ArrayRCP<unsigned int>& recvBuffer,
1665  const int sourceRank,
1666  const int tag,
1667  const Comm<int>& comm)
1668 {
1669  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, unsigned int>");
1670  return ireceiveImpl<unsigned int> (recvBuffer, sourceRank, tag, comm);
1671 }
1672 
1673 template<>
1674 void
1675 send<int, unsigned int> (const Comm<int>& comm,
1676  const int count,
1677  const unsigned int sendBuffer[],
1678  const int destRank)
1679 {
1680  return sendImpl<unsigned int> (comm, count, sendBuffer, destRank);
1681 }
1682 
1683 template<>
1684 void
1685 send<int, unsigned int> (const unsigned int sendBuffer[],
1686  const int count,
1687  const int destRank,
1688  const int tag,
1689  const Comm<int>& comm)
1690 {
1691  return sendImpl<unsigned int> (sendBuffer, count, destRank, tag, comm);
1692 }
1693 
1694 template<>
1695 RCP<Teuchos::CommRequest<int> >
1696 isend (const ArrayRCP<const unsigned int>& sendBuffer,
1697  const int destRank,
1698  const int tag,
1699  const Comm<int>& comm)
1700 {
1701  return isendImpl<unsigned int> (sendBuffer, destRank, tag, comm);
1702 }
1703 
1704 
1705 // Specialization for Ordinal=int and Packet=short.
1706 template<>
1707 void
1708 gather<int, short> (const short sendBuf[],
1709  const int sendCount,
1710  short recvBuf[],
1711  const int recvCount,
1712  const int root,
1713  const Comm<int>& comm)
1714 {
1715  gatherImpl<short> (sendBuf, sendCount, recvBuf, recvCount, root, comm);
1716 }
1717 
1718 template<>
1719 void
1720 gatherv<int, short> (const short sendBuf[],
1721  const int sendCount,
1722  short recvBuf[],
1723  const int recvCounts[],
1724  const int displs[],
1725  const int root,
1726  const Comm<int>& comm)
1727 {
1728  gathervImpl<short> (sendBuf, sendCount, recvBuf, recvCounts, displs, root, comm);
1729 }
1730 
1731 template<>
1732 void
1733 reduceAll<int, short> (const Comm<int>& comm,
1734  const EReductionType reductType,
1735  const int count,
1736  const short sendBuffer[],
1737  short globalReducts[])
1738 {
1739  TEUCHOS_COMM_TIME_MONITOR(
1740  "Teuchos::reduceAll<int, short> (" << count << ", "
1741  << toString (reductType) << ")"
1742  );
1743  reduceAllImpl<short> (comm, reductType, count, sendBuffer, globalReducts);
1744 }
1745 
1746 template<>
1747 RCP<Teuchos::CommRequest<int> >
1748 ireceive<int, short> (const Comm<int>& comm,
1749  const ArrayRCP<short>& recvBuffer,
1750  const int sourceRank)
1751 {
1752  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, short>");
1753  return ireceiveImpl<short> (comm, recvBuffer, sourceRank);
1754 }
1755 
1756 template<>
1757 RCP<Teuchos::CommRequest<int> >
1758 ireceive<int, short> (const ArrayRCP<short>& recvBuffer,
1759  const int sourceRank,
1760  const int tag,
1761  const Comm<int>& comm)
1762 {
1763  TEUCHOS_COMM_TIME_MONITOR("ireceive<int, short>");
1764  return ireceiveImpl<short> (recvBuffer, sourceRank, tag, comm);
1765 }
1766 
1767 template<>
1768 void
1769 send<int, short> (const Comm<int>& comm,
1770  const int count,
1771  const short sendBuffer[],
1772  const int destRank)
1773 {
1774  return sendImpl<short> (comm, count, sendBuffer, destRank);
1775 }
1776 
1777 template<>
1778 void
1779 send<int, short> (const short sendBuffer[],
1780  const int count,
1781  const int destRank,
1782  const int tag,
1783  const Comm<int>& comm)
1784 {
1785  return sendImpl<short> (sendBuffer, count, destRank, tag, comm);
1786 }
1787 
1788 template<>
1789 RCP<Teuchos::CommRequest<int> >
1790 isend (const ArrayRCP<const short>& sendBuffer,
1791  const int destRank,
1792  const int tag,
1793  const Comm<int>& comm)
1794 {
1795  return isendImpl<short> (sendBuffer, destRank, tag, comm);
1796 }
1797 
1798 // mfh 18 Oct 2012: The specialization for Packet=char seems to be
1799 // causing problems such as the following:
1800 //
1801 // http://testing.sandia.gov/cdash/testDetails.php?test=9909246&build=747699
1802 //
1803 // I am disabling it for now. This should revert back to the old
1804 // behavior for Packet=char. That should fix the Tpetra errors, since
1805 // many Tpetra objects inherit from DistObject<char, ...>.
1806 #if 0
1807 // Specialization for Ordinal=int and Packet=char.
1808 template<>
1809 void
1810 reduceAll<int, char> (const Comm<int>& comm,
1811  const EReductionType reductType,
1812  const int count,
1813  const char sendBuffer[],
1814  char globalReducts[])
1815 {
1816  TEUCHOS_COMM_TIME_MONITOR(
1817  "Teuchos::reduceAll<int, char> (" << count << ", "
1818  << toString (reductType) << ")"
1819  );
1820  reduceAllImpl<char> (comm, reductType, count, sendBuffer, globalReducts);
1821 }
1822 #endif // 0
1823 
1824 } // 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.
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.
Declaration of Teuchos::Details::MpiTypeTraits (only if building with MPI)