xref: /petsc/src/dm/impls/swarm/data_ex.c (revision ed923d712065d5cd07973a5b5fb0ac097e7d6cf0)
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 
17095059a4SDave May Eg: Proc 0 send to proc 1 with message id is 10. To recieve the correct
18095059a4SDave May message, proc 1 looks for the edge connected to proc 0, and then the
19095059a4SDave May messgae 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 
36095059a4SDave May User has to unpack message themselves. I can get you the pointer for each i
37095059a4SDave May entry, but you'll have to cast it to the appropriate data type.
38095059a4SDave May 
39095059a4SDave May 
40095059a4SDave May 
41095059a4SDave May 
42095059a4SDave May Phase A: Build topology
43095059a4SDave May 
44095059a4SDave May Phase B: Define message lengths
45095059a4SDave May 
46095059a4SDave May Phase C: Pack data
47095059a4SDave May 
48095059a4SDave May Phase D: Send data
49095059a4SDave May 
502064fc68SDave May + Constructor
51095059a4SDave May DataExCreate()
522064fc68SDave May + Phase A
53095059a4SDave May DataExTopologyInitialize()
54095059a4SDave May DataExTopologyAddNeighbour()
55095059a4SDave May DataExTopologyAddNeighbour()
56095059a4SDave May DataExTopologyFinalize()
572064fc68SDave May + Phase B
58095059a4SDave May DataExZeroAllSendCount()
59095059a4SDave May DataExAddToSendCount()
60095059a4SDave May DataExAddToSendCount()
61095059a4SDave May DataExAddToSendCount()
622064fc68SDave May + Phase C
63095059a4SDave May DataExPackInitialize()
64095059a4SDave May DataExPackData()
65095059a4SDave May DataExPackData()
66095059a4SDave May DataExPackFinalize()
672064fc68SDave May +Phase D
68095059a4SDave May DataExBegin()
692064fc68SDave May  ... perform any calculations ...
70095059a4SDave May DataExEnd()
71095059a4SDave May 
722064fc68SDave May ... user calls any getters here ...
73095059a4SDave May 
74095059a4SDave May 
75095059a4SDave May */
76095059a4SDave May 
77095059a4SDave May #include <petsc.h>
78095059a4SDave May #include <petscvec.h>
79095059a4SDave May #include <petscmat.h>
80095059a4SDave May 
81095059a4SDave May #include "data_ex.h"
82095059a4SDave May 
83095059a4SDave May const char *status_names[] = {"initialized", "finalized", "unknown"};
84095059a4SDave May 
85*ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerTopologySetup;
86*ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerBegin;
87*ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerEnd;
88*ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerSendCount;
89*ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerPack;
90095059a4SDave May 
91521f74f9SMatthew G. Knepley PetscErrorCode DataExCreate(MPI_Comm comm,const PetscInt count, DataEx *ex)
92095059a4SDave May {
93095059a4SDave May   PetscErrorCode ierr;
94521f74f9SMatthew G. Knepley   DataEx         d;
95095059a4SDave May 
96521f74f9SMatthew G. Knepley   PetscFunctionBegin;
97521f74f9SMatthew G. Knepley   ierr = PetscMalloc(sizeof(struct _p_DataEx), &d);CHKERRQ(ierr);
98521f74f9SMatthew G. Knepley   ierr = PetscMemzero(d, sizeof(struct _p_DataEx));CHKERRQ(ierr);
99521f74f9SMatthew G. Knepley   ierr = MPI_Comm_dup(comm,&d->comm);CHKERRQ(ierr);
100521f74f9SMatthew G. Knepley   ierr = MPI_Comm_rank(d->comm,&d->rank);CHKERRQ(ierr);
101095059a4SDave May 
102095059a4SDave May   d->instance = count;
103095059a4SDave May 
104095059a4SDave May   d->topology_status        = DEOBJECT_STATE_UNKNOWN;
105095059a4SDave May   d->message_lengths_status = DEOBJECT_STATE_UNKNOWN;
106095059a4SDave May   d->packer_status          = DEOBJECT_STATE_UNKNOWN;
107095059a4SDave May   d->communication_status   = DEOBJECT_STATE_UNKNOWN;
108095059a4SDave May 
109095059a4SDave May   d->n_neighbour_procs = -1;
110095059a4SDave May   d->neighbour_procs   = NULL;
111095059a4SDave May 
112095059a4SDave May   d->messages_to_be_sent      = NULL;
113095059a4SDave May   d->message_offsets          = NULL;
114095059a4SDave May   d->messages_to_be_recvieved = NULL;
115095059a4SDave May 
116095059a4SDave May   d->unit_message_size   = -1;
117095059a4SDave May   d->send_message        = NULL;
118095059a4SDave May   d->send_message_length = -1;
119095059a4SDave May   d->recv_message        = NULL;
120095059a4SDave May   d->recv_message_length = -1;
121095059a4SDave May   d->total_pack_cnt      = -1;
122095059a4SDave May   d->pack_cnt            = NULL;
123095059a4SDave May 
124095059a4SDave May   d->send_tags = NULL;
125095059a4SDave May   d->recv_tags = NULL;
126095059a4SDave May 
127095059a4SDave May   d->_stats    = NULL;
128095059a4SDave May   d->_requests = NULL;
129521f74f9SMatthew G. Knepley   *ex = d;
130521f74f9SMatthew G. Knepley   PetscFunctionReturn(0);
131095059a4SDave May }
132095059a4SDave May 
133095059a4SDave May PetscErrorCode DataExView(DataEx d)
134095059a4SDave May {
135095059a4SDave May   PetscMPIInt p;
136521f74f9SMatthew G. Knepley   PetscErrorCode ierr;
137095059a4SDave May 
138095059a4SDave May   PetscFunctionBegin;
139521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "DataEx: instance=%D\n",d->instance);CHKERRQ(ierr);
140521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  topology status:        %s \n", status_names[d->topology_status]);CHKERRQ(ierr);
141521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  message lengths status: %s \n", status_names[d->message_lengths_status] );CHKERRQ(ierr);
142521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  packer status status:   %s \n", status_names[d->packer_status] );CHKERRQ(ierr);
143521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  communication status:   %s \n", status_names[d->communication_status] );CHKERRQ(ierr);
144095059a4SDave May 
145095059a4SDave May   if (d->topology_status == DEOBJECT_FINALIZED) {
146521f74f9SMatthew G. Knepley     ierr = PetscPrintf( PETSC_COMM_WORLD, "  Topology:\n");CHKERRQ(ierr);
147521f74f9SMatthew G. Knepley     ierr = PetscPrintf( PETSC_COMM_SELF, "    [%d] neighbours: %d \n", (int)d->rank, (int)d->n_neighbour_procs );CHKERRQ(ierr);
148095059a4SDave May     for (p=0; p<d->n_neighbour_procs; p++) {
149521f74f9SMatthew G. Knepley       ierr = PetscPrintf( PETSC_COMM_SELF, "    [%d]   neighbour[%D] = %d \n", (int)d->rank, p, (int)d->neighbour_procs[p]);CHKERRQ(ierr);
150095059a4SDave May     }
151095059a4SDave May   }
152095059a4SDave May   if (d->message_lengths_status == DEOBJECT_FINALIZED) {
153521f74f9SMatthew G. Knepley     ierr = PetscPrintf( PETSC_COMM_WORLD, "  Message lengths:\n");CHKERRQ(ierr);
154521f74f9SMatthew G. Knepley     ierr = PetscPrintf( PETSC_COMM_SELF, "    [%d] atomic size: %ld \n", (int)d->rank, (long int)d->unit_message_size );CHKERRQ(ierr);
155095059a4SDave May     for (p=0; p<d->n_neighbour_procs; p++) {
156521f74f9SMatthew G. Knepley       ierr = PetscPrintf( PETSC_COMM_SELF, "    [%d] >>>>> ( %D units :: tag = %d ) >>>>> [%d] \n", (int)d->rank, d->messages_to_be_sent[p], d->send_tags[p], (int)d->neighbour_procs[p] );CHKERRQ(ierr);
157095059a4SDave May     }
158095059a4SDave May     for (p=0; p<d->n_neighbour_procs; p++) {
159521f74f9SMatthew G. Knepley       ierr = PetscPrintf( PETSC_COMM_SELF, "    [%d] <<<<< ( %D units :: tag = %d ) <<<<< [%d] \n", (int)d->rank, d->messages_to_be_recvieved[p], d->recv_tags[p], (int)d->neighbour_procs[p] );CHKERRQ(ierr);
160095059a4SDave May     }
161095059a4SDave May   }
162521f74f9SMatthew G. Knepley   if (d->packer_status == DEOBJECT_FINALIZED) {}
163521f74f9SMatthew G. Knepley   if (d->communication_status == DEOBJECT_FINALIZED) {}
164095059a4SDave May   PetscFunctionReturn(0);
165095059a4SDave May }
166095059a4SDave May 
167095059a4SDave May PetscErrorCode DataExDestroy(DataEx d)
168095059a4SDave May {
169095059a4SDave May   PetscErrorCode ierr;
170095059a4SDave May 
171095059a4SDave May   PetscFunctionBegin;
172095059a4SDave May   ierr = MPI_Comm_free(&d->comm);CHKERRQ(ierr);
173521f74f9SMatthew G. Knepley   if (d->neighbour_procs) {ierr = PetscFree(d->neighbour_procs);CHKERRQ(ierr);}
174521f74f9SMatthew G. Knepley   if (d->messages_to_be_sent) {ierr = PetscFree(d->messages_to_be_sent);CHKERRQ(ierr);}
175521f74f9SMatthew G. Knepley   if (d->message_offsets) {ierr = PetscFree(d->message_offsets);CHKERRQ(ierr);}
176521f74f9SMatthew G. Knepley   if (d->messages_to_be_recvieved) {ierr = PetscFree(d->messages_to_be_recvieved);CHKERRQ(ierr);}
177521f74f9SMatthew G. Knepley   if (d->send_message) {ierr = PetscFree(d->send_message);CHKERRQ(ierr);}
178521f74f9SMatthew G. Knepley   if (d->recv_message) {ierr = PetscFree(d->recv_message);CHKERRQ(ierr);}
179521f74f9SMatthew G. Knepley   if (d->pack_cnt) {ierr = PetscFree(d->pack_cnt);CHKERRQ(ierr);}
180521f74f9SMatthew G. Knepley   if (d->send_tags) {ierr = PetscFree(d->send_tags);CHKERRQ(ierr);}
181521f74f9SMatthew G. Knepley   if (d->recv_tags) {ierr = PetscFree(d->recv_tags);CHKERRQ(ierr);}
182521f74f9SMatthew G. Knepley   if (d->_stats) {ierr = PetscFree(d->_stats);CHKERRQ(ierr);}
183521f74f9SMatthew G. Knepley   if (d->_requests) {ierr = PetscFree(d->_requests);CHKERRQ(ierr);}
184521f74f9SMatthew G. Knepley   ierr = PetscFree(d);CHKERRQ(ierr);
185095059a4SDave May   PetscFunctionReturn(0);
186095059a4SDave May }
187095059a4SDave May 
188095059a4SDave May /* === Phase A === */
189095059a4SDave May 
190095059a4SDave May PetscErrorCode DataExTopologyInitialize(DataEx d)
191095059a4SDave May {
192521f74f9SMatthew G. Knepley   PetscErrorCode ierr;
193521f74f9SMatthew G. Knepley 
194095059a4SDave May   PetscFunctionBegin;
195095059a4SDave May   d->topology_status = DEOBJECT_INITIALIZED;
196095059a4SDave May   d->n_neighbour_procs = 0;
197781df12bSMatthew G. Knepley   ierr = PetscFree(d->neighbour_procs);CHKERRQ(ierr);
198781df12bSMatthew G. Knepley   ierr = PetscFree(d->messages_to_be_sent);CHKERRQ(ierr);
199781df12bSMatthew G. Knepley   ierr = PetscFree(d->message_offsets);CHKERRQ(ierr);
200781df12bSMatthew G. Knepley   ierr = PetscFree(d->messages_to_be_recvieved);CHKERRQ(ierr);
201781df12bSMatthew G. Knepley   ierr = PetscFree(d->pack_cnt);CHKERRQ(ierr);
202781df12bSMatthew G. Knepley   ierr = PetscFree(d->send_tags);CHKERRQ(ierr);
203781df12bSMatthew G. Knepley   ierr = PetscFree(d->recv_tags);CHKERRQ(ierr);
204095059a4SDave May   PetscFunctionReturn(0);
205095059a4SDave May }
206095059a4SDave May 
207095059a4SDave May PetscErrorCode DataExTopologyAddNeighbour(DataEx d,const PetscMPIInt proc_id)
208095059a4SDave May {
209095059a4SDave May   PetscMPIInt    n,found;
210095059a4SDave May   PetscMPIInt    nproc;
211095059a4SDave May   PetscErrorCode ierr;
212095059a4SDave May 
213095059a4SDave May   PetscFunctionBegin;
2142064fc68SDave May   if (d->topology_status == DEOBJECT_FINALIZED) SETERRQ(d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology has been finalized. To modify or update call DataExTopologyInitialize() first");
2152064fc68SDave May   else if (d->topology_status != DEOBJECT_INITIALIZED) SETERRQ(d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be intialised. Call DataExTopologyInitialize() first");
2162064fc68SDave May 
217095059a4SDave May   /* error on negative entries */
218521f74f9SMatthew G. Knepley   if (proc_id < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Trying to set proc neighbour with a rank < 0");
219095059a4SDave May   /* error on ranks larger than number of procs in communicator */
220095059a4SDave May   ierr = MPI_Comm_size(d->comm,&nproc);CHKERRQ(ierr);
221521f74f9SMatthew G. Knepley   if (proc_id >= nproc) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Trying to set proc neighbour with a rank >= nproc");
222521f74f9SMatthew G. Knepley   if (d->n_neighbour_procs == 0) {ierr = PetscMalloc1(1, &d->neighbour_procs);CHKERRQ(ierr);}
223095059a4SDave May   /* check for proc_id */
224095059a4SDave May   found = 0;
225095059a4SDave May   for (n = 0; n < d->n_neighbour_procs; n++) {
226095059a4SDave May     if (d->neighbour_procs[n] == proc_id) {
227095059a4SDave May       found  = 1;
228095059a4SDave May     }
229095059a4SDave May   }
230095059a4SDave May   if (found == 0) { /* add it to list */
2314be7464cSMatthew G. Knepley     ierr = PetscRealloc(sizeof(PetscMPIInt)*(d->n_neighbour_procs+1), &d->neighbour_procs);CHKERRQ(ierr);
232095059a4SDave May     d->neighbour_procs[ d->n_neighbour_procs ] = proc_id;
233095059a4SDave May     d->n_neighbour_procs++;
234095059a4SDave May   }
235095059a4SDave May   PetscFunctionReturn(0);
236095059a4SDave May }
237095059a4SDave May 
238095059a4SDave May /*
239095059a4SDave May counter: the index of the communication object
240095059a4SDave May N: the number of processors
241095059a4SDave May r0: rank of sender
242095059a4SDave May r1: rank of receiver
243095059a4SDave May 
244095059a4SDave May procs = { 0, 1, 2, 3 }
245095059a4SDave May 
246095059a4SDave May 0 ==> 0		e=0
247095059a4SDave May 0 ==> 1		e=1
248095059a4SDave May 0 ==> 2		e=2
249095059a4SDave May 0 ==> 3		e=3
250095059a4SDave May 
251095059a4SDave May 1 ==> 0		e=4
252095059a4SDave May 1 ==> 1		e=5
253095059a4SDave May 1 ==> 2		e=6
254095059a4SDave May 1 ==> 3		e=7
255095059a4SDave May 
256095059a4SDave May 2 ==> 0		e=8
257095059a4SDave May 2 ==> 1		e=9
258095059a4SDave May 2 ==> 2		e=10
259095059a4SDave May 2 ==> 3		e=11
260095059a4SDave May 
261095059a4SDave May 3 ==> 0		e=12
262095059a4SDave May 3 ==> 1		e=13
263095059a4SDave May 3 ==> 2		e=14
264095059a4SDave May 3 ==> 3		e=15
265095059a4SDave May 
266095059a4SDave May If we require that proc A sends to proc B, then the SEND tag index will be given by
267095059a4SDave May   N * rank(A) + rank(B) + offset
268095059a4SDave May If we require that proc A will receive from proc B, then the RECV tag index will be given by
269095059a4SDave May   N * rank(B) + rank(A) + offset
270095059a4SDave May 
271095059a4SDave May */
272521f74f9SMatthew G. Knepley static void _get_tags(PetscInt counter, PetscMPIInt N, PetscMPIInt r0,PetscMPIInt r1, PetscMPIInt *_st, PetscMPIInt *_rt)
273095059a4SDave May {
274095059a4SDave May   PetscMPIInt st,rt;
275095059a4SDave May 
276095059a4SDave May   st = N*r0 + r1   +   N*N*counter;
277095059a4SDave May   rt = N*r1 + r0   +   N*N*counter;
278095059a4SDave May   *_st = st;
279095059a4SDave May   *_rt = rt;
280095059a4SDave May }
281095059a4SDave May 
282095059a4SDave May /*
283095059a4SDave May Makes the communication map symmetric
284095059a4SDave May */
285095059a4SDave May PetscErrorCode _DataExCompleteCommunicationMap(MPI_Comm comm,PetscMPIInt n,PetscMPIInt proc_neighbours[],PetscMPIInt *n_new,PetscMPIInt **proc_neighbours_new)
286095059a4SDave May {
287dcf43ee8SDave May   Mat               A;
288095059a4SDave May   PetscInt          i,j,nc;
289095059a4SDave May   PetscInt          n_, *proc_neighbours_;
290095059a4SDave May   PetscInt          rank_i_;
291095059a4SDave May   PetscMPIInt       size,  rank_i;
292095059a4SDave May   PetscScalar       *vals;
293095059a4SDave May   const PetscInt    *cols;
294095059a4SDave May   const PetscScalar *red_vals;
295095059a4SDave May   PetscMPIInt       _n_new, *_proc_neighbours_new;
296095059a4SDave May   PetscErrorCode    ierr;
297095059a4SDave May 
298095059a4SDave May   PetscFunctionBegin;
299095059a4SDave May   n_ = n;
300095059a4SDave May   ierr = PetscMalloc(sizeof(PetscInt) * n_, &proc_neighbours_);CHKERRQ(ierr);
301521f74f9SMatthew G. Knepley   for (i = 0; i < n_; ++i) {
302095059a4SDave May     proc_neighbours_[i] = proc_neighbours[i];
303095059a4SDave May   }
304095059a4SDave May   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
305095059a4SDave May   ierr = MPI_Comm_rank(comm,&rank_i);CHKERRQ(ierr);
306095059a4SDave May   rank_i_ = rank_i;
307095059a4SDave May 
308095059a4SDave May   ierr = MatCreate(comm,&A);CHKERRQ(ierr);
309095059a4SDave May   ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,size,size);CHKERRQ(ierr);
310095059a4SDave May   ierr = MatSetType(A,MATAIJ);CHKERRQ(ierr);
311dcf43ee8SDave May   ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
312dcf43ee8SDave May   ierr = MatMPIAIJSetPreallocation(A,n_,NULL,n_,NULL);CHKERRQ(ierr);
313dcf43ee8SDave May   ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);CHKERRQ(ierr);
314095059a4SDave May   /* Build original map */
315521f74f9SMatthew G. Knepley   ierr = PetscMalloc1(n_, &vals);CHKERRQ(ierr);
316521f74f9SMatthew G. Knepley   for (i = 0; i < n_; ++i) {
317095059a4SDave May     vals[i] = 1.0;
318095059a4SDave May   }
319095059a4SDave May   ierr = MatSetValues( A, 1,&rank_i_, n_,proc_neighbours_, vals, INSERT_VALUES );CHKERRQ(ierr);
320095059a4SDave May   ierr = MatAssemblyBegin(A,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
321095059a4SDave May   ierr = MatAssemblyEnd(A,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
322095059a4SDave May   /* Now force all other connections if they are not already there */
323095059a4SDave May   /* It's more efficient to do them all at once */
324521f74f9SMatthew G. Knepley   for (i = 0; i < n_; ++i) {
325095059a4SDave May     vals[i] = 2.0;
326095059a4SDave May   }
327095059a4SDave May   ierr = MatSetValues( A, n_,proc_neighbours_, 1,&rank_i_, vals, INSERT_VALUES );CHKERRQ(ierr);
328095059a4SDave May   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
329095059a4SDave May   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3306275818cSDave May /*
331095059a4SDave May   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr);
332095059a4SDave May   ierr = MatView(A,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
333095059a4SDave May   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
3346275818cSDave May */
335095059a4SDave May   if ((n_new != NULL) && (proc_neighbours_new != NULL)) {
336dcf43ee8SDave May     ierr = MatGetRow(A, rank_i_, &nc, &cols, &red_vals);CHKERRQ(ierr);
337095059a4SDave May     _n_new = (PetscMPIInt) nc;
338521f74f9SMatthew G. Knepley     ierr = PetscMalloc1(_n_new, &_proc_neighbours_new);CHKERRQ(ierr);
339521f74f9SMatthew G. Knepley     for (j = 0; j < nc; ++j) {
340095059a4SDave May       _proc_neighbours_new[j] = (PetscMPIInt)cols[j];
341095059a4SDave May     }
342dcf43ee8SDave May     ierr = MatRestoreRow( A, rank_i_, &nc, &cols, &red_vals );CHKERRQ(ierr);
343095059a4SDave May     *n_new               = (PetscMPIInt)_n_new;
344095059a4SDave May     *proc_neighbours_new = (PetscMPIInt*)_proc_neighbours_new;
345095059a4SDave May   }
346095059a4SDave May   ierr = MatDestroy(&A);CHKERRQ(ierr);
347095059a4SDave May   ierr = PetscFree(vals);CHKERRQ(ierr);
348095059a4SDave May   ierr = PetscFree(proc_neighbours_);CHKERRQ(ierr);
349095059a4SDave May   ierr = MPI_Barrier(comm);CHKERRQ(ierr);
350095059a4SDave May   PetscFunctionReturn(0);
351095059a4SDave May }
352095059a4SDave May 
353095059a4SDave May PetscErrorCode DataExTopologyFinalize(DataEx d)
354095059a4SDave May {
355095059a4SDave May   PetscMPIInt    symm_nn;
356095059a4SDave May   PetscMPIInt   *symm_procs;
357095059a4SDave May   PetscMPIInt    r0,n,st,rt;
358095059a4SDave May   PetscMPIInt    nprocs;
359095059a4SDave May   PetscErrorCode ierr;
360095059a4SDave May 
361095059a4SDave May   PetscFunctionBegin;
3622064fc68SDave May   if (d->topology_status != DEOBJECT_INITIALIZED) SETERRQ(d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be intialised. Call DataExTopologyInitialize() first");
3632064fc68SDave May 
364*ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerTopologySetup,0,0,0,0);CHKERRQ(ierr);
365095059a4SDave May   /* given infomation about all my neighbours, make map symmetric */
366095059a4SDave May   ierr = _DataExCompleteCommunicationMap( d->comm,d->n_neighbour_procs,d->neighbour_procs, &symm_nn, &symm_procs );CHKERRQ(ierr);
367095059a4SDave May   /* update my arrays */
368459726d8SSatish Balay   ierr = PetscFree(d->neighbour_procs);CHKERRQ(ierr);
369095059a4SDave May   d->n_neighbour_procs = symm_nn;
370095059a4SDave May   d->neighbour_procs   = symm_procs;
371095059a4SDave May   /* allocates memory */
372b9a482c4SDave May   if (!d->messages_to_be_sent) {ierr = PetscMalloc1(d->n_neighbour_procs+1, &d->messages_to_be_sent);CHKERRQ(ierr);}
373b9a482c4SDave May   if (!d->message_offsets) {ierr = PetscMalloc1(d->n_neighbour_procs+1, &d->message_offsets);CHKERRQ(ierr);}
374b9a482c4SDave May   if (!d->messages_to_be_recvieved) {ierr = PetscMalloc1(d->n_neighbour_procs+1, &d->messages_to_be_recvieved);CHKERRQ(ierr);}
375521f74f9SMatthew G. Knepley   if (!d->pack_cnt) {ierr = PetscMalloc(sizeof(PetscInt) * d->n_neighbour_procs, &d->pack_cnt);CHKERRQ(ierr);}
376521f74f9SMatthew G. Knepley   if (!d->_stats) {ierr = PetscMalloc(sizeof(MPI_Status) * 2*d->n_neighbour_procs, &d->_stats);CHKERRQ(ierr);}
377521f74f9SMatthew G. Knepley   if (!d->_requests) {ierr = PetscMalloc(sizeof(MPI_Request) * 2*d->n_neighbour_procs, &d->_requests);CHKERRQ(ierr);}
378521f74f9SMatthew G. Knepley   if (!d->send_tags) {ierr = PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->send_tags);CHKERRQ(ierr);}
379521f74f9SMatthew G. Knepley   if (!d->recv_tags) {ierr = PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->recv_tags);CHKERRQ(ierr);}
380095059a4SDave May   /* compute message tags */
381095059a4SDave May   ierr = MPI_Comm_size(d->comm,&nprocs);CHKERRQ(ierr);
382095059a4SDave May   r0 = d->rank;
383521f74f9SMatthew G. Knepley   for (n = 0; n < d->n_neighbour_procs; ++n) {
384095059a4SDave May     PetscMPIInt r1 = d->neighbour_procs[n];
385095059a4SDave May 
386095059a4SDave May     _get_tags( d->instance, nprocs, r0,r1, &st, &rt );
387095059a4SDave May     d->send_tags[n] = (int)st;
388095059a4SDave May     d->recv_tags[n] = (int)rt;
389095059a4SDave May   }
390095059a4SDave May   d->topology_status = DEOBJECT_FINALIZED;
391*ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerTopologySetup,0,0,0,0);CHKERRQ(ierr);
392095059a4SDave May   PetscFunctionReturn(0);
393095059a4SDave May }
394095059a4SDave May 
395095059a4SDave May /* === Phase B === */
396095059a4SDave May PetscErrorCode _DataExConvertProcIdToLocalIndex(DataEx de,PetscMPIInt proc_id,PetscMPIInt *local)
397095059a4SDave May {
398095059a4SDave May   PetscMPIInt i,np;
399095059a4SDave May 
400095059a4SDave May   PetscFunctionBegin;
401095059a4SDave May   np = de->n_neighbour_procs;
402095059a4SDave May   *local = -1;
403521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
404095059a4SDave May     if (proc_id == de->neighbour_procs[i]) {
405095059a4SDave May       *local = i;
406095059a4SDave May       break;
407095059a4SDave May     }
408095059a4SDave May   }
409095059a4SDave May   PetscFunctionReturn(0);
410095059a4SDave May }
411095059a4SDave May 
412095059a4SDave May PetscErrorCode DataExInitializeSendCount(DataEx de)
413095059a4SDave May {
414095059a4SDave May   PetscMPIInt    i;
415*ed923d71SDave May   PetscErrorCode ierr;
416095059a4SDave May 
417095059a4SDave May   PetscFunctionBegin;
418521f74f9SMatthew G. Knepley   if (de->topology_status != DEOBJECT_FINALIZED) SETERRQ(de->comm, PETSC_ERR_ORDER, "Topology not finalized");
419*ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerSendCount,0,0,0,0);CHKERRQ(ierr);
420095059a4SDave May   de->message_lengths_status = DEOBJECT_INITIALIZED;
421521f74f9SMatthew G. Knepley   for (i = 0; i < de->n_neighbour_procs; ++i) {
422095059a4SDave May     de->messages_to_be_sent[i] = 0;
423095059a4SDave May   }
424095059a4SDave May   PetscFunctionReturn(0);
425095059a4SDave May }
426095059a4SDave May 
427095059a4SDave May /*
428095059a4SDave May 1) only allows counters to be set on neighbouring cpus
429095059a4SDave May */
430095059a4SDave May PetscErrorCode DataExAddToSendCount(DataEx de,const PetscMPIInt proc_id,const PetscInt count)
431095059a4SDave May {
432095059a4SDave May   PetscMPIInt    local_val;
433095059a4SDave May   PetscErrorCode ierr;
434095059a4SDave May 
435095059a4SDave May   PetscFunctionBegin;
4362064fc68SDave May   if (de->message_lengths_status == DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths have been defined. To modify these call DataExInitializeSendCount() first" );
4372064fc68SDave May   else if (de->message_lengths_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DataExInitializeSendCount() first" );
4382064fc68SDave May 
439095059a4SDave May   ierr = _DataExConvertProcIdToLocalIndex( de, proc_id, &local_val );CHKERRQ(ierr);
4402064fc68SDave May   if (local_val == -1) SETERRQ1( PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,"Proc %d is not a valid neighbour rank", (int)proc_id );
4412064fc68SDave May 
442095059a4SDave May   de->messages_to_be_sent[local_val] = de->messages_to_be_sent[local_val] + count;
443095059a4SDave May   PetscFunctionReturn(0);
444095059a4SDave May }
445095059a4SDave May 
446095059a4SDave May PetscErrorCode DataExFinalizeSendCount(DataEx de)
447095059a4SDave May {
448*ed923d71SDave May   PetscErrorCode ierr;
449*ed923d71SDave May 
450095059a4SDave May   PetscFunctionBegin;
4512064fc68SDave May   if (de->message_lengths_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DataExInitializeSendCount() first" );
4522064fc68SDave May 
453095059a4SDave May   de->message_lengths_status = DEOBJECT_FINALIZED;
454*ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerSendCount,0,0,0,0);CHKERRQ(ierr);
455095059a4SDave May   PetscFunctionReturn(0);
456095059a4SDave May }
457095059a4SDave May 
458095059a4SDave May /* === Phase C === */
459095059a4SDave May /*
460095059a4SDave May  * zero out all send counts
461095059a4SDave May  * free send and recv buffers
462095059a4SDave May  * zeros out message length
463095059a4SDave May  * zeros out all counters
464095059a4SDave May  * zero out packed data counters
465095059a4SDave May */
466095059a4SDave May PetscErrorCode _DataExInitializeTmpStorage(DataEx de)
467095059a4SDave May {
468095059a4SDave May   PetscMPIInt    i, np;
469521f74f9SMatthew G. Knepley   PetscErrorCode ierr;
470095059a4SDave May 
471095059a4SDave May   PetscFunctionBegin;
4722064fc68SDave May   /*if (de->n_neighbour_procs < 0) SETERRQ( PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of neighbour procs < 0");
473b9a482c4SDave May   */
474b9a482c4SDave May   /*
4752064fc68SDave May   if (!de->neighbour_procs) SETERRQ( PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Neighbour proc list is NULL" );
476b9a482c4SDave May   */
477095059a4SDave May   np = de->n_neighbour_procs;
478521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
479095059a4SDave May     /*	de->messages_to_be_sent[i] = -1; */
480095059a4SDave May     de->messages_to_be_recvieved[i] = -1;
481095059a4SDave May   }
482521f74f9SMatthew G. Knepley   ierr = PetscFree(de->send_message);CHKERRQ(ierr);
483521f74f9SMatthew G. Knepley   ierr = PetscFree(de->recv_message);CHKERRQ(ierr);
484095059a4SDave May   PetscFunctionReturn(0);
485095059a4SDave May }
486095059a4SDave May 
487095059a4SDave May /*
488095059a4SDave May *) Zeros out pack data counters
489095059a4SDave May *) Ensures mesaage length is set
490095059a4SDave May *) Checks send counts properly initialized
491095059a4SDave May *) allocates space for pack data
492095059a4SDave May */
493095059a4SDave May PetscErrorCode DataExPackInitialize(DataEx de,size_t unit_message_size)
494095059a4SDave May {
495095059a4SDave May   PetscMPIInt    i,np;
496095059a4SDave May   PetscInt       total;
497095059a4SDave May   PetscErrorCode ierr;
498095059a4SDave May 
499095059a4SDave May   PetscFunctionBegin;
500521f74f9SMatthew G. Knepley   if (de->topology_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Topology not finalized" );
501521f74f9SMatthew G. Knepley   if (de->message_lengths_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths not finalized" );
502*ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerPack,0,0,0,0);CHKERRQ(ierr);
503095059a4SDave May   de->packer_status = DEOBJECT_INITIALIZED;
504095059a4SDave May   ierr = _DataExInitializeTmpStorage(de);CHKERRQ(ierr);
505095059a4SDave May   np = de->n_neighbour_procs;
506095059a4SDave May   de->unit_message_size = unit_message_size;
507095059a4SDave May   total = 0;
508521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
509095059a4SDave May     if (de->messages_to_be_sent[i] == -1) {
510095059a4SDave May       PetscMPIInt proc_neighour = de->neighbour_procs[i];
511095059a4SDave May       SETERRQ1( PETSC_COMM_SELF, PETSC_ERR_ORDER, "Messages_to_be_sent[neighbour_proc=%d] is un-initialised. Call DataExSetSendCount() first", (int)proc_neighour );
512095059a4SDave May     }
513095059a4SDave May     total = total + de->messages_to_be_sent[i];
514095059a4SDave May   }
515095059a4SDave May   /* create space for the data to be sent */
516521f74f9SMatthew G. Knepley   ierr = PetscMalloc(unit_message_size * (total + 1), &de->send_message);CHKERRQ(ierr);
517095059a4SDave May   /* initialize memory */
518521f74f9SMatthew G. Knepley   ierr = PetscMemzero(de->send_message, unit_message_size * (total + 1));CHKERRQ(ierr);
519095059a4SDave May   /* set total items to send */
520095059a4SDave May   de->send_message_length = total;
521095059a4SDave May   de->message_offsets[0] = 0;
522095059a4SDave May   total = de->messages_to_be_sent[0];
523521f74f9SMatthew G. Knepley   for (i = 1; i < np; ++i) {
524095059a4SDave May     de->message_offsets[i] = total;
525095059a4SDave May     total = total + de->messages_to_be_sent[i];
526095059a4SDave May   }
527095059a4SDave May   /* init the packer counters */
528095059a4SDave May   de->total_pack_cnt = 0;
529521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
530095059a4SDave May     de->pack_cnt[i] = 0;
531095059a4SDave May   }
532095059a4SDave May   PetscFunctionReturn(0);
533095059a4SDave May }
534095059a4SDave May 
535095059a4SDave May /*
536095059a4SDave May *) Ensures data gets been packed appropriately and no overlaps occur
537095059a4SDave May */
538095059a4SDave May PetscErrorCode DataExPackData(DataEx de,PetscMPIInt proc_id,PetscInt n,void *data)
539095059a4SDave May {
540095059a4SDave May   PetscMPIInt    local;
541095059a4SDave May   PetscInt       insert_location;
542095059a4SDave May   void           *dest;
543095059a4SDave May   PetscErrorCode ierr;
544095059a4SDave May 
545095059a4SDave May   PetscFunctionBegin;
5462064fc68SDave May   if (de->packer_status == DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Packed data have been defined. To modify these call DataExInitializeSendCount(), DataExAddToSendCount(), DataExPackInitialize() first" );
5472064fc68SDave May   else if (de->packer_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Packed data must be defined. Call DataExInitializeSendCount(), DataExAddToSendCount(), DataExPackInitialize() first" );
5482064fc68SDave May 
549521f74f9SMatthew G. Knepley   if (!de->send_message) SETERRQ( de->comm, PETSC_ERR_ORDER, "send_message is not initialized. Call DataExPackInitialize() first" );
550095059a4SDave May   ierr = _DataExConvertProcIdToLocalIndex( de, proc_id, &local );CHKERRQ(ierr);
551521f74f9SMatthew G. Knepley   if (local == -1) SETERRQ1( PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "proc_id %d is not registered neighbour", (int)proc_id );
5522064fc68SDave May   if (n+de->pack_cnt[local] > de->messages_to_be_sent[local]) SETERRQ3( 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",
553095059a4SDave May               (int)proc_id, de->messages_to_be_sent[local], n+de->pack_cnt[local] );
5542064fc68SDave May 
555095059a4SDave May   /* copy memory */
556095059a4SDave May   insert_location = de->message_offsets[local] + de->pack_cnt[local];
557095059a4SDave May   dest = ((char*)de->send_message) + de->unit_message_size*insert_location;
558521f74f9SMatthew G. Knepley   ierr = PetscMemcpy(dest, data, de->unit_message_size * n);CHKERRQ(ierr);
559095059a4SDave May   /* increment counter */
560095059a4SDave May   de->pack_cnt[local] = de->pack_cnt[local] + n;
561095059a4SDave May   PetscFunctionReturn(0);
562095059a4SDave May }
563095059a4SDave May 
564095059a4SDave May /*
565095059a4SDave May *) Ensures all data has been packed
566095059a4SDave May */
567095059a4SDave May PetscErrorCode DataExPackFinalize(DataEx de)
568095059a4SDave May {
569095059a4SDave May   PetscMPIInt i,np;
570095059a4SDave May   PetscInt    total;
571095059a4SDave May   PetscErrorCode ierr;
572095059a4SDave May 
573095059a4SDave May   PetscFunctionBegin;
574521f74f9SMatthew G. Knepley   if (de->packer_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Packer has not been initialized. Must call DataExPackInitialize() first." );
575095059a4SDave May   np = de->n_neighbour_procs;
576521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
5772064fc68SDave May     if (de->pack_cnt[i] != de->messages_to_be_sent[i]) SETERRQ3( PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not all messages for neighbour[%d] have been packed. Expected %D : Inserted %D",
578095059a4SDave May                 (int)de->neighbour_procs[i], de->messages_to_be_sent[i], de->pack_cnt[i] );
579095059a4SDave May   }
580095059a4SDave May   /* init */
581521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
582095059a4SDave May     de->messages_to_be_recvieved[i] = -1;
583095059a4SDave May   }
584095059a4SDave May   /* figure out the recv counts here */
585521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
586095059a4SDave May     ierr = MPI_Isend(&de->messages_to_be_sent[i], 1, MPIU_INT, de->neighbour_procs[i], de->send_tags[i], de->comm, &de->_requests[i]);CHKERRQ(ierr);
587095059a4SDave May   }
588521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
589095059a4SDave May     ierr = 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]);CHKERRQ(ierr);
590095059a4SDave May   }
591095059a4SDave May   ierr = MPI_Waitall(2*np, de->_requests, de->_stats);CHKERRQ(ierr);
592095059a4SDave May   /* create space for the data to be recvieved */
593095059a4SDave May   total = 0;
594521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
595095059a4SDave May     total = total + de->messages_to_be_recvieved[i];
596095059a4SDave May   }
597521f74f9SMatthew G. Knepley   ierr = PetscMalloc(de->unit_message_size * (total + 1), &de->recv_message);CHKERRQ(ierr);
598095059a4SDave May   /* initialize memory */
599521f74f9SMatthew G. Knepley   ierr = PetscMemzero(de->recv_message, de->unit_message_size * (total + 1));CHKERRQ(ierr);
600095059a4SDave May   /* set total items to recieve */
601095059a4SDave May   de->recv_message_length = total;
602095059a4SDave May   de->packer_status = DEOBJECT_FINALIZED;
603095059a4SDave May   de->communication_status = DEOBJECT_INITIALIZED;
604*ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerPack,0,0,0,0);CHKERRQ(ierr);
605095059a4SDave May   PetscFunctionReturn(0);
606095059a4SDave May }
607095059a4SDave May 
608095059a4SDave May /* do the actual message passing now */
609095059a4SDave May PetscErrorCode DataExBegin(DataEx de)
610095059a4SDave May {
611095059a4SDave May   PetscMPIInt i,np;
612095059a4SDave May   void       *dest;
613095059a4SDave May   PetscInt    length;
614095059a4SDave May   PetscErrorCode ierr;
615095059a4SDave May 
616095059a4SDave May   PetscFunctionBegin;
617521f74f9SMatthew G. Knepley   if (de->topology_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Topology not finalized" );
618521f74f9SMatthew G. Knepley   if (de->message_lengths_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths not finalized" );
619521f74f9SMatthew G. Knepley   if (de->packer_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Packer not finalized" );
620521f74f9SMatthew G. Knepley   if (de->communication_status == DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Communication has already been finalized. Must call DataExInitialize() first." );
621521f74f9SMatthew G. Knepley   if (!de->recv_message) SETERRQ( de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DataExPackFinalize() first" );
622*ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerBegin,0,0,0,0);CHKERRQ(ierr);
623095059a4SDave May   np = de->n_neighbour_procs;
624095059a4SDave May   /* == NON BLOCKING == */
625521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
626095059a4SDave May     length = de->messages_to_be_sent[i] * de->unit_message_size;
627095059a4SDave May     dest = ((char*)de->send_message) + de->unit_message_size * de->message_offsets[i];
628095059a4SDave May     ierr = MPI_Isend( dest, length, MPI_CHAR, de->neighbour_procs[i], de->send_tags[i], de->comm, &de->_requests[i] );CHKERRQ(ierr);
629095059a4SDave May   }
630*ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerBegin,0,0,0,0);CHKERRQ(ierr);
631095059a4SDave May   PetscFunctionReturn(0);
632095059a4SDave May }
633095059a4SDave May 
634095059a4SDave May /* do the actual message passing now */
635095059a4SDave May PetscErrorCode DataExEnd(DataEx de)
636095059a4SDave May {
637095059a4SDave May   PetscMPIInt  i,np;
638095059a4SDave May   PetscInt     total;
639095059a4SDave May   PetscInt    *message_recv_offsets;
640095059a4SDave May   void        *dest;
641095059a4SDave May   PetscInt     length;
642095059a4SDave May   PetscErrorCode ierr;
643095059a4SDave May 
644095059a4SDave May   PetscFunctionBegin;
645521f74f9SMatthew G. Knepley   if (de->communication_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Communication has not been initialized. Must call DataExInitialize() first." );
646521f74f9SMatthew G. Knepley   if (!de->recv_message) SETERRQ( de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DataExPackFinalize() first" );
647*ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerEnd,0,0,0,0);CHKERRQ(ierr);
648095059a4SDave May   np = de->n_neighbour_procs;
649b9a482c4SDave May   ierr = PetscMalloc1(np+1, &message_recv_offsets);CHKERRQ(ierr);
650095059a4SDave May   message_recv_offsets[0] = 0;
651095059a4SDave May   total = de->messages_to_be_recvieved[0];
652521f74f9SMatthew G. Knepley   for (i = 1; i < np; ++i) {
653095059a4SDave May     message_recv_offsets[i] = total;
654095059a4SDave May     total = total + de->messages_to_be_recvieved[i];
655095059a4SDave May   }
656095059a4SDave May   /* == NON BLOCKING == */
657521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
658095059a4SDave May     length = de->messages_to_be_recvieved[i] * de->unit_message_size;
659095059a4SDave May     dest = ((char*)de->recv_message) + de->unit_message_size * message_recv_offsets[i];
660095059a4SDave May     ierr = MPI_Irecv( dest, length, MPI_CHAR, de->neighbour_procs[i], de->recv_tags[i], de->comm, &de->_requests[np+i] );CHKERRQ(ierr);
661095059a4SDave May   }
662095059a4SDave May   ierr = MPI_Waitall( 2*np, de->_requests, de->_stats );CHKERRQ(ierr);
663459726d8SSatish Balay   ierr = PetscFree(message_recv_offsets);CHKERRQ(ierr);
664095059a4SDave May   de->communication_status = DEOBJECT_FINALIZED;
665*ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerEnd,0,0,0,0);CHKERRQ(ierr);
666095059a4SDave May   PetscFunctionReturn(0);
667095059a4SDave May }
668095059a4SDave May 
669095059a4SDave May PetscErrorCode DataExGetSendData(DataEx de,PetscInt *length,void **send)
670095059a4SDave May {
671095059a4SDave May   PetscFunctionBegin;
672521f74f9SMatthew G. Knepley   if (de->packer_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being packed." );
673095059a4SDave May   *length = de->send_message_length;
674095059a4SDave May   *send   = de->send_message;
675095059a4SDave May   PetscFunctionReturn(0);
676095059a4SDave May }
677095059a4SDave May 
678095059a4SDave May PetscErrorCode DataExGetRecvData(DataEx de,PetscInt *length,void **recv)
679095059a4SDave May {
680095059a4SDave May   PetscFunctionBegin;
681521f74f9SMatthew G. Knepley   if (de->communication_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being sent." );
682095059a4SDave May   *length = de->recv_message_length;
683095059a4SDave May   *recv   = de->recv_message;
684095059a4SDave May   PetscFunctionReturn(0);
685095059a4SDave May }
686095059a4SDave May 
687095059a4SDave May PetscErrorCode DataExTopologyGetNeighbours(DataEx de,PetscMPIInt *n,PetscMPIInt *neigh[])
688095059a4SDave May {
689095059a4SDave May   PetscFunctionBegin;
690095059a4SDave May   if (n)     {*n     = de->n_neighbour_procs;}
691095059a4SDave May   if (neigh) {*neigh = de->neighbour_procs;}
692095059a4SDave May   PetscFunctionReturn(0);
693095059a4SDave May }
694095059a4SDave May 
695