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