xref: /petsc/src/dm/impls/swarm/data_ex.c (revision 2c71b3e237ead271e4f3aa1505f92bf476e3413d)
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;
905627991aSBarry Smith   ierr = PetscNew(&d);CHKERRQ(ierr);
91ffc4695bSBarry Smith   ierr = MPI_Comm_dup(comm,&d->comm);CHKERRMPI(ierr);
92ffc4695bSBarry Smith   ierr = MPI_Comm_rank(d->comm,&d->rank);CHKERRMPI(ierr);
93095059a4SDave May 
94095059a4SDave May   d->instance = count;
95095059a4SDave May 
96095059a4SDave May   d->topology_status        = DEOBJECT_STATE_UNKNOWN;
97095059a4SDave May   d->message_lengths_status = DEOBJECT_STATE_UNKNOWN;
98095059a4SDave May   d->packer_status          = DEOBJECT_STATE_UNKNOWN;
99095059a4SDave May   d->communication_status   = DEOBJECT_STATE_UNKNOWN;
100095059a4SDave May 
101095059a4SDave May   d->n_neighbour_procs = -1;
102095059a4SDave May   d->neighbour_procs   = NULL;
103095059a4SDave May 
104095059a4SDave May   d->messages_to_be_sent      = NULL;
105095059a4SDave May   d->message_offsets          = NULL;
106095059a4SDave May   d->messages_to_be_recvieved = NULL;
107095059a4SDave May 
10878c64234SJose E. Roman   d->unit_message_size   = (size_t)-1;
109095059a4SDave May   d->send_message        = NULL;
110095059a4SDave May   d->send_message_length = -1;
111095059a4SDave May   d->recv_message        = NULL;
112095059a4SDave May   d->recv_message_length = -1;
113095059a4SDave May   d->total_pack_cnt      = -1;
114095059a4SDave May   d->pack_cnt            = NULL;
115095059a4SDave May 
116095059a4SDave May   d->send_tags = NULL;
117095059a4SDave May   d->recv_tags = NULL;
118095059a4SDave May 
119095059a4SDave May   d->_stats    = NULL;
120095059a4SDave May   d->_requests = NULL;
121521f74f9SMatthew G. Knepley   *ex = d;
122521f74f9SMatthew G. Knepley   PetscFunctionReturn(0);
123095059a4SDave May }
124095059a4SDave May 
125298827fbSBarry Smith /*
1269dddd249SSatish Balay     This code is horrible, who let it get into main.
127298827fbSBarry Smith 
128298827fbSBarry Smith     Should be printing to a viewer, should not be using PETSC_COMM_WORLD
129298827fbSBarry Smith 
130298827fbSBarry Smith */
13177048351SPatrick Sanan PetscErrorCode DMSwarmDataExView(DMSwarmDataEx d)
132095059a4SDave May {
133095059a4SDave May   PetscMPIInt    p;
134521f74f9SMatthew G. Knepley   PetscErrorCode ierr;
135095059a4SDave May 
136095059a4SDave May   PetscFunctionBegin;
13777048351SPatrick Sanan   ierr = PetscPrintf( PETSC_COMM_WORLD, "DMSwarmDataEx: instance=%D\n",d->instance);CHKERRQ(ierr);
138521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  topology status:        %s \n", status_names[d->topology_status]);CHKERRQ(ierr);
139521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  message lengths status: %s \n", status_names[d->message_lengths_status]);CHKERRQ(ierr);
140521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  packer status status:   %s \n", status_names[d->packer_status]);CHKERRQ(ierr);
141521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  communication status:   %s \n", status_names[d->communication_status]);CHKERRQ(ierr);
142095059a4SDave May 
143095059a4SDave May   if (d->topology_status == DEOBJECT_FINALIZED) {
144521f74f9SMatthew G. Knepley     ierr = PetscPrintf( PETSC_COMM_WORLD, "  Topology:\n");CHKERRQ(ierr);
145dfe27cbaSBarry Smith     ierr = PetscSynchronizedPrintf( PETSC_COMM_WORLD, "    [%d] neighbours: %d \n", d->rank, d->n_neighbour_procs);CHKERRQ(ierr);
146095059a4SDave May     for (p=0; p<d->n_neighbour_procs; p++) {
147dfe27cbaSBarry Smith       ierr = PetscSynchronizedPrintf( PETSC_COMM_WORLD, "    [%d]   neighbour[%d] = %d \n", d->rank, p, d->neighbour_procs[p]);CHKERRQ(ierr);
148095059a4SDave May     }
149298827fbSBarry Smith     ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,stdout);CHKERRQ(ierr);
150095059a4SDave May   }
151298827fbSBarry Smith 
152095059a4SDave May   if (d->message_lengths_status == DEOBJECT_FINALIZED) {
153521f74f9SMatthew G. Knepley     ierr = PetscPrintf( PETSC_COMM_WORLD, "  Message lengths:\n");CHKERRQ(ierr);
154dfe27cbaSBarry Smith     ierr = PetscSynchronizedPrintf( PETSC_COMM_WORLD, "    [%d] atomic size: %ld \n", d->rank, (long int)d->unit_message_size);CHKERRQ(ierr);
155095059a4SDave May     for (p=0; p<d->n_neighbour_procs; p++) {
156dfe27cbaSBarry 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);
157095059a4SDave May     }
158095059a4SDave May     for (p=0; p<d->n_neighbour_procs; p++) {
159dfe27cbaSBarry 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);
160095059a4SDave May     }
161298827fbSBarry Smith     ierr = PetscSynchronizedFlush(PETSC_COMM_WORLD,stdout);CHKERRQ(ierr);
162095059a4SDave May   }
163521f74f9SMatthew G. Knepley   if (d->packer_status == DEOBJECT_FINALIZED) {}
164521f74f9SMatthew G. Knepley   if (d->communication_status == DEOBJECT_FINALIZED) {}
165095059a4SDave May   PetscFunctionReturn(0);
166095059a4SDave May }
167095059a4SDave May 
16877048351SPatrick Sanan PetscErrorCode DMSwarmDataExDestroy(DMSwarmDataEx d)
169095059a4SDave May {
170095059a4SDave May   PetscErrorCode ierr;
171095059a4SDave May 
172095059a4SDave May   PetscFunctionBegin;
173ffc4695bSBarry Smith   ierr = MPI_Comm_free(&d->comm);CHKERRMPI(ierr);
174521f74f9SMatthew G. Knepley   if (d->neighbour_procs) {ierr = PetscFree(d->neighbour_procs);CHKERRQ(ierr);}
175521f74f9SMatthew G. Knepley   if (d->messages_to_be_sent) {ierr = PetscFree(d->messages_to_be_sent);CHKERRQ(ierr);}
176521f74f9SMatthew G. Knepley   if (d->message_offsets) {ierr = PetscFree(d->message_offsets);CHKERRQ(ierr);}
177521f74f9SMatthew G. Knepley   if (d->messages_to_be_recvieved) {ierr = PetscFree(d->messages_to_be_recvieved);CHKERRQ(ierr);}
178521f74f9SMatthew G. Knepley   if (d->send_message) {ierr = PetscFree(d->send_message);CHKERRQ(ierr);}
179521f74f9SMatthew G. Knepley   if (d->recv_message) {ierr = PetscFree(d->recv_message);CHKERRQ(ierr);}
180521f74f9SMatthew G. Knepley   if (d->pack_cnt) {ierr = PetscFree(d->pack_cnt);CHKERRQ(ierr);}
181521f74f9SMatthew G. Knepley   if (d->send_tags) {ierr = PetscFree(d->send_tags);CHKERRQ(ierr);}
182521f74f9SMatthew G. Knepley   if (d->recv_tags) {ierr = PetscFree(d->recv_tags);CHKERRQ(ierr);}
183521f74f9SMatthew G. Knepley   if (d->_stats) {ierr = PetscFree(d->_stats);CHKERRQ(ierr);}
184521f74f9SMatthew G. Knepley   if (d->_requests) {ierr = PetscFree(d->_requests);CHKERRQ(ierr);}
185521f74f9SMatthew G. Knepley   ierr = PetscFree(d);CHKERRQ(ierr);
186095059a4SDave May   PetscFunctionReturn(0);
187095059a4SDave May }
188095059a4SDave May 
189095059a4SDave May /* === Phase A === */
190095059a4SDave May 
19177048351SPatrick Sanan PetscErrorCode DMSwarmDataExTopologyInitialize(DMSwarmDataEx d)
192095059a4SDave May {
193521f74f9SMatthew G. Knepley   PetscErrorCode ierr;
194521f74f9SMatthew G. Knepley 
195095059a4SDave May   PetscFunctionBegin;
196095059a4SDave May   d->topology_status = DEOBJECT_INITIALIZED;
197095059a4SDave May   d->n_neighbour_procs = 0;
198781df12bSMatthew G. Knepley   ierr = PetscFree(d->neighbour_procs);CHKERRQ(ierr);
199781df12bSMatthew G. Knepley   ierr = PetscFree(d->messages_to_be_sent);CHKERRQ(ierr);
200781df12bSMatthew G. Knepley   ierr = PetscFree(d->message_offsets);CHKERRQ(ierr);
201781df12bSMatthew G. Knepley   ierr = PetscFree(d->messages_to_be_recvieved);CHKERRQ(ierr);
202781df12bSMatthew G. Knepley   ierr = PetscFree(d->pack_cnt);CHKERRQ(ierr);
203781df12bSMatthew G. Knepley   ierr = PetscFree(d->send_tags);CHKERRQ(ierr);
204781df12bSMatthew G. Knepley   ierr = PetscFree(d->recv_tags);CHKERRQ(ierr);
205095059a4SDave May   PetscFunctionReturn(0);
206095059a4SDave May }
207095059a4SDave May 
20877048351SPatrick Sanan PetscErrorCode DMSwarmDataExTopologyAddNeighbour(DMSwarmDataEx d,const PetscMPIInt proc_id)
209095059a4SDave May {
210095059a4SDave May   PetscMPIInt    n,found;
211d7d19db6SBarry Smith   PetscMPIInt    size;
212095059a4SDave May   PetscErrorCode ierr;
213095059a4SDave May 
214095059a4SDave May   PetscFunctionBegin;
215*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(d->topology_status == DEOBJECT_FINALIZED,d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology has been finalized. To modify or update call DMSwarmDataExTopologyInitialize() first");
216*2c71b3e2SJacob Faibussowitsch   else PetscCheckFalse(d->topology_status != DEOBJECT_INITIALIZED,d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be initialised. Call DMSwarmDataExTopologyInitialize() first");
2172064fc68SDave May 
218095059a4SDave May   /* error on negative entries */
219*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(proc_id < 0,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Trying to set proc neighbour with a rank < 0");
220095059a4SDave May   /* error on ranks larger than number of procs in communicator */
221ffc4695bSBarry Smith   ierr = MPI_Comm_size(d->comm,&size);CHKERRMPI(ierr);
222*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(proc_id >= size,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Trying to set proc neighbour %d with a rank >= size %d",proc_id,size);
223521f74f9SMatthew G. Knepley   if (d->n_neighbour_procs == 0) {ierr = PetscMalloc1(1, &d->neighbour_procs);CHKERRQ(ierr);}
224095059a4SDave May   /* check for proc_id */
225095059a4SDave May   found = 0;
226095059a4SDave May   for (n = 0; n < d->n_neighbour_procs; n++) {
227095059a4SDave May     if (d->neighbour_procs[n] == proc_id) {
228095059a4SDave May       found  = 1;
229095059a4SDave May     }
230095059a4SDave May   }
231095059a4SDave May   if (found == 0) { /* add it to list */
2324be7464cSMatthew G. Knepley     ierr = PetscRealloc(sizeof(PetscMPIInt)*(d->n_neighbour_procs+1), &d->neighbour_procs);CHKERRQ(ierr);
233095059a4SDave May     d->neighbour_procs[ d->n_neighbour_procs ] = proc_id;
234095059a4SDave May     d->n_neighbour_procs++;
235095059a4SDave May   }
236095059a4SDave May   PetscFunctionReturn(0);
237095059a4SDave May }
238095059a4SDave May 
239095059a4SDave May /*
240095059a4SDave May counter: the index of the communication object
241095059a4SDave May N: the number of processors
242095059a4SDave May r0: rank of sender
243095059a4SDave May r1: rank of receiver
244095059a4SDave May 
245095059a4SDave May procs = { 0, 1, 2, 3 }
246095059a4SDave May 
247095059a4SDave May 0 ==> 0         e=0
248095059a4SDave May 0 ==> 1         e=1
249095059a4SDave May 0 ==> 2         e=2
250095059a4SDave May 0 ==> 3         e=3
251095059a4SDave May 
252095059a4SDave May 1 ==> 0         e=4
253095059a4SDave May 1 ==> 1         e=5
254095059a4SDave May 1 ==> 2         e=6
255095059a4SDave May 1 ==> 3         e=7
256095059a4SDave May 
257095059a4SDave May 2 ==> 0         e=8
258095059a4SDave May 2 ==> 1         e=9
259095059a4SDave May 2 ==> 2         e=10
260095059a4SDave May 2 ==> 3         e=11
261095059a4SDave May 
262095059a4SDave May 3 ==> 0         e=12
263095059a4SDave May 3 ==> 1         e=13
264095059a4SDave May 3 ==> 2         e=14
265095059a4SDave May 3 ==> 3         e=15
266095059a4SDave May 
267095059a4SDave May If we require that proc A sends to proc B, then the SEND tag index will be given by
268095059a4SDave May   N * rank(A) + rank(B) + offset
269095059a4SDave May If we require that proc A will receive from proc B, then the RECV tag index will be given by
270095059a4SDave May   N * rank(B) + rank(A) + offset
271095059a4SDave May 
272095059a4SDave May */
273521f74f9SMatthew G. Knepley static void _get_tags(PetscInt counter, PetscMPIInt N, PetscMPIInt r0,PetscMPIInt r1, PetscMPIInt *_st, PetscMPIInt *_rt)
274095059a4SDave May {
275095059a4SDave May   PetscMPIInt st,rt;
276095059a4SDave May 
277095059a4SDave May   st = N*r0 + r1   +   N*N*counter;
278095059a4SDave May   rt = N*r1 + r0   +   N*N*counter;
279095059a4SDave May   *_st = st;
280095059a4SDave May   *_rt = rt;
281095059a4SDave May }
282095059a4SDave May 
283095059a4SDave May /*
284095059a4SDave May Makes the communication map symmetric
285095059a4SDave May */
28677048351SPatrick Sanan PetscErrorCode _DMSwarmDataExCompleteCommunicationMap(MPI_Comm comm,PetscMPIInt n,PetscMPIInt proc_neighbours[],PetscMPIInt *n_new,PetscMPIInt **proc_neighbours_new)
287095059a4SDave May {
288dcf43ee8SDave May   Mat               A;
289095059a4SDave May   PetscInt          i,j,nc;
290095059a4SDave May   PetscInt          n_, *proc_neighbours_;
291e4fbd051SBarry Smith   PetscInt          rank_;
292e4fbd051SBarry Smith   PetscMPIInt       size,  rank;
293095059a4SDave May   PetscScalar       *vals;
294095059a4SDave May   const PetscInt    *cols;
295095059a4SDave May   const PetscScalar *red_vals;
296095059a4SDave May   PetscMPIInt       _n_new, *_proc_neighbours_new;
297095059a4SDave May   PetscErrorCode    ierr;
298095059a4SDave May 
299095059a4SDave May   PetscFunctionBegin;
300095059a4SDave May   n_ = n;
301095059a4SDave May   ierr = PetscMalloc(sizeof(PetscInt) * n_, &proc_neighbours_);CHKERRQ(ierr);
302521f74f9SMatthew G. Knepley   for (i = 0; i < n_; ++i) {
303095059a4SDave May     proc_neighbours_[i] = proc_neighbours[i];
304095059a4SDave May   }
305ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
306ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm,&rank);CHKERRMPI(ierr);
307e4fbd051SBarry Smith   rank_ = rank;
308095059a4SDave May 
309095059a4SDave May   ierr = MatCreate(comm,&A);CHKERRQ(ierr);
310095059a4SDave May   ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,size,size);CHKERRQ(ierr);
311095059a4SDave May   ierr = MatSetType(A,MATAIJ);CHKERRQ(ierr);
312dcf43ee8SDave May   ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
313dcf43ee8SDave May   ierr = MatMPIAIJSetPreallocation(A,n_,NULL,n_,NULL);CHKERRQ(ierr);
314dcf43ee8SDave May   ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);CHKERRQ(ierr);
315095059a4SDave May   /* Build original map */
316521f74f9SMatthew G. Knepley   ierr = PetscMalloc1(n_, &vals);CHKERRQ(ierr);
317521f74f9SMatthew G. Knepley   for (i = 0; i < n_; ++i) {
318095059a4SDave May     vals[i] = 1.0;
319095059a4SDave May   }
320e4fbd051SBarry Smith   ierr = MatSetValues( A, 1,&rank_, n_,proc_neighbours_, vals, INSERT_VALUES);CHKERRQ(ierr);
321095059a4SDave May   ierr = MatAssemblyBegin(A,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
322095059a4SDave May   ierr = MatAssemblyEnd(A,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
323095059a4SDave May   /* Now force all other connections if they are not already there */
324095059a4SDave May   /* It's more efficient to do them all at once */
325521f74f9SMatthew G. Knepley   for (i = 0; i < n_; ++i) {
326095059a4SDave May     vals[i] = 2.0;
327095059a4SDave May   }
328e4fbd051SBarry Smith   ierr = MatSetValues( A, n_,proc_neighbours_, 1,&rank_, vals, INSERT_VALUES);CHKERRQ(ierr);
329095059a4SDave May   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
330095059a4SDave May   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3316275818cSDave May /*
332095059a4SDave May   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr);
333095059a4SDave May   ierr = MatView(A,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
334095059a4SDave May   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
3356275818cSDave May */
336095059a4SDave May   if ((n_new != NULL) && (proc_neighbours_new != NULL)) {
337e4fbd051SBarry Smith     ierr = MatGetRow(A, rank_, &nc, &cols, &red_vals);CHKERRQ(ierr);
338095059a4SDave May     _n_new = (PetscMPIInt) nc;
339521f74f9SMatthew G. Knepley     ierr = PetscMalloc1(_n_new, &_proc_neighbours_new);CHKERRQ(ierr);
340521f74f9SMatthew G. Knepley     for (j = 0; j < nc; ++j) {
341095059a4SDave May       _proc_neighbours_new[j] = (PetscMPIInt)cols[j];
342095059a4SDave May     }
343e4fbd051SBarry Smith     ierr = MatRestoreRow( A, rank_, &nc, &cols, &red_vals);CHKERRQ(ierr);
344095059a4SDave May     *n_new               = (PetscMPIInt)_n_new;
345095059a4SDave May     *proc_neighbours_new = (PetscMPIInt*)_proc_neighbours_new;
346095059a4SDave May   }
347095059a4SDave May   ierr = MatDestroy(&A);CHKERRQ(ierr);
348095059a4SDave May   ierr = PetscFree(vals);CHKERRQ(ierr);
349095059a4SDave May   ierr = PetscFree(proc_neighbours_);CHKERRQ(ierr);
350ffc4695bSBarry Smith   ierr = MPI_Barrier(comm);CHKERRMPI(ierr);
351095059a4SDave May   PetscFunctionReturn(0);
352095059a4SDave May }
353095059a4SDave May 
35477048351SPatrick Sanan PetscErrorCode DMSwarmDataExTopologyFinalize(DMSwarmDataEx d)
355095059a4SDave May {
3565627991aSBarry Smith   PetscMPIInt    symm_nn, *symm_procs, r0,n,st,rt, size;
357095059a4SDave May   PetscErrorCode ierr;
358095059a4SDave May 
359095059a4SDave May   PetscFunctionBegin;
360*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(d->topology_status != DEOBJECT_INITIALIZED,d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be initialised. Call DMSwarmDataExTopologyInitialize() first");
3612064fc68SDave May 
362ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerTopologySetup,0,0,0,0);CHKERRQ(ierr);
363a5b23f4aSJose E. Roman   /* given information about all my neighbours, make map symmetric */
36477048351SPatrick Sanan   ierr = _DMSwarmDataExCompleteCommunicationMap( d->comm,d->n_neighbour_procs,d->neighbour_procs, &symm_nn, &symm_procs);CHKERRQ(ierr);
365095059a4SDave May   /* update my arrays */
366459726d8SSatish Balay   ierr = PetscFree(d->neighbour_procs);CHKERRQ(ierr);
367095059a4SDave May   d->n_neighbour_procs = symm_nn;
368095059a4SDave May   d->neighbour_procs   = symm_procs;
369095059a4SDave May   /* allocates memory */
370b9a482c4SDave May   if (!d->messages_to_be_sent) {ierr = PetscMalloc1(d->n_neighbour_procs+1, &d->messages_to_be_sent);CHKERRQ(ierr);}
371b9a482c4SDave May   if (!d->message_offsets) {ierr = PetscMalloc1(d->n_neighbour_procs+1, &d->message_offsets);CHKERRQ(ierr);}
372b9a482c4SDave May   if (!d->messages_to_be_recvieved) {ierr = PetscMalloc1(d->n_neighbour_procs+1, &d->messages_to_be_recvieved);CHKERRQ(ierr);}
373521f74f9SMatthew G. Knepley   if (!d->pack_cnt) {ierr = PetscMalloc(sizeof(PetscInt) * d->n_neighbour_procs, &d->pack_cnt);CHKERRQ(ierr);}
374521f74f9SMatthew G. Knepley   if (!d->_stats) {ierr = PetscMalloc(sizeof(MPI_Status) * 2*d->n_neighbour_procs, &d->_stats);CHKERRQ(ierr);}
375521f74f9SMatthew G. Knepley   if (!d->_requests) {ierr = PetscMalloc(sizeof(MPI_Request) * 2*d->n_neighbour_procs, &d->_requests);CHKERRQ(ierr);}
376521f74f9SMatthew G. Knepley   if (!d->send_tags) {ierr = PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->send_tags);CHKERRQ(ierr);}
377521f74f9SMatthew G. Knepley   if (!d->recv_tags) {ierr = PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->recv_tags);CHKERRQ(ierr);}
378095059a4SDave May   /* compute message tags */
379ffc4695bSBarry Smith   ierr = MPI_Comm_size(d->comm,&size);CHKERRMPI(ierr);
380095059a4SDave May   r0 = d->rank;
381521f74f9SMatthew G. Knepley   for (n = 0; n < d->n_neighbour_procs; ++n) {
382095059a4SDave May     PetscMPIInt r1 = d->neighbour_procs[n];
383095059a4SDave May 
384d7d19db6SBarry Smith     _get_tags( d->instance, size, r0,r1, &st, &rt);
385095059a4SDave May     d->send_tags[n] = (int)st;
386095059a4SDave May     d->recv_tags[n] = (int)rt;
387095059a4SDave May   }
388095059a4SDave May   d->topology_status = DEOBJECT_FINALIZED;
389ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerTopologySetup,0,0,0,0);CHKERRQ(ierr);
390095059a4SDave May   PetscFunctionReturn(0);
391095059a4SDave May }
392095059a4SDave May 
393095059a4SDave May /* === Phase B === */
39477048351SPatrick Sanan PetscErrorCode _DMSwarmDataExConvertProcIdToLocalIndex(DMSwarmDataEx de,PetscMPIInt proc_id,PetscMPIInt *local)
395095059a4SDave May {
396095059a4SDave May   PetscMPIInt i,np;
397095059a4SDave May 
398095059a4SDave May   PetscFunctionBegin;
399095059a4SDave May   np = de->n_neighbour_procs;
400095059a4SDave May   *local = -1;
401521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
402095059a4SDave May     if (proc_id == de->neighbour_procs[i]) {
403095059a4SDave May       *local = i;
404095059a4SDave May       break;
405095059a4SDave May     }
406095059a4SDave May   }
407095059a4SDave May   PetscFunctionReturn(0);
408095059a4SDave May }
409095059a4SDave May 
41077048351SPatrick Sanan PetscErrorCode DMSwarmDataExInitializeSendCount(DMSwarmDataEx de)
411095059a4SDave May {
412095059a4SDave May   PetscMPIInt    i;
413ed923d71SDave May   PetscErrorCode ierr;
414095059a4SDave May 
415095059a4SDave May   PetscFunctionBegin;
416*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->topology_status != DEOBJECT_FINALIZED,de->comm, PETSC_ERR_ORDER, "Topology not finalized");
417ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerSendCount,0,0,0,0);CHKERRQ(ierr);
418095059a4SDave May   de->message_lengths_status = DEOBJECT_INITIALIZED;
419521f74f9SMatthew G. Knepley   for (i = 0; i < de->n_neighbour_procs; ++i) {
420095059a4SDave May     de->messages_to_be_sent[i] = 0;
421095059a4SDave May   }
422095059a4SDave May   PetscFunctionReturn(0);
423095059a4SDave May }
424095059a4SDave May 
425095059a4SDave May /*
426095059a4SDave May 1) only allows counters to be set on neighbouring cpus
427095059a4SDave May */
42877048351SPatrick Sanan PetscErrorCode DMSwarmDataExAddToSendCount(DMSwarmDataEx de,const PetscMPIInt proc_id,const PetscInt count)
429095059a4SDave May {
430095059a4SDave May   PetscMPIInt    local_val;
431095059a4SDave May   PetscErrorCode ierr;
432095059a4SDave May 
433095059a4SDave May   PetscFunctionBegin;
434*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->message_lengths_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths have been defined. To modify these call DMSwarmDataExInitializeSendCount() first");
435*2c71b3e2SJacob Faibussowitsch   else PetscCheckFalse(de->message_lengths_status != DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DMSwarmDataExInitializeSendCount() first");
4362064fc68SDave May 
43777048351SPatrick Sanan   ierr = _DMSwarmDataExConvertProcIdToLocalIndex( de, proc_id, &local_val);CHKERRQ(ierr);
438*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(local_val == -1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,"Proc %d is not a valid neighbour rank", (int)proc_id);
4392064fc68SDave May 
440095059a4SDave May   de->messages_to_be_sent[local_val] = de->messages_to_be_sent[local_val] + count;
441095059a4SDave May   PetscFunctionReturn(0);
442095059a4SDave May }
443095059a4SDave May 
44477048351SPatrick Sanan PetscErrorCode DMSwarmDataExFinalizeSendCount(DMSwarmDataEx de)
445095059a4SDave May {
446ed923d71SDave May   PetscErrorCode ierr;
447ed923d71SDave May 
448095059a4SDave May   PetscFunctionBegin;
449*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->message_lengths_status != DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DMSwarmDataExInitializeSendCount() first");
4502064fc68SDave May 
451095059a4SDave May   de->message_lengths_status = DEOBJECT_FINALIZED;
452ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerSendCount,0,0,0,0);CHKERRQ(ierr);
453095059a4SDave May   PetscFunctionReturn(0);
454095059a4SDave May }
455095059a4SDave May 
456095059a4SDave May /* === Phase C === */
457095059a4SDave May /*
4585627991aSBarry Smith   zero out all send counts
4595627991aSBarry Smith   free send and recv buffers
4605627991aSBarry Smith   zeros out message length
4615627991aSBarry Smith   zeros out all counters
4625627991aSBarry Smith   zero out packed data counters
463095059a4SDave May */
46477048351SPatrick Sanan PetscErrorCode _DMSwarmDataExInitializeTmpStorage(DMSwarmDataEx de)
465095059a4SDave May {
466095059a4SDave May   PetscMPIInt    i, np;
467521f74f9SMatthew G. Knepley   PetscErrorCode ierr;
468095059a4SDave May 
469095059a4SDave May   PetscFunctionBegin;
470095059a4SDave May   np = de->n_neighbour_procs;
471521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
472095059a4SDave May     /*  de->messages_to_be_sent[i] = -1; */
473095059a4SDave May     de->messages_to_be_recvieved[i] = -1;
474095059a4SDave May   }
475521f74f9SMatthew G. Knepley   ierr = PetscFree(de->send_message);CHKERRQ(ierr);
476521f74f9SMatthew G. Knepley   ierr = PetscFree(de->recv_message);CHKERRQ(ierr);
477095059a4SDave May   PetscFunctionReturn(0);
478095059a4SDave May }
479095059a4SDave May 
480095059a4SDave May /*
4815627991aSBarry Smith    Zeros out pack data counters
4825627991aSBarry Smith    Ensures mesaage length is set
4835627991aSBarry Smith    Checks send counts properly initialized
4845627991aSBarry Smith    allocates space for pack data
485095059a4SDave May */
48677048351SPatrick Sanan PetscErrorCode DMSwarmDataExPackInitialize(DMSwarmDataEx de,size_t unit_message_size)
487095059a4SDave May {
488095059a4SDave May   PetscMPIInt    i,np;
489095059a4SDave May   PetscInt       total;
490095059a4SDave May   PetscErrorCode ierr;
491095059a4SDave May 
492095059a4SDave May   PetscFunctionBegin;
493*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->topology_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Topology not finalized");
494*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->message_lengths_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths not finalized");
495ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerPack,0,0,0,0);CHKERRQ(ierr);
496095059a4SDave May   de->packer_status = DEOBJECT_INITIALIZED;
49777048351SPatrick Sanan   ierr = _DMSwarmDataExInitializeTmpStorage(de);CHKERRQ(ierr);
498095059a4SDave May   np = de->n_neighbour_procs;
499095059a4SDave May   de->unit_message_size = unit_message_size;
500095059a4SDave May   total = 0;
501521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
502095059a4SDave May     if (de->messages_to_be_sent[i] == -1) {
503095059a4SDave May       PetscMPIInt proc_neighour = de->neighbour_procs[i];
50498921bdaSJacob Faibussowitsch       SETERRQ( PETSC_COMM_SELF, PETSC_ERR_ORDER, "Messages_to_be_sent[neighbour_proc=%d] is un-initialised. Call DMSwarmDataExSetSendCount() first", (int)proc_neighour);
505095059a4SDave May     }
506095059a4SDave May     total = total + de->messages_to_be_sent[i];
507095059a4SDave May   }
508095059a4SDave May   /* create space for the data to be sent */
509521f74f9SMatthew G. Knepley   ierr = PetscMalloc(unit_message_size * (total + 1), &de->send_message);CHKERRQ(ierr);
510095059a4SDave May   /* initialize memory */
511521f74f9SMatthew G. Knepley   ierr = PetscMemzero(de->send_message, unit_message_size * (total + 1));CHKERRQ(ierr);
512095059a4SDave May   /* set total items to send */
513095059a4SDave May   de->send_message_length = total;
514095059a4SDave May   de->message_offsets[0] = 0;
515095059a4SDave May   total = de->messages_to_be_sent[0];
516521f74f9SMatthew G. Knepley   for (i = 1; i < np; ++i) {
517095059a4SDave May     de->message_offsets[i] = total;
518095059a4SDave May     total = total + de->messages_to_be_sent[i];
519095059a4SDave May   }
520095059a4SDave May   /* init the packer counters */
521095059a4SDave May   de->total_pack_cnt = 0;
522521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
523095059a4SDave May     de->pack_cnt[i] = 0;
524095059a4SDave May   }
525095059a4SDave May   PetscFunctionReturn(0);
526095059a4SDave May }
527095059a4SDave May 
528095059a4SDave May /*
5295627991aSBarry Smith     Ensures data gets been packed appropriately and no overlaps occur
530095059a4SDave May */
53177048351SPatrick Sanan PetscErrorCode DMSwarmDataExPackData(DMSwarmDataEx de,PetscMPIInt proc_id,PetscInt n,void *data)
532095059a4SDave May {
533095059a4SDave May   PetscMPIInt    local;
534095059a4SDave May   PetscInt       insert_location;
535095059a4SDave May   void           *dest;
536095059a4SDave May   PetscErrorCode ierr;
537095059a4SDave May 
538095059a4SDave May   PetscFunctionBegin;
539*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->packer_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Packed data have been defined. To modify these call DMSwarmDataExInitializeSendCount(), DMSwarmDataExAddToSendCount(), DMSwarmDataExPackInitialize() first");
540*2c71b3e2SJacob Faibussowitsch   else PetscCheckFalse(de->packer_status != DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Packed data must be defined. Call DMSwarmDataExInitializeSendCount(), DMSwarmDataExAddToSendCount(), DMSwarmDataExPackInitialize() first");
5412064fc68SDave May 
542*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!de->send_message, de->comm, PETSC_ERR_ORDER, "send_message is not initialized. Call DMSwarmDataExPackInitialize() first");
54377048351SPatrick Sanan   ierr = _DMSwarmDataExConvertProcIdToLocalIndex( de, proc_id, &local);CHKERRQ(ierr);
544*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(local == -1, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "proc_id %d is not registered neighbour", (int)proc_id);
545*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(n+de->pack_cnt[local] > de->messages_to_be_sent[local], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Trying to pack too many entries to be sent to proc %d. Space requested = %D: Attempt to insert %D",
546095059a4SDave May               (int)proc_id, de->messages_to_be_sent[local], n+de->pack_cnt[local]);
5472064fc68SDave May 
548095059a4SDave May   /* copy memory */
549095059a4SDave May   insert_location = de->message_offsets[local] + de->pack_cnt[local];
550095059a4SDave May   dest = ((char*)de->send_message) + de->unit_message_size*insert_location;
551521f74f9SMatthew G. Knepley   ierr = PetscMemcpy(dest, data, de->unit_message_size * n);CHKERRQ(ierr);
552095059a4SDave May   /* increment counter */
553095059a4SDave May   de->pack_cnt[local] = de->pack_cnt[local] + n;
554095059a4SDave May   PetscFunctionReturn(0);
555095059a4SDave May }
556095059a4SDave May 
557095059a4SDave May /*
558095059a4SDave May *) Ensures all data has been packed
559095059a4SDave May */
56077048351SPatrick Sanan PetscErrorCode DMSwarmDataExPackFinalize(DMSwarmDataEx de)
561095059a4SDave May {
562095059a4SDave May   PetscMPIInt    i,np;
563095059a4SDave May   PetscInt       total;
564095059a4SDave May   PetscErrorCode ierr;
565095059a4SDave May 
566095059a4SDave May   PetscFunctionBegin;
567*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->packer_status != DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Packer has not been initialized. Must call DMSwarmDataExPackInitialize() first.");
568095059a4SDave May   np = de->n_neighbour_procs;
569521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
570*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(de->pack_cnt[i] != de->messages_to_be_sent[i], PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not all messages for neighbour[%d] have been packed. Expected %D : Inserted %D",
571095059a4SDave May                 (int)de->neighbour_procs[i], de->messages_to_be_sent[i], de->pack_cnt[i]);
572095059a4SDave May   }
573095059a4SDave May   /* init */
574521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
575095059a4SDave May     de->messages_to_be_recvieved[i] = -1;
576095059a4SDave May   }
577095059a4SDave May   /* figure out the recv counts here */
578521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
579ffc4695bSBarry 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);
580095059a4SDave May   }
581521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
582ffc4695bSBarry 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);
583095059a4SDave May   }
584ffc4695bSBarry Smith   ierr = MPI_Waitall(2*np, de->_requests, de->_stats);CHKERRMPI(ierr);
585095059a4SDave May   /* create space for the data to be recvieved */
586095059a4SDave May   total = 0;
587521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
588095059a4SDave May     total = total + de->messages_to_be_recvieved[i];
589095059a4SDave May   }
590521f74f9SMatthew G. Knepley   ierr = PetscMalloc(de->unit_message_size * (total + 1), &de->recv_message);CHKERRQ(ierr);
591095059a4SDave May   /* initialize memory */
592521f74f9SMatthew G. Knepley   ierr = PetscMemzero(de->recv_message, de->unit_message_size * (total + 1));CHKERRQ(ierr);
5932d4ee042Sprj-   /* set total items to receive */
594095059a4SDave May   de->recv_message_length = total;
595095059a4SDave May   de->packer_status = DEOBJECT_FINALIZED;
596095059a4SDave May   de->communication_status = DEOBJECT_INITIALIZED;
597ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerPack,0,0,0,0);CHKERRQ(ierr);
598095059a4SDave May   PetscFunctionReturn(0);
599095059a4SDave May }
600095059a4SDave May 
6015627991aSBarry Smith /* do the actual message passing */
60277048351SPatrick Sanan PetscErrorCode DMSwarmDataExBegin(DMSwarmDataEx de)
603095059a4SDave May {
604095059a4SDave May   PetscMPIInt    i,np;
605095059a4SDave May   void           *dest;
606095059a4SDave May   PetscInt       length;
607095059a4SDave May   PetscErrorCode ierr;
608095059a4SDave May 
609095059a4SDave May   PetscFunctionBegin;
610*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->topology_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Topology not finalized");
611*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->message_lengths_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Message lengths not finalized");
612*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->packer_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Packer not finalized");
613*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->communication_status == DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ORDER, "Communication has already been finalized. Must call DMSwarmDataExInitialize() first.");
614*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!de->recv_message, de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DMSwarmDataExPackFinalize() first");
615ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerBegin,0,0,0,0);CHKERRQ(ierr);
616095059a4SDave May   np = de->n_neighbour_procs;
617095059a4SDave May   /* == NON BLOCKING == */
618521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
619095059a4SDave May     length = de->messages_to_be_sent[i] * de->unit_message_size;
620095059a4SDave May     dest = ((char*)de->send_message) + de->unit_message_size * de->message_offsets[i];
621ffc4695bSBarry Smith     ierr = MPI_Isend( dest, length, MPI_CHAR, de->neighbour_procs[i], de->send_tags[i], de->comm, &de->_requests[i]);CHKERRMPI(ierr);
622095059a4SDave May   }
623ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerBegin,0,0,0,0);CHKERRQ(ierr);
624095059a4SDave May   PetscFunctionReturn(0);
625095059a4SDave May }
626095059a4SDave May 
627095059a4SDave May /* do the actual message passing now */
62877048351SPatrick Sanan PetscErrorCode DMSwarmDataExEnd(DMSwarmDataEx de)
629095059a4SDave May {
630095059a4SDave May   PetscMPIInt    i,np;
631095059a4SDave May   PetscInt       total;
632095059a4SDave May   PetscInt       *message_recv_offsets;
633095059a4SDave May   void           *dest;
634095059a4SDave May   PetscInt       length;
635095059a4SDave May   PetscErrorCode ierr;
636095059a4SDave May 
637095059a4SDave May   PetscFunctionBegin;
638*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->communication_status != DEOBJECT_INITIALIZED, de->comm, PETSC_ERR_ORDER, "Communication has not been initialized. Must call DMSwarmDataExInitialize() first.");
639*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!de->recv_message, de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DMSwarmDataExPackFinalize() first");
640ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_DataExchangerEnd,0,0,0,0);CHKERRQ(ierr);
641095059a4SDave May   np = de->n_neighbour_procs;
642b9a482c4SDave May   ierr = PetscMalloc1(np+1, &message_recv_offsets);CHKERRQ(ierr);
643095059a4SDave May   message_recv_offsets[0] = 0;
644095059a4SDave May   total = de->messages_to_be_recvieved[0];
645521f74f9SMatthew G. Knepley   for (i = 1; i < np; ++i) {
646095059a4SDave May     message_recv_offsets[i] = total;
647095059a4SDave May     total = total + de->messages_to_be_recvieved[i];
648095059a4SDave May   }
649095059a4SDave May   /* == NON BLOCKING == */
650521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
651095059a4SDave May     length = de->messages_to_be_recvieved[i] * de->unit_message_size;
652095059a4SDave May     dest = ((char*)de->recv_message) + de->unit_message_size * message_recv_offsets[i];
653ffc4695bSBarry Smith     ierr = MPI_Irecv( dest, length, MPI_CHAR, de->neighbour_procs[i], de->recv_tags[i], de->comm, &de->_requests[np+i]);CHKERRMPI(ierr);
654095059a4SDave May   }
655ffc4695bSBarry Smith   ierr = MPI_Waitall( 2*np, de->_requests, de->_stats);CHKERRMPI(ierr);
656459726d8SSatish Balay   ierr = PetscFree(message_recv_offsets);CHKERRQ(ierr);
657095059a4SDave May   de->communication_status = DEOBJECT_FINALIZED;
658ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_DataExchangerEnd,0,0,0,0);CHKERRQ(ierr);
659095059a4SDave May   PetscFunctionReturn(0);
660095059a4SDave May }
661095059a4SDave May 
66277048351SPatrick Sanan PetscErrorCode DMSwarmDataExGetSendData(DMSwarmDataEx de,PetscInt *length,void **send)
663095059a4SDave May {
664095059a4SDave May   PetscFunctionBegin;
665*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->packer_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being packed.");
666095059a4SDave May   *length = de->send_message_length;
667095059a4SDave May   *send   = de->send_message;
668095059a4SDave May   PetscFunctionReturn(0);
669095059a4SDave May }
670095059a4SDave May 
67177048351SPatrick Sanan PetscErrorCode DMSwarmDataExGetRecvData(DMSwarmDataEx de,PetscInt *length,void **recv)
672095059a4SDave May {
673095059a4SDave May   PetscFunctionBegin;
674*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(de->communication_status != DEOBJECT_FINALIZED, de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being sent.");
675095059a4SDave May   *length = de->recv_message_length;
676095059a4SDave May   *recv   = de->recv_message;
677095059a4SDave May   PetscFunctionReturn(0);
678095059a4SDave May }
679095059a4SDave May 
68077048351SPatrick Sanan PetscErrorCode DMSwarmDataExTopologyGetNeighbours(DMSwarmDataEx de,PetscMPIInt *n,PetscMPIInt *neigh[])
681095059a4SDave May {
682095059a4SDave May   PetscFunctionBegin;
683095059a4SDave May   if (n)     {*n     = de->n_neighbour_procs;}
684095059a4SDave May   if (neigh) {*neigh = de->neighbour_procs;}
685095059a4SDave May   PetscFunctionReturn(0);
686095059a4SDave May }
687