xref: /petsc/src/mat/utils/matstash.c (revision bc5ccf886fc7b029025ea4de8c4047e1db2135de)
1a5eb4965SSatish Balay #ifdef PETSC_RCS_HEADER
2*bc5ccf88SSatish Balay static char vcid[] = "$Id: stash.c,v 1.20 1999/02/25 22:48:34 balay Exp balay $";
32d5177cdSBarry Smith #endif
42d5177cdSBarry Smith 
52d5177cdSBarry Smith #include "src/vec/vecimpl.h"
670f55243SBarry Smith #include "src/mat/matimpl.h"
79417f4adSLois Curfman McInnes 
8*bc5ccf88SSatish Balay #define DEFAULT_STASH_SIZE   10000
99417f4adSLois Curfman McInnes /*
109417f4adSLois Curfman McInnes    This stash is currently used for all the parallel matrix implementations.
11d5d45c9bSBarry Smith    The stash is where elements of a matrix destined to be stored on other
12d5d45c9bSBarry Smith    processors are kept until matrix assembly is done.
139417f4adSLois Curfman McInnes 
1490f02eecSBarry Smith    This is a simple minded stash. Simply add entry to end of stash.
159417f4adSLois Curfman McInnes */
169417f4adSLois Curfman McInnes 
175615d1e5SSatish Balay #undef __FUNC__
18*bc5ccf88SSatish Balay #define __FUNC__ "StashCreate_Private"
19*bc5ccf88SSatish Balay int StashCreate_Private(MPI_Comm comm,int bs, Stash *stash)
209417f4adSLois Curfman McInnes {
21*bc5ccf88SSatish Balay   int ierr,flg,max=DEFAULT_STASH_SIZE;
22*bc5ccf88SSatish Balay 
233a40ed3dSBarry Smith   PetscFunctionBegin;
24*bc5ccf88SSatish Balay   /* Require 2 tags, get the second using PetscCommGetNewTag() */
25*bc5ccf88SSatish Balay   ierr = PetscCommDuplicate_Private(comm,&stash->comm,&stash->tag1);CHKERRQ(ierr);
26*bc5ccf88SSatish Balay   ierr = PetscCommGetNewTag(comm,&stash->tag2); CHKERRQ(ierr);
27*bc5ccf88SSatish Balay   ierr = OptionsGetInt(PETSC_NULL,"-stash_initial_size",&max,&flg);CHKERRQ(ierr);
28*bc5ccf88SSatish Balay   ierr = StashSetInitialSize_Private(stash,max); CHKERRQ(ierr);
29*bc5ccf88SSatish Balay 
30*bc5ccf88SSatish Balay   if (bs <= 0) bs = 1;
31*bc5ccf88SSatish Balay   stash->bs       = bs;
329417f4adSLois Curfman McInnes   stash->nmax     = 0;
339417f4adSLois Curfman McInnes   stash->n        = 0;
34*bc5ccf88SSatish Balay   stash->reallocs = 0;
359417f4adSLois Curfman McInnes   stash->idx      = 0;
369417f4adSLois Curfman McInnes   stash->idy      = 0;
37*bc5ccf88SSatish Balay   stash->array    = 0;
389417f4adSLois Curfman McInnes 
39*bc5ccf88SSatish Balay   stash->send_waits = 0;
40*bc5ccf88SSatish Balay   stash->recv_waits = 0;
41*bc5ccf88SSatish Balay   stash->nsends     = 0;
42*bc5ccf88SSatish Balay   stash->nrecvs     = 0;
43*bc5ccf88SSatish Balay   stash->svalues    = 0;
44*bc5ccf88SSatish Balay   stash->rvalues    = 0;
45*bc5ccf88SSatish Balay   stash->rmax       = 0;
46*bc5ccf88SSatish Balay   stash->rdata      = 0;
473a40ed3dSBarry Smith   PetscFunctionReturn(0);
489417f4adSLois Curfman McInnes }
499417f4adSLois Curfman McInnes 
505615d1e5SSatish Balay #undef __FUNC__
51d4bb536fSBarry Smith #define __FUNC__ "StashDestroy_Private"
529417f4adSLois Curfman McInnes int StashDestroy_Private(Stash *stash)
539417f4adSLois Curfman McInnes {
54*bc5ccf88SSatish Balay   int ierr;
55*bc5ccf88SSatish Balay   PetscFunctionBegin;
56*bc5ccf88SSatish Balay   ierr = PetscCommDestroy_Private(&stash->comm); CHKERRQ(ierr);
57*bc5ccf88SSatish Balay   if (stash->array) {PetscFree(stash->array); stash->array = 0;}
58*bc5ccf88SSatish Balay   PetscFunctionReturn(0);
59*bc5ccf88SSatish Balay }
60*bc5ccf88SSatish Balay 
61*bc5ccf88SSatish Balay #undef __FUNC__
62*bc5ccf88SSatish Balay #define __FUNC__ "StashReset_Private"
63*bc5ccf88SSatish Balay int StashReset_Private(Stash *stash)
64*bc5ccf88SSatish Balay {
653a40ed3dSBarry Smith   PetscFunctionBegin;
66d07ff455SSatish Balay   /* Now update nmaxold to be app 10% more than nmax, this way the
67d07ff455SSatish Balay      wastage of space is reduced the next time this stash is used */
68*bc5ccf88SSatish Balay   stash->oldnmax  = (int)(stash->nmax * 1.1) + 5;
69d07ff455SSatish Balay   stash->nmax     = 0;
70d07ff455SSatish Balay   stash->n        = 0;
71*bc5ccf88SSatish Balay   stash->reallocs = 0;
72*bc5ccf88SSatish Balay   stash->rmax     = 0;
73*bc5ccf88SSatish Balay 
74*bc5ccf88SSatish Balay   if (stash->array) {
75*bc5ccf88SSatish Balay     PetscFree(stash->array);
76*bc5ccf88SSatish Balay     stash->array = 0;
77*bc5ccf88SSatish Balay     stash->idx   = 0;
78*bc5ccf88SSatish Balay     stash->idy   = 0;
79*bc5ccf88SSatish Balay   }
80*bc5ccf88SSatish Balay   if (stash->send_waits) {PetscFree(stash->send_waits);stash->send_waits = 0;}
81*bc5ccf88SSatish Balay   if (stash->recv_waits) {PetscFree(stash->recv_waits);stash->recv_waits =0;}
82*bc5ccf88SSatish Balay   if (stash->svalues)    {PetscFree(stash->svalues);stash->svalues = 0;}
83*bc5ccf88SSatish Balay   if (stash->rvalues)    {PetscFree(stash->rvalues); stash->rvalues = 0;}
84*bc5ccf88SSatish Balay   if (stash->rdata)      {PetscFree(stash->rdata); stash->rdata = 0;}
85*bc5ccf88SSatish Balay 
863a40ed3dSBarry Smith   PetscFunctionReturn(0);
879417f4adSLois Curfman McInnes }
889417f4adSLois Curfman McInnes 
895615d1e5SSatish Balay #undef __FUNC__
90d4bb536fSBarry Smith #define __FUNC__ "StashInfo_Private"
9197530c3fSBarry Smith int StashInfo_Private(Stash *stash)
9297530c3fSBarry Smith {
933a40ed3dSBarry Smith   PetscFunctionBegin;
94*bc5ccf88SSatish Balay   PLogInfo(0,"StashInfo_Private:Stash size %d, mallocs incured %d\n",stash->n,stash->reallocs);
95*bc5ccf88SSatish Balay   PetscFunctionReturn(0);
96*bc5ccf88SSatish Balay }
97*bc5ccf88SSatish Balay #undef __FUNC__
98*bc5ccf88SSatish Balay #define __FUNC__ "StashSetInitialSize_Private"
99*bc5ccf88SSatish Balay int StashSetInitialSize_Private(Stash *stash,int max)
100*bc5ccf88SSatish Balay {
101*bc5ccf88SSatish Balay   PetscFunctionBegin;
102*bc5ccf88SSatish Balay   stash->oldnmax = max;
103*bc5ccf88SSatish Balay   stash->nmax    = 0;
1043a40ed3dSBarry Smith   PetscFunctionReturn(0);
10597530c3fSBarry Smith }
10697530c3fSBarry Smith 
1075615d1e5SSatish Balay #undef __FUNC__
108*bc5ccf88SSatish Balay #define __FUNC__ "StashExpand_Private"
109*bc5ccf88SSatish Balay static int StashExpand_Private(Stash *stash)
1109417f4adSLois Curfman McInnes {
111*bc5ccf88SSatish Balay   int    *n_idx,*n_idy,newnmax;
112*bc5ccf88SSatish Balay   Scalar *n_array;
1139417f4adSLois Curfman McInnes 
1143a40ed3dSBarry Smith   PetscFunctionBegin;
1159417f4adSLois Curfman McInnes   /* allocate a larger stash */
116d07ff455SSatish Balay   if (stash->nmax == 0) newnmax = stash->oldnmax;
117d07ff455SSatish Balay   else                  newnmax = stash->nmax *2;
118d07ff455SSatish Balay 
119d07ff455SSatish Balay   n_array = (Scalar *)PetscMalloc((newnmax)*(2*sizeof(int)+sizeof(Scalar)));CHKPTRQ(n_array);
120d07ff455SSatish Balay   n_idx = (int *) (n_array + newnmax);
121d07ff455SSatish Balay   n_idy = (int *) (n_idx + newnmax);
122416022c9SBarry Smith   PetscMemcpy(n_array,stash->array,stash->nmax*sizeof(Scalar));
123416022c9SBarry Smith   PetscMemcpy(n_idx,stash->idx,stash->nmax*sizeof(int));
124416022c9SBarry Smith   PetscMemcpy(n_idy,stash->idy,stash->nmax*sizeof(int));
1250452661fSBarry Smith   if (stash->array) PetscFree(stash->array);
126d07ff455SSatish Balay   stash->array   = n_array;
127d07ff455SSatish Balay   stash->idx     = n_idx;
128d07ff455SSatish Balay   stash->idy     = n_idy;
129d07ff455SSatish Balay   stash->nmax    = newnmax;
130d07ff455SSatish Balay   stash->oldnmax = newnmax;
131*bc5ccf88SSatish Balay   stash->reallocs++;
132*bc5ccf88SSatish Balay   PetscFunctionReturn(0);
133*bc5ccf88SSatish Balay }
134*bc5ccf88SSatish Balay 
135*bc5ccf88SSatish Balay /*
136*bc5ccf88SSatish Balay     Should do this properly. With a sorted array.
137*bc5ccf88SSatish Balay */
138*bc5ccf88SSatish Balay #undef __FUNC__
139*bc5ccf88SSatish Balay #define __FUNC__ "StashValues_Private"
140*bc5ccf88SSatish Balay int StashValues_Private(Stash *stash,int row,int n, int *idxn,Scalar *values,InsertMode addv)
141*bc5ccf88SSatish Balay {
142*bc5ccf88SSatish Balay   int    ierr,i,found;
143*bc5ccf88SSatish Balay   Scalar val;
144*bc5ccf88SSatish Balay 
145*bc5ccf88SSatish Balay   PetscFunctionBegin;
146*bc5ccf88SSatish Balay   for ( i=0; i<n; i++ ) {
147*bc5ccf88SSatish Balay     found = 0;
148*bc5ccf88SSatish Balay     val = *values++;
149*bc5ccf88SSatish Balay     if (!found) { /* not found so add to end */
150*bc5ccf88SSatish Balay       if ( stash->n == stash->nmax ) {
151*bc5ccf88SSatish Balay         ierr = StashExpand_Private(stash); CHKERRQ(ierr);
1529417f4adSLois Curfman McInnes       }
1539417f4adSLois Curfman McInnes       stash->array[stash->n] = val;
1549417f4adSLois Curfman McInnes       stash->idx[stash->n]   = row;
1559417f4adSLois Curfman McInnes       stash->idy[stash->n++] = idxn[i];
1569417f4adSLois Curfman McInnes     }
1579417f4adSLois Curfman McInnes   }
1583a40ed3dSBarry Smith   PetscFunctionReturn(0);
1599417f4adSLois Curfman McInnes }
160*bc5ccf88SSatish Balay 
161*bc5ccf88SSatish Balay #undef __FUNC__
162*bc5ccf88SSatish Balay #define __FUNC__ "StashScatterBegin_Private"
163*bc5ccf88SSatish Balay int StashScatterBegin_Private(Stash *stash,int *owners)
164*bc5ccf88SSatish Balay {
165*bc5ccf88SSatish Balay   MPI_Comm    comm = stash->comm;
166*bc5ccf88SSatish Balay   MPI_Request *send_waits,*recv_waits;
167*bc5ccf88SSatish Balay   Scalar      *rvalues,*svalues;
168*bc5ccf88SSatish Balay   int         *owner,*startv,*starti,tag1=stash->tag1,tag2=stash->tag2;
169*bc5ccf88SSatish Balay   int         rank,size,*nprocs,i,j,idx,*procs,nsends,nreceives,nmax,*work;
170*bc5ccf88SSatish Balay   int         count,ierr,*sindices,*rindices,bs=stash->bs;
171*bc5ccf88SSatish Balay 
172*bc5ccf88SSatish Balay   PetscFunctionBegin;
173*bc5ccf88SSatish Balay 
174*bc5ccf88SSatish Balay   ierr = MPI_Comm_size(comm,&size); CHKERRQ(ierr);
175*bc5ccf88SSatish Balay   ierr = MPI_Comm_rank(comm,&rank); CHKERRQ(ierr);
176*bc5ccf88SSatish Balay 
177*bc5ccf88SSatish Balay   /*  first count number of contributors to each processor */
178*bc5ccf88SSatish Balay   nprocs = (int *) PetscMalloc( 2*size*sizeof(int) ); CHKPTRQ(nprocs);
179*bc5ccf88SSatish Balay   PetscMemzero(nprocs,2*size*sizeof(int)); procs = nprocs + size;
180*bc5ccf88SSatish Balay   owner = (int *) PetscMalloc( (stash->n+1)*sizeof(int) ); CHKPTRQ(owner);
181*bc5ccf88SSatish Balay   for ( i=0; i<stash->n; i++ ) {
182*bc5ccf88SSatish Balay     idx = stash->idx[i];
183*bc5ccf88SSatish Balay     for ( j=0; j<size; j++ ) {
184*bc5ccf88SSatish Balay       if (idx >= bs*owners[j] && idx < bs*owners[j+1]) {
185*bc5ccf88SSatish Balay         nprocs[j]++; procs[j] = 1; owner[i] = j; break;
186*bc5ccf88SSatish Balay       }
187*bc5ccf88SSatish Balay     }
188*bc5ccf88SSatish Balay   }
189*bc5ccf88SSatish Balay   nsends = 0;  for ( i=0; i<size; i++ ) { nsends += procs[i];}
190*bc5ccf88SSatish Balay 
191*bc5ccf88SSatish Balay   /* inform other processors of number of messages and max length*/
192*bc5ccf88SSatish Balay   work = (int *)PetscMalloc(size*sizeof(int)); CHKPTRQ(work);
193*bc5ccf88SSatish Balay   ierr = MPI_Allreduce(procs,work,size,MPI_INT,MPI_SUM,comm);CHKERRQ(ierr);
194*bc5ccf88SSatish Balay   nreceives = work[rank];
195*bc5ccf88SSatish Balay   ierr = MPI_Allreduce(nprocs,work,size,MPI_INT,MPI_MAX,comm);CHKERRQ(ierr);
196*bc5ccf88SSatish Balay   nmax = work[rank];
197*bc5ccf88SSatish Balay   PetscFree(work);
198*bc5ccf88SSatish Balay   /* post receives:
199*bc5ccf88SSatish Balay      since we don't know how long each individual message is we
200*bc5ccf88SSatish Balay      allocate the largest needed buffer for each receive. Potentially
201*bc5ccf88SSatish Balay      this is a lot of wasted space.
202*bc5ccf88SSatish Balay   */
203*bc5ccf88SSatish Balay   rvalues    = (Scalar *)PetscMalloc((nreceives+1)*(nmax+1)*(sizeof(Scalar)+2*sizeof(int)));
204*bc5ccf88SSatish Balay   CHKPTRQ(rvalues);
205*bc5ccf88SSatish Balay   rindices   = (int *) (rvalues + nreceives*nmax);
206*bc5ccf88SSatish Balay   recv_waits = (MPI_Request *) PetscMalloc((nreceives+1)*2*sizeof(MPI_Request));
207*bc5ccf88SSatish Balay   CHKPTRQ(recv_waits);
208*bc5ccf88SSatish Balay   for ( i=0,count=0; i<nreceives; i++ ) {
209*bc5ccf88SSatish Balay     ierr = MPI_Irecv(rvalues+nmax*i,nmax,MPIU_SCALAR,MPI_ANY_SOURCE,tag1,comm,
210*bc5ccf88SSatish Balay                      recv_waits+count++); CHKERRQ(ierr);
211*bc5ccf88SSatish Balay     ierr = MPI_Irecv(rindices+2*nmax*i,2*nmax,MPI_INT,MPI_ANY_SOURCE,tag2,comm,
212*bc5ccf88SSatish Balay                      recv_waits+count++); CHKERRQ(ierr);
213*bc5ccf88SSatish Balay   }
214*bc5ccf88SSatish Balay 
215*bc5ccf88SSatish Balay   /* do sends:
216*bc5ccf88SSatish Balay       1) starts[i] gives the starting index in svalues for stuff going to
217*bc5ccf88SSatish Balay          the ith processor
218*bc5ccf88SSatish Balay   */
219*bc5ccf88SSatish Balay   svalues    = (Scalar *) PetscMalloc((stash->n+1)*(sizeof(Scalar)+2*sizeof(int)));
220*bc5ccf88SSatish Balay   CHKPTRQ(svalues);
221*bc5ccf88SSatish Balay   sindices   = (int *) (svalues + stash->n);
222*bc5ccf88SSatish Balay   send_waits = (MPI_Request *) PetscMalloc(2*(nsends+1)*sizeof(MPI_Request));
223*bc5ccf88SSatish Balay   CHKPTRQ(send_waits);
224*bc5ccf88SSatish Balay   startv     = (int *) PetscMalloc(2*size*sizeof(int) ); CHKPTRQ(startv);
225*bc5ccf88SSatish Balay   starti     = startv + size;
226*bc5ccf88SSatish Balay   /* use 2 sends the first with all_a, the next with all_i and then all_j */
227*bc5ccf88SSatish Balay   startv[0]  = 0; starti[0] = 0;
228*bc5ccf88SSatish Balay   for ( i=1; i<size; i++ ) {
229*bc5ccf88SSatish Balay     startv[i] = startv[i-1] + nprocs[i-1];
230*bc5ccf88SSatish Balay     starti[i] = starti[i-1] + nprocs[i-1]*2;
231*bc5ccf88SSatish Balay   }
232*bc5ccf88SSatish Balay   for ( i=0; i<stash->n; i++ ) {
233*bc5ccf88SSatish Balay     j = owner[i];
234*bc5ccf88SSatish Balay     svalues[startv[j]]              = stash->array[i];
235*bc5ccf88SSatish Balay     sindices[starti[j]]             = stash->idx[i];
236*bc5ccf88SSatish Balay     sindices[starti[j]+nprocs[j]]   = stash->idy[i];
237*bc5ccf88SSatish Balay     startv[j]++;
238*bc5ccf88SSatish Balay     starti[j]++;
239*bc5ccf88SSatish Balay   }
240*bc5ccf88SSatish Balay   startv[0] = 0;
241*bc5ccf88SSatish Balay   for ( i=1; i<size; i++ ) { startv[i] = startv[i-1] + nprocs[i-1];}
242*bc5ccf88SSatish Balay   for ( i=0,count=0; i<size; i++ ) {
243*bc5ccf88SSatish Balay     if (procs[i]) {
244*bc5ccf88SSatish Balay       ierr = MPI_Isend(svalues+startv[i],nprocs[i],MPIU_SCALAR,i,tag1,comm,
245*bc5ccf88SSatish Balay                        send_waits+count++);CHKERRQ(ierr);
246*bc5ccf88SSatish Balay       ierr = MPI_Isend(sindices+2*startv[i],2*nprocs[i],MPI_INT,i,tag2,comm,
247*bc5ccf88SSatish Balay                        send_waits+count++);CHKERRQ(ierr);
248*bc5ccf88SSatish Balay     }
249*bc5ccf88SSatish Balay   }
250*bc5ccf88SSatish Balay   PetscFree(owner);
251*bc5ccf88SSatish Balay   PetscFree(startv);
252*bc5ccf88SSatish Balay   PetscFree(nprocs);
253*bc5ccf88SSatish Balay   stash->svalues    = svalues;    stash->rvalues    = rvalues;
254*bc5ccf88SSatish Balay   stash->nsends     = nsends;     stash->nrecvs     = nreceives;
255*bc5ccf88SSatish Balay   stash->send_waits = send_waits; stash->recv_waits = recv_waits;
256*bc5ccf88SSatish Balay   stash->rmax       = nmax;
257*bc5ccf88SSatish Balay 
258*bc5ccf88SSatish Balay   PetscFunctionReturn(0);
259*bc5ccf88SSatish Balay }
260*bc5ccf88SSatish Balay 
261*bc5ccf88SSatish Balay 
262*bc5ccf88SSatish Balay #undef __FUNC__
263*bc5ccf88SSatish Balay #define __FUNC__ "StashScatterEnd_Private"
264*bc5ccf88SSatish Balay int StashScatterEnd_Private(Stash *stash)
265*bc5ccf88SSatish Balay {
266*bc5ccf88SSatish Balay   int         i,ierr,size,*nprocs;
267*bc5ccf88SSatish Balay   MPI_Status  *send_status,*recv_status;
268*bc5ccf88SSatish Balay   int         i1,i2,s1,s2,count,*rindices;
269*bc5ccf88SSatish Balay 
270*bc5ccf88SSatish Balay   PetscFunctionBegin;
271*bc5ccf88SSatish Balay 
272*bc5ccf88SSatish Balay   /* wait on receives */
273*bc5ccf88SSatish Balay   ierr = MPI_Comm_size(stash->comm,&size); CHKERRQ(ierr);
274*bc5ccf88SSatish Balay   if (stash->nrecvs) {
275*bc5ccf88SSatish Balay     recv_status = (MPI_Status *) PetscMalloc(2*(stash->nrecvs+1)*sizeof(MPI_Status));
276*bc5ccf88SSatish Balay     CHKPTRQ(recv_status);
277*bc5ccf88SSatish Balay     ierr = MPI_Waitall(2*stash->nrecvs,stash->recv_waits,recv_status);CHKERRQ(ierr);
278*bc5ccf88SSatish Balay     /* Now pack the received messages into a structure which is useable by others */
279*bc5ccf88SSatish Balay     stash->rdata = (Stash_rdata *) PetscMalloc(stash->nrecvs*sizeof(Stash_rdata));
280*bc5ccf88SSatish Balay     CHKPTRQ(stash->rdata);
281*bc5ccf88SSatish Balay     nprocs = (int *) PetscMalloc((2*size+1)*sizeof(int)); CHKPTRQ(nprocs);
282*bc5ccf88SSatish Balay     rindices = (int *) (stash->rvalues + stash->rmax*stash->nrecvs);
283*bc5ccf88SSatish Balay     for (i=0; i<2*size+1; i++ ) nprocs[i] = -1;
284*bc5ccf88SSatish Balay     for ( i=0; i<stash->nrecvs; i++ ){
285*bc5ccf88SSatish Balay       nprocs[2*recv_status[2*i].MPI_SOURCE] = i;
286*bc5ccf88SSatish Balay       nprocs[2*recv_status[2*i+1].MPI_SOURCE+1] = i;
287*bc5ccf88SSatish Balay     }
288*bc5ccf88SSatish Balay     for (i=0,count=0; i<size; i++) {
289*bc5ccf88SSatish Balay       i1 = nprocs[2*i];
290*bc5ccf88SSatish Balay       i2 = nprocs[2*i+1];
291*bc5ccf88SSatish Balay       if (i1 != -1) {
292*bc5ccf88SSatish Balay         if (i2 == -1) SETERRQ(1,0,"Internal Error");
293*bc5ccf88SSatish Balay         ierr = MPI_Get_count(recv_status+2*i1,MPIU_SCALAR,&s1);CHKERRQ(ierr);
294*bc5ccf88SSatish Balay         ierr = MPI_Get_count(recv_status+2*i2+1,MPI_INT,&s2);CHKERRQ(ierr);
295*bc5ccf88SSatish Balay         if (s1*2 != s2) SETERRQ(1,0,"Internal Error");
296*bc5ccf88SSatish Balay         stash->rdata[count].a = stash->rvalues + i1*stash->rmax;
297*bc5ccf88SSatish Balay         stash->rdata[count].i = rindices + 2*i2*stash->rmax;
298*bc5ccf88SSatish Balay         stash->rdata[count].j = stash->rdata[count].i + s1;
299*bc5ccf88SSatish Balay         stash->rdata[count].n = s1;
300*bc5ccf88SSatish Balay         count ++;
301*bc5ccf88SSatish Balay       }
302*bc5ccf88SSatish Balay     }
303*bc5ccf88SSatish Balay     PetscFree(recv_status);
304*bc5ccf88SSatish Balay     PetscFree(nprocs);
305*bc5ccf88SSatish Balay   }
306*bc5ccf88SSatish Balay   /* wait on sends */
307*bc5ccf88SSatish Balay   if (stash->nsends) {
308*bc5ccf88SSatish Balay     send_status = (MPI_Status *)PetscMalloc(2*stash->nsends*sizeof(MPI_Status));
309*bc5ccf88SSatish Balay     CHKPTRQ(send_status);
310*bc5ccf88SSatish Balay     ierr        = MPI_Waitall(2*stash->nsends,stash->send_waits,send_status);CHKERRQ(ierr);
311*bc5ccf88SSatish Balay     PetscFree(send_status);
312*bc5ccf88SSatish Balay   }
313*bc5ccf88SSatish Balay   PetscFunctionReturn(0);
314*bc5ccf88SSatish Balay }
315