1095059a4SDave May /* 2095059a4SDave May Build a few basic tools to help with partitioned domains. 3095059a4SDave May 4095059a4SDave May 1) 5095059a4SDave May On each processor, have a DomainExchangerTopology. 6095059a4SDave May This is a doubly-connected edge list which enumerates the 7095059a4SDave May communication paths between connected processors. By numbering 8095059a4SDave May these paths we can always uniquely assign message identifers. 9095059a4SDave May 10095059a4SDave May edge 11095059a4SDave May 10 12095059a4SDave May proc ---------> proc 13095059a4SDave May 0 <-------- 1 14095059a4SDave May 11 15095059a4SDave May twin 16095059a4SDave May 172d4ee042Sprj- Eg: Proc 0 send to proc 1 with message id is 10. To receive the correct 18095059a4SDave May message, proc 1 looks for the edge connected to proc 0, and then the 192d4ee042Sprj- message id comes from the twin of that edge 20095059a4SDave May 21095059a4SDave May 2) 22095059a4SDave May A DomainExchangerArrayPacker. 23095059a4SDave May A little function which given a piece of data, will memcpy the data into 24095059a4SDave May an array (which will be sent to procs) into the correct place. 25095059a4SDave May 26095059a4SDave May On Proc 1 we sent data to procs 0,2,3. The data is on different lengths. 27095059a4SDave May All data gets jammed into single array. Need to "jam" data into correct locations 28095059a4SDave May The Packer knows how much is to going to each processor and keeps track of the inserts 29095059a4SDave May so as to avoid ever packing TOO much into one slot, and inevatbly corrupting some memory 30095059a4SDave May 31095059a4SDave May data to 0 data to 2 data to 3 32095059a4SDave May 33095059a4SDave May |--------|-----------------|--| 34095059a4SDave May 35095059a4SDave May User has to unpack message themselves. I can get you the pointer for each i 36095059a4SDave May entry, but you'll have to cast it to the appropriate data type. 37095059a4SDave May 38095059a4SDave May Phase A: Build topology 39095059a4SDave May 40095059a4SDave May Phase B: Define message lengths 41095059a4SDave May 42095059a4SDave May Phase C: Pack data 43095059a4SDave May 44095059a4SDave May Phase D: Send data 45095059a4SDave May 462064fc68SDave May + Constructor 4777048351SPatrick Sanan DMSwarmDataExCreate() 482064fc68SDave May + Phase A 4977048351SPatrick Sanan DMSwarmDataExTopologyInitialize() 5077048351SPatrick Sanan DMSwarmDataExTopologyAddNeighbour() 5177048351SPatrick Sanan DMSwarmDataExTopologyAddNeighbour() 5277048351SPatrick Sanan DMSwarmDataExTopologyFinalize() 532064fc68SDave May + Phase B 5477048351SPatrick Sanan DMSwarmDataExZeroAllSendCount() 5577048351SPatrick Sanan DMSwarmDataExAddToSendCount() 5677048351SPatrick Sanan DMSwarmDataExAddToSendCount() 5777048351SPatrick Sanan DMSwarmDataExAddToSendCount() 582064fc68SDave May + Phase C 5977048351SPatrick Sanan DMSwarmDataExPackInitialize() 6077048351SPatrick Sanan DMSwarmDataExPackData() 6177048351SPatrick Sanan DMSwarmDataExPackData() 6277048351SPatrick Sanan DMSwarmDataExPackFinalize() 632064fc68SDave May +Phase D 6477048351SPatrick Sanan DMSwarmDataExBegin() 652064fc68SDave May ... perform any calculations ... 6677048351SPatrick Sanan DMSwarmDataExEnd() 67095059a4SDave May 682064fc68SDave May ... user calls any getters here ... 69095059a4SDave May 70095059a4SDave May */ 71095059a4SDave May #include <petscvec.h> 72095059a4SDave May #include <petscmat.h> 73095059a4SDave May 74279f676cSBarry Smith #include "../src/dm/impls/swarm/data_ex.h" 75095059a4SDave May 76095059a4SDave May const char *status_names[] = {"initialized", "finalized", "unknown"}; 77095059a4SDave May 78ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerTopologySetup; 79ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerBegin; 80ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerEnd; 81ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerSendCount; 82ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerPack; 83095059a4SDave May 84*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExCreate(MPI_Comm comm, const PetscInt count, DMSwarmDataEx *ex) 85*d71ae5a4SJacob Faibussowitsch { 8677048351SPatrick Sanan DMSwarmDataEx d; 87095059a4SDave May 88521f74f9SMatthew G. Knepley PetscFunctionBegin; 899566063dSJacob Faibussowitsch PetscCall(PetscNew(&d)); 909566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_dup(comm, &d->comm)); 919566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(d->comm, &d->rank)); 92095059a4SDave May 93095059a4SDave May d->instance = count; 94095059a4SDave May 95095059a4SDave May d->topology_status = DEOBJECT_STATE_UNKNOWN; 96095059a4SDave May d->message_lengths_status = DEOBJECT_STATE_UNKNOWN; 97095059a4SDave May d->packer_status = DEOBJECT_STATE_UNKNOWN; 98095059a4SDave May d->communication_status = DEOBJECT_STATE_UNKNOWN; 99095059a4SDave May 100095059a4SDave May d->n_neighbour_procs = -1; 101095059a4SDave May d->neighbour_procs = NULL; 102095059a4SDave May 103095059a4SDave May d->messages_to_be_sent = NULL; 104095059a4SDave May d->message_offsets = NULL; 105095059a4SDave May d->messages_to_be_recvieved = NULL; 106095059a4SDave May 10778c64234SJose E. Roman d->unit_message_size = (size_t)-1; 108095059a4SDave May d->send_message = NULL; 109095059a4SDave May d->send_message_length = -1; 110095059a4SDave May d->recv_message = NULL; 111095059a4SDave May d->recv_message_length = -1; 112095059a4SDave May d->total_pack_cnt = -1; 113095059a4SDave May d->pack_cnt = NULL; 114095059a4SDave May 115095059a4SDave May d->send_tags = NULL; 116095059a4SDave May d->recv_tags = NULL; 117095059a4SDave May 118095059a4SDave May d->_stats = NULL; 119095059a4SDave May d->_requests = NULL; 120521f74f9SMatthew G. Knepley *ex = d; 121521f74f9SMatthew G. Knepley PetscFunctionReturn(0); 122095059a4SDave May } 123095059a4SDave May 124298827fbSBarry Smith /* 1259dddd249SSatish Balay This code is horrible, who let it get into main. 126298827fbSBarry Smith 127298827fbSBarry Smith Should be printing to a viewer, should not be using PETSC_COMM_WORLD 128298827fbSBarry Smith 129298827fbSBarry Smith */ 130*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExView(DMSwarmDataEx d) 131*d71ae5a4SJacob Faibussowitsch { 132095059a4SDave May PetscMPIInt p; 133095059a4SDave May 134095059a4SDave May PetscFunctionBegin; 13563a3b9bcSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, "DMSwarmDataEx: instance=%" PetscInt_FMT "\n", d->instance)); 1369566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, " topology status: %s \n", status_names[d->topology_status])); 1379566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, " message lengths status: %s \n", status_names[d->message_lengths_status])); 1389566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, " packer status status: %s \n", status_names[d->packer_status])); 1399566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, " communication status: %s \n", status_names[d->communication_status])); 140095059a4SDave May 141095059a4SDave May if (d->topology_status == DEOBJECT_FINALIZED) { 1429566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, " Topology:\n")); 1439566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, " [%d] neighbours: %d \n", d->rank, d->n_neighbour_procs)); 14448a46eb9SPierre Jolivet for (p = 0; p < d->n_neighbour_procs; p++) PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, " [%d] neighbour[%d] = %d \n", d->rank, p, d->neighbour_procs[p])); 1459566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, stdout)); 146095059a4SDave May } 147298827fbSBarry Smith 148095059a4SDave May if (d->message_lengths_status == DEOBJECT_FINALIZED) { 1499566063dSJacob Faibussowitsch PetscCall(PetscPrintf(PETSC_COMM_WORLD, " Message lengths:\n")); 1509566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, " [%d] atomic size: %ld \n", d->rank, (long int)d->unit_message_size)); 151095059a4SDave May for (p = 0; p < d->n_neighbour_procs; p++) { 15263a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, " [%d] >>>>> ( %" PetscInt_FMT " units :: tag = %d) >>>>> [%d] \n", d->rank, d->messages_to_be_sent[p], d->send_tags[p], d->neighbour_procs[p])); 153095059a4SDave May } 154095059a4SDave May for (p = 0; p < d->n_neighbour_procs; p++) { 15563a3b9bcSJacob Faibussowitsch PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, " [%d] <<<<< ( %" PetscInt_FMT " units :: tag = %d) <<<<< [%d] \n", d->rank, d->messages_to_be_recvieved[p], d->recv_tags[p], d->neighbour_procs[p])); 156095059a4SDave May } 1579566063dSJacob Faibussowitsch PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, stdout)); 158095059a4SDave May } 159521f74f9SMatthew G. Knepley if (d->packer_status == DEOBJECT_FINALIZED) { } 160521f74f9SMatthew G. Knepley if (d->communication_status == DEOBJECT_FINALIZED) { } 161095059a4SDave May PetscFunctionReturn(0); 162095059a4SDave May } 163095059a4SDave May 164*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExDestroy(DMSwarmDataEx d) 165*d71ae5a4SJacob Faibussowitsch { 166095059a4SDave May PetscFunctionBegin; 1679566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_free(&d->comm)); 1689566063dSJacob Faibussowitsch if (d->neighbour_procs) PetscCall(PetscFree(d->neighbour_procs)); 1699566063dSJacob Faibussowitsch if (d->messages_to_be_sent) PetscCall(PetscFree(d->messages_to_be_sent)); 1709566063dSJacob Faibussowitsch if (d->message_offsets) PetscCall(PetscFree(d->message_offsets)); 1719566063dSJacob Faibussowitsch if (d->messages_to_be_recvieved) PetscCall(PetscFree(d->messages_to_be_recvieved)); 1729566063dSJacob Faibussowitsch if (d->send_message) PetscCall(PetscFree(d->send_message)); 1739566063dSJacob Faibussowitsch if (d->recv_message) PetscCall(PetscFree(d->recv_message)); 1749566063dSJacob Faibussowitsch if (d->pack_cnt) PetscCall(PetscFree(d->pack_cnt)); 1759566063dSJacob Faibussowitsch if (d->send_tags) PetscCall(PetscFree(d->send_tags)); 1769566063dSJacob Faibussowitsch if (d->recv_tags) PetscCall(PetscFree(d->recv_tags)); 1779566063dSJacob Faibussowitsch if (d->_stats) PetscCall(PetscFree(d->_stats)); 1789566063dSJacob Faibussowitsch if (d->_requests) PetscCall(PetscFree(d->_requests)); 1799566063dSJacob Faibussowitsch PetscCall(PetscFree(d)); 180095059a4SDave May PetscFunctionReturn(0); 181095059a4SDave May } 182095059a4SDave May 183095059a4SDave May /* === Phase A === */ 184095059a4SDave May 185*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExTopologyInitialize(DMSwarmDataEx d) 186*d71ae5a4SJacob Faibussowitsch { 187095059a4SDave May PetscFunctionBegin; 188095059a4SDave May d->topology_status = DEOBJECT_INITIALIZED; 189095059a4SDave May d->n_neighbour_procs = 0; 1909566063dSJacob Faibussowitsch PetscCall(PetscFree(d->neighbour_procs)); 1919566063dSJacob Faibussowitsch PetscCall(PetscFree(d->messages_to_be_sent)); 1929566063dSJacob Faibussowitsch PetscCall(PetscFree(d->message_offsets)); 1939566063dSJacob Faibussowitsch PetscCall(PetscFree(d->messages_to_be_recvieved)); 1949566063dSJacob Faibussowitsch PetscCall(PetscFree(d->pack_cnt)); 1959566063dSJacob Faibussowitsch PetscCall(PetscFree(d->send_tags)); 1969566063dSJacob Faibussowitsch PetscCall(PetscFree(d->recv_tags)); 197095059a4SDave May PetscFunctionReturn(0); 198095059a4SDave May } 199095059a4SDave May 200*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExTopologyAddNeighbour(DMSwarmDataEx d, const PetscMPIInt proc_id) 201*d71ae5a4SJacob Faibussowitsch { 202095059a4SDave May PetscMPIInt n, found; 203d7d19db6SBarry Smith PetscMPIInt size; 204095059a4SDave May 205095059a4SDave May PetscFunctionBegin; 20608401ef6SPierre Jolivet PetscCheck(d->topology_status != DEOBJECT_FINALIZED, d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology has been finalized. To modify or update call DMSwarmDataExTopologyInitialize() first"); 207f7d195e4SLawrence Mitchell PetscCheck(d->topology_status == DEOBJECT_INITIALIZED, d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be initialised. Call DMSwarmDataExTopologyInitialize() first"); 2082064fc68SDave May 209095059a4SDave May /* error on negative entries */ 21008401ef6SPierre Jolivet PetscCheck(proc_id >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Trying to set proc neighbour with a rank < 0"); 211095059a4SDave May /* error on ranks larger than number of procs in communicator */ 2129566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(d->comm, &size)); 21308401ef6SPierre Jolivet PetscCheck(proc_id < size, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Trying to set proc neighbour %d with a rank >= size %d", proc_id, size); 2149566063dSJacob Faibussowitsch if (d->n_neighbour_procs == 0) PetscCall(PetscMalloc1(1, &d->neighbour_procs)); 215095059a4SDave May /* check for proc_id */ 216095059a4SDave May found = 0; 217095059a4SDave May for (n = 0; n < d->n_neighbour_procs; n++) { 218ad540459SPierre Jolivet if (d->neighbour_procs[n] == proc_id) found = 1; 219095059a4SDave May } 220095059a4SDave May if (found == 0) { /* add it to list */ 2219566063dSJacob Faibussowitsch PetscCall(PetscRealloc(sizeof(PetscMPIInt) * (d->n_neighbour_procs + 1), &d->neighbour_procs)); 222095059a4SDave May d->neighbour_procs[d->n_neighbour_procs] = proc_id; 223095059a4SDave May d->n_neighbour_procs++; 224095059a4SDave May } 225095059a4SDave May PetscFunctionReturn(0); 226095059a4SDave May } 227095059a4SDave May 228095059a4SDave May /* 229095059a4SDave May counter: the index of the communication object 230095059a4SDave May N: the number of processors 231095059a4SDave May r0: rank of sender 232095059a4SDave May r1: rank of receiver 233095059a4SDave May 234095059a4SDave May procs = { 0, 1, 2, 3 } 235095059a4SDave May 236095059a4SDave May 0 ==> 0 e=0 237095059a4SDave May 0 ==> 1 e=1 238095059a4SDave May 0 ==> 2 e=2 239095059a4SDave May 0 ==> 3 e=3 240095059a4SDave May 241095059a4SDave May 1 ==> 0 e=4 242095059a4SDave May 1 ==> 1 e=5 243095059a4SDave May 1 ==> 2 e=6 244095059a4SDave May 1 ==> 3 e=7 245095059a4SDave May 246095059a4SDave May 2 ==> 0 e=8 247095059a4SDave May 2 ==> 1 e=9 248095059a4SDave May 2 ==> 2 e=10 249095059a4SDave May 2 ==> 3 e=11 250095059a4SDave May 251095059a4SDave May 3 ==> 0 e=12 252095059a4SDave May 3 ==> 1 e=13 253095059a4SDave May 3 ==> 2 e=14 254095059a4SDave May 3 ==> 3 e=15 255095059a4SDave May 256095059a4SDave May If we require that proc A sends to proc B, then the SEND tag index will be given by 257095059a4SDave May N * rank(A) + rank(B) + offset 258095059a4SDave May If we require that proc A will receive from proc B, then the RECV tag index will be given by 259095059a4SDave May N * rank(B) + rank(A) + offset 260095059a4SDave May 261095059a4SDave May */ 262*d71ae5a4SJacob Faibussowitsch static void _get_tags(PetscInt counter, PetscMPIInt N, PetscMPIInt r0, PetscMPIInt r1, PetscMPIInt *_st, PetscMPIInt *_rt) 263*d71ae5a4SJacob Faibussowitsch { 264095059a4SDave May PetscMPIInt st, rt; 265095059a4SDave May 266095059a4SDave May st = N * r0 + r1 + N * N * counter; 267095059a4SDave May rt = N * r1 + r0 + N * N * counter; 268095059a4SDave May *_st = st; 269095059a4SDave May *_rt = rt; 270095059a4SDave May } 271095059a4SDave May 272095059a4SDave May /* 273095059a4SDave May Makes the communication map symmetric 274095059a4SDave May */ 275*d71ae5a4SJacob Faibussowitsch PetscErrorCode _DMSwarmDataExCompleteCommunicationMap(MPI_Comm comm, PetscMPIInt n, PetscMPIInt proc_neighbours[], PetscMPIInt *n_new, PetscMPIInt **proc_neighbours_new) 276*d71ae5a4SJacob Faibussowitsch { 277dcf43ee8SDave May Mat A; 278095059a4SDave May PetscInt i, j, nc; 279095059a4SDave May PetscInt n_, *proc_neighbours_; 280e4fbd051SBarry Smith PetscInt rank_; 281e4fbd051SBarry Smith PetscMPIInt size, rank; 282095059a4SDave May PetscScalar *vals; 283095059a4SDave May const PetscInt *cols; 284095059a4SDave May const PetscScalar *red_vals; 285095059a4SDave May PetscMPIInt _n_new, *_proc_neighbours_new; 286095059a4SDave May 287095059a4SDave May PetscFunctionBegin; 288095059a4SDave May n_ = n; 2899566063dSJacob Faibussowitsch PetscCall(PetscMalloc(sizeof(PetscInt) * n_, &proc_neighbours_)); 290ad540459SPierre Jolivet for (i = 0; i < n_; ++i) proc_neighbours_[i] = proc_neighbours[i]; 2919566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(comm, &size)); 2929566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(comm, &rank)); 293e4fbd051SBarry Smith rank_ = rank; 294095059a4SDave May 2959566063dSJacob Faibussowitsch PetscCall(MatCreate(comm, &A)); 2969566063dSJacob Faibussowitsch PetscCall(MatSetSizes(A, PETSC_DECIDE, PETSC_DECIDE, size, size)); 2979566063dSJacob Faibussowitsch PetscCall(MatSetType(A, MATAIJ)); 2989566063dSJacob Faibussowitsch PetscCall(MatSeqAIJSetPreallocation(A, 1, NULL)); 2999566063dSJacob Faibussowitsch PetscCall(MatMPIAIJSetPreallocation(A, n_, NULL, n_, NULL)); 3009566063dSJacob Faibussowitsch PetscCall(MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE)); 301095059a4SDave May /* Build original map */ 3029566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(n_, &vals)); 303ad540459SPierre Jolivet for (i = 0; i < n_; ++i) vals[i] = 1.0; 3049566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &rank_, n_, proc_neighbours_, vals, INSERT_VALUES)); 3059566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FLUSH_ASSEMBLY)); 3069566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FLUSH_ASSEMBLY)); 307095059a4SDave May /* Now force all other connections if they are not already there */ 308095059a4SDave May /* It's more efficient to do them all at once */ 309ad540459SPierre Jolivet for (i = 0; i < n_; ++i) vals[i] = 2.0; 3109566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, n_, proc_neighbours_, 1, &rank_, vals, INSERT_VALUES)); 3119566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 3129566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 3136275818cSDave May /* 3149566063dSJacob Faibussowitsch PetscCall(PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO)); 3159566063dSJacob Faibussowitsch PetscCall(MatView(A,PETSC_VIEWER_STDOUT_WORLD)); 3169566063dSJacob Faibussowitsch PetscCall(PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD)); 3176275818cSDave May */ 318095059a4SDave May if ((n_new != NULL) && (proc_neighbours_new != NULL)) { 3199566063dSJacob Faibussowitsch PetscCall(MatGetRow(A, rank_, &nc, &cols, &red_vals)); 320095059a4SDave May _n_new = (PetscMPIInt)nc; 3219566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(_n_new, &_proc_neighbours_new)); 322ad540459SPierre Jolivet for (j = 0; j < nc; ++j) _proc_neighbours_new[j] = (PetscMPIInt)cols[j]; 3239566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A, rank_, &nc, &cols, &red_vals)); 324095059a4SDave May *n_new = (PetscMPIInt)_n_new; 325095059a4SDave May *proc_neighbours_new = (PetscMPIInt *)_proc_neighbours_new; 326095059a4SDave May } 3279566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 3289566063dSJacob Faibussowitsch PetscCall(PetscFree(vals)); 3299566063dSJacob Faibussowitsch PetscCall(PetscFree(proc_neighbours_)); 3309566063dSJacob Faibussowitsch PetscCallMPI(MPI_Barrier(comm)); 331095059a4SDave May PetscFunctionReturn(0); 332095059a4SDave May } 333095059a4SDave May 334*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExTopologyFinalize(DMSwarmDataEx d) 335*d71ae5a4SJacob Faibussowitsch { 3365627991aSBarry Smith PetscMPIInt symm_nn, *symm_procs, r0, n, st, rt, size; 337095059a4SDave May 338095059a4SDave May PetscFunctionBegin; 33908401ef6SPierre Jolivet PetscCheck(d->topology_status == DEOBJECT_INITIALIZED, d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be initialised. Call DMSwarmDataExTopologyInitialize() first"); 3402064fc68SDave May 3419566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerTopologySetup, 0, 0, 0, 0)); 342a5b23f4aSJose E. Roman /* given information about all my neighbours, make map symmetric */ 3439566063dSJacob Faibussowitsch PetscCall(_DMSwarmDataExCompleteCommunicationMap(d->comm, d->n_neighbour_procs, d->neighbour_procs, &symm_nn, &symm_procs)); 344095059a4SDave May /* update my arrays */ 3459566063dSJacob Faibussowitsch PetscCall(PetscFree(d->neighbour_procs)); 346095059a4SDave May d->n_neighbour_procs = symm_nn; 347095059a4SDave May d->neighbour_procs = symm_procs; 348095059a4SDave May /* allocates memory */ 3499566063dSJacob Faibussowitsch if (!d->messages_to_be_sent) PetscCall(PetscMalloc1(d->n_neighbour_procs + 1, &d->messages_to_be_sent)); 3509566063dSJacob Faibussowitsch if (!d->message_offsets) PetscCall(PetscMalloc1(d->n_neighbour_procs + 1, &d->message_offsets)); 3519566063dSJacob Faibussowitsch if (!d->messages_to_be_recvieved) PetscCall(PetscMalloc1(d->n_neighbour_procs + 1, &d->messages_to_be_recvieved)); 3529566063dSJacob Faibussowitsch if (!d->pack_cnt) PetscCall(PetscMalloc(sizeof(PetscInt) * d->n_neighbour_procs, &d->pack_cnt)); 3539566063dSJacob Faibussowitsch if (!d->_stats) PetscCall(PetscMalloc(sizeof(MPI_Status) * 2 * d->n_neighbour_procs, &d->_stats)); 3549566063dSJacob Faibussowitsch if (!d->_requests) PetscCall(PetscMalloc(sizeof(MPI_Request) * 2 * d->n_neighbour_procs, &d->_requests)); 3559566063dSJacob Faibussowitsch if (!d->send_tags) PetscCall(PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->send_tags)); 3569566063dSJacob Faibussowitsch if (!d->recv_tags) PetscCall(PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->recv_tags)); 357095059a4SDave May /* compute message tags */ 3589566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_size(d->comm, &size)); 359095059a4SDave May r0 = d->rank; 360521f74f9SMatthew G. Knepley for (n = 0; n < d->n_neighbour_procs; ++n) { 361095059a4SDave May PetscMPIInt r1 = d->neighbour_procs[n]; 362095059a4SDave May 363d7d19db6SBarry Smith _get_tags(d->instance, size, r0, r1, &st, &rt); 364095059a4SDave May d->send_tags[n] = (int)st; 365095059a4SDave May d->recv_tags[n] = (int)rt; 366095059a4SDave May } 367095059a4SDave May d->topology_status = DEOBJECT_FINALIZED; 3689566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerTopologySetup, 0, 0, 0, 0)); 369095059a4SDave May PetscFunctionReturn(0); 370095059a4SDave May } 371095059a4SDave May 372095059a4SDave May /* === Phase B === */ 373*d71ae5a4SJacob Faibussowitsch PetscErrorCode _DMSwarmDataExConvertProcIdToLocalIndex(DMSwarmDataEx de, PetscMPIInt proc_id, PetscMPIInt *local) 374*d71ae5a4SJacob Faibussowitsch { 375095059a4SDave May PetscMPIInt i, np; 376095059a4SDave May 377095059a4SDave May PetscFunctionBegin; 378095059a4SDave May np = de->n_neighbour_procs; 379095059a4SDave May *local = -1; 380521f74f9SMatthew G. Knepley for (i = 0; i < np; ++i) { 381095059a4SDave May if (proc_id == de->neighbour_procs[i]) { 382095059a4SDave May *local = i; 383095059a4SDave May break; 384095059a4SDave May } 385095059a4SDave May } 386095059a4SDave May PetscFunctionReturn(0); 387095059a4SDave May } 388095059a4SDave May 389*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExInitializeSendCount(DMSwarmDataEx de) 390*d71ae5a4SJacob Faibussowitsch { 391095059a4SDave May PetscMPIInt i; 392095059a4SDave May 393095059a4SDave May PetscFunctionBegin; 39408401ef6SPierre Jolivet PetscCheck(de->topology_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Topology not finalized"); 3959566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerSendCount, 0, 0, 0, 0)); 396095059a4SDave May de->message_lengths_status = DEOBJECT_INITIALIZED; 397ad540459SPierre Jolivet for (i = 0; i < de->n_neighbour_procs; ++i) de->messages_to_be_sent[i] = 0; 398095059a4SDave May PetscFunctionReturn(0); 399095059a4SDave May } 400095059a4SDave May 401095059a4SDave May /* 402095059a4SDave May 1) only allows counters to be set on neighbouring cpus 403095059a4SDave May */ 404*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExAddToSendCount(DMSwarmDataEx de, const PetscMPIInt proc_id, const PetscInt count) 405*d71ae5a4SJacob Faibussowitsch { 406095059a4SDave May PetscMPIInt local_val; 407095059a4SDave May 408095059a4SDave May PetscFunctionBegin; 40908401ef6SPierre Jolivet PetscCheck(de->message_lengths_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths have been defined. To modify these call DMSwarmDataExInitializeSendCount() first"); 410f7d195e4SLawrence Mitchell PetscCheck(de->message_lengths_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DMSwarmDataExInitializeSendCount() first"); 4112064fc68SDave May 4129566063dSJacob Faibussowitsch PetscCall(_DMSwarmDataExConvertProcIdToLocalIndex(de, proc_id, &local_val)); 41308401ef6SPierre Jolivet PetscCheck(local_val != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Proc %d is not a valid neighbour rank", (int)proc_id); 4142064fc68SDave May 415095059a4SDave May de->messages_to_be_sent[local_val] = de->messages_to_be_sent[local_val] + count; 416095059a4SDave May PetscFunctionReturn(0); 417095059a4SDave May } 418095059a4SDave May 419*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExFinalizeSendCount(DMSwarmDataEx de) 420*d71ae5a4SJacob Faibussowitsch { 421095059a4SDave May PetscFunctionBegin; 42208401ef6SPierre Jolivet PetscCheck(de->message_lengths_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DMSwarmDataExInitializeSendCount() first"); 4232064fc68SDave May 424095059a4SDave May de->message_lengths_status = DEOBJECT_FINALIZED; 4259566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerSendCount, 0, 0, 0, 0)); 426095059a4SDave May PetscFunctionReturn(0); 427095059a4SDave May } 428095059a4SDave May 429095059a4SDave May /* === Phase C === */ 430095059a4SDave May /* 4315627991aSBarry Smith zero out all send counts 4325627991aSBarry Smith free send and recv buffers 4335627991aSBarry Smith zeros out message length 4345627991aSBarry Smith zeros out all counters 4355627991aSBarry Smith zero out packed data counters 436095059a4SDave May */ 437*d71ae5a4SJacob Faibussowitsch PetscErrorCode _DMSwarmDataExInitializeTmpStorage(DMSwarmDataEx de) 438*d71ae5a4SJacob Faibussowitsch { 439095059a4SDave May PetscMPIInt i, np; 440095059a4SDave May 441095059a4SDave May PetscFunctionBegin; 442095059a4SDave May np = de->n_neighbour_procs; 443521f74f9SMatthew G. Knepley for (i = 0; i < np; ++i) { 444095059a4SDave May /* de->messages_to_be_sent[i] = -1; */ 445095059a4SDave May de->messages_to_be_recvieved[i] = -1; 446095059a4SDave May } 4479566063dSJacob Faibussowitsch PetscCall(PetscFree(de->send_message)); 4489566063dSJacob Faibussowitsch PetscCall(PetscFree(de->recv_message)); 449095059a4SDave May PetscFunctionReturn(0); 450095059a4SDave May } 451095059a4SDave May 452095059a4SDave May /* 4535627991aSBarry Smith Zeros out pack data counters 4545627991aSBarry Smith Ensures mesaage length is set 4555627991aSBarry Smith Checks send counts properly initialized 4565627991aSBarry Smith allocates space for pack data 457095059a4SDave May */ 458*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExPackInitialize(DMSwarmDataEx de, size_t unit_message_size) 459*d71ae5a4SJacob Faibussowitsch { 460095059a4SDave May PetscMPIInt i, np; 461095059a4SDave May PetscInt total; 462095059a4SDave May 463095059a4SDave May PetscFunctionBegin; 46408401ef6SPierre Jolivet PetscCheck(de->topology_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Topology not finalized"); 46508401ef6SPierre Jolivet PetscCheck(de->message_lengths_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths not finalized"); 4669566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerPack, 0, 0, 0, 0)); 467095059a4SDave May de->packer_status = DEOBJECT_INITIALIZED; 4689566063dSJacob Faibussowitsch PetscCall(_DMSwarmDataExInitializeTmpStorage(de)); 469095059a4SDave May np = de->n_neighbour_procs; 470095059a4SDave May de->unit_message_size = unit_message_size; 471095059a4SDave May total = 0; 472521f74f9SMatthew G. Knepley for (i = 0; i < np; ++i) { 473095059a4SDave May if (de->messages_to_be_sent[i] == -1) { 474095059a4SDave May PetscMPIInt proc_neighour = de->neighbour_procs[i]; 47598921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ORDER, "Messages_to_be_sent[neighbour_proc=%d] is un-initialised. Call DMSwarmDataExSetSendCount() first", (int)proc_neighour); 476095059a4SDave May } 477095059a4SDave May total = total + de->messages_to_be_sent[i]; 478095059a4SDave May } 479095059a4SDave May /* create space for the data to be sent */ 4809566063dSJacob Faibussowitsch PetscCall(PetscMalloc(unit_message_size * (total + 1), &de->send_message)); 481095059a4SDave May /* initialize memory */ 4829566063dSJacob Faibussowitsch PetscCall(PetscMemzero(de->send_message, unit_message_size * (total + 1))); 483095059a4SDave May /* set total items to send */ 484095059a4SDave May de->send_message_length = total; 485095059a4SDave May de->message_offsets[0] = 0; 486095059a4SDave May total = de->messages_to_be_sent[0]; 487521f74f9SMatthew G. Knepley for (i = 1; i < np; ++i) { 488095059a4SDave May de->message_offsets[i] = total; 489095059a4SDave May total = total + de->messages_to_be_sent[i]; 490095059a4SDave May } 491095059a4SDave May /* init the packer counters */ 492095059a4SDave May de->total_pack_cnt = 0; 493ad540459SPierre Jolivet for (i = 0; i < np; ++i) de->pack_cnt[i] = 0; 494095059a4SDave May PetscFunctionReturn(0); 495095059a4SDave May } 496095059a4SDave May 497095059a4SDave May /* 4985627991aSBarry Smith Ensures data gets been packed appropriately and no overlaps occur 499095059a4SDave May */ 500*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExPackData(DMSwarmDataEx de, PetscMPIInt proc_id, PetscInt n, void *data) 501*d71ae5a4SJacob Faibussowitsch { 502095059a4SDave May PetscMPIInt local; 503095059a4SDave May PetscInt insert_location; 504095059a4SDave May void *dest; 505095059a4SDave May 506095059a4SDave May PetscFunctionBegin; 50708401ef6SPierre Jolivet PetscCheck(de->packer_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Packed data have been defined. To modify these call DMSwarmDataExInitializeSendCount(), DMSwarmDataExAddToSendCount(), DMSwarmDataExPackInitialize() first"); 508f7d195e4SLawrence Mitchell PetscCheck(de->packer_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Packed data must be defined. Call DMSwarmDataExInitializeSendCount(), DMSwarmDataExAddToSendCount(), DMSwarmDataExPackInitialize() first"); 5092064fc68SDave May 51028b400f6SJacob Faibussowitsch PetscCheck(de->send_message, de->comm, PETSC_ERR_ORDER, "send_message is not initialized. Call DMSwarmDataExPackInitialize() first"); 5119566063dSJacob Faibussowitsch PetscCall(_DMSwarmDataExConvertProcIdToLocalIndex(de, proc_id, &local)); 51208401ef6SPierre Jolivet PetscCheck(local != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "proc_id %d is not registered neighbour", (int)proc_id); 5139371c9d4SSatish Balay PetscCheck(n + de->pack_cnt[local] <= de->messages_to_be_sent[local], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to pack too many entries to be sent to proc %d. Space requested = %" PetscInt_FMT ": Attempt to insert %" PetscInt_FMT, (int)proc_id, de->messages_to_be_sent[local], n + de->pack_cnt[local]); 5142064fc68SDave May 515095059a4SDave May /* copy memory */ 516095059a4SDave May insert_location = de->message_offsets[local] + de->pack_cnt[local]; 517095059a4SDave May dest = ((char *)de->send_message) + de->unit_message_size * insert_location; 5189566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(dest, data, de->unit_message_size * n)); 519095059a4SDave May /* increment counter */ 520095059a4SDave May de->pack_cnt[local] = de->pack_cnt[local] + n; 521095059a4SDave May PetscFunctionReturn(0); 522095059a4SDave May } 523095059a4SDave May 524095059a4SDave May /* 525095059a4SDave May *) Ensures all data has been packed 526095059a4SDave May */ 527*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExPackFinalize(DMSwarmDataEx de) 528*d71ae5a4SJacob Faibussowitsch { 529095059a4SDave May PetscMPIInt i, np; 530095059a4SDave May PetscInt total; 531095059a4SDave May 532095059a4SDave May PetscFunctionBegin; 53308401ef6SPierre Jolivet PetscCheck(de->packer_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Packer has not been initialized. Must call DMSwarmDataExPackInitialize() first."); 534095059a4SDave May np = de->n_neighbour_procs; 535521f74f9SMatthew G. Knepley for (i = 0; i < np; ++i) { 5369371c9d4SSatish Balay PetscCheck(de->pack_cnt[i] == de->messages_to_be_sent[i], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not all messages for neighbour[%d] have been packed. Expected %" PetscInt_FMT " : Inserted %" PetscInt_FMT, (int)de->neighbour_procs[i], de->messages_to_be_sent[i], de->pack_cnt[i]); 537095059a4SDave May } 538095059a4SDave May /* init */ 539ad540459SPierre Jolivet for (i = 0; i < np; ++i) de->messages_to_be_recvieved[i] = -1; 540095059a4SDave May /* figure out the recv counts here */ 54148a46eb9SPierre Jolivet for (i = 0; i < np; ++i) PetscCallMPI(MPI_Isend(&de->messages_to_be_sent[i], 1, MPIU_INT, de->neighbour_procs[i], de->send_tags[i], de->comm, &de->_requests[i])); 54248a46eb9SPierre Jolivet for (i = 0; i < np; ++i) PetscCallMPI(MPI_Irecv(&de->messages_to_be_recvieved[i], 1, MPIU_INT, de->neighbour_procs[i], de->recv_tags[i], de->comm, &de->_requests[np + i])); 5439566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(2 * np, de->_requests, de->_stats)); 544095059a4SDave May /* create space for the data to be recvieved */ 545095059a4SDave May total = 0; 546ad540459SPierre Jolivet for (i = 0; i < np; ++i) total = total + de->messages_to_be_recvieved[i]; 5479566063dSJacob Faibussowitsch PetscCall(PetscMalloc(de->unit_message_size * (total + 1), &de->recv_message)); 548095059a4SDave May /* initialize memory */ 5499566063dSJacob Faibussowitsch PetscCall(PetscMemzero(de->recv_message, de->unit_message_size * (total + 1))); 5502d4ee042Sprj- /* set total items to receive */ 551095059a4SDave May de->recv_message_length = total; 552095059a4SDave May de->packer_status = DEOBJECT_FINALIZED; 553095059a4SDave May de->communication_status = DEOBJECT_INITIALIZED; 5549566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerPack, 0, 0, 0, 0)); 555095059a4SDave May PetscFunctionReturn(0); 556095059a4SDave May } 557095059a4SDave May 5585627991aSBarry Smith /* do the actual message passing */ 559*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExBegin(DMSwarmDataEx de) 560*d71ae5a4SJacob Faibussowitsch { 561095059a4SDave May PetscMPIInt i, np; 562095059a4SDave May void *dest; 563095059a4SDave May PetscInt length; 564095059a4SDave May 565095059a4SDave May PetscFunctionBegin; 56608401ef6SPierre Jolivet PetscCheck(de->topology_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Topology not finalized"); 56708401ef6SPierre Jolivet PetscCheck(de->message_lengths_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths not finalized"); 56808401ef6SPierre Jolivet PetscCheck(de->packer_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Packer not finalized"); 56908401ef6SPierre Jolivet PetscCheck(de->communication_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Communication has already been finalized. Must call DMSwarmDataExInitialize() first."); 57028b400f6SJacob Faibussowitsch PetscCheck(de->recv_message, de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DMSwarmDataExPackFinalize() first"); 5719566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerBegin, 0, 0, 0, 0)); 572095059a4SDave May np = de->n_neighbour_procs; 573095059a4SDave May /* == NON BLOCKING == */ 574521f74f9SMatthew G. Knepley for (i = 0; i < np; ++i) { 575095059a4SDave May length = de->messages_to_be_sent[i] * de->unit_message_size; 576095059a4SDave May dest = ((char *)de->send_message) + de->unit_message_size * de->message_offsets[i]; 5779566063dSJacob Faibussowitsch PetscCallMPI(MPI_Isend(dest, length, MPI_CHAR, de->neighbour_procs[i], de->send_tags[i], de->comm, &de->_requests[i])); 578095059a4SDave May } 5799566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerBegin, 0, 0, 0, 0)); 580095059a4SDave May PetscFunctionReturn(0); 581095059a4SDave May } 582095059a4SDave May 583095059a4SDave May /* do the actual message passing now */ 584*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExEnd(DMSwarmDataEx de) 585*d71ae5a4SJacob Faibussowitsch { 586095059a4SDave May PetscMPIInt i, np; 587095059a4SDave May PetscInt total; 588095059a4SDave May PetscInt *message_recv_offsets; 589095059a4SDave May void *dest; 590095059a4SDave May PetscInt length; 591095059a4SDave May 592095059a4SDave May PetscFunctionBegin; 59308401ef6SPierre Jolivet PetscCheck(de->communication_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Communication has not been initialized. Must call DMSwarmDataExInitialize() first."); 59428b400f6SJacob Faibussowitsch PetscCheck(de->recv_message, de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DMSwarmDataExPackFinalize() first"); 5959566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerEnd, 0, 0, 0, 0)); 596095059a4SDave May np = de->n_neighbour_procs; 5979566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(np + 1, &message_recv_offsets)); 598095059a4SDave May message_recv_offsets[0] = 0; 599095059a4SDave May total = de->messages_to_be_recvieved[0]; 600521f74f9SMatthew G. Knepley for (i = 1; i < np; ++i) { 601095059a4SDave May message_recv_offsets[i] = total; 602095059a4SDave May total = total + de->messages_to_be_recvieved[i]; 603095059a4SDave May } 604095059a4SDave May /* == NON BLOCKING == */ 605521f74f9SMatthew G. Knepley for (i = 0; i < np; ++i) { 606095059a4SDave May length = de->messages_to_be_recvieved[i] * de->unit_message_size; 607095059a4SDave May dest = ((char *)de->recv_message) + de->unit_message_size * message_recv_offsets[i]; 6089566063dSJacob Faibussowitsch PetscCallMPI(MPI_Irecv(dest, length, MPI_CHAR, de->neighbour_procs[i], de->recv_tags[i], de->comm, &de->_requests[np + i])); 609095059a4SDave May } 6109566063dSJacob Faibussowitsch PetscCallMPI(MPI_Waitall(2 * np, de->_requests, de->_stats)); 6119566063dSJacob Faibussowitsch PetscCall(PetscFree(message_recv_offsets)); 612095059a4SDave May de->communication_status = DEOBJECT_FINALIZED; 6139566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerEnd, 0, 0, 0, 0)); 614095059a4SDave May PetscFunctionReturn(0); 615095059a4SDave May } 616095059a4SDave May 617*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExGetSendData(DMSwarmDataEx de, PetscInt *length, void **send) 618*d71ae5a4SJacob Faibussowitsch { 619095059a4SDave May PetscFunctionBegin; 62008401ef6SPierre Jolivet PetscCheck(de->packer_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being packed."); 621095059a4SDave May *length = de->send_message_length; 622095059a4SDave May *send = de->send_message; 623095059a4SDave May PetscFunctionReturn(0); 624095059a4SDave May } 625095059a4SDave May 626*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExGetRecvData(DMSwarmDataEx de, PetscInt *length, void **recv) 627*d71ae5a4SJacob Faibussowitsch { 628095059a4SDave May PetscFunctionBegin; 62908401ef6SPierre Jolivet PetscCheck(de->communication_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being sent."); 630095059a4SDave May *length = de->recv_message_length; 631095059a4SDave May *recv = de->recv_message; 632095059a4SDave May PetscFunctionReturn(0); 633095059a4SDave May } 634095059a4SDave May 635*d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExTopologyGetNeighbours(DMSwarmDataEx de, PetscMPIInt *n, PetscMPIInt *neigh[]) 636*d71ae5a4SJacob Faibussowitsch { 637095059a4SDave May PetscFunctionBegin; 638ad540459SPierre Jolivet if (n) *n = de->n_neighbour_procs; 639ad540459SPierre Jolivet if (neigh) *neigh = de->neighbour_procs; 640095059a4SDave May PetscFunctionReturn(0); 641095059a4SDave May } 642