1c6db04a5SJed Brown #include <petscsys.h> /*I "petscsys.h" I*/
26497c311SBarry Smith
3d6acfc2dSPierre Jolivet PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscGatherNumberOfMessages_Private(MPI_Comm, const PetscMPIInt[], const PetscInt[], PetscMPIInt *);
4d6acfc2dSPierre Jolivet PETSC_SINGLE_LIBRARY_INTERN PetscErrorCode PetscGatherMessageLengths_Private(MPI_Comm, PetscMPIInt, PetscMPIInt, const PetscInt[], PetscMPIInt **, PetscInt **);
5e5c89e4eSSatish Balay
6e5c89e4eSSatish Balay /*@C
7811af0c4SBarry Smith PetscGatherNumberOfMessages - Computes the number of messages an MPI rank expects to receive during a neighbor communication
8e5c89e4eSSatish Balay
9cc4c1da9SBarry Smith Collective, No Fortran Support
10e5c89e4eSSatish Balay
11e5c89e4eSSatish Balay Input Parameters:
12e5c89e4eSSatish Balay + comm - Communicator
13667f096bSBarry Smith . iflags - an array of integers of length sizeof(comm). A '1' in `ilengths`[i] represent a
14667f096bSBarry Smith message from current node to ith node. Optionally `NULL`
15667f096bSBarry Smith - ilengths - Non zero ilengths[i] represent a message to i of length `ilengths`[i].
16667f096bSBarry Smith Optionally `NULL`.
17e5c89e4eSSatish Balay
182fe279fdSBarry Smith Output Parameter:
19e5c89e4eSSatish Balay . nrecvs - number of messages received
20e5c89e4eSSatish Balay
21e5c89e4eSSatish Balay Level: developer
22e5c89e4eSSatish Balay
23e5c89e4eSSatish Balay Notes:
24e5c89e4eSSatish Balay With this info, the correct message lengths can be determined using
25811af0c4SBarry Smith `PetscGatherMessageLengths()`
26e5c89e4eSSatish Balay
27667f096bSBarry Smith Either `iflags` or `ilengths` should be provided. If `iflags` is not
28667f096bSBarry Smith provided (`NULL`) it can be computed from `ilengths`. If `iflags` is
29667f096bSBarry Smith provided, `ilengths` is not required.
30e5c89e4eSSatish Balay
31811af0c4SBarry Smith .seealso: `PetscGatherMessageLengths()`, `PetscGatherMessageLengths2()`, `PetscCommBuildTwoSided()`
32e5c89e4eSSatish Balay @*/
PetscGatherNumberOfMessages(MPI_Comm comm,const PetscMPIInt iflags[],const PetscMPIInt ilengths[],PetscMPIInt * nrecvs)33d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGatherNumberOfMessages(MPI_Comm comm, const PetscMPIInt iflags[], const PetscMPIInt ilengths[], PetscMPIInt *nrecvs)
34d71ae5a4SJacob Faibussowitsch {
358e3a54c0SPierre Jolivet PetscMPIInt size, rank, *recv_buf, i, *iflags_local = NULL, *iflags_localm;
36e5c89e4eSSatish Balay
37e5c89e4eSSatish Balay PetscFunctionBegin;
389566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
399566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
40e5c89e4eSSatish Balay
419566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(size, &recv_buf, size, &iflags_localm));
42e5c89e4eSSatish Balay
43e5c89e4eSSatish Balay /* If iflags not provided, compute iflags from ilengths */
44e5c89e4eSSatish Balay if (!iflags) {
4528b400f6SJacob Faibussowitsch PetscCheck(ilengths, 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
53be87f6c0SPierre Jolivet /* Post an allreduce to determine the number of messages the current MPI rank will receive */
54462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(iflags_local, recv_buf, size, MPI_INT, MPI_SUM, comm));
55e5c89e4eSSatish Balay *nrecvs = recv_buf[rank];
56e5c89e4eSSatish Balay
579566063dSJacob Faibussowitsch PetscCall(PetscFree2(recv_buf, iflags_localm));
583ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
59e5c89e4eSSatish Balay }
60e5c89e4eSSatish Balay
61e5c89e4eSSatish Balay /*@C
62da81f932SPierre Jolivet PetscGatherMessageLengths - Computes information about messages that an MPI rank will receive,
63e5c89e4eSSatish Balay including (from-id,length) pairs for each message.
64e5c89e4eSSatish Balay
65cc4c1da9SBarry Smith Collective, No Fortran Support
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)
72667f096bSBarry Smith a non zero `ilengths`[i] represent a message to i of length `ilengths`[i]
73e5c89e4eSSatish Balay
74e5c89e4eSSatish Balay Output Parameters:
75667f096bSBarry Smith + onodes - list of ranks from which messages are expected
76e5c89e4eSSatish Balay - olengths - corresponding message lengths
77e5c89e4eSSatish Balay
78e5c89e4eSSatish Balay Level: developer
79e5c89e4eSSatish Balay
80e5c89e4eSSatish Balay Notes:
816497c311SBarry Smith With this info, the correct `MPIU_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
86667f096bSBarry Smith To determine `nrecvs`, one can use `PetscGatherNumberOfMessages()`
87e5c89e4eSSatish Balay
88811af0c4SBarry Smith .seealso: `PetscGatherNumberOfMessages()`, `PetscGatherMessageLengths2()`, `PetscCommBuildTwoSided()`
89e5c89e4eSSatish Balay @*/
PetscGatherMessageLengths(MPI_Comm comm,PetscMPIInt nsends,PetscMPIInt nrecvs,const PetscMPIInt ilengths[],PetscMPIInt ** onodes,PetscMPIInt ** olengths)90d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGatherMessageLengths(MPI_Comm comm, PetscMPIInt nsends, PetscMPIInt nrecvs, const PetscMPIInt ilengths[], PetscMPIInt **onodes, PetscMPIInt **olengths)
91d71ae5a4SJacob Faibussowitsch {
926bfd7d4fSJunchao Zhang PetscMPIInt size, rank, tag, i, j;
938e3a54c0SPierre Jolivet MPI_Request *s_waits, *r_waits;
948e3a54c0SPierre Jolivet MPI_Status *w_status;
95e5c89e4eSSatish Balay
96e5c89e4eSSatish Balay PetscFunctionBegin;
979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
989566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
999566063dSJacob Faibussowitsch PetscCall(PetscCommGetNewTag(comm, &tag));
100e5c89e4eSSatish Balay
101e5c89e4eSSatish Balay /* cannot use PetscMalloc3() here because in the call to MPI_Waitall() they MUST be contiguous */
1029566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nrecvs + nsends, &r_waits, nrecvs + nsends, &w_status));
1038e3a54c0SPierre Jolivet s_waits = PetscSafePointerPlusOffset(r_waits, nrecvs);
104e5c89e4eSSatish Balay
105e5c89e4eSSatish Balay /* Post the Irecv to get the message length-info */
1069566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nrecvs, olengths));
1076497c311SBarry Smith for (i = 0; i < nrecvs; i++) PetscCallMPI(MPIU_Irecv((*olengths) + i, 1, MPI_INT, MPI_ANY_SOURCE, tag, comm, r_waits + i));
108e5c89e4eSSatish Balay
109e5c89e4eSSatish Balay /* Post the Isends with the message length-info */
110e5c89e4eSSatish Balay for (i = 0, j = 0; i < size; ++i) {
111e5c89e4eSSatish Balay if (ilengths[i]) {
1126497c311SBarry Smith PetscCallMPI(MPIU_Isend((void *)(ilengths + i), 1, MPI_INT, i, tag, comm, s_waits + j));
113e5c89e4eSSatish Balay j++;
114e5c89e4eSSatish Balay }
115e5c89e4eSSatish Balay }
116e5c89e4eSSatish Balay
1176aad120cSJose E. Roman /* Post waits on sends and receives */
1189566063dSJacob Faibussowitsch if (nrecvs + nsends) PetscCallMPI(MPI_Waitall(nrecvs + nsends, r_waits, w_status));
119e5c89e4eSSatish Balay
120e5c89e4eSSatish Balay /* Pack up the received data */
1219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nrecvs, onodes));
1226bfd7d4fSJunchao Zhang for (i = 0; i < nrecvs; ++i) {
1236bfd7d4fSJunchao Zhang (*onodes)[i] = w_status[i].MPI_SOURCE;
124100ffedbSJunchao Zhang #if defined(PETSC_HAVE_OPENMPI)
125337bb527SBarry Smith /* This line is a workaround for a bug in Open MPI 2.1.1 distributed by Ubuntu-18.04.2 LTS.
1266bfd7d4fSJunchao Zhang It happens in self-to-self MPI_Send/Recv using MPI_ANY_SOURCE for message matching. Open MPI
1276bfd7d4fSJunchao Zhang does not put correct value in recv buffer. See also
1286bfd7d4fSJunchao Zhang https://lists.mcs.anl.gov/pipermail/petsc-dev/2019-July/024803.html
1296bfd7d4fSJunchao Zhang https://www.mail-archive.com/users@lists.open-mpi.org//msg33383.html
1306bfd7d4fSJunchao Zhang */
1316bfd7d4fSJunchao Zhang if (w_status[i].MPI_SOURCE == rank) (*olengths)[i] = ilengths[rank];
1326bfd7d4fSJunchao Zhang #endif
1336bfd7d4fSJunchao Zhang }
1349566063dSJacob Faibussowitsch PetscCall(PetscFree2(r_waits, w_status));
1353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
136e5c89e4eSSatish Balay }
137dd6ea824SBarry Smith
13876eed172SJunchao Zhang /* Same as PetscGatherNumberOfMessages(), except using PetscInt for ilengths[] */
PetscGatherNumberOfMessages_Private(MPI_Comm comm,const PetscMPIInt iflags[],const PetscInt ilengths[],PetscMPIInt * nrecvs)139d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGatherNumberOfMessages_Private(MPI_Comm comm, const PetscMPIInt iflags[], const PetscInt ilengths[], PetscMPIInt *nrecvs)
140d71ae5a4SJacob Faibussowitsch {
1418e3a54c0SPierre Jolivet PetscMPIInt size, rank, *recv_buf, i, *iflags_local = NULL, *iflags_localm;
14276eed172SJunchao Zhang
14376eed172SJunchao Zhang PetscFunctionBegin;
1449566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
1459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
14676eed172SJunchao Zhang
1479566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(size, &recv_buf, size, &iflags_localm));
14876eed172SJunchao Zhang
14976eed172SJunchao Zhang /* If iflags not provided, compute iflags from ilengths */
15076eed172SJunchao Zhang if (!iflags) {
15128b400f6SJacob Faibussowitsch PetscCheck(ilengths, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Either iflags or ilengths should be provided");
15276eed172SJunchao Zhang iflags_local = iflags_localm;
15376eed172SJunchao Zhang for (i = 0; i < size; i++) {
15476eed172SJunchao Zhang if (ilengths[i]) iflags_local[i] = 1;
15576eed172SJunchao Zhang else iflags_local[i] = 0;
15676eed172SJunchao Zhang }
15776eed172SJunchao Zhang } else iflags_local = (PetscMPIInt *)iflags;
15876eed172SJunchao Zhang
159be87f6c0SPierre Jolivet /* Post an allreduce to determine the number of messages the current MPI rank will receive */
160462c564dSBarry Smith PetscCallMPI(MPIU_Allreduce(iflags_local, recv_buf, size, MPI_INT, MPI_SUM, comm));
16176eed172SJunchao Zhang *nrecvs = recv_buf[rank];
16276eed172SJunchao Zhang
1639566063dSJacob Faibussowitsch PetscCall(PetscFree2(recv_buf, iflags_localm));
1643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
16576eed172SJunchao Zhang }
16676eed172SJunchao Zhang
16776eed172SJunchao Zhang /* Same as PetscGatherMessageLengths(), except using PetscInt for message lengths */
PetscGatherMessageLengths_Private(MPI_Comm comm,PetscMPIInt nsends,PetscMPIInt nrecvs,const PetscInt ilengths[],PetscMPIInt ** onodes,PetscInt ** olengths)168d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGatherMessageLengths_Private(MPI_Comm comm, PetscMPIInt nsends, PetscMPIInt nrecvs, const PetscInt ilengths[], PetscMPIInt **onodes, PetscInt **olengths)
169d71ae5a4SJacob Faibussowitsch {
17076eed172SJunchao Zhang PetscMPIInt size, rank, tag, i, j;
1718e3a54c0SPierre Jolivet MPI_Request *s_waits, *r_waits;
1728e3a54c0SPierre Jolivet MPI_Status *w_status;
17376eed172SJunchao Zhang
17476eed172SJunchao Zhang PetscFunctionBegin;
1759566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
1769566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank));
1779566063dSJacob Faibussowitsch PetscCall(PetscCommGetNewTag(comm, &tag));
17876eed172SJunchao Zhang
17976eed172SJunchao Zhang /* cannot use PetscMalloc3() here because in the call to MPI_Waitall() they MUST be contiguous */
1809566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(nrecvs + nsends, &r_waits, nrecvs + nsends, &w_status));
1818e3a54c0SPierre Jolivet s_waits = PetscSafePointerPlusOffset(r_waits, nrecvs);
18276eed172SJunchao Zhang
18376eed172SJunchao Zhang /* Post the Irecv to get the message length-info */
1849566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nrecvs, olengths));
1856497c311SBarry Smith for (i = 0; i < nrecvs; i++) PetscCallMPI(MPIU_Irecv((*olengths) + i, 1, MPIU_INT, MPI_ANY_SOURCE, tag, comm, r_waits + i));
18676eed172SJunchao Zhang
18776eed172SJunchao Zhang /* Post the Isends with the message length-info */
18876eed172SJunchao Zhang for (i = 0, j = 0; i < size; ++i) {
18976eed172SJunchao Zhang if (ilengths[i]) {
1906497c311SBarry Smith PetscCallMPI(MPIU_Isend((void *)(ilengths + i), 1, MPIU_INT, i, tag, comm, s_waits + j));
19176eed172SJunchao Zhang j++;
19276eed172SJunchao Zhang }
19376eed172SJunchao Zhang }
19476eed172SJunchao Zhang
1956aad120cSJose E. Roman /* Post waits on sends and receives */
1969566063dSJacob Faibussowitsch if (nrecvs + nsends) PetscCallMPI(MPI_Waitall(nrecvs + nsends, r_waits, w_status));
19776eed172SJunchao Zhang
19876eed172SJunchao Zhang /* Pack up the received data */
1999566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nrecvs, onodes));
20076eed172SJunchao Zhang for (i = 0; i < nrecvs; ++i) {
20176eed172SJunchao Zhang (*onodes)[i] = w_status[i].MPI_SOURCE;
20276eed172SJunchao Zhang if (w_status[i].MPI_SOURCE == rank) (*olengths)[i] = ilengths[rank]; /* See comments in PetscGatherMessageLengths */
20376eed172SJunchao Zhang }
2049566063dSJacob Faibussowitsch PetscCall(PetscFree2(r_waits, w_status));
2053ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
20676eed172SJunchao Zhang }
20776eed172SJunchao Zhang
208e5c89e4eSSatish Balay /*@C
209811af0c4SBarry Smith PetscGatherMessageLengths2 - Computes info about messages that a MPI rank will receive,
210811af0c4SBarry Smith including (from-id,length) pairs for each message. Same functionality as `PetscGatherMessageLengths()`
211e5c89e4eSSatish Balay except it takes TWO ilenths and output TWO olengths.
212e5c89e4eSSatish Balay
213cc4c1da9SBarry Smith Collective, No Fortran Support
214e5c89e4eSSatish Balay
215e5c89e4eSSatish Balay Input Parameters:
216e5c89e4eSSatish Balay + comm - Communicator
217e5c89e4eSSatish Balay . nsends - number of messages that are to be sent.
218e5c89e4eSSatish Balay . nrecvs - number of messages being received
2196b867d5aSJose E. Roman . ilengths1 - first array of integers of length sizeof(comm)
2206b867d5aSJose E. Roman - ilengths2 - second array of integers of length sizeof(comm)
221e5c89e4eSSatish Balay
222e5c89e4eSSatish Balay Output Parameters:
223667f096bSBarry Smith + onodes - list of ranks from which messages are expected
2246b867d5aSJose E. Roman . olengths1 - first corresponding message lengths
2256b867d5aSJose E. Roman - olengths2 - second message lengths
226e5c89e4eSSatish Balay
227e5c89e4eSSatish Balay Level: developer
228e5c89e4eSSatish Balay
229e5c89e4eSSatish Balay Notes:
2306497c311SBarry Smith With this info, the correct `MPIU_Irecv()` can be posted with the correct
231e5c89e4eSSatish Balay from-id, with a buffer with the right amount of memory required.
232e5c89e4eSSatish Balay
233667f096bSBarry Smith The calling function should `PetscFree()` the memory in `onodes` and `olengths`
234e5c89e4eSSatish Balay
235667f096bSBarry Smith To determine `nrecvs`, one can use `PetscGatherNumberOfMessages()`
236e5c89e4eSSatish Balay
237811af0c4SBarry Smith .seealso: `PetscGatherMessageLengths()`, `PetscGatherNumberOfMessages()`, `PetscCommBuildTwoSided()`
238e5c89e4eSSatish Balay @*/
PetscGatherMessageLengths2(MPI_Comm comm,PetscMPIInt nsends,PetscMPIInt nrecvs,const PetscMPIInt ilengths1[],const PetscMPIInt ilengths2[],PetscMPIInt ** onodes,PetscMPIInt ** olengths1,PetscMPIInt ** olengths2)239d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGatherMessageLengths2(MPI_Comm comm, PetscMPIInt nsends, PetscMPIInt nrecvs, const PetscMPIInt ilengths1[], const PetscMPIInt ilengths2[], PetscMPIInt **onodes, PetscMPIInt **olengths1, PetscMPIInt **olengths2)
240d71ae5a4SJacob Faibussowitsch {
2418e3a54c0SPierre Jolivet PetscMPIInt size, tag, i, j, *buf_s, *buf_r, *buf_j = NULL;
2428e3a54c0SPierre Jolivet MPI_Request *s_waits, *r_waits;
2438e3a54c0SPierre Jolivet MPI_Status *w_status;
244e5c89e4eSSatish Balay
245e5c89e4eSSatish Balay PetscFunctionBegin;
2469566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size));
2479566063dSJacob Faibussowitsch PetscCall(PetscCommGetNewTag(comm, &tag));
248e5c89e4eSSatish Balay
2493bf92927SBarry Smith /* cannot use PetscMalloc5() because r_waits and s_waits must be contiguous for the call to MPI_Waitall() */
2509566063dSJacob Faibussowitsch PetscCall(PetscMalloc4(nrecvs + nsends, &r_waits, 2 * nrecvs, &buf_r, 2 * nsends, &buf_s, nrecvs + nsends, &w_status));
2518e3a54c0SPierre Jolivet s_waits = PetscSafePointerPlusOffset(r_waits, nrecvs);
252e5c89e4eSSatish Balay
253e5c89e4eSSatish Balay /* Post the Irecv to get the message length-info */
254*84648c2dSPierre Jolivet PetscCall(PetscMalloc1(nrecvs, olengths1));
255*84648c2dSPierre Jolivet PetscCall(PetscMalloc1(nrecvs, olengths2));
256e5c89e4eSSatish Balay for (i = 0; i < nrecvs; i++) {
257e5c89e4eSSatish Balay buf_j = buf_r + (2 * i);
2586497c311SBarry Smith PetscCallMPI(MPIU_Irecv(buf_j, 2, MPI_INT, MPI_ANY_SOURCE, tag, comm, r_waits + i));
259e5c89e4eSSatish Balay }
260e5c89e4eSSatish Balay
261e5c89e4eSSatish Balay /* Post the Isends with the message length-info */
262e5c89e4eSSatish Balay for (i = 0, j = 0; i < size; ++i) {
263e5c89e4eSSatish Balay if (ilengths1[i]) {
264e5c89e4eSSatish Balay buf_j = buf_s + (2 * j);
265e5c89e4eSSatish Balay buf_j[0] = *(ilengths1 + i);
266e5c89e4eSSatish Balay buf_j[1] = *(ilengths2 + i);
2676497c311SBarry Smith PetscCallMPI(MPIU_Isend(buf_j, 2, MPI_INT, i, tag, comm, s_waits + j));
268e5c89e4eSSatish Balay j++;
269e5c89e4eSSatish Balay }
270e5c89e4eSSatish Balay }
27108401ef6SPierre Jolivet PetscCheck(j == nsends, PETSC_COMM_SELF, PETSC_ERR_PLIB, "j %d not equal to expected number of sends %d", j, nsends);
272e5c89e4eSSatish Balay
2736aad120cSJose E. Roman /* Post waits on sends and receives */
2749566063dSJacob Faibussowitsch if (nrecvs + nsends) PetscCallMPI(MPI_Waitall(nrecvs + nsends, r_waits, w_status));
275e5c89e4eSSatish Balay
276e5c89e4eSSatish Balay /* Pack up the received data */
277*84648c2dSPierre Jolivet PetscCall(PetscMalloc1(nrecvs, onodes));
278e5c89e4eSSatish Balay for (i = 0; i < nrecvs; ++i) {
279e5c89e4eSSatish Balay (*onodes)[i] = w_status[i].MPI_SOURCE;
280e5c89e4eSSatish Balay buf_j = buf_r + (2 * i);
281e5c89e4eSSatish Balay (*olengths1)[i] = buf_j[0];
282e5c89e4eSSatish Balay (*olengths2)[i] = buf_j[1];
283e5c89e4eSSatish Balay }
284e5c89e4eSSatish Balay
2859566063dSJacob Faibussowitsch PetscCall(PetscFree4(r_waits, buf_r, buf_s, w_status));
2863ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
287e5c89e4eSSatish Balay }
288e5c89e4eSSatish Balay
289e5c89e4eSSatish Balay /*
290a5b23f4aSJose E. Roman Allocate a buffer sufficient to hold messages of size specified in olengths.
291e5c89e4eSSatish Balay And post Irecvs on these buffers using node info from onodes
292e5c89e4eSSatish Balay */
PetscPostIrecvInt(MPI_Comm comm,PetscMPIInt tag,PetscMPIInt nrecvs,const PetscMPIInt onodes[],const PetscMPIInt olengths[],PetscInt *** rbuf,MPI_Request ** r_waits)293d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPostIrecvInt(MPI_Comm comm, PetscMPIInt tag, PetscMPIInt nrecvs, const PetscMPIInt onodes[], const PetscMPIInt olengths[], PetscInt ***rbuf, MPI_Request **r_waits)
294d71ae5a4SJacob Faibussowitsch {
295c05d87d6SBarry Smith PetscInt **rbuf_t, i, len = 0;
296e5c89e4eSSatish Balay MPI_Request *r_waits_t;
297e5c89e4eSSatish Balay
298e5c89e4eSSatish Balay PetscFunctionBegin;
299e5c89e4eSSatish Balay /* compute memory required for recv buffers */
300e5c89e4eSSatish Balay for (i = 0; i < nrecvs; i++) len += olengths[i]; /* each message length */
301e5c89e4eSSatish Balay
302e5c89e4eSSatish Balay /* allocate memory for recv buffers */
3039566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nrecvs + 1, &rbuf_t));
3049566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(len, &rbuf_t[0]));
305e5c89e4eSSatish Balay for (i = 1; i < nrecvs; ++i) rbuf_t[i] = rbuf_t[i - 1] + olengths[i - 1];
306e5c89e4eSSatish Balay
307e5c89e4eSSatish Balay /* Post the receives */
3089566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nrecvs, &r_waits_t));
3096497c311SBarry Smith for (i = 0; i < nrecvs; ++i) PetscCallMPI(MPIU_Irecv(rbuf_t[i], olengths[i], MPIU_INT, onodes[i], tag, comm, r_waits_t + i));
310e5c89e4eSSatish Balay
311e5c89e4eSSatish Balay *rbuf = rbuf_t;
312e5c89e4eSSatish Balay *r_waits = r_waits_t;
3133ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
314e5c89e4eSSatish Balay }
315e5c89e4eSSatish Balay
PetscPostIrecvScalar(MPI_Comm comm,PetscMPIInt tag,PetscMPIInt nrecvs,const PetscMPIInt onodes[],const PetscMPIInt olengths[],PetscScalar *** rbuf,MPI_Request ** r_waits)316d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscPostIrecvScalar(MPI_Comm comm, PetscMPIInt tag, PetscMPIInt nrecvs, const PetscMPIInt onodes[], const PetscMPIInt olengths[], PetscScalar ***rbuf, MPI_Request **r_waits)
317d71ae5a4SJacob Faibussowitsch {
318052f0c41SBarry Smith PetscMPIInt i;
319e5c89e4eSSatish Balay PetscScalar **rbuf_t;
320e5c89e4eSSatish Balay MPI_Request *r_waits_t;
321c05d87d6SBarry Smith PetscInt len = 0;
322e5c89e4eSSatish Balay
323fe28d99cSBarry Smith PetscFunctionBegin;
324e5c89e4eSSatish Balay /* compute memory required for recv buffers */
325e5c89e4eSSatish Balay for (i = 0; i < nrecvs; i++) len += olengths[i]; /* each message length */
326e5c89e4eSSatish Balay
327e5c89e4eSSatish Balay /* allocate memory for recv buffers */
3289566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nrecvs + 1, &rbuf_t));
3299566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(len, &rbuf_t[0]));
330e5c89e4eSSatish Balay for (i = 1; i < nrecvs; ++i) rbuf_t[i] = rbuf_t[i - 1] + olengths[i - 1];
331e5c89e4eSSatish Balay
332e5c89e4eSSatish Balay /* Post the receives */
3339566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(nrecvs, &r_waits_t));
3346497c311SBarry Smith for (i = 0; i < nrecvs; ++i) PetscCallMPI(MPIU_Irecv(rbuf_t[i], olengths[i], MPIU_SCALAR, onodes[i], tag, comm, r_waits_t + i));
335e5c89e4eSSatish Balay
336e5c89e4eSSatish Balay *rbuf = rbuf_t;
337e5c89e4eSSatish Balay *r_waits = r_waits_t;
3383ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
339e5c89e4eSSatish Balay }
340