Tpetra parallel linear algebra Version of the Day
Loading...
Searching...
No Matches
Tpetra_Details_PackTriples.hpp
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#ifndef TPETRA_DETAILS_PACKTRIPLES_HPP
11#define TPETRA_DETAILS_PACKTRIPLES_HPP
12
13#include "TpetraCore_config.h"
14#include "Teuchos_Comm.hpp"
15#ifdef HAVE_TPETRACORE_MPI
18#endif // HAVE_TPETRACORE_MPI
19#include <ostream>
20
21namespace Tpetra {
22namespace Details {
23
24//
25// Search for "SKIP DOWN TO HERE" (omit quotes) for the "public"
26// interface. I put "public" in quotes because it's public only for
27// Tpetra developers, NOT for Tpetra users.
28//
29
30#ifdef HAVE_TPETRACORE_MPI
31
32// It's not useful to pack or unpack if not using MPI. Thus, we only
33// need to define these with MPI. For a non-MPI build, we just need
34// some outer stub interface that throws an exception.
35
36int countPackTriplesCountMpi(MPI_Comm comm,
37 int& size,
38 std::ostream* errStrm = NULL);
39
40int packTriplesCountMpi(const int numEnt,
41 char outBuf[],
42 const int outBufSize,
43 int& outBufCurPos,
44 MPI_Comm comm,
45 std::ostream* errStrm = NULL);
46
47template <class ScalarType, class OrdinalType>
48int countPackTriplesMpi(MPI_Datatype ordinalDt,
49 MPI_Datatype scalarDt,
50 const int numEnt,
51 MPI_Comm comm,
52 int& size,
53 std::ostream* errStrm = NULL) {
54 using std::endl;
55 int errCode = MPI_SUCCESS;
56
57 int totalSize = 0; // return value
58
59 // Count the global row and column indices.
60 {
61 int curSize = 0;
62 // We're packing two ordinals, the row resp. column index.
63 errCode = MPI_Pack_size(2, ordinalDt, comm, &curSize);
64 if (errCode != MPI_SUCCESS) {
65 if (errStrm != NULL) {
66 *errStrm << "countPackTripleMpi: MPI_Pack_size failed on "
67 "ordinalDt call"
68 << endl;
69 }
70 return errCode;
71 }
72 totalSize += curSize;
73 }
74 // Count the matrix value.
75 {
76 int curSize = 0;
77 errCode = MPI_Pack_size(1, scalarDt, comm, &curSize);
78 if (errCode != MPI_SUCCESS) {
79 if (errStrm != NULL) {
80 *errStrm << "countPackTripleMpi: MPI_Pack_size failed on "
81 "scalarDt call"
82 << endl;
83 }
84 return errCode;
85 }
86 totalSize += curSize; // one Scalar
87 }
88 totalSize *= numEnt; // all the entries we want to pack
89
90 size = totalSize; // "commit" the result
91 return errCode;
92}
93
94template <class ScalarType, class OrdinalType>
95int packTripleMpi(const OrdinalType gblRowInd,
96 const OrdinalType gblColInd,
97 MPI_Datatype ordinalDt,
98 const ScalarType& val,
99 MPI_Datatype scalarDt,
100 char outBuf[],
101 const int outBufSize,
102 int& outBufCurPos,
103 MPI_Comm comm,
104 std::ostream* errStrm = NULL) {
105 using std::endl;
106 int errCode = MPI_SUCCESS;
107
108 // Combine the two indices into a single MPI_Pack call.
109 OrdinalType inds[2] = {gblRowInd, gblColInd};
110 errCode = MPI_Pack(inds, 2, ordinalDt,
111 outBuf, outBufSize, &outBufCurPos, comm);
112 if (errCode != MPI_SUCCESS) {
113 if (errStrm != NULL) {
114 *errStrm << "packTripleMpi: MPI_Pack failed for indices i=" << gblRowInd
115 << ", j=" << gblColInd << ", where outBufSize=" << outBufSize
116 << " and outBufCurPos=" << outBufCurPos << "." << endl;
117 }
118 return errCode;
119 }
120 // mfh 17,20 Jan 2017: Some (generally older) MPI implementations
121 // want the first argument to be a pointer to nonconst, even though
122 // MPI_Pack does not modify that argument.
123 errCode = MPI_Pack(const_cast<ScalarType*>(&val), 1, scalarDt,
124 outBuf, outBufSize, &outBufCurPos, comm);
125 if (errCode != MPI_SUCCESS) {
126 if (errStrm != NULL) {
127 *errStrm << "packTripleMpi: MPI_Pack failed on val = " << val
128 << endl;
129 }
130 return errCode;
131 }
132 return errCode;
133}
134
135template <class ScalarType, class OrdinalType>
136int packTriplesMpi(const OrdinalType gblRowInds[],
137 const OrdinalType gblColInds[],
138 MPI_Datatype ordinalDt,
139 const ScalarType vals[],
140 MPI_Datatype scalarDt,
141 const int numEnt,
142 char outBuf[],
143 const int outBufSize,
144 int& outBufCurPos,
145 MPI_Comm comm,
146 std::ostream* errStrm = NULL) {
147 using std::endl;
148 int errCode = MPI_SUCCESS;
149
150 for (int k = 0; k < numEnt; ++k) {
151 errCode = packTripleMpi(gblRowInds[k], gblColInds[k], ordinalDt,
152 vals[k], scalarDt, outBuf, outBufSize,
153 outBufCurPos, comm, errStrm);
154 if (errCode != MPI_SUCCESS) {
155 if (errStrm != NULL) {
156 *errStrm << "packTriplesMpi: packTripleMpi failed at entry k=" << k
157 << endl;
158 }
159 return errCode;
160 }
161 }
162 return errCode;
163}
164
165template <class ScalarType, class OrdinalType>
166int unpackTripleMpi(const char inBuf[],
167 const int inBufSize,
168 int& inBufCurPos,
169 OrdinalType& gblRowInd,
170 OrdinalType& gblColInd,
171 MPI_Datatype ordinalDt,
172 ScalarType& val,
173 MPI_Datatype scalarDt,
174 MPI_Comm comm,
175 std::ostream* errStrm = NULL) {
176 using std::endl;
177 int errCode = MPI_SUCCESS;
178
179 // mfh 17 Jan 2017: Some (generally older) MPI implementations want
180 // the input buffer argument to be a pointer to nonconst, even
181 // though MPI_Unpack does not modify that argument.
182
183 // Combine the two indices into a single MPI_Pack call.
184 OrdinalType inds[2] = {static_cast<OrdinalType>(0),
185 static_cast<OrdinalType>(0)};
186 errCode = MPI_Unpack(const_cast<char*>(inBuf), inBufSize, &inBufCurPos,
187 inds, 2, ordinalDt, comm);
188 if (errCode != MPI_SUCCESS) {
189 if (errStrm != NULL) {
190 *errStrm << "unpackTripleMpi: MPI_Unpack failed when unpacking indices: "
191 "inBufSize="
192 << inBufSize << ", inBufCurPos=" << inBufCurPos << endl;
193 }
194 return errCode;
195 }
196 gblRowInd = inds[0];
197 gblColInd = inds[1];
198
199 // mfh 17 Jan 2017: Some (generally older) MPI implementations want
200 // the input buffer argument to be a pointer to nonconst, even
201 // though MPI_Unpack does not modify that argument.
202 errCode = MPI_Unpack(const_cast<char*>(inBuf), inBufSize, &inBufCurPos,
203 &val, 1, scalarDt, comm);
204 if (errCode != MPI_SUCCESS) {
205 if (errStrm != NULL) {
206 *errStrm << "unpackTripleMpi: MPI_Unpack failed when unpacking value: "
207 "inBufSize="
208 << inBufSize << ", inBufCurPos=" << inBufCurPos << endl;
209 }
210 return errCode;
211 }
212 return errCode;
213}
214
215int unpackTriplesCountMpi(const char inBuf[],
216 const int inBufSize,
217 int& inBufCurPos,
218 int& numEnt,
219 MPI_Comm comm,
220 std::ostream* errStrm = NULL);
221
222template <class ScalarType, class OrdinalType>
223int unpackTriplesMpi(const char inBuf[],
224 const int inBufSize,
225 int& inBufCurPos,
226 OrdinalType gblRowInds[],
227 OrdinalType gblColInds[],
228 MPI_Datatype ordinalDt,
229 ScalarType vals[],
230 MPI_Datatype scalarDt,
231 const int numEnt, // input arg, from unpackTriplesCountMpi
232 MPI_Comm comm,
233 std::ostream* errStrm = NULL) {
234 using std::endl;
235 int errCode = MPI_SUCCESS;
236
237 for (int k = 0; k < numEnt; ++k) {
238 errCode = unpackTripleMpi(inBuf, inBufSize, inBufCurPos,
239 gblRowInds[k], gblColInds[k], ordinalDt,
240 vals[k], scalarDt, comm, errStrm);
241 if (errCode != MPI_SUCCESS) {
242 if (errStrm != NULL) {
243 *errStrm << "unpackTriplesMpi: packTripleMpi failed at entry k=" << k
244 << ": inBufSize=" << inBufSize
245 << ", inBufCurPos=" << inBufCurPos
246 << "." << endl;
247 }
248 return errCode;
249 }
250 }
251 return errCode;
252}
253
254#endif // HAVE_TPETRACORE_MPI
255
256//
257// SKIP DOWN TO HERE FOR "PUBLIC" INTERFACE
258//
259
280int countPackTriplesCount(const ::Teuchos::Comm<int>& comm,
281 int& size,
282 std::ostream* errStrm = NULL);
283
309template <class ScalarType, class OrdinalType>
311 const ::Teuchos::Comm<int>& comm,
312 int& size, // output argument
313 std::ostream* errStrm = NULL) {
314#ifdef HAVE_TPETRACORE_MPI
315 using ::Tpetra::Details::extractMpiCommFromTeuchos;
316 using ::Tpetra::Details::MpiTypeTraits;
317
319 "countPackTriples: "
320 "ScalarType lacks an MpiTypeTraits specialization.");
322 "countPackTriples: "
323 "OrdinalType lacks an MpiTypeTraits specialization.");
324
328
329 const int errCode =
332 size, errStrm);
335 }
338 }
339 return errCode;
340
341#else // NOT HAVE_TPETRACORE_MPI
342 if (errStrm != NULL) {
343 *errStrm << "countPackTriples: Not implemented (no need; there's no need "
344 "to pack or unpack anything if there's only one process)."
345 << std::endl;
346 }
347 return -1;
348#endif // HAVE_TPETRACORE_MPI
349}
350
376int packTriplesCount(const int numEnt,
377 char outBuf[],
378 const int outBufSize,
379 int& outBufCurPos,
380 const ::Teuchos::Comm<int>& comm,
381 std::ostream* errStrm = NULL);
382
408template <class ScalarType, class OrdinalType>
409int
410#ifdef HAVE_TPETRACORE_MPI
412 const OrdinalType gblColInds[],
413 const ScalarType vals[],
414 const int numEnt,
415 char outBuf[],
416 const int outBufSize,
417 int& outBufCurPos,
418 const ::Teuchos::Comm<int>& comm,
419 std::ostream* errStrm = NULL)
420#else // NOT HAVE_TPETRACORE_MPI
421packTriples(const OrdinalType /* gblRowInds */[],
422 const OrdinalType /* gblColInds */[],
423 const ScalarType /* vals */[],
424 const int /* numEnt */,
425 char /* outBuf */[],
426 const int /* outBufSize */,
427 int& /* outBufCurPos */,
428 const ::Teuchos::Comm<int>& /* comm */,
429 std::ostream* errStrm = NULL)
430#endif // HAVE_TPETRACORE_MPI
431{
432#ifdef HAVE_TPETRACORE_MPI
433 using ::Tpetra::Details::extractMpiCommFromTeuchos;
434 using ::Tpetra::Details::MpiTypeTraits;
435
437 "packTriples: "
438 "ScalarType lacks an MpiTypeTraits specialization.");
440 "packTriples: "
441 "OrdinalType lacks an MpiTypeTraits specialization.");
442
446
447 const int errCode =
452 }
455 }
456 return errCode;
457
458#else // NOT HAVE_TPETRACORE_MPI
459 if (errStrm != NULL) {
460 *errStrm << "packTriples: Not implemented (no need; there's no need to "
461 "pack or unpack anything if there's only one process)."
462 << std::endl;
463 }
464 return -1;
465#endif // HAVE_TPETRACORE_MPI
466}
467
491int unpackTriplesCount(const char inBuf[],
492 const int inBufSize,
493 int& inBufCurPos,
494 int& numEnt, // output argument!
495 const ::Teuchos::Comm<int>& comm,
496 std::ostream* errStrm = NULL);
497
526template <class ScalarType, class OrdinalType>
527int
528#ifdef HAVE_TPETRACORE_MPI
529unpackTriples(const char inBuf[],
530 const int inBufSize,
531 int& inBufCurPos,
535 const int numEnt,
536 const ::Teuchos::Comm<int>& comm,
537 std::ostream* errStrm = NULL)
538#else // NOT HAVE_TPETRACORE_MPI
539unpackTriples(const char /* inBuf */[],
540 const int /* inBufSize */,
541 int& /* inBufCurPos */,
542 OrdinalType /* gblRowInds */[],
543 OrdinalType /* gblColInds */[],
544 ScalarType /* vals */[],
545 const int /* numEnt */,
546 const ::Teuchos::Comm<int>& /* comm */,
547 std::ostream* errStrm = NULL)
548#endif // HAVE_TPETRACORE_MPI
549{
550#ifdef HAVE_TPETRACORE_MPI
551 using ::Tpetra::Details::extractMpiCommFromTeuchos;
552 using ::Tpetra::Details::MpiTypeTraits;
553
555 "unpackTriples: "
556 "ScalarType lacks an MpiTypeTraits specialization.");
558 "unpackTriples: "
559 "OrdinalType lacks an MpiTypeTraits specialization.");
560
564
565 const int errCode =
571 }
574 }
575 return errCode;
576
577#else // NOT HAVE_TPETRACORE_MPI
578 if (errStrm != NULL) {
579 *errStrm << "unpackTriples: Not implemented (no need; there's no need to "
580 "pack or unpack anything if there's only one process)."
581 << std::endl;
582 }
583 return -1;
584#endif // HAVE_TPETRACORE_MPI
585}
586
587} // namespace Details
588} // namespace Tpetra
589
590#endif // TPETRA_DETAILS_PACKTRIPLES_HPP
Add specializations of Teuchos::Details::MpiTypeTraits for Kokkos::complex<float> and Kokkos::complex...
Declaration of Tpetra::Details::extractMpiCommFromTeuchos.
Struct that holds views of the contents of a CrsMatrix.
Implementation details of Tpetra.
int packTriplesCount(const int, char[], const int, int &, const ::Teuchos::Comm< int > &, std::ostream *errStrm)
Pack the count (number) of matrix triples.
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 ("triples").
int packTriples(const OrdinalType[], const OrdinalType[], const ScalarType[], const int, char[], const int, int &, const ::Teuchos::Comm< int > &, std::ostream *errStrm=NULL)
Pack matrix entries ("triples" (i, j, A(i,j))) into the given output buffer.
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 unpackTriples(const char[], const int, int &, OrdinalType[], OrdinalType[], ScalarType[], const int, const ::Teuchos::Comm< int > &, std::ostream *errStrm=NULL)
Unpack matrix entries ("triples" (i, j, A(i,j))) from the given input buffer.
int countPackTriples(const int numEnt, const ::Teuchos::Comm< int > &comm, int &size, std::ostream *errStrm=NULL)
Compute the buffer size required by packTriples for packing numEnt number of (i,j,...
Namespace Tpetra contains the class and methods constituting the Tpetra library.