xref: /petsc/src/sys/utils/mpimesg.c (revision 3ba1676111f5c958fe6c2729b46ca4d523958bb3)
1e5c89e4eSSatish Balay 
2c6db04a5SJed Brown #include <petscsys.h> /*I  "petscsys.h"  I*/
376eed172SJunchao Zhang #include <petsc/private/mpiutils.h>
4e5c89e4eSSatish Balay 
5e5c89e4eSSatish Balay /*@C
6811af0c4SBarry Smith   PetscGatherNumberOfMessages -  Computes the number of messages an MPI rank expects to receive during a neighbor communication
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
24811af0c4SBarry Smith   `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 
30811af0c4SBarry Smith .seealso: `PetscGatherMessageLengths()`, `PetscGatherMessageLengths2()`, `PetscCommBuildTwoSided()`
31e5c89e4eSSatish Balay @*/
32d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGatherNumberOfMessages(MPI_Comm comm, const PetscMPIInt iflags[], const PetscMPIInt ilengths[], PetscMPIInt *nrecvs)
33d71ae5a4SJacob Faibussowitsch {
340298fd71SBarry Smith   PetscMPIInt size, rank, *recv_buf, i, *iflags_local = NULL, *iflags_localm = NULL;
35e5c89e4eSSatish Balay 
36e5c89e4eSSatish Balay   PetscFunctionBegin;
379566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
389566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
39e5c89e4eSSatish Balay 
409566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(size, &recv_buf, size, &iflags_localm));
41e5c89e4eSSatish Balay 
42e5c89e4eSSatish Balay   /* If iflags not provided, compute iflags from ilengths */
43e5c89e4eSSatish Balay   if (!iflags) {
4428b400f6SJacob Faibussowitsch     PetscCheck(ilengths, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Either iflags or ilengths should be provided");
45e5c89e4eSSatish Balay     iflags_local = iflags_localm;
46e5c89e4eSSatish Balay     for (i = 0; i < size; i++) {
47e5c89e4eSSatish Balay       if (ilengths[i]) iflags_local[i] = 1;
48e5c89e4eSSatish Balay       else iflags_local[i] = 0;
49e5c89e4eSSatish Balay     }
50a297a907SKarl Rupp   } else iflags_local = (PetscMPIInt *)iflags;
51e5c89e4eSSatish Balay 
52e5c89e4eSSatish Balay   /* Post an allreduce to determine the numer of messages the current node will receive */
531c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(iflags_local, recv_buf, size, MPI_INT, MPI_SUM, comm));
54e5c89e4eSSatish Balay   *nrecvs = recv_buf[rank];
55e5c89e4eSSatish Balay 
569566063dSJacob Faibussowitsch   PetscCall(PetscFree2(recv_buf, iflags_localm));
57*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
58e5c89e4eSSatish Balay }
59e5c89e4eSSatish Balay 
60e5c89e4eSSatish Balay /*@C
61811af0c4SBarry Smith   PetscGatherMessageLengths - Computes infomation about messages that an MPI rank will receive,
62e5c89e4eSSatish Balay   including (from-id,length) pairs for each message.
63e5c89e4eSSatish Balay 
64d083f849SBarry Smith   Collective
65e5c89e4eSSatish Balay 
66e5c89e4eSSatish Balay   Input Parameters:
67e5c89e4eSSatish Balay + comm      - Communicator
68e5c89e4eSSatish Balay . nsends    - number of messages that are to be sent.
69e5c89e4eSSatish Balay . nrecvs    - number of messages being received
70e5c89e4eSSatish Balay - ilengths  - an array of integers of length sizeof(comm)
71e5c89e4eSSatish Balay               a non zero ilengths[i] represent a message to i of length ilengths[i]
72e5c89e4eSSatish Balay 
73e5c89e4eSSatish Balay   Output Parameters:
74e5c89e4eSSatish Balay + onodes    - list of node-ids from which messages are expected
75e5c89e4eSSatish Balay - olengths  - corresponding message lengths
76e5c89e4eSSatish Balay 
77e5c89e4eSSatish Balay   Level: developer
78e5c89e4eSSatish Balay 
79e5c89e4eSSatish Balay   Notes:
80811af0c4SBarry Smith   With this info, the correct `MPI_Irecv()` can be posted with the correct
81e5c89e4eSSatish Balay   from-id, with a buffer with the right amount of memory required.
82e5c89e4eSSatish Balay 
83e5c89e4eSSatish Balay   The calling function deallocates the memory in onodes and olengths
84e5c89e4eSSatish Balay 
85811af0c4SBarry Smith   To determine nrecvs, one can use `PetscGatherNumberOfMessages()`
86e5c89e4eSSatish Balay 
87811af0c4SBarry Smith .seealso: `PetscGatherNumberOfMessages()`, `PetscGatherMessageLengths2()`, `PetscCommBuildTwoSided()`
88e5c89e4eSSatish Balay @*/
89d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGatherMessageLengths(MPI_Comm comm, PetscMPIInt nsends, PetscMPIInt nrecvs, const PetscMPIInt ilengths[], PetscMPIInt **onodes, PetscMPIInt **olengths)
90d71ae5a4SJacob Faibussowitsch {
916bfd7d4fSJunchao Zhang   PetscMPIInt  size, rank, tag, i, j;
920298fd71SBarry Smith   MPI_Request *s_waits = NULL, *r_waits = NULL;
930298fd71SBarry Smith   MPI_Status  *w_status = NULL;
94e5c89e4eSSatish Balay 
95e5c89e4eSSatish Balay   PetscFunctionBegin;
969566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
979566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
989566063dSJacob Faibussowitsch   PetscCall(PetscCommGetNewTag(comm, &tag));
99e5c89e4eSSatish Balay 
100e5c89e4eSSatish Balay   /* cannot use PetscMalloc3() here because in the call to MPI_Waitall() they MUST be contiguous */
1019566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nrecvs + nsends, &r_waits, nrecvs + nsends, &w_status));
102e5c89e4eSSatish Balay   s_waits = r_waits + nrecvs;
103e5c89e4eSSatish Balay 
104e5c89e4eSSatish Balay   /* Post the Irecv to get the message length-info */
1059566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs, olengths));
10648a46eb9SPierre Jolivet   for (i = 0; i < nrecvs; i++) PetscCallMPI(MPI_Irecv((*olengths) + i, 1, MPI_INT, MPI_ANY_SOURCE, tag, comm, r_waits + i));
107e5c89e4eSSatish Balay 
108e5c89e4eSSatish Balay   /* Post the Isends with the message length-info */
109e5c89e4eSSatish Balay   for (i = 0, j = 0; i < size; ++i) {
110e5c89e4eSSatish Balay     if (ilengths[i]) {
1119566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Isend((void *)(ilengths + i), 1, MPI_INT, i, tag, comm, s_waits + j));
112e5c89e4eSSatish Balay       j++;
113e5c89e4eSSatish Balay     }
114e5c89e4eSSatish Balay   }
115e5c89e4eSSatish Balay 
1166aad120cSJose E. Roman   /* Post waits on sends and receives */
1179566063dSJacob Faibussowitsch   if (nrecvs + nsends) PetscCallMPI(MPI_Waitall(nrecvs + nsends, r_waits, w_status));
118e5c89e4eSSatish Balay 
119e5c89e4eSSatish Balay   /* Pack up the received data */
1209566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs, onodes));
1216bfd7d4fSJunchao Zhang   for (i = 0; i < nrecvs; ++i) {
1226bfd7d4fSJunchao Zhang     (*onodes)[i] = w_status[i].MPI_SOURCE;
1236bfd7d4fSJunchao Zhang #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION)
1246bfd7d4fSJunchao Zhang     /* This line is a workaround for a bug in OpenMPI-2.1.1 distributed by Ubuntu-18.04.2 LTS.
1256bfd7d4fSJunchao Zhang        It happens in self-to-self MPI_Send/Recv using MPI_ANY_SOURCE for message matching. OpenMPI
1266bfd7d4fSJunchao Zhang        does not put correct value in recv buffer. See also
1276bfd7d4fSJunchao Zhang        https://lists.mcs.anl.gov/pipermail/petsc-dev/2019-July/024803.html
1286bfd7d4fSJunchao Zhang        https://www.mail-archive.com/users@lists.open-mpi.org//msg33383.html
1296bfd7d4fSJunchao Zhang      */
1306bfd7d4fSJunchao Zhang     if (w_status[i].MPI_SOURCE == rank) (*olengths)[i] = ilengths[rank];
1316bfd7d4fSJunchao Zhang #endif
1326bfd7d4fSJunchao Zhang   }
1339566063dSJacob Faibussowitsch   PetscCall(PetscFree2(r_waits, w_status));
134*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
135e5c89e4eSSatish Balay }
136dd6ea824SBarry Smith 
13776eed172SJunchao Zhang /* Same as PetscGatherNumberOfMessages(), except using PetscInt for ilengths[] */
138d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGatherNumberOfMessages_Private(MPI_Comm comm, const PetscMPIInt iflags[], const PetscInt ilengths[], PetscMPIInt *nrecvs)
139d71ae5a4SJacob Faibussowitsch {
14076eed172SJunchao Zhang   PetscMPIInt size, rank, *recv_buf, i, *iflags_local = NULL, *iflags_localm = NULL;
14176eed172SJunchao Zhang 
14276eed172SJunchao Zhang   PetscFunctionBegin;
1439566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
1449566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
14576eed172SJunchao Zhang 
1469566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(size, &recv_buf, size, &iflags_localm));
14776eed172SJunchao Zhang 
14876eed172SJunchao Zhang   /* If iflags not provided, compute iflags from ilengths */
14976eed172SJunchao Zhang   if (!iflags) {
15028b400f6SJacob Faibussowitsch     PetscCheck(ilengths, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Either iflags or ilengths should be provided");
15176eed172SJunchao Zhang     iflags_local = iflags_localm;
15276eed172SJunchao Zhang     for (i = 0; i < size; i++) {
15376eed172SJunchao Zhang       if (ilengths[i]) iflags_local[i] = 1;
15476eed172SJunchao Zhang       else iflags_local[i] = 0;
15576eed172SJunchao Zhang     }
15676eed172SJunchao Zhang   } else iflags_local = (PetscMPIInt *)iflags;
15776eed172SJunchao Zhang 
15876eed172SJunchao Zhang   /* Post an allreduce to determine the numer of messages the current node will receive */
1591c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(iflags_local, recv_buf, size, MPI_INT, MPI_SUM, comm));
16076eed172SJunchao Zhang   *nrecvs = recv_buf[rank];
16176eed172SJunchao Zhang 
1629566063dSJacob Faibussowitsch   PetscCall(PetscFree2(recv_buf, iflags_localm));
163*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
16476eed172SJunchao Zhang }
16576eed172SJunchao Zhang 
16676eed172SJunchao Zhang /* Same as PetscGatherMessageLengths(), except using PetscInt for message lengths */
167d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGatherMessageLengths_Private(MPI_Comm comm, PetscMPIInt nsends, PetscMPIInt nrecvs, const PetscInt ilengths[], PetscMPIInt **onodes, PetscInt **olengths)
168d71ae5a4SJacob Faibussowitsch {
16976eed172SJunchao Zhang   PetscMPIInt  size, rank, tag, i, j;
17076eed172SJunchao Zhang   MPI_Request *s_waits = NULL, *r_waits = NULL;
17176eed172SJunchao Zhang   MPI_Status  *w_status = NULL;
17276eed172SJunchao Zhang 
17376eed172SJunchao Zhang   PetscFunctionBegin;
1749566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
1759566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1769566063dSJacob Faibussowitsch   PetscCall(PetscCommGetNewTag(comm, &tag));
17776eed172SJunchao Zhang 
17876eed172SJunchao Zhang   /* cannot use PetscMalloc3() here because in the call to MPI_Waitall() they MUST be contiguous */
1799566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(nrecvs + nsends, &r_waits, nrecvs + nsends, &w_status));
18076eed172SJunchao Zhang   s_waits = r_waits + nrecvs;
18176eed172SJunchao Zhang 
18276eed172SJunchao Zhang   /* Post the Irecv to get the message length-info */
1839566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs, olengths));
18448a46eb9SPierre Jolivet   for (i = 0; i < nrecvs; i++) PetscCallMPI(MPI_Irecv((*olengths) + i, 1, MPIU_INT, MPI_ANY_SOURCE, tag, comm, r_waits + i));
18576eed172SJunchao Zhang 
18676eed172SJunchao Zhang   /* Post the Isends with the message length-info */
18776eed172SJunchao Zhang   for (i = 0, j = 0; i < size; ++i) {
18876eed172SJunchao Zhang     if (ilengths[i]) {
1899566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Isend((void *)(ilengths + i), 1, MPIU_INT, i, tag, comm, s_waits + j));
19076eed172SJunchao Zhang       j++;
19176eed172SJunchao Zhang     }
19276eed172SJunchao Zhang   }
19376eed172SJunchao Zhang 
1946aad120cSJose E. Roman   /* Post waits on sends and receives */
1959566063dSJacob Faibussowitsch   if (nrecvs + nsends) PetscCallMPI(MPI_Waitall(nrecvs + nsends, r_waits, w_status));
19676eed172SJunchao Zhang 
19776eed172SJunchao Zhang   /* Pack up the received data */
1989566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs, onodes));
19976eed172SJunchao Zhang   for (i = 0; i < nrecvs; ++i) {
20076eed172SJunchao Zhang     (*onodes)[i] = w_status[i].MPI_SOURCE;
20176eed172SJunchao Zhang     if (w_status[i].MPI_SOURCE == rank) (*olengths)[i] = ilengths[rank]; /* See comments in PetscGatherMessageLengths */
20276eed172SJunchao Zhang   }
2039566063dSJacob Faibussowitsch   PetscCall(PetscFree2(r_waits, w_status));
204*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
20576eed172SJunchao Zhang }
20676eed172SJunchao Zhang 
207e5c89e4eSSatish Balay /*@C
208811af0c4SBarry Smith   PetscGatherMessageLengths2 - Computes info about messages that a MPI rank will receive,
209811af0c4SBarry Smith   including (from-id,length) pairs for each message. Same functionality as `PetscGatherMessageLengths()`
210e5c89e4eSSatish Balay   except it takes TWO ilenths and output TWO olengths.
211e5c89e4eSSatish Balay 
212d083f849SBarry Smith   Collective
213e5c89e4eSSatish Balay 
214e5c89e4eSSatish Balay   Input Parameters:
215e5c89e4eSSatish Balay + comm      - Communicator
216e5c89e4eSSatish Balay . nsends    - number of messages that are to be sent.
217e5c89e4eSSatish Balay . nrecvs    - number of messages being received
2186b867d5aSJose E. Roman . ilengths1 - first array of integers of length sizeof(comm)
2196b867d5aSJose E. Roman - ilengths2 - second array of integers of length sizeof(comm)
220e5c89e4eSSatish Balay 
221e5c89e4eSSatish Balay   Output Parameters:
222e5c89e4eSSatish Balay + onodes    - list of node-ids from which messages are expected
2236b867d5aSJose E. Roman . olengths1 - first corresponding message lengths
2246b867d5aSJose E. Roman - olengths2 - second  message lengths
225e5c89e4eSSatish Balay 
226e5c89e4eSSatish Balay   Level: developer
227e5c89e4eSSatish Balay 
228e5c89e4eSSatish Balay   Notes:
229811af0c4SBarry Smith   With this info, the correct `MPI_Irecv()` can be posted with the correct
230e5c89e4eSSatish Balay   from-id, with a buffer with the right amount of memory required.
231e5c89e4eSSatish Balay 
232e5c89e4eSSatish Balay   The calling function deallocates the memory in onodes and olengths
233e5c89e4eSSatish Balay 
234c2916339SPierre Jolivet   To determine nrecvs, one can use PetscGatherNumberOfMessages()
235e5c89e4eSSatish Balay 
236811af0c4SBarry Smith .seealso: `PetscGatherMessageLengths()`, `PetscGatherNumberOfMessages()`, `PetscCommBuildTwoSided()`
237e5c89e4eSSatish Balay @*/
238d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGatherMessageLengths2(MPI_Comm comm, PetscMPIInt nsends, PetscMPIInt nrecvs, const PetscMPIInt ilengths1[], const PetscMPIInt ilengths2[], PetscMPIInt **onodes, PetscMPIInt **olengths1, PetscMPIInt **olengths2)
239d71ae5a4SJacob Faibussowitsch {
2400298fd71SBarry Smith   PetscMPIInt  size, tag, i, j, *buf_s = NULL, *buf_r = NULL, *buf_j = NULL;
2410298fd71SBarry Smith   MPI_Request *s_waits = NULL, *r_waits = NULL;
2420298fd71SBarry Smith   MPI_Status  *w_status = NULL;
243e5c89e4eSSatish Balay 
244e5c89e4eSSatish Balay   PetscFunctionBegin;
2459566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
2469566063dSJacob Faibussowitsch   PetscCall(PetscCommGetNewTag(comm, &tag));
247e5c89e4eSSatish Balay 
2483bf92927SBarry Smith   /* cannot use PetscMalloc5() because r_waits and s_waits must be contiguous for the call to MPI_Waitall() */
2499566063dSJacob Faibussowitsch   PetscCall(PetscMalloc4(nrecvs + nsends, &r_waits, 2 * nrecvs, &buf_r, 2 * nsends, &buf_s, nrecvs + nsends, &w_status));
250e5c89e4eSSatish Balay   s_waits = r_waits + nrecvs;
251e5c89e4eSSatish Balay 
252e5c89e4eSSatish Balay   /* Post the Irecv to get the message length-info */
2539566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs + 1, olengths1));
2549566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs + 1, olengths2));
255e5c89e4eSSatish Balay   for (i = 0; i < nrecvs; i++) {
256e5c89e4eSSatish Balay     buf_j = buf_r + (2 * i);
2579566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Irecv(buf_j, 2, MPI_INT, MPI_ANY_SOURCE, tag, comm, r_waits + i));
258e5c89e4eSSatish Balay   }
259e5c89e4eSSatish Balay 
260e5c89e4eSSatish Balay   /* Post the Isends with the message length-info */
261e5c89e4eSSatish Balay   for (i = 0, j = 0; i < size; ++i) {
262e5c89e4eSSatish Balay     if (ilengths1[i]) {
263e5c89e4eSSatish Balay       buf_j    = buf_s + (2 * j);
264e5c89e4eSSatish Balay       buf_j[0] = *(ilengths1 + i);
265e5c89e4eSSatish Balay       buf_j[1] = *(ilengths2 + i);
2669566063dSJacob Faibussowitsch       PetscCallMPI(MPI_Isend(buf_j, 2, MPI_INT, i, tag, comm, s_waits + j));
267e5c89e4eSSatish Balay       j++;
268e5c89e4eSSatish Balay     }
269e5c89e4eSSatish Balay   }
27008401ef6SPierre Jolivet   PetscCheck(j == nsends, PETSC_COMM_SELF, PETSC_ERR_PLIB, "j %d not equal to expected number of sends %d", j, nsends);
271e5c89e4eSSatish Balay 
2726aad120cSJose E. Roman   /* Post waits on sends and receives */
2739566063dSJacob Faibussowitsch   if (nrecvs + nsends) PetscCallMPI(MPI_Waitall(nrecvs + nsends, r_waits, w_status));
274e5c89e4eSSatish Balay 
275e5c89e4eSSatish Balay   /* Pack up the received data */
2769566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs + 1, onodes));
277e5c89e4eSSatish Balay   for (i = 0; i < nrecvs; ++i) {
278e5c89e4eSSatish Balay     (*onodes)[i]    = w_status[i].MPI_SOURCE;
279e5c89e4eSSatish Balay     buf_j           = buf_r + (2 * i);
280e5c89e4eSSatish Balay     (*olengths1)[i] = buf_j[0];
281e5c89e4eSSatish Balay     (*olengths2)[i] = buf_j[1];
282e5c89e4eSSatish Balay   }
283e5c89e4eSSatish Balay 
2849566063dSJacob Faibussowitsch   PetscCall(PetscFree4(r_waits, buf_r, buf_s, w_status));
285*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
286e5c89e4eSSatish Balay }
287e5c89e4eSSatish Balay 
288e5c89e4eSSatish Balay /*
289a5b23f4aSJose E. Roman   Allocate a buffer sufficient to hold messages of size specified in olengths.
290e5c89e4eSSatish Balay   And post Irecvs on these buffers using node info from onodes
291e5c89e4eSSatish Balay  */
292d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPostIrecvInt(MPI_Comm comm, PetscMPIInt tag, PetscMPIInt nrecvs, const PetscMPIInt onodes[], const PetscMPIInt olengths[], PetscInt ***rbuf, MPI_Request **r_waits)
293d71ae5a4SJacob Faibussowitsch {
294c05d87d6SBarry Smith   PetscInt   **rbuf_t, i, len = 0;
295e5c89e4eSSatish Balay   MPI_Request *r_waits_t;
296e5c89e4eSSatish Balay 
297e5c89e4eSSatish Balay   PetscFunctionBegin;
298e5c89e4eSSatish Balay   /* compute memory required for recv buffers */
299e5c89e4eSSatish Balay   for (i = 0; i < nrecvs; i++) len += olengths[i]; /* each message length */
300e5c89e4eSSatish Balay 
301e5c89e4eSSatish Balay   /* allocate memory for recv buffers */
3029566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs + 1, &rbuf_t));
3039566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(len, &rbuf_t[0]));
304e5c89e4eSSatish Balay   for (i = 1; i < nrecvs; ++i) rbuf_t[i] = rbuf_t[i - 1] + olengths[i - 1];
305e5c89e4eSSatish Balay 
306e5c89e4eSSatish Balay   /* Post the receives */
3079566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs, &r_waits_t));
30848a46eb9SPierre 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));
309e5c89e4eSSatish Balay 
310e5c89e4eSSatish Balay   *rbuf    = rbuf_t;
311e5c89e4eSSatish Balay   *r_waits = r_waits_t;
312*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
313e5c89e4eSSatish Balay }
314e5c89e4eSSatish Balay 
315d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPostIrecvScalar(MPI_Comm comm, PetscMPIInt tag, PetscMPIInt nrecvs, const PetscMPIInt onodes[], const PetscMPIInt olengths[], PetscScalar ***rbuf, MPI_Request **r_waits)
316d71ae5a4SJacob Faibussowitsch {
317052f0c41SBarry Smith   PetscMPIInt   i;
318e5c89e4eSSatish Balay   PetscScalar **rbuf_t;
319e5c89e4eSSatish Balay   MPI_Request  *r_waits_t;
320c05d87d6SBarry Smith   PetscInt      len = 0;
321e5c89e4eSSatish Balay 
322fe28d99cSBarry Smith   PetscFunctionBegin;
323e5c89e4eSSatish Balay   /* compute memory required for recv buffers */
324e5c89e4eSSatish Balay   for (i = 0; i < nrecvs; i++) len += olengths[i]; /* each message length */
325e5c89e4eSSatish Balay 
326e5c89e4eSSatish Balay   /* allocate memory for recv buffers */
3279566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs + 1, &rbuf_t));
3289566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(len, &rbuf_t[0]));
329e5c89e4eSSatish Balay   for (i = 1; i < nrecvs; ++i) rbuf_t[i] = rbuf_t[i - 1] + olengths[i - 1];
330e5c89e4eSSatish Balay 
331e5c89e4eSSatish Balay   /* Post the receives */
3329566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(nrecvs, &r_waits_t));
33348a46eb9SPierre 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));
334e5c89e4eSSatish Balay 
335e5c89e4eSSatish Balay   *rbuf    = rbuf_t;
336e5c89e4eSSatish Balay   *r_waits = r_waits_t;
337*3ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
338e5c89e4eSSatish Balay }
339