xref: /petsc/src/dm/impls/swarm/data_ex.c (revision d7d19db6da0742cb282bef564243647d6beadfd6)
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 #include <petscvec.h>
77095059a4SDave May #include <petscmat.h>
78095059a4SDave May 
79095059a4SDave May #include "data_ex.h"
80095059a4SDave May 
81095059a4SDave May const char *status_names[] = {"initialized", "finalized", "unknown"};
82095059a4SDave May 
83ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerTopologySetup;
84ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerBegin;
85ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerEnd;
86ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerSendCount;
87ed923d71SDave May PETSC_EXTERN PetscLogEvent DMSWARM_DataExchangerPack;
88095059a4SDave May 
89521f74f9SMatthew G. Knepley PetscErrorCode DataExCreate(MPI_Comm comm,const PetscInt count, DataEx *ex)
90095059a4SDave May {
91095059a4SDave May   PetscErrorCode ierr;
92521f74f9SMatthew G. Knepley   DataEx         d;
93095059a4SDave May 
94521f74f9SMatthew G. Knepley   PetscFunctionBegin;
95521f74f9SMatthew G. Knepley   ierr = PetscMalloc(sizeof(struct _p_DataEx), &d);CHKERRQ(ierr);
96521f74f9SMatthew G. Knepley   ierr = PetscMemzero(d, sizeof(struct _p_DataEx));CHKERRQ(ierr);
97521f74f9SMatthew G. Knepley   ierr = MPI_Comm_dup(comm,&d->comm);CHKERRQ(ierr);
98521f74f9SMatthew G. Knepley   ierr = MPI_Comm_rank(d->comm,&d->rank);CHKERRQ(ierr);
99095059a4SDave May 
100095059a4SDave May   d->instance = count;
101095059a4SDave May 
102095059a4SDave May   d->topology_status        = DEOBJECT_STATE_UNKNOWN;
103095059a4SDave May   d->message_lengths_status = DEOBJECT_STATE_UNKNOWN;
104095059a4SDave May   d->packer_status          = DEOBJECT_STATE_UNKNOWN;
105095059a4SDave May   d->communication_status   = DEOBJECT_STATE_UNKNOWN;
106095059a4SDave May 
107095059a4SDave May   d->n_neighbour_procs = -1;
108095059a4SDave May   d->neighbour_procs   = NULL;
109095059a4SDave May 
110095059a4SDave May   d->messages_to_be_sent      = NULL;
111095059a4SDave May   d->message_offsets          = NULL;
112095059a4SDave May   d->messages_to_be_recvieved = NULL;
113095059a4SDave May 
114095059a4SDave May   d->unit_message_size   = -1;
115095059a4SDave May   d->send_message        = NULL;
116095059a4SDave May   d->send_message_length = -1;
117095059a4SDave May   d->recv_message        = NULL;
118095059a4SDave May   d->recv_message_length = -1;
119095059a4SDave May   d->total_pack_cnt      = -1;
120095059a4SDave May   d->pack_cnt            = NULL;
121095059a4SDave May 
122095059a4SDave May   d->send_tags = NULL;
123095059a4SDave May   d->recv_tags = NULL;
124095059a4SDave May 
125095059a4SDave May   d->_stats    = NULL;
126095059a4SDave May   d->_requests = NULL;
127521f74f9SMatthew G. Knepley   *ex = d;
128521f74f9SMatthew G. Knepley   PetscFunctionReturn(0);
129095059a4SDave May }
130095059a4SDave May 
131298827fbSBarry Smith /*
132298827fbSBarry Smith     This code is horrible, who let it get into master.
133298827fbSBarry Smith 
134298827fbSBarry Smith     Should be printing to a viewer, should not be using PETSC_COMM_WORLD
135298827fbSBarry Smith 
136298827fbSBarry Smith */
137095059a4SDave May PetscErrorCode DataExView(DataEx d)
138095059a4SDave May {
139095059a4SDave May   PetscMPIInt    p;
140521f74f9SMatthew G. Knepley   PetscErrorCode ierr;
141095059a4SDave May 
142095059a4SDave May   PetscFunctionBegin;
143521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "DataEx: instance=%D\n",d->instance);CHKERRQ(ierr);
144521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  topology status:        %s \n", status_names[d->topology_status]);CHKERRQ(ierr);
145521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  message lengths status: %s \n", status_names[d->message_lengths_status] );CHKERRQ(ierr);
146521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  packer status status:   %s \n", status_names[d->packer_status] );CHKERRQ(ierr);
147521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  communication status:   %s \n", status_names[d->communication_status] );CHKERRQ(ierr);
148095059a4SDave May 
149095059a4SDave May   if (d->topology_status == DEOBJECT_FINALIZED) {
150521f74f9SMatthew G. Knepley     ierr = PetscPrintf( PETSC_COMM_WORLD, "  Topology:\n");CHKERRQ(ierr);
151298827fbSBarry Smith     ierr = PetscSynchronizedPrintf( PETSC_COMM_WORLD, "    [%d] neighbours: %d \n", (int)d->rank, (int)d->n_neighbour_procs );CHKERRQ(ierr);
152095059a4SDave May     for (p=0; p<d->n_neighbour_procs; p++) {
153298827fbSBarry Smith       ierr = PetscSynchronizedPrintf( PETSC_COMM_WORLD, "    [%d]   neighbour[%D] = %d \n", (int)d->rank, p, (int)d->neighbour_procs[p]);CHKERRQ(ierr);
154095059a4SDave May     }
155298827fbSBarry Smith     ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,stdout);CHKERRQ(ierr);
156095059a4SDave May   }
157298827fbSBarry Smith 
158095059a4SDave May   if (d->message_lengths_status == DEOBJECT_FINALIZED) {
159521f74f9SMatthew G. Knepley     ierr = PetscPrintf( PETSC_COMM_WORLD, "  Message lengths:\n");CHKERRQ(ierr);
160298827fbSBarry Smith     ierr = PetscSynchronizedPrintf( PETSC_COMM_WORLD, "    [%d] atomic size: %ld \n", (int)d->rank, (long int)d->unit_message_size );CHKERRQ(ierr);
161095059a4SDave May     for (p=0; p<d->n_neighbour_procs; p++) {
162298827fbSBarry Smith       ierr = PetscSynchronizedPrintf( PETSC_COMM_WORLD, "    [%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);
163095059a4SDave May     }
164095059a4SDave May     for (p=0; p<d->n_neighbour_procs; p++) {
165298827fbSBarry Smith       ierr = PetscSynchronizedPrintf( PETSC_COMM_WORLD, "    [%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);
166095059a4SDave May     }
167298827fbSBarry Smith     ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,stdout);CHKERRQ(ierr);
168095059a4SDave May   }
169521f74f9SMatthew G. Knepley   if (d->packer_status == DEOBJECT_FINALIZED) {}
170521f74f9SMatthew G. Knepley   if (d->communication_status == DEOBJECT_FINALIZED) {}
171095059a4SDave May   PetscFunctionReturn(0);
172095059a4SDave May }
173095059a4SDave May 
174095059a4SDave May PetscErrorCode DataExDestroy(DataEx d)
175095059a4SDave May {
176095059a4SDave May   PetscErrorCode ierr;
177095059a4SDave May 
178095059a4SDave May   PetscFunctionBegin;
179095059a4SDave May   ierr = MPI_Comm_free(&d->comm);CHKERRQ(ierr);
180521f74f9SMatthew G. Knepley   if (d->neighbour_procs) {ierr = PetscFree(d->neighbour_procs);CHKERRQ(ierr);}
181521f74f9SMatthew G. Knepley   if (d->messages_to_be_sent) {ierr = PetscFree(d->messages_to_be_sent);CHKERRQ(ierr);}
182521f74f9SMatthew G. Knepley   if (d->message_offsets) {ierr = PetscFree(d->message_offsets);CHKERRQ(ierr);}
183521f74f9SMatthew G. Knepley   if (d->messages_to_be_recvieved) {ierr = PetscFree(d->messages_to_be_recvieved);CHKERRQ(ierr);}
184521f74f9SMatthew G. Knepley   if (d->send_message) {ierr = PetscFree(d->send_message);CHKERRQ(ierr);}
185521f74f9SMatthew G. Knepley   if (d->recv_message) {ierr = PetscFree(d->recv_message);CHKERRQ(ierr);}
186521f74f9SMatthew G. Knepley   if (d->pack_cnt) {ierr = PetscFree(d->pack_cnt);CHKERRQ(ierr);}
187521f74f9SMatthew G. Knepley   if (d->send_tags) {ierr = PetscFree(d->send_tags);CHKERRQ(ierr);}
188521f74f9SMatthew G. Knepley   if (d->recv_tags) {ierr = PetscFree(d->recv_tags);CHKERRQ(ierr);}
189521f74f9SMatthew G. Knepley   if (d->_stats) {ierr = PetscFree(d->_stats);CHKERRQ(ierr);}
190521f74f9SMatthew G. Knepley   if (d->_requests) {ierr = PetscFree(d->_requests);CHKERRQ(ierr);}
191521f74f9SMatthew G. Knepley   ierr = PetscFree(d);CHKERRQ(ierr);
192095059a4SDave May   PetscFunctionReturn(0);
193095059a4SDave May }
194095059a4SDave May 
195095059a4SDave May /* === Phase A === */
196095059a4SDave May 
197095059a4SDave May PetscErrorCode DataExTopologyInitialize(DataEx d)
198095059a4SDave May {
199521f74f9SMatthew G. Knepley   PetscErrorCode ierr;
200521f74f9SMatthew G. Knepley 
201095059a4SDave May   PetscFunctionBegin;
202095059a4SDave May   d->topology_status = DEOBJECT_INITIALIZED;
203095059a4SDave May   d->n_neighbour_procs = 0;
204781df12bSMatthew G. Knepley   ierr = PetscFree(d->neighbour_procs);CHKERRQ(ierr);
205781df12bSMatthew G. Knepley   ierr = PetscFree(d->messages_to_be_sent);CHKERRQ(ierr);
206781df12bSMatthew G. Knepley   ierr = PetscFree(d->message_offsets);CHKERRQ(ierr);
207781df12bSMatthew G. Knepley   ierr = PetscFree(d->messages_to_be_recvieved);CHKERRQ(ierr);
208781df12bSMatthew G. Knepley   ierr = PetscFree(d->pack_cnt);CHKERRQ(ierr);
209781df12bSMatthew G. Knepley   ierr = PetscFree(d->send_tags);CHKERRQ(ierr);
210781df12bSMatthew G. Knepley   ierr = PetscFree(d->recv_tags);CHKERRQ(ierr);
211095059a4SDave May   PetscFunctionReturn(0);
212095059a4SDave May }
213095059a4SDave May 
214095059a4SDave May PetscErrorCode DataExTopologyAddNeighbour(DataEx d,const PetscMPIInt proc_id)
215095059a4SDave May {
216095059a4SDave May   PetscMPIInt    n,found;
217*d7d19db6SBarry Smith   PetscMPIInt    size;
218095059a4SDave May   PetscErrorCode ierr;
219095059a4SDave May 
220095059a4SDave May   PetscFunctionBegin;
2212064fc68SDave 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");
2222064fc68SDave May   else if (d->topology_status != DEOBJECT_INITIALIZED) SETERRQ(d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be intialised. Call DataExTopologyInitialize() first");
2232064fc68SDave May 
224095059a4SDave May   /* error on negative entries */
225521f74f9SMatthew G. Knepley   if (proc_id < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Trying to set proc neighbour with a rank < 0");
226095059a4SDave May   /* error on ranks larger than number of procs in communicator */
227*d7d19db6SBarry Smith   ierr = MPI_Comm_size(d->comm,&size);CHKERRQ(ierr);
228*d7d19db6SBarry Smith   if (proc_id >= size) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Trying to set proc neighbour %d with a rank >= size %d",proc_id,size);
229521f74f9SMatthew G. Knepley   if (d->n_neighbour_procs == 0) {ierr = PetscMalloc1(1, &d->neighbour_procs);CHKERRQ(ierr);}
230095059a4SDave May   /* check for proc_id */
231095059a4SDave May   found = 0;
232095059a4SDave May   for (n = 0; n < d->n_neighbour_procs; n++) {
233095059a4SDave May     if (d->neighbour_procs[n] == proc_id) {
234095059a4SDave May       found  = 1;
235095059a4SDave May     }
236095059a4SDave May   }
237095059a4SDave May   if (found == 0) { /* add it to list */
2384be7464cSMatthew G. Knepley     ierr = PetscRealloc(sizeof(PetscMPIInt)*(d->n_neighbour_procs+1), &d->neighbour_procs);CHKERRQ(ierr);
239095059a4SDave May     d->neighbour_procs[ d->n_neighbour_procs ] = proc_id;
240095059a4SDave May     d->n_neighbour_procs++;
241095059a4SDave May   }
242095059a4SDave May   PetscFunctionReturn(0);
243095059a4SDave May }
244095059a4SDave May 
245095059a4SDave May /*
246095059a4SDave May counter: the index of the communication object
247095059a4SDave May N: the number of processors
248095059a4SDave May r0: rank of sender
249095059a4SDave May r1: rank of receiver
250095059a4SDave May 
251095059a4SDave May procs = { 0, 1, 2, 3 }
252095059a4SDave May 
253095059a4SDave May 0 ==> 0		e=0
254095059a4SDave May 0 ==> 1		e=1
255095059a4SDave May 0 ==> 2		e=2
256095059a4SDave May 0 ==> 3		e=3
257095059a4SDave May 
258095059a4SDave May 1 ==> 0		e=4
259095059a4SDave May 1 ==> 1		e=5
260095059a4SDave May 1 ==> 2		e=6
261095059a4SDave May 1 ==> 3		e=7
262095059a4SDave May 
263095059a4SDave May 2 ==> 0		e=8
264095059a4SDave May 2 ==> 1		e=9
265095059a4SDave May 2 ==> 2		e=10
266095059a4SDave May 2 ==> 3		e=11
267095059a4SDave May 
268095059a4SDave May 3 ==> 0		e=12
269095059a4SDave May 3 ==> 1		e=13
270095059a4SDave May 3 ==> 2		e=14
271095059a4SDave May 3 ==> 3		e=15
272095059a4SDave May 
273095059a4SDave May If we require that proc A sends to proc B, then the SEND tag index will be given by
274095059a4SDave May   N * rank(A) + rank(B) + offset
275095059a4SDave May If we require that proc A will receive from proc B, then the RECV tag index will be given by
276095059a4SDave May   N * rank(B) + rank(A) + offset
277095059a4SDave May 
278095059a4SDave May */
279521f74f9SMatthew G. Knepley static void _get_tags(PetscInt counter, PetscMPIInt N, PetscMPIInt r0,PetscMPIInt r1, PetscMPIInt *_st, PetscMPIInt *_rt)
280095059a4SDave May {
281095059a4SDave May   PetscMPIInt st,rt;
282095059a4SDave May 
283095059a4SDave May   st = N*r0 + r1   +   N*N*counter;
284095059a4SDave May   rt = N*r1 + r0   +   N*N*counter;
285095059a4SDave May   *_st = st;
286095059a4SDave May   *_rt = rt;
287095059a4SDave May }
288095059a4SDave May 
289095059a4SDave May /*
290095059a4SDave May Makes the communication map symmetric
291095059a4SDave May */
292095059a4SDave May PetscErrorCode _DataExCompleteCommunicationMap(MPI_Comm comm,PetscMPIInt n,PetscMPIInt proc_neighbours[],PetscMPIInt *n_new,PetscMPIInt **proc_neighbours_new)
293095059a4SDave May {
294dcf43ee8SDave May   Mat               A;
295095059a4SDave May   PetscInt          i,j,nc;
296095059a4SDave May   PetscInt          n_, *proc_neighbours_;
297095059a4SDave May   PetscInt          rank_i_;
298095059a4SDave May   PetscMPIInt       size,  rank_i;
299095059a4SDave May   PetscScalar       *vals;
300095059a4SDave May   const PetscInt    *cols;
301095059a4SDave May   const PetscScalar *red_vals;
302095059a4SDave May   PetscMPIInt       _n_new, *_proc_neighbours_new;
303095059a4SDave May   PetscErrorCode    ierr;
304095059a4SDave May 
305095059a4SDave May   PetscFunctionBegin;
306095059a4SDave May   n_ = n;
307095059a4SDave May   ierr = PetscMalloc(sizeof(PetscInt) * n_, &proc_neighbours_);CHKERRQ(ierr);
308521f74f9SMatthew G. Knepley   for (i = 0; i < n_; ++i) {
309095059a4SDave May     proc_neighbours_[i] = proc_neighbours[i];
310095059a4SDave May   }
311095059a4SDave May   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
312095059a4SDave May   ierr = MPI_Comm_rank(comm,&rank_i);CHKERRQ(ierr);
313095059a4SDave May   rank_i_ = rank_i;
314095059a4SDave May 
315095059a4SDave May   ierr = MatCreate(comm,&A);CHKERRQ(ierr);
316095059a4SDave May   ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,size,size);CHKERRQ(ierr);
317095059a4SDave May   ierr = MatSetType(A,MATAIJ);CHKERRQ(ierr);
318dcf43ee8SDave May   ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
319dcf43ee8SDave May   ierr = MatMPIAIJSetPreallocation(A,n_,NULL,n_,NULL);CHKERRQ(ierr);
320dcf43ee8SDave May   ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);CHKERRQ(ierr);
321095059a4SDave May   /* Build original map */
322521f74f9SMatthew G. Knepley   ierr = PetscMalloc1(n_, &vals);CHKERRQ(ierr);
323521f74f9SMatthew G. Knepley   for (i = 0; i < n_; ++i) {
324095059a4SDave May     vals[i] = 1.0;
325095059a4SDave May   }
326095059a4SDave May   ierr = MatSetValues( A, 1,&rank_i_, n_,proc_neighbours_, vals, INSERT_VALUES );CHKERRQ(ierr);
327095059a4SDave May   ierr = MatAssemblyBegin(A,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
328095059a4SDave May   ierr = MatAssemblyEnd(A,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
329095059a4SDave May   /* Now force all other connections if they are not already there */
330095059a4SDave May   /* It's more efficient to do them all at once */
331521f74f9SMatthew G. Knepley   for (i = 0; i < n_; ++i) {
332095059a4SDave May     vals[i] = 2.0;
333095059a4SDave May   }
334095059a4SDave May   ierr = MatSetValues( A, n_,proc_neighbours_, 1,&rank_i_, vals, INSERT_VALUES );CHKERRQ(ierr);
335095059a4SDave May   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
336095059a4SDave May   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3376275818cSDave May /*
338095059a4SDave May   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr);
339095059a4SDave May   ierr = MatView(A,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
340095059a4SDave May   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
3416275818cSDave May */
342095059a4SDave May   if ((n_new != NULL) && (proc_neighbours_new != NULL)) {
343dcf43ee8SDave May     ierr = MatGetRow(A, rank_i_, &nc, &cols, &red_vals);CHKERRQ(ierr);
344095059a4SDave May     _n_new = (PetscMPIInt) nc;
345521f74f9SMatthew G. Knepley     ierr = PetscMalloc1(_n_new, &_proc_neighbours_new);CHKERRQ(ierr);
346521f74f9SMatthew G. Knepley     for (j = 0; j < nc; ++j) {
347095059a4SDave May       _proc_neighbours_new[j] = (PetscMPIInt)cols[j];
348095059a4SDave May     }
349dcf43ee8SDave May     ierr = MatRestoreRow( A, rank_i_, &nc, &cols, &red_vals );CHKERRQ(ierr);
350095059a4SDave May     *n_new               = (PetscMPIInt)_n_new;
351095059a4SDave May     *proc_neighbours_new = (PetscMPIInt*)_proc_neighbours_new;
352095059a4SDave May   }
353095059a4SDave May   ierr = MatDestroy(&A);CHKERRQ(ierr);
354095059a4SDave May   ierr = PetscFree(vals);CHKERRQ(ierr);
355095059a4SDave May   ierr = PetscFree(proc_neighbours_);CHKERRQ(ierr);
356095059a4SDave May   ierr = MPI_Barrier(comm);CHKERRQ(ierr);
357095059a4SDave May   PetscFunctionReturn(0);
358095059a4SDave May }
359095059a4SDave May 
360095059a4SDave May PetscErrorCode DataExTopologyFinalize(DataEx d)
361095059a4SDave May {
362095059a4SDave May   PetscMPIInt    symm_nn;
363095059a4SDave May   PetscMPIInt   *symm_procs;
364095059a4SDave May   PetscMPIInt    r0,n,st,rt;
365*d7d19db6SBarry Smith   PetscMPIInt    size;
366095059a4SDave May   PetscErrorCode ierr;
367095059a4SDave May 
368095059a4SDave May   PetscFunctionBegin;
3692064fc68SDave May   if (d->topology_status != DEOBJECT_INITIALIZED) SETERRQ(d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be intialised. Call DataExTopologyInitialize() first");
3702064fc68SDave May 
371ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerTopologySetup,0,0,0,0);CHKERRQ(ierr);
372095059a4SDave May   /* given infomation about all my neighbours, make map symmetric */
373095059a4SDave May   ierr = _DataExCompleteCommunicationMap( d->comm,d->n_neighbour_procs,d->neighbour_procs, &symm_nn, &symm_procs );CHKERRQ(ierr);
374095059a4SDave May   /* update my arrays */
375459726d8SSatish Balay   ierr = PetscFree(d->neighbour_procs);CHKERRQ(ierr);
376095059a4SDave May   d->n_neighbour_procs = symm_nn;
377095059a4SDave May   d->neighbour_procs   = symm_procs;
378095059a4SDave May   /* allocates memory */
379b9a482c4SDave May   if (!d->messages_to_be_sent) {ierr = PetscMalloc1(d->n_neighbour_procs+1, &d->messages_to_be_sent);CHKERRQ(ierr);}
380b9a482c4SDave May   if (!d->message_offsets) {ierr = PetscMalloc1(d->n_neighbour_procs+1, &d->message_offsets);CHKERRQ(ierr);}
381b9a482c4SDave May   if (!d->messages_to_be_recvieved) {ierr = PetscMalloc1(d->n_neighbour_procs+1, &d->messages_to_be_recvieved);CHKERRQ(ierr);}
382521f74f9SMatthew G. Knepley   if (!d->pack_cnt) {ierr = PetscMalloc(sizeof(PetscInt) * d->n_neighbour_procs, &d->pack_cnt);CHKERRQ(ierr);}
383521f74f9SMatthew G. Knepley   if (!d->_stats) {ierr = PetscMalloc(sizeof(MPI_Status) * 2*d->n_neighbour_procs, &d->_stats);CHKERRQ(ierr);}
384521f74f9SMatthew G. Knepley   if (!d->_requests) {ierr = PetscMalloc(sizeof(MPI_Request) * 2*d->n_neighbour_procs, &d->_requests);CHKERRQ(ierr);}
385521f74f9SMatthew G. Knepley   if (!d->send_tags) {ierr = PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->send_tags);CHKERRQ(ierr);}
386521f74f9SMatthew G. Knepley   if (!d->recv_tags) {ierr = PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->recv_tags);CHKERRQ(ierr);}
387095059a4SDave May   /* compute message tags */
388*d7d19db6SBarry Smith   ierr = MPI_Comm_size(d->comm,&size);CHKERRQ(ierr);
389095059a4SDave May   r0 = d->rank;
390521f74f9SMatthew G. Knepley   for (n = 0; n < d->n_neighbour_procs; ++n) {
391095059a4SDave May     PetscMPIInt r1 = d->neighbour_procs[n];
392095059a4SDave May 
393*d7d19db6SBarry Smith     _get_tags( d->instance, size, r0,r1, &st, &rt );
394095059a4SDave May     d->send_tags[n] = (int)st;
395095059a4SDave May     d->recv_tags[n] = (int)rt;
396095059a4SDave May   }
397095059a4SDave May   d->topology_status = DEOBJECT_FINALIZED;
398ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerTopologySetup,0,0,0,0);CHKERRQ(ierr);
399095059a4SDave May   PetscFunctionReturn(0);
400095059a4SDave May }
401095059a4SDave May 
402095059a4SDave May /* === Phase B === */
403095059a4SDave May PetscErrorCode _DataExConvertProcIdToLocalIndex(DataEx de,PetscMPIInt proc_id,PetscMPIInt *local)
404095059a4SDave May {
405095059a4SDave May   PetscMPIInt i,np;
406095059a4SDave May 
407095059a4SDave May   PetscFunctionBegin;
408095059a4SDave May   np = de->n_neighbour_procs;
409095059a4SDave May   *local = -1;
410521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
411095059a4SDave May     if (proc_id == de->neighbour_procs[i]) {
412095059a4SDave May       *local = i;
413095059a4SDave May       break;
414095059a4SDave May     }
415095059a4SDave May   }
416095059a4SDave May   PetscFunctionReturn(0);
417095059a4SDave May }
418095059a4SDave May 
419095059a4SDave May PetscErrorCode DataExInitializeSendCount(DataEx de)
420095059a4SDave May {
421095059a4SDave May   PetscMPIInt    i;
422ed923d71SDave May   PetscErrorCode ierr;
423095059a4SDave May 
424095059a4SDave May   PetscFunctionBegin;
425521f74f9SMatthew G. Knepley   if (de->topology_status != DEOBJECT_FINALIZED) SETERRQ(de->comm, PETSC_ERR_ORDER, "Topology not finalized");
426ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerSendCount,0,0,0,0);CHKERRQ(ierr);
427095059a4SDave May   de->message_lengths_status = DEOBJECT_INITIALIZED;
428521f74f9SMatthew G. Knepley   for (i = 0; i < de->n_neighbour_procs; ++i) {
429095059a4SDave May     de->messages_to_be_sent[i] = 0;
430095059a4SDave May   }
431095059a4SDave May   PetscFunctionReturn(0);
432095059a4SDave May }
433095059a4SDave May 
434095059a4SDave May /*
435095059a4SDave May 1) only allows counters to be set on neighbouring cpus
436095059a4SDave May */
437095059a4SDave May PetscErrorCode DataExAddToSendCount(DataEx de,const PetscMPIInt proc_id,const PetscInt count)
438095059a4SDave May {
439095059a4SDave May   PetscMPIInt    local_val;
440095059a4SDave May   PetscErrorCode ierr;
441095059a4SDave May 
442095059a4SDave May   PetscFunctionBegin;
4432064fc68SDave 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" );
4442064fc68SDave May   else if (de->message_lengths_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DataExInitializeSendCount() first" );
4452064fc68SDave May 
446095059a4SDave May   ierr = _DataExConvertProcIdToLocalIndex( de, proc_id, &local_val );CHKERRQ(ierr);
4472064fc68SDave May   if (local_val == -1) SETERRQ1( PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,"Proc %d is not a valid neighbour rank", (int)proc_id );
4482064fc68SDave May 
449095059a4SDave May   de->messages_to_be_sent[local_val] = de->messages_to_be_sent[local_val] + count;
450095059a4SDave May   PetscFunctionReturn(0);
451095059a4SDave May }
452095059a4SDave May 
453095059a4SDave May PetscErrorCode DataExFinalizeSendCount(DataEx de)
454095059a4SDave May {
455ed923d71SDave May   PetscErrorCode ierr;
456ed923d71SDave May 
457095059a4SDave May   PetscFunctionBegin;
4582064fc68SDave May   if (de->message_lengths_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DataExInitializeSendCount() first" );
4592064fc68SDave May 
460095059a4SDave May   de->message_lengths_status = DEOBJECT_FINALIZED;
461ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerSendCount,0,0,0,0);CHKERRQ(ierr);
462095059a4SDave May   PetscFunctionReturn(0);
463095059a4SDave May }
464095059a4SDave May 
465095059a4SDave May /* === Phase C === */
466095059a4SDave May /*
467095059a4SDave May  * zero out all send counts
468095059a4SDave May  * free send and recv buffers
469095059a4SDave May  * zeros out message length
470095059a4SDave May  * zeros out all counters
471095059a4SDave May  * zero out packed data counters
472095059a4SDave May */
473095059a4SDave May PetscErrorCode _DataExInitializeTmpStorage(DataEx de)
474095059a4SDave May {
475095059a4SDave May   PetscMPIInt    i, np;
476521f74f9SMatthew G. Knepley   PetscErrorCode ierr;
477095059a4SDave May 
478095059a4SDave May   PetscFunctionBegin;
4792064fc68SDave May   /*if (de->n_neighbour_procs < 0) SETERRQ( PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of neighbour procs < 0");
480b9a482c4SDave May   */
481b9a482c4SDave May   /*
4822064fc68SDave May   if (!de->neighbour_procs) SETERRQ( PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Neighbour proc list is NULL" );
483b9a482c4SDave May   */
484095059a4SDave May   np = de->n_neighbour_procs;
485521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
486095059a4SDave May     /*	de->messages_to_be_sent[i] = -1; */
487095059a4SDave May     de->messages_to_be_recvieved[i] = -1;
488095059a4SDave May   }
489521f74f9SMatthew G. Knepley   ierr = PetscFree(de->send_message);CHKERRQ(ierr);
490521f74f9SMatthew G. Knepley   ierr = PetscFree(de->recv_message);CHKERRQ(ierr);
491095059a4SDave May   PetscFunctionReturn(0);
492095059a4SDave May }
493095059a4SDave May 
494095059a4SDave May /*
495095059a4SDave May *) Zeros out pack data counters
496095059a4SDave May *) Ensures mesaage length is set
497095059a4SDave May *) Checks send counts properly initialized
498095059a4SDave May *) allocates space for pack data
499095059a4SDave May */
500095059a4SDave May PetscErrorCode DataExPackInitialize(DataEx de,size_t unit_message_size)
501095059a4SDave May {
502095059a4SDave May   PetscMPIInt    i,np;
503095059a4SDave May   PetscInt       total;
504095059a4SDave May   PetscErrorCode ierr;
505095059a4SDave May 
506095059a4SDave May   PetscFunctionBegin;
507521f74f9SMatthew G. Knepley   if (de->topology_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Topology not finalized" );
508521f74f9SMatthew G. Knepley   if (de->message_lengths_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths not finalized" );
509ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerPack,0,0,0,0);CHKERRQ(ierr);
510095059a4SDave May   de->packer_status = DEOBJECT_INITIALIZED;
511095059a4SDave May   ierr = _DataExInitializeTmpStorage(de);CHKERRQ(ierr);
512095059a4SDave May   np = de->n_neighbour_procs;
513095059a4SDave May   de->unit_message_size = unit_message_size;
514095059a4SDave May   total = 0;
515521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
516095059a4SDave May     if (de->messages_to_be_sent[i] == -1) {
517095059a4SDave May       PetscMPIInt proc_neighour = de->neighbour_procs[i];
518095059a4SDave May       SETERRQ1( PETSC_COMM_SELF, PETSC_ERR_ORDER, "Messages_to_be_sent[neighbour_proc=%d] is un-initialised. Call DataExSetSendCount() first", (int)proc_neighour );
519095059a4SDave May     }
520095059a4SDave May     total = total + de->messages_to_be_sent[i];
521095059a4SDave May   }
522095059a4SDave May   /* create space for the data to be sent */
523521f74f9SMatthew G. Knepley   ierr = PetscMalloc(unit_message_size * (total + 1), &de->send_message);CHKERRQ(ierr);
524095059a4SDave May   /* initialize memory */
525521f74f9SMatthew G. Knepley   ierr = PetscMemzero(de->send_message, unit_message_size * (total + 1));CHKERRQ(ierr);
526095059a4SDave May   /* set total items to send */
527095059a4SDave May   de->send_message_length = total;
528095059a4SDave May   de->message_offsets[0] = 0;
529095059a4SDave May   total = de->messages_to_be_sent[0];
530521f74f9SMatthew G. Knepley   for (i = 1; i < np; ++i) {
531095059a4SDave May     de->message_offsets[i] = total;
532095059a4SDave May     total = total + de->messages_to_be_sent[i];
533095059a4SDave May   }
534095059a4SDave May   /* init the packer counters */
535095059a4SDave May   de->total_pack_cnt = 0;
536521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
537095059a4SDave May     de->pack_cnt[i] = 0;
538095059a4SDave May   }
539095059a4SDave May   PetscFunctionReturn(0);
540095059a4SDave May }
541095059a4SDave May 
542095059a4SDave May /*
543095059a4SDave May *) Ensures data gets been packed appropriately and no overlaps occur
544095059a4SDave May */
545095059a4SDave May PetscErrorCode DataExPackData(DataEx de,PetscMPIInt proc_id,PetscInt n,void *data)
546095059a4SDave May {
547095059a4SDave May   PetscMPIInt    local;
548095059a4SDave May   PetscInt       insert_location;
549095059a4SDave May   void           *dest;
550095059a4SDave May   PetscErrorCode ierr;
551095059a4SDave May 
552095059a4SDave May   PetscFunctionBegin;
5532064fc68SDave 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" );
5542064fc68SDave May   else if (de->packer_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Packed data must be defined. Call DataExInitializeSendCount(), DataExAddToSendCount(), DataExPackInitialize() first" );
5552064fc68SDave May 
556521f74f9SMatthew G. Knepley   if (!de->send_message) SETERRQ( de->comm, PETSC_ERR_ORDER, "send_message is not initialized. Call DataExPackInitialize() first" );
557095059a4SDave May   ierr = _DataExConvertProcIdToLocalIndex( de, proc_id, &local );CHKERRQ(ierr);
558521f74f9SMatthew G. Knepley   if (local == -1) SETERRQ1( PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "proc_id %d is not registered neighbour", (int)proc_id );
5592064fc68SDave 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",
560095059a4SDave May               (int)proc_id, de->messages_to_be_sent[local], n+de->pack_cnt[local] );
5612064fc68SDave May 
562095059a4SDave May   /* copy memory */
563095059a4SDave May   insert_location = de->message_offsets[local] + de->pack_cnt[local];
564095059a4SDave May   dest = ((char*)de->send_message) + de->unit_message_size*insert_location;
565521f74f9SMatthew G. Knepley   ierr = PetscMemcpy(dest, data, de->unit_message_size * n);CHKERRQ(ierr);
566095059a4SDave May   /* increment counter */
567095059a4SDave May   de->pack_cnt[local] = de->pack_cnt[local] + n;
568095059a4SDave May   PetscFunctionReturn(0);
569095059a4SDave May }
570095059a4SDave May 
571095059a4SDave May /*
572095059a4SDave May *) Ensures all data has been packed
573095059a4SDave May */
574095059a4SDave May PetscErrorCode DataExPackFinalize(DataEx de)
575095059a4SDave May {
576095059a4SDave May   PetscMPIInt i,np;
577095059a4SDave May   PetscInt    total;
578095059a4SDave May   PetscErrorCode ierr;
579095059a4SDave May 
580095059a4SDave May   PetscFunctionBegin;
581521f74f9SMatthew G. Knepley   if (de->packer_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Packer has not been initialized. Must call DataExPackInitialize() first." );
582095059a4SDave May   np = de->n_neighbour_procs;
583521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
5842064fc68SDave 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",
585095059a4SDave May                 (int)de->neighbour_procs[i], de->messages_to_be_sent[i], de->pack_cnt[i] );
586095059a4SDave May   }
587095059a4SDave May   /* init */
588521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
589095059a4SDave May     de->messages_to_be_recvieved[i] = -1;
590095059a4SDave May   }
591095059a4SDave May   /* figure out the recv counts here */
592521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
593095059a4SDave 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);
594095059a4SDave May   }
595521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
596095059a4SDave 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);
597095059a4SDave May   }
598095059a4SDave May   ierr = MPI_Waitall(2*np, de->_requests, de->_stats);CHKERRQ(ierr);
599095059a4SDave May   /* create space for the data to be recvieved */
600095059a4SDave May   total = 0;
601521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
602095059a4SDave May     total = total + de->messages_to_be_recvieved[i];
603095059a4SDave May   }
604521f74f9SMatthew G. Knepley   ierr = PetscMalloc(de->unit_message_size * (total + 1), &de->recv_message);CHKERRQ(ierr);
605095059a4SDave May   /* initialize memory */
606521f74f9SMatthew G. Knepley   ierr = PetscMemzero(de->recv_message, de->unit_message_size * (total + 1));CHKERRQ(ierr);
607095059a4SDave May   /* set total items to recieve */
608095059a4SDave May   de->recv_message_length = total;
609095059a4SDave May   de->packer_status = DEOBJECT_FINALIZED;
610095059a4SDave May   de->communication_status = DEOBJECT_INITIALIZED;
611ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerPack,0,0,0,0);CHKERRQ(ierr);
612095059a4SDave May   PetscFunctionReturn(0);
613095059a4SDave May }
614095059a4SDave May 
615095059a4SDave May /* do the actual message passing now */
616095059a4SDave May PetscErrorCode DataExBegin(DataEx de)
617095059a4SDave May {
618095059a4SDave May   PetscMPIInt i,np;
619095059a4SDave May   void       *dest;
620095059a4SDave May   PetscInt    length;
621095059a4SDave May   PetscErrorCode ierr;
622095059a4SDave May 
623095059a4SDave May   PetscFunctionBegin;
624521f74f9SMatthew G. Knepley   if (de->topology_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Topology not finalized" );
625521f74f9SMatthew G. Knepley   if (de->message_lengths_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths not finalized" );
626521f74f9SMatthew G. Knepley   if (de->packer_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Packer not finalized" );
627521f74f9SMatthew G. Knepley   if (de->communication_status == DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Communication has already been finalized. Must call DataExInitialize() first." );
628521f74f9SMatthew G. Knepley   if (!de->recv_message) SETERRQ( de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DataExPackFinalize() first" );
629ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerBegin,0,0,0,0);CHKERRQ(ierr);
630095059a4SDave May   np = de->n_neighbour_procs;
631095059a4SDave May   /* == NON BLOCKING == */
632521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
633095059a4SDave May     length = de->messages_to_be_sent[i] * de->unit_message_size;
634095059a4SDave May     dest = ((char*)de->send_message) + de->unit_message_size * de->message_offsets[i];
635095059a4SDave May     ierr = MPI_Isend( dest, length, MPI_CHAR, de->neighbour_procs[i], de->send_tags[i], de->comm, &de->_requests[i] );CHKERRQ(ierr);
636095059a4SDave May   }
637ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerBegin,0,0,0,0);CHKERRQ(ierr);
638095059a4SDave May   PetscFunctionReturn(0);
639095059a4SDave May }
640095059a4SDave May 
641095059a4SDave May /* do the actual message passing now */
642095059a4SDave May PetscErrorCode DataExEnd(DataEx de)
643095059a4SDave May {
644095059a4SDave May   PetscMPIInt  i,np;
645095059a4SDave May   PetscInt     total;
646095059a4SDave May   PetscInt    *message_recv_offsets;
647095059a4SDave May   void        *dest;
648095059a4SDave May   PetscInt     length;
649095059a4SDave May   PetscErrorCode ierr;
650095059a4SDave May 
651095059a4SDave May   PetscFunctionBegin;
652521f74f9SMatthew G. Knepley   if (de->communication_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Communication has not been initialized. Must call DataExInitialize() first." );
653521f74f9SMatthew G. Knepley   if (!de->recv_message) SETERRQ( de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DataExPackFinalize() first" );
654ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerEnd,0,0,0,0);CHKERRQ(ierr);
655095059a4SDave May   np = de->n_neighbour_procs;
656b9a482c4SDave May   ierr = PetscMalloc1(np+1, &message_recv_offsets);CHKERRQ(ierr);
657095059a4SDave May   message_recv_offsets[0] = 0;
658095059a4SDave May   total = de->messages_to_be_recvieved[0];
659521f74f9SMatthew G. Knepley   for (i = 1; i < np; ++i) {
660095059a4SDave May     message_recv_offsets[i] = total;
661095059a4SDave May     total = total + de->messages_to_be_recvieved[i];
662095059a4SDave May   }
663095059a4SDave May   /* == NON BLOCKING == */
664521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
665095059a4SDave May     length = de->messages_to_be_recvieved[i] * de->unit_message_size;
666095059a4SDave May     dest = ((char*)de->recv_message) + de->unit_message_size * message_recv_offsets[i];
667095059a4SDave May     ierr = MPI_Irecv( dest, length, MPI_CHAR, de->neighbour_procs[i], de->recv_tags[i], de->comm, &de->_requests[np+i] );CHKERRQ(ierr);
668095059a4SDave May   }
669095059a4SDave May   ierr = MPI_Waitall( 2*np, de->_requests, de->_stats );CHKERRQ(ierr);
670459726d8SSatish Balay   ierr = PetscFree(message_recv_offsets);CHKERRQ(ierr);
671095059a4SDave May   de->communication_status = DEOBJECT_FINALIZED;
672ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerEnd,0,0,0,0);CHKERRQ(ierr);
673095059a4SDave May   PetscFunctionReturn(0);
674095059a4SDave May }
675095059a4SDave May 
676095059a4SDave May PetscErrorCode DataExGetSendData(DataEx de,PetscInt *length,void **send)
677095059a4SDave May {
678095059a4SDave May   PetscFunctionBegin;
679521f74f9SMatthew G. Knepley   if (de->packer_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being packed." );
680095059a4SDave May   *length = de->send_message_length;
681095059a4SDave May   *send   = de->send_message;
682095059a4SDave May   PetscFunctionReturn(0);
683095059a4SDave May }
684095059a4SDave May 
685095059a4SDave May PetscErrorCode DataExGetRecvData(DataEx de,PetscInt *length,void **recv)
686095059a4SDave May {
687095059a4SDave May   PetscFunctionBegin;
688521f74f9SMatthew G. Knepley   if (de->communication_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being sent." );
689095059a4SDave May   *length = de->recv_message_length;
690095059a4SDave May   *recv   = de->recv_message;
691095059a4SDave May   PetscFunctionReturn(0);
692095059a4SDave May }
693095059a4SDave May 
694095059a4SDave May PetscErrorCode DataExTopologyGetNeighbours(DataEx de,PetscMPIInt *n,PetscMPIInt *neigh[])
695095059a4SDave May {
696095059a4SDave May   PetscFunctionBegin;
697095059a4SDave May   if (n)     {*n     = de->n_neighbour_procs;}
698095059a4SDave May   if (neigh) {*neigh = de->neighbour_procs;}
699095059a4SDave May   PetscFunctionReturn(0);
700095059a4SDave May }
701095059a4SDave May 
702