xref: /petsc/src/mat/impls/sbaij/mpi/mmsbaij.c (revision 9566063d113dddea24716c546802770db7481bc0)
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 
7dfbe8321SBarry Smith PetscErrorCode MatSetUpMultiply_MPISBAIJ(Mat mat)
8a30f8f8cSSatish Balay {
940781036SHong Zhang   Mat_MPISBAIJ   *sbaij = (Mat_MPISBAIJ*)mat->data;
1040781036SHong Zhang   Mat_SeqBAIJ    *B     = (Mat_SeqBAIJ*)(sbaij->B->data);
11a11b0bdaSJunchao Zhang   PetscInt       Nbs = sbaij->Nbs,i,j,*aj = B->j,ec = 0,*garray,*sgarray;
12d0f46423SBarry Smith   PetscInt       bs  = mat->rmap->bs,*stmp,mbs=sbaij->mbs, vec_size,nt;
1340781036SHong Zhang   IS             from,to;
1440781036SHong Zhang   Vec            gvec;
15a11b0bdaSJunchao Zhang   PetscMPIInt    rank = sbaij->rank,lsize;
16077aedafSJed Brown   PetscInt       *owners = sbaij->rangebs,*ec_owner,k;
17077aedafSJed Brown   const PetscInt *sowners;
1840781036SHong Zhang   PetscScalar    *ptr;
19a11b0bdaSJunchao Zhang #if defined(PETSC_USE_CTABLE)
20a11b0bdaSJunchao Zhang   PetscTable         gid1_lid1; /* one-based gid to lid table */
21a11b0bdaSJunchao Zhang   PetscTablePosition tpos;
22a11b0bdaSJunchao Zhang   PetscInt           gid,lid;
23a11b0bdaSJunchao Zhang #else
24a11b0bdaSJunchao Zhang   PetscInt           *indices;
25a11b0bdaSJunchao Zhang #endif
2640781036SHong Zhang 
2740781036SHong Zhang   PetscFunctionBegin;
28a11b0bdaSJunchao Zhang #if defined(PETSC_USE_CTABLE)
29*9566063dSJacob Faibussowitsch   PetscCall(PetscTableCreate(mbs,Nbs+1,&gid1_lid1));
30a11b0bdaSJunchao Zhang   for (i=0; i<B->mbs; i++) {
31a11b0bdaSJunchao Zhang     for (j=0; j<B->ilen[i]; j++) {
32a11b0bdaSJunchao Zhang       PetscInt data,gid1 = aj[B->i[i]+j] + 1;
33*9566063dSJacob Faibussowitsch       PetscCall(PetscTableFind(gid1_lid1,gid1,&data));
34*9566063dSJacob Faibussowitsch       if (!data) PetscCall(PetscTableAdd(gid1_lid1,gid1,++ec,INSERT_VALUES));
35a11b0bdaSJunchao Zhang     }
36a11b0bdaSJunchao Zhang   }
37a11b0bdaSJunchao Zhang   /* form array of columns we need */
38*9566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ec,&garray));
39*9566063dSJacob Faibussowitsch   PetscCall(PetscTableGetHeadPosition(gid1_lid1,&tpos));
40a11b0bdaSJunchao Zhang   while (tpos) {
41*9566063dSJacob Faibussowitsch     PetscCall(PetscTableGetNext(gid1_lid1,&tpos,&gid,&lid));
42a11b0bdaSJunchao Zhang     gid--; lid--;
43a11b0bdaSJunchao Zhang     garray[lid] = gid;
44a11b0bdaSJunchao Zhang   }
45*9566063dSJacob Faibussowitsch   PetscCall(PetscSortInt(ec,garray));
46*9566063dSJacob Faibussowitsch   PetscCall(PetscTableRemoveAll(gid1_lid1));
47*9566063dSJacob Faibussowitsch   for (i=0; i<ec; i++) PetscCall(PetscTableAdd(gid1_lid1,garray[i]+1,i+1,INSERT_VALUES));
48a11b0bdaSJunchao Zhang   /* compact out the extra columns in B */
49a11b0bdaSJunchao Zhang   for (i=0; i<B->mbs; i++) {
50a11b0bdaSJunchao Zhang     for (j=0; j<B->ilen[i]; j++) {
51a11b0bdaSJunchao Zhang       PetscInt gid1 = aj[B->i[i] + j] + 1;
52*9566063dSJacob Faibussowitsch       PetscCall(PetscTableFind(gid1_lid1,gid1,&lid));
53a11b0bdaSJunchao Zhang       lid--;
54a11b0bdaSJunchao Zhang       aj[B->i[i]+j] = lid;
55a11b0bdaSJunchao Zhang     }
56a11b0bdaSJunchao Zhang   }
57*9566063dSJacob Faibussowitsch   PetscCall(PetscTableDestroy(&gid1_lid1));
58*9566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(2*ec,&sgarray,ec,&ec_owner));
59a11b0bdaSJunchao Zhang   for (i=j=0; i<ec; i++) {
60a11b0bdaSJunchao Zhang     while (garray[i]>=owners[j+1]) j++;
61a11b0bdaSJunchao Zhang     ec_owner[i] = j;
62a11b0bdaSJunchao Zhang   }
63a11b0bdaSJunchao Zhang #else
6440781036SHong Zhang   /* For the first stab we make an array as long as the number of columns */
6540781036SHong Zhang   /* mark those columns that are in sbaij->B */
66*9566063dSJacob Faibussowitsch   PetscCall(PetscCalloc1(Nbs,&indices));
6740781036SHong Zhang   for (i=0; i<mbs; i++) {
6840781036SHong Zhang     for (j=0; j<B->ilen[i]; j++) {
6940781036SHong Zhang       if (!indices[aj[B->i[i] + j]]) ec++;
7040781036SHong Zhang       indices[aj[B->i[i] + j]] = 1;
7140781036SHong Zhang     }
7240781036SHong Zhang   }
7340781036SHong Zhang 
7440781036SHong Zhang   /* form arrays of columns we need */
75*9566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(ec,&garray));
76*9566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(2*ec,&sgarray,ec,&ec_owner));
7740781036SHong Zhang 
7840781036SHong Zhang   ec = 0;
79a11b0bdaSJunchao Zhang   for (j=0; j<sbaij->size; j++) {
8040781036SHong Zhang     for (i=owners[j]; i<owners[j+1]; i++) {
8140781036SHong Zhang       if (indices[i]) {
8240781036SHong Zhang         garray[ec]   = i;
8340781036SHong Zhang         ec_owner[ec] = j;
8440781036SHong Zhang         ec++;
8540781036SHong Zhang       }
8640781036SHong Zhang     }
8740781036SHong Zhang   }
8840781036SHong Zhang 
8940781036SHong Zhang   /* make indices now point into garray */
90b424e231SHong Zhang   for (i=0; i<ec; i++) indices[garray[i]] = i;
9140781036SHong Zhang 
9240781036SHong Zhang   /* compact out the extra columns in B */
9340781036SHong Zhang   for (i=0; i<mbs; i++) {
9440781036SHong Zhang     for (j=0; j<B->ilen[i]; j++) aj[B->i[i] + j] = indices[aj[B->i[i] + j]];
9540781036SHong Zhang   }
96*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(indices));
97a11b0bdaSJunchao Zhang #endif
9840781036SHong Zhang   B->nbs = ec;
99*9566063dSJacob Faibussowitsch   PetscCall(PetscLayoutDestroy(&sbaij->B->cmap));
100*9566063dSJacob Faibussowitsch   PetscCall(PetscLayoutCreateFromSizes(PetscObjectComm((PetscObject)sbaij->B),ec*mat->rmap->bs,ec*mat->rmap->bs,mat->rmap->bs,&sbaij->B->cmap));
10140781036SHong Zhang 
102*9566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&sbaij->sMvctx));
10340781036SHong Zhang   /* create local vector that is used to scatter into */
104*9566063dSJacob Faibussowitsch   PetscCall(VecCreateSeq(PETSC_COMM_SELF,ec*bs,&sbaij->lvec));
10540781036SHong Zhang 
10640781036SHong Zhang   /* create two temporary index sets for building scatter-gather */
107*9566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(2*ec,&stmp));
108*9566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(PETSC_COMM_SELF,bs,ec,garray,PETSC_COPY_VALUES,&from));
10926fbe8dcSKarl Rupp   for (i=0; i<ec; i++) stmp[i] = i;
110*9566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(PETSC_COMM_SELF,bs,ec,stmp,PETSC_COPY_VALUES,&to));
11140781036SHong Zhang 
11293d1592dSHong Zhang   /* generate the scatter context
113bd096759SJunchao Zhang      -- Mvctx and lvec are not used by MatMult_MPISBAIJ(), but have other uses, such as in MatDiagonalScale_MPISBAIJ */
114*9566063dSJacob Faibussowitsch   PetscCall(VecCreateMPIWithArray(PetscObjectComm((PetscObject)mat),1,mat->cmap->n,mat->cmap->N,NULL,&gvec));
115*9566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(gvec,from,sbaij->lvec,to,&sbaij->Mvctx));
116*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&gvec));
11740781036SHong Zhang 
11840781036SHong Zhang   sbaij->garray = garray;
11926fbe8dcSKarl Rupp 
120*9566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)sbaij->Mvctx));
121*9566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)sbaij->lvec));
122*9566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)from));
123*9566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)to));
12440781036SHong Zhang 
125*9566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&from));
126*9566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&to));
12740781036SHong Zhang 
12840781036SHong Zhang   /* create parallel vector that is used by SBAIJ matrix to scatter from/into */
12940781036SHong Zhang   lsize = (mbs + ec)*bs;
130*9566063dSJacob Faibussowitsch   PetscCall(VecCreateMPI(PetscObjectComm((PetscObject)mat),lsize,PETSC_DETERMINE,&sbaij->slvec0));
131*9566063dSJacob Faibussowitsch   PetscCall(VecDuplicate(sbaij->slvec0,&sbaij->slvec1));
132*9566063dSJacob Faibussowitsch   PetscCall(VecGetSize(sbaij->slvec0,&vec_size));
13340781036SHong Zhang 
134*9566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRanges(sbaij->slvec0,&sowners));
13540781036SHong Zhang 
13640781036SHong Zhang   /* x index in the IS sfrom */
13740781036SHong Zhang   for (i=0; i<ec; i++) {
13840781036SHong Zhang     j          = ec_owner[i];
13940781036SHong Zhang     sgarray[i] = garray[i] + (sowners[j]/bs - owners[j]);
14040781036SHong Zhang   }
14140781036SHong Zhang   /* b index in the IS sfrom */
14240781036SHong Zhang   k = sowners[rank]/bs + mbs;
14340781036SHong Zhang   for (i=ec,j=0; i< 2*ec; i++,j++) sgarray[i] = k + j;
144*9566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(PETSC_COMM_SELF,bs,2*ec,sgarray,PETSC_COPY_VALUES,&from));
14540781036SHong Zhang 
14640781036SHong Zhang   /* x index in the IS sto */
14740781036SHong Zhang   k = sowners[rank]/bs + mbs;
148e82e9f6bSBarry Smith   for (i=0; i<ec; i++) stmp[i] = (k + i);
14940781036SHong Zhang   /* b index in the IS sto */
150e82e9f6bSBarry Smith   for (i=ec; i<2*ec; i++) stmp[i] = sgarray[i-ec];
15140781036SHong Zhang 
152*9566063dSJacob Faibussowitsch   PetscCall(ISCreateBlock(PETSC_COMM_SELF,bs,2*ec,stmp,PETSC_COPY_VALUES,&to));
15340781036SHong Zhang 
154*9566063dSJacob Faibussowitsch   PetscCall(VecScatterCreate(sbaij->slvec0,from,sbaij->slvec1,to,&sbaij->sMvctx));
155*9566063dSJacob Faibussowitsch   PetscCall(VecScatterViewFromOptions(sbaij->sMvctx,(PetscObject)mat,"-matmult_vecscatter_view"));
15640781036SHong Zhang 
157*9566063dSJacob Faibussowitsch   PetscCall(VecGetLocalSize(sbaij->slvec1,&nt));
158*9566063dSJacob Faibussowitsch   PetscCall(VecGetArray(sbaij->slvec1,&ptr));
159*9566063dSJacob Faibussowitsch   PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF,1,bs*mbs,ptr,&sbaij->slvec1a));
160*9566063dSJacob Faibussowitsch   PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF,1,nt-bs*mbs,ptr+bs*mbs,&sbaij->slvec1b));
161*9566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(sbaij->slvec1,&ptr));
16240781036SHong Zhang 
163*9566063dSJacob Faibussowitsch   PetscCall(VecGetArray(sbaij->slvec0,&ptr));
164*9566063dSJacob Faibussowitsch   PetscCall(VecCreateSeqWithArray(PETSC_COMM_SELF,1,nt-bs*mbs,ptr+bs*mbs,&sbaij->slvec0b));
165*9566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(sbaij->slvec0,&ptr));
16640781036SHong Zhang 
167*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(stmp));
16840781036SHong Zhang 
169*9566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)sbaij->sMvctx));
170*9566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)sbaij->slvec0));
171*9566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)sbaij->slvec1));
172*9566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)sbaij->slvec0b));
173*9566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)sbaij->slvec1a));
174*9566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)sbaij->slvec1b));
175*9566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)from));
176*9566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectParent((PetscObject)mat,(PetscObject)to));
17740781036SHong Zhang 
178*9566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectMemory((PetscObject)mat,ec*sizeof(PetscInt)));
179*9566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&from));
180*9566063dSJacob Faibussowitsch   PetscCall(ISDestroy(&to));
181*9566063dSJacob Faibussowitsch   PetscCall(PetscFree2(sgarray,ec_owner));
18240781036SHong Zhang   PetscFunctionReturn(0);
18340781036SHong Zhang }
18440781036SHong Zhang 
185a30f8f8cSSatish Balay /*
18601b2bd88SHong Zhang      Takes the local part of an already assembled MPISBAIJ matrix
187a30f8f8cSSatish Balay    and disassembles it. This is to allow new nonzeros into the matrix
188a30f8f8cSSatish Balay    that require more communication in the matrix vector multiply.
189a30f8f8cSSatish Balay    Thus certain data-structures must be rebuilt.
190a30f8f8cSSatish Balay 
191a30f8f8cSSatish Balay    Kind of slow! But that's what application programmers get when
192a30f8f8cSSatish Balay    they are sloppy.
193a30f8f8cSSatish Balay */
194ab9863d7SBarry Smith PetscErrorCode MatDisAssemble_MPISBAIJ(Mat A)
195a30f8f8cSSatish Balay {
1962896befeSSatish Balay   Mat_MPISBAIJ   *baij  = (Mat_MPISBAIJ*)A->data;
197a30f8f8cSSatish Balay   Mat            B      = baij->B,Bnew;
198a30f8f8cSSatish Balay   Mat_SeqBAIJ    *Bbaij = (Mat_SeqBAIJ*)B->data;
199d0f46423SBarry Smith   PetscInt       i,j,mbs=Bbaij->mbs,n = A->cmap->N,col,*garray=baij->garray;
200d0f46423SBarry Smith   PetscInt       k,bs=A->rmap->bs,bs2=baij->bs2,*rvals,*nz,ec,m=A->rmap->n;
201a30f8f8cSSatish Balay   MatScalar      *a = Bbaij->a;
20287828ca2SBarry Smith   PetscScalar    *atmp;
203ce63c4c1SBarry Smith #if defined(PETSC_USE_REAL_MAT_SINGLE)
20413f74950SBarry Smith   PetscInt l;
205a30f8f8cSSatish Balay #endif
206a30f8f8cSSatish Balay 
207a30f8f8cSSatish Balay   PetscFunctionBegin;
208ce63c4c1SBarry Smith #if defined(PETSC_USE_REAL_MAT_SINGLE)
209*9566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(A->rmap->bs,&atmp));
21082502324SSatish Balay #endif
211a30f8f8cSSatish Balay   /* free stuff related to matrix-vec multiply */
212*9566063dSJacob Faibussowitsch   PetscCall(VecGetSize(baij->lvec,&ec)); /* needed for PetscLogObjectMemory below */
213*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&baij->lvec));
214*9566063dSJacob Faibussowitsch   PetscCall(VecScatterDestroy(&baij->Mvctx));
21501b2bd88SHong Zhang 
216*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&baij->slvec0));
217*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&baij->slvec0b));
218*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&baij->slvec1));
219*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&baij->slvec1a));
220*9566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&baij->slvec1b));
22101b2bd88SHong Zhang 
222a30f8f8cSSatish Balay   if (baij->colmap) {
223a30f8f8cSSatish Balay #if defined(PETSC_USE_CTABLE)
224*9566063dSJacob Faibussowitsch     PetscCall(PetscTableDestroy(&baij->colmap));
225a30f8f8cSSatish Balay #else
226*9566063dSJacob Faibussowitsch     PetscCall(PetscFree(baij->colmap));
227*9566063dSJacob Faibussowitsch     PetscCall(PetscLogObjectMemory((PetscObject)A,-Bbaij->nbs*sizeof(PetscInt)));
228a30f8f8cSSatish Balay #endif
229a30f8f8cSSatish Balay   }
230a30f8f8cSSatish Balay 
231a30f8f8cSSatish Balay   /* make sure that B is assembled so we can access its values */
232*9566063dSJacob Faibussowitsch   PetscCall(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY));
233*9566063dSJacob Faibussowitsch   PetscCall(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY));
234a30f8f8cSSatish Balay 
235a30f8f8cSSatish Balay   /* invent new B and copy stuff over */
236*9566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(mbs,&nz));
237a30f8f8cSSatish Balay   for (i=0; i<mbs; i++) {
238a30f8f8cSSatish Balay     nz[i] = Bbaij->i[i+1]-Bbaij->i[i];
239a30f8f8cSSatish Balay   }
240*9566063dSJacob Faibussowitsch   PetscCall(MatCreate(PETSC_COMM_SELF,&Bnew));
241*9566063dSJacob Faibussowitsch   PetscCall(MatSetSizes(Bnew,m,n,m,n));
242*9566063dSJacob Faibussowitsch   PetscCall(MatSetType(Bnew,((PetscObject)B)->type_name));
243*9566063dSJacob Faibussowitsch   PetscCall(MatSeqBAIJSetPreallocation(Bnew,B->rmap->bs,0,nz));
244*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(nz));
245a30f8f8cSSatish Balay 
246b38c15b3SStefano Zampini   if (Bbaij->nonew >= 0) { /* Inherit insertion error options (if positive). */
247b38c15b3SStefano Zampini     ((Mat_SeqSBAIJ*)Bnew->data)->nonew = Bbaij->nonew;
248b38c15b3SStefano Zampini   }
249b38c15b3SStefano Zampini 
25077341eacSDmitry Karpeev   /*
25177341eacSDmitry Karpeev    Ensure that B's nonzerostate is monotonically increasing.
25277341eacSDmitry Karpeev    Or should this follow the MatSetValues() loop to preserve B's nonzerstate across a MatDisAssemble() call?
25377341eacSDmitry Karpeev    */
25477341eacSDmitry Karpeev   Bnew->nonzerostate = B->nonzerostate;
255*9566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(bs,&rvals));
256a30f8f8cSSatish Balay   for (i=0; i<mbs; i++) {
257a30f8f8cSSatish Balay     rvals[0] = bs*i;
25826fbe8dcSKarl Rupp     for (j=1; j<bs; j++) rvals[j] = rvals[j-1] + 1;
259a30f8f8cSSatish Balay     for (j=Bbaij->i[i]; j<Bbaij->i[i+1]; j++) {
260a30f8f8cSSatish Balay       col = garray[Bbaij->j[j]]*bs;
261a30f8f8cSSatish Balay       for (k=0; k<bs; k++) {
262ce63c4c1SBarry Smith #if defined(PETSC_USE_REAL_MAT_SINGLE)
263a30f8f8cSSatish Balay         for (l=0; l<bs; l++) atmp[l] = a[j*bs2+l];
264a30f8f8cSSatish Balay #else
26571730473SSatish Balay         atmp = a+j*bs2 + k*bs;
266a30f8f8cSSatish Balay #endif
267*9566063dSJacob Faibussowitsch         PetscCall(MatSetValues_SeqSBAIJ(Bnew,bs,rvals,1,&col,atmp,B->insertmode));
268a30f8f8cSSatish Balay         col++;
269a30f8f8cSSatish Balay       }
270a30f8f8cSSatish Balay     }
271a30f8f8cSSatish Balay   }
272ce63c4c1SBarry Smith #if defined(PETSC_USE_REAL_MAT_SINGLE)
273*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(atmp));
274a30f8f8cSSatish Balay #endif
275*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(baij->garray));
27626fbe8dcSKarl Rupp 
277f4259b30SLisandro Dalcin   baij->garray = NULL;
27826fbe8dcSKarl Rupp 
279*9566063dSJacob Faibussowitsch   PetscCall(PetscFree(rvals));
280*9566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectMemory((PetscObject)A,-ec*sizeof(PetscInt)));
281*9566063dSJacob Faibussowitsch   PetscCall(MatDestroy(&B));
282*9566063dSJacob Faibussowitsch   PetscCall(PetscLogObjectParent((PetscObject)A,(PetscObject)Bnew));
28326fbe8dcSKarl Rupp 
284a30f8f8cSSatish Balay   baij->B = Bnew;
28526fbe8dcSKarl Rupp 
286a30f8f8cSSatish Balay   A->was_assembled = PETSC_FALSE;
287a30f8f8cSSatish Balay   PetscFunctionReturn(0);
288a30f8f8cSSatish Balay }
289