xref: /petsc/src/dm/impls/swarm/data_ex.c (revision a5b23f4acc7afc99d3844ebd5fb65a81c16e8b8c)
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 {
86095059a4SDave May   PetscErrorCode ierr;
8777048351SPatrick Sanan   DMSwarmDataEx  d;
88095059a4SDave May 
89521f74f9SMatthew G. Knepley   PetscFunctionBegin;
9077048351SPatrick Sanan   ierr = PetscMalloc(sizeof(struct _p_DMSwarmDataEx), &d);CHKERRQ(ierr);
9177048351SPatrick Sanan   ierr = PetscMemzero(d, sizeof(struct _p_DMSwarmDataEx));CHKERRQ(ierr);
92ffc4695bSBarry Smith   ierr = MPI_Comm_dup(comm,&d->comm);CHKERRMPI(ierr);
93ffc4695bSBarry Smith   ierr = MPI_Comm_rank(d->comm,&d->rank);CHKERRMPI(ierr);
94095059a4SDave May 
95095059a4SDave May   d->instance = count;
96095059a4SDave May 
97095059a4SDave May   d->topology_status        = DEOBJECT_STATE_UNKNOWN;
98095059a4SDave May   d->message_lengths_status = DEOBJECT_STATE_UNKNOWN;
99095059a4SDave May   d->packer_status          = DEOBJECT_STATE_UNKNOWN;
100095059a4SDave May   d->communication_status   = DEOBJECT_STATE_UNKNOWN;
101095059a4SDave May 
102095059a4SDave May   d->n_neighbour_procs = -1;
103095059a4SDave May   d->neighbour_procs   = NULL;
104095059a4SDave May 
105095059a4SDave May   d->messages_to_be_sent      = NULL;
106095059a4SDave May   d->message_offsets          = NULL;
107095059a4SDave May   d->messages_to_be_recvieved = NULL;
108095059a4SDave May 
10978c64234SJose E. Roman   d->unit_message_size   = (size_t)-1;
110095059a4SDave May   d->send_message        = NULL;
111095059a4SDave May   d->send_message_length = -1;
112095059a4SDave May   d->recv_message        = NULL;
113095059a4SDave May   d->recv_message_length = -1;
114095059a4SDave May   d->total_pack_cnt      = -1;
115095059a4SDave May   d->pack_cnt            = NULL;
116095059a4SDave May 
117095059a4SDave May   d->send_tags = NULL;
118095059a4SDave May   d->recv_tags = NULL;
119095059a4SDave May 
120095059a4SDave May   d->_stats    = NULL;
121095059a4SDave May   d->_requests = NULL;
122521f74f9SMatthew G. Knepley   *ex = d;
123521f74f9SMatthew G. Knepley   PetscFunctionReturn(0);
124095059a4SDave May }
125095059a4SDave May 
126298827fbSBarry Smith /*
1279dddd249SSatish Balay     This code is horrible, who let it get into main.
128298827fbSBarry Smith 
129298827fbSBarry Smith     Should be printing to a viewer, should not be using PETSC_COMM_WORLD
130298827fbSBarry Smith 
131298827fbSBarry Smith */
13277048351SPatrick Sanan PetscErrorCode DMSwarmDataExView(DMSwarmDataEx d)
133095059a4SDave May {
134095059a4SDave May   PetscMPIInt    p;
135521f74f9SMatthew G. Knepley   PetscErrorCode ierr;
136095059a4SDave May 
137095059a4SDave May   PetscFunctionBegin;
13877048351SPatrick Sanan   ierr = PetscPrintf( PETSC_COMM_WORLD, "DMSwarmDataEx: instance=%D\n",d->instance);CHKERRQ(ierr);
139521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  topology status:        %s \n", status_names[d->topology_status]);CHKERRQ(ierr);
140521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  message lengths status: %s \n", status_names[d->message_lengths_status]);CHKERRQ(ierr);
141521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  packer status status:   %s \n", status_names[d->packer_status]);CHKERRQ(ierr);
142521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  communication status:   %s \n", status_names[d->communication_status]);CHKERRQ(ierr);
143095059a4SDave May 
144095059a4SDave May   if (d->topology_status == DEOBJECT_FINALIZED) {
145521f74f9SMatthew G. Knepley     ierr = PetscPrintf( PETSC_COMM_WORLD, "  Topology:\n");CHKERRQ(ierr);
146dfe27cbaSBarry Smith     ierr = PetscSynchronizedPrintf( PETSC_COMM_WORLD, "    [%d] neighbours: %d \n", d->rank, d->n_neighbour_procs);CHKERRQ(ierr);
147095059a4SDave May     for (p=0; p<d->n_neighbour_procs; p++) {
148dfe27cbaSBarry Smith       ierr = PetscSynchronizedPrintf( PETSC_COMM_WORLD, "    [%d]   neighbour[%d] = %d \n", d->rank, p, d->neighbour_procs[p]);CHKERRQ(ierr);
149095059a4SDave May     }
150298827fbSBarry Smith     ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,stdout);CHKERRQ(ierr);
151095059a4SDave May   }
152298827fbSBarry Smith 
153095059a4SDave May   if (d->message_lengths_status == DEOBJECT_FINALIZED) {
154521f74f9SMatthew G. Knepley     ierr = PetscPrintf( PETSC_COMM_WORLD, "  Message lengths:\n");CHKERRQ(ierr);
155dfe27cbaSBarry Smith     ierr = PetscSynchronizedPrintf( PETSC_COMM_WORLD, "    [%d] atomic size: %ld \n", d->rank, (long int)d->unit_message_size);CHKERRQ(ierr);
156095059a4SDave May     for (p=0; p<d->n_neighbour_procs; p++) {
157dfe27cbaSBarry Smith       ierr = 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]);CHKERRQ(ierr);
158095059a4SDave May     }
159095059a4SDave May     for (p=0; p<d->n_neighbour_procs; p++) {
160dfe27cbaSBarry Smith       ierr = 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]);CHKERRQ(ierr);
161095059a4SDave May     }
162298827fbSBarry Smith     ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,stdout);CHKERRQ(ierr);
163095059a4SDave May   }
164521f74f9SMatthew G. Knepley   if (d->packer_status == DEOBJECT_FINALIZED) {}
165521f74f9SMatthew G. Knepley   if (d->communication_status == DEOBJECT_FINALIZED) {}
166095059a4SDave May   PetscFunctionReturn(0);
167095059a4SDave May }
168095059a4SDave May 
16977048351SPatrick Sanan PetscErrorCode DMSwarmDataExDestroy(DMSwarmDataEx d)
170095059a4SDave May {
171095059a4SDave May   PetscErrorCode ierr;
172095059a4SDave May 
173095059a4SDave May   PetscFunctionBegin;
174ffc4695bSBarry Smith   ierr = MPI_Comm_free(&d->comm);CHKERRMPI(ierr);
175521f74f9SMatthew G. Knepley   if (d->neighbour_procs) {ierr = PetscFree(d->neighbour_procs);CHKERRQ(ierr);}
176521f74f9SMatthew G. Knepley   if (d->messages_to_be_sent) {ierr = PetscFree(d->messages_to_be_sent);CHKERRQ(ierr);}
177521f74f9SMatthew G. Knepley   if (d->message_offsets) {ierr = PetscFree(d->message_offsets);CHKERRQ(ierr);}
178521f74f9SMatthew G. Knepley   if (d->messages_to_be_recvieved) {ierr = PetscFree(d->messages_to_be_recvieved);CHKERRQ(ierr);}
179521f74f9SMatthew G. Knepley   if (d->send_message) {ierr = PetscFree(d->send_message);CHKERRQ(ierr);}
180521f74f9SMatthew G. Knepley   if (d->recv_message) {ierr = PetscFree(d->recv_message);CHKERRQ(ierr);}
181521f74f9SMatthew G. Knepley   if (d->pack_cnt) {ierr = PetscFree(d->pack_cnt);CHKERRQ(ierr);}
182521f74f9SMatthew G. Knepley   if (d->send_tags) {ierr = PetscFree(d->send_tags);CHKERRQ(ierr);}
183521f74f9SMatthew G. Knepley   if (d->recv_tags) {ierr = PetscFree(d->recv_tags);CHKERRQ(ierr);}
184521f74f9SMatthew G. Knepley   if (d->_stats) {ierr = PetscFree(d->_stats);CHKERRQ(ierr);}
185521f74f9SMatthew G. Knepley   if (d->_requests) {ierr = PetscFree(d->_requests);CHKERRQ(ierr);}
186521f74f9SMatthew G. Knepley   ierr = PetscFree(d);CHKERRQ(ierr);
187095059a4SDave May   PetscFunctionReturn(0);
188095059a4SDave May }
189095059a4SDave May 
190095059a4SDave May /* === Phase A === */
191095059a4SDave May 
19277048351SPatrick Sanan PetscErrorCode DMSwarmDataExTopologyInitialize(DMSwarmDataEx d)
193095059a4SDave May {
194521f74f9SMatthew G. Knepley   PetscErrorCode ierr;
195521f74f9SMatthew G. Knepley 
196095059a4SDave May   PetscFunctionBegin;
197095059a4SDave May   d->topology_status = DEOBJECT_INITIALIZED;
198095059a4SDave May   d->n_neighbour_procs = 0;
199781df12bSMatthew G. Knepley   ierr = PetscFree(d->neighbour_procs);CHKERRQ(ierr);
200781df12bSMatthew G. Knepley   ierr = PetscFree(d->messages_to_be_sent);CHKERRQ(ierr);
201781df12bSMatthew G. Knepley   ierr = PetscFree(d->message_offsets);CHKERRQ(ierr);
202781df12bSMatthew G. Knepley   ierr = PetscFree(d->messages_to_be_recvieved);CHKERRQ(ierr);
203781df12bSMatthew G. Knepley   ierr = PetscFree(d->pack_cnt);CHKERRQ(ierr);
204781df12bSMatthew G. Knepley   ierr = PetscFree(d->send_tags);CHKERRQ(ierr);
205781df12bSMatthew G. Knepley   ierr = PetscFree(d->recv_tags);CHKERRQ(ierr);
206095059a4SDave May   PetscFunctionReturn(0);
207095059a4SDave May }
208095059a4SDave May 
20977048351SPatrick Sanan PetscErrorCode DMSwarmDataExTopologyAddNeighbour(DMSwarmDataEx d,const PetscMPIInt proc_id)
210095059a4SDave May {
211095059a4SDave May   PetscMPIInt    n,found;
212d7d19db6SBarry Smith   PetscMPIInt    size;
213095059a4SDave May   PetscErrorCode ierr;
214095059a4SDave May 
215095059a4SDave May   PetscFunctionBegin;
21677048351SPatrick Sanan   if (d->topology_status == DEOBJECT_FINALIZED) SETERRQ(d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology has been finalized. To modify or update call DMSwarmDataExTopologyInitialize() first");
2172d4ee042Sprj-   else if (d->topology_status != DEOBJECT_INITIALIZED) SETERRQ(d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be initialised. Call DMSwarmDataExTopologyInitialize() first");
2182064fc68SDave May 
219095059a4SDave May   /* error on negative entries */
220521f74f9SMatthew G. Knepley   if (proc_id < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Trying to set proc neighbour with a rank < 0");
221095059a4SDave May   /* error on ranks larger than number of procs in communicator */
222ffc4695bSBarry Smith   ierr = MPI_Comm_size(d->comm,&size);CHKERRMPI(ierr);
223d7d19db6SBarry 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);
224521f74f9SMatthew G. Knepley   if (d->n_neighbour_procs == 0) {ierr = PetscMalloc1(1, &d->neighbour_procs);CHKERRQ(ierr);}
225095059a4SDave May   /* check for proc_id */
226095059a4SDave May   found = 0;
227095059a4SDave May   for (n = 0; n < d->n_neighbour_procs; n++) {
228095059a4SDave May     if (d->neighbour_procs[n] == proc_id) {
229095059a4SDave May       found  = 1;
230095059a4SDave May     }
231095059a4SDave May   }
232095059a4SDave May   if (found == 0) { /* add it to list */
2334be7464cSMatthew G. Knepley     ierr = PetscRealloc(sizeof(PetscMPIInt)*(d->n_neighbour_procs+1), &d->neighbour_procs);CHKERRQ(ierr);
234095059a4SDave May     d->neighbour_procs[ d->n_neighbour_procs ] = proc_id;
235095059a4SDave May     d->n_neighbour_procs++;
236095059a4SDave May   }
237095059a4SDave May   PetscFunctionReturn(0);
238095059a4SDave May }
239095059a4SDave May 
240095059a4SDave May /*
241095059a4SDave May counter: the index of the communication object
242095059a4SDave May N: the number of processors
243095059a4SDave May r0: rank of sender
244095059a4SDave May r1: rank of receiver
245095059a4SDave May 
246095059a4SDave May procs = { 0, 1, 2, 3 }
247095059a4SDave May 
248095059a4SDave May 0 ==> 0         e=0
249095059a4SDave May 0 ==> 1         e=1
250095059a4SDave May 0 ==> 2         e=2
251095059a4SDave May 0 ==> 3         e=3
252095059a4SDave May 
253095059a4SDave May 1 ==> 0         e=4
254095059a4SDave May 1 ==> 1         e=5
255095059a4SDave May 1 ==> 2         e=6
256095059a4SDave May 1 ==> 3         e=7
257095059a4SDave May 
258095059a4SDave May 2 ==> 0         e=8
259095059a4SDave May 2 ==> 1         e=9
260095059a4SDave May 2 ==> 2         e=10
261095059a4SDave May 2 ==> 3         e=11
262095059a4SDave May 
263095059a4SDave May 3 ==> 0         e=12
264095059a4SDave May 3 ==> 1         e=13
265095059a4SDave May 3 ==> 2         e=14
266095059a4SDave May 3 ==> 3         e=15
267095059a4SDave May 
268095059a4SDave May If we require that proc A sends to proc B, then the SEND tag index will be given by
269095059a4SDave May   N * rank(A) + rank(B) + offset
270095059a4SDave May If we require that proc A will receive from proc B, then the RECV tag index will be given by
271095059a4SDave May   N * rank(B) + rank(A) + offset
272095059a4SDave May 
273095059a4SDave May */
274521f74f9SMatthew G. Knepley static void _get_tags(PetscInt counter, PetscMPIInt N, PetscMPIInt r0,PetscMPIInt r1, PetscMPIInt *_st, PetscMPIInt *_rt)
275095059a4SDave May {
276095059a4SDave May   PetscMPIInt st,rt;
277095059a4SDave May 
278095059a4SDave May   st = N*r0 + r1   +   N*N*counter;
279095059a4SDave May   rt = N*r1 + r0   +   N*N*counter;
280095059a4SDave May   *_st = st;
281095059a4SDave May   *_rt = rt;
282095059a4SDave May }
283095059a4SDave May 
284095059a4SDave May /*
285095059a4SDave May Makes the communication map symmetric
286095059a4SDave May */
28777048351SPatrick Sanan PetscErrorCode _DMSwarmDataExCompleteCommunicationMap(MPI_Comm comm,PetscMPIInt n,PetscMPIInt proc_neighbours[],PetscMPIInt *n_new,PetscMPIInt **proc_neighbours_new)
288095059a4SDave May {
289dcf43ee8SDave May   Mat               A;
290095059a4SDave May   PetscInt          i,j,nc;
291095059a4SDave May   PetscInt          n_, *proc_neighbours_;
292e4fbd051SBarry Smith   PetscInt          rank_;
293e4fbd051SBarry Smith   PetscMPIInt       size,  rank;
294095059a4SDave May   PetscScalar       *vals;
295095059a4SDave May   const PetscInt    *cols;
296095059a4SDave May   const PetscScalar *red_vals;
297095059a4SDave May   PetscMPIInt       _n_new, *_proc_neighbours_new;
298095059a4SDave May   PetscErrorCode    ierr;
299095059a4SDave May 
300095059a4SDave May   PetscFunctionBegin;
301095059a4SDave May   n_ = n;
302095059a4SDave May   ierr = PetscMalloc(sizeof(PetscInt) * n_, &proc_neighbours_);CHKERRQ(ierr);
303521f74f9SMatthew G. Knepley   for (i = 0; i < n_; ++i) {
304095059a4SDave May     proc_neighbours_[i] = proc_neighbours[i];
305095059a4SDave May   }
306ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
307ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
308e4fbd051SBarry Smith   rank_ = rank;
309095059a4SDave May 
310095059a4SDave May   ierr = MatCreate(comm,&A);CHKERRQ(ierr);
311095059a4SDave May   ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,size,size);CHKERRQ(ierr);
312095059a4SDave May   ierr = MatSetType(A,MATAIJ);CHKERRQ(ierr);
313dcf43ee8SDave May   ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
314dcf43ee8SDave May   ierr = MatMPIAIJSetPreallocation(A,n_,NULL,n_,NULL);CHKERRQ(ierr);
315dcf43ee8SDave May   ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);CHKERRQ(ierr);
316095059a4SDave May   /* Build original map */
317521f74f9SMatthew G. Knepley   ierr = PetscMalloc1(n_, &vals);CHKERRQ(ierr);
318521f74f9SMatthew G. Knepley   for (i = 0; i < n_; ++i) {
319095059a4SDave May     vals[i] = 1.0;
320095059a4SDave May   }
321e4fbd051SBarry Smith   ierr = MatSetValues( A, 1,&rank_, n_,proc_neighbours_, vals, INSERT_VALUES);CHKERRQ(ierr);
322095059a4SDave May   ierr = MatAssemblyBegin(A,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
323095059a4SDave May   ierr = MatAssemblyEnd(A,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
324095059a4SDave May   /* Now force all other connections if they are not already there */
325095059a4SDave May   /* It's more efficient to do them all at once */
326521f74f9SMatthew G. Knepley   for (i = 0; i < n_; ++i) {
327095059a4SDave May     vals[i] = 2.0;
328095059a4SDave May   }
329e4fbd051SBarry Smith   ierr = MatSetValues( A, n_,proc_neighbours_, 1,&rank_, vals, INSERT_VALUES);CHKERRQ(ierr);
330095059a4SDave May   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
331095059a4SDave May   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3326275818cSDave May /*
333095059a4SDave May   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr);
334095059a4SDave May   ierr = MatView(A,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
335095059a4SDave May   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
3366275818cSDave May */
337095059a4SDave May   if ((n_new != NULL) && (proc_neighbours_new != NULL)) {
338e4fbd051SBarry Smith     ierr = MatGetRow(A, rank_, &nc, &cols, &red_vals);CHKERRQ(ierr);
339095059a4SDave May     _n_new = (PetscMPIInt) nc;
340521f74f9SMatthew G. Knepley     ierr = PetscMalloc1(_n_new, &_proc_neighbours_new);CHKERRQ(ierr);
341521f74f9SMatthew G. Knepley     for (j = 0; j < nc; ++j) {
342095059a4SDave May       _proc_neighbours_new[j] = (PetscMPIInt)cols[j];
343095059a4SDave May     }
344e4fbd051SBarry Smith     ierr = MatRestoreRow( A, rank_, &nc, &cols, &red_vals);CHKERRQ(ierr);
345095059a4SDave May     *n_new               = (PetscMPIInt)_n_new;
346095059a4SDave May     *proc_neighbours_new = (PetscMPIInt*)_proc_neighbours_new;
347095059a4SDave May   }
348095059a4SDave May   ierr = MatDestroy(&A);CHKERRQ(ierr);
349095059a4SDave May   ierr = PetscFree(vals);CHKERRQ(ierr);
350095059a4SDave May   ierr = PetscFree(proc_neighbours_);CHKERRQ(ierr);
351ffc4695bSBarry Smith   ierr = MPI_Barrier(comm);CHKERRMPI(ierr);
352095059a4SDave May   PetscFunctionReturn(0);
353095059a4SDave May }
354095059a4SDave May 
35577048351SPatrick Sanan PetscErrorCode DMSwarmDataExTopologyFinalize(DMSwarmDataEx d)
356095059a4SDave May {
357095059a4SDave May   PetscMPIInt    symm_nn;
358095059a4SDave May   PetscMPIInt   *symm_procs;
359095059a4SDave May   PetscMPIInt    r0,n,st,rt;
360d7d19db6SBarry Smith   PetscMPIInt    size;
361095059a4SDave May   PetscErrorCode ierr;
362095059a4SDave May 
363095059a4SDave May   PetscFunctionBegin;
3642d4ee042Sprj-   if (d->topology_status != DEOBJECT_INITIALIZED) SETERRQ(d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be initialised. Call DMSwarmDataExTopologyInitialize() first");
3652064fc68SDave May 
366ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerTopologySetup,0,0,0,0);CHKERRQ(ierr);
367*a5b23f4aSJose E. Roman   /* given information about all my neighbours, make map symmetric */
36877048351SPatrick Sanan   ierr = _DMSwarmDataExCompleteCommunicationMap( d->comm,d->n_neighbour_procs,d->neighbour_procs, &symm_nn, &symm_procs);CHKERRQ(ierr);
369095059a4SDave May   /* update my arrays */
370459726d8SSatish Balay   ierr = PetscFree(d->neighbour_procs);CHKERRQ(ierr);
371095059a4SDave May   d->n_neighbour_procs = symm_nn;
372095059a4SDave May   d->neighbour_procs   = symm_procs;
373095059a4SDave May   /* allocates memory */
374b9a482c4SDave May   if (!d->messages_to_be_sent) {ierr = PetscMalloc1(d->n_neighbour_procs+1, &d->messages_to_be_sent);CHKERRQ(ierr);}
375b9a482c4SDave May   if (!d->message_offsets) {ierr = PetscMalloc1(d->n_neighbour_procs+1, &d->message_offsets);CHKERRQ(ierr);}
376b9a482c4SDave May   if (!d->messages_to_be_recvieved) {ierr = PetscMalloc1(d->n_neighbour_procs+1, &d->messages_to_be_recvieved);CHKERRQ(ierr);}
377521f74f9SMatthew G. Knepley   if (!d->pack_cnt) {ierr = PetscMalloc(sizeof(PetscInt) * d->n_neighbour_procs, &d->pack_cnt);CHKERRQ(ierr);}
378521f74f9SMatthew G. Knepley   if (!d->_stats) {ierr = PetscMalloc(sizeof(MPI_Status) * 2*d->n_neighbour_procs, &d->_stats);CHKERRQ(ierr);}
379521f74f9SMatthew G. Knepley   if (!d->_requests) {ierr = PetscMalloc(sizeof(MPI_Request) * 2*d->n_neighbour_procs, &d->_requests);CHKERRQ(ierr);}
380521f74f9SMatthew G. Knepley   if (!d->send_tags) {ierr = PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->send_tags);CHKERRQ(ierr);}
381521f74f9SMatthew G. Knepley   if (!d->recv_tags) {ierr = PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->recv_tags);CHKERRQ(ierr);}
382095059a4SDave May   /* compute message tags */
383ffc4695bSBarry Smith   ierr = MPI_Comm_size(d->comm,&size);CHKERRMPI(ierr);
384095059a4SDave May   r0 = d->rank;
385521f74f9SMatthew G. Knepley   for (n = 0; n < d->n_neighbour_procs; ++n) {
386095059a4SDave May     PetscMPIInt r1 = d->neighbour_procs[n];
387095059a4SDave May 
388d7d19db6SBarry Smith     _get_tags( d->instance, size, r0,r1, &st, &rt);
389095059a4SDave May     d->send_tags[n] = (int)st;
390095059a4SDave May     d->recv_tags[n] = (int)rt;
391095059a4SDave May   }
392095059a4SDave May   d->topology_status = DEOBJECT_FINALIZED;
393ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerTopologySetup,0,0,0,0);CHKERRQ(ierr);
394095059a4SDave May   PetscFunctionReturn(0);
395095059a4SDave May }
396095059a4SDave May 
397095059a4SDave May /* === Phase B === */
39877048351SPatrick Sanan PetscErrorCode _DMSwarmDataExConvertProcIdToLocalIndex(DMSwarmDataEx de,PetscMPIInt proc_id,PetscMPIInt *local)
399095059a4SDave May {
400095059a4SDave May   PetscMPIInt i,np;
401095059a4SDave May 
402095059a4SDave May   PetscFunctionBegin;
403095059a4SDave May   np = de->n_neighbour_procs;
404095059a4SDave May   *local = -1;
405521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
406095059a4SDave May     if (proc_id == de->neighbour_procs[i]) {
407095059a4SDave May       *local = i;
408095059a4SDave May       break;
409095059a4SDave May     }
410095059a4SDave May   }
411095059a4SDave May   PetscFunctionReturn(0);
412095059a4SDave May }
413095059a4SDave May 
41477048351SPatrick Sanan PetscErrorCode DMSwarmDataExInitializeSendCount(DMSwarmDataEx de)
415095059a4SDave May {
416095059a4SDave May   PetscMPIInt    i;
417ed923d71SDave May   PetscErrorCode ierr;
418095059a4SDave May 
419095059a4SDave May   PetscFunctionBegin;
420521f74f9SMatthew G. Knepley   if (de->topology_status != DEOBJECT_FINALIZED) SETERRQ(de->comm, PETSC_ERR_ORDER, "Topology not finalized");
421ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerSendCount,0,0,0,0);CHKERRQ(ierr);
422095059a4SDave May   de->message_lengths_status = DEOBJECT_INITIALIZED;
423521f74f9SMatthew G. Knepley   for (i = 0; i < de->n_neighbour_procs; ++i) {
424095059a4SDave May     de->messages_to_be_sent[i] = 0;
425095059a4SDave May   }
426095059a4SDave May   PetscFunctionReturn(0);
427095059a4SDave May }
428095059a4SDave May 
429095059a4SDave May /*
430095059a4SDave May 1) only allows counters to be set on neighbouring cpus
431095059a4SDave May */
43277048351SPatrick Sanan PetscErrorCode DMSwarmDataExAddToSendCount(DMSwarmDataEx de,const PetscMPIInt proc_id,const PetscInt count)
433095059a4SDave May {
434095059a4SDave May   PetscMPIInt    local_val;
435095059a4SDave May   PetscErrorCode ierr;
436095059a4SDave May 
437095059a4SDave May   PetscFunctionBegin;
43877048351SPatrick Sanan   if (de->message_lengths_status == DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths have been defined. To modify these call DMSwarmDataExInitializeSendCount() first");
43977048351SPatrick Sanan   else if (de->message_lengths_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DMSwarmDataExInitializeSendCount() first");
4402064fc68SDave May 
44177048351SPatrick Sanan   ierr = _DMSwarmDataExConvertProcIdToLocalIndex( de, proc_id, &local_val);CHKERRQ(ierr);
4422064fc68SDave May   if (local_val == -1) SETERRQ1( PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,"Proc %d is not a valid neighbour rank", (int)proc_id);
4432064fc68SDave May 
444095059a4SDave May   de->messages_to_be_sent[local_val] = de->messages_to_be_sent[local_val] + count;
445095059a4SDave May   PetscFunctionReturn(0);
446095059a4SDave May }
447095059a4SDave May 
44877048351SPatrick Sanan PetscErrorCode DMSwarmDataExFinalizeSendCount(DMSwarmDataEx de)
449095059a4SDave May {
450ed923d71SDave May   PetscErrorCode ierr;
451ed923d71SDave May 
452095059a4SDave May   PetscFunctionBegin;
45377048351SPatrick Sanan   if (de->message_lengths_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DMSwarmDataExInitializeSendCount() first");
4542064fc68SDave May 
455095059a4SDave May   de->message_lengths_status = DEOBJECT_FINALIZED;
456ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerSendCount,0,0,0,0);CHKERRQ(ierr);
457095059a4SDave May   PetscFunctionReturn(0);
458095059a4SDave May }
459095059a4SDave May 
460095059a4SDave May /* === Phase C === */
461095059a4SDave May /*
462095059a4SDave May  * zero out all send counts
463095059a4SDave May  * free send and recv buffers
464095059a4SDave May  * zeros out message length
465095059a4SDave May  * zeros out all counters
466095059a4SDave May  * zero out packed data counters
467095059a4SDave May */
46877048351SPatrick Sanan PetscErrorCode _DMSwarmDataExInitializeTmpStorage(DMSwarmDataEx de)
469095059a4SDave May {
470095059a4SDave May   PetscMPIInt    i, np;
471521f74f9SMatthew G. Knepley   PetscErrorCode ierr;
472095059a4SDave May 
473095059a4SDave May   PetscFunctionBegin;
4742064fc68SDave May   /*if (de->n_neighbour_procs < 0) SETERRQ( PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of neighbour procs < 0");
475b9a482c4SDave May   */
476b9a482c4SDave May   /*
4772064fc68SDave May   if (!de->neighbour_procs) SETERRQ( PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Neighbour proc list is NULL");
478b9a482c4SDave May   */
479095059a4SDave May   np = de->n_neighbour_procs;
480521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
481095059a4SDave May     /*  de->messages_to_be_sent[i] = -1; */
482095059a4SDave May     de->messages_to_be_recvieved[i] = -1;
483095059a4SDave May   }
484521f74f9SMatthew G. Knepley   ierr = PetscFree(de->send_message);CHKERRQ(ierr);
485521f74f9SMatthew G. Knepley   ierr = PetscFree(de->recv_message);CHKERRQ(ierr);
486095059a4SDave May   PetscFunctionReturn(0);
487095059a4SDave May }
488095059a4SDave May 
489095059a4SDave May /*
490095059a4SDave May  *) Zeros out pack data counters
491095059a4SDave May  *) Ensures mesaage length is set
492095059a4SDave May  *) Checks send counts properly initialized
493095059a4SDave May  *) allocates space for pack data
494095059a4SDave May */
49577048351SPatrick Sanan PetscErrorCode DMSwarmDataExPackInitialize(DMSwarmDataEx de,size_t unit_message_size)
496095059a4SDave May {
497095059a4SDave May   PetscMPIInt    i,np;
498095059a4SDave May   PetscInt       total;
499095059a4SDave May   PetscErrorCode ierr;
500095059a4SDave May 
501095059a4SDave May   PetscFunctionBegin;
502521f74f9SMatthew G. Knepley   if (de->topology_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Topology not finalized");
503521f74f9SMatthew G. Knepley   if (de->message_lengths_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths not finalized");
504ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerPack,0,0,0,0);CHKERRQ(ierr);
505095059a4SDave May   de->packer_status = DEOBJECT_INITIALIZED;
50677048351SPatrick Sanan   ierr = _DMSwarmDataExInitializeTmpStorage(de);CHKERRQ(ierr);
507095059a4SDave May   np = de->n_neighbour_procs;
508095059a4SDave May   de->unit_message_size = unit_message_size;
509095059a4SDave May   total = 0;
510521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
511095059a4SDave May     if (de->messages_to_be_sent[i] == -1) {
512095059a4SDave May       PetscMPIInt proc_neighour = de->neighbour_procs[i];
51377048351SPatrick Sanan       SETERRQ1( PETSC_COMM_SELF, PETSC_ERR_ORDER, "Messages_to_be_sent[neighbour_proc=%d] is un-initialised. Call DMSwarmDataExSetSendCount() first", (int)proc_neighour);
514095059a4SDave May     }
515095059a4SDave May     total = total + de->messages_to_be_sent[i];
516095059a4SDave May   }
517095059a4SDave May   /* create space for the data to be sent */
518521f74f9SMatthew G. Knepley   ierr = PetscMalloc(unit_message_size * (total + 1), &de->send_message);CHKERRQ(ierr);
519095059a4SDave May   /* initialize memory */
520521f74f9SMatthew G. Knepley   ierr = PetscMemzero(de->send_message, unit_message_size * (total + 1));CHKERRQ(ierr);
521095059a4SDave May   /* set total items to send */
522095059a4SDave May   de->send_message_length = total;
523095059a4SDave May   de->message_offsets[0] = 0;
524095059a4SDave May   total = de->messages_to_be_sent[0];
525521f74f9SMatthew G. Knepley   for (i = 1; i < np; ++i) {
526095059a4SDave May     de->message_offsets[i] = total;
527095059a4SDave May     total = total + de->messages_to_be_sent[i];
528095059a4SDave May   }
529095059a4SDave May   /* init the packer counters */
530095059a4SDave May   de->total_pack_cnt = 0;
531521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
532095059a4SDave May     de->pack_cnt[i] = 0;
533095059a4SDave May   }
534095059a4SDave May   PetscFunctionReturn(0);
535095059a4SDave May }
536095059a4SDave May 
537095059a4SDave May /*
538095059a4SDave May *) Ensures data gets been packed appropriately and no overlaps occur
539095059a4SDave May */
54077048351SPatrick Sanan PetscErrorCode DMSwarmDataExPackData(DMSwarmDataEx de,PetscMPIInt proc_id,PetscInt n,void *data)
541095059a4SDave May {
542095059a4SDave May   PetscMPIInt    local;
543095059a4SDave May   PetscInt       insert_location;
544095059a4SDave May   void           *dest;
545095059a4SDave May   PetscErrorCode ierr;
546095059a4SDave May 
547095059a4SDave May   PetscFunctionBegin;
54877048351SPatrick Sanan   if (de->packer_status == DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Packed data have been defined. To modify these call DMSwarmDataExInitializeSendCount(), DMSwarmDataExAddToSendCount(), DMSwarmDataExPackInitialize() first");
54977048351SPatrick Sanan   else if (de->packer_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Packed data must be defined. Call DMSwarmDataExInitializeSendCount(), DMSwarmDataExAddToSendCount(), DMSwarmDataExPackInitialize() first");
5502064fc68SDave May 
55177048351SPatrick Sanan   if (!de->send_message) SETERRQ( de->comm, PETSC_ERR_ORDER, "send_message is not initialized. Call DMSwarmDataExPackInitialize() first");
55277048351SPatrick Sanan   ierr = _DMSwarmDataExConvertProcIdToLocalIndex( de, proc_id, &local);CHKERRQ(ierr);
553521f74f9SMatthew G. Knepley   if (local == -1) SETERRQ1( PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "proc_id %d is not registered neighbour", (int)proc_id);
5542064fc68SDave 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",
555095059a4SDave May               (int)proc_id, de->messages_to_be_sent[local], n+de->pack_cnt[local]);
5562064fc68SDave May 
557095059a4SDave May   /* copy memory */
558095059a4SDave May   insert_location = de->message_offsets[local] + de->pack_cnt[local];
559095059a4SDave May   dest = ((char*)de->send_message) + de->unit_message_size*insert_location;
560521f74f9SMatthew G. Knepley   ierr = PetscMemcpy(dest, data, de->unit_message_size * n);CHKERRQ(ierr);
561095059a4SDave May   /* increment counter */
562095059a4SDave May   de->pack_cnt[local] = de->pack_cnt[local] + n;
563095059a4SDave May   PetscFunctionReturn(0);
564095059a4SDave May }
565095059a4SDave May 
566095059a4SDave May /*
567095059a4SDave May *) Ensures all data has been packed
568095059a4SDave May */
56977048351SPatrick Sanan PetscErrorCode DMSwarmDataExPackFinalize(DMSwarmDataEx de)
570095059a4SDave May {
571095059a4SDave May   PetscMPIInt i,np;
572095059a4SDave May   PetscInt    total;
573095059a4SDave May   PetscErrorCode ierr;
574095059a4SDave May 
575095059a4SDave May   PetscFunctionBegin;
57677048351SPatrick Sanan   if (de->packer_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Packer has not been initialized. Must call DMSwarmDataExPackInitialize() first.");
577095059a4SDave May   np = de->n_neighbour_procs;
578521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
5792064fc68SDave 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",
580095059a4SDave May                 (int)de->neighbour_procs[i], de->messages_to_be_sent[i], de->pack_cnt[i]);
581095059a4SDave May   }
582095059a4SDave May   /* init */
583521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
584095059a4SDave May     de->messages_to_be_recvieved[i] = -1;
585095059a4SDave May   }
586095059a4SDave May   /* figure out the recv counts here */
587521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
588ffc4695bSBarry Smith     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]);CHKERRMPI(ierr);
589095059a4SDave May   }
590521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
591ffc4695bSBarry Smith     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]);CHKERRMPI(ierr);
592095059a4SDave May   }
593ffc4695bSBarry Smith   ierr = MPI_Waitall(2*np, de->_requests, de->_stats);CHKERRMPI(ierr);
594095059a4SDave May   /* create space for the data to be recvieved */
595095059a4SDave May   total = 0;
596521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
597095059a4SDave May     total = total + de->messages_to_be_recvieved[i];
598095059a4SDave May   }
599521f74f9SMatthew G. Knepley   ierr = PetscMalloc(de->unit_message_size * (total + 1), &de->recv_message);CHKERRQ(ierr);
600095059a4SDave May   /* initialize memory */
601521f74f9SMatthew G. Knepley   ierr = PetscMemzero(de->recv_message, de->unit_message_size * (total + 1));CHKERRQ(ierr);
6022d4ee042Sprj-   /* set total items to receive */
603095059a4SDave May   de->recv_message_length = total;
604095059a4SDave May   de->packer_status = DEOBJECT_FINALIZED;
605095059a4SDave May   de->communication_status = DEOBJECT_INITIALIZED;
606ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerPack,0,0,0,0);CHKERRQ(ierr);
607095059a4SDave May   PetscFunctionReturn(0);
608095059a4SDave May }
609095059a4SDave May 
610095059a4SDave May /* do the actual message passing now */
61177048351SPatrick Sanan PetscErrorCode DMSwarmDataExBegin(DMSwarmDataEx de)
612095059a4SDave May {
613095059a4SDave May   PetscMPIInt i,np;
614095059a4SDave May   void       *dest;
615095059a4SDave May   PetscInt    length;
616095059a4SDave May   PetscErrorCode ierr;
617095059a4SDave May 
618095059a4SDave May   PetscFunctionBegin;
619521f74f9SMatthew G. Knepley   if (de->topology_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Topology not finalized");
620521f74f9SMatthew G. Knepley   if (de->message_lengths_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths not finalized");
621521f74f9SMatthew G. Knepley   if (de->packer_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Packer not finalized");
62277048351SPatrick Sanan   if (de->communication_status == DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Communication has already been finalized. Must call DMSwarmDataExInitialize() first.");
62377048351SPatrick Sanan   if (!de->recv_message) SETERRQ( de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DMSwarmDataExPackFinalize() first");
624ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerBegin,0,0,0,0);CHKERRQ(ierr);
625095059a4SDave May   np = de->n_neighbour_procs;
626095059a4SDave May   /* == NON BLOCKING == */
627521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
628095059a4SDave May     length = de->messages_to_be_sent[i] * de->unit_message_size;
629095059a4SDave May     dest = ((char*)de->send_message) + de->unit_message_size * de->message_offsets[i];
630ffc4695bSBarry Smith     ierr = MPI_Isend( dest, length, MPI_CHAR, de->neighbour_procs[i], de->send_tags[i], de->comm, &de->_requests[i]);CHKERRMPI(ierr);
631095059a4SDave May   }
632ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerBegin,0,0,0,0);CHKERRQ(ierr);
633095059a4SDave May   PetscFunctionReturn(0);
634095059a4SDave May }
635095059a4SDave May 
636095059a4SDave May /* do the actual message passing now */
63777048351SPatrick Sanan PetscErrorCode DMSwarmDataExEnd(DMSwarmDataEx de)
638095059a4SDave May {
639095059a4SDave May   PetscMPIInt  i,np;
640095059a4SDave May   PetscInt     total;
641095059a4SDave May   PetscInt    *message_recv_offsets;
642095059a4SDave May   void        *dest;
643095059a4SDave May   PetscInt     length;
644095059a4SDave May   PetscErrorCode ierr;
645095059a4SDave May 
646095059a4SDave May   PetscFunctionBegin;
64777048351SPatrick Sanan   if (de->communication_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Communication has not been initialized. Must call DMSwarmDataExInitialize() first.");
64877048351SPatrick Sanan   if (!de->recv_message) SETERRQ( de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DMSwarmDataExPackFinalize() first");
649ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerEnd,0,0,0,0);CHKERRQ(ierr);
650095059a4SDave May   np = de->n_neighbour_procs;
651b9a482c4SDave May   ierr = PetscMalloc1(np+1, &message_recv_offsets);CHKERRQ(ierr);
652095059a4SDave May   message_recv_offsets[0] = 0;
653095059a4SDave May   total = de->messages_to_be_recvieved[0];
654521f74f9SMatthew G. Knepley   for (i = 1; i < np; ++i) {
655095059a4SDave May     message_recv_offsets[i] = total;
656095059a4SDave May     total = total + de->messages_to_be_recvieved[i];
657095059a4SDave May   }
658095059a4SDave May   /* == NON BLOCKING == */
659521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
660095059a4SDave May     length = de->messages_to_be_recvieved[i] * de->unit_message_size;
661095059a4SDave May     dest = ((char*)de->recv_message) + de->unit_message_size * message_recv_offsets[i];
662ffc4695bSBarry Smith     ierr = MPI_Irecv( dest, length, MPI_CHAR, de->neighbour_procs[i], de->recv_tags[i], de->comm, &de->_requests[np+i]);CHKERRMPI(ierr);
663095059a4SDave May   }
664ffc4695bSBarry Smith   ierr = MPI_Waitall( 2*np, de->_requests, de->_stats);CHKERRMPI(ierr);
665459726d8SSatish Balay   ierr = PetscFree(message_recv_offsets);CHKERRQ(ierr);
666095059a4SDave May   de->communication_status = DEOBJECT_FINALIZED;
667ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerEnd,0,0,0,0);CHKERRQ(ierr);
668095059a4SDave May   PetscFunctionReturn(0);
669095059a4SDave May }
670095059a4SDave May 
67177048351SPatrick Sanan PetscErrorCode DMSwarmDataExGetSendData(DMSwarmDataEx de,PetscInt *length,void **send)
672095059a4SDave May {
673095059a4SDave May   PetscFunctionBegin;
674521f74f9SMatthew G. Knepley   if (de->packer_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being packed.");
675095059a4SDave May   *length = de->send_message_length;
676095059a4SDave May   *send   = de->send_message;
677095059a4SDave May   PetscFunctionReturn(0);
678095059a4SDave May }
679095059a4SDave May 
68077048351SPatrick Sanan PetscErrorCode DMSwarmDataExGetRecvData(DMSwarmDataEx de,PetscInt *length,void **recv)
681095059a4SDave May {
682095059a4SDave May   PetscFunctionBegin;
683521f74f9SMatthew G. Knepley   if (de->communication_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being sent.");
684095059a4SDave May   *length = de->recv_message_length;
685095059a4SDave May   *recv   = de->recv_message;
686095059a4SDave May   PetscFunctionReturn(0);
687095059a4SDave May }
688095059a4SDave May 
68977048351SPatrick Sanan PetscErrorCode DMSwarmDataExTopologyGetNeighbours(DMSwarmDataEx de,PetscMPIInt *n,PetscMPIInt *neigh[])
690095059a4SDave May {
691095059a4SDave May   PetscFunctionBegin;
692095059a4SDave May   if (n)     {*n     = de->n_neighbour_procs;}
693095059a4SDave May   if (neigh) {*neigh = de->neighbour_procs;}
694095059a4SDave May   PetscFunctionReturn(0);
695095059a4SDave May }
696