xref: /petsc/src/mat/impls/is/matis.c (revision a2b725a8db0d6bf6cc2a1c6df7dd8029aadfff6e)
1b4319ba4SBarry Smith /*
2b4319ba4SBarry Smith     Creates a matrix class for using the Neumann-Neumann type preconditioners.
3b4319ba4SBarry Smith     This stores the matrices in globally unassembled form. Each processor
4b4319ba4SBarry Smith     assembles only its local Neumann problem and the parallel matrix vector
5b4319ba4SBarry Smith     product is handled "implicitly".
6b4319ba4SBarry Smith 
7b4319ba4SBarry Smith     Currently this allows for only one subdomain per processor.
8b4319ba4SBarry Smith */
9b4319ba4SBarry Smith 
10c6db04a5SJed Brown #include <../src/mat/impls/is/matis.h>      /*I "petscmat.h" I*/
114f2d7cafSStefano Zampini #include <petsc/private/sfimpl.h>
1228f4e0baSStefano Zampini 
13f26d0771SStefano Zampini #define MATIS_MAX_ENTRIES_INSERTION 2048
14b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode);
15b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode);
168546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat);
17f26d0771SStefano Zampini 
1875d48cdbSStefano Zampini static PetscErrorCode MatISContainerDestroyPtAP_Private(void *ptr)
1975d48cdbSStefano Zampini {
2075d48cdbSStefano Zampini   MatISPtAP      ptap = (MatISPtAP)ptr;
2175d48cdbSStefano Zampini   PetscErrorCode ierr;
2275d48cdbSStefano Zampini 
2375d48cdbSStefano Zampini   PetscFunctionBegin;
2475d48cdbSStefano Zampini   ierr = MatDestroySubMatrices(ptap->ris1 ? 2 : 1,&ptap->lP);CHKERRQ(ierr);
2575d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->cis0);CHKERRQ(ierr);
2675d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->cis1);CHKERRQ(ierr);
2775d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->ris0);CHKERRQ(ierr);
2875d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->ris1);CHKERRQ(ierr);
2975d48cdbSStefano Zampini   ierr = PetscFree(ptap);CHKERRQ(ierr);
3075d48cdbSStefano Zampini   PetscFunctionReturn(0);
3175d48cdbSStefano Zampini }
3275d48cdbSStefano Zampini 
3375d48cdbSStefano Zampini static PetscErrorCode MatPtAPNumeric_IS_XAIJ(Mat A, Mat P, Mat C)
3475d48cdbSStefano Zampini {
3575d48cdbSStefano Zampini   MatISPtAP      ptap;
3675d48cdbSStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
3775d48cdbSStefano Zampini   Mat            lA,lC;
3875d48cdbSStefano Zampini   MatReuse       reuse;
3975d48cdbSStefano Zampini   IS             ris[2],cis[2];
4075d48cdbSStefano Zampini   PetscContainer c;
4175d48cdbSStefano Zampini   PetscInt       n;
4275d48cdbSStefano Zampini   PetscErrorCode ierr;
4375d48cdbSStefano Zampini 
4475d48cdbSStefano Zampini   PetscFunctionBegin;
456afe12f5SStefano Zampini   ierr = PetscObjectQuery((PetscObject)C,"_MatIS_PtAP",(PetscObject*)&c);CHKERRQ(ierr);
4675d48cdbSStefano Zampini   if (!c) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing PtAP information");
4775d48cdbSStefano Zampini   ierr   = PetscContainerGetPointer(c,(void**)&ptap);CHKERRQ(ierr);
4875d48cdbSStefano Zampini   ris[0] = ptap->ris0;
4975d48cdbSStefano Zampini   ris[1] = ptap->ris1;
5075d48cdbSStefano Zampini   cis[0] = ptap->cis0;
5175d48cdbSStefano Zampini   cis[1] = ptap->cis1;
5275d48cdbSStefano Zampini   n      = ptap->ris1 ? 2 : 1;
5375d48cdbSStefano Zampini   reuse  = ptap->lP ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX;
5475d48cdbSStefano Zampini   ierr   = MatCreateSubMatrices(P,n,ris,cis,reuse,&ptap->lP);CHKERRQ(ierr);
5575d48cdbSStefano Zampini 
5675d48cdbSStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
5775d48cdbSStefano Zampini   ierr = MatISGetLocalMat(C,&lC);CHKERRQ(ierr);
5875d48cdbSStefano Zampini   if (ptap->ris1) { /* unsymmetric A mapping */
5975d48cdbSStefano Zampini     Mat lPt;
6075d48cdbSStefano Zampini 
6175d48cdbSStefano Zampini     ierr = MatTranspose(ptap->lP[1],MAT_INITIAL_MATRIX,&lPt);CHKERRQ(ierr);
6275d48cdbSStefano Zampini     ierr = MatMatMatMult(lPt,lA,ptap->lP[0],reuse,ptap->fill,&lC);CHKERRQ(ierr);
6375d48cdbSStefano Zampini     if (matis->storel2l) {
6475d48cdbSStefano Zampini       ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",(PetscObject)lPt);CHKERRQ(ierr);
6575d48cdbSStefano Zampini     }
6675d48cdbSStefano Zampini     ierr = MatDestroy(&lPt);CHKERRQ(ierr);
6775d48cdbSStefano Zampini   } else {
6875d48cdbSStefano Zampini     ierr = MatPtAP(lA,ptap->lP[0],reuse,ptap->fill,&lC);CHKERRQ(ierr);
6975d48cdbSStefano Zampini     if (matis->storel2l) {
7075d48cdbSStefano Zampini      ierr = PetscObjectCompose((PetscObject)(C),"_MatIS_PtAP_l2l",(PetscObject)ptap->lP[0]);CHKERRQ(ierr);
7175d48cdbSStefano Zampini     }
7275d48cdbSStefano Zampini   }
7375d48cdbSStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
7475d48cdbSStefano Zampini     ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
7575d48cdbSStefano Zampini     ierr = MatDestroy(&lC);CHKERRQ(ierr);
7675d48cdbSStefano Zampini   }
7775d48cdbSStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7875d48cdbSStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7975d48cdbSStefano Zampini   PetscFunctionReturn(0);
8075d48cdbSStefano Zampini }
8175d48cdbSStefano Zampini 
8275d48cdbSStefano Zampini static PetscErrorCode MatGetNonzeroColumnsLocal_Private(Mat PT,IS *cis)
8375d48cdbSStefano Zampini {
8475d48cdbSStefano Zampini   Mat            Po,Pd;
8575d48cdbSStefano Zampini   IS             zd,zo;
8675d48cdbSStefano Zampini   const PetscInt *garray;
8775d48cdbSStefano Zampini   PetscInt       *aux,i,bs;
8875d48cdbSStefano Zampini   PetscInt       dc,stc,oc,ctd,cto;
8975d48cdbSStefano Zampini   PetscBool      ismpiaij,ismpibaij,isseqaij,isseqbaij;
9075d48cdbSStefano Zampini   MPI_Comm       comm;
9175d48cdbSStefano Zampini   PetscErrorCode ierr;
9275d48cdbSStefano Zampini 
9375d48cdbSStefano Zampini   PetscFunctionBegin;
9475d48cdbSStefano Zampini   PetscValidHeaderSpecific(PT,MAT_CLASSID,1);
9575d48cdbSStefano Zampini   PetscValidPointer(cis,2);
9675d48cdbSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)PT,&comm);CHKERRQ(ierr);
9775d48cdbSStefano Zampini   bs   = 1;
9875d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
9975d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
10004637862SRichard Tran Mills   ierr = PetscObjectBaseTypeCompare((PetscObject)PT,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
10175d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
10275d48cdbSStefano Zampini   if (isseqaij || isseqbaij) {
10375d48cdbSStefano Zampini     Pd = PT;
10475d48cdbSStefano Zampini     Po = NULL;
10575d48cdbSStefano Zampini     garray = NULL;
10675d48cdbSStefano Zampini   } else if (ismpiaij) {
10775d48cdbSStefano Zampini     ierr = MatMPIAIJGetSeqAIJ(PT,&Pd,&Po,&garray);CHKERRQ(ierr);
10875d48cdbSStefano Zampini   } else if (ismpibaij) {
10975d48cdbSStefano Zampini     ierr = MatMPIBAIJGetSeqBAIJ(PT,&Pd,&Po,&garray);CHKERRQ(ierr);
11075d48cdbSStefano Zampini     ierr = MatGetBlockSize(PT,&bs);CHKERRQ(ierr);
11175d48cdbSStefano Zampini   } else SETERRQ1(comm,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(PT))->type_name);
11275d48cdbSStefano Zampini 
11375d48cdbSStefano Zampini   /* identify any null columns in Pd or Po */
11422f7620eSStefano Zampini   /* We use a tolerance comparison since it may happen that, with geometric multigrid,
11522f7620eSStefano Zampini      some of the columns are not really zero, but very close to */
11675d48cdbSStefano Zampini   zo = zd = NULL;
11775d48cdbSStefano Zampini   if (Po) {
11822f7620eSStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(Po,PETSC_TRUE,PETSC_SMALL,&zo);CHKERRQ(ierr);
11975d48cdbSStefano Zampini   }
12022f7620eSStefano Zampini   ierr = MatFindNonzeroRowsOrCols_Basic(Pd,PETSC_TRUE,PETSC_SMALL,&zd);CHKERRQ(ierr);
12175d48cdbSStefano Zampini 
12275d48cdbSStefano Zampini   ierr = MatGetLocalSize(PT,NULL,&dc);CHKERRQ(ierr);
12375d48cdbSStefano Zampini   ierr = MatGetOwnershipRangeColumn(PT,&stc,NULL);CHKERRQ(ierr);
12475d48cdbSStefano Zampini   if (Po) { ierr = MatGetLocalSize(Po,NULL,&oc);CHKERRQ(ierr); }
12575d48cdbSStefano Zampini   else oc = 0;
12675d48cdbSStefano Zampini   ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
12775d48cdbSStefano Zampini   if (zd) {
12875d48cdbSStefano Zampini     const PetscInt *idxs;
12975d48cdbSStefano Zampini     PetscInt       nz;
13075d48cdbSStefano Zampini 
13175d48cdbSStefano Zampini     /* this will throw an error if bs is not valid */
13275d48cdbSStefano Zampini     ierr = ISSetBlockSize(zd,bs);CHKERRQ(ierr);
13375d48cdbSStefano Zampini     ierr = ISGetLocalSize(zd,&nz);CHKERRQ(ierr);
13475d48cdbSStefano Zampini     ierr = ISGetIndices(zd,&idxs);CHKERRQ(ierr);
13575d48cdbSStefano Zampini     ctd  = nz/bs;
13675d48cdbSStefano Zampini     for (i=0; i<ctd; i++) aux[i] = (idxs[bs*i]+stc)/bs;
13775d48cdbSStefano Zampini     ierr = ISRestoreIndices(zd,&idxs);CHKERRQ(ierr);
13875d48cdbSStefano Zampini   } else {
13975d48cdbSStefano Zampini     ctd = dc/bs;
14075d48cdbSStefano Zampini     for (i=0; i<ctd; i++) aux[i] = i+stc/bs;
14175d48cdbSStefano Zampini   }
14275d48cdbSStefano Zampini   if (zo) {
14375d48cdbSStefano Zampini     const PetscInt *idxs;
14475d48cdbSStefano Zampini     PetscInt       nz;
14575d48cdbSStefano Zampini 
14675d48cdbSStefano Zampini     /* this will throw an error if bs is not valid */
14775d48cdbSStefano Zampini     ierr = ISSetBlockSize(zo,bs);CHKERRQ(ierr);
14875d48cdbSStefano Zampini     ierr = ISGetLocalSize(zo,&nz);CHKERRQ(ierr);
14975d48cdbSStefano Zampini     ierr = ISGetIndices(zo,&idxs);CHKERRQ(ierr);
15075d48cdbSStefano Zampini     cto  = nz/bs;
15175d48cdbSStefano Zampini     for (i=0; i<cto; i++) aux[i+ctd] = garray[idxs[bs*i]/bs];
15275d48cdbSStefano Zampini     ierr = ISRestoreIndices(zo,&idxs);CHKERRQ(ierr);
15375d48cdbSStefano Zampini   } else {
15475d48cdbSStefano Zampini     cto = oc/bs;
15575d48cdbSStefano Zampini     for (i=0; i<cto; i++) aux[i+ctd] = garray[i];
15675d48cdbSStefano Zampini   }
15775d48cdbSStefano Zampini   ierr = ISCreateBlock(comm,bs,ctd+cto,aux,PETSC_OWN_POINTER,cis);CHKERRQ(ierr);
15875d48cdbSStefano Zampini   ierr = ISDestroy(&zd);CHKERRQ(ierr);
15975d48cdbSStefano Zampini   ierr = ISDestroy(&zo);CHKERRQ(ierr);
16075d48cdbSStefano Zampini   PetscFunctionReturn(0);
16175d48cdbSStefano Zampini }
16275d48cdbSStefano Zampini 
16375d48cdbSStefano Zampini static PetscErrorCode MatPtAPSymbolic_IS_XAIJ(Mat A,Mat P,PetscReal fill,Mat *C)
16475d48cdbSStefano Zampini {
1658546b261SStefano Zampini   Mat                    PT,lA;
16675d48cdbSStefano Zampini   MatISPtAP              ptap;
16775d48cdbSStefano Zampini   ISLocalToGlobalMapping Crl2g,Ccl2g,rl2g,cl2g;
16875d48cdbSStefano Zampini   PetscContainer         c;
1698546b261SStefano Zampini   MatType                lmtype;
17075d48cdbSStefano Zampini   const PetscInt         *garray;
17175d48cdbSStefano Zampini   PetscInt               ibs,N,dc;
17275d48cdbSStefano Zampini   MPI_Comm               comm;
17375d48cdbSStefano Zampini   PetscErrorCode         ierr;
17475d48cdbSStefano Zampini 
17575d48cdbSStefano Zampini   PetscFunctionBegin;
17675d48cdbSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
17775d48cdbSStefano Zampini   ierr = MatCreate(comm,C);CHKERRQ(ierr);
17875d48cdbSStefano Zampini   ierr = MatSetType(*C,MATIS);CHKERRQ(ierr);
1798546b261SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1808546b261SStefano Zampini   ierr = MatGetType(lA,&lmtype);CHKERRQ(ierr);
1818546b261SStefano Zampini   ierr = MatISSetLocalMatType(*C,lmtype);CHKERRQ(ierr);
18275d48cdbSStefano Zampini   ierr = MatGetSize(P,NULL,&N);CHKERRQ(ierr);
18375d48cdbSStefano Zampini   ierr = MatGetLocalSize(P,NULL,&dc);CHKERRQ(ierr);
18475d48cdbSStefano Zampini   ierr = MatSetSizes(*C,dc,dc,N,N);CHKERRQ(ierr);
18575d48cdbSStefano Zampini /* Not sure about this
18675d48cdbSStefano Zampini   ierr = MatGetBlockSizes(P,NULL,&ibs);CHKERRQ(ierr);
18775d48cdbSStefano Zampini   ierr = MatSetBlockSize(*C,ibs);CHKERRQ(ierr);
18875d48cdbSStefano Zampini */
18975d48cdbSStefano Zampini 
19075d48cdbSStefano Zampini   ierr = PetscNew(&ptap);CHKERRQ(ierr);
19175d48cdbSStefano Zampini   ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
19275d48cdbSStefano Zampini   ierr = PetscContainerSetPointer(c,ptap);CHKERRQ(ierr);
19375d48cdbSStefano Zampini   ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyPtAP_Private);CHKERRQ(ierr);
19475d48cdbSStefano Zampini   ierr = PetscObjectCompose((PetscObject)(*C),"_MatIS_PtAP",(PetscObject)c);CHKERRQ(ierr);
19575d48cdbSStefano Zampini   ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
19675d48cdbSStefano Zampini   ptap->fill = fill;
19775d48cdbSStefano Zampini 
19875d48cdbSStefano Zampini   ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
19975d48cdbSStefano Zampini 
20075d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cl2g,&ibs);CHKERRQ(ierr);
20175d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cl2g,&N);CHKERRQ(ierr);
20275d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockIndices(cl2g,&garray);CHKERRQ(ierr);
20375d48cdbSStefano Zampini   ierr = ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris0);CHKERRQ(ierr);
20475d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&garray);CHKERRQ(ierr);
20575d48cdbSStefano Zampini 
20675d48cdbSStefano Zampini   ierr = MatCreateSubMatrix(P,ptap->ris0,NULL,MAT_INITIAL_MATRIX,&PT);CHKERRQ(ierr);
20775d48cdbSStefano Zampini   ierr = MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis0);CHKERRQ(ierr);
20875d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(ptap->cis0,&Ccl2g);CHKERRQ(ierr);
20975d48cdbSStefano Zampini   ierr = MatDestroy(&PT);CHKERRQ(ierr);
21075d48cdbSStefano Zampini 
21175d48cdbSStefano Zampini   Crl2g = NULL;
21275d48cdbSStefano Zampini   if (rl2g != cl2g) { /* unsymmetric A mapping */
21375d48cdbSStefano Zampini     PetscBool same,lsame = PETSC_FALSE;
21475d48cdbSStefano Zampini     PetscInt  N1,ibs1;
21575d48cdbSStefano Zampini 
21675d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(rl2g,&N1);CHKERRQ(ierr);
21775d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(rl2g,&ibs1);CHKERRQ(ierr);
21875d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(rl2g,&garray);CHKERRQ(ierr);
21975d48cdbSStefano Zampini     ierr = ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris1);CHKERRQ(ierr);
22075d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&garray);CHKERRQ(ierr);
22175d48cdbSStefano Zampini     if (ibs1 == ibs && N1 == N) { /* check if the l2gmaps are the same */
22275d48cdbSStefano Zampini       const PetscInt *i1,*i2;
22375d48cdbSStefano Zampini 
22475d48cdbSStefano Zampini       ierr = ISBlockGetIndices(ptap->ris0,&i1);CHKERRQ(ierr);
22575d48cdbSStefano Zampini       ierr = ISBlockGetIndices(ptap->ris1,&i2);CHKERRQ(ierr);
22675d48cdbSStefano Zampini       ierr = PetscMemcmp(i1,i2,N*sizeof(*i1),&lsame);CHKERRQ(ierr);
22775d48cdbSStefano Zampini     }
22875d48cdbSStefano Zampini     ierr = MPIU_Allreduce(&lsame,&same,1,MPIU_BOOL,MPI_LAND,comm);CHKERRQ(ierr);
22975d48cdbSStefano Zampini     if (same) {
23075d48cdbSStefano Zampini       ierr = ISDestroy(&ptap->ris1);CHKERRQ(ierr);
23175d48cdbSStefano Zampini     } else {
23275d48cdbSStefano Zampini       ierr = MatCreateSubMatrix(P,ptap->ris1,NULL,MAT_INITIAL_MATRIX,&PT);CHKERRQ(ierr);
23375d48cdbSStefano Zampini       ierr = MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis1);CHKERRQ(ierr);
23475d48cdbSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(ptap->cis1,&Crl2g);CHKERRQ(ierr);
23575d48cdbSStefano Zampini       ierr = MatDestroy(&PT);CHKERRQ(ierr);
23675d48cdbSStefano Zampini     }
23775d48cdbSStefano Zampini   }
23875d48cdbSStefano Zampini /* Not sure about this
23975d48cdbSStefano Zampini   if (!Crl2g) {
24075d48cdbSStefano Zampini     ierr = MatGetBlockSize(*C,&ibs);CHKERRQ(ierr);
24175d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(Ccl2g,ibs);CHKERRQ(ierr);
24275d48cdbSStefano Zampini   }
24375d48cdbSStefano Zampini */
24475d48cdbSStefano Zampini   ierr = MatSetLocalToGlobalMapping(*C,Crl2g ? Crl2g : Ccl2g,Ccl2g);CHKERRQ(ierr);
24575d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&Crl2g);CHKERRQ(ierr);
24675d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&Ccl2g);CHKERRQ(ierr);
24775d48cdbSStefano Zampini 
24875d48cdbSStefano Zampini   (*C)->ops->ptapnumeric = MatPtAPNumeric_IS_XAIJ;
24975d48cdbSStefano Zampini   PetscFunctionReturn(0);
25075d48cdbSStefano Zampini }
25175d48cdbSStefano Zampini 
25275d48cdbSStefano Zampini PETSC_INTERN PetscErrorCode MatPtAP_IS_XAIJ(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
25375d48cdbSStefano Zampini {
25475d48cdbSStefano Zampini   PetscErrorCode ierr;
25575d48cdbSStefano Zampini 
25675d48cdbSStefano Zampini   PetscFunctionBegin;
25775d48cdbSStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
25875d48cdbSStefano Zampini     ierr = PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
25975d48cdbSStefano Zampini     ierr = MatPtAPSymbolic_IS_XAIJ(A,P,fill,C);CHKERRQ(ierr);
26075d48cdbSStefano Zampini     ierr = PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
26175d48cdbSStefano Zampini   }
26275d48cdbSStefano Zampini   ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
26375d48cdbSStefano Zampini   ierr = ((*C)->ops->ptapnumeric)(A,P,*C);CHKERRQ(ierr);
26475d48cdbSStefano Zampini   ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
26575d48cdbSStefano Zampini   PetscFunctionReturn(0);
26675d48cdbSStefano Zampini }
26775d48cdbSStefano Zampini 
2685b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr)
2695b003df0Sstefano_zampini {
2705b003df0Sstefano_zampini   MatISLocalFields lf = (MatISLocalFields)ptr;
2715b003df0Sstefano_zampini   PetscInt         i;
2725b003df0Sstefano_zampini   PetscErrorCode   ierr;
2735b003df0Sstefano_zampini 
274ab4d48faSStefano Zampini   PetscFunctionBegin;
2755b003df0Sstefano_zampini   for (i=0;i<lf->nr;i++) {
2765b003df0Sstefano_zampini     ierr = ISDestroy(&lf->rf[i]);CHKERRQ(ierr);
2775b003df0Sstefano_zampini   }
2785b003df0Sstefano_zampini   for (i=0;i<lf->nc;i++) {
2795b003df0Sstefano_zampini     ierr = ISDestroy(&lf->cf[i]);CHKERRQ(ierr);
2805b003df0Sstefano_zampini   }
2815b003df0Sstefano_zampini   ierr = PetscFree2(lf->rf,lf->cf);CHKERRQ(ierr);
2825b003df0Sstefano_zampini   ierr = PetscFree(lf);CHKERRQ(ierr);
2835b003df0Sstefano_zampini   PetscFunctionReturn(0);
2845b003df0Sstefano_zampini }
285a72627d2SStefano Zampini 
286c9225affSStefano Zampini static PetscErrorCode MatConvert_SeqXAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
2876989cf23SStefano Zampini {
288c9225affSStefano Zampini   Mat            B,lB;
289c9225affSStefano Zampini   PetscErrorCode ierr;
290c9225affSStefano Zampini 
291c9225affSStefano Zampini   PetscFunctionBegin;
292c9225affSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
293c9225affSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g;
294c9225affSStefano Zampini     PetscInt               bs;
295c9225affSStefano Zampini     IS                     is;
296c9225affSStefano Zampini 
297c9225affSStefano Zampini     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
298c9225affSStefano Zampini     ierr = ISCreateStride(PetscObjectComm((PetscObject)A),A->rmap->n/bs,0,1,&is);CHKERRQ(ierr);
299c9225affSStefano Zampini     if (bs > 1) {
300c9225affSStefano Zampini       IS       is2;
301c9225affSStefano Zampini       PetscInt i,*aux;
302c9225affSStefano Zampini 
303c9225affSStefano Zampini       ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
304c9225affSStefano Zampini       ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
305c9225affSStefano Zampini       ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
306c9225affSStefano Zampini       ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
307c9225affSStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
308c9225affSStefano Zampini       is   = is2;
309c9225affSStefano Zampini     }
310c9225affSStefano Zampini     ierr = ISSetIdentity(is);CHKERRQ(ierr);
311c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
312c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
313c9225affSStefano Zampini     ierr = ISCreateStride(PetscObjectComm((PetscObject)A),A->cmap->n/bs,0,1,&is);CHKERRQ(ierr);
314c9225affSStefano Zampini     if (bs > 1) {
315c9225affSStefano Zampini       IS       is2;
316c9225affSStefano Zampini       PetscInt i,*aux;
317c9225affSStefano Zampini 
318c9225affSStefano Zampini       ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
319c9225affSStefano Zampini       ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
320c9225affSStefano Zampini       ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
321c9225affSStefano Zampini       ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
322c9225affSStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
323c9225affSStefano Zampini       is   = is2;
324c9225affSStefano Zampini     }
325c9225affSStefano Zampini     ierr = ISSetIdentity(is);CHKERRQ(ierr);
326c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
327c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
328c9225affSStefano Zampini     ierr = MatCreateIS(PetscObjectComm((PetscObject)A),bs,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N,rl2g,cl2g,&B);CHKERRQ(ierr);
329c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
330c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
331c9225affSStefano Zampini     ierr = MatDuplicate(A,MAT_COPY_VALUES,&lB);CHKERRQ(ierr);
332c9225affSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *newmat = B;
333c9225affSStefano Zampini   } else {
334c9225affSStefano Zampini     B    = *newmat;
335c9225affSStefano Zampini     ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
336c9225affSStefano Zampini     lB   = A;
337c9225affSStefano Zampini   }
338c9225affSStefano Zampini   ierr = MatISSetLocalMat(B,lB);CHKERRQ(ierr);
339c9225affSStefano Zampini   ierr = MatDestroy(&lB);CHKERRQ(ierr);
340c9225affSStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
341c9225affSStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
342c9225affSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
343c9225affSStefano Zampini     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
344c9225affSStefano Zampini   }
345c9225affSStefano Zampini   PetscFunctionReturn(0);
346c9225affSStefano Zampini }
347c9225affSStefano Zampini 
348c9225affSStefano Zampini static PetscErrorCode MatISScaleDisassembling_Private(Mat A)
349c9225affSStefano Zampini {
350c9225affSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(A->data);
351c9225affSStefano Zampini   PetscScalar    *aa;
352c9225affSStefano Zampini   const PetscInt *ii,*jj;
353c9225affSStefano Zampini   PetscInt       i,n,m;
354fabe8965SStefano Zampini   PetscInt       *ecount,**eneighs;
355c9225affSStefano Zampini   PetscBool      flg;
356c9225affSStefano Zampini   PetscErrorCode ierr;
357c9225affSStefano Zampini 
358c9225affSStefano Zampini   PetscFunctionBegin;
359c9225affSStefano Zampini   ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg);CHKERRQ(ierr);
360c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
361fabe8965SStefano Zampini   ierr = ISLocalToGlobalMappingGetNodeInfo(A->rmap->mapping,&n,&ecount,&eneighs);CHKERRQ(ierr);
362c9225affSStefano Zampini   if (m != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",m,n);
363c9225affSStefano Zampini   ierr = MatSeqAIJGetArray(matis->A,&aa);CHKERRQ(ierr);
364c9225affSStefano Zampini   for (i=0;i<n;i++) {
365fabe8965SStefano Zampini     if (ecount[i] > 1) {
366c9225affSStefano Zampini       PetscInt j;
367c9225affSStefano Zampini 
368c9225affSStefano Zampini       for (j=ii[i];j<ii[i+1];j++) {
369c9225affSStefano Zampini         PetscInt    i2 = jj[j],p,p2;
370fabe8965SStefano Zampini         PetscReal   scal = 0.0;
371c9225affSStefano Zampini 
372c9225affSStefano Zampini         for (p=0;p<ecount[i];p++) {
373c9225affSStefano Zampini           for (p2=0;p2<ecount[i2];p2++) {
374c9225affSStefano Zampini             if (eneighs[i][p] == eneighs[i2][p2]) { scal += 1.0; break; }
375c9225affSStefano Zampini           }
376c9225affSStefano Zampini         }
377fabe8965SStefano Zampini         if (scal) aa[j] /= scal;
378c9225affSStefano Zampini       }
379c9225affSStefano Zampini     }
380c9225affSStefano Zampini   }
381fabe8965SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreNodeInfo(A->rmap->mapping,&n,&ecount,&eneighs);CHKERRQ(ierr);
382c9225affSStefano Zampini   ierr = MatSeqAIJRestoreArray(matis->A,&aa);CHKERRQ(ierr);
383c9225affSStefano Zampini   ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg);CHKERRQ(ierr);
384c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
385c9225affSStefano Zampini   PetscFunctionReturn(0);
386c9225affSStefano Zampini }
387c9225affSStefano Zampini 
388fabe8965SStefano Zampini typedef enum {MAT_IS_DISASSEMBLE_L2G_NATURAL,MAT_IS_DISASSEMBLE_L2G_MAT, MAT_IS_DISASSEMBLE_L2G_ND} MatISDisassemblel2gType;
389fabe8965SStefano Zampini 
390c9225affSStefano Zampini static PetscErrorCode MatMPIXAIJComputeLocalToGlobalMapping_Private(Mat A, ISLocalToGlobalMapping *l2g)
391c9225affSStefano Zampini {
392fabe8965SStefano Zampini   Mat                     Ad,Ao;
393fabe8965SStefano Zampini   IS                      is,ndmap,ndsub;
394c9225affSStefano Zampini   MPI_Comm                comm;
395fabe8965SStefano Zampini   const PetscInt          *garray,*ndmapi;
396fabe8965SStefano Zampini   PetscInt                bs,i,cnt,nl,*ncount,*ndmapc;
397fabe8965SStefano Zampini   PetscBool               ismpiaij,ismpibaij;
398fabe8965SStefano Zampini   const char *const       MatISDisassemblel2gTypes[] = {"NATURAL","MAT","ND","MatISDisassemblel2gType","MAT_IS_DISASSEMBLE_L2G_",0};
399fabe8965SStefano Zampini   MatISDisassemblel2gType mode = MAT_IS_DISASSEMBLE_L2G_NATURAL;
400fabe8965SStefano Zampini   MatPartitioning         part;
401fabe8965SStefano Zampini   PetscSF                 sf;
402c9225affSStefano Zampini   PetscErrorCode          ierr;
403c9225affSStefano Zampini 
404c9225affSStefano Zampini   PetscFunctionBegin;
405fabe8965SStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"MatIS l2g disassembling options","Mat");CHKERRQ(ierr);
406fabe8965SStefano Zampini   ierr = PetscOptionsEnum("-mat_is_disassemble_l2g_type","Type of local-to-global mapping to be used for disassembling","MatISDisassemblel2gType",MatISDisassemblel2gTypes,(PetscEnum)mode,(PetscEnum*)&mode,NULL);CHKERRQ(ierr);
407fabe8965SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
408fabe8965SStefano Zampini   if (mode == MAT_IS_DISASSEMBLE_L2G_MAT) {
409c9225affSStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,l2g,NULL);CHKERRQ(ierr);
410c9225affSStefano Zampini     PetscFunctionReturn(0);
411c9225affSStefano Zampini   }
412c9225affSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
413c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij);CHKERRQ(ierr);
414c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
415c9225affSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
416fabe8965SStefano Zampini   switch (mode) {
417fabe8965SStefano Zampini   case MAT_IS_DISASSEMBLE_L2G_ND:
418fabe8965SStefano Zampini     ierr = MatPartitioningCreate(comm,&part);CHKERRQ(ierr);
419fabe8965SStefano Zampini     ierr = MatPartitioningSetAdjacency(part,A);CHKERRQ(ierr);
420fabe8965SStefano Zampini     ierr = PetscObjectSetOptionsPrefix((PetscObject)part,((PetscObject)A)->prefix);CHKERRQ(ierr);
421fabe8965SStefano Zampini     ierr = MatPartitioningSetFromOptions(part);CHKERRQ(ierr);
422fabe8965SStefano Zampini     ierr = MatPartitioningApplyND(part,&ndmap);CHKERRQ(ierr);
423fabe8965SStefano Zampini     ierr = MatPartitioningDestroy(&part);CHKERRQ(ierr);
424fabe8965SStefano Zampini     ierr = ISBuildTwoSided(ndmap,NULL,&ndsub);CHKERRQ(ierr);
425fabe8965SStefano Zampini     ierr = MatMPIAIJSetUseScalableIncreaseOverlap(A,PETSC_TRUE);CHKERRQ(ierr);
426fabe8965SStefano Zampini     ierr = MatIncreaseOverlap(A,1,&ndsub,1);CHKERRQ(ierr);
427fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(ndsub,l2g);CHKERRQ(ierr);
428fabe8965SStefano Zampini 
429fabe8965SStefano Zampini     /* it may happen that a separator node is not properly shared */
430fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingGetNodeInfo(*l2g,&nl,&ncount,NULL);CHKERRQ(ierr);
431fabe8965SStefano Zampini     ierr = PetscSFCreate(comm,&sf);CHKERRQ(ierr);
432fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(*l2g,&garray);CHKERRQ(ierr);
433fabe8965SStefano Zampini     ierr = PetscSFSetGraphLayout(sf,A->rmap,nl,NULL,PETSC_OWN_POINTER,garray);CHKERRQ(ierr);
434fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(*l2g,&garray);CHKERRQ(ierr);
435fabe8965SStefano Zampini     ierr = PetscCalloc1(A->rmap->n,&ndmapc);CHKERRQ(ierr);
436fabe8965SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,ncount,ndmapc,MPIU_REPLACE);CHKERRQ(ierr);
437fabe8965SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,ncount,ndmapc,MPIU_REPLACE);CHKERRQ(ierr);
438fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreNodeInfo(*l2g,NULL,&ncount,NULL);CHKERRQ(ierr);
439fabe8965SStefano Zampini     ierr = ISGetIndices(ndmap,&ndmapi);CHKERRQ(ierr);
440fabe8965SStefano Zampini     for (i = 0, cnt = 0; i < A->rmap->n; i++)
441fabe8965SStefano Zampini       if (ndmapi[i] < 0 && ndmapc[i] < 2)
442fabe8965SStefano Zampini         cnt++;
443fabe8965SStefano Zampini 
444fabe8965SStefano Zampini     ierr = MPIU_Allreduce(&cnt,&i,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
445fabe8965SStefano Zampini     if (i) { /* we detected isolated separator nodes */
446fabe8965SStefano Zampini       Mat                    A2,A3;
447fabe8965SStefano Zampini       IS                     *workis,is2;
448fabe8965SStefano Zampini       PetscScalar            *vals;
449fabe8965SStefano Zampini       PetscInt               gcnt = i,*dnz,*onz,j,*lndmapi;
450fabe8965SStefano Zampini       ISLocalToGlobalMapping ll2g;
451fabe8965SStefano Zampini       PetscBool              flg;
452fabe8965SStefano Zampini       const PetscInt         *ii,*jj;
453fabe8965SStefano Zampini 
454fabe8965SStefano Zampini       /* communicate global id of separators */
455fabe8965SStefano Zampini       ierr = MatPreallocateInitialize(comm,A->rmap->n,A->cmap->n,dnz,onz);CHKERRQ(ierr);
456fabe8965SStefano Zampini       for (i = 0, cnt = 0; i < A->rmap->n; i++)
457fabe8965SStefano Zampini         dnz[i] = ndmapi[i] < 0 ? i + A->rmap->rstart : -1;
458fabe8965SStefano Zampini 
459fabe8965SStefano Zampini       ierr = PetscMalloc1(nl,&lndmapi);CHKERRQ(ierr);
460fabe8965SStefano Zampini       ierr = PetscSFBcastBegin(sf,MPIU_INT,dnz,lndmapi);CHKERRQ(ierr);
461fabe8965SStefano Zampini 
462fabe8965SStefano Zampini       /* compute adjacency of isolated separators node */
463fabe8965SStefano Zampini       ierr = PetscMalloc1(gcnt,&workis);CHKERRQ(ierr);
464fabe8965SStefano Zampini       for (i = 0, cnt = 0; i < A->rmap->n; i++) {
465fabe8965SStefano Zampini         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
466fabe8965SStefano Zampini           ierr = ISCreateStride(comm,1,i+A->rmap->rstart,1,&workis[cnt++]);CHKERRQ(ierr);
467fabe8965SStefano Zampini         }
468fabe8965SStefano Zampini       }
469fabe8965SStefano Zampini       for (i = cnt; i < gcnt; i++) {
470fabe8965SStefano Zampini         ierr = ISCreateStride(comm,0,0,1,&workis[i]);CHKERRQ(ierr);
471fabe8965SStefano Zampini       }
472fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
473fabe8965SStefano Zampini         ierr = PetscObjectSetName((PetscObject)workis[i],"ISOLATED");CHKERRQ(ierr);
474fabe8965SStefano Zampini         ierr = ISViewFromOptions(workis[i],NULL,"-view_isolated_separators");CHKERRQ(ierr);
475fabe8965SStefano Zampini       }
476fabe8965SStefano Zampini 
477fabe8965SStefano Zampini       /* no communications since all the ISes correspond to locally owned rows */
478fabe8965SStefano Zampini       ierr = MatIncreaseOverlap(A,gcnt,workis,1);CHKERRQ(ierr);
479fabe8965SStefano Zampini 
480fabe8965SStefano Zampini       /* end communicate global id of separators */
481fabe8965SStefano Zampini       ierr = PetscSFBcastEnd(sf,MPIU_INT,dnz,lndmapi);CHKERRQ(ierr);
482fabe8965SStefano Zampini 
483fabe8965SStefano Zampini       /* communicate new layers : create a matrix and transpose it */
484fabe8965SStefano Zampini       ierr = PetscMemzero(dnz,A->rmap->n*sizeof(*dnz));CHKERRQ(ierr);
485fabe8965SStefano Zampini       ierr = PetscMemzero(onz,A->rmap->n*sizeof(*onz));CHKERRQ(ierr);
486fabe8965SStefano Zampini       for (i = 0, j = 0; i < A->rmap->n; i++) {
487fabe8965SStefano Zampini         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
488fabe8965SStefano Zampini           const PetscInt* idxs;
489fabe8965SStefano Zampini           PetscInt        s;
490fabe8965SStefano Zampini 
491fabe8965SStefano Zampini           ierr = ISGetLocalSize(workis[j],&s);CHKERRQ(ierr);
492fabe8965SStefano Zampini           ierr = ISGetIndices(workis[j],&idxs);CHKERRQ(ierr);
493fabe8965SStefano Zampini           ierr = MatPreallocateSet(i+A->rmap->rstart,s,idxs,dnz,onz);CHKERRQ(ierr);
494fabe8965SStefano Zampini           j++;
495fabe8965SStefano Zampini         }
496fabe8965SStefano Zampini       }
497fabe8965SStefano Zampini       if (j != cnt) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %D != %D",j,cnt);
498fabe8965SStefano Zampini 
499fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
500fabe8965SStefano Zampini         ierr = PetscObjectSetName((PetscObject)workis[i],"EXTENDED");CHKERRQ(ierr);
501fabe8965SStefano Zampini         ierr = ISViewFromOptions(workis[i],NULL,"-view_isolated_separators");CHKERRQ(ierr);
502fabe8965SStefano Zampini       }
503fabe8965SStefano Zampini 
504fabe8965SStefano Zampini       for (i = 0, j = 0; i < A->rmap->n; i++) j = PetscMax(j,dnz[i]+onz[i]);
505fabe8965SStefano Zampini       ierr = PetscMalloc1(j,&vals);CHKERRQ(ierr);
506fabe8965SStefano Zampini       for (i = 0; i < j; i++) vals[i] = 1.0;
507fabe8965SStefano Zampini 
508fabe8965SStefano Zampini       ierr = MatCreate(comm,&A2);CHKERRQ(ierr);
509fabe8965SStefano Zampini       ierr = MatSetType(A2,MATMPIAIJ);CHKERRQ(ierr);
510fabe8965SStefano Zampini       ierr = MatSetSizes(A2,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
511fabe8965SStefano Zampini       ierr = MatMPIAIJSetPreallocation(A2,0,dnz,0,onz);CHKERRQ(ierr);
512fabe8965SStefano Zampini       ierr = MatSetOption(A2,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
513fabe8965SStefano Zampini       for (i = 0, j = 0; i < A2->rmap->n; i++) {
514fabe8965SStefano Zampini         PetscInt        row = i+A2->rmap->rstart,s = dnz[i] + onz[i];
515fabe8965SStefano Zampini         const PetscInt* idxs;
516fabe8965SStefano Zampini 
517fabe8965SStefano Zampini         if (s) {
518fabe8965SStefano Zampini           ierr = ISGetIndices(workis[j],&idxs);CHKERRQ(ierr);
519fabe8965SStefano Zampini           ierr = MatSetValues(A2,1,&row,s,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
520fabe8965SStefano Zampini           ierr = ISRestoreIndices(workis[j],&idxs);CHKERRQ(ierr);
521fabe8965SStefano Zampini           j++;
522fabe8965SStefano Zampini         }
523fabe8965SStefano Zampini       }
524fabe8965SStefano Zampini       if (j != cnt) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %D != %D",j,cnt);
525fabe8965SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
526fabe8965SStefano Zampini       ierr = MatAssemblyBegin(A2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
527fabe8965SStefano Zampini       ierr = MatAssemblyEnd(A2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
528fabe8965SStefano Zampini       ierr = MatTranspose(A2,MAT_INPLACE_MATRIX,&A2);CHKERRQ(ierr);
529fabe8965SStefano Zampini 
530fabe8965SStefano Zampini       /* extract submatrix corresponding to the coupling "owned separators" x "isolated separators" */
531fabe8965SStefano Zampini       for (i = 0, j = 0; i < nl; i++)
532fabe8965SStefano Zampini         if (lndmapi[i] >= 0) lndmapi[j++] = lndmapi[i];
533fabe8965SStefano Zampini       ierr = ISCreateGeneral(comm,j,lndmapi,PETSC_USE_POINTER,&is);CHKERRQ(ierr);
534fabe8965SStefano Zampini       ierr = MatMPIAIJGetLocalMatCondensed(A2,MAT_INITIAL_MATRIX,&is,NULL,&A3);CHKERRQ(ierr);
535fabe8965SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
536fabe8965SStefano Zampini       ierr = MatDestroy(&A2);CHKERRQ(ierr);
537fabe8965SStefano Zampini 
538fabe8965SStefano Zampini       /* extend local to global map to include connected isolated separators */
539fabe8965SStefano Zampini       ierr = PetscObjectQuery((PetscObject)A3,"_petsc_GetLocalMatCondensed_iscol",(PetscObject*)&is);CHKERRQ(ierr);
540fabe8965SStefano Zampini       if (!is) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing column map");
541fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&ll2g);CHKERRQ(ierr);
542fabe8965SStefano Zampini       ierr = MatGetRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg);CHKERRQ(ierr);
543fabe8965SStefano Zampini       if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
544fabe8965SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,ii[i],jj,PETSC_COPY_VALUES,&is);CHKERRQ(ierr);
545fabe8965SStefano Zampini       ierr = MatRestoreRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg);CHKERRQ(ierr);
546fabe8965SStefano Zampini       if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
547fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(ll2g,is,&is2);CHKERRQ(ierr);
548fabe8965SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
549fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&ll2g);CHKERRQ(ierr);
550fabe8965SStefano Zampini 
551fabe8965SStefano Zampini       /* add new nodes to the local-to-global map */
552fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(l2g);CHKERRQ(ierr);
553fabe8965SStefano Zampini       ierr = ISExpand(ndsub,is2,&is);CHKERRQ(ierr);
554fabe8965SStefano Zampini       ierr = ISDestroy(&is2);CHKERRQ(ierr);
555fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,l2g);CHKERRQ(ierr);
556fabe8965SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
557fabe8965SStefano Zampini 
558fabe8965SStefano Zampini       ierr = MatDestroy(&A3);CHKERRQ(ierr);
559fabe8965SStefano Zampini       ierr = PetscFree(lndmapi);CHKERRQ(ierr);
560fabe8965SStefano Zampini       ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
561fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
562fabe8965SStefano Zampini         ierr = ISDestroy(&workis[i]);CHKERRQ(ierr);
563fabe8965SStefano Zampini       }
564fabe8965SStefano Zampini       ierr = PetscFree(workis);CHKERRQ(ierr);
565fabe8965SStefano Zampini     }
566fabe8965SStefano Zampini     ierr = ISRestoreIndices(ndmap,&ndmapi);CHKERRQ(ierr);
567fabe8965SStefano Zampini     ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
568fabe8965SStefano Zampini     ierr = PetscFree(ndmapc);CHKERRQ(ierr);
569fabe8965SStefano Zampini     ierr = ISDestroy(&ndmap);CHKERRQ(ierr);
570fabe8965SStefano Zampini     ierr = ISDestroy(&ndsub);CHKERRQ(ierr);
571fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(*l2g,bs);CHKERRQ(ierr);
572fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingViewFromOptions(*l2g,NULL,"-matis_nd_l2g_view");CHKERRQ(ierr);
573fabe8965SStefano Zampini     break;
574fabe8965SStefano Zampini   case MAT_IS_DISASSEMBLE_L2G_NATURAL:
575fabe8965SStefano Zampini     if (ismpiaij) {
576fabe8965SStefano Zampini       ierr = MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
577fabe8965SStefano Zampini     } else if (ismpibaij) {
578fabe8965SStefano Zampini       ierr = MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
579c9225affSStefano Zampini     } else SETERRQ1(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
580c9225affSStefano Zampini     if (!garray) SETERRQ(comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
581c9225affSStefano Zampini     if (A->rmap->n) {
582fabe8965SStefano Zampini       PetscInt dc,oc,stc,*aux;
583c9225affSStefano Zampini 
584c9225affSStefano Zampini       ierr = MatGetLocalSize(A,NULL,&dc);CHKERRQ(ierr);
585c9225affSStefano Zampini       ierr = MatGetLocalSize(Ao,NULL,&oc);CHKERRQ(ierr);
586c9225affSStefano Zampini       ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
587c9225affSStefano Zampini       ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
588c9225affSStefano Zampini       for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
589c9225affSStefano Zampini       for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i];
590c9225affSStefano Zampini       ierr = ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
591c9225affSStefano Zampini     } else {
592c9225affSStefano Zampini       ierr = ISCreateBlock(comm,1,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
593c9225affSStefano Zampini     }
594c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,l2g);CHKERRQ(ierr);
595c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
596fabe8965SStefano Zampini     break;
597fabe8965SStefano Zampini   default:
598fabe8965SStefano Zampini     SETERRQ1(comm,PETSC_ERR_ARG_WRONG,"Unsupported l2g disassembling type %D",mode);
599c9225affSStefano Zampini   }
600c9225affSStefano Zampini   PetscFunctionReturn(0);
601c9225affSStefano Zampini }
602c9225affSStefano Zampini 
603c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
604c9225affSStefano Zampini {
605c9225affSStefano Zampini   Mat                    lA,Ad,Ao,B = NULL;
6066989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
6076989cf23SStefano Zampini   IS                     is;
6086989cf23SStefano Zampini   MPI_Comm               comm;
6096989cf23SStefano Zampini   void                   *ptrs[2];
6106989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
611c9225affSStefano Zampini   const PetscInt         *garray;
6126989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
613c9225affSStefano Zampini   const PetscInt         *di,*dj,*oi,*oj;
614c9225affSStefano Zampini   const PetscInt         *odi,*odj,*ooi,*ooj;
6156989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
616c9225affSStefano Zampini   PetscInt               bs,lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
617c9225affSStefano Zampini   PetscBool              flg,ismpiaij,ismpibaij,was_inplace = PETSC_FALSE;
618c9225affSStefano Zampini   PetscMPIInt            size;
6196989cf23SStefano Zampini   PetscErrorCode         ierr;
6206989cf23SStefano Zampini 
621ab4d48faSStefano Zampini   PetscFunctionBegin;
6226989cf23SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
623c9225affSStefano Zampini   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
624c9225affSStefano Zampini   if (size == 1) {
625c9225affSStefano Zampini     ierr = MatConvert_SeqXAIJ_IS(A,type,reuse,newmat);CHKERRQ(ierr);
626c9225affSStefano Zampini     PetscFunctionReturn(0);
627c9225affSStefano Zampini   }
628c9225affSStefano Zampini   if (reuse != MAT_REUSE_MATRIX && A->cmap->N == A->rmap->N) {
629c9225affSStefano Zampini     ierr = MatMPIXAIJComputeLocalToGlobalMapping_Private(A,&rl2g);CHKERRQ(ierr);
630c9225affSStefano Zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
631c9225affSStefano Zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
632c9225affSStefano Zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
633c9225affSStefano Zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,rl2g);CHKERRQ(ierr);
634c9225affSStefano Zampini     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
635c9225affSStefano Zampini     ierr = MatSetBlockSize(B,bs);CHKERRQ(ierr);
636c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
637c9225affSStefano Zampini     if (reuse == MAT_INPLACE_MATRIX) was_inplace = PETSC_TRUE;
638c9225affSStefano Zampini     reuse = MAT_REUSE_MATRIX;
639c9225affSStefano Zampini   }
640c9225affSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
641c9225affSStefano Zampini     Mat            *newlA, lA;
642c9225affSStefano Zampini     IS             rows, cols;
643c9225affSStefano Zampini     const PetscInt *ridx, *cidx;
644c9225affSStefano Zampini     PetscInt       rbs, cbs, nr, nc;
645c9225affSStefano Zampini 
646c9225affSStefano Zampini     if (!B) B = *newmat;
647c9225affSStefano Zampini     ierr = MatGetLocalToGlobalMapping(B,&rl2g,&cl2g);CHKERRQ(ierr);
648c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(rl2g,&ridx);CHKERRQ(ierr);
649c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(cl2g,&cidx);CHKERRQ(ierr);
650c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(rl2g,&nr);CHKERRQ(ierr);
651c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(cl2g,&nc);CHKERRQ(ierr);
652c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(rl2g,&rbs);CHKERRQ(ierr);
653c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(cl2g,&cbs);CHKERRQ(ierr);
654c9225affSStefano Zampini     ierr = ISCreateBlock(comm,rbs,nr/rbs,ridx,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
655c9225affSStefano Zampini     if (rl2g != cl2g) {
656c9225affSStefano Zampini       ierr = ISCreateBlock(comm,cbs,nc/cbs,cidx,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
657c9225affSStefano Zampini     } else {
658c9225affSStefano Zampini       ierr = PetscObjectReference((PetscObject)rows);CHKERRQ(ierr);
659c9225affSStefano Zampini       cols = rows;
660c9225affSStefano Zampini     }
661c9225affSStefano Zampini     ierr = MatISGetLocalMat(B,&lA);CHKERRQ(ierr);
662c9225affSStefano Zampini     ierr = MatCreateSubMatrices(A,1,&rows,&cols,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
663c9225affSStefano Zampini     ierr = MatConvert(newlA[0],MATSEQAIJ,MAT_INPLACE_MATRIX,&newlA[0]);CHKERRQ(ierr);
664c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&ridx);CHKERRQ(ierr);
665c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&cidx);CHKERRQ(ierr);
666c9225affSStefano Zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
667c9225affSStefano Zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
668c9225affSStefano Zampini     if (!lA->preallocated) { /* first time */
669c9225affSStefano Zampini       ierr = MatDuplicate(newlA[0],MAT_COPY_VALUES,&lA);CHKERRQ(ierr);
670c9225affSStefano Zampini       ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
671c9225affSStefano Zampini       ierr = PetscObjectDereference((PetscObject)lA);CHKERRQ(ierr);
672c9225affSStefano Zampini     }
673c9225affSStefano Zampini     ierr = MatCopy(newlA[0],lA,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
674c9225affSStefano Zampini     ierr = MatDestroySubMatrices(1,&newlA);CHKERRQ(ierr);
675c9225affSStefano Zampini     ierr = MatISScaleDisassembling_Private(B);CHKERRQ(ierr);
676c9225affSStefano Zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
677c9225affSStefano Zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
678c9225affSStefano Zampini     if (was_inplace) { ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); }
679c9225affSStefano Zampini     else *newmat = B;
680c9225affSStefano Zampini     PetscFunctionReturn(0);
681c9225affSStefano Zampini   }
682c9225affSStefano Zampini   /* rectangular case, just compress out the column space */
683c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij);CHKERRQ(ierr);
684c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
685c9225affSStefano Zampini   if (ismpiaij) {
686c9225affSStefano Zampini     bs   = 1;
687c9225affSStefano Zampini     ierr = MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
688c9225affSStefano Zampini   } else if (ismpibaij) {
689c9225affSStefano Zampini     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
690c9225affSStefano Zampini     ierr = MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
691c9225affSStefano Zampini     ierr = MatConvert(Ad,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ad);CHKERRQ(ierr);
692c9225affSStefano Zampini     ierr = MatConvert(Ao,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ao);CHKERRQ(ierr);
693c9225affSStefano Zampini   } else SETERRQ1(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
694c9225affSStefano Zampini   ierr = MatSeqAIJGetArray(Ad,&dd);CHKERRQ(ierr);
695c9225affSStefano Zampini   ierr = MatSeqAIJGetArray(Ao,&od);CHKERRQ(ierr);
696c9225affSStefano Zampini   if (!garray) SETERRQ(comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
6976989cf23SStefano Zampini 
6986989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
6996989cf23SStefano Zampini   ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr);
7006989cf23SStefano Zampini   ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
7016989cf23SStefano Zampini   ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr);
702c9225affSStefano Zampini   ierr = MatGetLocalSize(Ao,NULL,&oc);CHKERRQ(ierr);
703c9225affSStefano Zampini   ierr = MatGetRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&di,&dj,&flg);CHKERRQ(ierr);
704c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
705c9225affSStefano Zampini   ierr = MatGetRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&oi,&oj,&flg);CHKERRQ(ierr);
706c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
707c9225affSStefano Zampini   nnz = di[dr] + oi[dr];
708c9225affSStefano Zampini   /* store original pointers to be restored later */
709c9225affSStefano Zampini   odi = di; odj = dj; ooi = oi; ooj = oj;
7106989cf23SStefano Zampini 
7116989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
712c9225affSStefano Zampini   ierr = ISCreateStride(comm,dr/bs,str/bs,1,&is);CHKERRQ(ierr);
713c9225affSStefano Zampini   if (bs > 1) {
714c9225affSStefano Zampini     IS is2;
715c9225affSStefano Zampini 
716c9225affSStefano Zampini     ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
717c9225affSStefano Zampini     ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
718c9225affSStefano Zampini     ierr = ISCreateBlock(comm,bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
719c9225affSStefano Zampini     ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
720c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
721c9225affSStefano Zampini     is   = is2;
722c9225affSStefano Zampini   }
7236989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
7246989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
725e363d98aSStefano Zampini   if (dr) {
726c9225affSStefano Zampini     ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
727c9225affSStefano Zampini     for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
728c9225affSStefano Zampini     for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i];
729c9225affSStefano Zampini     ierr = ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
730e363d98aSStefano Zampini     lc   = dc+oc;
731e363d98aSStefano Zampini   } else {
732c9225affSStefano Zampini     ierr = ISCreateBlock(comm,bs,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
733e363d98aSStefano Zampini     lc   = 0;
734e363d98aSStefano Zampini   }
7356989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
7366989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
7376989cf23SStefano Zampini 
7386989cf23SStefano Zampini   /* create MATIS object */
739c9225affSStefano Zampini   ierr = MatCreate(comm,&B);CHKERRQ(ierr);
740c9225affSStefano Zampini   ierr = MatSetSizes(B,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
741c9225affSStefano Zampini   ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
742c9225affSStefano Zampini   ierr = MatSetBlockSize(B,bs);CHKERRQ(ierr);
743c9225affSStefano Zampini   ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
7446989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
7456989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
7466989cf23SStefano Zampini 
7476989cf23SStefano Zampini   /* merge local matrices */
7486989cf23SStefano Zampini   ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr);
7496989cf23SStefano Zampini   ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
7506989cf23SStefano Zampini   ii   = aux;
7516989cf23SStefano Zampini   jj   = aux+dr+1;
7526989cf23SStefano Zampini   aa   = data;
7536989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
7546989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
7556989cf23SStefano Zampini   {
7566989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
7576989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
7586989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
7596989cf23SStefano Zampini   }
7606989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
761c9225affSStefano Zampini 
762c9225affSStefano Zampini   ierr = MatRestoreRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&odi,&odj,&flg);CHKERRQ(ierr);
763c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
764c9225affSStefano Zampini   ierr = MatRestoreRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&ooi,&ooj,&flg);CHKERRQ(ierr);
765c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
766c9225affSStefano Zampini   ierr = MatSeqAIJRestoreArray(Ad,&dd);CHKERRQ(ierr);
767c9225affSStefano Zampini   ierr = MatSeqAIJRestoreArray(Ao,&od);CHKERRQ(ierr);
768c9225affSStefano Zampini 
7696989cf23SStefano Zampini   ii   = aux;
7706989cf23SStefano Zampini   jj   = aux+dr+1;
7716989cf23SStefano Zampini   aa   = data;
772e363d98aSStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr);
7736989cf23SStefano Zampini 
7746989cf23SStefano Zampini   /* create containers to destroy the data */
7756989cf23SStefano Zampini   ptrs[0] = aux;
7766989cf23SStefano Zampini   ptrs[1] = data;
7776989cf23SStefano Zampini   for (i=0; i<2; i++) {
7786989cf23SStefano Zampini     PetscContainer c;
7796989cf23SStefano Zampini 
7806989cf23SStefano Zampini     ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
7816989cf23SStefano Zampini     ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
782b81c21eeSStefano Zampini     ierr = PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault);CHKERRQ(ierr);
7836989cf23SStefano Zampini     ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr);
7846989cf23SStefano Zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
7856989cf23SStefano Zampini   }
786c9225affSStefano Zampini   if (ismpibaij) { /* destroy converted local matrices */
787c9225affSStefano Zampini     ierr = MatDestroy(&Ad);CHKERRQ(ierr);
788c9225affSStefano Zampini     ierr = MatDestroy(&Ao);CHKERRQ(ierr);
789c9225affSStefano Zampini   }
7906989cf23SStefano Zampini 
7916989cf23SStefano Zampini   /* finalize matrix */
792c9225affSStefano Zampini   ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
7936989cf23SStefano Zampini   ierr = MatDestroy(&lA);CHKERRQ(ierr);
794c9225affSStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
795c9225affSStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
796c9225affSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
797c9225affSStefano Zampini     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
798c9225affSStefano Zampini   } else *newmat = B;
7996989cf23SStefano Zampini   PetscFunctionReturn(0);
8006989cf23SStefano Zampini }
8016989cf23SStefano Zampini 
8025e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
8035e3038f0Sstefano_zampini {
8045e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
8055e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
8065e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
8075e3038f0Sstefano_zampini   MPI_Comm               comm;
8085b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
8095b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
8109e7b2b25Sstefano_zampini   PetscBool              convert,lreuse,*istrans;
8115e3038f0Sstefano_zampini   PetscErrorCode         ierr;
8125e3038f0Sstefano_zampini 
813ab4d48faSStefano Zampini   PetscFunctionBegin;
8145e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
8155e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
8165e3038f0Sstefano_zampini   rnest  = NULL;
8175e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
8185e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
8195e3038f0Sstefano_zampini 
8205e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
8215e3038f0Sstefano_zampini     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
8225e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
8235e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
8245e3038f0Sstefano_zampini     if (isnest) {
8255e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
8265e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
8275e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
8285e3038f0Sstefano_zampini     }
8295e3038f0Sstefano_zampini   }
8305e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
8315b003df0Sstefano_zampini   ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr);
8329e7b2b25Sstefano_zampini   ierr = PetscCalloc6(nr,&isrow,nc,&iscol,
8335e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
8349e7b2b25Sstefano_zampini                       nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr);
8355e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
8365e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
8375e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
8385e3038f0Sstefano_zampini       PetscBool ismatis;
8399e7b2b25Sstefano_zampini       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
8405e3038f0Sstefano_zampini 
8415e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
8425e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
8435e3038f0Sstefano_zampini 
8445e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
8459e7b2b25Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr);
8469e7b2b25Sstefano_zampini       if (istrans[ij]) {
8479e7b2b25Sstefano_zampini         Mat T,lT;
8489e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
8499e7b2b25Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr);
8509e7b2b25Sstefano_zampini         if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) (transposed) is not of type MATIS",i,j);
8519e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr);
8529e7b2b25Sstefano_zampini         ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr);
8539e7b2b25Sstefano_zampini       } else {
8545e3038f0Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
8555e3038f0Sstefano_zampini         if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) is not of type MATIS",i,j);
8569e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
8579e7b2b25Sstefano_zampini       }
8585e3038f0Sstefano_zampini 
8595e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
8605e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
8619e7b2b25Sstefano_zampini       ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr);
8625e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
8635e3038f0Sstefano_zampini       if (lr[i] && l1 != lr[i]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid local size %D != %D",i,j,lr[i],l1);
8645e3038f0Sstefano_zampini       if (lc[j] && l2 != lc[j]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid local size %D != %D",i,j,lc[j],l2);
8655e3038f0Sstefano_zampini       lr[i] = l1;
8665e3038f0Sstefano_zampini       lc[j] = l2;
8675e3038f0Sstefano_zampini 
8685e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
8695e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
8705e3038f0Sstefano_zampini     }
8715e3038f0Sstefano_zampini   }
8725e3038f0Sstefano_zampini 
8735e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
8745e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
8755e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
8765e3038f0Sstefano_zampini     rl2g = NULL;
8775e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
8785e3038f0Sstefano_zampini       PetscInt n1,n2;
8795e3038f0Sstefano_zampini 
8805e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
8819e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
8829e7b2b25Sstefano_zampini         Mat T;
8839e7b2b25Sstefano_zampini 
8849e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
8859e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr);
8869e7b2b25Sstefano_zampini       } else {
8875e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
8889e7b2b25Sstefano_zampini       }
8895e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
8905e3038f0Sstefano_zampini       if (!n1) continue;
8915e3038f0Sstefano_zampini       if (!rl2g) {
8925e3038f0Sstefano_zampini         rl2g = cl2g;
8935e3038f0Sstefano_zampini       } else {
8945e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
8955e3038f0Sstefano_zampini         PetscBool      same;
8965e3038f0Sstefano_zampini 
8975e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
8985e3038f0Sstefano_zampini         if (n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid row l2gmap size %D != %D",i,j,n1,n2);
8995e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
9005e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
9015e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
9025e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
9035e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
9045e3038f0Sstefano_zampini         if (!same) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid row l2gmap",i,j);
9055e3038f0Sstefano_zampini       }
9065e3038f0Sstefano_zampini     }
9075e3038f0Sstefano_zampini   }
9085e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
9095e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
9105e3038f0Sstefano_zampini     rl2g = NULL;
9115e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
9125e3038f0Sstefano_zampini       PetscInt n1,n2;
9135e3038f0Sstefano_zampini 
9145e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
9159e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
9169e7b2b25Sstefano_zampini         Mat T;
9179e7b2b25Sstefano_zampini 
9189e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr);
9199e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr);
9209e7b2b25Sstefano_zampini       } else {
9215e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
9229e7b2b25Sstefano_zampini       }
9235e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
9245e3038f0Sstefano_zampini       if (!n1) continue;
9255e3038f0Sstefano_zampini       if (!rl2g) {
9265e3038f0Sstefano_zampini         rl2g = cl2g;
9275e3038f0Sstefano_zampini       } else {
9285e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
9295e3038f0Sstefano_zampini         PetscBool      same;
9305e3038f0Sstefano_zampini 
9315e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
9325e3038f0Sstefano_zampini         if (n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid column l2gmap size %D != %D",j,i,n1,n2);
9335e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
9345e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
9355e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
9365e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
9375e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
9385e3038f0Sstefano_zampini         if (!same) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid column l2gmap",j,i);
9395e3038f0Sstefano_zampini       }
9405e3038f0Sstefano_zampini     }
9415e3038f0Sstefano_zampini   }
9425e3038f0Sstefano_zampini #endif
9435e3038f0Sstefano_zampini 
9445e3038f0Sstefano_zampini   B = NULL;
9455e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
9465b003df0Sstefano_zampini     PetscInt stl;
9475b003df0Sstefano_zampini 
9485e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
9495e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
9505e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
9515b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
9525e3038f0Sstefano_zampini       Mat            usedmat;
9535e3038f0Sstefano_zampini       Mat_IS         *matis;
9545e3038f0Sstefano_zampini       const PetscInt *idxs;
9555e3038f0Sstefano_zampini 
9565e3038f0Sstefano_zampini       /* local IS for local NEST */
9575b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
9585e3038f0Sstefano_zampini 
9595e3038f0Sstefano_zampini       /* l2gmap */
9605e3038f0Sstefano_zampini       j = 0;
9615e3038f0Sstefano_zampini       usedmat = nest[i][j];
9629e7b2b25Sstefano_zampini       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
9639e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat");
9649e7b2b25Sstefano_zampini 
9659e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
9669e7b2b25Sstefano_zampini         Mat T;
9679e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
9689e7b2b25Sstefano_zampini         usedmat = T;
9699e7b2b25Sstefano_zampini       }
9705e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
9715e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
9729e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
9739e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
9749e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
9759e7b2b25Sstefano_zampini       } else {
9765e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
9775e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
9789e7b2b25Sstefano_zampini       }
9795e3038f0Sstefano_zampini       ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
9805e3038f0Sstefano_zampini       stl += lr[i];
9815e3038f0Sstefano_zampini     }
9825e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
9835e3038f0Sstefano_zampini 
9845e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
9855e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
9865e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
9875b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
9885e3038f0Sstefano_zampini       Mat            usedmat;
9895e3038f0Sstefano_zampini       Mat_IS         *matis;
9905e3038f0Sstefano_zampini       const PetscInt *idxs;
9915e3038f0Sstefano_zampini 
9925e3038f0Sstefano_zampini       /* local IS for local NEST */
9935b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
9945e3038f0Sstefano_zampini 
9955e3038f0Sstefano_zampini       /* l2gmap */
9965e3038f0Sstefano_zampini       j = 0;
9975e3038f0Sstefano_zampini       usedmat = nest[j][i];
9989e7b2b25Sstefano_zampini       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
9999e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat");
10009e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
10019e7b2b25Sstefano_zampini         Mat T;
10029e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
10039e7b2b25Sstefano_zampini         usedmat = T;
10049e7b2b25Sstefano_zampini       }
10055e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
10065e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
10079e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
10089e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10099e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10109e7b2b25Sstefano_zampini       } else {
10115e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10125e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10139e7b2b25Sstefano_zampini       }
10145e3038f0Sstefano_zampini       ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
10155e3038f0Sstefano_zampini       stl += lc[i];
10165e3038f0Sstefano_zampini     }
10175e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
10185e3038f0Sstefano_zampini 
10195e3038f0Sstefano_zampini     /* Create MATIS */
10205e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
10215e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
10225e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
10235e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
10245e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
10258546b261SStefano Zampini     ierr = MatISSetLocalMatType(B,MATNEST);CHKERRQ(ierr);
10268546b261SStefano Zampini     { /* hack : avoid setup of scatters */
10278546b261SStefano Zampini       Mat_IS *matis = (Mat_IS*)(B->data);
10288546b261SStefano Zampini       matis->islocalref = PETSC_TRUE;
10298546b261SStefano Zampini     }
10305e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
10315e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
10325e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
10335e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
10348546b261SStefano Zampini     ierr = MatNestSetVecType(lA,VECNEST);CHKERRQ(ierr);
10359e7b2b25Sstefano_zampini     for (i=0;i<nr*nc;i++) {
10369e7b2b25Sstefano_zampini       if (istrans[i]) {
10379e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
10389e7b2b25Sstefano_zampini       }
10399e7b2b25Sstefano_zampini     }
10405e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
10415e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
10428546b261SStefano Zampini     { /* hack : setup of scatters done here */
10438546b261SStefano Zampini       Mat_IS *matis = (Mat_IS*)(B->data);
10448546b261SStefano Zampini 
10458546b261SStefano Zampini       matis->islocalref = PETSC_FALSE;
10468546b261SStefano Zampini       ierr = MatISSetUpScatters_Private(B);CHKERRQ(ierr);
10478546b261SStefano Zampini     }
10485e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10495e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10505e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
10515e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
10525e3038f0Sstefano_zampini     } else {
10535e3038f0Sstefano_zampini       *newmat = B;
10545e3038f0Sstefano_zampini     }
10555e3038f0Sstefano_zampini   } else {
10565e3038f0Sstefano_zampini     if (lreuse) {
10575e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
10585e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
10595e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
10605e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
10615e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
10629e7b2b25Sstefano_zampini             if (istrans[i*nc+j]) {
10639e7b2b25Sstefano_zampini               ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr);
10649e7b2b25Sstefano_zampini             }
10655e3038f0Sstefano_zampini           }
10665e3038f0Sstefano_zampini         }
10675e3038f0Sstefano_zampini       }
10685e3038f0Sstefano_zampini     } else {
10695b003df0Sstefano_zampini       PetscInt stl;
10705b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
10715b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
10725b003df0Sstefano_zampini         stl  += lr[i];
10735e3038f0Sstefano_zampini       }
10745b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
10755b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
10765b003df0Sstefano_zampini         stl  += lc[i];
10775e3038f0Sstefano_zampini       }
10785e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
1079ab4d48faSStefano Zampini       for (i=0;i<nr*nc;i++) {
10809e7b2b25Sstefano_zampini         if (istrans[i]) {
10819e7b2b25Sstefano_zampini           ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
10829e7b2b25Sstefano_zampini         }
1083ab4d48faSStefano Zampini       }
10845e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
10855e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
10865e3038f0Sstefano_zampini     }
10875e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10885e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10895e3038f0Sstefano_zampini   }
10905e3038f0Sstefano_zampini 
10915b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
10925b003df0Sstefano_zampini   convert = PETSC_FALSE;
10935b003df0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
10945b003df0Sstefano_zampini   if (convert) {
10955b003df0Sstefano_zampini     Mat              M;
10965b003df0Sstefano_zampini     MatISLocalFields lf;
10975b003df0Sstefano_zampini     PetscContainer   c;
10985b003df0Sstefano_zampini 
10995b003df0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
11005b003df0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
11015b003df0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
11025b003df0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
11035b003df0Sstefano_zampini 
11045b003df0Sstefano_zampini     /* attach local fields to the matrix */
11055b003df0Sstefano_zampini     ierr = PetscNew(&lf);CHKERRQ(ierr);
11065b003df0Sstefano_zampini     ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr);
11075b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
11085b003df0Sstefano_zampini       PetscInt n,st;
11095b003df0Sstefano_zampini 
11105b003df0Sstefano_zampini       ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr);
11115b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr);
11125b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr);
11135b003df0Sstefano_zampini     }
11145b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
11155b003df0Sstefano_zampini       PetscInt n,st;
11165b003df0Sstefano_zampini 
11175b003df0Sstefano_zampini       ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr);
11185b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr);
11195b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr);
11205b003df0Sstefano_zampini     }
11215b003df0Sstefano_zampini     lf->nr = nr;
11225b003df0Sstefano_zampini     lf->nc = nc;
11235b003df0Sstefano_zampini     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr);
11245b003df0Sstefano_zampini     ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr);
11255b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr);
11265b003df0Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr);
11275b003df0Sstefano_zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
11285b003df0Sstefano_zampini   }
11295b003df0Sstefano_zampini 
11305e3038f0Sstefano_zampini   /* Free workspace */
11315e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
11325e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
11335e3038f0Sstefano_zampini   }
11345e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
11355e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
11365e3038f0Sstefano_zampini   }
11379e7b2b25Sstefano_zampini   ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr);
11385b003df0Sstefano_zampini   ierr = PetscFree2(lr,lc);CHKERRQ(ierr);
11395e3038f0Sstefano_zampini   PetscFunctionReturn(0);
11405e3038f0Sstefano_zampini }
11415e3038f0Sstefano_zampini 
1142ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
1143ad219c80Sstefano_zampini {
1144ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS*)A->data;
1145ad219c80Sstefano_zampini   Vec               ll,rr;
1146ad219c80Sstefano_zampini   const PetscScalar *Y,*X;
1147ad219c80Sstefano_zampini   PetscScalar       *x,*y;
1148ad219c80Sstefano_zampini   PetscErrorCode    ierr;
1149ad219c80Sstefano_zampini 
1150ad219c80Sstefano_zampini   PetscFunctionBegin;
1151ad219c80Sstefano_zampini   if (l) {
1152ad219c80Sstefano_zampini     ll   = matis->y;
1153ad219c80Sstefano_zampini     ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr);
1154ad219c80Sstefano_zampini     ierr = VecGetArray(ll,&y);CHKERRQ(ierr);
1155ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
1156ad219c80Sstefano_zampini   } else {
1157ad219c80Sstefano_zampini     ll = NULL;
1158ad219c80Sstefano_zampini   }
1159ad219c80Sstefano_zampini   if (r) {
1160ad219c80Sstefano_zampini     rr   = matis->x;
1161ad219c80Sstefano_zampini     ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr);
1162ad219c80Sstefano_zampini     ierr = VecGetArray(rr,&x);CHKERRQ(ierr);
1163ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
1164ad219c80Sstefano_zampini   } else {
1165ad219c80Sstefano_zampini     rr = NULL;
1166ad219c80Sstefano_zampini   }
1167ad219c80Sstefano_zampini   if (ll) {
1168ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
1169ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr);
1170ad219c80Sstefano_zampini     ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr);
1171ad219c80Sstefano_zampini   }
1172ad219c80Sstefano_zampini   if (rr) {
1173ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
1174ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr);
1175ad219c80Sstefano_zampini     ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr);
1176ad219c80Sstefano_zampini   }
1177ad219c80Sstefano_zampini   ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr);
1178ad219c80Sstefano_zampini   PetscFunctionReturn(0);
1179ad219c80Sstefano_zampini }
1180ad219c80Sstefano_zampini 
11817fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
11827fa8f2d3SStefano Zampini {
11837fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
11847fa8f2d3SStefano Zampini   MatInfo        info;
1185314ce898Sstefano_zampini   PetscReal      isend[6],irecv[6];
11867fa8f2d3SStefano Zampini   PetscInt       bs;
11877fa8f2d3SStefano Zampini   PetscErrorCode ierr;
11887fa8f2d3SStefano Zampini 
11897fa8f2d3SStefano Zampini   PetscFunctionBegin;
11907fa8f2d3SStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
1191a2ccb5f9Sstefano_zampini   if (matis->A->ops->getinfo) {
11927fa8f2d3SStefano Zampini     ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
11937fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
11947fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
11957fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
11967fa8f2d3SStefano Zampini     isend[3] = info.memory;
11977fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
1198a2ccb5f9Sstefano_zampini   } else {
1199a2ccb5f9Sstefano_zampini     isend[0] = 0.;
1200a2ccb5f9Sstefano_zampini     isend[1] = 0.;
1201a2ccb5f9Sstefano_zampini     isend[2] = 0.;
1202a2ccb5f9Sstefano_zampini     isend[3] = 0.;
1203a2ccb5f9Sstefano_zampini     isend[4] = 0.;
1204a2ccb5f9Sstefano_zampini   }
1205314ce898Sstefano_zampini   isend[5] = matis->A->num_ass;
12067fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
12077fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
12087fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
12097fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
12107fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
12117fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
1212314ce898Sstefano_zampini     ginfo->assemblies   = isend[5];
12137fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
1214314ce898Sstefano_zampini     ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
12157fa8f2d3SStefano Zampini 
12167fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
12177fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
12187fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
12197fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
12207fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
1221314ce898Sstefano_zampini     ginfo->assemblies   = irecv[5];
12227fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
12237fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
12247fa8f2d3SStefano Zampini 
12257fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
12267fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
12277fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
12287fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
12297fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
12307fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
12317fa8f2d3SStefano Zampini   }
12327fa8f2d3SStefano Zampini   ginfo->block_size        = bs;
12337fa8f2d3SStefano Zampini   ginfo->fill_ratio_given  = 0;
12347fa8f2d3SStefano Zampini   ginfo->fill_ratio_needed = 0;
12357fa8f2d3SStefano Zampini   ginfo->factor_mallocs    = 0;
12365e3038f0Sstefano_zampini   PetscFunctionReturn(0);
12375e3038f0Sstefano_zampini }
12385e3038f0Sstefano_zampini 
1239d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
1240d7f69cd0SStefano Zampini {
1241d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
1242d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
1243d7f69cd0SStefano Zampini 
1244d7f69cd0SStefano Zampini   PetscFunctionBegin;
1245cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
1246cf37664fSBarry Smith     ISLocalToGlobalMapping rl2g,cl2g;
1247d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
1248d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
1249d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
1250d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
1251d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
1252d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
1253cf37664fSBarry Smith   } else {
1254cf37664fSBarry Smith     C = *B;
1255d7f69cd0SStefano Zampini   }
1256d7f69cd0SStefano Zampini 
1257d7f69cd0SStefano Zampini   /* perform local transposition */
1258d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1259d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
1260d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
1261d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
1262d7f69cd0SStefano Zampini 
1263cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
1264d7f69cd0SStefano Zampini     *B = C;
1265d7f69cd0SStefano Zampini   } else {
1266d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
1267d7f69cd0SStefano Zampini   }
12687aa7aec5Sstefano_zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
12697aa7aec5Sstefano_zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1270d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
1271d7f69cd0SStefano Zampini }
1272d7f69cd0SStefano Zampini 
12733fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
12743fd1c9e7SStefano Zampini {
12753fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
12763fd1c9e7SStefano Zampini   PetscErrorCode ierr;
12773fd1c9e7SStefano Zampini 
12783fd1c9e7SStefano Zampini   PetscFunctionBegin;
12794b89b9cdSStefano Zampini   if (D) { /* MatShift_IS pass D = NULL */
12803fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12813fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12823fd1c9e7SStefano Zampini   }
12833fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
12843fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
12853fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
12863fd1c9e7SStefano Zampini }
12873fd1c9e7SStefano Zampini 
12883fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
12893fd1c9e7SStefano Zampini {
12904b89b9cdSStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
12913fd1c9e7SStefano Zampini   PetscErrorCode ierr;
12923fd1c9e7SStefano Zampini 
12933fd1c9e7SStefano Zampini   PetscFunctionBegin;
12944b89b9cdSStefano Zampini   ierr = VecSet(is->y,a);CHKERRQ(ierr);
12953fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
12963fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
12973fd1c9e7SStefano Zampini }
12983fd1c9e7SStefano Zampini 
1299f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1300f26d0771SStefano Zampini {
1301f26d0771SStefano Zampini   PetscErrorCode ierr;
1302f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1303f26d0771SStefano Zampini 
1304f26d0771SStefano Zampini   PetscFunctionBegin;
1305f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1306f26d0771SStefano Zampini   if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n);
1307f26d0771SStefano Zampini #endif
1308f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
1309f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
1310b4f971dfSStefano Zampini   ierr = MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
1311f26d0771SStefano Zampini   PetscFunctionReturn(0);
1312f26d0771SStefano Zampini }
1313f26d0771SStefano Zampini 
1314f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1315f26d0771SStefano Zampini {
1316f26d0771SStefano Zampini   PetscErrorCode ierr;
1317f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1318f26d0771SStefano Zampini 
1319f26d0771SStefano Zampini   PetscFunctionBegin;
1320f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1321f26d0771SStefano Zampini   if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column block indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n);
1322f26d0771SStefano Zampini #endif
1323f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
1324f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
1325b4f971dfSStefano Zampini   ierr = MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
1326f26d0771SStefano Zampini   PetscFunctionReturn(0);
1327f26d0771SStefano Zampini }
1328f26d0771SStefano Zampini 
1329f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
1330a8116848SStefano Zampini {
1331a8116848SStefano Zampini   PetscInt      *owners = map->range;
1332a8116848SStefano Zampini   PetscInt       n      = map->n;
1333a8116848SStefano Zampini   PetscSF        sf;
1334a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
1335a8116848SStefano Zampini   PetscSFNode   *ridxs;
1336a8116848SStefano Zampini   PetscMPIInt    rank;
1337a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
1338a8116848SStefano Zampini   PetscErrorCode ierr;
1339a8116848SStefano Zampini 
1340a8116848SStefano Zampini   PetscFunctionBegin;
1341fd3a879cSJed Brown   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
1342a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
1343a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
1344a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
1345a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
1346a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
1347a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
1348a8116848SStefano Zampini     const PetscInt idx = idxs[r];
1349a8116848SStefano Zampini     if (idx < 0 || map->N <= idx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Index %D out of range [0,%D)",idx,map->N);
1350a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
1351a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
1352a8116848SStefano Zampini     }
1353a8116848SStefano Zampini     ridxs[r].rank = p;
1354a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
1355a8116848SStefano Zampini   }
1356a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
1357a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
1358a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
1359a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
1360f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
1361a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
1362f0ae7da4SStefano Zampini 
1363f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
1364a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
1365a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
1366a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
1367a8116848SStefano Zampini     start -= cum;
1368a8116848SStefano Zampini     cum = 0;
1369a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
1370a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
1371a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
1372a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
1373a8116848SStefano Zampini   }
1374a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
1375a8116848SStefano Zampini   /* Compress and put in indices */
1376a8116848SStefano Zampini   for (r = 0; r < n; ++r)
1377a8116848SStefano Zampini     if (lidxs[r] >= 0) {
1378a8116848SStefano Zampini       if (work) work[len] = work[r];
1379a8116848SStefano Zampini       lidxs[len++] = r;
1380a8116848SStefano Zampini     }
1381a8116848SStefano Zampini   if (on) *on = len;
1382a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
1383a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
1384a8116848SStefano Zampini   PetscFunctionReturn(0);
1385a8116848SStefano Zampini }
1386a8116848SStefano Zampini 
13877dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
1388a8116848SStefano Zampini {
1389a8116848SStefano Zampini   Mat               locmat,newlocmat;
1390a8116848SStefano Zampini   Mat_IS            *newmatis;
1391a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
1392a8116848SStefano Zampini   Vec               rtest,ltest;
1393a8116848SStefano Zampini   const PetscScalar *array;
1394a8116848SStefano Zampini #endif
1395a8116848SStefano Zampini   const PetscInt    *idxs;
1396a8116848SStefano Zampini   PetscInt          i,m,n;
1397a8116848SStefano Zampini   PetscErrorCode    ierr;
1398a8116848SStefano Zampini 
1399a8116848SStefano Zampini   PetscFunctionBegin;
1400a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
1401a8116848SStefano Zampini     PetscBool ismatis;
1402a8116848SStefano Zampini 
1403a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
1404a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
1405a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
1406a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
1407a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
1408a8116848SStefano Zampini   }
1409a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
1410a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
1411a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
1412a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
1413a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
1414a8116848SStefano Zampini   for (i=0;i<n;i++) {
1415a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
1416a8116848SStefano Zampini   }
1417a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
1418a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
1419a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
1420a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
1421a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
1422fd479f66SMatthew G. Knepley   for (i=0;i<n;i++) if (array[i] != 0. && array[i] != 1.) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %D counted %D times! Irow may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i]));
1423a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
1424a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
1425a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
1426a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
1427a8116848SStefano Zampini   for (i=0;i<n;i++) {
1428a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
1429a8116848SStefano Zampini   }
1430a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
1431a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
1432a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
1433a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
1434a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
1435fd479f66SMatthew G. Knepley   for (i=0;i<n;i++) if (array[i] != 0. && array[i] != 1.) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %D counted %D times! Icol may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i]));
1436a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
1437a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
1438a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
1439a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
1440a8116848SStefano Zampini #endif
1441a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1442a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
1443a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
1444a8116848SStefano Zampini     IS                     is;
1445a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
1446306cf5c7SStefano Zampini     PetscInt               ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs;
144794342113SStefano Zampini     PetscBool              cong;
1448a8116848SStefano Zampini     MPI_Comm               comm;
1449a8116848SStefano Zampini 
1450a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
1451306cf5c7SStefano Zampini     ierr = MatGetBlockSizes(mat,&arbs,&acbs);CHKERRQ(ierr);
1452306cf5c7SStefano Zampini     ierr = ISGetBlockSize(irow,&irbs);CHKERRQ(ierr);
1453306cf5c7SStefano Zampini     ierr = ISGetBlockSize(icol,&icbs);CHKERRQ(ierr);
1454306cf5c7SStefano Zampini     rbs  = arbs == irbs ? irbs : 1;
1455306cf5c7SStefano Zampini     cbs  = acbs == icbs ? icbs : 1;
1456a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
1457a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
1458a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
1459a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
1460a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1461306cf5c7SStefano Zampini     ierr = MatSetBlockSizes(*newmat,rbs,cbs);CHKERRQ(ierr);
1462a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
1463a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
1464f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
1465a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
14663d996552SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
1467a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
1468a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
1469a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
1470a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
1471a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
14723d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
1473a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
1474a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
14753d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
1476a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
1477a8116848SStefano Zampini         lidxs[newloc] = i;
1478a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
1479a8116848SStefano Zampini       }
1480a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1481a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
1482306cf5c7SStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(rl2g,rbs);CHKERRQ(ierr);
1483a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
1484a8116848SStefano Zampini     /* local is to extract local submatrix */
1485a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
1486a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
148794342113SStefano Zampini     ierr = MatHasCongruentLayouts(mat,&cong);CHKERRQ(ierr);
148894342113SStefano Zampini     if (cong && irow == icol && matis->csf == matis->sf) {
1489a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
1490a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
1491a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
1492a8116848SStefano Zampini     } else {
1493a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
1494a8116848SStefano Zampini 
1495a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
1496a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
1497f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
1498a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
14993d996552SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
1500a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
1501a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
1502a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
1503a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
1504a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
15053d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
1506a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
1507a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
15083d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
1509a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
1510a8116848SStefano Zampini           lidxs[newloc] = i;
1511a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
1512a8116848SStefano Zampini         }
1513a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1514a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
1515306cf5c7SStefano Zampini       ierr = ISLocalToGlobalMappingSetBlockSize(cl2g,cbs);CHKERRQ(ierr);
1516a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
1517a8116848SStefano Zampini       /* local is to extract local submatrix */
1518a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
1519a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
1520a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1521a8116848SStefano Zampini     }
1522a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1523a8116848SStefano Zampini   } else {
1524a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
1525a8116848SStefano Zampini   }
1526a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
1527a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
15287dae84e0SHong Zhang   ierr = MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
1529a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1530a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
1531a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
1532a8116848SStefano Zampini   }
1533a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1534a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1535a8116848SStefano Zampini   PetscFunctionReturn(0);
1536a8116848SStefano Zampini }
1537a8116848SStefano Zampini 
1538a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
15392b404112SStefano Zampini {
15402b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
15412b404112SStefano Zampini   PetscBool      ismatis;
15422b404112SStefano Zampini   PetscErrorCode ierr;
15432b404112SStefano Zampini 
15442b404112SStefano Zampini   PetscFunctionBegin;
15452b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
15462b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
15472b404112SStefano Zampini   b = (Mat_IS*)B->data;
15482b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
1549cdc753b6SBarry Smith   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
15502b404112SStefano Zampini   PetscFunctionReturn(0);
15512b404112SStefano Zampini }
15522b404112SStefano Zampini 
1553a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
15546bd84002SStefano Zampini {
1555527b2640SStefano Zampini   Vec               v;
1556527b2640SStefano Zampini   const PetscScalar *array;
1557527b2640SStefano Zampini   PetscInt          i,n;
15586bd84002SStefano Zampini   PetscErrorCode    ierr;
15596bd84002SStefano Zampini 
15606bd84002SStefano Zampini   PetscFunctionBegin;
1561527b2640SStefano Zampini   *missing = PETSC_FALSE;
1562527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
1563527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
1564527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1565527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
1566527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
1567527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
1568527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1569527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
1570527b2640SStefano Zampini   if (d) {
1571527b2640SStefano Zampini     *d = -1;
1572527b2640SStefano Zampini     if (*missing) {
1573527b2640SStefano Zampini       PetscInt rstart;
1574527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
1575527b2640SStefano Zampini       *d = i+rstart;
1576527b2640SStefano Zampini     }
1577527b2640SStefano Zampini   }
15786bd84002SStefano Zampini   PetscFunctionReturn(0);
15796bd84002SStefano Zampini }
15806bd84002SStefano Zampini 
1581cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
158228f4e0baSStefano Zampini {
158328f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
158428f4e0baSStefano Zampini   const PetscInt *gidxs;
15854f2d7cafSStefano Zampini   PetscInt       nleaves;
158628f4e0baSStefano Zampini   PetscErrorCode ierr;
158728f4e0baSStefano Zampini 
158828f4e0baSStefano Zampini   PetscFunctionBegin;
15894f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
159028f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
15913bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
15924f2d7cafSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
15934f2d7cafSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
15943bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
15954f2d7cafSStefano Zampini   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
1596a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
15973d996552SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
1598a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
1599a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
16003d996552SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
1601a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
16023d996552SStefano Zampini     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
1603a8116848SStefano Zampini   } else {
1604a8116848SStefano Zampini     matis->csf = matis->sf;
1605a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
1606a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
1607a8116848SStefano Zampini   }
160828f4e0baSStefano Zampini   PetscFunctionReturn(0);
160928f4e0baSStefano Zampini }
16102e1947a5SStefano Zampini 
1611eb82efa4SStefano Zampini /*@
161275d48cdbSStefano Zampini    MatISStoreL2L - Store local-to-local operators during the Galerkin process of MatPtAP.
161375d48cdbSStefano Zampini 
161475d48cdbSStefano Zampini    Collective on MPI_Comm
161575d48cdbSStefano Zampini 
161675d48cdbSStefano Zampini    Input Parameters:
161775d48cdbSStefano Zampini +  A - the matrix
161875d48cdbSStefano Zampini -  store - the boolean flag
161975d48cdbSStefano Zampini 
162075d48cdbSStefano Zampini    Level: advanced
162175d48cdbSStefano Zampini 
162275d48cdbSStefano Zampini    Notes:
162375d48cdbSStefano Zampini 
162475d48cdbSStefano Zampini .keywords: matrix
162575d48cdbSStefano Zampini 
162675d48cdbSStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatPtAP()
162775d48cdbSStefano Zampini @*/
162875d48cdbSStefano Zampini PetscErrorCode  MatISStoreL2L(Mat A, PetscBool store)
162975d48cdbSStefano Zampini {
163075d48cdbSStefano Zampini   PetscErrorCode ierr;
163175d48cdbSStefano Zampini 
163275d48cdbSStefano Zampini   PetscFunctionBegin;
163375d48cdbSStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
163475d48cdbSStefano Zampini   PetscValidType(A,1);
163575d48cdbSStefano Zampini   PetscValidLogicalCollectiveBool(A,store,2);
163675d48cdbSStefano Zampini   ierr = PetscTryMethod(A,"MatISStoreL2L_C",(Mat,PetscBool),(A,store));CHKERRQ(ierr);
163775d48cdbSStefano Zampini   PetscFunctionReturn(0);
163875d48cdbSStefano Zampini }
163975d48cdbSStefano Zampini 
164075d48cdbSStefano Zampini static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store)
164175d48cdbSStefano Zampini {
164275d48cdbSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(A->data);
164375d48cdbSStefano Zampini   PetscErrorCode ierr;
164475d48cdbSStefano Zampini 
164575d48cdbSStefano Zampini   PetscFunctionBegin;
164675d48cdbSStefano Zampini   matis->storel2l = store;
164775d48cdbSStefano Zampini   if (!store) {
164875d48cdbSStefano Zampini     ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",NULL);CHKERRQ(ierr);
164975d48cdbSStefano Zampini   }
165075d48cdbSStefano Zampini   PetscFunctionReturn(0);
165175d48cdbSStefano Zampini }
165275d48cdbSStefano Zampini 
165375d48cdbSStefano Zampini /*@
1654f03112d0SStefano Zampini    MatISFixLocalEmpty - Compress out zero local rows from the local matrices
1655f03112d0SStefano Zampini 
1656f03112d0SStefano Zampini    Collective on MPI_Comm
1657f03112d0SStefano Zampini 
1658f03112d0SStefano Zampini    Input Parameters:
1659f03112d0SStefano Zampini +  A - the matrix
1660f03112d0SStefano Zampini -  fix - the boolean flag
1661f03112d0SStefano Zampini 
1662f03112d0SStefano Zampini    Level: advanced
1663f03112d0SStefano Zampini 
1664f03112d0SStefano Zampini    Notes: When fix is true, new local matrices and l2g maps are generated during the final assembly process.
1665f03112d0SStefano Zampini 
1666f03112d0SStefano Zampini .keywords: matrix
1667f03112d0SStefano Zampini 
1668f03112d0SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatAssemblyEnd(), MAT_FINAL_ASSEMBLY
1669f03112d0SStefano Zampini @*/
1670f03112d0SStefano Zampini PetscErrorCode  MatISFixLocalEmpty(Mat A, PetscBool fix)
1671f03112d0SStefano Zampini {
1672f03112d0SStefano Zampini   PetscErrorCode ierr;
1673f03112d0SStefano Zampini 
1674f03112d0SStefano Zampini   PetscFunctionBegin;
1675f03112d0SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1676f03112d0SStefano Zampini   PetscValidType(A,1);
1677f03112d0SStefano Zampini   PetscValidLogicalCollectiveBool(A,fix,2);
1678f03112d0SStefano Zampini   ierr = PetscTryMethod(A,"MatISFixLocalEmpty_C",(Mat,PetscBool),(A,fix));CHKERRQ(ierr);
1679f03112d0SStefano Zampini   PetscFunctionReturn(0);
1680f03112d0SStefano Zampini }
1681f03112d0SStefano Zampini 
1682f03112d0SStefano Zampini static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix)
1683f03112d0SStefano Zampini {
1684f03112d0SStefano Zampini   Mat_IS *matis = (Mat_IS*)(A->data);
1685f03112d0SStefano Zampini 
1686f03112d0SStefano Zampini   PetscFunctionBegin;
1687f03112d0SStefano Zampini   matis->locempty = fix;
1688f03112d0SStefano Zampini   PetscFunctionReturn(0);
1689f03112d0SStefano Zampini }
1690f03112d0SStefano Zampini 
1691f03112d0SStefano Zampini /*@
1692a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
1693a88811baSStefano Zampini 
1694a88811baSStefano Zampini    Collective on MPI_Comm
1695a88811baSStefano Zampini 
1696a88811baSStefano Zampini    Input Parameters:
1697a88811baSStefano Zampini +  B - the matrix
1698a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1699a88811baSStefano Zampini            (same value is used for all local rows)
1700a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
1701a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
1702a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
1703a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
1704a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
1705a88811baSStefano Zampini            the diagonal entry even if it is zero.
1706a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1707a88811baSStefano Zampini            submatrix (same value is used for all local rows).
1708a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
1709a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
1710a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
1711a88811baSStefano Zampini            structure. The size of this array is equal to the number
1712a88811baSStefano Zampini            of local rows, i.e 'm'.
1713a88811baSStefano Zampini 
1714a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
1715a88811baSStefano Zampini 
1716a88811baSStefano Zampini    Level: intermediate
1717a88811baSStefano Zampini 
171895452b02SPatrick Sanan    Notes:
171995452b02SPatrick Sanan     This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
1720a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
1721a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1722a88811baSStefano Zampini 
1723a88811baSStefano Zampini .keywords: matrix
1724a88811baSStefano Zampini 
17253c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
1726a88811baSStefano Zampini @*/
17272e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
17282e1947a5SStefano Zampini {
17292e1947a5SStefano Zampini   PetscErrorCode ierr;
17302e1947a5SStefano Zampini 
17312e1947a5SStefano Zampini   PetscFunctionBegin;
17322e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
17332e1947a5SStefano Zampini   PetscValidType(B,1);
17342e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
17352e1947a5SStefano Zampini   PetscFunctionReturn(0);
17362e1947a5SStefano Zampini }
17372e1947a5SStefano Zampini 
1738844bd0d7SStefano Zampini /* this is used by DMDA */
1739844bd0d7SStefano Zampini PETSC_EXTERN PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
17402e1947a5SStefano Zampini {
17412e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
174228f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
17432e1947a5SStefano Zampini   PetscErrorCode ierr;
17442e1947a5SStefano Zampini 
17452e1947a5SStefano Zampini   PetscFunctionBegin;
17466c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
17474f2d7cafSStefano Zampini 
17484f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
17494f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
17504f2d7cafSStefano Zampini 
17514f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
17524f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
17534f2d7cafSStefano Zampini 
175428f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
175528f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
175628f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
175728f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
17584f2d7cafSStefano Zampini 
17594f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
176028f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
17610f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE)
17620f2f62c7SStefano Zampini   ierr = MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL);CHKERRQ(ierr);
17630f2f62c7SStefano Zampini #endif
17644f2d7cafSStefano Zampini 
17654f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
176628f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
17674f2d7cafSStefano Zampini 
176800a59248SStefano Zampini   nlocalcols /= bs;
176900a59248SStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols - i);
177028f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
17710f2f62c7SStefano Zampini 
17720f2f62c7SStefano Zampini   /* for other matrix types */
17730f2f62c7SStefano Zampini   ierr = MatSetUp(matis->A);CHKERRQ(ierr);
17742e1947a5SStefano Zampini   PetscFunctionReturn(0);
17752e1947a5SStefano Zampini }
1776b4319ba4SBarry Smith 
17773927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
17783927de2eSStefano Zampini {
17793927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
17803927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1781ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
17823927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
17833927de2eSStefano Zampini   PetscInt        lrows,lcols;
17843927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
1785f03112d0SStefano Zampini   PetscMPIInt     size;
17863927de2eSStefano Zampini   PetscBool       isdense,issbaij;
17873927de2eSStefano Zampini   PetscErrorCode  ierr;
17883927de2eSStefano Zampini 
17893927de2eSStefano Zampini   PetscFunctionBegin;
1790f03112d0SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr);
17913927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
17923927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
17933927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
17943927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
17953927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1796ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1797ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
17987230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1799ecf5a873SStefano Zampini   } else {
1800ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
1801ecf5a873SStefano Zampini   }
1802ecf5a873SStefano Zampini 
18033927de2eSStefano Zampini   if (issbaij) {
18043927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
18053927de2eSStefano Zampini   }
18063927de2eSStefano Zampini   /*
1807ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
18083927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
18093927de2eSStefano Zampini   */
18103927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
18113927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
18123927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
18133927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
18143927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
1815f03112d0SStefano Zampini   for (i=0;i<size;i++) {
18163927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
18173927de2eSStefano Zampini       row_ownership[j] = i;
18183927de2eSStefano Zampini     }
18193927de2eSStefano Zampini   }
18207230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
18213927de2eSStefano Zampini 
18223927de2eSStefano Zampini   /*
18233927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
18243927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
18253927de2eSStefano Zampini   */
18263927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
18273927de2eSStefano Zampini   /* preallocation as a MATAIJ */
18283927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
18293927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
183012dfadf8SStefano Zampini       PetscInt owner = row_ownership[global_indices_r[i]];
183112dfadf8SStefano Zampini       for (j=0;j<local_cols;j++) {
1832ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
18333927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
18343927de2eSStefano Zampini           my_dnz[i] += 1;
18353927de2eSStefano Zampini         } else { /* offdiag block */
18363927de2eSStefano Zampini           my_onz[i] += 1;
18373927de2eSStefano Zampini         }
18383927de2eSStefano Zampini       }
18393927de2eSStefano Zampini     }
1840bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1841bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1842bb1015c3SStefano Zampini     PetscBool      done;
1843bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1844938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1845bb1015c3SStefano Zampini     jptr = jj;
1846bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1847bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1848bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1849bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1850bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1851bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1852bb1015c3SStefano Zampini           my_dnz[i] += 1;
1853bb1015c3SStefano Zampini         } else { /* offdiag block */
1854bb1015c3SStefano Zampini           my_onz[i] += 1;
1855bb1015c3SStefano Zampini         }
1856bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1857bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1858bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1859bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1860bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1861bb1015c3SStefano Zampini           } else {
1862bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1863bb1015c3SStefano Zampini           }
1864bb1015c3SStefano Zampini         }
1865bb1015c3SStefano Zampini       }
1866bb1015c3SStefano Zampini     }
1867bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1868938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1869bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
18703927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
18713927de2eSStefano Zampini       const PetscInt *cols;
1872ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
18733927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
18743927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
18753927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1876ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
18773927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
18783927de2eSStefano Zampini           my_dnz[i] += 1;
18793927de2eSStefano Zampini         } else { /* offdiag block */
18803927de2eSStefano Zampini           my_onz[i] += 1;
18813927de2eSStefano Zampini         }
18823927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1883d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
18843927de2eSStefano Zampini           owner = row_ownership[index_col];
18853927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1886d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
18873927de2eSStefano Zampini           } else {
1888d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
18893927de2eSStefano Zampini           }
18903927de2eSStefano Zampini         }
18913927de2eSStefano Zampini       }
18923927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
18933927de2eSStefano Zampini     }
18943927de2eSStefano Zampini   }
1895ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
18967230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1897ecf5a873SStefano Zampini   }
18984f619741Sstefano_zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
18993927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1900ecf5a873SStefano Zampini 
1901ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
19023927de2eSStefano Zampini   if (maxreduce) {
19033927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
19043927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1905bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
19063927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
19073927de2eSStefano Zampini   } else {
19083927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
19093927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1910bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
19113927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
19123927de2eSStefano Zampini   }
19133927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
19143927de2eSStefano Zampini 
19153927de2eSStefano Zampini   /* Resize preallocation if overestimated */
19163927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
19173927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
19183927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
19193927de2eSStefano Zampini   }
19201670daf9Sstefano_zampini 
19211670daf9Sstefano_zampini   /* Set preallocation */
1922268753edSStefano Zampini   ierr = MatSeqAIJSetPreallocation(B,0,dnz);CHKERRQ(ierr);
19233927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
192453b44cf5SStefano Zampini   for (i=0;i<lrows;i+=bs) {
192553b44cf5SStefano Zampini     PetscInt b, d = dnz[i],o = onz[i];
192653b44cf5SStefano Zampini 
192753b44cf5SStefano Zampini     for (b=1;b<bs;b++) {
192853b44cf5SStefano Zampini       d = PetscMax(d,dnz[i+b]);
192953b44cf5SStefano Zampini       o = PetscMax(o,onz[i+b]);
193053b44cf5SStefano Zampini     }
193153b44cf5SStefano Zampini     dnz[i/bs] = PetscMin(d/bs + d%bs,lcols/bs);
193253b44cf5SStefano Zampini     onz[i/bs] = PetscMin(o/bs + o%bs,(cols-lcols)/bs);
19333927de2eSStefano Zampini   }
1934268753edSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(B,bs,0,dnz);CHKERRQ(ierr);
19353927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
19363927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
19373927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
19383927de2eSStefano Zampini   if (issbaij) {
19393927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
19403927de2eSStefano Zampini   }
19419be90c3fSStefano Zampini   ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
19423927de2eSStefano Zampini   PetscFunctionReturn(0);
19433927de2eSStefano Zampini }
19443927de2eSStefano Zampini 
1945487b449aSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M)
1946b7ce53b6SStefano Zampini {
1947b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1948487b449aSStefano Zampini   Mat            local_mat,MT;
194953b44cf5SStefano Zampini   PetscInt       rbs,cbs,rows,cols,lrows,lcols;
1950b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
1951b9ed4604SStefano Zampini   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1952b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1953b9ed4604SStefano Zampini   PetscBool      lb[4],bb[4];
1954b9ed4604SStefano Zampini #endif
1955f03112d0SStefano Zampini   PetscMPIInt    size;
1956b7ce53b6SStefano Zampini   PetscScalar    *array;
1957b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1958b7ce53b6SStefano Zampini 
1959b7ce53b6SStefano Zampini   PetscFunctionBegin;
1960f03112d0SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
1961f03112d0SStefano Zampini   if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N) {
19621670daf9Sstefano_zampini     Mat      B;
196353b44cf5SStefano Zampini     IS       irows = NULL,icols = NULL;
1964487b449aSStefano Zampini     PetscInt rbs,cbs;
19651670daf9Sstefano_zampini 
1966487b449aSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
1967487b449aSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
196853b44cf5SStefano Zampini     if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */
196953b44cf5SStefano Zampini       IS             rows,cols;
197053b44cf5SStefano Zampini       const PetscInt *ridxs,*cidxs;
197153b44cf5SStefano Zampini       PetscInt       i,nw,*work;
197253b44cf5SStefano Zampini 
197353b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
197453b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&nw);CHKERRQ(ierr);
197553b44cf5SStefano Zampini       nw   = nw/rbs;
197653b44cf5SStefano Zampini       ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr);
197753b44cf5SStefano Zampini       for (i=0;i<nw;i++) work[ridxs[i]] += 1;
197853b44cf5SStefano Zampini       for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
197953b44cf5SStefano Zampini       if (i == nw) {
198053b44cf5SStefano Zampini         ierr = ISCreateBlock(PETSC_COMM_SELF,rbs,nw,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
1981acdf38a7Sstefano_zampini         ierr = ISSetPermutation(rows);CHKERRQ(ierr);
198253b44cf5SStefano Zampini         ierr = ISInvertPermutation(rows,PETSC_DECIDE,&irows);CHKERRQ(ierr);
1983acdf38a7Sstefano_zampini         ierr = ISDestroy(&rows);CHKERRQ(ierr);
198453b44cf5SStefano Zampini       }
198553b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
198653b44cf5SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
198753b44cf5SStefano Zampini       if (irows && mat->rmap->mapping != mat->cmap->mapping) {
198853b44cf5SStefano Zampini         ierr = ISLocalToGlobalMappingGetBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
198953b44cf5SStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(mat->cmap->mapping,&nw);CHKERRQ(ierr);
199053b44cf5SStefano Zampini         nw   = nw/cbs;
199153b44cf5SStefano Zampini         ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr);
199253b44cf5SStefano Zampini         for (i=0;i<nw;i++) work[cidxs[i]] += 1;
199353b44cf5SStefano Zampini         for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
199453b44cf5SStefano Zampini         if (i == nw) {
199553b44cf5SStefano Zampini           ierr = ISCreateBlock(PETSC_COMM_SELF,cbs,nw,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
199653b44cf5SStefano Zampini           ierr = ISSetPermutation(cols);CHKERRQ(ierr);
199753b44cf5SStefano Zampini           ierr = ISInvertPermutation(cols,PETSC_DECIDE,&icols);CHKERRQ(ierr);
199853b44cf5SStefano Zampini           ierr = ISDestroy(&cols);CHKERRQ(ierr);
199953b44cf5SStefano Zampini         }
200053b44cf5SStefano Zampini         ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
200153b44cf5SStefano Zampini         ierr = PetscFree(work);CHKERRQ(ierr);
200253b44cf5SStefano Zampini       } else if (irows) {
200353b44cf5SStefano Zampini         ierr  = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr);
200453b44cf5SStefano Zampini         icols = irows;
200553b44cf5SStefano Zampini       }
200653b44cf5SStefano Zampini     } else {
200753b44cf5SStefano Zampini       ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject*)&irows);CHKERRQ(ierr);
200853b44cf5SStefano Zampini       ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject*)&icols);CHKERRQ(ierr);
200953b44cf5SStefano Zampini       if (irows) { ierr = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr); }
201053b44cf5SStefano Zampini       if (icols) { ierr = PetscObjectReference((PetscObject)icols);CHKERRQ(ierr); }
201153b44cf5SStefano Zampini     }
201253b44cf5SStefano Zampini     if (!irows || !icols) {
201353b44cf5SStefano Zampini       ierr = ISDestroy(&icols);CHKERRQ(ierr);
201453b44cf5SStefano Zampini       ierr = ISDestroy(&irows);CHKERRQ(ierr);
201553b44cf5SStefano Zampini       goto general_assembly;
201653b44cf5SStefano Zampini     }
2017487b449aSStefano Zampini     ierr = MatConvert(matis->A,(rbs == cbs && rbs > 1) ? MATSEQBAIJ : MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
2018487b449aSStefano Zampini     if (reuse != MAT_INPLACE_MATRIX) {
20197dae84e0SHong Zhang       ierr = MatCreateSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr);
202053b44cf5SStefano Zampini       ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject)irows);CHKERRQ(ierr);
202153b44cf5SStefano Zampini       ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject)icols);CHKERRQ(ierr);
2022487b449aSStefano Zampini     } else {
2023487b449aSStefano Zampini       Mat C;
2024487b449aSStefano Zampini 
2025487b449aSStefano Zampini       ierr = MatCreateSubMatrix(B,irows,icols,MAT_INITIAL_MATRIX,&C);CHKERRQ(ierr);
2026487b449aSStefano Zampini       ierr = MatHeaderReplace(mat,&C);CHKERRQ(ierr);
2027487b449aSStefano Zampini     }
2028acdf38a7Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
2029acdf38a7Sstefano_zampini     ierr = ISDestroy(&icols);CHKERRQ(ierr);
2030acdf38a7Sstefano_zampini     ierr = ISDestroy(&irows);CHKERRQ(ierr);
20317c03b4e8SStefano Zampini     PetscFunctionReturn(0);
20327c03b4e8SStefano Zampini   }
203353b44cf5SStefano Zampini general_assembly:
2034b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
203553b44cf5SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
203653b44cf5SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
20373cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
2038b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
2039b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
20404099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
2041b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
2042b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
2043b9ed4604SStefano Zampini   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
2044b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
2045b9ed4604SStefano Zampini   lb[0] = isseqdense;
2046b9ed4604SStefano Zampini   lb[1] = isseqaij;
2047b9ed4604SStefano Zampini   lb[2] = isseqbaij;
2048b9ed4604SStefano Zampini   lb[3] = isseqsbaij;
2049b9ed4604SStefano Zampini   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
2050b9ed4604SStefano Zampini   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
2051b9ed4604SStefano Zampini #endif
2052b7ce53b6SStefano Zampini 
2053487b449aSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
2054487b449aSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),&MT);CHKERRQ(ierr);
2055487b449aSStefano Zampini     ierr = MatSetSizes(MT,lrows,lcols,rows,cols);CHKERRQ(ierr);
2056487b449aSStefano Zampini     ierr = MatSetType(MT,mtype);CHKERRQ(ierr);
205753b44cf5SStefano Zampini     ierr = MatSetBlockSizes(MT,rbs,cbs);CHKERRQ(ierr);
2058487b449aSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,MT,PETSC_FALSE);CHKERRQ(ierr);
2059b7ce53b6SStefano Zampini   } else {
206053b44cf5SStefano Zampini     PetscInt mrbs,mcbs,mrows,mcols,mlrows,mlcols;
2061487b449aSStefano Zampini 
2062b7ce53b6SStefano Zampini     /* some checks */
2063487b449aSStefano Zampini     MT   = *M;
206453b44cf5SStefano Zampini     ierr = MatGetBlockSizes(MT,&mrbs,&mcbs);CHKERRQ(ierr);
2065487b449aSStefano Zampini     ierr = MatGetSize(MT,&mrows,&mcols);CHKERRQ(ierr);
2066487b449aSStefano Zampini     ierr = MatGetLocalSize(MT,&mlrows,&mlcols);CHKERRQ(ierr);
20676c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
20686c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
20696c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
20706c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
207153b44cf5SStefano Zampini     if (mrbs != rbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong row block size (%d != %d)",rbs,mrbs);
207253b44cf5SStefano Zampini     if (mcbs != cbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong col block size (%d != %d)",cbs,mcbs);
2073487b449aSStefano Zampini     ierr = MatZeroEntries(MT);CHKERRQ(ierr);
2074b7ce53b6SStefano Zampini   }
2075d9a9e74cSStefano Zampini 
20768546b261SStefano Zampini   if (isseqsbaij || isseqbaij) {
20778546b261SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
20788546b261SStefano Zampini     isseqaij = PETSC_TRUE;
2079d9a9e74cSStefano Zampini   } else {
2080d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
2081d9a9e74cSStefano Zampini     local_mat = matis->A;
2082d9a9e74cSStefano Zampini   }
2083686e3a49SStefano Zampini 
2084b7ce53b6SStefano Zampini   /* Set values */
2085487b449aSStefano Zampini   ierr = MatSetLocalToGlobalMapping(MT,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
2086b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
208765066ba5SStefano Zampini     PetscInt i,*dummy;
2088ecf5a873SStefano Zampini 
208965066ba5SStefano Zampini     ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr);
209065066ba5SStefano Zampini     for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i;
2091487b449aSStefano Zampini     ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
2092d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
2093487b449aSStefano Zampini     ierr = MatSetValuesLocal(MT,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr);
2094d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
209565066ba5SStefano Zampini     ierr = PetscFree(dummy);CHKERRQ(ierr);
2096686e3a49SStefano Zampini   } else if (isseqaij) {
20976afe12f5SStefano Zampini     const PetscInt *blocks;
20986afe12f5SStefano Zampini     PetscInt       i,nvtxs,*xadj,*adjncy, nb;
2099686e3a49SStefano Zampini     PetscBool      done;
2100686e3a49SStefano Zampini 
2101d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2102938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
2103d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
21046afe12f5SStefano Zampini     ierr = MatGetVariableBlockSizes(local_mat,&nb,&blocks);CHKERRQ(ierr);
21056afe12f5SStefano Zampini     if (nb) { /* speed up assembly for special blocked matrices (used by BDDC) */
21066afe12f5SStefano Zampini       PetscInt sum;
21076afe12f5SStefano Zampini 
21086afe12f5SStefano Zampini       for (i=0,sum=0;i<nb;i++) sum += blocks[i];
21096afe12f5SStefano Zampini       if (sum == nvtxs) {
21106afe12f5SStefano Zampini         PetscInt r;
21116afe12f5SStefano Zampini 
21126afe12f5SStefano Zampini         for (i=0,r=0;i<nb;i++) {
21136afe12f5SStefano Zampini           if (blocks[i] != xadj[r+1] - xadj[r]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid block sizes prescribed for block %D: expected %D, got %D",i,blocks[i],xadj[r+1] - xadj[r]);
21146afe12f5SStefano Zampini           ierr = MatSetValuesLocal(MT,blocks[i],adjncy+xadj[r],blocks[i],adjncy+xadj[r],array+xadj[r],ADD_VALUES);CHKERRQ(ierr);
21156afe12f5SStefano Zampini           r   += blocks[i];
21166afe12f5SStefano Zampini         }
21176afe12f5SStefano Zampini       } else {
2118686e3a49SStefano Zampini         for (i=0;i<nvtxs;i++) {
2119487b449aSStefano Zampini           ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
2120686e3a49SStefano Zampini         }
21216afe12f5SStefano Zampini       }
21226afe12f5SStefano Zampini     } else {
21236afe12f5SStefano Zampini       for (i=0;i<nvtxs;i++) {
21246afe12f5SStefano Zampini         ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
21256afe12f5SStefano Zampini       }
21266afe12f5SStefano Zampini     }
2127d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2128938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
2129d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
2130686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
2131ecf5a873SStefano Zampini     PetscInt i;
2132c0962df8SStefano Zampini 
2133686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
2134686e3a49SStefano Zampini       PetscInt       j;
2135ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
2136686e3a49SStefano Zampini 
2137ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
2138487b449aSStefano Zampini       ierr = MatSetValuesLocal(MT,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
2139ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
2140686e3a49SStefano Zampini     }
2141b7ce53b6SStefano Zampini   }
2142487b449aSStefano Zampini   ierr = MatAssemblyBegin(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2143d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
2144487b449aSStefano Zampini   ierr = MatAssemblyEnd(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2145b9ed4604SStefano Zampini   if (isseqdense) {
2146487b449aSStefano Zampini     ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
2147487b449aSStefano Zampini   }
2148487b449aSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
2149487b449aSStefano Zampini     ierr = MatHeaderReplace(mat,&MT);CHKERRQ(ierr);
2150487b449aSStefano Zampini   } else if (reuse == MAT_INITIAL_MATRIX) {
2151487b449aSStefano Zampini     *M = MT;
2152b7ce53b6SStefano Zampini   }
2153b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
2154b7ce53b6SStefano Zampini }
2155b7ce53b6SStefano Zampini 
2156b7ce53b6SStefano Zampini /*@
2157b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
2158b7ce53b6SStefano Zampini 
2159b7ce53b6SStefano Zampini   Input Parameter:
2160*a2b725a8SWilliam Gropp +  mat - the matrix (should be of type MATIS)
2161*a2b725a8SWilliam Gropp -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
2162b7ce53b6SStefano Zampini 
2163b7ce53b6SStefano Zampini   Output Parameter:
2164b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
2165b7ce53b6SStefano Zampini 
2166b7ce53b6SStefano Zampini   Level: developer
2167b7ce53b6SStefano Zampini 
216895452b02SPatrick Sanan   Notes:
2169487b449aSStefano Zampini     This function has been deprecated and it will be removed in future releases. Update your code to use the MatConvert() interface.
2170b7ce53b6SStefano Zampini 
2171487b449aSStefano Zampini .seealso: MATIS, MatConvert()
2172b7ce53b6SStefano Zampini @*/
2173b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
2174b7ce53b6SStefano Zampini {
2175b7ce53b6SStefano Zampini   PetscErrorCode ierr;
2176b7ce53b6SStefano Zampini 
2177b7ce53b6SStefano Zampini   PetscFunctionBegin;
2178b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2179b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
2180b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
2181487b449aSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
2182b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
2183b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
21846c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
2185b7ce53b6SStefano Zampini   }
2186487b449aSStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatType,MatReuse,Mat*),(mat,MATAIJ,reuse,newmat));CHKERRQ(ierr);
2187b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
2188b7ce53b6SStefano Zampini }
2189b7ce53b6SStefano Zampini 
2190ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
2191ad6194a2SStefano Zampini {
2192ad6194a2SStefano Zampini   PetscErrorCode ierr;
2193ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
2194c9225affSStefano Zampini   PetscInt       rbs,cbs,m,n,M,N;
2195ad6194a2SStefano Zampini   Mat            B,localmat;
2196ad6194a2SStefano Zampini 
2197ad6194a2SStefano Zampini   PetscFunctionBegin;
2198c9225affSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
2199c9225affSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
2200ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
2201ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
22028546b261SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)mat),&B);CHKERRQ(ierr);
22038546b261SStefano Zampini   ierr = MatSetSizes(B,m,n,M,N);CHKERRQ(ierr);
22048546b261SStefano Zampini   ierr = MatSetBlockSize(B,rbs == cbs ? rbs : 1);CHKERRQ(ierr);
22058546b261SStefano Zampini   ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
22068546b261SStefano Zampini   ierr = MatISSetLocalMatType(B,matis->lmattype);CHKERRQ(ierr);
22078546b261SStefano Zampini   ierr = MatSetLocalToGlobalMapping(B,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
2208ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
2209ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
2210b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
2211ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2212ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2213ad6194a2SStefano Zampini   *newmat = B;
2214ad6194a2SStefano Zampini   PetscFunctionReturn(0);
2215ad6194a2SStefano Zampini }
2216ad6194a2SStefano Zampini 
2217a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
221869796d55SStefano Zampini {
221969796d55SStefano Zampini   PetscErrorCode ierr;
222069796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
222169796d55SStefano Zampini   PetscBool      local_sym;
222269796d55SStefano Zampini 
222369796d55SStefano Zampini   PetscFunctionBegin;
222469796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
2225b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
222669796d55SStefano Zampini   PetscFunctionReturn(0);
222769796d55SStefano Zampini }
222869796d55SStefano Zampini 
2229a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
223069796d55SStefano Zampini {
223169796d55SStefano Zampini   PetscErrorCode ierr;
223269796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
223369796d55SStefano Zampini   PetscBool      local_sym;
223469796d55SStefano Zampini 
223569796d55SStefano Zampini   PetscFunctionBegin;
223669796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
2237b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
223869796d55SStefano Zampini   PetscFunctionReturn(0);
223969796d55SStefano Zampini }
224069796d55SStefano Zampini 
224145471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
224245471136SStefano Zampini {
224345471136SStefano Zampini   PetscErrorCode ierr;
224445471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
224545471136SStefano Zampini   PetscBool      local_sym;
224645471136SStefano Zampini 
224745471136SStefano Zampini   PetscFunctionBegin;
224845471136SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
224945471136SStefano Zampini     *flg = PETSC_FALSE;
225045471136SStefano Zampini     PetscFunctionReturn(0);
225145471136SStefano Zampini   }
225245471136SStefano Zampini   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
225345471136SStefano Zampini   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
225445471136SStefano Zampini   PetscFunctionReturn(0);
225545471136SStefano Zampini }
225645471136SStefano Zampini 
2257a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
2258b4319ba4SBarry Smith {
2259dfbe8321SBarry Smith   PetscErrorCode ierr;
2260b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
2261b4319ba4SBarry Smith 
2262b4319ba4SBarry Smith   PetscFunctionBegin;
2263b89f26deSStefano Zampini   ierr = PetscFree(b->bdiag);CHKERRQ(ierr);
22648546b261SStefano Zampini   ierr = PetscFree(b->lmattype);CHKERRQ(ierr);
22656bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
2266e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
2267e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
22686bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
22696bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
22703fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
2271a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
2272a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
2273a8116848SStefano Zampini   if (b->sf != b->csf) {
2274a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
2275a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
2276f03112d0SStefano Zampini   } else b->csf = NULL;
227728f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
227828f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
2279bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
2280dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
22818546b261SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",NULL);CHKERRQ(ierr);
2282bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
2283b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
2284b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
22852e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
228675d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",NULL);CHKERRQ(ierr);
2287f03112d0SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",NULL);CHKERRQ(ierr);
2288487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",NULL);CHKERRQ(ierr);
2289487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",NULL);CHKERRQ(ierr);
2290487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",NULL);CHKERRQ(ierr);
2291487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",NULL);CHKERRQ(ierr);
2292487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",NULL);CHKERRQ(ierr);
2293487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",NULL);CHKERRQ(ierr);
2294487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",NULL);CHKERRQ(ierr);
2295b4319ba4SBarry Smith   PetscFunctionReturn(0);
2296b4319ba4SBarry Smith }
2297b4319ba4SBarry Smith 
2298a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
2299b4319ba4SBarry Smith {
2300dfbe8321SBarry Smith   PetscErrorCode ierr;
2301b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
2302b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
2303b4319ba4SBarry Smith 
2304b4319ba4SBarry Smith   PetscFunctionBegin;
2305b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
2306e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2307e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2308b4319ba4SBarry Smith 
2309b4319ba4SBarry Smith   /* multiply the local matrix */
2310b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
2311b4319ba4SBarry Smith 
2312b4319ba4SBarry Smith   /* scatter product back into global memory */
23132dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
2314e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2315e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2316b4319ba4SBarry Smith   PetscFunctionReturn(0);
2317b4319ba4SBarry Smith }
2318b4319ba4SBarry Smith 
2319a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
23202e74eeadSLisandro Dalcin {
2321650997f4SStefano Zampini   Vec            temp_vec;
23222e74eeadSLisandro Dalcin   PetscErrorCode ierr;
23232e74eeadSLisandro Dalcin 
23242e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
2325650997f4SStefano Zampini   if (v3 != v2) {
2326650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
2327650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
2328650997f4SStefano Zampini   } else {
2329650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
2330650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
2331650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
2332650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
2333650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
2334650997f4SStefano Zampini   }
23352e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
23362e74eeadSLisandro Dalcin }
23372e74eeadSLisandro Dalcin 
2338a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
23392e74eeadSLisandro Dalcin {
23402e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
23412e74eeadSLisandro Dalcin   PetscErrorCode ierr;
23422e74eeadSLisandro Dalcin 
2343e176bc59SStefano Zampini   PetscFunctionBegin;
23442e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
2345e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2346e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23472e74eeadSLisandro Dalcin 
23482e74eeadSLisandro Dalcin   /* multiply the local matrix */
2349e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
23502e74eeadSLisandro Dalcin 
23512e74eeadSLisandro Dalcin   /* scatter product back into global vector */
2352e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
2353e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2354e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23552e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
23562e74eeadSLisandro Dalcin }
23572e74eeadSLisandro Dalcin 
2358a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
23592e74eeadSLisandro Dalcin {
2360650997f4SStefano Zampini   Vec            temp_vec;
23612e74eeadSLisandro Dalcin   PetscErrorCode ierr;
23622e74eeadSLisandro Dalcin 
23632e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
2364650997f4SStefano Zampini   if (v3 != v2) {
2365650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
2366650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
2367650997f4SStefano Zampini   } else {
2368650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
2369650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
2370650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
2371650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
2372650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
2373650997f4SStefano Zampini   }
23742e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
23752e74eeadSLisandro Dalcin }
23762e74eeadSLisandro Dalcin 
2377a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
2378b4319ba4SBarry Smith {
2379b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
2380dfbe8321SBarry Smith   PetscErrorCode ierr;
2381b4319ba4SBarry Smith   PetscViewer    sviewer;
2382ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
2383b4319ba4SBarry Smith 
2384b4319ba4SBarry Smith   PetscFunctionBegin;
2385ee2491ecSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
2386ee2491ecSStefano Zampini   if (isascii)  {
2387ee2491ecSStefano Zampini     PetscViewerFormat format;
2388ee2491ecSStefano Zampini 
2389ee2491ecSStefano Zampini     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
2390ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
2391ee2491ecSStefano Zampini   }
2392ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
23933f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
2394b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
23953f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
23966e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2397b4319ba4SBarry Smith   PetscFunctionReturn(0);
2398b4319ba4SBarry Smith }
2399b4319ba4SBarry Smith 
2400b89f26deSStefano Zampini static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat,const PetscScalar **values)
2401b89f26deSStefano Zampini {
2402b89f26deSStefano Zampini   Mat_IS            *is = (Mat_IS*)mat->data;
2403b89f26deSStefano Zampini   MPI_Datatype      nodeType;
2404b89f26deSStefano Zampini   const PetscScalar *lv;
2405b89f26deSStefano Zampini   PetscInt          bs;
2406b89f26deSStefano Zampini   PetscErrorCode    ierr;
2407b89f26deSStefano Zampini 
2408b89f26deSStefano Zampini   PetscFunctionBegin;
2409b89f26deSStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
2410b89f26deSStefano Zampini   ierr = MatSetBlockSize(is->A,bs);CHKERRQ(ierr);
2411b89f26deSStefano Zampini   ierr = MatInvertBlockDiagonal(is->A,&lv);CHKERRQ(ierr);
2412b89f26deSStefano Zampini   if (!is->bdiag) {
2413b89f26deSStefano Zampini     ierr = PetscMalloc1(bs*mat->rmap->n,&is->bdiag);CHKERRQ(ierr);
2414b89f26deSStefano Zampini   }
2415b89f26deSStefano Zampini   ierr = MPI_Type_contiguous(bs,MPIU_SCALAR,&nodeType);CHKERRQ(ierr);
2416b89f26deSStefano Zampini   ierr = MPI_Type_commit(&nodeType);CHKERRQ(ierr);
2417b89f26deSStefano Zampini   ierr = PetscSFReduceBegin(is->sf,nodeType,lv,is->bdiag,MPIU_REPLACE);CHKERRQ(ierr);
2418b89f26deSStefano Zampini   ierr = PetscSFReduceEnd(is->sf,nodeType,lv,is->bdiag,MPIU_REPLACE);CHKERRQ(ierr);
2419b89f26deSStefano Zampini   ierr = MPI_Type_free(&nodeType);CHKERRQ(ierr);
2420b89f26deSStefano Zampini   if (values) *values = is->bdiag;
2421b89f26deSStefano Zampini   PetscFunctionReturn(0);
2422b89f26deSStefano Zampini }
2423b89f26deSStefano Zampini 
24248546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat A)
2425b4319ba4SBarry Smith {
2426e176bc59SStefano Zampini   Vec            cglobal,rglobal;
24278546b261SStefano Zampini   IS             from;
24288546b261SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
2429b89f26deSStefano Zampini   PetscScalar    sum;
24308546b261SStefano Zampini   const PetscInt *garray;
24318546b261SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
24328546b261SStefano Zampini   PetscBool      iscuda;
24338546b261SStefano Zampini   PetscErrorCode ierr;
2434b4319ba4SBarry Smith 
2435b4319ba4SBarry Smith   PetscFunctionBegin;
24368546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nr);CHKERRQ(ierr);
24378546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(A->rmap->mapping,&rbs);CHKERRQ(ierr);
24388546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&nc);CHKERRQ(ierr);
24398546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(A->cmap->mapping,&cbs);CHKERRQ(ierr);
244070cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
244170cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
24423fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
2443e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
2444e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
24458546b261SStefano Zampini   ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
24468546b261SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)is->y,VECSEQCUDA,&iscuda);CHKERRQ(ierr);
24478546b261SStefano Zampini   if (iscuda) {
24488546b261SStefano Zampini     ierr = PetscFree(A->defaultvectype);CHKERRQ(ierr);
24498546b261SStefano Zampini     ierr = PetscStrallocpy(VECCUDA,&A->defaultvectype);CHKERRQ(ierr);
24508546b261SStefano Zampini   }
24518546b261SStefano Zampini   ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
24528546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockIndices(A->rmap->mapping,&garray);CHKERRQ(ierr);
24538546b261SStefano Zampini   ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),rbs,nr/rbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
24549448b7f1SJunchao Zhang   ierr = VecScatterCreate(rglobal,from,is->y,NULL,&is->rctx);CHKERRQ(ierr);
24558546b261SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreBlockIndices(A->rmap->mapping,&garray);CHKERRQ(ierr);
24568546b261SStefano Zampini   ierr = ISDestroy(&from);CHKERRQ(ierr);
24578546b261SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
24588546b261SStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(A->cmap->mapping,&garray);CHKERRQ(ierr);
24598546b261SStefano Zampini     ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),cbs,nc/cbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
24609448b7f1SJunchao Zhang     ierr = VecScatterCreate(cglobal,from,is->x,NULL,&is->cctx);CHKERRQ(ierr);
24618546b261SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(A->cmap->mapping,&garray);CHKERRQ(ierr);
24628546b261SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
24638546b261SStefano Zampini   } else {
24648546b261SStefano Zampini     ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
24658546b261SStefano Zampini     is->cctx = is->rctx;
24668546b261SStefano Zampini   }
2467b89f26deSStefano Zampini   ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
2468b89f26deSStefano Zampini 
24698546b261SStefano Zampini   /* interface counter vector (local) */
24708546b261SStefano Zampini   ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
24718546b261SStefano Zampini   ierr = VecSet(is->y,1.);CHKERRQ(ierr);
24728546b261SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24738546b261SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24748546b261SStefano Zampini   ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
24758546b261SStefano Zampini   ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2476b89f26deSStefano Zampini 
2477b89f26deSStefano Zampini   /* special functions for block-diagonal matrices */
2478b89f26deSStefano Zampini   ierr = VecSum(rglobal,&sum);CHKERRQ(ierr);
2479b89f26deSStefano Zampini   if ((PetscInt)(PetscRealPart(sum)) == A->rmap->N && A->rmap->N == A->cmap->N && A->rmap->mapping == A->cmap->mapping) {
2480b89f26deSStefano Zampini     A->ops->invertblockdiagonal = MatInvertBlockDiagonal_IS;
2481b89f26deSStefano Zampini   } else {
2482b89f26deSStefano Zampini     A->ops->invertblockdiagonal = NULL;
2483b89f26deSStefano Zampini   }
24848546b261SStefano Zampini   ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
2485b0cc1f67SStefano Zampini 
2486b0cc1f67SStefano Zampini   /* setup SF for general purpose shared indices based communications */
2487b0cc1f67SStefano Zampini   ierr = MatISSetUpSF_IS(A);CHKERRQ(ierr);
24888546b261SStefano Zampini   PetscFunctionReturn(0);
24898546b261SStefano Zampini }
24908546b261SStefano Zampini 
24918546b261SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
24928546b261SStefano Zampini {
24938546b261SStefano Zampini   PetscErrorCode ierr;
24948546b261SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
24958546b261SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
24968546b261SStefano Zampini 
24978546b261SStefano Zampini   PetscFunctionBegin;
24988546b261SStefano Zampini   PetscCheckSameComm(A,1,rmapping,2);
24998546b261SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
25001c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
2501872cf891SStefano Zampini   if (is->csf != is->sf) {
2502872cf891SStefano Zampini     ierr = PetscSFDestroy(&is->csf);CHKERRQ(ierr);
2503872cf891SStefano Zampini     ierr = PetscFree2(is->csf_rootdata,is->csf_leafdata);CHKERRQ(ierr);
2504f03112d0SStefano Zampini   } else is->csf = NULL;
250528f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
250628f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
2507b89f26deSStefano Zampini   ierr = PetscFree(is->bdiag);CHKERRQ(ierr);
25083bbff08aSStefano Zampini 
25093bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
2510fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
2511fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
2512e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
2513e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
2514e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
2515e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
25166625354bSStefano Zampini   /* check if the two mappings are actually the same for square matrices (DOLFIN passes 2 different objects) */
25176625354bSStefano Zampini   if (rmapping != cmapping && A->rmap->N == A->cmap->N) {
25186625354bSStefano Zampini     PetscBool same,gsame;
25196625354bSStefano Zampini 
25206625354bSStefano Zampini     same = PETSC_FALSE;
25216625354bSStefano Zampini     if (nr == nc && cbs == rbs) {
25226625354bSStefano Zampini       const PetscInt *idxs1,*idxs2;
25236625354bSStefano Zampini 
25246625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
25256625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
25266625354bSStefano Zampini       ierr = PetscMemcmp(idxs1,idxs2,(nr/rbs)*sizeof(PetscInt),&same);CHKERRQ(ierr);
25276625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
25286625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
25296625354bSStefano Zampini     }
25306625354bSStefano Zampini     ierr = MPIU_Allreduce(&same,&gsame,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
25316625354bSStefano Zampini     if (gsame) cmapping = rmapping;
25326625354bSStefano Zampini   }
253353b44cf5SStefano Zampini   ierr = PetscLayoutSetBlockSize(A->rmap,rbs);CHKERRQ(ierr);
253453b44cf5SStefano Zampini   ierr = PetscLayoutSetBlockSize(A->cmap,cbs);CHKERRQ(ierr);
25356625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
25366625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
25376625354bSStefano Zampini 
25386625354bSStefano Zampini   /* Create the local matrix A */
2539f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
25408546b261SStefano Zampini   ierr = MatSetType(is->A,is->lmattype);CHKERRQ(ierr);
2541e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
2542e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
25438546b261SStefano Zampini   ierr = MatSetOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
25448546b261SStefano Zampini   ierr = MatAppendOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
2545c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->rmap);CHKERRQ(ierr);
2546c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->cmap);CHKERRQ(ierr);
2547b4319ba4SBarry Smith 
2548f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
25498546b261SStefano Zampini     ierr = MatISSetUpScatters_Private(A);CHKERRQ(ierr);
2550f26d0771SStefano Zampini   }
255148ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
2552b4319ba4SBarry Smith   PetscFunctionReturn(0);
2553b4319ba4SBarry Smith }
2554b4319ba4SBarry Smith 
2555a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
25562e74eeadSLisandro Dalcin {
25572e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
25582e74eeadSLisandro Dalcin   PetscErrorCode ierr;
255997563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
256097563a80SStefano Zampini   PetscInt       i,zm,zn;
256197563a80SStefano Zampini #endif
2562f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
25632e74eeadSLisandro Dalcin 
25642e74eeadSLisandro Dalcin   PetscFunctionBegin;
25652e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
2566f26d0771SStefano Zampini   if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n);
256797563a80SStefano Zampini   /* count negative indices */
256897563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
256997563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
25702e74eeadSLisandro Dalcin #endif
257197563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
257297563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
257397563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
257497563a80SStefano Zampini   /* count negative indices (should be the same as before) */
257597563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
257697563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
2577b4f971dfSStefano Zampini   if (!is->A->rmap->mapping && zm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS");
2578b4f971dfSStefano Zampini   if (!is->A->cmap->mapping && zn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS");
257997563a80SStefano Zampini #endif
25802e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
25812e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
25822e74eeadSLisandro Dalcin }
25832e74eeadSLisandro Dalcin 
2584a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
258597563a80SStefano Zampini {
258697563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
258797563a80SStefano Zampini   PetscErrorCode ierr;
258897563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
258997563a80SStefano Zampini   PetscInt       i,zm,zn;
259097563a80SStefano Zampini #endif
2591f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
259297563a80SStefano Zampini 
259397563a80SStefano Zampini   PetscFunctionBegin;
259497563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
2595f26d0771SStefano Zampini   if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column block indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n);
259697563a80SStefano Zampini   /* count negative indices */
259797563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
259897563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
259997563a80SStefano Zampini #endif
260097563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
260197563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
260297563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
260397563a80SStefano Zampini   /* count negative indices (should be the same as before) */
260497563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
260597563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
2606b4f971dfSStefano Zampini   if (!is->A->rmap->mapping && zm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS");
2607b4f971dfSStefano Zampini   if (!is->A->cmap->mapping && zn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS");
260897563a80SStefano Zampini #endif
2609d59cf9ebSStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
261097563a80SStefano Zampini   PetscFunctionReturn(0);
261197563a80SStefano Zampini }
261297563a80SStefano Zampini 
2613a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2614b4319ba4SBarry Smith {
2615dfbe8321SBarry Smith   PetscErrorCode ierr;
2616b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2617b4319ba4SBarry Smith 
2618b4319ba4SBarry Smith   PetscFunctionBegin;
2619b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
2620872cf891SStefano Zampini     ierr = MatSetValuesLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2621872cf891SStefano Zampini   } else {
2622b4319ba4SBarry Smith     ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2623872cf891SStefano Zampini   }
2624b4319ba4SBarry Smith   PetscFunctionReturn(0);
2625b4319ba4SBarry Smith }
2626b4319ba4SBarry Smith 
2627a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2628f0006bf2SLisandro Dalcin {
2629f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
2630f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
2631f0006bf2SLisandro Dalcin 
2632f0006bf2SLisandro Dalcin   PetscFunctionBegin;
2633b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
2634b4f971dfSStefano Zampini #if defined(PETSC_USE_DEBUG)
2635b4f971dfSStefano Zampini     PetscInt ibs,bs;
2636b4f971dfSStefano Zampini 
2637b4f971dfSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(is->A->rmap->mapping,&ibs);CHKERRQ(ierr);
2638b4f971dfSStefano Zampini     ierr = MatGetBlockSize(is->A,&bs);CHKERRQ(ierr);
2639b4f971dfSStefano Zampini     if (ibs != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Different block sizes! local mat %D, local l2g map %D",bs,ibs);
2640b4f971dfSStefano Zampini #endif
2641b4f971dfSStefano Zampini     ierr = MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2642b4f971dfSStefano Zampini   } else {
2643f0006bf2SLisandro Dalcin     ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2644b4f971dfSStefano Zampini   }
2645f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
2646f0006bf2SLisandro Dalcin }
2647f0006bf2SLisandro Dalcin 
2648f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
2649f0ae7da4SStefano Zampini {
2650f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
2651f0ae7da4SStefano Zampini   PetscErrorCode ierr;
2652f0ae7da4SStefano Zampini 
2653f0ae7da4SStefano Zampini   PetscFunctionBegin;
2654f0ae7da4SStefano Zampini   if (!n) {
2655f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
2656f0ae7da4SStefano Zampini   } else {
2657f0ae7da4SStefano Zampini     PetscInt i;
2658f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
2659f0ae7da4SStefano Zampini 
2660f0ae7da4SStefano Zampini     if (columns) {
2661f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
2662f0ae7da4SStefano Zampini     } else {
2663f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
2664f0ae7da4SStefano Zampini     }
2665f0ae7da4SStefano Zampini     if (diag != 0.) {
2666f0ae7da4SStefano Zampini       const PetscScalar *array;
2667f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
2668f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
2669f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
2670f0ae7da4SStefano Zampini       }
2671f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
2672f0ae7da4SStefano Zampini     }
2673f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2674f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2675f0ae7da4SStefano Zampini   }
2676f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2677f0ae7da4SStefano Zampini }
2678f0ae7da4SStefano Zampini 
2679f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
26802e74eeadSLisandro Dalcin {
26816e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
26826e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
26836e520ac8SStefano Zampini   PetscInt       *lrows;
26842e74eeadSLisandro Dalcin   PetscErrorCode ierr;
26852e74eeadSLisandro Dalcin 
26862e74eeadSLisandro Dalcin   PetscFunctionBegin;
2687f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
2688f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
2689f0ae7da4SStefano Zampini     PetscBool cong;
269026b0207aSStefano Zampini 
2691f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
269226b0207aSStefano Zampini     cong = (PetscBool)(cong && matis->sf == matis->csf);
2693268753edSStefano Zampini     if (!cong && columns) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Columns can be zeroed if and only if A->rmap and A->cmap are congruent and the l2g maps are the same for MATIS");
2694268753edSStefano Zampini     if (!cong && diag != 0.) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Nonzero diagonal value supported if and only if A->rmap and A->cmap are congruent and the l2g maps are the same for MATIS");
2695268753edSStefano Zampini     if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent, and the l2g maps be the same");
2696f0ae7da4SStefano Zampini   }
2697f0ae7da4SStefano Zampini #endif
26986e520ac8SStefano Zampini   /* get locally owned rows */
2699f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
27006e520ac8SStefano Zampini   /* fix right hand side if needed */
27016e520ac8SStefano Zampini   if (x && b) {
27026e520ac8SStefano Zampini     const PetscScalar *xx;
27036e520ac8SStefano Zampini     PetscScalar       *bb;
27046e520ac8SStefano Zampini 
27056e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
27066e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
27076e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
27086e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
27096e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
27102e74eeadSLisandro Dalcin   }
27116e520ac8SStefano Zampini   /* get rows associated to the local matrices */
27126e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
27136e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
27146e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
27156e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
27166e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
27176e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
27186e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
27196e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
27206e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
2721f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
27226e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
27232e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
27242e74eeadSLisandro Dalcin }
27252e74eeadSLisandro Dalcin 
2726f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2727b4319ba4SBarry Smith {
2728dfbe8321SBarry Smith   PetscErrorCode ierr;
2729b4319ba4SBarry Smith 
2730b4319ba4SBarry Smith   PetscFunctionBegin;
2731f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
2732f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2733f0ae7da4SStefano Zampini }
27342205254eSKarl Rupp 
2735f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2736f0ae7da4SStefano Zampini {
2737f0ae7da4SStefano Zampini   PetscErrorCode ierr;
2738f0ae7da4SStefano Zampini 
2739f0ae7da4SStefano Zampini   PetscFunctionBegin;
2740f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
2741b4319ba4SBarry Smith   PetscFunctionReturn(0);
2742b4319ba4SBarry Smith }
2743b4319ba4SBarry Smith 
2744a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
2745b4319ba4SBarry Smith {
2746b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2747dfbe8321SBarry Smith   PetscErrorCode ierr;
2748b4319ba4SBarry Smith 
2749b4319ba4SBarry Smith   PetscFunctionBegin;
2750b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
2751b4319ba4SBarry Smith   PetscFunctionReturn(0);
2752b4319ba4SBarry Smith }
2753b4319ba4SBarry Smith 
2754a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
2755b4319ba4SBarry Smith {
2756b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2757dfbe8321SBarry Smith   PetscErrorCode ierr;
2758b4319ba4SBarry Smith 
2759b4319ba4SBarry Smith   PetscFunctionBegin;
2760b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
2761872cf891SStefano Zampini   /* fix for local empty rows/cols */
2762872cf891SStefano Zampini   if (is->locempty && type == MAT_FINAL_ASSEMBLY) {
2763872cf891SStefano Zampini     Mat                    newlA;
2764f03112d0SStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g;
2765f03112d0SStefano Zampini     IS                     nzr,nzc;
2766f03112d0SStefano Zampini     PetscInt               nr,nc,nnzr,nnzc;
2767f03112d0SStefano Zampini     PetscBool              lnewl2g,newl2g;
2768872cf891SStefano Zampini 
2769f03112d0SStefano Zampini     ierr = MatGetSize(is->A,&nr,&nc);CHKERRQ(ierr);
2770f03112d0SStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_FALSE,PETSC_SMALL,&nzr);CHKERRQ(ierr);
2771f03112d0SStefano Zampini     if (!nzr) {
2772f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&nzr);CHKERRQ(ierr);
2773872cf891SStefano Zampini     }
2774f03112d0SStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_TRUE,PETSC_SMALL,&nzc);CHKERRQ(ierr);
2775f03112d0SStefano Zampini     if (!nzc) {
2776f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&nzc);CHKERRQ(ierr);
2777872cf891SStefano Zampini     }
2778f03112d0SStefano Zampini     ierr = ISGetSize(nzr,&nnzr);CHKERRQ(ierr);
2779f03112d0SStefano Zampini     ierr = ISGetSize(nzc,&nnzc);CHKERRQ(ierr);
2780f03112d0SStefano Zampini     if (nnzr != nr || nnzc != nc) {
2781f03112d0SStefano Zampini       ISLocalToGlobalMapping l2g;
2782f03112d0SStefano Zampini       IS                     is1,is2;
2783f03112d0SStefano Zampini 
2784f03112d0SStefano Zampini       /* need new global l2g map */
2785f03112d0SStefano Zampini       lnewl2g = PETSC_TRUE;
2786f03112d0SStefano Zampini       ierr    = MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
2787f03112d0SStefano Zampini 
2788872cf891SStefano Zampini       /* extract valid submatrix */
2789f03112d0SStefano Zampini       ierr = MatCreateSubMatrix(is->A,nzr,nzc,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
2790f03112d0SStefano Zampini 
2791f03112d0SStefano Zampini       /* attach local l2g maps for successive calls of MatSetValues on the local matrix */
2792f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(nzr,&l2g);CHKERRQ(ierr);
2793f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&is1);CHKERRQ(ierr);
2794f03112d0SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_MASK,is1,&is2);CHKERRQ(ierr);
2795872cf891SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
279672ed36d8SStefano Zampini       if (is->A->rmap->mapping) { /* the matrix has a local-to-local map already attached (probably DMDA generated) */
279772ed36d8SStefano Zampini         const PetscInt *idxs1,*idxs2;
279872ed36d8SStefano Zampini         PetscInt       j,i,nl,*tidxs;
279972ed36d8SStefano Zampini 
280072ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(is->A->rmap->mapping,&nl);CHKERRQ(ierr);
280172ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(is->A->rmap->mapping,&idxs1);CHKERRQ(ierr);
280272ed36d8SStefano Zampini         ierr = PetscMalloc1(nl,&tidxs);CHKERRQ(ierr);
280372ed36d8SStefano Zampini         ierr = ISGetIndices(is2,&idxs2);CHKERRQ(ierr);
280472ed36d8SStefano Zampini         for (i=0,j=0;i<nl;i++) tidxs[i] = idxs1[i] < 0 ? -1 : idxs2[j++];
280572ed36d8SStefano Zampini         if (j != nr) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected count %D != %D",j,nr);
280672ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(is->A->rmap->mapping,&idxs1);CHKERRQ(ierr);
280772ed36d8SStefano Zampini         ierr = ISRestoreIndices(is2,&idxs2);CHKERRQ(ierr);
280872ed36d8SStefano Zampini         ierr = ISDestroy(&is2);CHKERRQ(ierr);
280972ed36d8SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A->rmap->mapping),nl,tidxs,PETSC_OWN_POINTER,&is2);CHKERRQ(ierr);
281072ed36d8SStefano Zampini       }
2811f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is2,&rl2g);CHKERRQ(ierr);
2812f03112d0SStefano Zampini       ierr = ISDestroy(&is1);CHKERRQ(ierr);
2813f03112d0SStefano Zampini       ierr = ISDestroy(&is2);CHKERRQ(ierr);
281472ed36d8SStefano Zampini 
2815f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(nzc,&l2g);CHKERRQ(ierr);
2816f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&is1);CHKERRQ(ierr);
2817f03112d0SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_MASK,is1,&is2);CHKERRQ(ierr);
2818f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
281972ed36d8SStefano Zampini       if (is->A->cmap->mapping) { /* the matrix has a local-to-local map already attached (probably DMDA generated) */
282072ed36d8SStefano Zampini         const PetscInt *idxs1,*idxs2;
282172ed36d8SStefano Zampini         PetscInt       j,i,nl,*tidxs;
282272ed36d8SStefano Zampini 
282372ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(is->A->cmap->mapping,&nl);CHKERRQ(ierr);
282472ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(is->A->cmap->mapping,&idxs1);CHKERRQ(ierr);
282572ed36d8SStefano Zampini         ierr = PetscMalloc1(nl,&tidxs);CHKERRQ(ierr);
282672ed36d8SStefano Zampini         ierr = ISGetIndices(is2,&idxs2);CHKERRQ(ierr);
282772ed36d8SStefano Zampini         for (i=0,j=0;i<nl;i++) tidxs[i] = idxs1[i] < 0 ? -1 : idxs2[j++];
282872ed36d8SStefano Zampini         if (j != nc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected count %D != %D",j,nc);
282972ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(is->A->cmap->mapping,&idxs1);CHKERRQ(ierr);
283072ed36d8SStefano Zampini         ierr = ISRestoreIndices(is2,&idxs2);CHKERRQ(ierr);
283172ed36d8SStefano Zampini         ierr = ISDestroy(&is2);CHKERRQ(ierr);
283272ed36d8SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A->cmap->mapping),nl,tidxs,PETSC_OWN_POINTER,&is2);CHKERRQ(ierr);
283372ed36d8SStefano Zampini       }
2834f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is2,&cl2g);CHKERRQ(ierr);
2835f03112d0SStefano Zampini       ierr = ISDestroy(&is1);CHKERRQ(ierr);
2836f03112d0SStefano Zampini       ierr = ISDestroy(&is2);CHKERRQ(ierr);
283772ed36d8SStefano Zampini 
2838f03112d0SStefano Zampini       ierr = MatSetLocalToGlobalMapping(newlA,rl2g,cl2g);CHKERRQ(ierr);
283972ed36d8SStefano Zampini 
2840f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2841f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2842f03112d0SStefano Zampini     } else { /* local matrix fully populated */
2843f03112d0SStefano Zampini       lnewl2g = PETSC_FALSE;
2844f03112d0SStefano Zampini       ierr    = MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
2845f03112d0SStefano Zampini       ierr    = PetscObjectReference((PetscObject)is->A);CHKERRQ(ierr);
2846f03112d0SStefano Zampini       newlA   = is->A;
2847f03112d0SStefano Zampini     }
2848f03112d0SStefano Zampini     /* attach new global l2g map if needed */
2849f03112d0SStefano Zampini     if (newl2g) {
2850f03112d0SStefano Zampini       IS             gnzr,gnzc;
2851f03112d0SStefano Zampini       const PetscInt *grid,*gcid;
2852f03112d0SStefano Zampini 
2853f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(A->rmap->mapping,nzr,&gnzr);CHKERRQ(ierr);
2854f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(A->cmap->mapping,nzc,&gnzc);CHKERRQ(ierr);
2855f03112d0SStefano Zampini       ierr = ISGetIndices(gnzr,&grid);CHKERRQ(ierr);
2856f03112d0SStefano Zampini       ierr = ISGetIndices(gnzc,&gcid);CHKERRQ(ierr);
2857f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nnzr,grid,PETSC_COPY_VALUES,&rl2g);CHKERRQ(ierr);
2858f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nnzc,gcid,PETSC_COPY_VALUES,&cl2g);CHKERRQ(ierr);
2859f03112d0SStefano Zampini       ierr = ISRestoreIndices(gnzr,&grid);CHKERRQ(ierr);
2860f03112d0SStefano Zampini       ierr = ISRestoreIndices(gnzc,&gcid);CHKERRQ(ierr);
2861f03112d0SStefano Zampini       ierr = ISDestroy(&gnzr);CHKERRQ(ierr);
2862f03112d0SStefano Zampini       ierr = ISDestroy(&gnzc);CHKERRQ(ierr);
2863f03112d0SStefano Zampini       ierr = MatSetLocalToGlobalMapping(A,rl2g,cl2g);CHKERRQ(ierr);
2864f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2865f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2866f03112d0SStefano Zampini     }
2867872cf891SStefano Zampini     ierr = MatISSetLocalMat(A,newlA);CHKERRQ(ierr);
2868872cf891SStefano Zampini     ierr = MatDestroy(&newlA);CHKERRQ(ierr);
2869f03112d0SStefano Zampini     ierr = ISDestroy(&nzr);CHKERRQ(ierr);
2870f03112d0SStefano Zampini     ierr = ISDestroy(&nzc);CHKERRQ(ierr);
2871872cf891SStefano Zampini     is->locempty = PETSC_FALSE;
2872f03112d0SStefano Zampini   }
2873b4319ba4SBarry Smith   PetscFunctionReturn(0);
2874b4319ba4SBarry Smith }
2875b4319ba4SBarry Smith 
2876a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
2877b4319ba4SBarry Smith {
2878b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
2879b4319ba4SBarry Smith 
2880b4319ba4SBarry Smith   PetscFunctionBegin;
2881b4319ba4SBarry Smith   *local = is->A;
2882b4319ba4SBarry Smith   PetscFunctionReturn(0);
2883b4319ba4SBarry Smith }
2884b4319ba4SBarry Smith 
28853b3b1effSJed Brown static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local)
28863b3b1effSJed Brown {
28873b3b1effSJed Brown   PetscFunctionBegin;
28883b3b1effSJed Brown   *local = NULL;
28893b3b1effSJed Brown   PetscFunctionReturn(0);
28903b3b1effSJed Brown }
28913b3b1effSJed Brown 
2892b4319ba4SBarry Smith /*@
2893b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
2894b4319ba4SBarry Smith 
2895b4319ba4SBarry Smith   Input Parameter:
2896b4319ba4SBarry Smith .  mat - the matrix
2897b4319ba4SBarry Smith 
2898b4319ba4SBarry Smith   Output Parameter:
2899eb82efa4SStefano Zampini .  local - the local matrix
2900b4319ba4SBarry Smith 
2901b4319ba4SBarry Smith   Level: advanced
2902b4319ba4SBarry Smith 
2903b4319ba4SBarry Smith   Notes:
2904b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
2905b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
2906b4319ba4SBarry Smith   of the MatSetValues() operation.
2907b4319ba4SBarry Smith 
29083b3b1effSJed Brown   Call MatISRestoreLocalMat() when finished with the local matrix.
290996a6f129SJed Brown 
2910b4319ba4SBarry Smith .seealso: MATIS
2911b4319ba4SBarry Smith @*/
29127087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
2913b4319ba4SBarry Smith {
29144ac538c5SBarry Smith   PetscErrorCode ierr;
2915b4319ba4SBarry Smith 
2916b4319ba4SBarry Smith   PetscFunctionBegin;
29170700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2918b4319ba4SBarry Smith   PetscValidPointer(local,2);
29194ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
2920b4319ba4SBarry Smith   PetscFunctionReturn(0);
2921b4319ba4SBarry Smith }
2922b4319ba4SBarry Smith 
29233b3b1effSJed Brown /*@
29243b3b1effSJed Brown     MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat()
29253b3b1effSJed Brown 
29263b3b1effSJed Brown   Input Parameter:
29273b3b1effSJed Brown .  mat - the matrix
29283b3b1effSJed Brown 
29293b3b1effSJed Brown   Output Parameter:
29303b3b1effSJed Brown .  local - the local matrix
29313b3b1effSJed Brown 
29323b3b1effSJed Brown   Level: advanced
29333b3b1effSJed Brown 
29343b3b1effSJed Brown .seealso: MATIS
29353b3b1effSJed Brown @*/
29363b3b1effSJed Brown PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local)
29373b3b1effSJed Brown {
29383b3b1effSJed Brown   PetscErrorCode ierr;
29393b3b1effSJed Brown 
29403b3b1effSJed Brown   PetscFunctionBegin;
29413b3b1effSJed Brown   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
29423b3b1effSJed Brown   PetscValidPointer(local,2);
29433b3b1effSJed Brown   ierr = PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
29443b3b1effSJed Brown   PetscFunctionReturn(0);
29453b3b1effSJed Brown }
29463b3b1effSJed Brown 
29478546b261SStefano Zampini static PetscErrorCode MatISSetLocalMatType_IS(Mat mat,MatType mtype)
29488546b261SStefano Zampini {
29498546b261SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
29508546b261SStefano Zampini   PetscErrorCode ierr;
29518546b261SStefano Zampini 
29528546b261SStefano Zampini   PetscFunctionBegin;
29538546b261SStefano Zampini   if (is->A) {
29548546b261SStefano Zampini     ierr = MatSetType(is->A,mtype);CHKERRQ(ierr);
29558546b261SStefano Zampini   }
29568546b261SStefano Zampini   ierr = PetscFree(is->lmattype);CHKERRQ(ierr);
29578546b261SStefano Zampini   ierr = PetscStrallocpy(mtype,&is->lmattype);CHKERRQ(ierr);
29588546b261SStefano Zampini   PetscFunctionReturn(0);
29598546b261SStefano Zampini }
29608546b261SStefano Zampini 
29618546b261SStefano Zampini /*@
29628546b261SStefano Zampini     MatISSetLocalMatType - Specifies the type of local matrix
29638546b261SStefano Zampini 
29648546b261SStefano Zampini   Input Parameter:
2965*a2b725a8SWilliam Gropp +  mat - the matrix
2966*a2b725a8SWilliam Gropp -  mtype - the local matrix type
29678546b261SStefano Zampini 
29688546b261SStefano Zampini   Output Parameter:
29698546b261SStefano Zampini 
29708546b261SStefano Zampini   Level: advanced
29718546b261SStefano Zampini 
29728546b261SStefano Zampini .seealso: MATIS, MatSetType(), MatType
29738546b261SStefano Zampini @*/
29748546b261SStefano Zampini PetscErrorCode MatISSetLocalMatType(Mat mat,MatType mtype)
29758546b261SStefano Zampini {
29768546b261SStefano Zampini   PetscErrorCode ierr;
29778546b261SStefano Zampini 
29788546b261SStefano Zampini   PetscFunctionBegin;
29798546b261SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
29808546b261SStefano Zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMatType_C",(Mat,MatType),(mat,mtype));CHKERRQ(ierr);
29818546b261SStefano Zampini   PetscFunctionReturn(0);
29828546b261SStefano Zampini }
29838546b261SStefano Zampini 
2984a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
29853b03a366Sstefano_zampini {
29863b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
29873b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
29883b03a366Sstefano_zampini   PetscErrorCode ierr;
29898546b261SStefano Zampini   MatType        mtype,otype;
29908546b261SStefano Zampini   PetscBool      sametype = PETSC_TRUE;
29913b03a366Sstefano_zampini 
29923b03a366Sstefano_zampini   PetscFunctionBegin;
29934e4c7dbeSStefano Zampini   if (is->A) {
29943b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
29953b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
2996f0ae7da4SStefano Zampini     if (orows != nrows || ocols != ncols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local MATIS matrix should be of size %Dx%D (you passed a %Dx%D matrix)",orows,ocols,nrows,ncols);
29978546b261SStefano Zampini     ierr = MatGetType(local,&mtype);CHKERRQ(ierr);
29988546b261SStefano Zampini     ierr = MatGetType(is->A,&otype);CHKERRQ(ierr);
29998546b261SStefano Zampini     ierr = PetscStrcmp(mtype,otype,&sametype);CHKERRQ(ierr);
30004e4c7dbeSStefano Zampini   }
30013b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
30023b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
30033b03a366Sstefano_zampini   is->A = local;
30048546b261SStefano Zampini   ierr  = MatGetType(is->A,&mtype);CHKERRQ(ierr);
30058546b261SStefano Zampini   ierr  = MatISSetLocalMatType(mat,mtype);CHKERRQ(ierr);
30068546b261SStefano Zampini   if (!sametype && !is->islocalref) {
30078546b261SStefano Zampini     ierr = MatISSetUpScatters_Private(mat);CHKERRQ(ierr);
30088546b261SStefano Zampini   }
30093b03a366Sstefano_zampini   PetscFunctionReturn(0);
30103b03a366Sstefano_zampini }
30113b03a366Sstefano_zampini 
30123b03a366Sstefano_zampini /*@
3013eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
30143b03a366Sstefano_zampini 
30158546b261SStefano Zampini   Collective on Mat
30168546b261SStefano Zampini 
30173b03a366Sstefano_zampini   Input Parameter:
3018*a2b725a8SWilliam Gropp +  mat - the matrix
3019*a2b725a8SWilliam Gropp -  local - the local matrix
30203b03a366Sstefano_zampini 
30213b03a366Sstefano_zampini   Output Parameter:
30223b03a366Sstefano_zampini 
30233b03a366Sstefano_zampini   Level: advanced
30243b03a366Sstefano_zampini 
30253b03a366Sstefano_zampini   Notes:
30263b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
30273b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
30283b03a366Sstefano_zampini 
30293b03a366Sstefano_zampini .seealso: MATIS
30303b03a366Sstefano_zampini @*/
30313b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
30323b03a366Sstefano_zampini {
30333b03a366Sstefano_zampini   PetscErrorCode ierr;
30343b03a366Sstefano_zampini 
30353b03a366Sstefano_zampini   PetscFunctionBegin;
30363b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3037b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
30383b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
30393b03a366Sstefano_zampini   PetscFunctionReturn(0);
30403b03a366Sstefano_zampini }
30413b03a366Sstefano_zampini 
3042a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
30436726f965SBarry Smith {
30446726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
30456726f965SBarry Smith   PetscErrorCode ierr;
30466726f965SBarry Smith 
30476726f965SBarry Smith   PetscFunctionBegin;
30486726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
30496726f965SBarry Smith   PetscFunctionReturn(0);
30506726f965SBarry Smith }
30516726f965SBarry Smith 
3052a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
30532e74eeadSLisandro Dalcin {
30542e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
30552e74eeadSLisandro Dalcin   PetscErrorCode ierr;
30562e74eeadSLisandro Dalcin 
30572e74eeadSLisandro Dalcin   PetscFunctionBegin;
30582e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
30592e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
30602e74eeadSLisandro Dalcin }
30612e74eeadSLisandro Dalcin 
3062a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
30632e74eeadSLisandro Dalcin {
30642e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
30652e74eeadSLisandro Dalcin   PetscErrorCode ierr;
30662e74eeadSLisandro Dalcin 
30672e74eeadSLisandro Dalcin   PetscFunctionBegin;
30682e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
3069e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
30702e74eeadSLisandro Dalcin 
30712e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
30722e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
3073e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3074e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
30752e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
30762e74eeadSLisandro Dalcin }
30772e74eeadSLisandro Dalcin 
3078a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
30796726f965SBarry Smith {
30806726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
30816726f965SBarry Smith   PetscErrorCode ierr;
30826726f965SBarry Smith 
30836726f965SBarry Smith   PetscFunctionBegin;
30844e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
30856726f965SBarry Smith   PetscFunctionReturn(0);
30866726f965SBarry Smith }
30876726f965SBarry Smith 
3088f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
3089f26d0771SStefano Zampini {
3090f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
3091f26d0771SStefano Zampini   Mat_IS         *x;
3092f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3093f26d0771SStefano Zampini   PetscBool      ismatis;
3094f26d0771SStefano Zampini #endif
3095f26d0771SStefano Zampini   PetscErrorCode ierr;
3096f26d0771SStefano Zampini 
3097f26d0771SStefano Zampini   PetscFunctionBegin;
3098f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3099f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
3100f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
3101f26d0771SStefano Zampini #endif
3102f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
3103f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
3104f26d0771SStefano Zampini   PetscFunctionReturn(0);
3105f26d0771SStefano Zampini }
3106f26d0771SStefano Zampini 
3107f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
3108f26d0771SStefano Zampini {
3109f26d0771SStefano Zampini   Mat                    lA;
3110f26d0771SStefano Zampini   Mat_IS                 *matis;
3111f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
3112f26d0771SStefano Zampini   IS                     is;
3113f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
3114f26d0771SStefano Zampini   PetscInt               nrg;
3115f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
3116f26d0771SStefano Zampini   PetscErrorCode         ierr;
3117f26d0771SStefano Zampini 
3118f26d0771SStefano Zampini   PetscFunctionBegin;
3119f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
3120f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
3121f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
3122f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
3123f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3124249c8a71SStefano Zampini   for (i=0;i<nrl;i++) if (rl[i]>=nrg) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row index %D -> %D greater then maximum possible %D",i,rl[i],nrg);
3125f26d0771SStefano Zampini #endif
3126f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
3127f26d0771SStefano Zampini   /* map from [0,nrl) to row */
3128f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
3129f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
3130f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
3131f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
3132f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
3133f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
3134f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
3135f26d0771SStefano Zampini   /* compute new l2g map for columns */
3136f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
3137f26d0771SStefano Zampini     const PetscInt *cg,*cl;
3138f26d0771SStefano Zampini     PetscInt       ncg;
3139f26d0771SStefano Zampini     PetscInt       ncl;
3140f26d0771SStefano Zampini 
3141f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
3142f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
3143f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
3144f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
3145f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3146249c8a71SStefano Zampini     for (i=0;i<ncl;i++) if (cl[i]>=ncg) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local column index %D -> %D greater then maximum possible %D",i,cl[i],ncg);
3147f26d0771SStefano Zampini #endif
3148f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
3149f26d0771SStefano Zampini     /* map from [0,ncl) to col */
3150f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
3151f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
3152f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
3153f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
3154f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
3155f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
3156f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
3157f26d0771SStefano Zampini   } else {
3158f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
3159f26d0771SStefano Zampini     cl2g = rl2g;
3160f26d0771SStefano Zampini   }
3161f26d0771SStefano Zampini   /* create the MATIS submatrix */
3162f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
3163f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
3164f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
3165f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
3166b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
3167f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
3168f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
3169f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
3170f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
3171f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
3172f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3173f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3174f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3175f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3176f26d0771SStefano Zampini   /* remove unsupported ops */
3177f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
3178f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
3179f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
3180f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
3181f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
3182f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
3183f26d0771SStefano Zampini   PetscFunctionReturn(0);
3184f26d0771SStefano Zampini }
3185f26d0771SStefano Zampini 
3186872cf891SStefano Zampini static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A)
3187872cf891SStefano Zampini {
3188872cf891SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
31898546b261SStefano Zampini   char           type[256];
31908546b261SStefano Zampini   PetscBool      flg;
3191872cf891SStefano Zampini   PetscErrorCode ierr;
3192872cf891SStefano Zampini 
3193872cf891SStefano Zampini   PetscFunctionBegin;
3194872cf891SStefano Zampini   ierr = PetscOptionsHead(PetscOptionsObject,"MATIS options");CHKERRQ(ierr);
3195f03112d0SStefano Zampini   ierr = PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns","MatISFixLocalEmpty",a->locempty,&a->locempty,NULL);CHKERRQ(ierr);
319675d48cdbSStefano Zampini   ierr = PetscOptionsBool("-matis_storel2l","Store local-to-local matrices generated from PtAP operations","MatISStoreL2L",a->storel2l,&a->storel2l,NULL);CHKERRQ(ierr);
31978546b261SStefano Zampini   ierr = PetscOptionsFList("-matis_localmat_type","Matrix type","MatISSetLocalMatType",MatList,a->lmattype,type,256,&flg);CHKERRQ(ierr);
31988546b261SStefano Zampini   if (flg) {
31998546b261SStefano Zampini     ierr = MatISSetLocalMatType(A,type);CHKERRQ(ierr);
32008546b261SStefano Zampini   }
32018546b261SStefano Zampini   if (a->A) {
32028546b261SStefano Zampini     ierr = MatSetFromOptions(a->A);CHKERRQ(ierr);
32038546b261SStefano Zampini   }
32040af67c1bSStefano Zampini   ierr = PetscOptionsTail();CHKERRQ(ierr);
3205872cf891SStefano Zampini   PetscFunctionReturn(0);
3206872cf891SStefano Zampini }
3207872cf891SStefano Zampini 
3208284134d9SBarry Smith /*@
32093c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
3210284134d9SBarry Smith        process but not across processes.
3211284134d9SBarry Smith 
3212284134d9SBarry Smith    Input Parameters:
3213284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
3214e176bc59SStefano Zampini .     bs      - block size of the matrix
3215df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
3216e176bc59SStefano Zampini .     rmap    - local to global map for rows
3217e176bc59SStefano Zampini -     cmap    - local to global map for cols
3218284134d9SBarry Smith 
3219284134d9SBarry Smith    Output Parameter:
3220284134d9SBarry Smith .    A - the resulting matrix
3221284134d9SBarry Smith 
32228e6c10adSSatish Balay    Level: advanced
32238e6c10adSSatish Balay 
322495452b02SPatrick Sanan    Notes:
322595452b02SPatrick Sanan     See MATIS for more details.
32266fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
32276fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
32283c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
3229284134d9SBarry Smith 
3230284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
3231284134d9SBarry Smith @*/
3232e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
3233284134d9SBarry Smith {
3234284134d9SBarry Smith   PetscErrorCode ierr;
3235284134d9SBarry Smith 
3236284134d9SBarry Smith   PetscFunctionBegin;
32376fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
3238284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
3239284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
32406fdf41d1SStefano Zampini   if (bs > 0) {
3241284134d9SBarry Smith     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
32426fdf41d1SStefano Zampini   }
3243284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
3244e176bc59SStefano Zampini   if (rmap && cmap) {
3245e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
3246e176bc59SStefano Zampini   } else if (!rmap) {
3247e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
3248e176bc59SStefano Zampini   } else {
3249e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
3250e176bc59SStefano Zampini   }
3251284134d9SBarry Smith   PetscFunctionReturn(0);
3252284134d9SBarry Smith }
3253284134d9SBarry Smith 
3254b4319ba4SBarry Smith /*MC
3255f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
3256b89f26deSStefano Zampini    This stores the matrices in globally unassembled form. Each processor assembles only its local Neumann problem and the parallel matrix vector
3257b4319ba4SBarry Smith    product is handled "implicitly".
3258b4319ba4SBarry Smith 
3259b4319ba4SBarry Smith    Options Database Keys:
326075d48cdbSStefano Zampini + -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
326175d48cdbSStefano Zampini . -matis_fixempty - Fixes local matrices in case of empty local rows/columns.
326275d48cdbSStefano Zampini - -matis_storel2l - stores the local-to-local operators generated by the Galerkin process of MatPtAP().
3263b4319ba4SBarry Smith 
326495452b02SPatrick Sanan    Notes:
326595452b02SPatrick Sanan     Options prefix for the inner matrix are given by -is_mat_xxx
3266b4319ba4SBarry Smith 
3267b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
3268b4319ba4SBarry Smith 
3269b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
3270eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
3271b4319ba4SBarry Smith 
3272b4319ba4SBarry Smith   Level: advanced
3273b4319ba4SBarry Smith 
3274f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
3275b4319ba4SBarry Smith 
3276b4319ba4SBarry Smith M*/
3277b4319ba4SBarry Smith 
32788cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
3279b4319ba4SBarry Smith {
3280dfbe8321SBarry Smith   PetscErrorCode ierr;
3281b4319ba4SBarry Smith   Mat_IS         *b;
3282b4319ba4SBarry Smith 
3283b4319ba4SBarry Smith   PetscFunctionBegin;
3284b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
32858546b261SStefano Zampini   ierr    = PetscStrallocpy(MATAIJ,&b->lmattype);CHKERRQ(ierr);
3286b4319ba4SBarry Smith   A->data = (void*)b;
3287b4319ba4SBarry Smith 
3288e176bc59SStefano Zampini   /* matrix ops */
3289e176bc59SStefano Zampini   ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
3290b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
32912e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
32922e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
32932e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
3294b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
3295b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
32962e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
329798921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
3298b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
3299f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
33002e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
3301f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
3302b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
3303b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
3304b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
33056726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
33062e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
33072e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
33086726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
330969796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
331069796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
331145471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
3312ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
33136bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
33142b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
3315659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
33167dae84e0SHong Zhang   A->ops->createsubmatrix         = MatCreateSubMatrix_IS;
3317f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
33183fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
33193fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
3320d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
33217fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
3322ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
3323872cf891SStefano Zampini   A->ops->setfromoptions          = MatSetFromOptions_IS;
3324b4319ba4SBarry Smith 
3325b7ce53b6SStefano Zampini   /* special MATIS functions */
33268546b261SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",MatISSetLocalMatType_IS);CHKERRQ(ierr);
3327bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
33283b3b1effSJed Brown   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS);CHKERRQ(ierr);
3329bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
3330487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
33312e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
333275d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",MatISStoreL2L_IS);CHKERRQ(ierr);
3333f03112d0SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",MatISFixLocalEmpty_IS);CHKERRQ(ierr);
3334487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3335487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3336487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3337487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3338487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3339487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3340487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
334117667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
3342b4319ba4SBarry Smith   PetscFunctionReturn(0);
3343b4319ba4SBarry Smith }
3344