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 @*/ 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 @*/ 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[] */ 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 */ 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 @*/ 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 */ 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 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