Tpetra parallel linear algebra  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
Tpetra_Details_PackTriples.cpp
1 // @HEADER
2 // ***********************************************************************
3 //
4 // Tpetra: Templated Linear Algebra Services Package
5 // Copyright (2008) Sandia Corporation
6 //
7 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8 // the U.S. Government retains certain rights in this software.
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 "Tpetra_Details_PackTriples.hpp"
43 
44 #ifdef HAVE_TPETRACORE_MPI
45 
46 namespace { // (anonymous)
47  std::string
48  mpiErrorCodeToString (const int errCode)
49  {
50  if (errCode == MPI_SUCCESS) {
51  return "MPI_SUCCESS";
52  }
53  else {
54  char rawErrString[MPI_MAX_ERROR_STRING];
55  int len = 0;
56  int err = MPI_Error_string (errCode, rawErrString, &len);
57  if (err != MPI_SUCCESS) {
58  // Assume that the string wasn't written. This means it might
59  // not be null terminated, so make it a valid empty string by
60  // writing the null termination character to it.
61  if (MPI_MAX_ERROR_STRING > 0) {
62  rawErrString[0] = '\0';
63  }
64  }
65  return std::string (rawErrString);
66  }
67  }
68 } // namespace (anonymous)
69 
70 #endif // HAVE_TPETRACORE_MPI
71 
72 namespace Tpetra {
73 namespace Details {
74 
75 #ifdef HAVE_TPETRACORE_MPI
76 
77 int
78 countPackTriplesCountMpi (MPI_Comm comm,
79  int& size,
80  std::ostream* errStrm)
81 {
82  using std::endl;
83 
84  int curSize = 0;
85  const int errCode = MPI_Pack_size (1, MPI_INT, comm, &curSize);
86  if (errCode != MPI_SUCCESS) {
87  if (errStrm != NULL) {
88  *errStrm << "countPackTripleMpi: MPI_Pack_size failed on "
89  << "MPI_INT call. MPI reports: "
90  << mpiErrorCodeToString (errCode) << endl;
91  }
92  return errCode;
93  }
94  size = curSize; // "commit" the result
95 
96  return errCode;
97 }
98 
99 int
100 packTriplesCountMpi (const int numEnt,
101  char outBuf[],
102  const int outBufSize,
103  int& outBufCurPos,
104  MPI_Comm comm,
105  std::ostream* errStrm)
106 {
107  using std::endl;
108 
109  // mfh 19 Jan 2017: Some (generally older) MPI implementations want
110  // the first argument of MPI_Pack to be a pointer to nonconst, even
111  // though it's an input argument that MPI_Pack does not modify.
112  int theNumEnt = numEnt;
113  const int errCode = MPI_Pack (&theNumEnt, 1, MPI_INT, outBuf,
114  outBufSize, &outBufCurPos, comm);
115  if (errCode != MPI_SUCCESS) {
116  if (errStrm != NULL) {
117  *errStrm << "packTriplesCountMpi: MPI_Pack failed with outBufSize="
118  << outBufSize << " and outBufCurPos=" << outBufCurPos
119  << ". MPI reports: " << mpiErrorCodeToString (errCode)
120  << endl;
121  }
122  return errCode;
123  }
124  return errCode;
125 }
126 
127 int
128 unpackTriplesCountMpi (const char inBuf[],
129  const int inBufSize,
130  int& inBufCurPos,
131  int& numEnt,
132  MPI_Comm comm,
133  std::ostream* errStrm)
134 {
135  using std::endl;
136  int errCode = MPI_SUCCESS;
137 
138  // mfh 19 Jan 2017: Some (generally older) MPI implementations want
139  // the first argument to be a nonconst pointer, even though
140  // MPI_Unpack does not modify that argument.
141  int theNumEnt = 0;
142  errCode = MPI_Unpack (const_cast<char*> (inBuf), inBufSize, &inBufCurPos,
143  &theNumEnt, 1, MPI_INT, comm);
144  if (errCode != MPI_SUCCESS) {
145  if (errStrm != NULL) {
146  *errStrm << "unpackTriplesCountMpi: MPI_Unpack failed on gblRowInd: "
147  << "inBufSize=" << inBufSize
148  << ", inBufCurPos=" << inBufCurPos
149  << ". MPI reports: " << mpiErrorCodeToString (errCode)
150  << endl;
151  }
152  return errCode;
153  }
154  if (theNumEnt < 0) {
155  if (errStrm != NULL) {
156  *errStrm << "unpackTriplesCountMpi: The unpacked number of entries "
157  << theNumEnt << " is negative." << endl;
158  }
159  return -1;
160  }
161  numEnt = theNumEnt; // "commit" the change to the output argument
162  return errCode;
163 }
164 
165 #endif // HAVE_TPETRACORE_MPI
166 
167 int
168 #ifdef HAVE_TPETRACORE_MPI
169 countPackTriplesCount (const ::Teuchos::Comm<int>& comm,
170  int& size,
171  std::ostream* errStrm)
172 #else // NOT HAVE_TPETRACORE_MPI
173 countPackTriplesCount (const ::Teuchos::Comm<int>& /* comm */,
174  int& size,
175  std::ostream* errStrm)
176 #endif // HAVE_TPETRACORE_MPI
177 {
178 #ifdef HAVE_TPETRACORE_MPI
179  using ::Tpetra::Details::extractMpiCommFromTeuchos;
180  MPI_Comm mpiComm = extractMpiCommFromTeuchos (comm);
181  return countPackTriplesCountMpi (mpiComm, size, errStrm);
182 #else // NOT HAVE_TPETRACORE_MPI
183  using std::endl;
184  if (errStrm != NULL) {
185  *errStrm << "countPackTriplesCount: Not implemented (no need; there's no "
186  "need to pack or unpack anything if there's only one process)." << endl;
187  }
188  return -1;
189 #endif // HAVE_TPETRACORE_MPI
190 }
191 
192 int
193 #ifdef HAVE_TPETRACORE_MPI
194 packTriplesCount (const int numEnt,
195  char outBuf[],
196  const int outBufSize,
197  int& outBufCurPos,
198  const ::Teuchos::Comm<int>& comm,
199  std::ostream* errStrm)
200 #else // NOT HAVE_TPETRACORE_MPI
201 packTriplesCount (const int /* numEnt */,
202  char /* outBuf */[],
203  const int /* outBufSize */,
204  int& /* outBufCurPos */,
205  const ::Teuchos::Comm<int>& /* comm */,
206  std::ostream* errStrm)
207 #endif // HAVE_TPETRACORE_MPI
208 {
209 #ifdef HAVE_TPETRACORE_MPI
210  using ::Tpetra::Details::extractMpiCommFromTeuchos;
211  MPI_Comm mpiComm = extractMpiCommFromTeuchos (comm);
212  return packTriplesCountMpi (numEnt, outBuf, outBufSize,
213  outBufCurPos, mpiComm, errStrm);
214 #else // NOT HAVE_TPETRACORE_MPI
215  if (errStrm != NULL) {
216  *errStrm << "packTriplesCount: Not implemented (no need; there's no need "
217  "to pack or unpack anything if there's only one process)." << std::endl;
218  }
219  return -1;
220 #endif // HAVE_TPETRACORE_MPI
221 }
222 
223 int
224 #ifdef HAVE_TPETRACORE_MPI
225 unpackTriplesCount (const char inBuf[],
226  const int inBufSize,
227  int& inBufCurPos,
228  int& numEnt, // output argument!
229  const ::Teuchos::Comm<int>& comm,
230  std::ostream* errStrm)
231 #else // NOT HAVE_TPETRACORE_MPI
232 unpackTriplesCount (const char /* inBuf */[],
233  const int /* inBufSize */,
234  int& /* inBufCurPos */,
235  int& /* numEnt */,
236  const ::Teuchos::Comm<int>& /* comm */,
237  std::ostream* errStrm)
238 #endif // HAVE_TPETRACORE_MPI
239 {
240 #ifdef HAVE_TPETRACORE_MPI
241  using ::Tpetra::Details::extractMpiCommFromTeuchos;
242 
243  MPI_Comm mpiComm = extractMpiCommFromTeuchos (comm);
244  const int errCode =
245  unpackTriplesCountMpi (inBuf, inBufSize, inBufCurPos,
246  numEnt, mpiComm, errStrm);
247  return errCode;
248 
249 #else // NOT HAVE_TPETRACORE_MPI
250  if (errStrm != NULL) {
251  *errStrm << "unpackTriplesCount: Not implemented (no need; there's no need "
252  "to pack or unpack anything if there's only one process)." << std::endl;
253  }
254  return -1;
255 #endif // HAVE_TPETRACORE_MPI
256 }
257 
258 } // namespace Details
259 } // namespace Tpetra
260 
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;)...