xref: /petsc/src/mat/impls/sbaij/mpi/mmsbaij.c (revision 6bf464f92cc51e6fd6163850774a6badb2f63b6b)
1a30f8f8cSSatish Balay 
2a30f8f8cSSatish Balay /*
3a30f8f8cSSatish Balay    Support for the parallel SBAIJ matrix vector multiply
4a30f8f8cSSatish Balay */
5c6db04a5SJed Brown #include <../src/mat/impls/sbaij/mpi/mpisbaij.h>
67cff1425SSatish Balay 
709573ac7SBarry Smith extern PetscErrorCode MatSetValues_SeqSBAIJ(Mat,PetscInt,const PetscInt [],PetscInt,const PetscInt [],const PetscScalar [],InsertMode);
87cff1425SSatish Balay 
9a30f8f8cSSatish Balay 
104a2ae208SSatish Balay #undef __FUNCT__
114a2ae208SSatish Balay #define __FUNCT__ "MatSetUpMultiply_MPISBAIJ"
12dfbe8321SBarry Smith PetscErrorCode MatSetUpMultiply_MPISBAIJ(Mat mat)
13a30f8f8cSSatish Balay {
1440781036SHong Zhang   Mat_MPISBAIJ   *sbaij = (Mat_MPISBAIJ*)mat->data;
1540781036SHong Zhang   Mat_SeqBAIJ    *B = (Mat_SeqBAIJ*)(sbaij->B->data);
166849ba73SBarry Smith   PetscErrorCode ierr;
1713f74950SBarry Smith   PetscInt       Nbs = sbaij->Nbs,i,j,*indices,*aj = B->j,ec = 0,*garray,*sgarray;
18d0f46423SBarry Smith   PetscInt       bs = mat->rmap->bs,*stmp,mbs=sbaij->mbs, vec_size,nt;
1940781036SHong Zhang   IS             from,to;
2040781036SHong Zhang   Vec            gvec;
2113f74950SBarry Smith   PetscMPIInt    rank=sbaij->rank,lsize,size=sbaij->size;
22899cda47SBarry Smith   PetscInt       *owners=sbaij->rangebs,*sowners,*ec_owner,k;
2340781036SHong Zhang   PetscScalar    *ptr;
2440781036SHong Zhang 
2540781036SHong Zhang   PetscFunctionBegin;
26*6bf464f9SBarry Smith   ierr = VecScatterDestroy(&sbaij->sMvctx);CHKERRQ(ierr);
2740781036SHong Zhang 
2840781036SHong Zhang   /* For the first stab we make an array as long as the number of columns */
2940781036SHong Zhang   /* mark those columns that are in sbaij->B */
3074ed9c26SBarry Smith   ierr = PetscMalloc(Nbs*sizeof(PetscInt),&indices);CHKERRQ(ierr);
3113f74950SBarry Smith   ierr = PetscMemzero(indices,Nbs*sizeof(PetscInt));CHKERRQ(ierr);
3240781036SHong Zhang   for (i=0; i<mbs; i++) {
3340781036SHong Zhang     for (j=0; j<B->ilen[i]; j++) {
3440781036SHong Zhang       if (!indices[aj[B->i[i] + j]]) ec++;
3540781036SHong Zhang       indices[aj[B->i[i] + j] ] = 1;
3640781036SHong Zhang     }
3740781036SHong Zhang   }
3840781036SHong Zhang 
3940781036SHong Zhang   /* form arrays of columns we need */
4074ed9c26SBarry Smith   ierr = PetscMalloc(ec*sizeof(PetscInt),&garray);CHKERRQ(ierr);
4174ed9c26SBarry Smith   ierr = PetscMalloc2(2*ec,PetscInt,&sgarray,ec,PetscInt,&ec_owner);CHKERRQ(ierr);
4240781036SHong Zhang 
4340781036SHong Zhang   ec = 0;
4440781036SHong Zhang   for (j=0; j<size; j++){
4540781036SHong Zhang     for (i=owners[j]; i<owners[j+1]; i++){
4640781036SHong Zhang       if (indices[i]) {
4740781036SHong Zhang         garray[ec]   = i;
4840781036SHong Zhang         ec_owner[ec] = j;
4940781036SHong Zhang         ec++;
5040781036SHong Zhang       }
5140781036SHong Zhang     }
5240781036SHong Zhang   }
5340781036SHong Zhang 
5440781036SHong Zhang   /* make indices now point into garray */
55b424e231SHong Zhang   for (i=0; i<ec; i++) indices[garray[i]] = i;
5640781036SHong Zhang 
5740781036SHong Zhang   /* compact out the extra columns in B */
5840781036SHong Zhang   for (i=0; i<mbs; i++) {
5940781036SHong Zhang     for (j=0; j<B->ilen[i]; j++) aj[B->i[i] + j] = indices[aj[B->i[i] + j]];
6040781036SHong Zhang   }
6140781036SHong Zhang   B->nbs      = ec;
62d0f46423SBarry Smith   sbaij->B->cmap->n = sbaij->B->cmap->N = ec*mat->rmap->bs;
6326283091SBarry Smith   ierr = PetscLayoutSetUp((sbaij->B->cmap));CHKERRQ(ierr);
6440781036SHong Zhang   ierr = PetscFree(indices);CHKERRQ(ierr);
6540781036SHong Zhang 
6640781036SHong Zhang   /* create local vector that is used to scatter into */
6740781036SHong Zhang   ierr = VecCreateSeq(PETSC_COMM_SELF,ec*bs,&sbaij->lvec);CHKERRQ(ierr);
6840781036SHong Zhang 
6940781036SHong Zhang   /* create two temporary index sets for building scatter-gather */
7074ed9c26SBarry Smith   ierr = PetscMalloc(2*ec*sizeof(PetscInt),&stmp);CHKERRQ(ierr);
71deff0451SBarry Smith   ierr = ISCreateBlock(PETSC_COMM_SELF,bs,ec,garray,PETSC_COPY_VALUES,&from);CHKERRQ(ierr);
72e82e9f6bSBarry Smith   for (i=0; i<ec; i++) { stmp[i] = i; }
73deff0451SBarry Smith   ierr = ISCreateBlock(PETSC_COMM_SELF,bs,ec,stmp,PETSC_COPY_VALUES,&to);CHKERRQ(ierr);
7440781036SHong Zhang 
7593d1592dSHong Zhang   /* generate the scatter context
7693d1592dSHong Zhang      -- Mvctx and lvec are not used by MatMult_MPISBAIJ(), but usefule for some applications */
77d0f46423SBarry Smith   ierr = VecCreateMPIWithArray(((PetscObject)mat)->comm,mat->cmap->n,mat->cmap->N,PETSC_NULL,&gvec);CHKERRQ(ierr);
7840781036SHong Zhang   ierr = VecScatterCreate(gvec,from,sbaij->lvec,to,&sbaij->Mvctx);CHKERRQ(ierr);
79*6bf464f9SBarry Smith   ierr = VecDestroy(&gvec);CHKERRQ(ierr);
8040781036SHong Zhang 
8140781036SHong Zhang   sbaij->garray = garray;
8252e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,sbaij->Mvctx);CHKERRQ(ierr);
8352e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,sbaij->lvec);CHKERRQ(ierr);
8452e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,from);CHKERRQ(ierr);
8552e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,to);CHKERRQ(ierr);
8640781036SHong Zhang 
87*6bf464f9SBarry Smith   ierr = ISDestroy(&from);CHKERRQ(ierr);
88*6bf464f9SBarry Smith   ierr = ISDestroy(&to);CHKERRQ(ierr);
8940781036SHong Zhang 
9040781036SHong Zhang   /* create parallel vector that is used by SBAIJ matrix to scatter from/into */
9140781036SHong Zhang   lsize = (mbs + ec)*bs;
927adad957SLisandro Dalcin   ierr = VecCreateMPI(((PetscObject)mat)->comm,lsize,PETSC_DETERMINE,&sbaij->slvec0);CHKERRQ(ierr);
9340781036SHong Zhang   ierr = VecDuplicate(sbaij->slvec0,&sbaij->slvec1);CHKERRQ(ierr);
9440781036SHong Zhang   ierr = VecGetSize(sbaij->slvec0,&vec_size);CHKERRQ(ierr);
9540781036SHong Zhang 
96d0f46423SBarry Smith   sowners = sbaij->slvec0->map->range;
9740781036SHong Zhang 
9840781036SHong Zhang   /* x index in the IS sfrom */
9940781036SHong Zhang   for (i=0; i<ec; i++) {
10040781036SHong Zhang     j = ec_owner[i];
10140781036SHong Zhang     sgarray[i]  = garray[i] + (sowners[j]/bs - owners[j]);
10240781036SHong Zhang   }
10340781036SHong Zhang   /* b index in the IS sfrom */
10440781036SHong Zhang   k = sowners[rank]/bs + mbs;
10540781036SHong Zhang   for (i=ec,j=0; i< 2*ec; i++,j++) sgarray[i] = k + j;
106deff0451SBarry Smith   ierr = ISCreateBlock(PETSC_COMM_SELF,bs,2*ec,sgarray,PETSC_COPY_VALUES,&from);CHKERRQ(ierr);
10740781036SHong Zhang 
10840781036SHong Zhang   /* x index in the IS sto */
10940781036SHong Zhang   k = sowners[rank]/bs + mbs;
110e82e9f6bSBarry Smith   for (i=0; i<ec; i++) stmp[i] = (k + i);
11140781036SHong Zhang   /* b index in the IS sto */
112e82e9f6bSBarry Smith   for (i=ec; i<2*ec; i++) stmp[i] = sgarray[i-ec];
11340781036SHong Zhang 
114deff0451SBarry Smith   ierr = ISCreateBlock(PETSC_COMM_SELF,bs,2*ec,stmp,PETSC_COPY_VALUES,&to);CHKERRQ(ierr);
11540781036SHong Zhang 
11640781036SHong Zhang   ierr = VecScatterCreate(sbaij->slvec0,from,sbaij->slvec1,to,&sbaij->sMvctx);CHKERRQ(ierr);
11740781036SHong Zhang 
11840781036SHong Zhang   ierr = VecGetLocalSize(sbaij->slvec1,&nt);CHKERRQ(ierr);
1191ebc52fbSHong Zhang   ierr = VecGetArray(sbaij->slvec1,&ptr);CHKERRQ(ierr);
12040781036SHong Zhang   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,bs*mbs,ptr,&sbaij->slvec1a);CHKERRQ(ierr);
12140781036SHong Zhang   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,nt-bs*mbs,ptr+bs*mbs,&sbaij->slvec1b);CHKERRQ(ierr);
1221ebc52fbSHong Zhang   ierr = VecRestoreArray(sbaij->slvec1,&ptr);CHKERRQ(ierr);
12340781036SHong Zhang 
1241ebc52fbSHong Zhang   ierr = VecGetArray(sbaij->slvec0,&ptr);CHKERRQ(ierr);
12540781036SHong Zhang   ierr = VecCreateSeqWithArray(PETSC_COMM_SELF,nt-bs*mbs,ptr+bs*mbs,&sbaij->slvec0b);CHKERRQ(ierr);
1261ebc52fbSHong Zhang   ierr = VecRestoreArray(sbaij->slvec0,&ptr);CHKERRQ(ierr);
12740781036SHong Zhang 
12840781036SHong Zhang   ierr = PetscFree(stmp);CHKERRQ(ierr);
1297adad957SLisandro Dalcin   ierr = MPI_Barrier(((PetscObject)mat)->comm);CHKERRQ(ierr);
13040781036SHong Zhang 
13152e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,sbaij->sMvctx);CHKERRQ(ierr);
13252e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,sbaij->slvec0);CHKERRQ(ierr);
13352e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,sbaij->slvec1);CHKERRQ(ierr);
13452e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,sbaij->slvec0b);CHKERRQ(ierr);
13552e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,sbaij->slvec1a);CHKERRQ(ierr);
13652e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,sbaij->slvec1b);CHKERRQ(ierr);
13752e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,from);CHKERRQ(ierr);
13852e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,to);CHKERRQ(ierr);
13940781036SHong Zhang 
14052e6d16bSBarry Smith   ierr = PetscLogObjectMemory(mat,(ec+1)*sizeof(PetscInt));CHKERRQ(ierr);
141*6bf464f9SBarry Smith   ierr = ISDestroy(&from);CHKERRQ(ierr);
142*6bf464f9SBarry Smith   ierr = ISDestroy(&to);CHKERRQ(ierr);
14374ed9c26SBarry Smith   ierr = PetscFree2(sgarray,ec_owner);CHKERRQ(ierr);
14440781036SHong Zhang   PetscFunctionReturn(0);
14540781036SHong Zhang }
14640781036SHong Zhang 
14740781036SHong Zhang #undef __FUNCT__
14840781036SHong Zhang #define __FUNCT__ "MatSetUpMultiply_MPISBAIJ_2comm"
149dfbe8321SBarry Smith PetscErrorCode MatSetUpMultiply_MPISBAIJ_2comm(Mat mat)
15040781036SHong Zhang {
1512896befeSSatish Balay   Mat_MPISBAIJ       *baij = (Mat_MPISBAIJ*)mat->data;
152a30f8f8cSSatish Balay   Mat_SeqBAIJ        *B = (Mat_SeqBAIJ*)(baij->B->data);
1536849ba73SBarry Smith   PetscErrorCode     ierr;
15413f74950SBarry Smith   PetscInt           i,j,*aj = B->j,ec = 0,*garray;
155d0f46423SBarry Smith   PetscInt           bs = mat->rmap->bs,*stmp;
156a30f8f8cSSatish Balay   IS                 from,to;
157a30f8f8cSSatish Balay   Vec                gvec;
158a30f8f8cSSatish Balay #if defined (PETSC_USE_CTABLE)
159a30f8f8cSSatish Balay   PetscTable         gid1_lid1;
160a30f8f8cSSatish Balay   PetscTablePosition tpos;
16113f74950SBarry Smith   PetscInt           gid,lid;
1626f531f54SSatish Balay #else
16313f74950SBarry Smith   PetscInt           Nbs = baij->Nbs,*indices;
164a30f8f8cSSatish Balay #endif
165a30f8f8cSSatish Balay 
166a30f8f8cSSatish Balay   PetscFunctionBegin;
167a30f8f8cSSatish Balay #if defined (PETSC_USE_CTABLE)
168a30f8f8cSSatish Balay   /* use a table - Mark Adams */
169a30f8f8cSSatish Balay   PetscTableCreate(B->mbs,&gid1_lid1);
170a30f8f8cSSatish Balay   for (i=0; i<B->mbs; i++) {
171a30f8f8cSSatish Balay     for (j=0; j<B->ilen[i]; j++) {
17213f74950SBarry Smith       PetscInt data,gid1 = aj[B->i[i]+j] + 1;
173a30f8f8cSSatish Balay       ierr = PetscTableFind(gid1_lid1,gid1,&data);CHKERRQ(ierr);
174a30f8f8cSSatish Balay       if (!data) {
175a30f8f8cSSatish Balay         /* one based table */
176a30f8f8cSSatish Balay         ierr = PetscTableAdd(gid1_lid1,gid1,++ec);CHKERRQ(ierr);
177a30f8f8cSSatish Balay       }
178a30f8f8cSSatish Balay     }
179a30f8f8cSSatish Balay   }
180a30f8f8cSSatish Balay   /* form array of columns we need */
18174ed9c26SBarry Smith   ierr = PetscMalloc(ec*sizeof(PetscInt),&garray);CHKERRQ(ierr);
182a30f8f8cSSatish Balay   ierr = PetscTableGetHeadPosition(gid1_lid1,&tpos);CHKERRQ(ierr);
183a30f8f8cSSatish Balay   while (tpos) {
184a30f8f8cSSatish Balay     ierr = PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid);CHKERRQ(ierr);
185a30f8f8cSSatish Balay     gid--; lid--;
186a30f8f8cSSatish Balay     garray[lid] = gid;
187a30f8f8cSSatish Balay   }
188a30f8f8cSSatish Balay   ierr = PetscSortInt(ec,garray);CHKERRQ(ierr);
189a30f8f8cSSatish Balay   ierr = PetscTableRemoveAll(gid1_lid1);CHKERRQ(ierr);
190a30f8f8cSSatish Balay   for (i=0; i<ec; i++) {
191a30f8f8cSSatish Balay     ierr = PetscTableAdd(gid1_lid1,garray[i]+1,i+1);CHKERRQ(ierr);
192a30f8f8cSSatish Balay   }
193a30f8f8cSSatish Balay   /* compact out the extra columns in B */
194a30f8f8cSSatish Balay   for (i=0; i<B->mbs; i++) {
195a30f8f8cSSatish Balay     for (j=0; j<B->ilen[i]; j++) {
19613f74950SBarry Smith       PetscInt gid1 = aj[B->i[i] + j] + 1;
197a30f8f8cSSatish Balay       ierr = PetscTableFind(gid1_lid1,gid1,&lid);CHKERRQ(ierr);
198a30f8f8cSSatish Balay       lid --;
199a30f8f8cSSatish Balay       aj[B->i[i]+j] = lid;
200a30f8f8cSSatish Balay     }
201a30f8f8cSSatish Balay   }
202a30f8f8cSSatish Balay   B->nbs     = ec;
203d0f46423SBarry Smith   baij->B->cmap->n = baij->B->cmap->N = ec*mat->rmap->bs;
20426283091SBarry Smith   ierr = PetscLayoutSetUp((baij->B->cmap));CHKERRQ(ierr);
2059c666560SBarry Smith   ierr = PetscTableDestroy(gid1_lid1);CHKERRQ(ierr);
206a30f8f8cSSatish Balay   /* Mark Adams */
207a30f8f8cSSatish Balay #else
208a30f8f8cSSatish Balay   /* For the first stab we make an array as long as the number of columns */
209a30f8f8cSSatish Balay   /* mark those columns that are in baij->B */
21074ed9c26SBarry Smith   ierr = PetscMalloc(Nbs*sizeof(PetscInt),&indices);CHKERRQ(ierr);
21113f74950SBarry Smith   ierr = PetscMemzero(indices,Nbs*sizeof(PetscInt));CHKERRQ(ierr);
212a30f8f8cSSatish Balay   for (i=0; i<B->mbs; i++) {
213a30f8f8cSSatish Balay     for (j=0; j<B->ilen[i]; j++) {
214a30f8f8cSSatish Balay       if (!indices[aj[B->i[i] + j]]) ec++;
215a30f8f8cSSatish Balay       indices[aj[B->i[i] + j] ] = 1;
216a30f8f8cSSatish Balay     }
217a30f8f8cSSatish Balay   }
218a30f8f8cSSatish Balay 
219a30f8f8cSSatish Balay   /* form array of columns we need */
22074ed9c26SBarry Smith   ierr = PetscMalloc(ec*sizeof(PetscInt),&garray);CHKERRQ(ierr);
221f3ef73ceSBarry Smith   ec = 0;
222f3ef73ceSBarry Smith   for (i=0; i<Nbs; i++) {
223f3ef73ceSBarry Smith     if (indices[i]) {
224f3ef73ceSBarry Smith       garray[ec++] = i;
225f3ef73ceSBarry Smith     }
226f3ef73ceSBarry Smith   }
227a30f8f8cSSatish Balay 
228a30f8f8cSSatish Balay   /* make indices now point into garray */
229a30f8f8cSSatish Balay   for (i=0; i<ec; i++) {
230a30f8f8cSSatish Balay     indices[garray[i]] = i;
231a30f8f8cSSatish Balay   }
232a30f8f8cSSatish Balay 
233a30f8f8cSSatish Balay   /* compact out the extra columns in B */
234a30f8f8cSSatish Balay   for (i=0; i<B->mbs; i++) {
235a30f8f8cSSatish Balay     for (j=0; j<B->ilen[i]; j++) {
236a30f8f8cSSatish Balay       aj[B->i[i] + j] = indices[aj[B->i[i] + j]];
237a30f8f8cSSatish Balay     }
238a30f8f8cSSatish Balay   }
239a30f8f8cSSatish Balay   B->nbs       = ec;
240d0f46423SBarry Smith   baij->B->cmap->n   = ec*mat->rmap->bs;
241a30f8f8cSSatish Balay   ierr = PetscFree(indices);CHKERRQ(ierr);
242a30f8f8cSSatish Balay #endif
243633e10c7SHong Zhang 
244a30f8f8cSSatish Balay   /* create local vector that is used to scatter into */
245a30f8f8cSSatish Balay   ierr = VecCreateSeq(PETSC_COMM_SELF,ec*bs,&baij->lvec);CHKERRQ(ierr);
246a30f8f8cSSatish Balay 
247a30f8f8cSSatish Balay   /* create two temporary index sets for building scatter-gather */
248deff0451SBarry Smith   ierr = ISCreateBlock(PETSC_COMM_SELF,bs,ec,garray,PETSC_COPY_VALUES,&from);CHKERRQ(ierr);
249a30f8f8cSSatish Balay 
25074ed9c26SBarry Smith   ierr = PetscMalloc(ec*sizeof(PetscInt),&stmp);CHKERRQ(ierr);
251e82e9f6bSBarry Smith   for (i=0; i<ec; i++) { stmp[i] = i; }
252deff0451SBarry Smith   ierr = ISCreateBlock(PETSC_COMM_SELF,bs,ec,stmp,PETSC_OWN_POINTER,&to);CHKERRQ(ierr);
253a30f8f8cSSatish Balay 
254a30f8f8cSSatish Balay   /* create temporary global vector to generate scatter context */
255d0f46423SBarry Smith   ierr = VecCreateMPIWithArray(((PetscObject)mat)->comm,mat->cmap->n,mat->cmap->N,PETSC_NULL,&gvec);CHKERRQ(ierr);
256a30f8f8cSSatish Balay   ierr = VecScatterCreate(gvec,from,baij->lvec,to,&baij->Mvctx);CHKERRQ(ierr);
257*6bf464f9SBarry Smith   ierr = VecDestroy(&gvec);CHKERRQ(ierr);
258a30f8f8cSSatish Balay 
25952e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,baij->Mvctx);CHKERRQ(ierr);
26052e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,baij->lvec);CHKERRQ(ierr);
26152e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,from);CHKERRQ(ierr);
26252e6d16bSBarry Smith   ierr = PetscLogObjectParent(mat,to);CHKERRQ(ierr);
263a30f8f8cSSatish Balay   baij->garray = garray;
26452e6d16bSBarry Smith   ierr = PetscLogObjectMemory(mat,(ec+1)*sizeof(PetscInt));CHKERRQ(ierr);
265*6bf464f9SBarry Smith   ierr = ISDestroy(&from);CHKERRQ(ierr);
266*6bf464f9SBarry Smith   ierr = ISDestroy(&to);CHKERRQ(ierr);
267a30f8f8cSSatish Balay   PetscFunctionReturn(0);
268a30f8f8cSSatish Balay }
269a30f8f8cSSatish Balay 
270a30f8f8cSSatish Balay /*
27101b2bd88SHong Zhang      Takes the local part of an already assembled MPISBAIJ matrix
272a30f8f8cSSatish Balay    and disassembles it. This is to allow new nonzeros into the matrix
273a30f8f8cSSatish Balay    that require more communication in the matrix vector multiply.
274a30f8f8cSSatish Balay    Thus certain data-structures must be rebuilt.
275a30f8f8cSSatish Balay 
276a30f8f8cSSatish Balay    Kind of slow! But that's what application programmers get when
277a30f8f8cSSatish Balay    they are sloppy.
278a30f8f8cSSatish Balay */
2794a2ae208SSatish Balay #undef __FUNCT__
2804a2ae208SSatish Balay #define __FUNCT__ "DisAssemble_MPISBAIJ"
281dfbe8321SBarry Smith PetscErrorCode DisAssemble_MPISBAIJ(Mat A)
282a30f8f8cSSatish Balay {
2832896befeSSatish Balay   Mat_MPISBAIJ   *baij = (Mat_MPISBAIJ*)A->data;
284a30f8f8cSSatish Balay   Mat            B = baij->B,Bnew;
285a30f8f8cSSatish Balay   Mat_SeqBAIJ    *Bbaij = (Mat_SeqBAIJ*)B->data;
286dfbe8321SBarry Smith   PetscErrorCode ierr;
287d0f46423SBarry Smith   PetscInt       i,j,mbs=Bbaij->mbs,n = A->cmap->N,col,*garray=baij->garray;
288d0f46423SBarry Smith   PetscInt       k,bs=A->rmap->bs,bs2=baij->bs2,*rvals,*nz,ec,m=A->rmap->n;
289a30f8f8cSSatish Balay   MatScalar      *a = Bbaij->a;
29087828ca2SBarry Smith   PetscScalar    *atmp;
291ce63c4c1SBarry Smith #if defined(PETSC_USE_REAL_MAT_SINGLE)
29213f74950SBarry Smith   PetscInt       l;
293a30f8f8cSSatish Balay #endif
294a30f8f8cSSatish Balay 
295a30f8f8cSSatish Balay   PetscFunctionBegin;
296ce63c4c1SBarry Smith #if defined(PETSC_USE_REAL_MAT_SINGLE)
297d0f46423SBarry Smith   ierr = PetscMalloc(A->rmap->bs*sizeof(PetscScalar),&atmp);
29882502324SSatish Balay #endif
299a30f8f8cSSatish Balay   /* free stuff related to matrix-vec multiply */
300b0a32e0cSBarry Smith   ierr = VecGetSize(baij->lvec,&ec);CHKERRQ(ierr); /* needed for PetscLogObjectMemory below */
301*6bf464f9SBarry Smith   ierr = VecDestroy(&baij->lvec);CHKERRQ(ierr);
302*6bf464f9SBarry Smith   ierr = VecScatterDestroy(&baij->Mvctx);CHKERRQ(ierr);
30301b2bd88SHong Zhang 
304*6bf464f9SBarry Smith   ierr = VecDestroy(&baij->slvec0);CHKERRQ(ierr);
305*6bf464f9SBarry Smith   ierr = VecDestroy(&baij->slvec0b);CHKERRQ(ierr);
306*6bf464f9SBarry Smith   ierr = VecDestroy(&baij->slvec1);CHKERRQ(ierr);
307*6bf464f9SBarry Smith   ierr = VecDestroy(&baij->slvec1a);CHKERRQ(ierr);
308*6bf464f9SBarry Smith   ierr = VecDestroy(&baij->slvec1b);CHKERRQ(ierr);
30901b2bd88SHong Zhang 
310a30f8f8cSSatish Balay   if (baij->colmap) {
311a30f8f8cSSatish Balay #if defined (PETSC_USE_CTABLE)
3129c666560SBarry Smith     ierr = PetscTableDestroy(baij->colmap); baij->colmap = 0;CHKERRQ(ierr);
313a30f8f8cSSatish Balay #else
314a30f8f8cSSatish Balay     ierr = PetscFree(baij->colmap);CHKERRQ(ierr);
315a30f8f8cSSatish Balay     baij->colmap = 0;
31652e6d16bSBarry Smith     ierr = PetscLogObjectMemory(A,-Bbaij->nbs*sizeof(PetscInt));CHKERRQ(ierr);
317a30f8f8cSSatish Balay #endif
318a30f8f8cSSatish Balay   }
319a30f8f8cSSatish Balay 
320a30f8f8cSSatish Balay   /* make sure that B is assembled so we can access its values */
321a30f8f8cSSatish Balay   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
322a30f8f8cSSatish Balay   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
323a30f8f8cSSatish Balay 
324a30f8f8cSSatish Balay   /* invent new B and copy stuff over */
32513f74950SBarry Smith   ierr = PetscMalloc(mbs*sizeof(PetscInt),&nz);CHKERRQ(ierr);
326a30f8f8cSSatish Balay   for (i=0; i<mbs; i++) {
327a30f8f8cSSatish Balay     nz[i] = Bbaij->i[i+1]-Bbaij->i[i];
328a30f8f8cSSatish Balay   }
329f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&Bnew);CHKERRQ(ierr);
330f69a0ea3SMatthew Knepley   ierr = MatSetSizes(Bnew,m,n,m,n);CHKERRQ(ierr);
3317adad957SLisandro Dalcin   ierr = MatSetType(Bnew,((PetscObject)B)->type_name);CHKERRQ(ierr);
332d0f46423SBarry Smith   ierr = MatSeqBAIJSetPreallocation(Bnew,B->rmap->bs,0,nz);CHKERRQ(ierr);
333a30f8f8cSSatish Balay   ierr = PetscFree(nz);CHKERRQ(ierr);
334a30f8f8cSSatish Balay 
33513f74950SBarry Smith   ierr = PetscMalloc(bs*sizeof(PetscInt),&rvals);CHKERRQ(ierr);
336a30f8f8cSSatish Balay   for (i=0; i<mbs; i++) {
337a30f8f8cSSatish Balay     rvals[0] = bs*i;
338a30f8f8cSSatish Balay     for (j=1; j<bs; j++) { rvals[j] = rvals[j-1] + 1; }
339a30f8f8cSSatish Balay     for (j=Bbaij->i[i]; j<Bbaij->i[i+1]; j++) {
340a30f8f8cSSatish Balay       col = garray[Bbaij->j[j]]*bs;
341a30f8f8cSSatish Balay       for (k=0; k<bs; k++) {
342ce63c4c1SBarry Smith #if defined(PETSC_USE_REAL_MAT_SINGLE)
343a30f8f8cSSatish Balay         for (l=0; l<bs; l++) atmp[l] = a[j*bs2+l];
344a30f8f8cSSatish Balay #else
34571730473SSatish Balay         atmp = a+j*bs2 + k*bs;
346a30f8f8cSSatish Balay #endif
347c8407628SSatish Balay         ierr = MatSetValues_SeqSBAIJ(Bnew,bs,rvals,1,&col,atmp,B->insertmode);CHKERRQ(ierr);
348a30f8f8cSSatish Balay         col++;
349a30f8f8cSSatish Balay       }
350a30f8f8cSSatish Balay     }
351a30f8f8cSSatish Balay   }
352ce63c4c1SBarry Smith #if defined(PETSC_USE_REAL_MAT_SINGLE)
353a30f8f8cSSatish Balay   ierr = PetscFree(atmp);CHKERRQ(ierr);
354a30f8f8cSSatish Balay #endif
355a30f8f8cSSatish Balay   ierr = PetscFree(baij->garray);CHKERRQ(ierr);
356a30f8f8cSSatish Balay   baij->garray = 0;
357a30f8f8cSSatish Balay   ierr = PetscFree(rvals);CHKERRQ(ierr);
35852e6d16bSBarry Smith   ierr = PetscLogObjectMemory(A,-ec*sizeof(PetscInt));CHKERRQ(ierr);
359*6bf464f9SBarry Smith   ierr = MatDestroy(&B);CHKERRQ(ierr);
36052e6d16bSBarry Smith   ierr = PetscLogObjectParent(A,Bnew);CHKERRQ(ierr);
361a30f8f8cSSatish Balay   baij->B = Bnew;
362a30f8f8cSSatish Balay   A->was_assembled = PETSC_FALSE;
363a30f8f8cSSatish Balay   PetscFunctionReturn(0);
364a30f8f8cSSatish Balay }
365a30f8f8cSSatish Balay 
366a30f8f8cSSatish Balay 
367a30f8f8cSSatish Balay 
368