xref: /petsc/src/dm/impls/swarm/data_ex.c (revision dcf43ee8151790df9d04c78a9ee59340338a1d5a)
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 
50095059a4SDave May //
51095059a4SDave May DataExCreate()
52095059a4SDave May // A
53095059a4SDave May DataExTopologyInitialize()
54095059a4SDave May DataExTopologyAddNeighbour()
55095059a4SDave May DataExTopologyAddNeighbour()
56095059a4SDave May DataExTopologyFinalize()
57095059a4SDave May // B
58095059a4SDave May DataExZeroAllSendCount()
59095059a4SDave May DataExAddToSendCount()
60095059a4SDave May DataExAddToSendCount()
61095059a4SDave May DataExAddToSendCount()
62095059a4SDave May // C
63095059a4SDave May DataExPackInitialize()
64095059a4SDave May DataExPackData()
65095059a4SDave May DataExPackData()
66095059a4SDave May DataExPackFinalize()
67095059a4SDave May // D
68095059a4SDave May DataExBegin()
69095059a4SDave May // ... perform any calculations ... ///
70095059a4SDave May DataExEnd()
71095059a4SDave May 
72095059a4SDave May // Call any getters //
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 
90095059a4SDave May #undef __FUNCT__
91095059a4SDave May #define __FUNCT__ "DataExCreate"
92095059a4SDave May DataEx DataExCreate(MPI_Comm comm,const PetscInt count)
93095059a4SDave May {
94095059a4SDave May 	DataEx         d;
95095059a4SDave May 	PetscErrorCode ierr;
96095059a4SDave May 
97095059a4SDave May 	d = (DataEx)malloc( sizeof(struct _p_DataEx) );
98095059a4SDave May 	memset( d, 0, sizeof(struct _p_DataEx) );
99095059a4SDave May 
100095059a4SDave May 	ierr = MPI_Comm_dup(comm,&d->comm);
101095059a4SDave May 	ierr = MPI_Comm_rank(d->comm,&d->rank);
102095059a4SDave May 
103095059a4SDave May 	d->instance = count;
104095059a4SDave May 
105095059a4SDave May 	d->topology_status        = DEOBJECT_STATE_UNKNOWN;
106095059a4SDave May 	d->message_lengths_status = DEOBJECT_STATE_UNKNOWN;
107095059a4SDave May 	d->packer_status          = DEOBJECT_STATE_UNKNOWN;
108095059a4SDave May 	d->communication_status   = DEOBJECT_STATE_UNKNOWN;
109095059a4SDave May 
110095059a4SDave May 	d->n_neighbour_procs = -1;
111095059a4SDave May 	d->neighbour_procs   = NULL;
112095059a4SDave May 
113095059a4SDave May 	d->messages_to_be_sent      = NULL;
114095059a4SDave May 	d->message_offsets          = NULL;
115095059a4SDave May 	d->messages_to_be_recvieved = NULL;
116095059a4SDave May 
117095059a4SDave May 	d->unit_message_size   = -1;
118095059a4SDave May 	d->send_message        = NULL;
119095059a4SDave May 	d->send_message_length = -1;
120095059a4SDave May 	d->recv_message        = NULL;
121095059a4SDave May 	d->recv_message_length = -1;
122095059a4SDave May 	d->total_pack_cnt      = -1;
123095059a4SDave May 	d->pack_cnt            = NULL;
124095059a4SDave May 
125095059a4SDave May 	d->send_tags = NULL;
126095059a4SDave May 	d->recv_tags = NULL;
127095059a4SDave May 
128095059a4SDave May 	d->_stats    = NULL;
129095059a4SDave May 	d->_requests = NULL;
130095059a4SDave May 
131095059a4SDave May 	return d;
132095059a4SDave May }
133095059a4SDave May 
134095059a4SDave May #undef __FUNCT__
135095059a4SDave May #define __FUNCT__ "DataExView"
136095059a4SDave May PetscErrorCode DataExView(DataEx d)
137095059a4SDave May {
138095059a4SDave May 	PetscMPIInt p;
139095059a4SDave May 
140095059a4SDave May 
141095059a4SDave May 	PetscFunctionBegin;
142095059a4SDave May 	PetscPrintf( PETSC_COMM_WORLD, "DataEx: instance=%D\n",d->instance);
143095059a4SDave May 
144095059a4SDave May 	PetscPrintf( PETSC_COMM_WORLD, "  topology status:        %s \n", status_names[d->topology_status]);
145095059a4SDave May 	PetscPrintf( PETSC_COMM_WORLD, "  message lengths status: %s \n", status_names[d->message_lengths_status] );
146095059a4SDave May 	PetscPrintf( PETSC_COMM_WORLD, "  packer status status:   %s \n", status_names[d->packer_status] );
147095059a4SDave May 	PetscPrintf( PETSC_COMM_WORLD, "  communication status:   %s \n", status_names[d->communication_status] );
148095059a4SDave May 
149095059a4SDave May 	if (d->topology_status == DEOBJECT_FINALIZED) {
150095059a4SDave May 		PetscPrintf( PETSC_COMM_WORLD, "  Topology:\n");
151095059a4SDave May 		PetscPrintf( PETSC_COMM_SELF, "    [%d] neighbours: %d \n", (int)d->rank, (int)d->n_neighbour_procs );
152095059a4SDave May 		for (p=0; p<d->n_neighbour_procs; p++) {
153095059a4SDave May 			PetscPrintf( PETSC_COMM_SELF, "    [%d]   neighbour[%D] = %d \n", (int)d->rank, p, (int)d->neighbour_procs[p]);
154095059a4SDave May 		}
155095059a4SDave May 	}
156095059a4SDave May 
157095059a4SDave May 	if (d->message_lengths_status == DEOBJECT_FINALIZED) {
158095059a4SDave May 		PetscPrintf( PETSC_COMM_WORLD, "  Message lengths:\n");
159095059a4SDave May 		PetscPrintf( PETSC_COMM_SELF, "    [%d] atomic size: %ld \n", (int)d->rank, (long int)d->unit_message_size );
160095059a4SDave May 		for (p=0; p<d->n_neighbour_procs; p++) {
161095059a4SDave May 			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] );
162095059a4SDave May 		}
163095059a4SDave May 		for (p=0; p<d->n_neighbour_procs; p++) {
164095059a4SDave May 			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] );
165095059a4SDave May 		}
166095059a4SDave May 	}
167095059a4SDave May 
168095059a4SDave May 	if (d->packer_status == DEOBJECT_FINALIZED) {
169095059a4SDave May 
170095059a4SDave May 	}
171095059a4SDave May 
172095059a4SDave May 	if (d->communication_status == DEOBJECT_FINALIZED) {
173095059a4SDave May 
174095059a4SDave May 	}
175095059a4SDave May 
176095059a4SDave May 	PetscFunctionReturn(0);
177095059a4SDave May }
178095059a4SDave May 
179095059a4SDave May #undef __FUNCT__
180095059a4SDave May #define __FUNCT__ "DataExDestroy"
181095059a4SDave May PetscErrorCode DataExDestroy(DataEx d)
182095059a4SDave May {
183095059a4SDave May 	PetscErrorCode ierr;
184095059a4SDave May 
185095059a4SDave May 	PetscFunctionBegin;
186095059a4SDave May 	ierr = MPI_Comm_free(&d->comm);CHKERRQ(ierr);
187095059a4SDave May 
188095059a4SDave May 	if (d->neighbour_procs != NULL) {
189095059a4SDave May 		free(d->neighbour_procs);
190095059a4SDave May 	}
191095059a4SDave May 
192095059a4SDave May 	if (d->messages_to_be_sent != NULL) {
193095059a4SDave May 		free(d->messages_to_be_sent);
194095059a4SDave May 	}
195095059a4SDave May 
196095059a4SDave May 	if (d->message_offsets != NULL) {
197095059a4SDave May 		free(d->message_offsets);
198095059a4SDave May 	}
199095059a4SDave May 
200095059a4SDave May 	if (d->messages_to_be_recvieved != NULL) {
201095059a4SDave May 		free(d->messages_to_be_recvieved);
202095059a4SDave May 	}
203095059a4SDave May 
204095059a4SDave May 	if (d->send_message != NULL) {
205095059a4SDave May 		free(d->send_message);
206095059a4SDave May 	}
207095059a4SDave May 
208095059a4SDave May 	if (d->recv_message != NULL) {
209095059a4SDave May 		free(d->recv_message);
210095059a4SDave May 	}
211095059a4SDave May 
212095059a4SDave May 	if (d->pack_cnt != NULL) {
213095059a4SDave May 		free(d->pack_cnt);
214095059a4SDave May 	}
215095059a4SDave May 
216095059a4SDave May 	if (d->send_tags != NULL) {
217095059a4SDave May 		free(d->send_tags);
218095059a4SDave May 	}
219095059a4SDave May 	if (d->recv_tags != NULL) {
220095059a4SDave May 		free(d->recv_tags);
221095059a4SDave May 	}
222095059a4SDave May 
223095059a4SDave May 	if (d->_stats != NULL) {
224095059a4SDave May 		free(d->_stats);
225095059a4SDave May 	}
226095059a4SDave May 	if (d->_requests != NULL) {
227095059a4SDave May 		free(d->_requests);
228095059a4SDave May 	}
229095059a4SDave May 
230095059a4SDave May 	free(d);
231095059a4SDave May 
232095059a4SDave May 	PetscFunctionReturn(0);
233095059a4SDave May }
234095059a4SDave May 
235095059a4SDave May /* === Phase A === */
236095059a4SDave May 
237095059a4SDave May #undef __FUNCT__
238095059a4SDave May #define __FUNCT__ "DataExTopologyInitialize"
239095059a4SDave May PetscErrorCode DataExTopologyInitialize(DataEx d)
240095059a4SDave May {
241095059a4SDave May 	PetscFunctionBegin;
242095059a4SDave May 	d->topology_status = DEOBJECT_INITIALIZED;
243095059a4SDave May 
244095059a4SDave May 	d->n_neighbour_procs = 0;
245095059a4SDave May 	if (d->neighbour_procs          != NULL)  {  free(d->neighbour_procs);            d->neighbour_procs          = NULL;  }
246095059a4SDave May 	if (d->messages_to_be_sent      != NULL)  {  free(d->messages_to_be_sent);        d->messages_to_be_sent      = NULL;  }
247095059a4SDave May 	if (d->message_offsets          != NULL)  {  free(d->message_offsets);            d->message_offsets          = NULL;  }
248095059a4SDave May 	if (d->messages_to_be_recvieved != NULL)  {  free(d->messages_to_be_recvieved);   d->messages_to_be_recvieved = NULL;  }
249095059a4SDave May 	if (d->pack_cnt                 != NULL)  {  free(d->pack_cnt);                   d->pack_cnt                 = NULL;  }
250095059a4SDave May 
251095059a4SDave May 	if (d->send_tags != NULL)                 {  free(d->send_tags);                  d->send_tags = NULL;  }
252095059a4SDave May 	if (d->recv_tags != NULL)                 {  free(d->recv_tags);                  d->recv_tags = NULL;  }
253095059a4SDave May 
254095059a4SDave May 	PetscFunctionReturn(0);
255095059a4SDave May }
256095059a4SDave May 
257095059a4SDave May #undef __FUNCT__
258095059a4SDave May #define __FUNCT__ "DataExTopologyAddNeighbour"
259095059a4SDave May PetscErrorCode DataExTopologyAddNeighbour(DataEx d,const PetscMPIInt proc_id)
260095059a4SDave May {
261095059a4SDave May 	PetscMPIInt    n,found;
262095059a4SDave May 	PetscMPIInt    nproc;
263095059a4SDave May 	PetscErrorCode ierr;
264095059a4SDave May 
265095059a4SDave May 
266095059a4SDave May 	PetscFunctionBegin;
267095059a4SDave May 	if (d->topology_status == DEOBJECT_FINALIZED) {
268095059a4SDave May 		SETERRQ( d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology has been finalized. To modify or update call DataExTopologyInitialize() first" );
269095059a4SDave May 	}
270095059a4SDave May 	else if (d->topology_status != DEOBJECT_INITIALIZED) {
271095059a4SDave May 		SETERRQ( d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be intialised. Call DataExTopologyInitialize() first" );
272095059a4SDave May 	}
273095059a4SDave May 
274095059a4SDave May 	/* error on negative entries */
275095059a4SDave May 	if (proc_id < 0) {
276095059a4SDave May 		SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Trying to set proc neighbour with a rank < 0");
277095059a4SDave May 	}
278095059a4SDave May 	/* error on ranks larger than number of procs in communicator */
279095059a4SDave May 	ierr = MPI_Comm_size(d->comm,&nproc);CHKERRQ(ierr);
280095059a4SDave May 	if (proc_id >= nproc) {
281095059a4SDave May 		SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONGSTATE,"Trying to set proc neighbour with a rank >= nproc");
282095059a4SDave May 	}
283095059a4SDave May 
284095059a4SDave May 	if (d->n_neighbour_procs == 0) {
285095059a4SDave May 		d->neighbour_procs = (PetscMPIInt*)malloc( sizeof(PetscMPIInt) );
286095059a4SDave May 	}
287095059a4SDave May 
288095059a4SDave May 	/* check for proc_id */
289095059a4SDave May 	found = 0;
290095059a4SDave May 	for (n=0; n<d->n_neighbour_procs; n++) {
291095059a4SDave May 		if (d->neighbour_procs[n] == proc_id) {
292095059a4SDave May 			found  = 1;
293095059a4SDave May 		}
294095059a4SDave May 	}
295095059a4SDave May 	if (found == 0) { /* add it to list */
296095059a4SDave May 		PetscMPIInt *tmp;
297095059a4SDave May 
298095059a4SDave May 		tmp = (PetscMPIInt*)realloc( d->neighbour_procs, sizeof(PetscMPIInt)*(d->n_neighbour_procs+1) );
299095059a4SDave May 		d->neighbour_procs = tmp;
300095059a4SDave May 
301095059a4SDave May 		d->neighbour_procs[ d->n_neighbour_procs ] = proc_id;
302095059a4SDave May 		d->n_neighbour_procs++;
303095059a4SDave May 	}
304095059a4SDave May 
305095059a4SDave May 	PetscFunctionReturn(0);
306095059a4SDave May }
307095059a4SDave May 
308095059a4SDave May /*
309095059a4SDave May counter: the index of the communication object
310095059a4SDave May N: the number of processors
311095059a4SDave May r0: rank of sender
312095059a4SDave May r1: rank of receiver
313095059a4SDave May 
314095059a4SDave May procs = { 0, 1, 2, 3 }
315095059a4SDave May 
316095059a4SDave May 0 ==> 0		e=0
317095059a4SDave May 0 ==> 1		e=1
318095059a4SDave May 0 ==> 2		e=2
319095059a4SDave May 0 ==> 3		e=3
320095059a4SDave May 
321095059a4SDave May 1 ==> 0		e=4
322095059a4SDave May 1 ==> 1		e=5
323095059a4SDave May 1 ==> 2		e=6
324095059a4SDave May 1 ==> 3		e=7
325095059a4SDave May 
326095059a4SDave May 2 ==> 0		e=8
327095059a4SDave May 2 ==> 1		e=9
328095059a4SDave May 2 ==> 2		e=10
329095059a4SDave May 2 ==> 3		e=11
330095059a4SDave May 
331095059a4SDave May 3 ==> 0		e=12
332095059a4SDave May 3 ==> 1		e=13
333095059a4SDave May 3 ==> 2		e=14
334095059a4SDave May 3 ==> 3		e=15
335095059a4SDave May 
336095059a4SDave May If we require that proc A sends to proc B, then the SEND tag index will be given by
337095059a4SDave May   N * rank(A) + rank(B) + offset
338095059a4SDave May If we require that proc A will receive from proc B, then the RECV tag index will be given by
339095059a4SDave May   N * rank(B) + rank(A) + offset
340095059a4SDave May 
341095059a4SDave May */
342095059a4SDave May void _get_tags( PetscInt counter, PetscMPIInt N, PetscMPIInt r0,PetscMPIInt r1, PetscMPIInt *_st, PetscMPIInt *_rt )
343095059a4SDave May {
344095059a4SDave May 	PetscMPIInt st,rt;
345095059a4SDave May 
346095059a4SDave May 
347095059a4SDave May 	st = N*r0 + r1   +   N*N*counter;
348095059a4SDave May 	rt = N*r1 + r0   +   N*N*counter;
349095059a4SDave May 
350095059a4SDave May 	*_st = st;
351095059a4SDave May 	*_rt = rt;
352095059a4SDave May }
353095059a4SDave May 
354095059a4SDave May /*
355095059a4SDave May Makes the communication map symmetric
356095059a4SDave May */
357095059a4SDave May #undef __FUNCT__
358095059a4SDave May #define __FUNCT__ "_DataExCompleteCommunicationMap"
359095059a4SDave May PetscErrorCode _DataExCompleteCommunicationMap(MPI_Comm comm,PetscMPIInt n,PetscMPIInt proc_neighbours[],PetscMPIInt *n_new,PetscMPIInt **proc_neighbours_new)
360095059a4SDave May {
361*dcf43ee8SDave May 	Mat               A;
362095059a4SDave May 	PetscInt          i,j,nc;
363095059a4SDave May 	PetscInt          n_, *proc_neighbours_;
364095059a4SDave May   PetscInt          rank_i_;
365095059a4SDave May 	PetscMPIInt       size,  rank_i;
366095059a4SDave May 	PetscScalar       *vals;
367095059a4SDave May 	const PetscInt    *cols;
368095059a4SDave May 	const PetscScalar *red_vals;
369095059a4SDave May 	PetscMPIInt       _n_new, *_proc_neighbours_new;
370095059a4SDave May 	PetscLogDouble    t0,t1;
371095059a4SDave May 	PetscErrorCode    ierr;
372095059a4SDave May 
373095059a4SDave May 
374095059a4SDave May 	PetscFunctionBegin;
375*dcf43ee8SDave May 	PetscPrintf(PETSC_COMM_WORLD,"*** Starting _DataExCompleteCommunicationMap *** \n");
376095059a4SDave May 	PetscTime(&t0);
377095059a4SDave May 
378095059a4SDave May 	n_ = n;
379095059a4SDave May 	ierr = PetscMalloc( sizeof(PetscInt) * n_, &proc_neighbours_ );CHKERRQ(ierr);
380095059a4SDave May 	for (i=0; i<n_; i++) {
381095059a4SDave May 		proc_neighbours_[i] = proc_neighbours[i];
382095059a4SDave May 	}
383095059a4SDave May 
384095059a4SDave May 	ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
385095059a4SDave May 	ierr = MPI_Comm_rank(comm,&rank_i);CHKERRQ(ierr);
386095059a4SDave May 	rank_i_ = rank_i;
387095059a4SDave May 
388095059a4SDave May 	ierr = MatCreate(comm,&A);CHKERRQ(ierr);
389095059a4SDave May 	ierr = MatSetSizes(A,PETSC_DECIDE,PETSC_DECIDE,size,size);CHKERRQ(ierr);
390095059a4SDave May 	ierr = MatSetType(A,MATAIJ);CHKERRQ(ierr);
391095059a4SDave May 
392*dcf43ee8SDave May 	ierr = MatSeqAIJSetPreallocation(A,1,NULL);CHKERRQ(ierr);
393*dcf43ee8SDave May   ierr = MatMPIAIJSetPreallocation(A,n_,NULL,n_,NULL);CHKERRQ(ierr);
394095059a4SDave May 
395*dcf43ee8SDave May   ierr = MatSetOption(A, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);CHKERRQ(ierr);
396095059a4SDave May 
397095059a4SDave May 	/* Build original map */
398095059a4SDave May 	ierr = PetscMalloc( sizeof(PetscScalar)*n_, &vals );CHKERRQ(ierr);
399095059a4SDave May 	for (i=0; i<n_; i++) {
400095059a4SDave May 		vals[i] = 1.0;
401095059a4SDave May 	}
402095059a4SDave May 	ierr = MatSetValues( A, 1,&rank_i_, n_,proc_neighbours_, vals, INSERT_VALUES );CHKERRQ(ierr);
403095059a4SDave May 
404095059a4SDave May 	ierr = MatAssemblyBegin(A,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
405095059a4SDave May 	ierr = MatAssemblyEnd(A,MAT_FLUSH_ASSEMBLY);CHKERRQ(ierr);
406095059a4SDave May 
407095059a4SDave May 	/* Now force all other connections if they are not already there */
408095059a4SDave May 	/* It's more efficient to do them all at once */
409095059a4SDave May 	for (i=0; i<n_; i++) {
410095059a4SDave May 		vals[i] = 2.0;
411095059a4SDave May 	}
412095059a4SDave May 	ierr = MatSetValues( A, n_,proc_neighbours_, 1,&rank_i_, vals, INSERT_VALUES );CHKERRQ(ierr);
413095059a4SDave May 
414095059a4SDave May 	ierr = MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
415095059a4SDave May 	ierr = MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
416095059a4SDave May 
417095059a4SDave May 	ierr = PetscViewerPushFormat(PETSC_VIEWER_STDOUT_WORLD,PETSC_VIEWER_ASCII_INFO);CHKERRQ(ierr);
418095059a4SDave May 	ierr = MatView(A,PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
419095059a4SDave May   ierr = PetscViewerPopFormat(PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr);
420095059a4SDave May 
421095059a4SDave May 	if ((n_new != NULL) && (proc_neighbours_new != NULL)) {
422095059a4SDave May 
423*dcf43ee8SDave May 		ierr = MatGetRow( A, rank_i_, &nc, &cols, &red_vals );CHKERRQ(ierr);
424095059a4SDave May 
425095059a4SDave May 		_n_new = (PetscMPIInt)nc;
426095059a4SDave May 		_proc_neighbours_new = (PetscMPIInt*)malloc( sizeof(PetscMPIInt) * _n_new );
427095059a4SDave May 
428095059a4SDave May 		for (j=0; j<nc; j++) {
429095059a4SDave May 			_proc_neighbours_new[j] = (PetscMPIInt)cols[j];
430095059a4SDave May 		}
431*dcf43ee8SDave May 		ierr = MatRestoreRow( A, rank_i_, &nc, &cols, &red_vals );CHKERRQ(ierr);
432095059a4SDave May 
433095059a4SDave May 		*n_new               = (PetscMPIInt)_n_new;
434095059a4SDave May 		*proc_neighbours_new = (PetscMPIInt*)_proc_neighbours_new;
435095059a4SDave May 	}
436095059a4SDave May 
437095059a4SDave May 	ierr = MatDestroy(&A);CHKERRQ(ierr);
438095059a4SDave May 	ierr = PetscFree(vals);CHKERRQ(ierr);
439095059a4SDave May 	ierr = PetscFree(proc_neighbours_);CHKERRQ(ierr);
440095059a4SDave May 
441095059a4SDave May 	ierr = MPI_Barrier(comm);CHKERRQ(ierr);
442095059a4SDave May 	PetscTime(&t1);
443*dcf43ee8SDave May 	PetscPrintf(PETSC_COMM_WORLD,"*** Ending _DataExCompleteCommunicationMap [setup time: %1.4e (sec)] *** \n",t1-t0);
444095059a4SDave May 
445095059a4SDave May 	PetscFunctionReturn(0);
446095059a4SDave May }
447095059a4SDave May 
448095059a4SDave May #undef __FUNCT__
449095059a4SDave May #define __FUNCT__ "DataExTopologyFinalize"
450095059a4SDave May PetscErrorCode DataExTopologyFinalize(DataEx d)
451095059a4SDave May {
452095059a4SDave May 	PetscMPIInt    symm_nn;
453095059a4SDave May 	PetscMPIInt   *symm_procs;
454095059a4SDave May 	PetscMPIInt    r0,n,st,rt;
455095059a4SDave May 	PetscMPIInt    nprocs;
456095059a4SDave May 	PetscErrorCode ierr;
457095059a4SDave May 
458095059a4SDave May 
459095059a4SDave May 	PetscFunctionBegin;
460095059a4SDave May 	if (d->topology_status != DEOBJECT_INITIALIZED) {
461095059a4SDave May 		SETERRQ( d->comm, PETSC_ERR_ARG_WRONGSTATE, "Topology must be intialised. Call DataExTopologyInitialize() first" );
462095059a4SDave May 	}
463095059a4SDave May 	ierr = PetscLogEventBegin(PTATIN_DataExchangerTopologySetup,0,0,0,0);CHKERRQ(ierr);
464095059a4SDave May 
465095059a4SDave May 	/* given infomation about all my neighbours, make map symmetric */
466095059a4SDave May 	ierr = _DataExCompleteCommunicationMap( d->comm,d->n_neighbour_procs,d->neighbour_procs, &symm_nn, &symm_procs );CHKERRQ(ierr);
467095059a4SDave May 	/* update my arrays */
468095059a4SDave May 	free(d->neighbour_procs);
469095059a4SDave May 
470095059a4SDave May 	d->n_neighbour_procs = symm_nn;
471095059a4SDave May 	d->neighbour_procs   = symm_procs;
472095059a4SDave May 
473095059a4SDave May 
474095059a4SDave May 	/* allocates memory */
475095059a4SDave May 	if (d->messages_to_be_sent == NULL) {
476095059a4SDave May 		d->messages_to_be_sent = (PetscInt*)malloc( sizeof(PetscInt) * d->n_neighbour_procs );
477095059a4SDave May 	}
478095059a4SDave May 	if (d->message_offsets == NULL) {
479095059a4SDave May 		d->message_offsets = (PetscInt*)malloc( sizeof(PetscInt) * d->n_neighbour_procs );
480095059a4SDave May 	}
481095059a4SDave May 	if (d->messages_to_be_recvieved == NULL) {
482095059a4SDave May 		d->messages_to_be_recvieved = (PetscInt*)malloc( sizeof(PetscInt) * d->n_neighbour_procs );
483095059a4SDave May 	}
484095059a4SDave May 
485095059a4SDave May 	if (d->pack_cnt == NULL) {
486095059a4SDave May 		d->pack_cnt = (PetscInt*)malloc( sizeof(PetscInt) * d->n_neighbour_procs );
487095059a4SDave May 	}
488095059a4SDave May 
489095059a4SDave May 	if (d->_stats == NULL) {
490095059a4SDave May 		d->_stats = (MPI_Status*)malloc( sizeof(MPI_Status) * 2*d->n_neighbour_procs );
491095059a4SDave May 	}
492095059a4SDave May 	if (d->_requests == NULL) {
493095059a4SDave May 		d->_requests = (MPI_Request*)malloc( sizeof(MPI_Request) * 2*d->n_neighbour_procs );
494095059a4SDave May 	}
495095059a4SDave May 
496095059a4SDave May 	if (d->send_tags == NULL) {
497095059a4SDave May 		d->send_tags = (int*)malloc( sizeof(int) * d->n_neighbour_procs );
498095059a4SDave May 	}
499095059a4SDave May 	if (d->recv_tags == NULL) {
500095059a4SDave May 		d->recv_tags = (int*)malloc( sizeof(int) * d->n_neighbour_procs );
501095059a4SDave May 	}
502095059a4SDave May 
503095059a4SDave May 	/* compute message tags */
504095059a4SDave May 	ierr = MPI_Comm_size(d->comm,&nprocs);CHKERRQ(ierr);
505095059a4SDave May 	r0 = d->rank;
506095059a4SDave May 	for (n=0; n<d->n_neighbour_procs; n++) {
507095059a4SDave May 		PetscMPIInt r1 = d->neighbour_procs[n];
508095059a4SDave May 
509095059a4SDave May 		_get_tags( d->instance, nprocs, r0,r1, &st, &rt );
510095059a4SDave May 
511095059a4SDave May 		d->send_tags[n] = (int)st;
512095059a4SDave May 		d->recv_tags[n] = (int)rt;
513095059a4SDave May 	}
514095059a4SDave May 
515095059a4SDave May 	d->topology_status = DEOBJECT_FINALIZED;
516095059a4SDave May 	ierr = PetscLogEventEnd(PTATIN_DataExchangerTopologySetup,0,0,0,0);CHKERRQ(ierr);
517095059a4SDave May 
518095059a4SDave May 	PetscFunctionReturn(0);
519095059a4SDave May }
520095059a4SDave May 
521095059a4SDave May /* === Phase B === */
522095059a4SDave May #undef __FUNCT__
523095059a4SDave May #define __FUNCT__ "_DataExConvertProcIdToLocalIndex"
524095059a4SDave May PetscErrorCode _DataExConvertProcIdToLocalIndex(DataEx de,PetscMPIInt proc_id,PetscMPIInt *local)
525095059a4SDave May {
526095059a4SDave May 	PetscMPIInt i,np;
527095059a4SDave May 
528095059a4SDave May 
529095059a4SDave May 	PetscFunctionBegin;
530095059a4SDave May 	np = de->n_neighbour_procs;
531095059a4SDave May 
532095059a4SDave May 	*local = -1;
533095059a4SDave May 	for (i=0; i<np; i++) {
534095059a4SDave May 		if (proc_id == de->neighbour_procs[i]) {
535095059a4SDave May 			*local = i;
536095059a4SDave May 			break;
537095059a4SDave May 		}
538095059a4SDave May 	}
539095059a4SDave May 	PetscFunctionReturn(0);
540095059a4SDave May }
541095059a4SDave May 
542095059a4SDave May #undef __FUNCT__
543095059a4SDave May #define __FUNCT__ "DataExInitializeSendCount"
544095059a4SDave May PetscErrorCode DataExInitializeSendCount(DataEx de)
545095059a4SDave May {
546095059a4SDave May 	PetscMPIInt i;
547095059a4SDave May 
548095059a4SDave May 
549095059a4SDave May 	PetscFunctionBegin;
550095059a4SDave May 	if (de->topology_status != DEOBJECT_FINALIZED) {
551095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ORDER, "Topology not finalized" );
552095059a4SDave May 	}
553095059a4SDave May 
554095059a4SDave May 	de->message_lengths_status = DEOBJECT_INITIALIZED;
555095059a4SDave May 
556095059a4SDave May 	for (i=0; i<de->n_neighbour_procs; i++) {
557095059a4SDave May 		de->messages_to_be_sent[i] = 0;
558095059a4SDave May 	}
559095059a4SDave May 
560095059a4SDave May 	PetscFunctionReturn(0);
561095059a4SDave May }
562095059a4SDave May 
563095059a4SDave May /*
564095059a4SDave May 1) only allows counters to be set on neighbouring cpus
565095059a4SDave May */
566095059a4SDave May #undef __FUNCT__
567095059a4SDave May #define __FUNCT__ "DataExAddToSendCount"
568095059a4SDave May PetscErrorCode DataExAddToSendCount(DataEx de,const PetscMPIInt proc_id,const PetscInt count)
569095059a4SDave May {
570095059a4SDave May 	PetscMPIInt    local_val;
571095059a4SDave May 	PetscErrorCode ierr;
572095059a4SDave May 
573095059a4SDave May 
574095059a4SDave May 	PetscFunctionBegin;
575095059a4SDave May 	if (de->message_lengths_status == DEOBJECT_FINALIZED) {
576095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths have been defined. To modify these call DataExInitializeSendCount() first" );
577095059a4SDave May 	}
578095059a4SDave May 	else if (de->message_lengths_status != DEOBJECT_INITIALIZED) {
579095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DataExInitializeSendCount() first" );
580095059a4SDave May 	}
581095059a4SDave May 
582095059a4SDave May 	ierr = _DataExConvertProcIdToLocalIndex( de, proc_id, &local_val );CHKERRQ(ierr);
583095059a4SDave May 	if (local_val == -1) {
584095059a4SDave May 		SETERRQ1( PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,"Proc %d is not a valid neighbour rank", (int)proc_id );
585095059a4SDave May 	}
586095059a4SDave May 
587095059a4SDave May 	de->messages_to_be_sent[local_val] = de->messages_to_be_sent[local_val] + count;
588095059a4SDave May 	PetscFunctionReturn(0);
589095059a4SDave May }
590095059a4SDave May 
591095059a4SDave May #undef __FUNCT__
592095059a4SDave May #define __FUNCT__ "DataExFinalizeSendCount"
593095059a4SDave May PetscErrorCode DataExFinalizeSendCount(DataEx de)
594095059a4SDave May {
595095059a4SDave May 	PetscFunctionBegin;
596095059a4SDave May 	if (de->message_lengths_status != DEOBJECT_INITIALIZED) {
597095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths must be defined. Call DataExInitializeSendCount() first" );
598095059a4SDave May 	}
599095059a4SDave May 	de->message_lengths_status = DEOBJECT_FINALIZED;
600095059a4SDave May 
601095059a4SDave May 	PetscFunctionReturn(0);
602095059a4SDave May }
603095059a4SDave May 
604095059a4SDave May /* === Phase C === */
605095059a4SDave May /*
606095059a4SDave May  * zero out all send counts
607095059a4SDave May  * free send and recv buffers
608095059a4SDave May  * zeros out message length
609095059a4SDave May  * zeros out all counters
610095059a4SDave May  * zero out packed data counters
611095059a4SDave May */
612095059a4SDave May #undef __FUNCT__
613095059a4SDave May #define __FUNCT__ "_DataExInitializeTmpStorage"
614095059a4SDave May PetscErrorCode _DataExInitializeTmpStorage(DataEx de)
615095059a4SDave May {
616095059a4SDave May 	PetscMPIInt i,np;
617095059a4SDave May 
618095059a4SDave May 
619095059a4SDave May 	PetscFunctionBegin;
620095059a4SDave May 	if (de->n_neighbour_procs < 0) {
621095059a4SDave May 		SETERRQ( PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Number of neighbour procs < 0");
622095059a4SDave May 	}
623095059a4SDave May 	if (de->neighbour_procs == NULL) {
624095059a4SDave May 		SETERRQ( PETSC_COMM_SELF, PETSC_ERR_ARG_NULL, "Neighbour proc list is NULL" );
625095059a4SDave May 	}
626095059a4SDave May 
627095059a4SDave May 	np = de->n_neighbour_procs;
628095059a4SDave May 	for (i=0; i<np; i++) {
629095059a4SDave May 	/*	de->messages_to_be_sent[i] = -1; */
630095059a4SDave May 		de->messages_to_be_recvieved[i] = -1;
631095059a4SDave May 	}
632095059a4SDave May 
633095059a4SDave May 	if (de->send_message != NULL) {
634095059a4SDave May 		free(de->send_message);
635095059a4SDave May 		de->send_message = NULL;
636095059a4SDave May 	}
637095059a4SDave May 	if (de->recv_message != NULL) {
638095059a4SDave May 		free(de->recv_message);
639095059a4SDave May 		de->recv_message = NULL;
640095059a4SDave May 	}
641095059a4SDave May 
642095059a4SDave May 	PetscFunctionReturn(0);
643095059a4SDave May }
644095059a4SDave May 
645095059a4SDave May /*
646095059a4SDave May *) Zeros out pack data counters
647095059a4SDave May *) Ensures mesaage length is set
648095059a4SDave May *) Checks send counts properly initialized
649095059a4SDave May *) allocates space for pack data
650095059a4SDave May */
651095059a4SDave May #undef __FUNCT__
652095059a4SDave May #define __FUNCT__ "DataExPackInitialize"
653095059a4SDave May PetscErrorCode DataExPackInitialize(DataEx de,size_t unit_message_size)
654095059a4SDave May {
655095059a4SDave May 	PetscMPIInt    i,np;
656095059a4SDave May 	PetscInt       total;
657095059a4SDave May 	PetscErrorCode ierr;
658095059a4SDave May 
659095059a4SDave May 
660095059a4SDave May 	PetscFunctionBegin;
661095059a4SDave May 	if (de->topology_status != DEOBJECT_FINALIZED) {
662095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ORDER, "Topology not finalized" );
663095059a4SDave May 	}
664095059a4SDave May 	if (de->message_lengths_status != DEOBJECT_FINALIZED) {
665095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths not finalized" );
666095059a4SDave May 	}
667095059a4SDave May 
668095059a4SDave May 	de->packer_status = DEOBJECT_INITIALIZED;
669095059a4SDave May 
670095059a4SDave May 	ierr = _DataExInitializeTmpStorage(de);CHKERRQ(ierr);
671095059a4SDave May 
672095059a4SDave May 	np = de->n_neighbour_procs;
673095059a4SDave May 
674095059a4SDave May 	de->unit_message_size = unit_message_size;
675095059a4SDave May 
676095059a4SDave May 	total = 0;
677095059a4SDave May 	for (i=0; i<np; i++) {
678095059a4SDave May 		if (de->messages_to_be_sent[i] == -1) {
679095059a4SDave May 			PetscMPIInt proc_neighour = de->neighbour_procs[i];
680095059a4SDave May 			SETERRQ1( PETSC_COMM_SELF, PETSC_ERR_ORDER, "Messages_to_be_sent[neighbour_proc=%d] is un-initialised. Call DataExSetSendCount() first", (int)proc_neighour );
681095059a4SDave May 		}
682095059a4SDave May 		total = total + de->messages_to_be_sent[i];
683095059a4SDave May 	}
684095059a4SDave May 
685095059a4SDave May 	/* create space for the data to be sent */
686095059a4SDave May 	de->send_message = (void*)malloc( unit_message_size * (total + 1) );
687095059a4SDave May 	/* initialize memory */
688095059a4SDave May 	memset( de->send_message, 0, unit_message_size * (total + 1) );
689095059a4SDave May 	/* set total items to send */
690095059a4SDave May 	de->send_message_length = total;
691095059a4SDave May 
692095059a4SDave May 	de->message_offsets[0] = 0;
693095059a4SDave May 	total = de->messages_to_be_sent[0];
694095059a4SDave May 	for (i=1; i<np; i++) {
695095059a4SDave May 		de->message_offsets[i] = total;
696095059a4SDave May 		total = total + de->messages_to_be_sent[i];
697095059a4SDave May 	}
698095059a4SDave May 
699095059a4SDave May 	/* init the packer counters */
700095059a4SDave May 	de->total_pack_cnt = 0;
701095059a4SDave May 	for (i=0; i<np; i++) {
702095059a4SDave May 		de->pack_cnt[i] = 0;
703095059a4SDave May 	}
704095059a4SDave May 
705095059a4SDave May 	PetscFunctionReturn(0);
706095059a4SDave May }
707095059a4SDave May 
708095059a4SDave May /*
709095059a4SDave May *) Ensures data gets been packed appropriately and no overlaps occur
710095059a4SDave May */
711095059a4SDave May #undef __FUNCT__
712095059a4SDave May #define __FUNCT__ "DataExPackData"
713095059a4SDave May PetscErrorCode DataExPackData(DataEx de,PetscMPIInt proc_id,PetscInt n,void *data)
714095059a4SDave May {
715095059a4SDave May 	PetscMPIInt    local;
716095059a4SDave May 	PetscInt       insert_location;
717095059a4SDave May 	void           *dest;
718095059a4SDave May 	PetscErrorCode ierr;
719095059a4SDave May 
720095059a4SDave May 
721095059a4SDave May 	PetscFunctionBegin;
722095059a4SDave May 	if (de->packer_status == DEOBJECT_FINALIZED) {
723095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ORDER, "Packed data have been defined. To modify these call DataExInitializeSendCount(), DataExAddToSendCount(), DataExPackInitialize() first" );
724095059a4SDave May 	}
725095059a4SDave May 	else if (de->packer_status != DEOBJECT_INITIALIZED) {
726095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ORDER, "Packed data must be defined. Call DataExInitializeSendCount(), DataExAddToSendCount(), DataExPackInitialize() first" );
727095059a4SDave May 	}
728095059a4SDave May 
729095059a4SDave May 
730095059a4SDave May 	if (de->send_message == NULL){
731095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ORDER, "send_message is not initialized. Call DataExPackInitialize() first" );
732095059a4SDave May 	}
733095059a4SDave May 
734095059a4SDave May 
735095059a4SDave May 	ierr = _DataExConvertProcIdToLocalIndex( de, proc_id, &local );CHKERRQ(ierr);
736095059a4SDave May 	if (local == -1) {
737095059a4SDave May 		SETERRQ1( PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "proc_id %d is not registered neighbour", (int)proc_id );
738095059a4SDave May 	}
739095059a4SDave May 
740095059a4SDave May 	if (n+de->pack_cnt[local] > de->messages_to_be_sent[local]) {
741095059a4SDave May 		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",
742095059a4SDave May 				(int)proc_id, de->messages_to_be_sent[local], n+de->pack_cnt[local] );
743095059a4SDave May 
744095059a4SDave May 		/* don't need this - the catch for too many messages will pick this up. Gives us more info though */
745095059a4SDave May 		if (de->packer_status == DEOBJECT_FINALIZED) {
746095059a4SDave May 			SETERRQ( de->comm, PETSC_ERR_ARG_WRONG, "Cannot insert any more data. DataExPackFinalize() has been called." );
747095059a4SDave May 		}
748095059a4SDave May 	}
749095059a4SDave May 
750095059a4SDave May 	/* copy memory */
751095059a4SDave May 	insert_location = de->message_offsets[local] + de->pack_cnt[local];
752095059a4SDave May 	dest = ((char*)de->send_message) + de->unit_message_size*insert_location;
753095059a4SDave May 	memcpy( dest, data, de->unit_message_size * n );
754095059a4SDave May 
755095059a4SDave May 	/* increment counter */
756095059a4SDave May 	de->pack_cnt[local] = de->pack_cnt[local] + n;
757095059a4SDave May 
758095059a4SDave May 	PetscFunctionReturn(0);
759095059a4SDave May }
760095059a4SDave May 
761095059a4SDave May /*
762095059a4SDave May *) Ensures all data has been packed
763095059a4SDave May */
764095059a4SDave May #undef __FUNCT__
765095059a4SDave May #define __FUNCT__ "DataExPackFinalize"
766095059a4SDave May PetscErrorCode DataExPackFinalize(DataEx de)
767095059a4SDave May {
768095059a4SDave May 	PetscMPIInt i,np;
769095059a4SDave May 	PetscInt    total;
770095059a4SDave May 	PetscErrorCode ierr;
771095059a4SDave May 
772095059a4SDave May 
773095059a4SDave May 	PetscFunctionBegin;
774095059a4SDave May 	if (de->packer_status != DEOBJECT_INITIALIZED) {
775095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ORDER, "Packer has not been initialized. Must call DataExPackInitialize() first." );
776095059a4SDave May 	}
777095059a4SDave May 
778095059a4SDave May 	np = de->n_neighbour_procs;
779095059a4SDave May 
780095059a4SDave May 	for (i=0; i<np; i++) {
781095059a4SDave May 		if (de->pack_cnt[i] != de->messages_to_be_sent[i]) {
782095059a4SDave May 			SETERRQ3( PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "Not all messages for neighbour[%d] have been packed. Expected %D : Inserted %D",
783095059a4SDave May 					(int)de->neighbour_procs[i], de->messages_to_be_sent[i], de->pack_cnt[i] );
784095059a4SDave May 		}
785095059a4SDave May 	}
786095059a4SDave May 
787095059a4SDave May 	/* init */
788095059a4SDave May 	for (i=0; i<np; i++) {
789095059a4SDave May 		de->messages_to_be_recvieved[i] = -1;
790095059a4SDave May 	}
791095059a4SDave May 
792095059a4SDave May 	/* figure out the recv counts here */
793095059a4SDave May 	for (i=0; i<np; i++) {
794095059a4SDave May 	//	MPI_Send( &de->messages_to_be_sent[i], 1, MPI_INT, de->neighbour_procs[i], de->send_tags[i], de->comm );
795095059a4SDave 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);
796095059a4SDave May 	//	MPI_Send( &de->messages_to_be_sent[i], 1, MPI_INT, de->neighbour_procs[i], 0, de->comm );
797095059a4SDave May 	}
798095059a4SDave May 	for (i=0; i<np; i++) {
799095059a4SDave May 	//	MPI_Recv( &de->messages_to_be_recvieved[i], 1, MPI_INT, de->neighbour_procs[i], de->recv_tags[i], de->comm, &stat );
800095059a4SDave 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);
801095059a4SDave May 	//	MPI_Recv( &de->messages_to_be_recvieved[i], 1, MPI_INT, de->neighbour_procs[i], 0, de->comm, &stat );
802095059a4SDave May 	}
803095059a4SDave May 	ierr = MPI_Waitall( 2*np, de->_requests, de->_stats );CHKERRQ(ierr);
804095059a4SDave May 
805095059a4SDave May 	/* create space for the data to be recvieved */
806095059a4SDave May 	total = 0;
807095059a4SDave May 	for (i=0; i<np; i++) {
808095059a4SDave May 		total = total + de->messages_to_be_recvieved[i];
809095059a4SDave May 	}
810095059a4SDave May 	de->recv_message = (void*)malloc( de->unit_message_size * (total + 1) );
811095059a4SDave May 	/* initialize memory */
812095059a4SDave May 	memset( de->recv_message, 0, de->unit_message_size * (total + 1) );
813095059a4SDave May 	/* set total items to recieve */
814095059a4SDave May 	de->recv_message_length = total;
815095059a4SDave May 
816095059a4SDave May 	de->packer_status = DEOBJECT_FINALIZED;
817095059a4SDave May 
818095059a4SDave May 	de->communication_status = DEOBJECT_INITIALIZED;
819095059a4SDave May 
820095059a4SDave May 	PetscFunctionReturn(0);
821095059a4SDave May }
822095059a4SDave May 
823095059a4SDave May /* do the actual message passing now */
824095059a4SDave May #undef __FUNCT__
825095059a4SDave May #define __FUNCT__ "DataExBegin"
826095059a4SDave May PetscErrorCode DataExBegin(DataEx de)
827095059a4SDave May {
828095059a4SDave May 	PetscMPIInt i,np;
829095059a4SDave May 	void       *dest;
830095059a4SDave May 	PetscInt    length;
831095059a4SDave May 	PetscErrorCode ierr;
832095059a4SDave May 
833095059a4SDave May 
834095059a4SDave May 	PetscFunctionBegin;
835095059a4SDave May 	if (de->topology_status != DEOBJECT_FINALIZED) {
836095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ORDER, "Topology not finalized" );
837095059a4SDave May 	}
838095059a4SDave May 	if (de->message_lengths_status != DEOBJECT_FINALIZED) {
839095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ORDER, "Message lengths not finalized" );
840095059a4SDave May 	}
841095059a4SDave May 	if (de->packer_status != DEOBJECT_FINALIZED) {
842095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ORDER, "Packer not finalized" );
843095059a4SDave May 	}
844095059a4SDave May 
845095059a4SDave May 	if (de->communication_status == DEOBJECT_FINALIZED) {
846095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ORDER, "Communication has already been finalized. Must call DataExInitialize() first." );
847095059a4SDave May 	}
848095059a4SDave May 
849095059a4SDave May 	if (de->recv_message == NULL) {
850095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DataExPackFinalize() first" );
851095059a4SDave May 	}
852095059a4SDave May 
853095059a4SDave May 	ierr = PetscLogEventBegin(PTATIN_DataExchangerBegin,0,0,0,0);CHKERRQ(ierr);
854095059a4SDave May 	np = de->n_neighbour_procs;
855095059a4SDave May 
856095059a4SDave May 	/* == NON BLOCKING == */
857095059a4SDave May 	for (i=0; i<np; i++) {
858095059a4SDave May 		length = de->messages_to_be_sent[i] * de->unit_message_size;
859095059a4SDave May 		dest = ((char*)de->send_message) + de->unit_message_size * de->message_offsets[i];
860095059a4SDave May 		ierr = MPI_Isend( dest, length, MPI_CHAR, de->neighbour_procs[i], de->send_tags[i], de->comm, &de->_requests[i] );CHKERRQ(ierr);
861095059a4SDave May 	}
862095059a4SDave May 
863095059a4SDave May 	ierr = PetscLogEventEnd(PTATIN_DataExchangerBegin,0,0,0,0);CHKERRQ(ierr);
864095059a4SDave May 	PetscFunctionReturn(0);
865095059a4SDave May }
866095059a4SDave May 
867095059a4SDave May /* do the actual message passing now */
868095059a4SDave May #undef __FUNCT__
869095059a4SDave May #define __FUNCT__ "DataExEnd"
870095059a4SDave May PetscErrorCode DataExEnd(DataEx de)
871095059a4SDave May {
872095059a4SDave May 	PetscMPIInt  i,np;
873095059a4SDave May 	PetscInt     total;
874095059a4SDave May 	PetscInt    *message_recv_offsets;
875095059a4SDave May 	void        *dest;
876095059a4SDave May 	PetscInt     length;
877095059a4SDave May 	PetscErrorCode ierr;
878095059a4SDave May 
879095059a4SDave May 
880095059a4SDave May 	PetscFunctionBegin;
881095059a4SDave May 	if (de->communication_status != DEOBJECT_INITIALIZED) {
882095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ORDER, "Communication has not been initialized. Must call DataExInitialize() first." );
883095059a4SDave May 	}
884095059a4SDave May 	if (de->recv_message == NULL) {
885095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ORDER, "recv_message has not been initialized. Must call DataExPackFinalize() first" );
886095059a4SDave May 	}
887095059a4SDave May 
888095059a4SDave May 	ierr = PetscLogEventBegin(PTATIN_DataExchangerEnd,0,0,0,0);CHKERRQ(ierr);
889095059a4SDave May 	np = de->n_neighbour_procs;
890095059a4SDave May 
891095059a4SDave May 	message_recv_offsets = (PetscInt*)malloc( sizeof(PetscInt) * np );
892095059a4SDave May 	message_recv_offsets[0] = 0;
893095059a4SDave May 	total = de->messages_to_be_recvieved[0];
894095059a4SDave May 	for (i=1; i<np; i++) {
895095059a4SDave May 		message_recv_offsets[i] = total;
896095059a4SDave May 		total = total + de->messages_to_be_recvieved[i];
897095059a4SDave May 	}
898095059a4SDave May 
899095059a4SDave May 	/* == NON BLOCKING == */
900095059a4SDave May 	for (i=0; i<np; i++) {
901095059a4SDave May 		length = de->messages_to_be_recvieved[i] * de->unit_message_size;
902095059a4SDave May 		dest = ((char*)de->recv_message) + de->unit_message_size * message_recv_offsets[i];
903095059a4SDave May 		ierr = MPI_Irecv( dest, length, MPI_CHAR, de->neighbour_procs[i], de->recv_tags[i], de->comm, &de->_requests[np+i] );CHKERRQ(ierr);
904095059a4SDave May 	}
905095059a4SDave May 	ierr = MPI_Waitall( 2*np, de->_requests, de->_stats );CHKERRQ(ierr);
906095059a4SDave May 
907095059a4SDave May 	free(message_recv_offsets);
908095059a4SDave May 
909095059a4SDave May 	de->communication_status = DEOBJECT_FINALIZED;
910095059a4SDave May 	ierr = PetscLogEventEnd(PTATIN_DataExchangerEnd,0,0,0,0);CHKERRQ(ierr);
911095059a4SDave May 	PetscFunctionReturn(0);
912095059a4SDave May }
913095059a4SDave May 
914095059a4SDave May #undef __FUNCT__
915095059a4SDave May #define __FUNCT__ "DataExGetSendData"
916095059a4SDave May PetscErrorCode DataExGetSendData(DataEx de,PetscInt *length,void **send)
917095059a4SDave May {
918095059a4SDave May 	PetscFunctionBegin;
919095059a4SDave May 	if (de->packer_status != DEOBJECT_FINALIZED) {
920095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being packed." );
921095059a4SDave May 	}
922095059a4SDave May 	*length = de->send_message_length;
923095059a4SDave May 	*send   = de->send_message;
924095059a4SDave May 	PetscFunctionReturn(0);
925095059a4SDave May }
926095059a4SDave May 
927095059a4SDave May #undef __FUNCT__
928095059a4SDave May #define __FUNCT__ "DataExGetRecvData"
929095059a4SDave May PetscErrorCode DataExGetRecvData(DataEx de,PetscInt *length,void **recv)
930095059a4SDave May {
931095059a4SDave May 	PetscFunctionBegin;
932095059a4SDave May 	if (de->communication_status != DEOBJECT_FINALIZED) {
933095059a4SDave May 		SETERRQ( de->comm, PETSC_ERR_ARG_WRONGSTATE, "Data has not finished being sent." );
934095059a4SDave May 	}
935095059a4SDave May 	*length = de->recv_message_length;
936095059a4SDave May 	*recv   = de->recv_message;
937095059a4SDave May 	PetscFunctionReturn(0);
938095059a4SDave May }
939095059a4SDave May 
940095059a4SDave May #undef __FUNCT__
941095059a4SDave May #define __FUNCT__ "DataExTopologyGetNeighbours"
942095059a4SDave May PetscErrorCode DataExTopologyGetNeighbours(DataEx de,PetscMPIInt *n,PetscMPIInt *neigh[])
943095059a4SDave May {
944095059a4SDave May 	PetscFunctionBegin;
945095059a4SDave May 	if (n)     { *n     = de->n_neighbour_procs; }
946095059a4SDave May 	if (neigh) { *neigh = de->neighbour_procs; }
947095059a4SDave May 	PetscFunctionReturn(0);
948095059a4SDave May }
949095059a4SDave May 
950