xref: /petsc/src/mat/impls/sbaij/mpi/mmsbaij.c (revision 7cff14251fee5e64e42567ef603020fb7101bc78)
173f4d377SMatthew Knepley /*$Id: mmsbaij.c,v 1.10 2001/08/07 03:03:05 balay Exp $*/
2a30f8f8cSSatish Balay 
3a30f8f8cSSatish Balay /*
4a30f8f8cSSatish Balay    Support for the parallel SBAIJ matrix vector multiply
5a30f8f8cSSatish Balay */
62896befeSSatish Balay #include "src/mat/impls/sbaij/mpi/mpisbaij.h"
7a30f8f8cSSatish Balay #include "src/vec/vecimpl.h"
8*7cff1425SSatish Balay 
9*7cff1425SSatish Balay extern int MatSetValues_SeqSBAIJ(Mat,int,const int [],int,const int [],const PetscScalar [],InsertMode);
10*7cff1425SSatish Balay 
11a30f8f8cSSatish Balay 
124a2ae208SSatish Balay #undef __FUNCT__
134a2ae208SSatish Balay #define __FUNCT__ "MatSetUpMultiply_MPISBAIJ"
14a30f8f8cSSatish Balay int MatSetUpMultiply_MPISBAIJ(Mat mat)
15a30f8f8cSSatish Balay {
1640781036SHong Zhang   Mat_MPISBAIJ       *sbaij = (Mat_MPISBAIJ*)mat->data;
1740781036SHong Zhang   Mat_SeqBAIJ        *B = (Mat_SeqBAIJ*)(sbaij->B->data);
1840781036SHong Zhang   int                Nbs = sbaij->Nbs,i,j,*indices,*aj = B->j,ierr,ec = 0,*garray,*sgarray;
1940781036SHong Zhang   int                bs = sbaij->bs,*stmp,mbs=sbaij->mbs, vec_size,nt;
2040781036SHong Zhang   IS                 from,to;
2140781036SHong Zhang   Vec                gvec;
2240781036SHong Zhang   int                rank=sbaij->rank,lsize,size=sbaij->size;
23b424e231SHong Zhang   int                *owners=sbaij->rowners,*sowners,*ec_owner,k;
2440781036SHong Zhang   PetscMap           vecmap;
2540781036SHong Zhang   PetscScalar        *ptr;
2640781036SHong Zhang 
2740781036SHong Zhang   PetscFunctionBegin;
2840781036SHong Zhang   if (sbaij->lvec) {
2940781036SHong Zhang     ierr = VecDestroy(sbaij->lvec);CHKERRQ(ierr);
3040781036SHong Zhang     sbaij->lvec = 0;
3140781036SHong Zhang   }
3240781036SHong Zhang   if (sbaij->Mvctx) {
3340781036SHong Zhang     ierr = VecScatterDestroy(sbaij->Mvctx);CHKERRQ(ierr);
3440781036SHong Zhang     sbaij->Mvctx = 0;
3540781036SHong Zhang   }
3640781036SHong Zhang 
3740781036SHong Zhang   /* For the first stab we make an array as long as the number of columns */
3840781036SHong Zhang   /* mark those columns that are in sbaij->B */
3940781036SHong Zhang   ierr = PetscMalloc((Nbs+1)*sizeof(int),&indices);CHKERRQ(ierr);
4040781036SHong Zhang   ierr = PetscMemzero(indices,Nbs*sizeof(int));CHKERRQ(ierr);
4140781036SHong Zhang   for (i=0; i<mbs; i++) {
4240781036SHong Zhang     for (j=0; j<B->ilen[i]; j++) {
4340781036SHong Zhang       if (!indices[aj[B->i[i] + j]]) ec++;
4440781036SHong Zhang       indices[aj[B->i[i] + j] ] = 1;
4540781036SHong Zhang     }
4640781036SHong Zhang   }
4740781036SHong Zhang 
4840781036SHong Zhang   /* form arrays of columns we need */
4940781036SHong Zhang   ierr = PetscMalloc((ec+1)*sizeof(int),&garray);CHKERRQ(ierr);
5040781036SHong Zhang   ierr = PetscMalloc((3*ec+1)*sizeof(int),&sgarray);CHKERRQ(ierr);
5140781036SHong Zhang   ec_owner = sgarray + 2*ec;
5240781036SHong Zhang 
5340781036SHong Zhang   ec = 0;
5440781036SHong Zhang   for (j=0; j<size; j++){
5540781036SHong Zhang     for (i=owners[j]; i<owners[j+1]; i++){
5640781036SHong Zhang       if (indices[i]) {
5740781036SHong Zhang         garray[ec]   = i;
5840781036SHong Zhang         ec_owner[ec] = j;
5940781036SHong Zhang         ec++;
6040781036SHong Zhang       }
6140781036SHong Zhang     }
6240781036SHong Zhang   }
6340781036SHong Zhang 
6440781036SHong Zhang   /* make indices now point into garray */
65b424e231SHong Zhang   for (i=0; i<ec; i++) indices[garray[i]] = i;
6640781036SHong Zhang 
6740781036SHong Zhang   /* compact out the extra columns in B */
6840781036SHong Zhang   for (i=0; i<mbs; i++) {
6940781036SHong Zhang     for (j=0; j<B->ilen[i]; j++) aj[B->i[i] + j] = indices[aj[B->i[i] + j]];
7040781036SHong Zhang   }
7140781036SHong Zhang   B->nbs       = ec;
7240781036SHong Zhang   sbaij->B->n   = ec*B->bs;
7340781036SHong Zhang   ierr = PetscFree(indices);CHKERRQ(ierr);
7440781036SHong Zhang 
7540781036SHong Zhang   /* create local vector that is used to scatter into */
7640781036SHong Zhang   ierr = VecCreateSeq(PETSC_COMM_SELF,ec*bs,&sbaij->lvec);CHKERRQ(ierr);
7740781036SHong Zhang 
7840781036SHong Zhang   /* create two temporary index sets for building scatter-gather */
7940781036SHong Zhang   ierr = PetscMalloc((2*ec+1)*sizeof(int),&stmp);CHKERRQ(ierr);
8040781036SHong Zhang   for (i=0; i<ec; i++) stmp[i] = bs*garray[i];
8140781036SHong Zhang   ierr = ISCreateBlock(PETSC_COMM_SELF,bs,ec,stmp,&from);CHKERRQ(ierr);
8240781036SHong Zhang 
8340781036SHong Zhang   for (i=0; i<ec; i++) { stmp[i] = bs*i; }
8440781036SHong Zhang   ierr = ISCreateBlock(PETSC_COMM_SELF,bs,ec,stmp,&to);CHKERRQ(ierr);
8540781036SHong Zhang 
8640781036SHong Zhang   /* generate the scatter context */
8740781036SHong Zhang   ierr = VecCreateMPI(mat->comm,mat->n,mat->N,&gvec);CHKERRQ(ierr);
8840781036SHong Zhang   ierr = VecScatterCreate(gvec,from,sbaij->lvec,to,&sbaij->Mvctx);CHKERRQ(ierr);
8940781036SHong Zhang   ierr = VecScatterPostRecvs(gvec,sbaij->lvec,INSERT_VALUES,SCATTER_FORWARD,sbaij->Mvctx);CHKERRQ(ierr);
9040781036SHong Zhang 
9140781036SHong Zhang   sbaij->garray = garray;
9240781036SHong Zhang   PetscLogObjectParent(mat,sbaij->Mvctx);
9340781036SHong Zhang   PetscLogObjectParent(mat,sbaij->lvec);
9440781036SHong Zhang   PetscLogObjectParent(mat,from);
9540781036SHong Zhang   PetscLogObjectParent(mat,to);
9640781036SHong Zhang 
9740781036SHong Zhang   ierr = ISDestroy(from);CHKERRQ(ierr);
9840781036SHong Zhang   ierr = ISDestroy(to);CHKERRQ(ierr);
9940781036SHong Zhang 
10040781036SHong Zhang   /* create parallel vector that is used by SBAIJ matrix to scatter from/into */
10140781036SHong Zhang   lsize = (mbs + ec)*bs;
10240781036SHong Zhang   ierr = VecCreateMPI(mat->comm,lsize,PETSC_DETERMINE,&sbaij->slvec0);CHKERRQ(ierr);
10340781036SHong Zhang   ierr = VecDuplicate(sbaij->slvec0,&sbaij->slvec1);CHKERRQ(ierr);
10440781036SHong Zhang   ierr = VecGetSize(sbaij->slvec0,&vec_size);CHKERRQ(ierr);
10540781036SHong Zhang 
10640781036SHong Zhang   ierr = VecGetPetscMap(sbaij->slvec0,&vecmap);CHKERRQ(ierr);
10740781036SHong Zhang   ierr = PetscMapGetGlobalRange(vecmap,&sowners);CHKERRQ(ierr);
10840781036SHong Zhang 
10940781036SHong Zhang   /* x index in the IS sfrom */
11040781036SHong Zhang   for (i=0; i<ec; i++) {
11140781036SHong Zhang     j = ec_owner[i];
11240781036SHong Zhang     sgarray[i]  = garray[i] + (sowners[j]/bs - owners[j]);
11340781036SHong Zhang   }
11440781036SHong Zhang   /* b index in the IS sfrom */
11540781036SHong Zhang   k = sowners[rank]/bs + mbs;
11640781036SHong Zhang   for (i=ec,j=0; i< 2*ec; i++,j++) sgarray[i] = k + j;
11740781036SHong Zhang 
11840781036SHong Zhang   for (i=0; i<2*ec; i++) stmp[i] = bs*sgarray[i];
11940781036SHong Zhang   ierr = ISCreateBlock(PETSC_COMM_SELF,bs,2*ec,stmp,&from);CHKERRQ(ierr);
12040781036SHong Zhang 
12140781036SHong Zhang   /* x index in the IS sto */
12240781036SHong Zhang   k = sowners[rank]/bs + mbs;
12340781036SHong Zhang   for (i=0; i<ec; i++) stmp[i] = bs*(k + i);
12440781036SHong Zhang   /* b index in the IS sto */
12540781036SHong Zhang   for (i=ec; i<2*ec; i++) stmp[i] = bs*sgarray[i-ec];
12640781036SHong Zhang 
12740781036SHong Zhang   ierr = ISCreateBlock(PETSC_COMM_SELF,bs,2*ec,stmp,&to);CHKERRQ(ierr);
12840781036SHong Zhang 
12940781036SHong Zhang   /* gnerate the SBAIJ scatter context */
13040781036SHong Zhang   ierr = VecScatterCreate(sbaij->slvec0,from,sbaij->slvec1,to,&sbaij->sMvctx);CHKERRQ(ierr);
13140781036SHong Zhang 
13240781036SHong Zhang    /*
13340781036SHong Zhang       Post the receives for the first matrix vector product. We sync-chronize after
13440781036SHong Zhang     this on the chance that the user immediately calls MatMult() after assemblying
13540781036SHong Zhang     the matrix.
13640781036SHong Zhang   */
13740781036SHong Zhang   ierr = VecScatterPostRecvs(sbaij->slvec0,sbaij->slvec1,INSERT_VALUES,SCATTER_FORWARD,sbaij->sMvctx);CHKERRQ(ierr);
13840781036SHong Zhang 
13940781036SHong Zhang   ierr = VecGetLocalSize(sbaij->slvec1,&nt);CHKERRQ(ierr);
14040781036SHong Zhang   ierr = VecGetArray(sbaij->slvec1,&ptr);CHKERRQ(ierr);
14140781036SHong Zhang   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,bs*mbs,ptr,&sbaij->slvec1a);CHKERRQ(ierr);
14240781036SHong Zhang   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,nt-bs*mbs,ptr+bs*mbs,&sbaij->slvec1b);CHKERRQ(ierr);
14340781036SHong Zhang   ierr = VecRestoreArray(sbaij->slvec1,&ptr);CHKERRQ(ierr);
14440781036SHong Zhang 
14540781036SHong Zhang   ierr = VecGetArray(sbaij->slvec0,&ptr);CHKERRQ(ierr);
14640781036SHong Zhang   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,nt-bs*mbs,ptr+bs*mbs,&sbaij->slvec0b);CHKERRQ(ierr);
14740781036SHong Zhang   ierr = VecRestoreArray(sbaij->slvec0,&ptr);CHKERRQ(ierr);
14840781036SHong Zhang 
14940781036SHong Zhang   ierr = PetscFree(stmp);CHKERRQ(ierr);
15040781036SHong Zhang   ierr = MPI_Barrier(mat->comm);CHKERRQ(ierr);
15140781036SHong Zhang 
15240781036SHong Zhang   PetscLogObjectParent(mat,sbaij->sMvctx);
15340781036SHong Zhang   PetscLogObjectParent(mat,sbaij->slvec0);
15440781036SHong Zhang   PetscLogObjectParent(mat,sbaij->slvec1);
15540781036SHong Zhang   PetscLogObjectParent(mat,sbaij->slvec0b);
15640781036SHong Zhang   PetscLogObjectParent(mat,sbaij->slvec1a);
15740781036SHong Zhang   PetscLogObjectParent(mat,sbaij->slvec1b);
15840781036SHong Zhang   PetscLogObjectParent(mat,from);
15940781036SHong Zhang   PetscLogObjectParent(mat,to);
16040781036SHong Zhang 
16140781036SHong Zhang   PetscLogObjectMemory(mat,(ec+1)*sizeof(int));
16240781036SHong Zhang   ierr = ISDestroy(from);CHKERRQ(ierr);
16340781036SHong Zhang   ierr = ISDestroy(to);CHKERRQ(ierr);
16440781036SHong Zhang   ierr = VecDestroy(gvec);CHKERRQ(ierr);
16540781036SHong Zhang   ierr = PetscFree(sgarray);CHKERRQ(ierr);
16640781036SHong Zhang 
16740781036SHong Zhang   PetscFunctionReturn(0);
16840781036SHong Zhang }
16940781036SHong Zhang 
17040781036SHong Zhang #undef __FUNCT__
17140781036SHong Zhang #define __FUNCT__ "MatSetUpMultiply_MPISBAIJ_2comm"
17240781036SHong Zhang int MatSetUpMultiply_MPISBAIJ_2comm(Mat mat)
17340781036SHong Zhang {
1742896befeSSatish Balay   Mat_MPISBAIJ       *baij = (Mat_MPISBAIJ*)mat->data;
175a30f8f8cSSatish Balay   Mat_SeqBAIJ        *B = (Mat_SeqBAIJ*)(baij->B->data);
176a30f8f8cSSatish Balay   int                Nbs = baij->Nbs,i,j,*indices,*aj = B->j,ierr,ec = 0,*garray;
17786e15631SSatish Balay   int                bs = baij->bs,*stmp;
178a30f8f8cSSatish Balay   IS                 from,to;
179a30f8f8cSSatish Balay   Vec                gvec;
180a30f8f8cSSatish Balay #if defined (PETSC_USE_CTABLE)
181a30f8f8cSSatish Balay   PetscTable         gid1_lid1;
182a30f8f8cSSatish Balay   PetscTablePosition tpos;
183a30f8f8cSSatish Balay   int                gid,lid;
184a30f8f8cSSatish Balay #endif
185a30f8f8cSSatish Balay 
186a30f8f8cSSatish Balay   PetscFunctionBegin;
187a30f8f8cSSatish Balay 
188a30f8f8cSSatish Balay #if defined (PETSC_USE_CTABLE)
189a30f8f8cSSatish Balay   /* use a table - Mark Adams */
190a30f8f8cSSatish Balay   PetscTableCreate(B->mbs,&gid1_lid1);
191a30f8f8cSSatish Balay   for (i=0; i<B->mbs; i++) {
192a30f8f8cSSatish Balay     for (j=0; j<B->ilen[i]; j++) {
193a30f8f8cSSatish Balay       int data,gid1 = aj[B->i[i]+j] + 1;
194a30f8f8cSSatish Balay       ierr = PetscTableFind(gid1_lid1,gid1,&data) ;CHKERRQ(ierr);
195a30f8f8cSSatish Balay       if (!data) {
196a30f8f8cSSatish Balay         /* one based table */
197a30f8f8cSSatish Balay         ierr = PetscTableAdd(gid1_lid1,gid1,++ec);CHKERRQ(ierr);
198a30f8f8cSSatish Balay       }
199a30f8f8cSSatish Balay     }
200a30f8f8cSSatish Balay   }
201a30f8f8cSSatish Balay   /* form array of columns we need */
202b0a32e0cSBarry Smith   ierr = PetscMalloc((ec+1)*sizeof(int),&garray);CHKERRQ(ierr);
203a30f8f8cSSatish Balay   ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr);
204a30f8f8cSSatish Balay   while (tpos) {
205a30f8f8cSSatish Balay     ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr);
206a30f8f8cSSatish Balay     gid--; lid--;
207a30f8f8cSSatish Balay     garray[lid] = gid;
208a30f8f8cSSatish Balay   }
209a30f8f8cSSatish Balay   ierr = PetscSortInt(ec,garray);CHKERRQ(ierr);
210a30f8f8cSSatish Balay   /* qsort(garray, ec, sizeof(int), intcomparcarc); */
211a30f8f8cSSatish Balay   ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr);
212a30f8f8cSSatish Balay   for (i=0; i<ec; i++) {
213a30f8f8cSSatish Balay     ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1);CHKERRQ(ierr);
214a30f8f8cSSatish Balay   }
215a30f8f8cSSatish Balay   /* compact out the extra columns in B */
216a30f8f8cSSatish Balay   for (i=0; i<B->mbs; i++) {
217a30f8f8cSSatish Balay     for (j=0; j<B->ilen[i]; j++) {
218a30f8f8cSSatish Balay       int gid1 = aj[B->i[i] + j] + 1;
219a30f8f8cSSatish Balay       ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr);
220a30f8f8cSSatish Balay       lid --;
221a30f8f8cSSatish Balay       aj[B->i[i]+j] = lid;
222a30f8f8cSSatish Balay     }
223a30f8f8cSSatish Balay   }
224a30f8f8cSSatish Balay   B->nbs     = ec;
225273d9f13SBarry Smith   baij->B->n = ec*B->bs;
226a30f8f8cSSatish Balay   ierr = PetscTableDelete(gid1_lid1);CHKERRQ(ierr);
227a30f8f8cSSatish Balay   /* Mark Adams */
228a30f8f8cSSatish Balay #else
229a30f8f8cSSatish Balay   /* For the first stab we make an array as long as the number of columns */
230a30f8f8cSSatish Balay   /* mark those columns that are in baij->B */
231b0a32e0cSBarry Smith   ierr = PetscMalloc((Nbs+1)*sizeof(int),&indices);CHKERRQ(ierr);
232a30f8f8cSSatish Balay   ierr = PetscMemzero(indices,Nbs*sizeof(int));CHKERRQ(ierr);
233a30f8f8cSSatish Balay   for (i=0; i<B->mbs; i++) {
234a30f8f8cSSatish Balay     for (j=0; j<B->ilen[i]; j++) {
235a30f8f8cSSatish Balay       if (!indices[aj[B->i[i] + j]]) ec++;
236a30f8f8cSSatish Balay       indices[aj[B->i[i] + j] ] = 1;
237a30f8f8cSSatish Balay     }
238a30f8f8cSSatish Balay   }
239a30f8f8cSSatish Balay 
240a30f8f8cSSatish Balay   /* form array of columns we need */
241b0a32e0cSBarry Smith   ierr = PetscMalloc((ec+1)*sizeof(int),&garray);CHKERRQ(ierr);
242f3ef73ceSBarry Smith   ec = 0;
243f3ef73ceSBarry Smith   for (i=0; i<Nbs; i++) {
244f3ef73ceSBarry Smith     if (indices[i]) {
245f3ef73ceSBarry Smith       garray[ec++] = i;
246f3ef73ceSBarry Smith     }
247f3ef73ceSBarry Smith   }
248a30f8f8cSSatish Balay 
249a30f8f8cSSatish Balay   /* make indices now point into garray */
250a30f8f8cSSatish Balay   for (i=0; i<ec; i++) {
251a30f8f8cSSatish Balay     indices[garray[i]] = i;
252a30f8f8cSSatish Balay   }
253a30f8f8cSSatish Balay 
254a30f8f8cSSatish Balay   /* compact out the extra columns in B */
255a30f8f8cSSatish Balay   for (i=0; i<B->mbs; i++) {
256a30f8f8cSSatish Balay     for (j=0; j<B->ilen[i]; j++) {
257a30f8f8cSSatish Balay       aj[B->i[i] + j] = indices[aj[B->i[i] + j]];
258a30f8f8cSSatish Balay     }
259a30f8f8cSSatish Balay   }
260a30f8f8cSSatish Balay   B->nbs       = ec;
261273d9f13SBarry Smith   baij->B->n   = ec*B->bs;
262a30f8f8cSSatish Balay   ierr = PetscFree(indices);CHKERRQ(ierr);
263a30f8f8cSSatish Balay #endif
264633e10c7SHong Zhang 
265a30f8f8cSSatish Balay   /* create local vector that is used to scatter into */
266a30f8f8cSSatish Balay   ierr = VecCreateSeq(PETSC_COMM_SELF,ec*bs,&baij->lvec);CHKERRQ(ierr);
267a30f8f8cSSatish Balay 
268a30f8f8cSSatish Balay   /* create two temporary index sets for building scatter-gather */
269eb7adc28SSatish Balay   for (i=0; i<ec; i++) {
270a30f8f8cSSatish Balay     garray[i] = bs*garray[i];
271a30f8f8cSSatish Balay   }
272a30f8f8cSSatish Balay   ierr = ISCreateBlock(PETSC_COMM_SELF,bs,ec,garray,&from);CHKERRQ(ierr);
27386e15631SSatish Balay   for (i=0; i<ec; i++) {
274a30f8f8cSSatish Balay     garray[i] = garray[i]/bs;
275a30f8f8cSSatish Balay   }
276a30f8f8cSSatish Balay 
277b0a32e0cSBarry Smith   ierr = PetscMalloc((ec+1)*sizeof(int),&stmp);CHKERRQ(ierr);
278a30f8f8cSSatish Balay   for (i=0; i<ec; i++) { stmp[i] = bs*i; }
279a30f8f8cSSatish Balay   ierr = ISCreateBlock(PETSC_COMM_SELF,bs,ec,stmp,&to);CHKERRQ(ierr);
280a30f8f8cSSatish Balay   ierr = PetscFree(stmp);CHKERRQ(ierr);
281a30f8f8cSSatish Balay 
282a30f8f8cSSatish Balay   /* create temporary global vector to generate scatter context */
283a30f8f8cSSatish Balay   /* this is inefficient, but otherwise we must do either
284a30f8f8cSSatish Balay      1) save garray until the first actual scatter when the vector is known or
285a30f8f8cSSatish Balay      2) have another way of generating a scatter context without a vector.*/
286273d9f13SBarry Smith   ierr = VecCreateMPI(mat->comm,mat->n,mat->N,&gvec);CHKERRQ(ierr);
287a30f8f8cSSatish Balay 
288a30f8f8cSSatish Balay   /* gnerate the scatter context */
289a30f8f8cSSatish Balay   ierr = VecScatterCreate(gvec,from,baij->lvec,to,&baij->Mvctx);CHKERRQ(ierr);
290a30f8f8cSSatish Balay 
291a30f8f8cSSatish Balay   /*
292a30f8f8cSSatish Balay       Post the receives for the first matrix vector product. We sync-chronize after
293a30f8f8cSSatish Balay     this on the chance that the user immediately calls MatMult() after assemblying
294a30f8f8cSSatish Balay     the matrix.
295a30f8f8cSSatish Balay   */
296a30f8f8cSSatish Balay   ierr = VecScatterPostRecvs(gvec,baij->lvec,INSERT_VALUES,SCATTER_FORWARD,baij->Mvctx);CHKERRQ(ierr);
297a30f8f8cSSatish Balay   ierr = MPI_Barrier(mat->comm);CHKERRQ(ierr);
298a30f8f8cSSatish Balay 
299b0a32e0cSBarry Smith   PetscLogObjectParent(mat,baij->Mvctx);
300b0a32e0cSBarry Smith   PetscLogObjectParent(mat,baij->lvec);
301b0a32e0cSBarry Smith   PetscLogObjectParent(mat,from);
302b0a32e0cSBarry Smith   PetscLogObjectParent(mat,to);
303a30f8f8cSSatish Balay   baij->garray = garray;
304b0a32e0cSBarry Smith   PetscLogObjectMemory(mat,(ec+1)*sizeof(int));
305a30f8f8cSSatish Balay   ierr = ISDestroy(from);CHKERRQ(ierr);
306a30f8f8cSSatish Balay   ierr = ISDestroy(to);CHKERRQ(ierr);
307a30f8f8cSSatish Balay   ierr = VecDestroy(gvec);CHKERRQ(ierr);
308a30f8f8cSSatish Balay   PetscFunctionReturn(0);
309a30f8f8cSSatish Balay }
310a30f8f8cSSatish Balay 
311a30f8f8cSSatish Balay 
312a30f8f8cSSatish Balay /*
313a30f8f8cSSatish Balay      Takes the local part of an already assembled MPIBAIJ matrix
314a30f8f8cSSatish Balay    and disassembles it. This is to allow new nonzeros into the matrix
315a30f8f8cSSatish Balay    that require more communication in the matrix vector multiply.
316a30f8f8cSSatish Balay    Thus certain data-structures must be rebuilt.
317a30f8f8cSSatish Balay 
318a30f8f8cSSatish Balay    Kind of slow! But that's what application programmers get when
319a30f8f8cSSatish Balay    they are sloppy.
320a30f8f8cSSatish Balay */
3214a2ae208SSatish Balay #undef __FUNCT__
3224a2ae208SSatish Balay #define __FUNCT__ "DisAssemble_MPISBAIJ"
323a30f8f8cSSatish Balay int DisAssemble_MPISBAIJ(Mat A)
324a30f8f8cSSatish Balay {
3252896befeSSatish Balay   Mat_MPISBAIJ   *baij = (Mat_MPISBAIJ*)A->data;
326a30f8f8cSSatish Balay   Mat           B = baij->B,Bnew;
327a30f8f8cSSatish Balay   Mat_SeqBAIJ   *Bbaij = (Mat_SeqBAIJ*)B->data;
328273d9f13SBarry Smith   int           ierr,i,j,mbs=Bbaij->mbs,n = A->N,col,*garray=baij->garray;
329273d9f13SBarry Smith   int           k,bs=baij->bs,bs2=baij->bs2,*rvals,*nz,ec,m=A->m;
330a30f8f8cSSatish Balay   MatScalar     *a = Bbaij->a;
33187828ca2SBarry Smith   PetscScalar   *atmp;
33282502324SSatish Balay #if defined(PETSC_USE_MAT_SINGLE)
33382502324SSatish Balay   int           l;
334a30f8f8cSSatish Balay #endif
335a30f8f8cSSatish Balay 
336a30f8f8cSSatish Balay   PetscFunctionBegin;
33782502324SSatish Balay #if defined(PETSC_USE_MAT_SINGLE)
33887828ca2SBarry Smith   ierr = PetscMalloc(baij->bs*sizeof(PetscScalar),&atmp);
33982502324SSatish Balay #endif
340a30f8f8cSSatish Balay   /* free stuff related to matrix-vec multiply */
341b0a32e0cSBarry Smith   ierr = VecGetSize(baij->lvec,&ec);CHKERRQ(ierr); /* needed for PetscLogObjectMemory below */
342a30f8f8cSSatish Balay   ierr = VecDestroy(baij->lvec);CHKERRQ(ierr); baij->lvec = 0;
343a30f8f8cSSatish Balay   ierr = VecScatterDestroy(baij->Mvctx);CHKERRQ(ierr); baij->Mvctx = 0;
344a30f8f8cSSatish Balay   if (baij->colmap) {
345a30f8f8cSSatish Balay #if defined (PETSC_USE_CTABLE)
346a30f8f8cSSatish Balay     ierr = PetscTableDelete(baij->colmap); baij->colmap = 0;CHKERRQ(ierr);
347a30f8f8cSSatish Balay #else
348a30f8f8cSSatish Balay     ierr = PetscFree(baij->colmap);CHKERRQ(ierr);
349a30f8f8cSSatish Balay     baij->colmap = 0;
350b0a32e0cSBarry Smith     PetscLogObjectMemory(A,-Bbaij->nbs*sizeof(int));
351a30f8f8cSSatish Balay #endif
352a30f8f8cSSatish Balay   }
353a30f8f8cSSatish Balay 
354a30f8f8cSSatish Balay   /* make sure that B is assembled so we can access its values */
355a30f8f8cSSatish Balay   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
356a30f8f8cSSatish Balay   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
357a30f8f8cSSatish Balay 
358a30f8f8cSSatish Balay   /* invent new B and copy stuff over */
35982502324SSatish Balay   ierr = PetscMalloc(mbs*sizeof(int),&nz);CHKERRQ(ierr);
360a30f8f8cSSatish Balay   for (i=0; i<mbs; i++) {
361a30f8f8cSSatish Balay     nz[i] = Bbaij->i[i+1]-Bbaij->i[i];
362a30f8f8cSSatish Balay   }
363a30f8f8cSSatish Balay   ierr = MatCreateSeqBAIJ(PETSC_COMM_SELF,baij->bs,m,n,0,nz,&Bnew);CHKERRQ(ierr);
364a30f8f8cSSatish Balay   ierr = PetscFree(nz);CHKERRQ(ierr);
365a30f8f8cSSatish Balay 
36682502324SSatish Balay   ierr = PetscMalloc(bs*sizeof(int),&rvals);CHKERRQ(ierr);
367a30f8f8cSSatish Balay   for (i=0; i<mbs; i++) {
368a30f8f8cSSatish Balay     rvals[0] = bs*i;
369a30f8f8cSSatish Balay     for (j=1; j<bs; j++) { rvals[j] = rvals[j-1] + 1; }
370a30f8f8cSSatish Balay     for (j=Bbaij->i[i]; j<Bbaij->i[i+1]; j++) {
371a30f8f8cSSatish Balay       col = garray[Bbaij->j[j]]*bs;
372a30f8f8cSSatish Balay       for (k=0; k<bs; k++) {
373a30f8f8cSSatish Balay #if defined(PETSC_USE_MAT_SINGLE)
374a30f8f8cSSatish Balay         for (l=0; l<bs; l++) atmp[l] = a[j*bs2+l];
375a30f8f8cSSatish Balay #else
37671730473SSatish Balay         atmp = a+j*bs2 + k*bs;
377a30f8f8cSSatish Balay #endif
378c8407628SSatish Balay         ierr = MatSetValues_SeqSBAIJ(Bnew,bs,rvals,1,&col,atmp,B->insertmode);CHKERRQ(ierr);
379a30f8f8cSSatish Balay         col++;
380a30f8f8cSSatish Balay       }
381a30f8f8cSSatish Balay     }
382a30f8f8cSSatish Balay   }
383a30f8f8cSSatish Balay #if defined(PETSC_USE_MAT_SINGLE)
384a30f8f8cSSatish Balay   ierr = PetscFree(atmp);CHKERRQ(ierr);
385a30f8f8cSSatish Balay #endif
386a30f8f8cSSatish Balay   ierr = PetscFree(baij->garray);CHKERRQ(ierr);
387a30f8f8cSSatish Balay   baij->garray = 0;
388a30f8f8cSSatish Balay   ierr = PetscFree(rvals);CHKERRQ(ierr);
389b0a32e0cSBarry Smith   PetscLogObjectMemory(A,-ec*sizeof(int));
390a30f8f8cSSatish Balay   ierr = MatDestroy(B);CHKERRQ(ierr);
391b0a32e0cSBarry Smith   PetscLogObjectParent(A,Bnew);
392a30f8f8cSSatish Balay   baij->B = Bnew;
393a30f8f8cSSatish Balay   A->was_assembled = PETSC_FALSE;
394a30f8f8cSSatish Balay   PetscFunctionReturn(0);
395a30f8f8cSSatish Balay }
396a30f8f8cSSatish Balay 
397a30f8f8cSSatish Balay 
398a30f8f8cSSatish Balay 
399