xref: /petsc/src/dm/impls/swarm/data_ex.c (revision 5f80ce2ab25dff0f4601e710601cbbcecf323266)
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 
8477048351SPatrick Sanan PetscErrorCode DMSwarmDataExCreate(MPI_Comm comm,const PetscInt count, DMSwarmDataEx *ex)
85095059a4SDave May {
8677048351SPatrick Sanan   DMSwarmDataEx  d;
87095059a4SDave May 
88521f74f9SMatthew G. Knepley   PetscFunctionBegin;
89*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNew(&d));
90*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_dup(comm,&d->comm));
91*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(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 */
13077048351SPatrick Sanan PetscErrorCode DMSwarmDataExView(DMSwarmDataEx d)
131095059a4SDave May {
132095059a4SDave May   PetscMPIInt    p;
133095059a4SDave May 
134095059a4SDave May   PetscFunctionBegin;
135*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPrintf( PETSC_COMM_WORLD, "DMSwarmDataEx: instance=%D\n",d->instance));
136*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPrintf( PETSC_COMM_WORLD, "  topology status:        %s \n", status_names[d->topology_status]));
137*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPrintf( PETSC_COMM_WORLD, "  message lengths status: %s \n", status_names[d->message_lengths_status]));
138*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPrintf( PETSC_COMM_WORLD, "  packer status status:   %s \n", status_names[d->packer_status]));
139*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscPrintf( PETSC_COMM_WORLD, "  communication status:   %s \n", status_names[d->communication_status]));
140095059a4SDave May 
141095059a4SDave May   if (d->topology_status == DEOBJECT_FINALIZED) {
142*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPrintf( PETSC_COMM_WORLD, "  Topology:\n"));
143*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSynchronizedPrintf( PETSC_COMM_WORLD, "    [%d] neighbours: %d \n", d->rank, d->n_neighbour_procs));
144095059a4SDave May     for (p=0; p<d->n_neighbour_procs; p++) {
145*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSynchronizedPrintf( PETSC_COMM_WORLD, "    [%d]   neighbour[%d] = %d \n", d->rank, p, d->neighbour_procs[p]));
146095059a4SDave May     }
147*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSynchronizedFlush(PETSC_COMM_WORLD,stdout));
148095059a4SDave May   }
149298827fbSBarry Smith 
150095059a4SDave May   if (d->message_lengths_status == DEOBJECT_FINALIZED) {
151*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscPrintf( PETSC_COMM_WORLD, "  Message lengths:\n"));
152*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSynchronizedPrintf( PETSC_COMM_WORLD, "    [%d] atomic size: %ld \n", d->rank, (long int)d->unit_message_size));
153095059a4SDave May     for (p=0; p<d->n_neighbour_procs; p++) {
154*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSynchronizedPrintf( PETSC_COMM_WORLD, "    [%d] >>>>> ( %D units :: tag = %d) >>>>> [%d] \n", d->rank, d->messages_to_be_sent[p], d->send_tags[p], d->neighbour_procs[p]));
155095059a4SDave May     }
156095059a4SDave May     for (p=0; p<d->n_neighbour_procs; p++) {
157*5f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscSynchronizedPrintf( PETSC_COMM_WORLD, "    [%d] <<<<< ( %D units :: tag = %d) <<<<< [%d] \n", d->rank, d->messages_to_be_recvieved[p], d->recv_tags[p], d->neighbour_procs[p]));
158095059a4SDave May     }
159*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSynchronizedFlush(PETSC_COMM_WORLD,stdout));
160095059a4SDave May   }
161521f74f9SMatthew G. Knepley   if (d->packer_status == DEOBJECT_FINALIZED) {}
162521f74f9SMatthew G. Knepley   if (d->communication_status == DEOBJECT_FINALIZED) {}
163095059a4SDave May   PetscFunctionReturn(0);
164095059a4SDave May }
165095059a4SDave May 
16677048351SPatrick Sanan PetscErrorCode DMSwarmDataExDestroy(DMSwarmDataEx d)
167095059a4SDave May {
168095059a4SDave May   PetscFunctionBegin;
169*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_free(&d->comm));
170*5f80ce2aSJacob Faibussowitsch   if (d->neighbour_procs) CHKERRQ(PetscFree(d->neighbour_procs));
171*5f80ce2aSJacob Faibussowitsch   if (d->messages_to_be_sent) CHKERRQ(PetscFree(d->messages_to_be_sent));
172*5f80ce2aSJacob Faibussowitsch   if (d->message_offsets) CHKERRQ(PetscFree(d->message_offsets));
173*5f80ce2aSJacob Faibussowitsch   if (d->messages_to_be_recvieved) CHKERRQ(PetscFree(d->messages_to_be_recvieved));
174*5f80ce2aSJacob Faibussowitsch   if (d->send_message) CHKERRQ(PetscFree(d->send_message));
175*5f80ce2aSJacob Faibussowitsch   if (d->recv_message) CHKERRQ(PetscFree(d->recv_message));
176*5f80ce2aSJacob Faibussowitsch   if (d->pack_cnt) CHKERRQ(PetscFree(d->pack_cnt));
177*5f80ce2aSJacob Faibussowitsch   if (d->send_tags) CHKERRQ(PetscFree(d->send_tags));
178*5f80ce2aSJacob Faibussowitsch   if (d->recv_tags) CHKERRQ(PetscFree(d->recv_tags));
179*5f80ce2aSJacob Faibussowitsch   if (d->_stats) CHKERRQ(PetscFree(d->_stats));
180*5f80ce2aSJacob Faibussowitsch   if (d->_requests) CHKERRQ(PetscFree(d->_requests));
181*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(d));
182095059a4SDave May   PetscFunctionReturn(0);
183095059a4SDave May }
184095059a4SDave May 
185095059a4SDave May /* === Phase A === */
186095059a4SDave May 
18777048351SPatrick Sanan PetscErrorCode DMSwarmDataExTopologyInitialize(DMSwarmDataEx d)
188095059a4SDave May {
189095059a4SDave May   PetscFunctionBegin;
190095059a4SDave May   d->topology_status = DEOBJECT_INITIALIZED;
191095059a4SDave May   d->n_neighbour_procs = 0;
192*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(d->neighbour_procs));
193*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(d->messages_to_be_sent));
194*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(d->message_offsets));
195*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(d->messages_to_be_recvieved));
196*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(d->pack_cnt));
197*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(d->send_tags));
198*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(d->recv_tags));
199095059a4SDave May   PetscFunctionReturn(0);
200095059a4SDave May }
201095059a4SDave May 
20277048351SPatrick Sanan PetscErrorCode DMSwarmDataExTopologyAddNeighbour(DMSwarmDataEx d,const PetscMPIInt proc_id)
203095059a4SDave May {
204095059a4SDave May   PetscMPIInt    n,found;
205d7d19db6SBarry Smith   PetscMPIInt    size;
206095059a4SDave May 
207095059a4SDave May   PetscFunctionBegin;
2082c71b3e2SJacob Faibussowitsch   PetscCheckFalse(d->topology_status == DEOBJECT_FINALIZED,d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology has been finalized. To modify or update call DMSwarmDataExTopologyInitialize() first");
2092c71b3e2SJacob Faibussowitsch   else PetscCheckFalse(d->topology_status != DEOBJECT_INITIALIZED,d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be initialised. Call DMSwarmDataExTopologyInitialize() first");
2102064fc68SDave May 
211095059a4SDave May   /* error on negative entries */
2122c71b3e2SJacob Faibussowitsch   PetscCheckFalse(proc_id < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Trying to set proc neighbour with a rank < 0");
213095059a4SDave May   /* error on ranks larger than number of procs in communicator */
214*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(d->comm,&size));
2152c71b3e2SJacob Faibussowitsch   PetscCheckFalse(proc_id >= size,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Trying to set proc neighbour %d with a rank >= size %d",proc_id,size);
216*5f80ce2aSJacob Faibussowitsch   if (d->n_neighbour_procs == 0) CHKERRQ(PetscMalloc1(1, &d->neighbour_procs));
217095059a4SDave May   /* check for proc_id */
218095059a4SDave May   found = 0;
219095059a4SDave May   for (n = 0; n < d->n_neighbour_procs; n++) {
220095059a4SDave May     if (d->neighbour_procs[n] == proc_id) {
221095059a4SDave May       found  = 1;
222095059a4SDave May     }
223095059a4SDave May   }
224095059a4SDave May   if (found == 0) { /* add it to list */
225*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscRealloc(sizeof(PetscMPIInt)*(d->n_neighbour_procs+1), &d->neighbour_procs));
226095059a4SDave May     d->neighbour_procs[ d->n_neighbour_procs ] = proc_id;
227095059a4SDave May     d->n_neighbour_procs++;
228095059a4SDave May   }
229095059a4SDave May   PetscFunctionReturn(0);
230095059a4SDave May }
231095059a4SDave May 
232095059a4SDave May /*
233095059a4SDave May counter: the index of the communication object
234095059a4SDave May N: the number of processors
235095059a4SDave May r0: rank of sender
236095059a4SDave May r1: rank of receiver
237095059a4SDave May 
238095059a4SDave May procs = { 0, 1, 2, 3 }
239095059a4SDave May 
240095059a4SDave May 0 ==> 0         e=0
241095059a4SDave May 0 ==> 1         e=1
242095059a4SDave May 0 ==> 2         e=2
243095059a4SDave May 0 ==> 3         e=3
244095059a4SDave May 
245095059a4SDave May 1 ==> 0         e=4
246095059a4SDave May 1 ==> 1         e=5
247095059a4SDave May 1 ==> 2         e=6
248095059a4SDave May 1 ==> 3         e=7
249095059a4SDave May 
250095059a4SDave May 2 ==> 0         e=8
251095059a4SDave May 2 ==> 1         e=9
252095059a4SDave May 2 ==> 2         e=10
253095059a4SDave May 2 ==> 3         e=11
254095059a4SDave May 
255095059a4SDave May 3 ==> 0         e=12
256095059a4SDave May 3 ==> 1         e=13
257095059a4SDave May 3 ==> 2         e=14
258095059a4SDave May 3 ==> 3         e=15
259095059a4SDave May 
260095059a4SDave May If we require that proc A sends to proc B, then the SEND tag index will be given by
261095059a4SDave May   N * rank(A) + rank(B) + offset
262095059a4SDave May If we require that proc A will receive from proc B, then the RECV tag index will be given by
263095059a4SDave May   N * rank(B) + rank(A) + offset
264095059a4SDave May 
265095059a4SDave May */
266521f74f9SMatthew G. Knepley static void _get_tags(PetscInt counter, PetscMPIInt N, PetscMPIInt r0,PetscMPIInt r1, PetscMPIInt *_st, PetscMPIInt *_rt)
267095059a4SDave May {
268095059a4SDave May   PetscMPIInt st,rt;
269095059a4SDave May 
270095059a4SDave May   st = N*r0 + r1   +   N*N*counter;
271095059a4SDave May   rt = N*r1 + r0   +   N*N*counter;
272095059a4SDave May   *_st = st;
273095059a4SDave May   *_rt = rt;
274095059a4SDave May }
275095059a4SDave May 
276095059a4SDave May /*
277095059a4SDave May Makes the communication map symmetric
278095059a4SDave May */
27977048351SPatrick Sanan PetscErrorCode _DMSwarmDataExCompleteCommunicationMap(MPI_Comm comm,PetscMPIInt n,PetscMPIInt proc_neighbours[],PetscMPIInt *n_new,PetscMPIInt **proc_neighbours_new)
280095059a4SDave May {
281dcf43ee8SDave May   Mat               A;
282095059a4SDave May   PetscInt          i,j,nc;
283095059a4SDave May   PetscInt          n_, *proc_neighbours_;
284e4fbd051SBarry Smith   PetscInt          rank_;
285e4fbd051SBarry Smith   PetscMPIInt       size,  rank;
286095059a4SDave May   PetscScalar       *vals;
287095059a4SDave May   const PetscInt    *cols;
288095059a4SDave May   const PetscScalar *red_vals;
289095059a4SDave May   PetscMPIInt       _n_new, *_proc_neighbours_new;
290095059a4SDave May 
291095059a4SDave May   PetscFunctionBegin;
292095059a4SDave May   n_ = n;
293*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc(sizeof(PetscInt) * n_, &proc_neighbours_));
294521f74f9SMatthew G. Knepley   for (i = 0; i < n_; ++i) {
295095059a4SDave May     proc_neighbours_[i] = proc_neighbours[i];
296095059a4SDave May   }
297*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm,&size));
298*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm,&rank));
299e4fbd051SBarry Smith   rank_ = rank;
300095059a4SDave May 
301*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatCreate(comm,&A));
302*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,size,size));
303*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetType(A,MATAIJ));
304*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSeqAIJSetPreallocation(A,1,NULL));
305*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatMPIAIJSetPreallocation(A,n_,NULL,n_,NULL));
306*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE));
307095059a4SDave May   /* Build original map */
308*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(n_, &vals));
309521f74f9SMatthew G. Knepley   for (i = 0; i < n_; ++i) {
310095059a4SDave May     vals[i] = 1.0;
311095059a4SDave May   }
312*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetValues( A, 1,&rank_, n_,proc_neighbours_, vals, INSERT_VALUES));
313*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(A,MAT_FLUSH_ASSEMBLY));
314*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(A,MAT_FLUSH_ASSEMBLY));
315095059a4SDave May   /* Now force all other connections if they are not already there */
316095059a4SDave May   /* It's more efficient to do them all at once */
317521f74f9SMatthew G. Knepley   for (i = 0; i < n_; ++i) {
318095059a4SDave May     vals[i] = 2.0;
319095059a4SDave May   }
320*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatSetValues( A, n_,proc_neighbours_, 1,&rank_, vals, INSERT_VALUES));
321*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY));
322*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY));
3236275818cSDave May /*
324*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO));
325*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatView(A,PETSC_VIEWER_STDOUT_WORLD));
326*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD));
3276275818cSDave May */
328095059a4SDave May   if ((n_new != NULL) && (proc_neighbours_new != NULL)) {
329*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatGetRow(A, rank_, &nc, &cols, &red_vals));
330095059a4SDave May     _n_new = (PetscMPIInt) nc;
331*5f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(_n_new, &_proc_neighbours_new));
332521f74f9SMatthew G. Knepley     for (j = 0; j < nc; ++j) {
333095059a4SDave May       _proc_neighbours_new[j] = (PetscMPIInt)cols[j];
334095059a4SDave May     }
335*5f80ce2aSJacob Faibussowitsch     CHKERRQ(MatRestoreRow( A, rank_, &nc, &cols, &red_vals));
336095059a4SDave May     *n_new               = (PetscMPIInt)_n_new;
337095059a4SDave May     *proc_neighbours_new = (PetscMPIInt*)_proc_neighbours_new;
338095059a4SDave May   }
339*5f80ce2aSJacob Faibussowitsch   CHKERRQ(MatDestroy(&A));
340*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(vals));
341*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(proc_neighbours_));
342*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Barrier(comm));
343095059a4SDave May   PetscFunctionReturn(0);
344095059a4SDave May }
345095059a4SDave May 
34677048351SPatrick Sanan PetscErrorCode DMSwarmDataExTopologyFinalize(DMSwarmDataEx d)
347095059a4SDave May {
3485627991aSBarry Smith   PetscMPIInt    symm_nn, *symm_procs, r0,n,st,rt, size;
349095059a4SDave May 
350095059a4SDave May   PetscFunctionBegin;
3512c71b3e2SJacob Faibussowitsch   PetscCheckFalse(d->topology_status != DEOBJECT_INITIALIZED,d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be initialised. Call DMSwarmDataExTopologyInitialize() first");
3522064fc68SDave May 
353*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMSWARM_DataExchangerTopologySetup,0,0,0,0));
354a5b23f4aSJose E. Roman   /* given information about all my neighbours, make map symmetric */
355*5f80ce2aSJacob Faibussowitsch   CHKERRQ(_DMSwarmDataExCompleteCommunicationMap( d->comm,d->n_neighbour_procs,d->neighbour_procs, &symm_nn, &symm_procs));
356095059a4SDave May   /* update my arrays */
357*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(d->neighbour_procs));
358095059a4SDave May   d->n_neighbour_procs = symm_nn;
359095059a4SDave May   d->neighbour_procs   = symm_procs;
360095059a4SDave May   /* allocates memory */
361*5f80ce2aSJacob Faibussowitsch   if (!d->messages_to_be_sent) CHKERRQ(PetscMalloc1(d->n_neighbour_procs+1, &d->messages_to_be_sent));
362*5f80ce2aSJacob Faibussowitsch   if (!d->message_offsets) CHKERRQ(PetscMalloc1(d->n_neighbour_procs+1, &d->message_offsets));
363*5f80ce2aSJacob Faibussowitsch   if (!d->messages_to_be_recvieved) CHKERRQ(PetscMalloc1(d->n_neighbour_procs+1, &d->messages_to_be_recvieved));
364*5f80ce2aSJacob Faibussowitsch   if (!d->pack_cnt) CHKERRQ(PetscMalloc(sizeof(PetscInt) * d->n_neighbour_procs, &d->pack_cnt));
365*5f80ce2aSJacob Faibussowitsch   if (!d->_stats) CHKERRQ(PetscMalloc(sizeof(MPI_Status) * 2*d->n_neighbour_procs, &d->_stats));
366*5f80ce2aSJacob Faibussowitsch   if (!d->_requests) CHKERRQ(PetscMalloc(sizeof(MPI_Request) * 2*d->n_neighbour_procs, &d->_requests));
367*5f80ce2aSJacob Faibussowitsch   if (!d->send_tags) CHKERRQ(PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->send_tags));
368*5f80ce2aSJacob Faibussowitsch   if (!d->recv_tags) CHKERRQ(PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->recv_tags));
369095059a4SDave May   /* compute message tags */
370*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(d->comm,&size));
371095059a4SDave May   r0 = d->rank;
372521f74f9SMatthew G. Knepley   for (n = 0; n < d->n_neighbour_procs; ++n) {
373095059a4SDave May     PetscMPIInt r1 = d->neighbour_procs[n];
374095059a4SDave May 
375d7d19db6SBarry Smith     _get_tags( d->instance, size, r0,r1, &st, &rt);
376095059a4SDave May     d->send_tags[n] = (int)st;
377095059a4SDave May     d->recv_tags[n] = (int)rt;
378095059a4SDave May   }
379095059a4SDave May   d->topology_status = DEOBJECT_FINALIZED;
380*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMSWARM_DataExchangerTopologySetup,0,0,0,0));
381095059a4SDave May   PetscFunctionReturn(0);
382095059a4SDave May }
383095059a4SDave May 
384095059a4SDave May /* === Phase B === */
38577048351SPatrick Sanan PetscErrorCode _DMSwarmDataExConvertProcIdToLocalIndex(DMSwarmDataEx de,PetscMPIInt proc_id,PetscMPIInt *local)
386095059a4SDave May {
387095059a4SDave May   PetscMPIInt i,np;
388095059a4SDave May 
389095059a4SDave May   PetscFunctionBegin;
390095059a4SDave May   np = de->n_neighbour_procs;
391095059a4SDave May   *local = -1;
392521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
393095059a4SDave May     if (proc_id == de->neighbour_procs[i]) {
394095059a4SDave May       *local = i;
395095059a4SDave May       break;
396095059a4SDave May     }
397095059a4SDave May   }
398095059a4SDave May   PetscFunctionReturn(0);
399095059a4SDave May }
400095059a4SDave May 
40177048351SPatrick Sanan PetscErrorCode DMSwarmDataExInitializeSendCount(DMSwarmDataEx de)
402095059a4SDave May {
403095059a4SDave May   PetscMPIInt    i;
404095059a4SDave May 
405095059a4SDave May   PetscFunctionBegin;
4062c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->topology_status != DEOBJECT_FINALIZED,de->comm, PETSC_ERR_ORDER, "Topology not finalized");
407*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMSWARM_DataExchangerSendCount,0,0,0,0));
408095059a4SDave May   de->message_lengths_status = DEOBJECT_INITIALIZED;
409521f74f9SMatthew G. Knepley   for (i = 0; i < de->n_neighbour_procs; ++i) {
410095059a4SDave May     de->messages_to_be_sent[i] = 0;
411095059a4SDave May   }
412095059a4SDave May   PetscFunctionReturn(0);
413095059a4SDave May }
414095059a4SDave May 
415095059a4SDave May /*
416095059a4SDave May 1) only allows counters to be set on neighbouring cpus
417095059a4SDave May */
41877048351SPatrick Sanan PetscErrorCode DMSwarmDataExAddToSendCount(DMSwarmDataEx de,const PetscMPIInt proc_id,const PetscInt count)
419095059a4SDave May {
420095059a4SDave May   PetscMPIInt    local_val;
421095059a4SDave May 
422095059a4SDave May   PetscFunctionBegin;
4232c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->message_lengths_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths have been defined. To modify these call DMSwarmDataExInitializeSendCount() first");
4242c71b3e2SJacob Faibussowitsch   else PetscCheckFalse(de->message_lengths_status != DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DMSwarmDataExInitializeSendCount() first");
4252064fc68SDave May 
426*5f80ce2aSJacob Faibussowitsch   CHKERRQ(_DMSwarmDataExConvertProcIdToLocalIndex( de, proc_id, &local_val));
4272c71b3e2SJacob Faibussowitsch   PetscCheckFalse(local_val == -1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,"Proc %d is not a valid neighbour rank", (int)proc_id);
4282064fc68SDave May 
429095059a4SDave May   de->messages_to_be_sent[local_val] = de->messages_to_be_sent[local_val] + count;
430095059a4SDave May   PetscFunctionReturn(0);
431095059a4SDave May }
432095059a4SDave May 
43377048351SPatrick Sanan PetscErrorCode DMSwarmDataExFinalizeSendCount(DMSwarmDataEx de)
434095059a4SDave May {
435095059a4SDave May   PetscFunctionBegin;
4362c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->message_lengths_status != DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DMSwarmDataExInitializeSendCount() first");
4372064fc68SDave May 
438095059a4SDave May   de->message_lengths_status = DEOBJECT_FINALIZED;
439*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMSWARM_DataExchangerSendCount,0,0,0,0));
440095059a4SDave May   PetscFunctionReturn(0);
441095059a4SDave May }
442095059a4SDave May 
443095059a4SDave May /* === Phase C === */
444095059a4SDave May /*
4455627991aSBarry Smith   zero out all send counts
4465627991aSBarry Smith   free send and recv buffers
4475627991aSBarry Smith   zeros out message length
4485627991aSBarry Smith   zeros out all counters
4495627991aSBarry Smith   zero out packed data counters
450095059a4SDave May */
45177048351SPatrick Sanan PetscErrorCode _DMSwarmDataExInitializeTmpStorage(DMSwarmDataEx de)
452095059a4SDave May {
453095059a4SDave May   PetscMPIInt    i, np;
454095059a4SDave May 
455095059a4SDave May   PetscFunctionBegin;
456095059a4SDave May   np = de->n_neighbour_procs;
457521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
458095059a4SDave May     /*  de->messages_to_be_sent[i] = -1; */
459095059a4SDave May     de->messages_to_be_recvieved[i] = -1;
460095059a4SDave May   }
461*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(de->send_message));
462*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(de->recv_message));
463095059a4SDave May   PetscFunctionReturn(0);
464095059a4SDave May }
465095059a4SDave May 
466095059a4SDave May /*
4675627991aSBarry Smith    Zeros out pack data counters
4685627991aSBarry Smith    Ensures mesaage length is set
4695627991aSBarry Smith    Checks send counts properly initialized
4705627991aSBarry Smith    allocates space for pack data
471095059a4SDave May */
47277048351SPatrick Sanan PetscErrorCode DMSwarmDataExPackInitialize(DMSwarmDataEx de,size_t unit_message_size)
473095059a4SDave May {
474095059a4SDave May   PetscMPIInt    i,np;
475095059a4SDave May   PetscInt       total;
476095059a4SDave May 
477095059a4SDave May   PetscFunctionBegin;
4782c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->topology_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Topology not finalized");
4792c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->message_lengths_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths not finalized");
480*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMSWARM_DataExchangerPack,0,0,0,0));
481095059a4SDave May   de->packer_status = DEOBJECT_INITIALIZED;
482*5f80ce2aSJacob Faibussowitsch   CHKERRQ(_DMSwarmDataExInitializeTmpStorage(de));
483095059a4SDave May   np = de->n_neighbour_procs;
484095059a4SDave May   de->unit_message_size = unit_message_size;
485095059a4SDave May   total = 0;
486521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
487095059a4SDave May     if (de->messages_to_be_sent[i] == -1) {
488095059a4SDave May       PetscMPIInt proc_neighour = de->neighbour_procs[i];
48998921bdaSJacob Faibussowitsch       SETERRQ( PETSC_COMM_SELF, PETSC_ERR_ORDER, "Messages_to_be_sent[neighbour_proc=%d] is un-initialised. Call DMSwarmDataExSetSendCount() first", (int)proc_neighour);
490095059a4SDave May     }
491095059a4SDave May     total = total + de->messages_to_be_sent[i];
492095059a4SDave May   }
493095059a4SDave May   /* create space for the data to be sent */
494*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc(unit_message_size * (total + 1), &de->send_message));
495095059a4SDave May   /* initialize memory */
496*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMemzero(de->send_message, unit_message_size * (total + 1)));
497095059a4SDave May   /* set total items to send */
498095059a4SDave May   de->send_message_length = total;
499095059a4SDave May   de->message_offsets[0] = 0;
500095059a4SDave May   total = de->messages_to_be_sent[0];
501521f74f9SMatthew G. Knepley   for (i = 1; i < np; ++i) {
502095059a4SDave May     de->message_offsets[i] = total;
503095059a4SDave May     total = total + de->messages_to_be_sent[i];
504095059a4SDave May   }
505095059a4SDave May   /* init the packer counters */
506095059a4SDave May   de->total_pack_cnt = 0;
507521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
508095059a4SDave May     de->pack_cnt[i] = 0;
509095059a4SDave May   }
510095059a4SDave May   PetscFunctionReturn(0);
511095059a4SDave May }
512095059a4SDave May 
513095059a4SDave May /*
5145627991aSBarry Smith     Ensures data gets been packed appropriately and no overlaps occur
515095059a4SDave May */
51677048351SPatrick Sanan PetscErrorCode DMSwarmDataExPackData(DMSwarmDataEx de,PetscMPIInt proc_id,PetscInt n,void *data)
517095059a4SDave May {
518095059a4SDave May   PetscMPIInt    local;
519095059a4SDave May   PetscInt       insert_location;
520095059a4SDave May   void           *dest;
521095059a4SDave May 
522095059a4SDave May   PetscFunctionBegin;
5232c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->packer_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Packed data have been defined. To modify these call DMSwarmDataExInitializeSendCount(), DMSwarmDataExAddToSendCount(), DMSwarmDataExPackInitialize() first");
5242c71b3e2SJacob Faibussowitsch   else PetscCheckFalse(de->packer_status != DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Packed data must be defined. Call DMSwarmDataExInitializeSendCount(), DMSwarmDataExAddToSendCount(), DMSwarmDataExPackInitialize() first");
5252064fc68SDave May 
5262c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!de->send_message, de->comm, PETSC_ERR_ORDER, "send_message is not initialized. Call DMSwarmDataExPackInitialize() first");
527*5f80ce2aSJacob Faibussowitsch   CHKERRQ(_DMSwarmDataExConvertProcIdToLocalIndex( de, proc_id, &local));
5282c71b3e2SJacob Faibussowitsch   PetscCheckFalse(local == -1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "proc_id %d is not registered neighbour", (int)proc_id);
5292c71b3e2SJacob Faibussowitsch   PetscCheckFalse(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 = %D: Attempt to insert %D",
530095059a4SDave May               (int)proc_id, de->messages_to_be_sent[local], n+de->pack_cnt[local]);
5312064fc68SDave May 
532095059a4SDave May   /* copy memory */
533095059a4SDave May   insert_location = de->message_offsets[local] + de->pack_cnt[local];
534095059a4SDave May   dest = ((char*)de->send_message) + de->unit_message_size*insert_location;
535*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMemcpy(dest, data, de->unit_message_size * n));
536095059a4SDave May   /* increment counter */
537095059a4SDave May   de->pack_cnt[local] = de->pack_cnt[local] + n;
538095059a4SDave May   PetscFunctionReturn(0);
539095059a4SDave May }
540095059a4SDave May 
541095059a4SDave May /*
542095059a4SDave May *) Ensures all data has been packed
543095059a4SDave May */
54477048351SPatrick Sanan PetscErrorCode DMSwarmDataExPackFinalize(DMSwarmDataEx de)
545095059a4SDave May {
546095059a4SDave May   PetscMPIInt    i,np;
547095059a4SDave May   PetscInt       total;
548095059a4SDave May 
549095059a4SDave May   PetscFunctionBegin;
5502c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->packer_status != DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Packer has not been initialized. Must call DMSwarmDataExPackInitialize() first.");
551095059a4SDave May   np = de->n_neighbour_procs;
552521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
5532c71b3e2SJacob Faibussowitsch     PetscCheckFalse(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 %D : Inserted %D",
554095059a4SDave May                 (int)de->neighbour_procs[i], de->messages_to_be_sent[i], de->pack_cnt[i]);
555095059a4SDave May   }
556095059a4SDave May   /* init */
557521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
558095059a4SDave May     de->messages_to_be_recvieved[i] = -1;
559095059a4SDave May   }
560095059a4SDave May   /* figure out the recv counts here */
561521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
562*5f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Isend(&de->messages_to_be_sent[i], 1, MPIU_INT, de->neighbour_procs[i], de->send_tags[i], de->comm, &de->_requests[i]));
563095059a4SDave May   }
564521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
565*5f80ce2aSJacob Faibussowitsch     CHKERRMPI(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]));
566095059a4SDave May   }
567*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Waitall(2*np, de->_requests, de->_stats));
568095059a4SDave May   /* create space for the data to be recvieved */
569095059a4SDave May   total = 0;
570521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
571095059a4SDave May     total = total + de->messages_to_be_recvieved[i];
572095059a4SDave May   }
573*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc(de->unit_message_size * (total + 1), &de->recv_message));
574095059a4SDave May   /* initialize memory */
575*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMemzero(de->recv_message, de->unit_message_size * (total + 1)));
5762d4ee042Sprj-   /* set total items to receive */
577095059a4SDave May   de->recv_message_length = total;
578095059a4SDave May   de->packer_status = DEOBJECT_FINALIZED;
579095059a4SDave May   de->communication_status = DEOBJECT_INITIALIZED;
580*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMSWARM_DataExchangerPack,0,0,0,0));
581095059a4SDave May   PetscFunctionReturn(0);
582095059a4SDave May }
583095059a4SDave May 
5845627991aSBarry Smith /* do the actual message passing */
58577048351SPatrick Sanan PetscErrorCode DMSwarmDataExBegin(DMSwarmDataEx de)
586095059a4SDave May {
587095059a4SDave May   PetscMPIInt    i,np;
588095059a4SDave May   void           *dest;
589095059a4SDave May   PetscInt       length;
590095059a4SDave May 
591095059a4SDave May   PetscFunctionBegin;
5922c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->topology_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Topology not finalized");
5932c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->message_lengths_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths not finalized");
5942c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->packer_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Packer not finalized");
5952c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->communication_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Communication has already been finalized. Must call DMSwarmDataExInitialize() first.");
5962c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!de->recv_message, de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DMSwarmDataExPackFinalize() first");
597*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMSWARM_DataExchangerBegin,0,0,0,0));
598095059a4SDave May   np = de->n_neighbour_procs;
599095059a4SDave May   /* == NON BLOCKING == */
600521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
601095059a4SDave May     length = de->messages_to_be_sent[i] * de->unit_message_size;
602095059a4SDave May     dest = ((char*)de->send_message) + de->unit_message_size * de->message_offsets[i];
603*5f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Isend( dest, length, MPI_CHAR, de->neighbour_procs[i], de->send_tags[i], de->comm, &de->_requests[i]));
604095059a4SDave May   }
605*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMSWARM_DataExchangerBegin,0,0,0,0));
606095059a4SDave May   PetscFunctionReturn(0);
607095059a4SDave May }
608095059a4SDave May 
609095059a4SDave May /* do the actual message passing now */
61077048351SPatrick Sanan PetscErrorCode DMSwarmDataExEnd(DMSwarmDataEx de)
611095059a4SDave May {
612095059a4SDave May   PetscMPIInt    i,np;
613095059a4SDave May   PetscInt       total;
614095059a4SDave May   PetscInt       *message_recv_offsets;
615095059a4SDave May   void           *dest;
616095059a4SDave May   PetscInt       length;
617095059a4SDave May 
618095059a4SDave May   PetscFunctionBegin;
6192c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->communication_status != DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Communication has not been initialized. Must call DMSwarmDataExInitialize() first.");
6202c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!de->recv_message, de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DMSwarmDataExPackFinalize() first");
621*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventBegin(DMSWARM_DataExchangerEnd,0,0,0,0));
622095059a4SDave May   np = de->n_neighbour_procs;
623*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc1(np+1, &message_recv_offsets));
624095059a4SDave May   message_recv_offsets[0] = 0;
625095059a4SDave May   total = de->messages_to_be_recvieved[0];
626521f74f9SMatthew G. Knepley   for (i = 1; i < np; ++i) {
627095059a4SDave May     message_recv_offsets[i] = total;
628095059a4SDave May     total = total + de->messages_to_be_recvieved[i];
629095059a4SDave May   }
630095059a4SDave May   /* == NON BLOCKING == */
631521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
632095059a4SDave May     length = de->messages_to_be_recvieved[i] * de->unit_message_size;
633095059a4SDave May     dest = ((char*)de->recv_message) + de->unit_message_size * message_recv_offsets[i];
634*5f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Irecv( dest, length, MPI_CHAR, de->neighbour_procs[i], de->recv_tags[i], de->comm, &de->_requests[np+i]));
635095059a4SDave May   }
636*5f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Waitall( 2*np, de->_requests, de->_stats));
637*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(message_recv_offsets));
638095059a4SDave May   de->communication_status = DEOBJECT_FINALIZED;
639*5f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscLogEventEnd(DMSWARM_DataExchangerEnd,0,0,0,0));
640095059a4SDave May   PetscFunctionReturn(0);
641095059a4SDave May }
642095059a4SDave May 
64377048351SPatrick Sanan PetscErrorCode DMSwarmDataExGetSendData(DMSwarmDataEx de,PetscInt *length,void **send)
644095059a4SDave May {
645095059a4SDave May   PetscFunctionBegin;
6462c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->packer_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being packed.");
647095059a4SDave May   *length = de->send_message_length;
648095059a4SDave May   *send   = de->send_message;
649095059a4SDave May   PetscFunctionReturn(0);
650095059a4SDave May }
651095059a4SDave May 
65277048351SPatrick Sanan PetscErrorCode DMSwarmDataExGetRecvData(DMSwarmDataEx de,PetscInt *length,void **recv)
653095059a4SDave May {
654095059a4SDave May   PetscFunctionBegin;
6552c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->communication_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being sent.");
656095059a4SDave May   *length = de->recv_message_length;
657095059a4SDave May   *recv   = de->recv_message;
658095059a4SDave May   PetscFunctionReturn(0);
659095059a4SDave May }
660095059a4SDave May 
66177048351SPatrick Sanan PetscErrorCode DMSwarmDataExTopologyGetNeighbours(DMSwarmDataEx de,PetscMPIInt *n,PetscMPIInt *neigh[])
662095059a4SDave May {
663095059a4SDave May   PetscFunctionBegin;
664095059a4SDave May   if (n)     {*n     = de->n_neighbour_procs;}
665095059a4SDave May   if (neigh) {*neigh = de->neighbour_procs;}
666095059a4SDave May   PetscFunctionReturn(0);
667095059a4SDave May }
668