Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Tpetra_Details_PackTriples.cpp
1 // @HEADER
2 // *****************************************************************************
3 // Tpetra: Templated Linear Algebra Services Package
4 //
5 // Copyright 2008 NTESS and the Tpetra contributors.
6 // SPDX-License-Identifier: BSD-3-Clause
7 // *****************************************************************************
8 // @HEADER
9 
10 #include "Tpetra_Details_PackTriples.hpp"
11 
12 #ifdef HAVE_TPETRACORE_MPI
13 
14 namespace { // (anonymous)
15 std::string
16 mpiErrorCodeToString(const int errCode) {
17  if (errCode == MPI_SUCCESS) {
18  return "MPI_SUCCESS";
19  } else {
20  char rawErrString[MPI_MAX_ERROR_STRING];
21  int len = 0;
22  int err = MPI_Error_string(errCode, rawErrString, &len);
23  if (err != MPI_SUCCESS) {
24  // Assume that the string wasn't written. This means it might
25  // not be null terminated, so make it a valid empty string by
26  // writing the null termination character to it.
27  if (MPI_MAX_ERROR_STRING > 0) {
28  rawErrString[0] = '\0';
29  }
30  }
31  return std::string(rawErrString);
32  }
33 }
34 } // namespace
35 
36 #endif // HAVE_TPETRACORE_MPI
37 
38 namespace Tpetra {
39 namespace Details {
40 
41 #ifdef HAVE_TPETRACORE_MPI
42 
43 int countPackTriplesCountMpi(MPI_Comm comm,
44  int& size,
45  std::ostream* errStrm) {
46  using std::endl;
47 
48  int curSize = 0;
49  const int errCode = MPI_Pack_size(1, MPI_INT, comm, &curSize);
50  if (errCode != MPI_SUCCESS) {
51  if (errStrm != NULL) {
52  *errStrm << "countPackTripleMpi: MPI_Pack_size failed on "
53  << "MPI_INT call. MPI reports: "
54  << mpiErrorCodeToString(errCode) << endl;
55  }
56  return errCode;
57  }
58  size = curSize; // "commit" the result
59 
60  return errCode;
61 }
62 
63 int packTriplesCountMpi(const int numEnt,
64  char outBuf[],
65  const int outBufSize,
66  int& outBufCurPos,
67  MPI_Comm comm,
68  std::ostream* errStrm) {
69  using std::endl;
70 
71  // mfh 19 Jan 2017: Some (generally older) MPI implementations want
72  // the first argument of MPI_Pack to be a pointer to nonconst, even
73  // though it's an input argument that MPI_Pack does not modify.
74  int theNumEnt = numEnt;
75  const int errCode = MPI_Pack(&theNumEnt, 1, MPI_INT, outBuf,
76  outBufSize, &outBufCurPos, comm);
77  if (errCode != MPI_SUCCESS) {
78  if (errStrm != NULL) {
79  *errStrm << "packTriplesCountMpi: MPI_Pack failed with outBufSize="
80  << outBufSize << " and outBufCurPos=" << outBufCurPos
81  << ". MPI reports: " << mpiErrorCodeToString(errCode)
82  << endl;
83  }
84  return errCode;
85  }
86  return errCode;
87 }
88 
89 int unpackTriplesCountMpi(const char inBuf[],
90  const int inBufSize,
91  int& inBufCurPos,
92  int& numEnt,
93  MPI_Comm comm,
94  std::ostream* errStrm) {
95  using std::endl;
96  int errCode = MPI_SUCCESS;
97 
98  // mfh 19 Jan 2017: Some (generally older) MPI implementations want
99  // the first argument to be a nonconst pointer, even though
100  // MPI_Unpack does not modify that argument.
101  int theNumEnt = 0;
102  errCode = MPI_Unpack(const_cast<char*>(inBuf), inBufSize, &inBufCurPos,
103  &theNumEnt, 1, MPI_INT, comm);
104  if (errCode != MPI_SUCCESS) {
105  if (errStrm != NULL) {
106  *errStrm << "unpackTriplesCountMpi: MPI_Unpack failed on gblRowInd: "
107  << "inBufSize=" << inBufSize
108  << ", inBufCurPos=" << inBufCurPos
109  << ". MPI reports: " << mpiErrorCodeToString(errCode)
110  << endl;
111  }
112  return errCode;
113  }
114  if (theNumEnt < 0) {
115  if (errStrm != NULL) {
116  *errStrm << "unpackTriplesCountMpi: The unpacked number of entries "
117  << theNumEnt << " is negative." << endl;
118  }
119  return -1;
120  }
121  numEnt = theNumEnt; // "commit" the change to the output argument
122  return errCode;
123 }
124 
125 #endif // HAVE_TPETRACORE_MPI
126 
127 int
128 #ifdef HAVE_TPETRACORE_MPI
129 countPackTriplesCount(const ::Teuchos::Comm<int>& comm,
130  int& size,
131  std::ostream* errStrm)
132 #else // NOT HAVE_TPETRACORE_MPI
133 countPackTriplesCount(const ::Teuchos::Comm<int>& /* comm */,
134  int& size,
135  std::ostream* errStrm)
136 #endif // HAVE_TPETRACORE_MPI
137 {
138 #ifdef HAVE_TPETRACORE_MPI
139  using ::Tpetra::Details::extractMpiCommFromTeuchos;
140  MPI_Comm mpiComm = extractMpiCommFromTeuchos(comm);
141  return countPackTriplesCountMpi(mpiComm, size, errStrm);
142 #else // NOT HAVE_TPETRACORE_MPI
143  using std::endl;
144  if (errStrm != NULL) {
145  *errStrm << "countPackTriplesCount: Not implemented (no need; there's no "
146  "need to pack or unpack anything if there's only one process)."
147  << endl;
148  }
149  return -1;
150 #endif // HAVE_TPETRACORE_MPI
151 }
152 
153 int
154 #ifdef HAVE_TPETRACORE_MPI
155 packTriplesCount(const int numEnt,
156  char outBuf[],
157  const int outBufSize,
158  int& outBufCurPos,
159  const ::Teuchos::Comm<int>& comm,
160  std::ostream* errStrm)
161 #else // NOT HAVE_TPETRACORE_MPI
162 packTriplesCount(const int /* numEnt */,
163  char /* outBuf */[],
164  const int /* outBufSize */,
165  int& /* outBufCurPos */,
166  const ::Teuchos::Comm<int>& /* comm */,
167  std::ostream* errStrm)
168 #endif // HAVE_TPETRACORE_MPI
169 {
170 #ifdef HAVE_TPETRACORE_MPI
171  using ::Tpetra::Details::extractMpiCommFromTeuchos;
172  MPI_Comm mpiComm = extractMpiCommFromTeuchos(comm);
173  return packTriplesCountMpi(numEnt, outBuf, outBufSize,
174  outBufCurPos, mpiComm, errStrm);
175 #else // NOT HAVE_TPETRACORE_MPI
176  if (errStrm != NULL) {
177  *errStrm << "packTriplesCount: Not implemented (no need; there's no need "
178  "to pack or unpack anything if there's only one process)."
179  << std::endl;
180  }
181  return -1;
182 #endif // HAVE_TPETRACORE_MPI
183 }
184 
185 int
186 #ifdef HAVE_TPETRACORE_MPI
187 unpackTriplesCount(const char inBuf[],
188  const int inBufSize,
189  int& inBufCurPos,
190  int& numEnt, // output argument!
191  const ::Teuchos::Comm<int>& comm,
192  std::ostream* errStrm)
193 #else // NOT HAVE_TPETRACORE_MPI
194 unpackTriplesCount(const char /* inBuf */[],
195  const int /* inBufSize */,
196  int& /* inBufCurPos */,
197  int& /* numEnt */,
198  const ::Teuchos::Comm<int>& /* comm */,
199  std::ostream* errStrm)
200 #endif // HAVE_TPETRACORE_MPI
201 {
202 #ifdef HAVE_TPETRACORE_MPI
203  using ::Tpetra::Details::extractMpiCommFromTeuchos;
204 
205  MPI_Comm mpiComm = extractMpiCommFromTeuchos(comm);
206  const int errCode =
207  unpackTriplesCountMpi(inBuf, inBufSize, inBufCurPos,
208  numEnt, mpiComm, errStrm);
209  return errCode;
210 
211 #else // NOT HAVE_TPETRACORE_MPI
212  if (errStrm != NULL) {
213  *errStrm << "unpackTriplesCount: Not implemented (no need; there's no need "
214  "to pack or unpack anything if there's only one process)."
215  << std::endl;
216  }
217  return -1;
218 #endif // HAVE_TPETRACORE_MPI
219 }
220 
221 } // namespace Details
222 } // namespace Tpetra
int packTriplesCount(const int, char[], const int, int &, const ::Teuchos::Comm< int > &, std::ostream *errStrm)
Pack the count (number) of matrix triples.
int unpackTriplesCount(const char[], const int, int &, int &, const ::Teuchos::Comm< int > &, std::ostream *errStrm)
Unpack just the count of triples from the given input buffer.
int countPackTriplesCount(const ::Teuchos::Comm< int > &, int &size, std::ostream *errStrm)
Compute the buffer size required by packTriples for packing the number of matrix entries (&quot;triples&quot;)...