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