xref: /petsc/src/sys/utils/mpimesg.c (revision 8e3a54c0662fee99ad69f33e814fb6a3f3eef16b)
1c6db04a5SJed Brown #include <petscsys.h> /*I  "petscsys.h"  I*/
276eed172SJunchao Zhang #include <petsc/private/mpiutils.h>
3e5c89e4eSSatish Balay 
4e5c89e4eSSatish Balay /*@C
5811af0c4SBarry Smith   PetscGatherNumberOfMessages -  Computes the number of messages an MPI rank expects to receive during a neighbor communication
6e5c89e4eSSatish Balay 
7d083f849SBarry Smith   Collective
8e5c89e4eSSatish Balay 
9e5c89e4eSSatish Balay   Input Parameters:
10e5c89e4eSSatish Balay + comm     - Communicator
11667f096bSBarry Smith . iflags   - an array of integers of length sizeof(comm). A '1' in `ilengths`[i] represent a
12667f096bSBarry Smith              message from current node to ith node. Optionally `NULL`
13667f096bSBarry Smith - ilengths - Non zero ilengths[i] represent a message to i of length `ilengths`[i].
14667f096bSBarry Smith              Optionally `NULL`.
15e5c89e4eSSatish Balay 
162fe279fdSBarry Smith   Output Parameter:
17e5c89e4eSSatish Balay . nrecvs - number of messages received
18e5c89e4eSSatish Balay 
19e5c89e4eSSatish Balay   Level: developer
20e5c89e4eSSatish Balay 
21e5c89e4eSSatish Balay   Notes:
22e5c89e4eSSatish Balay   With this info, the correct message lengths can be determined using
23811af0c4SBarry Smith   `PetscGatherMessageLengths()`
24e5c89e4eSSatish Balay 
25667f096bSBarry Smith   Either `iflags` or `ilengths` should be provided.  If `iflags` is not
26667f096bSBarry Smith   provided (`NULL`) it can be computed from `ilengths`. If `iflags` is
27667f096bSBarry Smith   provided, `ilengths` is not required.
28e5c89e4eSSatish Balay 
29811af0c4SBarry Smith .seealso: `PetscGatherMessageLengths()`, `PetscGatherMessageLengths2()`, `PetscCommBuildTwoSided()`
30e5c89e4eSSatish Balay @*/
31d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGatherNumberOfMessages(MPI_Comm comm, const PetscMPIInt iflags[], const PetscMPIInt ilengths[], PetscMPIInt *nrecvs)
32d71ae5a4SJacob Faibussowitsch {
33*8e3a54c0SPierre Jolivet   PetscMPIInt size, rank, *recv_buf, i, *iflags_local = NULL, *iflags_localm;
34e5c89e4eSSatish Balay 
35e5c89e4eSSatish Balay   PetscFunctionBegin;
369566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
379566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
38e5c89e4eSSatish Balay 
399566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(size, &recv_buf, size, &iflags_localm));
40e5c89e4eSSatish Balay 
41e5c89e4eSSatish Balay   /* If iflags not provided, compute iflags from ilengths */
42e5c89e4eSSatish Balay   if (!iflags) {
4328b400f6SJacob Faibussowitsch     PetscCheck(ilengths, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Either iflags or ilengths should be provided");
44e5c89e4eSSatish Balay     iflags_local = iflags_localm;
45e5c89e4eSSatish Balay     for (i = 0; i < size; i++) {
46e5c89e4eSSatish Balay       if (ilengths[i]) iflags_local[i] = 1;
47e5c89e4eSSatish Balay       else iflags_local[i] = 0;
48e5c89e4eSSatish Balay     }
49a297a907SKarl Rupp   } else iflags_local = (PetscMPIInt *)iflags;
50e5c89e4eSSatish Balay 
51be87f6c0SPierre Jolivet   /* Post an allreduce to determine the number of messages the current MPI rank will receive */
521c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(iflags_local, recv_buf, size, MPI_INT, MPI_SUM, comm));
53e5c89e4eSSatish Balay   *nrecvs = recv_buf[rank];
54e5c89e4eSSatish Balay 
559566063dSJacob Faibussowitsch   PetscCall(PetscFree2(recv_buf, iflags_localm));
563ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
57e5c89e4eSSatish Balay }
58e5c89e4eSSatish Balay 
59e5c89e4eSSatish Balay /*@C
60da81f932SPierre Jolivet   PetscGatherMessageLengths - Computes information about messages that an MPI rank will receive,
61e5c89e4eSSatish Balay   including (from-id,length) pairs for each message.
62e5c89e4eSSatish Balay 
63d083f849SBarry Smith   Collective
64e5c89e4eSSatish Balay 
65e5c89e4eSSatish Balay   Input Parameters:
66e5c89e4eSSatish Balay + comm     - Communicator
67e5c89e4eSSatish Balay . nsends   - number of messages that are to be sent.
68e5c89e4eSSatish Balay . nrecvs   - number of messages being received
69e5c89e4eSSatish Balay - ilengths - an array of integers of length sizeof(comm)
70667f096bSBarry Smith               a non zero `ilengths`[i] represent a message to i of length `ilengths`[i]
71e5c89e4eSSatish Balay 
72e5c89e4eSSatish Balay   Output Parameters:
73667f096bSBarry Smith + onodes   - list of ranks from which messages are expected
74e5c89e4eSSatish Balay - olengths - corresponding message lengths
75e5c89e4eSSatish Balay 
76e5c89e4eSSatish Balay   Level: developer
77e5c89e4eSSatish Balay 
78e5c89e4eSSatish Balay   Notes:
79811af0c4SBarry Smith   With this info, the correct `MPI_Irecv()` can be posted with the correct
80e5c89e4eSSatish Balay   from-id, with a buffer with the right amount of memory required.
81e5c89e4eSSatish Balay 
82e5c89e4eSSatish Balay   The calling function deallocates the memory in onodes and olengths
83e5c89e4eSSatish Balay 
84667f096bSBarry Smith   To determine `nrecvs`, one can use `PetscGatherNumberOfMessages()`
85e5c89e4eSSatish Balay 
86811af0c4SBarry Smith .seealso: `PetscGatherNumberOfMessages()`, `PetscGatherMessageLengths2()`, `PetscCommBuildTwoSided()`
87e5c89e4eSSatish Balay @*/
88d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGatherMessageLengths(MPI_Comm comm, PetscMPIInt nsends, PetscMPIInt nrecvs, const PetscMPIInt ilengths[], PetscMPIInt **onodes, PetscMPIInt **olengths)
89d71ae5a4SJacob Faibussowitsch {
906bfd7d4fSJunchao Zhang   PetscMPIInt  size, rank, tag, i, j;
91*8e3a54c0SPierre Jolivet   MPI_Request *s_waits, *r_waits;
92*8e3a54c0SPierre Jolivet   MPI_Status  *w_status;
93e5c89e4eSSatish Balay 
94e5c89e4eSSatish Balay   PetscFunctionBegin;
959566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
969566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
979566063dSJacob Faibussowitsch   PetscCall(PetscCommGetNewTag(comm, &tag));
98e5c89e4eSSatish Balay 
99e5c89e4eSSatish Balay   /* cannot use PetscMalloc3() here because in the call to MPI_Waitall() they MUST be contiguous */
1009566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nrecvs + nsends, &r_waits, nrecvs + nsends, &w_status));
101*8e3a54c0SPierre Jolivet   s_waits = PetscSafePointerPlusOffset(r_waits, nrecvs);
102e5c89e4eSSatish Balay 
103e5c89e4eSSatish Balay   /* Post the Irecv to get the message length-info */
1049566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs, olengths));
10548a46eb9SPierre Jolivet   for (i = 0; i < nrecvs; i++) PetscCallMPI(MPI_Irecv((*olengths) + i, 1, MPI_INT, MPI_ANY_SOURCE, tag, comm, r_waits + i));
106e5c89e4eSSatish Balay 
107e5c89e4eSSatish Balay   /* Post the Isends with the message length-info */
108e5c89e4eSSatish Balay   for (i = 0, j = 0; i < size; ++i) {
109e5c89e4eSSatish Balay     if (ilengths[i]) {
1109566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Isend((void *)(ilengths + i), 1, MPI_INT, i, tag, comm, s_waits + j));
111e5c89e4eSSatish Balay       j++;
112e5c89e4eSSatish Balay     }
113e5c89e4eSSatish Balay   }
114e5c89e4eSSatish Balay 
1156aad120cSJose E. Roman   /* Post waits on sends and receives */
1169566063dSJacob Faibussowitsch   if (nrecvs + nsends) PetscCallMPI(MPI_Waitall(nrecvs + nsends, r_waits, w_status));
117e5c89e4eSSatish Balay 
118e5c89e4eSSatish Balay   /* Pack up the received data */
1199566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs, onodes));
1206bfd7d4fSJunchao Zhang   for (i = 0; i < nrecvs; ++i) {
1216bfd7d4fSJunchao Zhang     (*onodes)[i] = w_status[i].MPI_SOURCE;
1226bfd7d4fSJunchao Zhang #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION)
123337bb527SBarry Smith     /* This line is a workaround for a bug in Open MPI 2.1.1 distributed by Ubuntu-18.04.2 LTS.
1246bfd7d4fSJunchao Zhang        It happens in self-to-self MPI_Send/Recv using MPI_ANY_SOURCE for message matching. Open MPI
1256bfd7d4fSJunchao Zhang        does not put correct value in recv buffer. See also
1266bfd7d4fSJunchao Zhang        https://lists.mcs.anl.gov/pipermail/petsc-dev/2019-July/024803.html
1276bfd7d4fSJunchao Zhang        https://www.mail-archive.com/users@lists.open-mpi.org//msg33383.html
1286bfd7d4fSJunchao Zhang      */
1296bfd7d4fSJunchao Zhang     if (w_status[i].MPI_SOURCE == rank) (*olengths)[i] = ilengths[rank];
1306bfd7d4fSJunchao Zhang #endif
1316bfd7d4fSJunchao Zhang   }
1329566063dSJacob Faibussowitsch   PetscCall(PetscFree2(r_waits, w_status));
1333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
134e5c89e4eSSatish Balay }
135dd6ea824SBarry Smith 
13676eed172SJunchao Zhang /* Same as PetscGatherNumberOfMessages(), except using PetscInt for ilengths[] */
137d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGatherNumberOfMessages_Private(MPI_Comm comm, const PetscMPIInt iflags[], const PetscInt ilengths[], PetscMPIInt *nrecvs)
138d71ae5a4SJacob Faibussowitsch {
139*8e3a54c0SPierre Jolivet   PetscMPIInt size, rank, *recv_buf, i, *iflags_local = NULL, *iflags_localm;
14076eed172SJunchao Zhang 
14176eed172SJunchao Zhang   PetscFunctionBegin;
1429566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
1439566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
14476eed172SJunchao Zhang 
1459566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(size, &recv_buf, size, &iflags_localm));
14676eed172SJunchao Zhang 
14776eed172SJunchao Zhang   /* If iflags not provided, compute iflags from ilengths */
14876eed172SJunchao Zhang   if (!iflags) {
14928b400f6SJacob Faibussowitsch     PetscCheck(ilengths, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Either iflags or ilengths should be provided");
15076eed172SJunchao Zhang     iflags_local = iflags_localm;
15176eed172SJunchao Zhang     for (i = 0; i < size; i++) {
15276eed172SJunchao Zhang       if (ilengths[i]) iflags_local[i] = 1;
15376eed172SJunchao Zhang       else iflags_local[i] = 0;
15476eed172SJunchao Zhang     }
15576eed172SJunchao Zhang   } else iflags_local = (PetscMPIInt *)iflags;
15676eed172SJunchao Zhang 
157be87f6c0SPierre Jolivet   /* Post an allreduce to determine the number of messages the current MPI rank will receive */
1581c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(iflags_local, recv_buf, size, MPI_INT, MPI_SUM, comm));
15976eed172SJunchao Zhang   *nrecvs = recv_buf[rank];
16076eed172SJunchao Zhang 
1619566063dSJacob Faibussowitsch   PetscCall(PetscFree2(recv_buf, iflags_localm));
1623ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16376eed172SJunchao Zhang }
16476eed172SJunchao Zhang 
16576eed172SJunchao Zhang /* Same as PetscGatherMessageLengths(), except using PetscInt for message lengths */
166d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGatherMessageLengths_Private(MPI_Comm comm, PetscMPIInt nsends, PetscMPIInt nrecvs, const PetscInt ilengths[], PetscMPIInt **onodes, PetscInt **olengths)
167d71ae5a4SJacob Faibussowitsch {
16876eed172SJunchao Zhang   PetscMPIInt  size, rank, tag, i, j;
169*8e3a54c0SPierre Jolivet   MPI_Request *s_waits, *r_waits;
170*8e3a54c0SPierre Jolivet   MPI_Status  *w_status;
17176eed172SJunchao Zhang 
17276eed172SJunchao Zhang   PetscFunctionBegin;
1739566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
1749566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1759566063dSJacob Faibussowitsch   PetscCall(PetscCommGetNewTag(comm, &tag));
17676eed172SJunchao Zhang 
17776eed172SJunchao Zhang   /* cannot use PetscMalloc3() here because in the call to MPI_Waitall() they MUST be contiguous */
1789566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nrecvs + nsends, &r_waits, nrecvs + nsends, &w_status));
179*8e3a54c0SPierre Jolivet   s_waits = PetscSafePointerPlusOffset(r_waits, nrecvs);
18076eed172SJunchao Zhang 
18176eed172SJunchao Zhang   /* Post the Irecv to get the message length-info */
1829566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs, olengths));
18348a46eb9SPierre Jolivet   for (i = 0; i < nrecvs; i++) PetscCallMPI(MPI_Irecv((*olengths) + i, 1, MPIU_INT, MPI_ANY_SOURCE, tag, comm, r_waits + i));
18476eed172SJunchao Zhang 
18576eed172SJunchao Zhang   /* Post the Isends with the message length-info */
18676eed172SJunchao Zhang   for (i = 0, j = 0; i < size; ++i) {
18776eed172SJunchao Zhang     if (ilengths[i]) {
1889566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Isend((void *)(ilengths + i), 1, MPIU_INT, i, tag, comm, s_waits + j));
18976eed172SJunchao Zhang       j++;
19076eed172SJunchao Zhang     }
19176eed172SJunchao Zhang   }
19276eed172SJunchao Zhang 
1936aad120cSJose E. Roman   /* Post waits on sends and receives */
1949566063dSJacob Faibussowitsch   if (nrecvs + nsends) PetscCallMPI(MPI_Waitall(nrecvs + nsends, r_waits, w_status));
19576eed172SJunchao Zhang 
19676eed172SJunchao Zhang   /* Pack up the received data */
1979566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs, onodes));
19876eed172SJunchao Zhang   for (i = 0; i < nrecvs; ++i) {
19976eed172SJunchao Zhang     (*onodes)[i] = w_status[i].MPI_SOURCE;
20076eed172SJunchao Zhang     if (w_status[i].MPI_SOURCE == rank) (*olengths)[i] = ilengths[rank]; /* See comments in PetscGatherMessageLengths */
20176eed172SJunchao Zhang   }
2029566063dSJacob Faibussowitsch   PetscCall(PetscFree2(r_waits, w_status));
2033ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20476eed172SJunchao Zhang }
20576eed172SJunchao Zhang 
206e5c89e4eSSatish Balay /*@C
207811af0c4SBarry Smith   PetscGatherMessageLengths2 - Computes info about messages that a MPI rank will receive,
208811af0c4SBarry Smith   including (from-id,length) pairs for each message. Same functionality as `PetscGatherMessageLengths()`
209e5c89e4eSSatish Balay   except it takes TWO ilenths and output TWO olengths.
210e5c89e4eSSatish Balay 
211d083f849SBarry Smith   Collective
212e5c89e4eSSatish Balay 
213e5c89e4eSSatish Balay   Input Parameters:
214e5c89e4eSSatish Balay + comm      - Communicator
215e5c89e4eSSatish Balay . nsends    - number of messages that are to be sent.
216e5c89e4eSSatish Balay . nrecvs    - number of messages being received
2176b867d5aSJose E. Roman . ilengths1 - first array of integers of length sizeof(comm)
2186b867d5aSJose E. Roman - ilengths2 - second array of integers of length sizeof(comm)
219e5c89e4eSSatish Balay 
220e5c89e4eSSatish Balay   Output Parameters:
221667f096bSBarry Smith + onodes    - list of ranks from which messages are expected
2226b867d5aSJose E. Roman . olengths1 - first corresponding message lengths
2236b867d5aSJose E. Roman - olengths2 - second  message lengths
224e5c89e4eSSatish Balay 
225e5c89e4eSSatish Balay   Level: developer
226e5c89e4eSSatish Balay 
227e5c89e4eSSatish Balay   Notes:
228811af0c4SBarry Smith   With this info, the correct `MPI_Irecv()` can be posted with the correct
229e5c89e4eSSatish Balay   from-id, with a buffer with the right amount of memory required.
230e5c89e4eSSatish Balay 
231667f096bSBarry Smith   The calling function should `PetscFree()` the memory in `onodes` and `olengths`
232e5c89e4eSSatish Balay 
233667f096bSBarry Smith   To determine `nrecvs`, one can use `PetscGatherNumberOfMessages()`
234e5c89e4eSSatish Balay 
235811af0c4SBarry Smith .seealso: `PetscGatherMessageLengths()`, `PetscGatherNumberOfMessages()`, `PetscCommBuildTwoSided()`
236e5c89e4eSSatish Balay @*/
237d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGatherMessageLengths2(MPI_Comm comm, PetscMPIInt nsends, PetscMPIInt nrecvs, const PetscMPIInt ilengths1[], const PetscMPIInt ilengths2[], PetscMPIInt **onodes, PetscMPIInt **olengths1, PetscMPIInt **olengths2)
238d71ae5a4SJacob Faibussowitsch {
239*8e3a54c0SPierre Jolivet   PetscMPIInt  size, tag, i, j, *buf_s, *buf_r, *buf_j = NULL;
240*8e3a54c0SPierre Jolivet   MPI_Request *s_waits, *r_waits;
241*8e3a54c0SPierre Jolivet   MPI_Status  *w_status;
242e5c89e4eSSatish Balay 
243e5c89e4eSSatish Balay   PetscFunctionBegin;
2449566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
2459566063dSJacob Faibussowitsch   PetscCall(PetscCommGetNewTag(comm, &tag));
246e5c89e4eSSatish Balay 
2473bf92927SBarry Smith   /* cannot use PetscMalloc5() because r_waits and s_waits must be contiguous for the call to MPI_Waitall() */
2489566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(nrecvs + nsends, &r_waits, 2 * nrecvs, &buf_r, 2 * nsends, &buf_s, nrecvs + nsends, &w_status));
249*8e3a54c0SPierre Jolivet   s_waits = PetscSafePointerPlusOffset(r_waits, nrecvs);
250e5c89e4eSSatish Balay 
251e5c89e4eSSatish Balay   /* Post the Irecv to get the message length-info */
2529566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs + 1, olengths1));
2539566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs + 1, olengths2));
254e5c89e4eSSatish Balay   for (i = 0; i < nrecvs; i++) {
255e5c89e4eSSatish Balay     buf_j = buf_r + (2 * i);
2569566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Irecv(buf_j, 2, MPI_INT, MPI_ANY_SOURCE, tag, comm, r_waits + i));
257e5c89e4eSSatish Balay   }
258e5c89e4eSSatish Balay 
259e5c89e4eSSatish Balay   /* Post the Isends with the message length-info */
260e5c89e4eSSatish Balay   for (i = 0, j = 0; i < size; ++i) {
261e5c89e4eSSatish Balay     if (ilengths1[i]) {
262e5c89e4eSSatish Balay       buf_j    = buf_s + (2 * j);
263e5c89e4eSSatish Balay       buf_j[0] = *(ilengths1 + i);
264e5c89e4eSSatish Balay       buf_j[1] = *(ilengths2 + i);
2659566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Isend(buf_j, 2, MPI_INT, i, tag, comm, s_waits + j));
266e5c89e4eSSatish Balay       j++;
267e5c89e4eSSatish Balay     }
268e5c89e4eSSatish Balay   }
26908401ef6SPierre Jolivet   PetscCheck(j == nsends, PETSC_COMM_SELF, PETSC_ERR_PLIB, "j %d not equal to expected number of sends %d", j, nsends);
270e5c89e4eSSatish Balay 
2716aad120cSJose E. Roman   /* Post waits on sends and receives */
2729566063dSJacob Faibussowitsch   if (nrecvs + nsends) PetscCallMPI(MPI_Waitall(nrecvs + nsends, r_waits, w_status));
273e5c89e4eSSatish Balay 
274e5c89e4eSSatish Balay   /* Pack up the received data */
2759566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs + 1, onodes));
276e5c89e4eSSatish Balay   for (i = 0; i < nrecvs; ++i) {
277e5c89e4eSSatish Balay     (*onodes)[i]    = w_status[i].MPI_SOURCE;
278e5c89e4eSSatish Balay     buf_j           = buf_r + (2 * i);
279e5c89e4eSSatish Balay     (*olengths1)[i] = buf_j[0];
280e5c89e4eSSatish Balay     (*olengths2)[i] = buf_j[1];
281e5c89e4eSSatish Balay   }
282e5c89e4eSSatish Balay 
2839566063dSJacob Faibussowitsch   PetscCall(PetscFree4(r_waits, buf_r, buf_s, w_status));
2843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
285e5c89e4eSSatish Balay }
286e5c89e4eSSatish Balay 
287e5c89e4eSSatish Balay /*
288a5b23f4aSJose E. Roman   Allocate a buffer sufficient to hold messages of size specified in olengths.
289e5c89e4eSSatish Balay   And post Irecvs on these buffers using node info from onodes
290e5c89e4eSSatish Balay  */
291d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPostIrecvInt(MPI_Comm comm, PetscMPIInt tag, PetscMPIInt nrecvs, const PetscMPIInt onodes[], const PetscMPIInt olengths[], PetscInt ***rbuf, MPI_Request **r_waits)
292d71ae5a4SJacob Faibussowitsch {
293c05d87d6SBarry Smith   PetscInt   **rbuf_t, i, len = 0;
294e5c89e4eSSatish Balay   MPI_Request *r_waits_t;
295e5c89e4eSSatish Balay 
296e5c89e4eSSatish Balay   PetscFunctionBegin;
297e5c89e4eSSatish Balay   /* compute memory required for recv buffers */
298e5c89e4eSSatish Balay   for (i = 0; i < nrecvs; i++) len += olengths[i]; /* each message length */
299e5c89e4eSSatish Balay 
300e5c89e4eSSatish Balay   /* allocate memory for recv buffers */
3019566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs + 1, &rbuf_t));
3029566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(len, &rbuf_t[0]));
303e5c89e4eSSatish Balay   for (i = 1; i < nrecvs; ++i) rbuf_t[i] = rbuf_t[i - 1] + olengths[i - 1];
304e5c89e4eSSatish Balay 
305e5c89e4eSSatish Balay   /* Post the receives */
3069566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs, &r_waits_t));
30748a46eb9SPierre Jolivet   for (i = 0; i < nrecvs; ++i) PetscCallMPI(MPI_Irecv(rbuf_t[i], olengths[i], MPIU_INT, onodes[i], tag, comm, r_waits_t + i));
308e5c89e4eSSatish Balay 
309e5c89e4eSSatish Balay   *rbuf    = rbuf_t;
310e5c89e4eSSatish Balay   *r_waits = r_waits_t;
3113ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
312e5c89e4eSSatish Balay }
313e5c89e4eSSatish Balay 
314d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPostIrecvScalar(MPI_Comm comm, PetscMPIInt tag, PetscMPIInt nrecvs, const PetscMPIInt onodes[], const PetscMPIInt olengths[], PetscScalar ***rbuf, MPI_Request **r_waits)
315d71ae5a4SJacob Faibussowitsch {
316052f0c41SBarry Smith   PetscMPIInt   i;
317e5c89e4eSSatish Balay   PetscScalar **rbuf_t;
318e5c89e4eSSatish Balay   MPI_Request  *r_waits_t;
319c05d87d6SBarry Smith   PetscInt      len = 0;
320e5c89e4eSSatish Balay 
321fe28d99cSBarry Smith   PetscFunctionBegin;
322e5c89e4eSSatish Balay   /* compute memory required for recv buffers */
323e5c89e4eSSatish Balay   for (i = 0; i < nrecvs; i++) len += olengths[i]; /* each message length */
324e5c89e4eSSatish Balay 
325e5c89e4eSSatish Balay   /* allocate memory for recv buffers */
3269566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs + 1, &rbuf_t));
3279566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(len, &rbuf_t[0]));
328e5c89e4eSSatish Balay   for (i = 1; i < nrecvs; ++i) rbuf_t[i] = rbuf_t[i - 1] + olengths[i - 1];
329e5c89e4eSSatish Balay 
330e5c89e4eSSatish Balay   /* Post the receives */
3319566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs, &r_waits_t));
33248a46eb9SPierre Jolivet   for (i = 0; i < nrecvs; ++i) PetscCallMPI(MPI_Irecv(rbuf_t[i], olengths[i], MPIU_SCALAR, onodes[i], tag, comm, r_waits_t + i));
333e5c89e4eSSatish Balay 
334e5c89e4eSSatish Balay   *rbuf    = rbuf_t;
335e5c89e4eSSatish Balay   *r_waits = r_waits_t;
3363ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
337e5c89e4eSSatish Balay }
338