xref: /petsc/src/mat/impls/is/matis.c (revision 35928de7f7ca26a8de4874654cc856a8423a00bd)
1b4319ba4SBarry Smith /*
2b4319ba4SBarry Smith     Creates a matrix class for using the Neumann-Neumann type preconditioners.
3b4319ba4SBarry Smith     This stores the matrices in globally unassembled form. Each processor
4b4319ba4SBarry Smith     assembles only its local Neumann problem and the parallel matrix vector
5b4319ba4SBarry Smith     product is handled "implicitly".
6b4319ba4SBarry Smith 
7b4319ba4SBarry Smith     Currently this allows for only one subdomain per processor.
8b4319ba4SBarry Smith */
9b4319ba4SBarry Smith 
10c6db04a5SJed Brown #include <../src/mat/impls/is/matis.h>      /*I "petscmat.h" I*/
114f2d7cafSStefano Zampini #include <petsc/private/sfimpl.h>
1228f4e0baSStefano Zampini 
13f26d0771SStefano Zampini #define MATIS_MAX_ENTRIES_INSERTION 2048
14b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode);
15b4f971dfSStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat,PetscInt,const PetscInt*,PetscInt,const PetscInt*,const PetscScalar*,InsertMode);
168546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat);
17f26d0771SStefano Zampini 
1875d48cdbSStefano Zampini static PetscErrorCode MatISContainerDestroyPtAP_Private(void *ptr)
1975d48cdbSStefano Zampini {
2075d48cdbSStefano Zampini   MatISPtAP      ptap = (MatISPtAP)ptr;
2175d48cdbSStefano Zampini   PetscErrorCode ierr;
2275d48cdbSStefano Zampini 
2375d48cdbSStefano Zampini   PetscFunctionBegin;
2475d48cdbSStefano Zampini   ierr = MatDestroySubMatrices(ptap->ris1 ? 2 : 1,&ptap->lP);CHKERRQ(ierr);
2575d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->cis0);CHKERRQ(ierr);
2675d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->cis1);CHKERRQ(ierr);
2775d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->ris0);CHKERRQ(ierr);
2875d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->ris1);CHKERRQ(ierr);
2975d48cdbSStefano Zampini   ierr = PetscFree(ptap);CHKERRQ(ierr);
3075d48cdbSStefano Zampini   PetscFunctionReturn(0);
3175d48cdbSStefano Zampini }
3275d48cdbSStefano Zampini 
3375d48cdbSStefano Zampini static PetscErrorCode MatPtAPNumeric_IS_XAIJ(Mat A, Mat P, Mat C)
3475d48cdbSStefano Zampini {
3575d48cdbSStefano Zampini   MatISPtAP      ptap;
3675d48cdbSStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
3775d48cdbSStefano Zampini   Mat            lA,lC;
3875d48cdbSStefano Zampini   MatReuse       reuse;
3975d48cdbSStefano Zampini   IS             ris[2],cis[2];
4075d48cdbSStefano Zampini   PetscContainer c;
4175d48cdbSStefano Zampini   PetscInt       n;
4275d48cdbSStefano Zampini   PetscErrorCode ierr;
4375d48cdbSStefano Zampini 
4475d48cdbSStefano Zampini   PetscFunctionBegin;
456afe12f5SStefano Zampini   ierr = PetscObjectQuery((PetscObject)C,"_MatIS_PtAP",(PetscObject*)&c);CHKERRQ(ierr);
4675d48cdbSStefano Zampini   if (!c) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing PtAP information");
4775d48cdbSStefano Zampini   ierr   = PetscContainerGetPointer(c,(void**)&ptap);CHKERRQ(ierr);
4875d48cdbSStefano Zampini   ris[0] = ptap->ris0;
4975d48cdbSStefano Zampini   ris[1] = ptap->ris1;
5075d48cdbSStefano Zampini   cis[0] = ptap->cis0;
5175d48cdbSStefano Zampini   cis[1] = ptap->cis1;
5275d48cdbSStefano Zampini   n      = ptap->ris1 ? 2 : 1;
5375d48cdbSStefano Zampini   reuse  = ptap->lP ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX;
5475d48cdbSStefano Zampini   ierr   = MatCreateSubMatrices(P,n,ris,cis,reuse,&ptap->lP);CHKERRQ(ierr);
5575d48cdbSStefano Zampini 
5675d48cdbSStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
5775d48cdbSStefano Zampini   ierr = MatISGetLocalMat(C,&lC);CHKERRQ(ierr);
5875d48cdbSStefano Zampini   if (ptap->ris1) { /* unsymmetric A mapping */
5975d48cdbSStefano Zampini     Mat lPt;
6075d48cdbSStefano Zampini 
6175d48cdbSStefano Zampini     ierr = MatTranspose(ptap->lP[1],MAT_INITIAL_MATRIX,&lPt);CHKERRQ(ierr);
6275d48cdbSStefano Zampini     ierr = MatMatMatMult(lPt,lA,ptap->lP[0],reuse,ptap->fill,&lC);CHKERRQ(ierr);
6375d48cdbSStefano Zampini     if (matis->storel2l) {
6475d48cdbSStefano Zampini       ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",(PetscObject)lPt);CHKERRQ(ierr);
6575d48cdbSStefano Zampini     }
6675d48cdbSStefano Zampini     ierr = MatDestroy(&lPt);CHKERRQ(ierr);
6775d48cdbSStefano Zampini   } else {
6875d48cdbSStefano Zampini     ierr = MatPtAP(lA,ptap->lP[0],reuse,ptap->fill,&lC);CHKERRQ(ierr);
6975d48cdbSStefano Zampini     if (matis->storel2l) {
7075d48cdbSStefano Zampini      ierr = PetscObjectCompose((PetscObject)(C),"_MatIS_PtAP_l2l",(PetscObject)ptap->lP[0]);CHKERRQ(ierr);
7175d48cdbSStefano Zampini     }
7275d48cdbSStefano Zampini   }
7375d48cdbSStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
7475d48cdbSStefano Zampini     ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
7575d48cdbSStefano Zampini     ierr = MatDestroy(&lC);CHKERRQ(ierr);
7675d48cdbSStefano Zampini   }
7775d48cdbSStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7875d48cdbSStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7975d48cdbSStefano Zampini   PetscFunctionReturn(0);
8075d48cdbSStefano Zampini }
8175d48cdbSStefano Zampini 
8275d48cdbSStefano Zampini static PetscErrorCode MatGetNonzeroColumnsLocal_Private(Mat PT,IS *cis)
8375d48cdbSStefano Zampini {
8475d48cdbSStefano Zampini   Mat            Po,Pd;
8575d48cdbSStefano Zampini   IS             zd,zo;
8675d48cdbSStefano Zampini   const PetscInt *garray;
8775d48cdbSStefano Zampini   PetscInt       *aux,i,bs;
8875d48cdbSStefano Zampini   PetscInt       dc,stc,oc,ctd,cto;
8975d48cdbSStefano Zampini   PetscBool      ismpiaij,ismpibaij,isseqaij,isseqbaij;
9075d48cdbSStefano Zampini   MPI_Comm       comm;
9175d48cdbSStefano Zampini   PetscErrorCode ierr;
9275d48cdbSStefano Zampini 
9375d48cdbSStefano Zampini   PetscFunctionBegin;
9475d48cdbSStefano Zampini   PetscValidHeaderSpecific(PT,MAT_CLASSID,1);
9575d48cdbSStefano Zampini   PetscValidPointer(cis,2);
9675d48cdbSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)PT,&comm);CHKERRQ(ierr);
9775d48cdbSStefano Zampini   bs   = 1;
9875d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
9975d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
10004637862SRichard Tran Mills   ierr = PetscObjectBaseTypeCompare((PetscObject)PT,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
10175d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
10275d48cdbSStefano Zampini   if (isseqaij || isseqbaij) {
10375d48cdbSStefano Zampini     Pd = PT;
10475d48cdbSStefano Zampini     Po = NULL;
10575d48cdbSStefano Zampini     garray = NULL;
10675d48cdbSStefano Zampini   } else if (ismpiaij) {
10775d48cdbSStefano Zampini     ierr = MatMPIAIJGetSeqAIJ(PT,&Pd,&Po,&garray);CHKERRQ(ierr);
10875d48cdbSStefano Zampini   } else if (ismpibaij) {
10975d48cdbSStefano Zampini     ierr = MatMPIBAIJGetSeqBAIJ(PT,&Pd,&Po,&garray);CHKERRQ(ierr);
11075d48cdbSStefano Zampini     ierr = MatGetBlockSize(PT,&bs);CHKERRQ(ierr);
11175d48cdbSStefano Zampini   } else SETERRQ1(comm,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(PT))->type_name);
11275d48cdbSStefano Zampini 
11375d48cdbSStefano Zampini   /* identify any null columns in Pd or Po */
11422f7620eSStefano Zampini   /* We use a tolerance comparison since it may happen that, with geometric multigrid,
11522f7620eSStefano Zampini      some of the columns are not really zero, but very close to */
11675d48cdbSStefano Zampini   zo = zd = NULL;
11775d48cdbSStefano Zampini   if (Po) {
11822f7620eSStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(Po,PETSC_TRUE,PETSC_SMALL,&zo);CHKERRQ(ierr);
11975d48cdbSStefano Zampini   }
12022f7620eSStefano Zampini   ierr = MatFindNonzeroRowsOrCols_Basic(Pd,PETSC_TRUE,PETSC_SMALL,&zd);CHKERRQ(ierr);
12175d48cdbSStefano Zampini 
12275d48cdbSStefano Zampini   ierr = MatGetLocalSize(PT,NULL,&dc);CHKERRQ(ierr);
12375d48cdbSStefano Zampini   ierr = MatGetOwnershipRangeColumn(PT,&stc,NULL);CHKERRQ(ierr);
12475d48cdbSStefano Zampini   if (Po) { ierr = MatGetLocalSize(Po,NULL,&oc);CHKERRQ(ierr); }
12575d48cdbSStefano Zampini   else oc = 0;
12675d48cdbSStefano Zampini   ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
12775d48cdbSStefano Zampini   if (zd) {
12875d48cdbSStefano Zampini     const PetscInt *idxs;
12975d48cdbSStefano Zampini     PetscInt       nz;
13075d48cdbSStefano Zampini 
13175d48cdbSStefano Zampini     /* this will throw an error if bs is not valid */
13275d48cdbSStefano Zampini     ierr = ISSetBlockSize(zd,bs);CHKERRQ(ierr);
13375d48cdbSStefano Zampini     ierr = ISGetLocalSize(zd,&nz);CHKERRQ(ierr);
13475d48cdbSStefano Zampini     ierr = ISGetIndices(zd,&idxs);CHKERRQ(ierr);
13575d48cdbSStefano Zampini     ctd  = nz/bs;
13675d48cdbSStefano Zampini     for (i=0; i<ctd; i++) aux[i] = (idxs[bs*i]+stc)/bs;
13775d48cdbSStefano Zampini     ierr = ISRestoreIndices(zd,&idxs);CHKERRQ(ierr);
13875d48cdbSStefano Zampini   } else {
13975d48cdbSStefano Zampini     ctd = dc/bs;
14075d48cdbSStefano Zampini     for (i=0; i<ctd; i++) aux[i] = i+stc/bs;
14175d48cdbSStefano Zampini   }
14275d48cdbSStefano Zampini   if (zo) {
14375d48cdbSStefano Zampini     const PetscInt *idxs;
14475d48cdbSStefano Zampini     PetscInt       nz;
14575d48cdbSStefano Zampini 
14675d48cdbSStefano Zampini     /* this will throw an error if bs is not valid */
14775d48cdbSStefano Zampini     ierr = ISSetBlockSize(zo,bs);CHKERRQ(ierr);
14875d48cdbSStefano Zampini     ierr = ISGetLocalSize(zo,&nz);CHKERRQ(ierr);
14975d48cdbSStefano Zampini     ierr = ISGetIndices(zo,&idxs);CHKERRQ(ierr);
15075d48cdbSStefano Zampini     cto  = nz/bs;
15175d48cdbSStefano Zampini     for (i=0; i<cto; i++) aux[i+ctd] = garray[idxs[bs*i]/bs];
15275d48cdbSStefano Zampini     ierr = ISRestoreIndices(zo,&idxs);CHKERRQ(ierr);
15375d48cdbSStefano Zampini   } else {
15475d48cdbSStefano Zampini     cto = oc/bs;
15575d48cdbSStefano Zampini     for (i=0; i<cto; i++) aux[i+ctd] = garray[i];
15675d48cdbSStefano Zampini   }
15775d48cdbSStefano Zampini   ierr = ISCreateBlock(comm,bs,ctd+cto,aux,PETSC_OWN_POINTER,cis);CHKERRQ(ierr);
15875d48cdbSStefano Zampini   ierr = ISDestroy(&zd);CHKERRQ(ierr);
15975d48cdbSStefano Zampini   ierr = ISDestroy(&zo);CHKERRQ(ierr);
16075d48cdbSStefano Zampini   PetscFunctionReturn(0);
16175d48cdbSStefano Zampini }
16275d48cdbSStefano Zampini 
16375d48cdbSStefano Zampini static PetscErrorCode MatPtAPSymbolic_IS_XAIJ(Mat A,Mat P,PetscReal fill,Mat *C)
16475d48cdbSStefano Zampini {
1658546b261SStefano Zampini   Mat                    PT,lA;
16675d48cdbSStefano Zampini   MatISPtAP              ptap;
16775d48cdbSStefano Zampini   ISLocalToGlobalMapping Crl2g,Ccl2g,rl2g,cl2g;
16875d48cdbSStefano Zampini   PetscContainer         c;
1698546b261SStefano Zampini   MatType                lmtype;
17075d48cdbSStefano Zampini   const PetscInt         *garray;
17175d48cdbSStefano Zampini   PetscInt               ibs,N,dc;
17275d48cdbSStefano Zampini   MPI_Comm               comm;
17375d48cdbSStefano Zampini   PetscErrorCode         ierr;
17475d48cdbSStefano Zampini 
17575d48cdbSStefano Zampini   PetscFunctionBegin;
17675d48cdbSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
17775d48cdbSStefano Zampini   ierr = MatCreate(comm,C);CHKERRQ(ierr);
17875d48cdbSStefano Zampini   ierr = MatSetType(*C,MATIS);CHKERRQ(ierr);
1798546b261SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1808546b261SStefano Zampini   ierr = MatGetType(lA,&lmtype);CHKERRQ(ierr);
1818546b261SStefano Zampini   ierr = MatISSetLocalMatType(*C,lmtype);CHKERRQ(ierr);
18275d48cdbSStefano Zampini   ierr = MatGetSize(P,NULL,&N);CHKERRQ(ierr);
18375d48cdbSStefano Zampini   ierr = MatGetLocalSize(P,NULL,&dc);CHKERRQ(ierr);
18475d48cdbSStefano Zampini   ierr = MatSetSizes(*C,dc,dc,N,N);CHKERRQ(ierr);
18575d48cdbSStefano Zampini /* Not sure about this
18675d48cdbSStefano Zampini   ierr = MatGetBlockSizes(P,NULL,&ibs);CHKERRQ(ierr);
18775d48cdbSStefano Zampini   ierr = MatSetBlockSize(*C,ibs);CHKERRQ(ierr);
18875d48cdbSStefano Zampini */
18975d48cdbSStefano Zampini 
19075d48cdbSStefano Zampini   ierr = PetscNew(&ptap);CHKERRQ(ierr);
19175d48cdbSStefano Zampini   ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
19275d48cdbSStefano Zampini   ierr = PetscContainerSetPointer(c,ptap);CHKERRQ(ierr);
19375d48cdbSStefano Zampini   ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyPtAP_Private);CHKERRQ(ierr);
19475d48cdbSStefano Zampini   ierr = PetscObjectCompose((PetscObject)(*C),"_MatIS_PtAP",(PetscObject)c);CHKERRQ(ierr);
19575d48cdbSStefano Zampini   ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
19675d48cdbSStefano Zampini   ptap->fill = fill;
19775d48cdbSStefano Zampini 
19875d48cdbSStefano Zampini   ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
19975d48cdbSStefano Zampini 
20075d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cl2g,&ibs);CHKERRQ(ierr);
20175d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cl2g,&N);CHKERRQ(ierr);
20275d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockIndices(cl2g,&garray);CHKERRQ(ierr);
20375d48cdbSStefano Zampini   ierr = ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris0);CHKERRQ(ierr);
20475d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&garray);CHKERRQ(ierr);
20575d48cdbSStefano Zampini 
20675d48cdbSStefano Zampini   ierr = MatCreateSubMatrix(P,ptap->ris0,NULL,MAT_INITIAL_MATRIX,&PT);CHKERRQ(ierr);
20775d48cdbSStefano Zampini   ierr = MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis0);CHKERRQ(ierr);
20875d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(ptap->cis0,&Ccl2g);CHKERRQ(ierr);
20975d48cdbSStefano Zampini   ierr = MatDestroy(&PT);CHKERRQ(ierr);
21075d48cdbSStefano Zampini 
21175d48cdbSStefano Zampini   Crl2g = NULL;
21275d48cdbSStefano Zampini   if (rl2g != cl2g) { /* unsymmetric A mapping */
21375d48cdbSStefano Zampini     PetscBool same,lsame = PETSC_FALSE;
21475d48cdbSStefano Zampini     PetscInt  N1,ibs1;
21575d48cdbSStefano Zampini 
21675d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(rl2g,&N1);CHKERRQ(ierr);
21775d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(rl2g,&ibs1);CHKERRQ(ierr);
21875d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(rl2g,&garray);CHKERRQ(ierr);
21975d48cdbSStefano Zampini     ierr = ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris1);CHKERRQ(ierr);
22075d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&garray);CHKERRQ(ierr);
22175d48cdbSStefano Zampini     if (ibs1 == ibs && N1 == N) { /* check if the l2gmaps are the same */
22275d48cdbSStefano Zampini       const PetscInt *i1,*i2;
22375d48cdbSStefano Zampini 
22475d48cdbSStefano Zampini       ierr = ISBlockGetIndices(ptap->ris0,&i1);CHKERRQ(ierr);
22575d48cdbSStefano Zampini       ierr = ISBlockGetIndices(ptap->ris1,&i2);CHKERRQ(ierr);
22675d48cdbSStefano Zampini       ierr = PetscMemcmp(i1,i2,N*sizeof(*i1),&lsame);CHKERRQ(ierr);
22775d48cdbSStefano Zampini     }
22875d48cdbSStefano Zampini     ierr = MPIU_Allreduce(&lsame,&same,1,MPIU_BOOL,MPI_LAND,comm);CHKERRQ(ierr);
22975d48cdbSStefano Zampini     if (same) {
23075d48cdbSStefano Zampini       ierr = ISDestroy(&ptap->ris1);CHKERRQ(ierr);
23175d48cdbSStefano Zampini     } else {
23275d48cdbSStefano Zampini       ierr = MatCreateSubMatrix(P,ptap->ris1,NULL,MAT_INITIAL_MATRIX,&PT);CHKERRQ(ierr);
23375d48cdbSStefano Zampini       ierr = MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis1);CHKERRQ(ierr);
23475d48cdbSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(ptap->cis1,&Crl2g);CHKERRQ(ierr);
23575d48cdbSStefano Zampini       ierr = MatDestroy(&PT);CHKERRQ(ierr);
23675d48cdbSStefano Zampini     }
23775d48cdbSStefano Zampini   }
23875d48cdbSStefano Zampini /* Not sure about this
23975d48cdbSStefano Zampini   if (!Crl2g) {
24075d48cdbSStefano Zampini     ierr = MatGetBlockSize(*C,&ibs);CHKERRQ(ierr);
24175d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(Ccl2g,ibs);CHKERRQ(ierr);
24275d48cdbSStefano Zampini   }
24375d48cdbSStefano Zampini */
24475d48cdbSStefano Zampini   ierr = MatSetLocalToGlobalMapping(*C,Crl2g ? Crl2g : Ccl2g,Ccl2g);CHKERRQ(ierr);
24575d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&Crl2g);CHKERRQ(ierr);
24675d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&Ccl2g);CHKERRQ(ierr);
24775d48cdbSStefano Zampini 
24875d48cdbSStefano Zampini   (*C)->ops->ptapnumeric = MatPtAPNumeric_IS_XAIJ;
24975d48cdbSStefano Zampini   PetscFunctionReturn(0);
25075d48cdbSStefano Zampini }
25175d48cdbSStefano Zampini 
25275d48cdbSStefano Zampini PETSC_INTERN PetscErrorCode MatPtAP_IS_XAIJ(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
25375d48cdbSStefano Zampini {
25475d48cdbSStefano Zampini   PetscErrorCode ierr;
25575d48cdbSStefano Zampini 
25675d48cdbSStefano Zampini   PetscFunctionBegin;
25775d48cdbSStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
25875d48cdbSStefano Zampini     ierr = PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
25975d48cdbSStefano Zampini     ierr = MatPtAPSymbolic_IS_XAIJ(A,P,fill,C);CHKERRQ(ierr);
26075d48cdbSStefano Zampini     ierr = PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
26175d48cdbSStefano Zampini   }
26275d48cdbSStefano Zampini   ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
26375d48cdbSStefano Zampini   ierr = ((*C)->ops->ptapnumeric)(A,P,*C);CHKERRQ(ierr);
26475d48cdbSStefano Zampini   ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
26575d48cdbSStefano Zampini   PetscFunctionReturn(0);
26675d48cdbSStefano Zampini }
26775d48cdbSStefano Zampini 
2685b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr)
2695b003df0Sstefano_zampini {
2705b003df0Sstefano_zampini   MatISLocalFields lf = (MatISLocalFields)ptr;
2715b003df0Sstefano_zampini   PetscInt         i;
2725b003df0Sstefano_zampini   PetscErrorCode   ierr;
2735b003df0Sstefano_zampini 
274ab4d48faSStefano Zampini   PetscFunctionBegin;
2755b003df0Sstefano_zampini   for (i=0;i<lf->nr;i++) {
2765b003df0Sstefano_zampini     ierr = ISDestroy(&lf->rf[i]);CHKERRQ(ierr);
2775b003df0Sstefano_zampini   }
2785b003df0Sstefano_zampini   for (i=0;i<lf->nc;i++) {
2795b003df0Sstefano_zampini     ierr = ISDestroy(&lf->cf[i]);CHKERRQ(ierr);
2805b003df0Sstefano_zampini   }
2815b003df0Sstefano_zampini   ierr = PetscFree2(lf->rf,lf->cf);CHKERRQ(ierr);
2825b003df0Sstefano_zampini   ierr = PetscFree(lf);CHKERRQ(ierr);
2835b003df0Sstefano_zampini   PetscFunctionReturn(0);
2845b003df0Sstefano_zampini }
285a72627d2SStefano Zampini 
286c9225affSStefano Zampini static PetscErrorCode MatConvert_SeqXAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
2876989cf23SStefano Zampini {
288c9225affSStefano Zampini   Mat            B,lB;
289c9225affSStefano Zampini   PetscErrorCode ierr;
290c9225affSStefano Zampini 
291c9225affSStefano Zampini   PetscFunctionBegin;
292c9225affSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
293c9225affSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g;
294c9225affSStefano Zampini     PetscInt               bs;
295c9225affSStefano Zampini     IS                     is;
296c9225affSStefano Zampini 
297c9225affSStefano Zampini     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
298c9225affSStefano Zampini     ierr = ISCreateStride(PetscObjectComm((PetscObject)A),A->rmap->n/bs,0,1,&is);CHKERRQ(ierr);
299c9225affSStefano Zampini     if (bs > 1) {
300c9225affSStefano Zampini       IS       is2;
301c9225affSStefano Zampini       PetscInt i,*aux;
302c9225affSStefano Zampini 
303c9225affSStefano Zampini       ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
304c9225affSStefano Zampini       ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
305c9225affSStefano Zampini       ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
306c9225affSStefano Zampini       ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
307c9225affSStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
308c9225affSStefano Zampini       is   = is2;
309c9225affSStefano Zampini     }
310c9225affSStefano Zampini     ierr = ISSetIdentity(is);CHKERRQ(ierr);
311c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
312c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
313c9225affSStefano Zampini     ierr = ISCreateStride(PetscObjectComm((PetscObject)A),A->cmap->n/bs,0,1,&is);CHKERRQ(ierr);
314c9225affSStefano Zampini     if (bs > 1) {
315c9225affSStefano Zampini       IS       is2;
316c9225affSStefano Zampini       PetscInt i,*aux;
317c9225affSStefano Zampini 
318c9225affSStefano Zampini       ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
319c9225affSStefano Zampini       ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
320c9225affSStefano Zampini       ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
321c9225affSStefano Zampini       ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
322c9225affSStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
323c9225affSStefano Zampini       is   = is2;
324c9225affSStefano Zampini     }
325c9225affSStefano Zampini     ierr = ISSetIdentity(is);CHKERRQ(ierr);
326c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
327c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
328c9225affSStefano Zampini     ierr = MatCreateIS(PetscObjectComm((PetscObject)A),bs,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N,rl2g,cl2g,&B);CHKERRQ(ierr);
329c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
330c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
331c9225affSStefano Zampini     ierr = MatDuplicate(A,MAT_COPY_VALUES,&lB);CHKERRQ(ierr);
332c9225affSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *newmat = B;
333c9225affSStefano Zampini   } else {
334c9225affSStefano Zampini     B    = *newmat;
335c9225affSStefano Zampini     ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
336c9225affSStefano Zampini     lB   = A;
337c9225affSStefano Zampini   }
338c9225affSStefano Zampini   ierr = MatISSetLocalMat(B,lB);CHKERRQ(ierr);
339c9225affSStefano Zampini   ierr = MatDestroy(&lB);CHKERRQ(ierr);
340c9225affSStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
341c9225affSStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
342c9225affSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
343c9225affSStefano Zampini     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
344c9225affSStefano Zampini   }
345c9225affSStefano Zampini   PetscFunctionReturn(0);
346c9225affSStefano Zampini }
347c9225affSStefano Zampini 
348c9225affSStefano Zampini static PetscErrorCode MatISScaleDisassembling_Private(Mat A)
349c9225affSStefano Zampini {
350c9225affSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(A->data);
351c9225affSStefano Zampini   PetscScalar    *aa;
352c9225affSStefano Zampini   const PetscInt *ii,*jj;
353c9225affSStefano Zampini   PetscInt       i,n,m;
354fabe8965SStefano Zampini   PetscInt       *ecount,**eneighs;
355c9225affSStefano Zampini   PetscBool      flg;
356c9225affSStefano Zampini   PetscErrorCode ierr;
357c9225affSStefano Zampini 
358c9225affSStefano Zampini   PetscFunctionBegin;
359c9225affSStefano Zampini   ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg);CHKERRQ(ierr);
360c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
361fabe8965SStefano Zampini   ierr = ISLocalToGlobalMappingGetNodeInfo(A->rmap->mapping,&n,&ecount,&eneighs);CHKERRQ(ierr);
362c9225affSStefano Zampini   if (m != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",m,n);
363c9225affSStefano Zampini   ierr = MatSeqAIJGetArray(matis->A,&aa);CHKERRQ(ierr);
364c9225affSStefano Zampini   for (i=0;i<n;i++) {
365fabe8965SStefano Zampini     if (ecount[i] > 1) {
366c9225affSStefano Zampini       PetscInt j;
367c9225affSStefano Zampini 
368c9225affSStefano Zampini       for (j=ii[i];j<ii[i+1];j++) {
369c9225affSStefano Zampini         PetscInt    i2 = jj[j],p,p2;
370fabe8965SStefano Zampini         PetscReal   scal = 0.0;
371c9225affSStefano Zampini 
372c9225affSStefano Zampini         for (p=0;p<ecount[i];p++) {
373c9225affSStefano Zampini           for (p2=0;p2<ecount[i2];p2++) {
374c9225affSStefano Zampini             if (eneighs[i][p] == eneighs[i2][p2]) { scal += 1.0; break; }
375c9225affSStefano Zampini           }
376c9225affSStefano Zampini         }
377fabe8965SStefano Zampini         if (scal) aa[j] /= scal;
378c9225affSStefano Zampini       }
379c9225affSStefano Zampini     }
380c9225affSStefano Zampini   }
381fabe8965SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreNodeInfo(A->rmap->mapping,&n,&ecount,&eneighs);CHKERRQ(ierr);
382c9225affSStefano Zampini   ierr = MatSeqAIJRestoreArray(matis->A,&aa);CHKERRQ(ierr);
383c9225affSStefano Zampini   ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg);CHKERRQ(ierr);
384c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
385c9225affSStefano Zampini   PetscFunctionReturn(0);
386c9225affSStefano Zampini }
387c9225affSStefano Zampini 
388fabe8965SStefano Zampini typedef enum {MAT_IS_DISASSEMBLE_L2G_NATURAL,MAT_IS_DISASSEMBLE_L2G_MAT, MAT_IS_DISASSEMBLE_L2G_ND} MatISDisassemblel2gType;
389fabe8965SStefano Zampini 
390c9225affSStefano Zampini static PetscErrorCode MatMPIXAIJComputeLocalToGlobalMapping_Private(Mat A, ISLocalToGlobalMapping *l2g)
391c9225affSStefano Zampini {
392fabe8965SStefano Zampini   Mat                     Ad,Ao;
393fabe8965SStefano Zampini   IS                      is,ndmap,ndsub;
394c9225affSStefano Zampini   MPI_Comm                comm;
395fabe8965SStefano Zampini   const PetscInt          *garray,*ndmapi;
396fabe8965SStefano Zampini   PetscInt                bs,i,cnt,nl,*ncount,*ndmapc;
397fabe8965SStefano Zampini   PetscBool               ismpiaij,ismpibaij;
398fabe8965SStefano Zampini   const char *const       MatISDisassemblel2gTypes[] = {"NATURAL","MAT","ND","MatISDisassemblel2gType","MAT_IS_DISASSEMBLE_L2G_",0};
399fabe8965SStefano Zampini   MatISDisassemblel2gType mode = MAT_IS_DISASSEMBLE_L2G_NATURAL;
400fabe8965SStefano Zampini   MatPartitioning         part;
401fabe8965SStefano Zampini   PetscSF                 sf;
402c9225affSStefano Zampini   PetscErrorCode          ierr;
403c9225affSStefano Zampini 
404c9225affSStefano Zampini   PetscFunctionBegin;
405fabe8965SStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"MatIS l2g disassembling options","Mat");CHKERRQ(ierr);
406fabe8965SStefano Zampini   ierr = PetscOptionsEnum("-mat_is_disassemble_l2g_type","Type of local-to-global mapping to be used for disassembling","MatISDisassemblel2gType",MatISDisassemblel2gTypes,(PetscEnum)mode,(PetscEnum*)&mode,NULL);CHKERRQ(ierr);
407fabe8965SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
408fabe8965SStefano Zampini   if (mode == MAT_IS_DISASSEMBLE_L2G_MAT) {
409c9225affSStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,l2g,NULL);CHKERRQ(ierr);
410c9225affSStefano Zampini     PetscFunctionReturn(0);
411c9225affSStefano Zampini   }
412c9225affSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
413c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij);CHKERRQ(ierr);
414c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
415c9225affSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
416fabe8965SStefano Zampini   switch (mode) {
417fabe8965SStefano Zampini   case MAT_IS_DISASSEMBLE_L2G_ND:
418fabe8965SStefano Zampini     ierr = MatPartitioningCreate(comm,&part);CHKERRQ(ierr);
419fabe8965SStefano Zampini     ierr = MatPartitioningSetAdjacency(part,A);CHKERRQ(ierr);
420fabe8965SStefano Zampini     ierr = PetscObjectSetOptionsPrefix((PetscObject)part,((PetscObject)A)->prefix);CHKERRQ(ierr);
421fabe8965SStefano Zampini     ierr = MatPartitioningSetFromOptions(part);CHKERRQ(ierr);
422fabe8965SStefano Zampini     ierr = MatPartitioningApplyND(part,&ndmap);CHKERRQ(ierr);
423fabe8965SStefano Zampini     ierr = MatPartitioningDestroy(&part);CHKERRQ(ierr);
424fabe8965SStefano Zampini     ierr = ISBuildTwoSided(ndmap,NULL,&ndsub);CHKERRQ(ierr);
425fabe8965SStefano Zampini     ierr = MatMPIAIJSetUseScalableIncreaseOverlap(A,PETSC_TRUE);CHKERRQ(ierr);
426fabe8965SStefano Zampini     ierr = MatIncreaseOverlap(A,1,&ndsub,1);CHKERRQ(ierr);
427fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(ndsub,l2g);CHKERRQ(ierr);
428fabe8965SStefano Zampini 
429fabe8965SStefano Zampini     /* it may happen that a separator node is not properly shared */
430fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingGetNodeInfo(*l2g,&nl,&ncount,NULL);CHKERRQ(ierr);
431fabe8965SStefano Zampini     ierr = PetscSFCreate(comm,&sf);CHKERRQ(ierr);
432fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(*l2g,&garray);CHKERRQ(ierr);
433fabe8965SStefano Zampini     ierr = PetscSFSetGraphLayout(sf,A->rmap,nl,NULL,PETSC_OWN_POINTER,garray);CHKERRQ(ierr);
434fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(*l2g,&garray);CHKERRQ(ierr);
435fabe8965SStefano Zampini     ierr = PetscCalloc1(A->rmap->n,&ndmapc);CHKERRQ(ierr);
436fabe8965SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,ncount,ndmapc,MPIU_REPLACE);CHKERRQ(ierr);
437fabe8965SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,ncount,ndmapc,MPIU_REPLACE);CHKERRQ(ierr);
438fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreNodeInfo(*l2g,NULL,&ncount,NULL);CHKERRQ(ierr);
439fabe8965SStefano Zampini     ierr = ISGetIndices(ndmap,&ndmapi);CHKERRQ(ierr);
440fabe8965SStefano Zampini     for (i = 0, cnt = 0; i < A->rmap->n; i++)
441fabe8965SStefano Zampini       if (ndmapi[i] < 0 && ndmapc[i] < 2)
442fabe8965SStefano Zampini         cnt++;
443fabe8965SStefano Zampini 
444fabe8965SStefano Zampini     ierr = MPIU_Allreduce(&cnt,&i,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
445fabe8965SStefano Zampini     if (i) { /* we detected isolated separator nodes */
446fabe8965SStefano Zampini       Mat                    A2,A3;
447fabe8965SStefano Zampini       IS                     *workis,is2;
448fabe8965SStefano Zampini       PetscScalar            *vals;
449fabe8965SStefano Zampini       PetscInt               gcnt = i,*dnz,*onz,j,*lndmapi;
450fabe8965SStefano Zampini       ISLocalToGlobalMapping ll2g;
451fabe8965SStefano Zampini       PetscBool              flg;
452fabe8965SStefano Zampini       const PetscInt         *ii,*jj;
453fabe8965SStefano Zampini 
454fabe8965SStefano Zampini       /* communicate global id of separators */
455fabe8965SStefano Zampini       ierr = MatPreallocateInitialize(comm,A->rmap->n,A->cmap->n,dnz,onz);CHKERRQ(ierr);
456fabe8965SStefano Zampini       for (i = 0, cnt = 0; i < A->rmap->n; i++)
457fabe8965SStefano Zampini         dnz[i] = ndmapi[i] < 0 ? i + A->rmap->rstart : -1;
458fabe8965SStefano Zampini 
459fabe8965SStefano Zampini       ierr = PetscMalloc1(nl,&lndmapi);CHKERRQ(ierr);
460fabe8965SStefano Zampini       ierr = PetscSFBcastBegin(sf,MPIU_INT,dnz,lndmapi);CHKERRQ(ierr);
461fabe8965SStefano Zampini 
462fabe8965SStefano Zampini       /* compute adjacency of isolated separators node */
463fabe8965SStefano Zampini       ierr = PetscMalloc1(gcnt,&workis);CHKERRQ(ierr);
464fabe8965SStefano Zampini       for (i = 0, cnt = 0; i < A->rmap->n; i++) {
465fabe8965SStefano Zampini         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
466fabe8965SStefano Zampini           ierr = ISCreateStride(comm,1,i+A->rmap->rstart,1,&workis[cnt++]);CHKERRQ(ierr);
467fabe8965SStefano Zampini         }
468fabe8965SStefano Zampini       }
469fabe8965SStefano Zampini       for (i = cnt; i < gcnt; i++) {
470fabe8965SStefano Zampini         ierr = ISCreateStride(comm,0,0,1,&workis[i]);CHKERRQ(ierr);
471fabe8965SStefano Zampini       }
472fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
473fabe8965SStefano Zampini         ierr = PetscObjectSetName((PetscObject)workis[i],"ISOLATED");CHKERRQ(ierr);
474fabe8965SStefano Zampini         ierr = ISViewFromOptions(workis[i],NULL,"-view_isolated_separators");CHKERRQ(ierr);
475fabe8965SStefano Zampini       }
476fabe8965SStefano Zampini 
477fabe8965SStefano Zampini       /* no communications since all the ISes correspond to locally owned rows */
478fabe8965SStefano Zampini       ierr = MatIncreaseOverlap(A,gcnt,workis,1);CHKERRQ(ierr);
479fabe8965SStefano Zampini 
480fabe8965SStefano Zampini       /* end communicate global id of separators */
481fabe8965SStefano Zampini       ierr = PetscSFBcastEnd(sf,MPIU_INT,dnz,lndmapi);CHKERRQ(ierr);
482fabe8965SStefano Zampini 
483fabe8965SStefano Zampini       /* communicate new layers : create a matrix and transpose it */
484fabe8965SStefano Zampini       ierr = PetscMemzero(dnz,A->rmap->n*sizeof(*dnz));CHKERRQ(ierr);
485fabe8965SStefano Zampini       ierr = PetscMemzero(onz,A->rmap->n*sizeof(*onz));CHKERRQ(ierr);
486fabe8965SStefano Zampini       for (i = 0, j = 0; i < A->rmap->n; i++) {
487fabe8965SStefano Zampini         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
488fabe8965SStefano Zampini           const PetscInt* idxs;
489fabe8965SStefano Zampini           PetscInt        s;
490fabe8965SStefano Zampini 
491fabe8965SStefano Zampini           ierr = ISGetLocalSize(workis[j],&s);CHKERRQ(ierr);
492fabe8965SStefano Zampini           ierr = ISGetIndices(workis[j],&idxs);CHKERRQ(ierr);
493fabe8965SStefano Zampini           ierr = MatPreallocateSet(i+A->rmap->rstart,s,idxs,dnz,onz);CHKERRQ(ierr);
494fabe8965SStefano Zampini           j++;
495fabe8965SStefano Zampini         }
496fabe8965SStefano Zampini       }
497fabe8965SStefano Zampini       if (j != cnt) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %D != %D",j,cnt);
498fabe8965SStefano Zampini 
499fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
500fabe8965SStefano Zampini         ierr = PetscObjectSetName((PetscObject)workis[i],"EXTENDED");CHKERRQ(ierr);
501fabe8965SStefano Zampini         ierr = ISViewFromOptions(workis[i],NULL,"-view_isolated_separators");CHKERRQ(ierr);
502fabe8965SStefano Zampini       }
503fabe8965SStefano Zampini 
504fabe8965SStefano Zampini       for (i = 0, j = 0; i < A->rmap->n; i++) j = PetscMax(j,dnz[i]+onz[i]);
505fabe8965SStefano Zampini       ierr = PetscMalloc1(j,&vals);CHKERRQ(ierr);
506fabe8965SStefano Zampini       for (i = 0; i < j; i++) vals[i] = 1.0;
507fabe8965SStefano Zampini 
508fabe8965SStefano Zampini       ierr = MatCreate(comm,&A2);CHKERRQ(ierr);
509fabe8965SStefano Zampini       ierr = MatSetType(A2,MATMPIAIJ);CHKERRQ(ierr);
510fabe8965SStefano Zampini       ierr = MatSetSizes(A2,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
511fabe8965SStefano Zampini       ierr = MatMPIAIJSetPreallocation(A2,0,dnz,0,onz);CHKERRQ(ierr);
512fabe8965SStefano Zampini       ierr = MatSetOption(A2,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
513fabe8965SStefano Zampini       for (i = 0, j = 0; i < A2->rmap->n; i++) {
514fabe8965SStefano Zampini         PetscInt        row = i+A2->rmap->rstart,s = dnz[i] + onz[i];
515fabe8965SStefano Zampini         const PetscInt* idxs;
516fabe8965SStefano Zampini 
517fabe8965SStefano Zampini         if (s) {
518fabe8965SStefano Zampini           ierr = ISGetIndices(workis[j],&idxs);CHKERRQ(ierr);
519fabe8965SStefano Zampini           ierr = MatSetValues(A2,1,&row,s,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
520fabe8965SStefano Zampini           ierr = ISRestoreIndices(workis[j],&idxs);CHKERRQ(ierr);
521fabe8965SStefano Zampini           j++;
522fabe8965SStefano Zampini         }
523fabe8965SStefano Zampini       }
524fabe8965SStefano Zampini       if (j != cnt) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %D != %D",j,cnt);
525fabe8965SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
526fabe8965SStefano Zampini       ierr = MatAssemblyBegin(A2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
527fabe8965SStefano Zampini       ierr = MatAssemblyEnd(A2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
528fabe8965SStefano Zampini       ierr = MatTranspose(A2,MAT_INPLACE_MATRIX,&A2);CHKERRQ(ierr);
529fabe8965SStefano Zampini 
530fabe8965SStefano Zampini       /* extract submatrix corresponding to the coupling "owned separators" x "isolated separators" */
531fabe8965SStefano Zampini       for (i = 0, j = 0; i < nl; i++)
532fabe8965SStefano Zampini         if (lndmapi[i] >= 0) lndmapi[j++] = lndmapi[i];
533fabe8965SStefano Zampini       ierr = ISCreateGeneral(comm,j,lndmapi,PETSC_USE_POINTER,&is);CHKERRQ(ierr);
534fabe8965SStefano Zampini       ierr = MatMPIAIJGetLocalMatCondensed(A2,MAT_INITIAL_MATRIX,&is,NULL,&A3);CHKERRQ(ierr);
535fabe8965SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
536fabe8965SStefano Zampini       ierr = MatDestroy(&A2);CHKERRQ(ierr);
537fabe8965SStefano Zampini 
538fabe8965SStefano Zampini       /* extend local to global map to include connected isolated separators */
539fabe8965SStefano Zampini       ierr = PetscObjectQuery((PetscObject)A3,"_petsc_GetLocalMatCondensed_iscol",(PetscObject*)&is);CHKERRQ(ierr);
540fabe8965SStefano Zampini       if (!is) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing column map");
541fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&ll2g);CHKERRQ(ierr);
542fabe8965SStefano Zampini       ierr = MatGetRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg);CHKERRQ(ierr);
543fabe8965SStefano Zampini       if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
544fabe8965SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,ii[i],jj,PETSC_COPY_VALUES,&is);CHKERRQ(ierr);
545fabe8965SStefano Zampini       ierr = MatRestoreRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg);CHKERRQ(ierr);
546fabe8965SStefano Zampini       if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
547fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(ll2g,is,&is2);CHKERRQ(ierr);
548fabe8965SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
549fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&ll2g);CHKERRQ(ierr);
550fabe8965SStefano Zampini 
551fabe8965SStefano Zampini       /* add new nodes to the local-to-global map */
552fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(l2g);CHKERRQ(ierr);
553fabe8965SStefano Zampini       ierr = ISExpand(ndsub,is2,&is);CHKERRQ(ierr);
554fabe8965SStefano Zampini       ierr = ISDestroy(&is2);CHKERRQ(ierr);
555fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,l2g);CHKERRQ(ierr);
556fabe8965SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
557fabe8965SStefano Zampini 
558fabe8965SStefano Zampini       ierr = MatDestroy(&A3);CHKERRQ(ierr);
559fabe8965SStefano Zampini       ierr = PetscFree(lndmapi);CHKERRQ(ierr);
560fabe8965SStefano Zampini       ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
561fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
562fabe8965SStefano Zampini         ierr = ISDestroy(&workis[i]);CHKERRQ(ierr);
563fabe8965SStefano Zampini       }
564fabe8965SStefano Zampini       ierr = PetscFree(workis);CHKERRQ(ierr);
565fabe8965SStefano Zampini     }
566fabe8965SStefano Zampini     ierr = ISRestoreIndices(ndmap,&ndmapi);CHKERRQ(ierr);
567fabe8965SStefano Zampini     ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
568fabe8965SStefano Zampini     ierr = PetscFree(ndmapc);CHKERRQ(ierr);
569fabe8965SStefano Zampini     ierr = ISDestroy(&ndmap);CHKERRQ(ierr);
570fabe8965SStefano Zampini     ierr = ISDestroy(&ndsub);CHKERRQ(ierr);
571fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(*l2g,bs);CHKERRQ(ierr);
572fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingViewFromOptions(*l2g,NULL,"-matis_nd_l2g_view");CHKERRQ(ierr);
573fabe8965SStefano Zampini     break;
574fabe8965SStefano Zampini   case MAT_IS_DISASSEMBLE_L2G_NATURAL:
575fabe8965SStefano Zampini     if (ismpiaij) {
576fabe8965SStefano Zampini       ierr = MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
577fabe8965SStefano Zampini     } else if (ismpibaij) {
578fabe8965SStefano Zampini       ierr = MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
579c9225affSStefano Zampini     } else SETERRQ1(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
580c9225affSStefano Zampini     if (!garray) SETERRQ(comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
581c9225affSStefano Zampini     if (A->rmap->n) {
582fabe8965SStefano Zampini       PetscInt dc,oc,stc,*aux;
583c9225affSStefano Zampini 
584c9225affSStefano Zampini       ierr = MatGetLocalSize(A,NULL,&dc);CHKERRQ(ierr);
585c9225affSStefano Zampini       ierr = MatGetLocalSize(Ao,NULL,&oc);CHKERRQ(ierr);
586c9225affSStefano Zampini       ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
587c9225affSStefano Zampini       ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
588c9225affSStefano Zampini       for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
589c9225affSStefano Zampini       for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i];
590c9225affSStefano Zampini       ierr = ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
591c9225affSStefano Zampini     } else {
592c9225affSStefano Zampini       ierr = ISCreateBlock(comm,1,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
593c9225affSStefano Zampini     }
594c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,l2g);CHKERRQ(ierr);
595c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
596fabe8965SStefano Zampini     break;
597fabe8965SStefano Zampini   default:
598fabe8965SStefano Zampini     SETERRQ1(comm,PETSC_ERR_ARG_WRONG,"Unsupported l2g disassembling type %D",mode);
599c9225affSStefano Zampini   }
600c9225affSStefano Zampini   PetscFunctionReturn(0);
601c9225affSStefano Zampini }
602c9225affSStefano Zampini 
603c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
604c9225affSStefano Zampini {
605c9225affSStefano Zampini   Mat                    lA,Ad,Ao,B = NULL;
6066989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
6076989cf23SStefano Zampini   IS                     is;
6086989cf23SStefano Zampini   MPI_Comm               comm;
6096989cf23SStefano Zampini   void                   *ptrs[2];
6106989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
611c9225affSStefano Zampini   const PetscInt         *garray;
6126989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
613c9225affSStefano Zampini   const PetscInt         *di,*dj,*oi,*oj;
614c9225affSStefano Zampini   const PetscInt         *odi,*odj,*ooi,*ooj;
6156989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
616c9225affSStefano Zampini   PetscInt               bs,lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
617c9225affSStefano Zampini   PetscBool              flg,ismpiaij,ismpibaij,was_inplace = PETSC_FALSE;
618c9225affSStefano Zampini   PetscMPIInt            size;
6196989cf23SStefano Zampini   PetscErrorCode         ierr;
6206989cf23SStefano Zampini 
621ab4d48faSStefano Zampini   PetscFunctionBegin;
6226989cf23SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
623c9225affSStefano Zampini   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
624c9225affSStefano Zampini   if (size == 1) {
625c9225affSStefano Zampini     ierr = MatConvert_SeqXAIJ_IS(A,type,reuse,newmat);CHKERRQ(ierr);
626c9225affSStefano Zampini     PetscFunctionReturn(0);
627c9225affSStefano Zampini   }
628c9225affSStefano Zampini   if (reuse != MAT_REUSE_MATRIX && A->cmap->N == A->rmap->N) {
629c9225affSStefano Zampini     ierr = MatMPIXAIJComputeLocalToGlobalMapping_Private(A,&rl2g);CHKERRQ(ierr);
630c9225affSStefano Zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
631c9225affSStefano Zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
632c9225affSStefano Zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
633c9225affSStefano Zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,rl2g);CHKERRQ(ierr);
634c9225affSStefano Zampini     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
635c9225affSStefano Zampini     ierr = MatSetBlockSize(B,bs);CHKERRQ(ierr);
636c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
637c9225affSStefano Zampini     if (reuse == MAT_INPLACE_MATRIX) was_inplace = PETSC_TRUE;
638c9225affSStefano Zampini     reuse = MAT_REUSE_MATRIX;
639c9225affSStefano Zampini   }
640c9225affSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
641c9225affSStefano Zampini     Mat            *newlA, lA;
642c9225affSStefano Zampini     IS             rows, cols;
643c9225affSStefano Zampini     const PetscInt *ridx, *cidx;
644c9225affSStefano Zampini     PetscInt       rbs, cbs, nr, nc;
645c9225affSStefano Zampini 
646c9225affSStefano Zampini     if (!B) B = *newmat;
647c9225affSStefano Zampini     ierr = MatGetLocalToGlobalMapping(B,&rl2g,&cl2g);CHKERRQ(ierr);
648c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(rl2g,&ridx);CHKERRQ(ierr);
649c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(cl2g,&cidx);CHKERRQ(ierr);
650c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(rl2g,&nr);CHKERRQ(ierr);
651c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(cl2g,&nc);CHKERRQ(ierr);
652c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(rl2g,&rbs);CHKERRQ(ierr);
653c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(cl2g,&cbs);CHKERRQ(ierr);
654c9225affSStefano Zampini     ierr = ISCreateBlock(comm,rbs,nr/rbs,ridx,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
655c9225affSStefano Zampini     if (rl2g != cl2g) {
656c9225affSStefano Zampini       ierr = ISCreateBlock(comm,cbs,nc/cbs,cidx,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
657c9225affSStefano Zampini     } else {
658c9225affSStefano Zampini       ierr = PetscObjectReference((PetscObject)rows);CHKERRQ(ierr);
659c9225affSStefano Zampini       cols = rows;
660c9225affSStefano Zampini     }
661c9225affSStefano Zampini     ierr = MatISGetLocalMat(B,&lA);CHKERRQ(ierr);
662c9225affSStefano Zampini     ierr = MatCreateSubMatrices(A,1,&rows,&cols,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
663c9225affSStefano Zampini     ierr = MatConvert(newlA[0],MATSEQAIJ,MAT_INPLACE_MATRIX,&newlA[0]);CHKERRQ(ierr);
664c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&ridx);CHKERRQ(ierr);
665c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&cidx);CHKERRQ(ierr);
666c9225affSStefano Zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
667c9225affSStefano Zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
668c9225affSStefano Zampini     if (!lA->preallocated) { /* first time */
669c9225affSStefano Zampini       ierr = MatDuplicate(newlA[0],MAT_COPY_VALUES,&lA);CHKERRQ(ierr);
670c9225affSStefano Zampini       ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
671c9225affSStefano Zampini       ierr = PetscObjectDereference((PetscObject)lA);CHKERRQ(ierr);
672c9225affSStefano Zampini     }
673c9225affSStefano Zampini     ierr = MatCopy(newlA[0],lA,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
674c9225affSStefano Zampini     ierr = MatDestroySubMatrices(1,&newlA);CHKERRQ(ierr);
675c9225affSStefano Zampini     ierr = MatISScaleDisassembling_Private(B);CHKERRQ(ierr);
676c9225affSStefano Zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
677c9225affSStefano Zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
678c9225affSStefano Zampini     if (was_inplace) { ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); }
679c9225affSStefano Zampini     else *newmat = B;
680c9225affSStefano Zampini     PetscFunctionReturn(0);
681c9225affSStefano Zampini   }
682c9225affSStefano Zampini   /* rectangular case, just compress out the column space */
683c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij);CHKERRQ(ierr);
684c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
685c9225affSStefano Zampini   if (ismpiaij) {
686c9225affSStefano Zampini     bs   = 1;
687c9225affSStefano Zampini     ierr = MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
688c9225affSStefano Zampini   } else if (ismpibaij) {
689c9225affSStefano Zampini     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
690c9225affSStefano Zampini     ierr = MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
691c9225affSStefano Zampini     ierr = MatConvert(Ad,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ad);CHKERRQ(ierr);
692c9225affSStefano Zampini     ierr = MatConvert(Ao,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ao);CHKERRQ(ierr);
693c9225affSStefano Zampini   } else SETERRQ1(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
694c9225affSStefano Zampini   ierr = MatSeqAIJGetArray(Ad,&dd);CHKERRQ(ierr);
695c9225affSStefano Zampini   ierr = MatSeqAIJGetArray(Ao,&od);CHKERRQ(ierr);
696c9225affSStefano Zampini   if (!garray) SETERRQ(comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
6976989cf23SStefano Zampini 
6986989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
6996989cf23SStefano Zampini   ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr);
7006989cf23SStefano Zampini   ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
7016989cf23SStefano Zampini   ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr);
702c9225affSStefano Zampini   ierr = MatGetLocalSize(Ao,NULL,&oc);CHKERRQ(ierr);
703c9225affSStefano Zampini   ierr = MatGetRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&di,&dj,&flg);CHKERRQ(ierr);
704c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
705c9225affSStefano Zampini   ierr = MatGetRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&oi,&oj,&flg);CHKERRQ(ierr);
706c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
707c9225affSStefano Zampini   nnz = di[dr] + oi[dr];
708c9225affSStefano Zampini   /* store original pointers to be restored later */
709c9225affSStefano Zampini   odi = di; odj = dj; ooi = oi; ooj = oj;
7106989cf23SStefano Zampini 
7116989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
712c9225affSStefano Zampini   ierr = ISCreateStride(comm,dr/bs,str/bs,1,&is);CHKERRQ(ierr);
713c9225affSStefano Zampini   if (bs > 1) {
714c9225affSStefano Zampini     IS is2;
715c9225affSStefano Zampini 
716c9225affSStefano Zampini     ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
717c9225affSStefano Zampini     ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
718c9225affSStefano Zampini     ierr = ISCreateBlock(comm,bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
719c9225affSStefano Zampini     ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
720c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
721c9225affSStefano Zampini     is   = is2;
722c9225affSStefano Zampini   }
7236989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
7246989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
725e363d98aSStefano Zampini   if (dr) {
726c9225affSStefano Zampini     ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
727c9225affSStefano Zampini     for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
728c9225affSStefano Zampini     for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i];
729c9225affSStefano Zampini     ierr = ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
730e363d98aSStefano Zampini     lc   = dc+oc;
731e363d98aSStefano Zampini   } else {
732c9225affSStefano Zampini     ierr = ISCreateBlock(comm,bs,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
733e363d98aSStefano Zampini     lc   = 0;
734e363d98aSStefano Zampini   }
7356989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
7366989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
7376989cf23SStefano Zampini 
7386989cf23SStefano Zampini   /* create MATIS object */
739c9225affSStefano Zampini   ierr = MatCreate(comm,&B);CHKERRQ(ierr);
740c9225affSStefano Zampini   ierr = MatSetSizes(B,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
741c9225affSStefano Zampini   ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
742c9225affSStefano Zampini   ierr = MatSetBlockSize(B,bs);CHKERRQ(ierr);
743c9225affSStefano Zampini   ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
7446989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
7456989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
7466989cf23SStefano Zampini 
7476989cf23SStefano Zampini   /* merge local matrices */
7486989cf23SStefano Zampini   ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr);
7496989cf23SStefano Zampini   ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
7506989cf23SStefano Zampini   ii   = aux;
7516989cf23SStefano Zampini   jj   = aux+dr+1;
7526989cf23SStefano Zampini   aa   = data;
7536989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
7546989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
7556989cf23SStefano Zampini   {
7566989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
7576989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
7586989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
7596989cf23SStefano Zampini   }
7606989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
761c9225affSStefano Zampini 
762c9225affSStefano Zampini   ierr = MatRestoreRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&odi,&odj,&flg);CHKERRQ(ierr);
763c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
764c9225affSStefano Zampini   ierr = MatRestoreRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&ooi,&ooj,&flg);CHKERRQ(ierr);
765c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
766c9225affSStefano Zampini   ierr = MatSeqAIJRestoreArray(Ad,&dd);CHKERRQ(ierr);
767c9225affSStefano Zampini   ierr = MatSeqAIJRestoreArray(Ao,&od);CHKERRQ(ierr);
768c9225affSStefano Zampini 
7696989cf23SStefano Zampini   ii   = aux;
7706989cf23SStefano Zampini   jj   = aux+dr+1;
7716989cf23SStefano Zampini   aa   = data;
772e363d98aSStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr);
7736989cf23SStefano Zampini 
7746989cf23SStefano Zampini   /* create containers to destroy the data */
7756989cf23SStefano Zampini   ptrs[0] = aux;
7766989cf23SStefano Zampini   ptrs[1] = data;
7776989cf23SStefano Zampini   for (i=0; i<2; i++) {
7786989cf23SStefano Zampini     PetscContainer c;
7796989cf23SStefano Zampini 
7806989cf23SStefano Zampini     ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
7816989cf23SStefano Zampini     ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
782b81c21eeSStefano Zampini     ierr = PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault);CHKERRQ(ierr);
7836989cf23SStefano Zampini     ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr);
7846989cf23SStefano Zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
7856989cf23SStefano Zampini   }
786c9225affSStefano Zampini   if (ismpibaij) { /* destroy converted local matrices */
787c9225affSStefano Zampini     ierr = MatDestroy(&Ad);CHKERRQ(ierr);
788c9225affSStefano Zampini     ierr = MatDestroy(&Ao);CHKERRQ(ierr);
789c9225affSStefano Zampini   }
7906989cf23SStefano Zampini 
7916989cf23SStefano Zampini   /* finalize matrix */
792c9225affSStefano Zampini   ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
7936989cf23SStefano Zampini   ierr = MatDestroy(&lA);CHKERRQ(ierr);
794c9225affSStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
795c9225affSStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
796c9225affSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
797c9225affSStefano Zampini     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
798c9225affSStefano Zampini   } else *newmat = B;
7996989cf23SStefano Zampini   PetscFunctionReturn(0);
8006989cf23SStefano Zampini }
8016989cf23SStefano Zampini 
802cf0a3239SStefano Zampini /*@
8033d996552SStefano Zampini    MatISSetUpSF - Setup star forest objects used by MatIS.
804cf0a3239SStefano Zampini 
8058546b261SStefano Zampini    Collective on Mat
806cf0a3239SStefano Zampini 
807cf0a3239SStefano Zampini    Input Parameters:
808cf0a3239SStefano Zampini +  A - the matrix
809cf0a3239SStefano Zampini 
810cf0a3239SStefano Zampini    Level: advanced
811cf0a3239SStefano Zampini 
81295452b02SPatrick Sanan    Notes:
81395452b02SPatrick Sanan     This function does not need to be called by the user.
814cf0a3239SStefano Zampini 
815cf0a3239SStefano Zampini .keywords: matrix
816cf0a3239SStefano Zampini 
817cf0a3239SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatISGetLocalMat()
818cf0a3239SStefano Zampini @*/
819cf0a3239SStefano Zampini PetscErrorCode  MatISSetUpSF(Mat A)
820cf0a3239SStefano Zampini {
8217fa8f2d3SStefano Zampini   PetscErrorCode ierr;
8227fa8f2d3SStefano Zampini 
8237fa8f2d3SStefano Zampini   PetscFunctionBegin;
824cf0a3239SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
825cf0a3239SStefano Zampini   PetscValidType(A,1);
826cf0a3239SStefano Zampini   ierr = PetscTryMethod(A,"MatISSetUpSF_C",(Mat),(A));CHKERRQ(ierr);
8277fa8f2d3SStefano Zampini   PetscFunctionReturn(0);
8287fa8f2d3SStefano Zampini }
8297fa8f2d3SStefano Zampini 
8305e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
8315e3038f0Sstefano_zampini {
8325e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
8335e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
8345e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
8355e3038f0Sstefano_zampini   MPI_Comm               comm;
8365b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
8375b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
8389e7b2b25Sstefano_zampini   PetscBool              convert,lreuse,*istrans;
8395e3038f0Sstefano_zampini   PetscErrorCode         ierr;
8405e3038f0Sstefano_zampini 
841ab4d48faSStefano Zampini   PetscFunctionBegin;
8425e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
8435e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
8445e3038f0Sstefano_zampini   rnest  = NULL;
8455e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
8465e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
8475e3038f0Sstefano_zampini 
8485e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
8495e3038f0Sstefano_zampini     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
8505e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
8515e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
8525e3038f0Sstefano_zampini     if (isnest) {
8535e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
8545e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
8555e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
8565e3038f0Sstefano_zampini     }
8575e3038f0Sstefano_zampini   }
8585e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
8595b003df0Sstefano_zampini   ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr);
8609e7b2b25Sstefano_zampini   ierr = PetscCalloc6(nr,&isrow,nc,&iscol,
8615e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
8629e7b2b25Sstefano_zampini                       nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr);
8635e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
8645e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
8655e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
8665e3038f0Sstefano_zampini       PetscBool ismatis;
8679e7b2b25Sstefano_zampini       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
8685e3038f0Sstefano_zampini 
8695e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
8705e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
8715e3038f0Sstefano_zampini 
8725e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
8739e7b2b25Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr);
8749e7b2b25Sstefano_zampini       if (istrans[ij]) {
8759e7b2b25Sstefano_zampini         Mat T,lT;
8769e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
8779e7b2b25Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr);
8789e7b2b25Sstefano_zampini         if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) (transposed) is not of type MATIS",i,j);
8799e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr);
8809e7b2b25Sstefano_zampini         ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr);
8819e7b2b25Sstefano_zampini       } else {
8825e3038f0Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
8835e3038f0Sstefano_zampini         if (!ismatis) SETERRQ2(comm,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) is not of type MATIS",i,j);
8849e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
8859e7b2b25Sstefano_zampini       }
8865e3038f0Sstefano_zampini 
8875e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
8885e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
8899e7b2b25Sstefano_zampini       ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr);
8905e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
8915e3038f0Sstefano_zampini       if (lr[i] && l1 != lr[i]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid local size %D != %D",i,j,lr[i],l1);
8925e3038f0Sstefano_zampini       if (lc[j] && l2 != lc[j]) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid local size %D != %D",i,j,lc[j],l2);
8935e3038f0Sstefano_zampini       lr[i] = l1;
8945e3038f0Sstefano_zampini       lc[j] = l2;
8955e3038f0Sstefano_zampini 
8965e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
8975e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
8985e3038f0Sstefano_zampini     }
8995e3038f0Sstefano_zampini   }
9005e3038f0Sstefano_zampini 
9015e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
9025e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
9035e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
9045e3038f0Sstefano_zampini     rl2g = NULL;
9055e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
9065e3038f0Sstefano_zampini       PetscInt n1,n2;
9075e3038f0Sstefano_zampini 
9085e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
9099e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
9109e7b2b25Sstefano_zampini         Mat T;
9119e7b2b25Sstefano_zampini 
9129e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
9139e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr);
9149e7b2b25Sstefano_zampini       } else {
9155e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
9169e7b2b25Sstefano_zampini       }
9175e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
9185e3038f0Sstefano_zampini       if (!n1) continue;
9195e3038f0Sstefano_zampini       if (!rl2g) {
9205e3038f0Sstefano_zampini         rl2g = cl2g;
9215e3038f0Sstefano_zampini       } else {
9225e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
9235e3038f0Sstefano_zampini         PetscBool      same;
9245e3038f0Sstefano_zampini 
9255e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
9265e3038f0Sstefano_zampini         if (n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid row l2gmap size %D != %D",i,j,n1,n2);
9275e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
9285e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
9295e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
9305e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
9315e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
9325e3038f0Sstefano_zampini         if (!same) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid row l2gmap",i,j);
9335e3038f0Sstefano_zampini       }
9345e3038f0Sstefano_zampini     }
9355e3038f0Sstefano_zampini   }
9365e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
9375e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
9385e3038f0Sstefano_zampini     rl2g = NULL;
9395e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
9405e3038f0Sstefano_zampini       PetscInt n1,n2;
9415e3038f0Sstefano_zampini 
9425e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
9439e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
9449e7b2b25Sstefano_zampini         Mat T;
9459e7b2b25Sstefano_zampini 
9469e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr);
9479e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr);
9489e7b2b25Sstefano_zampini       } else {
9495e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
9509e7b2b25Sstefano_zampini       }
9515e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
9525e3038f0Sstefano_zampini       if (!n1) continue;
9535e3038f0Sstefano_zampini       if (!rl2g) {
9545e3038f0Sstefano_zampini         rl2g = cl2g;
9555e3038f0Sstefano_zampini       } else {
9565e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
9575e3038f0Sstefano_zampini         PetscBool      same;
9585e3038f0Sstefano_zampini 
9595e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
9605e3038f0Sstefano_zampini         if (n1 != n2) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid column l2gmap size %D != %D",j,i,n1,n2);
9615e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
9625e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
9635e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
9645e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
9655e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
9665e3038f0Sstefano_zampini         if (!same) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot convert from MATNEST to MATIS! Matrix block (%D,%D) has invalid column l2gmap",j,i);
9675e3038f0Sstefano_zampini       }
9685e3038f0Sstefano_zampini     }
9695e3038f0Sstefano_zampini   }
9705e3038f0Sstefano_zampini #endif
9715e3038f0Sstefano_zampini 
9725e3038f0Sstefano_zampini   B = NULL;
9735e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
9745b003df0Sstefano_zampini     PetscInt stl;
9755b003df0Sstefano_zampini 
9765e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
9775e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
9785e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
9795b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
9805e3038f0Sstefano_zampini       Mat            usedmat;
9815e3038f0Sstefano_zampini       Mat_IS         *matis;
9825e3038f0Sstefano_zampini       const PetscInt *idxs;
9835e3038f0Sstefano_zampini 
9845e3038f0Sstefano_zampini       /* local IS for local NEST */
9855b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
9865e3038f0Sstefano_zampini 
9875e3038f0Sstefano_zampini       /* l2gmap */
9885e3038f0Sstefano_zampini       j = 0;
9895e3038f0Sstefano_zampini       usedmat = nest[i][j];
9909e7b2b25Sstefano_zampini       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
9919e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat");
9929e7b2b25Sstefano_zampini 
9939e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
9949e7b2b25Sstefano_zampini         Mat T;
9959e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
9969e7b2b25Sstefano_zampini         usedmat = T;
9979e7b2b25Sstefano_zampini       }
99882d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
9995e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
10005e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
10019e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
10029e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10039e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10049e7b2b25Sstefano_zampini       } else {
10055e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10065e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10079e7b2b25Sstefano_zampini       }
10085e3038f0Sstefano_zampini       ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
10095e3038f0Sstefano_zampini       stl += lr[i];
10105e3038f0Sstefano_zampini     }
10115e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
10125e3038f0Sstefano_zampini 
10135e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
10145e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
10155e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
10165b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
10175e3038f0Sstefano_zampini       Mat            usedmat;
10185e3038f0Sstefano_zampini       Mat_IS         *matis;
10195e3038f0Sstefano_zampini       const PetscInt *idxs;
10205e3038f0Sstefano_zampini 
10215e3038f0Sstefano_zampini       /* local IS for local NEST */
10225b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
10235e3038f0Sstefano_zampini 
10245e3038f0Sstefano_zampini       /* l2gmap */
10255e3038f0Sstefano_zampini       j = 0;
10265e3038f0Sstefano_zampini       usedmat = nest[j][i];
10279e7b2b25Sstefano_zampini       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
10289e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat");
10299e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
10309e7b2b25Sstefano_zampini         Mat T;
10319e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
10329e7b2b25Sstefano_zampini         usedmat = T;
10339e7b2b25Sstefano_zampini       }
103482d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
10355e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
10365e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
10379e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
10389e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10399e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10409e7b2b25Sstefano_zampini       } else {
10415e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10425e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10439e7b2b25Sstefano_zampini       }
10445e3038f0Sstefano_zampini       ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
10455e3038f0Sstefano_zampini       stl += lc[i];
10465e3038f0Sstefano_zampini     }
10475e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
10485e3038f0Sstefano_zampini 
10495e3038f0Sstefano_zampini     /* Create MATIS */
10505e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
10515e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
10525e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
10535e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
10545e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
10558546b261SStefano Zampini     ierr = MatISSetLocalMatType(B,MATNEST);CHKERRQ(ierr);
10568546b261SStefano Zampini     { /* hack : avoid setup of scatters */
10578546b261SStefano Zampini       Mat_IS *matis = (Mat_IS*)(B->data);
10588546b261SStefano Zampini       matis->islocalref = PETSC_TRUE;
10598546b261SStefano Zampini     }
10605e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
10615e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
10625e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
10635e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
10648546b261SStefano Zampini     ierr = MatNestSetVecType(lA,VECNEST);CHKERRQ(ierr);
10659e7b2b25Sstefano_zampini     for (i=0;i<nr*nc;i++) {
10669e7b2b25Sstefano_zampini       if (istrans[i]) {
10679e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
10689e7b2b25Sstefano_zampini       }
10699e7b2b25Sstefano_zampini     }
10705e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
10715e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
10728546b261SStefano Zampini     { /* hack : setup of scatters done here */
10738546b261SStefano Zampini       Mat_IS *matis = (Mat_IS*)(B->data);
10748546b261SStefano Zampini 
10758546b261SStefano Zampini       matis->islocalref = PETSC_FALSE;
10768546b261SStefano Zampini       ierr = MatISSetUpScatters_Private(B);CHKERRQ(ierr);
10778546b261SStefano Zampini     }
10785e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10795e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10805e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
10815e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
10825e3038f0Sstefano_zampini     } else {
10835e3038f0Sstefano_zampini       *newmat = B;
10845e3038f0Sstefano_zampini     }
10855e3038f0Sstefano_zampini   } else {
10865e3038f0Sstefano_zampini     if (lreuse) {
10875e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
10885e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
10895e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
10905e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
10915e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
10929e7b2b25Sstefano_zampini             if (istrans[i*nc+j]) {
10939e7b2b25Sstefano_zampini               ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr);
10949e7b2b25Sstefano_zampini             }
10955e3038f0Sstefano_zampini           }
10965e3038f0Sstefano_zampini         }
10975e3038f0Sstefano_zampini       }
10985e3038f0Sstefano_zampini     } else {
10995b003df0Sstefano_zampini       PetscInt stl;
11005b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
11015b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
11025b003df0Sstefano_zampini         stl  += lr[i];
11035e3038f0Sstefano_zampini       }
11045b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
11055b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
11065b003df0Sstefano_zampini         stl  += lc[i];
11075e3038f0Sstefano_zampini       }
11085e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
1109ab4d48faSStefano Zampini       for (i=0;i<nr*nc;i++) {
11109e7b2b25Sstefano_zampini         if (istrans[i]) {
11119e7b2b25Sstefano_zampini           ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
11129e7b2b25Sstefano_zampini         }
1113ab4d48faSStefano Zampini       }
11145e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
11155e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
11165e3038f0Sstefano_zampini     }
11175e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11185e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11195e3038f0Sstefano_zampini   }
11205e3038f0Sstefano_zampini 
11215b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
11225b003df0Sstefano_zampini   convert = PETSC_FALSE;
11235b003df0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
11245b003df0Sstefano_zampini   if (convert) {
11255b003df0Sstefano_zampini     Mat              M;
11265b003df0Sstefano_zampini     MatISLocalFields lf;
11275b003df0Sstefano_zampini     PetscContainer   c;
11285b003df0Sstefano_zampini 
11295b003df0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
11305b003df0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
11315b003df0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
11325b003df0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
11335b003df0Sstefano_zampini 
11345b003df0Sstefano_zampini     /* attach local fields to the matrix */
11355b003df0Sstefano_zampini     ierr = PetscNew(&lf);CHKERRQ(ierr);
11365b003df0Sstefano_zampini     ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr);
11375b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
11385b003df0Sstefano_zampini       PetscInt n,st;
11395b003df0Sstefano_zampini 
11405b003df0Sstefano_zampini       ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr);
11415b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr);
11425b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr);
11435b003df0Sstefano_zampini     }
11445b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
11455b003df0Sstefano_zampini       PetscInt n,st;
11465b003df0Sstefano_zampini 
11475b003df0Sstefano_zampini       ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr);
11485b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr);
11495b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr);
11505b003df0Sstefano_zampini     }
11515b003df0Sstefano_zampini     lf->nr = nr;
11525b003df0Sstefano_zampini     lf->nc = nc;
11535b003df0Sstefano_zampini     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr);
11545b003df0Sstefano_zampini     ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr);
11555b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr);
11565b003df0Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr);
11575b003df0Sstefano_zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
11585b003df0Sstefano_zampini   }
11595b003df0Sstefano_zampini 
11605e3038f0Sstefano_zampini   /* Free workspace */
11615e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
11625e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
11635e3038f0Sstefano_zampini   }
11645e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
11655e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
11665e3038f0Sstefano_zampini   }
11679e7b2b25Sstefano_zampini   ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr);
11685b003df0Sstefano_zampini   ierr = PetscFree2(lr,lc);CHKERRQ(ierr);
11695e3038f0Sstefano_zampini   PetscFunctionReturn(0);
11705e3038f0Sstefano_zampini }
11715e3038f0Sstefano_zampini 
1172ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
1173ad219c80Sstefano_zampini {
1174ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS*)A->data;
1175ad219c80Sstefano_zampini   Vec               ll,rr;
1176ad219c80Sstefano_zampini   const PetscScalar *Y,*X;
1177ad219c80Sstefano_zampini   PetscScalar       *x,*y;
1178ad219c80Sstefano_zampini   PetscErrorCode    ierr;
1179ad219c80Sstefano_zampini 
1180ad219c80Sstefano_zampini   PetscFunctionBegin;
1181ad219c80Sstefano_zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
1182ad219c80Sstefano_zampini   if (l) {
1183ad219c80Sstefano_zampini     ll   = matis->y;
1184ad219c80Sstefano_zampini     ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr);
1185ad219c80Sstefano_zampini     ierr = VecGetArray(ll,&y);CHKERRQ(ierr);
1186ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
1187ad219c80Sstefano_zampini   } else {
1188ad219c80Sstefano_zampini     ll = NULL;
1189ad219c80Sstefano_zampini   }
1190ad219c80Sstefano_zampini   if (r) {
1191ad219c80Sstefano_zampini     rr   = matis->x;
1192ad219c80Sstefano_zampini     ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr);
1193ad219c80Sstefano_zampini     ierr = VecGetArray(rr,&x);CHKERRQ(ierr);
1194ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
1195ad219c80Sstefano_zampini   } else {
1196ad219c80Sstefano_zampini     rr = NULL;
1197ad219c80Sstefano_zampini   }
1198ad219c80Sstefano_zampini   if (ll) {
1199ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
1200ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr);
1201ad219c80Sstefano_zampini     ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr);
1202ad219c80Sstefano_zampini   }
1203ad219c80Sstefano_zampini   if (rr) {
1204ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
1205ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr);
1206ad219c80Sstefano_zampini     ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr);
1207ad219c80Sstefano_zampini   }
1208ad219c80Sstefano_zampini   ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr);
1209ad219c80Sstefano_zampini   PetscFunctionReturn(0);
1210ad219c80Sstefano_zampini }
1211ad219c80Sstefano_zampini 
12127fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
12137fa8f2d3SStefano Zampini {
12147fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
12157fa8f2d3SStefano Zampini   MatInfo        info;
12167fa8f2d3SStefano Zampini   PetscReal      isend[6],irecv[6];
12177fa8f2d3SStefano Zampini   PetscInt       bs;
12187fa8f2d3SStefano Zampini   PetscErrorCode ierr;
12197fa8f2d3SStefano Zampini 
12207fa8f2d3SStefano Zampini   PetscFunctionBegin;
12217fa8f2d3SStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
12227fa8f2d3SStefano Zampini   if (matis->A->ops->getinfo) {
12237fa8f2d3SStefano Zampini     ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
12247fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
12257fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
12267fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
12277fa8f2d3SStefano Zampini     isend[3] = info.memory;
12287fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
12297fa8f2d3SStefano Zampini   } else {
12307fa8f2d3SStefano Zampini     isend[0] = 0.;
12317fa8f2d3SStefano Zampini     isend[1] = 0.;
12327fa8f2d3SStefano Zampini     isend[2] = 0.;
12337fa8f2d3SStefano Zampini     isend[3] = 0.;
12347fa8f2d3SStefano Zampini     isend[4] = 0.;
12357fa8f2d3SStefano Zampini   }
12367fa8f2d3SStefano Zampini   isend[5] = matis->A->num_ass;
12377fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
12387fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
12397fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
12407fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
12417fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
12427fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
12437fa8f2d3SStefano Zampini     ginfo->assemblies   = isend[5];
12447fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
12457fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
12467fa8f2d3SStefano Zampini 
12477fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
12487fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
12497fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
12507fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
12517fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
12527fa8f2d3SStefano Zampini     ginfo->assemblies   = irecv[5];
12537fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
12547fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
12557fa8f2d3SStefano Zampini 
12567fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
12577fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
12587fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
12597fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
12607fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
12617fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
1262d7f69cd0SStefano Zampini   }
1263d7f69cd0SStefano Zampini   ginfo->block_size        = bs;
1264d7f69cd0SStefano Zampini   ginfo->fill_ratio_given  = 0;
1265d7f69cd0SStefano Zampini   ginfo->fill_ratio_needed = 0;
1266d7f69cd0SStefano Zampini   ginfo->factor_mallocs    = 0;
12675e3038f0Sstefano_zampini   PetscFunctionReturn(0);
12685e3038f0Sstefano_zampini }
12695e3038f0Sstefano_zampini 
1270d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
1271d7f69cd0SStefano Zampini {
1272d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
1273d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
1274d7f69cd0SStefano Zampini 
1275d7f69cd0SStefano Zampini   PetscFunctionBegin;
1276cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
1277cf37664fSBarry Smith     ISLocalToGlobalMapping rl2g,cl2g;
1278d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
1279d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
1280d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
1281d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
1282d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
1283d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
1284cf37664fSBarry Smith   } else {
1285cf37664fSBarry Smith     C = *B;
1286d7f69cd0SStefano Zampini   }
1287d7f69cd0SStefano Zampini 
1288d7f69cd0SStefano Zampini   /* perform local transposition */
1289d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1290d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
1291d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
1292d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
1293d7f69cd0SStefano Zampini 
1294cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
1295d7f69cd0SStefano Zampini     *B = C;
1296d7f69cd0SStefano Zampini   } else {
1297d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
1298d7f69cd0SStefano Zampini   }
12997aa7aec5Sstefano_zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
13007aa7aec5Sstefano_zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1301d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
1302d7f69cd0SStefano Zampini }
1303d7f69cd0SStefano Zampini 
13043fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
13053fd1c9e7SStefano Zampini {
13063fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
13073fd1c9e7SStefano Zampini   PetscErrorCode ierr;
13083fd1c9e7SStefano Zampini 
13093fd1c9e7SStefano Zampini   PetscFunctionBegin;
13104b89b9cdSStefano Zampini   if (D) { /* MatShift_IS pass D = NULL */
13113fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13123fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
13133fd1c9e7SStefano Zampini   }
13143fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
13153fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
13163fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
13173fd1c9e7SStefano Zampini }
13183fd1c9e7SStefano Zampini 
13193fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
13203fd1c9e7SStefano Zampini {
13214b89b9cdSStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
13223fd1c9e7SStefano Zampini   PetscErrorCode ierr;
13233fd1c9e7SStefano Zampini 
13243fd1c9e7SStefano Zampini   PetscFunctionBegin;
13254b89b9cdSStefano Zampini   ierr = VecSet(is->y,a);CHKERRQ(ierr);
13263fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
13273fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
13283fd1c9e7SStefano Zampini }
13293fd1c9e7SStefano Zampini 
1330f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1331f26d0771SStefano Zampini {
1332f26d0771SStefano Zampini   PetscErrorCode ierr;
1333f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1334f26d0771SStefano Zampini 
1335f26d0771SStefano Zampini   PetscFunctionBegin;
1336f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1337f26d0771SStefano Zampini   if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n);
1338f26d0771SStefano Zampini #endif
1339f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
1340f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
1341b4f971dfSStefano Zampini   ierr = MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
1342f26d0771SStefano Zampini   PetscFunctionReturn(0);
1343f26d0771SStefano Zampini }
1344f26d0771SStefano Zampini 
1345f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1346f26d0771SStefano Zampini {
1347f26d0771SStefano Zampini   PetscErrorCode ierr;
1348f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1349f26d0771SStefano Zampini 
1350f26d0771SStefano Zampini   PetscFunctionBegin;
1351f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1352f26d0771SStefano Zampini   if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column block indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n);
1353f26d0771SStefano Zampini #endif
1354f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
1355f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
1356b4f971dfSStefano Zampini   ierr = MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
1357f26d0771SStefano Zampini   PetscFunctionReturn(0);
1358f26d0771SStefano Zampini }
1359f26d0771SStefano Zampini 
1360f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
1361a8116848SStefano Zampini {
1362a8116848SStefano Zampini   PetscInt      *owners = map->range;
1363a8116848SStefano Zampini   PetscInt       n      = map->n;
1364a8116848SStefano Zampini   PetscSF        sf;
1365a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
1366a8116848SStefano Zampini   PetscSFNode   *ridxs;
1367a8116848SStefano Zampini   PetscMPIInt    rank;
1368a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
1369a8116848SStefano Zampini   PetscErrorCode ierr;
1370a8116848SStefano Zampini 
1371a8116848SStefano Zampini   PetscFunctionBegin;
1372fd3a879cSJed Brown   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
1373a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
1374a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
1375a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
1376a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
1377a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
1378a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
1379a8116848SStefano Zampini     const PetscInt idx = idxs[r];
1380a8116848SStefano Zampini     if (idx < 0 || map->N <= idx) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Index %D out of range [0,%D)",idx,map->N);
1381a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
1382a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
1383a8116848SStefano Zampini     }
1384a8116848SStefano Zampini     ridxs[r].rank = p;
1385a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
1386a8116848SStefano Zampini   }
1387a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
1388a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
1389a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
1390a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
1391f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
1392a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
1393f0ae7da4SStefano Zampini 
1394f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
1395a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
1396a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
1397a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
1398a8116848SStefano Zampini     start -= cum;
1399a8116848SStefano Zampini     cum = 0;
1400a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
1401a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
1402a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
1403a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
1404a8116848SStefano Zampini   }
1405a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
1406a8116848SStefano Zampini   /* Compress and put in indices */
1407a8116848SStefano Zampini   for (r = 0; r < n; ++r)
1408a8116848SStefano Zampini     if (lidxs[r] >= 0) {
1409a8116848SStefano Zampini       if (work) work[len] = work[r];
1410a8116848SStefano Zampini       lidxs[len++] = r;
1411a8116848SStefano Zampini     }
1412a8116848SStefano Zampini   if (on) *on = len;
1413a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
1414a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
1415a8116848SStefano Zampini   PetscFunctionReturn(0);
1416a8116848SStefano Zampini }
1417a8116848SStefano Zampini 
14187dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
1419a8116848SStefano Zampini {
1420a8116848SStefano Zampini   Mat               locmat,newlocmat;
1421a8116848SStefano Zampini   Mat_IS            *newmatis;
1422a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
1423a8116848SStefano Zampini   Vec               rtest,ltest;
1424a8116848SStefano Zampini   const PetscScalar *array;
1425a8116848SStefano Zampini #endif
1426a8116848SStefano Zampini   const PetscInt    *idxs;
1427a8116848SStefano Zampini   PetscInt          i,m,n;
1428a8116848SStefano Zampini   PetscErrorCode    ierr;
1429a8116848SStefano Zampini 
1430a8116848SStefano Zampini   PetscFunctionBegin;
1431a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
1432a8116848SStefano Zampini     PetscBool ismatis;
1433a8116848SStefano Zampini 
1434a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
1435a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
1436a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
1437a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
1438a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
1439a8116848SStefano Zampini   }
1440a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
1441a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
1442a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
1443a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
1444a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
1445a8116848SStefano Zampini   for (i=0;i<n;i++) {
1446a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
1447a8116848SStefano Zampini   }
1448a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
1449a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
1450a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
1451a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
1452a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
1453fd479f66SMatthew G. Knepley   for (i=0;i<n;i++) if (array[i] != 0. && array[i] != 1.) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %D counted %D times! Irow may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i]));
1454a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
1455a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
1456a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
1457a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
1458a8116848SStefano Zampini   for (i=0;i<n;i++) {
1459a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
1460a8116848SStefano Zampini   }
1461a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
1462a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
1463a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
1464a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
1465a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
1466fd479f66SMatthew G. Knepley   for (i=0;i<n;i++) if (array[i] != 0. && array[i] != 1.) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Index %D counted %D times! Icol may not have duplicate entries",i+m,(PetscInt)PetscRealPart(array[i]));
1467a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
1468a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
1469a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
1470a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
1471a8116848SStefano Zampini #endif
1472a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1473a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
1474a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
1475a8116848SStefano Zampini     IS                     is;
1476a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
1477306cf5c7SStefano Zampini     PetscInt               ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs;
147894342113SStefano Zampini     PetscBool              cong;
1479a8116848SStefano Zampini     MPI_Comm               comm;
1480a8116848SStefano Zampini 
1481a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
1482306cf5c7SStefano Zampini     ierr = MatGetBlockSizes(mat,&arbs,&acbs);CHKERRQ(ierr);
1483306cf5c7SStefano Zampini     ierr = ISGetBlockSize(irow,&irbs);CHKERRQ(ierr);
1484306cf5c7SStefano Zampini     ierr = ISGetBlockSize(icol,&icbs);CHKERRQ(ierr);
1485306cf5c7SStefano Zampini     rbs  = arbs == irbs ? irbs : 1;
1486306cf5c7SStefano Zampini     cbs  = acbs == icbs ? icbs : 1;
1487a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
1488a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
1489a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
1490a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
1491a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1492306cf5c7SStefano Zampini     ierr = MatSetBlockSizes(*newmat,rbs,cbs);CHKERRQ(ierr);
1493a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
1494a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
1495f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
1496a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
14973d996552SStefano Zampini     ierr = MatISSetUpSF(mat);CHKERRQ(ierr);
14983d996552SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
1499a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
1500a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
1501a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
1502a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
1503a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
15043d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
1505a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
1506a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
15073d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
1508a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
1509a8116848SStefano Zampini         lidxs[newloc] = i;
1510a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
1511a8116848SStefano Zampini       }
1512a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1513a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
1514306cf5c7SStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(rl2g,rbs);CHKERRQ(ierr);
1515a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
1516a8116848SStefano Zampini     /* local is to extract local submatrix */
1517a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
1518a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
151994342113SStefano Zampini     ierr = MatHasCongruentLayouts(mat,&cong);CHKERRQ(ierr);
152094342113SStefano Zampini     if (cong && irow == icol && matis->csf == matis->sf) {
1521a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
1522a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
1523a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
1524a8116848SStefano Zampini     } else {
1525a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
1526a8116848SStefano Zampini 
1527a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
1528a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
1529f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
1530a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
15313d996552SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
1532a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
1533a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
1534a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
1535a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
1536a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
15373d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
1538a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
1539a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
15403d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
1541a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
1542a8116848SStefano Zampini           lidxs[newloc] = i;
1543a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
1544a8116848SStefano Zampini         }
1545a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1546a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
1547306cf5c7SStefano Zampini       ierr = ISLocalToGlobalMappingSetBlockSize(cl2g,cbs);CHKERRQ(ierr);
1548a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
1549a8116848SStefano Zampini       /* local is to extract local submatrix */
1550a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
1551a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
1552a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1553a8116848SStefano Zampini     }
1554a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1555a8116848SStefano Zampini   } else {
1556a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
1557a8116848SStefano Zampini   }
1558a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
1559a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
15607dae84e0SHong Zhang   ierr = MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
1561a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1562a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
1563a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
1564a8116848SStefano Zampini   }
1565a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1566a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1567a8116848SStefano Zampini   PetscFunctionReturn(0);
1568a8116848SStefano Zampini }
1569a8116848SStefano Zampini 
1570a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
15712b404112SStefano Zampini {
15722b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
15732b404112SStefano Zampini   PetscBool      ismatis;
15742b404112SStefano Zampini   PetscErrorCode ierr;
15752b404112SStefano Zampini 
15762b404112SStefano Zampini   PetscFunctionBegin;
15772b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
15782b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
15792b404112SStefano Zampini   b = (Mat_IS*)B->data;
15802b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
1581cdc753b6SBarry Smith   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
15822b404112SStefano Zampini   PetscFunctionReturn(0);
15832b404112SStefano Zampini }
15842b404112SStefano Zampini 
1585a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
15866bd84002SStefano Zampini {
1587527b2640SStefano Zampini   Vec               v;
1588527b2640SStefano Zampini   const PetscScalar *array;
1589527b2640SStefano Zampini   PetscInt          i,n;
15906bd84002SStefano Zampini   PetscErrorCode    ierr;
15916bd84002SStefano Zampini 
15926bd84002SStefano Zampini   PetscFunctionBegin;
1593527b2640SStefano Zampini   *missing = PETSC_FALSE;
1594527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
1595527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
1596527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1597527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
1598527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
1599527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
1600527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1601527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
1602527b2640SStefano Zampini   if (d) {
1603527b2640SStefano Zampini     *d = -1;
1604527b2640SStefano Zampini     if (*missing) {
1605527b2640SStefano Zampini       PetscInt rstart;
1606527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
1607527b2640SStefano Zampini       *d = i+rstart;
1608527b2640SStefano Zampini     }
1609527b2640SStefano Zampini   }
16106bd84002SStefano Zampini   PetscFunctionReturn(0);
16116bd84002SStefano Zampini }
16126bd84002SStefano Zampini 
1613cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
161428f4e0baSStefano Zampini {
161528f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
161628f4e0baSStefano Zampini   const PetscInt *gidxs;
16174f2d7cafSStefano Zampini   PetscInt       nleaves;
161828f4e0baSStefano Zampini   PetscErrorCode ierr;
161928f4e0baSStefano Zampini 
162028f4e0baSStefano Zampini   PetscFunctionBegin;
16214f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
162275d48cdbSStefano Zampini   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
162375d48cdbSStefano Zampini   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
162428f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
16253bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
16264f2d7cafSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
16274f2d7cafSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
16283bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
16294f2d7cafSStefano Zampini   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
1630a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
16313d996552SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
1632a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
1633a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
16343d996552SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
1635a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
16363d996552SStefano Zampini     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
1637a8116848SStefano Zampini   } else {
1638a8116848SStefano Zampini     matis->csf = matis->sf;
1639a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
1640a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
1641a8116848SStefano Zampini   }
164228f4e0baSStefano Zampini   PetscFunctionReturn(0);
164328f4e0baSStefano Zampini }
16442e1947a5SStefano Zampini 
1645eb82efa4SStefano Zampini /*@
164675d48cdbSStefano Zampini    MatISStoreL2L - Store local-to-local operators during the Galerkin process of MatPtAP.
164775d48cdbSStefano Zampini 
164875d48cdbSStefano Zampini    Collective on MPI_Comm
164975d48cdbSStefano Zampini 
165075d48cdbSStefano Zampini    Input Parameters:
165175d48cdbSStefano Zampini +  A - the matrix
165275d48cdbSStefano Zampini -  store - the boolean flag
165375d48cdbSStefano Zampini 
165475d48cdbSStefano Zampini    Level: advanced
165575d48cdbSStefano Zampini 
165675d48cdbSStefano Zampini    Notes:
165775d48cdbSStefano Zampini 
165875d48cdbSStefano Zampini .keywords: matrix
165975d48cdbSStefano Zampini 
166075d48cdbSStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatPtAP()
166175d48cdbSStefano Zampini @*/
166275d48cdbSStefano Zampini PetscErrorCode  MatISStoreL2L(Mat A, PetscBool store)
166375d48cdbSStefano Zampini {
166475d48cdbSStefano Zampini   PetscErrorCode ierr;
166575d48cdbSStefano Zampini 
166675d48cdbSStefano Zampini   PetscFunctionBegin;
166775d48cdbSStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
166875d48cdbSStefano Zampini   PetscValidType(A,1);
166975d48cdbSStefano Zampini   PetscValidLogicalCollectiveBool(A,store,2);
167075d48cdbSStefano Zampini   ierr = PetscTryMethod(A,"MatISStoreL2L_C",(Mat,PetscBool),(A,store));CHKERRQ(ierr);
167175d48cdbSStefano Zampini   PetscFunctionReturn(0);
167275d48cdbSStefano Zampini }
167375d48cdbSStefano Zampini 
167475d48cdbSStefano Zampini static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store)
167575d48cdbSStefano Zampini {
167675d48cdbSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(A->data);
167775d48cdbSStefano Zampini   PetscErrorCode ierr;
167875d48cdbSStefano Zampini 
167975d48cdbSStefano Zampini   PetscFunctionBegin;
168075d48cdbSStefano Zampini   matis->storel2l = store;
168175d48cdbSStefano Zampini   if (!store) {
168275d48cdbSStefano Zampini     ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",NULL);CHKERRQ(ierr);
168375d48cdbSStefano Zampini   }
168475d48cdbSStefano Zampini   PetscFunctionReturn(0);
168575d48cdbSStefano Zampini }
168675d48cdbSStefano Zampini 
168775d48cdbSStefano Zampini /*@
1688f03112d0SStefano Zampini    MatISFixLocalEmpty - Compress out zero local rows from the local matrices
1689f03112d0SStefano Zampini 
1690f03112d0SStefano Zampini    Collective on MPI_Comm
1691f03112d0SStefano Zampini 
1692f03112d0SStefano Zampini    Input Parameters:
1693f03112d0SStefano Zampini +  A - the matrix
1694f03112d0SStefano Zampini -  fix - the boolean flag
1695f03112d0SStefano Zampini 
1696f03112d0SStefano Zampini    Level: advanced
1697f03112d0SStefano Zampini 
1698f03112d0SStefano Zampini    Notes: When fix is true, new local matrices and l2g maps are generated during the final assembly process.
1699f03112d0SStefano Zampini 
1700f03112d0SStefano Zampini .keywords: matrix
1701f03112d0SStefano Zampini 
1702f03112d0SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatAssemblyEnd(), MAT_FINAL_ASSEMBLY
1703f03112d0SStefano Zampini @*/
1704f03112d0SStefano Zampini PetscErrorCode  MatISFixLocalEmpty(Mat A, PetscBool fix)
1705f03112d0SStefano Zampini {
1706f03112d0SStefano Zampini   PetscErrorCode ierr;
1707f03112d0SStefano Zampini 
1708f03112d0SStefano Zampini   PetscFunctionBegin;
1709f03112d0SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1710f03112d0SStefano Zampini   PetscValidType(A,1);
1711f03112d0SStefano Zampini   PetscValidLogicalCollectiveBool(A,fix,2);
1712f03112d0SStefano Zampini   ierr = PetscTryMethod(A,"MatISFixLocalEmpty_C",(Mat,PetscBool),(A,fix));CHKERRQ(ierr);
1713f03112d0SStefano Zampini   PetscFunctionReturn(0);
1714f03112d0SStefano Zampini }
1715f03112d0SStefano Zampini 
1716f03112d0SStefano Zampini static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix)
1717f03112d0SStefano Zampini {
1718f03112d0SStefano Zampini   Mat_IS *matis = (Mat_IS*)(A->data);
1719f03112d0SStefano Zampini 
1720f03112d0SStefano Zampini   PetscFunctionBegin;
1721f03112d0SStefano Zampini   matis->locempty = fix;
1722f03112d0SStefano Zampini   PetscFunctionReturn(0);
1723f03112d0SStefano Zampini }
1724f03112d0SStefano Zampini 
1725f03112d0SStefano Zampini /*@
1726a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
1727a88811baSStefano Zampini 
1728a88811baSStefano Zampini    Collective on MPI_Comm
1729a88811baSStefano Zampini 
1730a88811baSStefano Zampini    Input Parameters:
1731a88811baSStefano Zampini +  B - the matrix
1732a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1733a88811baSStefano Zampini            (same value is used for all local rows)
1734a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
1735a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
1736a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
1737a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
1738a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
1739a88811baSStefano Zampini            the diagonal entry even if it is zero.
1740a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1741a88811baSStefano Zampini            submatrix (same value is used for all local rows).
1742a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
1743a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
1744a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
1745a88811baSStefano Zampini            structure. The size of this array is equal to the number
1746a88811baSStefano Zampini            of local rows, i.e 'm'.
1747a88811baSStefano Zampini 
1748a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
1749a88811baSStefano Zampini 
1750a88811baSStefano Zampini    Level: intermediate
1751a88811baSStefano Zampini 
175295452b02SPatrick Sanan    Notes:
175395452b02SPatrick Sanan     This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
1754a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
1755a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1756a88811baSStefano Zampini 
1757a88811baSStefano Zampini .keywords: matrix
1758a88811baSStefano Zampini 
17593c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
1760a88811baSStefano Zampini @*/
17612e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
17622e1947a5SStefano Zampini {
17632e1947a5SStefano Zampini   PetscErrorCode ierr;
17642e1947a5SStefano Zampini 
17652e1947a5SStefano Zampini   PetscFunctionBegin;
17662e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
17672e1947a5SStefano Zampini   PetscValidType(B,1);
17682e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
17692e1947a5SStefano Zampini   PetscFunctionReturn(0);
17702e1947a5SStefano Zampini }
17712e1947a5SStefano Zampini 
1772844bd0d7SStefano Zampini /* this is used by DMDA */
1773844bd0d7SStefano Zampini PETSC_EXTERN PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
17742e1947a5SStefano Zampini {
17752e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
177628f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
17772e1947a5SStefano Zampini   PetscErrorCode ierr;
17782e1947a5SStefano Zampini 
17792e1947a5SStefano Zampini   PetscFunctionBegin;
17806c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
1781cf0a3239SStefano Zampini   ierr = MatISSetUpSF(B);CHKERRQ(ierr);
17824f2d7cafSStefano Zampini 
17834f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
17844f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
17854f2d7cafSStefano Zampini 
17864f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
17874f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
17884f2d7cafSStefano Zampini 
178928f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
179028f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
179128f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
179228f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
17934f2d7cafSStefano Zampini 
17944f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
179528f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
17960f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE)
17970f2f62c7SStefano Zampini   ierr = MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL);CHKERRQ(ierr);
17980f2f62c7SStefano Zampini #endif
17994f2d7cafSStefano Zampini 
18004f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
180128f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
18024f2d7cafSStefano Zampini 
180300a59248SStefano Zampini   nlocalcols /= bs;
180400a59248SStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols - i);
180528f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
18060f2f62c7SStefano Zampini 
18070f2f62c7SStefano Zampini   /* for other matrix types */
18080f2f62c7SStefano Zampini   ierr = MatSetUp(matis->A);CHKERRQ(ierr);
18092e1947a5SStefano Zampini   PetscFunctionReturn(0);
18102e1947a5SStefano Zampini }
1811b4319ba4SBarry Smith 
18123927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
18133927de2eSStefano Zampini {
18143927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
18153927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1816ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
18173927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
18183927de2eSStefano Zampini   PetscInt        lrows,lcols;
18193927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
1820f03112d0SStefano Zampini   PetscMPIInt     size;
18213927de2eSStefano Zampini   PetscBool       isdense,issbaij;
18223927de2eSStefano Zampini   PetscErrorCode  ierr;
18233927de2eSStefano Zampini 
18243927de2eSStefano Zampini   PetscFunctionBegin;
1825f03112d0SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr);
18263927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
18273927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
18283927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
18293927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
18303927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1831ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1832ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
18337230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1834ecf5a873SStefano Zampini   } else {
1835ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
1836ecf5a873SStefano Zampini   }
1837ecf5a873SStefano Zampini 
18383927de2eSStefano Zampini   if (issbaij) {
18393927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
18403927de2eSStefano Zampini   }
18413927de2eSStefano Zampini   /*
1842ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
18433927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
18443927de2eSStefano Zampini   */
1845cf0a3239SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
18463927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
18473927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
18483927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
18493927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
18503927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
1851f03112d0SStefano Zampini   for (i=0;i<size;i++) {
18523927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
18533927de2eSStefano Zampini       row_ownership[j] = i;
18543927de2eSStefano Zampini     }
18553927de2eSStefano Zampini   }
18567230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
18573927de2eSStefano Zampini 
18583927de2eSStefano Zampini   /*
18593927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
18603927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
18613927de2eSStefano Zampini   */
18623927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
18633927de2eSStefano Zampini   /* preallocation as a MATAIJ */
18643927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
18653927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
186612dfadf8SStefano Zampini       PetscInt owner = row_ownership[global_indices_r[i]];
186712dfadf8SStefano Zampini       for (j=0;j<local_cols;j++) {
1868ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
18693927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
18703927de2eSStefano Zampini           my_dnz[i] += 1;
18713927de2eSStefano Zampini         } else { /* offdiag block */
18723927de2eSStefano Zampini           my_onz[i] += 1;
18733927de2eSStefano Zampini         }
18743927de2eSStefano Zampini       }
18753927de2eSStefano Zampini     }
1876bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1877bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1878bb1015c3SStefano Zampini     PetscBool      done;
1879bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1880938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1881bb1015c3SStefano Zampini     jptr = jj;
1882bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1883bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1884bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1885bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1886bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1887bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1888bb1015c3SStefano Zampini           my_dnz[i] += 1;
1889bb1015c3SStefano Zampini         } else { /* offdiag block */
1890bb1015c3SStefano Zampini           my_onz[i] += 1;
1891bb1015c3SStefano Zampini         }
1892bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1893bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1894bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1895bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1896bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1897bb1015c3SStefano Zampini           } else {
1898bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1899bb1015c3SStefano Zampini           }
1900bb1015c3SStefano Zampini         }
1901bb1015c3SStefano Zampini       }
1902bb1015c3SStefano Zampini     }
1903bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1904938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1905bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
19063927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
19073927de2eSStefano Zampini       const PetscInt *cols;
1908ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
19093927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
19103927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
19113927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1912ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
19133927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
19143927de2eSStefano Zampini           my_dnz[i] += 1;
19153927de2eSStefano Zampini         } else { /* offdiag block */
19163927de2eSStefano Zampini           my_onz[i] += 1;
19173927de2eSStefano Zampini         }
19183927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1919d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
19203927de2eSStefano Zampini           owner = row_ownership[index_col];
19213927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1922d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
19233927de2eSStefano Zampini           } else {
1924d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
19253927de2eSStefano Zampini           }
19263927de2eSStefano Zampini         }
19273927de2eSStefano Zampini       }
19283927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
19293927de2eSStefano Zampini     }
19303927de2eSStefano Zampini   }
1931ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
19327230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1933ecf5a873SStefano Zampini   }
19344f619741Sstefano_zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
19353927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1936ecf5a873SStefano Zampini 
1937ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
19383927de2eSStefano Zampini   if (maxreduce) {
19393927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
19403927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1941bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
19423927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
19433927de2eSStefano Zampini   } else {
19443927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
19453927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1946bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
19473927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
19483927de2eSStefano Zampini   }
19493927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
19503927de2eSStefano Zampini 
19513927de2eSStefano Zampini   /* Resize preallocation if overestimated */
19523927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
19533927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
19543927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
19553927de2eSStefano Zampini   }
19561670daf9Sstefano_zampini 
19571670daf9Sstefano_zampini   /* Set preallocation */
1958268753edSStefano Zampini   ierr = MatSeqAIJSetPreallocation(B,0,dnz);CHKERRQ(ierr);
19593927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
196053b44cf5SStefano Zampini   for (i=0;i<lrows;i+=bs) {
196153b44cf5SStefano Zampini     PetscInt b, d = dnz[i],o = onz[i];
196253b44cf5SStefano Zampini 
196353b44cf5SStefano Zampini     for (b=1;b<bs;b++) {
196453b44cf5SStefano Zampini       d = PetscMax(d,dnz[i+b]);
196553b44cf5SStefano Zampini       o = PetscMax(o,onz[i+b]);
196653b44cf5SStefano Zampini     }
196753b44cf5SStefano Zampini     dnz[i/bs] = PetscMin(d/bs + d%bs,lcols/bs);
196853b44cf5SStefano Zampini     onz[i/bs] = PetscMin(o/bs + o%bs,(cols-lcols)/bs);
19693927de2eSStefano Zampini   }
1970268753edSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(B,bs,0,dnz);CHKERRQ(ierr);
19713927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
19723927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
19733927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
19743927de2eSStefano Zampini   if (issbaij) {
19753927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
19763927de2eSStefano Zampini   }
19779be90c3fSStefano Zampini   ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
19783927de2eSStefano Zampini   PetscFunctionReturn(0);
19793927de2eSStefano Zampini }
19803927de2eSStefano Zampini 
1981487b449aSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M)
1982b7ce53b6SStefano Zampini {
1983b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1984487b449aSStefano Zampini   Mat            local_mat,MT;
198553b44cf5SStefano Zampini   PetscInt       rbs,cbs,rows,cols,lrows,lcols;
1986b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
1987b9ed4604SStefano Zampini   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1988b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1989b9ed4604SStefano Zampini   PetscBool      lb[4],bb[4];
1990b9ed4604SStefano Zampini #endif
1991f03112d0SStefano Zampini   PetscMPIInt    size;
1992b7ce53b6SStefano Zampini   PetscScalar    *array;
1993b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1994b7ce53b6SStefano Zampini 
1995b7ce53b6SStefano Zampini   PetscFunctionBegin;
1996f03112d0SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
1997f03112d0SStefano Zampini   if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N) {
19981670daf9Sstefano_zampini     Mat      B;
199953b44cf5SStefano Zampini     IS       irows = NULL,icols = NULL;
2000487b449aSStefano Zampini     PetscInt rbs,cbs;
20011670daf9Sstefano_zampini 
2002487b449aSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
2003487b449aSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
200453b44cf5SStefano Zampini     if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */
200553b44cf5SStefano Zampini       IS             rows,cols;
200653b44cf5SStefano Zampini       const PetscInt *ridxs,*cidxs;
200753b44cf5SStefano Zampini       PetscInt       i,nw,*work;
200853b44cf5SStefano Zampini 
200953b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
201053b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&nw);CHKERRQ(ierr);
201153b44cf5SStefano Zampini       nw   = nw/rbs;
201253b44cf5SStefano Zampini       ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr);
201353b44cf5SStefano Zampini       for (i=0;i<nw;i++) work[ridxs[i]] += 1;
201453b44cf5SStefano Zampini       for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
201553b44cf5SStefano Zampini       if (i == nw) {
201653b44cf5SStefano Zampini         ierr = ISCreateBlock(PETSC_COMM_SELF,rbs,nw,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
2017acdf38a7Sstefano_zampini         ierr = ISSetPermutation(rows);CHKERRQ(ierr);
201853b44cf5SStefano Zampini         ierr = ISInvertPermutation(rows,PETSC_DECIDE,&irows);CHKERRQ(ierr);
2019acdf38a7Sstefano_zampini         ierr = ISDestroy(&rows);CHKERRQ(ierr);
202053b44cf5SStefano Zampini       }
202153b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
202253b44cf5SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
202353b44cf5SStefano Zampini       if (irows && mat->rmap->mapping != mat->cmap->mapping) {
202453b44cf5SStefano Zampini         ierr = ISLocalToGlobalMappingGetBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
202553b44cf5SStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(mat->cmap->mapping,&nw);CHKERRQ(ierr);
202653b44cf5SStefano Zampini         nw   = nw/cbs;
202753b44cf5SStefano Zampini         ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr);
202853b44cf5SStefano Zampini         for (i=0;i<nw;i++) work[cidxs[i]] += 1;
202953b44cf5SStefano Zampini         for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
203053b44cf5SStefano Zampini         if (i == nw) {
203153b44cf5SStefano Zampini           ierr = ISCreateBlock(PETSC_COMM_SELF,cbs,nw,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
203253b44cf5SStefano Zampini           ierr = ISSetPermutation(cols);CHKERRQ(ierr);
203353b44cf5SStefano Zampini           ierr = ISInvertPermutation(cols,PETSC_DECIDE,&icols);CHKERRQ(ierr);
203453b44cf5SStefano Zampini           ierr = ISDestroy(&cols);CHKERRQ(ierr);
203553b44cf5SStefano Zampini         }
203653b44cf5SStefano Zampini         ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
203753b44cf5SStefano Zampini         ierr = PetscFree(work);CHKERRQ(ierr);
203853b44cf5SStefano Zampini       } else if (irows) {
203953b44cf5SStefano Zampini         ierr  = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr);
204053b44cf5SStefano Zampini         icols = irows;
204153b44cf5SStefano Zampini       }
204253b44cf5SStefano Zampini     } else {
204353b44cf5SStefano Zampini       ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject*)&irows);CHKERRQ(ierr);
204453b44cf5SStefano Zampini       ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject*)&icols);CHKERRQ(ierr);
204553b44cf5SStefano Zampini       if (irows) { ierr = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr); }
204653b44cf5SStefano Zampini       if (icols) { ierr = PetscObjectReference((PetscObject)icols);CHKERRQ(ierr); }
204753b44cf5SStefano Zampini     }
204853b44cf5SStefano Zampini     if (!irows || !icols) {
204953b44cf5SStefano Zampini       ierr = ISDestroy(&icols);CHKERRQ(ierr);
205053b44cf5SStefano Zampini       ierr = ISDestroy(&irows);CHKERRQ(ierr);
205153b44cf5SStefano Zampini       goto general_assembly;
205253b44cf5SStefano Zampini     }
2053487b449aSStefano Zampini     ierr = MatConvert(matis->A,(rbs == cbs && rbs > 1) ? MATSEQBAIJ : MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
2054487b449aSStefano Zampini     if (reuse != MAT_INPLACE_MATRIX) {
20557dae84e0SHong Zhang       ierr = MatCreateSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr);
205653b44cf5SStefano Zampini       ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject)irows);CHKERRQ(ierr);
205753b44cf5SStefano Zampini       ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject)icols);CHKERRQ(ierr);
2058487b449aSStefano Zampini     } else {
2059487b449aSStefano Zampini       Mat C;
2060487b449aSStefano Zampini 
2061487b449aSStefano Zampini       ierr = MatCreateSubMatrix(B,irows,icols,MAT_INITIAL_MATRIX,&C);CHKERRQ(ierr);
2062487b449aSStefano Zampini       ierr = MatHeaderReplace(mat,&C);CHKERRQ(ierr);
2063487b449aSStefano Zampini     }
2064acdf38a7Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
2065acdf38a7Sstefano_zampini     ierr = ISDestroy(&icols);CHKERRQ(ierr);
2066acdf38a7Sstefano_zampini     ierr = ISDestroy(&irows);CHKERRQ(ierr);
20677c03b4e8SStefano Zampini     PetscFunctionReturn(0);
20687c03b4e8SStefano Zampini   }
206953b44cf5SStefano Zampini general_assembly:
2070b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
207153b44cf5SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
207253b44cf5SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
20733cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
2074b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
2075b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
20764099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
2077b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
2078b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
2079b9ed4604SStefano Zampini   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
2080b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
2081b9ed4604SStefano Zampini   lb[0] = isseqdense;
2082b9ed4604SStefano Zampini   lb[1] = isseqaij;
2083b9ed4604SStefano Zampini   lb[2] = isseqbaij;
2084b9ed4604SStefano Zampini   lb[3] = isseqsbaij;
2085b9ed4604SStefano Zampini   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
2086b9ed4604SStefano Zampini   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
2087b9ed4604SStefano Zampini #endif
2088b7ce53b6SStefano Zampini 
2089487b449aSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
2090487b449aSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),&MT);CHKERRQ(ierr);
2091487b449aSStefano Zampini     ierr = MatSetSizes(MT,lrows,lcols,rows,cols);CHKERRQ(ierr);
2092487b449aSStefano Zampini     ierr = MatSetType(MT,mtype);CHKERRQ(ierr);
209353b44cf5SStefano Zampini     ierr = MatSetBlockSizes(MT,rbs,cbs);CHKERRQ(ierr);
2094487b449aSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,MT,PETSC_FALSE);CHKERRQ(ierr);
2095b7ce53b6SStefano Zampini   } else {
209653b44cf5SStefano Zampini     PetscInt mrbs,mcbs,mrows,mcols,mlrows,mlcols;
2097487b449aSStefano Zampini 
2098b7ce53b6SStefano Zampini     /* some checks */
2099487b449aSStefano Zampini     MT   = *M;
210053b44cf5SStefano Zampini     ierr = MatGetBlockSizes(MT,&mrbs,&mcbs);CHKERRQ(ierr);
2101487b449aSStefano Zampini     ierr = MatGetSize(MT,&mrows,&mcols);CHKERRQ(ierr);
2102487b449aSStefano Zampini     ierr = MatGetLocalSize(MT,&mlrows,&mlcols);CHKERRQ(ierr);
21036c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
21046c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
21056c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
21066c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
210753b44cf5SStefano Zampini     if (mrbs != rbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong row block size (%d != %d)",rbs,mrbs);
210853b44cf5SStefano Zampini     if (mcbs != cbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong col block size (%d != %d)",cbs,mcbs);
2109487b449aSStefano Zampini     ierr = MatZeroEntries(MT);CHKERRQ(ierr);
2110b7ce53b6SStefano Zampini   }
2111d9a9e74cSStefano Zampini 
21128546b261SStefano Zampini   if (isseqsbaij || isseqbaij) {
21138546b261SStefano Zampini     ierr = MatConvert(matis->A,MATSEQAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
21148546b261SStefano Zampini     isseqaij = PETSC_TRUE;
2115d9a9e74cSStefano Zampini   } else {
2116d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
2117d9a9e74cSStefano Zampini     local_mat = matis->A;
2118d9a9e74cSStefano Zampini   }
2119686e3a49SStefano Zampini 
2120b7ce53b6SStefano Zampini   /* Set values */
2121487b449aSStefano Zampini   ierr = MatSetLocalToGlobalMapping(MT,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
2122b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
212365066ba5SStefano Zampini     PetscInt i,*dummy;
2124ecf5a873SStefano Zampini 
212565066ba5SStefano Zampini     ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr);
212665066ba5SStefano Zampini     for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i;
2127487b449aSStefano Zampini     ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
2128d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
2129487b449aSStefano Zampini     ierr = MatSetValuesLocal(MT,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr);
2130d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
213165066ba5SStefano Zampini     ierr = PetscFree(dummy);CHKERRQ(ierr);
2132686e3a49SStefano Zampini   } else if (isseqaij) {
21336afe12f5SStefano Zampini     const PetscInt *blocks;
21346afe12f5SStefano Zampini     PetscInt       i,nvtxs,*xadj,*adjncy, nb;
2135686e3a49SStefano Zampini     PetscBool      done;
2136686e3a49SStefano Zampini 
2137d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2138938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
2139d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
21406afe12f5SStefano Zampini     ierr = MatGetVariableBlockSizes(local_mat,&nb,&blocks);CHKERRQ(ierr);
21416afe12f5SStefano Zampini     if (nb) { /* speed up assembly for special blocked matrices (used by BDDC) */
21426afe12f5SStefano Zampini       PetscInt sum;
21436afe12f5SStefano Zampini 
21446afe12f5SStefano Zampini       for (i=0,sum=0;i<nb;i++) sum += blocks[i];
21456afe12f5SStefano Zampini       if (sum == nvtxs) {
21466afe12f5SStefano Zampini         PetscInt r;
21476afe12f5SStefano Zampini 
21486afe12f5SStefano Zampini         for (i=0,r=0;i<nb;i++) {
21496afe12f5SStefano Zampini           if (blocks[i] != xadj[r+1] - xadj[r]) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Invalid block sizes prescribed for block %D: expected %D, got %D",i,blocks[i],xadj[r+1] - xadj[r]);
21506afe12f5SStefano Zampini           ierr = MatSetValuesLocal(MT,blocks[i],adjncy+xadj[r],blocks[i],adjncy+xadj[r],array+xadj[r],ADD_VALUES);CHKERRQ(ierr);
21516afe12f5SStefano Zampini           r   += blocks[i];
21526afe12f5SStefano Zampini         }
21536afe12f5SStefano Zampini       } else {
2154686e3a49SStefano Zampini         for (i=0;i<nvtxs;i++) {
2155487b449aSStefano Zampini           ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
2156686e3a49SStefano Zampini         }
21576afe12f5SStefano Zampini       }
21586afe12f5SStefano Zampini     } else {
21596afe12f5SStefano Zampini       for (i=0;i<nvtxs;i++) {
21606afe12f5SStefano Zampini         ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
21616afe12f5SStefano Zampini       }
21626afe12f5SStefano Zampini     }
2163d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2164938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
2165d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
2166686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
2167ecf5a873SStefano Zampini     PetscInt i;
2168c0962df8SStefano Zampini 
2169686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
2170686e3a49SStefano Zampini       PetscInt       j;
2171ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
2172686e3a49SStefano Zampini 
2173ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
2174487b449aSStefano Zampini       ierr = MatSetValuesLocal(MT,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
2175ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
2176686e3a49SStefano Zampini     }
2177b7ce53b6SStefano Zampini   }
2178487b449aSStefano Zampini   ierr = MatAssemblyBegin(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2179d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
2180487b449aSStefano Zampini   ierr = MatAssemblyEnd(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2181b9ed4604SStefano Zampini   if (isseqdense) {
2182487b449aSStefano Zampini     ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
2183487b449aSStefano Zampini   }
2184487b449aSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
2185487b449aSStefano Zampini     ierr = MatHeaderReplace(mat,&MT);CHKERRQ(ierr);
2186487b449aSStefano Zampini   } else if (reuse == MAT_INITIAL_MATRIX) {
2187487b449aSStefano Zampini     *M = MT;
2188b7ce53b6SStefano Zampini   }
2189b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
2190b7ce53b6SStefano Zampini }
2191b7ce53b6SStefano Zampini 
2192b7ce53b6SStefano Zampini /*@
2193b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
2194b7ce53b6SStefano Zampini 
2195b7ce53b6SStefano Zampini   Input Parameter:
2196b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
2197b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
2198b7ce53b6SStefano Zampini 
2199b7ce53b6SStefano Zampini   Output Parameter:
2200b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
2201b7ce53b6SStefano Zampini 
2202b7ce53b6SStefano Zampini   Level: developer
2203b7ce53b6SStefano Zampini 
220495452b02SPatrick Sanan   Notes:
2205487b449aSStefano Zampini     This function has been deprecated and it will be removed in future releases. Update your code to use the MatConvert() interface.
2206b7ce53b6SStefano Zampini 
2207487b449aSStefano Zampini .seealso: MATIS, MatConvert()
2208b7ce53b6SStefano Zampini @*/
2209b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
2210b7ce53b6SStefano Zampini {
2211b7ce53b6SStefano Zampini   PetscErrorCode ierr;
2212b7ce53b6SStefano Zampini 
2213b7ce53b6SStefano Zampini   PetscFunctionBegin;
2214b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2215b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
2216b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
2217487b449aSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
2218b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
2219b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
22206c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
2221b7ce53b6SStefano Zampini   }
2222487b449aSStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatType,MatReuse,Mat*),(mat,MATAIJ,reuse,newmat));CHKERRQ(ierr);
2223b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
2224b7ce53b6SStefano Zampini }
2225b7ce53b6SStefano Zampini 
2226ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
2227ad6194a2SStefano Zampini {
2228ad6194a2SStefano Zampini   PetscErrorCode ierr;
2229ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
2230c9225affSStefano Zampini   PetscInt       rbs,cbs,m,n,M,N;
2231ad6194a2SStefano Zampini   Mat            B,localmat;
2232ad6194a2SStefano Zampini 
2233ad6194a2SStefano Zampini   PetscFunctionBegin;
2234c9225affSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
2235c9225affSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
2236ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
2237ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
22388546b261SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)mat),&B);CHKERRQ(ierr);
22398546b261SStefano Zampini   ierr = MatSetSizes(B,m,n,M,N);CHKERRQ(ierr);
22408546b261SStefano Zampini   ierr = MatSetBlockSize(B,rbs == cbs ? rbs : 1);CHKERRQ(ierr);
22418546b261SStefano Zampini   ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
22428546b261SStefano Zampini   ierr = MatISSetLocalMatType(B,matis->lmattype);CHKERRQ(ierr);
22438546b261SStefano Zampini   ierr = MatSetLocalToGlobalMapping(B,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
2244ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
2245ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
2246b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
2247b0f2910eSStefano Zampini   if (matis->sf) {
2248b0f2910eSStefano Zampini     Mat_IS *bmatis = (Mat_IS*)(B->data);
2249b0f2910eSStefano Zampini 
2250b0f2910eSStefano Zampini     ierr       = PetscObjectReference((PetscObject)matis->sf);CHKERRQ(ierr);
2251b0f2910eSStefano Zampini     bmatis->sf = matis->sf;
2252b0f2910eSStefano Zampini     ierr       = PetscMalloc2(matis->sf->nroots,&bmatis->sf_rootdata,matis->sf->nleaves,&bmatis->sf_leafdata);CHKERRQ(ierr);
2253b0f2910eSStefano Zampini     if (matis->sf != matis->csf) {
2254b0f2910eSStefano Zampini       ierr        = PetscObjectReference((PetscObject)matis->csf);CHKERRQ(ierr);
2255b0f2910eSStefano Zampini       bmatis->csf = matis->csf;
2256b0f2910eSStefano Zampini       ierr        = PetscMalloc2(matis->csf->nroots,&bmatis->csf_rootdata,matis->csf->nleaves,&bmatis->csf_leafdata);CHKERRQ(ierr);
2257b0f2910eSStefano Zampini     } else {
2258b0f2910eSStefano Zampini       bmatis->csf          = bmatis->sf;
2259b0f2910eSStefano Zampini       bmatis->csf_leafdata = bmatis->sf_leafdata;
2260b0f2910eSStefano Zampini       bmatis->csf_rootdata = bmatis->sf_rootdata;
2261b0f2910eSStefano Zampini     }
2262b0f2910eSStefano Zampini   }
2263ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2264ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2265ad6194a2SStefano Zampini   *newmat = B;
2266ad6194a2SStefano Zampini   PetscFunctionReturn(0);
2267ad6194a2SStefano Zampini }
2268ad6194a2SStefano Zampini 
2269a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
227069796d55SStefano Zampini {
227169796d55SStefano Zampini   PetscErrorCode ierr;
227269796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
227369796d55SStefano Zampini   PetscBool      local_sym;
227469796d55SStefano Zampini 
227569796d55SStefano Zampini   PetscFunctionBegin;
227669796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
2277b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
227869796d55SStefano Zampini   PetscFunctionReturn(0);
227969796d55SStefano Zampini }
228069796d55SStefano Zampini 
2281a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
228269796d55SStefano Zampini {
228369796d55SStefano Zampini   PetscErrorCode ierr;
228469796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
228569796d55SStefano Zampini   PetscBool      local_sym;
228669796d55SStefano Zampini 
228769796d55SStefano Zampini   PetscFunctionBegin;
228869796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
2289b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
229069796d55SStefano Zampini   PetscFunctionReturn(0);
229169796d55SStefano Zampini }
229269796d55SStefano Zampini 
229345471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
229445471136SStefano Zampini {
229545471136SStefano Zampini   PetscErrorCode ierr;
229645471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
229745471136SStefano Zampini   PetscBool      local_sym;
229845471136SStefano Zampini 
229945471136SStefano Zampini   PetscFunctionBegin;
230045471136SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
230145471136SStefano Zampini     *flg = PETSC_FALSE;
230245471136SStefano Zampini     PetscFunctionReturn(0);
230345471136SStefano Zampini   }
230445471136SStefano Zampini   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
230545471136SStefano Zampini   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
230645471136SStefano Zampini   PetscFunctionReturn(0);
230745471136SStefano Zampini }
230845471136SStefano Zampini 
2309a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
2310b4319ba4SBarry Smith {
2311dfbe8321SBarry Smith   PetscErrorCode ierr;
2312b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
2313b4319ba4SBarry Smith 
2314b4319ba4SBarry Smith   PetscFunctionBegin;
23158546b261SStefano Zampini   ierr = PetscFree(b->lmattype);CHKERRQ(ierr);
23166bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
2317e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
2318e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
23196bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
23206bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
23213fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
2322a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
2323a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
2324a8116848SStefano Zampini   if (b->sf != b->csf) {
2325a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
2326a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
2327f03112d0SStefano Zampini   } else b->csf = NULL;
232828f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
232928f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
2330bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
2331dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
23328546b261SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",NULL);CHKERRQ(ierr);
2333bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
2334b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
2335b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
23362e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
2337cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",NULL);CHKERRQ(ierr);
233875d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",NULL);CHKERRQ(ierr);
2339f03112d0SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",NULL);CHKERRQ(ierr);
2340487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",NULL);CHKERRQ(ierr);
2341487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",NULL);CHKERRQ(ierr);
2342487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",NULL);CHKERRQ(ierr);
2343487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",NULL);CHKERRQ(ierr);
2344487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",NULL);CHKERRQ(ierr);
2345487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",NULL);CHKERRQ(ierr);
2346487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",NULL);CHKERRQ(ierr);
2347b4319ba4SBarry Smith   PetscFunctionReturn(0);
2348b4319ba4SBarry Smith }
2349b4319ba4SBarry Smith 
2350a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
2351b4319ba4SBarry Smith {
2352dfbe8321SBarry Smith   PetscErrorCode ierr;
2353b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
2354b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
2355b4319ba4SBarry Smith 
2356b4319ba4SBarry Smith   PetscFunctionBegin;
2357b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
2358e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2359e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2360b4319ba4SBarry Smith 
2361b4319ba4SBarry Smith   /* multiply the local matrix */
2362b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
2363b4319ba4SBarry Smith 
2364b4319ba4SBarry Smith   /* scatter product back into global memory */
23652dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
2366e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2367e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2368b4319ba4SBarry Smith   PetscFunctionReturn(0);
2369b4319ba4SBarry Smith }
2370b4319ba4SBarry Smith 
2371a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
23722e74eeadSLisandro Dalcin {
2373650997f4SStefano Zampini   Vec            temp_vec;
23742e74eeadSLisandro Dalcin   PetscErrorCode ierr;
23752e74eeadSLisandro Dalcin 
23762e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
2377650997f4SStefano Zampini   if (v3 != v2) {
2378650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
2379650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
2380650997f4SStefano Zampini   } else {
2381650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
2382650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
2383650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
2384650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
2385650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
2386650997f4SStefano Zampini   }
23872e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
23882e74eeadSLisandro Dalcin }
23892e74eeadSLisandro Dalcin 
2390a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
23912e74eeadSLisandro Dalcin {
23922e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
23932e74eeadSLisandro Dalcin   PetscErrorCode ierr;
23942e74eeadSLisandro Dalcin 
2395e176bc59SStefano Zampini   PetscFunctionBegin;
23962e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
2397e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2398e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23992e74eeadSLisandro Dalcin 
24002e74eeadSLisandro Dalcin   /* multiply the local matrix */
2401e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
24022e74eeadSLisandro Dalcin 
24032e74eeadSLisandro Dalcin   /* scatter product back into global vector */
2404e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
2405e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2406e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24072e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
24082e74eeadSLisandro Dalcin }
24092e74eeadSLisandro Dalcin 
2410a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
24112e74eeadSLisandro Dalcin {
2412650997f4SStefano Zampini   Vec            temp_vec;
24132e74eeadSLisandro Dalcin   PetscErrorCode ierr;
24142e74eeadSLisandro Dalcin 
24152e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
2416650997f4SStefano Zampini   if (v3 != v2) {
2417650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
2418650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
2419650997f4SStefano Zampini   } else {
2420650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
2421650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
2422650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
2423650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
2424650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
2425650997f4SStefano Zampini   }
24262e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
24272e74eeadSLisandro Dalcin }
24282e74eeadSLisandro Dalcin 
2429a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
2430b4319ba4SBarry Smith {
2431b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
2432dfbe8321SBarry Smith   PetscErrorCode ierr;
2433b4319ba4SBarry Smith   PetscViewer    sviewer;
2434ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
2435b4319ba4SBarry Smith 
2436b4319ba4SBarry Smith   PetscFunctionBegin;
2437ee2491ecSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
2438ee2491ecSStefano Zampini   if (isascii)  {
2439ee2491ecSStefano Zampini     PetscViewerFormat format;
2440ee2491ecSStefano Zampini 
2441ee2491ecSStefano Zampini     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
2442ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
2443ee2491ecSStefano Zampini   }
2444ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
24453f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
2446b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
24473f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
24486e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2449b4319ba4SBarry Smith   PetscFunctionReturn(0);
2450b4319ba4SBarry Smith }
2451b4319ba4SBarry Smith 
24528546b261SStefano Zampini static PetscErrorCode MatISSetUpScatters_Private(Mat A)
2453b4319ba4SBarry Smith {
2454e176bc59SStefano Zampini   Vec            cglobal,rglobal;
24558546b261SStefano Zampini   IS             from;
24568546b261SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
24578546b261SStefano Zampini   const PetscInt *garray;
24588546b261SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
24598546b261SStefano Zampini   PetscBool      iscuda;
24608546b261SStefano Zampini   PetscErrorCode ierr;
2461b4319ba4SBarry Smith 
2462b4319ba4SBarry Smith   PetscFunctionBegin;
24638546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nr);CHKERRQ(ierr);
24648546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(A->rmap->mapping,&rbs);CHKERRQ(ierr);
24658546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&nc);CHKERRQ(ierr);
24668546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(A->cmap->mapping,&cbs);CHKERRQ(ierr);
246770cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
246870cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
24693fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
2470e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
2471e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
24728546b261SStefano Zampini   ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
24738546b261SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)is->y,VECSEQCUDA,&iscuda);CHKERRQ(ierr);
24748546b261SStefano Zampini   if (iscuda) {
24758546b261SStefano Zampini     ierr = PetscFree(A->defaultvectype);CHKERRQ(ierr);
24768546b261SStefano Zampini     ierr = PetscStrallocpy(VECCUDA,&A->defaultvectype);CHKERRQ(ierr);
24778546b261SStefano Zampini   }
24788546b261SStefano Zampini   ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
24798546b261SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockIndices(A->rmap->mapping,&garray);CHKERRQ(ierr);
24808546b261SStefano Zampini   ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),rbs,nr/rbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
2481*35928de7SBarry Smith   ierr = VecScatterCreateWithData(rglobal,from,is->y,NULL,&is->rctx);CHKERRQ(ierr);
24828546b261SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreBlockIndices(A->rmap->mapping,&garray);CHKERRQ(ierr);
24838546b261SStefano Zampini   ierr = ISDestroy(&from);CHKERRQ(ierr);
24848546b261SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
24858546b261SStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(A->cmap->mapping,&garray);CHKERRQ(ierr);
24868546b261SStefano Zampini     ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),cbs,nc/cbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
2487*35928de7SBarry Smith     ierr = VecScatterCreateWithData(cglobal,from,is->x,NULL,&is->cctx);CHKERRQ(ierr);
24888546b261SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(A->cmap->mapping,&garray);CHKERRQ(ierr);
24898546b261SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
24908546b261SStefano Zampini   } else {
24918546b261SStefano Zampini     ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
24928546b261SStefano Zampini     is->cctx = is->rctx;
24938546b261SStefano Zampini   }
24948546b261SStefano Zampini   /* interface counter vector (local) */
24958546b261SStefano Zampini   ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
24968546b261SStefano Zampini   ierr = VecSet(is->y,1.);CHKERRQ(ierr);
24978546b261SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24988546b261SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
24998546b261SStefano Zampini   ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
25008546b261SStefano Zampini   ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
25018546b261SStefano Zampini   ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
25028546b261SStefano Zampini   ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
25038546b261SStefano Zampini   ierr = ISDestroy(&from);CHKERRQ(ierr);
25048546b261SStefano Zampini   PetscFunctionReturn(0);
25058546b261SStefano Zampini }
25068546b261SStefano Zampini 
25078546b261SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
25088546b261SStefano Zampini {
25098546b261SStefano Zampini   PetscErrorCode ierr;
25108546b261SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
25118546b261SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
25128546b261SStefano Zampini 
25138546b261SStefano Zampini   PetscFunctionBegin;
25148546b261SStefano Zampini   PetscCheckSameComm(A,1,rmapping,2);
25158546b261SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
25161c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
2517872cf891SStefano Zampini   if (is->csf != is->sf) {
2518872cf891SStefano Zampini     ierr = PetscSFDestroy(&is->csf);CHKERRQ(ierr);
2519872cf891SStefano Zampini     ierr = PetscFree2(is->csf_rootdata,is->csf_leafdata);CHKERRQ(ierr);
2520f03112d0SStefano Zampini   } else is->csf = NULL;
252128f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
252228f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
25233bbff08aSStefano Zampini 
25243bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
2525fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
2526fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
2527e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
2528e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
2529e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
2530e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
25316625354bSStefano Zampini   /* check if the two mappings are actually the same for square matrices (DOLFIN passes 2 different objects) */
25326625354bSStefano Zampini   if (rmapping != cmapping && A->rmap->N == A->cmap->N) {
25336625354bSStefano Zampini     PetscBool same,gsame;
25346625354bSStefano Zampini 
25356625354bSStefano Zampini     same = PETSC_FALSE;
25366625354bSStefano Zampini     if (nr == nc && cbs == rbs) {
25376625354bSStefano Zampini       const PetscInt *idxs1,*idxs2;
25386625354bSStefano Zampini 
25396625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
25406625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
25416625354bSStefano Zampini       ierr = PetscMemcmp(idxs1,idxs2,(nr/rbs)*sizeof(PetscInt),&same);CHKERRQ(ierr);
25426625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
25436625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
25446625354bSStefano Zampini     }
25456625354bSStefano Zampini     ierr = MPIU_Allreduce(&same,&gsame,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
25466625354bSStefano Zampini     if (gsame) cmapping = rmapping;
25476625354bSStefano Zampini   }
254853b44cf5SStefano Zampini   ierr = PetscLayoutSetBlockSize(A->rmap,rbs);CHKERRQ(ierr);
254953b44cf5SStefano Zampini   ierr = PetscLayoutSetBlockSize(A->cmap,cbs);CHKERRQ(ierr);
25506625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
25516625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
25526625354bSStefano Zampini 
25536625354bSStefano Zampini   /* Create the local matrix A */
2554f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
25558546b261SStefano Zampini   ierr = MatSetType(is->A,is->lmattype);CHKERRQ(ierr);
2556e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
2557e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
25588546b261SStefano Zampini   ierr = MatSetOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
25598546b261SStefano Zampini   ierr = MatAppendOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
2560c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->rmap);CHKERRQ(ierr);
2561c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->cmap);CHKERRQ(ierr);
2562b4319ba4SBarry Smith 
2563f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
25648546b261SStefano Zampini     ierr = MatISSetUpScatters_Private(A);CHKERRQ(ierr);
2565f26d0771SStefano Zampini   }
256648ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
2567b4319ba4SBarry Smith   PetscFunctionReturn(0);
2568b4319ba4SBarry Smith }
2569b4319ba4SBarry Smith 
2570a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
25712e74eeadSLisandro Dalcin {
25722e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
25732e74eeadSLisandro Dalcin   PetscErrorCode ierr;
257497563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
257597563a80SStefano Zampini   PetscInt       i,zm,zn;
257697563a80SStefano Zampini #endif
2577f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
25782e74eeadSLisandro Dalcin 
25792e74eeadSLisandro Dalcin   PetscFunctionBegin;
25802e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
2581f26d0771SStefano Zampini   if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n);
258297563a80SStefano Zampini   /* count negative indices */
258397563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
258497563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
25852e74eeadSLisandro Dalcin #endif
258697563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
258797563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
258897563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
258997563a80SStefano Zampini   /* count negative indices (should be the same as before) */
259097563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
259197563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
2592b4f971dfSStefano Zampini   if (!is->A->rmap->mapping && zm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS");
2593b4f971dfSStefano Zampini   if (!is->A->cmap->mapping && zn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS");
259497563a80SStefano Zampini #endif
25952e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
25962e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
25972e74eeadSLisandro Dalcin }
25982e74eeadSLisandro Dalcin 
2599a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
260097563a80SStefano Zampini {
260197563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
260297563a80SStefano Zampini   PetscErrorCode ierr;
260397563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
260497563a80SStefano Zampini   PetscInt       i,zm,zn;
260597563a80SStefano Zampini #endif
2606f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
260797563a80SStefano Zampini 
260897563a80SStefano Zampini   PetscFunctionBegin;
260997563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
2610f26d0771SStefano Zampini   if (m > MATIS_MAX_ENTRIES_INSERTION || n > MATIS_MAX_ENTRIES_INSERTION) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_SUP,"Number of row/column block indices must be <= %D: they are %D %D",MATIS_MAX_ENTRIES_INSERTION,m,n);
261197563a80SStefano Zampini   /* count negative indices */
261297563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
261397563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
261497563a80SStefano Zampini #endif
261597563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
261697563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
261797563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
261897563a80SStefano Zampini   /* count negative indices (should be the same as before) */
261997563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
262097563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
2621b4f971dfSStefano Zampini   if (!is->A->rmap->mapping && zm) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the row indices can not be mapped! Maybe you should not use MATIS");
2622b4f971dfSStefano Zampini   if (!is->A->cmap->mapping && zn) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Some of the column indices can not be mapped! Maybe you should not use MATIS");
262397563a80SStefano Zampini #endif
2624d59cf9ebSStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
262597563a80SStefano Zampini   PetscFunctionReturn(0);
262697563a80SStefano Zampini }
262797563a80SStefano Zampini 
2628a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2629b4319ba4SBarry Smith {
2630dfbe8321SBarry Smith   PetscErrorCode ierr;
2631b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2632b4319ba4SBarry Smith 
2633b4319ba4SBarry Smith   PetscFunctionBegin;
2634b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
2635872cf891SStefano Zampini     ierr = MatSetValuesLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2636872cf891SStefano Zampini   } else {
2637b4319ba4SBarry Smith     ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2638872cf891SStefano Zampini   }
2639b4319ba4SBarry Smith   PetscFunctionReturn(0);
2640b4319ba4SBarry Smith }
2641b4319ba4SBarry Smith 
2642a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2643f0006bf2SLisandro Dalcin {
2644f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
2645f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
2646f0006bf2SLisandro Dalcin 
2647f0006bf2SLisandro Dalcin   PetscFunctionBegin;
2648b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
2649b4f971dfSStefano Zampini #if defined(PETSC_USE_DEBUG)
2650b4f971dfSStefano Zampini     PetscInt ibs,bs;
2651b4f971dfSStefano Zampini 
2652b4f971dfSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(is->A->rmap->mapping,&ibs);CHKERRQ(ierr);
2653b4f971dfSStefano Zampini     ierr = MatGetBlockSize(is->A,&bs);CHKERRQ(ierr);
2654b4f971dfSStefano Zampini     if (ibs != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Different block sizes! local mat %D, local l2g map %D",bs,ibs);
2655b4f971dfSStefano Zampini #endif
2656b4f971dfSStefano Zampini     ierr = MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2657b4f971dfSStefano Zampini   } else {
2658f0006bf2SLisandro Dalcin     ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2659b4f971dfSStefano Zampini   }
2660f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
2661f0006bf2SLisandro Dalcin }
2662f0006bf2SLisandro Dalcin 
2663f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
2664f0ae7da4SStefano Zampini {
2665f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
2666f0ae7da4SStefano Zampini   PetscErrorCode ierr;
2667f0ae7da4SStefano Zampini 
2668f0ae7da4SStefano Zampini   PetscFunctionBegin;
2669f0ae7da4SStefano Zampini   if (!n) {
2670f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
2671f0ae7da4SStefano Zampini   } else {
2672f0ae7da4SStefano Zampini     PetscInt i;
2673f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
2674f0ae7da4SStefano Zampini 
2675f0ae7da4SStefano Zampini     if (columns) {
2676f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
2677f0ae7da4SStefano Zampini     } else {
2678f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
2679f0ae7da4SStefano Zampini     }
2680f0ae7da4SStefano Zampini     if (diag != 0.) {
2681f0ae7da4SStefano Zampini       const PetscScalar *array;
2682f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
2683f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
2684f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
2685f0ae7da4SStefano Zampini       }
2686f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
2687f0ae7da4SStefano Zampini     }
2688f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2689f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2690f0ae7da4SStefano Zampini   }
2691f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2692f0ae7da4SStefano Zampini }
2693f0ae7da4SStefano Zampini 
2694f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
26952e74eeadSLisandro Dalcin {
26966e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
26976e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
26986e520ac8SStefano Zampini   PetscInt       *lrows;
26992e74eeadSLisandro Dalcin   PetscErrorCode ierr;
27002e74eeadSLisandro Dalcin 
27012e74eeadSLisandro Dalcin   PetscFunctionBegin;
2702f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
2703f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
2704f0ae7da4SStefano Zampini     PetscBool cong;
270526b0207aSStefano Zampini 
2706f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
270726b0207aSStefano Zampini     cong = (PetscBool)(cong && matis->sf == matis->csf);
2708268753edSStefano Zampini     if (!cong && columns) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Columns can be zeroed if and only if A->rmap and A->cmap are congruent and the l2g maps are the same for MATIS");
2709268753edSStefano Zampini     if (!cong && diag != 0.) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"Nonzero diagonal value supported if and only if A->rmap and A->cmap are congruent and the l2g maps are the same for MATIS");
2710268753edSStefano Zampini     if (!cong && x && b) SETERRQ(PetscObjectComm((PetscObject)A),PETSC_ERR_SUP,"A->rmap and A->cmap need to be congruent, and the l2g maps be the same");
2711f0ae7da4SStefano Zampini   }
2712f0ae7da4SStefano Zampini #endif
27136e520ac8SStefano Zampini   /* get locally owned rows */
2714f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
27156e520ac8SStefano Zampini   /* fix right hand side if needed */
27166e520ac8SStefano Zampini   if (x && b) {
27176e520ac8SStefano Zampini     const PetscScalar *xx;
27186e520ac8SStefano Zampini     PetscScalar       *bb;
27196e520ac8SStefano Zampini 
27206e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
27216e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
27226e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
27236e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
27246e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
27252e74eeadSLisandro Dalcin   }
27266e520ac8SStefano Zampini   /* get rows associated to the local matrices */
27273d996552SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
27286e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
27296e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
27306e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
27316e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
27326e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
27336e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
27346e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
27356e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
27366e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
2737f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
27386e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
27392e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
27402e74eeadSLisandro Dalcin }
27412e74eeadSLisandro Dalcin 
2742f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2743b4319ba4SBarry Smith {
2744dfbe8321SBarry Smith   PetscErrorCode ierr;
2745b4319ba4SBarry Smith 
2746b4319ba4SBarry Smith   PetscFunctionBegin;
2747f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
2748f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2749f0ae7da4SStefano Zampini }
27502205254eSKarl Rupp 
2751f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2752f0ae7da4SStefano Zampini {
2753f0ae7da4SStefano Zampini   PetscErrorCode ierr;
2754f0ae7da4SStefano Zampini 
2755f0ae7da4SStefano Zampini   PetscFunctionBegin;
2756f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
2757b4319ba4SBarry Smith   PetscFunctionReturn(0);
2758b4319ba4SBarry Smith }
2759b4319ba4SBarry Smith 
2760a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
2761b4319ba4SBarry Smith {
2762b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2763dfbe8321SBarry Smith   PetscErrorCode ierr;
2764b4319ba4SBarry Smith 
2765b4319ba4SBarry Smith   PetscFunctionBegin;
2766b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
2767b4319ba4SBarry Smith   PetscFunctionReturn(0);
2768b4319ba4SBarry Smith }
2769b4319ba4SBarry Smith 
2770a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
2771b4319ba4SBarry Smith {
2772b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2773dfbe8321SBarry Smith   PetscErrorCode ierr;
2774b4319ba4SBarry Smith 
2775b4319ba4SBarry Smith   PetscFunctionBegin;
2776b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
2777872cf891SStefano Zampini   /* fix for local empty rows/cols */
2778872cf891SStefano Zampini   if (is->locempty && type == MAT_FINAL_ASSEMBLY) {
2779872cf891SStefano Zampini     Mat                    newlA;
2780f03112d0SStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g;
2781f03112d0SStefano Zampini     IS                     nzr,nzc;
2782f03112d0SStefano Zampini     PetscInt               nr,nc,nnzr,nnzc;
2783f03112d0SStefano Zampini     PetscBool              lnewl2g,newl2g;
2784872cf891SStefano Zampini 
2785f03112d0SStefano Zampini     ierr = MatGetSize(is->A,&nr,&nc);CHKERRQ(ierr);
2786f03112d0SStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_FALSE,PETSC_SMALL,&nzr);CHKERRQ(ierr);
2787f03112d0SStefano Zampini     if (!nzr) {
2788f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&nzr);CHKERRQ(ierr);
2789872cf891SStefano Zampini     }
2790f03112d0SStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_TRUE,PETSC_SMALL,&nzc);CHKERRQ(ierr);
2791f03112d0SStefano Zampini     if (!nzc) {
2792f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&nzc);CHKERRQ(ierr);
2793872cf891SStefano Zampini     }
2794f03112d0SStefano Zampini     ierr = ISGetSize(nzr,&nnzr);CHKERRQ(ierr);
2795f03112d0SStefano Zampini     ierr = ISGetSize(nzc,&nnzc);CHKERRQ(ierr);
2796f03112d0SStefano Zampini     if (nnzr != nr || nnzc != nc) {
2797f03112d0SStefano Zampini       ISLocalToGlobalMapping l2g;
2798f03112d0SStefano Zampini       IS                     is1,is2;
2799f03112d0SStefano Zampini 
2800f03112d0SStefano Zampini       /* need new global l2g map */
2801f03112d0SStefano Zampini       lnewl2g = PETSC_TRUE;
2802f03112d0SStefano Zampini       ierr    = MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
2803f03112d0SStefano Zampini 
2804872cf891SStefano Zampini       /* extract valid submatrix */
2805f03112d0SStefano Zampini       ierr = MatCreateSubMatrix(is->A,nzr,nzc,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
2806f03112d0SStefano Zampini 
2807f03112d0SStefano Zampini       /* attach local l2g maps for successive calls of MatSetValues on the local matrix */
2808f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(nzr,&l2g);CHKERRQ(ierr);
2809f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&is1);CHKERRQ(ierr);
2810f03112d0SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_MASK,is1,&is2);CHKERRQ(ierr);
2811872cf891SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
281272ed36d8SStefano Zampini       if (is->A->rmap->mapping) { /* the matrix has a local-to-local map already attached (probably DMDA generated) */
281372ed36d8SStefano Zampini         const PetscInt *idxs1,*idxs2;
281472ed36d8SStefano Zampini         PetscInt       j,i,nl,*tidxs;
281572ed36d8SStefano Zampini 
281672ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(is->A->rmap->mapping,&nl);CHKERRQ(ierr);
281772ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(is->A->rmap->mapping,&idxs1);CHKERRQ(ierr);
281872ed36d8SStefano Zampini         ierr = PetscMalloc1(nl,&tidxs);CHKERRQ(ierr);
281972ed36d8SStefano Zampini         ierr = ISGetIndices(is2,&idxs2);CHKERRQ(ierr);
282072ed36d8SStefano Zampini         for (i=0,j=0;i<nl;i++) tidxs[i] = idxs1[i] < 0 ? -1 : idxs2[j++];
282172ed36d8SStefano Zampini         if (j != nr) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected count %D != %D",j,nr);
282272ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(is->A->rmap->mapping,&idxs1);CHKERRQ(ierr);
282372ed36d8SStefano Zampini         ierr = ISRestoreIndices(is2,&idxs2);CHKERRQ(ierr);
282472ed36d8SStefano Zampini         ierr = ISDestroy(&is2);CHKERRQ(ierr);
282572ed36d8SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A->rmap->mapping),nl,tidxs,PETSC_OWN_POINTER,&is2);CHKERRQ(ierr);
282672ed36d8SStefano Zampini       }
2827f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is2,&rl2g);CHKERRQ(ierr);
2828f03112d0SStefano Zampini       ierr = ISDestroy(&is1);CHKERRQ(ierr);
2829f03112d0SStefano Zampini       ierr = ISDestroy(&is2);CHKERRQ(ierr);
283072ed36d8SStefano Zampini 
2831f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(nzc,&l2g);CHKERRQ(ierr);
2832f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&is1);CHKERRQ(ierr);
2833f03112d0SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_MASK,is1,&is2);CHKERRQ(ierr);
2834f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
283572ed36d8SStefano Zampini       if (is->A->cmap->mapping) { /* the matrix has a local-to-local map already attached (probably DMDA generated) */
283672ed36d8SStefano Zampini         const PetscInt *idxs1,*idxs2;
283772ed36d8SStefano Zampini         PetscInt       j,i,nl,*tidxs;
283872ed36d8SStefano Zampini 
283972ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(is->A->cmap->mapping,&nl);CHKERRQ(ierr);
284072ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(is->A->cmap->mapping,&idxs1);CHKERRQ(ierr);
284172ed36d8SStefano Zampini         ierr = PetscMalloc1(nl,&tidxs);CHKERRQ(ierr);
284272ed36d8SStefano Zampini         ierr = ISGetIndices(is2,&idxs2);CHKERRQ(ierr);
284372ed36d8SStefano Zampini         for (i=0,j=0;i<nl;i++) tidxs[i] = idxs1[i] < 0 ? -1 : idxs2[j++];
284472ed36d8SStefano Zampini         if (j != nc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected count %D != %D",j,nc);
284572ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(is->A->cmap->mapping,&idxs1);CHKERRQ(ierr);
284672ed36d8SStefano Zampini         ierr = ISRestoreIndices(is2,&idxs2);CHKERRQ(ierr);
284772ed36d8SStefano Zampini         ierr = ISDestroy(&is2);CHKERRQ(ierr);
284872ed36d8SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A->cmap->mapping),nl,tidxs,PETSC_OWN_POINTER,&is2);CHKERRQ(ierr);
284972ed36d8SStefano Zampini       }
2850f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is2,&cl2g);CHKERRQ(ierr);
2851f03112d0SStefano Zampini       ierr = ISDestroy(&is1);CHKERRQ(ierr);
2852f03112d0SStefano Zampini       ierr = ISDestroy(&is2);CHKERRQ(ierr);
285372ed36d8SStefano Zampini 
2854f03112d0SStefano Zampini       ierr = MatSetLocalToGlobalMapping(newlA,rl2g,cl2g);CHKERRQ(ierr);
285572ed36d8SStefano Zampini 
2856f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2857f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2858f03112d0SStefano Zampini     } else { /* local matrix fully populated */
2859f03112d0SStefano Zampini       lnewl2g = PETSC_FALSE;
2860f03112d0SStefano Zampini       ierr    = MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
2861f03112d0SStefano Zampini       ierr    = PetscObjectReference((PetscObject)is->A);CHKERRQ(ierr);
2862f03112d0SStefano Zampini       newlA   = is->A;
2863f03112d0SStefano Zampini     }
2864f03112d0SStefano Zampini     /* attach new global l2g map if needed */
2865f03112d0SStefano Zampini     if (newl2g) {
2866f03112d0SStefano Zampini       IS             gnzr,gnzc;
2867f03112d0SStefano Zampini       const PetscInt *grid,*gcid;
2868f03112d0SStefano Zampini 
2869f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(A->rmap->mapping,nzr,&gnzr);CHKERRQ(ierr);
2870f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(A->cmap->mapping,nzc,&gnzc);CHKERRQ(ierr);
2871f03112d0SStefano Zampini       ierr = ISGetIndices(gnzr,&grid);CHKERRQ(ierr);
2872f03112d0SStefano Zampini       ierr = ISGetIndices(gnzc,&gcid);CHKERRQ(ierr);
2873f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nnzr,grid,PETSC_COPY_VALUES,&rl2g);CHKERRQ(ierr);
2874f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nnzc,gcid,PETSC_COPY_VALUES,&cl2g);CHKERRQ(ierr);
2875f03112d0SStefano Zampini       ierr = ISRestoreIndices(gnzr,&grid);CHKERRQ(ierr);
2876f03112d0SStefano Zampini       ierr = ISRestoreIndices(gnzc,&gcid);CHKERRQ(ierr);
2877f03112d0SStefano Zampini       ierr = ISDestroy(&gnzr);CHKERRQ(ierr);
2878f03112d0SStefano Zampini       ierr = ISDestroy(&gnzc);CHKERRQ(ierr);
2879f03112d0SStefano Zampini       ierr = MatSetLocalToGlobalMapping(A,rl2g,cl2g);CHKERRQ(ierr);
2880f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2881f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2882f03112d0SStefano Zampini     }
2883872cf891SStefano Zampini     ierr = MatISSetLocalMat(A,newlA);CHKERRQ(ierr);
2884872cf891SStefano Zampini     ierr = MatDestroy(&newlA);CHKERRQ(ierr);
2885f03112d0SStefano Zampini     ierr = ISDestroy(&nzr);CHKERRQ(ierr);
2886f03112d0SStefano Zampini     ierr = ISDestroy(&nzc);CHKERRQ(ierr);
2887872cf891SStefano Zampini     is->locempty = PETSC_FALSE;
2888f03112d0SStefano Zampini   }
2889b4319ba4SBarry Smith   PetscFunctionReturn(0);
2890b4319ba4SBarry Smith }
2891b4319ba4SBarry Smith 
2892a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
2893b4319ba4SBarry Smith {
2894b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
2895b4319ba4SBarry Smith 
2896b4319ba4SBarry Smith   PetscFunctionBegin;
2897b4319ba4SBarry Smith   *local = is->A;
2898b4319ba4SBarry Smith   PetscFunctionReturn(0);
2899b4319ba4SBarry Smith }
2900b4319ba4SBarry Smith 
29013b3b1effSJed Brown static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local)
29023b3b1effSJed Brown {
29033b3b1effSJed Brown   PetscFunctionBegin;
29043b3b1effSJed Brown   *local = NULL;
29053b3b1effSJed Brown   PetscFunctionReturn(0);
29063b3b1effSJed Brown }
29073b3b1effSJed Brown 
2908b4319ba4SBarry Smith /*@
2909b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
2910b4319ba4SBarry Smith 
2911b4319ba4SBarry Smith   Input Parameter:
2912b4319ba4SBarry Smith .  mat - the matrix
2913b4319ba4SBarry Smith 
2914b4319ba4SBarry Smith   Output Parameter:
2915eb82efa4SStefano Zampini .  local - the local matrix
2916b4319ba4SBarry Smith 
2917b4319ba4SBarry Smith   Level: advanced
2918b4319ba4SBarry Smith 
2919b4319ba4SBarry Smith   Notes:
2920b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
2921b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
2922b4319ba4SBarry Smith   of the MatSetValues() operation.
2923b4319ba4SBarry Smith 
29243b3b1effSJed Brown   Call MatISRestoreLocalMat() when finished with the local matrix.
292596a6f129SJed Brown 
2926b4319ba4SBarry Smith .seealso: MATIS
2927b4319ba4SBarry Smith @*/
29287087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
2929b4319ba4SBarry Smith {
29304ac538c5SBarry Smith   PetscErrorCode ierr;
2931b4319ba4SBarry Smith 
2932b4319ba4SBarry Smith   PetscFunctionBegin;
29330700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2934b4319ba4SBarry Smith   PetscValidPointer(local,2);
29354ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
2936b4319ba4SBarry Smith   PetscFunctionReturn(0);
2937b4319ba4SBarry Smith }
2938b4319ba4SBarry Smith 
29393b3b1effSJed Brown /*@
29403b3b1effSJed Brown     MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat()
29413b3b1effSJed Brown 
29423b3b1effSJed Brown   Input Parameter:
29433b3b1effSJed Brown .  mat - the matrix
29443b3b1effSJed Brown 
29453b3b1effSJed Brown   Output Parameter:
29463b3b1effSJed Brown .  local - the local matrix
29473b3b1effSJed Brown 
29483b3b1effSJed Brown   Level: advanced
29493b3b1effSJed Brown 
29503b3b1effSJed Brown .seealso: MATIS
29513b3b1effSJed Brown @*/
29523b3b1effSJed Brown PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local)
29533b3b1effSJed Brown {
29543b3b1effSJed Brown   PetscErrorCode ierr;
29553b3b1effSJed Brown 
29563b3b1effSJed Brown   PetscFunctionBegin;
29573b3b1effSJed Brown   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
29583b3b1effSJed Brown   PetscValidPointer(local,2);
29593b3b1effSJed Brown   ierr = PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
29603b3b1effSJed Brown   PetscFunctionReturn(0);
29613b3b1effSJed Brown }
29623b3b1effSJed Brown 
29638546b261SStefano Zampini static PetscErrorCode MatISSetLocalMatType_IS(Mat mat,MatType mtype)
29648546b261SStefano Zampini {
29658546b261SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
29668546b261SStefano Zampini   PetscErrorCode ierr;
29678546b261SStefano Zampini 
29688546b261SStefano Zampini   PetscFunctionBegin;
29698546b261SStefano Zampini   if (is->A) {
29708546b261SStefano Zampini     ierr = MatSetType(is->A,mtype);CHKERRQ(ierr);
29718546b261SStefano Zampini   }
29728546b261SStefano Zampini   ierr = PetscFree(is->lmattype);CHKERRQ(ierr);
29738546b261SStefano Zampini   ierr = PetscStrallocpy(mtype,&is->lmattype);CHKERRQ(ierr);
29748546b261SStefano Zampini   PetscFunctionReturn(0);
29758546b261SStefano Zampini }
29768546b261SStefano Zampini 
29778546b261SStefano Zampini /*@
29788546b261SStefano Zampini     MatISSetLocalMatType - Specifies the type of local matrix
29798546b261SStefano Zampini 
29808546b261SStefano Zampini   Input Parameter:
29818546b261SStefano Zampini .  mat - the matrix
29828546b261SStefano Zampini .  mtype - the local matrix type
29838546b261SStefano Zampini 
29848546b261SStefano Zampini   Output Parameter:
29858546b261SStefano Zampini 
29868546b261SStefano Zampini   Level: advanced
29878546b261SStefano Zampini 
29888546b261SStefano Zampini .seealso: MATIS, MatSetType(), MatType
29898546b261SStefano Zampini @*/
29908546b261SStefano Zampini PetscErrorCode MatISSetLocalMatType(Mat mat,MatType mtype)
29918546b261SStefano Zampini {
29928546b261SStefano Zampini   PetscErrorCode ierr;
29938546b261SStefano Zampini 
29948546b261SStefano Zampini   PetscFunctionBegin;
29958546b261SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
29968546b261SStefano Zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMatType_C",(Mat,MatType),(mat,mtype));CHKERRQ(ierr);
29978546b261SStefano Zampini   PetscFunctionReturn(0);
29988546b261SStefano Zampini }
29998546b261SStefano Zampini 
3000a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
30013b03a366Sstefano_zampini {
30023b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
30033b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
30043b03a366Sstefano_zampini   PetscErrorCode ierr;
30058546b261SStefano Zampini   MatType        mtype,otype;
30068546b261SStefano Zampini   PetscBool      sametype = PETSC_TRUE;
30073b03a366Sstefano_zampini 
30083b03a366Sstefano_zampini   PetscFunctionBegin;
30094e4c7dbeSStefano Zampini   if (is->A) {
30103b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
30113b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
3012f0ae7da4SStefano Zampini     if (orows != nrows || ocols != ncols) SETERRQ4(PETSC_COMM_SELF,PETSC_ERR_ARG_SIZ,"Local MATIS matrix should be of size %Dx%D (you passed a %Dx%D matrix)",orows,ocols,nrows,ncols);
30138546b261SStefano Zampini     ierr = MatGetType(local,&mtype);CHKERRQ(ierr);
30148546b261SStefano Zampini     ierr = MatGetType(is->A,&otype);CHKERRQ(ierr);
30158546b261SStefano Zampini     ierr = PetscStrcmp(mtype,otype,&sametype);CHKERRQ(ierr);
30164e4c7dbeSStefano Zampini   }
30173b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
30183b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
30193b03a366Sstefano_zampini   is->A = local;
30208546b261SStefano Zampini   ierr  = MatGetType(is->A,&mtype);CHKERRQ(ierr);
30218546b261SStefano Zampini   ierr  = MatISSetLocalMatType(mat,mtype);CHKERRQ(ierr);
30228546b261SStefano Zampini   if (!sametype && !is->islocalref) {
30238546b261SStefano Zampini     ierr = MatISSetUpScatters_Private(mat);CHKERRQ(ierr);
30248546b261SStefano Zampini   }
30253b03a366Sstefano_zampini   PetscFunctionReturn(0);
30263b03a366Sstefano_zampini }
30273b03a366Sstefano_zampini 
30283b03a366Sstefano_zampini /*@
3029eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
30303b03a366Sstefano_zampini 
30318546b261SStefano Zampini   Collective on Mat
30328546b261SStefano Zampini 
30333b03a366Sstefano_zampini   Input Parameter:
30343b03a366Sstefano_zampini .  mat - the matrix
3035eb82efa4SStefano Zampini .  local - the local matrix
30363b03a366Sstefano_zampini 
30373b03a366Sstefano_zampini   Output Parameter:
30383b03a366Sstefano_zampini 
30393b03a366Sstefano_zampini   Level: advanced
30403b03a366Sstefano_zampini 
30413b03a366Sstefano_zampini   Notes:
30423b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
30433b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
30443b03a366Sstefano_zampini 
30453b03a366Sstefano_zampini .seealso: MATIS
30463b03a366Sstefano_zampini @*/
30473b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
30483b03a366Sstefano_zampini {
30493b03a366Sstefano_zampini   PetscErrorCode ierr;
30503b03a366Sstefano_zampini 
30513b03a366Sstefano_zampini   PetscFunctionBegin;
30523b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
3053b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
30543b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
30553b03a366Sstefano_zampini   PetscFunctionReturn(0);
30563b03a366Sstefano_zampini }
30573b03a366Sstefano_zampini 
3058a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
30596726f965SBarry Smith {
30606726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
30616726f965SBarry Smith   PetscErrorCode ierr;
30626726f965SBarry Smith 
30636726f965SBarry Smith   PetscFunctionBegin;
30646726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
30656726f965SBarry Smith   PetscFunctionReturn(0);
30666726f965SBarry Smith }
30676726f965SBarry Smith 
3068a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
30692e74eeadSLisandro Dalcin {
30702e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
30712e74eeadSLisandro Dalcin   PetscErrorCode ierr;
30722e74eeadSLisandro Dalcin 
30732e74eeadSLisandro Dalcin   PetscFunctionBegin;
30742e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
30752e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
30762e74eeadSLisandro Dalcin }
30772e74eeadSLisandro Dalcin 
3078a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
30792e74eeadSLisandro Dalcin {
30802e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
30812e74eeadSLisandro Dalcin   PetscErrorCode ierr;
30822e74eeadSLisandro Dalcin 
30832e74eeadSLisandro Dalcin   PetscFunctionBegin;
30842e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
3085e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
30862e74eeadSLisandro Dalcin 
30872e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
30882e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
3089e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3090e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
30912e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
30922e74eeadSLisandro Dalcin }
30932e74eeadSLisandro Dalcin 
3094a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
30956726f965SBarry Smith {
30966726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
30976726f965SBarry Smith   PetscErrorCode ierr;
30986726f965SBarry Smith 
30996726f965SBarry Smith   PetscFunctionBegin;
31004e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
31016726f965SBarry Smith   PetscFunctionReturn(0);
31026726f965SBarry Smith }
31036726f965SBarry Smith 
3104f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
3105f26d0771SStefano Zampini {
3106f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
3107f26d0771SStefano Zampini   Mat_IS         *x;
3108f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3109f26d0771SStefano Zampini   PetscBool      ismatis;
3110f26d0771SStefano Zampini #endif
3111f26d0771SStefano Zampini   PetscErrorCode ierr;
3112f26d0771SStefano Zampini 
3113f26d0771SStefano Zampini   PetscFunctionBegin;
3114f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3115f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
3116f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
3117f26d0771SStefano Zampini #endif
3118f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
3119f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
3120f26d0771SStefano Zampini   PetscFunctionReturn(0);
3121f26d0771SStefano Zampini }
3122f26d0771SStefano Zampini 
3123f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
3124f26d0771SStefano Zampini {
3125f26d0771SStefano Zampini   Mat                    lA;
3126f26d0771SStefano Zampini   Mat_IS                 *matis;
3127f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
3128f26d0771SStefano Zampini   IS                     is;
3129f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
3130f26d0771SStefano Zampini   PetscInt               nrg;
3131f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
3132f26d0771SStefano Zampini   PetscErrorCode         ierr;
3133f26d0771SStefano Zampini 
3134f26d0771SStefano Zampini   PetscFunctionBegin;
3135f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
3136f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
3137f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
3138f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
3139f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3140249c8a71SStefano Zampini   for (i=0;i<nrl;i++) if (rl[i]>=nrg) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local row index %D -> %D greater then maximum possible %D",i,rl[i],nrg);
3141f26d0771SStefano Zampini #endif
3142f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
3143f26d0771SStefano Zampini   /* map from [0,nrl) to row */
3144f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
3145f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3146f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
3147f26d0771SStefano Zampini #else
3148f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
3149f26d0771SStefano Zampini #endif
3150f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
3151f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
3152f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
3153f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
3154f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
3155f26d0771SStefano Zampini   /* compute new l2g map for columns */
3156f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
3157f26d0771SStefano Zampini     const PetscInt *cg,*cl;
3158f26d0771SStefano Zampini     PetscInt       ncg;
3159f26d0771SStefano Zampini     PetscInt       ncl;
3160f26d0771SStefano Zampini 
3161f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
3162f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
3163f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
3164f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
3165f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3166249c8a71SStefano Zampini     for (i=0;i<ncl;i++) if (cl[i]>=ncg) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Local column index %D -> %D greater then maximum possible %D",i,cl[i],ncg);
3167f26d0771SStefano Zampini #endif
3168f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
3169f26d0771SStefano Zampini     /* map from [0,ncl) to col */
3170f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
3171f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3172f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
3173f26d0771SStefano Zampini #else
3174f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
3175f26d0771SStefano Zampini #endif
3176f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
3177f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
3178f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
3179f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
3180f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
3181f26d0771SStefano Zampini   } else {
3182f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
3183f26d0771SStefano Zampini     cl2g = rl2g;
3184f26d0771SStefano Zampini   }
3185f26d0771SStefano Zampini   /* create the MATIS submatrix */
3186f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
3187f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
3188f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
3189f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
3190b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
3191f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
3192f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
3193f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
3194f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
3195f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
3196f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3197f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3198f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3199f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3200f26d0771SStefano Zampini   /* remove unsupported ops */
3201f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
3202f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
3203f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
3204f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
3205f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
3206f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
3207f26d0771SStefano Zampini   PetscFunctionReturn(0);
3208f26d0771SStefano Zampini }
3209f26d0771SStefano Zampini 
3210872cf891SStefano Zampini static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A)
3211872cf891SStefano Zampini {
3212872cf891SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
32138546b261SStefano Zampini   char           type[256];
32148546b261SStefano Zampini   PetscBool      flg;
3215872cf891SStefano Zampini   PetscErrorCode ierr;
3216872cf891SStefano Zampini 
3217872cf891SStefano Zampini   PetscFunctionBegin;
3218872cf891SStefano Zampini   ierr = PetscOptionsHead(PetscOptionsObject,"MATIS options");CHKERRQ(ierr);
3219f03112d0SStefano Zampini   ierr = PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns","MatISFixLocalEmpty",a->locempty,&a->locempty,NULL);CHKERRQ(ierr);
322075d48cdbSStefano Zampini   ierr = PetscOptionsBool("-matis_storel2l","Store local-to-local matrices generated from PtAP operations","MatISStoreL2L",a->storel2l,&a->storel2l,NULL);CHKERRQ(ierr);
32218546b261SStefano Zampini   ierr = PetscOptionsFList("-matis_localmat_type","Matrix type","MatISSetLocalMatType",MatList,a->lmattype,type,256,&flg);CHKERRQ(ierr);
32228546b261SStefano Zampini   if (flg) {
32238546b261SStefano Zampini     ierr = MatISSetLocalMatType(A,type);CHKERRQ(ierr);
32248546b261SStefano Zampini   }
32258546b261SStefano Zampini   if (a->A) {
32268546b261SStefano Zampini     ierr = MatSetFromOptions(a->A);CHKERRQ(ierr);
32278546b261SStefano Zampini   }
32280af67c1bSStefano Zampini   ierr = PetscOptionsTail();CHKERRQ(ierr);
3229872cf891SStefano Zampini   PetscFunctionReturn(0);
3230872cf891SStefano Zampini }
3231872cf891SStefano Zampini 
3232284134d9SBarry Smith /*@
32333c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
3234284134d9SBarry Smith        process but not across processes.
3235284134d9SBarry Smith 
3236284134d9SBarry Smith    Input Parameters:
3237284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
3238e176bc59SStefano Zampini .     bs      - block size of the matrix
3239df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
3240e176bc59SStefano Zampini .     rmap    - local to global map for rows
3241e176bc59SStefano Zampini -     cmap    - local to global map for cols
3242284134d9SBarry Smith 
3243284134d9SBarry Smith    Output Parameter:
3244284134d9SBarry Smith .    A - the resulting matrix
3245284134d9SBarry Smith 
32468e6c10adSSatish Balay    Level: advanced
32478e6c10adSSatish Balay 
324895452b02SPatrick Sanan    Notes:
324995452b02SPatrick Sanan     See MATIS for more details.
32506fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
32516fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
32523c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
3253284134d9SBarry Smith 
3254284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
3255284134d9SBarry Smith @*/
3256e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
3257284134d9SBarry Smith {
3258284134d9SBarry Smith   PetscErrorCode ierr;
3259284134d9SBarry Smith 
3260284134d9SBarry Smith   PetscFunctionBegin;
32616fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
3262284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
3263284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
32646fdf41d1SStefano Zampini   if (bs > 0) {
3265284134d9SBarry Smith     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
32666fdf41d1SStefano Zampini   }
3267284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
3268e176bc59SStefano Zampini   if (rmap && cmap) {
3269e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
3270e176bc59SStefano Zampini   } else if (!rmap) {
3271e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
3272e176bc59SStefano Zampini   } else {
3273e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
3274e176bc59SStefano Zampini   }
3275284134d9SBarry Smith   PetscFunctionReturn(0);
3276284134d9SBarry Smith }
3277284134d9SBarry Smith 
3278b4319ba4SBarry Smith /*MC
3279f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
3280b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
3281b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
3282b4319ba4SBarry Smith    product is handled "implicitly".
3283b4319ba4SBarry Smith 
3284b4319ba4SBarry Smith    Operations Provided:
32856726f965SBarry Smith +  MatMult()
32862e74eeadSLisandro Dalcin .  MatMultAdd()
32872e74eeadSLisandro Dalcin .  MatMultTranspose()
32882e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
32896726f965SBarry Smith .  MatZeroEntries()
32906726f965SBarry Smith .  MatSetOption()
32912e74eeadSLisandro Dalcin .  MatZeroRows()
32922e74eeadSLisandro Dalcin .  MatSetValues()
329397563a80SStefano Zampini .  MatSetValuesBlocked()
32946726f965SBarry Smith .  MatSetValuesLocal()
329597563a80SStefano Zampini .  MatSetValuesBlockedLocal()
32962e74eeadSLisandro Dalcin .  MatScale()
32972e74eeadSLisandro Dalcin .  MatGetDiagonal()
32982b404112SStefano Zampini .  MatMissingDiagonal()
32992b404112SStefano Zampini .  MatDuplicate()
33002b404112SStefano Zampini .  MatCopy()
3301f26d0771SStefano Zampini .  MatAXPY()
33027dae84e0SHong Zhang .  MatCreateSubMatrix()
3303f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
3304d7f69cd0SStefano Zampini .  MatTranspose()
330575d48cdbSStefano Zampini .  MatPtAP() (with P of AIJ type)
33066726f965SBarry Smith -  MatSetLocalToGlobalMapping()
3307b4319ba4SBarry Smith 
3308b4319ba4SBarry Smith    Options Database Keys:
330975d48cdbSStefano Zampini + -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
331075d48cdbSStefano Zampini . -matis_fixempty - Fixes local matrices in case of empty local rows/columns.
331175d48cdbSStefano Zampini - -matis_storel2l - stores the local-to-local operators generated by the Galerkin process of MatPtAP().
3312b4319ba4SBarry Smith 
331395452b02SPatrick Sanan    Notes:
331495452b02SPatrick Sanan     Options prefix for the inner matrix are given by -is_mat_xxx
3315b4319ba4SBarry Smith 
3316b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
3317b4319ba4SBarry Smith 
3318b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
3319eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
3320b4319ba4SBarry Smith 
3321b4319ba4SBarry Smith   Level: advanced
3322b4319ba4SBarry Smith 
3323f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
3324b4319ba4SBarry Smith 
3325b4319ba4SBarry Smith M*/
3326b4319ba4SBarry Smith 
33278cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
3328b4319ba4SBarry Smith {
3329dfbe8321SBarry Smith   PetscErrorCode ierr;
3330b4319ba4SBarry Smith   Mat_IS         *b;
3331b4319ba4SBarry Smith 
3332b4319ba4SBarry Smith   PetscFunctionBegin;
3333b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
33348546b261SStefano Zampini   ierr    = PetscStrallocpy(MATAIJ,&b->lmattype);CHKERRQ(ierr);
3335b4319ba4SBarry Smith   A->data = (void*)b;
3336b4319ba4SBarry Smith 
3337e176bc59SStefano Zampini   /* matrix ops */
3338e176bc59SStefano Zampini   ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
3339b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
33402e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
33412e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
33422e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
3343b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
3344b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
33452e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
334698921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
3347b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
3348f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
33492e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
3350f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
3351b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
3352b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
3353b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
33546726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
33552e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
33562e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
33576726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
335869796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
335969796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
336045471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
3361ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
33626bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
33632b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
3364659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
33657dae84e0SHong Zhang   A->ops->createsubmatrix         = MatCreateSubMatrix_IS;
3366f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
33673fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
33683fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
3369d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
33707fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
3371ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
3372872cf891SStefano Zampini   A->ops->setfromoptions          = MatSetFromOptions_IS;
3373b4319ba4SBarry Smith 
3374b7ce53b6SStefano Zampini   /* special MATIS functions */
33758546b261SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMatType_C",MatISSetLocalMatType_IS);CHKERRQ(ierr);
3376bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
33773b3b1effSJed Brown   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS);CHKERRQ(ierr);
3378bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
3379487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
33802e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
3381cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",MatISSetUpSF_IS);CHKERRQ(ierr);
338275d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",MatISStoreL2L_IS);CHKERRQ(ierr);
3383f03112d0SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",MatISFixLocalEmpty_IS);CHKERRQ(ierr);
3384487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3385487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3386487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3387487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3388487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3389487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3390487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
339117667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
3392b4319ba4SBarry Smith   PetscFunctionReturn(0);
3393b4319ba4SBarry Smith }
3394