Tpetra parallel linear algebra Version of the Day
Loading...
Searching...
No Matches
Tpetra_Details_PackTriples.hpp
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#ifndef TPETRA_DETAILS_PACKTRIPLES_HPP
43#define TPETRA_DETAILS_PACKTRIPLES_HPP
44
45#include "TpetraCore_config.h"
46#include "Teuchos_Comm.hpp"
47#ifdef HAVE_TPETRACORE_MPI
50#endif // HAVE_TPETRACORE_MPI
51#include <ostream>
52
53namespace Tpetra {
54namespace Details {
55
56//
57// Search for "SKIP DOWN TO HERE" (omit quotes) for the "public"
58// interface. I put "public" in quotes because it's public only for
59// Tpetra developers, NOT for Tpetra users.
60//
61
62#ifdef HAVE_TPETRACORE_MPI
63
64// It's not useful to pack or unpack if not using MPI. Thus, we only
65// need to define these with MPI. For a non-MPI build, we just need
66// some outer stub interface that throws an exception.
67
68int
69countPackTriplesCountMpi (MPI_Comm comm,
70 int& size,
71 std::ostream* errStrm = NULL);
72
73int
74packTriplesCountMpi (const int numEnt,
75 char outBuf[],
76 const int outBufSize,
77 int& outBufCurPos,
78 MPI_Comm comm,
79 std::ostream* errStrm = NULL);
80
81template<class ScalarType, class OrdinalType>
82int
83countPackTriplesMpi (MPI_Datatype ordinalDt,
84 MPI_Datatype scalarDt,
85 const int numEnt,
86 MPI_Comm comm,
87 int& size,
88 std::ostream* errStrm = NULL)
89{
90 using std::endl;
91 int errCode = MPI_SUCCESS;
92
93 int totalSize = 0; // return value
94
95 // Count the global row and column indices.
96 {
97 int curSize = 0;
98 // We're packing two ordinals, the row resp. column index.
99 errCode = MPI_Pack_size (2, ordinalDt, comm, &curSize);
100 if (errCode != MPI_SUCCESS) {
101 if (errStrm != NULL) {
102 *errStrm << "countPackTripleMpi: MPI_Pack_size failed on "
103 "ordinalDt call" << endl;
104 }
105 return errCode;
106 }
107 totalSize += curSize;
108 }
109 // Count the matrix value.
110 {
111 int curSize = 0;
112 errCode = MPI_Pack_size (1, scalarDt, comm, &curSize);
113 if (errCode != MPI_SUCCESS) {
114 if (errStrm != NULL) {
115 *errStrm << "countPackTripleMpi: MPI_Pack_size failed on "
116 "scalarDt call" << endl;
117 }
118 return errCode;
119 }
120 totalSize += curSize; // one Scalar
121 }
122 totalSize *= numEnt; // all the entries we want to pack
123
124 size = totalSize; // "commit" the result
125 return errCode;
126}
127
128template<class ScalarType, class OrdinalType>
129int
130packTripleMpi (const OrdinalType gblRowInd,
131 const OrdinalType gblColInd,
132 MPI_Datatype ordinalDt,
133 const ScalarType& val,
134 MPI_Datatype scalarDt,
135 char outBuf[],
136 const int outBufSize,
137 int& outBufCurPos,
138 MPI_Comm comm,
139 std::ostream* errStrm = NULL)
140{
141 using std::endl;
142 int errCode = MPI_SUCCESS;
143
144 // Combine the two indices into a single MPI_Pack call.
145 OrdinalType inds[2] = {gblRowInd, gblColInd};
146 errCode = MPI_Pack (inds, 2, ordinalDt,
147 outBuf, outBufSize, &outBufCurPos, comm);
148 if (errCode != MPI_SUCCESS) {
149 if (errStrm != NULL) {
150 *errStrm << "packTripleMpi: MPI_Pack failed for indices i=" << gblRowInd
151 << ", j=" << gblColInd << ", where outBufSize=" << outBufSize
152 << " and outBufCurPos=" << outBufCurPos << "." << endl;
153 }
154 return errCode;
155 }
156 // mfh 17,20 Jan 2017: Some (generally older) MPI implementations
157 // want the first argument to be a pointer to nonconst, even though
158 // MPI_Pack does not modify that argument.
159 errCode = MPI_Pack (const_cast<ScalarType*> (&val), 1, scalarDt,
160 outBuf, outBufSize, &outBufCurPos, comm);
161 if (errCode != MPI_SUCCESS) {
162 if (errStrm != NULL) {
163 *errStrm << "packTripleMpi: MPI_Pack failed on val = " << val
164 << endl;
165 }
166 return errCode;
167 }
168 return errCode;
169}
170
171template<class ScalarType, class OrdinalType>
172int
173packTriplesMpi (const OrdinalType gblRowInds[],
174 const OrdinalType gblColInds[],
175 MPI_Datatype ordinalDt,
176 const ScalarType vals[],
177 MPI_Datatype scalarDt,
178 const int numEnt,
179 char outBuf[],
180 const int outBufSize,
181 int& outBufCurPos,
182 MPI_Comm comm,
183 std::ostream* errStrm = NULL)
184{
185 using std::endl;
186 int errCode = MPI_SUCCESS;
187
188 for (int k = 0; k < numEnt; ++k) {
189 errCode = packTripleMpi (gblRowInds[k], gblColInds[k], ordinalDt,
190 vals[k], scalarDt, outBuf, outBufSize,
191 outBufCurPos, comm, errStrm);
192 if (errCode != MPI_SUCCESS) {
193 if (errStrm != NULL) {
194 *errStrm << "packTriplesMpi: packTripleMpi failed at entry k=" << k
195 << endl;
196 }
197 return errCode;
198 }
199 }
200 return errCode;
201}
202
203template<class ScalarType, class OrdinalType>
204int
205unpackTripleMpi (const char inBuf[],
206 const int inBufSize,
207 int& inBufCurPos,
208 OrdinalType& gblRowInd,
209 OrdinalType& gblColInd,
210 MPI_Datatype ordinalDt,
211 ScalarType& val,
212 MPI_Datatype scalarDt,
213 MPI_Comm comm,
214 std::ostream* errStrm = NULL)
215{
216 using std::endl;
217 int errCode = MPI_SUCCESS;
218
219 // mfh 17 Jan 2017: Some (generally older) MPI implementations want
220 // the input buffer argument to be a pointer to nonconst, even
221 // though MPI_Unpack does not modify that argument.
222
223 // Combine the two indices into a single MPI_Pack call.
224 OrdinalType inds[2] = {static_cast<OrdinalType> (0),
225 static_cast<OrdinalType> (0)};
226 errCode = MPI_Unpack (const_cast<char*> (inBuf), inBufSize, &inBufCurPos,
227 inds, 2, ordinalDt, comm);
228 if (errCode != MPI_SUCCESS) {
229 if (errStrm != NULL) {
230 *errStrm << "unpackTripleMpi: MPI_Unpack failed when unpacking indices: "
231 "inBufSize=" << inBufSize << ", inBufCurPos=" << inBufCurPos << endl;
232 }
233 return errCode;
234 }
235 gblRowInd = inds[0];
236 gblColInd = inds[1];
237
238 // mfh 17 Jan 2017: Some (generally older) MPI implementations want
239 // the input buffer argument to be a pointer to nonconst, even
240 // though MPI_Unpack does not modify that argument.
241 errCode = MPI_Unpack (const_cast<char*> (inBuf), inBufSize, &inBufCurPos,
242 &val, 1, scalarDt, comm);
243 if (errCode != MPI_SUCCESS) {
244 if (errStrm != NULL) {
245 *errStrm << "unpackTripleMpi: MPI_Unpack failed when unpacking value: "
246 "inBufSize=" << inBufSize << ", inBufCurPos=" << inBufCurPos << endl;
247 }
248 return errCode;
249 }
250 return errCode;
251}
252
253int
254unpackTriplesCountMpi (const char inBuf[],
255 const int inBufSize,
256 int& inBufCurPos,
257 int& numEnt,
258 MPI_Comm comm,
259 std::ostream* errStrm = NULL);
260
261template<class ScalarType, class OrdinalType>
262int
263unpackTriplesMpi (const char inBuf[],
264 const int inBufSize,
265 int& inBufCurPos,
266 OrdinalType gblRowInds[],
267 OrdinalType gblColInds[],
268 MPI_Datatype ordinalDt,
269 ScalarType vals[],
270 MPI_Datatype scalarDt,
271 const int numEnt, // input arg, from unpackTriplesCountMpi
272 MPI_Comm comm,
273 std::ostream* errStrm = NULL)
274{
275 using std::endl;
276 int errCode = MPI_SUCCESS;
277
278 for (int k = 0; k < numEnt; ++k) {
279 errCode = unpackTripleMpi (inBuf, inBufSize, inBufCurPos,
280 gblRowInds[k], gblColInds[k], ordinalDt,
281 vals[k], scalarDt, comm, errStrm);
282 if (errCode != MPI_SUCCESS) {
283 if (errStrm != NULL) {
284 *errStrm << "unpackTriplesMpi: packTripleMpi failed at entry k=" << k
285 << ": inBufSize=" << inBufSize
286 << ", inBufCurPos=" << inBufCurPos
287 << "." << endl;
288 }
289 return errCode;
290 }
291 }
292 return errCode;
293}
294
295#endif // HAVE_TPETRACORE_MPI
296
297//
298// SKIP DOWN TO HERE FOR "PUBLIC" INTERFACE
299//
300
321int
322countPackTriplesCount (const ::Teuchos::Comm<int>& comm,
323 int& size,
324 std::ostream* errStrm = NULL);
325
351template<class ScalarType, class OrdinalType>
352int
353countPackTriples (const int numEnt,
354 const ::Teuchos::Comm<int>& comm,
355 int& size, // output argument
356 std::ostream* errStrm = NULL)
357{
358#ifdef HAVE_TPETRACORE_MPI
359 using ::Tpetra::Details::extractMpiCommFromTeuchos;
360 using ::Tpetra::Details::MpiTypeTraits;
361
362 static_assert (MpiTypeTraits<ScalarType>::isSpecialized, "countPackTriples: "
363 "ScalarType lacks an MpiTypeTraits specialization.");
364 static_assert (MpiTypeTraits<OrdinalType>::isSpecialized, "countPackTriples: "
365 "OrdinalType lacks an MpiTypeTraits specialization.");
366
367 MPI_Comm mpiComm = extractMpiCommFromTeuchos (comm);
368 MPI_Datatype ordinalDt = MpiTypeTraits<OrdinalType>::getType ();
369 MPI_Datatype scalarDt = MpiTypeTraits<ScalarType>::getType ();
370
371 const int errCode =
372 countPackTriplesMpi<ScalarType, OrdinalType> (ordinalDt, scalarDt,
373 numEnt, mpiComm,
374 size, errStrm);
375 if (MpiTypeTraits<ScalarType>::needsFree) {
376 (void) MPI_Type_free (&scalarDt);
377 }
378 if (MpiTypeTraits<OrdinalType>::needsFree) {
379 (void) MPI_Type_free (&ordinalDt);
380 }
381 return errCode;
382
383#else // NOT HAVE_TPETRACORE_MPI
384 if (errStrm != NULL) {
385 *errStrm << "countPackTriples: Not implemented (no need; there's no need "
386 "to pack or unpack anything if there's only one process)." << std::endl;
387 }
388 return -1;
389#endif // HAVE_TPETRACORE_MPI
390}
391
417int
418packTriplesCount (const int numEnt,
419 char outBuf[],
420 const int outBufSize,
421 int& outBufCurPos,
422 const ::Teuchos::Comm<int>& comm,
423 std::ostream* errStrm = NULL);
424
450template<class ScalarType, class OrdinalType>
451int
452#ifdef HAVE_TPETRACORE_MPI
453packTriples (const OrdinalType gblRowInds[],
454 const OrdinalType gblColInds[],
455 const ScalarType vals[],
456 const int numEnt,
457 char outBuf[],
458 const int outBufSize,
459 int& outBufCurPos,
460 const ::Teuchos::Comm<int>& comm,
461 std::ostream* errStrm = NULL)
462#else // NOT HAVE_TPETRACORE_MPI
463packTriples (const OrdinalType /* gblRowInds */ [],
464 const OrdinalType /* gblColInds */ [],
465 const ScalarType /* vals */ [],
466 const int /* numEnt */,
467 char /* outBuf */ [],
468 const int /* outBufSize */,
469 int& /* outBufCurPos */,
470 const ::Teuchos::Comm<int>& /* comm */,
471 std::ostream* errStrm = NULL)
472#endif // HAVE_TPETRACORE_MPI
473{
474#ifdef HAVE_TPETRACORE_MPI
475 using ::Tpetra::Details::extractMpiCommFromTeuchos;
476 using ::Tpetra::Details::MpiTypeTraits;
477
478 static_assert (MpiTypeTraits<ScalarType>::isSpecialized, "packTriples: "
479 "ScalarType lacks an MpiTypeTraits specialization.");
480 static_assert (MpiTypeTraits<OrdinalType>::isSpecialized, "packTriples: "
481 "OrdinalType lacks an MpiTypeTraits specialization.");
482
483 MPI_Comm mpiComm = extractMpiCommFromTeuchos (comm);
484 MPI_Datatype ordinalDt = MpiTypeTraits<OrdinalType>::getType ();
485 MPI_Datatype scalarDt = MpiTypeTraits<ScalarType>::getType ();
486
487 const int errCode =
488 packTriplesMpi (gblRowInds, gblColInds, ordinalDt, vals, scalarDt,
489 numEnt, outBuf, outBufSize, outBufCurPos, mpiComm, errStrm);
490 if (MpiTypeTraits<ScalarType>::needsFree) {
491 (void) MPI_Type_free (&scalarDt);
492 }
493 if (MpiTypeTraits<OrdinalType>::needsFree) {
494 (void) MPI_Type_free (&ordinalDt);
495 }
496 return errCode;
497
498#else // NOT HAVE_TPETRACORE_MPI
499 if (errStrm != NULL) {
500 *errStrm << "packTriples: Not implemented (no need; there's no need to "
501 "pack or unpack anything if there's only one process)." << std::endl;
502 }
503 return -1;
504#endif // HAVE_TPETRACORE_MPI
505}
506
530int
531unpackTriplesCount (const char inBuf[],
532 const int inBufSize,
533 int& inBufCurPos,
534 int& numEnt, // output argument!
535 const ::Teuchos::Comm<int>& comm,
536 std::ostream* errStrm = NULL);
537
566template<class ScalarType, class OrdinalType>
567int
568#ifdef HAVE_TPETRACORE_MPI
569unpackTriples (const char inBuf[],
570 const int inBufSize,
571 int& inBufCurPos,
572 OrdinalType gblRowInds[],
573 OrdinalType gblColInds[],
574 ScalarType vals[],
575 const int numEnt,
576 const ::Teuchos::Comm<int>& comm,
577 std::ostream* errStrm = NULL)
578#else // NOT HAVE_TPETRACORE_MPI
579unpackTriples (const char /* inBuf */ [],
580 const int /* inBufSize */,
581 int& /* inBufCurPos */,
582 OrdinalType /* gblRowInds */ [],
583 OrdinalType /* gblColInds */ [],
584 ScalarType /* vals */ [],
585 const int /* numEnt */,
586 const ::Teuchos::Comm<int>& /* comm */,
587 std::ostream* errStrm = NULL)
588#endif // HAVE_TPETRACORE_MPI
589{
590#ifdef HAVE_TPETRACORE_MPI
591 using ::Tpetra::Details::extractMpiCommFromTeuchos;
592 using ::Tpetra::Details::MpiTypeTraits;
593
594 static_assert (MpiTypeTraits<ScalarType>::isSpecialized, "unpackTriples: "
595 "ScalarType lacks an MpiTypeTraits specialization.");
596 static_assert (MpiTypeTraits<OrdinalType>::isSpecialized, "unpackTriples: "
597 "OrdinalType lacks an MpiTypeTraits specialization.");
598
599 MPI_Comm mpiComm = extractMpiCommFromTeuchos (comm);
600 MPI_Datatype ordinalDt = MpiTypeTraits<OrdinalType>::getType ();
601 MPI_Datatype scalarDt = MpiTypeTraits<ScalarType>::getType ();
602
603 const int errCode =
604 unpackTriplesMpi (inBuf, inBufSize, inBufCurPos,
605 gblRowInds, gblColInds, ordinalDt,
606 vals, scalarDt, numEnt, mpiComm, errStrm);
607 if (MpiTypeTraits<ScalarType>::needsFree) {
608 (void) MPI_Type_free (&scalarDt);
609 }
610 if (MpiTypeTraits<OrdinalType>::needsFree) {
611 (void) MPI_Type_free (&ordinalDt);
612 }
613 return errCode;
614
615#else // NOT HAVE_TPETRACORE_MPI
616 if (errStrm != NULL) {
617 *errStrm << "unpackTriples: Not implemented (no need; there's no need to "
618 "pack or unpack anything if there's only one process)." << std::endl;
619 }
620 return -1;
621#endif // HAVE_TPETRACORE_MPI
622}
623
624} // namespace Details
625} // namespace Tpetra
626
627#endif // TPETRA_DETAILS_PACKTRIPLES_HPP
Add specializations of Teuchos::Details::MpiTypeTraits for Kokkos::complex<float> and Kokkos::complex...
Declaration of Tpetra::Details::extractMpiCommFromTeuchos.
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.