xref: /petsc/src/mat/impls/is/matis.c (revision 2c71b3e237ead271e4f3aa1505f92bf476e3413d)
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>
12a72d46e8SStefano Zampini #include <petsc/private/vecimpl.h>
1328f4e0baSStefano Zampini 
14f26d0771SStefano Zampini #define MATIS_MAX_ENTRIES_INSERTION 2048
15b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode);
16b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode);
178546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat);
18f26d0771SStefano Zampini 
1975d48cdbSStefano Zampini static PetscErrorCode MatISContainerDestroyPtAP_Private(void *ptr)
2075d48cdbSStefano Zampini {
2175d48cdbSStefano Zampini   MatISPtAP      ptap = (MatISPtAP)ptr;
2275d48cdbSStefano Zampini   PetscErrorCode ierr;
2375d48cdbSStefano Zampini 
2475d48cdbSStefano Zampini   PetscFunctionBegin;
2575d48cdbSStefano Zampini   ierr = MatDestroySubMatrices(ptap->ris1 ? 2 : 1,&ptap->lP);CHKERRQ(ierr);
2675d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->cis0);CHKERRQ(ierr);
2775d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->cis1);CHKERRQ(ierr);
2875d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->ris0);CHKERRQ(ierr);
2975d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->ris1);CHKERRQ(ierr);
3075d48cdbSStefano Zampini   ierr = PetscFree(ptap);CHKERRQ(ierr);
3175d48cdbSStefano Zampini   PetscFunctionReturn(0);
3275d48cdbSStefano Zampini }
3375d48cdbSStefano Zampini 
3475d48cdbSStefano Zampini static PetscErrorCode MatPtAPNumeric_IS_XAIJ(Mat A, Mat P, Mat C)
3575d48cdbSStefano Zampini {
3675d48cdbSStefano Zampini   MatISPtAP      ptap;
3775d48cdbSStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
3875d48cdbSStefano Zampini   Mat            lA,lC;
3975d48cdbSStefano Zampini   MatReuse       reuse;
4075d48cdbSStefano Zampini   IS             ris[2],cis[2];
4175d48cdbSStefano Zampini   PetscContainer c;
4275d48cdbSStefano Zampini   PetscInt       n;
4375d48cdbSStefano Zampini   PetscErrorCode ierr;
4475d48cdbSStefano Zampini 
4575d48cdbSStefano Zampini   PetscFunctionBegin;
466afe12f5SStefano Zampini   ierr = PetscObjectQuery((PetscObject)C,"_MatIS_PtAP",(PetscObject*)&c);CHKERRQ(ierr);
47*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!c,PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing PtAP information");
4875d48cdbSStefano Zampini   ierr   = PetscContainerGetPointer(c,(void**)&ptap);CHKERRQ(ierr);
4975d48cdbSStefano Zampini   ris[0] = ptap->ris0;
5075d48cdbSStefano Zampini   ris[1] = ptap->ris1;
5175d48cdbSStefano Zampini   cis[0] = ptap->cis0;
5275d48cdbSStefano Zampini   cis[1] = ptap->cis1;
5375d48cdbSStefano Zampini   n      = ptap->ris1 ? 2 : 1;
5475d48cdbSStefano Zampini   reuse  = ptap->lP ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX;
5575d48cdbSStefano Zampini   ierr   = MatCreateSubMatrices(P,n,ris,cis,reuse,&ptap->lP);CHKERRQ(ierr);
5675d48cdbSStefano Zampini 
5775d48cdbSStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
5875d48cdbSStefano Zampini   ierr = MatISGetLocalMat(C,&lC);CHKERRQ(ierr);
5975d48cdbSStefano Zampini   if (ptap->ris1) { /* unsymmetric A mapping */
6075d48cdbSStefano Zampini     Mat lPt;
6175d48cdbSStefano Zampini 
6275d48cdbSStefano Zampini     ierr = MatTranspose(ptap->lP[1],MAT_INITIAL_MATRIX,&lPt);CHKERRQ(ierr);
6375d48cdbSStefano Zampini     ierr = MatMatMatMult(lPt,lA,ptap->lP[0],reuse,ptap->fill,&lC);CHKERRQ(ierr);
6475d48cdbSStefano Zampini     if (matis->storel2l) {
6575d48cdbSStefano Zampini       ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",(PetscObject)lPt);CHKERRQ(ierr);
6675d48cdbSStefano Zampini     }
6775d48cdbSStefano Zampini     ierr = MatDestroy(&lPt);CHKERRQ(ierr);
6875d48cdbSStefano Zampini   } else {
6975d48cdbSStefano Zampini     ierr = MatPtAP(lA,ptap->lP[0],reuse,ptap->fill,&lC);CHKERRQ(ierr);
7075d48cdbSStefano Zampini     if (matis->storel2l) {
714222ddf1SHong Zhang      ierr = PetscObjectCompose((PetscObject)C,"_MatIS_PtAP_l2l",(PetscObject)ptap->lP[0]);CHKERRQ(ierr);
7275d48cdbSStefano Zampini     }
7375d48cdbSStefano Zampini   }
7475d48cdbSStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
7575d48cdbSStefano Zampini     ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
7675d48cdbSStefano Zampini     ierr = MatDestroy(&lC);CHKERRQ(ierr);
7775d48cdbSStefano Zampini   }
7875d48cdbSStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7975d48cdbSStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
8075d48cdbSStefano Zampini   PetscFunctionReturn(0);
8175d48cdbSStefano Zampini }
8275d48cdbSStefano Zampini 
8375d48cdbSStefano Zampini static PetscErrorCode MatGetNonzeroColumnsLocal_Private(Mat PT,IS *cis)
8475d48cdbSStefano Zampini {
8575d48cdbSStefano Zampini   Mat            Po,Pd;
8675d48cdbSStefano Zampini   IS             zd,zo;
8775d48cdbSStefano Zampini   const PetscInt *garray;
8875d48cdbSStefano Zampini   PetscInt       *aux,i,bs;
8975d48cdbSStefano Zampini   PetscInt       dc,stc,oc,ctd,cto;
9075d48cdbSStefano Zampini   PetscBool      ismpiaij,ismpibaij,isseqaij,isseqbaij;
9175d48cdbSStefano Zampini   MPI_Comm       comm;
9275d48cdbSStefano Zampini   PetscErrorCode ierr;
9375d48cdbSStefano Zampini 
9475d48cdbSStefano Zampini   PetscFunctionBegin;
9575d48cdbSStefano Zampini   PetscValidHeaderSpecific(PT,MAT_CLASSID,1);
9675d48cdbSStefano Zampini   PetscValidPointer(cis,2);
9775d48cdbSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)PT,&comm);CHKERRQ(ierr);
9875d48cdbSStefano Zampini   bs   = 1;
99b9e7e5c1SBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)PT,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
100b9e7e5c1SBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)PT,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
10104637862SRichard Tran Mills   ierr = PetscObjectBaseTypeCompare((PetscObject)PT,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
10275d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
10375d48cdbSStefano Zampini   if (isseqaij || isseqbaij) {
10475d48cdbSStefano Zampini     Pd = PT;
10575d48cdbSStefano Zampini     Po = NULL;
10675d48cdbSStefano Zampini     garray = NULL;
10775d48cdbSStefano Zampini   } else if (ismpiaij) {
10875d48cdbSStefano Zampini     ierr = MatMPIAIJGetSeqAIJ(PT,&Pd,&Po,&garray);CHKERRQ(ierr);
10975d48cdbSStefano Zampini   } else if (ismpibaij) {
11075d48cdbSStefano Zampini     ierr = MatMPIBAIJGetSeqBAIJ(PT,&Pd,&Po,&garray);CHKERRQ(ierr);
11175d48cdbSStefano Zampini     ierr = MatGetBlockSize(PT,&bs);CHKERRQ(ierr);
11298921bdaSJacob Faibussowitsch   } else SETERRQ(comm,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(PT))->type_name);
11375d48cdbSStefano Zampini 
11475d48cdbSStefano Zampini   /* identify any null columns in Pd or Po */
11522f7620eSStefano Zampini   /* We use a tolerance comparison since it may happen that, with geometric multigrid,
11622f7620eSStefano Zampini      some of the columns are not really zero, but very close to */
11775d48cdbSStefano Zampini   zo = zd = NULL;
11875d48cdbSStefano Zampini   if (Po) {
11922f7620eSStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(Po,PETSC_TRUE,PETSC_SMALL,&zo);CHKERRQ(ierr);
12075d48cdbSStefano Zampini   }
12122f7620eSStefano Zampini   ierr = MatFindNonzeroRowsOrCols_Basic(Pd,PETSC_TRUE,PETSC_SMALL,&zd);CHKERRQ(ierr);
12275d48cdbSStefano Zampini 
12375d48cdbSStefano Zampini   ierr = MatGetLocalSize(PT,NULL,&dc);CHKERRQ(ierr);
12475d48cdbSStefano Zampini   ierr = MatGetOwnershipRangeColumn(PT,&stc,NULL);CHKERRQ(ierr);
12575d48cdbSStefano Zampini   if (Po) { ierr = MatGetLocalSize(Po,NULL,&oc);CHKERRQ(ierr); }
12675d48cdbSStefano Zampini   else oc = 0;
12775d48cdbSStefano Zampini   ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
12875d48cdbSStefano Zampini   if (zd) {
12975d48cdbSStefano Zampini     const PetscInt *idxs;
13075d48cdbSStefano Zampini     PetscInt       nz;
13175d48cdbSStefano Zampini 
13275d48cdbSStefano Zampini     /* this will throw an error if bs is not valid */
13375d48cdbSStefano Zampini     ierr = ISSetBlockSize(zd,bs);CHKERRQ(ierr);
13475d48cdbSStefano Zampini     ierr = ISGetLocalSize(zd,&nz);CHKERRQ(ierr);
13575d48cdbSStefano Zampini     ierr = ISGetIndices(zd,&idxs);CHKERRQ(ierr);
13675d48cdbSStefano Zampini     ctd  = nz/bs;
13775d48cdbSStefano Zampini     for (i=0; i<ctd; i++) aux[i] = (idxs[bs*i]+stc)/bs;
13875d48cdbSStefano Zampini     ierr = ISRestoreIndices(zd,&idxs);CHKERRQ(ierr);
13975d48cdbSStefano Zampini   } else {
14075d48cdbSStefano Zampini     ctd = dc/bs;
14175d48cdbSStefano Zampini     for (i=0; i<ctd; i++) aux[i] = i+stc/bs;
14275d48cdbSStefano Zampini   }
14375d48cdbSStefano Zampini   if (zo) {
14475d48cdbSStefano Zampini     const PetscInt *idxs;
14575d48cdbSStefano Zampini     PetscInt       nz;
14675d48cdbSStefano Zampini 
14775d48cdbSStefano Zampini     /* this will throw an error if bs is not valid */
14875d48cdbSStefano Zampini     ierr = ISSetBlockSize(zo,bs);CHKERRQ(ierr);
14975d48cdbSStefano Zampini     ierr = ISGetLocalSize(zo,&nz);CHKERRQ(ierr);
15075d48cdbSStefano Zampini     ierr = ISGetIndices(zo,&idxs);CHKERRQ(ierr);
15175d48cdbSStefano Zampini     cto  = nz/bs;
15275d48cdbSStefano Zampini     for (i=0; i<cto; i++) aux[i+ctd] = garray[idxs[bs*i]/bs];
15375d48cdbSStefano Zampini     ierr = ISRestoreIndices(zo,&idxs);CHKERRQ(ierr);
15475d48cdbSStefano Zampini   } else {
15575d48cdbSStefano Zampini     cto = oc/bs;
15675d48cdbSStefano Zampini     for (i=0; i<cto; i++) aux[i+ctd] = garray[i];
15775d48cdbSStefano Zampini   }
15875d48cdbSStefano Zampini   ierr = ISCreateBlock(comm,bs,ctd+cto,aux,PETSC_OWN_POINTER,cis);CHKERRQ(ierr);
15975d48cdbSStefano Zampini   ierr = ISDestroy(&zd);CHKERRQ(ierr);
16075d48cdbSStefano Zampini   ierr = ISDestroy(&zo);CHKERRQ(ierr);
16175d48cdbSStefano Zampini   PetscFunctionReturn(0);
16275d48cdbSStefano Zampini }
16375d48cdbSStefano Zampini 
1644222ddf1SHong Zhang static PetscErrorCode MatPtAPSymbolic_IS_XAIJ(Mat A,Mat P,PetscReal fill,Mat C)
16575d48cdbSStefano Zampini {
1668546b261SStefano Zampini   Mat                    PT,lA;
16775d48cdbSStefano Zampini   MatISPtAP              ptap;
16875d48cdbSStefano Zampini   ISLocalToGlobalMapping Crl2g,Ccl2g,rl2g,cl2g;
16975d48cdbSStefano Zampini   PetscContainer         c;
1708546b261SStefano Zampini   MatType                lmtype;
17175d48cdbSStefano Zampini   const PetscInt         *garray;
17275d48cdbSStefano Zampini   PetscInt               ibs,N,dc;
17375d48cdbSStefano Zampini   MPI_Comm               comm;
17475d48cdbSStefano Zampini   PetscErrorCode         ierr;
17575d48cdbSStefano Zampini 
17675d48cdbSStefano Zampini   PetscFunctionBegin;
17775d48cdbSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
1784222ddf1SHong Zhang   ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
1798546b261SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1808546b261SStefano Zampini   ierr = MatGetType(lA,&lmtype);CHKERRQ(ierr);
1814222ddf1SHong Zhang   ierr = MatISSetLocalMatType(C,lmtype);CHKERRQ(ierr);
18275d48cdbSStefano Zampini   ierr = MatGetSize(P,NULL,&N);CHKERRQ(ierr);
18375d48cdbSStefano Zampini   ierr = MatGetLocalSize(P,NULL,&dc);CHKERRQ(ierr);
1844222ddf1SHong Zhang   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);
1944222ddf1SHong Zhang   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);
226580bdb30SBarry Smith       ierr = PetscArraycmp(i1,i2,N,&lsame);CHKERRQ(ierr);
22775d48cdbSStefano Zampini     }
228820f2d46SBarry Smith     ierr = MPIU_Allreduce(&lsame,&same,1,MPIU_BOOL,MPI_LAND,comm);CHKERRMPI(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) {
2404222ddf1SHong Zhang     ierr = MatGetBlockSize(C,&ibs);CHKERRQ(ierr);
24175d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(Ccl2g,ibs);CHKERRQ(ierr);
24275d48cdbSStefano Zampini   }
24375d48cdbSStefano Zampini */
2444222ddf1SHong Zhang   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 
2484222ddf1SHong Zhang   C->ops->ptapnumeric = MatPtAPNumeric_IS_XAIJ;
24975d48cdbSStefano Zampini   PetscFunctionReturn(0);
25075d48cdbSStefano Zampini }
25175d48cdbSStefano Zampini 
2524222ddf1SHong Zhang /* ----------------------------------------- */
2534222ddf1SHong Zhang static PetscErrorCode MatProductSymbolic_PtAP_IS_XAIJ(Mat C)
25475d48cdbSStefano Zampini {
25575d48cdbSStefano Zampini   PetscErrorCode ierr;
2564222ddf1SHong Zhang   Mat_Product    *product = C->product;
2574222ddf1SHong Zhang   Mat            A=product->A,P=product->B;
2584222ddf1SHong Zhang   PetscReal      fill=product->fill;
25975d48cdbSStefano Zampini 
26075d48cdbSStefano Zampini   PetscFunctionBegin;
26175d48cdbSStefano Zampini   ierr = MatPtAPSymbolic_IS_XAIJ(A,P,fill,C);CHKERRQ(ierr);
2624222ddf1SHong Zhang   C->ops->productnumeric = MatProductNumeric_PtAP;
26375d48cdbSStefano Zampini   PetscFunctionReturn(0);
26475d48cdbSStefano Zampini }
26575d48cdbSStefano Zampini 
2664222ddf1SHong Zhang static PetscErrorCode MatProductSetFromOptions_IS_XAIJ_PtAP(Mat C)
2674222ddf1SHong Zhang {
2684222ddf1SHong Zhang   PetscFunctionBegin;
2694222ddf1SHong Zhang   C->ops->productsymbolic = MatProductSymbolic_PtAP_IS_XAIJ;
2704222ddf1SHong Zhang   PetscFunctionReturn(0);
2714222ddf1SHong Zhang }
2724222ddf1SHong Zhang 
2734222ddf1SHong Zhang PETSC_INTERN PetscErrorCode MatProductSetFromOptions_IS_XAIJ(Mat C)
2744222ddf1SHong Zhang {
2754222ddf1SHong Zhang   PetscErrorCode ierr;
2764222ddf1SHong Zhang   Mat_Product    *product = C->product;
2774222ddf1SHong Zhang 
2784222ddf1SHong Zhang   PetscFunctionBegin;
2794222ddf1SHong Zhang   if (product->type == MATPRODUCT_PtAP) {
2804222ddf1SHong Zhang     ierr = MatProductSetFromOptions_IS_XAIJ_PtAP(C);CHKERRQ(ierr);
2816718818eSStefano Zampini   }
2824222ddf1SHong Zhang   PetscFunctionReturn(0);
2834222ddf1SHong Zhang }
2844222ddf1SHong Zhang 
2854222ddf1SHong Zhang /* ----------------------------------------- */
2865b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr)
2875b003df0Sstefano_zampini {
2885b003df0Sstefano_zampini   MatISLocalFields lf = (MatISLocalFields)ptr;
2895b003df0Sstefano_zampini   PetscInt         i;
2905b003df0Sstefano_zampini   PetscErrorCode   ierr;
2915b003df0Sstefano_zampini 
292ab4d48faSStefano Zampini   PetscFunctionBegin;
2935b003df0Sstefano_zampini   for (i=0;i<lf->nr;i++) {
2945b003df0Sstefano_zampini     ierr = ISDestroy(&lf->rf[i]);CHKERRQ(ierr);
2955b003df0Sstefano_zampini   }
2965b003df0Sstefano_zampini   for (i=0;i<lf->nc;i++) {
2975b003df0Sstefano_zampini     ierr = ISDestroy(&lf->cf[i]);CHKERRQ(ierr);
2985b003df0Sstefano_zampini   }
2995b003df0Sstefano_zampini   ierr = PetscFree2(lf->rf,lf->cf);CHKERRQ(ierr);
3005b003df0Sstefano_zampini   ierr = PetscFree(lf);CHKERRQ(ierr);
3015b003df0Sstefano_zampini   PetscFunctionReturn(0);
3025b003df0Sstefano_zampini }
303a72627d2SStefano Zampini 
304c9225affSStefano Zampini static PetscErrorCode MatConvert_SeqXAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
3056989cf23SStefano Zampini {
306c9225affSStefano Zampini   Mat            B,lB;
307c9225affSStefano Zampini   PetscErrorCode ierr;
308c9225affSStefano Zampini 
309c9225affSStefano Zampini   PetscFunctionBegin;
310c9225affSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
311c9225affSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g;
312c9225affSStefano Zampini     PetscInt               bs;
313c9225affSStefano Zampini     IS                     is;
314c9225affSStefano Zampini 
315c9225affSStefano Zampini     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
316c9225affSStefano Zampini     ierr = ISCreateStride(PetscObjectComm((PetscObject)A),A->rmap->n/bs,0,1,&is);CHKERRQ(ierr);
317c9225affSStefano Zampini     if (bs > 1) {
318c9225affSStefano Zampini       IS       is2;
319c9225affSStefano Zampini       PetscInt i,*aux;
320c9225affSStefano Zampini 
321c9225affSStefano Zampini       ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
322c9225affSStefano Zampini       ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
323c9225affSStefano Zampini       ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
324c9225affSStefano Zampini       ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
325c9225affSStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
326c9225affSStefano Zampini       is   = is2;
327c9225affSStefano Zampini     }
328c9225affSStefano Zampini     ierr = ISSetIdentity(is);CHKERRQ(ierr);
329c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
330c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
331c9225affSStefano Zampini     ierr = ISCreateStride(PetscObjectComm((PetscObject)A),A->cmap->n/bs,0,1,&is);CHKERRQ(ierr);
332c9225affSStefano Zampini     if (bs > 1) {
333c9225affSStefano Zampini       IS       is2;
334c9225affSStefano Zampini       PetscInt i,*aux;
335c9225affSStefano Zampini 
336c9225affSStefano Zampini       ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
337c9225affSStefano Zampini       ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
338c9225affSStefano Zampini       ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
339c9225affSStefano Zampini       ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
340c9225affSStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
341c9225affSStefano Zampini       is   = is2;
342c9225affSStefano Zampini     }
343c9225affSStefano Zampini     ierr = ISSetIdentity(is);CHKERRQ(ierr);
344c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
345c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
346c9225affSStefano Zampini     ierr = MatCreateIS(PetscObjectComm((PetscObject)A),bs,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N,rl2g,cl2g,&B);CHKERRQ(ierr);
347c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
348c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
349c9225affSStefano Zampini     ierr = MatDuplicate(A,MAT_COPY_VALUES,&lB);CHKERRQ(ierr);
350c9225affSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *newmat = B;
351c9225affSStefano Zampini   } else {
352c9225affSStefano Zampini     B    = *newmat;
353c9225affSStefano Zampini     ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
354c9225affSStefano Zampini     lB   = A;
355c9225affSStefano Zampini   }
356c9225affSStefano Zampini   ierr = MatISSetLocalMat(B,lB);CHKERRQ(ierr);
357c9225affSStefano Zampini   ierr = MatDestroy(&lB);CHKERRQ(ierr);
358c9225affSStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
359c9225affSStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
360c9225affSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
361c9225affSStefano Zampini     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
362c9225affSStefano Zampini   }
363c9225affSStefano Zampini   PetscFunctionReturn(0);
364c9225affSStefano Zampini }
365c9225affSStefano Zampini 
366c9225affSStefano Zampini static PetscErrorCode MatISScaleDisassembling_Private(Mat A)
367c9225affSStefano Zampini {
368c9225affSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(A->data);
369c9225affSStefano Zampini   PetscScalar    *aa;
370c9225affSStefano Zampini   const PetscInt *ii,*jj;
371c9225affSStefano Zampini   PetscInt       i,n,m;
372fabe8965SStefano Zampini   PetscInt       *ecount,**eneighs;
373c9225affSStefano Zampini   PetscBool      flg;
374c9225affSStefano Zampini   PetscErrorCode ierr;
375c9225affSStefano Zampini 
376c9225affSStefano Zampini   PetscFunctionBegin;
377c9225affSStefano Zampini   ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg);CHKERRQ(ierr);
378*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
379fabe8965SStefano Zampini   ierr = ISLocalToGlobalMappingGetNodeInfo(A->rmap->mapping,&n,&ecount,&eneighs);CHKERRQ(ierr);
380*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(m != n,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %" PetscInt_FMT " != %" PetscInt_FMT,m,n);
381c9225affSStefano Zampini   ierr = MatSeqAIJGetArray(matis->A,&aa);CHKERRQ(ierr);
382c9225affSStefano Zampini   for (i=0;i<n;i++) {
383fabe8965SStefano Zampini     if (ecount[i] > 1) {
384c9225affSStefano Zampini       PetscInt j;
385c9225affSStefano Zampini 
386c9225affSStefano Zampini       for (j=ii[i];j<ii[i+1];j++) {
387c9225affSStefano Zampini         PetscInt    i2 = jj[j],p,p2;
388fabe8965SStefano Zampini         PetscReal   scal = 0.0;
389c9225affSStefano Zampini 
390c9225affSStefano Zampini         for (p=0;p<ecount[i];p++) {
391c9225affSStefano Zampini           for (p2=0;p2<ecount[i2];p2++) {
392c9225affSStefano Zampini             if (eneighs[i][p] == eneighs[i2][p2]) { scal += 1.0; break; }
393c9225affSStefano Zampini           }
394c9225affSStefano Zampini         }
395fabe8965SStefano Zampini         if (scal) aa[j] /= scal;
396c9225affSStefano Zampini       }
397c9225affSStefano Zampini     }
398c9225affSStefano Zampini   }
399fabe8965SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreNodeInfo(A->rmap->mapping,&n,&ecount,&eneighs);CHKERRQ(ierr);
400c9225affSStefano Zampini   ierr = MatSeqAIJRestoreArray(matis->A,&aa);CHKERRQ(ierr);
401c9225affSStefano Zampini   ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg);CHKERRQ(ierr);
402*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
403c9225affSStefano Zampini   PetscFunctionReturn(0);
404c9225affSStefano Zampini }
405c9225affSStefano Zampini 
406fabe8965SStefano Zampini typedef enum {MAT_IS_DISASSEMBLE_L2G_NATURAL,MAT_IS_DISASSEMBLE_L2G_MAT, MAT_IS_DISASSEMBLE_L2G_ND} MatISDisassemblel2gType;
407fabe8965SStefano Zampini 
408c9225affSStefano Zampini static PetscErrorCode MatMPIXAIJComputeLocalToGlobalMapping_Private(Mat A, ISLocalToGlobalMapping *l2g)
409c9225affSStefano Zampini {
410fabe8965SStefano Zampini   Mat                     Ad,Ao;
411fabe8965SStefano Zampini   IS                      is,ndmap,ndsub;
412c9225affSStefano Zampini   MPI_Comm                comm;
413fabe8965SStefano Zampini   const PetscInt          *garray,*ndmapi;
414fabe8965SStefano Zampini   PetscInt                bs,i,cnt,nl,*ncount,*ndmapc;
415fabe8965SStefano Zampini   PetscBool               ismpiaij,ismpibaij;
416f4259b30SLisandro Dalcin   const char *const       MatISDisassemblel2gTypes[] = {"NATURAL","MAT","ND","MatISDisassemblel2gType","MAT_IS_DISASSEMBLE_L2G_",NULL};
417fabe8965SStefano Zampini   MatISDisassemblel2gType mode = MAT_IS_DISASSEMBLE_L2G_NATURAL;
418fabe8965SStefano Zampini   MatPartitioning         part;
419fabe8965SStefano Zampini   PetscSF                 sf;
420c9225affSStefano Zampini   PetscErrorCode          ierr;
421c9225affSStefano Zampini 
422c9225affSStefano Zampini   PetscFunctionBegin;
423fabe8965SStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"MatIS l2g disassembling options","Mat");CHKERRQ(ierr);
424fabe8965SStefano 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);
425fabe8965SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
426fabe8965SStefano Zampini   if (mode == MAT_IS_DISASSEMBLE_L2G_MAT) {
427c9225affSStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,l2g,NULL);CHKERRQ(ierr);
428c9225affSStefano Zampini     PetscFunctionReturn(0);
429c9225affSStefano Zampini   }
430c9225affSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
431b9e7e5c1SBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij);CHKERRQ(ierr);
432b9e7e5c1SBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
433c9225affSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
434fabe8965SStefano Zampini   switch (mode) {
435fabe8965SStefano Zampini   case MAT_IS_DISASSEMBLE_L2G_ND:
436fabe8965SStefano Zampini     ierr = MatPartitioningCreate(comm,&part);CHKERRQ(ierr);
437fabe8965SStefano Zampini     ierr = MatPartitioningSetAdjacency(part,A);CHKERRQ(ierr);
438fabe8965SStefano Zampini     ierr = PetscObjectSetOptionsPrefix((PetscObject)part,((PetscObject)A)->prefix);CHKERRQ(ierr);
439fabe8965SStefano Zampini     ierr = MatPartitioningSetFromOptions(part);CHKERRQ(ierr);
440fabe8965SStefano Zampini     ierr = MatPartitioningApplyND(part,&ndmap);CHKERRQ(ierr);
441fabe8965SStefano Zampini     ierr = MatPartitioningDestroy(&part);CHKERRQ(ierr);
442fabe8965SStefano Zampini     ierr = ISBuildTwoSided(ndmap,NULL,&ndsub);CHKERRQ(ierr);
443fabe8965SStefano Zampini     ierr = MatMPIAIJSetUseScalableIncreaseOverlap(A,PETSC_TRUE);CHKERRQ(ierr);
444fabe8965SStefano Zampini     ierr = MatIncreaseOverlap(A,1,&ndsub,1);CHKERRQ(ierr);
445fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(ndsub,l2g);CHKERRQ(ierr);
446fabe8965SStefano Zampini 
447fabe8965SStefano Zampini     /* it may happen that a separator node is not properly shared */
448fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingGetNodeInfo(*l2g,&nl,&ncount,NULL);CHKERRQ(ierr);
449fabe8965SStefano Zampini     ierr = PetscSFCreate(comm,&sf);CHKERRQ(ierr);
450fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(*l2g,&garray);CHKERRQ(ierr);
451fabe8965SStefano Zampini     ierr = PetscSFSetGraphLayout(sf,A->rmap,nl,NULL,PETSC_OWN_POINTER,garray);CHKERRQ(ierr);
452fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(*l2g,&garray);CHKERRQ(ierr);
453fabe8965SStefano Zampini     ierr = PetscCalloc1(A->rmap->n,&ndmapc);CHKERRQ(ierr);
45483df288dSJunchao Zhang     ierr = PetscSFReduceBegin(sf,MPIU_INT,ncount,ndmapc,MPI_REPLACE);CHKERRQ(ierr);
45583df288dSJunchao Zhang     ierr = PetscSFReduceEnd(sf,MPIU_INT,ncount,ndmapc,MPI_REPLACE);CHKERRQ(ierr);
456fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreNodeInfo(*l2g,NULL,&ncount,NULL);CHKERRQ(ierr);
457fabe8965SStefano Zampini     ierr = ISGetIndices(ndmap,&ndmapi);CHKERRQ(ierr);
458fabe8965SStefano Zampini     for (i = 0, cnt = 0; i < A->rmap->n; i++)
459fabe8965SStefano Zampini       if (ndmapi[i] < 0 && ndmapc[i] < 2)
460fabe8965SStefano Zampini         cnt++;
461fabe8965SStefano Zampini 
462820f2d46SBarry Smith     ierr = MPIU_Allreduce(&cnt,&i,1,MPIU_INT,MPI_MAX,comm);CHKERRMPI(ierr);
463fabe8965SStefano Zampini     if (i) { /* we detected isolated separator nodes */
464fabe8965SStefano Zampini       Mat                    A2,A3;
465fabe8965SStefano Zampini       IS                     *workis,is2;
466fabe8965SStefano Zampini       PetscScalar            *vals;
467fabe8965SStefano Zampini       PetscInt               gcnt = i,*dnz,*onz,j,*lndmapi;
468fabe8965SStefano Zampini       ISLocalToGlobalMapping ll2g;
469fabe8965SStefano Zampini       PetscBool              flg;
470fabe8965SStefano Zampini       const PetscInt         *ii,*jj;
471fabe8965SStefano Zampini 
472fabe8965SStefano Zampini       /* communicate global id of separators */
473fabe8965SStefano Zampini       ierr = MatPreallocateInitialize(comm,A->rmap->n,A->cmap->n,dnz,onz);CHKERRQ(ierr);
474fabe8965SStefano Zampini       for (i = 0, cnt = 0; i < A->rmap->n; i++)
475fabe8965SStefano Zampini         dnz[i] = ndmapi[i] < 0 ? i + A->rmap->rstart : -1;
476fabe8965SStefano Zampini 
477fabe8965SStefano Zampini       ierr = PetscMalloc1(nl,&lndmapi);CHKERRQ(ierr);
478ad227feaSJunchao Zhang       ierr = PetscSFBcastBegin(sf,MPIU_INT,dnz,lndmapi,MPI_REPLACE);CHKERRQ(ierr);
479fabe8965SStefano Zampini 
480fabe8965SStefano Zampini       /* compute adjacency of isolated separators node */
481fabe8965SStefano Zampini       ierr = PetscMalloc1(gcnt,&workis);CHKERRQ(ierr);
482fabe8965SStefano Zampini       for (i = 0, cnt = 0; i < A->rmap->n; i++) {
483fabe8965SStefano Zampini         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
484fabe8965SStefano Zampini           ierr = ISCreateStride(comm,1,i+A->rmap->rstart,1,&workis[cnt++]);CHKERRQ(ierr);
485fabe8965SStefano Zampini         }
486fabe8965SStefano Zampini       }
487fabe8965SStefano Zampini       for (i = cnt; i < gcnt; i++) {
488fabe8965SStefano Zampini         ierr = ISCreateStride(comm,0,0,1,&workis[i]);CHKERRQ(ierr);
489fabe8965SStefano Zampini       }
490fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
491fabe8965SStefano Zampini         ierr = PetscObjectSetName((PetscObject)workis[i],"ISOLATED");CHKERRQ(ierr);
492fabe8965SStefano Zampini         ierr = ISViewFromOptions(workis[i],NULL,"-view_isolated_separators");CHKERRQ(ierr);
493fabe8965SStefano Zampini       }
494fabe8965SStefano Zampini 
495fabe8965SStefano Zampini       /* no communications since all the ISes correspond to locally owned rows */
496fabe8965SStefano Zampini       ierr = MatIncreaseOverlap(A,gcnt,workis,1);CHKERRQ(ierr);
497fabe8965SStefano Zampini 
498fabe8965SStefano Zampini       /* end communicate global id of separators */
499ad227feaSJunchao Zhang       ierr = PetscSFBcastEnd(sf,MPIU_INT,dnz,lndmapi,MPI_REPLACE);CHKERRQ(ierr);
500fabe8965SStefano Zampini 
501fabe8965SStefano Zampini       /* communicate new layers : create a matrix and transpose it */
502580bdb30SBarry Smith       ierr = PetscArrayzero(dnz,A->rmap->n);CHKERRQ(ierr);
503580bdb30SBarry Smith       ierr = PetscArrayzero(onz,A->rmap->n);CHKERRQ(ierr);
504fabe8965SStefano Zampini       for (i = 0, j = 0; i < A->rmap->n; i++) {
505fabe8965SStefano Zampini         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
506fabe8965SStefano Zampini           const PetscInt* idxs;
507fabe8965SStefano Zampini           PetscInt        s;
508fabe8965SStefano Zampini 
509fabe8965SStefano Zampini           ierr = ISGetLocalSize(workis[j],&s);CHKERRQ(ierr);
510fabe8965SStefano Zampini           ierr = ISGetIndices(workis[j],&idxs);CHKERRQ(ierr);
511fabe8965SStefano Zampini           ierr = MatPreallocateSet(i+A->rmap->rstart,s,idxs,dnz,onz);CHKERRQ(ierr);
512fabe8965SStefano Zampini           j++;
513fabe8965SStefano Zampini         }
514fabe8965SStefano Zampini       }
515*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(j != cnt,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT,j,cnt);
516fabe8965SStefano Zampini 
517fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
518fabe8965SStefano Zampini         ierr = PetscObjectSetName((PetscObject)workis[i],"EXTENDED");CHKERRQ(ierr);
519fabe8965SStefano Zampini         ierr = ISViewFromOptions(workis[i],NULL,"-view_isolated_separators");CHKERRQ(ierr);
520fabe8965SStefano Zampini       }
521fabe8965SStefano Zampini 
522fabe8965SStefano Zampini       for (i = 0, j = 0; i < A->rmap->n; i++) j = PetscMax(j,dnz[i]+onz[i]);
523fabe8965SStefano Zampini       ierr = PetscMalloc1(j,&vals);CHKERRQ(ierr);
524fabe8965SStefano Zampini       for (i = 0; i < j; i++) vals[i] = 1.0;
525fabe8965SStefano Zampini 
526fabe8965SStefano Zampini       ierr = MatCreate(comm,&A2);CHKERRQ(ierr);
527fabe8965SStefano Zampini       ierr = MatSetType(A2,MATMPIAIJ);CHKERRQ(ierr);
528fabe8965SStefano Zampini       ierr = MatSetSizes(A2,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
529fabe8965SStefano Zampini       ierr = MatMPIAIJSetPreallocation(A2,0,dnz,0,onz);CHKERRQ(ierr);
530fabe8965SStefano Zampini       ierr = MatSetOption(A2,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
531fabe8965SStefano Zampini       for (i = 0, j = 0; i < A2->rmap->n; i++) {
532fabe8965SStefano Zampini         PetscInt        row = i+A2->rmap->rstart,s = dnz[i] + onz[i];
533fabe8965SStefano Zampini         const PetscInt* idxs;
534fabe8965SStefano Zampini 
535fabe8965SStefano Zampini         if (s) {
536fabe8965SStefano Zampini           ierr = ISGetIndices(workis[j],&idxs);CHKERRQ(ierr);
537fabe8965SStefano Zampini           ierr = MatSetValues(A2,1,&row,s,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
538fabe8965SStefano Zampini           ierr = ISRestoreIndices(workis[j],&idxs);CHKERRQ(ierr);
539fabe8965SStefano Zampini           j++;
540fabe8965SStefano Zampini         }
541fabe8965SStefano Zampini       }
542*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(j != cnt,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %" PetscInt_FMT " != %" PetscInt_FMT,j,cnt);
543fabe8965SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
544fabe8965SStefano Zampini       ierr = MatAssemblyBegin(A2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
545fabe8965SStefano Zampini       ierr = MatAssemblyEnd(A2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
546fabe8965SStefano Zampini       ierr = MatTranspose(A2,MAT_INPLACE_MATRIX,&A2);CHKERRQ(ierr);
547fabe8965SStefano Zampini 
548fabe8965SStefano Zampini       /* extract submatrix corresponding to the coupling "owned separators" x "isolated separators" */
549fabe8965SStefano Zampini       for (i = 0, j = 0; i < nl; i++)
550fabe8965SStefano Zampini         if (lndmapi[i] >= 0) lndmapi[j++] = lndmapi[i];
551fabe8965SStefano Zampini       ierr = ISCreateGeneral(comm,j,lndmapi,PETSC_USE_POINTER,&is);CHKERRQ(ierr);
552fabe8965SStefano Zampini       ierr = MatMPIAIJGetLocalMatCondensed(A2,MAT_INITIAL_MATRIX,&is,NULL,&A3);CHKERRQ(ierr);
553fabe8965SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
554fabe8965SStefano Zampini       ierr = MatDestroy(&A2);CHKERRQ(ierr);
555fabe8965SStefano Zampini 
556fabe8965SStefano Zampini       /* extend local to global map to include connected isolated separators */
557fabe8965SStefano Zampini       ierr = PetscObjectQuery((PetscObject)A3,"_petsc_GetLocalMatCondensed_iscol",(PetscObject*)&is);CHKERRQ(ierr);
558*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!is,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing column map");
559fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&ll2g);CHKERRQ(ierr);
560fabe8965SStefano Zampini       ierr = MatGetRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg);CHKERRQ(ierr);
561*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
562fabe8965SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,ii[i],jj,PETSC_COPY_VALUES,&is);CHKERRQ(ierr);
563fabe8965SStefano Zampini       ierr = MatRestoreRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg);CHKERRQ(ierr);
564*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
565fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(ll2g,is,&is2);CHKERRQ(ierr);
566fabe8965SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
567fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&ll2g);CHKERRQ(ierr);
568fabe8965SStefano Zampini 
569fabe8965SStefano Zampini       /* add new nodes to the local-to-global map */
570fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(l2g);CHKERRQ(ierr);
571fabe8965SStefano Zampini       ierr = ISExpand(ndsub,is2,&is);CHKERRQ(ierr);
572fabe8965SStefano Zampini       ierr = ISDestroy(&is2);CHKERRQ(ierr);
573fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,l2g);CHKERRQ(ierr);
574fabe8965SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
575fabe8965SStefano Zampini 
576fabe8965SStefano Zampini       ierr = MatDestroy(&A3);CHKERRQ(ierr);
577fabe8965SStefano Zampini       ierr = PetscFree(lndmapi);CHKERRQ(ierr);
578fabe8965SStefano Zampini       ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
579fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
580fabe8965SStefano Zampini         ierr = ISDestroy(&workis[i]);CHKERRQ(ierr);
581fabe8965SStefano Zampini       }
582fabe8965SStefano Zampini       ierr = PetscFree(workis);CHKERRQ(ierr);
583fabe8965SStefano Zampini     }
584fabe8965SStefano Zampini     ierr = ISRestoreIndices(ndmap,&ndmapi);CHKERRQ(ierr);
585fabe8965SStefano Zampini     ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
586fabe8965SStefano Zampini     ierr = PetscFree(ndmapc);CHKERRQ(ierr);
587fabe8965SStefano Zampini     ierr = ISDestroy(&ndmap);CHKERRQ(ierr);
588fabe8965SStefano Zampini     ierr = ISDestroy(&ndsub);CHKERRQ(ierr);
589fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(*l2g,bs);CHKERRQ(ierr);
590fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingViewFromOptions(*l2g,NULL,"-matis_nd_l2g_view");CHKERRQ(ierr);
591fabe8965SStefano Zampini     break;
592fabe8965SStefano Zampini   case MAT_IS_DISASSEMBLE_L2G_NATURAL:
593fabe8965SStefano Zampini     if (ismpiaij) {
594fabe8965SStefano Zampini       ierr = MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
595fabe8965SStefano Zampini     } else if (ismpibaij) {
596fabe8965SStefano Zampini       ierr = MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
59798921bdaSJacob Faibussowitsch     } else SETERRQ(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
598*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!garray,comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
599c9225affSStefano Zampini     if (A->rmap->n) {
600fabe8965SStefano Zampini       PetscInt dc,oc,stc,*aux;
601c9225affSStefano Zampini 
602c9225affSStefano Zampini       ierr = MatGetLocalSize(A,NULL,&dc);CHKERRQ(ierr);
603c9225affSStefano Zampini       ierr = MatGetLocalSize(Ao,NULL,&oc);CHKERRQ(ierr);
604c9225affSStefano Zampini       ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
605c9225affSStefano Zampini       ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
606c9225affSStefano Zampini       for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
607c9225affSStefano Zampini       for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i];
608c9225affSStefano Zampini       ierr = ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
609c9225affSStefano Zampini     } else {
610c9225affSStefano Zampini       ierr = ISCreateBlock(comm,1,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
611c9225affSStefano Zampini     }
612c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,l2g);CHKERRQ(ierr);
613c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
614fabe8965SStefano Zampini     break;
615fabe8965SStefano Zampini   default:
61698921bdaSJacob Faibussowitsch     SETERRQ(comm,PETSC_ERR_ARG_WRONG,"Unsupported l2g disassembling type %d",mode);
617c9225affSStefano Zampini   }
618c9225affSStefano Zampini   PetscFunctionReturn(0);
619c9225affSStefano Zampini }
620c9225affSStefano Zampini 
621c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
622c9225affSStefano Zampini {
623c9225affSStefano Zampini   Mat                    lA,Ad,Ao,B = NULL;
6246989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
6256989cf23SStefano Zampini   IS                     is;
6266989cf23SStefano Zampini   MPI_Comm               comm;
6276989cf23SStefano Zampini   void                   *ptrs[2];
6286989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
629c9225affSStefano Zampini   const PetscInt         *garray;
6306989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
631c9225affSStefano Zampini   const PetscInt         *di,*dj,*oi,*oj;
632c9225affSStefano Zampini   const PetscInt         *odi,*odj,*ooi,*ooj;
6336989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
634c9225affSStefano Zampini   PetscInt               bs,lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
635c9225affSStefano Zampini   PetscBool              flg,ismpiaij,ismpibaij,was_inplace = PETSC_FALSE;
636c9225affSStefano Zampini   PetscMPIInt            size;
6376989cf23SStefano Zampini   PetscErrorCode         ierr;
6386989cf23SStefano Zampini 
639ab4d48faSStefano Zampini   PetscFunctionBegin;
6406989cf23SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
641ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm,&size);CHKERRMPI(ierr);
642c9225affSStefano Zampini   if (size == 1) {
643c9225affSStefano Zampini     ierr = MatConvert_SeqXAIJ_IS(A,type,reuse,newmat);CHKERRQ(ierr);
644c9225affSStefano Zampini     PetscFunctionReturn(0);
645c9225affSStefano Zampini   }
646c9225affSStefano Zampini   if (reuse != MAT_REUSE_MATRIX && A->cmap->N == A->rmap->N) {
647c9225affSStefano Zampini     ierr = MatMPIXAIJComputeLocalToGlobalMapping_Private(A,&rl2g);CHKERRQ(ierr);
648c9225affSStefano Zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
649c9225affSStefano Zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
650c9225affSStefano Zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
651c9225affSStefano Zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,rl2g);CHKERRQ(ierr);
652c9225affSStefano Zampini     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
653c9225affSStefano Zampini     ierr = MatSetBlockSize(B,bs);CHKERRQ(ierr);
654c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
655c9225affSStefano Zampini     if (reuse == MAT_INPLACE_MATRIX) was_inplace = PETSC_TRUE;
656c9225affSStefano Zampini     reuse = MAT_REUSE_MATRIX;
657c9225affSStefano Zampini   }
658c9225affSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
659c9225affSStefano Zampini     Mat            *newlA, lA;
660c9225affSStefano Zampini     IS             rows, cols;
661c9225affSStefano Zampini     const PetscInt *ridx, *cidx;
662c9225affSStefano Zampini     PetscInt       rbs, cbs, nr, nc;
663c9225affSStefano Zampini 
664c9225affSStefano Zampini     if (!B) B = *newmat;
665c9225affSStefano Zampini     ierr = MatGetLocalToGlobalMapping(B,&rl2g,&cl2g);CHKERRQ(ierr);
666c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(rl2g,&ridx);CHKERRQ(ierr);
667c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(cl2g,&cidx);CHKERRQ(ierr);
668c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(rl2g,&nr);CHKERRQ(ierr);
669c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(cl2g,&nc);CHKERRQ(ierr);
670c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(rl2g,&rbs);CHKERRQ(ierr);
671c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(cl2g,&cbs);CHKERRQ(ierr);
672c9225affSStefano Zampini     ierr = ISCreateBlock(comm,rbs,nr/rbs,ridx,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
673c9225affSStefano Zampini     if (rl2g != cl2g) {
674c9225affSStefano Zampini       ierr = ISCreateBlock(comm,cbs,nc/cbs,cidx,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
675c9225affSStefano Zampini     } else {
676c9225affSStefano Zampini       ierr = PetscObjectReference((PetscObject)rows);CHKERRQ(ierr);
677c9225affSStefano Zampini       cols = rows;
678c9225affSStefano Zampini     }
679c9225affSStefano Zampini     ierr = MatISGetLocalMat(B,&lA);CHKERRQ(ierr);
680c9225affSStefano Zampini     ierr = MatCreateSubMatrices(A,1,&rows,&cols,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
681c9225affSStefano Zampini     ierr = MatConvert(newlA[0],MATSEQAIJ,MAT_INPLACE_MATRIX,&newlA[0]);CHKERRQ(ierr);
682c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&ridx);CHKERRQ(ierr);
683c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&cidx);CHKERRQ(ierr);
684c9225affSStefano Zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
685c9225affSStefano Zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
686c9225affSStefano Zampini     if (!lA->preallocated) { /* first time */
687c9225affSStefano Zampini       ierr = MatDuplicate(newlA[0],MAT_COPY_VALUES,&lA);CHKERRQ(ierr);
688c9225affSStefano Zampini       ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
689c9225affSStefano Zampini       ierr = PetscObjectDereference((PetscObject)lA);CHKERRQ(ierr);
690c9225affSStefano Zampini     }
691c9225affSStefano Zampini     ierr = MatCopy(newlA[0],lA,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
692c9225affSStefano Zampini     ierr = MatDestroySubMatrices(1,&newlA);CHKERRQ(ierr);
693c9225affSStefano Zampini     ierr = MatISScaleDisassembling_Private(B);CHKERRQ(ierr);
694c9225affSStefano Zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
695c9225affSStefano Zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
696c9225affSStefano Zampini     if (was_inplace) { ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); }
697c9225affSStefano Zampini     else *newmat = B;
698c9225affSStefano Zampini     PetscFunctionReturn(0);
699c9225affSStefano Zampini   }
700c9225affSStefano Zampini   /* rectangular case, just compress out the column space */
701b9e7e5c1SBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij);CHKERRQ(ierr);
702b9e7e5c1SBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
703c9225affSStefano Zampini   if (ismpiaij) {
704c9225affSStefano Zampini     bs   = 1;
705c9225affSStefano Zampini     ierr = MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
706c9225affSStefano Zampini   } else if (ismpibaij) {
707c9225affSStefano Zampini     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
708c9225affSStefano Zampini     ierr = MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
709c9225affSStefano Zampini     ierr = MatConvert(Ad,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ad);CHKERRQ(ierr);
710c9225affSStefano Zampini     ierr = MatConvert(Ao,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ao);CHKERRQ(ierr);
71198921bdaSJacob Faibussowitsch   } else SETERRQ(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
712c9225affSStefano Zampini   ierr = MatSeqAIJGetArray(Ad,&dd);CHKERRQ(ierr);
713c9225affSStefano Zampini   ierr = MatSeqAIJGetArray(Ao,&od);CHKERRQ(ierr);
714*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!garray,comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
7156989cf23SStefano Zampini 
7166989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
7176989cf23SStefano Zampini   ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr);
7186989cf23SStefano Zampini   ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
7196989cf23SStefano Zampini   ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr);
720c9225affSStefano Zampini   ierr = MatGetLocalSize(Ao,NULL,&oc);CHKERRQ(ierr);
721c9225affSStefano Zampini   ierr = MatGetRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&di,&dj,&flg);CHKERRQ(ierr);
722*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
723c9225affSStefano Zampini   ierr = MatGetRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&oi,&oj,&flg);CHKERRQ(ierr);
724*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
725c9225affSStefano Zampini   nnz = di[dr] + oi[dr];
726c9225affSStefano Zampini   /* store original pointers to be restored later */
727c9225affSStefano Zampini   odi = di; odj = dj; ooi = oi; ooj = oj;
7286989cf23SStefano Zampini 
7296989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
730c9225affSStefano Zampini   ierr = ISCreateStride(comm,dr/bs,str/bs,1,&is);CHKERRQ(ierr);
731c9225affSStefano Zampini   if (bs > 1) {
732c9225affSStefano Zampini     IS is2;
733c9225affSStefano Zampini 
734c9225affSStefano Zampini     ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
735c9225affSStefano Zampini     ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
736c9225affSStefano Zampini     ierr = ISCreateBlock(comm,bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
737c9225affSStefano Zampini     ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
738c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
739c9225affSStefano Zampini     is   = is2;
740c9225affSStefano Zampini   }
7416989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
7426989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
743e363d98aSStefano Zampini   if (dr) {
744c9225affSStefano Zampini     ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
745c9225affSStefano Zampini     for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
746c9225affSStefano Zampini     for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i];
747c9225affSStefano Zampini     ierr = ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
748e363d98aSStefano Zampini     lc   = dc+oc;
749e363d98aSStefano Zampini   } else {
750c9225affSStefano Zampini     ierr = ISCreateBlock(comm,bs,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
751e363d98aSStefano Zampini     lc   = 0;
752e363d98aSStefano Zampini   }
7536989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
7546989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
7556989cf23SStefano Zampini 
7566989cf23SStefano Zampini   /* create MATIS object */
757c9225affSStefano Zampini   ierr = MatCreate(comm,&B);CHKERRQ(ierr);
758c9225affSStefano Zampini   ierr = MatSetSizes(B,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
759c9225affSStefano Zampini   ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
760c9225affSStefano Zampini   ierr = MatSetBlockSize(B,bs);CHKERRQ(ierr);
761c9225affSStefano Zampini   ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
7626989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
7636989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
7646989cf23SStefano Zampini 
7656989cf23SStefano Zampini   /* merge local matrices */
7666989cf23SStefano Zampini   ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr);
7676989cf23SStefano Zampini   ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
7686989cf23SStefano Zampini   ii   = aux;
7696989cf23SStefano Zampini   jj   = aux+dr+1;
7706989cf23SStefano Zampini   aa   = data;
7716989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
7726989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
7736989cf23SStefano Zampini   {
7746989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
7756989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
7766989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
7776989cf23SStefano Zampini   }
7786989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
779c9225affSStefano Zampini 
780c9225affSStefano Zampini   ierr = MatRestoreRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&odi,&odj,&flg);CHKERRQ(ierr);
781*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
782c9225affSStefano Zampini   ierr = MatRestoreRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&ooi,&ooj,&flg);CHKERRQ(ierr);
783*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!flg,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
784c9225affSStefano Zampini   ierr = MatSeqAIJRestoreArray(Ad,&dd);CHKERRQ(ierr);
785c9225affSStefano Zampini   ierr = MatSeqAIJRestoreArray(Ao,&od);CHKERRQ(ierr);
786c9225affSStefano Zampini 
7876989cf23SStefano Zampini   ii   = aux;
7886989cf23SStefano Zampini   jj   = aux+dr+1;
7896989cf23SStefano Zampini   aa   = data;
790e363d98aSStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr);
7916989cf23SStefano Zampini 
7926989cf23SStefano Zampini   /* create containers to destroy the data */
7936989cf23SStefano Zampini   ptrs[0] = aux;
7946989cf23SStefano Zampini   ptrs[1] = data;
7956989cf23SStefano Zampini   for (i=0; i<2; i++) {
7966989cf23SStefano Zampini     PetscContainer c;
7976989cf23SStefano Zampini 
7986989cf23SStefano Zampini     ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
7996989cf23SStefano Zampini     ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
800b81c21eeSStefano Zampini     ierr = PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault);CHKERRQ(ierr);
8016989cf23SStefano Zampini     ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr);
8026989cf23SStefano Zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
8036989cf23SStefano Zampini   }
804c9225affSStefano Zampini   if (ismpibaij) { /* destroy converted local matrices */
805c9225affSStefano Zampini     ierr = MatDestroy(&Ad);CHKERRQ(ierr);
806c9225affSStefano Zampini     ierr = MatDestroy(&Ao);CHKERRQ(ierr);
807c9225affSStefano Zampini   }
8086989cf23SStefano Zampini 
8096989cf23SStefano Zampini   /* finalize matrix */
810c9225affSStefano Zampini   ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
8116989cf23SStefano Zampini   ierr = MatDestroy(&lA);CHKERRQ(ierr);
812c9225affSStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
813c9225affSStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
814c9225affSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
815c9225affSStefano Zampini     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
816c9225affSStefano Zampini   } else *newmat = B;
8176989cf23SStefano Zampini   PetscFunctionReturn(0);
8186989cf23SStefano Zampini }
8196989cf23SStefano Zampini 
8205e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
8215e3038f0Sstefano_zampini {
8225e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
8235e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
8245e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
8255e3038f0Sstefano_zampini   MPI_Comm               comm;
8265b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
8275b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
8289e7b2b25Sstefano_zampini   PetscBool              convert,lreuse,*istrans;
8295e3038f0Sstefano_zampini   PetscErrorCode         ierr;
8305e3038f0Sstefano_zampini 
831ab4d48faSStefano Zampini   PetscFunctionBegin;
8325e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
8335e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
8345e3038f0Sstefano_zampini   rnest  = NULL;
8355e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
8365e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
8375e3038f0Sstefano_zampini 
8385e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
839*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!ismatis,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type_name);
8405e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
8415e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
8425e3038f0Sstefano_zampini     if (isnest) {
8435e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
8445e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
8455e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
8465e3038f0Sstefano_zampini     }
8475e3038f0Sstefano_zampini   }
8485e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
8495b003df0Sstefano_zampini   ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr);
850071fcb05SBarry Smith   ierr = PetscCalloc6(nr,&isrow,nc,&iscol,nr,&islrow,nc,&islcol,nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr);
8515e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
8525e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
8535e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
8545e3038f0Sstefano_zampini       PetscBool ismatis;
8559e7b2b25Sstefano_zampini       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
8565e3038f0Sstefano_zampini 
8575e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
8585e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
8595e3038f0Sstefano_zampini 
8605e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
8619e7b2b25Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr);
8629e7b2b25Sstefano_zampini       if (istrans[ij]) {
8639e7b2b25Sstefano_zampini         Mat T,lT;
8649e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
8659e7b2b25Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr);
866*2c71b3e2SJacob Faibussowitsch         PetscCheckFalse(!ismatis,comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") (transposed) is not of type MATIS",i,j);
8679e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr);
8689e7b2b25Sstefano_zampini         ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr);
8699e7b2b25Sstefano_zampini       } else {
8705e3038f0Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
871*2c71b3e2SJacob Faibussowitsch         PetscCheckFalse(!ismatis,comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") is not of type MATIS",i,j);
8729e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
8739e7b2b25Sstefano_zampini       }
8745e3038f0Sstefano_zampini 
8755e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
8765e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
8779e7b2b25Sstefano_zampini       ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr);
8785e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
879*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(lr[i] && l1 != lr[i],PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid local size %" PetscInt_FMT " != %" PetscInt_FMT,i,j,lr[i],l1);
880*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(lc[j] && l2 != lc[j],PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid local size %" PetscInt_FMT " != %" PetscInt_FMT,i,j,lc[j],l2);
8815e3038f0Sstefano_zampini       lr[i] = l1;
8825e3038f0Sstefano_zampini       lc[j] = l2;
8835e3038f0Sstefano_zampini 
8845e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
8855e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
8865e3038f0Sstefano_zampini     }
8875e3038f0Sstefano_zampini   }
8885e3038f0Sstefano_zampini 
88976bd3646SJed Brown   if (PetscDefined (USE_DEBUG)) {
8905e3038f0Sstefano_zampini     /* Check compatibility of l2g maps for rows */
8915e3038f0Sstefano_zampini     for (i=0;i<nr;i++) {
8925e3038f0Sstefano_zampini       rl2g = NULL;
8935e3038f0Sstefano_zampini       for (j=0;j<nc;j++) {
8945e3038f0Sstefano_zampini         PetscInt n1,n2;
8955e3038f0Sstefano_zampini 
8965e3038f0Sstefano_zampini         if (!nest[i][j]) continue;
8979e7b2b25Sstefano_zampini         if (istrans[i*nc+j]) {
8989e7b2b25Sstefano_zampini           Mat T;
8999e7b2b25Sstefano_zampini 
9009e7b2b25Sstefano_zampini           ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
9019e7b2b25Sstefano_zampini           ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr);
9029e7b2b25Sstefano_zampini         } else {
9035e3038f0Sstefano_zampini           ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
9049e7b2b25Sstefano_zampini         }
9055e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
9065e3038f0Sstefano_zampini         if (!n1) continue;
9075e3038f0Sstefano_zampini         if (!rl2g) {
9085e3038f0Sstefano_zampini           rl2g = cl2g;
9095e3038f0Sstefano_zampini         } else {
9105e3038f0Sstefano_zampini           const PetscInt *idxs1,*idxs2;
9115e3038f0Sstefano_zampini           PetscBool      same;
9125e3038f0Sstefano_zampini 
9135e3038f0Sstefano_zampini           ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
914*2c71b3e2SJacob Faibussowitsch           PetscCheckFalse(n1 != n2,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid row l2gmap size %" PetscInt_FMT " != %" PetscInt_FMT,i,j,n1,n2);
9155e3038f0Sstefano_zampini           ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
9165e3038f0Sstefano_zampini           ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
917580bdb30SBarry Smith           ierr = PetscArraycmp(idxs1,idxs2,n1,&same);CHKERRQ(ierr);
9185e3038f0Sstefano_zampini           ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
9195e3038f0Sstefano_zampini           ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
920*2c71b3e2SJacob Faibussowitsch           PetscCheckFalse(!same,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid row l2gmap",i,j);
9215e3038f0Sstefano_zampini         }
9225e3038f0Sstefano_zampini       }
9235e3038f0Sstefano_zampini     }
9245e3038f0Sstefano_zampini     /* Check compatibility of l2g maps for columns */
9255e3038f0Sstefano_zampini     for (i=0;i<nc;i++) {
9265e3038f0Sstefano_zampini       rl2g = NULL;
9275e3038f0Sstefano_zampini       for (j=0;j<nr;j++) {
9285e3038f0Sstefano_zampini         PetscInt n1,n2;
9295e3038f0Sstefano_zampini 
9305e3038f0Sstefano_zampini         if (!nest[j][i]) continue;
9319e7b2b25Sstefano_zampini         if (istrans[j*nc+i]) {
9329e7b2b25Sstefano_zampini           Mat T;
9339e7b2b25Sstefano_zampini 
9349e7b2b25Sstefano_zampini           ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr);
9359e7b2b25Sstefano_zampini           ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr);
9369e7b2b25Sstefano_zampini         } else {
9375e3038f0Sstefano_zampini           ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
9389e7b2b25Sstefano_zampini         }
9395e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
9405e3038f0Sstefano_zampini         if (!n1) continue;
9415e3038f0Sstefano_zampini         if (!rl2g) {
9425e3038f0Sstefano_zampini           rl2g = cl2g;
9435e3038f0Sstefano_zampini         } else {
9445e3038f0Sstefano_zampini           const PetscInt *idxs1,*idxs2;
9455e3038f0Sstefano_zampini           PetscBool      same;
9465e3038f0Sstefano_zampini 
9475e3038f0Sstefano_zampini           ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
948*2c71b3e2SJacob Faibussowitsch           PetscCheckFalse(n1 != n2,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid column l2gmap size %" PetscInt_FMT " != %" PetscInt_FMT,j,i,n1,n2);
9495e3038f0Sstefano_zampini           ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
9505e3038f0Sstefano_zampini           ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
951580bdb30SBarry Smith           ierr = PetscArraycmp(idxs1,idxs2,n1,&same);CHKERRQ(ierr);
9525e3038f0Sstefano_zampini           ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
9535e3038f0Sstefano_zampini           ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
954*2c71b3e2SJacob Faibussowitsch           PetscCheckFalse(!same,PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%" PetscInt_FMT ",%" PetscInt_FMT ") has invalid column l2gmap",j,i);
9555e3038f0Sstefano_zampini         }
9565e3038f0Sstefano_zampini       }
9575e3038f0Sstefano_zampini     }
95876bd3646SJed Brown   }
9595e3038f0Sstefano_zampini 
9605e3038f0Sstefano_zampini   B = NULL;
9615e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
9625b003df0Sstefano_zampini     PetscInt stl;
9635b003df0Sstefano_zampini 
9645e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
9655e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
9665e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
9675b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
9685e3038f0Sstefano_zampini       Mat            usedmat;
9695e3038f0Sstefano_zampini       Mat_IS         *matis;
9705e3038f0Sstefano_zampini       const PetscInt *idxs;
9715e3038f0Sstefano_zampini 
9725e3038f0Sstefano_zampini       /* local IS for local NEST */
9735b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
9745e3038f0Sstefano_zampini 
9755e3038f0Sstefano_zampini       /* l2gmap */
9765e3038f0Sstefano_zampini       j = 0;
9775e3038f0Sstefano_zampini       usedmat = nest[i][j];
9789e7b2b25Sstefano_zampini       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
979*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!usedmat,comm,PETSC_ERR_SUP,"Cannot find valid row mat");
9809e7b2b25Sstefano_zampini 
9819e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
9829e7b2b25Sstefano_zampini         Mat T;
9839e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
9849e7b2b25Sstefano_zampini         usedmat = T;
9859e7b2b25Sstefano_zampini       }
9865e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
9875e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
9889e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
989ad227feaSJunchao Zhang         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE);CHKERRQ(ierr);
990ad227feaSJunchao Zhang         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE);CHKERRQ(ierr);
9919e7b2b25Sstefano_zampini       } else {
992ad227feaSJunchao Zhang         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE);CHKERRQ(ierr);
993ad227feaSJunchao Zhang         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE);CHKERRQ(ierr);
9949e7b2b25Sstefano_zampini       }
9955e3038f0Sstefano_zampini       ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
9965e3038f0Sstefano_zampini       stl += lr[i];
9975e3038f0Sstefano_zampini     }
9985e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
9995e3038f0Sstefano_zampini 
10005e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
10015e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
10025e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
10035b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
10045e3038f0Sstefano_zampini       Mat            usedmat;
10055e3038f0Sstefano_zampini       Mat_IS         *matis;
10065e3038f0Sstefano_zampini       const PetscInt *idxs;
10075e3038f0Sstefano_zampini 
10085e3038f0Sstefano_zampini       /* local IS for local NEST */
10095b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
10105e3038f0Sstefano_zampini 
10115e3038f0Sstefano_zampini       /* l2gmap */
10125e3038f0Sstefano_zampini       j = 0;
10135e3038f0Sstefano_zampini       usedmat = nest[j][i];
10149e7b2b25Sstefano_zampini       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
1015*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(!usedmat,comm,PETSC_ERR_SUP,"Cannot find valid column mat");
10169e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
10179e7b2b25Sstefano_zampini         Mat T;
10189e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
10199e7b2b25Sstefano_zampini         usedmat = T;
10209e7b2b25Sstefano_zampini       }
10215e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
10225e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
10239e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
1024ad227feaSJunchao Zhang         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE);CHKERRQ(ierr);
1025ad227feaSJunchao Zhang         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE);CHKERRQ(ierr);
10269e7b2b25Sstefano_zampini       } else {
1027ad227feaSJunchao Zhang         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE);CHKERRQ(ierr);
1028ad227feaSJunchao Zhang         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl,MPI_REPLACE);CHKERRQ(ierr);
10299e7b2b25Sstefano_zampini       }
10305e3038f0Sstefano_zampini       ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
10315e3038f0Sstefano_zampini       stl += lc[i];
10325e3038f0Sstefano_zampini     }
10335e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
10345e3038f0Sstefano_zampini 
10355e3038f0Sstefano_zampini     /* Create MATIS */
10365e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
10375e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
10385e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
10395e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
10405e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
10418546b261SStefano Zampini     ierr = MatISSetLocalMatType(B,MATNEST);CHKERRQ(ierr);
10428546b261SStefano Zampini     { /* hack : avoid setup of scatters */
10438546b261SStefano Zampini       Mat_IS *matis = (Mat_IS*)(B->data);
10448546b261SStefano Zampini       matis->islocalref = PETSC_TRUE;
10458546b261SStefano Zampini     }
10465e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
10475e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
10485e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
10495e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
10508546b261SStefano Zampini     ierr = MatNestSetVecType(lA,VECNEST);CHKERRQ(ierr);
10519e7b2b25Sstefano_zampini     for (i=0;i<nr*nc;i++) {
10529e7b2b25Sstefano_zampini       if (istrans[i]) {
10539e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
10549e7b2b25Sstefano_zampini       }
10559e7b2b25Sstefano_zampini     }
10565e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
10575e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
10588546b261SStefano Zampini     { /* hack : setup of scatters done here */
10598546b261SStefano Zampini       Mat_IS *matis = (Mat_IS*)(B->data);
10608546b261SStefano Zampini 
10618546b261SStefano Zampini       matis->islocalref = PETSC_FALSE;
10628546b261SStefano Zampini       ierr = MatISSetUpScatters_Private(B);CHKERRQ(ierr);
10638546b261SStefano Zampini     }
10645e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10655e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10665e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
10675e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
10685e3038f0Sstefano_zampini     } else {
10695e3038f0Sstefano_zampini       *newmat = B;
10705e3038f0Sstefano_zampini     }
10715e3038f0Sstefano_zampini   } else {
10725e3038f0Sstefano_zampini     if (lreuse) {
10735e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
10745e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
10755e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
10765e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
10775e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
10789e7b2b25Sstefano_zampini             if (istrans[i*nc+j]) {
10799e7b2b25Sstefano_zampini               ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr);
10809e7b2b25Sstefano_zampini             }
10815e3038f0Sstefano_zampini           }
10825e3038f0Sstefano_zampini         }
10835e3038f0Sstefano_zampini       }
10845e3038f0Sstefano_zampini     } else {
10855b003df0Sstefano_zampini       PetscInt stl;
10865b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
10875b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
10885b003df0Sstefano_zampini         stl  += lr[i];
10895e3038f0Sstefano_zampini       }
10905b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
10915b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
10925b003df0Sstefano_zampini         stl  += lc[i];
10935e3038f0Sstefano_zampini       }
10945e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
1095ab4d48faSStefano Zampini       for (i=0;i<nr*nc;i++) {
10969e7b2b25Sstefano_zampini         if (istrans[i]) {
10979e7b2b25Sstefano_zampini           ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
10989e7b2b25Sstefano_zampini         }
1099ab4d48faSStefano Zampini       }
11005e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
11015e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
11025e3038f0Sstefano_zampini     }
11035e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11045e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11055e3038f0Sstefano_zampini   }
11065e3038f0Sstefano_zampini 
11075b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
11085b003df0Sstefano_zampini   convert = PETSC_FALSE;
11095b003df0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
11105b003df0Sstefano_zampini   if (convert) {
11115b003df0Sstefano_zampini     Mat              M;
11125b003df0Sstefano_zampini     MatISLocalFields lf;
11135b003df0Sstefano_zampini     PetscContainer   c;
11145b003df0Sstefano_zampini 
11155b003df0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
11165b003df0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
11175b003df0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
11185b003df0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
11195b003df0Sstefano_zampini 
11205b003df0Sstefano_zampini     /* attach local fields to the matrix */
11215b003df0Sstefano_zampini     ierr = PetscNew(&lf);CHKERRQ(ierr);
1122071fcb05SBarry Smith     ierr = PetscMalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr);
11235b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
11245b003df0Sstefano_zampini       PetscInt n,st;
11255b003df0Sstefano_zampini 
11265b003df0Sstefano_zampini       ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr);
11275b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr);
11285b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr);
11295b003df0Sstefano_zampini     }
11305b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
11315b003df0Sstefano_zampini       PetscInt n,st;
11325b003df0Sstefano_zampini 
11335b003df0Sstefano_zampini       ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr);
11345b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr);
11355b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr);
11365b003df0Sstefano_zampini     }
11375b003df0Sstefano_zampini     lf->nr = nr;
11385b003df0Sstefano_zampini     lf->nc = nc;
11395b003df0Sstefano_zampini     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr);
11405b003df0Sstefano_zampini     ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr);
11415b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr);
11425b003df0Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr);
11435b003df0Sstefano_zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
11445b003df0Sstefano_zampini   }
11455b003df0Sstefano_zampini 
11465e3038f0Sstefano_zampini   /* Free workspace */
11475e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
11485e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
11495e3038f0Sstefano_zampini   }
11505e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
11515e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
11525e3038f0Sstefano_zampini   }
11539e7b2b25Sstefano_zampini   ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr);
11545b003df0Sstefano_zampini   ierr = PetscFree2(lr,lc);CHKERRQ(ierr);
11555e3038f0Sstefano_zampini   PetscFunctionReturn(0);
11565e3038f0Sstefano_zampini }
11575e3038f0Sstefano_zampini 
1158ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
1159ad219c80Sstefano_zampini {
1160ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS*)A->data;
1161ad219c80Sstefano_zampini   Vec               ll,rr;
1162ad219c80Sstefano_zampini   const PetscScalar *Y,*X;
1163ad219c80Sstefano_zampini   PetscScalar       *x,*y;
1164ad219c80Sstefano_zampini   PetscErrorCode    ierr;
1165ad219c80Sstefano_zampini 
1166ad219c80Sstefano_zampini   PetscFunctionBegin;
1167ad219c80Sstefano_zampini   if (l) {
1168ad219c80Sstefano_zampini     ll   = matis->y;
1169ad219c80Sstefano_zampini     ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr);
1170ad219c80Sstefano_zampini     ierr = VecGetArray(ll,&y);CHKERRQ(ierr);
1171ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y,MPI_REPLACE);CHKERRQ(ierr);
1172ad219c80Sstefano_zampini   } else {
1173ad219c80Sstefano_zampini     ll = NULL;
1174ad219c80Sstefano_zampini   }
1175ad219c80Sstefano_zampini   if (r) {
1176ad219c80Sstefano_zampini     rr   = matis->x;
1177ad219c80Sstefano_zampini     ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr);
1178ad219c80Sstefano_zampini     ierr = VecGetArray(rr,&x);CHKERRQ(ierr);
1179ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x,MPI_REPLACE);CHKERRQ(ierr);
1180ad219c80Sstefano_zampini   } else {
1181ad219c80Sstefano_zampini     rr = NULL;
1182ad219c80Sstefano_zampini   }
1183ad219c80Sstefano_zampini   if (ll) {
1184ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y,MPI_REPLACE);CHKERRQ(ierr);
1185ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr);
1186ad219c80Sstefano_zampini     ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr);
1187ad219c80Sstefano_zampini   }
1188ad219c80Sstefano_zampini   if (rr) {
1189ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x,MPI_REPLACE);CHKERRQ(ierr);
1190ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr);
1191ad219c80Sstefano_zampini     ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr);
1192ad219c80Sstefano_zampini   }
1193ad219c80Sstefano_zampini   ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr);
1194ad219c80Sstefano_zampini   PetscFunctionReturn(0);
1195ad219c80Sstefano_zampini }
1196ad219c80Sstefano_zampini 
11977fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
11987fa8f2d3SStefano Zampini {
11997fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
12007fa8f2d3SStefano Zampini   MatInfo        info;
12013966268fSBarry Smith   PetscLogDouble isend[6],irecv[6];
12027fa8f2d3SStefano Zampini   PetscInt       bs;
12037fa8f2d3SStefano Zampini   PetscErrorCode ierr;
12047fa8f2d3SStefano Zampini 
12057fa8f2d3SStefano Zampini   PetscFunctionBegin;
12067fa8f2d3SStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
1207a2ccb5f9Sstefano_zampini   if (matis->A->ops->getinfo) {
12087fa8f2d3SStefano Zampini     ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
12097fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
12107fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
12117fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
12127fa8f2d3SStefano Zampini     isend[3] = info.memory;
12137fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
1214a2ccb5f9Sstefano_zampini   } else {
1215a2ccb5f9Sstefano_zampini     isend[0] = 0.;
1216a2ccb5f9Sstefano_zampini     isend[1] = 0.;
1217a2ccb5f9Sstefano_zampini     isend[2] = 0.;
1218a2ccb5f9Sstefano_zampini     isend[3] = 0.;
1219a2ccb5f9Sstefano_zampini     isend[4] = 0.;
1220a2ccb5f9Sstefano_zampini   }
1221314ce898Sstefano_zampini   isend[5] = matis->A->num_ass;
12227fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
12237fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
12247fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
12257fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
12267fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
12277fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
1228314ce898Sstefano_zampini     ginfo->assemblies   = isend[5];
12297fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
1230820f2d46SBarry Smith     ierr = MPIU_Allreduce(isend,irecv,6,MPIU_PETSCLOGDOUBLE,MPI_MAX,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr);
12317fa8f2d3SStefano Zampini 
12327fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
12337fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
12347fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
12357fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
12367fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
1237314ce898Sstefano_zampini     ginfo->assemblies   = irecv[5];
12387fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
1239820f2d46SBarry Smith     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_PETSCLOGDOUBLE,MPI_SUM,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr);
12407fa8f2d3SStefano Zampini 
12417fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
12427fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
12437fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
12447fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
12457fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
12467fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
12477fa8f2d3SStefano Zampini   }
12487fa8f2d3SStefano Zampini   ginfo->block_size        = bs;
12497fa8f2d3SStefano Zampini   ginfo->fill_ratio_given  = 0;
12507fa8f2d3SStefano Zampini   ginfo->fill_ratio_needed = 0;
12517fa8f2d3SStefano Zampini   ginfo->factor_mallocs    = 0;
12525e3038f0Sstefano_zampini   PetscFunctionReturn(0);
12535e3038f0Sstefano_zampini }
12545e3038f0Sstefano_zampini 
12558b9382cfSStefano Zampini static PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
1256d7f69cd0SStefano Zampini {
1257d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
1258d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
1259d7f69cd0SStefano Zampini 
1260d7f69cd0SStefano Zampini   PetscFunctionBegin;
1261cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
1262cf37664fSBarry Smith     ISLocalToGlobalMapping rl2g,cl2g;
1263d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
1264d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
1265d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
1266d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
1267d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
1268d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
1269cf37664fSBarry Smith   } else {
1270cf37664fSBarry Smith     C = *B;
1271d7f69cd0SStefano Zampini   }
1272d7f69cd0SStefano Zampini 
1273d7f69cd0SStefano Zampini   /* perform local transposition */
1274d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1275d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
1276d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
1277d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
1278d7f69cd0SStefano Zampini 
1279cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
1280d7f69cd0SStefano Zampini     *B = C;
1281d7f69cd0SStefano Zampini   } else {
1282d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
1283d7f69cd0SStefano Zampini   }
12847aa7aec5Sstefano_zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
12857aa7aec5Sstefano_zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1286d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
1287d7f69cd0SStefano Zampini }
1288d7f69cd0SStefano Zampini 
12898b9382cfSStefano Zampini static PetscErrorCode MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
12903fd1c9e7SStefano Zampini {
12913fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
12923fd1c9e7SStefano Zampini   PetscErrorCode ierr;
12933fd1c9e7SStefano Zampini 
12943fd1c9e7SStefano Zampini   PetscFunctionBegin;
12954b89b9cdSStefano Zampini   if (D) { /* MatShift_IS pass D = NULL */
12963fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12973fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12983fd1c9e7SStefano Zampini   }
12993fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
13003fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
13013fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
13023fd1c9e7SStefano Zampini }
13033fd1c9e7SStefano Zampini 
13048b9382cfSStefano Zampini static PetscErrorCode MatShift_IS(Mat A,PetscScalar a)
13053fd1c9e7SStefano Zampini {
13064b89b9cdSStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
13073fd1c9e7SStefano Zampini   PetscErrorCode ierr;
13083fd1c9e7SStefano Zampini 
13093fd1c9e7SStefano Zampini   PetscFunctionBegin;
13104b89b9cdSStefano Zampini   ierr = VecSet(is->y,a);CHKERRQ(ierr);
13113fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
13123fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
13133fd1c9e7SStefano Zampini }
13143fd1c9e7SStefano Zampini 
1315f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1316f26d0771SStefano Zampini {
1317f26d0771SStefano Zampini   PetscErrorCode ierr;
1318f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1319f26d0771SStefano Zampini 
1320f26d0771SStefano Zampini   PetscFunctionBegin;
1321*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION,PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= %d: they are %" PetscInt_FMT " %" PetscInt_FMT,MATIS_MAX_ENTRIES_INSERTION,m,n);
1322f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
1323f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
1324b4f971dfSStefano Zampini   ierr = MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
1325f26d0771SStefano Zampini   PetscFunctionReturn(0);
1326f26d0771SStefano Zampini }
1327f26d0771SStefano Zampini 
1328f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1329f26d0771SStefano Zampini {
1330f26d0771SStefano Zampini   PetscErrorCode ierr;
1331f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1332f26d0771SStefano Zampini 
1333f26d0771SStefano Zampini   PetscFunctionBegin;
1334*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION,PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column block indices must be <= %d: they are %" PetscInt_FMT " %" PetscInt_FMT,MATIS_MAX_ENTRIES_INSERTION,m,n);
1335f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
1336f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
1337b4f971dfSStefano Zampini   ierr = MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
1338f26d0771SStefano Zampini   PetscFunctionReturn(0);
1339f26d0771SStefano Zampini }
1340f26d0771SStefano Zampini 
13417dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
1342a8116848SStefano Zampini {
1343a8116848SStefano Zampini   Mat               locmat,newlocmat;
1344a8116848SStefano Zampini   Mat_IS            *newmatis;
1345a8116848SStefano Zampini   const PetscInt    *idxs;
1346a8116848SStefano Zampini   PetscInt          i,m,n;
1347a8116848SStefano Zampini   PetscErrorCode    ierr;
1348a8116848SStefano Zampini 
1349a8116848SStefano Zampini   PetscFunctionBegin;
1350a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
1351a8116848SStefano Zampini     PetscBool ismatis;
1352a8116848SStefano Zampini 
1353a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
1354*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!ismatis,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
1355a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
1356*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!newmatis->getsub_ris,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
1357*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!newmatis->getsub_cis,PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
1358a8116848SStefano Zampini   }
1359a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
136076bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
136176bd3646SJed Brown     Vec               rtest,ltest;
136276bd3646SJed Brown     const PetscScalar *array;
136376bd3646SJed Brown 
1364a8116848SStefano Zampini     ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
1365a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
1366a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
1367a8116848SStefano Zampini     for (i=0;i<n;i++) {
1368a8116848SStefano Zampini       ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
1369a8116848SStefano Zampini     }
1370a8116848SStefano Zampini     ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
1371a8116848SStefano Zampini     ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
1372a8116848SStefano Zampini     ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
1373a8116848SStefano Zampini     ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
1374a8116848SStefano Zampini     ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
1375*2c71b3e2SJacob Faibussowitsch     for (i=0;i<n;i++) PetscCheckFalse(array[i] != 0. && array[i] != 1.,PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %" PetscInt_FMT " counted %" PetscInt_FMT " times! Irow may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i]));
1376a8116848SStefano Zampini     ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
1377a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
1378a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
1379a8116848SStefano Zampini     ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
1380a8116848SStefano Zampini     for (i=0;i<n;i++) {
1381a8116848SStefano Zampini       ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
1382a8116848SStefano Zampini     }
1383a8116848SStefano Zampini     ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
1384a8116848SStefano Zampini     ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
1385a8116848SStefano Zampini     ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
1386a8116848SStefano Zampini     ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
1387a8116848SStefano Zampini     ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
1388*2c71b3e2SJacob Faibussowitsch     for (i=0;i<n;i++) PetscCheckFalse(array[i] != 0. && array[i] != 1.,PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %" PetscInt_FMT " counted %" PetscInt_FMT " times! Icol may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i]));
1389a8116848SStefano Zampini     ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
1390a8116848SStefano Zampini     ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
1391a8116848SStefano Zampini     ierr = VecDestroy(&rtest);CHKERRQ(ierr);
1392a8116848SStefano Zampini     ierr = VecDestroy(&ltest);CHKERRQ(ierr);
139376bd3646SJed Brown   }
1394a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1395a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
1396a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
1397a8116848SStefano Zampini     IS                     is;
1398a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
1399306cf5c7SStefano Zampini     PetscInt               ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs;
140094342113SStefano Zampini     PetscBool              cong;
1401a8116848SStefano Zampini     MPI_Comm               comm;
1402a8116848SStefano Zampini 
1403a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
1404306cf5c7SStefano Zampini     ierr = MatGetBlockSizes(mat,&arbs,&acbs);CHKERRQ(ierr);
1405306cf5c7SStefano Zampini     ierr = ISGetBlockSize(irow,&irbs);CHKERRQ(ierr);
1406306cf5c7SStefano Zampini     ierr = ISGetBlockSize(icol,&icbs);CHKERRQ(ierr);
1407306cf5c7SStefano Zampini     rbs  = arbs == irbs ? irbs : 1;
1408306cf5c7SStefano Zampini     cbs  = acbs == icbs ? icbs : 1;
1409a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
1410a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
1411a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
1412a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
1413a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1414306cf5c7SStefano Zampini     ierr = MatSetBlockSizes(*newmat,rbs,cbs);CHKERRQ(ierr);
1415a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
1416a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
1417a72d46e8SStefano Zampini     ierr = PetscLayoutMapLocal(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
1418a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
1419580bdb30SBarry Smith     ierr = PetscArrayzero(matis->sf_rootdata,matis->sf->nroots);CHKERRQ(ierr);
1420a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
1421a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
1422a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
1423ad227feaSJunchao Zhang     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE);CHKERRQ(ierr);
1424ad227feaSJunchao Zhang     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE);CHKERRQ(ierr);
14253d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
1426a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
1427a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
14283d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
1429a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
1430a8116848SStefano Zampini         lidxs[newloc] = i;
1431a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
1432a8116848SStefano Zampini       }
1433a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1434a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
1435306cf5c7SStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(rl2g,rbs);CHKERRQ(ierr);
1436a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
1437a8116848SStefano Zampini     /* local is to extract local submatrix */
1438a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
1439a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
144094342113SStefano Zampini     ierr = MatHasCongruentLayouts(mat,&cong);CHKERRQ(ierr);
144194342113SStefano Zampini     if (cong && irow == icol && matis->csf == matis->sf) {
1442a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
1443a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
1444a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
1445a8116848SStefano Zampini     } else {
1446a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
1447a8116848SStefano Zampini 
1448a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
1449a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
1450a72d46e8SStefano Zampini       ierr = PetscLayoutMapLocal(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
1451a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
1452580bdb30SBarry Smith       ierr = PetscArrayzero(matis->csf_rootdata,matis->csf->nroots);CHKERRQ(ierr);
1453a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
1454a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
1455a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
1456ad227feaSJunchao Zhang       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata,MPI_REPLACE);CHKERRQ(ierr);
1457ad227feaSJunchao Zhang       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata,MPI_REPLACE);CHKERRQ(ierr);
14583d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
1459a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
1460a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
14613d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
1462a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
1463a8116848SStefano Zampini           lidxs[newloc] = i;
1464a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
1465a8116848SStefano Zampini         }
1466a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1467a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
1468306cf5c7SStefano Zampini       ierr = ISLocalToGlobalMappingSetBlockSize(cl2g,cbs);CHKERRQ(ierr);
1469a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
1470a8116848SStefano Zampini       /* local is to extract local submatrix */
1471a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
1472a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
1473a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1474a8116848SStefano Zampini     }
1475a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1476a8116848SStefano Zampini   } else {
1477a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
1478a8116848SStefano Zampini   }
1479a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
1480a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
14817dae84e0SHong Zhang   ierr = MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
1482a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1483a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
1484a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
1485a8116848SStefano Zampini   }
1486a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1487a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1488a8116848SStefano Zampini   PetscFunctionReturn(0);
1489a8116848SStefano Zampini }
1490a8116848SStefano Zampini 
1491a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
14922b404112SStefano Zampini {
14932b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
14942b404112SStefano Zampini   PetscBool      ismatis;
14952b404112SStefano Zampini   PetscErrorCode ierr;
14962b404112SStefano Zampini 
14972b404112SStefano Zampini   PetscFunctionBegin;
14982b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
1499*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!ismatis,PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
15002b404112SStefano Zampini   b = (Mat_IS*)B->data;
15012b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
1502cdc753b6SBarry Smith   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
15032b404112SStefano Zampini   PetscFunctionReturn(0);
15042b404112SStefano Zampini }
15052b404112SStefano Zampini 
1506a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
15076bd84002SStefano Zampini {
1508527b2640SStefano Zampini   Vec               v;
1509527b2640SStefano Zampini   const PetscScalar *array;
1510527b2640SStefano Zampini   PetscInt          i,n;
15116bd84002SStefano Zampini   PetscErrorCode    ierr;
15126bd84002SStefano Zampini 
15136bd84002SStefano Zampini   PetscFunctionBegin;
1514527b2640SStefano Zampini   *missing = PETSC_FALSE;
1515527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
1516527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
1517527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1518527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
1519527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
1520527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
1521527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1522527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
1523527b2640SStefano Zampini   if (d) {
1524527b2640SStefano Zampini     *d = -1;
1525527b2640SStefano Zampini     if (*missing) {
1526527b2640SStefano Zampini       PetscInt rstart;
1527527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
1528527b2640SStefano Zampini       *d = i+rstart;
1529527b2640SStefano Zampini     }
1530527b2640SStefano Zampini   }
15316bd84002SStefano Zampini   PetscFunctionReturn(0);
15326bd84002SStefano Zampini }
15336bd84002SStefano Zampini 
1534cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
153528f4e0baSStefano Zampini {
153628f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
153728f4e0baSStefano Zampini   const PetscInt *gidxs;
15384f2d7cafSStefano Zampini   PetscInt       nleaves;
153928f4e0baSStefano Zampini   PetscErrorCode ierr;
154028f4e0baSStefano Zampini 
154128f4e0baSStefano Zampini   PetscFunctionBegin;
15424f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
154328f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
15443bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
15454f2d7cafSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
15464f2d7cafSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
15473bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
15484f2d7cafSStefano Zampini   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
1549a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
15503d996552SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
1551a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
1552a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
15533d996552SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
1554a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
15553d996552SStefano Zampini     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
1556a8116848SStefano Zampini   } else {
1557a8116848SStefano Zampini     matis->csf = matis->sf;
1558a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
1559a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
1560a8116848SStefano Zampini   }
156128f4e0baSStefano Zampini   PetscFunctionReturn(0);
156228f4e0baSStefano Zampini }
15632e1947a5SStefano Zampini 
1564eb82efa4SStefano Zampini /*@
156575d48cdbSStefano Zampini    MatISStoreL2L - Store local-to-local operators during the Galerkin process of MatPtAP.
156675d48cdbSStefano Zampini 
1567d083f849SBarry Smith    Collective
156875d48cdbSStefano Zampini 
156975d48cdbSStefano Zampini    Input Parameters:
157075d48cdbSStefano Zampini +  A - the matrix
157175d48cdbSStefano Zampini -  store - the boolean flag
157275d48cdbSStefano Zampini 
157375d48cdbSStefano Zampini    Level: advanced
157475d48cdbSStefano Zampini 
157575d48cdbSStefano Zampini    Notes:
157675d48cdbSStefano Zampini 
157775d48cdbSStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatPtAP()
157875d48cdbSStefano Zampini @*/
157975d48cdbSStefano Zampini PetscErrorCode MatISStoreL2L(Mat A, PetscBool store)
158075d48cdbSStefano Zampini {
158175d48cdbSStefano Zampini   PetscErrorCode ierr;
158275d48cdbSStefano Zampini 
158375d48cdbSStefano Zampini   PetscFunctionBegin;
158475d48cdbSStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
158575d48cdbSStefano Zampini   PetscValidType(A,1);
158675d48cdbSStefano Zampini   PetscValidLogicalCollectiveBool(A,store,2);
158775d48cdbSStefano Zampini   ierr = PetscTryMethod(A,"MatISStoreL2L_C",(Mat,PetscBool),(A,store));CHKERRQ(ierr);
158875d48cdbSStefano Zampini   PetscFunctionReturn(0);
158975d48cdbSStefano Zampini }
159075d48cdbSStefano Zampini 
159175d48cdbSStefano Zampini static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store)
159275d48cdbSStefano Zampini {
159375d48cdbSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(A->data);
159475d48cdbSStefano Zampini   PetscErrorCode ierr;
159575d48cdbSStefano Zampini 
159675d48cdbSStefano Zampini   PetscFunctionBegin;
159775d48cdbSStefano Zampini   matis->storel2l = store;
159875d48cdbSStefano Zampini   if (!store) {
159975d48cdbSStefano Zampini     ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",NULL);CHKERRQ(ierr);
160075d48cdbSStefano Zampini   }
160175d48cdbSStefano Zampini   PetscFunctionReturn(0);
160275d48cdbSStefano Zampini }
160375d48cdbSStefano Zampini 
160475d48cdbSStefano Zampini /*@
1605f03112d0SStefano Zampini    MatISFixLocalEmpty - Compress out zero local rows from the local matrices
1606f03112d0SStefano Zampini 
1607d083f849SBarry Smith    Collective
1608f03112d0SStefano Zampini 
1609f03112d0SStefano Zampini    Input Parameters:
1610f03112d0SStefano Zampini +  A - the matrix
1611f03112d0SStefano Zampini -  fix - the boolean flag
1612f03112d0SStefano Zampini 
1613f03112d0SStefano Zampini    Level: advanced
1614f03112d0SStefano Zampini 
1615f03112d0SStefano Zampini    Notes: When fix is true, new local matrices and l2g maps are generated during the final assembly process.
1616f03112d0SStefano Zampini 
1617f03112d0SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatAssemblyEnd(), MAT_FINAL_ASSEMBLY
1618f03112d0SStefano Zampini @*/
1619f03112d0SStefano Zampini PetscErrorCode MatISFixLocalEmpty(Mat A, PetscBool fix)
1620f03112d0SStefano Zampini {
1621f03112d0SStefano Zampini   PetscErrorCode ierr;
1622f03112d0SStefano Zampini 
1623f03112d0SStefano Zampini   PetscFunctionBegin;
1624f03112d0SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1625f03112d0SStefano Zampini   PetscValidType(A,1);
1626f03112d0SStefano Zampini   PetscValidLogicalCollectiveBool(A,fix,2);
1627f03112d0SStefano Zampini   ierr = PetscTryMethod(A,"MatISFixLocalEmpty_C",(Mat,PetscBool),(A,fix));CHKERRQ(ierr);
1628f03112d0SStefano Zampini   PetscFunctionReturn(0);
1629f03112d0SStefano Zampini }
1630f03112d0SStefano Zampini 
1631f03112d0SStefano Zampini static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix)
1632f03112d0SStefano Zampini {
1633f03112d0SStefano Zampini   Mat_IS *matis = (Mat_IS*)(A->data);
1634f03112d0SStefano Zampini 
1635f03112d0SStefano Zampini   PetscFunctionBegin;
1636f03112d0SStefano Zampini   matis->locempty = fix;
1637f03112d0SStefano Zampini   PetscFunctionReturn(0);
1638f03112d0SStefano Zampini }
1639f03112d0SStefano Zampini 
1640f03112d0SStefano Zampini /*@
1641a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
1642a88811baSStefano Zampini 
1643d083f849SBarry Smith    Collective
1644a88811baSStefano Zampini 
1645a88811baSStefano Zampini    Input Parameters:
1646a88811baSStefano Zampini +  B - the matrix
1647a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1648a88811baSStefano Zampini            (same value is used for all local rows)
1649a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
1650a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
1651a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
1652a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
1653a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
1654a88811baSStefano Zampini            the diagonal entry even if it is zero.
1655a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1656a88811baSStefano Zampini            submatrix (same value is used for all local rows).
1657a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
1658a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
1659a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
1660a88811baSStefano Zampini            structure. The size of this array is equal to the number
1661a88811baSStefano Zampini            of local rows, i.e 'm'.
1662a88811baSStefano Zampini 
1663a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
1664a88811baSStefano Zampini 
1665a88811baSStefano Zampini    Level: intermediate
1666a88811baSStefano Zampini 
166795452b02SPatrick Sanan    Notes:
166895452b02SPatrick Sanan     This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
1669a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
1670a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1671a88811baSStefano Zampini 
16723c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
1673a88811baSStefano Zampini @*/
16742e1947a5SStefano Zampini PetscErrorCode MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
16752e1947a5SStefano Zampini {
16762e1947a5SStefano Zampini   PetscErrorCode ierr;
16772e1947a5SStefano Zampini 
16782e1947a5SStefano Zampini   PetscFunctionBegin;
16792e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
16802e1947a5SStefano Zampini   PetscValidType(B,1);
16812e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
16822e1947a5SStefano Zampini   PetscFunctionReturn(0);
16832e1947a5SStefano Zampini }
16842e1947a5SStefano Zampini 
1685844bd0d7SStefano Zampini /* this is used by DMDA */
1686844bd0d7SStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
16872e1947a5SStefano Zampini {
16882e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
168928f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
16902e1947a5SStefano Zampini   PetscErrorCode ierr;
16912e1947a5SStefano Zampini 
16922e1947a5SStefano Zampini   PetscFunctionBegin;
1693fc989267SStefano Zampini   ierr = MatSetUp(B);CHKERRQ(ierr);
16944f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
16954f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
16964f2d7cafSStefano Zampini 
16974f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
16984f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
16994f2d7cafSStefano Zampini 
1700ad227feaSJunchao Zhang   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE);CHKERRQ(ierr);
170128f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
170228f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
1703ad227feaSJunchao Zhang   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE);CHKERRQ(ierr);
17044f2d7cafSStefano Zampini 
17054f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
170628f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
17070f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE)
17080f2f62c7SStefano Zampini   ierr = MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL);CHKERRQ(ierr);
17090f2f62c7SStefano Zampini #endif
17104f2d7cafSStefano Zampini 
1711fc989267SStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) {
1712fc989267SStefano Zampini     PetscInt b;
1713fc989267SStefano Zampini 
1714fc989267SStefano Zampini     matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
1715fc989267SStefano Zampini     for (b=1;b<bs;b++) {
1716fc989267SStefano Zampini       matis->sf_leafdata[i] = PetscMax(matis->sf_leafdata[i],matis->sf_leafdata[i*bs+b]/bs);
1717fc989267SStefano Zampini     }
1718fc989267SStefano Zampini   }
171928f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
17204f2d7cafSStefano Zampini 
172100a59248SStefano Zampini   nlocalcols /= bs;
172200a59248SStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols - i);
172328f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
17240f2f62c7SStefano Zampini 
17250f2f62c7SStefano Zampini   /* for other matrix types */
17260f2f62c7SStefano Zampini   ierr = MatSetUp(matis->A);CHKERRQ(ierr);
17272e1947a5SStefano Zampini   PetscFunctionReturn(0);
17282e1947a5SStefano Zampini }
1729b4319ba4SBarry Smith 
17303927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
17313927de2eSStefano Zampini {
17323927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
17333927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1734ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
17353927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
17363927de2eSStefano Zampini   PetscInt        lrows,lcols;
17373927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
1738f03112d0SStefano Zampini   PetscMPIInt     size;
17393927de2eSStefano Zampini   PetscBool       isdense,issbaij;
17403927de2eSStefano Zampini   PetscErrorCode  ierr;
17413927de2eSStefano Zampini 
17423927de2eSStefano Zampini   PetscFunctionBegin;
1743ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRMPI(ierr);
17443927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
17453927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
17463927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1747b9e7e5c1SBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
1748b9e7e5c1SBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1749ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1750ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
17517230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1752ecf5a873SStefano Zampini   } else {
1753ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
1754ecf5a873SStefano Zampini   }
1755ecf5a873SStefano Zampini 
17563927de2eSStefano Zampini   if (issbaij) {
17573927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
17583927de2eSStefano Zampini   }
17593927de2eSStefano Zampini   /*
1760ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
17613927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
17623927de2eSStefano Zampini   */
17633927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
17643927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
17653927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
17663927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
17673927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
1768f03112d0SStefano Zampini   for (i=0;i<size;i++) {
17693927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
17703927de2eSStefano Zampini       row_ownership[j] = i;
17713927de2eSStefano Zampini     }
17723927de2eSStefano Zampini   }
17737230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
17743927de2eSStefano Zampini 
17753927de2eSStefano Zampini   /*
17763927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
17773927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
17783927de2eSStefano Zampini   */
17793927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
17803927de2eSStefano Zampini   /* preallocation as a MATAIJ */
17813927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
17823927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
178312dfadf8SStefano Zampini       PetscInt owner = row_ownership[global_indices_r[i]];
178412dfadf8SStefano Zampini       for (j=0;j<local_cols;j++) {
1785ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
17863927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */
17873927de2eSStefano Zampini           my_dnz[i] += 1;
17883927de2eSStefano Zampini         } else { /* offdiag block */
17893927de2eSStefano Zampini           my_onz[i] += 1;
17903927de2eSStefano Zampini         }
17913927de2eSStefano Zampini       }
17923927de2eSStefano Zampini     }
1793bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1794bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1795bb1015c3SStefano Zampini     PetscBool      done;
1796bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1797*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!done,PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1798bb1015c3SStefano Zampini     jptr = jj;
1799bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1800bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1801bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1802bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1803bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1804bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */
1805bb1015c3SStefano Zampini           my_dnz[i] += 1;
1806bb1015c3SStefano Zampini         } else { /* offdiag block */
1807bb1015c3SStefano Zampini           my_onz[i] += 1;
1808bb1015c3SStefano Zampini         }
1809bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1810bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1811bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1812bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1]) {
1813bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1814bb1015c3SStefano Zampini           } else {
1815bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1816bb1015c3SStefano Zampini           }
1817bb1015c3SStefano Zampini         }
1818bb1015c3SStefano Zampini       }
1819bb1015c3SStefano Zampini     }
1820bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1821*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!done,PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1822bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
18233927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
18243927de2eSStefano Zampini       const PetscInt *cols;
1825ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
18263927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
18273927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
18283927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1829ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
18303927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1]) { /* diag block */
18313927de2eSStefano Zampini           my_dnz[i] += 1;
18323927de2eSStefano Zampini         } else { /* offdiag block */
18333927de2eSStefano Zampini           my_onz[i] += 1;
18343927de2eSStefano Zampini         }
18353927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1836d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
18373927de2eSStefano Zampini           owner = row_ownership[index_col];
18383927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1]) {
1839d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
18403927de2eSStefano Zampini           } else {
1841d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
18423927de2eSStefano Zampini           }
18433927de2eSStefano Zampini         }
18443927de2eSStefano Zampini       }
18453927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
18463927de2eSStefano Zampini     }
18473927de2eSStefano Zampini   }
1848ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
18497230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1850ecf5a873SStefano Zampini   }
18514f619741Sstefano_zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
18523927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1853ecf5a873SStefano Zampini 
1854ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
18553927de2eSStefano Zampini   if (maxreduce) {
18563927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
18573927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1858bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
18593927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
18603927de2eSStefano Zampini   } else {
18613927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
18623927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1863bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
18643927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
18653927de2eSStefano Zampini   }
18663927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
18673927de2eSStefano Zampini 
18683927de2eSStefano Zampini   /* Resize preallocation if overestimated */
18693927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
18703927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
18713927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
18723927de2eSStefano Zampini   }
18731670daf9Sstefano_zampini 
18741670daf9Sstefano_zampini   /* Set preallocation */
1875268753edSStefano Zampini   ierr = MatSeqAIJSetPreallocation(B,0,dnz);CHKERRQ(ierr);
18763927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
187753b44cf5SStefano Zampini   for (i=0;i<lrows;i+=bs) {
187853b44cf5SStefano Zampini     PetscInt b, d = dnz[i],o = onz[i];
187953b44cf5SStefano Zampini 
188053b44cf5SStefano Zampini     for (b=1;b<bs;b++) {
188153b44cf5SStefano Zampini       d = PetscMax(d,dnz[i+b]);
188253b44cf5SStefano Zampini       o = PetscMax(o,onz[i+b]);
188353b44cf5SStefano Zampini     }
188453b44cf5SStefano Zampini     dnz[i/bs] = PetscMin(d/bs + d%bs,lcols/bs);
188553b44cf5SStefano Zampini     onz[i/bs] = PetscMin(o/bs + o%bs,(cols-lcols)/bs);
18863927de2eSStefano Zampini   }
1887268753edSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(B,bs,0,dnz);CHKERRQ(ierr);
18883927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
18893927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
18903927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
18913927de2eSStefano Zampini   if (issbaij) {
18923927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
18933927de2eSStefano Zampini   }
18949be90c3fSStefano Zampini   ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
18953927de2eSStefano Zampini   PetscFunctionReturn(0);
18963927de2eSStefano Zampini }
18973927de2eSStefano Zampini 
1898487b449aSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M)
1899b7ce53b6SStefano Zampini {
1900b7ce53b6SStefano Zampini   Mat_IS            *matis = (Mat_IS*)(mat->data);
1901487b449aSStefano Zampini   Mat               local_mat,MT;
190253b44cf5SStefano Zampini   PetscInt          rbs,cbs,rows,cols,lrows,lcols;
1903b7ce53b6SStefano Zampini   PetscInt          local_rows,local_cols;
1904b9ed4604SStefano Zampini   PetscBool         isseqdense,isseqsbaij,isseqaij,isseqbaij;
1905f03112d0SStefano Zampini   PetscMPIInt       size;
19061683a169SBarry Smith   const PetscScalar *array;
1907b7ce53b6SStefano Zampini   PetscErrorCode    ierr;
1908b7ce53b6SStefano Zampini 
1909b7ce53b6SStefano Zampini   PetscFunctionBegin;
1910ffc4695bSBarry Smith   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRMPI(ierr);
1911f03112d0SStefano Zampini   if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N) {
19121670daf9Sstefano_zampini     Mat      B;
191353b44cf5SStefano Zampini     IS       irows = NULL,icols = NULL;
1914487b449aSStefano Zampini     PetscInt rbs,cbs;
19151670daf9Sstefano_zampini 
1916487b449aSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
1917487b449aSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
191853b44cf5SStefano Zampini     if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */
191953b44cf5SStefano Zampini       IS             rows,cols;
192053b44cf5SStefano Zampini       const PetscInt *ridxs,*cidxs;
192153b44cf5SStefano Zampini       PetscInt       i,nw,*work;
192253b44cf5SStefano Zampini 
192353b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
192453b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&nw);CHKERRQ(ierr);
192553b44cf5SStefano Zampini       nw   = nw/rbs;
192653b44cf5SStefano Zampini       ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr);
192753b44cf5SStefano Zampini       for (i=0;i<nw;i++) work[ridxs[i]] += 1;
192853b44cf5SStefano Zampini       for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
192953b44cf5SStefano Zampini       if (i == nw) {
193053b44cf5SStefano Zampini         ierr = ISCreateBlock(PETSC_COMM_SELF,rbs,nw,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
1931acdf38a7Sstefano_zampini         ierr = ISSetPermutation(rows);CHKERRQ(ierr);
193253b44cf5SStefano Zampini         ierr = ISInvertPermutation(rows,PETSC_DECIDE,&irows);CHKERRQ(ierr);
1933acdf38a7Sstefano_zampini         ierr = ISDestroy(&rows);CHKERRQ(ierr);
193453b44cf5SStefano Zampini       }
193553b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
193653b44cf5SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
193753b44cf5SStefano Zampini       if (irows && mat->rmap->mapping != mat->cmap->mapping) {
193853b44cf5SStefano Zampini         ierr = ISLocalToGlobalMappingGetBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
193953b44cf5SStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(mat->cmap->mapping,&nw);CHKERRQ(ierr);
194053b44cf5SStefano Zampini         nw   = nw/cbs;
194153b44cf5SStefano Zampini         ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr);
194253b44cf5SStefano Zampini         for (i=0;i<nw;i++) work[cidxs[i]] += 1;
194353b44cf5SStefano Zampini         for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
194453b44cf5SStefano Zampini         if (i == nw) {
194553b44cf5SStefano Zampini           ierr = ISCreateBlock(PETSC_COMM_SELF,cbs,nw,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
194653b44cf5SStefano Zampini           ierr = ISSetPermutation(cols);CHKERRQ(ierr);
194753b44cf5SStefano Zampini           ierr = ISInvertPermutation(cols,PETSC_DECIDE,&icols);CHKERRQ(ierr);
194853b44cf5SStefano Zampini           ierr = ISDestroy(&cols);CHKERRQ(ierr);
194953b44cf5SStefano Zampini         }
195053b44cf5SStefano Zampini         ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
195153b44cf5SStefano Zampini         ierr = PetscFree(work);CHKERRQ(ierr);
195253b44cf5SStefano Zampini       } else if (irows) {
195353b44cf5SStefano Zampini         ierr  = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr);
195453b44cf5SStefano Zampini         icols = irows;
195553b44cf5SStefano Zampini       }
195653b44cf5SStefano Zampini     } else {
195753b44cf5SStefano Zampini       ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject*)&irows);CHKERRQ(ierr);
195853b44cf5SStefano Zampini       ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject*)&icols);CHKERRQ(ierr);
195953b44cf5SStefano Zampini       if (irows) { ierr = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr); }
196053b44cf5SStefano Zampini       if (icols) { ierr = PetscObjectReference((PetscObject)icols);CHKERRQ(ierr); }
196153b44cf5SStefano Zampini     }
196253b44cf5SStefano Zampini     if (!irows || !icols) {
196353b44cf5SStefano Zampini       ierr = ISDestroy(&icols);CHKERRQ(ierr);
196453b44cf5SStefano Zampini       ierr = ISDestroy(&irows);CHKERRQ(ierr);
196553b44cf5SStefano Zampini       goto general_assembly;
196653b44cf5SStefano Zampini     }
1967d8e18881SStefano Zampini     ierr = MatConvert(matis->A,mtype,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
1968487b449aSStefano Zampini     if (reuse != MAT_INPLACE_MATRIX) {
19697dae84e0SHong Zhang       ierr = MatCreateSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr);
197053b44cf5SStefano Zampini       ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject)irows);CHKERRQ(ierr);
197153b44cf5SStefano Zampini       ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject)icols);CHKERRQ(ierr);
1972487b449aSStefano Zampini     } else {
1973487b449aSStefano Zampini       Mat C;
1974487b449aSStefano Zampini 
1975487b449aSStefano Zampini       ierr = MatCreateSubMatrix(B,irows,icols,MAT_INITIAL_MATRIX,&C);CHKERRQ(ierr);
1976487b449aSStefano Zampini       ierr = MatHeaderReplace(mat,&C);CHKERRQ(ierr);
1977487b449aSStefano Zampini     }
1978acdf38a7Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
1979acdf38a7Sstefano_zampini     ierr = ISDestroy(&icols);CHKERRQ(ierr);
1980acdf38a7Sstefano_zampini     ierr = ISDestroy(&irows);CHKERRQ(ierr);
19817c03b4e8SStefano Zampini     PetscFunctionReturn(0);
19827c03b4e8SStefano Zampini   }
198353b44cf5SStefano Zampini general_assembly:
1984b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
198553b44cf5SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
198653b44cf5SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
19873cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
1988b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
1989b9e7e5c1SBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
19904099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
1991b9e7e5c1SBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
1992b9e7e5c1SBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
1993*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
199476bd3646SJed Brown   if (PetscDefined (USE_DEBUG)) {
199576bd3646SJed Brown     PetscBool         lb[4],bb[4];
199676bd3646SJed Brown 
1997b9ed4604SStefano Zampini     lb[0] = isseqdense;
1998b9ed4604SStefano Zampini     lb[1] = isseqaij;
1999b9ed4604SStefano Zampini     lb[2] = isseqbaij;
2000b9ed4604SStefano Zampini     lb[3] = isseqsbaij;
2001820f2d46SBarry Smith     ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRMPI(ierr);
2002*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!bb[0] && !bb[1] && !bb[2] && !bb[3],PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
200376bd3646SJed Brown   }
2004b7ce53b6SStefano Zampini 
2005487b449aSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
2006487b449aSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),&MT);CHKERRQ(ierr);
2007487b449aSStefano Zampini     ierr = MatSetSizes(MT,lrows,lcols,rows,cols);CHKERRQ(ierr);
2008487b449aSStefano Zampini     ierr = MatSetType(MT,mtype);CHKERRQ(ierr);
200953b44cf5SStefano Zampini     ierr = MatSetBlockSizes(MT,rbs,cbs);CHKERRQ(ierr);
2010487b449aSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,MT,PETSC_FALSE);CHKERRQ(ierr);
2011b7ce53b6SStefano Zampini   } else {
201253b44cf5SStefano Zampini     PetscInt mrbs,mcbs,mrows,mcols,mlrows,mlcols;
2013487b449aSStefano Zampini 
2014b7ce53b6SStefano Zampini     /* some checks */
2015487b449aSStefano Zampini     MT   = *M;
201653b44cf5SStefano Zampini     ierr = MatGetBlockSizes(MT,&mrbs,&mcbs);CHKERRQ(ierr);
2017487b449aSStefano Zampini     ierr = MatGetSize(MT,&mrows,&mcols);CHKERRQ(ierr);
2018487b449aSStefano Zampini     ierr = MatGetLocalSize(MT,&mlrows,&mlcols);CHKERRQ(ierr);
2019*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(mrows != rows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%" PetscInt_FMT " != %" PetscInt_FMT ")",rows,mrows);
2020*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(mcols != cols,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%" PetscInt_FMT " != %" PetscInt_FMT ")",cols,mcols);
2021*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(mlrows != lrows,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%" PetscInt_FMT " != %" PetscInt_FMT ")",lrows,mlrows);
2022*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(mlcols != lcols,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%" PetscInt_FMT " != %" PetscInt_FMT ")",lcols,mlcols);
2023*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(mrbs != rbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong row block size (%" PetscInt_FMT " != %" PetscInt_FMT ")",rbs,mrbs);
2024*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(mcbs != cbs,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong col block size (%" PetscInt_FMT " != %" PetscInt_FMT ")",cbs,mcbs);
2025487b449aSStefano Zampini     ierr = MatZeroEntries(MT);CHKERRQ(ierr);
2026b7ce53b6SStefano Zampini   }
2027d9a9e74cSStefano Zampini 
20288546b261SStefano Zampini   if (isseqsbaij || isseqbaij) {
20298546b261SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
20308546b261SStefano Zampini     isseqaij = PETSC_TRUE;
2031d9a9e74cSStefano Zampini   } else {
2032d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
2033d9a9e74cSStefano Zampini     local_mat = matis->A;
2034d9a9e74cSStefano Zampini   }
2035686e3a49SStefano Zampini 
2036b7ce53b6SStefano Zampini   /* Set values */
2037487b449aSStefano Zampini   ierr = MatSetLocalToGlobalMapping(MT,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
2038b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
203965066ba5SStefano Zampini     PetscInt          i,*dummy;
2040ecf5a873SStefano Zampini 
204165066ba5SStefano Zampini     ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr);
204265066ba5SStefano Zampini     for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i;
2043487b449aSStefano Zampini     ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
20441683a169SBarry Smith     ierr = MatDenseGetArrayRead(local_mat,&array);CHKERRQ(ierr);
2045487b449aSStefano Zampini     ierr = MatSetValuesLocal(MT,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr);
20461683a169SBarry Smith     ierr = MatDenseRestoreArrayRead(local_mat,&array);CHKERRQ(ierr);
204765066ba5SStefano Zampini     ierr = PetscFree(dummy);CHKERRQ(ierr);
2048686e3a49SStefano Zampini   } else if (isseqaij) {
20496afe12f5SStefano Zampini     const PetscInt *blocks;
20506afe12f5SStefano Zampini     PetscInt       i,nvtxs,*xadj,*adjncy, nb;
2051686e3a49SStefano Zampini     PetscBool      done;
20521683a169SBarry Smith     PetscScalar    *sarray;
2053686e3a49SStefano Zampini 
2054d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2055*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!done,PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
20561683a169SBarry Smith     ierr = MatSeqAIJGetArray(local_mat,&sarray);CHKERRQ(ierr);
20576afe12f5SStefano Zampini     ierr = MatGetVariableBlockSizes(local_mat,&nb,&blocks);CHKERRQ(ierr);
20586afe12f5SStefano Zampini     if (nb) { /* speed up assembly for special blocked matrices (used by BDDC) */
20596afe12f5SStefano Zampini       PetscInt sum;
20606afe12f5SStefano Zampini 
20616afe12f5SStefano Zampini       for (i=0,sum=0;i<nb;i++) sum += blocks[i];
20626afe12f5SStefano Zampini       if (sum == nvtxs) {
20636afe12f5SStefano Zampini         PetscInt r;
20646afe12f5SStefano Zampini 
20656afe12f5SStefano Zampini         for (i=0,r=0;i<nb;i++) {
2066*2c71b3e2SJacob Faibussowitsch           PetscAssertFalse(blocks[i] != xadj[r+1] - xadj[r],PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid block sizes prescribed for block %" PetscInt_FMT ": expected %" PetscInt_FMT ", got %" PetscInt_FMT,i,blocks[i],xadj[r+1] - xadj[r]);
20671683a169SBarry Smith           ierr = MatSetValuesLocal(MT,blocks[i],adjncy+xadj[r],blocks[i],adjncy+xadj[r],sarray+xadj[r],ADD_VALUES);CHKERRQ(ierr);
20686afe12f5SStefano Zampini           r   += blocks[i];
20696afe12f5SStefano Zampini         }
20706afe12f5SStefano Zampini       } else {
2071686e3a49SStefano Zampini         for (i=0;i<nvtxs;i++) {
20721683a169SBarry Smith           ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],sarray+xadj[i],ADD_VALUES);CHKERRQ(ierr);
2073686e3a49SStefano Zampini         }
20746afe12f5SStefano Zampini       }
20756afe12f5SStefano Zampini     } else {
20766afe12f5SStefano Zampini       for (i=0;i<nvtxs;i++) {
20771683a169SBarry Smith         ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],sarray+xadj[i],ADD_VALUES);CHKERRQ(ierr);
20786afe12f5SStefano Zampini       }
20796afe12f5SStefano Zampini     }
2080d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2081*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!done,PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
20821683a169SBarry Smith     ierr = MatSeqAIJRestoreArray(local_mat,&sarray);CHKERRQ(ierr);
2083686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
2084ecf5a873SStefano Zampini     PetscInt i;
2085c0962df8SStefano Zampini 
2086686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
2087686e3a49SStefano Zampini       PetscInt       j;
2088ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
2089686e3a49SStefano Zampini 
20901683a169SBarry Smith       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,&array);CHKERRQ(ierr);
2091487b449aSStefano Zampini       ierr = MatSetValuesLocal(MT,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
20921683a169SBarry Smith       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,&array);CHKERRQ(ierr);
2093686e3a49SStefano Zampini     }
2094b7ce53b6SStefano Zampini   }
2095487b449aSStefano Zampini   ierr = MatAssemblyBegin(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2096d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
2097487b449aSStefano Zampini   ierr = MatAssemblyEnd(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2098b9ed4604SStefano Zampini   if (isseqdense) {
2099487b449aSStefano Zampini     ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
2100487b449aSStefano Zampini   }
2101487b449aSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
2102487b449aSStefano Zampini     ierr = MatHeaderReplace(mat,&MT);CHKERRQ(ierr);
2103487b449aSStefano Zampini   } else if (reuse == MAT_INITIAL_MATRIX) {
2104487b449aSStefano Zampini     *M = MT;
2105b7ce53b6SStefano Zampini   }
2106b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
2107b7ce53b6SStefano Zampini }
2108b7ce53b6SStefano Zampini 
2109b7ce53b6SStefano Zampini /*@
2110b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
2111b7ce53b6SStefano Zampini 
2112d8d19677SJose E. Roman   Input Parameters:
2113a2b725a8SWilliam Gropp +  mat - the matrix (should be of type MATIS)
2114a2b725a8SWilliam Gropp -  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
2115b7ce53b6SStefano Zampini 
2116b7ce53b6SStefano Zampini   Output Parameter:
2117b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
2118b7ce53b6SStefano Zampini 
2119b7ce53b6SStefano Zampini   Level: developer
2120b7ce53b6SStefano Zampini 
212195452b02SPatrick Sanan   Notes:
2122487b449aSStefano Zampini     This function has been deprecated and it will be removed in future releases. Update your code to use the MatConvert() interface.
2123b7ce53b6SStefano Zampini 
2124487b449aSStefano Zampini .seealso: MATIS, MatConvert()
2125b7ce53b6SStefano Zampini @*/
2126b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
2127b7ce53b6SStefano Zampini {
2128b7ce53b6SStefano Zampini   PetscErrorCode ierr;
2129b7ce53b6SStefano Zampini 
2130b7ce53b6SStefano Zampini   PetscFunctionBegin;
2131b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2132b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
2133b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
2134487b449aSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
2135b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
2136b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
2137*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(mat == *newmat,PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
2138b7ce53b6SStefano Zampini   }
2139487b449aSStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatType,MatReuse,Mat*),(mat,MATAIJ,reuse,newmat));CHKERRQ(ierr);
2140b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
2141b7ce53b6SStefano Zampini }
2142b7ce53b6SStefano Zampini 
21438b9382cfSStefano Zampini static PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
2144ad6194a2SStefano Zampini {
2145ad6194a2SStefano Zampini   PetscErrorCode ierr;
2146ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
2147c9225affSStefano Zampini   PetscInt       rbs,cbs,m,n,M,N;
2148ad6194a2SStefano Zampini   Mat            B,localmat;
2149ad6194a2SStefano Zampini 
2150ad6194a2SStefano Zampini   PetscFunctionBegin;
2151c9225affSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
2152c9225affSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
2153ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
2154ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
21558546b261SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)mat),&B);CHKERRQ(ierr);
21568546b261SStefano Zampini   ierr = MatSetSizes(B,m,n,M,N);CHKERRQ(ierr);
21578546b261SStefano Zampini   ierr = MatSetBlockSize(B,rbs == cbs ? rbs : 1);CHKERRQ(ierr);
21588546b261SStefano Zampini   ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
21598546b261SStefano Zampini   ierr = MatISSetLocalMatType(B,matis->lmattype);CHKERRQ(ierr);
21608546b261SStefano Zampini   ierr = MatSetLocalToGlobalMapping(B,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
2161ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
2162ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
2163b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
2164ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2165ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2166ad6194a2SStefano Zampini   *newmat = B;
2167ad6194a2SStefano Zampini   PetscFunctionReturn(0);
2168ad6194a2SStefano Zampini }
2169ad6194a2SStefano Zampini 
2170a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
217169796d55SStefano Zampini {
217269796d55SStefano Zampini   PetscErrorCode ierr;
217369796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
217469796d55SStefano Zampini   PetscBool      local_sym;
217569796d55SStefano Zampini 
217669796d55SStefano Zampini   PetscFunctionBegin;
217769796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
2178820f2d46SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr);
217969796d55SStefano Zampini   PetscFunctionReturn(0);
218069796d55SStefano Zampini }
218169796d55SStefano Zampini 
2182a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
218369796d55SStefano Zampini {
218469796d55SStefano Zampini   PetscErrorCode ierr;
218569796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
218669796d55SStefano Zampini   PetscBool      local_sym;
218769796d55SStefano Zampini 
218869796d55SStefano Zampini   PetscFunctionBegin;
218969796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
2190820f2d46SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr);
219169796d55SStefano Zampini   PetscFunctionReturn(0);
219269796d55SStefano Zampini }
219369796d55SStefano Zampini 
219445471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
219545471136SStefano Zampini {
219645471136SStefano Zampini   PetscErrorCode ierr;
219745471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
219845471136SStefano Zampini   PetscBool      local_sym;
219945471136SStefano Zampini 
220045471136SStefano Zampini   PetscFunctionBegin;
220145471136SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
220245471136SStefano Zampini     *flg = PETSC_FALSE;
220345471136SStefano Zampini     PetscFunctionReturn(0);
220445471136SStefano Zampini   }
220545471136SStefano Zampini   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
2206820f2d46SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr);
220745471136SStefano Zampini   PetscFunctionReturn(0);
220845471136SStefano Zampini }
220945471136SStefano Zampini 
2210a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
2211b4319ba4SBarry Smith {
2212dfbe8321SBarry Smith   PetscErrorCode ierr;
2213b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
2214b4319ba4SBarry Smith 
2215b4319ba4SBarry Smith   PetscFunctionBegin;
2216b89f26deSStefano Zampini   ierr = PetscFree(b->bdiag);CHKERRQ(ierr);
22178546b261SStefano Zampini   ierr = PetscFree(b->lmattype);CHKERRQ(ierr);
22186bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
2219e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
2220e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
22216bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
22226bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
22233fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
2224a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
2225a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
2226a8116848SStefano Zampini   if (b->sf != b->csf) {
2227a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
2228a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
2229f03112d0SStefano Zampini   } else b->csf = NULL;
223028f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
223128f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
2232bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
2233f4259b30SLisandro Dalcin   ierr = PetscObjectChangeTypeName((PetscObject)A,NULL);CHKERRQ(ierr);
22348546b261SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",NULL);CHKERRQ(ierr);
2235bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
2236b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
2237b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
22382e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
223975d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",NULL);CHKERRQ(ierr);
2240f03112d0SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",NULL);CHKERRQ(ierr);
2241487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",NULL);CHKERRQ(ierr);
2242487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",NULL);CHKERRQ(ierr);
2243487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",NULL);CHKERRQ(ierr);
2244487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",NULL);CHKERRQ(ierr);
2245487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",NULL);CHKERRQ(ierr);
2246487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",NULL);CHKERRQ(ierr);
2247487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",NULL);CHKERRQ(ierr);
2248b4319ba4SBarry Smith   PetscFunctionReturn(0);
2249b4319ba4SBarry Smith }
2250b4319ba4SBarry Smith 
2251a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
2252b4319ba4SBarry Smith {
2253dfbe8321SBarry Smith   PetscErrorCode ierr;
2254b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
2255b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
2256b4319ba4SBarry Smith 
2257b4319ba4SBarry Smith   PetscFunctionBegin;
2258b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
2259e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2260e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2261b4319ba4SBarry Smith 
2262b4319ba4SBarry Smith   /* multiply the local matrix */
2263b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
2264b4319ba4SBarry Smith 
2265b4319ba4SBarry Smith   /* scatter product back into global memory */
22662dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
2267e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2268e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2269b4319ba4SBarry Smith   PetscFunctionReturn(0);
2270b4319ba4SBarry Smith }
2271b4319ba4SBarry Smith 
2272a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
22732e74eeadSLisandro Dalcin {
2274650997f4SStefano Zampini   Vec            temp_vec;
22752e74eeadSLisandro Dalcin   PetscErrorCode ierr;
22762e74eeadSLisandro Dalcin 
22772e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
2278650997f4SStefano Zampini   if (v3 != v2) {
2279650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
2280650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
2281650997f4SStefano Zampini   } else {
2282650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
2283650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
2284650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
2285650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
2286650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
2287650997f4SStefano Zampini   }
22882e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
22892e74eeadSLisandro Dalcin }
22902e74eeadSLisandro Dalcin 
2291a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
22922e74eeadSLisandro Dalcin {
22932e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
22942e74eeadSLisandro Dalcin   PetscErrorCode ierr;
22952e74eeadSLisandro Dalcin 
2296e176bc59SStefano Zampini   PetscFunctionBegin;
22972e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
2298e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2299e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23002e74eeadSLisandro Dalcin 
23012e74eeadSLisandro Dalcin   /* multiply the local matrix */
2302e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
23032e74eeadSLisandro Dalcin 
23042e74eeadSLisandro Dalcin   /* scatter product back into global vector */
2305e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
2306e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2307e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23082e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
23092e74eeadSLisandro Dalcin }
23102e74eeadSLisandro Dalcin 
2311a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
23122e74eeadSLisandro Dalcin {
2313650997f4SStefano Zampini   Vec            temp_vec;
23142e74eeadSLisandro Dalcin   PetscErrorCode ierr;
23152e74eeadSLisandro Dalcin 
23162e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
2317650997f4SStefano Zampini   if (v3 != v2) {
2318650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
2319650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
2320650997f4SStefano Zampini   } else {
2321650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
2322650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
2323650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
2324650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
2325650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
2326650997f4SStefano Zampini   }
23272e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
23282e74eeadSLisandro Dalcin }
23292e74eeadSLisandro Dalcin 
2330a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
2331b4319ba4SBarry Smith {
2332b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
2333dfbe8321SBarry Smith   PetscErrorCode ierr;
2334b4319ba4SBarry Smith   PetscViewer    sviewer;
2335ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
2336b4319ba4SBarry Smith 
2337b4319ba4SBarry Smith   PetscFunctionBegin;
2338ee2491ecSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
2339ee2491ecSStefano Zampini   if (isascii)  {
2340ee2491ecSStefano Zampini     PetscViewerFormat format;
2341ee2491ecSStefano Zampini 
2342ee2491ecSStefano Zampini     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
2343ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
2344ee2491ecSStefano Zampini   }
2345ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
23463f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
2347b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
23483f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
23496e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2350b4319ba4SBarry Smith   PetscFunctionReturn(0);
2351b4319ba4SBarry Smith }
2352b4319ba4SBarry Smith 
2353b89f26deSStefano Zampini static PetscErrorCode MatInvertBlockDiagonal_IS(Mat mat,const PetscScalar **values)
2354b89f26deSStefano Zampini {
2355b89f26deSStefano Zampini   Mat_IS            *is = (Mat_IS*)mat->data;
2356b89f26deSStefano Zampini   MPI_Datatype      nodeType;
2357b89f26deSStefano Zampini   const PetscScalar *lv;
2358b89f26deSStefano Zampini   PetscInt          bs;
2359b89f26deSStefano Zampini   PetscErrorCode    ierr;
2360b89f26deSStefano Zampini 
2361b89f26deSStefano Zampini   PetscFunctionBegin;
2362b89f26deSStefano Zampini   ierr = MatGetBlockSize(mat,&bs);CHKERRQ(ierr);
2363b89f26deSStefano Zampini   ierr = MatSetBlockSize(is->A,bs);CHKERRQ(ierr);
2364b89f26deSStefano Zampini   ierr = MatInvertBlockDiagonal(is->A,&lv);CHKERRQ(ierr);
2365b89f26deSStefano Zampini   if (!is->bdiag) {
2366b89f26deSStefano Zampini     ierr = PetscMalloc1(bs*mat->rmap->n,&is->bdiag);CHKERRQ(ierr);
2367b89f26deSStefano Zampini   }
2368ffc4695bSBarry Smith   ierr = MPI_Type_contiguous(bs,MPIU_SCALAR,&nodeType);CHKERRMPI(ierr);
2369ffc4695bSBarry Smith   ierr = MPI_Type_commit(&nodeType);CHKERRMPI(ierr);
237083df288dSJunchao Zhang   ierr = PetscSFReduceBegin(is->sf,nodeType,lv,is->bdiag,MPI_REPLACE);CHKERRQ(ierr);
237183df288dSJunchao Zhang   ierr = PetscSFReduceEnd(is->sf,nodeType,lv,is->bdiag,MPI_REPLACE);CHKERRQ(ierr);
2372ffc4695bSBarry Smith   ierr = MPI_Type_free(&nodeType);CHKERRMPI(ierr);
2373b89f26deSStefano Zampini   if (values) *values = is->bdiag;
2374b89f26deSStefano Zampini   PetscFunctionReturn(0);
2375b89f26deSStefano Zampini }
2376b89f26deSStefano Zampini 
23778546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat A)
2378b4319ba4SBarry Smith {
2379e176bc59SStefano Zampini   Vec            cglobal,rglobal;
23808546b261SStefano Zampini   IS             from;
23818546b261SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
2382b89f26deSStefano Zampini   PetscScalar    sum;
23838546b261SStefano Zampini   const PetscInt *garray;
23848546b261SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
23858546b261SStefano Zampini   PetscBool      iscuda;
23868546b261SStefano Zampini   PetscErrorCode ierr;
2387b4319ba4SBarry Smith 
2388b4319ba4SBarry Smith   PetscFunctionBegin;
23898546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nr);CHKERRQ(ierr);
23908546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(A->rmap->mapping,&rbs);CHKERRQ(ierr);
23918546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&nc);CHKERRQ(ierr);
23928546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(A->cmap->mapping,&cbs);CHKERRQ(ierr);
239370cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
239470cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
23953fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
2396e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
2397e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
23988546b261SStefano Zampini   ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
2399b470e4b4SRichard Tran Mills   ierr = VecBindToCPU(is->y,PETSC_TRUE);CHKERRQ(ierr);
24008546b261SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)is->y,VECSEQCUDA,&iscuda);CHKERRQ(ierr);
24018546b261SStefano Zampini   if (iscuda) {
24028546b261SStefano Zampini     ierr = PetscFree(A->defaultvectype);CHKERRQ(ierr);
24038546b261SStefano Zampini     ierr = PetscStrallocpy(VECCUDA,&A->defaultvectype);CHKERRQ(ierr);
24048546b261SStefano Zampini   }
24058546b261SStefano Zampini   ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
2406b470e4b4SRichard Tran Mills   ierr = VecBindToCPU(rglobal,PETSC_TRUE);CHKERRQ(ierr);
24078546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockIndices(A->rmap->mapping,&garray);CHKERRQ(ierr);
24088546b261SStefano Zampini   ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),rbs,nr/rbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
24099448b7f1SJunchao Zhang   ierr = VecScatterCreate(rglobal,from,is->y,NULL,&is->rctx);CHKERRQ(ierr);
24108546b261SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreBlockIndices(A->rmap->mapping,&garray);CHKERRQ(ierr);
24118546b261SStefano Zampini   ierr = ISDestroy(&from);CHKERRQ(ierr);
24128546b261SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
24138546b261SStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(A->cmap->mapping,&garray);CHKERRQ(ierr);
24148546b261SStefano Zampini     ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),cbs,nc/cbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
24159448b7f1SJunchao Zhang     ierr = VecScatterCreate(cglobal,from,is->x,NULL,&is->cctx);CHKERRQ(ierr);
24168546b261SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(A->cmap->mapping,&garray);CHKERRQ(ierr);
24178546b261SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
24188546b261SStefano Zampini   } else {
24198546b261SStefano Zampini     ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
24208546b261SStefano Zampini     is->cctx = is->rctx;
24218546b261SStefano Zampini   }
2422b89f26deSStefano Zampini   ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
2423b89f26deSStefano Zampini 
24248546b261SStefano Zampini   /* interface counter vector (local) */
24258546b261SStefano Zampini   ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
2426b470e4b4SRichard Tran Mills   ierr = VecBindToCPU(is->counter,PETSC_TRUE);CHKERRQ(ierr);
24278546b261SStefano Zampini   ierr = VecSet(is->y,1.);CHKERRQ(ierr);
24288546b261SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24298546b261SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24308546b261SStefano Zampini   ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
24318546b261SStefano Zampini   ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2432b470e4b4SRichard Tran Mills   ierr = VecBindToCPU(is->y,PETSC_FALSE);CHKERRQ(ierr);
2433b470e4b4SRichard Tran Mills   ierr = VecBindToCPU(is->counter,PETSC_FALSE);CHKERRQ(ierr);
2434b89f26deSStefano Zampini 
2435b89f26deSStefano Zampini   /* special functions for block-diagonal matrices */
2436b89f26deSStefano Zampini   ierr = VecSum(rglobal,&sum);CHKERRQ(ierr);
2437b89f26deSStefano Zampini   if ((PetscInt)(PetscRealPart(sum)) == A->rmap->N && A->rmap->N == A->cmap->N && A->rmap->mapping == A->cmap->mapping) {
2438b89f26deSStefano Zampini     A->ops->invertblockdiagonal = MatInvertBlockDiagonal_IS;
2439b89f26deSStefano Zampini   } else {
2440b89f26deSStefano Zampini     A->ops->invertblockdiagonal = NULL;
2441b89f26deSStefano Zampini   }
24428546b261SStefano Zampini   ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
2443b0cc1f67SStefano Zampini 
2444b0cc1f67SStefano Zampini   /* setup SF for general purpose shared indices based communications */
2445b0cc1f67SStefano Zampini   ierr = MatISSetUpSF_IS(A);CHKERRQ(ierr);
24468546b261SStefano Zampini   PetscFunctionReturn(0);
24478546b261SStefano Zampini }
24488546b261SStefano Zampini 
24498546b261SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
24508546b261SStefano Zampini {
24518546b261SStefano Zampini   PetscErrorCode ierr;
24528546b261SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
24538546b261SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
2454fc989267SStefano Zampini   PetscBool      cong, same = PETSC_FALSE;
24558546b261SStefano Zampini 
24568546b261SStefano Zampini   PetscFunctionBegin;
2457fc989267SStefano Zampini   if (rmapping) PetscCheckSameComm(A,1,rmapping,2);
2458fc989267SStefano Zampini   if (cmapping) PetscCheckSameComm(A,1,cmapping,3);
2459fc989267SStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
2460fc989267SStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
2461fc989267SStefano Zampini   ierr = MatHasCongruentLayouts(A,&cong);CHKERRQ(ierr);
2462fc989267SStefano Zampini   ierr = PetscObjectReference((PetscObject)rmapping);CHKERRQ(ierr);
2463fc989267SStefano Zampini   ierr = PetscObjectReference((PetscObject)cmapping);CHKERRQ(ierr);
2464fc989267SStefano Zampini   /* If NULL, local space matches global space */
2465fc989267SStefano Zampini   if (!rmapping) {
2466fc989267SStefano Zampini     IS is;
2467fc989267SStefano Zampini 
2468fc989267SStefano Zampini     ierr = ISCreateStride(PetscObjectComm((PetscObject)A),A->rmap->N,0,1,&is);CHKERRQ(ierr);
2469fc989267SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rmapping);CHKERRQ(ierr);
2470fc989267SStefano Zampini     if (A->rmap->bs > 0) { ierr = ISLocalToGlobalMappingSetBlockSize(rmapping,A->rmap->bs);CHKERRQ(ierr); }
2471fc989267SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
2472fc989267SStefano Zampini 
2473fc989267SStefano Zampini     if (!cmapping && cong) {
2474fc989267SStefano Zampini       ierr = PetscObjectReference((PetscObject)rmapping);CHKERRQ(ierr);
2475fc989267SStefano Zampini       cmapping = rmapping;
2476fc989267SStefano Zampini     }
2477fc989267SStefano Zampini   }
2478fc989267SStefano Zampini   if (!cmapping) {
2479fc989267SStefano Zampini     IS is;
2480fc989267SStefano Zampini 
2481fc989267SStefano Zampini     ierr = ISCreateStride(PetscObjectComm((PetscObject)A),A->cmap->N,0,1,&is);CHKERRQ(ierr);
2482fc989267SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cmapping);CHKERRQ(ierr);
2483fc989267SStefano Zampini     if (A->cmap->bs > 0) { ierr = ISLocalToGlobalMappingSetBlockSize(cmapping,A->cmap->bs);CHKERRQ(ierr); }
2484fc989267SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
2485fc989267SStefano Zampini   }
2486fc989267SStefano Zampini 
2487fc989267SStefano Zampini   /* Clean up */
24881c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
2489872cf891SStefano Zampini   if (is->csf != is->sf) {
2490872cf891SStefano Zampini     ierr = PetscSFDestroy(&is->csf);CHKERRQ(ierr);
2491872cf891SStefano Zampini     ierr = PetscFree2(is->csf_rootdata,is->csf_leafdata);CHKERRQ(ierr);
2492f03112d0SStefano Zampini   } else is->csf = NULL;
249328f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
249428f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
2495b89f26deSStefano Zampini   ierr = PetscFree(is->bdiag);CHKERRQ(ierr);
24963bbff08aSStefano Zampini 
2497fc989267SStefano Zampini   /* check if the two mappings are actually the same for square matrices since MATIS has some optimization for this case
2498fc989267SStefano Zampini      (DOLFIN passes 2 different objects) */
2499e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
2500e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
2501e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
2502e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
2503fc989267SStefano Zampini   if (rmapping != cmapping && cong) {
25046625354bSStefano Zampini     if (nr == nc && cbs == rbs) {
25056625354bSStefano Zampini       const PetscInt *idxs1,*idxs2;
25066625354bSStefano Zampini 
25076625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
25086625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
2509580bdb30SBarry Smith       ierr = PetscArraycmp(idxs1,idxs2,nr/rbs,&same);CHKERRQ(ierr);
25106625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
25116625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
25126625354bSStefano Zampini     }
2513fc989267SStefano Zampini     ierr = MPIU_Allreduce(MPI_IN_PLACE,&same,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr);
25146625354bSStefano Zampini   }
251553b44cf5SStefano Zampini   ierr = PetscLayoutSetBlockSize(A->rmap,rbs);CHKERRQ(ierr);
251653b44cf5SStefano Zampini   ierr = PetscLayoutSetBlockSize(A->cmap,cbs);CHKERRQ(ierr);
25176625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
2518fc989267SStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,same ? rmapping : cmapping);CHKERRQ(ierr);
2519fc989267SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rmapping);CHKERRQ(ierr);
2520fc989267SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cmapping);CHKERRQ(ierr);
25216625354bSStefano Zampini 
25226625354bSStefano Zampini   /* Create the local matrix A */
2523f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
25248546b261SStefano Zampini   ierr = MatSetType(is->A,is->lmattype);CHKERRQ(ierr);
2525e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
2526e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
25278546b261SStefano Zampini   ierr = MatSetOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
25288546b261SStefano Zampini   ierr = MatAppendOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
2529c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->rmap);CHKERRQ(ierr);
2530c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->cmap);CHKERRQ(ierr);
2531b4319ba4SBarry Smith 
2532fc989267SStefano Zampini   /* setup scatters and local vectors for MatMult */
2533fc989267SStefano Zampini   if (!is->islocalref) {
25348546b261SStefano Zampini     ierr = MatISSetUpScatters_Private(A);CHKERRQ(ierr);
2535f26d0771SStefano Zampini   }
2536fc989267SStefano Zampini   A->preallocated = PETSC_TRUE;
2537fc989267SStefano Zampini   PetscFunctionReturn(0);
2538fc989267SStefano Zampini }
2539fc989267SStefano Zampini 
2540fc989267SStefano Zampini static PetscErrorCode MatSetUp_IS(Mat A)
2541fc989267SStefano Zampini {
2542fc989267SStefano Zampini   ISLocalToGlobalMapping rmap, cmap;
2543fc989267SStefano Zampini   PetscErrorCode         ierr;
2544fc989267SStefano Zampini 
2545fc989267SStefano Zampini   PetscFunctionBegin;
2546fc989267SStefano Zampini   ierr = MatGetLocalToGlobalMapping(A,&rmap,&cmap);CHKERRQ(ierr);
2547*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(rmap && !cmap,PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Missing column mapping");
2548*2c71b3e2SJacob Faibussowitsch   PetscCheckFalse(cmap && !rmap,PetscObjectComm((PetscObject)A),PETSC_ERR_PLIB,"Missing row mapping");
2549fc989267SStefano Zampini   if (!rmap && !cmap) {
2550fc989267SStefano Zampini     ierr = MatSetLocalToGlobalMapping(A,NULL,NULL);CHKERRQ(ierr);
2551fc989267SStefano Zampini   }
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   PetscInt       i,zm,zn;
2560f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
25612e74eeadSLisandro Dalcin 
25622e74eeadSLisandro Dalcin   PetscFunctionBegin;
256376bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2564*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION,PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= %d: they are %" PetscInt_FMT " %" PetscInt_FMT,MATIS_MAX_ENTRIES_INSERTION,m,n);
256597563a80SStefano Zampini     /* count negative indices */
256697563a80SStefano Zampini     for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
256797563a80SStefano Zampini     for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
256876bd3646SJed Brown   }
256997563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
257097563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
257176bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
257297563a80SStefano Zampini     /* count negative indices (should be the same as before) */
257397563a80SStefano Zampini     for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
257497563a80SStefano Zampini     for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
2575*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!is->A->rmap->mapping && zm,PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS");
2576*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!is->A->cmap->mapping && zn,PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS");
257776bd3646SJed Brown   }
25782e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
25792e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
25802e74eeadSLisandro Dalcin }
25812e74eeadSLisandro Dalcin 
2582a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
258397563a80SStefano Zampini {
258497563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
258597563a80SStefano Zampini   PetscErrorCode ierr;
258697563a80SStefano Zampini   PetscInt       i,zm,zn;
2587f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
258897563a80SStefano Zampini 
258997563a80SStefano Zampini   PetscFunctionBegin;
259076bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
2591*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION,PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column block indices must be <= %d: they are %" PetscInt_FMT " %" PetscInt_FMT,MATIS_MAX_ENTRIES_INSERTION,m,n);
259297563a80SStefano Zampini     /* count negative indices */
259397563a80SStefano Zampini     for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
259497563a80SStefano Zampini     for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
259576bd3646SJed Brown   }
259697563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
259797563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
259876bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
259997563a80SStefano Zampini     /* count negative indices (should be the same as before) */
260097563a80SStefano Zampini     for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
260197563a80SStefano Zampini     for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
2602*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!is->A->rmap->mapping && zm,PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS");
2603*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!is->A->cmap->mapping && zn,PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS");
260476bd3646SJed Brown   }
2605d59cf9ebSStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
260697563a80SStefano Zampini   PetscFunctionReturn(0);
260797563a80SStefano Zampini }
260897563a80SStefano Zampini 
2609a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2610b4319ba4SBarry Smith {
2611dfbe8321SBarry Smith   PetscErrorCode ierr;
2612b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2613b4319ba4SBarry Smith 
2614b4319ba4SBarry Smith   PetscFunctionBegin;
2615b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
2616872cf891SStefano Zampini     ierr = MatSetValuesLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2617872cf891SStefano Zampini   } else {
2618b4319ba4SBarry Smith     ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2619872cf891SStefano Zampini   }
2620b4319ba4SBarry Smith   PetscFunctionReturn(0);
2621b4319ba4SBarry Smith }
2622b4319ba4SBarry Smith 
2623a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2624f0006bf2SLisandro Dalcin {
2625f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
2626f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
2627f0006bf2SLisandro Dalcin 
2628f0006bf2SLisandro Dalcin   PetscFunctionBegin;
2629b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
263076bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
2631b4f971dfSStefano Zampini       PetscInt ibs,bs;
2632b4f971dfSStefano Zampini 
2633b4f971dfSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockSize(is->A->rmap->mapping,&ibs);CHKERRQ(ierr);
2634b4f971dfSStefano Zampini       ierr = MatGetBlockSize(is->A,&bs);CHKERRQ(ierr);
2635*2c71b3e2SJacob Faibussowitsch       PetscCheckFalse(ibs != bs,PETSC_COMM_SELF,PETSC_ERR_SUP,"Different block sizes! local mat %" PetscInt_FMT ", local l2g map %" PetscInt_FMT,bs,ibs);
263676bd3646SJed Brown     }
2637b4f971dfSStefano Zampini     ierr = MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2638b4f971dfSStefano Zampini   } else {
2639f0006bf2SLisandro Dalcin     ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2640b4f971dfSStefano Zampini   }
2641f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
2642f0006bf2SLisandro Dalcin }
2643f0006bf2SLisandro Dalcin 
2644f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
2645f0ae7da4SStefano Zampini {
2646f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
2647f0ae7da4SStefano Zampini   PetscErrorCode ierr;
2648f0ae7da4SStefano Zampini 
2649f0ae7da4SStefano Zampini   PetscFunctionBegin;
2650f0ae7da4SStefano Zampini   if (!n) {
2651f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
2652f0ae7da4SStefano Zampini   } else {
2653f0ae7da4SStefano Zampini     PetscInt i;
2654f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
2655f0ae7da4SStefano Zampini 
2656f0ae7da4SStefano Zampini     if (columns) {
2657f4259b30SLisandro Dalcin       ierr = MatZeroRowsColumns(is->A,n,rows,diag,NULL,NULL);CHKERRQ(ierr);
2658f0ae7da4SStefano Zampini     } else {
2659f4259b30SLisandro Dalcin       ierr = MatZeroRows(is->A,n,rows,diag,NULL,NULL);CHKERRQ(ierr);
2660f0ae7da4SStefano Zampini     }
2661f0ae7da4SStefano Zampini     if (diag != 0.) {
2662f0ae7da4SStefano Zampini       const PetscScalar *array;
2663f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
2664f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
2665f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
2666f0ae7da4SStefano Zampini       }
2667f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
2668f0ae7da4SStefano Zampini     }
2669f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2670f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2671f0ae7da4SStefano Zampini   }
2672f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2673f0ae7da4SStefano Zampini }
2674f0ae7da4SStefano Zampini 
2675f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
26762e74eeadSLisandro Dalcin {
26776e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
26786e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
26796e520ac8SStefano Zampini   PetscInt       *lrows;
26802e74eeadSLisandro Dalcin   PetscErrorCode ierr;
26812e74eeadSLisandro Dalcin 
26822e74eeadSLisandro Dalcin   PetscFunctionBegin;
2683cf9c20a2SJed Brown   if (PetscUnlikelyDebug(columns || diag != 0. || (x && b))) {
2684f0ae7da4SStefano Zampini     PetscBool cong;
268526b0207aSStefano Zampini 
2686f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
268726b0207aSStefano Zampini     cong = (PetscBool)(cong && matis->sf == matis->csf);
2688*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!cong && columns,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");
2689*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!cong && diag != 0.,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");
2690*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!cong && x && b,PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent, and the l2g maps be the same");
2691f0ae7da4SStefano Zampini   }
26926e520ac8SStefano Zampini   /* get locally owned rows */
2693a72d46e8SStefano Zampini   ierr = PetscLayoutMapLocal(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
26946e520ac8SStefano Zampini   /* fix right hand side if needed */
26956e520ac8SStefano Zampini   if (x && b) {
26966e520ac8SStefano Zampini     const PetscScalar *xx;
26976e520ac8SStefano Zampini     PetscScalar       *bb;
26986e520ac8SStefano Zampini 
26996e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
27006e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
27016e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
27026e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
27036e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
27042e74eeadSLisandro Dalcin   }
27056e520ac8SStefano Zampini   /* get rows associated to the local matrices */
27066e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
2707580bdb30SBarry Smith   ierr = PetscArrayzero(matis->sf_leafdata,nl);CHKERRQ(ierr);
2708580bdb30SBarry Smith   ierr = PetscArrayzero(matis->sf_rootdata,A->rmap->n);CHKERRQ(ierr);
27096e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
27106e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
2711ad227feaSJunchao Zhang   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE);CHKERRQ(ierr);
2712ad227feaSJunchao Zhang   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata,MPI_REPLACE);CHKERRQ(ierr);
27136e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
27146e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
2715f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
27166e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
27172e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
27182e74eeadSLisandro Dalcin }
27192e74eeadSLisandro Dalcin 
2720f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2721b4319ba4SBarry Smith {
2722dfbe8321SBarry Smith   PetscErrorCode ierr;
2723b4319ba4SBarry Smith 
2724b4319ba4SBarry Smith   PetscFunctionBegin;
2725f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
2726f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2727f0ae7da4SStefano Zampini }
27282205254eSKarl Rupp 
2729f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2730f0ae7da4SStefano Zampini {
2731f0ae7da4SStefano Zampini   PetscErrorCode ierr;
2732f0ae7da4SStefano Zampini 
2733f0ae7da4SStefano Zampini   PetscFunctionBegin;
2734f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
2735b4319ba4SBarry Smith   PetscFunctionReturn(0);
2736b4319ba4SBarry Smith }
2737b4319ba4SBarry Smith 
2738a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
2739b4319ba4SBarry Smith {
2740b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2741dfbe8321SBarry Smith   PetscErrorCode ierr;
2742b4319ba4SBarry Smith 
2743b4319ba4SBarry Smith   PetscFunctionBegin;
2744b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
2745b4319ba4SBarry Smith   PetscFunctionReturn(0);
2746b4319ba4SBarry Smith }
2747b4319ba4SBarry Smith 
2748a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
2749b4319ba4SBarry Smith {
2750b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2751dfbe8321SBarry Smith   PetscErrorCode ierr;
2752b4319ba4SBarry Smith 
2753b4319ba4SBarry Smith   PetscFunctionBegin;
2754b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
2755872cf891SStefano Zampini   /* fix for local empty rows/cols */
2756872cf891SStefano Zampini   if (is->locempty && type == MAT_FINAL_ASSEMBLY) {
2757872cf891SStefano Zampini     Mat                    newlA;
2758f03112d0SStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g;
2759f03112d0SStefano Zampini     IS                     nzr,nzc;
2760f03112d0SStefano Zampini     PetscInt               nr,nc,nnzr,nnzc;
2761f03112d0SStefano Zampini     PetscBool              lnewl2g,newl2g;
2762872cf891SStefano Zampini 
2763f03112d0SStefano Zampini     ierr = MatGetSize(is->A,&nr,&nc);CHKERRQ(ierr);
2764f03112d0SStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_FALSE,PETSC_SMALL,&nzr);CHKERRQ(ierr);
2765f03112d0SStefano Zampini     if (!nzr) {
2766f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&nzr);CHKERRQ(ierr);
2767872cf891SStefano Zampini     }
2768f03112d0SStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_TRUE,PETSC_SMALL,&nzc);CHKERRQ(ierr);
2769f03112d0SStefano Zampini     if (!nzc) {
2770f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&nzc);CHKERRQ(ierr);
2771872cf891SStefano Zampini     }
2772f03112d0SStefano Zampini     ierr = ISGetSize(nzr,&nnzr);CHKERRQ(ierr);
2773f03112d0SStefano Zampini     ierr = ISGetSize(nzc,&nnzc);CHKERRQ(ierr);
2774f03112d0SStefano Zampini     if (nnzr != nr || nnzc != nc) {
2775f03112d0SStefano Zampini       ISLocalToGlobalMapping l2g;
2776f03112d0SStefano Zampini       IS                     is1,is2;
2777f03112d0SStefano Zampini 
2778f03112d0SStefano Zampini       /* need new global l2g map */
2779f03112d0SStefano Zampini       lnewl2g = PETSC_TRUE;
278055b25c41SPierre Jolivet       ierr    = MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr);
2781f03112d0SStefano Zampini 
2782872cf891SStefano Zampini       /* extract valid submatrix */
2783f03112d0SStefano Zampini       ierr = MatCreateSubMatrix(is->A,nzr,nzc,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
2784f03112d0SStefano Zampini 
2785f03112d0SStefano Zampini       /* attach local l2g maps for successive calls of MatSetValues on the local matrix */
2786f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(nzr,&l2g);CHKERRQ(ierr);
2787f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&is1);CHKERRQ(ierr);
2788f03112d0SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_MASK,is1,&is2);CHKERRQ(ierr);
2789872cf891SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
279072ed36d8SStefano Zampini       if (is->A->rmap->mapping) { /* the matrix has a local-to-local map already attached (probably DMDA generated) */
279172ed36d8SStefano Zampini         const PetscInt *idxs1,*idxs2;
279272ed36d8SStefano Zampini         PetscInt       j,i,nl,*tidxs;
279372ed36d8SStefano Zampini 
279472ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(is->A->rmap->mapping,&nl);CHKERRQ(ierr);
279572ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(is->A->rmap->mapping,&idxs1);CHKERRQ(ierr);
279672ed36d8SStefano Zampini         ierr = PetscMalloc1(nl,&tidxs);CHKERRQ(ierr);
279772ed36d8SStefano Zampini         ierr = ISGetIndices(is2,&idxs2);CHKERRQ(ierr);
279872ed36d8SStefano Zampini         for (i=0,j=0;i<nl;i++) tidxs[i] = idxs1[i] < 0 ? -1 : idxs2[j++];
2799*2c71b3e2SJacob Faibussowitsch         PetscCheckFalse(j != nr,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected count %" PetscInt_FMT " != %" PetscInt_FMT,j,nr);
280072ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(is->A->rmap->mapping,&idxs1);CHKERRQ(ierr);
280172ed36d8SStefano Zampini         ierr = ISRestoreIndices(is2,&idxs2);CHKERRQ(ierr);
280272ed36d8SStefano Zampini         ierr = ISDestroy(&is2);CHKERRQ(ierr);
280372ed36d8SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A->rmap->mapping),nl,tidxs,PETSC_OWN_POINTER,&is2);CHKERRQ(ierr);
280472ed36d8SStefano Zampini       }
2805f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is2,&rl2g);CHKERRQ(ierr);
2806f03112d0SStefano Zampini       ierr = ISDestroy(&is1);CHKERRQ(ierr);
2807f03112d0SStefano Zampini       ierr = ISDestroy(&is2);CHKERRQ(ierr);
280872ed36d8SStefano Zampini 
2809f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(nzc,&l2g);CHKERRQ(ierr);
2810f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&is1);CHKERRQ(ierr);
2811f03112d0SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_MASK,is1,&is2);CHKERRQ(ierr);
2812f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
281372ed36d8SStefano Zampini       if (is->A->cmap->mapping) { /* the matrix has a local-to-local map already attached (probably DMDA generated) */
281472ed36d8SStefano Zampini         const PetscInt *idxs1,*idxs2;
281572ed36d8SStefano Zampini         PetscInt       j,i,nl,*tidxs;
281672ed36d8SStefano Zampini 
281772ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(is->A->cmap->mapping,&nl);CHKERRQ(ierr);
281872ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(is->A->cmap->mapping,&idxs1);CHKERRQ(ierr);
281972ed36d8SStefano Zampini         ierr = PetscMalloc1(nl,&tidxs);CHKERRQ(ierr);
282072ed36d8SStefano Zampini         ierr = ISGetIndices(is2,&idxs2);CHKERRQ(ierr);
282172ed36d8SStefano Zampini         for (i=0,j=0;i<nl;i++) tidxs[i] = idxs1[i] < 0 ? -1 : idxs2[j++];
2822*2c71b3e2SJacob Faibussowitsch         PetscCheckFalse(j != nc,PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected count %" PetscInt_FMT " != %" PetscInt_FMT,j,nc);
282372ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(is->A->cmap->mapping,&idxs1);CHKERRQ(ierr);
282472ed36d8SStefano Zampini         ierr = ISRestoreIndices(is2,&idxs2);CHKERRQ(ierr);
282572ed36d8SStefano Zampini         ierr = ISDestroy(&is2);CHKERRQ(ierr);
282672ed36d8SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A->cmap->mapping),nl,tidxs,PETSC_OWN_POINTER,&is2);CHKERRQ(ierr);
282772ed36d8SStefano Zampini       }
2828f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is2,&cl2g);CHKERRQ(ierr);
2829f03112d0SStefano Zampini       ierr = ISDestroy(&is1);CHKERRQ(ierr);
2830f03112d0SStefano Zampini       ierr = ISDestroy(&is2);CHKERRQ(ierr);
283172ed36d8SStefano Zampini 
2832f03112d0SStefano Zampini       ierr = MatSetLocalToGlobalMapping(newlA,rl2g,cl2g);CHKERRQ(ierr);
283372ed36d8SStefano Zampini 
2834f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2835f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2836f03112d0SStefano Zampini     } else { /* local matrix fully populated */
2837f03112d0SStefano Zampini       lnewl2g = PETSC_FALSE;
283855b25c41SPierre Jolivet       ierr    = MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRMPI(ierr);
2839f03112d0SStefano Zampini       ierr    = PetscObjectReference((PetscObject)is->A);CHKERRQ(ierr);
2840f03112d0SStefano Zampini       newlA   = is->A;
2841f03112d0SStefano Zampini     }
2842f03112d0SStefano Zampini     /* attach new global l2g map if needed */
2843f03112d0SStefano Zampini     if (newl2g) {
2844f03112d0SStefano Zampini       IS             gnzr,gnzc;
2845f03112d0SStefano Zampini       const PetscInt *grid,*gcid;
2846f03112d0SStefano Zampini 
2847f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(A->rmap->mapping,nzr,&gnzr);CHKERRQ(ierr);
2848f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(A->cmap->mapping,nzc,&gnzc);CHKERRQ(ierr);
2849f03112d0SStefano Zampini       ierr = ISGetIndices(gnzr,&grid);CHKERRQ(ierr);
2850f03112d0SStefano Zampini       ierr = ISGetIndices(gnzc,&gcid);CHKERRQ(ierr);
2851f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nnzr,grid,PETSC_COPY_VALUES,&rl2g);CHKERRQ(ierr);
2852f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nnzc,gcid,PETSC_COPY_VALUES,&cl2g);CHKERRQ(ierr);
2853f03112d0SStefano Zampini       ierr = ISRestoreIndices(gnzr,&grid);CHKERRQ(ierr);
2854f03112d0SStefano Zampini       ierr = ISRestoreIndices(gnzc,&gcid);CHKERRQ(ierr);
2855f03112d0SStefano Zampini       ierr = ISDestroy(&gnzr);CHKERRQ(ierr);
2856f03112d0SStefano Zampini       ierr = ISDestroy(&gnzc);CHKERRQ(ierr);
2857f03112d0SStefano Zampini       ierr = MatSetLocalToGlobalMapping(A,rl2g,cl2g);CHKERRQ(ierr);
2858f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2859f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2860f03112d0SStefano Zampini     }
2861872cf891SStefano Zampini     ierr = MatISSetLocalMat(A,newlA);CHKERRQ(ierr);
2862872cf891SStefano Zampini     ierr = MatDestroy(&newlA);CHKERRQ(ierr);
2863f03112d0SStefano Zampini     ierr = ISDestroy(&nzr);CHKERRQ(ierr);
2864f03112d0SStefano Zampini     ierr = ISDestroy(&nzc);CHKERRQ(ierr);
2865872cf891SStefano Zampini     is->locempty = PETSC_FALSE;
2866f03112d0SStefano Zampini   }
2867b4319ba4SBarry Smith   PetscFunctionReturn(0);
2868b4319ba4SBarry Smith }
2869b4319ba4SBarry Smith 
2870a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
2871b4319ba4SBarry Smith {
2872b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
2873b4319ba4SBarry Smith 
2874b4319ba4SBarry Smith   PetscFunctionBegin;
2875b4319ba4SBarry Smith   *local = is->A;
2876b4319ba4SBarry Smith   PetscFunctionReturn(0);
2877b4319ba4SBarry Smith }
2878b4319ba4SBarry Smith 
28793b3b1effSJed Brown static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local)
28803b3b1effSJed Brown {
28813b3b1effSJed Brown   PetscFunctionBegin;
28823b3b1effSJed Brown   *local = NULL;
28833b3b1effSJed Brown   PetscFunctionReturn(0);
28843b3b1effSJed Brown }
28853b3b1effSJed Brown 
2886b4319ba4SBarry Smith /*@
2887b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
2888b4319ba4SBarry Smith 
2889b4319ba4SBarry Smith   Input Parameter:
2890b4319ba4SBarry Smith .  mat - the matrix
2891b4319ba4SBarry Smith 
2892b4319ba4SBarry Smith   Output Parameter:
2893eb82efa4SStefano Zampini .  local - the local matrix
2894b4319ba4SBarry Smith 
2895b4319ba4SBarry Smith   Level: advanced
2896b4319ba4SBarry Smith 
2897b4319ba4SBarry Smith   Notes:
2898b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
2899b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
2900b4319ba4SBarry Smith   of the MatSetValues() operation.
2901b4319ba4SBarry Smith 
29023b3b1effSJed Brown   Call MatISRestoreLocalMat() when finished with the local matrix.
290396a6f129SJed Brown 
2904b4319ba4SBarry Smith .seealso: MATIS
2905b4319ba4SBarry Smith @*/
29067087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
2907b4319ba4SBarry Smith {
29084ac538c5SBarry Smith   PetscErrorCode ierr;
2909b4319ba4SBarry Smith 
2910b4319ba4SBarry Smith   PetscFunctionBegin;
29110700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2912b4319ba4SBarry Smith   PetscValidPointer(local,2);
29134ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
2914b4319ba4SBarry Smith   PetscFunctionReturn(0);
2915b4319ba4SBarry Smith }
2916b4319ba4SBarry Smith 
29173b3b1effSJed Brown /*@
29183b3b1effSJed Brown     MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat()
29193b3b1effSJed Brown 
29203b3b1effSJed Brown   Input Parameter:
29213b3b1effSJed Brown .  mat - the matrix
29223b3b1effSJed Brown 
29233b3b1effSJed Brown   Output Parameter:
29243b3b1effSJed Brown .  local - the local matrix
29253b3b1effSJed Brown 
29263b3b1effSJed Brown   Level: advanced
29273b3b1effSJed Brown 
29283b3b1effSJed Brown .seealso: MATIS
29293b3b1effSJed Brown @*/
29303b3b1effSJed Brown PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local)
29313b3b1effSJed Brown {
29323b3b1effSJed Brown   PetscErrorCode ierr;
29333b3b1effSJed Brown 
29343b3b1effSJed Brown   PetscFunctionBegin;
29353b3b1effSJed Brown   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
29363b3b1effSJed Brown   PetscValidPointer(local,2);
29373b3b1effSJed Brown   ierr = PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
29383b3b1effSJed Brown   PetscFunctionReturn(0);
29393b3b1effSJed Brown }
29403b3b1effSJed Brown 
29418546b261SStefano Zampini static PetscErrorCode MatISSetLocalMatType_IS(Mat mat,MatType mtype)
29428546b261SStefano Zampini {
29438546b261SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
29448546b261SStefano Zampini   PetscErrorCode ierr;
29458546b261SStefano Zampini 
29468546b261SStefano Zampini   PetscFunctionBegin;
29478546b261SStefano Zampini   if (is->A) {
29488546b261SStefano Zampini     ierr = MatSetType(is->A,mtype);CHKERRQ(ierr);
29498546b261SStefano Zampini   }
29508546b261SStefano Zampini   ierr = PetscFree(is->lmattype);CHKERRQ(ierr);
29518546b261SStefano Zampini   ierr = PetscStrallocpy(mtype,&is->lmattype);CHKERRQ(ierr);
29528546b261SStefano Zampini   PetscFunctionReturn(0);
29538546b261SStefano Zampini }
29548546b261SStefano Zampini 
29558546b261SStefano Zampini /*@
29568546b261SStefano Zampini     MatISSetLocalMatType - Specifies the type of local matrix
29578546b261SStefano Zampini 
2958d8d19677SJose E. Roman   Input Parameters:
2959a2b725a8SWilliam Gropp +  mat - the matrix
2960a2b725a8SWilliam Gropp -  mtype - the local matrix type
29618546b261SStefano Zampini 
29628546b261SStefano Zampini   Output Parameter:
29638546b261SStefano Zampini 
29648546b261SStefano Zampini   Level: advanced
29658546b261SStefano Zampini 
29668546b261SStefano Zampini .seealso: MATIS, MatSetType(), MatType
29678546b261SStefano Zampini @*/
29688546b261SStefano Zampini PetscErrorCode MatISSetLocalMatType(Mat mat,MatType mtype)
29698546b261SStefano Zampini {
29708546b261SStefano Zampini   PetscErrorCode ierr;
29718546b261SStefano Zampini 
29728546b261SStefano Zampini   PetscFunctionBegin;
29738546b261SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
29748546b261SStefano Zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMatType_C",(Mat,MatType),(mat,mtype));CHKERRQ(ierr);
29758546b261SStefano Zampini   PetscFunctionReturn(0);
29768546b261SStefano Zampini }
29778546b261SStefano Zampini 
2978a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
29793b03a366Sstefano_zampini {
29803b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
29813b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
29823b03a366Sstefano_zampini   PetscErrorCode ierr;
29838546b261SStefano Zampini   MatType        mtype,otype;
29848546b261SStefano Zampini   PetscBool      sametype = PETSC_TRUE;
29853b03a366Sstefano_zampini 
29863b03a366Sstefano_zampini   PetscFunctionBegin;
29874e4c7dbeSStefano Zampini   if (is->A) {
29883b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
29893b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
2990*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(orows != nrows || ocols != ncols,PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local MATIS matrix should be of size %" PetscInt_FMT "x%" PetscInt_FMT " (you passed a %" PetscInt_FMT "x%" PetscInt_FMT " matrix)",orows,ocols,nrows,ncols);
29918546b261SStefano Zampini     ierr = MatGetType(local,&mtype);CHKERRQ(ierr);
29928546b261SStefano Zampini     ierr = MatGetType(is->A,&otype);CHKERRQ(ierr);
29938546b261SStefano Zampini     ierr = PetscStrcmp(mtype,otype,&sametype);CHKERRQ(ierr);
29944e4c7dbeSStefano Zampini   }
29953b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
29963b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
29973b03a366Sstefano_zampini   is->A = local;
29988546b261SStefano Zampini   ierr  = MatGetType(is->A,&mtype);CHKERRQ(ierr);
29998546b261SStefano Zampini   ierr  = MatISSetLocalMatType(mat,mtype);CHKERRQ(ierr);
30008546b261SStefano Zampini   if (!sametype && !is->islocalref) {
30018546b261SStefano Zampini     ierr = MatISSetUpScatters_Private(mat);CHKERRQ(ierr);
30028546b261SStefano Zampini   }
30033b03a366Sstefano_zampini   PetscFunctionReturn(0);
30043b03a366Sstefano_zampini }
30053b03a366Sstefano_zampini 
30063b03a366Sstefano_zampini /*@
3007eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
30083b03a366Sstefano_zampini 
30098546b261SStefano Zampini   Collective on Mat
30108546b261SStefano Zampini 
3011d8d19677SJose E. Roman   Input Parameters:
3012a2b725a8SWilliam Gropp +  mat - the matrix
3013a2b725a8SWilliam Gropp -  local - the local matrix
30143b03a366Sstefano_zampini 
30153b03a366Sstefano_zampini   Output Parameter:
30163b03a366Sstefano_zampini 
30173b03a366Sstefano_zampini   Level: advanced
30183b03a366Sstefano_zampini 
30193b03a366Sstefano_zampini   Notes:
30203b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
30213b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
30223b03a366Sstefano_zampini 
30233b03a366Sstefano_zampini .seealso: MATIS
30243b03a366Sstefano_zampini @*/
30253b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
30263b03a366Sstefano_zampini {
30273b03a366Sstefano_zampini   PetscErrorCode ierr;
30283b03a366Sstefano_zampini 
30293b03a366Sstefano_zampini   PetscFunctionBegin;
30303b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3031b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
30323b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
30333b03a366Sstefano_zampini   PetscFunctionReturn(0);
30343b03a366Sstefano_zampini }
30353b03a366Sstefano_zampini 
3036a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
30376726f965SBarry Smith {
30386726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
30396726f965SBarry Smith   PetscErrorCode ierr;
30406726f965SBarry Smith 
30416726f965SBarry Smith   PetscFunctionBegin;
30426726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
30436726f965SBarry Smith   PetscFunctionReturn(0);
30446726f965SBarry Smith }
30456726f965SBarry Smith 
3046a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
30472e74eeadSLisandro Dalcin {
30482e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
30492e74eeadSLisandro Dalcin   PetscErrorCode ierr;
30502e74eeadSLisandro Dalcin 
30512e74eeadSLisandro Dalcin   PetscFunctionBegin;
30522e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
30532e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
30542e74eeadSLisandro Dalcin }
30552e74eeadSLisandro Dalcin 
3056a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
30572e74eeadSLisandro Dalcin {
30582e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
30592e74eeadSLisandro Dalcin   PetscErrorCode ierr;
30602e74eeadSLisandro Dalcin 
30612e74eeadSLisandro Dalcin   PetscFunctionBegin;
30622e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
3063e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
30642e74eeadSLisandro Dalcin 
30652e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
30662e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
3067e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3068e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
30692e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
30702e74eeadSLisandro Dalcin }
30712e74eeadSLisandro Dalcin 
3072a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
30736726f965SBarry Smith {
30746726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
30756726f965SBarry Smith   PetscErrorCode ierr;
30766726f965SBarry Smith 
30776726f965SBarry Smith   PetscFunctionBegin;
30784e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
30796726f965SBarry Smith   PetscFunctionReturn(0);
30806726f965SBarry Smith }
30816726f965SBarry Smith 
3082f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
3083f26d0771SStefano Zampini {
3084f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
3085f26d0771SStefano Zampini   Mat_IS         *x;
3086f26d0771SStefano Zampini   PetscErrorCode ierr;
3087f26d0771SStefano Zampini 
3088f26d0771SStefano Zampini   PetscFunctionBegin;
308976bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
309076bd3646SJed Brown     PetscBool      ismatis;
3091f26d0771SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
3092*2c71b3e2SJacob Faibussowitsch     PetscCheckFalse(!ismatis,PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
309376bd3646SJed Brown   }
3094f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
3095f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
3096f26d0771SStefano Zampini   PetscFunctionReturn(0);
3097f26d0771SStefano Zampini }
3098f26d0771SStefano Zampini 
3099f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
3100f26d0771SStefano Zampini {
3101f26d0771SStefano Zampini   Mat                    lA;
3102f26d0771SStefano Zampini   Mat_IS                 *matis;
3103f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
3104f26d0771SStefano Zampini   IS                     is;
3105f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
3106f26d0771SStefano Zampini   PetscInt               nrg;
3107f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
3108f26d0771SStefano Zampini   PetscErrorCode         ierr;
3109f26d0771SStefano Zampini 
3110f26d0771SStefano Zampini   PetscFunctionBegin;
3111f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
3112f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
3113f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
3114f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
311576bd3646SJed Brown   if (PetscDefined(USE_DEBUG)) {
3116*2c71b3e2SJacob Faibussowitsch     for (i=0; i<nrl; i++) PetscCheckFalse(rl[i]>=nrg,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row index %" PetscInt_FMT " -> %" PetscInt_FMT " greater then maximum possible %" PetscInt_FMT,i,rl[i],nrg);
311776bd3646SJed Brown   }
3118f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
3119f26d0771SStefano Zampini   /* map from [0,nrl) to row */
3120f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
3121f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
3122f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
3123f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
3124f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
3125f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
3126f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
3127f26d0771SStefano Zampini   /* compute new l2g map for columns */
3128f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
3129f26d0771SStefano Zampini     const PetscInt *cg,*cl;
3130f26d0771SStefano Zampini     PetscInt       ncg;
3131f26d0771SStefano Zampini     PetscInt       ncl;
3132f26d0771SStefano Zampini 
3133f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
3134f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
3135f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
3136f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
313776bd3646SJed Brown     if (PetscDefined(USE_DEBUG)) {
3138*2c71b3e2SJacob Faibussowitsch       for (i=0; i<ncl; i++) PetscCheckFalse(cl[i]>=ncg,PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local column index %" PetscInt_FMT " -> %" PetscInt_FMT " greater then maximum possible %" PetscInt_FMT,i,cl[i],ncg);
313976bd3646SJed Brown     }
3140f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
3141f26d0771SStefano Zampini     /* map from [0,ncl) to col */
3142f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
3143f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
3144f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
3145f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
3146f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
3147f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
3148f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
3149f26d0771SStefano Zampini   } else {
3150f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
3151f26d0771SStefano Zampini     cl2g = rl2g;
3152f26d0771SStefano Zampini   }
3153f26d0771SStefano Zampini   /* create the MATIS submatrix */
3154f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
3155f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
3156f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
3157f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
3158b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
3159f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
3160f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
3161f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
3162f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
3163f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
3164f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3165f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3166f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3167f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3168f26d0771SStefano Zampini   /* remove unsupported ops */
3169f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
3170f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
3171f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
3172f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
3173f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
3174f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
3175f26d0771SStefano Zampini   PetscFunctionReturn(0);
3176f26d0771SStefano Zampini }
3177f26d0771SStefano Zampini 
3178872cf891SStefano Zampini static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A)
3179872cf891SStefano Zampini {
3180872cf891SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
31818546b261SStefano Zampini   char           type[256];
31828546b261SStefano Zampini   PetscBool      flg;
3183872cf891SStefano Zampini   PetscErrorCode ierr;
3184872cf891SStefano Zampini 
3185872cf891SStefano Zampini   PetscFunctionBegin;
3186872cf891SStefano Zampini   ierr = PetscOptionsHead(PetscOptionsObject,"MATIS options");CHKERRQ(ierr);
3187f03112d0SStefano Zampini   ierr = PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns","MatISFixLocalEmpty",a->locempty,&a->locempty,NULL);CHKERRQ(ierr);
318875d48cdbSStefano Zampini   ierr = PetscOptionsBool("-matis_storel2l","Store local-to-local matrices generated from PtAP operations","MatISStoreL2L",a->storel2l,&a->storel2l,NULL);CHKERRQ(ierr);
31898546b261SStefano Zampini   ierr = PetscOptionsFList("-matis_localmat_type","Matrix type","MatISSetLocalMatType",MatList,a->lmattype,type,256,&flg);CHKERRQ(ierr);
31908546b261SStefano Zampini   if (flg) {
31918546b261SStefano Zampini     ierr = MatISSetLocalMatType(A,type);CHKERRQ(ierr);
31928546b261SStefano Zampini   }
31938546b261SStefano Zampini   if (a->A) {
31948546b261SStefano Zampini     ierr = MatSetFromOptions(a->A);CHKERRQ(ierr);
31958546b261SStefano Zampini   }
31960af67c1bSStefano Zampini   ierr = PetscOptionsTail();CHKERRQ(ierr);
3197872cf891SStefano Zampini   PetscFunctionReturn(0);
3198872cf891SStefano Zampini }
3199872cf891SStefano Zampini 
3200284134d9SBarry Smith /*@
32013c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
3202284134d9SBarry Smith        process but not across processes.
3203284134d9SBarry Smith 
3204284134d9SBarry Smith    Input Parameters:
3205284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
3206e176bc59SStefano Zampini .     bs      - block size of the matrix
3207df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
3208e176bc59SStefano Zampini .     rmap    - local to global map for rows
3209e176bc59SStefano Zampini -     cmap    - local to global map for cols
3210284134d9SBarry Smith 
3211284134d9SBarry Smith    Output Parameter:
3212284134d9SBarry Smith .    A - the resulting matrix
3213284134d9SBarry Smith 
32148e6c10adSSatish Balay    Level: advanced
32158e6c10adSSatish Balay 
321695452b02SPatrick Sanan    Notes:
321795452b02SPatrick Sanan     See MATIS for more details.
3218fc989267SStefano Zampini     m and n are NOT related to the size of the map; they represent the size of the local parts of the distributed vectors
32196fdf41d1SStefano Zampini     used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
3220fc989267SStefano Zampini     If rmap (cmap) is NULL, then the local row (column) spaces matches the global space.
3221284134d9SBarry Smith 
3222284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
3223284134d9SBarry Smith @*/
3224e176bc59SStefano Zampini PetscErrorCode MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
3225284134d9SBarry Smith {
3226284134d9SBarry Smith   PetscErrorCode ierr;
3227284134d9SBarry Smith 
3228284134d9SBarry Smith   PetscFunctionBegin;
3229284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
3230284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
32316fdf41d1SStefano Zampini   if (bs > 0) {
3232284134d9SBarry Smith     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
32336fdf41d1SStefano Zampini   }
3234284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
3235e176bc59SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
3236284134d9SBarry Smith   PetscFunctionReturn(0);
3237284134d9SBarry Smith }
3238284134d9SBarry Smith 
32398b9382cfSStefano Zampini static PetscErrorCode MatHasOperation_IS(Mat A, MatOperation op, PetscBool *has)
32408b9382cfSStefano Zampini {
32418b9382cfSStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
32428b9382cfSStefano Zampini   PetscErrorCode ierr;
32438b9382cfSStefano Zampini 
32448b9382cfSStefano Zampini   PetscFunctionBegin;
32458b9382cfSStefano Zampini   *has = PETSC_FALSE;
32468b9382cfSStefano Zampini   if (!((void**)A->ops)[op]) PetscFunctionReturn(0);
32478b9382cfSStefano Zampini   ierr = MatHasOperation(a->A,op,has);CHKERRQ(ierr);
32488b9382cfSStefano Zampini   PetscFunctionReturn(0);
32498b9382cfSStefano Zampini }
32508b9382cfSStefano Zampini 
3251b4319ba4SBarry Smith /*MC
3252f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
3253b89f26deSStefano Zampini    This stores the matrices in globally unassembled form. Each processor assembles only its local Neumann problem and the parallel matrix vector
3254b4319ba4SBarry Smith    product is handled "implicitly".
3255b4319ba4SBarry Smith 
3256b4319ba4SBarry Smith    Options Database Keys:
325775d48cdbSStefano Zampini + -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
325875d48cdbSStefano Zampini . -matis_fixempty - Fixes local matrices in case of empty local rows/columns.
325975d48cdbSStefano Zampini - -matis_storel2l - stores the local-to-local operators generated by the Galerkin process of MatPtAP().
3260b4319ba4SBarry Smith 
326195452b02SPatrick Sanan    Notes:
326295452b02SPatrick Sanan     Options prefix for the inner matrix are given by -is_mat_xxx
3263b4319ba4SBarry Smith 
3264b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
3265b4319ba4SBarry Smith 
3266b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
3267eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
3268b4319ba4SBarry Smith 
3269b4319ba4SBarry Smith   Level: advanced
3270b4319ba4SBarry Smith 
3271f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
3272b4319ba4SBarry Smith 
3273b4319ba4SBarry Smith M*/
32748cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
3275b4319ba4SBarry Smith {
3276dfbe8321SBarry Smith   PetscErrorCode ierr;
3277b4319ba4SBarry Smith   Mat_IS         *b;
3278b4319ba4SBarry Smith 
3279b4319ba4SBarry Smith   PetscFunctionBegin;
3280b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
32818546b261SStefano Zampini   ierr    = PetscStrallocpy(MATAIJ,&b->lmattype);CHKERRQ(ierr);
3282b4319ba4SBarry Smith   A->data = (void*)b;
3283b4319ba4SBarry Smith 
3284e176bc59SStefano Zampini   /* matrix ops */
3285e176bc59SStefano Zampini   ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
3286b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
32872e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
32882e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
32892e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
3290b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
3291b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
32922e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
329398921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
3294b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
3295f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
32962e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
3297f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
3298b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
3299b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
3300b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
33016726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
33022e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
33032e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
33046726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
330569796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
330669796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
330745471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
3308ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
33096bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
33102b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
3311659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
33127dae84e0SHong Zhang   A->ops->createsubmatrix         = MatCreateSubMatrix_IS;
3313f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
33143fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
33153fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
3316d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
33177fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
3318ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
3319872cf891SStefano Zampini   A->ops->setfromoptions          = MatSetFromOptions_IS;
3320fc989267SStefano Zampini   A->ops->setup                   = MatSetUp_IS;
33218b9382cfSStefano Zampini   A->ops->hasoperation            = MatHasOperation_IS;
3322b4319ba4SBarry Smith 
3323b7ce53b6SStefano Zampini   /* special MATIS functions */
33248546b261SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",MatISSetLocalMatType_IS);CHKERRQ(ierr);
3325bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
33263b3b1effSJed Brown   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS);CHKERRQ(ierr);
3327bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
3328487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
33292e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
333075d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",MatISStoreL2L_IS);CHKERRQ(ierr);
3331f03112d0SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",MatISFixLocalEmpty_IS);CHKERRQ(ierr);
3332487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3333487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3334487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3335487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3336487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3337487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3338487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
333917667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
3340b4319ba4SBarry Smith   PetscFunctionReturn(0);
3341b4319ba4SBarry Smith }
3342