xref: /petsc/src/dm/impls/swarm/data_ex.c (revision 48a46eb9bd028bec07ec0f396b1a3abb43f14558)
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 
849371c9d4SSatish Balay PetscErrorCode DMSwarmDataExCreate(MPI_Comm comm, const PetscInt count, DMSwarmDataEx *ex) {
8577048351SPatrick Sanan   DMSwarmDataEx d;
86095059a4SDave May 
87521f74f9SMatthew G. Knepley   PetscFunctionBegin;
889566063dSJacob Faibussowitsch   PetscCall(PetscNew(&d));
899566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_dup(comm, &d->comm));
909566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(d->comm, &d->rank));
91095059a4SDave May 
92095059a4SDave May   d->instance = count;
93095059a4SDave May 
94095059a4SDave May   d->topology_status        = DEOBJECT_STATE_UNKNOWN;
95095059a4SDave May   d->message_lengths_status = DEOBJECT_STATE_UNKNOWN;
96095059a4SDave May   d->packer_status          = DEOBJECT_STATE_UNKNOWN;
97095059a4SDave May   d->communication_status   = DEOBJECT_STATE_UNKNOWN;
98095059a4SDave May 
99095059a4SDave May   d->n_neighbour_procs = -1;
100095059a4SDave May   d->neighbour_procs   = NULL;
101095059a4SDave May 
102095059a4SDave May   d->messages_to_be_sent      = NULL;
103095059a4SDave May   d->message_offsets          = NULL;
104095059a4SDave May   d->messages_to_be_recvieved = NULL;
105095059a4SDave May 
10678c64234SJose E. Roman   d->unit_message_size   = (size_t)-1;
107095059a4SDave May   d->send_message        = NULL;
108095059a4SDave May   d->send_message_length = -1;
109095059a4SDave May   d->recv_message        = NULL;
110095059a4SDave May   d->recv_message_length = -1;
111095059a4SDave May   d->total_pack_cnt      = -1;
112095059a4SDave May   d->pack_cnt            = NULL;
113095059a4SDave May 
114095059a4SDave May   d->send_tags = NULL;
115095059a4SDave May   d->recv_tags = NULL;
116095059a4SDave May 
117095059a4SDave May   d->_stats    = NULL;
118095059a4SDave May   d->_requests = NULL;
119521f74f9SMatthew G. Knepley   *ex          = d;
120521f74f9SMatthew G. Knepley   PetscFunctionReturn(0);
121095059a4SDave May }
122095059a4SDave May 
123298827fbSBarry Smith /*
1249dddd249SSatish Balay     This code is horrible, who let it get into main.
125298827fbSBarry Smith 
126298827fbSBarry Smith     Should be printing to a viewer, should not be using PETSC_COMM_WORLD
127298827fbSBarry Smith 
128298827fbSBarry Smith */
1299371c9d4SSatish Balay PetscErrorCode DMSwarmDataExView(DMSwarmDataEx d) {
130095059a4SDave May   PetscMPIInt p;
131095059a4SDave May 
132095059a4SDave May   PetscFunctionBegin;
13363a3b9bcSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "DMSwarmDataEx: instance=%" PetscInt_FMT "\n", d->instance));
1349566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "  topology status:        %s \n", status_names[d->topology_status]));
1359566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "  message lengths status: %s \n", status_names[d->message_lengths_status]));
1369566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "  packer status status:   %s \n", status_names[d->packer_status]));
1379566063dSJacob Faibussowitsch   PetscCall(PetscPrintf(PETSC_COMM_WORLD, "  communication status:   %s \n", status_names[d->communication_status]));
138095059a4SDave May 
139095059a4SDave May   if (d->topology_status == DEOBJECT_FINALIZED) {
1409566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "  Topology:\n"));
1419566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, "    [%d] neighbours: %d \n", d->rank, d->n_neighbour_procs));
142*48a46eb9SPierre 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]));
1439566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, stdout));
144095059a4SDave May   }
145298827fbSBarry Smith 
146095059a4SDave May   if (d->message_lengths_status == DEOBJECT_FINALIZED) {
1479566063dSJacob Faibussowitsch     PetscCall(PetscPrintf(PETSC_COMM_WORLD, "  Message lengths:\n"));
1489566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedPrintf(PETSC_COMM_WORLD, "    [%d] atomic size: %ld \n", d->rank, (long int)d->unit_message_size));
149095059a4SDave May     for (p = 0; p < d->n_neighbour_procs; p++) {
15063a3b9bcSJacob 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]));
151095059a4SDave May     }
152095059a4SDave May     for (p = 0; p < d->n_neighbour_procs; p++) {
15363a3b9bcSJacob 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]));
154095059a4SDave May     }
1559566063dSJacob Faibussowitsch     PetscCall(PetscSynchronizedFlush(PETSC_COMM_WORLD, stdout));
156095059a4SDave May   }
157521f74f9SMatthew G. Knepley   if (d->packer_status == DEOBJECT_FINALIZED) { }
158521f74f9SMatthew G. Knepley   if (d->communication_status == DEOBJECT_FINALIZED) { }
159095059a4SDave May   PetscFunctionReturn(0);
160095059a4SDave May }
161095059a4SDave May 
1629371c9d4SSatish Balay PetscErrorCode DMSwarmDataExDestroy(DMSwarmDataEx d) {
163095059a4SDave May   PetscFunctionBegin;
1649566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_free(&d->comm));
1659566063dSJacob Faibussowitsch   if (d->neighbour_procs) PetscCall(PetscFree(d->neighbour_procs));
1669566063dSJacob Faibussowitsch   if (d->messages_to_be_sent) PetscCall(PetscFree(d->messages_to_be_sent));
1679566063dSJacob Faibussowitsch   if (d->message_offsets) PetscCall(PetscFree(d->message_offsets));
1689566063dSJacob Faibussowitsch   if (d->messages_to_be_recvieved) PetscCall(PetscFree(d->messages_to_be_recvieved));
1699566063dSJacob Faibussowitsch   if (d->send_message) PetscCall(PetscFree(d->send_message));
1709566063dSJacob Faibussowitsch   if (d->recv_message) PetscCall(PetscFree(d->recv_message));
1719566063dSJacob Faibussowitsch   if (d->pack_cnt) PetscCall(PetscFree(d->pack_cnt));
1729566063dSJacob Faibussowitsch   if (d->send_tags) PetscCall(PetscFree(d->send_tags));
1739566063dSJacob Faibussowitsch   if (d->recv_tags) PetscCall(PetscFree(d->recv_tags));
1749566063dSJacob Faibussowitsch   if (d->_stats) PetscCall(PetscFree(d->_stats));
1759566063dSJacob Faibussowitsch   if (d->_requests) PetscCall(PetscFree(d->_requests));
1769566063dSJacob Faibussowitsch   PetscCall(PetscFree(d));
177095059a4SDave May   PetscFunctionReturn(0);
178095059a4SDave May }
179095059a4SDave May 
180095059a4SDave May /* === Phase A === */
181095059a4SDave May 
1829371c9d4SSatish Balay PetscErrorCode DMSwarmDataExTopologyInitialize(DMSwarmDataEx d) {
183095059a4SDave May   PetscFunctionBegin;
184095059a4SDave May   d->topology_status   = DEOBJECT_INITIALIZED;
185095059a4SDave May   d->n_neighbour_procs = 0;
1869566063dSJacob Faibussowitsch   PetscCall(PetscFree(d->neighbour_procs));
1879566063dSJacob Faibussowitsch   PetscCall(PetscFree(d->messages_to_be_sent));
1889566063dSJacob Faibussowitsch   PetscCall(PetscFree(d->message_offsets));
1899566063dSJacob Faibussowitsch   PetscCall(PetscFree(d->messages_to_be_recvieved));
1909566063dSJacob Faibussowitsch   PetscCall(PetscFree(d->pack_cnt));
1919566063dSJacob Faibussowitsch   PetscCall(PetscFree(d->send_tags));
1929566063dSJacob Faibussowitsch   PetscCall(PetscFree(d->recv_tags));
193095059a4SDave May   PetscFunctionReturn(0);
194095059a4SDave May }
195095059a4SDave May 
1969371c9d4SSatish Balay PetscErrorCode DMSwarmDataExTopologyAddNeighbour(DMSwarmDataEx d, const PetscMPIInt proc_id) {
197095059a4SDave May   PetscMPIInt n, found;
198d7d19db6SBarry Smith   PetscMPIInt size;
199095059a4SDave May 
200095059a4SDave May   PetscFunctionBegin;
20108401ef6SPierre Jolivet   PetscCheck(d->topology_status != DEOBJECT_FINALIZED, d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology has been finalized. To modify or update call DMSwarmDataExTopologyInitialize() first");
202f7d195e4SLawrence Mitchell   PetscCheck(d->topology_status == DEOBJECT_INITIALIZED, d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be initialised. Call DMSwarmDataExTopologyInitialize() first");
2032064fc68SDave May 
204095059a4SDave May   /* error on negative entries */
20508401ef6SPierre Jolivet   PetscCheck(proc_id >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Trying to set proc neighbour with a rank < 0");
206095059a4SDave May   /* error on ranks larger than number of procs in communicator */
2079566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(d->comm, &size));
20808401ef6SPierre 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);
2099566063dSJacob Faibussowitsch   if (d->n_neighbour_procs == 0) PetscCall(PetscMalloc1(1, &d->neighbour_procs));
210095059a4SDave May   /* check for proc_id */
211095059a4SDave May   found = 0;
212095059a4SDave May   for (n = 0; n < d->n_neighbour_procs; n++) {
2139371c9d4SSatish Balay     if (d->neighbour_procs[n] == proc_id) { found = 1; }
214095059a4SDave May   }
215095059a4SDave May   if (found == 0) { /* add it to list */
2169566063dSJacob Faibussowitsch     PetscCall(PetscRealloc(sizeof(PetscMPIInt) * (d->n_neighbour_procs + 1), &d->neighbour_procs));
217095059a4SDave May     d->neighbour_procs[d->n_neighbour_procs] = proc_id;
218095059a4SDave May     d->n_neighbour_procs++;
219095059a4SDave May   }
220095059a4SDave May   PetscFunctionReturn(0);
221095059a4SDave May }
222095059a4SDave May 
223095059a4SDave May /*
224095059a4SDave May counter: the index of the communication object
225095059a4SDave May N: the number of processors
226095059a4SDave May r0: rank of sender
227095059a4SDave May r1: rank of receiver
228095059a4SDave May 
229095059a4SDave May procs = { 0, 1, 2, 3 }
230095059a4SDave May 
231095059a4SDave May 0 ==> 0         e=0
232095059a4SDave May 0 ==> 1         e=1
233095059a4SDave May 0 ==> 2         e=2
234095059a4SDave May 0 ==> 3         e=3
235095059a4SDave May 
236095059a4SDave May 1 ==> 0         e=4
237095059a4SDave May 1 ==> 1         e=5
238095059a4SDave May 1 ==> 2         e=6
239095059a4SDave May 1 ==> 3         e=7
240095059a4SDave May 
241095059a4SDave May 2 ==> 0         e=8
242095059a4SDave May 2 ==> 1         e=9
243095059a4SDave May 2 ==> 2         e=10
244095059a4SDave May 2 ==> 3         e=11
245095059a4SDave May 
246095059a4SDave May 3 ==> 0         e=12
247095059a4SDave May 3 ==> 1         e=13
248095059a4SDave May 3 ==> 2         e=14
249095059a4SDave May 3 ==> 3         e=15
250095059a4SDave May 
251095059a4SDave May If we require that proc A sends to proc B, then the SEND tag index will be given by
252095059a4SDave May   N * rank(A) + rank(B) + offset
253095059a4SDave May If we require that proc A will receive from proc B, then the RECV tag index will be given by
254095059a4SDave May   N * rank(B) + rank(A) + offset
255095059a4SDave May 
256095059a4SDave May */
2579371c9d4SSatish Balay static void _get_tags(PetscInt counter, PetscMPIInt N, PetscMPIInt r0, PetscMPIInt r1, PetscMPIInt *_st, PetscMPIInt *_rt) {
258095059a4SDave May   PetscMPIInt st, rt;
259095059a4SDave May 
260095059a4SDave May   st   = N * r0 + r1 + N * N * counter;
261095059a4SDave May   rt   = N * r1 + r0 + N * N * counter;
262095059a4SDave May   *_st = st;
263095059a4SDave May   *_rt = rt;
264095059a4SDave May }
265095059a4SDave May 
266095059a4SDave May /*
267095059a4SDave May Makes the communication map symmetric
268095059a4SDave May */
2699371c9d4SSatish Balay PetscErrorCode _DMSwarmDataExCompleteCommunicationMap(MPI_Comm comm, PetscMPIInt n, PetscMPIInt proc_neighbours[], PetscMPIInt *n_new, PetscMPIInt **proc_neighbours_new) {
270dcf43ee8SDave May   Mat                A;
271095059a4SDave May   PetscInt           i, j, nc;
272095059a4SDave May   PetscInt           n_, *proc_neighbours_;
273e4fbd051SBarry Smith   PetscInt           rank_;
274e4fbd051SBarry Smith   PetscMPIInt        size, rank;
275095059a4SDave May   PetscScalar       *vals;
276095059a4SDave May   const PetscInt    *cols;
277095059a4SDave May   const PetscScalar *red_vals;
278095059a4SDave May   PetscMPIInt        _n_new, *_proc_neighbours_new;
279095059a4SDave May 
280095059a4SDave May   PetscFunctionBegin;
281095059a4SDave May   n_ = n;
2829566063dSJacob Faibussowitsch   PetscCall(PetscMalloc(sizeof(PetscInt) * n_, &proc_neighbours_));
2839371c9d4SSatish Balay   for (i = 0; i < n_; ++i) { proc_neighbours_[i] = proc_neighbours[i]; }
2849566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
2859566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
286e4fbd051SBarry Smith   rank_ = rank;
287095059a4SDave May 
2889566063dSJacob Faibussowitsch   PetscCall(MatCreate(comm, &A));
2899566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(A, PETSC_DECIDE, PETSC_DECIDE, size, size));
2909566063dSJacob Faibussowitsch   PetscCall(MatSetType(A, MATAIJ));
2919566063dSJacob Faibussowitsch   PetscCall(MatSeqAIJSetPreallocation(A, 1, NULL));
2929566063dSJacob Faibussowitsch   PetscCall(MatMPIAIJSetPreallocation(A, n_, NULL, n_, NULL));
2939566063dSJacob Faibussowitsch   PetscCall(MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
294095059a4SDave May   /* Build original map */
2959566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(n_, &vals));
2969371c9d4SSatish Balay   for (i = 0; i < n_; ++i) { vals[i] = 1.0; }
2979566063dSJacob Faibussowitsch   PetscCall(MatSetValues(A, 1, &rank_, n_, proc_neighbours_, vals, INSERT_VALUES));
2989566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A, MAT_FLUSH_ASSEMBLY));
2999566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A, MAT_FLUSH_ASSEMBLY));
300095059a4SDave May   /* Now force all other connections if they are not already there */
301095059a4SDave May   /* It's more efficient to do them all at once */
3029371c9d4SSatish Balay   for (i = 0; i < n_; ++i) { vals[i] = 2.0; }
3039566063dSJacob Faibussowitsch   PetscCall(MatSetValues(A, n_, proc_neighbours_, 1, &rank_, vals, INSERT_VALUES));
3049566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY));
3059566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY));
3066275818cSDave May   /*
3079566063dSJacob Faibussowitsch   PetscCall(PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO));
3089566063dSJacob Faibussowitsch   PetscCall(MatView(A,PETSC_VIEWER_STDOUT_WORLD));
3099566063dSJacob Faibussowitsch   PetscCall(PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD));
3106275818cSDave May */
311095059a4SDave May   if ((n_new != NULL) && (proc_neighbours_new != NULL)) {
3129566063dSJacob Faibussowitsch     PetscCall(MatGetRow(A, rank_, &nc, &cols, &red_vals));
313095059a4SDave May     _n_new = (PetscMPIInt)nc;
3149566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(_n_new, &_proc_neighbours_new));
3159371c9d4SSatish Balay     for (j = 0; j < nc; ++j) { _proc_neighbours_new[j] = (PetscMPIInt)cols[j]; }
3169566063dSJacob Faibussowitsch     PetscCall(MatRestoreRow(A, rank_, &nc, &cols, &red_vals));
317095059a4SDave May     *n_new               = (PetscMPIInt)_n_new;
318095059a4SDave May     *proc_neighbours_new = (PetscMPIInt *)_proc_neighbours_new;
319095059a4SDave May   }
3209566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&A));
3219566063dSJacob Faibussowitsch   PetscCall(PetscFree(vals));
3229566063dSJacob Faibussowitsch   PetscCall(PetscFree(proc_neighbours_));
3239566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Barrier(comm));
324095059a4SDave May   PetscFunctionReturn(0);
325095059a4SDave May }
326095059a4SDave May 
3279371c9d4SSatish Balay PetscErrorCode DMSwarmDataExTopologyFinalize(DMSwarmDataEx d) {
3285627991aSBarry Smith   PetscMPIInt symm_nn, *symm_procs, r0, n, st, rt, size;
329095059a4SDave May 
330095059a4SDave May   PetscFunctionBegin;
33108401ef6SPierre Jolivet   PetscCheck(d->topology_status == DEOBJECT_INITIALIZED, d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be initialised. Call DMSwarmDataExTopologyInitialize() first");
3322064fc68SDave May 
3339566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerTopologySetup, 0, 0, 0, 0));
334a5b23f4aSJose E. Roman   /* given information about all my neighbours, make map symmetric */
3359566063dSJacob Faibussowitsch   PetscCall(_DMSwarmDataExCompleteCommunicationMap(d->comm, d->n_neighbour_procs, d->neighbour_procs, &symm_nn, &symm_procs));
336095059a4SDave May   /* update my arrays */
3379566063dSJacob Faibussowitsch   PetscCall(PetscFree(d->neighbour_procs));
338095059a4SDave May   d->n_neighbour_procs = symm_nn;
339095059a4SDave May   d->neighbour_procs   = symm_procs;
340095059a4SDave May   /* allocates memory */
3419566063dSJacob Faibussowitsch   if (!d->messages_to_be_sent) PetscCall(PetscMalloc1(d->n_neighbour_procs + 1, &d->messages_to_be_sent));
3429566063dSJacob Faibussowitsch   if (!d->message_offsets) PetscCall(PetscMalloc1(d->n_neighbour_procs + 1, &d->message_offsets));
3439566063dSJacob Faibussowitsch   if (!d->messages_to_be_recvieved) PetscCall(PetscMalloc1(d->n_neighbour_procs + 1, &d->messages_to_be_recvieved));
3449566063dSJacob Faibussowitsch   if (!d->pack_cnt) PetscCall(PetscMalloc(sizeof(PetscInt) * d->n_neighbour_procs, &d->pack_cnt));
3459566063dSJacob Faibussowitsch   if (!d->_stats) PetscCall(PetscMalloc(sizeof(MPI_Status) * 2 * d->n_neighbour_procs, &d->_stats));
3469566063dSJacob Faibussowitsch   if (!d->_requests) PetscCall(PetscMalloc(sizeof(MPI_Request) * 2 * d->n_neighbour_procs, &d->_requests));
3479566063dSJacob Faibussowitsch   if (!d->send_tags) PetscCall(PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->send_tags));
3489566063dSJacob Faibussowitsch   if (!d->recv_tags) PetscCall(PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->recv_tags));
349095059a4SDave May   /* compute message tags */
3509566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(d->comm, &size));
351095059a4SDave May   r0 = d->rank;
352521f74f9SMatthew G. Knepley   for (n = 0; n < d->n_neighbour_procs; ++n) {
353095059a4SDave May     PetscMPIInt r1 = d->neighbour_procs[n];
354095059a4SDave May 
355d7d19db6SBarry Smith     _get_tags(d->instance, size, r0, r1, &st, &rt);
356095059a4SDave May     d->send_tags[n] = (int)st;
357095059a4SDave May     d->recv_tags[n] = (int)rt;
358095059a4SDave May   }
359095059a4SDave May   d->topology_status = DEOBJECT_FINALIZED;
3609566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerTopologySetup, 0, 0, 0, 0));
361095059a4SDave May   PetscFunctionReturn(0);
362095059a4SDave May }
363095059a4SDave May 
364095059a4SDave May /* === Phase B === */
3659371c9d4SSatish Balay PetscErrorCode _DMSwarmDataExConvertProcIdToLocalIndex(DMSwarmDataEx de, PetscMPIInt proc_id, PetscMPIInt *local) {
366095059a4SDave May   PetscMPIInt i, np;
367095059a4SDave May 
368095059a4SDave May   PetscFunctionBegin;
369095059a4SDave May   np     = de->n_neighbour_procs;
370095059a4SDave May   *local = -1;
371521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
372095059a4SDave May     if (proc_id == de->neighbour_procs[i]) {
373095059a4SDave May       *local = i;
374095059a4SDave May       break;
375095059a4SDave May     }
376095059a4SDave May   }
377095059a4SDave May   PetscFunctionReturn(0);
378095059a4SDave May }
379095059a4SDave May 
3809371c9d4SSatish Balay PetscErrorCode DMSwarmDataExInitializeSendCount(DMSwarmDataEx de) {
381095059a4SDave May   PetscMPIInt i;
382095059a4SDave May 
383095059a4SDave May   PetscFunctionBegin;
38408401ef6SPierre Jolivet   PetscCheck(de->topology_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Topology not finalized");
3859566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerSendCount, 0, 0, 0, 0));
386095059a4SDave May   de->message_lengths_status = DEOBJECT_INITIALIZED;
3879371c9d4SSatish Balay   for (i = 0; i < de->n_neighbour_procs; ++i) { de->messages_to_be_sent[i] = 0; }
388095059a4SDave May   PetscFunctionReturn(0);
389095059a4SDave May }
390095059a4SDave May 
391095059a4SDave May /*
392095059a4SDave May 1) only allows counters to be set on neighbouring cpus
393095059a4SDave May */
3949371c9d4SSatish Balay PetscErrorCode DMSwarmDataExAddToSendCount(DMSwarmDataEx de, const PetscMPIInt proc_id, const PetscInt count) {
395095059a4SDave May   PetscMPIInt local_val;
396095059a4SDave May 
397095059a4SDave May   PetscFunctionBegin;
39808401ef6SPierre Jolivet   PetscCheck(de->message_lengths_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths have been defined. To modify these call DMSwarmDataExInitializeSendCount() first");
399f7d195e4SLawrence Mitchell   PetscCheck(de->message_lengths_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DMSwarmDataExInitializeSendCount() first");
4002064fc68SDave May 
4019566063dSJacob Faibussowitsch   PetscCall(_DMSwarmDataExConvertProcIdToLocalIndex(de, proc_id, &local_val));
40208401ef6SPierre Jolivet   PetscCheck(local_val != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Proc %d is not a valid neighbour rank", (int)proc_id);
4032064fc68SDave May 
404095059a4SDave May   de->messages_to_be_sent[local_val] = de->messages_to_be_sent[local_val] + count;
405095059a4SDave May   PetscFunctionReturn(0);
406095059a4SDave May }
407095059a4SDave May 
4089371c9d4SSatish Balay PetscErrorCode DMSwarmDataExFinalizeSendCount(DMSwarmDataEx de) {
409095059a4SDave May   PetscFunctionBegin;
41008401ef6SPierre Jolivet   PetscCheck(de->message_lengths_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DMSwarmDataExInitializeSendCount() first");
4112064fc68SDave May 
412095059a4SDave May   de->message_lengths_status = DEOBJECT_FINALIZED;
4139566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerSendCount, 0, 0, 0, 0));
414095059a4SDave May   PetscFunctionReturn(0);
415095059a4SDave May }
416095059a4SDave May 
417095059a4SDave May /* === Phase C === */
418095059a4SDave May /*
4195627991aSBarry Smith   zero out all send counts
4205627991aSBarry Smith   free send and recv buffers
4215627991aSBarry Smith   zeros out message length
4225627991aSBarry Smith   zeros out all counters
4235627991aSBarry Smith   zero out packed data counters
424095059a4SDave May */
4259371c9d4SSatish Balay PetscErrorCode _DMSwarmDataExInitializeTmpStorage(DMSwarmDataEx de) {
426095059a4SDave May   PetscMPIInt i, np;
427095059a4SDave May 
428095059a4SDave May   PetscFunctionBegin;
429095059a4SDave May   np = de->n_neighbour_procs;
430521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
431095059a4SDave May     /*  de->messages_to_be_sent[i] = -1; */
432095059a4SDave May     de->messages_to_be_recvieved[i] = -1;
433095059a4SDave May   }
4349566063dSJacob Faibussowitsch   PetscCall(PetscFree(de->send_message));
4359566063dSJacob Faibussowitsch   PetscCall(PetscFree(de->recv_message));
436095059a4SDave May   PetscFunctionReturn(0);
437095059a4SDave May }
438095059a4SDave May 
439095059a4SDave May /*
4405627991aSBarry Smith    Zeros out pack data counters
4415627991aSBarry Smith    Ensures mesaage length is set
4425627991aSBarry Smith    Checks send counts properly initialized
4435627991aSBarry Smith    allocates space for pack data
444095059a4SDave May */
4459371c9d4SSatish Balay PetscErrorCode DMSwarmDataExPackInitialize(DMSwarmDataEx de, size_t unit_message_size) {
446095059a4SDave May   PetscMPIInt i, np;
447095059a4SDave May   PetscInt    total;
448095059a4SDave May 
449095059a4SDave May   PetscFunctionBegin;
45008401ef6SPierre Jolivet   PetscCheck(de->topology_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Topology not finalized");
45108401ef6SPierre Jolivet   PetscCheck(de->message_lengths_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths not finalized");
4529566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerPack, 0, 0, 0, 0));
453095059a4SDave May   de->packer_status = DEOBJECT_INITIALIZED;
4549566063dSJacob Faibussowitsch   PetscCall(_DMSwarmDataExInitializeTmpStorage(de));
455095059a4SDave May   np                    = de->n_neighbour_procs;
456095059a4SDave May   de->unit_message_size = unit_message_size;
457095059a4SDave May   total                 = 0;
458521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
459095059a4SDave May     if (de->messages_to_be_sent[i] == -1) {
460095059a4SDave May       PetscMPIInt proc_neighour = de->neighbour_procs[i];
46198921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ORDER, "Messages_to_be_sent[neighbour_proc=%d] is un-initialised. Call DMSwarmDataExSetSendCount() first", (int)proc_neighour);
462095059a4SDave May     }
463095059a4SDave May     total = total + de->messages_to_be_sent[i];
464095059a4SDave May   }
465095059a4SDave May   /* create space for the data to be sent */
4669566063dSJacob Faibussowitsch   PetscCall(PetscMalloc(unit_message_size * (total + 1), &de->send_message));
467095059a4SDave May   /* initialize memory */
4689566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(de->send_message, unit_message_size * (total + 1)));
469095059a4SDave May   /* set total items to send */
470095059a4SDave May   de->send_message_length = total;
471095059a4SDave May   de->message_offsets[0]  = 0;
472095059a4SDave May   total                   = de->messages_to_be_sent[0];
473521f74f9SMatthew G. Knepley   for (i = 1; i < np; ++i) {
474095059a4SDave May     de->message_offsets[i] = total;
475095059a4SDave May     total                  = total + de->messages_to_be_sent[i];
476095059a4SDave May   }
477095059a4SDave May   /* init the packer counters */
478095059a4SDave May   de->total_pack_cnt = 0;
4799371c9d4SSatish Balay   for (i = 0; i < np; ++i) { de->pack_cnt[i] = 0; }
480095059a4SDave May   PetscFunctionReturn(0);
481095059a4SDave May }
482095059a4SDave May 
483095059a4SDave May /*
4845627991aSBarry Smith     Ensures data gets been packed appropriately and no overlaps occur
485095059a4SDave May */
4869371c9d4SSatish Balay PetscErrorCode DMSwarmDataExPackData(DMSwarmDataEx de, PetscMPIInt proc_id, PetscInt n, void *data) {
487095059a4SDave May   PetscMPIInt local;
488095059a4SDave May   PetscInt    insert_location;
489095059a4SDave May   void       *dest;
490095059a4SDave May 
491095059a4SDave May   PetscFunctionBegin;
49208401ef6SPierre 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");
493f7d195e4SLawrence Mitchell   PetscCheck(de->packer_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Packed data must be defined. Call DMSwarmDataExInitializeSendCount(), DMSwarmDataExAddToSendCount(), DMSwarmDataExPackInitialize() first");
4942064fc68SDave May 
49528b400f6SJacob Faibussowitsch   PetscCheck(de->send_message, de->comm, PETSC_ERR_ORDER, "send_message is not initialized. Call DMSwarmDataExPackInitialize() first");
4969566063dSJacob Faibussowitsch   PetscCall(_DMSwarmDataExConvertProcIdToLocalIndex(de, proc_id, &local));
49708401ef6SPierre Jolivet   PetscCheck(local != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "proc_id %d is not registered neighbour", (int)proc_id);
4989371c9d4SSatish 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]);
4992064fc68SDave May 
500095059a4SDave May   /* copy memory */
501095059a4SDave May   insert_location = de->message_offsets[local] + de->pack_cnt[local];
502095059a4SDave May   dest            = ((char *)de->send_message) + de->unit_message_size * insert_location;
5039566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(dest, data, de->unit_message_size * n));
504095059a4SDave May   /* increment counter */
505095059a4SDave May   de->pack_cnt[local] = de->pack_cnt[local] + n;
506095059a4SDave May   PetscFunctionReturn(0);
507095059a4SDave May }
508095059a4SDave May 
509095059a4SDave May /*
510095059a4SDave May *) Ensures all data has been packed
511095059a4SDave May */
5129371c9d4SSatish Balay PetscErrorCode DMSwarmDataExPackFinalize(DMSwarmDataEx de) {
513095059a4SDave May   PetscMPIInt i, np;
514095059a4SDave May   PetscInt    total;
515095059a4SDave May 
516095059a4SDave May   PetscFunctionBegin;
51708401ef6SPierre Jolivet   PetscCheck(de->packer_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Packer has not been initialized. Must call DMSwarmDataExPackInitialize() first.");
518095059a4SDave May   np = de->n_neighbour_procs;
519521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
5209371c9d4SSatish 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]);
521095059a4SDave May   }
522095059a4SDave May   /* init */
5239371c9d4SSatish Balay   for (i = 0; i < np; ++i) { de->messages_to_be_recvieved[i] = -1; }
524095059a4SDave May   /* figure out the recv counts here */
525*48a46eb9SPierre 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]));
526*48a46eb9SPierre 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]));
5279566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Waitall(2 * np, de->_requests, de->_stats));
528095059a4SDave May   /* create space for the data to be recvieved */
529095059a4SDave May   total = 0;
5309371c9d4SSatish Balay   for (i = 0; i < np; ++i) { total = total + de->messages_to_be_recvieved[i]; }
5319566063dSJacob Faibussowitsch   PetscCall(PetscMalloc(de->unit_message_size * (total + 1), &de->recv_message));
532095059a4SDave May   /* initialize memory */
5339566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(de->recv_message, de->unit_message_size * (total + 1)));
5342d4ee042Sprj-   /* set total items to receive */
535095059a4SDave May   de->recv_message_length  = total;
536095059a4SDave May   de->packer_status        = DEOBJECT_FINALIZED;
537095059a4SDave May   de->communication_status = DEOBJECT_INITIALIZED;
5389566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerPack, 0, 0, 0, 0));
539095059a4SDave May   PetscFunctionReturn(0);
540095059a4SDave May }
541095059a4SDave May 
5425627991aSBarry Smith /* do the actual message passing */
5439371c9d4SSatish Balay PetscErrorCode DMSwarmDataExBegin(DMSwarmDataEx de) {
544095059a4SDave May   PetscMPIInt i, np;
545095059a4SDave May   void       *dest;
546095059a4SDave May   PetscInt    length;
547095059a4SDave May 
548095059a4SDave May   PetscFunctionBegin;
54908401ef6SPierre Jolivet   PetscCheck(de->topology_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Topology not finalized");
55008401ef6SPierre Jolivet   PetscCheck(de->message_lengths_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths not finalized");
55108401ef6SPierre Jolivet   PetscCheck(de->packer_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Packer not finalized");
55208401ef6SPierre Jolivet   PetscCheck(de->communication_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Communication has already been finalized. Must call DMSwarmDataExInitialize() first.");
55328b400f6SJacob Faibussowitsch   PetscCheck(de->recv_message, de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DMSwarmDataExPackFinalize() first");
5549566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerBegin, 0, 0, 0, 0));
555095059a4SDave May   np = de->n_neighbour_procs;
556095059a4SDave May   /* == NON BLOCKING == */
557521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
558095059a4SDave May     length = de->messages_to_be_sent[i] * de->unit_message_size;
559095059a4SDave May     dest   = ((char *)de->send_message) + de->unit_message_size * de->message_offsets[i];
5609566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Isend(dest, length, MPI_CHAR, de->neighbour_procs[i], de->send_tags[i], de->comm, &de->_requests[i]));
561095059a4SDave May   }
5629566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerBegin, 0, 0, 0, 0));
563095059a4SDave May   PetscFunctionReturn(0);
564095059a4SDave May }
565095059a4SDave May 
566095059a4SDave May /* do the actual message passing now */
5679371c9d4SSatish Balay PetscErrorCode DMSwarmDataExEnd(DMSwarmDataEx de) {
568095059a4SDave May   PetscMPIInt i, np;
569095059a4SDave May   PetscInt    total;
570095059a4SDave May   PetscInt   *message_recv_offsets;
571095059a4SDave May   void       *dest;
572095059a4SDave May   PetscInt    length;
573095059a4SDave May 
574095059a4SDave May   PetscFunctionBegin;
57508401ef6SPierre Jolivet   PetscCheck(de->communication_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Communication has not been initialized. Must call DMSwarmDataExInitialize() first.");
57628b400f6SJacob Faibussowitsch   PetscCheck(de->recv_message, de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DMSwarmDataExPackFinalize() first");
5779566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerEnd, 0, 0, 0, 0));
578095059a4SDave May   np = de->n_neighbour_procs;
5799566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(np + 1, &message_recv_offsets));
580095059a4SDave May   message_recv_offsets[0] = 0;
581095059a4SDave May   total                   = de->messages_to_be_recvieved[0];
582521f74f9SMatthew G. Knepley   for (i = 1; i < np; ++i) {
583095059a4SDave May     message_recv_offsets[i] = total;
584095059a4SDave May     total                   = total + de->messages_to_be_recvieved[i];
585095059a4SDave May   }
586095059a4SDave May   /* == NON BLOCKING == */
587521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
588095059a4SDave May     length = de->messages_to_be_recvieved[i] * de->unit_message_size;
589095059a4SDave May     dest   = ((char *)de->recv_message) + de->unit_message_size * message_recv_offsets[i];
5909566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Irecv(dest, length, MPI_CHAR, de->neighbour_procs[i], de->recv_tags[i], de->comm, &de->_requests[np + i]));
591095059a4SDave May   }
5929566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Waitall(2 * np, de->_requests, de->_stats));
5939566063dSJacob Faibussowitsch   PetscCall(PetscFree(message_recv_offsets));
594095059a4SDave May   de->communication_status = DEOBJECT_FINALIZED;
5959566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerEnd, 0, 0, 0, 0));
596095059a4SDave May   PetscFunctionReturn(0);
597095059a4SDave May }
598095059a4SDave May 
5999371c9d4SSatish Balay PetscErrorCode DMSwarmDataExGetSendData(DMSwarmDataEx de, PetscInt *length, void **send) {
600095059a4SDave May   PetscFunctionBegin;
60108401ef6SPierre Jolivet   PetscCheck(de->packer_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being packed.");
602095059a4SDave May   *length = de->send_message_length;
603095059a4SDave May   *send   = de->send_message;
604095059a4SDave May   PetscFunctionReturn(0);
605095059a4SDave May }
606095059a4SDave May 
6079371c9d4SSatish Balay PetscErrorCode DMSwarmDataExGetRecvData(DMSwarmDataEx de, PetscInt *length, void **recv) {
608095059a4SDave May   PetscFunctionBegin;
60908401ef6SPierre Jolivet   PetscCheck(de->communication_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being sent.");
610095059a4SDave May   *length = de->recv_message_length;
611095059a4SDave May   *recv   = de->recv_message;
612095059a4SDave May   PetscFunctionReturn(0);
613095059a4SDave May }
614095059a4SDave May 
6159371c9d4SSatish Balay PetscErrorCode DMSwarmDataExTopologyGetNeighbours(DMSwarmDataEx de, PetscMPIInt *n, PetscMPIInt *neigh[]) {
616095059a4SDave May   PetscFunctionBegin;
617095059a4SDave May   if (n) { *n = de->n_neighbour_procs; }
618095059a4SDave May   if (neigh) { *neigh = de->neighbour_procs; }
619095059a4SDave May   PetscFunctionReturn(0);
620095059a4SDave May }
621