xref: /petsc/src/dm/impls/swarm/data_ex.c (revision 2064fc68ddaf0b6ccb104ffebb987b4fd7e8f5bc)
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 
50*2064fc68SDave May + Constructor
51095059a4SDave May DataExCreate()
52*2064fc68SDave May + Phase A
53095059a4SDave May DataExTopologyInitialize()
54095059a4SDave May DataExTopologyAddNeighbour()
55095059a4SDave May DataExTopologyAddNeighbour()
56095059a4SDave May DataExTopologyFinalize()
57*2064fc68SDave May + Phase B
58095059a4SDave May DataExZeroAllSendCount()
59095059a4SDave May DataExAddToSendCount()
60095059a4SDave May DataExAddToSendCount()
61095059a4SDave May DataExAddToSendCount()
62*2064fc68SDave May + Phase C
63095059a4SDave May DataExPackInitialize()
64095059a4SDave May DataExPackData()
65095059a4SDave May DataExPackData()
66095059a4SDave May DataExPackFinalize()
67*2064fc68SDave May +Phase D
68095059a4SDave May DataExBegin()
69*2064fc68SDave May  ... perform any calculations ...
70095059a4SDave May DataExEnd()
71095059a4SDave May 
72*2064fc68SDave May ... user calls any getters here ...
73095059a4SDave May 
74095059a4SDave May 
75095059a4SDave May */
76095059a4SDave May 
77095059a4SDave May #include <petsc.h>
78095059a4SDave May #include <petscvec.h>
79095059a4SDave May #include <petscmat.h>
80095059a4SDave May 
81095059a4SDave May #include "data_ex.h"
82095059a4SDave May 
83095059a4SDave May const char *status_names[] = {"initialized", "finalized", "unknown"};
84095059a4SDave May 
85095059a4SDave May PetscLogEvent PTATIN_DataExchangerTopologySetup;
86095059a4SDave May PetscLogEvent PTATIN_DataExchangerBegin;
87095059a4SDave May PetscLogEvent PTATIN_DataExchangerEnd;
88095059a4SDave May 
89095059a4SDave May #undef __FUNCT__
90095059a4SDave May #define __FUNCT__ "DataExCreate"
91521f74f9SMatthew G. Knepley PetscErrorCode DataExCreate(MPI_Comm comm,const PetscInt count, DataEx *ex)
92095059a4SDave May {
93095059a4SDave May   PetscErrorCode ierr;
94521f74f9SMatthew G. Knepley   DataEx         d;
95095059a4SDave May 
96521f74f9SMatthew G. Knepley   PetscFunctionBegin;
97521f74f9SMatthew G. Knepley   ierr = PetscMalloc(sizeof(struct _p_DataEx), &d);CHKERRQ(ierr);
98521f74f9SMatthew G. Knepley   ierr = PetscMemzero(d, sizeof(struct _p_DataEx));CHKERRQ(ierr);
99521f74f9SMatthew G. Knepley   ierr = MPI_Comm_dup(comm,&d->comm);CHKERRQ(ierr);
100521f74f9SMatthew G. Knepley   ierr = MPI_Comm_rank(d->comm,&d->rank);CHKERRQ(ierr);
101095059a4SDave May 
102095059a4SDave May   d->instance = count;
103095059a4SDave May 
104095059a4SDave May   d->topology_status        = DEOBJECT_STATE_UNKNOWN;
105095059a4SDave May   d->message_lengths_status = DEOBJECT_STATE_UNKNOWN;
106095059a4SDave May   d->packer_status          = DEOBJECT_STATE_UNKNOWN;
107095059a4SDave May   d->communication_status   = DEOBJECT_STATE_UNKNOWN;
108095059a4SDave May 
109095059a4SDave May   d->n_neighbour_procs = -1;
110095059a4SDave May   d->neighbour_procs   = NULL;
111095059a4SDave May 
112095059a4SDave May   d->messages_to_be_sent      = NULL;
113095059a4SDave May   d->message_offsets          = NULL;
114095059a4SDave May   d->messages_to_be_recvieved = NULL;
115095059a4SDave May 
116095059a4SDave May   d->unit_message_size   = -1;
117095059a4SDave May   d->send_message        = NULL;
118095059a4SDave May   d->send_message_length = -1;
119095059a4SDave May   d->recv_message        = NULL;
120095059a4SDave May   d->recv_message_length = -1;
121095059a4SDave May   d->total_pack_cnt      = -1;
122095059a4SDave May   d->pack_cnt            = NULL;
123095059a4SDave May 
124095059a4SDave May   d->send_tags = NULL;
125095059a4SDave May   d->recv_tags = NULL;
126095059a4SDave May 
127095059a4SDave May   d->_stats    = NULL;
128095059a4SDave May   d->_requests = NULL;
129521f74f9SMatthew G. Knepley   *ex = d;
130521f74f9SMatthew G. Knepley   PetscFunctionReturn(0);
131095059a4SDave May }
132095059a4SDave May 
133095059a4SDave May #undef __FUNCT__
134095059a4SDave May #define __FUNCT__ "DataExView"
135095059a4SDave May PetscErrorCode DataExView(DataEx d)
136095059a4SDave May {
137095059a4SDave May   PetscMPIInt p;
138521f74f9SMatthew G. Knepley   PetscErrorCode ierr;
139095059a4SDave May 
140095059a4SDave May   PetscFunctionBegin;
141521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "DataEx: instance=%D\n",d->instance);CHKERRQ(ierr);
142521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  topology status:        %s \n", status_names[d->topology_status]);CHKERRQ(ierr);
143521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  message lengths status: %s \n", status_names[d->message_lengths_status] );CHKERRQ(ierr);
144521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  packer status status:   %s \n", status_names[d->packer_status] );CHKERRQ(ierr);
145521f74f9SMatthew G. Knepley   ierr = PetscPrintf( PETSC_COMM_WORLD, "  communication status:   %s \n", status_names[d->communication_status] );CHKERRQ(ierr);
146095059a4SDave May 
147095059a4SDave May   if (d->topology_status == DEOBJECT_FINALIZED) {
148521f74f9SMatthew G. Knepley     ierr = PetscPrintf( PETSC_COMM_WORLD, "  Topology:\n");CHKERRQ(ierr);
149521f74f9SMatthew G. Knepley     ierr = PetscPrintf( PETSC_COMM_SELF, "    [%d] neighbours: %d \n", (int)d->rank, (int)d->n_neighbour_procs );CHKERRQ(ierr);
150095059a4SDave May     for (p=0; p<d->n_neighbour_procs; p++) {
151521f74f9SMatthew G. Knepley       ierr = PetscPrintf( PETSC_COMM_SELF, "    [%d]   neighbour[%D] = %d \n", (int)d->rank, p, (int)d->neighbour_procs[p]);CHKERRQ(ierr);
152095059a4SDave May     }
153095059a4SDave May   }
154095059a4SDave May   if (d->message_lengths_status == DEOBJECT_FINALIZED) {
155521f74f9SMatthew G. Knepley     ierr = PetscPrintf( PETSC_COMM_WORLD, "  Message lengths:\n");CHKERRQ(ierr);
156521f74f9SMatthew G. Knepley     ierr = PetscPrintf( PETSC_COMM_SELF, "    [%d] atomic size: %ld \n", (int)d->rank, (long int)d->unit_message_size );CHKERRQ(ierr);
157095059a4SDave May     for (p=0; p<d->n_neighbour_procs; p++) {
158521f74f9SMatthew G. Knepley       ierr = PetscPrintf( PETSC_COMM_SELF, "    [%d] >>>>> ( %D units :: tag = %d ) >>>>> [%d] \n", (int)d->rank, d->messages_to_be_sent[p], d->send_tags[p], (int)d->neighbour_procs[p] );CHKERRQ(ierr);
159095059a4SDave May     }
160095059a4SDave May     for (p=0; p<d->n_neighbour_procs; p++) {
161521f74f9SMatthew G. Knepley       ierr = PetscPrintf( PETSC_COMM_SELF, "    [%d] <<<<< ( %D units :: tag = %d ) <<<<< [%d] \n", (int)d->rank, d->messages_to_be_recvieved[p], d->recv_tags[p], (int)d->neighbour_procs[p] );CHKERRQ(ierr);
162095059a4SDave May     }
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 
169095059a4SDave May #undef __FUNCT__
170095059a4SDave May #define __FUNCT__ "DataExDestroy"
171095059a4SDave May PetscErrorCode DataExDestroy(DataEx d)
172095059a4SDave May {
173095059a4SDave May   PetscErrorCode ierr;
174095059a4SDave May 
175095059a4SDave May   PetscFunctionBegin;
176095059a4SDave May   ierr = MPI_Comm_free(&d->comm);CHKERRQ(ierr);
177521f74f9SMatthew G. Knepley   if (d->neighbour_procs) {ierr = PetscFree(d->neighbour_procs);CHKERRQ(ierr);}
178521f74f9SMatthew G. Knepley   if (d->messages_to_be_sent) {ierr = PetscFree(d->messages_to_be_sent);CHKERRQ(ierr);}
179521f74f9SMatthew G. Knepley   if (d->message_offsets) {ierr = PetscFree(d->message_offsets);CHKERRQ(ierr);}
180521f74f9SMatthew G. Knepley   if (d->messages_to_be_recvieved) {ierr = PetscFree(d->messages_to_be_recvieved);CHKERRQ(ierr);}
181521f74f9SMatthew G. Knepley   if (d->send_message) {ierr = PetscFree(d->send_message);CHKERRQ(ierr);}
182521f74f9SMatthew G. Knepley   if (d->recv_message) {ierr = PetscFree(d->recv_message);CHKERRQ(ierr);}
183521f74f9SMatthew G. Knepley   if (d->pack_cnt) {ierr = PetscFree(d->pack_cnt);CHKERRQ(ierr);}
184521f74f9SMatthew G. Knepley   if (d->send_tags) {ierr = PetscFree(d->send_tags);CHKERRQ(ierr);}
185521f74f9SMatthew G. Knepley   if (d->recv_tags) {ierr = PetscFree(d->recv_tags);CHKERRQ(ierr);}
186521f74f9SMatthew G. Knepley   if (d->_stats) {ierr = PetscFree(d->_stats);CHKERRQ(ierr);}
187521f74f9SMatthew G. Knepley   if (d->_requests) {ierr = PetscFree(d->_requests);CHKERRQ(ierr);}
188521f74f9SMatthew G. Knepley   ierr = PetscFree(d);CHKERRQ(ierr);
189095059a4SDave May   PetscFunctionReturn(0);
190095059a4SDave May }
191095059a4SDave May 
192095059a4SDave May /* === Phase A === */
193095059a4SDave May 
194095059a4SDave May #undef __FUNCT__
195095059a4SDave May #define __FUNCT__ "DataExTopologyInitialize"
196095059a4SDave May PetscErrorCode DataExTopologyInitialize(DataEx d)
197095059a4SDave May {
198521f74f9SMatthew G. Knepley   PetscErrorCode ierr;
199521f74f9SMatthew G. Knepley 
200095059a4SDave May   PetscFunctionBegin;
201095059a4SDave May   d->topology_status = DEOBJECT_INITIALIZED;
202095059a4SDave May   d->n_neighbour_procs = 0;
203781df12bSMatthew G. Knepley   ierr = PetscFree(d->neighbour_procs);CHKERRQ(ierr);
204781df12bSMatthew G. Knepley   ierr = PetscFree(d->messages_to_be_sent);CHKERRQ(ierr);
205781df12bSMatthew G. Knepley   ierr = PetscFree(d->message_offsets);CHKERRQ(ierr);
206781df12bSMatthew G. Knepley   ierr = PetscFree(d->messages_to_be_recvieved);CHKERRQ(ierr);
207781df12bSMatthew G. Knepley   ierr = PetscFree(d->pack_cnt);CHKERRQ(ierr);
208781df12bSMatthew G. Knepley   ierr = PetscFree(d->send_tags);CHKERRQ(ierr);
209781df12bSMatthew G. Knepley   ierr = PetscFree(d->recv_tags);CHKERRQ(ierr);
210095059a4SDave May   PetscFunctionReturn(0);
211095059a4SDave May }
212095059a4SDave May 
213095059a4SDave May #undef __FUNCT__
214095059a4SDave May #define __FUNCT__ "DataExTopologyAddNeighbour"
215095059a4SDave May PetscErrorCode DataExTopologyAddNeighbour(DataEx d,const PetscMPIInt proc_id)
216095059a4SDave May {
217095059a4SDave May   PetscMPIInt    n,found;
218095059a4SDave May   PetscMPIInt    nproc;
219095059a4SDave May   PetscErrorCode ierr;
220095059a4SDave May 
221095059a4SDave May   PetscFunctionBegin;
222*2064fc68SDave 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");
223*2064fc68SDave May   else if (d->topology_status != DEOBJECT_INITIALIZED) SETERRQ(d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be intialised. Call DataExTopologyInitialize() first");
224*2064fc68SDave May 
225095059a4SDave May   /* error on negative entries */
226521f74f9SMatthew G. Knepley   if (proc_id < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Trying to set proc neighbour with a rank < 0");
227095059a4SDave May   /* error on ranks larger than number of procs in communicator */
228095059a4SDave May   ierr = MPI_Comm_size(d->comm,&nproc);CHKERRQ(ierr);
229521f74f9SMatthew G. Knepley   if (proc_id >= nproc) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Trying to set proc neighbour with a rank >= nproc");
230521f74f9SMatthew G. Knepley   if (d->n_neighbour_procs == 0) {ierr = PetscMalloc1(1, &d->neighbour_procs);CHKERRQ(ierr);}
231095059a4SDave May   /* check for proc_id */
232095059a4SDave May   found = 0;
233095059a4SDave May   for (n = 0; n < d->n_neighbour_procs; n++) {
234095059a4SDave May     if (d->neighbour_procs[n] == proc_id) {
235095059a4SDave May       found  = 1;
236095059a4SDave May     }
237095059a4SDave May   }
238095059a4SDave May   if (found == 0) { /* add it to list */
2394be7464cSMatthew G. Knepley     ierr = PetscRealloc(sizeof(PetscMPIInt)*(d->n_neighbour_procs+1), &d->neighbour_procs);CHKERRQ(ierr);
240095059a4SDave May     d->neighbour_procs[ d->n_neighbour_procs ] = proc_id;
241095059a4SDave May     d->n_neighbour_procs++;
242095059a4SDave May   }
243095059a4SDave May   PetscFunctionReturn(0);
244095059a4SDave May }
245095059a4SDave May 
246095059a4SDave May /*
247095059a4SDave May counter: the index of the communication object
248095059a4SDave May N: the number of processors
249095059a4SDave May r0: rank of sender
250095059a4SDave May r1: rank of receiver
251095059a4SDave May 
252095059a4SDave May procs = { 0, 1, 2, 3 }
253095059a4SDave May 
254095059a4SDave May 0 ==> 0		e=0
255095059a4SDave May 0 ==> 1		e=1
256095059a4SDave May 0 ==> 2		e=2
257095059a4SDave May 0 ==> 3		e=3
258095059a4SDave May 
259095059a4SDave May 1 ==> 0		e=4
260095059a4SDave May 1 ==> 1		e=5
261095059a4SDave May 1 ==> 2		e=6
262095059a4SDave May 1 ==> 3		e=7
263095059a4SDave May 
264095059a4SDave May 2 ==> 0		e=8
265095059a4SDave May 2 ==> 1		e=9
266095059a4SDave May 2 ==> 2		e=10
267095059a4SDave May 2 ==> 3		e=11
268095059a4SDave May 
269095059a4SDave May 3 ==> 0		e=12
270095059a4SDave May 3 ==> 1		e=13
271095059a4SDave May 3 ==> 2		e=14
272095059a4SDave May 3 ==> 3		e=15
273095059a4SDave May 
274095059a4SDave May If we require that proc A sends to proc B, then the SEND tag index will be given by
275095059a4SDave May   N * rank(A) + rank(B) + offset
276095059a4SDave May If we require that proc A will receive from proc B, then the RECV tag index will be given by
277095059a4SDave May   N * rank(B) + rank(A) + offset
278095059a4SDave May 
279095059a4SDave May */
280521f74f9SMatthew G. Knepley static void _get_tags(PetscInt counter, PetscMPIInt N, PetscMPIInt r0,PetscMPIInt r1, PetscMPIInt *_st, PetscMPIInt *_rt)
281095059a4SDave May {
282095059a4SDave May   PetscMPIInt st,rt;
283095059a4SDave May 
284095059a4SDave May   st = N*r0 + r1   +   N*N*counter;
285095059a4SDave May   rt = N*r1 + r0   +   N*N*counter;
286095059a4SDave May   *_st = st;
287095059a4SDave May   *_rt = rt;
288095059a4SDave May }
289095059a4SDave May 
290095059a4SDave May /*
291095059a4SDave May Makes the communication map symmetric
292095059a4SDave May */
293095059a4SDave May #undef __FUNCT__
294095059a4SDave May #define __FUNCT__ "_DataExCompleteCommunicationMap"
295095059a4SDave May PetscErrorCode _DataExCompleteCommunicationMap(MPI_Comm comm,PetscMPIInt n,PetscMPIInt proc_neighbours[],PetscMPIInt *n_new,PetscMPIInt **proc_neighbours_new)
296095059a4SDave May {
297dcf43ee8SDave May   Mat               A;
298095059a4SDave May   PetscInt          i,j,nc;
299095059a4SDave May   PetscInt          n_, *proc_neighbours_;
300095059a4SDave May   PetscInt          rank_i_;
301095059a4SDave May   PetscMPIInt       size,  rank_i;
302095059a4SDave May   PetscScalar       *vals;
303095059a4SDave May   const PetscInt    *cols;
304095059a4SDave May   const PetscScalar *red_vals;
305095059a4SDave May   PetscMPIInt       _n_new, *_proc_neighbours_new;
306095059a4SDave May   PetscErrorCode    ierr;
307095059a4SDave May 
308095059a4SDave May   PetscFunctionBegin;
309095059a4SDave May   n_ = n;
310095059a4SDave May   ierr = PetscMalloc(sizeof(PetscInt) * n_, &proc_neighbours_);CHKERRQ(ierr);
311521f74f9SMatthew G. Knepley   for (i = 0; i < n_; ++i) {
312095059a4SDave May     proc_neighbours_[i] = proc_neighbours[i];
313095059a4SDave May   }
314095059a4SDave May   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
315095059a4SDave May   ierr = MPI_Comm_rank(comm,&rank_i);CHKERRQ(ierr);
316095059a4SDave May   rank_i_ = rank_i;
317095059a4SDave May 
318095059a4SDave May   ierr = MatCreate(comm,&A);CHKERRQ(ierr);
319095059a4SDave May   ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,size,size);CHKERRQ(ierr);
320095059a4SDave May   ierr = MatSetType(A,MATAIJ);CHKERRQ(ierr);
321dcf43ee8SDave May   ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
322dcf43ee8SDave May   ierr = MatMPIAIJSetPreallocation(A,n_,NULL,n_,NULL);CHKERRQ(ierr);
323dcf43ee8SDave May   ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);CHKERRQ(ierr);
324095059a4SDave May   /* Build original map */
325521f74f9SMatthew G. Knepley   ierr = PetscMalloc1(n_, &vals);CHKERRQ(ierr);
326521f74f9SMatthew G. Knepley   for (i = 0; i < n_; ++i) {
327095059a4SDave May     vals[i] = 1.0;
328095059a4SDave May   }
329095059a4SDave May   ierr = MatSetValues( A, 1,&rank_i_, n_,proc_neighbours_, vals, INSERT_VALUES );CHKERRQ(ierr);
330095059a4SDave May   ierr = MatAssemblyBegin(A,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
331095059a4SDave May   ierr = MatAssemblyEnd(A,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
332095059a4SDave May   /* Now force all other connections if they are not already there */
333095059a4SDave May   /* It's more efficient to do them all at once */
334521f74f9SMatthew G. Knepley   for (i = 0; i < n_; ++i) {
335095059a4SDave May     vals[i] = 2.0;
336095059a4SDave May   }
337095059a4SDave May   ierr = MatSetValues( A, n_,proc_neighbours_, 1,&rank_i_, vals, INSERT_VALUES );CHKERRQ(ierr);
338095059a4SDave May   ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
339095059a4SDave May   ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3406275818cSDave May /*
341095059a4SDave May   ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr);
342095059a4SDave May   ierr = MatView(A,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
343095059a4SDave May   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
3446275818cSDave May */
345095059a4SDave May   if ((n_new != NULL) && (proc_neighbours_new != NULL)) {
346dcf43ee8SDave May     ierr = MatGetRow(A, rank_i_, &nc, &cols, &red_vals);CHKERRQ(ierr);
347095059a4SDave May     _n_new = (PetscMPIInt) nc;
348521f74f9SMatthew G. Knepley     ierr = PetscMalloc1(_n_new, &_proc_neighbours_new);CHKERRQ(ierr);
349521f74f9SMatthew G. Knepley     for (j = 0; j < nc; ++j) {
350095059a4SDave May       _proc_neighbours_new[j] = (PetscMPIInt)cols[j];
351095059a4SDave May     }
352dcf43ee8SDave May     ierr = MatRestoreRow( A, rank_i_, &nc, &cols, &red_vals );CHKERRQ(ierr);
353095059a4SDave May     *n_new               = (PetscMPIInt)_n_new;
354095059a4SDave May     *proc_neighbours_new = (PetscMPIInt*)_proc_neighbours_new;
355095059a4SDave May   }
356095059a4SDave May   ierr = MatDestroy(&A);CHKERRQ(ierr);
357095059a4SDave May   ierr = PetscFree(vals);CHKERRQ(ierr);
358095059a4SDave May   ierr = PetscFree(proc_neighbours_);CHKERRQ(ierr);
359095059a4SDave May   ierr = MPI_Barrier(comm);CHKERRQ(ierr);
360095059a4SDave May   PetscFunctionReturn(0);
361095059a4SDave May }
362095059a4SDave May 
363095059a4SDave May #undef __FUNCT__
364095059a4SDave May #define __FUNCT__ "DataExTopologyFinalize"
365095059a4SDave May PetscErrorCode DataExTopologyFinalize(DataEx d)
366095059a4SDave May {
367095059a4SDave May   PetscMPIInt    symm_nn;
368095059a4SDave May   PetscMPIInt   *symm_procs;
369095059a4SDave May   PetscMPIInt    r0,n,st,rt;
370095059a4SDave May   PetscMPIInt    nprocs;
371095059a4SDave May   PetscErrorCode ierr;
372095059a4SDave May 
373095059a4SDave May   PetscFunctionBegin;
374*2064fc68SDave May   if (d->topology_status != DEOBJECT_INITIALIZED) SETERRQ(d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be intialised. Call DataExTopologyInitialize() first");
375*2064fc68SDave May 
376095059a4SDave May   ierr = PetscLogEventBegin(PTATIN_DataExchangerTopologySetup,0,0,0,0);CHKERRQ(ierr);
377095059a4SDave May   /* given infomation about all my neighbours, make map symmetric */
378095059a4SDave May   ierr = _DataExCompleteCommunicationMap( d->comm,d->n_neighbour_procs,d->neighbour_procs, &symm_nn, &symm_procs );CHKERRQ(ierr);
379095059a4SDave May   /* update my arrays */
380521f74f9SMatthew G. Knepley   ierr = PetscFree(d->neighbour_procs);
381095059a4SDave May   d->n_neighbour_procs = symm_nn;
382095059a4SDave May   d->neighbour_procs   = symm_procs;
383095059a4SDave May   /* allocates memory */
384b9a482c4SDave May   if (!d->messages_to_be_sent) {ierr = PetscMalloc1(d->n_neighbour_procs+1, &d->messages_to_be_sent);CHKERRQ(ierr);}
385b9a482c4SDave May   if (!d->message_offsets) {ierr = PetscMalloc1(d->n_neighbour_procs+1, &d->message_offsets);CHKERRQ(ierr);}
386b9a482c4SDave May   if (!d->messages_to_be_recvieved) {ierr = PetscMalloc1(d->n_neighbour_procs+1, &d->messages_to_be_recvieved);CHKERRQ(ierr);}
387521f74f9SMatthew G. Knepley   if (!d->pack_cnt) {ierr = PetscMalloc(sizeof(PetscInt) * d->n_neighbour_procs, &d->pack_cnt);CHKERRQ(ierr);}
388521f74f9SMatthew G. Knepley   if (!d->_stats) {ierr = PetscMalloc(sizeof(MPI_Status) * 2*d->n_neighbour_procs, &d->_stats);CHKERRQ(ierr);}
389521f74f9SMatthew G. Knepley   if (!d->_requests) {ierr = PetscMalloc(sizeof(MPI_Request) * 2*d->n_neighbour_procs, &d->_requests);CHKERRQ(ierr);}
390521f74f9SMatthew G. Knepley   if (!d->send_tags) {ierr = PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->send_tags);CHKERRQ(ierr);}
391521f74f9SMatthew G. Knepley   if (!d->recv_tags) {ierr = PetscMalloc(sizeof(int) * d->n_neighbour_procs, &d->recv_tags);CHKERRQ(ierr);}
392095059a4SDave May   /* compute message tags */
393095059a4SDave May   ierr = MPI_Comm_size(d->comm,&nprocs);CHKERRQ(ierr);
394095059a4SDave May   r0 = d->rank;
395521f74f9SMatthew G. Knepley   for (n = 0; n < d->n_neighbour_procs; ++n) {
396095059a4SDave May     PetscMPIInt r1 = d->neighbour_procs[n];
397095059a4SDave May 
398095059a4SDave May     _get_tags( d->instance, nprocs, r0,r1, &st, &rt );
399095059a4SDave May     d->send_tags[n] = (int)st;
400095059a4SDave May     d->recv_tags[n] = (int)rt;
401095059a4SDave May   }
402095059a4SDave May   d->topology_status = DEOBJECT_FINALIZED;
403095059a4SDave May   ierr = PetscLogEventEnd(PTATIN_DataExchangerTopologySetup,0,0,0,0);CHKERRQ(ierr);
404095059a4SDave May   PetscFunctionReturn(0);
405095059a4SDave May }
406095059a4SDave May 
407095059a4SDave May /* === Phase B === */
408095059a4SDave May #undef __FUNCT__
409095059a4SDave May #define __FUNCT__ "_DataExConvertProcIdToLocalIndex"
410095059a4SDave May PetscErrorCode _DataExConvertProcIdToLocalIndex(DataEx de,PetscMPIInt proc_id,PetscMPIInt *local)
411095059a4SDave May {
412095059a4SDave May   PetscMPIInt i,np;
413095059a4SDave May 
414095059a4SDave May   PetscFunctionBegin;
415095059a4SDave May   np = de->n_neighbour_procs;
416095059a4SDave May   *local = -1;
417521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
418095059a4SDave May     if (proc_id == de->neighbour_procs[i]) {
419095059a4SDave May       *local = i;
420095059a4SDave May       break;
421095059a4SDave May     }
422095059a4SDave May   }
423095059a4SDave May   PetscFunctionReturn(0);
424095059a4SDave May }
425095059a4SDave May 
426095059a4SDave May #undef __FUNCT__
427095059a4SDave May #define __FUNCT__ "DataExInitializeSendCount"
428095059a4SDave May PetscErrorCode DataExInitializeSendCount(DataEx de)
429095059a4SDave May {
430095059a4SDave May   PetscMPIInt i;
431095059a4SDave May 
432095059a4SDave May   PetscFunctionBegin;
433521f74f9SMatthew G. Knepley   if (de->topology_status != DEOBJECT_FINALIZED) SETERRQ(de->comm, PETSC_ERR_ORDER, "Topology not finalized");
434095059a4SDave May   de->message_lengths_status = DEOBJECT_INITIALIZED;
435521f74f9SMatthew G. Knepley   for (i = 0; i < de->n_neighbour_procs; ++i) {
436095059a4SDave May     de->messages_to_be_sent[i] = 0;
437095059a4SDave May   }
438095059a4SDave May   PetscFunctionReturn(0);
439095059a4SDave May }
440095059a4SDave May 
441095059a4SDave May /*
442095059a4SDave May 1) only allows counters to be set on neighbouring cpus
443095059a4SDave May */
444095059a4SDave May #undef __FUNCT__
445095059a4SDave May #define __FUNCT__ "DataExAddToSendCount"
446095059a4SDave May PetscErrorCode DataExAddToSendCount(DataEx de,const PetscMPIInt proc_id,const PetscInt count)
447095059a4SDave May {
448095059a4SDave May   PetscMPIInt    local_val;
449095059a4SDave May   PetscErrorCode ierr;
450095059a4SDave May 
451095059a4SDave May   PetscFunctionBegin;
452*2064fc68SDave 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" );
453*2064fc68SDave May   else if (de->message_lengths_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DataExInitializeSendCount() first" );
454*2064fc68SDave May 
455095059a4SDave May   ierr = _DataExConvertProcIdToLocalIndex( de, proc_id, &local_val );CHKERRQ(ierr);
456*2064fc68SDave May   if (local_val == -1) SETERRQ1( PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,"Proc %d is not a valid neighbour rank", (int)proc_id );
457*2064fc68SDave May 
458095059a4SDave May   de->messages_to_be_sent[local_val] = de->messages_to_be_sent[local_val] + count;
459095059a4SDave May   PetscFunctionReturn(0);
460095059a4SDave May }
461095059a4SDave May 
462095059a4SDave May #undef __FUNCT__
463095059a4SDave May #define __FUNCT__ "DataExFinalizeSendCount"
464095059a4SDave May PetscErrorCode DataExFinalizeSendCount(DataEx de)
465095059a4SDave May {
466095059a4SDave May   PetscFunctionBegin;
467*2064fc68SDave May   if (de->message_lengths_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DataExInitializeSendCount() first" );
468*2064fc68SDave May 
469095059a4SDave May   de->message_lengths_status = DEOBJECT_FINALIZED;
470095059a4SDave May   PetscFunctionReturn(0);
471095059a4SDave May }
472095059a4SDave May 
473095059a4SDave May /* === Phase C === */
474095059a4SDave May /*
475095059a4SDave May  * zero out all send counts
476095059a4SDave May  * free send and recv buffers
477095059a4SDave May  * zeros out message length
478095059a4SDave May  * zeros out all counters
479095059a4SDave May  * zero out packed data counters
480095059a4SDave May */
481095059a4SDave May #undef __FUNCT__
482095059a4SDave May #define __FUNCT__ "_DataExInitializeTmpStorage"
483095059a4SDave May PetscErrorCode _DataExInitializeTmpStorage(DataEx de)
484095059a4SDave May {
485095059a4SDave May   PetscMPIInt    i, np;
486521f74f9SMatthew G. Knepley   PetscErrorCode ierr;
487095059a4SDave May 
488095059a4SDave May   PetscFunctionBegin;
489*2064fc68SDave May   /*if (de->n_neighbour_procs < 0) SETERRQ( PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of neighbour procs < 0");
490b9a482c4SDave May   */
491b9a482c4SDave May   /*
492*2064fc68SDave May   if (!de->neighbour_procs) SETERRQ( PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Neighbour proc list is NULL" );
493b9a482c4SDave May   */
494095059a4SDave May   np = de->n_neighbour_procs;
495521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
496095059a4SDave May     /*	de->messages_to_be_sent[i] = -1; */
497095059a4SDave May     de->messages_to_be_recvieved[i] = -1;
498095059a4SDave May   }
499521f74f9SMatthew G. Knepley   ierr = PetscFree(de->send_message);CHKERRQ(ierr);
500521f74f9SMatthew G. Knepley   ierr = PetscFree(de->recv_message);CHKERRQ(ierr);
501095059a4SDave May   PetscFunctionReturn(0);
502095059a4SDave May }
503095059a4SDave May 
504095059a4SDave May /*
505095059a4SDave May *) Zeros out pack data counters
506095059a4SDave May *) Ensures mesaage length is set
507095059a4SDave May *) Checks send counts properly initialized
508095059a4SDave May *) allocates space for pack data
509095059a4SDave May */
510095059a4SDave May #undef __FUNCT__
511095059a4SDave May #define __FUNCT__ "DataExPackInitialize"
512095059a4SDave May PetscErrorCode DataExPackInitialize(DataEx de,size_t unit_message_size)
513095059a4SDave May {
514095059a4SDave May   PetscMPIInt    i,np;
515095059a4SDave May   PetscInt       total;
516095059a4SDave May   PetscErrorCode ierr;
517095059a4SDave May 
518095059a4SDave May   PetscFunctionBegin;
519521f74f9SMatthew G. Knepley   if (de->topology_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Topology not finalized" );
520521f74f9SMatthew G. Knepley   if (de->message_lengths_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths not finalized" );
521095059a4SDave May   de->packer_status = DEOBJECT_INITIALIZED;
522095059a4SDave May   ierr = _DataExInitializeTmpStorage(de);CHKERRQ(ierr);
523095059a4SDave May   np = de->n_neighbour_procs;
524095059a4SDave May   de->unit_message_size = unit_message_size;
525095059a4SDave May   total = 0;
526521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
527095059a4SDave May     if (de->messages_to_be_sent[i] == -1) {
528095059a4SDave May       PetscMPIInt proc_neighour = de->neighbour_procs[i];
529095059a4SDave May       SETERRQ1( PETSC_COMM_SELF, PETSC_ERR_ORDER, "Messages_to_be_sent[neighbour_proc=%d] is un-initialised. Call DataExSetSendCount() first", (int)proc_neighour );
530095059a4SDave May     }
531095059a4SDave May     total = total + de->messages_to_be_sent[i];
532095059a4SDave May   }
533095059a4SDave May   /* create space for the data to be sent */
534521f74f9SMatthew G. Knepley   ierr = PetscMalloc(unit_message_size * (total + 1), &de->send_message);CHKERRQ(ierr);
535095059a4SDave May   /* initialize memory */
536521f74f9SMatthew G. Knepley   ierr = PetscMemzero(de->send_message, unit_message_size * (total + 1));CHKERRQ(ierr);
537095059a4SDave May   /* set total items to send */
538095059a4SDave May   de->send_message_length = total;
539095059a4SDave May   de->message_offsets[0] = 0;
540095059a4SDave May   total = de->messages_to_be_sent[0];
541521f74f9SMatthew G. Knepley   for (i = 1; i < np; ++i) {
542095059a4SDave May     de->message_offsets[i] = total;
543095059a4SDave May     total = total + de->messages_to_be_sent[i];
544095059a4SDave May   }
545095059a4SDave May   /* init the packer counters */
546095059a4SDave May   de->total_pack_cnt = 0;
547521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
548095059a4SDave May     de->pack_cnt[i] = 0;
549095059a4SDave May   }
550095059a4SDave May   PetscFunctionReturn(0);
551095059a4SDave May }
552095059a4SDave May 
553095059a4SDave May /*
554095059a4SDave May *) Ensures data gets been packed appropriately and no overlaps occur
555095059a4SDave May */
556095059a4SDave May #undef __FUNCT__
557095059a4SDave May #define __FUNCT__ "DataExPackData"
558095059a4SDave May PetscErrorCode DataExPackData(DataEx de,PetscMPIInt proc_id,PetscInt n,void *data)
559095059a4SDave May {
560095059a4SDave May   PetscMPIInt    local;
561095059a4SDave May   PetscInt       insert_location;
562095059a4SDave May   void           *dest;
563095059a4SDave May   PetscErrorCode ierr;
564095059a4SDave May 
565095059a4SDave May   PetscFunctionBegin;
566*2064fc68SDave 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" );
567*2064fc68SDave May   else if (de->packer_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Packed data must be defined. Call DataExInitializeSendCount(), DataExAddToSendCount(), DataExPackInitialize() first" );
568*2064fc68SDave May 
569521f74f9SMatthew G. Knepley   if (!de->send_message) SETERRQ( de->comm, PETSC_ERR_ORDER, "send_message is not initialized. Call DataExPackInitialize() first" );
570095059a4SDave May   ierr = _DataExConvertProcIdToLocalIndex( de, proc_id, &local );CHKERRQ(ierr);
571521f74f9SMatthew G. Knepley   if (local == -1) SETERRQ1( PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "proc_id %d is not registered neighbour", (int)proc_id );
572*2064fc68SDave 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",
573095059a4SDave May               (int)proc_id, de->messages_to_be_sent[local], n+de->pack_cnt[local] );
574*2064fc68SDave May 
575095059a4SDave May   /* copy memory */
576095059a4SDave May   insert_location = de->message_offsets[local] + de->pack_cnt[local];
577095059a4SDave May   dest = ((char*)de->send_message) + de->unit_message_size*insert_location;
578521f74f9SMatthew G. Knepley   ierr = PetscMemcpy(dest, data, de->unit_message_size * n);CHKERRQ(ierr);
579095059a4SDave May   /* increment counter */
580095059a4SDave May   de->pack_cnt[local] = de->pack_cnt[local] + n;
581095059a4SDave May   PetscFunctionReturn(0);
582095059a4SDave May }
583095059a4SDave May 
584095059a4SDave May /*
585095059a4SDave May *) Ensures all data has been packed
586095059a4SDave May */
587095059a4SDave May #undef __FUNCT__
588095059a4SDave May #define __FUNCT__ "DataExPackFinalize"
589095059a4SDave May PetscErrorCode DataExPackFinalize(DataEx de)
590095059a4SDave May {
591095059a4SDave May   PetscMPIInt i,np;
592095059a4SDave May   PetscInt    total;
593095059a4SDave May   PetscErrorCode ierr;
594095059a4SDave May 
595095059a4SDave May   PetscFunctionBegin;
596521f74f9SMatthew G. Knepley   if (de->packer_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Packer has not been initialized. Must call DataExPackInitialize() first." );
597095059a4SDave May   np = de->n_neighbour_procs;
598521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
599*2064fc68SDave 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",
600095059a4SDave May                 (int)de->neighbour_procs[i], de->messages_to_be_sent[i], de->pack_cnt[i] );
601095059a4SDave May   }
602095059a4SDave May   /* init */
603521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
604095059a4SDave May     de->messages_to_be_recvieved[i] = -1;
605095059a4SDave May   }
606095059a4SDave May   /* figure out the recv counts here */
607521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
608095059a4SDave 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);
609095059a4SDave May   }
610521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
611095059a4SDave 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);
612095059a4SDave May   }
613095059a4SDave May   ierr = MPI_Waitall(2*np, de->_requests, de->_stats);CHKERRQ(ierr);
614095059a4SDave May   /* create space for the data to be recvieved */
615095059a4SDave May   total = 0;
616521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
617095059a4SDave May     total = total + de->messages_to_be_recvieved[i];
618095059a4SDave May   }
619521f74f9SMatthew G. Knepley   ierr = PetscMalloc(de->unit_message_size * (total + 1), &de->recv_message);CHKERRQ(ierr);
620095059a4SDave May   /* initialize memory */
621521f74f9SMatthew G. Knepley   ierr = PetscMemzero(de->recv_message, de->unit_message_size * (total + 1));CHKERRQ(ierr);
622095059a4SDave May   /* set total items to recieve */
623095059a4SDave May   de->recv_message_length = total;
624095059a4SDave May   de->packer_status = DEOBJECT_FINALIZED;
625095059a4SDave May   de->communication_status = DEOBJECT_INITIALIZED;
626095059a4SDave May   PetscFunctionReturn(0);
627095059a4SDave May }
628095059a4SDave May 
629095059a4SDave May /* do the actual message passing now */
630095059a4SDave May #undef __FUNCT__
631095059a4SDave May #define __FUNCT__ "DataExBegin"
632095059a4SDave May PetscErrorCode DataExBegin(DataEx de)
633095059a4SDave May {
634095059a4SDave May   PetscMPIInt i,np;
635095059a4SDave May   void       *dest;
636095059a4SDave May   PetscInt    length;
637095059a4SDave May   PetscErrorCode ierr;
638095059a4SDave May 
639095059a4SDave May   PetscFunctionBegin;
640521f74f9SMatthew G. Knepley   if (de->topology_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Topology not finalized" );
641521f74f9SMatthew G. Knepley   if (de->message_lengths_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths not finalized" );
642521f74f9SMatthew G. Knepley   if (de->packer_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Packer not finalized" );
643521f74f9SMatthew G. Knepley   if (de->communication_status == DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Communication has already been finalized. Must call DataExInitialize() first." );
644521f74f9SMatthew G. Knepley   if (!de->recv_message) SETERRQ( de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DataExPackFinalize() first" );
645095059a4SDave May   ierr = PetscLogEventBegin(PTATIN_DataExchangerBegin,0,0,0,0);CHKERRQ(ierr);
646095059a4SDave May   np = de->n_neighbour_procs;
647095059a4SDave May   /* == NON BLOCKING == */
648521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
649095059a4SDave May     length = de->messages_to_be_sent[i] * de->unit_message_size;
650095059a4SDave May     dest = ((char*)de->send_message) + de->unit_message_size * de->message_offsets[i];
651095059a4SDave May     ierr = MPI_Isend( dest, length, MPI_CHAR, de->neighbour_procs[i], de->send_tags[i], de->comm, &de->_requests[i] );CHKERRQ(ierr);
652095059a4SDave May   }
653095059a4SDave May   ierr = PetscLogEventEnd(PTATIN_DataExchangerBegin,0,0,0,0);CHKERRQ(ierr);
654095059a4SDave May   PetscFunctionReturn(0);
655095059a4SDave May }
656095059a4SDave May 
657095059a4SDave May /* do the actual message passing now */
658095059a4SDave May #undef __FUNCT__
659095059a4SDave May #define __FUNCT__ "DataExEnd"
660095059a4SDave May PetscErrorCode DataExEnd(DataEx de)
661095059a4SDave May {
662095059a4SDave May   PetscMPIInt  i,np;
663095059a4SDave May   PetscInt     total;
664095059a4SDave May   PetscInt    *message_recv_offsets;
665095059a4SDave May   void        *dest;
666095059a4SDave May   PetscInt     length;
667095059a4SDave May   PetscErrorCode ierr;
668095059a4SDave May 
669095059a4SDave May   PetscFunctionBegin;
670521f74f9SMatthew G. Knepley   if (de->communication_status != DEOBJECT_INITIALIZED) SETERRQ( de->comm, PETSC_ERR_ORDER, "Communication has not been initialized. Must call DataExInitialize() first." );
671521f74f9SMatthew G. Knepley   if (!de->recv_message) SETERRQ( de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DataExPackFinalize() first" );
672095059a4SDave May   ierr = PetscLogEventBegin(PTATIN_DataExchangerEnd,0,0,0,0);CHKERRQ(ierr);
673095059a4SDave May   np = de->n_neighbour_procs;
674b9a482c4SDave May   ierr = PetscMalloc1(np+1, &message_recv_offsets);CHKERRQ(ierr);
675095059a4SDave May   message_recv_offsets[0] = 0;
676095059a4SDave May   total = de->messages_to_be_recvieved[0];
677521f74f9SMatthew G. Knepley   for (i = 1; i < np; ++i) {
678095059a4SDave May     message_recv_offsets[i] = total;
679095059a4SDave May     total = total + de->messages_to_be_recvieved[i];
680095059a4SDave May   }
681095059a4SDave May   /* == NON BLOCKING == */
682521f74f9SMatthew G. Knepley   for (i = 0; i < np; ++i) {
683095059a4SDave May     length = de->messages_to_be_recvieved[i] * de->unit_message_size;
684095059a4SDave May     dest = ((char*)de->recv_message) + de->unit_message_size * message_recv_offsets[i];
685095059a4SDave May     ierr = MPI_Irecv( dest, length, MPI_CHAR, de->neighbour_procs[i], de->recv_tags[i], de->comm, &de->_requests[np+i] );CHKERRQ(ierr);
686095059a4SDave May   }
687095059a4SDave May   ierr = MPI_Waitall( 2*np, de->_requests, de->_stats );CHKERRQ(ierr);
688521f74f9SMatthew G. Knepley   ierr = PetscFree(message_recv_offsets);
689095059a4SDave May   de->communication_status = DEOBJECT_FINALIZED;
690095059a4SDave May   ierr = PetscLogEventEnd(PTATIN_DataExchangerEnd,0,0,0,0);CHKERRQ(ierr);
691095059a4SDave May   PetscFunctionReturn(0);
692095059a4SDave May }
693095059a4SDave May 
694095059a4SDave May #undef __FUNCT__
695095059a4SDave May #define __FUNCT__ "DataExGetSendData"
696095059a4SDave May PetscErrorCode DataExGetSendData(DataEx de,PetscInt *length,void **send)
697095059a4SDave May {
698095059a4SDave May   PetscFunctionBegin;
699521f74f9SMatthew G. Knepley   if (de->packer_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being packed." );
700095059a4SDave May   *length = de->send_message_length;
701095059a4SDave May   *send   = de->send_message;
702095059a4SDave May   PetscFunctionReturn(0);
703095059a4SDave May }
704095059a4SDave May 
705095059a4SDave May #undef __FUNCT__
706095059a4SDave May #define __FUNCT__ "DataExGetRecvData"
707095059a4SDave May PetscErrorCode DataExGetRecvData(DataEx de,PetscInt *length,void **recv)
708095059a4SDave May {
709095059a4SDave May   PetscFunctionBegin;
710521f74f9SMatthew G. Knepley   if (de->communication_status != DEOBJECT_FINALIZED) SETERRQ( de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being sent." );
711095059a4SDave May   *length = de->recv_message_length;
712095059a4SDave May   *recv   = de->recv_message;
713095059a4SDave May   PetscFunctionReturn(0);
714095059a4SDave May }
715095059a4SDave May 
716095059a4SDave May #undef __FUNCT__
717095059a4SDave May #define __FUNCT__ "DataExTopologyGetNeighbours"
718095059a4SDave May PetscErrorCode DataExTopologyGetNeighbours(DataEx de,PetscMPIInt *n,PetscMPIInt *neigh[])
719095059a4SDave May {
720095059a4SDave May   PetscFunctionBegin;
721095059a4SDave May   if (n)     {*n     = de->n_neighbour_procs;}
722095059a4SDave May   if (neigh) {*neigh = de->neighbour_procs;}
723095059a4SDave May   PetscFunctionReturn(0);
724095059a4SDave May }
725095059a4SDave May 
726