xref: /petsc/src/dm/impls/swarm/data_ex.c (revision 52c42f6eed5dc58f037c69fc8f9775d633d9f564)
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 
84d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExCreate(MPI_Comm comm, const PetscInt count, DMSwarmDataEx *ex)
85d71ae5a4SJacob 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 */
130d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExView(DMSwarmDataEx d)
131d71ae5a4SJacob 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 
164d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExDestroy(DMSwarmDataEx d)
165d71ae5a4SJacob 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 
185d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExTopologyInitialize(DMSwarmDataEx d)
186d71ae5a4SJacob 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 
200d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExTopologyAddNeighbour(DMSwarmDataEx d, const PetscMPIInt proc_id)
201d71ae5a4SJacob 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*52c42f6eSMatthew G. Knepley static void _get_tags(PetscInt counter, PetscMPIInt N, PetscMPIInt r0, PetscMPIInt r1, PetscMPIInt maxtag, PetscMPIInt *_st, PetscMPIInt *_rt)
263d71ae5a4SJacob Faibussowitsch {
264095059a4SDave May   PetscMPIInt st, rt;
265095059a4SDave May 
266*52c42f6eSMatthew G. Knepley   st   = (N * r0 + r1 + N * N * counter) % maxtag;
267*52c42f6eSMatthew G. Knepley   rt   = (N * r1 + r0 + N * N * counter) % maxtag;
268095059a4SDave May   *_st = st;
269095059a4SDave May   *_rt = rt;
270095059a4SDave May }
271095059a4SDave May 
272095059a4SDave May /*
273095059a4SDave May Makes the communication map symmetric
274095059a4SDave May */
275d71ae5a4SJacob Faibussowitsch PetscErrorCode _DMSwarmDataExCompleteCommunicationMap(MPI_Comm comm, PetscMPIInt n, PetscMPIInt proc_neighbours[], PetscMPIInt *n_new, PetscMPIInt **proc_neighbours_new)
276d71ae5a4SJacob 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 
334d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExTopologyFinalize(DMSwarmDataEx d)
335d71ae5a4SJacob Faibussowitsch {
336*52c42f6eSMatthew G. Knepley   PetscMPIInt symm_nn, *symm_procs, r0, n, st, rt, size, *maxtag, flg;
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));
359*52c42f6eSMatthew G. Knepley   PetscCallMPI(MPI_Comm_get_attr(MPI_COMM_WORLD, MPI_TAG_UB, &maxtag, &flg));
360*52c42f6eSMatthew G. Knepley   PetscCheck(flg, d->comm, PETSC_ERR_LIB, "MPI error: MPI_Comm_get_attr() is not returning a MPI_TAG_UB");
361095059a4SDave May   r0 = d->rank;
362521f74f9SMatthew G. Knepley   for (n = 0; n < d->n_neighbour_procs; ++n) {
363095059a4SDave May     PetscMPIInt r1 = d->neighbour_procs[n];
364095059a4SDave May 
365*52c42f6eSMatthew G. Knepley     _get_tags(d->instance, size, r0, r1, *maxtag, &st, &rt);
366095059a4SDave May     d->send_tags[n] = (int)st;
367095059a4SDave May     d->recv_tags[n] = (int)rt;
368095059a4SDave May   }
369095059a4SDave May   d->topology_status = DEOBJECT_FINALIZED;
3709566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerTopologySetup, 0, 0, 0, 0));
371095059a4SDave May   PetscFunctionReturn(0);
372095059a4SDave May }
373095059a4SDave May 
374095059a4SDave May /* === Phase B === */
375d71ae5a4SJacob Faibussowitsch PetscErrorCode _DMSwarmDataExConvertProcIdToLocalIndex(DMSwarmDataEx de, PetscMPIInt proc_id, PetscMPIInt *local)
376d71ae5a4SJacob Faibussowitsch {
377095059a4SDave May   PetscMPIInt i, np;
378095059a4SDave May 
379095059a4SDave May   PetscFunctionBegin;
380095059a4SDave May   np     = de->n_neighbour_procs;
381095059a4SDave May   *local = -1;
382521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
383095059a4SDave May     if (proc_id == de->neighbour_procs[i]) {
384095059a4SDave May       *local = i;
385095059a4SDave May       break;
386095059a4SDave May     }
387095059a4SDave May   }
388095059a4SDave May   PetscFunctionReturn(0);
389095059a4SDave May }
390095059a4SDave May 
391d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExInitializeSendCount(DMSwarmDataEx de)
392d71ae5a4SJacob Faibussowitsch {
393095059a4SDave May   PetscMPIInt i;
394095059a4SDave May 
395095059a4SDave May   PetscFunctionBegin;
39608401ef6SPierre Jolivet   PetscCheck(de->topology_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Topology not finalized");
3979566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerSendCount, 0, 0, 0, 0));
398095059a4SDave May   de->message_lengths_status = DEOBJECT_INITIALIZED;
399ad540459SPierre Jolivet   for (i = 0; i < de->n_neighbour_procs; ++i) de->messages_to_be_sent[i] = 0;
400095059a4SDave May   PetscFunctionReturn(0);
401095059a4SDave May }
402095059a4SDave May 
403095059a4SDave May /*
404095059a4SDave May 1) only allows counters to be set on neighbouring cpus
405095059a4SDave May */
406d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExAddToSendCount(DMSwarmDataEx de, const PetscMPIInt proc_id, const PetscInt count)
407d71ae5a4SJacob Faibussowitsch {
408095059a4SDave May   PetscMPIInt local_val;
409095059a4SDave May 
410095059a4SDave May   PetscFunctionBegin;
41108401ef6SPierre Jolivet   PetscCheck(de->message_lengths_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths have been defined. To modify these call DMSwarmDataExInitializeSendCount() first");
412f7d195e4SLawrence Mitchell   PetscCheck(de->message_lengths_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DMSwarmDataExInitializeSendCount() first");
4132064fc68SDave May 
4149566063dSJacob Faibussowitsch   PetscCall(_DMSwarmDataExConvertProcIdToLocalIndex(de, proc_id, &local_val));
41508401ef6SPierre Jolivet   PetscCheck(local_val != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Proc %d is not a valid neighbour rank", (int)proc_id);
4162064fc68SDave May 
417095059a4SDave May   de->messages_to_be_sent[local_val] = de->messages_to_be_sent[local_val] + count;
418095059a4SDave May   PetscFunctionReturn(0);
419095059a4SDave May }
420095059a4SDave May 
421d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExFinalizeSendCount(DMSwarmDataEx de)
422d71ae5a4SJacob Faibussowitsch {
423095059a4SDave May   PetscFunctionBegin;
42408401ef6SPierre Jolivet   PetscCheck(de->message_lengths_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DMSwarmDataExInitializeSendCount() first");
4252064fc68SDave May 
426095059a4SDave May   de->message_lengths_status = DEOBJECT_FINALIZED;
4279566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerSendCount, 0, 0, 0, 0));
428095059a4SDave May   PetscFunctionReturn(0);
429095059a4SDave May }
430095059a4SDave May 
431095059a4SDave May /* === Phase C === */
432095059a4SDave May /*
4335627991aSBarry Smith   zero out all send counts
4345627991aSBarry Smith   free send and recv buffers
4355627991aSBarry Smith   zeros out message length
4365627991aSBarry Smith   zeros out all counters
4375627991aSBarry Smith   zero out packed data counters
438095059a4SDave May */
439d71ae5a4SJacob Faibussowitsch PetscErrorCode _DMSwarmDataExInitializeTmpStorage(DMSwarmDataEx de)
440d71ae5a4SJacob Faibussowitsch {
441095059a4SDave May   PetscMPIInt i, np;
442095059a4SDave May 
443095059a4SDave May   PetscFunctionBegin;
444095059a4SDave May   np = de->n_neighbour_procs;
445521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
446095059a4SDave May     /*  de->messages_to_be_sent[i] = -1; */
447095059a4SDave May     de->messages_to_be_recvieved[i] = -1;
448095059a4SDave May   }
4499566063dSJacob Faibussowitsch   PetscCall(PetscFree(de->send_message));
4509566063dSJacob Faibussowitsch   PetscCall(PetscFree(de->recv_message));
451095059a4SDave May   PetscFunctionReturn(0);
452095059a4SDave May }
453095059a4SDave May 
454095059a4SDave May /*
4555627991aSBarry Smith    Zeros out pack data counters
4565627991aSBarry Smith    Ensures mesaage length is set
4575627991aSBarry Smith    Checks send counts properly initialized
4585627991aSBarry Smith    allocates space for pack data
459095059a4SDave May */
460d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExPackInitialize(DMSwarmDataEx de, size_t unit_message_size)
461d71ae5a4SJacob Faibussowitsch {
462095059a4SDave May   PetscMPIInt i, np;
463095059a4SDave May   PetscInt    total;
464095059a4SDave May 
465095059a4SDave May   PetscFunctionBegin;
46608401ef6SPierre Jolivet   PetscCheck(de->topology_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Topology not finalized");
46708401ef6SPierre Jolivet   PetscCheck(de->message_lengths_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths not finalized");
4689566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerPack, 0, 0, 0, 0));
469095059a4SDave May   de->packer_status = DEOBJECT_INITIALIZED;
4709566063dSJacob Faibussowitsch   PetscCall(_DMSwarmDataExInitializeTmpStorage(de));
471095059a4SDave May   np                    = de->n_neighbour_procs;
472095059a4SDave May   de->unit_message_size = unit_message_size;
473095059a4SDave May   total                 = 0;
474521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
475095059a4SDave May     if (de->messages_to_be_sent[i] == -1) {
476095059a4SDave May       PetscMPIInt proc_neighour = de->neighbour_procs[i];
47798921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ORDER, "Messages_to_be_sent[neighbour_proc=%d] is un-initialised. Call DMSwarmDataExSetSendCount() first", (int)proc_neighour);
478095059a4SDave May     }
479095059a4SDave May     total = total + de->messages_to_be_sent[i];
480095059a4SDave May   }
481095059a4SDave May   /* create space for the data to be sent */
4829566063dSJacob Faibussowitsch   PetscCall(PetscMalloc(unit_message_size * (total + 1), &de->send_message));
483095059a4SDave May   /* initialize memory */
4849566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(de->send_message, unit_message_size * (total + 1)));
485095059a4SDave May   /* set total items to send */
486095059a4SDave May   de->send_message_length = total;
487095059a4SDave May   de->message_offsets[0]  = 0;
488095059a4SDave May   total                   = de->messages_to_be_sent[0];
489521f74f9SMatthew G. Knepley   for (i = 1; i < np; ++i) {
490095059a4SDave May     de->message_offsets[i] = total;
491095059a4SDave May     total                  = total + de->messages_to_be_sent[i];
492095059a4SDave May   }
493095059a4SDave May   /* init the packer counters */
494095059a4SDave May   de->total_pack_cnt = 0;
495ad540459SPierre Jolivet   for (i = 0; i < np; ++i) de->pack_cnt[i] = 0;
496095059a4SDave May   PetscFunctionReturn(0);
497095059a4SDave May }
498095059a4SDave May 
499095059a4SDave May /*
5005627991aSBarry Smith     Ensures data gets been packed appropriately and no overlaps occur
501095059a4SDave May */
502d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExPackData(DMSwarmDataEx de, PetscMPIInt proc_id, PetscInt n, void *data)
503d71ae5a4SJacob Faibussowitsch {
504095059a4SDave May   PetscMPIInt local;
505095059a4SDave May   PetscInt    insert_location;
506095059a4SDave May   void       *dest;
507095059a4SDave May 
508095059a4SDave May   PetscFunctionBegin;
50908401ef6SPierre 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");
510f7d195e4SLawrence Mitchell   PetscCheck(de->packer_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Packed data must be defined. Call DMSwarmDataExInitializeSendCount(), DMSwarmDataExAddToSendCount(), DMSwarmDataExPackInitialize() first");
5112064fc68SDave May 
51228b400f6SJacob Faibussowitsch   PetscCheck(de->send_message, de->comm, PETSC_ERR_ORDER, "send_message is not initialized. Call DMSwarmDataExPackInitialize() first");
5139566063dSJacob Faibussowitsch   PetscCall(_DMSwarmDataExConvertProcIdToLocalIndex(de, proc_id, &local));
51408401ef6SPierre Jolivet   PetscCheck(local != -1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "proc_id %d is not registered neighbour", (int)proc_id);
5159371c9d4SSatish 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]);
5162064fc68SDave May 
517095059a4SDave May   /* copy memory */
518095059a4SDave May   insert_location = de->message_offsets[local] + de->pack_cnt[local];
519095059a4SDave May   dest            = ((char *)de->send_message) + de->unit_message_size * insert_location;
5209566063dSJacob Faibussowitsch   PetscCall(PetscMemcpy(dest, data, de->unit_message_size * n));
521095059a4SDave May   /* increment counter */
522095059a4SDave May   de->pack_cnt[local] = de->pack_cnt[local] + n;
523095059a4SDave May   PetscFunctionReturn(0);
524095059a4SDave May }
525095059a4SDave May 
526095059a4SDave May /*
527095059a4SDave May *) Ensures all data has been packed
528095059a4SDave May */
529d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExPackFinalize(DMSwarmDataEx de)
530d71ae5a4SJacob Faibussowitsch {
531095059a4SDave May   PetscMPIInt i, np;
532095059a4SDave May   PetscInt    total;
533095059a4SDave May 
534095059a4SDave May   PetscFunctionBegin;
53508401ef6SPierre Jolivet   PetscCheck(de->packer_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Packer has not been initialized. Must call DMSwarmDataExPackInitialize() first.");
536095059a4SDave May   np = de->n_neighbour_procs;
537521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
5389371c9d4SSatish 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]);
539095059a4SDave May   }
540095059a4SDave May   /* init */
541ad540459SPierre Jolivet   for (i = 0; i < np; ++i) de->messages_to_be_recvieved[i] = -1;
542095059a4SDave May   /* figure out the recv counts here */
54348a46eb9SPierre 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]));
54448a46eb9SPierre 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]));
5459566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Waitall(2 * np, de->_requests, de->_stats));
546095059a4SDave May   /* create space for the data to be recvieved */
547095059a4SDave May   total = 0;
548ad540459SPierre Jolivet   for (i = 0; i < np; ++i) total = total + de->messages_to_be_recvieved[i];
5499566063dSJacob Faibussowitsch   PetscCall(PetscMalloc(de->unit_message_size * (total + 1), &de->recv_message));
550095059a4SDave May   /* initialize memory */
5519566063dSJacob Faibussowitsch   PetscCall(PetscMemzero(de->recv_message, de->unit_message_size * (total + 1)));
5522d4ee042Sprj-   /* set total items to receive */
553095059a4SDave May   de->recv_message_length  = total;
554095059a4SDave May   de->packer_status        = DEOBJECT_FINALIZED;
555095059a4SDave May   de->communication_status = DEOBJECT_INITIALIZED;
5569566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerPack, 0, 0, 0, 0));
557095059a4SDave May   PetscFunctionReturn(0);
558095059a4SDave May }
559095059a4SDave May 
5605627991aSBarry Smith /* do the actual message passing */
561d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExBegin(DMSwarmDataEx de)
562d71ae5a4SJacob Faibussowitsch {
563095059a4SDave May   PetscMPIInt i, np;
564095059a4SDave May   void       *dest;
565095059a4SDave May   PetscInt    length;
566095059a4SDave May 
567095059a4SDave May   PetscFunctionBegin;
56808401ef6SPierre Jolivet   PetscCheck(de->topology_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Topology not finalized");
56908401ef6SPierre Jolivet   PetscCheck(de->message_lengths_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths not finalized");
57008401ef6SPierre Jolivet   PetscCheck(de->packer_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Packer not finalized");
57108401ef6SPierre Jolivet   PetscCheck(de->communication_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Communication has already been finalized. Must call DMSwarmDataExInitialize() first.");
57228b400f6SJacob Faibussowitsch   PetscCheck(de->recv_message, de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DMSwarmDataExPackFinalize() first");
5739566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerBegin, 0, 0, 0, 0));
574095059a4SDave May   np = de->n_neighbour_procs;
575095059a4SDave May   /* == NON BLOCKING == */
576521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
577095059a4SDave May     length = de->messages_to_be_sent[i] * de->unit_message_size;
578095059a4SDave May     dest   = ((char *)de->send_message) + de->unit_message_size * de->message_offsets[i];
5799566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Isend(dest, length, MPI_CHAR, de->neighbour_procs[i], de->send_tags[i], de->comm, &de->_requests[i]));
580095059a4SDave May   }
5819566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerBegin, 0, 0, 0, 0));
582095059a4SDave May   PetscFunctionReturn(0);
583095059a4SDave May }
584095059a4SDave May 
585095059a4SDave May /* do the actual message passing now */
586d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExEnd(DMSwarmDataEx de)
587d71ae5a4SJacob Faibussowitsch {
588095059a4SDave May   PetscMPIInt i, np;
589095059a4SDave May   PetscInt    total;
590095059a4SDave May   PetscInt   *message_recv_offsets;
591095059a4SDave May   void       *dest;
592095059a4SDave May   PetscInt    length;
593095059a4SDave May 
594095059a4SDave May   PetscFunctionBegin;
59508401ef6SPierre Jolivet   PetscCheck(de->communication_status == DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Communication has not been initialized. Must call DMSwarmDataExInitialize() first.");
59628b400f6SJacob Faibussowitsch   PetscCheck(de->recv_message, de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DMSwarmDataExPackFinalize() first");
5979566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(DMSWARM_DataExchangerEnd, 0, 0, 0, 0));
598095059a4SDave May   np = de->n_neighbour_procs;
5999566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(np + 1, &message_recv_offsets));
600095059a4SDave May   message_recv_offsets[0] = 0;
601095059a4SDave May   total                   = de->messages_to_be_recvieved[0];
602521f74f9SMatthew G. Knepley   for (i = 1; i < np; ++i) {
603095059a4SDave May     message_recv_offsets[i] = total;
604095059a4SDave May     total                   = total + de->messages_to_be_recvieved[i];
605095059a4SDave May   }
606095059a4SDave May   /* == NON BLOCKING == */
607521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
608095059a4SDave May     length = de->messages_to_be_recvieved[i] * de->unit_message_size;
609095059a4SDave May     dest   = ((char *)de->recv_message) + de->unit_message_size * message_recv_offsets[i];
6109566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Irecv(dest, length, MPI_CHAR, de->neighbour_procs[i], de->recv_tags[i], de->comm, &de->_requests[np + i]));
611095059a4SDave May   }
6129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Waitall(2 * np, de->_requests, de->_stats));
6139566063dSJacob Faibussowitsch   PetscCall(PetscFree(message_recv_offsets));
614095059a4SDave May   de->communication_status = DEOBJECT_FINALIZED;
6159566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(DMSWARM_DataExchangerEnd, 0, 0, 0, 0));
616095059a4SDave May   PetscFunctionReturn(0);
617095059a4SDave May }
618095059a4SDave May 
619d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExGetSendData(DMSwarmDataEx de, PetscInt *length, void **send)
620d71ae5a4SJacob Faibussowitsch {
621095059a4SDave May   PetscFunctionBegin;
62208401ef6SPierre Jolivet   PetscCheck(de->packer_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being packed.");
623095059a4SDave May   *length = de->send_message_length;
624095059a4SDave May   *send   = de->send_message;
625095059a4SDave May   PetscFunctionReturn(0);
626095059a4SDave May }
627095059a4SDave May 
628d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExGetRecvData(DMSwarmDataEx de, PetscInt *length, void **recv)
629d71ae5a4SJacob Faibussowitsch {
630095059a4SDave May   PetscFunctionBegin;
63108401ef6SPierre Jolivet   PetscCheck(de->communication_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being sent.");
632095059a4SDave May   *length = de->recv_message_length;
633095059a4SDave May   *recv   = de->recv_message;
634095059a4SDave May   PetscFunctionReturn(0);
635095059a4SDave May }
636095059a4SDave May 
637d71ae5a4SJacob Faibussowitsch PetscErrorCode DMSwarmDataExTopologyGetNeighbours(DMSwarmDataEx de, PetscMPIInt *n, PetscMPIInt *neigh[])
638d71ae5a4SJacob Faibussowitsch {
639095059a4SDave May   PetscFunctionBegin;
640ad540459SPierre Jolivet   if (n) *n = de->n_neighbour_procs;
641ad540459SPierre Jolivet   if (neigh) *neigh = de->neighbour_procs;
642095059a4SDave May   PetscFunctionReturn(0);
643095059a4SDave May }
644