xref: /petsc/src/sys/utils/mpimesg.c (revision 76eed172866ae3c93fee5629ebef2b8e6cba8eea)
1e5c89e4eSSatish Balay 
2c6db04a5SJed Brown #include <petscsys.h>        /*I  "petscsys.h"  I*/
3*76eed172SJunchao 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 
30e5c89e4eSSatish Balay .seealso: PetscGatherMessageLengths()
31e5c89e4eSSatish Balay @*/
327087cfbeSBarry Smith PetscErrorCode  PetscGatherNumberOfMessages(MPI_Comm comm,const PetscMPIInt iflags[],const PetscMPIInt ilengths[],PetscMPIInt *nrecvs)
33e5c89e4eSSatish Balay {
340298fd71SBarry Smith   PetscMPIInt    size,rank,*recv_buf,i,*iflags_local = NULL,*iflags_localm = NULL;
35e5c89e4eSSatish Balay   PetscErrorCode ierr;
36e5c89e4eSSatish Balay 
37e5c89e4eSSatish Balay   PetscFunctionBegin;
38ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
39ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
40e5c89e4eSSatish Balay 
41dcca6d9dSJed Brown   ierr = PetscMalloc2(size,&recv_buf,size,&iflags_localm);CHKERRQ(ierr);
42e5c89e4eSSatish Balay 
43e5c89e4eSSatish Balay   /* If iflags not provided, compute iflags from ilengths */
44e5c89e4eSSatish Balay   if (!iflags) {
45e32f2f54SBarry Smith     if (!ilengths) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Either iflags or ilengths should be provided");
46e5c89e4eSSatish Balay     iflags_local = iflags_localm;
47e5c89e4eSSatish Balay     for (i=0; i<size; i++) {
48e5c89e4eSSatish Balay       if (ilengths[i]) iflags_local[i] = 1;
49e5c89e4eSSatish Balay       else iflags_local[i] = 0;
50e5c89e4eSSatish Balay     }
51a297a907SKarl Rupp   } else iflags_local = (PetscMPIInt*) iflags;
52e5c89e4eSSatish Balay 
53e5c89e4eSSatish Balay   /* Post an allreduce to determine the numer of messages the current node will receive */
54820f2d46SBarry Smith   ierr    = MPIU_Allreduce(iflags_local,recv_buf,size,MPI_INT,MPI_SUM,comm);CHKERRMPI(ierr);
55e5c89e4eSSatish Balay   *nrecvs = recv_buf[rank];
56e5c89e4eSSatish Balay 
57e5c89e4eSSatish Balay   ierr = PetscFree2(recv_buf,iflags_localm);CHKERRQ(ierr);
58e5c89e4eSSatish Balay   PetscFunctionReturn(0);
59e5c89e4eSSatish Balay }
60e5c89e4eSSatish Balay 
61e5c89e4eSSatish Balay /*@C
62e5c89e4eSSatish Balay   PetscGatherMessageLengths - Computes info about messages that a MPI-node will receive,
63e5c89e4eSSatish Balay   including (from-id,length) pairs for each message.
64e5c89e4eSSatish Balay 
65d083f849SBarry Smith   Collective
66e5c89e4eSSatish Balay 
67e5c89e4eSSatish Balay   Input Parameters:
68e5c89e4eSSatish Balay + comm      - Communicator
69e5c89e4eSSatish Balay . nsends    - number of messages that are to be sent.
70e5c89e4eSSatish Balay . nrecvs    - number of messages being received
71e5c89e4eSSatish Balay - ilengths  - an array of integers of length sizeof(comm)
72e5c89e4eSSatish Balay               a non zero ilengths[i] represent a message to i of length ilengths[i]
73e5c89e4eSSatish Balay 
74e5c89e4eSSatish Balay   Output Parameters:
75e5c89e4eSSatish Balay + onodes    - list of node-ids from which messages are expected
76e5c89e4eSSatish Balay - olengths  - corresponding message lengths
77e5c89e4eSSatish Balay 
78e5c89e4eSSatish Balay   Level: developer
79e5c89e4eSSatish Balay 
80e5c89e4eSSatish Balay   Notes:
81e5c89e4eSSatish Balay   With this info, the correct MPI_Irecv() can be posted with the correct
82e5c89e4eSSatish Balay   from-id, with a buffer with the right amount of memory required.
83e5c89e4eSSatish Balay 
84e5c89e4eSSatish Balay   The calling function deallocates the memory in onodes and olengths
85e5c89e4eSSatish Balay 
86c2916339SPierre Jolivet   To determine nrecvs, one can use PetscGatherNumberOfMessages()
87e5c89e4eSSatish Balay 
88e5c89e4eSSatish Balay .seealso: PetscGatherNumberOfMessages()
89e5c89e4eSSatish Balay @*/
907087cfbeSBarry Smith PetscErrorCode  PetscGatherMessageLengths(MPI_Comm comm,PetscMPIInt nsends,PetscMPIInt nrecvs,const PetscMPIInt ilengths[],PetscMPIInt **onodes,PetscMPIInt **olengths)
91e5c89e4eSSatish Balay {
92e5c89e4eSSatish Balay   PetscErrorCode ierr;
936bfd7d4fSJunchao Zhang   PetscMPIInt    size,rank,tag,i,j;
940298fd71SBarry Smith   MPI_Request    *s_waits  = NULL,*r_waits = NULL;
950298fd71SBarry Smith   MPI_Status     *w_status = NULL;
96e5c89e4eSSatish Balay 
97e5c89e4eSSatish Balay   PetscFunctionBegin;
98ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
99ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
100e5c89e4eSSatish Balay   ierr = PetscCommGetNewTag(comm,&tag);CHKERRQ(ierr);
101e5c89e4eSSatish Balay 
102e5c89e4eSSatish Balay   /* cannot use PetscMalloc3() here because in the call to MPI_Waitall() they MUST be contiguous */
103dcca6d9dSJed Brown   ierr    = PetscMalloc2(nrecvs+nsends,&r_waits,nrecvs+nsends,&w_status);CHKERRQ(ierr);
104e5c89e4eSSatish Balay   s_waits = r_waits+nrecvs;
105e5c89e4eSSatish Balay 
106e5c89e4eSSatish Balay   /* Post the Irecv to get the message length-info */
107785e854fSJed Brown   ierr = PetscMalloc1(nrecvs,olengths);CHKERRQ(ierr);
108e5c89e4eSSatish Balay   for (i=0; i<nrecvs; i++) {
109ffc4695bSBarry Smith     ierr = MPI_Irecv((*olengths)+i,1,MPI_INT,MPI_ANY_SOURCE,tag,comm,r_waits+i);CHKERRMPI(ierr);
110e5c89e4eSSatish Balay   }
111e5c89e4eSSatish Balay 
112e5c89e4eSSatish Balay   /* Post the Isends with the message length-info */
113e5c89e4eSSatish Balay   for (i=0,j=0; i<size; ++i) {
114e5c89e4eSSatish Balay     if (ilengths[i]) {
115ffc4695bSBarry Smith       ierr = MPI_Isend((void*)(ilengths+i),1,MPI_INT,i,tag,comm,s_waits+j);CHKERRMPI(ierr);
116e5c89e4eSSatish Balay       j++;
117e5c89e4eSSatish Balay     }
118e5c89e4eSSatish Balay   }
119e5c89e4eSSatish Balay 
120e5c89e4eSSatish Balay   /* Post waits on sends and receivs */
121ffc4695bSBarry Smith   if (nrecvs+nsends) {ierr = MPI_Waitall(nrecvs+nsends,r_waits,w_status);CHKERRMPI(ierr);}
122e5c89e4eSSatish Balay 
123e5c89e4eSSatish Balay   /* Pack up the received data */
124785e854fSJed Brown   ierr = PetscMalloc1(nrecvs,onodes);CHKERRQ(ierr);
1256bfd7d4fSJunchao Zhang   for (i=0; i<nrecvs; ++i) {
1266bfd7d4fSJunchao Zhang     (*onodes)[i] = w_status[i].MPI_SOURCE;
1276bfd7d4fSJunchao Zhang #if defined(PETSC_HAVE_OMPI_MAJOR_VERSION)
1286bfd7d4fSJunchao Zhang     /* This line is a workaround for a bug in OpenMPI-2.1.1 distributed by Ubuntu-18.04.2 LTS.
1296bfd7d4fSJunchao Zhang        It happens in self-to-self MPI_Send/Recv using MPI_ANY_SOURCE for message matching. OpenMPI
1306bfd7d4fSJunchao Zhang        does not put correct value in recv buffer. See also
1316bfd7d4fSJunchao Zhang        https://lists.mcs.anl.gov/pipermail/petsc-dev/2019-July/024803.html
1326bfd7d4fSJunchao Zhang        https://www.mail-archive.com/users@lists.open-mpi.org//msg33383.html
1336bfd7d4fSJunchao Zhang      */
1346bfd7d4fSJunchao Zhang     if (w_status[i].MPI_SOURCE == rank) (*olengths)[i] = ilengths[rank];
1356bfd7d4fSJunchao Zhang #endif
1366bfd7d4fSJunchao Zhang   }
137e5c89e4eSSatish Balay   ierr = PetscFree2(r_waits,w_status);CHKERRQ(ierr);
138e5c89e4eSSatish Balay   PetscFunctionReturn(0);
139e5c89e4eSSatish Balay }
140dd6ea824SBarry Smith 
141*76eed172SJunchao Zhang /* Same as PetscGatherNumberOfMessages(), except using PetscInt for ilengths[] */
142*76eed172SJunchao Zhang PetscErrorCode  PetscGatherNumberOfMessages_Private(MPI_Comm comm,const PetscMPIInt iflags[],const PetscInt ilengths[],PetscMPIInt *nrecvs)
143*76eed172SJunchao Zhang {
144*76eed172SJunchao Zhang   PetscMPIInt    size,rank,*recv_buf,i,*iflags_local = NULL,*iflags_localm = NULL;
145*76eed172SJunchao Zhang   PetscErrorCode ierr;
146*76eed172SJunchao Zhang 
147*76eed172SJunchao Zhang   PetscFunctionBegin;
148*76eed172SJunchao Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
149*76eed172SJunchao Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
150*76eed172SJunchao Zhang 
151*76eed172SJunchao Zhang   ierr = PetscMalloc2(size,&recv_buf,size,&iflags_localm);CHKERRQ(ierr);
152*76eed172SJunchao Zhang 
153*76eed172SJunchao Zhang   /* If iflags not provided, compute iflags from ilengths */
154*76eed172SJunchao Zhang   if (!iflags) {
155*76eed172SJunchao Zhang     if (!ilengths) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Either iflags or ilengths should be provided");
156*76eed172SJunchao Zhang     iflags_local = iflags_localm;
157*76eed172SJunchao Zhang     for (i=0; i<size; i++) {
158*76eed172SJunchao Zhang       if (ilengths[i]) iflags_local[i] = 1;
159*76eed172SJunchao Zhang       else iflags_local[i] = 0;
160*76eed172SJunchao Zhang     }
161*76eed172SJunchao Zhang   } else iflags_local = (PetscMPIInt*) iflags;
162*76eed172SJunchao Zhang 
163*76eed172SJunchao Zhang   /* Post an allreduce to determine the numer of messages the current node will receive */
164*76eed172SJunchao Zhang   ierr    = MPIU_Allreduce(iflags_local,recv_buf,size,MPI_INT,MPI_SUM,comm);CHKERRMPI(ierr);
165*76eed172SJunchao Zhang   *nrecvs = recv_buf[rank];
166*76eed172SJunchao Zhang 
167*76eed172SJunchao Zhang   ierr = PetscFree2(recv_buf,iflags_localm);CHKERRQ(ierr);
168*76eed172SJunchao Zhang   PetscFunctionReturn(0);
169*76eed172SJunchao Zhang }
170*76eed172SJunchao Zhang 
171*76eed172SJunchao Zhang /* Same as PetscGatherMessageLengths(), except using PetscInt for message lengths */
172*76eed172SJunchao Zhang PetscErrorCode  PetscGatherMessageLengths_Private(MPI_Comm comm,PetscMPIInt nsends,PetscMPIInt nrecvs,const PetscInt ilengths[],PetscMPIInt **onodes,PetscInt **olengths)
173*76eed172SJunchao Zhang {
174*76eed172SJunchao Zhang   PetscErrorCode ierr;
175*76eed172SJunchao Zhang   PetscMPIInt    size,rank,tag,i,j;
176*76eed172SJunchao Zhang   MPI_Request    *s_waits  = NULL,*r_waits = NULL;
177*76eed172SJunchao Zhang   MPI_Status     *w_status = NULL;
178*76eed172SJunchao Zhang 
179*76eed172SJunchao Zhang   PetscFunctionBegin;
180*76eed172SJunchao Zhang   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
181*76eed172SJunchao Zhang   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
182*76eed172SJunchao Zhang   ierr = PetscCommGetNewTag(comm,&tag);CHKERRQ(ierr);
183*76eed172SJunchao Zhang 
184*76eed172SJunchao Zhang   /* cannot use PetscMalloc3() here because in the call to MPI_Waitall() they MUST be contiguous */
185*76eed172SJunchao Zhang   ierr    = PetscMalloc2(nrecvs+nsends,&r_waits,nrecvs+nsends,&w_status);CHKERRQ(ierr);
186*76eed172SJunchao Zhang   s_waits = r_waits+nrecvs;
187*76eed172SJunchao Zhang 
188*76eed172SJunchao Zhang   /* Post the Irecv to get the message length-info */
189*76eed172SJunchao Zhang   ierr = PetscMalloc1(nrecvs,olengths);CHKERRQ(ierr);
190*76eed172SJunchao Zhang   for (i=0; i<nrecvs; i++) {
191*76eed172SJunchao Zhang     ierr = MPI_Irecv((*olengths)+i,1,MPIU_INT,MPI_ANY_SOURCE,tag,comm,r_waits+i);CHKERRMPI(ierr);
192*76eed172SJunchao Zhang   }
193*76eed172SJunchao Zhang 
194*76eed172SJunchao Zhang   /* Post the Isends with the message length-info */
195*76eed172SJunchao Zhang   for (i=0,j=0; i<size; ++i) {
196*76eed172SJunchao Zhang     if (ilengths[i]) {
197*76eed172SJunchao Zhang       ierr = MPI_Isend((void*)(ilengths+i),1,MPIU_INT,i,tag,comm,s_waits+j);CHKERRMPI(ierr);
198*76eed172SJunchao Zhang       j++;
199*76eed172SJunchao Zhang     }
200*76eed172SJunchao Zhang   }
201*76eed172SJunchao Zhang 
202*76eed172SJunchao Zhang   /* Post waits on sends and receivs */
203*76eed172SJunchao Zhang   if (nrecvs+nsends) {ierr = MPI_Waitall(nrecvs+nsends,r_waits,w_status);CHKERRMPI(ierr);}
204*76eed172SJunchao Zhang 
205*76eed172SJunchao Zhang   /* Pack up the received data */
206*76eed172SJunchao Zhang   ierr = PetscMalloc1(nrecvs,onodes);CHKERRQ(ierr);
207*76eed172SJunchao Zhang   for (i=0; i<nrecvs; ++i) {
208*76eed172SJunchao Zhang     (*onodes)[i] = w_status[i].MPI_SOURCE;
209*76eed172SJunchao Zhang     if (w_status[i].MPI_SOURCE == rank) (*olengths)[i] = ilengths[rank]; /* See comments in PetscGatherMessageLengths */
210*76eed172SJunchao Zhang   }
211*76eed172SJunchao Zhang   ierr = PetscFree2(r_waits,w_status);CHKERRQ(ierr);
212*76eed172SJunchao Zhang   PetscFunctionReturn(0);
213*76eed172SJunchao Zhang }
214*76eed172SJunchao Zhang 
215e5c89e4eSSatish Balay /*@C
216e5c89e4eSSatish Balay   PetscGatherMessageLengths2 - Computes info about messages that a MPI-node will receive,
217e5c89e4eSSatish Balay   including (from-id,length) pairs for each message. Same functionality as PetscGatherMessageLengths()
218e5c89e4eSSatish Balay   except it takes TWO ilenths and output TWO olengths.
219e5c89e4eSSatish Balay 
220d083f849SBarry Smith   Collective
221e5c89e4eSSatish Balay 
222e5c89e4eSSatish Balay   Input Parameters:
223e5c89e4eSSatish Balay + comm      - Communicator
224e5c89e4eSSatish Balay . nsends    - number of messages that are to be sent.
225e5c89e4eSSatish Balay . nrecvs    - number of messages being received
2266b867d5aSJose E. Roman . ilengths1 - first array of integers of length sizeof(comm)
2276b867d5aSJose E. Roman - ilengths2 - second array of integers of length sizeof(comm)
228e5c89e4eSSatish Balay 
229e5c89e4eSSatish Balay   Output Parameters:
230e5c89e4eSSatish Balay + onodes    - list of node-ids from which messages are expected
2316b867d5aSJose E. Roman . olengths1 - first corresponding message lengths
2326b867d5aSJose E. Roman - olengths2 - second  message lengths
233e5c89e4eSSatish Balay 
234e5c89e4eSSatish Balay   Level: developer
235e5c89e4eSSatish Balay 
236e5c89e4eSSatish Balay   Notes:
237e5c89e4eSSatish Balay   With this info, the correct MPI_Irecv() can be posted with the correct
238e5c89e4eSSatish Balay   from-id, with a buffer with the right amount of memory required.
239e5c89e4eSSatish Balay 
240e5c89e4eSSatish Balay   The calling function deallocates the memory in onodes and olengths
241e5c89e4eSSatish Balay 
242c2916339SPierre Jolivet   To determine nrecvs, one can use PetscGatherNumberOfMessages()
243e5c89e4eSSatish Balay 
244e5c89e4eSSatish Balay .seealso: PetscGatherMessageLengths() and PetscGatherNumberOfMessages()
245e5c89e4eSSatish Balay @*/
2467087cfbeSBarry Smith PetscErrorCode  PetscGatherMessageLengths2(MPI_Comm comm,PetscMPIInt nsends,PetscMPIInt nrecvs,const PetscMPIInt ilengths1[],const PetscMPIInt ilengths2[],PetscMPIInt **onodes,PetscMPIInt **olengths1,PetscMPIInt **olengths2)
247e5c89e4eSSatish Balay {
248e5c89e4eSSatish Balay   PetscErrorCode ierr;
2490298fd71SBarry Smith   PetscMPIInt    size,tag,i,j,*buf_s = NULL,*buf_r = NULL,*buf_j = NULL;
2500298fd71SBarry Smith   MPI_Request    *s_waits  = NULL,*r_waits = NULL;
2510298fd71SBarry Smith   MPI_Status     *w_status = NULL;
252e5c89e4eSSatish Balay 
253e5c89e4eSSatish Balay   PetscFunctionBegin;
254ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
255e5c89e4eSSatish Balay   ierr = PetscCommGetNewTag(comm,&tag);CHKERRQ(ierr);
256e5c89e4eSSatish Balay 
2573bf92927SBarry Smith   /* cannot use PetscMalloc5() because r_waits and s_waits must be contiguous for the call to MPI_Waitall() */
258dcca6d9dSJed Brown   ierr = PetscMalloc4(nrecvs+nsends,&r_waits,2*nrecvs,&buf_r,2*nsends,&buf_s,nrecvs+nsends,&w_status);CHKERRQ(ierr);
259e5c89e4eSSatish Balay   s_waits = r_waits + nrecvs;
260e5c89e4eSSatish Balay 
261e5c89e4eSSatish Balay   /* Post the Irecv to get the message length-info */
262854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,olengths1);CHKERRQ(ierr);
263854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,olengths2);CHKERRQ(ierr);
264e5c89e4eSSatish Balay   for (i=0; i<nrecvs; i++) {
265e5c89e4eSSatish Balay     buf_j = buf_r + (2*i);
26655b25c41SPierre Jolivet     ierr  = MPI_Irecv(buf_j,2,MPI_INT,MPI_ANY_SOURCE,tag,comm,r_waits+i);CHKERRMPI(ierr);
267e5c89e4eSSatish Balay   }
268e5c89e4eSSatish Balay 
269e5c89e4eSSatish Balay   /* Post the Isends with the message length-info */
270e5c89e4eSSatish Balay   for (i=0,j=0; i<size; ++i) {
271e5c89e4eSSatish Balay     if (ilengths1[i]) {
272e5c89e4eSSatish Balay       buf_j    = buf_s + (2*j);
273e5c89e4eSSatish Balay       buf_j[0] = *(ilengths1+i);
274e5c89e4eSSatish Balay       buf_j[1] = *(ilengths2+i);
275ffc4695bSBarry Smith       ierr = MPI_Isend(buf_j,2,MPI_INT,i,tag,comm,s_waits+j);CHKERRMPI(ierr);
276e5c89e4eSSatish Balay       j++;
277e5c89e4eSSatish Balay     }
278e5c89e4eSSatish Balay   }
279f327f304SBarry Smith   if (j != nsends) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"j %d not equal to expected number of sends %d\n",j,nsends);
280e5c89e4eSSatish Balay 
281e5c89e4eSSatish Balay   /* Post waits on sends and receivs */
282ffc4695bSBarry Smith   if (nrecvs+nsends) {ierr = MPI_Waitall(nrecvs+nsends,r_waits,w_status);CHKERRMPI(ierr);}
283e5c89e4eSSatish Balay 
284e5c89e4eSSatish Balay   /* Pack up the received data */
285854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,onodes);CHKERRQ(ierr);
286e5c89e4eSSatish Balay   for (i=0; i<nrecvs; ++i) {
287e5c89e4eSSatish Balay     (*onodes)[i]    = w_status[i].MPI_SOURCE;
288e5c89e4eSSatish Balay     buf_j           = buf_r + (2*i);
289e5c89e4eSSatish Balay     (*olengths1)[i] = buf_j[0];
290e5c89e4eSSatish Balay     (*olengths2)[i] = buf_j[1];
291e5c89e4eSSatish Balay   }
292e5c89e4eSSatish Balay 
293e5c89e4eSSatish Balay   ierr = PetscFree4(r_waits,buf_r,buf_s,w_status);CHKERRQ(ierr);
294e5c89e4eSSatish Balay   PetscFunctionReturn(0);
295e5c89e4eSSatish Balay }
296e5c89e4eSSatish Balay 
297e5c89e4eSSatish Balay /*
298e5c89e4eSSatish Balay 
299a5b23f4aSJose E. Roman   Allocate a buffer sufficient to hold messages of size specified in olengths.
300e5c89e4eSSatish Balay   And post Irecvs on these buffers using node info from onodes
301e5c89e4eSSatish Balay 
302e5c89e4eSSatish Balay  */
3037087cfbeSBarry Smith PetscErrorCode  PetscPostIrecvInt(MPI_Comm comm,PetscMPIInt tag,PetscMPIInt nrecvs,const PetscMPIInt onodes[],const PetscMPIInt olengths[],PetscInt ***rbuf,MPI_Request **r_waits)
304e5c89e4eSSatish Balay {
305e5c89e4eSSatish Balay   PetscErrorCode ierr;
306c05d87d6SBarry Smith   PetscInt       **rbuf_t,i,len = 0;
307e5c89e4eSSatish Balay   MPI_Request    *r_waits_t;
308e5c89e4eSSatish Balay 
309e5c89e4eSSatish Balay   PetscFunctionBegin;
310e5c89e4eSSatish Balay   /* compute memory required for recv buffers */
311e5c89e4eSSatish Balay   for (i=0; i<nrecvs; i++) len += olengths[i];  /* each message length */
312e5c89e4eSSatish Balay 
313e5c89e4eSSatish Balay   /* allocate memory for recv buffers */
314854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&rbuf_t);CHKERRQ(ierr);
315785e854fSJed Brown   ierr = PetscMalloc1(len,&rbuf_t[0]);CHKERRQ(ierr);
316e5c89e4eSSatish Balay   for (i=1; i<nrecvs; ++i) rbuf_t[i] = rbuf_t[i-1] + olengths[i-1];
317e5c89e4eSSatish Balay 
318e5c89e4eSSatish Balay   /* Post the receives */
319785e854fSJed Brown   ierr = PetscMalloc1(nrecvs,&r_waits_t);CHKERRQ(ierr);
320e5c89e4eSSatish Balay   for (i=0; i<nrecvs; ++i) {
321ffc4695bSBarry Smith     ierr = MPI_Irecv(rbuf_t[i],olengths[i],MPIU_INT,onodes[i],tag,comm,r_waits_t+i);CHKERRMPI(ierr);
322e5c89e4eSSatish Balay   }
323e5c89e4eSSatish Balay 
324e5c89e4eSSatish Balay   *rbuf    = rbuf_t;
325e5c89e4eSSatish Balay   *r_waits = r_waits_t;
326e5c89e4eSSatish Balay   PetscFunctionReturn(0);
327e5c89e4eSSatish Balay }
328e5c89e4eSSatish Balay 
3297087cfbeSBarry Smith PetscErrorCode  PetscPostIrecvScalar(MPI_Comm comm,PetscMPIInt tag,PetscMPIInt nrecvs,const PetscMPIInt onodes[],const PetscMPIInt olengths[],PetscScalar ***rbuf,MPI_Request **r_waits)
330e5c89e4eSSatish Balay {
331e5c89e4eSSatish Balay   PetscErrorCode ierr;
332052f0c41SBarry Smith   PetscMPIInt    i;
333e5c89e4eSSatish Balay   PetscScalar    **rbuf_t;
334e5c89e4eSSatish Balay   MPI_Request    *r_waits_t;
335c05d87d6SBarry Smith   PetscInt       len = 0;
336e5c89e4eSSatish Balay 
337fe28d99cSBarry Smith   PetscFunctionBegin;
338e5c89e4eSSatish Balay   /* compute memory required for recv buffers */
339e5c89e4eSSatish Balay   for (i=0; i<nrecvs; i++) len += olengths[i];  /* each message length */
340e5c89e4eSSatish Balay 
341e5c89e4eSSatish Balay   /* allocate memory for recv buffers */
342854ce69bSBarry Smith   ierr = PetscMalloc1(nrecvs+1,&rbuf_t);CHKERRQ(ierr);
343785e854fSJed Brown   ierr = PetscMalloc1(len,&rbuf_t[0]);CHKERRQ(ierr);
344e5c89e4eSSatish Balay   for (i=1; i<nrecvs; ++i) rbuf_t[i] = rbuf_t[i-1] + olengths[i-1];
345e5c89e4eSSatish Balay 
346e5c89e4eSSatish Balay   /* Post the receives */
347785e854fSJed Brown   ierr = PetscMalloc1(nrecvs,&r_waits_t);CHKERRQ(ierr);
348e5c89e4eSSatish Balay   for (i=0; i<nrecvs; ++i) {
349ffc4695bSBarry Smith     ierr = MPI_Irecv(rbuf_t[i],olengths[i],MPIU_SCALAR,onodes[i],tag,comm,r_waits_t+i);CHKERRMPI(ierr);
350e5c89e4eSSatish Balay   }
351e5c89e4eSSatish Balay 
352e5c89e4eSSatish Balay   *rbuf    = rbuf_t;
353e5c89e4eSSatish Balay   *r_waits = r_waits_t;
354e5c89e4eSSatish Balay   PetscFunctionReturn(0);
355e5c89e4eSSatish Balay }
356