xref: /petsc/src/sys/utils/mpimesg.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
1e5c89e4eSSatish Balay 
2c6db04a5SJed Brown #include <petscsys.h> /*I  "petscsys.h"  I*/
376eed172SJunchao Zhang #include <petsc/private/mpiutils.h>
4e5c89e4eSSatish Balay 
5e5c89e4eSSatish Balay /*@C
6e5c89e4eSSatish Balay   PetscGatherNumberOfMessages -  Computes the number of messages a node expects to receive
7e5c89e4eSSatish Balay 
8d083f849SBarry Smith   Collective
9e5c89e4eSSatish Balay 
10e5c89e4eSSatish Balay   Input Parameters:
11e5c89e4eSSatish Balay + comm     - Communicator
12e5c89e4eSSatish Balay . iflags   - an array of integers of length sizeof(comm). A '1' in ilengths[i] represent a
130298fd71SBarry Smith              message from current node to ith node. Optionally NULL
14e5c89e4eSSatish Balay - ilengths - Non zero ilengths[i] represent a message to i of length ilengths[i].
150298fd71SBarry Smith              Optionally NULL.
16e5c89e4eSSatish Balay 
17e5c89e4eSSatish Balay   Output Parameters:
18e5c89e4eSSatish Balay . nrecvs    - number of messages received
19e5c89e4eSSatish Balay 
20e5c89e4eSSatish Balay   Level: developer
21e5c89e4eSSatish Balay 
22e5c89e4eSSatish Balay   Notes:
23e5c89e4eSSatish Balay   With this info, the correct message lengths can be determined using
24e5c89e4eSSatish Balay   PetscGatherMessageLengths()
25e5c89e4eSSatish Balay 
26e5c89e4eSSatish Balay   Either iflags or ilengths should be provided.  If iflags is not
270298fd71SBarry Smith   provided (NULL) it can be computed from ilengths. If iflags is
28e5c89e4eSSatish Balay   provided, ilengths is not required.
29e5c89e4eSSatish Balay 
30db781477SPatrick Sanan .seealso: `PetscGatherMessageLengths()`
31e5c89e4eSSatish Balay @*/
329371c9d4SSatish Balay PetscErrorCode PetscGatherNumberOfMessages(MPI_Comm comm, const PetscMPIInt iflags[], const PetscMPIInt ilengths[], PetscMPIInt *nrecvs) {
330298fd71SBarry Smith   PetscMPIInt size, rank, *recv_buf, i, *iflags_local = NULL, *iflags_localm = NULL;
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 
51e5c89e4eSSatish Balay   /* Post an allreduce to determine the numer of messages the current node 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));
56e5c89e4eSSatish Balay   PetscFunctionReturn(0);
57e5c89e4eSSatish Balay }
58e5c89e4eSSatish Balay 
59e5c89e4eSSatish Balay /*@C
60e5c89e4eSSatish Balay   PetscGatherMessageLengths - Computes info about messages that a MPI-node 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)
70e5c89e4eSSatish Balay               a non zero ilengths[i] represent a message to i of length ilengths[i]
71e5c89e4eSSatish Balay 
72e5c89e4eSSatish Balay   Output Parameters:
73e5c89e4eSSatish Balay + onodes    - list of node-ids from which messages are expected
74e5c89e4eSSatish Balay - olengths  - corresponding message lengths
75e5c89e4eSSatish Balay 
76e5c89e4eSSatish Balay   Level: developer
77e5c89e4eSSatish Balay 
78e5c89e4eSSatish Balay   Notes:
79e5c89e4eSSatish Balay   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 
84c2916339SPierre Jolivet   To determine nrecvs, one can use PetscGatherNumberOfMessages()
85e5c89e4eSSatish Balay 
86db781477SPatrick Sanan .seealso: `PetscGatherNumberOfMessages()`
87e5c89e4eSSatish Balay @*/
889371c9d4SSatish Balay PetscErrorCode PetscGatherMessageLengths(MPI_Comm comm, PetscMPIInt nsends, PetscMPIInt nrecvs, const PetscMPIInt ilengths[], PetscMPIInt **onodes, PetscMPIInt **olengths) {
896bfd7d4fSJunchao Zhang   PetscMPIInt  size, rank, tag, i, j;
900298fd71SBarry Smith   MPI_Request *s_waits = NULL, *r_waits = NULL;
910298fd71SBarry Smith   MPI_Status  *w_status = NULL;
92e5c89e4eSSatish Balay 
93e5c89e4eSSatish Balay   PetscFunctionBegin;
949566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
959566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
969566063dSJacob Faibussowitsch   PetscCall(PetscCommGetNewTag(comm, &tag));
97e5c89e4eSSatish Balay 
98e5c89e4eSSatish Balay   /* cannot use PetscMalloc3() here because in the call to MPI_Waitall() they MUST be contiguous */
999566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nrecvs + nsends, &r_waits, nrecvs + nsends, &w_status));
100e5c89e4eSSatish Balay   s_waits = r_waits + nrecvs;
101e5c89e4eSSatish Balay 
102e5c89e4eSSatish Balay   /* Post the Irecv to get the message length-info */
1039566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs, olengths));
104*48a46eb9SPierre Jolivet   for (i = 0; i < nrecvs; i++) PetscCallMPI(MPI_Irecv((*olengths) + i, 1, MPI_INT, MPI_ANY_SOURCE, tag, comm, r_waits + i));
105e5c89e4eSSatish Balay 
106e5c89e4eSSatish Balay   /* Post the Isends with the message length-info */
107e5c89e4eSSatish Balay   for (i = 0, j = 0; i < size; ++i) {
108e5c89e4eSSatish Balay     if (ilengths[i]) {
1099566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Isend((void *)(ilengths + i), 1, MPI_INT, i, tag, comm, s_waits + j));
110e5c89e4eSSatish Balay       j++;
111e5c89e4eSSatish Balay     }
112e5c89e4eSSatish Balay   }
113e5c89e4eSSatish Balay 
1146aad120cSJose E. Roman   /* Post waits on sends and receives */
1159566063dSJacob Faibussowitsch   if (nrecvs + nsends) PetscCallMPI(MPI_Waitall(nrecvs + nsends, r_waits, w_status));
116e5c89e4eSSatish Balay 
117e5c89e4eSSatish Balay   /* Pack up the received data */
1189566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs, onodes));
1196bfd7d4fSJunchao Zhang   for (i = 0; i < nrecvs; ++i) {
1206bfd7d4fSJunchao Zhang     (*onodes)[i] = w_status[i].MPI_SOURCE;
1216bfd7d4fSJunchao Zhang #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION)
1226bfd7d4fSJunchao Zhang     /* This line is a workaround for a bug in OpenMPI-2.1.1 distributed by Ubuntu-18.04.2 LTS.
1236bfd7d4fSJunchao Zhang        It happens in self-to-self MPI_Send/Recv using MPI_ANY_SOURCE for message matching. OpenMPI
1246bfd7d4fSJunchao Zhang        does not put correct value in recv buffer. See also
1256bfd7d4fSJunchao Zhang        https://lists.mcs.anl.gov/pipermail/petsc-dev/2019-July/024803.html
1266bfd7d4fSJunchao Zhang        https://www.mail-archive.com/users@lists.open-mpi.org//msg33383.html
1276bfd7d4fSJunchao Zhang      */
1286bfd7d4fSJunchao Zhang     if (w_status[i].MPI_SOURCE == rank) (*olengths)[i] = ilengths[rank];
1296bfd7d4fSJunchao Zhang #endif
1306bfd7d4fSJunchao Zhang   }
1319566063dSJacob Faibussowitsch   PetscCall(PetscFree2(r_waits, w_status));
132e5c89e4eSSatish Balay   PetscFunctionReturn(0);
133e5c89e4eSSatish Balay }
134dd6ea824SBarry Smith 
13576eed172SJunchao Zhang /* Same as PetscGatherNumberOfMessages(), except using PetscInt for ilengths[] */
1369371c9d4SSatish Balay PetscErrorCode PetscGatherNumberOfMessages_Private(MPI_Comm comm, const PetscMPIInt iflags[], const PetscInt ilengths[], PetscMPIInt *nrecvs) {
13776eed172SJunchao Zhang   PetscMPIInt size, rank, *recv_buf, i, *iflags_local = NULL, *iflags_localm = NULL;
13876eed172SJunchao Zhang 
13976eed172SJunchao Zhang   PetscFunctionBegin;
1409566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
1419566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
14276eed172SJunchao Zhang 
1439566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(size, &recv_buf, size, &iflags_localm));
14476eed172SJunchao Zhang 
14576eed172SJunchao Zhang   /* If iflags not provided, compute iflags from ilengths */
14676eed172SJunchao Zhang   if (!iflags) {
14728b400f6SJacob Faibussowitsch     PetscCheck(ilengths, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Either iflags or ilengths should be provided");
14876eed172SJunchao Zhang     iflags_local = iflags_localm;
14976eed172SJunchao Zhang     for (i = 0; i < size; i++) {
15076eed172SJunchao Zhang       if (ilengths[i]) iflags_local[i] = 1;
15176eed172SJunchao Zhang       else iflags_local[i] = 0;
15276eed172SJunchao Zhang     }
15376eed172SJunchao Zhang   } else iflags_local = (PetscMPIInt *)iflags;
15476eed172SJunchao Zhang 
15576eed172SJunchao Zhang   /* Post an allreduce to determine the numer of messages the current node will receive */
1561c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(iflags_local, recv_buf, size, MPI_INT, MPI_SUM, comm));
15776eed172SJunchao Zhang   *nrecvs = recv_buf[rank];
15876eed172SJunchao Zhang 
1599566063dSJacob Faibussowitsch   PetscCall(PetscFree2(recv_buf, iflags_localm));
16076eed172SJunchao Zhang   PetscFunctionReturn(0);
16176eed172SJunchao Zhang }
16276eed172SJunchao Zhang 
16376eed172SJunchao Zhang /* Same as PetscGatherMessageLengths(), except using PetscInt for message lengths */
1649371c9d4SSatish Balay PetscErrorCode PetscGatherMessageLengths_Private(MPI_Comm comm, PetscMPIInt nsends, PetscMPIInt nrecvs, const PetscInt ilengths[], PetscMPIInt **onodes, PetscInt **olengths) {
16576eed172SJunchao Zhang   PetscMPIInt  size, rank, tag, i, j;
16676eed172SJunchao Zhang   MPI_Request *s_waits = NULL, *r_waits = NULL;
16776eed172SJunchao Zhang   MPI_Status  *w_status = NULL;
16876eed172SJunchao Zhang 
16976eed172SJunchao Zhang   PetscFunctionBegin;
1709566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
1719566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1729566063dSJacob Faibussowitsch   PetscCall(PetscCommGetNewTag(comm, &tag));
17376eed172SJunchao Zhang 
17476eed172SJunchao Zhang   /* cannot use PetscMalloc3() here because in the call to MPI_Waitall() they MUST be contiguous */
1759566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nrecvs + nsends, &r_waits, nrecvs + nsends, &w_status));
17676eed172SJunchao Zhang   s_waits = r_waits + nrecvs;
17776eed172SJunchao Zhang 
17876eed172SJunchao Zhang   /* Post the Irecv to get the message length-info */
1799566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs, olengths));
180*48a46eb9SPierre Jolivet   for (i = 0; i < nrecvs; i++) PetscCallMPI(MPI_Irecv((*olengths) + i, 1, MPIU_INT, MPI_ANY_SOURCE, tag, comm, r_waits + i));
18176eed172SJunchao Zhang 
18276eed172SJunchao Zhang   /* Post the Isends with the message length-info */
18376eed172SJunchao Zhang   for (i = 0, j = 0; i < size; ++i) {
18476eed172SJunchao Zhang     if (ilengths[i]) {
1859566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Isend((void *)(ilengths + i), 1, MPIU_INT, i, tag, comm, s_waits + j));
18676eed172SJunchao Zhang       j++;
18776eed172SJunchao Zhang     }
18876eed172SJunchao Zhang   }
18976eed172SJunchao Zhang 
1906aad120cSJose E. Roman   /* Post waits on sends and receives */
1919566063dSJacob Faibussowitsch   if (nrecvs + nsends) PetscCallMPI(MPI_Waitall(nrecvs + nsends, r_waits, w_status));
19276eed172SJunchao Zhang 
19376eed172SJunchao Zhang   /* Pack up the received data */
1949566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs, onodes));
19576eed172SJunchao Zhang   for (i = 0; i < nrecvs; ++i) {
19676eed172SJunchao Zhang     (*onodes)[i] = w_status[i].MPI_SOURCE;
19776eed172SJunchao Zhang     if (w_status[i].MPI_SOURCE == rank) (*olengths)[i] = ilengths[rank]; /* See comments in PetscGatherMessageLengths */
19876eed172SJunchao Zhang   }
1999566063dSJacob Faibussowitsch   PetscCall(PetscFree2(r_waits, w_status));
20076eed172SJunchao Zhang   PetscFunctionReturn(0);
20176eed172SJunchao Zhang }
20276eed172SJunchao Zhang 
203e5c89e4eSSatish Balay /*@C
204e5c89e4eSSatish Balay   PetscGatherMessageLengths2 - Computes info about messages that a MPI-node will receive,
205e5c89e4eSSatish Balay   including (from-id,length) pairs for each message. Same functionality as PetscGatherMessageLengths()
206e5c89e4eSSatish Balay   except it takes TWO ilenths and output TWO olengths.
207e5c89e4eSSatish Balay 
208d083f849SBarry Smith   Collective
209e5c89e4eSSatish Balay 
210e5c89e4eSSatish Balay   Input Parameters:
211e5c89e4eSSatish Balay + comm      - Communicator
212e5c89e4eSSatish Balay . nsends    - number of messages that are to be sent.
213e5c89e4eSSatish Balay . nrecvs    - number of messages being received
2146b867d5aSJose E. Roman . ilengths1 - first array of integers of length sizeof(comm)
2156b867d5aSJose E. Roman - ilengths2 - second array of integers of length sizeof(comm)
216e5c89e4eSSatish Balay 
217e5c89e4eSSatish Balay   Output Parameters:
218e5c89e4eSSatish Balay + onodes    - list of node-ids from which messages are expected
2196b867d5aSJose E. Roman . olengths1 - first corresponding message lengths
2206b867d5aSJose E. Roman - olengths2 - second  message lengths
221e5c89e4eSSatish Balay 
222e5c89e4eSSatish Balay   Level: developer
223e5c89e4eSSatish Balay 
224e5c89e4eSSatish Balay   Notes:
225e5c89e4eSSatish Balay   With this info, the correct MPI_Irecv() can be posted with the correct
226e5c89e4eSSatish Balay   from-id, with a buffer with the right amount of memory required.
227e5c89e4eSSatish Balay 
228e5c89e4eSSatish Balay   The calling function deallocates the memory in onodes and olengths
229e5c89e4eSSatish Balay 
230c2916339SPierre Jolivet   To determine nrecvs, one can use PetscGatherNumberOfMessages()
231e5c89e4eSSatish Balay 
232db781477SPatrick Sanan .seealso: `PetscGatherMessageLengths()` `and` `PetscGatherNumberOfMessages()`
233e5c89e4eSSatish Balay @*/
2349371c9d4SSatish Balay PetscErrorCode PetscGatherMessageLengths2(MPI_Comm comm, PetscMPIInt nsends, PetscMPIInt nrecvs, const PetscMPIInt ilengths1[], const PetscMPIInt ilengths2[], PetscMPIInt **onodes, PetscMPIInt **olengths1, PetscMPIInt **olengths2) {
2350298fd71SBarry Smith   PetscMPIInt  size, tag, i, j, *buf_s = NULL, *buf_r = NULL, *buf_j = NULL;
2360298fd71SBarry Smith   MPI_Request *s_waits = NULL, *r_waits = NULL;
2370298fd71SBarry Smith   MPI_Status  *w_status = NULL;
238e5c89e4eSSatish Balay 
239e5c89e4eSSatish Balay   PetscFunctionBegin;
2409566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
2419566063dSJacob Faibussowitsch   PetscCall(PetscCommGetNewTag(comm, &tag));
242e5c89e4eSSatish Balay 
2433bf92927SBarry Smith   /* cannot use PetscMalloc5() because r_waits and s_waits must be contiguous for the call to MPI_Waitall() */
2449566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(nrecvs + nsends, &r_waits, 2 * nrecvs, &buf_r, 2 * nsends, &buf_s, nrecvs + nsends, &w_status));
245e5c89e4eSSatish Balay   s_waits = r_waits + nrecvs;
246e5c89e4eSSatish Balay 
247e5c89e4eSSatish Balay   /* Post the Irecv to get the message length-info */
2489566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs + 1, olengths1));
2499566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs + 1, olengths2));
250e5c89e4eSSatish Balay   for (i = 0; i < nrecvs; i++) {
251e5c89e4eSSatish Balay     buf_j = buf_r + (2 * i);
2529566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Irecv(buf_j, 2, MPI_INT, MPI_ANY_SOURCE, tag, comm, r_waits + i));
253e5c89e4eSSatish Balay   }
254e5c89e4eSSatish Balay 
255e5c89e4eSSatish Balay   /* Post the Isends with the message length-info */
256e5c89e4eSSatish Balay   for (i = 0, j = 0; i < size; ++i) {
257e5c89e4eSSatish Balay     if (ilengths1[i]) {
258e5c89e4eSSatish Balay       buf_j    = buf_s + (2 * j);
259e5c89e4eSSatish Balay       buf_j[0] = *(ilengths1 + i);
260e5c89e4eSSatish Balay       buf_j[1] = *(ilengths2 + i);
2619566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Isend(buf_j, 2, MPI_INT, i, tag, comm, s_waits + j));
262e5c89e4eSSatish Balay       j++;
263e5c89e4eSSatish Balay     }
264e5c89e4eSSatish Balay   }
26508401ef6SPierre Jolivet   PetscCheck(j == nsends, PETSC_COMM_SELF, PETSC_ERR_PLIB, "j %d not equal to expected number of sends %d", j, nsends);
266e5c89e4eSSatish Balay 
2676aad120cSJose E. Roman   /* Post waits on sends and receives */
2689566063dSJacob Faibussowitsch   if (nrecvs + nsends) PetscCallMPI(MPI_Waitall(nrecvs + nsends, r_waits, w_status));
269e5c89e4eSSatish Balay 
270e5c89e4eSSatish Balay   /* Pack up the received data */
2719566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs + 1, onodes));
272e5c89e4eSSatish Balay   for (i = 0; i < nrecvs; ++i) {
273e5c89e4eSSatish Balay     (*onodes)[i]    = w_status[i].MPI_SOURCE;
274e5c89e4eSSatish Balay     buf_j           = buf_r + (2 * i);
275e5c89e4eSSatish Balay     (*olengths1)[i] = buf_j[0];
276e5c89e4eSSatish Balay     (*olengths2)[i] = buf_j[1];
277e5c89e4eSSatish Balay   }
278e5c89e4eSSatish Balay 
2799566063dSJacob Faibussowitsch   PetscCall(PetscFree4(r_waits, buf_r, buf_s, w_status));
280e5c89e4eSSatish Balay   PetscFunctionReturn(0);
281e5c89e4eSSatish Balay }
282e5c89e4eSSatish Balay 
283e5c89e4eSSatish Balay /*
284e5c89e4eSSatish Balay 
285a5b23f4aSJose E. Roman   Allocate a buffer sufficient to hold messages of size specified in olengths.
286e5c89e4eSSatish Balay   And post Irecvs on these buffers using node info from onodes
287e5c89e4eSSatish Balay 
288e5c89e4eSSatish Balay  */
2899371c9d4SSatish Balay PetscErrorCode PetscPostIrecvInt(MPI_Comm comm, PetscMPIInt tag, PetscMPIInt nrecvs, const PetscMPIInt onodes[], const PetscMPIInt olengths[], PetscInt ***rbuf, MPI_Request **r_waits) {
290c05d87d6SBarry Smith   PetscInt   **rbuf_t, i, len = 0;
291e5c89e4eSSatish Balay   MPI_Request *r_waits_t;
292e5c89e4eSSatish Balay 
293e5c89e4eSSatish Balay   PetscFunctionBegin;
294e5c89e4eSSatish Balay   /* compute memory required for recv buffers */
295e5c89e4eSSatish Balay   for (i = 0; i < nrecvs; i++) len += olengths[i]; /* each message length */
296e5c89e4eSSatish Balay 
297e5c89e4eSSatish Balay   /* allocate memory for recv buffers */
2989566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs + 1, &rbuf_t));
2999566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(len, &rbuf_t[0]));
300e5c89e4eSSatish Balay   for (i = 1; i < nrecvs; ++i) rbuf_t[i] = rbuf_t[i - 1] + olengths[i - 1];
301e5c89e4eSSatish Balay 
302e5c89e4eSSatish Balay   /* Post the receives */
3039566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs, &r_waits_t));
304*48a46eb9SPierre 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));
305e5c89e4eSSatish Balay 
306e5c89e4eSSatish Balay   *rbuf    = rbuf_t;
307e5c89e4eSSatish Balay   *r_waits = r_waits_t;
308e5c89e4eSSatish Balay   PetscFunctionReturn(0);
309e5c89e4eSSatish Balay }
310e5c89e4eSSatish Balay 
3119371c9d4SSatish Balay PetscErrorCode PetscPostIrecvScalar(MPI_Comm comm, PetscMPIInt tag, PetscMPIInt nrecvs, const PetscMPIInt onodes[], const PetscMPIInt olengths[], PetscScalar ***rbuf, MPI_Request **r_waits) {
312052f0c41SBarry Smith   PetscMPIInt   i;
313e5c89e4eSSatish Balay   PetscScalar **rbuf_t;
314e5c89e4eSSatish Balay   MPI_Request  *r_waits_t;
315c05d87d6SBarry Smith   PetscInt      len = 0;
316e5c89e4eSSatish Balay 
317fe28d99cSBarry Smith   PetscFunctionBegin;
318e5c89e4eSSatish Balay   /* compute memory required for recv buffers */
319e5c89e4eSSatish Balay   for (i = 0; i < nrecvs; i++) len += olengths[i]; /* each message length */
320e5c89e4eSSatish Balay 
321e5c89e4eSSatish Balay   /* allocate memory for recv buffers */
3229566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs + 1, &rbuf_t));
3239566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(len, &rbuf_t[0]));
324e5c89e4eSSatish Balay   for (i = 1; i < nrecvs; ++i) rbuf_t[i] = rbuf_t[i - 1] + olengths[i - 1];
325e5c89e4eSSatish Balay 
326e5c89e4eSSatish Balay   /* Post the receives */
3279566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs, &r_waits_t));
328*48a46eb9SPierre 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));
329e5c89e4eSSatish Balay 
330e5c89e4eSSatish Balay   *rbuf    = rbuf_t;
331e5c89e4eSSatish Balay   *r_waits = r_waits_t;
332e5c89e4eSSatish Balay   PetscFunctionReturn(0);
333e5c89e4eSSatish Balay }
334