xref: /petsc/src/mat/utils/matstash.c (revision ac2b2aa072733048646740f7267415a7b45ae633)
12d5177cdSBarry Smith 
2b45d2f2cSJed Brown #include <petsc-private/matimpl.h>
35bd3b8fbSHong Zhang 
4bc5ccf88SSatish Balay #define DEFAULT_STASH_SIZE   10000
54c1ff481SSatish Balay 
6*ac2b2aa0SJed Brown static PetscErrorCode MatStashScatterBegin_Ref(Mat,MatStash*,PetscInt*);
7*ac2b2aa0SJed Brown static PetscErrorCode MatStashScatterGetMesg_Ref(MatStash*,PetscMPIInt*,PetscInt**,PetscInt**,PetscScalar**,PetscInt*);
8*ac2b2aa0SJed Brown static PetscErrorCode MatStashScatterEnd_Ref(MatStash*);
99417f4adSLois Curfman McInnes /*
108798bf22SSatish Balay   MatStashCreate_Private - Creates a stash,currently used for all the parallel
114c1ff481SSatish Balay   matrix implementations. The stash is where elements of a matrix destined
124c1ff481SSatish Balay   to be stored on other processors are kept until matrix assembly is done.
139417f4adSLois Curfman McInnes 
144c1ff481SSatish Balay   This is a simple minded stash. Simply adds entries to end of stash.
154c1ff481SSatish Balay 
164c1ff481SSatish Balay   Input Parameters:
174c1ff481SSatish Balay   comm - communicator, required for scatters.
184c1ff481SSatish Balay   bs   - stash block size. used when stashing blocks of values
194c1ff481SSatish Balay 
204c1ff481SSatish Balay   Output Parameters:
214c1ff481SSatish Balay   stash    - the newly created stash
229417f4adSLois Curfman McInnes */
234a2ae208SSatish Balay #undef __FUNCT__
244a2ae208SSatish Balay #define __FUNCT__ "MatStashCreate_Private"
25c1ac3661SBarry Smith PetscErrorCode MatStashCreate_Private(MPI_Comm comm,PetscInt bs,MatStash *stash)
269417f4adSLois Curfman McInnes {
27dfbe8321SBarry Smith   PetscErrorCode ierr;
28533163c2SBarry Smith   PetscInt       max,*opt,nopt,i;
29ace3abfcSBarry Smith   PetscBool      flg;
30bc5ccf88SSatish Balay 
313a40ed3dSBarry Smith   PetscFunctionBegin;
32bc5ccf88SSatish Balay   /* Require 2 tags,get the second using PetscCommGetNewTag() */
33752ec6e0SSatish Balay   stash->comm = comm;
348865f1eaSKarl Rupp 
35752ec6e0SSatish Balay   ierr = PetscCommGetNewTag(stash->comm,&stash->tag1);CHKERRQ(ierr);
36a2d1c673SSatish Balay   ierr = PetscCommGetNewTag(stash->comm,&stash->tag2);CHKERRQ(ierr);
37a2d1c673SSatish Balay   ierr = MPI_Comm_size(stash->comm,&stash->size);CHKERRQ(ierr);
38a2d1c673SSatish Balay   ierr = MPI_Comm_rank(stash->comm,&stash->rank);CHKERRQ(ierr);
39785e854fSJed Brown   ierr = PetscMalloc1(2*stash->size,&stash->flg_v);CHKERRQ(ierr);
40533163c2SBarry Smith   for (i=0; i<2*stash->size; i++) stash->flg_v[i] = -1;
41533163c2SBarry Smith 
42bc5ccf88SSatish Balay 
43434d7ff9SSatish Balay   nopt = stash->size;
44785e854fSJed Brown   ierr = PetscMalloc1(nopt,&opt);CHKERRQ(ierr);
450298fd71SBarry Smith   ierr = PetscOptionsGetIntArray(NULL,"-matstash_initial_size",opt,&nopt,&flg);CHKERRQ(ierr);
46434d7ff9SSatish Balay   if (flg) {
47434d7ff9SSatish Balay     if (nopt == 1)                max = opt[0];
48434d7ff9SSatish Balay     else if (nopt == stash->size) max = opt[stash->rank];
49434d7ff9SSatish Balay     else if (stash->rank < nopt)  max = opt[stash->rank];
50f4ab19daSSatish Balay     else                          max = 0; /* Use default */
51434d7ff9SSatish Balay     stash->umax = max;
52434d7ff9SSatish Balay   } else {
53434d7ff9SSatish Balay     stash->umax = 0;
54434d7ff9SSatish Balay   }
55606d414cSSatish Balay   ierr = PetscFree(opt);CHKERRQ(ierr);
564c1ff481SSatish Balay   if (bs <= 0) bs = 1;
57a2d1c673SSatish Balay 
584c1ff481SSatish Balay   stash->bs         = bs;
599417f4adSLois Curfman McInnes   stash->nmax       = 0;
60434d7ff9SSatish Balay   stash->oldnmax    = 0;
619417f4adSLois Curfman McInnes   stash->n          = 0;
624c1ff481SSatish Balay   stash->reallocs   = -1;
6375cae7c1SHong Zhang   stash->space_head = 0;
6475cae7c1SHong Zhang   stash->space      = 0;
659417f4adSLois Curfman McInnes 
66bc5ccf88SSatish Balay   stash->send_waits  = 0;
67bc5ccf88SSatish Balay   stash->recv_waits  = 0;
68a2d1c673SSatish Balay   stash->send_status = 0;
69bc5ccf88SSatish Balay   stash->nsends      = 0;
70bc5ccf88SSatish Balay   stash->nrecvs      = 0;
71bc5ccf88SSatish Balay   stash->svalues     = 0;
72bc5ccf88SSatish Balay   stash->rvalues     = 0;
73563fb871SSatish Balay   stash->rindices    = 0;
74a2d1c673SSatish Balay   stash->nprocessed  = 0;
7567318a8aSJed Brown   stash->reproduce   = PETSC_FALSE;
768865f1eaSKarl Rupp 
770298fd71SBarry Smith   ierr = PetscOptionsGetBool(NULL,"-matstash_reproduce",&stash->reproduce,NULL);CHKERRQ(ierr);
78*ac2b2aa0SJed Brown   ierr = PetscOptionsGetBool(NULL,"-matstash_bts",&flg,NULL);CHKERRQ(ierr);
79*ac2b2aa0SJed Brown   if (flg) {
80*ac2b2aa0SJed Brown     SETERRQ(comm,PETSC_ERR_SUP,"Not implemented yet");
81*ac2b2aa0SJed Brown   } else {
82*ac2b2aa0SJed Brown     stash->ScatterBegin   = MatStashScatterBegin_Ref;
83*ac2b2aa0SJed Brown     stash->ScatterGetMesg = MatStashScatterGetMesg_Ref;
84*ac2b2aa0SJed Brown     stash->ScatterEnd     = MatStashScatterEnd_Ref;
85*ac2b2aa0SJed Brown     stash->ScatterDestroy = NULL;
86*ac2b2aa0SJed Brown   }
873a40ed3dSBarry Smith   PetscFunctionReturn(0);
889417f4adSLois Curfman McInnes }
899417f4adSLois Curfman McInnes 
904c1ff481SSatish Balay /*
918798bf22SSatish Balay    MatStashDestroy_Private - Destroy the stash
924c1ff481SSatish Balay */
934a2ae208SSatish Balay #undef __FUNCT__
944a2ae208SSatish Balay #define __FUNCT__ "MatStashDestroy_Private"
95dfbe8321SBarry Smith PetscErrorCode MatStashDestroy_Private(MatStash *stash)
969417f4adSLois Curfman McInnes {
97dfbe8321SBarry Smith   PetscErrorCode ierr;
98a2d1c673SSatish Balay 
99bc5ccf88SSatish Balay   PetscFunctionBegin;
1006bf464f9SBarry Smith   ierr = PetscMatStashSpaceDestroy(&stash->space_head);CHKERRQ(ierr);
101*ac2b2aa0SJed Brown   if (stash->ScatterDestroy) {ierr = (*stash->ScatterDestroy)(stash);CHKERRQ(ierr);}
1028865f1eaSKarl Rupp 
10382740460SHong Zhang   stash->space = 0;
1048865f1eaSKarl Rupp 
105533163c2SBarry Smith   ierr = PetscFree(stash->flg_v);CHKERRQ(ierr);
106bc5ccf88SSatish Balay   PetscFunctionReturn(0);
107bc5ccf88SSatish Balay }
108bc5ccf88SSatish Balay 
1094c1ff481SSatish Balay /*
11067318a8aSJed Brown    MatStashScatterEnd_Private - This is called as the final stage of
1114c1ff481SSatish Balay    scatter. The final stages of message passing is done here, and
11267318a8aSJed Brown    all the memory used for message passing is cleaned up. This
1134c1ff481SSatish Balay    routine also resets the stash, and deallocates the memory used
1144c1ff481SSatish Balay    for the stash. It also keeps track of the current memory usage
1154c1ff481SSatish Balay    so that the same value can be used the next time through.
1164c1ff481SSatish Balay */
1174a2ae208SSatish Balay #undef __FUNCT__
1184a2ae208SSatish Balay #define __FUNCT__ "MatStashScatterEnd_Private"
119dfbe8321SBarry Smith PetscErrorCode MatStashScatterEnd_Private(MatStash *stash)
120bc5ccf88SSatish Balay {
1216849ba73SBarry Smith   PetscErrorCode ierr;
122*ac2b2aa0SJed Brown 
123*ac2b2aa0SJed Brown   PetscFunctionBegin;
124*ac2b2aa0SJed Brown   ierr = (*stash->ScatterEnd)(stash);CHKERRQ(ierr);
125*ac2b2aa0SJed Brown   PetscFunctionReturn(0);
126*ac2b2aa0SJed Brown }
127*ac2b2aa0SJed Brown 
128*ac2b2aa0SJed Brown #undef __FUNCT__
129*ac2b2aa0SJed Brown #define __FUNCT__ "MatStashScatterEnd_Ref"
130*ac2b2aa0SJed Brown static PetscErrorCode MatStashScatterEnd_Ref(MatStash *stash)
131*ac2b2aa0SJed Brown {
132*ac2b2aa0SJed Brown   PetscErrorCode ierr;
133533163c2SBarry Smith   PetscInt       nsends=stash->nsends,bs2,oldnmax,i;
134a2d1c673SSatish Balay   MPI_Status     *send_status;
135a2d1c673SSatish Balay 
1363a40ed3dSBarry Smith   PetscFunctionBegin;
137533163c2SBarry Smith   for (i=0; i<2*stash->size; i++) stash->flg_v[i] = -1;
138a2d1c673SSatish Balay   /* wait on sends */
139a2d1c673SSatish Balay   if (nsends) {
140785e854fSJed Brown     ierr = PetscMalloc1(2*nsends,&send_status);CHKERRQ(ierr);
141a2d1c673SSatish Balay     ierr = MPI_Waitall(2*nsends,stash->send_waits,send_status);CHKERRQ(ierr);
142606d414cSSatish Balay     ierr = PetscFree(send_status);CHKERRQ(ierr);
143a2d1c673SSatish Balay   }
144a2d1c673SSatish Balay 
145c0c58ca7SSatish Balay   /* Now update nmaxold to be app 10% more than max n used, this way the
146434d7ff9SSatish Balay      wastage of space is reduced the next time this stash is used.
147434d7ff9SSatish Balay      Also update the oldmax, only if it increases */
148b9b97703SBarry Smith   if (stash->n) {
14994b769a5SSatish Balay     bs2     = stash->bs*stash->bs;
1508a9378f0SSatish Balay     oldnmax = ((int)(stash->n * 1.1) + 5)*bs2;
151434d7ff9SSatish Balay     if (oldnmax > stash->oldnmax) stash->oldnmax = oldnmax;
152b9b97703SBarry Smith   }
153434d7ff9SSatish Balay 
154d07ff455SSatish Balay   stash->nmax       = 0;
155d07ff455SSatish Balay   stash->n          = 0;
1564c1ff481SSatish Balay   stash->reallocs   = -1;
157a2d1c673SSatish Balay   stash->nprocessed = 0;
1588865f1eaSKarl Rupp 
1596bf464f9SBarry Smith   ierr = PetscMatStashSpaceDestroy(&stash->space_head);CHKERRQ(ierr);
1608865f1eaSKarl Rupp 
16182740460SHong Zhang   stash->space = 0;
1628865f1eaSKarl Rupp 
163606d414cSSatish Balay   ierr = PetscFree(stash->send_waits);CHKERRQ(ierr);
164606d414cSSatish Balay   ierr = PetscFree(stash->recv_waits);CHKERRQ(ierr);
165c05d87d6SBarry Smith   ierr = PetscFree2(stash->svalues,stash->sindices);CHKERRQ(ierr);
166c05d87d6SBarry Smith   ierr = PetscFree(stash->rvalues[0]);CHKERRQ(ierr);
167606d414cSSatish Balay   ierr = PetscFree(stash->rvalues);CHKERRQ(ierr);
168c05d87d6SBarry Smith   ierr = PetscFree(stash->rindices[0]);CHKERRQ(ierr);
169563fb871SSatish Balay   ierr = PetscFree(stash->rindices);CHKERRQ(ierr);
1703a40ed3dSBarry Smith   PetscFunctionReturn(0);
1719417f4adSLois Curfman McInnes }
1729417f4adSLois Curfman McInnes 
1734c1ff481SSatish Balay /*
1748798bf22SSatish Balay    MatStashGetInfo_Private - Gets the relavant statistics of the stash
1754c1ff481SSatish Balay 
1764c1ff481SSatish Balay    Input Parameters:
1774c1ff481SSatish Balay    stash    - the stash
17894b769a5SSatish Balay    nstash   - the size of the stash. Indicates the number of values stored.
1794c1ff481SSatish Balay    reallocs - the number of additional mallocs incurred.
1804c1ff481SSatish Balay 
1814c1ff481SSatish Balay */
1824a2ae208SSatish Balay #undef __FUNCT__
1834a2ae208SSatish Balay #define __FUNCT__ "MatStashGetInfo_Private"
184c1ac3661SBarry Smith PetscErrorCode MatStashGetInfo_Private(MatStash *stash,PetscInt *nstash,PetscInt *reallocs)
18597530c3fSBarry Smith {
186c1ac3661SBarry Smith   PetscInt bs2 = stash->bs*stash->bs;
18794b769a5SSatish Balay 
1883a40ed3dSBarry Smith   PetscFunctionBegin;
1891ecfd215SBarry Smith   if (nstash) *nstash = stash->n*bs2;
1901ecfd215SBarry Smith   if (reallocs) {
191434d7ff9SSatish Balay     if (stash->reallocs < 0) *reallocs = 0;
192434d7ff9SSatish Balay     else                     *reallocs = stash->reallocs;
1931ecfd215SBarry Smith   }
194bc5ccf88SSatish Balay   PetscFunctionReturn(0);
195bc5ccf88SSatish Balay }
1964c1ff481SSatish Balay 
1974c1ff481SSatish Balay /*
1988798bf22SSatish Balay    MatStashSetInitialSize_Private - Sets the initial size of the stash
1994c1ff481SSatish Balay 
2004c1ff481SSatish Balay    Input Parameters:
2014c1ff481SSatish Balay    stash  - the stash
2024c1ff481SSatish Balay    max    - the value that is used as the max size of the stash.
2034c1ff481SSatish Balay             this value is used while allocating memory.
2044c1ff481SSatish Balay */
2054a2ae208SSatish Balay #undef __FUNCT__
2064a2ae208SSatish Balay #define __FUNCT__ "MatStashSetInitialSize_Private"
207c1ac3661SBarry Smith PetscErrorCode MatStashSetInitialSize_Private(MatStash *stash,PetscInt max)
208bc5ccf88SSatish Balay {
209bc5ccf88SSatish Balay   PetscFunctionBegin;
210434d7ff9SSatish Balay   stash->umax = max;
2113a40ed3dSBarry Smith   PetscFunctionReturn(0);
21297530c3fSBarry Smith }
21397530c3fSBarry Smith 
2148798bf22SSatish Balay /* MatStashExpand_Private - Expand the stash. This function is called
2154c1ff481SSatish Balay    when the space in the stash is not sufficient to add the new values
2164c1ff481SSatish Balay    being inserted into the stash.
2174c1ff481SSatish Balay 
2184c1ff481SSatish Balay    Input Parameters:
2194c1ff481SSatish Balay    stash - the stash
2204c1ff481SSatish Balay    incr  - the minimum increase requested
2214c1ff481SSatish Balay 
2224c1ff481SSatish Balay    Notes:
2234c1ff481SSatish Balay    This routine doubles the currently used memory.
2244c1ff481SSatish Balay  */
2254a2ae208SSatish Balay #undef __FUNCT__
2264a2ae208SSatish Balay #define __FUNCT__ "MatStashExpand_Private"
227c1ac3661SBarry Smith static PetscErrorCode MatStashExpand_Private(MatStash *stash,PetscInt incr)
2289417f4adSLois Curfman McInnes {
2296849ba73SBarry Smith   PetscErrorCode ierr;
2305bd3b8fbSHong Zhang   PetscInt       newnmax,bs2= stash->bs*stash->bs;
2319417f4adSLois Curfman McInnes 
2323a40ed3dSBarry Smith   PetscFunctionBegin;
2339417f4adSLois Curfman McInnes   /* allocate a larger stash */
234c481ceb5SSatish Balay   if (!stash->oldnmax && !stash->nmax) { /* new stash */
235434d7ff9SSatish Balay     if (stash->umax)                  newnmax = stash->umax/bs2;
236434d7ff9SSatish Balay     else                              newnmax = DEFAULT_STASH_SIZE/bs2;
237c481ceb5SSatish Balay   } else if (!stash->nmax) { /* resuing stash */
238434d7ff9SSatish Balay     if (stash->umax > stash->oldnmax) newnmax = stash->umax/bs2;
239434d7ff9SSatish Balay     else                              newnmax = stash->oldnmax/bs2;
240434d7ff9SSatish Balay   } else                              newnmax = stash->nmax*2;
2414c1ff481SSatish Balay   if (newnmax  < (stash->nmax + incr)) newnmax += 2*incr;
242d07ff455SSatish Balay 
24375cae7c1SHong Zhang   /* Get a MatStashSpace and attach it to stash */
24475cae7c1SHong Zhang   ierr = PetscMatStashSpaceGet(bs2,newnmax,&stash->space);CHKERRQ(ierr);
245b087b6d6SSatish Balay   if (!stash->space_head) { /* new stash or resuing stash->oldnmax */
246b087b6d6SSatish Balay     stash->space_head = stash->space;
24775cae7c1SHong Zhang   }
248b087b6d6SSatish Balay 
249bc5ccf88SSatish Balay   stash->reallocs++;
25075cae7c1SHong Zhang   stash->nmax = newnmax;
251bc5ccf88SSatish Balay   PetscFunctionReturn(0);
252bc5ccf88SSatish Balay }
253bc5ccf88SSatish Balay /*
2548798bf22SSatish Balay   MatStashValuesRow_Private - inserts values into the stash. This function
2554c1ff481SSatish Balay   expects the values to be roworiented. Multiple columns belong to the same row
2564c1ff481SSatish Balay   can be inserted with a single call to this function.
2574c1ff481SSatish Balay 
2584c1ff481SSatish Balay   Input Parameters:
2594c1ff481SSatish Balay   stash  - the stash
2604c1ff481SSatish Balay   row    - the global row correspoiding to the values
2614c1ff481SSatish Balay   n      - the number of elements inserted. All elements belong to the above row.
2624c1ff481SSatish Balay   idxn   - the global column indices corresponding to each of the values.
2634c1ff481SSatish Balay   values - the values inserted
264bc5ccf88SSatish Balay */
2654a2ae208SSatish Balay #undef __FUNCT__
2664a2ae208SSatish Balay #define __FUNCT__ "MatStashValuesRow_Private"
267ace3abfcSBarry Smith PetscErrorCode MatStashValuesRow_Private(MatStash *stash,PetscInt row,PetscInt n,const PetscInt idxn[],const PetscScalar values[],PetscBool ignorezeroentries)
268bc5ccf88SSatish Balay {
269dfbe8321SBarry Smith   PetscErrorCode     ierr;
270b400d20cSBarry Smith   PetscInt           i,k,cnt = 0;
27175cae7c1SHong Zhang   PetscMatStashSpace space=stash->space;
272bc5ccf88SSatish Balay 
273bc5ccf88SSatish Balay   PetscFunctionBegin;
2744c1ff481SSatish Balay   /* Check and see if we have sufficient memory */
27575cae7c1SHong Zhang   if (!space || space->local_remaining < n) {
2768798bf22SSatish Balay     ierr = MatStashExpand_Private(stash,n);CHKERRQ(ierr);
2779417f4adSLois Curfman McInnes   }
27875cae7c1SHong Zhang   space = stash->space;
27975cae7c1SHong Zhang   k     = space->local_used;
2804c1ff481SSatish Balay   for (i=0; i<n; i++) {
28188c3974fSBarry Smith     if (ignorezeroentries && (values[i] == 0.0)) continue;
28275cae7c1SHong Zhang     space->idx[k] = row;
28375cae7c1SHong Zhang     space->idy[k] = idxn[i];
28475cae7c1SHong Zhang     space->val[k] = values[i];
28575cae7c1SHong Zhang     k++;
286b400d20cSBarry Smith     cnt++;
2879417f4adSLois Curfman McInnes   }
288b400d20cSBarry Smith   stash->n               += cnt;
289b400d20cSBarry Smith   space->local_used      += cnt;
290b400d20cSBarry Smith   space->local_remaining -= cnt;
291a2d1c673SSatish Balay   PetscFunctionReturn(0);
292a2d1c673SSatish Balay }
29375cae7c1SHong Zhang 
2944c1ff481SSatish Balay /*
2958798bf22SSatish Balay   MatStashValuesCol_Private - inserts values into the stash. This function
2964c1ff481SSatish Balay   expects the values to be columnoriented. Multiple columns belong to the same row
2974c1ff481SSatish Balay   can be inserted with a single call to this function.
298a2d1c673SSatish Balay 
2994c1ff481SSatish Balay   Input Parameters:
3004c1ff481SSatish Balay   stash   - the stash
3014c1ff481SSatish Balay   row     - the global row correspoiding to the values
3024c1ff481SSatish Balay   n       - the number of elements inserted. All elements belong to the above row.
3034c1ff481SSatish Balay   idxn    - the global column indices corresponding to each of the values.
3044c1ff481SSatish Balay   values  - the values inserted
3054c1ff481SSatish Balay   stepval - the consecutive values are sepated by a distance of stepval.
3064c1ff481SSatish Balay             this happens because the input is columnoriented.
3074c1ff481SSatish Balay */
3084a2ae208SSatish Balay #undef __FUNCT__
3094a2ae208SSatish Balay #define __FUNCT__ "MatStashValuesCol_Private"
310ace3abfcSBarry Smith PetscErrorCode MatStashValuesCol_Private(MatStash *stash,PetscInt row,PetscInt n,const PetscInt idxn[],const PetscScalar values[],PetscInt stepval,PetscBool ignorezeroentries)
311a2d1c673SSatish Balay {
312dfbe8321SBarry Smith   PetscErrorCode     ierr;
31350e9ab7cSBarry Smith   PetscInt           i,k,cnt = 0;
31475cae7c1SHong Zhang   PetscMatStashSpace space=stash->space;
315a2d1c673SSatish Balay 
3164c1ff481SSatish Balay   PetscFunctionBegin;
3174c1ff481SSatish Balay   /* Check and see if we have sufficient memory */
31875cae7c1SHong Zhang   if (!space || space->local_remaining < n) {
3198798bf22SSatish Balay     ierr = MatStashExpand_Private(stash,n);CHKERRQ(ierr);
3204c1ff481SSatish Balay   }
32175cae7c1SHong Zhang   space = stash->space;
32275cae7c1SHong Zhang   k     = space->local_used;
3234c1ff481SSatish Balay   for (i=0; i<n; i++) {
32488c3974fSBarry Smith     if (ignorezeroentries && (values[i*stepval] == 0.0)) continue;
32575cae7c1SHong Zhang     space->idx[k] = row;
32675cae7c1SHong Zhang     space->idy[k] = idxn[i];
32775cae7c1SHong Zhang     space->val[k] = values[i*stepval];
32875cae7c1SHong Zhang     k++;
329b400d20cSBarry Smith     cnt++;
3304c1ff481SSatish Balay   }
331b400d20cSBarry Smith   stash->n               += cnt;
332b400d20cSBarry Smith   space->local_used      += cnt;
333b400d20cSBarry Smith   space->local_remaining -= cnt;
3344c1ff481SSatish Balay   PetscFunctionReturn(0);
3354c1ff481SSatish Balay }
3364c1ff481SSatish Balay 
3374c1ff481SSatish Balay /*
3388798bf22SSatish Balay   MatStashValuesRowBlocked_Private - inserts blocks of values into the stash.
3394c1ff481SSatish Balay   This function expects the values to be roworiented. Multiple columns belong
3404c1ff481SSatish Balay   to the same block-row can be inserted with a single call to this function.
3414c1ff481SSatish Balay   This function extracts the sub-block of values based on the dimensions of
3424c1ff481SSatish Balay   the original input block, and the row,col values corresponding to the blocks.
3434c1ff481SSatish Balay 
3444c1ff481SSatish Balay   Input Parameters:
3454c1ff481SSatish Balay   stash  - the stash
3464c1ff481SSatish Balay   row    - the global block-row correspoiding to the values
3474c1ff481SSatish Balay   n      - the number of elements inserted. All elements belong to the above row.
3484c1ff481SSatish Balay   idxn   - the global block-column indices corresponding to each of the blocks of
3494c1ff481SSatish Balay            values. Each block is of size bs*bs.
3504c1ff481SSatish Balay   values - the values inserted
3514c1ff481SSatish Balay   rmax   - the number of block-rows in the original block.
3524c1ff481SSatish Balay   cmax   - the number of block-columsn on the original block.
3534c1ff481SSatish Balay   idx    - the index of the current block-row in the original block.
3544c1ff481SSatish Balay */
3554a2ae208SSatish Balay #undef __FUNCT__
3564a2ae208SSatish Balay #define __FUNCT__ "MatStashValuesRowBlocked_Private"
35754f21887SBarry Smith PetscErrorCode MatStashValuesRowBlocked_Private(MatStash *stash,PetscInt row,PetscInt n,const PetscInt idxn[],const PetscScalar values[],PetscInt rmax,PetscInt cmax,PetscInt idx)
3584c1ff481SSatish Balay {
359dfbe8321SBarry Smith   PetscErrorCode     ierr;
36075cae7c1SHong Zhang   PetscInt           i,j,k,bs2,bs=stash->bs,l;
36154f21887SBarry Smith   const PetscScalar  *vals;
36254f21887SBarry Smith   PetscScalar        *array;
36375cae7c1SHong Zhang   PetscMatStashSpace space=stash->space;
364a2d1c673SSatish Balay 
365a2d1c673SSatish Balay   PetscFunctionBegin;
36675cae7c1SHong Zhang   if (!space || space->local_remaining < n) {
3678798bf22SSatish Balay     ierr = MatStashExpand_Private(stash,n);CHKERRQ(ierr);
368a2d1c673SSatish Balay   }
36975cae7c1SHong Zhang   space = stash->space;
37075cae7c1SHong Zhang   l     = space->local_used;
37175cae7c1SHong Zhang   bs2   = bs*bs;
3724c1ff481SSatish Balay   for (i=0; i<n; i++) {
37375cae7c1SHong Zhang     space->idx[l] = row;
37475cae7c1SHong Zhang     space->idy[l] = idxn[i];
37575cae7c1SHong Zhang     /* Now copy over the block of values. Store the values column oriented.
37675cae7c1SHong Zhang        This enables inserting multiple blocks belonging to a row with a single
37775cae7c1SHong Zhang        funtion call */
37875cae7c1SHong Zhang     array = space->val + bs2*l;
37975cae7c1SHong Zhang     vals  = values + idx*bs2*n + bs*i;
38075cae7c1SHong Zhang     for (j=0; j<bs; j++) {
38175cae7c1SHong Zhang       for (k=0; k<bs; k++) array[k*bs] = vals[k];
38275cae7c1SHong Zhang       array++;
38375cae7c1SHong Zhang       vals += cmax*bs;
38475cae7c1SHong Zhang     }
38575cae7c1SHong Zhang     l++;
386a2d1c673SSatish Balay   }
3875bd3b8fbSHong Zhang   stash->n               += n;
38875cae7c1SHong Zhang   space->local_used      += n;
38975cae7c1SHong Zhang   space->local_remaining -= n;
3904c1ff481SSatish Balay   PetscFunctionReturn(0);
3914c1ff481SSatish Balay }
3924c1ff481SSatish Balay 
3934c1ff481SSatish Balay /*
3948798bf22SSatish Balay   MatStashValuesColBlocked_Private - inserts blocks of values into the stash.
3954c1ff481SSatish Balay   This function expects the values to be roworiented. Multiple columns belong
3964c1ff481SSatish Balay   to the same block-row can be inserted with a single call to this function.
3974c1ff481SSatish Balay   This function extracts the sub-block of values based on the dimensions of
3984c1ff481SSatish Balay   the original input block, and the row,col values corresponding to the blocks.
3994c1ff481SSatish Balay 
4004c1ff481SSatish Balay   Input Parameters:
4014c1ff481SSatish Balay   stash  - the stash
4024c1ff481SSatish Balay   row    - the global block-row correspoiding to the values
4034c1ff481SSatish Balay   n      - the number of elements inserted. All elements belong to the above row.
4044c1ff481SSatish Balay   idxn   - the global block-column indices corresponding to each of the blocks of
4054c1ff481SSatish Balay            values. Each block is of size bs*bs.
4064c1ff481SSatish Balay   values - the values inserted
4074c1ff481SSatish Balay   rmax   - the number of block-rows in the original block.
4084c1ff481SSatish Balay   cmax   - the number of block-columsn on the original block.
4094c1ff481SSatish Balay   idx    - the index of the current block-row in the original block.
4104c1ff481SSatish Balay */
4114a2ae208SSatish Balay #undef __FUNCT__
4124a2ae208SSatish Balay #define __FUNCT__ "MatStashValuesColBlocked_Private"
41354f21887SBarry Smith PetscErrorCode MatStashValuesColBlocked_Private(MatStash *stash,PetscInt row,PetscInt n,const PetscInt idxn[],const PetscScalar values[],PetscInt rmax,PetscInt cmax,PetscInt idx)
4144c1ff481SSatish Balay {
415dfbe8321SBarry Smith   PetscErrorCode     ierr;
41675cae7c1SHong Zhang   PetscInt           i,j,k,bs2,bs=stash->bs,l;
41754f21887SBarry Smith   const PetscScalar  *vals;
41854f21887SBarry Smith   PetscScalar        *array;
41975cae7c1SHong Zhang   PetscMatStashSpace space=stash->space;
4204c1ff481SSatish Balay 
4214c1ff481SSatish Balay   PetscFunctionBegin;
42275cae7c1SHong Zhang   if (!space || space->local_remaining < n) {
4238798bf22SSatish Balay     ierr = MatStashExpand_Private(stash,n);CHKERRQ(ierr);
4244c1ff481SSatish Balay   }
42575cae7c1SHong Zhang   space = stash->space;
42675cae7c1SHong Zhang   l     = space->local_used;
42775cae7c1SHong Zhang   bs2   = bs*bs;
4284c1ff481SSatish Balay   for (i=0; i<n; i++) {
42975cae7c1SHong Zhang     space->idx[l] = row;
43075cae7c1SHong Zhang     space->idy[l] = idxn[i];
43175cae7c1SHong Zhang     /* Now copy over the block of values. Store the values column oriented.
43275cae7c1SHong Zhang      This enables inserting multiple blocks belonging to a row with a single
43375cae7c1SHong Zhang      funtion call */
43475cae7c1SHong Zhang     array = space->val + bs2*l;
43575cae7c1SHong Zhang     vals  = values + idx*bs2*n + bs*i;
43675cae7c1SHong Zhang     for (j=0; j<bs; j++) {
4378865f1eaSKarl Rupp       for (k=0; k<bs; k++) array[k] = vals[k];
43875cae7c1SHong Zhang       array += bs;
43975cae7c1SHong Zhang       vals  += rmax*bs;
44075cae7c1SHong Zhang     }
4415bd3b8fbSHong Zhang     l++;
442a2d1c673SSatish Balay   }
4435bd3b8fbSHong Zhang   stash->n               += n;
44475cae7c1SHong Zhang   space->local_used      += n;
44575cae7c1SHong Zhang   space->local_remaining -= n;
4463a40ed3dSBarry Smith   PetscFunctionReturn(0);
4479417f4adSLois Curfman McInnes }
4484c1ff481SSatish Balay /*
4498798bf22SSatish Balay   MatStashScatterBegin_Private - Initiates the transfer of values to the
4504c1ff481SSatish Balay   correct owners. This function goes through the stash, and check the
4514c1ff481SSatish Balay   owners of each stashed value, and sends the values off to the owner
4524c1ff481SSatish Balay   processors.
453bc5ccf88SSatish Balay 
4544c1ff481SSatish Balay   Input Parameters:
4554c1ff481SSatish Balay   stash  - the stash
4564c1ff481SSatish Balay   owners - an array of size 'no-of-procs' which gives the ownership range
4574c1ff481SSatish Balay            for each node.
4584c1ff481SSatish Balay 
4594c1ff481SSatish Balay   Notes: The 'owners' array in the cased of the blocked-stash has the
4604c1ff481SSatish Balay   ranges specified blocked global indices, and for the regular stash in
4614c1ff481SSatish Balay   the proper global indices.
4624c1ff481SSatish Balay */
4634a2ae208SSatish Balay #undef __FUNCT__
4644a2ae208SSatish Balay #define __FUNCT__ "MatStashScatterBegin_Private"
4651e2582c4SBarry Smith PetscErrorCode MatStashScatterBegin_Private(Mat mat,MatStash *stash,PetscInt *owners)
466bc5ccf88SSatish Balay {
467*ac2b2aa0SJed Brown   PetscErrorCode ierr;
468*ac2b2aa0SJed Brown 
469*ac2b2aa0SJed Brown   PetscFunctionBegin;
470*ac2b2aa0SJed Brown   ierr = (*stash->ScatterBegin)(mat,stash,owners);CHKERRQ(ierr);
471*ac2b2aa0SJed Brown   PetscFunctionReturn(0);
472*ac2b2aa0SJed Brown }
473*ac2b2aa0SJed Brown 
474*ac2b2aa0SJed Brown #undef __FUNCT__
475*ac2b2aa0SJed Brown #define __FUNCT__ "MatStashScatterBegin_Ref"
476*ac2b2aa0SJed Brown static PetscErrorCode MatStashScatterBegin_Ref(Mat mat,MatStash *stash,PetscInt *owners)
477*ac2b2aa0SJed Brown {
478c1ac3661SBarry Smith   PetscInt           *owner,*startv,*starti,tag1=stash->tag1,tag2=stash->tag2,bs2;
479fe09c992SBarry Smith   PetscInt           size=stash->size,nsends;
4806849ba73SBarry Smith   PetscErrorCode     ierr;
48175cae7c1SHong Zhang   PetscInt           count,*sindices,**rindices,i,j,idx,lastidx,l;
48254f21887SBarry Smith   PetscScalar        **rvalues,*svalues;
483bc5ccf88SSatish Balay   MPI_Comm           comm = stash->comm;
484563fb871SSatish Balay   MPI_Request        *send_waits,*recv_waits,*recv_waits1,*recv_waits2;
48576ec1555SBarry Smith   PetscMPIInt        *sizes,*nlengths,nreceives;
4865bd3b8fbSHong Zhang   PetscInt           *sp_idx,*sp_idy;
48754f21887SBarry Smith   PetscScalar        *sp_val;
4885bd3b8fbSHong Zhang   PetscMatStashSpace space,space_next;
489bc5ccf88SSatish Balay 
490bc5ccf88SSatish Balay   PetscFunctionBegin;
4914c1ff481SSatish Balay   bs2 = stash->bs*stash->bs;
49275cae7c1SHong Zhang 
493bc5ccf88SSatish Balay   /*  first count number of contributors to each processor */
494037dbc42SBarry Smith   ierr = PetscCalloc1(size,&sizes);CHKERRQ(ierr);
4951795a4d1SJed Brown   ierr = PetscCalloc1(size,&nlengths);CHKERRQ(ierr);
496037dbc42SBarry Smith   ierr = PetscMalloc1(stash->n+1,&owner);CHKERRQ(ierr);
497a2d1c673SSatish Balay 
49875cae7c1SHong Zhang   i       = j    = 0;
4997357eb19SBarry Smith   lastidx = -1;
5005bd3b8fbSHong Zhang   space   = stash->space_head;
5010298fd71SBarry Smith   while (space != NULL) {
50275cae7c1SHong Zhang     space_next = space->next;
5035bd3b8fbSHong Zhang     sp_idx     = space->idx;
50475cae7c1SHong Zhang     for (l=0; l<space->local_used; l++) {
5057357eb19SBarry Smith       /* if indices are NOT locally sorted, need to start search at the beginning */
5065bd3b8fbSHong Zhang       if (lastidx > (idx = sp_idx[l])) j = 0;
5077357eb19SBarry Smith       lastidx = idx;
5087357eb19SBarry Smith       for (; j<size; j++) {
5094c1ff481SSatish Balay         if (idx >= owners[j] && idx < owners[j+1]) {
510563fb871SSatish Balay           nlengths[j]++; owner[i] = j; break;
511bc5ccf88SSatish Balay         }
512bc5ccf88SSatish Balay       }
51375cae7c1SHong Zhang       i++;
51475cae7c1SHong Zhang     }
51575cae7c1SHong Zhang     space = space_next;
516bc5ccf88SSatish Balay   }
517563fb871SSatish Balay   /* Now check what procs get messages - and compute nsends. */
518563fb871SSatish Balay   for (i=0, nsends=0; i<size; i++) {
5198865f1eaSKarl Rupp     if (nlengths[i]) {
52076ec1555SBarry Smith       sizes[i] = 1; nsends++;
5218865f1eaSKarl Rupp     }
522563fb871SSatish Balay   }
523bc5ccf88SSatish Balay 
52454f21887SBarry Smith   {PetscMPIInt *onodes,*olengths;
525563fb871SSatish Balay    /* Determine the number of messages to expect, their lengths, from from-ids */
52676ec1555SBarry Smith    ierr = PetscGatherNumberOfMessages(comm,sizes,nlengths,&nreceives);CHKERRQ(ierr);
527563fb871SSatish Balay    ierr = PetscGatherMessageLengths(comm,nsends,nreceives,nlengths,&onodes,&olengths);CHKERRQ(ierr);
528563fb871SSatish Balay    /* since clubbing row,col - lengths are multiplied by 2 */
529563fb871SSatish Balay    for (i=0; i<nreceives; i++) olengths[i] *=2;
530563fb871SSatish Balay    ierr = PetscPostIrecvInt(comm,tag1,nreceives,onodes,olengths,&rindices,&recv_waits1);CHKERRQ(ierr);
531563fb871SSatish Balay    /* values are size 'bs2' lengths (and remove earlier factor 2 */
532563fb871SSatish Balay    for (i=0; i<nreceives; i++) olengths[i] = olengths[i]*bs2/2;
533563fb871SSatish Balay    ierr = PetscPostIrecvScalar(comm,tag2,nreceives,onodes,olengths,&rvalues,&recv_waits2);CHKERRQ(ierr);
534563fb871SSatish Balay    ierr = PetscFree(onodes);CHKERRQ(ierr);
5358865f1eaSKarl Rupp    ierr = PetscFree(olengths);CHKERRQ(ierr);}
536bc5ccf88SSatish Balay 
537bc5ccf88SSatish Balay   /* do sends:
538bc5ccf88SSatish Balay       1) starts[i] gives the starting index in svalues for stuff going to
539bc5ccf88SSatish Balay          the ith processor
540bc5ccf88SSatish Balay   */
541dcca6d9dSJed Brown   ierr = PetscMalloc2(bs2*stash->n,&svalues,2*(stash->n+1),&sindices);CHKERRQ(ierr);
542785e854fSJed Brown   ierr = PetscMalloc1(2*nsends,&send_waits);CHKERRQ(ierr);
543dcca6d9dSJed Brown   ierr = PetscMalloc2(size,&startv,size,&starti);CHKERRQ(ierr);
544a2d1c673SSatish Balay   /* use 2 sends the first with all_a, the next with all_i and all_j */
545bc5ccf88SSatish Balay   startv[0] = 0; starti[0] = 0;
546bc5ccf88SSatish Balay   for (i=1; i<size; i++) {
547563fb871SSatish Balay     startv[i] = startv[i-1] + nlengths[i-1];
548533163c2SBarry Smith     starti[i] = starti[i-1] + 2*nlengths[i-1];
549bc5ccf88SSatish Balay   }
55075cae7c1SHong Zhang 
55175cae7c1SHong Zhang   i     = 0;
5525bd3b8fbSHong Zhang   space = stash->space_head;
5530298fd71SBarry Smith   while (space != NULL) {
55475cae7c1SHong Zhang     space_next = space->next;
5555bd3b8fbSHong Zhang     sp_idx     = space->idx;
5565bd3b8fbSHong Zhang     sp_idy     = space->idy;
5575bd3b8fbSHong Zhang     sp_val     = space->val;
55875cae7c1SHong Zhang     for (l=0; l<space->local_used; l++) {
559bc5ccf88SSatish Balay       j = owner[i];
560a2d1c673SSatish Balay       if (bs2 == 1) {
5615bd3b8fbSHong Zhang         svalues[startv[j]] = sp_val[l];
562a2d1c673SSatish Balay       } else {
563c1ac3661SBarry Smith         PetscInt    k;
56454f21887SBarry Smith         PetscScalar *buf1,*buf2;
5654c1ff481SSatish Balay         buf1 = svalues+bs2*startv[j];
566b087b6d6SSatish Balay         buf2 = space->val + bs2*l;
5678865f1eaSKarl Rupp         for (k=0; k<bs2; k++) buf1[k] = buf2[k];
568a2d1c673SSatish Balay       }
5695bd3b8fbSHong Zhang       sindices[starti[j]]             = sp_idx[l];
5705bd3b8fbSHong Zhang       sindices[starti[j]+nlengths[j]] = sp_idy[l];
571bc5ccf88SSatish Balay       startv[j]++;
572bc5ccf88SSatish Balay       starti[j]++;
57375cae7c1SHong Zhang       i++;
57475cae7c1SHong Zhang     }
57575cae7c1SHong Zhang     space = space_next;
576bc5ccf88SSatish Balay   }
577bc5ccf88SSatish Balay   startv[0] = 0;
5788865f1eaSKarl Rupp   for (i=1; i<size; i++) startv[i] = startv[i-1] + nlengths[i-1];
579e5d0e772SSatish Balay 
580bc5ccf88SSatish Balay   for (i=0,count=0; i<size; i++) {
58176ec1555SBarry Smith     if (sizes[i]) {
582563fb871SSatish Balay       ierr = MPI_Isend(sindices+2*startv[i],2*nlengths[i],MPIU_INT,i,tag1,comm,send_waits+count++);CHKERRQ(ierr);
583a77337e4SBarry Smith       ierr = MPI_Isend(svalues+bs2*startv[i],bs2*nlengths[i],MPIU_SCALAR,i,tag2,comm,send_waits+count++);CHKERRQ(ierr);
584bc5ccf88SSatish Balay     }
585b85c94c3SSatish Balay   }
5866cf91177SBarry Smith #if defined(PETSC_USE_INFO)
58793157e10SBarry Smith   ierr = PetscInfo1(NULL,"No of messages: %d \n",nsends);CHKERRQ(ierr);
588e5d0e772SSatish Balay   for (i=0; i<size; i++) {
58976ec1555SBarry Smith     if (sizes[i]) {
59030c47e72SSatish Balay       ierr = PetscInfo2(NULL,"Mesg_to: %d: size: %d bytes\n",i,nlengths[i]*(bs2*sizeof(PetscScalar)+2*sizeof(PetscInt)));CHKERRQ(ierr);
591e5d0e772SSatish Balay     }
592e5d0e772SSatish Balay   }
593e5d0e772SSatish Balay #endif
594c05d87d6SBarry Smith   ierr = PetscFree(nlengths);CHKERRQ(ierr);
595606d414cSSatish Balay   ierr = PetscFree(owner);CHKERRQ(ierr);
596c05d87d6SBarry Smith   ierr = PetscFree2(startv,starti);CHKERRQ(ierr);
59776ec1555SBarry Smith   ierr = PetscFree(sizes);CHKERRQ(ierr);
598a2d1c673SSatish Balay 
599563fb871SSatish Balay   /* recv_waits need to be contiguous for MatStashScatterGetMesg_Private() */
600785e854fSJed Brown   ierr = PetscMalloc1(2*nreceives,&recv_waits);CHKERRQ(ierr);
601563fb871SSatish Balay 
602563fb871SSatish Balay   for (i=0; i<nreceives; i++) {
603563fb871SSatish Balay     recv_waits[2*i]   = recv_waits1[i];
604563fb871SSatish Balay     recv_waits[2*i+1] = recv_waits2[i];
605563fb871SSatish Balay   }
606563fb871SSatish Balay   stash->recv_waits = recv_waits;
6078865f1eaSKarl Rupp 
608563fb871SSatish Balay   ierr = PetscFree(recv_waits1);CHKERRQ(ierr);
609563fb871SSatish Balay   ierr = PetscFree(recv_waits2);CHKERRQ(ierr);
610563fb871SSatish Balay 
611c05d87d6SBarry Smith   stash->svalues         = svalues;
612c05d87d6SBarry Smith   stash->sindices        = sindices;
613c05d87d6SBarry Smith   stash->rvalues         = rvalues;
614c05d87d6SBarry Smith   stash->rindices        = rindices;
615c05d87d6SBarry Smith   stash->send_waits      = send_waits;
616c05d87d6SBarry Smith   stash->nsends          = nsends;
617c05d87d6SBarry Smith   stash->nrecvs          = nreceives;
61867318a8aSJed Brown   stash->reproduce_count = 0;
619bc5ccf88SSatish Balay   PetscFunctionReturn(0);
620bc5ccf88SSatish Balay }
621bc5ccf88SSatish Balay 
622a2d1c673SSatish Balay /*
6238798bf22SSatish Balay    MatStashScatterGetMesg_Private - This function waits on the receives posted
6248798bf22SSatish Balay    in the function MatStashScatterBegin_Private() and returns one message at
6254c1ff481SSatish Balay    a time to the calling function. If no messages are left, it indicates this
6264c1ff481SSatish Balay    by setting flg = 0, else it sets flg = 1.
6274c1ff481SSatish Balay 
6284c1ff481SSatish Balay    Input Parameters:
6294c1ff481SSatish Balay    stash - the stash
6304c1ff481SSatish Balay 
6314c1ff481SSatish Balay    Output Parameters:
6324c1ff481SSatish Balay    nvals - the number of entries in the current message.
6334c1ff481SSatish Balay    rows  - an array of row indices (or blocked indices) corresponding to the values
6344c1ff481SSatish Balay    cols  - an array of columnindices (or blocked indices) corresponding to the values
6354c1ff481SSatish Balay    vals  - the values
6364c1ff481SSatish Balay    flg   - 0 indicates no more message left, and the current call has no values associated.
6374c1ff481SSatish Balay            1 indicates that the current call successfully received a message, and the
6384c1ff481SSatish Balay              other output parameters nvals,rows,cols,vals are set appropriately.
639a2d1c673SSatish Balay */
6404a2ae208SSatish Balay #undef __FUNCT__
6414a2ae208SSatish Balay #define __FUNCT__ "MatStashScatterGetMesg_Private"
64254f21887SBarry Smith PetscErrorCode MatStashScatterGetMesg_Private(MatStash *stash,PetscMPIInt *nvals,PetscInt **rows,PetscInt **cols,PetscScalar **vals,PetscInt *flg)
643bc5ccf88SSatish Balay {
6446849ba73SBarry Smith   PetscErrorCode ierr;
645*ac2b2aa0SJed Brown 
646*ac2b2aa0SJed Brown   PetscFunctionBegin;
647*ac2b2aa0SJed Brown   ierr = (*stash->ScatterGetMesg)(stash,nvals,rows,cols,vals,flg);CHKERRQ(ierr);
648*ac2b2aa0SJed Brown   PetscFunctionReturn(0);
649*ac2b2aa0SJed Brown }
650*ac2b2aa0SJed Brown 
651*ac2b2aa0SJed Brown #undef __FUNCT__
652*ac2b2aa0SJed Brown #define __FUNCT__ "MatStashScatterGetMesg_Ref"
653*ac2b2aa0SJed Brown static PetscErrorCode MatStashScatterGetMesg_Ref(MatStash *stash,PetscMPIInt *nvals,PetscInt **rows,PetscInt **cols,PetscScalar **vals,PetscInt *flg)
654*ac2b2aa0SJed Brown {
655*ac2b2aa0SJed Brown   PetscErrorCode ierr;
656533163c2SBarry Smith   PetscMPIInt    i,*flg_v = stash->flg_v,i1,i2;
657fe09c992SBarry Smith   PetscInt       bs2;
658a2d1c673SSatish Balay   MPI_Status     recv_status;
659ace3abfcSBarry Smith   PetscBool      match_found = PETSC_FALSE;
660bc5ccf88SSatish Balay 
661bc5ccf88SSatish Balay   PetscFunctionBegin;
662a2d1c673SSatish Balay   *flg = 0; /* When a message is discovered this is reset to 1 */
663a2d1c673SSatish Balay   /* Return if no more messages to process */
6648865f1eaSKarl Rupp   if (stash->nprocessed == stash->nrecvs) PetscFunctionReturn(0);
665a2d1c673SSatish Balay 
6664c1ff481SSatish Balay   bs2 = stash->bs*stash->bs;
66767318a8aSJed Brown   /* If a matching pair of receives are found, process them, and return the data to
668a2d1c673SSatish Balay      the calling function. Until then keep receiving messages */
669a2d1c673SSatish Balay   while (!match_found) {
67067318a8aSJed Brown     if (stash->reproduce) {
67167318a8aSJed Brown       i    = stash->reproduce_count++;
67267318a8aSJed Brown       ierr = MPI_Wait(stash->recv_waits+i,&recv_status);CHKERRQ(ierr);
67367318a8aSJed Brown     } else {
674a2d1c673SSatish Balay       ierr = MPI_Waitany(2*stash->nrecvs,stash->recv_waits,&i,&recv_status);CHKERRQ(ierr);
67567318a8aSJed Brown     }
676e32f2f54SBarry Smith     if (recv_status.MPI_SOURCE < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Negative MPI source!");
677533163c2SBarry Smith 
67867318a8aSJed Brown     /* Now pack the received message into a structure which is usable by others */
679a2d1c673SSatish Balay     if (i % 2) {
680a77337e4SBarry Smith       ierr = MPI_Get_count(&recv_status,MPIU_SCALAR,nvals);CHKERRQ(ierr);
6818865f1eaSKarl Rupp 
682c1dc657dSBarry Smith       flg_v[2*recv_status.MPI_SOURCE] = i/2;
6838865f1eaSKarl Rupp 
684a2d1c673SSatish Balay       *nvals = *nvals/bs2;
685563fb871SSatish Balay     } else {
686563fb871SSatish Balay       ierr = MPI_Get_count(&recv_status,MPIU_INT,nvals);CHKERRQ(ierr);
6878865f1eaSKarl Rupp 
688563fb871SSatish Balay       flg_v[2*recv_status.MPI_SOURCE+1] = i/2;
6898865f1eaSKarl Rupp 
690563fb871SSatish Balay       *nvals = *nvals/2; /* This message has both row indices and col indices */
691bc5ccf88SSatish Balay     }
692a2d1c673SSatish Balay 
693cb2b73ccSBarry Smith     /* Check if we have both messages from this proc */
694c1dc657dSBarry Smith     i1 = flg_v[2*recv_status.MPI_SOURCE];
695c1dc657dSBarry Smith     i2 = flg_v[2*recv_status.MPI_SOURCE+1];
696a2d1c673SSatish Balay     if (i1 != -1 && i2 != -1) {
697563fb871SSatish Balay       *rows = stash->rindices[i2];
698a2d1c673SSatish Balay       *cols = *rows + *nvals;
699563fb871SSatish Balay       *vals = stash->rvalues[i1];
700a2d1c673SSatish Balay       *flg  = 1;
701a2d1c673SSatish Balay       stash->nprocessed++;
70235d8aa7fSBarry Smith       match_found = PETSC_TRUE;
703bc5ccf88SSatish Balay     }
704bc5ccf88SSatish Balay   }
705bc5ccf88SSatish Balay   PetscFunctionReturn(0);
706bc5ccf88SSatish Balay }
707