xref: /petsc/src/mat/impls/is/matis.c (revision 249c8a7109f3f02db1bdad39df014d76aeb045cb)
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);
16f26d0771SStefano Zampini 
1775d48cdbSStefano Zampini static PetscErrorCode MatISContainerDestroyPtAP_Private(void *ptr)
1875d48cdbSStefano Zampini {
1975d48cdbSStefano Zampini   MatISPtAP      ptap = (MatISPtAP)ptr;
2075d48cdbSStefano Zampini   PetscErrorCode ierr;
2175d48cdbSStefano Zampini 
2275d48cdbSStefano Zampini   PetscFunctionBegin;
2375d48cdbSStefano Zampini   ierr = MatDestroySubMatrices(ptap->ris1 ? 2 : 1,&ptap->lP);CHKERRQ(ierr);
2475d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->cis0);CHKERRQ(ierr);
2575d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->cis1);CHKERRQ(ierr);
2675d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->ris0);CHKERRQ(ierr);
2775d48cdbSStefano Zampini   ierr = ISDestroy(&ptap->ris1);CHKERRQ(ierr);
2875d48cdbSStefano Zampini   ierr = PetscFree(ptap);CHKERRQ(ierr);
2975d48cdbSStefano Zampini   PetscFunctionReturn(0);
3075d48cdbSStefano Zampini }
3175d48cdbSStefano Zampini 
3275d48cdbSStefano Zampini static PetscErrorCode MatPtAPNumeric_IS_XAIJ(Mat A, Mat P, Mat C)
3375d48cdbSStefano Zampini {
3475d48cdbSStefano Zampini   MatISPtAP      ptap;
3575d48cdbSStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
3675d48cdbSStefano Zampini   Mat            lA,lC;
3775d48cdbSStefano Zampini   MatReuse       reuse;
3875d48cdbSStefano Zampini   IS             ris[2],cis[2];
3975d48cdbSStefano Zampini   PetscContainer c;
4075d48cdbSStefano Zampini   PetscInt       n;
4175d48cdbSStefano Zampini   PetscErrorCode ierr;
4275d48cdbSStefano Zampini 
4375d48cdbSStefano Zampini   PetscFunctionBegin;
446afe12f5SStefano Zampini   ierr = PetscObjectQuery((PetscObject)C,"_MatIS_PtAP",(PetscObject*)&c);CHKERRQ(ierr);
4575d48cdbSStefano Zampini   if (!c) SETERRQ(PetscObjectComm((PetscObject)C),PETSC_ERR_PLIB,"Missing PtAP information");
4675d48cdbSStefano Zampini   ierr   = PetscContainerGetPointer(c,(void**)&ptap);CHKERRQ(ierr);
4775d48cdbSStefano Zampini   ris[0] = ptap->ris0;
4875d48cdbSStefano Zampini   ris[1] = ptap->ris1;
4975d48cdbSStefano Zampini   cis[0] = ptap->cis0;
5075d48cdbSStefano Zampini   cis[1] = ptap->cis1;
5175d48cdbSStefano Zampini   n      = ptap->ris1 ? 2 : 1;
5275d48cdbSStefano Zampini   reuse  = ptap->lP ? MAT_REUSE_MATRIX : MAT_INITIAL_MATRIX;
5375d48cdbSStefano Zampini   ierr   = MatCreateSubMatrices(P,n,ris,cis,reuse,&ptap->lP);CHKERRQ(ierr);
5475d48cdbSStefano Zampini 
5575d48cdbSStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
5675d48cdbSStefano Zampini   ierr = MatISGetLocalMat(C,&lC);CHKERRQ(ierr);
5775d48cdbSStefano Zampini   if (ptap->ris1) { /* unsymmetric A mapping */
5875d48cdbSStefano Zampini     Mat lPt;
5975d48cdbSStefano Zampini 
6075d48cdbSStefano Zampini     ierr = MatTranspose(ptap->lP[1],MAT_INITIAL_MATRIX,&lPt);CHKERRQ(ierr);
6175d48cdbSStefano Zampini     ierr = MatMatMatMult(lPt,lA,ptap->lP[0],reuse,ptap->fill,&lC);CHKERRQ(ierr);
6275d48cdbSStefano Zampini     if (matis->storel2l) {
6375d48cdbSStefano Zampini       ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",(PetscObject)lPt);CHKERRQ(ierr);
6475d48cdbSStefano Zampini     }
6575d48cdbSStefano Zampini     ierr = MatDestroy(&lPt);CHKERRQ(ierr);
6675d48cdbSStefano Zampini   } else {
6775d48cdbSStefano Zampini     ierr = MatPtAP(lA,ptap->lP[0],reuse,ptap->fill,&lC);CHKERRQ(ierr);
6875d48cdbSStefano Zampini     if (matis->storel2l) {
6975d48cdbSStefano Zampini      ierr = PetscObjectCompose((PetscObject)(C),"_MatIS_PtAP_l2l",(PetscObject)ptap->lP[0]);CHKERRQ(ierr);
7075d48cdbSStefano Zampini     }
7175d48cdbSStefano Zampini   }
7275d48cdbSStefano Zampini   if (reuse == MAT_INITIAL_MATRIX) {
7375d48cdbSStefano Zampini     ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
7475d48cdbSStefano Zampini     ierr = MatDestroy(&lC);CHKERRQ(ierr);
7575d48cdbSStefano Zampini   }
7675d48cdbSStefano Zampini   ierr = MatAssemblyBegin(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7775d48cdbSStefano Zampini   ierr = MatAssemblyEnd(C,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
7875d48cdbSStefano Zampini   PetscFunctionReturn(0);
7975d48cdbSStefano Zampini }
8075d48cdbSStefano Zampini 
8175d48cdbSStefano Zampini static PetscErrorCode MatGetNonzeroColumnsLocal_Private(Mat PT,IS *cis)
8275d48cdbSStefano Zampini {
8375d48cdbSStefano Zampini   Mat            Po,Pd;
8475d48cdbSStefano Zampini   IS             zd,zo;
8575d48cdbSStefano Zampini   const PetscInt *garray;
8675d48cdbSStefano Zampini   PetscInt       *aux,i,bs;
8775d48cdbSStefano Zampini   PetscInt       dc,stc,oc,ctd,cto;
8875d48cdbSStefano Zampini   PetscBool      ismpiaij,ismpibaij,isseqaij,isseqbaij;
8975d48cdbSStefano Zampini   MPI_Comm       comm;
9075d48cdbSStefano Zampini   PetscErrorCode ierr;
9175d48cdbSStefano Zampini 
9275d48cdbSStefano Zampini   PetscFunctionBegin;
9375d48cdbSStefano Zampini   PetscValidHeaderSpecific(PT,MAT_CLASSID,1);
9475d48cdbSStefano Zampini   PetscValidPointer(cis,2);
9575d48cdbSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)PT,&comm);CHKERRQ(ierr);
9675d48cdbSStefano Zampini   bs   = 1;
9775d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATMPIAIJ,&ismpiaij);CHKERRQ(ierr);
9875d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
9904637862SRichard Tran Mills   ierr = PetscObjectBaseTypeCompare((PetscObject)PT,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
10075d48cdbSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)PT,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
10175d48cdbSStefano Zampini   if (isseqaij || isseqbaij) {
10275d48cdbSStefano Zampini     Pd = PT;
10375d48cdbSStefano Zampini     Po = NULL;
10475d48cdbSStefano Zampini     garray = NULL;
10575d48cdbSStefano Zampini   } else if (ismpiaij) {
10675d48cdbSStefano Zampini     ierr = MatMPIAIJGetSeqAIJ(PT,&Pd,&Po,&garray);CHKERRQ(ierr);
10775d48cdbSStefano Zampini   } else if (ismpibaij) {
10875d48cdbSStefano Zampini     ierr = MatMPIBAIJGetSeqBAIJ(PT,&Pd,&Po,&garray);CHKERRQ(ierr);
10975d48cdbSStefano Zampini     ierr = MatGetBlockSize(PT,&bs);CHKERRQ(ierr);
11075d48cdbSStefano Zampini   } else SETERRQ1(comm,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(PT))->type_name);
11175d48cdbSStefano Zampini 
11275d48cdbSStefano Zampini   /* identify any null columns in Pd or Po */
11322f7620eSStefano Zampini   /* We use a tolerance comparison since it may happen that, with geometric multigrid,
11422f7620eSStefano Zampini      some of the columns are not really zero, but very close to */
11575d48cdbSStefano Zampini   zo = zd = NULL;
11675d48cdbSStefano Zampini   if (Po) {
11722f7620eSStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(Po,PETSC_TRUE,PETSC_SMALL,&zo);CHKERRQ(ierr);
11875d48cdbSStefano Zampini   }
11922f7620eSStefano Zampini   ierr = MatFindNonzeroRowsOrCols_Basic(Pd,PETSC_TRUE,PETSC_SMALL,&zd);CHKERRQ(ierr);
12075d48cdbSStefano Zampini 
12175d48cdbSStefano Zampini   ierr = MatGetLocalSize(PT,NULL,&dc);CHKERRQ(ierr);
12275d48cdbSStefano Zampini   ierr = MatGetOwnershipRangeColumn(PT,&stc,NULL);CHKERRQ(ierr);
12375d48cdbSStefano Zampini   if (Po) { ierr = MatGetLocalSize(Po,NULL,&oc);CHKERRQ(ierr); }
12475d48cdbSStefano Zampini   else oc = 0;
12575d48cdbSStefano Zampini   ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
12675d48cdbSStefano Zampini   if (zd) {
12775d48cdbSStefano Zampini     const PetscInt *idxs;
12875d48cdbSStefano Zampini     PetscInt       nz;
12975d48cdbSStefano Zampini 
13075d48cdbSStefano Zampini     /* this will throw an error if bs is not valid */
13175d48cdbSStefano Zampini     ierr = ISSetBlockSize(zd,bs);CHKERRQ(ierr);
13275d48cdbSStefano Zampini     ierr = ISGetLocalSize(zd,&nz);CHKERRQ(ierr);
13375d48cdbSStefano Zampini     ierr = ISGetIndices(zd,&idxs);CHKERRQ(ierr);
13475d48cdbSStefano Zampini     ctd  = nz/bs;
13575d48cdbSStefano Zampini     for (i=0; i<ctd; i++) aux[i] = (idxs[bs*i]+stc)/bs;
13675d48cdbSStefano Zampini     ierr = ISRestoreIndices(zd,&idxs);CHKERRQ(ierr);
13775d48cdbSStefano Zampini   } else {
13875d48cdbSStefano Zampini     ctd = dc/bs;
13975d48cdbSStefano Zampini     for (i=0; i<ctd; i++) aux[i] = i+stc/bs;
14075d48cdbSStefano Zampini   }
14175d48cdbSStefano Zampini   if (zo) {
14275d48cdbSStefano Zampini     const PetscInt *idxs;
14375d48cdbSStefano Zampini     PetscInt       nz;
14475d48cdbSStefano Zampini 
14575d48cdbSStefano Zampini     /* this will throw an error if bs is not valid */
14675d48cdbSStefano Zampini     ierr = ISSetBlockSize(zo,bs);CHKERRQ(ierr);
14775d48cdbSStefano Zampini     ierr = ISGetLocalSize(zo,&nz);CHKERRQ(ierr);
14875d48cdbSStefano Zampini     ierr = ISGetIndices(zo,&idxs);CHKERRQ(ierr);
14975d48cdbSStefano Zampini     cto  = nz/bs;
15075d48cdbSStefano Zampini     for (i=0; i<cto; i++) aux[i+ctd] = garray[idxs[bs*i]/bs];
15175d48cdbSStefano Zampini     ierr = ISRestoreIndices(zo,&idxs);CHKERRQ(ierr);
15275d48cdbSStefano Zampini   } else {
15375d48cdbSStefano Zampini     cto = oc/bs;
15475d48cdbSStefano Zampini     for (i=0; i<cto; i++) aux[i+ctd] = garray[i];
15575d48cdbSStefano Zampini   }
15675d48cdbSStefano Zampini   ierr = ISCreateBlock(comm,bs,ctd+cto,aux,PETSC_OWN_POINTER,cis);CHKERRQ(ierr);
15775d48cdbSStefano Zampini   ierr = ISDestroy(&zd);CHKERRQ(ierr);
15875d48cdbSStefano Zampini   ierr = ISDestroy(&zo);CHKERRQ(ierr);
15975d48cdbSStefano Zampini   PetscFunctionReturn(0);
16075d48cdbSStefano Zampini }
16175d48cdbSStefano Zampini 
16275d48cdbSStefano Zampini static PetscErrorCode MatPtAPSymbolic_IS_XAIJ(Mat A,Mat P,PetscReal fill,Mat *C)
16375d48cdbSStefano Zampini {
16475d48cdbSStefano Zampini   Mat                    PT;
16575d48cdbSStefano Zampini   MatISPtAP              ptap;
16675d48cdbSStefano Zampini   ISLocalToGlobalMapping Crl2g,Ccl2g,rl2g,cl2g;
16775d48cdbSStefano Zampini   PetscContainer         c;
16875d48cdbSStefano Zampini   const PetscInt         *garray;
16975d48cdbSStefano Zampini   PetscInt               ibs,N,dc;
17075d48cdbSStefano Zampini   MPI_Comm               comm;
17175d48cdbSStefano Zampini   PetscErrorCode         ierr;
17275d48cdbSStefano Zampini 
17375d48cdbSStefano Zampini   PetscFunctionBegin;
17475d48cdbSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
17575d48cdbSStefano Zampini   ierr = MatCreate(comm,C);CHKERRQ(ierr);
17675d48cdbSStefano Zampini   ierr = MatSetType(*C,MATIS);CHKERRQ(ierr);
17775d48cdbSStefano Zampini   ierr = MatGetSize(P,NULL,&N);CHKERRQ(ierr);
17875d48cdbSStefano Zampini   ierr = MatGetLocalSize(P,NULL,&dc);CHKERRQ(ierr);
17975d48cdbSStefano Zampini   ierr = MatSetSizes(*C,dc,dc,N,N);CHKERRQ(ierr);
18075d48cdbSStefano Zampini /* Not sure about this
18175d48cdbSStefano Zampini   ierr = MatGetBlockSizes(P,NULL,&ibs);CHKERRQ(ierr);
18275d48cdbSStefano Zampini   ierr = MatSetBlockSize(*C,ibs);CHKERRQ(ierr);
18375d48cdbSStefano Zampini */
18475d48cdbSStefano Zampini 
18575d48cdbSStefano Zampini   ierr = PetscNew(&ptap);CHKERRQ(ierr);
18675d48cdbSStefano Zampini   ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
18775d48cdbSStefano Zampini   ierr = PetscContainerSetPointer(c,ptap);CHKERRQ(ierr);
18875d48cdbSStefano Zampini   ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyPtAP_Private);CHKERRQ(ierr);
18975d48cdbSStefano Zampini   ierr = PetscObjectCompose((PetscObject)(*C),"_MatIS_PtAP",(PetscObject)c);CHKERRQ(ierr);
19075d48cdbSStefano Zampini   ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
19175d48cdbSStefano Zampini   ptap->fill = fill;
19275d48cdbSStefano Zampini 
19375d48cdbSStefano Zampini   ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
19475d48cdbSStefano Zampini 
19575d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cl2g,&ibs);CHKERRQ(ierr);
19675d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cl2g,&N);CHKERRQ(ierr);
19775d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockIndices(cl2g,&garray);CHKERRQ(ierr);
19875d48cdbSStefano Zampini   ierr = ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris0);CHKERRQ(ierr);
19975d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&garray);CHKERRQ(ierr);
20075d48cdbSStefano Zampini 
20175d48cdbSStefano Zampini   ierr = MatCreateSubMatrix(P,ptap->ris0,NULL,MAT_INITIAL_MATRIX,&PT);CHKERRQ(ierr);
20275d48cdbSStefano Zampini   ierr = MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis0);CHKERRQ(ierr);
20375d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(ptap->cis0,&Ccl2g);CHKERRQ(ierr);
20475d48cdbSStefano Zampini   ierr = MatDestroy(&PT);CHKERRQ(ierr);
20575d48cdbSStefano Zampini 
20675d48cdbSStefano Zampini   Crl2g = NULL;
20775d48cdbSStefano Zampini   if (rl2g != cl2g) { /* unsymmetric A mapping */
20875d48cdbSStefano Zampini     PetscBool same,lsame = PETSC_FALSE;
20975d48cdbSStefano Zampini     PetscInt  N1,ibs1;
21075d48cdbSStefano Zampini 
21175d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(rl2g,&N1);CHKERRQ(ierr);
21275d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(rl2g,&ibs1);CHKERRQ(ierr);
21375d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(rl2g,&garray);CHKERRQ(ierr);
21475d48cdbSStefano Zampini     ierr = ISCreateBlock(comm,ibs,N/ibs,garray,PETSC_COPY_VALUES,&ptap->ris1);CHKERRQ(ierr);
21575d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&garray);CHKERRQ(ierr);
21675d48cdbSStefano Zampini     if (ibs1 == ibs && N1 == N) { /* check if the l2gmaps are the same */
21775d48cdbSStefano Zampini       const PetscInt *i1,*i2;
21875d48cdbSStefano Zampini 
21975d48cdbSStefano Zampini       ierr = ISBlockGetIndices(ptap->ris0,&i1);CHKERRQ(ierr);
22075d48cdbSStefano Zampini       ierr = ISBlockGetIndices(ptap->ris1,&i2);CHKERRQ(ierr);
22175d48cdbSStefano Zampini       ierr = PetscMemcmp(i1,i2,N*sizeof(*i1),&lsame);CHKERRQ(ierr);
22275d48cdbSStefano Zampini     }
22375d48cdbSStefano Zampini     ierr = MPIU_Allreduce(&lsame,&same,1,MPIU_BOOL,MPI_LAND,comm);CHKERRQ(ierr);
22475d48cdbSStefano Zampini     if (same) {
22575d48cdbSStefano Zampini       ierr = ISDestroy(&ptap->ris1);CHKERRQ(ierr);
22675d48cdbSStefano Zampini     } else {
22775d48cdbSStefano Zampini       ierr = MatCreateSubMatrix(P,ptap->ris1,NULL,MAT_INITIAL_MATRIX,&PT);CHKERRQ(ierr);
22875d48cdbSStefano Zampini       ierr = MatGetNonzeroColumnsLocal_Private(PT,&ptap->cis1);CHKERRQ(ierr);
22975d48cdbSStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(ptap->cis1,&Crl2g);CHKERRQ(ierr);
23075d48cdbSStefano Zampini       ierr = MatDestroy(&PT);CHKERRQ(ierr);
23175d48cdbSStefano Zampini     }
23275d48cdbSStefano Zampini   }
23375d48cdbSStefano Zampini /* Not sure about this
23475d48cdbSStefano Zampini   if (!Crl2g) {
23575d48cdbSStefano Zampini     ierr = MatGetBlockSize(*C,&ibs);CHKERRQ(ierr);
23675d48cdbSStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(Ccl2g,ibs);CHKERRQ(ierr);
23775d48cdbSStefano Zampini   }
23875d48cdbSStefano Zampini */
23975d48cdbSStefano Zampini   ierr = MatSetLocalToGlobalMapping(*C,Crl2g ? Crl2g : Ccl2g,Ccl2g);CHKERRQ(ierr);
24075d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&Crl2g);CHKERRQ(ierr);
24175d48cdbSStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&Ccl2g);CHKERRQ(ierr);
24275d48cdbSStefano Zampini 
24375d48cdbSStefano Zampini   (*C)->ops->ptapnumeric = MatPtAPNumeric_IS_XAIJ;
24475d48cdbSStefano Zampini   PetscFunctionReturn(0);
24575d48cdbSStefano Zampini }
24675d48cdbSStefano Zampini 
24775d48cdbSStefano Zampini PETSC_INTERN PetscErrorCode MatPtAP_IS_XAIJ(Mat A,Mat P,MatReuse scall,PetscReal fill,Mat *C)
24875d48cdbSStefano Zampini {
24975d48cdbSStefano Zampini   PetscErrorCode ierr;
25075d48cdbSStefano Zampini 
25175d48cdbSStefano Zampini   PetscFunctionBegin;
25275d48cdbSStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
25375d48cdbSStefano Zampini     ierr = PetscLogEventBegin(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
25475d48cdbSStefano Zampini     ierr = MatPtAPSymbolic_IS_XAIJ(A,P,fill,C);CHKERRQ(ierr);
25575d48cdbSStefano Zampini     ierr = PetscLogEventEnd(MAT_PtAPSymbolic,A,P,0,0);CHKERRQ(ierr);
25675d48cdbSStefano Zampini   }
25775d48cdbSStefano Zampini   ierr = PetscLogEventBegin(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
25875d48cdbSStefano Zampini   ierr = ((*C)->ops->ptapnumeric)(A,P,*C);CHKERRQ(ierr);
25975d48cdbSStefano Zampini   ierr = PetscLogEventEnd(MAT_PtAPNumeric,A,P,0,0);CHKERRQ(ierr);
26075d48cdbSStefano Zampini   PetscFunctionReturn(0);
26175d48cdbSStefano Zampini }
26275d48cdbSStefano Zampini 
2635b003df0Sstefano_zampini static PetscErrorCode MatISContainerDestroyFields_Private(void *ptr)
2645b003df0Sstefano_zampini {
2655b003df0Sstefano_zampini   MatISLocalFields lf = (MatISLocalFields)ptr;
2665b003df0Sstefano_zampini   PetscInt         i;
2675b003df0Sstefano_zampini   PetscErrorCode   ierr;
2685b003df0Sstefano_zampini 
269ab4d48faSStefano Zampini   PetscFunctionBegin;
2705b003df0Sstefano_zampini   for (i=0;i<lf->nr;i++) {
2715b003df0Sstefano_zampini     ierr = ISDestroy(&lf->rf[i]);CHKERRQ(ierr);
2725b003df0Sstefano_zampini   }
2735b003df0Sstefano_zampini   for (i=0;i<lf->nc;i++) {
2745b003df0Sstefano_zampini     ierr = ISDestroy(&lf->cf[i]);CHKERRQ(ierr);
2755b003df0Sstefano_zampini   }
2765b003df0Sstefano_zampini   ierr = PetscFree2(lf->rf,lf->cf);CHKERRQ(ierr);
2775b003df0Sstefano_zampini   ierr = PetscFree(lf);CHKERRQ(ierr);
2785b003df0Sstefano_zampini   PetscFunctionReturn(0);
2795b003df0Sstefano_zampini }
280a72627d2SStefano Zampini 
281c9225affSStefano Zampini static PetscErrorCode MatConvert_SeqXAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
2826989cf23SStefano Zampini {
283c9225affSStefano Zampini   Mat            B,lB;
284c9225affSStefano Zampini   PetscErrorCode ierr;
285c9225affSStefano Zampini 
286c9225affSStefano Zampini   PetscFunctionBegin;
287c9225affSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
288c9225affSStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g;
289c9225affSStefano Zampini     PetscInt               bs;
290c9225affSStefano Zampini     IS                     is;
291c9225affSStefano Zampini 
292c9225affSStefano Zampini     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
293c9225affSStefano Zampini     ierr = ISCreateStride(PetscObjectComm((PetscObject)A),A->rmap->n/bs,0,1,&is);CHKERRQ(ierr);
294c9225affSStefano Zampini     if (bs > 1) {
295c9225affSStefano Zampini       IS       is2;
296c9225affSStefano Zampini       PetscInt i,*aux;
297c9225affSStefano Zampini 
298c9225affSStefano Zampini       ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
299c9225affSStefano Zampini       ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
300c9225affSStefano Zampini       ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
301c9225affSStefano Zampini       ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
302c9225affSStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
303c9225affSStefano Zampini       is   = is2;
304c9225affSStefano Zampini     }
305c9225affSStefano Zampini     ierr = ISSetIdentity(is);CHKERRQ(ierr);
306c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
307c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
308c9225affSStefano Zampini     ierr = ISCreateStride(PetscObjectComm((PetscObject)A),A->cmap->n/bs,0,1,&is);CHKERRQ(ierr);
309c9225affSStefano Zampini     if (bs > 1) {
310c9225affSStefano Zampini       IS       is2;
311c9225affSStefano Zampini       PetscInt i,*aux;
312c9225affSStefano Zampini 
313c9225affSStefano Zampini       ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
314c9225affSStefano Zampini       ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
315c9225affSStefano Zampini       ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
316c9225affSStefano Zampini       ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
317c9225affSStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
318c9225affSStefano Zampini       is   = is2;
319c9225affSStefano Zampini     }
320c9225affSStefano Zampini     ierr = ISSetIdentity(is);CHKERRQ(ierr);
321c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
322c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
323c9225affSStefano Zampini     ierr = MatCreateIS(PetscObjectComm((PetscObject)A),bs,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N,rl2g,cl2g,&B);CHKERRQ(ierr);
324c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
325c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
326c9225affSStefano Zampini     ierr = MatDuplicate(A,MAT_COPY_VALUES,&lB);CHKERRQ(ierr);
327c9225affSStefano Zampini     if (reuse == MAT_INITIAL_MATRIX) *newmat = B;
328c9225affSStefano Zampini   } else {
329c9225affSStefano Zampini     B    = *newmat;
330c9225affSStefano Zampini     ierr = PetscObjectReference((PetscObject)A);CHKERRQ(ierr);
331c9225affSStefano Zampini     lB   = A;
332c9225affSStefano Zampini   }
333c9225affSStefano Zampini   ierr = MatISSetLocalMat(B,lB);CHKERRQ(ierr);
334c9225affSStefano Zampini   ierr = MatDestroy(&lB);CHKERRQ(ierr);
335c9225affSStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
336c9225affSStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
337c9225affSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
338c9225affSStefano Zampini     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
339c9225affSStefano Zampini   }
340c9225affSStefano Zampini   PetscFunctionReturn(0);
341c9225affSStefano Zampini }
342c9225affSStefano Zampini 
343c9225affSStefano Zampini static PetscErrorCode MatISScaleDisassembling_Private(Mat A)
344c9225affSStefano Zampini {
345c9225affSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(A->data);
346c9225affSStefano Zampini   PetscScalar    *aa;
347c9225affSStefano Zampini   const PetscInt *ii,*jj;
348c9225affSStefano Zampini   PetscInt       i,n,m;
349fabe8965SStefano Zampini   PetscInt       *ecount,**eneighs;
350c9225affSStefano Zampini   PetscBool      flg;
351c9225affSStefano Zampini   PetscErrorCode ierr;
352c9225affSStefano Zampini 
353c9225affSStefano Zampini   PetscFunctionBegin;
354c9225affSStefano Zampini   ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg);CHKERRQ(ierr);
355c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
356fabe8965SStefano Zampini   ierr = ISLocalToGlobalMappingGetNodeInfo(A->rmap->mapping,&n,&ecount,&eneighs);CHKERRQ(ierr);
357c9225affSStefano Zampini   if (m != n) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected %D != %D",m,n);
358c9225affSStefano Zampini   ierr = MatSeqAIJGetArray(matis->A,&aa);CHKERRQ(ierr);
359c9225affSStefano Zampini   for (i=0;i<n;i++) {
360fabe8965SStefano Zampini     if (ecount[i] > 1) {
361c9225affSStefano Zampini       PetscInt j;
362c9225affSStefano Zampini 
363c9225affSStefano Zampini       for (j=ii[i];j<ii[i+1];j++) {
364c9225affSStefano Zampini         PetscInt    i2 = jj[j],p,p2;
365fabe8965SStefano Zampini         PetscReal   scal = 0.0;
366c9225affSStefano Zampini 
367c9225affSStefano Zampini         for (p=0;p<ecount[i];p++) {
368c9225affSStefano Zampini           for (p2=0;p2<ecount[i2];p2++) {
369c9225affSStefano Zampini             if (eneighs[i][p] == eneighs[i2][p2]) { scal += 1.0; break; }
370c9225affSStefano Zampini           }
371c9225affSStefano Zampini         }
372fabe8965SStefano Zampini         if (scal) aa[j] /= scal;
373c9225affSStefano Zampini       }
374c9225affSStefano Zampini     }
375c9225affSStefano Zampini   }
376fabe8965SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreNodeInfo(A->rmap->mapping,&n,&ecount,&eneighs);CHKERRQ(ierr);
377c9225affSStefano Zampini   ierr = MatSeqAIJRestoreArray(matis->A,&aa);CHKERRQ(ierr);
378c9225affSStefano Zampini   ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&m,&ii,&jj,&flg);CHKERRQ(ierr);
379c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
380c9225affSStefano Zampini   PetscFunctionReturn(0);
381c9225affSStefano Zampini }
382c9225affSStefano Zampini 
383fabe8965SStefano Zampini typedef enum {MAT_IS_DISASSEMBLE_L2G_NATURAL,MAT_IS_DISASSEMBLE_L2G_MAT, MAT_IS_DISASSEMBLE_L2G_ND} MatISDisassemblel2gType;
384fabe8965SStefano Zampini 
385c9225affSStefano Zampini static PetscErrorCode MatMPIXAIJComputeLocalToGlobalMapping_Private(Mat A, ISLocalToGlobalMapping *l2g)
386c9225affSStefano Zampini {
387fabe8965SStefano Zampini   Mat                     Ad,Ao;
388fabe8965SStefano Zampini   IS                      is,ndmap,ndsub;
389c9225affSStefano Zampini   MPI_Comm                comm;
390fabe8965SStefano Zampini   const PetscInt          *garray,*ndmapi;
391fabe8965SStefano Zampini   PetscInt                bs,i,cnt,nl,*ncount,*ndmapc;
392fabe8965SStefano Zampini   PetscBool               ismpiaij,ismpibaij;
393fabe8965SStefano Zampini   const char *const       MatISDisassemblel2gTypes[] = {"NATURAL","MAT","ND","MatISDisassemblel2gType","MAT_IS_DISASSEMBLE_L2G_",0};
394fabe8965SStefano Zampini   MatISDisassemblel2gType mode = MAT_IS_DISASSEMBLE_L2G_NATURAL;
395fabe8965SStefano Zampini   MatPartitioning         part;
396fabe8965SStefano Zampini   PetscSF                 sf;
397c9225affSStefano Zampini   PetscErrorCode          ierr;
398c9225affSStefano Zampini 
399c9225affSStefano Zampini   PetscFunctionBegin;
400fabe8965SStefano Zampini   ierr = PetscOptionsBegin(PetscObjectComm((PetscObject)A),((PetscObject)A)->prefix,"MatIS l2g disassembling options","Mat");CHKERRQ(ierr);
401fabe8965SStefano 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);
402fabe8965SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
403fabe8965SStefano Zampini   if (mode == MAT_IS_DISASSEMBLE_L2G_MAT) {
404c9225affSStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,l2g,NULL);CHKERRQ(ierr);
405c9225affSStefano Zampini     PetscFunctionReturn(0);
406c9225affSStefano Zampini   }
407c9225affSStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
408c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij);CHKERRQ(ierr);
409c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
410c9225affSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
411fabe8965SStefano Zampini   switch (mode) {
412fabe8965SStefano Zampini   case MAT_IS_DISASSEMBLE_L2G_ND:
413fabe8965SStefano Zampini     ierr = MatPartitioningCreate(comm,&part);CHKERRQ(ierr);
414fabe8965SStefano Zampini     ierr = MatPartitioningSetAdjacency(part,A);CHKERRQ(ierr);
415fabe8965SStefano Zampini     ierr = PetscObjectSetOptionsPrefix((PetscObject)part,((PetscObject)A)->prefix);CHKERRQ(ierr);
416fabe8965SStefano Zampini     ierr = MatPartitioningSetFromOptions(part);CHKERRQ(ierr);
417fabe8965SStefano Zampini     ierr = MatPartitioningApplyND(part,&ndmap);CHKERRQ(ierr);
418fabe8965SStefano Zampini     ierr = MatPartitioningDestroy(&part);CHKERRQ(ierr);
419fabe8965SStefano Zampini     ierr = ISBuildTwoSided(ndmap,NULL,&ndsub);CHKERRQ(ierr);
420fabe8965SStefano Zampini     ierr = MatMPIAIJSetUseScalableIncreaseOverlap(A,PETSC_TRUE);CHKERRQ(ierr);
421fabe8965SStefano Zampini     ierr = MatIncreaseOverlap(A,1,&ndsub,1);CHKERRQ(ierr);
422fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(ndsub,l2g);CHKERRQ(ierr);
423fabe8965SStefano Zampini 
424fabe8965SStefano Zampini     /* it may happen that a separator node is not properly shared */
425fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingGetNodeInfo(*l2g,&nl,&ncount,NULL);CHKERRQ(ierr);
426fabe8965SStefano Zampini     ierr = PetscSFCreate(comm,&sf);CHKERRQ(ierr);
427fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(*l2g,&garray);CHKERRQ(ierr);
428fabe8965SStefano Zampini     ierr = PetscSFSetGraphLayout(sf,A->rmap,nl,NULL,PETSC_OWN_POINTER,garray);CHKERRQ(ierr);
429fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(*l2g,&garray);CHKERRQ(ierr);
430fabe8965SStefano Zampini     ierr = PetscCalloc1(A->rmap->n,&ndmapc);CHKERRQ(ierr);
431fabe8965SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,ncount,ndmapc,MPIU_REPLACE);CHKERRQ(ierr);
432fabe8965SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,ncount,ndmapc,MPIU_REPLACE);CHKERRQ(ierr);
433fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreNodeInfo(*l2g,NULL,&ncount,NULL);CHKERRQ(ierr);
434fabe8965SStefano Zampini     ierr = ISGetIndices(ndmap,&ndmapi);CHKERRQ(ierr);
435fabe8965SStefano Zampini     for (i = 0, cnt = 0; i < A->rmap->n; i++)
436fabe8965SStefano Zampini       if (ndmapi[i] < 0 && ndmapc[i] < 2)
437fabe8965SStefano Zampini         cnt++;
438fabe8965SStefano Zampini 
439fabe8965SStefano Zampini     ierr = MPIU_Allreduce(&cnt,&i,1,MPIU_INT,MPI_MAX,comm);CHKERRQ(ierr);
440fabe8965SStefano Zampini     if (i) { /* we detected isolated separator nodes */
441fabe8965SStefano Zampini       Mat                    A2,A3;
442fabe8965SStefano Zampini       IS                     *workis,is2;
443fabe8965SStefano Zampini       PetscScalar            *vals;
444fabe8965SStefano Zampini       PetscInt               gcnt = i,*dnz,*onz,j,*lndmapi;
445fabe8965SStefano Zampini       ISLocalToGlobalMapping ll2g;
446fabe8965SStefano Zampini       PetscBool              flg;
447fabe8965SStefano Zampini       const PetscInt         *ii,*jj;
448fabe8965SStefano Zampini 
449fabe8965SStefano Zampini       /* communicate global id of separators */
450fabe8965SStefano Zampini       ierr = MatPreallocateInitialize(comm,A->rmap->n,A->cmap->n,dnz,onz);CHKERRQ(ierr);
451fabe8965SStefano Zampini       for (i = 0, cnt = 0; i < A->rmap->n; i++)
452fabe8965SStefano Zampini         dnz[i] = ndmapi[i] < 0 ? i + A->rmap->rstart : -1;
453fabe8965SStefano Zampini 
454fabe8965SStefano Zampini       ierr = PetscMalloc1(nl,&lndmapi);CHKERRQ(ierr);
455fabe8965SStefano Zampini       ierr = PetscSFBcastBegin(sf,MPIU_INT,dnz,lndmapi);CHKERRQ(ierr);
456fabe8965SStefano Zampini 
457fabe8965SStefano Zampini       /* compute adjacency of isolated separators node */
458fabe8965SStefano Zampini       ierr = PetscMalloc1(gcnt,&workis);CHKERRQ(ierr);
459fabe8965SStefano Zampini       for (i = 0, cnt = 0; i < A->rmap->n; i++) {
460fabe8965SStefano Zampini         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
461fabe8965SStefano Zampini           ierr = ISCreateStride(comm,1,i+A->rmap->rstart,1,&workis[cnt++]);CHKERRQ(ierr);
462fabe8965SStefano Zampini         }
463fabe8965SStefano Zampini       }
464fabe8965SStefano Zampini       for (i = cnt; i < gcnt; i++) {
465fabe8965SStefano Zampini         ierr = ISCreateStride(comm,0,0,1,&workis[i]);CHKERRQ(ierr);
466fabe8965SStefano Zampini       }
467fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
468fabe8965SStefano Zampini         ierr = PetscObjectSetName((PetscObject)workis[i],"ISOLATED");CHKERRQ(ierr);
469fabe8965SStefano Zampini         ierr = ISViewFromOptions(workis[i],NULL,"-view_isolated_separators");CHKERRQ(ierr);
470fabe8965SStefano Zampini       }
471fabe8965SStefano Zampini 
472fabe8965SStefano Zampini       /* no communications since all the ISes correspond to locally owned rows */
473fabe8965SStefano Zampini       ierr = MatIncreaseOverlap(A,gcnt,workis,1);CHKERRQ(ierr);
474fabe8965SStefano Zampini 
475fabe8965SStefano Zampini       /* end communicate global id of separators */
476fabe8965SStefano Zampini       ierr = PetscSFBcastEnd(sf,MPIU_INT,dnz,lndmapi);CHKERRQ(ierr);
477fabe8965SStefano Zampini 
478fabe8965SStefano Zampini       /* communicate new layers : create a matrix and transpose it */
479fabe8965SStefano Zampini       ierr = PetscMemzero(dnz,A->rmap->n*sizeof(*dnz));CHKERRQ(ierr);
480fabe8965SStefano Zampini       ierr = PetscMemzero(onz,A->rmap->n*sizeof(*onz));CHKERRQ(ierr);
481fabe8965SStefano Zampini       for (i = 0, j = 0; i < A->rmap->n; i++) {
482fabe8965SStefano Zampini         if (ndmapi[i] < 0 && ndmapc[i] < 2) {
483fabe8965SStefano Zampini           const PetscInt* idxs;
484fabe8965SStefano Zampini           PetscInt        s;
485fabe8965SStefano Zampini 
486fabe8965SStefano Zampini           ierr = ISGetLocalSize(workis[j],&s);CHKERRQ(ierr);
487fabe8965SStefano Zampini           ierr = ISGetIndices(workis[j],&idxs);CHKERRQ(ierr);
488fabe8965SStefano Zampini           ierr = MatPreallocateSet(i+A->rmap->rstart,s,idxs,dnz,onz);CHKERRQ(ierr);
489fabe8965SStefano Zampini           j++;
490fabe8965SStefano Zampini         }
491fabe8965SStefano Zampini       }
492fabe8965SStefano Zampini       if (j != cnt) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %D != %D",j,cnt);
493fabe8965SStefano Zampini 
494fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
495fabe8965SStefano Zampini         ierr = PetscObjectSetName((PetscObject)workis[i],"EXTENDED");CHKERRQ(ierr);
496fabe8965SStefano Zampini         ierr = ISViewFromOptions(workis[i],NULL,"-view_isolated_separators");CHKERRQ(ierr);
497fabe8965SStefano Zampini       }
498fabe8965SStefano Zampini 
499fabe8965SStefano Zampini       for (i = 0, j = 0; i < A->rmap->n; i++) j = PetscMax(j,dnz[i]+onz[i]);
500fabe8965SStefano Zampini       ierr = PetscMalloc1(j,&vals);CHKERRQ(ierr);
501fabe8965SStefano Zampini       for (i = 0; i < j; i++) vals[i] = 1.0;
502fabe8965SStefano Zampini 
503fabe8965SStefano Zampini       ierr = MatCreate(comm,&A2);CHKERRQ(ierr);
504fabe8965SStefano Zampini       ierr = MatSetType(A2,MATMPIAIJ);CHKERRQ(ierr);
505fabe8965SStefano Zampini       ierr = MatSetSizes(A2,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
506fabe8965SStefano Zampini       ierr = MatMPIAIJSetPreallocation(A2,0,dnz,0,onz);CHKERRQ(ierr);
507fabe8965SStefano Zampini       ierr = MatSetOption(A2,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE);CHKERRQ(ierr);
508fabe8965SStefano Zampini       for (i = 0, j = 0; i < A2->rmap->n; i++) {
509fabe8965SStefano Zampini         PetscInt        row = i+A2->rmap->rstart,s = dnz[i] + onz[i];
510fabe8965SStefano Zampini         const PetscInt* idxs;
511fabe8965SStefano Zampini 
512fabe8965SStefano Zampini         if (s) {
513fabe8965SStefano Zampini           ierr = ISGetIndices(workis[j],&idxs);CHKERRQ(ierr);
514fabe8965SStefano Zampini           ierr = MatSetValues(A2,1,&row,s,idxs,vals,INSERT_VALUES);CHKERRQ(ierr);
515fabe8965SStefano Zampini           ierr = ISRestoreIndices(workis[j],&idxs);CHKERRQ(ierr);
516fabe8965SStefano Zampini           j++;
517fabe8965SStefano Zampini         }
518fabe8965SStefano Zampini       }
519fabe8965SStefano Zampini       if (j != cnt) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected local count %D != %D",j,cnt);
520fabe8965SStefano Zampini       ierr = PetscFree(vals);CHKERRQ(ierr);
521fabe8965SStefano Zampini       ierr = MatAssemblyBegin(A2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
522fabe8965SStefano Zampini       ierr = MatAssemblyEnd(A2,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
523fabe8965SStefano Zampini       ierr = MatTranspose(A2,MAT_INPLACE_MATRIX,&A2);CHKERRQ(ierr);
524fabe8965SStefano Zampini 
525fabe8965SStefano Zampini       /* extract submatrix corresponding to the coupling "owned separators" x "isolated separators" */
526fabe8965SStefano Zampini       for (i = 0, j = 0; i < nl; i++)
527fabe8965SStefano Zampini         if (lndmapi[i] >= 0) lndmapi[j++] = lndmapi[i];
528fabe8965SStefano Zampini       ierr = ISCreateGeneral(comm,j,lndmapi,PETSC_USE_POINTER,&is);CHKERRQ(ierr);
529fabe8965SStefano Zampini       ierr = MatMPIAIJGetLocalMatCondensed(A2,MAT_INITIAL_MATRIX,&is,NULL,&A3);CHKERRQ(ierr);
530fabe8965SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
531fabe8965SStefano Zampini       ierr = MatDestroy(&A2);CHKERRQ(ierr);
532fabe8965SStefano Zampini 
533fabe8965SStefano Zampini       /* extend local to global map to include connected isolated separators */
534fabe8965SStefano Zampini       ierr = PetscObjectQuery((PetscObject)A3,"_petsc_GetLocalMatCondensed_iscol",(PetscObject*)&is);CHKERRQ(ierr);
535fabe8965SStefano Zampini       if (!is) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Missing column map");
536fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&ll2g);CHKERRQ(ierr);
537fabe8965SStefano Zampini       ierr = MatGetRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg);CHKERRQ(ierr);
538fabe8965SStefano Zampini       if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
539fabe8965SStefano Zampini       ierr = ISCreateGeneral(PETSC_COMM_SELF,ii[i],jj,PETSC_COPY_VALUES,&is);CHKERRQ(ierr);
540fabe8965SStefano Zampini       ierr = MatRestoreRowIJ(A3,0,PETSC_FALSE,PETSC_FALSE,&i,&ii,&jj,&flg);CHKERRQ(ierr);
541fabe8965SStefano Zampini       if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
542fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(ll2g,is,&is2);CHKERRQ(ierr);
543fabe8965SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
544fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&ll2g);CHKERRQ(ierr);
545fabe8965SStefano Zampini 
546fabe8965SStefano Zampini       /* add new nodes to the local-to-global map */
547fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(l2g);CHKERRQ(ierr);
548fabe8965SStefano Zampini       ierr = ISExpand(ndsub,is2,&is);CHKERRQ(ierr);
549fabe8965SStefano Zampini       ierr = ISDestroy(&is2);CHKERRQ(ierr);
550fabe8965SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,l2g);CHKERRQ(ierr);
551fabe8965SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
552fabe8965SStefano Zampini 
553fabe8965SStefano Zampini       ierr = MatDestroy(&A3);CHKERRQ(ierr);
554fabe8965SStefano Zampini       ierr = PetscFree(lndmapi);CHKERRQ(ierr);
555fabe8965SStefano Zampini       ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
556fabe8965SStefano Zampini       for (i = 0; i < gcnt; i++) {
557fabe8965SStefano Zampini         ierr = ISDestroy(&workis[i]);CHKERRQ(ierr);
558fabe8965SStefano Zampini       }
559fabe8965SStefano Zampini       ierr = PetscFree(workis);CHKERRQ(ierr);
560fabe8965SStefano Zampini     }
561fabe8965SStefano Zampini     ierr = ISRestoreIndices(ndmap,&ndmapi);CHKERRQ(ierr);
562fabe8965SStefano Zampini     ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
563fabe8965SStefano Zampini     ierr = PetscFree(ndmapc);CHKERRQ(ierr);
564fabe8965SStefano Zampini     ierr = ISDestroy(&ndmap);CHKERRQ(ierr);
565fabe8965SStefano Zampini     ierr = ISDestroy(&ndsub);CHKERRQ(ierr);
566fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(*l2g,bs);CHKERRQ(ierr);
567fabe8965SStefano Zampini     ierr = ISLocalToGlobalMappingViewFromOptions(*l2g,NULL,"-matis_nd_l2g_view");CHKERRQ(ierr);
568fabe8965SStefano Zampini     break;
569fabe8965SStefano Zampini   case MAT_IS_DISASSEMBLE_L2G_NATURAL:
570fabe8965SStefano Zampini     if (ismpiaij) {
571fabe8965SStefano Zampini       ierr = MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
572fabe8965SStefano Zampini     } else if (ismpibaij) {
573fabe8965SStefano Zampini       ierr = MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
574c9225affSStefano Zampini     } else SETERRQ1(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
575c9225affSStefano Zampini     if (!garray) SETERRQ(comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
576c9225affSStefano Zampini     if (A->rmap->n) {
577fabe8965SStefano Zampini       PetscInt dc,oc,stc,*aux;
578c9225affSStefano Zampini 
579c9225affSStefano Zampini       ierr = MatGetLocalSize(A,NULL,&dc);CHKERRQ(ierr);
580c9225affSStefano Zampini       ierr = MatGetLocalSize(Ao,NULL,&oc);CHKERRQ(ierr);
581c9225affSStefano Zampini       ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
582c9225affSStefano Zampini       ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
583c9225affSStefano Zampini       for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
584c9225affSStefano Zampini       for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i];
585c9225affSStefano Zampini       ierr = ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
586c9225affSStefano Zampini     } else {
587c9225affSStefano Zampini       ierr = ISCreateBlock(comm,1,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
588c9225affSStefano Zampini     }
589c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,l2g);CHKERRQ(ierr);
590c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
591fabe8965SStefano Zampini     break;
592fabe8965SStefano Zampini   default:
593fabe8965SStefano Zampini     SETERRQ1(comm,PETSC_ERR_ARG_WRONG,"Unsupported l2g disassembling type %D",mode);
594c9225affSStefano Zampini   }
595c9225affSStefano Zampini   PetscFunctionReturn(0);
596c9225affSStefano Zampini }
597c9225affSStefano Zampini 
598c9225affSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_XAIJ_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
599c9225affSStefano Zampini {
600c9225affSStefano Zampini   Mat                    lA,Ad,Ao,B = NULL;
6016989cf23SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
6026989cf23SStefano Zampini   IS                     is;
6036989cf23SStefano Zampini   MPI_Comm               comm;
6046989cf23SStefano Zampini   void                   *ptrs[2];
6056989cf23SStefano Zampini   const char             *names[2] = {"_convert_csr_aux","_convert_csr_data"};
606c9225affSStefano Zampini   const PetscInt         *garray;
6076989cf23SStefano Zampini   PetscScalar            *dd,*od,*aa,*data;
608c9225affSStefano Zampini   const PetscInt         *di,*dj,*oi,*oj;
609c9225affSStefano Zampini   const PetscInt         *odi,*odj,*ooi,*ooj;
6106989cf23SStefano Zampini   PetscInt               *aux,*ii,*jj;
611c9225affSStefano Zampini   PetscInt               bs,lc,dr,dc,oc,str,stc,nnz,i,jd,jo,cum;
612c9225affSStefano Zampini   PetscBool              flg,ismpiaij,ismpibaij,was_inplace = PETSC_FALSE;
613c9225affSStefano Zampini   PetscMPIInt            size;
6146989cf23SStefano Zampini   PetscErrorCode         ierr;
6156989cf23SStefano Zampini 
616ab4d48faSStefano Zampini   PetscFunctionBegin;
6176989cf23SStefano Zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
618c9225affSStefano Zampini   ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr);
619c9225affSStefano Zampini   if (size == 1) {
620c9225affSStefano Zampini     ierr = MatConvert_SeqXAIJ_IS(A,type,reuse,newmat);CHKERRQ(ierr);
621c9225affSStefano Zampini     PetscFunctionReturn(0);
622c9225affSStefano Zampini   }
623c9225affSStefano Zampini   if (reuse != MAT_REUSE_MATRIX && A->cmap->N == A->rmap->N) {
624c9225affSStefano Zampini     ierr = MatMPIXAIJComputeLocalToGlobalMapping_Private(A,&rl2g);CHKERRQ(ierr);
625c9225affSStefano Zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
626c9225affSStefano Zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
627c9225affSStefano Zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
628c9225affSStefano Zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,rl2g);CHKERRQ(ierr);
629c9225affSStefano Zampini     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
630c9225affSStefano Zampini     ierr = MatSetBlockSize(B,bs);CHKERRQ(ierr);
631c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
632c9225affSStefano Zampini     if (reuse == MAT_INPLACE_MATRIX) was_inplace = PETSC_TRUE;
633c9225affSStefano Zampini     reuse = MAT_REUSE_MATRIX;
634c9225affSStefano Zampini   }
635c9225affSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
636c9225affSStefano Zampini     Mat            *newlA, lA;
637c9225affSStefano Zampini     IS             rows, cols;
638c9225affSStefano Zampini     const PetscInt *ridx, *cidx;
639c9225affSStefano Zampini     PetscInt       rbs, cbs, nr, nc;
640c9225affSStefano Zampini 
641c9225affSStefano Zampini     if (!B) B = *newmat;
642c9225affSStefano Zampini     ierr = MatGetLocalToGlobalMapping(B,&rl2g,&cl2g);CHKERRQ(ierr);
643c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(rl2g,&ridx);CHKERRQ(ierr);
644c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(cl2g,&cidx);CHKERRQ(ierr);
645c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(rl2g,&nr);CHKERRQ(ierr);
646c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(cl2g,&nc);CHKERRQ(ierr);
647c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(rl2g,&rbs);CHKERRQ(ierr);
648c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(cl2g,&cbs);CHKERRQ(ierr);
649c9225affSStefano Zampini     ierr = ISCreateBlock(comm,rbs,nr/rbs,ridx,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
650c9225affSStefano Zampini     if (rl2g != cl2g) {
651c9225affSStefano Zampini       ierr = ISCreateBlock(comm,cbs,nc/cbs,cidx,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
652c9225affSStefano Zampini     } else {
653c9225affSStefano Zampini       ierr = PetscObjectReference((PetscObject)rows);CHKERRQ(ierr);
654c9225affSStefano Zampini       cols = rows;
655c9225affSStefano Zampini     }
656c9225affSStefano Zampini     ierr = MatISGetLocalMat(B,&lA);CHKERRQ(ierr);
657c9225affSStefano Zampini     ierr = MatCreateSubMatrices(A,1,&rows,&cols,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
658c9225affSStefano Zampini     ierr = MatConvert(newlA[0],MATSEQAIJ,MAT_INPLACE_MATRIX,&newlA[0]);CHKERRQ(ierr);
659c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(rl2g,&ridx);CHKERRQ(ierr);
660c9225affSStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(cl2g,&cidx);CHKERRQ(ierr);
661c9225affSStefano Zampini     ierr = ISDestroy(&rows);CHKERRQ(ierr);
662c9225affSStefano Zampini     ierr = ISDestroy(&cols);CHKERRQ(ierr);
663c9225affSStefano Zampini     if (!lA->preallocated) { /* first time */
664c9225affSStefano Zampini       ierr = MatDuplicate(newlA[0],MAT_COPY_VALUES,&lA);CHKERRQ(ierr);
665c9225affSStefano Zampini       ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
666c9225affSStefano Zampini       ierr = PetscObjectDereference((PetscObject)lA);CHKERRQ(ierr);
667c9225affSStefano Zampini     }
668c9225affSStefano Zampini     ierr = MatCopy(newlA[0],lA,SAME_NONZERO_PATTERN);CHKERRQ(ierr);
669c9225affSStefano Zampini     ierr = MatDestroySubMatrices(1,&newlA);CHKERRQ(ierr);
670c9225affSStefano Zampini     ierr = MatISScaleDisassembling_Private(B);CHKERRQ(ierr);
671c9225affSStefano Zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
672c9225affSStefano Zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
673c9225affSStefano Zampini     if (was_inplace) { ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr); }
674c9225affSStefano Zampini     else *newmat = B;
675c9225affSStefano Zampini     PetscFunctionReturn(0);
676c9225affSStefano Zampini   }
677c9225affSStefano Zampini   /* rectangular case, just compress out the column space */
678c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIAIJ ,&ismpiaij);CHKERRQ(ierr);
679c9225affSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)A,MATMPIBAIJ,&ismpibaij);CHKERRQ(ierr);
680c9225affSStefano Zampini   if (ismpiaij) {
681c9225affSStefano Zampini     bs   = 1;
682c9225affSStefano Zampini     ierr = MatMPIAIJGetSeqAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
683c9225affSStefano Zampini   } else if (ismpibaij) {
684c9225affSStefano Zampini     ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
685c9225affSStefano Zampini     ierr = MatMPIBAIJGetSeqBAIJ(A,&Ad,&Ao,&garray);CHKERRQ(ierr);
686c9225affSStefano Zampini     ierr = MatConvert(Ad,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ad);CHKERRQ(ierr);
687c9225affSStefano Zampini     ierr = MatConvert(Ao,MATSEQAIJ,MAT_INITIAL_MATRIX,&Ao);CHKERRQ(ierr);
688c9225affSStefano Zampini   } else SETERRQ1(comm,PETSC_ERR_SUP,"Type %s",((PetscObject)A)->type_name);
689c9225affSStefano Zampini   ierr = MatSeqAIJGetArray(Ad,&dd);CHKERRQ(ierr);
690c9225affSStefano Zampini   ierr = MatSeqAIJGetArray(Ao,&od);CHKERRQ(ierr);
691c9225affSStefano Zampini   if (!garray) SETERRQ(comm,PETSC_ERR_ARG_WRONGSTATE,"garray not present");
6926989cf23SStefano Zampini 
6936989cf23SStefano Zampini   /* access relevant information from MPIAIJ */
6946989cf23SStefano Zampini   ierr = MatGetOwnershipRange(A,&str,NULL);CHKERRQ(ierr);
6956989cf23SStefano Zampini   ierr = MatGetOwnershipRangeColumn(A,&stc,NULL);CHKERRQ(ierr);
6966989cf23SStefano Zampini   ierr = MatGetLocalSize(A,&dr,&dc);CHKERRQ(ierr);
697c9225affSStefano Zampini   ierr = MatGetLocalSize(Ao,NULL,&oc);CHKERRQ(ierr);
698c9225affSStefano Zampini   ierr = MatGetRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&di,&dj,&flg);CHKERRQ(ierr);
699c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
700c9225affSStefano Zampini   ierr = MatGetRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&oi,&oj,&flg);CHKERRQ(ierr);
701c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get IJ structure");
702c9225affSStefano Zampini   nnz = di[dr] + oi[dr];
703c9225affSStefano Zampini   /* store original pointers to be restored later */
704c9225affSStefano Zampini   odi = di; odj = dj; ooi = oi; ooj = oj;
7056989cf23SStefano Zampini 
7066989cf23SStefano Zampini   /* generate l2g maps for rows and cols */
707c9225affSStefano Zampini   ierr = ISCreateStride(comm,dr/bs,str/bs,1,&is);CHKERRQ(ierr);
708c9225affSStefano Zampini   if (bs > 1) {
709c9225affSStefano Zampini     IS is2;
710c9225affSStefano Zampini 
711c9225affSStefano Zampini     ierr = ISGetLocalSize(is,&i);CHKERRQ(ierr);
712c9225affSStefano Zampini     ierr = ISGetIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
713c9225affSStefano Zampini     ierr = ISCreateBlock(comm,bs,i,aux,PETSC_COPY_VALUES,&is2);CHKERRQ(ierr);
714c9225affSStefano Zampini     ierr = ISRestoreIndices(is,(const PetscInt**)&aux);CHKERRQ(ierr);
715c9225affSStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
716c9225affSStefano Zampini     is   = is2;
717c9225affSStefano Zampini   }
7186989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
7196989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
720e363d98aSStefano Zampini   if (dr) {
721c9225affSStefano Zampini     ierr = PetscMalloc1((dc+oc)/bs,&aux);CHKERRQ(ierr);
722c9225affSStefano Zampini     for (i=0; i<dc/bs; i++) aux[i]       = i+stc/bs;
723c9225affSStefano Zampini     for (i=0; i<oc/bs; i++) aux[i+dc/bs] = garray[i];
724c9225affSStefano Zampini     ierr = ISCreateBlock(comm,bs,(dc+oc)/bs,aux,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
725e363d98aSStefano Zampini     lc   = dc+oc;
726e363d98aSStefano Zampini   } else {
727c9225affSStefano Zampini     ierr = ISCreateBlock(comm,bs,0,NULL,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
728e363d98aSStefano Zampini     lc   = 0;
729e363d98aSStefano Zampini   }
7306989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
7316989cf23SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
7326989cf23SStefano Zampini 
7336989cf23SStefano Zampini   /* create MATIS object */
734c9225affSStefano Zampini   ierr = MatCreate(comm,&B);CHKERRQ(ierr);
735c9225affSStefano Zampini   ierr = MatSetSizes(B,dr,dc,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
736c9225affSStefano Zampini   ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
737c9225affSStefano Zampini   ierr = MatSetBlockSize(B,bs);CHKERRQ(ierr);
738c9225affSStefano Zampini   ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
7396989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
7406989cf23SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
7416989cf23SStefano Zampini 
7426989cf23SStefano Zampini   /* merge local matrices */
7436989cf23SStefano Zampini   ierr = PetscMalloc1(nnz+dr+1,&aux);CHKERRQ(ierr);
7446989cf23SStefano Zampini   ierr = PetscMalloc1(nnz,&data);CHKERRQ(ierr);
7456989cf23SStefano Zampini   ii   = aux;
7466989cf23SStefano Zampini   jj   = aux+dr+1;
7476989cf23SStefano Zampini   aa   = data;
7486989cf23SStefano Zampini   *ii  = *(di++) + *(oi++);
7496989cf23SStefano Zampini   for (jd=0,jo=0,cum=0;*ii<nnz;cum++)
7506989cf23SStefano Zampini   {
7516989cf23SStefano Zampini      for (;jd<*di;jd++) { *jj++ = *dj++;      *aa++ = *dd++; }
7526989cf23SStefano Zampini      for (;jo<*oi;jo++) { *jj++ = *oj++ + dc; *aa++ = *od++; }
7536989cf23SStefano Zampini      *(++ii) = *(di++) + *(oi++);
7546989cf23SStefano Zampini   }
7556989cf23SStefano Zampini   for (;cum<dr;cum++) *(++ii) = nnz;
756c9225affSStefano Zampini 
757c9225affSStefano Zampini   ierr = MatRestoreRowIJ(Ad,0,PETSC_FALSE,PETSC_FALSE,&i,&odi,&odj,&flg);CHKERRQ(ierr);
758c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
759c9225affSStefano Zampini   ierr = MatRestoreRowIJ(Ao,0,PETSC_FALSE,PETSC_FALSE,&i,&ooi,&ooj,&flg);CHKERRQ(ierr);
760c9225affSStefano Zampini   if (!flg) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore IJ structure");
761c9225affSStefano Zampini   ierr = MatSeqAIJRestoreArray(Ad,&dd);CHKERRQ(ierr);
762c9225affSStefano Zampini   ierr = MatSeqAIJRestoreArray(Ao,&od);CHKERRQ(ierr);
763c9225affSStefano Zampini 
7646989cf23SStefano Zampini   ii   = aux;
7656989cf23SStefano Zampini   jj   = aux+dr+1;
7666989cf23SStefano Zampini   aa   = data;
767e363d98aSStefano Zampini   ierr = MatCreateSeqAIJWithArrays(PETSC_COMM_SELF,dr,lc,ii,jj,aa,&lA);CHKERRQ(ierr);
7686989cf23SStefano Zampini 
7696989cf23SStefano Zampini   /* create containers to destroy the data */
7706989cf23SStefano Zampini   ptrs[0] = aux;
7716989cf23SStefano Zampini   ptrs[1] = data;
7726989cf23SStefano Zampini   for (i=0; i<2; i++) {
7736989cf23SStefano Zampini     PetscContainer c;
7746989cf23SStefano Zampini 
7756989cf23SStefano Zampini     ierr = PetscContainerCreate(PETSC_COMM_SELF,&c);CHKERRQ(ierr);
7766989cf23SStefano Zampini     ierr = PetscContainerSetPointer(c,ptrs[i]);CHKERRQ(ierr);
777b81c21eeSStefano Zampini     ierr = PetscContainerSetUserDestroy(c,PetscContainerUserDestroyDefault);CHKERRQ(ierr);
7786989cf23SStefano Zampini     ierr = PetscObjectCompose((PetscObject)lA,names[i],(PetscObject)c);CHKERRQ(ierr);
7796989cf23SStefano Zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
7806989cf23SStefano Zampini   }
781c9225affSStefano Zampini   if (ismpibaij) { /* destroy converted local matrices */
782c9225affSStefano Zampini     ierr = MatDestroy(&Ad);CHKERRQ(ierr);
783c9225affSStefano Zampini     ierr = MatDestroy(&Ao);CHKERRQ(ierr);
784c9225affSStefano Zampini   }
7856989cf23SStefano Zampini 
7866989cf23SStefano Zampini   /* finalize matrix */
787c9225affSStefano Zampini   ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
7886989cf23SStefano Zampini   ierr = MatDestroy(&lA);CHKERRQ(ierr);
789c9225affSStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
790c9225affSStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
791c9225affSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
792c9225affSStefano Zampini     ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
793c9225affSStefano Zampini   } else *newmat = B;
7946989cf23SStefano Zampini   PetscFunctionReturn(0);
7956989cf23SStefano Zampini }
7966989cf23SStefano Zampini 
797cf0a3239SStefano Zampini /*@
7983d996552SStefano Zampini    MatISSetUpSF - Setup star forest objects used by MatIS.
799cf0a3239SStefano Zampini 
800cf0a3239SStefano Zampini    Collective on MPI_Comm
801cf0a3239SStefano Zampini 
802cf0a3239SStefano Zampini    Input Parameters:
803cf0a3239SStefano Zampini +  A - the matrix
804cf0a3239SStefano Zampini 
805cf0a3239SStefano Zampini    Level: advanced
806cf0a3239SStefano Zampini 
80795452b02SPatrick Sanan    Notes:
80895452b02SPatrick Sanan     This function does not need to be called by the user.
809cf0a3239SStefano Zampini 
810cf0a3239SStefano Zampini .keywords: matrix
811cf0a3239SStefano Zampini 
812cf0a3239SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatISGetLocalMat()
813cf0a3239SStefano Zampini @*/
814cf0a3239SStefano Zampini PetscErrorCode  MatISSetUpSF(Mat A)
815cf0a3239SStefano Zampini {
8167fa8f2d3SStefano Zampini   PetscErrorCode ierr;
8177fa8f2d3SStefano Zampini 
8187fa8f2d3SStefano Zampini   PetscFunctionBegin;
819cf0a3239SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
820cf0a3239SStefano Zampini   PetscValidType(A,1);
821cf0a3239SStefano Zampini   ierr = PetscTryMethod(A,"MatISSetUpSF_C",(Mat),(A));CHKERRQ(ierr);
8227fa8f2d3SStefano Zampini   PetscFunctionReturn(0);
8237fa8f2d3SStefano Zampini }
8247fa8f2d3SStefano Zampini 
8255e3038f0Sstefano_zampini PETSC_INTERN PetscErrorCode MatConvert_Nest_IS(Mat A,MatType type,MatReuse reuse,Mat *newmat)
8265e3038f0Sstefano_zampini {
8275e3038f0Sstefano_zampini   Mat                    **nest,*snest,**rnest,lA,B;
8285e3038f0Sstefano_zampini   IS                     *iscol,*isrow,*islrow,*islcol;
8295e3038f0Sstefano_zampini   ISLocalToGlobalMapping rl2g,cl2g;
8305e3038f0Sstefano_zampini   MPI_Comm               comm;
8315b003df0Sstefano_zampini   PetscInt               *lr,*lc,*l2gidxs;
8325b003df0Sstefano_zampini   PetscInt               i,j,nr,nc,rbs,cbs;
8339e7b2b25Sstefano_zampini   PetscBool              convert,lreuse,*istrans;
8345e3038f0Sstefano_zampini   PetscErrorCode         ierr;
8355e3038f0Sstefano_zampini 
836ab4d48faSStefano Zampini   PetscFunctionBegin;
8375e3038f0Sstefano_zampini   ierr   = MatNestGetSubMats(A,&nr,&nc,&nest);CHKERRQ(ierr);
8385e3038f0Sstefano_zampini   lreuse = PETSC_FALSE;
8395e3038f0Sstefano_zampini   rnest  = NULL;
8405e3038f0Sstefano_zampini   if (reuse == MAT_REUSE_MATRIX) {
8415e3038f0Sstefano_zampini     PetscBool ismatis,isnest;
8425e3038f0Sstefano_zampini 
8435e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
8445e3038f0Sstefano_zampini     if (!ismatis) SETERRQ1(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_USER,"Cannot reuse matrix of type %s",((PetscObject)(*newmat))->type);
8455e3038f0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
8465e3038f0Sstefano_zampini     ierr = PetscObjectTypeCompare((PetscObject)lA,MATNEST,&isnest);CHKERRQ(ierr);
8475e3038f0Sstefano_zampini     if (isnest) {
8485e3038f0Sstefano_zampini       ierr   = MatNestGetSubMats(lA,&i,&j,&rnest);CHKERRQ(ierr);
8495e3038f0Sstefano_zampini       lreuse = (PetscBool)(i == nr && j == nc);
8505e3038f0Sstefano_zampini       if (!lreuse) rnest = NULL;
8515e3038f0Sstefano_zampini     }
8525e3038f0Sstefano_zampini   }
8535e3038f0Sstefano_zampini   ierr = PetscObjectGetComm((PetscObject)A,&comm);CHKERRQ(ierr);
8545b003df0Sstefano_zampini   ierr = PetscCalloc2(nr,&lr,nc,&lc);CHKERRQ(ierr);
8559e7b2b25Sstefano_zampini   ierr = PetscCalloc6(nr,&isrow,nc,&iscol,
8565e3038f0Sstefano_zampini                       nr,&islrow,nc,&islcol,
8579e7b2b25Sstefano_zampini                       nr*nc,&snest,nr*nc,&istrans);CHKERRQ(ierr);
8585e3038f0Sstefano_zampini   ierr = MatNestGetISs(A,isrow,iscol);CHKERRQ(ierr);
8595e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
8605e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
8615e3038f0Sstefano_zampini       PetscBool ismatis;
8629e7b2b25Sstefano_zampini       PetscInt  l1,l2,lb1,lb2,ij=i*nc+j;
8635e3038f0Sstefano_zampini 
8645e3038f0Sstefano_zampini       /* Null matrix pointers are allowed in MATNEST */
8655e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
8665e3038f0Sstefano_zampini 
8675e3038f0Sstefano_zampini       /* Nested matrices should be of type MATIS */
8689e7b2b25Sstefano_zampini       ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATTRANSPOSEMAT,&istrans[ij]);CHKERRQ(ierr);
8699e7b2b25Sstefano_zampini       if (istrans[ij]) {
8709e7b2b25Sstefano_zampini         Mat T,lT;
8719e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
8729e7b2b25Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)T,MATIS,&ismatis);CHKERRQ(ierr);
8739e7b2b25Sstefano_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);
8749e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(T,&lT);CHKERRQ(ierr);
8759e7b2b25Sstefano_zampini         ierr = MatCreateTranspose(lT,&snest[ij]);CHKERRQ(ierr);
8769e7b2b25Sstefano_zampini       } else {
8775e3038f0Sstefano_zampini         ierr = PetscObjectTypeCompare((PetscObject)nest[i][j],MATIS,&ismatis);CHKERRQ(ierr);
8785e3038f0Sstefano_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);
8799e7b2b25Sstefano_zampini         ierr = MatISGetLocalMat(nest[i][j],&snest[ij]);CHKERRQ(ierr);
8809e7b2b25Sstefano_zampini       }
8815e3038f0Sstefano_zampini 
8825e3038f0Sstefano_zampini       /* Check compatibility of local sizes */
8835e3038f0Sstefano_zampini       ierr = MatGetSize(snest[ij],&l1,&l2);CHKERRQ(ierr);
8849e7b2b25Sstefano_zampini       ierr = MatGetBlockSizes(snest[ij],&lb1,&lb2);CHKERRQ(ierr);
8855e3038f0Sstefano_zampini       if (!l1 || !l2) continue;
8865e3038f0Sstefano_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);
8875e3038f0Sstefano_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);
8885e3038f0Sstefano_zampini       lr[i] = l1;
8895e3038f0Sstefano_zampini       lc[j] = l2;
8905e3038f0Sstefano_zampini 
8915e3038f0Sstefano_zampini       /* check compatibilty for local matrix reusage */
8925e3038f0Sstefano_zampini       if (rnest && !rnest[i][j] != !snest[ij]) lreuse = PETSC_FALSE;
8935e3038f0Sstefano_zampini     }
8945e3038f0Sstefano_zampini   }
8955e3038f0Sstefano_zampini 
8965e3038f0Sstefano_zampini #if defined (PETSC_USE_DEBUG)
8975e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for rows */
8985e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
8995e3038f0Sstefano_zampini     rl2g = NULL;
9005e3038f0Sstefano_zampini     for (j=0;j<nc;j++) {
9015e3038f0Sstefano_zampini       PetscInt n1,n2;
9025e3038f0Sstefano_zampini 
9035e3038f0Sstefano_zampini       if (!nest[i][j]) continue;
9049e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
9059e7b2b25Sstefano_zampini         Mat T;
9069e7b2b25Sstefano_zampini 
9079e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[i][j],&T);CHKERRQ(ierr);
9089e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,NULL,&cl2g);CHKERRQ(ierr);
9099e7b2b25Sstefano_zampini       } else {
9105e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[i][j],&cl2g,NULL);CHKERRQ(ierr);
9119e7b2b25Sstefano_zampini       }
9125e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
9135e3038f0Sstefano_zampini       if (!n1) continue;
9145e3038f0Sstefano_zampini       if (!rl2g) {
9155e3038f0Sstefano_zampini         rl2g = cl2g;
9165e3038f0Sstefano_zampini       } else {
9175e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
9185e3038f0Sstefano_zampini         PetscBool      same;
9195e3038f0Sstefano_zampini 
9205e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
9215e3038f0Sstefano_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);
9225e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
9235e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
9245e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
9255e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
9265e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
9275e3038f0Sstefano_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);
9285e3038f0Sstefano_zampini       }
9295e3038f0Sstefano_zampini     }
9305e3038f0Sstefano_zampini   }
9315e3038f0Sstefano_zampini   /* Check compatibility of l2g maps for columns */
9325e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
9335e3038f0Sstefano_zampini     rl2g = NULL;
9345e3038f0Sstefano_zampini     for (j=0;j<nr;j++) {
9355e3038f0Sstefano_zampini       PetscInt n1,n2;
9365e3038f0Sstefano_zampini 
9375e3038f0Sstefano_zampini       if (!nest[j][i]) continue;
9389e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
9399e7b2b25Sstefano_zampini         Mat T;
9409e7b2b25Sstefano_zampini 
9419e7b2b25Sstefano_zampini         ierr = MatTransposeGetMat(nest[j][i],&T);CHKERRQ(ierr);
9429e7b2b25Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(T,&cl2g,NULL);CHKERRQ(ierr);
9439e7b2b25Sstefano_zampini       } else {
9445e3038f0Sstefano_zampini         ierr = MatGetLocalToGlobalMapping(nest[j][i],NULL,&cl2g);CHKERRQ(ierr);
9459e7b2b25Sstefano_zampini       }
9465e3038f0Sstefano_zampini       ierr = ISLocalToGlobalMappingGetSize(cl2g,&n1);CHKERRQ(ierr);
9475e3038f0Sstefano_zampini       if (!n1) continue;
9485e3038f0Sstefano_zampini       if (!rl2g) {
9495e3038f0Sstefano_zampini         rl2g = cl2g;
9505e3038f0Sstefano_zampini       } else {
9515e3038f0Sstefano_zampini         const PetscInt *idxs1,*idxs2;
9525e3038f0Sstefano_zampini         PetscBool      same;
9535e3038f0Sstefano_zampini 
9545e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetSize(rl2g,&n2);CHKERRQ(ierr);
9555e3038f0Sstefano_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);
9565e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(cl2g,&idxs1);CHKERRQ(ierr);
9575e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingGetIndices(rl2g,&idxs2);CHKERRQ(ierr);
9585e3038f0Sstefano_zampini         ierr = PetscMemcmp(idxs1,idxs2,n1*sizeof(PetscInt),&same);CHKERRQ(ierr);
9595e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(cl2g,&idxs1);CHKERRQ(ierr);
9605e3038f0Sstefano_zampini         ierr = ISLocalToGlobalMappingRestoreIndices(rl2g,&idxs2);CHKERRQ(ierr);
9615e3038f0Sstefano_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);
9625e3038f0Sstefano_zampini       }
9635e3038f0Sstefano_zampini     }
9645e3038f0Sstefano_zampini   }
9655e3038f0Sstefano_zampini #endif
9665e3038f0Sstefano_zampini 
9675e3038f0Sstefano_zampini   B = NULL;
9685e3038f0Sstefano_zampini   if (reuse != MAT_REUSE_MATRIX) {
9695b003df0Sstefano_zampini     PetscInt stl;
9705b003df0Sstefano_zampini 
9715e3038f0Sstefano_zampini     /* Create l2g map for the rows of the new matrix and index sets for the local MATNEST */
9725e3038f0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) stl += lr[i];
9735e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
9745b003df0Sstefano_zampini     for (i=0,stl=0;i<nr;i++) {
9755e3038f0Sstefano_zampini       Mat            usedmat;
9765e3038f0Sstefano_zampini       Mat_IS         *matis;
9775e3038f0Sstefano_zampini       const PetscInt *idxs;
9785e3038f0Sstefano_zampini 
9795e3038f0Sstefano_zampini       /* local IS for local NEST */
9805b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
9815e3038f0Sstefano_zampini 
9825e3038f0Sstefano_zampini       /* l2gmap */
9835e3038f0Sstefano_zampini       j = 0;
9845e3038f0Sstefano_zampini       usedmat = nest[i][j];
9859e7b2b25Sstefano_zampini       while (!usedmat && j < nc-1) usedmat = nest[i][++j];
9869e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid row mat");
9879e7b2b25Sstefano_zampini 
9889e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
9899e7b2b25Sstefano_zampini         Mat T;
9909e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
9919e7b2b25Sstefano_zampini         usedmat = T;
9929e7b2b25Sstefano_zampini       }
99382d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
9945e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
9955e3038f0Sstefano_zampini       ierr  = ISGetIndices(isrow[i],&idxs);CHKERRQ(ierr);
9969e7b2b25Sstefano_zampini       if (istrans[i*nc+j]) {
9979e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
9989e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
9999e7b2b25Sstefano_zampini       } else {
10005e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10015e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10029e7b2b25Sstefano_zampini       }
10035e3038f0Sstefano_zampini       ierr = ISRestoreIndices(isrow[i],&idxs);CHKERRQ(ierr);
10045e3038f0Sstefano_zampini       stl += lr[i];
10055e3038f0Sstefano_zampini     }
10065e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&rl2g);CHKERRQ(ierr);
10075e3038f0Sstefano_zampini 
10085e3038f0Sstefano_zampini     /* Create l2g map for columns of the new matrix and index sets for the local MATNEST */
10095e3038f0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) stl += lc[i];
10105e3038f0Sstefano_zampini     ierr = PetscMalloc1(stl,&l2gidxs);CHKERRQ(ierr);
10115b003df0Sstefano_zampini     for (i=0,stl=0;i<nc;i++) {
10125e3038f0Sstefano_zampini       Mat            usedmat;
10135e3038f0Sstefano_zampini       Mat_IS         *matis;
10145e3038f0Sstefano_zampini       const PetscInt *idxs;
10155e3038f0Sstefano_zampini 
10165e3038f0Sstefano_zampini       /* local IS for local NEST */
10175b003df0Sstefano_zampini       ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
10185e3038f0Sstefano_zampini 
10195e3038f0Sstefano_zampini       /* l2gmap */
10205e3038f0Sstefano_zampini       j = 0;
10215e3038f0Sstefano_zampini       usedmat = nest[j][i];
10229e7b2b25Sstefano_zampini       while (!usedmat && j < nr-1) usedmat = nest[++j][i];
10239e7b2b25Sstefano_zampini       if (!usedmat) SETERRQ(comm,PETSC_ERR_SUP,"Cannot find valid column mat");
10249e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
10259e7b2b25Sstefano_zampini         Mat T;
10269e7b2b25Sstefano_zampini         ierr    = MatTransposeGetMat(usedmat,&T);CHKERRQ(ierr);
10279e7b2b25Sstefano_zampini         usedmat = T;
10289e7b2b25Sstefano_zampini       }
102982d73161Sstefano_zampini       ierr  = MatISSetUpSF(usedmat);CHKERRQ(ierr);
10305e3038f0Sstefano_zampini       matis = (Mat_IS*)(usedmat->data);
10315e3038f0Sstefano_zampini       ierr  = ISGetIndices(iscol[i],&idxs);CHKERRQ(ierr);
10329e7b2b25Sstefano_zampini       if (istrans[j*nc+i]) {
10339e7b2b25Sstefano_zampini         ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10349e7b2b25Sstefano_zampini         ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10359e7b2b25Sstefano_zampini       } else {
10365e3038f0Sstefano_zampini         ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10375e3038f0Sstefano_zampini         ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,idxs,l2gidxs+stl);CHKERRQ(ierr);
10389e7b2b25Sstefano_zampini       }
10395e3038f0Sstefano_zampini       ierr = ISRestoreIndices(iscol[i],&idxs);CHKERRQ(ierr);
10405e3038f0Sstefano_zampini       stl += lc[i];
10415e3038f0Sstefano_zampini     }
10425e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingCreate(comm,1,stl,l2gidxs,PETSC_OWN_POINTER,&cl2g);CHKERRQ(ierr);
10435e3038f0Sstefano_zampini 
10445e3038f0Sstefano_zampini     /* Create MATIS */
10455e3038f0Sstefano_zampini     ierr = MatCreate(comm,&B);CHKERRQ(ierr);
10465e3038f0Sstefano_zampini     ierr = MatSetSizes(B,A->rmap->n,A->cmap->n,A->rmap->N,A->cmap->N);CHKERRQ(ierr);
10475e3038f0Sstefano_zampini     ierr = MatGetBlockSizes(A,&rbs,&cbs);CHKERRQ(ierr);
10485e3038f0Sstefano_zampini     ierr = MatSetBlockSizes(B,rbs,cbs);CHKERRQ(ierr);
10495e3038f0Sstefano_zampini     ierr = MatSetType(B,MATIS);CHKERRQ(ierr);
10505e3038f0Sstefano_zampini     ierr = MatSetLocalToGlobalMapping(B,rl2g,cl2g);CHKERRQ(ierr);
10515e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
10525e3038f0Sstefano_zampini     ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
10535e3038f0Sstefano_zampini     ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
10549e7b2b25Sstefano_zampini     for (i=0;i<nr*nc;i++) {
10559e7b2b25Sstefano_zampini       if (istrans[i]) {
10569e7b2b25Sstefano_zampini         ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
10579e7b2b25Sstefano_zampini       }
10589e7b2b25Sstefano_zampini     }
10595e3038f0Sstefano_zampini     ierr = MatISSetLocalMat(B,lA);CHKERRQ(ierr);
10605e3038f0Sstefano_zampini     ierr = MatDestroy(&lA);CHKERRQ(ierr);
10615e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10625e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
10635e3038f0Sstefano_zampini     if (reuse == MAT_INPLACE_MATRIX) {
10645e3038f0Sstefano_zampini       ierr = MatHeaderReplace(A,&B);CHKERRQ(ierr);
10655e3038f0Sstefano_zampini     } else {
10665e3038f0Sstefano_zampini       *newmat = B;
10675e3038f0Sstefano_zampini     }
10685e3038f0Sstefano_zampini   } else {
10695e3038f0Sstefano_zampini     if (lreuse) {
10705e3038f0Sstefano_zampini       ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
10715e3038f0Sstefano_zampini       for (i=0;i<nr;i++) {
10725e3038f0Sstefano_zampini         for (j=0;j<nc;j++) {
10735e3038f0Sstefano_zampini           if (snest[i*nc+j]) {
10745e3038f0Sstefano_zampini             ierr = MatNestSetSubMat(lA,i,j,snest[i*nc+j]);CHKERRQ(ierr);
10759e7b2b25Sstefano_zampini             if (istrans[i*nc+j]) {
10769e7b2b25Sstefano_zampini               ierr = MatDestroy(&snest[i*nc+j]);CHKERRQ(ierr);
10779e7b2b25Sstefano_zampini             }
10785e3038f0Sstefano_zampini           }
10795e3038f0Sstefano_zampini         }
10805e3038f0Sstefano_zampini       }
10815e3038f0Sstefano_zampini     } else {
10825b003df0Sstefano_zampini       PetscInt stl;
10835b003df0Sstefano_zampini       for (i=0,stl=0;i<nr;i++) {
10845b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lr[i],stl,1,&islrow[i]);CHKERRQ(ierr);
10855b003df0Sstefano_zampini         stl  += lr[i];
10865e3038f0Sstefano_zampini       }
10875b003df0Sstefano_zampini       for (i=0,stl=0;i<nc;i++) {
10885b003df0Sstefano_zampini         ierr  = ISCreateStride(PETSC_COMM_SELF,lc[i],stl,1,&islcol[i]);CHKERRQ(ierr);
10895b003df0Sstefano_zampini         stl  += lc[i];
10905e3038f0Sstefano_zampini       }
10915e3038f0Sstefano_zampini       ierr = MatCreateNest(PETSC_COMM_SELF,nr,islrow,nc,islcol,snest,&lA);CHKERRQ(ierr);
1092ab4d48faSStefano Zampini       for (i=0;i<nr*nc;i++) {
10939e7b2b25Sstefano_zampini         if (istrans[i]) {
10949e7b2b25Sstefano_zampini           ierr = MatDestroy(&snest[i]);CHKERRQ(ierr);
10959e7b2b25Sstefano_zampini         }
1096ab4d48faSStefano Zampini       }
10975e3038f0Sstefano_zampini       ierr = MatISSetLocalMat(*newmat,lA);CHKERRQ(ierr);
10985e3038f0Sstefano_zampini       ierr = MatDestroy(&lA);CHKERRQ(ierr);
10995e3038f0Sstefano_zampini     }
11005e3038f0Sstefano_zampini     ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11015e3038f0Sstefano_zampini     ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
11025e3038f0Sstefano_zampini   }
11035e3038f0Sstefano_zampini 
11045b003df0Sstefano_zampini   /* Create local matrix in MATNEST format */
11055b003df0Sstefano_zampini   convert = PETSC_FALSE;
11065b003df0Sstefano_zampini   ierr = PetscOptionsGetBool(NULL,((PetscObject)A)->prefix,"-matis_convert_local_nest",&convert,NULL);CHKERRQ(ierr);
11075b003df0Sstefano_zampini   if (convert) {
11085b003df0Sstefano_zampini     Mat              M;
11095b003df0Sstefano_zampini     MatISLocalFields lf;
11105b003df0Sstefano_zampini     PetscContainer   c;
11115b003df0Sstefano_zampini 
11125b003df0Sstefano_zampini     ierr = MatISGetLocalMat(*newmat,&lA);CHKERRQ(ierr);
11135b003df0Sstefano_zampini     ierr = MatConvert(lA,MATAIJ,MAT_INITIAL_MATRIX,&M);CHKERRQ(ierr);
11145b003df0Sstefano_zampini     ierr = MatISSetLocalMat(*newmat,M);CHKERRQ(ierr);
11155b003df0Sstefano_zampini     ierr = MatDestroy(&M);CHKERRQ(ierr);
11165b003df0Sstefano_zampini 
11175b003df0Sstefano_zampini     /* attach local fields to the matrix */
11185b003df0Sstefano_zampini     ierr = PetscNew(&lf);CHKERRQ(ierr);
11195b003df0Sstefano_zampini     ierr = PetscCalloc2(nr,&lf->rf,nc,&lf->cf);CHKERRQ(ierr);
11205b003df0Sstefano_zampini     for (i=0;i<nr;i++) {
11215b003df0Sstefano_zampini       PetscInt n,st;
11225b003df0Sstefano_zampini 
11235b003df0Sstefano_zampini       ierr = ISGetLocalSize(islrow[i],&n);CHKERRQ(ierr);
11245b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islrow[i],&st,NULL);CHKERRQ(ierr);
11255b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->rf[i]);CHKERRQ(ierr);
11265b003df0Sstefano_zampini     }
11275b003df0Sstefano_zampini     for (i=0;i<nc;i++) {
11285b003df0Sstefano_zampini       PetscInt n,st;
11295b003df0Sstefano_zampini 
11305b003df0Sstefano_zampini       ierr = ISGetLocalSize(islcol[i],&n);CHKERRQ(ierr);
11315b003df0Sstefano_zampini       ierr = ISStrideGetInfo(islcol[i],&st,NULL);CHKERRQ(ierr);
11325b003df0Sstefano_zampini       ierr = ISCreateStride(comm,n,st,1,&lf->cf[i]);CHKERRQ(ierr);
11335b003df0Sstefano_zampini     }
11345b003df0Sstefano_zampini     lf->nr = nr;
11355b003df0Sstefano_zampini     lf->nc = nc;
11365b003df0Sstefano_zampini     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)(*newmat)),&c);CHKERRQ(ierr);
11375b003df0Sstefano_zampini     ierr = PetscContainerSetPointer(c,lf);CHKERRQ(ierr);
11385b003df0Sstefano_zampini     ierr = PetscContainerSetUserDestroy(c,MatISContainerDestroyFields_Private);CHKERRQ(ierr);
11395b003df0Sstefano_zampini     ierr = PetscObjectCompose((PetscObject)(*newmat),"_convert_nest_lfields",(PetscObject)c);CHKERRQ(ierr);
11405b003df0Sstefano_zampini     ierr = PetscContainerDestroy(&c);CHKERRQ(ierr);
11415b003df0Sstefano_zampini   }
11425b003df0Sstefano_zampini 
11435e3038f0Sstefano_zampini   /* Free workspace */
11445e3038f0Sstefano_zampini   for (i=0;i<nr;i++) {
11455e3038f0Sstefano_zampini     ierr = ISDestroy(&islrow[i]);CHKERRQ(ierr);
11465e3038f0Sstefano_zampini   }
11475e3038f0Sstefano_zampini   for (i=0;i<nc;i++) {
11485e3038f0Sstefano_zampini     ierr = ISDestroy(&islcol[i]);CHKERRQ(ierr);
11495e3038f0Sstefano_zampini   }
11509e7b2b25Sstefano_zampini   ierr = PetscFree6(isrow,iscol,islrow,islcol,snest,istrans);CHKERRQ(ierr);
11515b003df0Sstefano_zampini   ierr = PetscFree2(lr,lc);CHKERRQ(ierr);
11525e3038f0Sstefano_zampini   PetscFunctionReturn(0);
11535e3038f0Sstefano_zampini }
11545e3038f0Sstefano_zampini 
1155ad219c80Sstefano_zampini static PetscErrorCode MatDiagonalScale_IS(Mat A, Vec l, Vec r)
1156ad219c80Sstefano_zampini {
1157ad219c80Sstefano_zampini   Mat_IS            *matis = (Mat_IS*)A->data;
1158ad219c80Sstefano_zampini   Vec               ll,rr;
1159ad219c80Sstefano_zampini   const PetscScalar *Y,*X;
1160ad219c80Sstefano_zampini   PetscScalar       *x,*y;
1161ad219c80Sstefano_zampini   PetscErrorCode    ierr;
1162ad219c80Sstefano_zampini 
1163ad219c80Sstefano_zampini   PetscFunctionBegin;
1164ad219c80Sstefano_zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
1165ad219c80Sstefano_zampini   if (l) {
1166ad219c80Sstefano_zampini     ll   = matis->y;
1167ad219c80Sstefano_zampini     ierr = VecGetArrayRead(l,&Y);CHKERRQ(ierr);
1168ad219c80Sstefano_zampini     ierr = VecGetArray(ll,&y);CHKERRQ(ierr);
1169ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
1170ad219c80Sstefano_zampini   } else {
1171ad219c80Sstefano_zampini     ll = NULL;
1172ad219c80Sstefano_zampini   }
1173ad219c80Sstefano_zampini   if (r) {
1174ad219c80Sstefano_zampini     rr   = matis->x;
1175ad219c80Sstefano_zampini     ierr = VecGetArrayRead(r,&X);CHKERRQ(ierr);
1176ad219c80Sstefano_zampini     ierr = VecGetArray(rr,&x);CHKERRQ(ierr);
1177ad219c80Sstefano_zampini     ierr = PetscSFBcastBegin(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
1178ad219c80Sstefano_zampini   } else {
1179ad219c80Sstefano_zampini     rr = NULL;
1180ad219c80Sstefano_zampini   }
1181ad219c80Sstefano_zampini   if (ll) {
1182ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_SCALAR,Y,y);CHKERRQ(ierr);
1183ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(l,&Y);CHKERRQ(ierr);
1184ad219c80Sstefano_zampini     ierr = VecRestoreArray(ll,&y);CHKERRQ(ierr);
1185ad219c80Sstefano_zampini   }
1186ad219c80Sstefano_zampini   if (rr) {
1187ad219c80Sstefano_zampini     ierr = PetscSFBcastEnd(matis->csf,MPIU_SCALAR,X,x);CHKERRQ(ierr);
1188ad219c80Sstefano_zampini     ierr = VecRestoreArrayRead(r,&X);CHKERRQ(ierr);
1189ad219c80Sstefano_zampini     ierr = VecRestoreArray(rr,&x);CHKERRQ(ierr);
1190ad219c80Sstefano_zampini   }
1191ad219c80Sstefano_zampini   ierr = MatDiagonalScale(matis->A,ll,rr);CHKERRQ(ierr);
1192ad219c80Sstefano_zampini   PetscFunctionReturn(0);
1193ad219c80Sstefano_zampini }
1194ad219c80Sstefano_zampini 
11957fa8f2d3SStefano Zampini static PetscErrorCode MatGetInfo_IS(Mat A,MatInfoType flag,MatInfo *ginfo)
11967fa8f2d3SStefano Zampini {
11977fa8f2d3SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
11987fa8f2d3SStefano Zampini   MatInfo        info;
11997fa8f2d3SStefano Zampini   PetscReal      isend[6],irecv[6];
12007fa8f2d3SStefano Zampini   PetscInt       bs;
12017fa8f2d3SStefano Zampini   PetscErrorCode ierr;
12027fa8f2d3SStefano Zampini 
12037fa8f2d3SStefano Zampini   PetscFunctionBegin;
12047fa8f2d3SStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
12057fa8f2d3SStefano Zampini   if (matis->A->ops->getinfo) {
12067fa8f2d3SStefano Zampini     ierr     = MatGetInfo(matis->A,MAT_LOCAL,&info);CHKERRQ(ierr);
12077fa8f2d3SStefano Zampini     isend[0] = info.nz_used;
12087fa8f2d3SStefano Zampini     isend[1] = info.nz_allocated;
12097fa8f2d3SStefano Zampini     isend[2] = info.nz_unneeded;
12107fa8f2d3SStefano Zampini     isend[3] = info.memory;
12117fa8f2d3SStefano Zampini     isend[4] = info.mallocs;
12127fa8f2d3SStefano Zampini   } else {
12137fa8f2d3SStefano Zampini     isend[0] = 0.;
12147fa8f2d3SStefano Zampini     isend[1] = 0.;
12157fa8f2d3SStefano Zampini     isend[2] = 0.;
12167fa8f2d3SStefano Zampini     isend[3] = 0.;
12177fa8f2d3SStefano Zampini     isend[4] = 0.;
12187fa8f2d3SStefano Zampini   }
12197fa8f2d3SStefano Zampini   isend[5] = matis->A->num_ass;
12207fa8f2d3SStefano Zampini   if (flag == MAT_LOCAL) {
12217fa8f2d3SStefano Zampini     ginfo->nz_used      = isend[0];
12227fa8f2d3SStefano Zampini     ginfo->nz_allocated = isend[1];
12237fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = isend[2];
12247fa8f2d3SStefano Zampini     ginfo->memory       = isend[3];
12257fa8f2d3SStefano Zampini     ginfo->mallocs      = isend[4];
12267fa8f2d3SStefano Zampini     ginfo->assemblies   = isend[5];
12277fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_MAX) {
12287fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,6,MPIU_REAL,MPIU_MAX,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
12297fa8f2d3SStefano Zampini 
12307fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
12317fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
12327fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
12337fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
12347fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
12357fa8f2d3SStefano Zampini     ginfo->assemblies   = irecv[5];
12367fa8f2d3SStefano Zampini   } else if (flag == MAT_GLOBAL_SUM) {
12377fa8f2d3SStefano Zampini     ierr = MPIU_Allreduce(isend,irecv,5,MPIU_REAL,MPIU_SUM,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
12387fa8f2d3SStefano Zampini 
12397fa8f2d3SStefano Zampini     ginfo->nz_used      = irecv[0];
12407fa8f2d3SStefano Zampini     ginfo->nz_allocated = irecv[1];
12417fa8f2d3SStefano Zampini     ginfo->nz_unneeded  = irecv[2];
12427fa8f2d3SStefano Zampini     ginfo->memory       = irecv[3];
12437fa8f2d3SStefano Zampini     ginfo->mallocs      = irecv[4];
12447fa8f2d3SStefano Zampini     ginfo->assemblies   = A->num_ass;
1245d7f69cd0SStefano Zampini   }
1246d7f69cd0SStefano Zampini   ginfo->block_size        = bs;
1247d7f69cd0SStefano Zampini   ginfo->fill_ratio_given  = 0;
1248d7f69cd0SStefano Zampini   ginfo->fill_ratio_needed = 0;
1249d7f69cd0SStefano Zampini   ginfo->factor_mallocs    = 0;
12505e3038f0Sstefano_zampini   PetscFunctionReturn(0);
12515e3038f0Sstefano_zampini }
12525e3038f0Sstefano_zampini 
1253d7f69cd0SStefano Zampini PetscErrorCode MatTranspose_IS(Mat A,MatReuse reuse,Mat *B)
1254d7f69cd0SStefano Zampini {
1255d7f69cd0SStefano Zampini   Mat                    C,lC,lA;
1256d7f69cd0SStefano Zampini   PetscErrorCode         ierr;
1257d7f69cd0SStefano Zampini 
1258d7f69cd0SStefano Zampini   PetscFunctionBegin;
1259cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_INPLACE_MATRIX) {
1260cf37664fSBarry Smith     ISLocalToGlobalMapping rl2g,cl2g;
1261d7f69cd0SStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)A),&C);CHKERRQ(ierr);
1262d7f69cd0SStefano Zampini     ierr = MatSetSizes(C,A->cmap->n,A->rmap->n,A->cmap->N,A->rmap->N);CHKERRQ(ierr);
1263d7f69cd0SStefano Zampini     ierr = MatSetBlockSizes(C,PetscAbs(A->cmap->bs),PetscAbs(A->rmap->bs));CHKERRQ(ierr);
1264d7f69cd0SStefano Zampini     ierr = MatSetType(C,MATIS);CHKERRQ(ierr);
1265d7f69cd0SStefano Zampini     ierr = MatGetLocalToGlobalMapping(A,&rl2g,&cl2g);CHKERRQ(ierr);
1266d7f69cd0SStefano Zampini     ierr = MatSetLocalToGlobalMapping(C,cl2g,rl2g);CHKERRQ(ierr);
1267cf37664fSBarry Smith   } else {
1268cf37664fSBarry Smith     C = *B;
1269d7f69cd0SStefano Zampini   }
1270d7f69cd0SStefano Zampini 
1271d7f69cd0SStefano Zampini   /* perform local transposition */
1272d7f69cd0SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
1273d7f69cd0SStefano Zampini   ierr = MatTranspose(lA,MAT_INITIAL_MATRIX,&lC);CHKERRQ(ierr);
1274d7f69cd0SStefano Zampini   ierr = MatISSetLocalMat(C,lC);CHKERRQ(ierr);
1275d7f69cd0SStefano Zampini   ierr = MatDestroy(&lC);CHKERRQ(ierr);
1276d7f69cd0SStefano Zampini 
1277cf37664fSBarry Smith   if (reuse == MAT_INITIAL_MATRIX || reuse == MAT_REUSE_MATRIX) {
1278d7f69cd0SStefano Zampini     *B = C;
1279d7f69cd0SStefano Zampini   } else {
1280d7f69cd0SStefano Zampini     ierr = MatHeaderMerge(A,&C);CHKERRQ(ierr);
1281d7f69cd0SStefano Zampini   }
12827aa7aec5Sstefano_zampini   ierr = MatAssemblyBegin(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
12837aa7aec5Sstefano_zampini   ierr = MatAssemblyEnd(*B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1284d7f69cd0SStefano Zampini   PetscFunctionReturn(0);
1285d7f69cd0SStefano Zampini }
1286d7f69cd0SStefano Zampini 
12873fd1c9e7SStefano Zampini PetscErrorCode  MatDiagonalSet_IS(Mat A,Vec D,InsertMode insmode)
12883fd1c9e7SStefano Zampini {
12893fd1c9e7SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
12903fd1c9e7SStefano Zampini   PetscErrorCode ierr;
12913fd1c9e7SStefano Zampini 
12923fd1c9e7SStefano Zampini   PetscFunctionBegin;
12934b89b9cdSStefano Zampini   if (D) { /* MatShift_IS pass D = NULL */
12943fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12953fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,D,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
12963fd1c9e7SStefano Zampini   }
12973fd1c9e7SStefano Zampini   ierr = VecPointwiseDivide(is->y,is->y,is->counter);CHKERRQ(ierr);
12983fd1c9e7SStefano Zampini   ierr = MatDiagonalSet(is->A,is->y,insmode);CHKERRQ(ierr);
12993fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
13003fd1c9e7SStefano Zampini }
13013fd1c9e7SStefano Zampini 
13023fd1c9e7SStefano Zampini PetscErrorCode  MatShift_IS(Mat A,PetscScalar a)
13033fd1c9e7SStefano Zampini {
13044b89b9cdSStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
13053fd1c9e7SStefano Zampini   PetscErrorCode ierr;
13063fd1c9e7SStefano Zampini 
13073fd1c9e7SStefano Zampini   PetscFunctionBegin;
13084b89b9cdSStefano Zampini   ierr = VecSet(is->y,a);CHKERRQ(ierr);
13093fd1c9e7SStefano Zampini   ierr = MatDiagonalSet_IS(A,NULL,ADD_VALUES);CHKERRQ(ierr);
13103fd1c9e7SStefano Zampini   PetscFunctionReturn(0);
13113fd1c9e7SStefano Zampini }
13123fd1c9e7SStefano Zampini 
1313f26d0771SStefano Zampini static PetscErrorCode MatSetValuesLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1314f26d0771SStefano Zampini {
1315f26d0771SStefano Zampini   PetscErrorCode ierr;
1316f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1317f26d0771SStefano Zampini 
1318f26d0771SStefano Zampini   PetscFunctionBegin;
1319f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1320f26d0771SStefano 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);
1321f26d0771SStefano Zampini #endif
1322f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
1323f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApply(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
1324b4f971dfSStefano Zampini   ierr = MatSetValuesLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
1325f26d0771SStefano Zampini   PetscFunctionReturn(0);
1326f26d0771SStefano Zampini }
1327f26d0771SStefano Zampini 
1328f26d0771SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_SubMat_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
1329f26d0771SStefano Zampini {
1330f26d0771SStefano Zampini   PetscErrorCode ierr;
1331f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
1332f26d0771SStefano Zampini 
1333f26d0771SStefano Zampini   PetscFunctionBegin;
1334f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
1335f26d0771SStefano 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);
1336f26d0771SStefano Zampini #endif
1337f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->rmap->mapping,m,rows,rows_l);CHKERRQ(ierr);
1338f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingApplyBlock(A->cmap->mapping,n,cols,cols_l);CHKERRQ(ierr);
1339b4f971dfSStefano Zampini   ierr = MatSetValuesBlockedLocal_IS(A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
1340f26d0771SStefano Zampini   PetscFunctionReturn(0);
1341f26d0771SStefano Zampini }
1342f26d0771SStefano Zampini 
1343f0ae7da4SStefano Zampini static PetscErrorCode PetscLayoutMapLocal_Private(PetscLayout map,PetscInt N,const PetscInt idxs[], PetscInt *on,PetscInt **oidxs,PetscInt **ogidxs)
1344a8116848SStefano Zampini {
1345a8116848SStefano Zampini   PetscInt      *owners = map->range;
1346a8116848SStefano Zampini   PetscInt       n      = map->n;
1347a8116848SStefano Zampini   PetscSF        sf;
1348a8116848SStefano Zampini   PetscInt      *lidxs,*work = NULL;
1349a8116848SStefano Zampini   PetscSFNode   *ridxs;
1350a8116848SStefano Zampini   PetscMPIInt    rank;
1351a8116848SStefano Zampini   PetscInt       r, p = 0, len = 0;
1352a8116848SStefano Zampini   PetscErrorCode ierr;
1353a8116848SStefano Zampini 
1354a8116848SStefano Zampini   PetscFunctionBegin;
1355fd3a879cSJed Brown   if (on) *on = 0;              /* squelch -Wmaybe-uninitialized */
1356a8116848SStefano Zampini   /* Create SF where leaves are input idxs and roots are owned idxs (code adapted from MatZeroRowsMapLocal_Private) */
1357a8116848SStefano Zampini   ierr = MPI_Comm_rank(map->comm,&rank);CHKERRQ(ierr);
1358a8116848SStefano Zampini   ierr = PetscMalloc1(n,&lidxs);CHKERRQ(ierr);
1359a8116848SStefano Zampini   for (r = 0; r < n; ++r) lidxs[r] = -1;
1360a8116848SStefano Zampini   ierr = PetscMalloc1(N,&ridxs);CHKERRQ(ierr);
1361a8116848SStefano Zampini   for (r = 0; r < N; ++r) {
1362a8116848SStefano Zampini     const PetscInt idx = idxs[r];
1363a8116848SStefano 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);
1364a8116848SStefano Zampini     if (idx < owners[p] || owners[p+1] <= idx) { /* short-circuit the search if the last p owns this idx too */
1365a8116848SStefano Zampini       ierr = PetscLayoutFindOwner(map,idx,&p);CHKERRQ(ierr);
1366a8116848SStefano Zampini     }
1367a8116848SStefano Zampini     ridxs[r].rank = p;
1368a8116848SStefano Zampini     ridxs[r].index = idxs[r] - owners[p];
1369a8116848SStefano Zampini   }
1370a8116848SStefano Zampini   ierr = PetscSFCreate(map->comm,&sf);CHKERRQ(ierr);
1371a8116848SStefano Zampini   ierr = PetscSFSetGraph(sf,n,N,NULL,PETSC_OWN_POINTER,ridxs,PETSC_OWN_POINTER);CHKERRQ(ierr);
1372a8116848SStefano Zampini   ierr = PetscSFReduceBegin(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
1373a8116848SStefano Zampini   ierr = PetscSFReduceEnd(sf,MPIU_INT,(PetscInt*)idxs,lidxs,MPI_LOR);CHKERRQ(ierr);
1374f0ae7da4SStefano Zampini   if (ogidxs) { /* communicate global idxs */
1375a8116848SStefano Zampini     PetscInt cum = 0,start,*work2;
1376f0ae7da4SStefano Zampini 
1377f0ae7da4SStefano Zampini     ierr = PetscMalloc1(n,&work);CHKERRQ(ierr);
1378a8116848SStefano Zampini     ierr = PetscCalloc1(N,&work2);CHKERRQ(ierr);
1379a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) cum++;
1380a8116848SStefano Zampini     ierr = MPI_Scan(&cum,&start,1,MPIU_INT,MPI_SUM,map->comm);CHKERRQ(ierr);
1381a8116848SStefano Zampini     start -= cum;
1382a8116848SStefano Zampini     cum = 0;
1383a8116848SStefano Zampini     for (r = 0; r < N; ++r) if (idxs[r] >=0) work2[r] = start+cum++;
1384a8116848SStefano Zampini     ierr = PetscSFReduceBegin(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
1385a8116848SStefano Zampini     ierr = PetscSFReduceEnd(sf,MPIU_INT,work2,work,MPIU_REPLACE);CHKERRQ(ierr);
1386a8116848SStefano Zampini     ierr = PetscFree(work2);CHKERRQ(ierr);
1387a8116848SStefano Zampini   }
1388a8116848SStefano Zampini   ierr = PetscSFDestroy(&sf);CHKERRQ(ierr);
1389a8116848SStefano Zampini   /* Compress and put in indices */
1390a8116848SStefano Zampini   for (r = 0; r < n; ++r)
1391a8116848SStefano Zampini     if (lidxs[r] >= 0) {
1392a8116848SStefano Zampini       if (work) work[len] = work[r];
1393a8116848SStefano Zampini       lidxs[len++] = r;
1394a8116848SStefano Zampini     }
1395a8116848SStefano Zampini   if (on) *on = len;
1396a8116848SStefano Zampini   if (oidxs) *oidxs = lidxs;
1397a8116848SStefano Zampini   if (ogidxs) *ogidxs = work;
1398a8116848SStefano Zampini   PetscFunctionReturn(0);
1399a8116848SStefano Zampini }
1400a8116848SStefano Zampini 
14017dae84e0SHong Zhang static PetscErrorCode MatCreateSubMatrix_IS(Mat mat,IS irow,IS icol,MatReuse scall,Mat *newmat)
1402a8116848SStefano Zampini {
1403a8116848SStefano Zampini   Mat               locmat,newlocmat;
1404a8116848SStefano Zampini   Mat_IS            *newmatis;
1405a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
1406a8116848SStefano Zampini   Vec               rtest,ltest;
1407a8116848SStefano Zampini   const PetscScalar *array;
1408a8116848SStefano Zampini #endif
1409a8116848SStefano Zampini   const PetscInt    *idxs;
1410a8116848SStefano Zampini   PetscInt          i,m,n;
1411a8116848SStefano Zampini   PetscErrorCode    ierr;
1412a8116848SStefano Zampini 
1413a8116848SStefano Zampini   PetscFunctionBegin;
1414a8116848SStefano Zampini   if (scall == MAT_REUSE_MATRIX) {
1415a8116848SStefano Zampini     PetscBool ismatis;
1416a8116848SStefano Zampini 
1417a8116848SStefano Zampini     ierr = PetscObjectTypeCompare((PetscObject)*newmat,MATIS,&ismatis);CHKERRQ(ierr);
1418a8116848SStefano Zampini     if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Not of MATIS type");
1419a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
1420a8116848SStefano Zampini     if (!newmatis->getsub_ris) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local row IS");
1421a8116848SStefano Zampini     if (!newmatis->getsub_cis) SETERRQ(PetscObjectComm((PetscObject)*newmat),PETSC_ERR_ARG_WRONG,"Cannot reuse matrix! Misses local col IS");
1422a8116848SStefano Zampini   }
1423a8116848SStefano Zampini   /* irow and icol may not have duplicate entries */
1424a8116848SStefano Zampini #if defined(PETSC_USE_DEBUG)
1425a8116848SStefano Zampini   ierr = MatCreateVecs(mat,&ltest,&rtest);CHKERRQ(ierr);
1426a8116848SStefano Zampini   ierr = ISGetLocalSize(irow,&n);CHKERRQ(ierr);
1427a8116848SStefano Zampini   ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
1428a8116848SStefano Zampini   for (i=0;i<n;i++) {
1429a8116848SStefano Zampini     ierr = VecSetValue(rtest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
1430a8116848SStefano Zampini   }
1431a8116848SStefano Zampini   ierr = VecAssemblyBegin(rtest);CHKERRQ(ierr);
1432a8116848SStefano Zampini   ierr = VecAssemblyEnd(rtest);CHKERRQ(ierr);
1433a8116848SStefano Zampini   ierr = VecGetLocalSize(rtest,&n);CHKERRQ(ierr);
1434a8116848SStefano Zampini   ierr = VecGetOwnershipRange(rtest,&m,NULL);CHKERRQ(ierr);
1435a8116848SStefano Zampini   ierr = VecGetArrayRead(rtest,&array);CHKERRQ(ierr);
1436fd479f66SMatthew 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]));
1437a8116848SStefano Zampini   ierr = VecRestoreArrayRead(rtest,&array);CHKERRQ(ierr);
1438a8116848SStefano Zampini   ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
1439a8116848SStefano Zampini   ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
1440a8116848SStefano Zampini   ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
1441a8116848SStefano Zampini   for (i=0;i<n;i++) {
1442a8116848SStefano Zampini     ierr = VecSetValue(ltest,idxs[i],1.0,ADD_VALUES);CHKERRQ(ierr);
1443a8116848SStefano Zampini   }
1444a8116848SStefano Zampini   ierr = VecAssemblyBegin(ltest);CHKERRQ(ierr);
1445a8116848SStefano Zampini   ierr = VecAssemblyEnd(ltest);CHKERRQ(ierr);
1446a8116848SStefano Zampini   ierr = VecGetLocalSize(ltest,&n);CHKERRQ(ierr);
1447a8116848SStefano Zampini   ierr = VecGetOwnershipRange(ltest,&m,NULL);CHKERRQ(ierr);
1448a8116848SStefano Zampini   ierr = VecGetArrayRead(ltest,&array);CHKERRQ(ierr);
1449fd479f66SMatthew 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]));
1450a8116848SStefano Zampini   ierr = VecRestoreArrayRead(ltest,&array);CHKERRQ(ierr);
1451a8116848SStefano Zampini   ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
1452a8116848SStefano Zampini   ierr = VecDestroy(&rtest);CHKERRQ(ierr);
1453a8116848SStefano Zampini   ierr = VecDestroy(&ltest);CHKERRQ(ierr);
1454a8116848SStefano Zampini #endif
1455a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1456a8116848SStefano Zampini     Mat_IS                 *matis = (Mat_IS*)mat->data;
1457a8116848SStefano Zampini     ISLocalToGlobalMapping rl2g;
1458a8116848SStefano Zampini     IS                     is;
1459a8116848SStefano Zampini     PetscInt               *lidxs,*lgidxs,*newgidxs;
1460306cf5c7SStefano Zampini     PetscInt               ll,newloc,irbs,icbs,arbs,acbs,rbs,cbs;
146194342113SStefano Zampini     PetscBool              cong;
1462a8116848SStefano Zampini     MPI_Comm               comm;
1463a8116848SStefano Zampini 
1464a8116848SStefano Zampini     ierr = PetscObjectGetComm((PetscObject)mat,&comm);CHKERRQ(ierr);
1465306cf5c7SStefano Zampini     ierr = MatGetBlockSizes(mat,&arbs,&acbs);CHKERRQ(ierr);
1466306cf5c7SStefano Zampini     ierr = ISGetBlockSize(irow,&irbs);CHKERRQ(ierr);
1467306cf5c7SStefano Zampini     ierr = ISGetBlockSize(icol,&icbs);CHKERRQ(ierr);
1468306cf5c7SStefano Zampini     rbs  = arbs == irbs ? irbs : 1;
1469306cf5c7SStefano Zampini     cbs  = acbs == icbs ? icbs : 1;
1470a8116848SStefano Zampini     ierr = ISGetLocalSize(irow,&m);CHKERRQ(ierr);
1471a8116848SStefano Zampini     ierr = ISGetLocalSize(icol,&n);CHKERRQ(ierr);
1472a8116848SStefano Zampini     ierr = MatCreate(comm,newmat);CHKERRQ(ierr);
1473a8116848SStefano Zampini     ierr = MatSetType(*newmat,MATIS);CHKERRQ(ierr);
1474a8116848SStefano Zampini     ierr = MatSetSizes(*newmat,m,n,PETSC_DECIDE,PETSC_DECIDE);CHKERRQ(ierr);
1475306cf5c7SStefano Zampini     ierr = MatSetBlockSizes(*newmat,rbs,cbs);CHKERRQ(ierr);
1476a8116848SStefano Zampini     /* communicate irow to their owners in the layout */
1477a8116848SStefano Zampini     ierr = ISGetIndices(irow,&idxs);CHKERRQ(ierr);
1478f0ae7da4SStefano Zampini     ierr = PetscLayoutMapLocal_Private(mat->rmap,m,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
1479a8116848SStefano Zampini     ierr = ISRestoreIndices(irow,&idxs);CHKERRQ(ierr);
14803d996552SStefano Zampini     ierr = MatISSetUpSF(mat);CHKERRQ(ierr);
14813d996552SStefano Zampini     ierr = PetscMemzero(matis->sf_rootdata,matis->sf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
1482a8116848SStefano Zampini     for (i=0;i<ll;i++) matis->sf_rootdata[lidxs[i]] = lgidxs[i]+1;
1483a8116848SStefano Zampini     ierr = PetscFree(lidxs);CHKERRQ(ierr);
1484a8116848SStefano Zampini     ierr = PetscFree(lgidxs);CHKERRQ(ierr);
1485a8116848SStefano Zampini     ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
1486a8116848SStefano Zampini     ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
14873d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++) if (matis->sf_leafdata[i]) newloc++;
1488a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
1489a8116848SStefano Zampini     ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
14903d996552SStefano Zampini     for (i=0,newloc=0;i<matis->sf->nleaves;i++)
1491a8116848SStefano Zampini       if (matis->sf_leafdata[i]) {
1492a8116848SStefano Zampini         lidxs[newloc] = i;
1493a8116848SStefano Zampini         newgidxs[newloc++] = matis->sf_leafdata[i]-1;
1494a8116848SStefano Zampini       }
1495a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1496a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
1497306cf5c7SStefano Zampini     ierr = ISLocalToGlobalMappingSetBlockSize(rl2g,rbs);CHKERRQ(ierr);
1498a8116848SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
1499a8116848SStefano Zampini     /* local is to extract local submatrix */
1500a8116848SStefano Zampini     newmatis = (Mat_IS*)(*newmat)->data;
1501a8116848SStefano Zampini     ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_ris);CHKERRQ(ierr);
150294342113SStefano Zampini     ierr = MatHasCongruentLayouts(mat,&cong);CHKERRQ(ierr);
150394342113SStefano Zampini     if (cong && irow == icol && matis->csf == matis->sf) {
1504a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,rl2g);CHKERRQ(ierr);
1505a8116848SStefano Zampini       ierr = PetscObjectReference((PetscObject)newmatis->getsub_ris);CHKERRQ(ierr);
1506a8116848SStefano Zampini       newmatis->getsub_cis = newmatis->getsub_ris;
1507a8116848SStefano Zampini     } else {
1508a8116848SStefano Zampini       ISLocalToGlobalMapping cl2g;
1509a8116848SStefano Zampini 
1510a8116848SStefano Zampini       /* communicate icol to their owners in the layout */
1511a8116848SStefano Zampini       ierr = ISGetIndices(icol,&idxs);CHKERRQ(ierr);
1512f0ae7da4SStefano Zampini       ierr = PetscLayoutMapLocal_Private(mat->cmap,n,idxs,&ll,&lidxs,&lgidxs);CHKERRQ(ierr);
1513a8116848SStefano Zampini       ierr = ISRestoreIndices(icol,&idxs);CHKERRQ(ierr);
15143d996552SStefano Zampini       ierr = PetscMemzero(matis->csf_rootdata,matis->csf->nroots*sizeof(PetscInt));CHKERRQ(ierr);
1515a8116848SStefano Zampini       for (i=0;i<ll;i++) matis->csf_rootdata[lidxs[i]] = lgidxs[i]+1;
1516a8116848SStefano Zampini       ierr = PetscFree(lidxs);CHKERRQ(ierr);
1517a8116848SStefano Zampini       ierr = PetscFree(lgidxs);CHKERRQ(ierr);
1518a8116848SStefano Zampini       ierr = PetscSFBcastBegin(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
1519a8116848SStefano Zampini       ierr = PetscSFBcastEnd(matis->csf,MPIU_INT,matis->csf_rootdata,matis->csf_leafdata);CHKERRQ(ierr);
15203d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++) if (matis->csf_leafdata[i]) newloc++;
1521a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&newgidxs);CHKERRQ(ierr);
1522a8116848SStefano Zampini       ierr = PetscMalloc1(newloc,&lidxs);CHKERRQ(ierr);
15233d996552SStefano Zampini       for (i=0,newloc=0;i<matis->csf->nleaves;i++)
1524a8116848SStefano Zampini         if (matis->csf_leafdata[i]) {
1525a8116848SStefano Zampini           lidxs[newloc] = i;
1526a8116848SStefano Zampini           newgidxs[newloc++] = matis->csf_leafdata[i]-1;
1527a8116848SStefano Zampini         }
1528a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,newgidxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
1529a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
1530306cf5c7SStefano Zampini       ierr = ISLocalToGlobalMappingSetBlockSize(cl2g,cbs);CHKERRQ(ierr);
1531a8116848SStefano Zampini       ierr = ISDestroy(&is);CHKERRQ(ierr);
1532a8116848SStefano Zampini       /* local is to extract local submatrix */
1533a8116848SStefano Zampini       ierr = ISCreateGeneral(comm,newloc,lidxs,PETSC_OWN_POINTER,&newmatis->getsub_cis);CHKERRQ(ierr);
1534a8116848SStefano Zampini       ierr = MatSetLocalToGlobalMapping(*newmat,rl2g,cl2g);CHKERRQ(ierr);
1535a8116848SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
1536a8116848SStefano Zampini     }
1537a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
1538a8116848SStefano Zampini   } else {
1539a8116848SStefano Zampini     ierr = MatISGetLocalMat(*newmat,&newlocmat);CHKERRQ(ierr);
1540a8116848SStefano Zampini   }
1541a8116848SStefano Zampini   ierr = MatISGetLocalMat(mat,&locmat);CHKERRQ(ierr);
1542a8116848SStefano Zampini   newmatis = (Mat_IS*)(*newmat)->data;
15437dae84e0SHong Zhang   ierr = MatCreateSubMatrix(locmat,newmatis->getsub_ris,newmatis->getsub_cis,scall,&newlocmat);CHKERRQ(ierr);
1544a8116848SStefano Zampini   if (scall == MAT_INITIAL_MATRIX) {
1545a8116848SStefano Zampini     ierr = MatISSetLocalMat(*newmat,newlocmat);CHKERRQ(ierr);
1546a8116848SStefano Zampini     ierr = MatDestroy(&newlocmat);CHKERRQ(ierr);
1547a8116848SStefano Zampini   }
1548a8116848SStefano Zampini   ierr = MatAssemblyBegin(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1549a8116848SStefano Zampini   ierr = MatAssemblyEnd(*newmat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
1550a8116848SStefano Zampini   PetscFunctionReturn(0);
1551a8116848SStefano Zampini }
1552a8116848SStefano Zampini 
1553a8116848SStefano Zampini static PetscErrorCode MatCopy_IS(Mat A,Mat B,MatStructure str)
15542b404112SStefano Zampini {
15552b404112SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data,*b;
15562b404112SStefano Zampini   PetscBool      ismatis;
15572b404112SStefano Zampini   PetscErrorCode ierr;
15582b404112SStefano Zampini 
15592b404112SStefano Zampini   PetscFunctionBegin;
15602b404112SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)B,MATIS,&ismatis);CHKERRQ(ierr);
15612b404112SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"Need to be implemented");
15622b404112SStefano Zampini   b = (Mat_IS*)B->data;
15632b404112SStefano Zampini   ierr = MatCopy(a->A,b->A,str);CHKERRQ(ierr);
1564cdc753b6SBarry Smith   ierr = PetscObjectStateIncrease((PetscObject)B);CHKERRQ(ierr);
15652b404112SStefano Zampini   PetscFunctionReturn(0);
15662b404112SStefano Zampini }
15672b404112SStefano Zampini 
1568a8116848SStefano Zampini static PetscErrorCode MatMissingDiagonal_IS(Mat A,PetscBool  *missing,PetscInt *d)
15696bd84002SStefano Zampini {
1570527b2640SStefano Zampini   Vec               v;
1571527b2640SStefano Zampini   const PetscScalar *array;
1572527b2640SStefano Zampini   PetscInt          i,n;
15736bd84002SStefano Zampini   PetscErrorCode    ierr;
15746bd84002SStefano Zampini 
15756bd84002SStefano Zampini   PetscFunctionBegin;
1576527b2640SStefano Zampini   *missing = PETSC_FALSE;
1577527b2640SStefano Zampini   ierr = MatCreateVecs(A,NULL,&v);CHKERRQ(ierr);
1578527b2640SStefano Zampini   ierr = MatGetDiagonal(A,v);CHKERRQ(ierr);
1579527b2640SStefano Zampini   ierr = VecGetLocalSize(v,&n);CHKERRQ(ierr);
1580527b2640SStefano Zampini   ierr = VecGetArrayRead(v,&array);CHKERRQ(ierr);
1581527b2640SStefano Zampini   for (i=0;i<n;i++) if (array[i] == 0.) break;
1582527b2640SStefano Zampini   ierr = VecRestoreArrayRead(v,&array);CHKERRQ(ierr);
1583527b2640SStefano Zampini   ierr = VecDestroy(&v);CHKERRQ(ierr);
1584527b2640SStefano Zampini   if (i != n) *missing = PETSC_TRUE;
1585527b2640SStefano Zampini   if (d) {
1586527b2640SStefano Zampini     *d = -1;
1587527b2640SStefano Zampini     if (*missing) {
1588527b2640SStefano Zampini       PetscInt rstart;
1589527b2640SStefano Zampini       ierr = MatGetOwnershipRange(A,&rstart,NULL);CHKERRQ(ierr);
1590527b2640SStefano Zampini       *d = i+rstart;
1591527b2640SStefano Zampini     }
1592527b2640SStefano Zampini   }
15936bd84002SStefano Zampini   PetscFunctionReturn(0);
15946bd84002SStefano Zampini }
15956bd84002SStefano Zampini 
1596cf0a3239SStefano Zampini static PetscErrorCode MatISSetUpSF_IS(Mat B)
159728f4e0baSStefano Zampini {
159828f4e0baSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
159928f4e0baSStefano Zampini   const PetscInt *gidxs;
16004f2d7cafSStefano Zampini   PetscInt       nleaves;
160128f4e0baSStefano Zampini   PetscErrorCode ierr;
160228f4e0baSStefano Zampini 
160328f4e0baSStefano Zampini   PetscFunctionBegin;
16044f2d7cafSStefano Zampini   if (matis->sf) PetscFunctionReturn(0);
160575d48cdbSStefano Zampini   ierr = PetscLayoutSetUp(B->rmap);CHKERRQ(ierr);
160675d48cdbSStefano Zampini   ierr = PetscLayoutSetUp(B->cmap);CHKERRQ(ierr);
160728f4e0baSStefano Zampini   ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->sf);CHKERRQ(ierr);
16083bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
16094f2d7cafSStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(B->rmap->mapping,&nleaves);CHKERRQ(ierr);
16104f2d7cafSStefano Zampini   ierr = PetscSFSetGraphLayout(matis->sf,B->rmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
16113bbff08aSStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(B->rmap->mapping,&gidxs);CHKERRQ(ierr);
16124f2d7cafSStefano Zampini   ierr = PetscMalloc2(matis->sf->nroots,&matis->sf_rootdata,matis->sf->nleaves,&matis->sf_leafdata);CHKERRQ(ierr);
1613a8116848SStefano Zampini   if (B->rmap->mapping != B->cmap->mapping) { /* setup SF for columns */
16143d996552SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(B->cmap->mapping,&nleaves);CHKERRQ(ierr);
1615a8116848SStefano Zampini     ierr = PetscSFCreate(PetscObjectComm((PetscObject)B),&matis->csf);CHKERRQ(ierr);
1616a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
16173d996552SStefano Zampini     ierr = PetscSFSetGraphLayout(matis->csf,B->cmap,nleaves,NULL,PETSC_OWN_POINTER,gidxs);CHKERRQ(ierr);
1618a8116848SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(B->cmap->mapping,&gidxs);CHKERRQ(ierr);
16193d996552SStefano Zampini     ierr = PetscMalloc2(matis->csf->nroots,&matis->csf_rootdata,matis->csf->nleaves,&matis->csf_leafdata);CHKERRQ(ierr);
1620a8116848SStefano Zampini   } else {
1621a8116848SStefano Zampini     matis->csf = matis->sf;
1622a8116848SStefano Zampini     matis->csf_leafdata = matis->sf_leafdata;
1623a8116848SStefano Zampini     matis->csf_rootdata = matis->sf_rootdata;
1624a8116848SStefano Zampini   }
162528f4e0baSStefano Zampini   PetscFunctionReturn(0);
162628f4e0baSStefano Zampini }
16272e1947a5SStefano Zampini 
1628eb82efa4SStefano Zampini /*@
162975d48cdbSStefano Zampini    MatISStoreL2L - Store local-to-local operators during the Galerkin process of MatPtAP.
163075d48cdbSStefano Zampini 
163175d48cdbSStefano Zampini    Collective on MPI_Comm
163275d48cdbSStefano Zampini 
163375d48cdbSStefano Zampini    Input Parameters:
163475d48cdbSStefano Zampini +  A - the matrix
163575d48cdbSStefano Zampini -  store - the boolean flag
163675d48cdbSStefano Zampini 
163775d48cdbSStefano Zampini    Level: advanced
163875d48cdbSStefano Zampini 
163975d48cdbSStefano Zampini    Notes:
164075d48cdbSStefano Zampini 
164175d48cdbSStefano Zampini .keywords: matrix
164275d48cdbSStefano Zampini 
164375d48cdbSStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatPtAP()
164475d48cdbSStefano Zampini @*/
164575d48cdbSStefano Zampini PetscErrorCode  MatISStoreL2L(Mat A, PetscBool store)
164675d48cdbSStefano Zampini {
164775d48cdbSStefano Zampini   PetscErrorCode ierr;
164875d48cdbSStefano Zampini 
164975d48cdbSStefano Zampini   PetscFunctionBegin;
165075d48cdbSStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
165175d48cdbSStefano Zampini   PetscValidType(A,1);
165275d48cdbSStefano Zampini   PetscValidLogicalCollectiveBool(A,store,2);
165375d48cdbSStefano Zampini   ierr = PetscTryMethod(A,"MatISStoreL2L_C",(Mat,PetscBool),(A,store));CHKERRQ(ierr);
165475d48cdbSStefano Zampini   PetscFunctionReturn(0);
165575d48cdbSStefano Zampini }
165675d48cdbSStefano Zampini 
165775d48cdbSStefano Zampini static PetscErrorCode MatISStoreL2L_IS(Mat A, PetscBool store)
165875d48cdbSStefano Zampini {
165975d48cdbSStefano Zampini   Mat_IS         *matis = (Mat_IS*)(A->data);
166075d48cdbSStefano Zampini   PetscErrorCode ierr;
166175d48cdbSStefano Zampini 
166275d48cdbSStefano Zampini   PetscFunctionBegin;
166375d48cdbSStefano Zampini   matis->storel2l = store;
166475d48cdbSStefano Zampini   if (!store) {
166575d48cdbSStefano Zampini     ierr = PetscObjectCompose((PetscObject)(A),"_MatIS_PtAP_l2l",NULL);CHKERRQ(ierr);
166675d48cdbSStefano Zampini   }
166775d48cdbSStefano Zampini   PetscFunctionReturn(0);
166875d48cdbSStefano Zampini }
166975d48cdbSStefano Zampini 
167075d48cdbSStefano Zampini /*@
1671f03112d0SStefano Zampini    MatISFixLocalEmpty - Compress out zero local rows from the local matrices
1672f03112d0SStefano Zampini 
1673f03112d0SStefano Zampini    Collective on MPI_Comm
1674f03112d0SStefano Zampini 
1675f03112d0SStefano Zampini    Input Parameters:
1676f03112d0SStefano Zampini +  A - the matrix
1677f03112d0SStefano Zampini -  fix - the boolean flag
1678f03112d0SStefano Zampini 
1679f03112d0SStefano Zampini    Level: advanced
1680f03112d0SStefano Zampini 
1681f03112d0SStefano Zampini    Notes: When fix is true, new local matrices and l2g maps are generated during the final assembly process.
1682f03112d0SStefano Zampini 
1683f03112d0SStefano Zampini .keywords: matrix
1684f03112d0SStefano Zampini 
1685f03112d0SStefano Zampini .seealso: MatCreate(), MatCreateIS(), MatISSetPreallocation(), MatAssemblyEnd(), MAT_FINAL_ASSEMBLY
1686f03112d0SStefano Zampini @*/
1687f03112d0SStefano Zampini PetscErrorCode  MatISFixLocalEmpty(Mat A, PetscBool fix)
1688f03112d0SStefano Zampini {
1689f03112d0SStefano Zampini   PetscErrorCode ierr;
1690f03112d0SStefano Zampini 
1691f03112d0SStefano Zampini   PetscFunctionBegin;
1692f03112d0SStefano Zampini   PetscValidHeaderSpecific(A,MAT_CLASSID,1);
1693f03112d0SStefano Zampini   PetscValidType(A,1);
1694f03112d0SStefano Zampini   PetscValidLogicalCollectiveBool(A,fix,2);
1695f03112d0SStefano Zampini   ierr = PetscTryMethod(A,"MatISFixLocalEmpty_C",(Mat,PetscBool),(A,fix));CHKERRQ(ierr);
1696f03112d0SStefano Zampini   PetscFunctionReturn(0);
1697f03112d0SStefano Zampini }
1698f03112d0SStefano Zampini 
1699f03112d0SStefano Zampini static PetscErrorCode MatISFixLocalEmpty_IS(Mat A, PetscBool fix)
1700f03112d0SStefano Zampini {
1701f03112d0SStefano Zampini   Mat_IS *matis = (Mat_IS*)(A->data);
1702f03112d0SStefano Zampini 
1703f03112d0SStefano Zampini   PetscFunctionBegin;
1704f03112d0SStefano Zampini   matis->locempty = fix;
1705f03112d0SStefano Zampini   PetscFunctionReturn(0);
1706f03112d0SStefano Zampini }
1707f03112d0SStefano Zampini 
1708f03112d0SStefano Zampini /*@
1709a88811baSStefano Zampini    MatISSetPreallocation - Preallocates memory for a MATIS parallel matrix.
1710a88811baSStefano Zampini 
1711a88811baSStefano Zampini    Collective on MPI_Comm
1712a88811baSStefano Zampini 
1713a88811baSStefano Zampini    Input Parameters:
1714a88811baSStefano Zampini +  B - the matrix
1715a88811baSStefano Zampini .  d_nz  - number of nonzeros per row in DIAGONAL portion of local submatrix
1716a88811baSStefano Zampini            (same value is used for all local rows)
1717a88811baSStefano Zampini .  d_nnz - array containing the number of nonzeros in the various rows of the
1718a88811baSStefano Zampini            DIAGONAL portion of the local submatrix (possibly different for each row)
1719a88811baSStefano Zampini            or NULL, if d_nz is used to specify the nonzero structure.
1720a88811baSStefano Zampini            The size of this array is equal to the number of local rows, i.e 'm'.
1721a88811baSStefano Zampini            For matrices that will be factored, you must leave room for (and set)
1722a88811baSStefano Zampini            the diagonal entry even if it is zero.
1723a88811baSStefano Zampini .  o_nz  - number of nonzeros per row in the OFF-DIAGONAL portion of local
1724a88811baSStefano Zampini            submatrix (same value is used for all local rows).
1725a88811baSStefano Zampini -  o_nnz - array containing the number of nonzeros in the various rows of the
1726a88811baSStefano Zampini            OFF-DIAGONAL portion of the local submatrix (possibly different for
1727a88811baSStefano Zampini            each row) or NULL, if o_nz is used to specify the nonzero
1728a88811baSStefano Zampini            structure. The size of this array is equal to the number
1729a88811baSStefano Zampini            of local rows, i.e 'm'.
1730a88811baSStefano Zampini 
1731a88811baSStefano Zampini    If the *_nnz parameter is given then the *_nz parameter is ignored
1732a88811baSStefano Zampini 
1733a88811baSStefano Zampini    Level: intermediate
1734a88811baSStefano Zampini 
173595452b02SPatrick Sanan    Notes:
173695452b02SPatrick Sanan     This function has the same interface as the MPIAIJ preallocation routine in order to simplify the transition
1737a88811baSStefano Zampini           from the asssembled format to the unassembled one. It overestimates the preallocation of MATIS local
1738a88811baSStefano Zampini           matrices; for exact preallocation, the user should set the preallocation directly on local matrix objects.
1739a88811baSStefano Zampini 
1740a88811baSStefano Zampini .keywords: matrix
1741a88811baSStefano Zampini 
17423c212e90SHong Zhang .seealso: MatCreate(), MatCreateIS(), MatMPIAIJSetPreallocation(), MatISGetLocalMat(), MATIS
1743a88811baSStefano Zampini @*/
17442e1947a5SStefano Zampini PetscErrorCode  MatISSetPreallocation(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
17452e1947a5SStefano Zampini {
17462e1947a5SStefano Zampini   PetscErrorCode ierr;
17472e1947a5SStefano Zampini 
17482e1947a5SStefano Zampini   PetscFunctionBegin;
17492e1947a5SStefano Zampini   PetscValidHeaderSpecific(B,MAT_CLASSID,1);
17502e1947a5SStefano Zampini   PetscValidType(B,1);
17512e1947a5SStefano Zampini   ierr = PetscTryMethod(B,"MatISSetPreallocation_C",(Mat,PetscInt,const PetscInt[],PetscInt,const PetscInt[]),(B,d_nz,d_nnz,o_nz,o_nnz));CHKERRQ(ierr);
17522e1947a5SStefano Zampini   PetscFunctionReturn(0);
17532e1947a5SStefano Zampini }
17542e1947a5SStefano Zampini 
1755844bd0d7SStefano Zampini /* this is used by DMDA */
1756844bd0d7SStefano Zampini PETSC_EXTERN PetscErrorCode  MatISSetPreallocation_IS(Mat B,PetscInt d_nz,const PetscInt d_nnz[],PetscInt o_nz,const PetscInt o_nnz[])
17572e1947a5SStefano Zampini {
17582e1947a5SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(B->data);
175928f4e0baSStefano Zampini   PetscInt       bs,i,nlocalcols;
17602e1947a5SStefano Zampini   PetscErrorCode ierr;
17612e1947a5SStefano Zampini 
17622e1947a5SStefano Zampini   PetscFunctionBegin;
17636c4ed002SBarry Smith   if (!matis->A) SETERRQ(PetscObjectComm((PetscObject)B),PETSC_ERR_SUP,"You should first call MatSetLocalToGlobalMapping");
1764cf0a3239SStefano Zampini   ierr = MatISSetUpSF(B);CHKERRQ(ierr);
17654f2d7cafSStefano Zampini 
17664f2d7cafSStefano Zampini   if (!d_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nz;
17674f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] = d_nnz[i];
17684f2d7cafSStefano Zampini 
17694f2d7cafSStefano Zampini   if (!o_nnz) for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nz;
17704f2d7cafSStefano Zampini   else for (i=0;i<matis->sf->nroots;i++) matis->sf_rootdata[i] += o_nnz[i];
17714f2d7cafSStefano Zampini 
177228f4e0baSStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
177328f4e0baSStefano Zampini   ierr = MatGetSize(matis->A,NULL,&nlocalcols);CHKERRQ(ierr);
177428f4e0baSStefano Zampini   ierr = MatGetBlockSize(matis->A,&bs);CHKERRQ(ierr);
177528f4e0baSStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
17764f2d7cafSStefano Zampini 
17774f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves;i++) matis->sf_leafdata[i] = PetscMin(matis->sf_leafdata[i],nlocalcols);
177828f4e0baSStefano Zampini   ierr = MatSeqAIJSetPreallocation(matis->A,0,matis->sf_leafdata);CHKERRQ(ierr);
17790f2f62c7SStefano Zampini #if defined(PETSC_HAVE_HYPRE)
17800f2f62c7SStefano Zampini   ierr = MatHYPRESetPreallocation(matis->A,0,matis->sf_leafdata,0,NULL);CHKERRQ(ierr);
17810f2f62c7SStefano Zampini #endif
17824f2d7cafSStefano Zampini 
17834f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i*bs]/bs;
178428f4e0baSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
17854f2d7cafSStefano Zampini 
17864f2d7cafSStefano Zampini   for (i=0;i<matis->sf->nleaves/bs;i++) matis->sf_leafdata[i] = matis->sf_leafdata[i]-i;
178728f4e0baSStefano Zampini   ierr = MatSeqSBAIJSetPreallocation(matis->A,bs,0,matis->sf_leafdata);CHKERRQ(ierr);
17880f2f62c7SStefano Zampini 
17890f2f62c7SStefano Zampini   /* for other matrix types */
17900f2f62c7SStefano Zampini   ierr = MatSetUp(matis->A);CHKERRQ(ierr);
17912e1947a5SStefano Zampini   PetscFunctionReturn(0);
17922e1947a5SStefano Zampini }
1793b4319ba4SBarry Smith 
17943927de2eSStefano Zampini PETSC_EXTERN PetscErrorCode MatISSetMPIXAIJPreallocation_Private(Mat A, Mat B, PetscBool maxreduce)
17953927de2eSStefano Zampini {
17963927de2eSStefano Zampini   Mat_IS          *matis = (Mat_IS*)(A->data);
17973927de2eSStefano Zampini   PetscInt        *my_dnz,*my_onz,*dnz,*onz,*mat_ranges,*row_ownership;
1798ecf5a873SStefano Zampini   const PetscInt  *global_indices_r,*global_indices_c;
17993927de2eSStefano Zampini   PetscInt        i,j,bs,rows,cols;
18003927de2eSStefano Zampini   PetscInt        lrows,lcols;
18013927de2eSStefano Zampini   PetscInt        local_rows,local_cols;
1802f03112d0SStefano Zampini   PetscMPIInt     size;
18033927de2eSStefano Zampini   PetscBool       isdense,issbaij;
18043927de2eSStefano Zampini   PetscErrorCode  ierr;
18053927de2eSStefano Zampini 
18063927de2eSStefano Zampini   PetscFunctionBegin;
1807f03112d0SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)A),&size);CHKERRQ(ierr);
18083927de2eSStefano Zampini   ierr = MatGetSize(A,&rows,&cols);CHKERRQ(ierr);
18093927de2eSStefano Zampini   ierr = MatGetBlockSize(A,&bs);CHKERRQ(ierr);
18103927de2eSStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
18113927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isdense);CHKERRQ(ierr);
18123927de2eSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&issbaij);CHKERRQ(ierr);
1813ecf5a873SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
1814ecf5a873SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
18157230de76SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1816ecf5a873SStefano Zampini   } else {
1817ecf5a873SStefano Zampini     global_indices_c = global_indices_r;
1818ecf5a873SStefano Zampini   }
1819ecf5a873SStefano Zampini 
18203927de2eSStefano Zampini   if (issbaij) {
18213927de2eSStefano Zampini     ierr = MatGetRowUpperTriangular(matis->A);CHKERRQ(ierr);
18223927de2eSStefano Zampini   }
18233927de2eSStefano Zampini   /*
1824ecf5a873SStefano Zampini      An SF reduce is needed to sum up properly on shared rows.
18253927de2eSStefano Zampini      Note that generally preallocation is not exact, since it overestimates nonzeros
18263927de2eSStefano Zampini   */
1827cf0a3239SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
18283927de2eSStefano Zampini   ierr = MatGetLocalSize(A,&lrows,&lcols);CHKERRQ(ierr);
18293927de2eSStefano Zampini   ierr = MatPreallocateInitialize(PetscObjectComm((PetscObject)A),lrows,lcols,dnz,onz);CHKERRQ(ierr);
18303927de2eSStefano Zampini   /* All processes need to compute entire row ownership */
18313927de2eSStefano Zampini   ierr = PetscMalloc1(rows,&row_ownership);CHKERRQ(ierr);
18323927de2eSStefano Zampini   ierr = MatGetOwnershipRanges(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
1833f03112d0SStefano Zampini   for (i=0;i<size;i++) {
18343927de2eSStefano Zampini     for (j=mat_ranges[i];j<mat_ranges[i+1];j++) {
18353927de2eSStefano Zampini       row_ownership[j] = i;
18363927de2eSStefano Zampini     }
18373927de2eSStefano Zampini   }
18387230de76SStefano Zampini   ierr = MatGetOwnershipRangesColumn(A,(const PetscInt**)&mat_ranges);CHKERRQ(ierr);
18393927de2eSStefano Zampini 
18403927de2eSStefano Zampini   /*
18413927de2eSStefano Zampini      my_dnz and my_onz contains exact contribution to preallocation from each local mat
18423927de2eSStefano Zampini      then, they will be summed up properly. This way, preallocation is always sufficient
18433927de2eSStefano Zampini   */
18443927de2eSStefano Zampini   ierr = PetscCalloc2(local_rows,&my_dnz,local_rows,&my_onz);CHKERRQ(ierr);
18453927de2eSStefano Zampini   /* preallocation as a MATAIJ */
18463927de2eSStefano Zampini   if (isdense) { /* special case for dense local matrices */
18473927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
184812dfadf8SStefano Zampini       PetscInt owner = row_ownership[global_indices_r[i]];
184912dfadf8SStefano Zampini       for (j=0;j<local_cols;j++) {
1850ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[j];
18513927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
18523927de2eSStefano Zampini           my_dnz[i] += 1;
18533927de2eSStefano Zampini         } else { /* offdiag block */
18543927de2eSStefano Zampini           my_onz[i] += 1;
18553927de2eSStefano Zampini         }
18563927de2eSStefano Zampini       }
18573927de2eSStefano Zampini     }
1858bb1015c3SStefano Zampini   } else if (matis->A->ops->getrowij) {
1859bb1015c3SStefano Zampini     const PetscInt *ii,*jj,*jptr;
1860bb1015c3SStefano Zampini     PetscBool      done;
1861bb1015c3SStefano Zampini     ierr = MatGetRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1862938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
1863bb1015c3SStefano Zampini     jptr = jj;
1864bb1015c3SStefano Zampini     for (i=0;i<local_rows;i++) {
1865bb1015c3SStefano Zampini       PetscInt index_row = global_indices_r[i];
1866bb1015c3SStefano Zampini       for (j=0;j<ii[i+1]-ii[i];j++,jptr++) {
1867bb1015c3SStefano Zampini         PetscInt owner = row_ownership[index_row];
1868bb1015c3SStefano Zampini         PetscInt index_col = global_indices_c[*jptr];
1869bb1015c3SStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
1870bb1015c3SStefano Zampini           my_dnz[i] += 1;
1871bb1015c3SStefano Zampini         } else { /* offdiag block */
1872bb1015c3SStefano Zampini           my_onz[i] += 1;
1873bb1015c3SStefano Zampini         }
1874bb1015c3SStefano Zampini         /* same as before, interchanging rows and cols */
1875bb1015c3SStefano Zampini         if (issbaij && index_col != index_row) {
1876bb1015c3SStefano Zampini           owner = row_ownership[index_col];
1877bb1015c3SStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1878bb1015c3SStefano Zampini             my_dnz[*jptr] += 1;
1879bb1015c3SStefano Zampini           } else {
1880bb1015c3SStefano Zampini             my_onz[*jptr] += 1;
1881bb1015c3SStefano Zampini           }
1882bb1015c3SStefano Zampini         }
1883bb1015c3SStefano Zampini       }
1884bb1015c3SStefano Zampini     }
1885bb1015c3SStefano Zampini     ierr = MatRestoreRowIJ(matis->A,0,PETSC_FALSE,PETSC_FALSE,&local_rows,&ii,&jj,&done);CHKERRQ(ierr);
1886938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)(matis->A)),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
1887bb1015c3SStefano Zampini   } else { /* loop over rows and use MatGetRow */
18883927de2eSStefano Zampini     for (i=0;i<local_rows;i++) {
18893927de2eSStefano Zampini       const PetscInt *cols;
1890ecf5a873SStefano Zampini       PetscInt       ncols,index_row = global_indices_r[i];
18913927de2eSStefano Zampini       ierr = MatGetRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
18923927de2eSStefano Zampini       for (j=0;j<ncols;j++) {
18933927de2eSStefano Zampini         PetscInt owner = row_ownership[index_row];
1894ecf5a873SStefano Zampini         PetscInt index_col = global_indices_c[cols[j]];
18953927de2eSStefano Zampini         if (index_col > mat_ranges[owner]-1 && index_col < mat_ranges[owner+1] ) { /* diag block */
18963927de2eSStefano Zampini           my_dnz[i] += 1;
18973927de2eSStefano Zampini         } else { /* offdiag block */
18983927de2eSStefano Zampini           my_onz[i] += 1;
18993927de2eSStefano Zampini         }
19003927de2eSStefano Zampini         /* same as before, interchanging rows and cols */
1901d9a9e74cSStefano Zampini         if (issbaij && index_col != index_row) {
19023927de2eSStefano Zampini           owner = row_ownership[index_col];
19033927de2eSStefano Zampini           if (index_row > mat_ranges[owner]-1 && index_row < mat_ranges[owner+1] ) {
1904d9a9e74cSStefano Zampini             my_dnz[cols[j]] += 1;
19053927de2eSStefano Zampini           } else {
1906d9a9e74cSStefano Zampini             my_onz[cols[j]] += 1;
19073927de2eSStefano Zampini           }
19083927de2eSStefano Zampini         }
19093927de2eSStefano Zampini       }
19103927de2eSStefano Zampini       ierr = MatRestoreRow(matis->A,i,&ncols,&cols,NULL);CHKERRQ(ierr);
19113927de2eSStefano Zampini     }
19123927de2eSStefano Zampini   }
1913ecf5a873SStefano Zampini   if (global_indices_c != global_indices_r) {
19147230de76SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&global_indices_c);CHKERRQ(ierr);
1915ecf5a873SStefano Zampini   }
19164f619741Sstefano_zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&global_indices_r);CHKERRQ(ierr);
19173927de2eSStefano Zampini   ierr = PetscFree(row_ownership);CHKERRQ(ierr);
1918ecf5a873SStefano Zampini 
1919ecf5a873SStefano Zampini   /* Reduce my_dnz and my_onz */
19203927de2eSStefano Zampini   if (maxreduce) {
19213927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
19223927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
1923bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_MAX);CHKERRQ(ierr);
19243927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_MAX);CHKERRQ(ierr);
19253927de2eSStefano Zampini   } else {
19263927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
19273927de2eSStefano Zampini     ierr = PetscSFReduceBegin(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
1928bb1015c3SStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_dnz,dnz,MPI_SUM);CHKERRQ(ierr);
19293927de2eSStefano Zampini     ierr = PetscSFReduceEnd(matis->sf,MPIU_INT,my_onz,onz,MPI_SUM);CHKERRQ(ierr);
19303927de2eSStefano Zampini   }
19313927de2eSStefano Zampini   ierr = PetscFree2(my_dnz,my_onz);CHKERRQ(ierr);
19323927de2eSStefano Zampini 
19333927de2eSStefano Zampini   /* Resize preallocation if overestimated */
19343927de2eSStefano Zampini   for (i=0;i<lrows;i++) {
19353927de2eSStefano Zampini     dnz[i] = PetscMin(dnz[i],lcols);
19363927de2eSStefano Zampini     onz[i] = PetscMin(onz[i],cols-lcols);
19373927de2eSStefano Zampini   }
19381670daf9Sstefano_zampini 
19391670daf9Sstefano_zampini   /* Set preallocation */
1940268753edSStefano Zampini   ierr = MatSeqAIJSetPreallocation(B,0,dnz);CHKERRQ(ierr);
19413927de2eSStefano Zampini   ierr = MatMPIAIJSetPreallocation(B,0,dnz,0,onz);CHKERRQ(ierr);
194253b44cf5SStefano Zampini   for (i=0;i<lrows;i+=bs) {
194353b44cf5SStefano Zampini     PetscInt b, d = dnz[i],o = onz[i];
194453b44cf5SStefano Zampini 
194553b44cf5SStefano Zampini     for (b=1;b<bs;b++) {
194653b44cf5SStefano Zampini       d = PetscMax(d,dnz[i+b]);
194753b44cf5SStefano Zampini       o = PetscMax(o,onz[i+b]);
194853b44cf5SStefano Zampini     }
194953b44cf5SStefano Zampini     dnz[i/bs] = PetscMin(d/bs + d%bs,lcols/bs);
195053b44cf5SStefano Zampini     onz[i/bs] = PetscMin(o/bs + o%bs,(cols-lcols)/bs);
19513927de2eSStefano Zampini   }
1952268753edSStefano Zampini   ierr = MatSeqBAIJSetPreallocation(B,bs,0,dnz);CHKERRQ(ierr);
19533927de2eSStefano Zampini   ierr = MatMPIBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
19543927de2eSStefano Zampini   ierr = MatMPISBAIJSetPreallocation(B,bs,0,dnz,0,onz);CHKERRQ(ierr);
19553927de2eSStefano Zampini   ierr = MatPreallocateFinalize(dnz,onz);CHKERRQ(ierr);
19563927de2eSStefano Zampini   if (issbaij) {
19573927de2eSStefano Zampini     ierr = MatRestoreRowUpperTriangular(matis->A);CHKERRQ(ierr);
19583927de2eSStefano Zampini   }
19599be90c3fSStefano Zampini   ierr = MatSetOption(B,MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
19603927de2eSStefano Zampini   PetscFunctionReturn(0);
19613927de2eSStefano Zampini }
19623927de2eSStefano Zampini 
1963487b449aSStefano Zampini PETSC_INTERN PetscErrorCode MatConvert_IS_XAIJ(Mat mat, MatType mtype, MatReuse reuse, Mat *M)
1964b7ce53b6SStefano Zampini {
1965b7ce53b6SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
1966487b449aSStefano Zampini   Mat            local_mat,MT;
1967b7ce53b6SStefano Zampini   /* info on mat */
196853b44cf5SStefano Zampini   PetscInt       rbs,cbs,rows,cols,lrows,lcols;
1969b7ce53b6SStefano Zampini   PetscInt       local_rows,local_cols;
1970b9ed4604SStefano Zampini   PetscBool      isseqdense,isseqsbaij,isseqaij,isseqbaij;
1971b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
1972b9ed4604SStefano Zampini   PetscBool      lb[4],bb[4];
1973b9ed4604SStefano Zampini #endif
1974f03112d0SStefano Zampini   PetscMPIInt    size;
1975b7ce53b6SStefano Zampini   /* values insertion */
1976b7ce53b6SStefano Zampini   PetscScalar    *array;
1977b7ce53b6SStefano Zampini   /* work */
1978b7ce53b6SStefano Zampini   PetscErrorCode ierr;
1979b7ce53b6SStefano Zampini 
1980b7ce53b6SStefano Zampini   PetscFunctionBegin;
1981b7ce53b6SStefano Zampini   /* get info from mat */
1982f03112d0SStefano Zampini   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)mat),&size);CHKERRQ(ierr);
1983f03112d0SStefano Zampini   if (size == 1 && mat->rmap->N == matis->A->rmap->N && mat->cmap->N == matis->A->cmap->N) {
19841670daf9Sstefano_zampini     Mat      B;
198553b44cf5SStefano Zampini     IS       irows = NULL,icols = NULL;
1986487b449aSStefano Zampini     PetscInt rbs,cbs;
19871670daf9Sstefano_zampini 
1988487b449aSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
1989487b449aSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
199053b44cf5SStefano Zampini     if (reuse != MAT_REUSE_MATRIX) { /* check if l2g maps are one-to-one */
199153b44cf5SStefano Zampini       IS             rows,cols;
199253b44cf5SStefano Zampini       const PetscInt *ridxs,*cidxs;
199353b44cf5SStefano Zampini       PetscInt       i,nw,*work;
199453b44cf5SStefano Zampini 
199553b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
199653b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingGetSize(mat->rmap->mapping,&nw);CHKERRQ(ierr);
199753b44cf5SStefano Zampini       nw   = nw/rbs;
199853b44cf5SStefano Zampini       ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr);
199953b44cf5SStefano Zampini       for (i=0;i<nw;i++) work[ridxs[i]] += 1;
200053b44cf5SStefano Zampini       for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
200153b44cf5SStefano Zampini       if (i == nw) {
200253b44cf5SStefano Zampini         ierr = ISCreateBlock(PETSC_COMM_SELF,rbs,nw,ridxs,PETSC_USE_POINTER,&rows);CHKERRQ(ierr);
2003acdf38a7Sstefano_zampini         ierr = ISSetPermutation(rows);CHKERRQ(ierr);
200453b44cf5SStefano Zampini         ierr = ISInvertPermutation(rows,PETSC_DECIDE,&irows);CHKERRQ(ierr);
2005acdf38a7Sstefano_zampini         ierr = ISDestroy(&rows);CHKERRQ(ierr);
200653b44cf5SStefano Zampini       }
200753b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->rmap->mapping,&ridxs);CHKERRQ(ierr);
200853b44cf5SStefano Zampini       ierr = PetscFree(work);CHKERRQ(ierr);
200953b44cf5SStefano Zampini       if (irows && mat->rmap->mapping != mat->cmap->mapping) {
201053b44cf5SStefano Zampini         ierr = ISLocalToGlobalMappingGetBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
201153b44cf5SStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(mat->cmap->mapping,&nw);CHKERRQ(ierr);
201253b44cf5SStefano Zampini         nw   = nw/cbs;
201353b44cf5SStefano Zampini         ierr = PetscCalloc1(nw,&work);CHKERRQ(ierr);
201453b44cf5SStefano Zampini         for (i=0;i<nw;i++) work[cidxs[i]] += 1;
201553b44cf5SStefano Zampini         for (i=0;i<nw;i++) if (!work[i] || work[i] > 1) break;
201653b44cf5SStefano Zampini         if (i == nw) {
201753b44cf5SStefano Zampini           ierr = ISCreateBlock(PETSC_COMM_SELF,cbs,nw,cidxs,PETSC_USE_POINTER,&cols);CHKERRQ(ierr);
201853b44cf5SStefano Zampini           ierr = ISSetPermutation(cols);CHKERRQ(ierr);
201953b44cf5SStefano Zampini           ierr = ISInvertPermutation(cols,PETSC_DECIDE,&icols);CHKERRQ(ierr);
202053b44cf5SStefano Zampini           ierr = ISDestroy(&cols);CHKERRQ(ierr);
202153b44cf5SStefano Zampini         }
202253b44cf5SStefano Zampini         ierr = ISLocalToGlobalMappingRestoreBlockIndices(mat->cmap->mapping,&cidxs);CHKERRQ(ierr);
202353b44cf5SStefano Zampini         ierr = PetscFree(work);CHKERRQ(ierr);
202453b44cf5SStefano Zampini       } else if (irows) {
202553b44cf5SStefano Zampini         ierr  = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr);
202653b44cf5SStefano Zampini         icols = irows;
202753b44cf5SStefano Zampini       }
202853b44cf5SStefano Zampini     } else {
202953b44cf5SStefano Zampini       ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject*)&irows);CHKERRQ(ierr);
203053b44cf5SStefano Zampini       ierr = PetscObjectQuery((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject*)&icols);CHKERRQ(ierr);
203153b44cf5SStefano Zampini       if (irows) { ierr = PetscObjectReference((PetscObject)irows);CHKERRQ(ierr); }
203253b44cf5SStefano Zampini       if (icols) { ierr = PetscObjectReference((PetscObject)icols);CHKERRQ(ierr); }
203353b44cf5SStefano Zampini     }
203453b44cf5SStefano Zampini     if (!irows || !icols) {
203553b44cf5SStefano Zampini       ierr = ISDestroy(&icols);CHKERRQ(ierr);
203653b44cf5SStefano Zampini       ierr = ISDestroy(&irows);CHKERRQ(ierr);
203753b44cf5SStefano Zampini       goto general_assembly;
203853b44cf5SStefano Zampini     }
2039487b449aSStefano Zampini     ierr = MatConvert(matis->A,(rbs == cbs && rbs > 1) ? MATSEQBAIJ : MATSEQAIJ,MAT_INITIAL_MATRIX,&B);CHKERRQ(ierr);
2040487b449aSStefano Zampini     if (reuse != MAT_INPLACE_MATRIX) {
20417dae84e0SHong Zhang       ierr = MatCreateSubMatrix(B,irows,icols,reuse,M);CHKERRQ(ierr);
204253b44cf5SStefano Zampini       ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_irows",(PetscObject)irows);CHKERRQ(ierr);
204353b44cf5SStefano Zampini       ierr = PetscObjectCompose((PetscObject)(*M),"_MatIS_IS_XAIJ_icols",(PetscObject)icols);CHKERRQ(ierr);
2044487b449aSStefano Zampini     } else {
2045487b449aSStefano Zampini       Mat C;
2046487b449aSStefano Zampini 
2047487b449aSStefano Zampini       ierr = MatCreateSubMatrix(B,irows,icols,MAT_INITIAL_MATRIX,&C);CHKERRQ(ierr);
2048487b449aSStefano Zampini       ierr = MatHeaderReplace(mat,&C);CHKERRQ(ierr);
2049487b449aSStefano Zampini     }
2050acdf38a7Sstefano_zampini     ierr = MatDestroy(&B);CHKERRQ(ierr);
2051acdf38a7Sstefano_zampini     ierr = ISDestroy(&icols);CHKERRQ(ierr);
2052acdf38a7Sstefano_zampini     ierr = ISDestroy(&irows);CHKERRQ(ierr);
20537c03b4e8SStefano Zampini     PetscFunctionReturn(0);
20547c03b4e8SStefano Zampini   }
205553b44cf5SStefano Zampini general_assembly:
2056b7ce53b6SStefano Zampini   ierr = MatGetSize(mat,&rows,&cols);CHKERRQ(ierr);
205753b44cf5SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
205853b44cf5SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
20593cfa4ea4SStefano Zampini   ierr = MatGetLocalSize(mat,&lrows,&lcols);CHKERRQ(ierr);
2060b7ce53b6SStefano Zampini   ierr = MatGetSize(matis->A,&local_rows,&local_cols);CHKERRQ(ierr);
2061b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQDENSE,&isseqdense);CHKERRQ(ierr);
20624099cc6bSBarry Smith   ierr = PetscObjectBaseTypeCompare((PetscObject)matis->A,MATSEQAIJ,&isseqaij);CHKERRQ(ierr);
2063b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQBAIJ,&isseqbaij);CHKERRQ(ierr);
2064b9ed4604SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)matis->A,MATSEQSBAIJ,&isseqsbaij);CHKERRQ(ierr);
2065b9ed4604SStefano Zampini   if (!isseqdense && !isseqaij && !isseqbaij && !isseqsbaij) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for matrix type %s",((PetscObject)(matis->A))->type_name);
2066b9ed4604SStefano Zampini #if defined (PETSC_USE_DEBUG)
2067b9ed4604SStefano Zampini   lb[0] = isseqdense;
2068b9ed4604SStefano Zampini   lb[1] = isseqaij;
2069b9ed4604SStefano Zampini   lb[2] = isseqbaij;
2070b9ed4604SStefano Zampini   lb[3] = isseqsbaij;
2071b9ed4604SStefano Zampini   ierr = MPIU_Allreduce(lb,bb,4,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)mat));CHKERRQ(ierr);
2072b9ed4604SStefano Zampini   if (!bb[0] && !bb[1] && !bb[2] && !bb[3]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Local matrices must have the same type");
2073b9ed4604SStefano Zampini #endif
2074b7ce53b6SStefano Zampini 
2075487b449aSStefano Zampini   if (reuse != MAT_REUSE_MATRIX) {
2076487b449aSStefano Zampini     ierr = MatCreate(PetscObjectComm((PetscObject)mat),&MT);CHKERRQ(ierr);
2077487b449aSStefano Zampini     ierr = MatSetSizes(MT,lrows,lcols,rows,cols);CHKERRQ(ierr);
2078487b449aSStefano Zampini     ierr = MatSetType(MT,mtype);CHKERRQ(ierr);
207953b44cf5SStefano Zampini     ierr = MatSetBlockSizes(MT,rbs,cbs);CHKERRQ(ierr);
2080487b449aSStefano Zampini     ierr = MatISSetMPIXAIJPreallocation_Private(mat,MT,PETSC_FALSE);CHKERRQ(ierr);
2081b7ce53b6SStefano Zampini   } else {
208253b44cf5SStefano Zampini     PetscInt mrbs,mcbs,mrows,mcols,mlrows,mlcols;
2083487b449aSStefano Zampini 
2084b7ce53b6SStefano Zampini     /* some checks */
2085487b449aSStefano Zampini     MT   = *M;
208653b44cf5SStefano Zampini     ierr = MatGetBlockSizes(MT,&mrbs,&mcbs);CHKERRQ(ierr);
2087487b449aSStefano Zampini     ierr = MatGetSize(MT,&mrows,&mcols);CHKERRQ(ierr);
2088487b449aSStefano Zampini     ierr = MatGetLocalSize(MT,&mlrows,&mlcols);CHKERRQ(ierr);
20896c4ed002SBarry Smith     if (mrows != rows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of rows (%d != %d)",rows,mrows);
20906c4ed002SBarry Smith     if (mcols != cols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of cols (%d != %d)",cols,mcols);
20916c4ed002SBarry Smith     if (mlrows != lrows) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local rows (%d != %d)",lrows,mlrows);
20926c4ed002SBarry Smith     if (mlcols != lcols) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong number of local cols (%d != %d)",lcols,mlcols);
209353b44cf5SStefano Zampini     if (mrbs != rbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong row block size (%d != %d)",rbs,mrbs);
209453b44cf5SStefano Zampini     if (mcbs != cbs) SETERRQ2(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse matrix. Wrong col block size (%d != %d)",cbs,mcbs);
2095487b449aSStefano Zampini     ierr = MatZeroEntries(MT);CHKERRQ(ierr);
2096b7ce53b6SStefano Zampini   }
2097d9a9e74cSStefano Zampini 
2098b9ed4604SStefano Zampini   if (isseqsbaij) {
2099d9a9e74cSStefano Zampini     ierr = MatConvert(matis->A,MATSEQBAIJ,MAT_INITIAL_MATRIX,&local_mat);CHKERRQ(ierr);
2100d9a9e74cSStefano Zampini   } else {
2101d9a9e74cSStefano Zampini     ierr = PetscObjectReference((PetscObject)matis->A);CHKERRQ(ierr);
2102d9a9e74cSStefano Zampini     local_mat = matis->A;
2103d9a9e74cSStefano Zampini   }
2104686e3a49SStefano Zampini 
2105b7ce53b6SStefano Zampini   /* Set values */
2106487b449aSStefano Zampini   ierr = MatSetLocalToGlobalMapping(MT,mat->rmap->mapping,mat->cmap->mapping);CHKERRQ(ierr);
2107b9ed4604SStefano Zampini   if (isseqdense) { /* special case for dense local matrices */
210865066ba5SStefano Zampini     PetscInt i,*dummy;
2109ecf5a873SStefano Zampini 
211065066ba5SStefano Zampini     ierr = PetscMalloc1(PetscMax(local_rows,local_cols),&dummy);CHKERRQ(ierr);
211165066ba5SStefano Zampini     for (i=0;i<PetscMax(local_rows,local_cols);i++) dummy[i] = i;
2112487b449aSStefano Zampini     ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_FALSE);CHKERRQ(ierr);
2113d9a9e74cSStefano Zampini     ierr = MatDenseGetArray(local_mat,&array);CHKERRQ(ierr);
2114487b449aSStefano Zampini     ierr = MatSetValuesLocal(MT,local_rows,dummy,local_cols,dummy,array,ADD_VALUES);CHKERRQ(ierr);
2115d9a9e74cSStefano Zampini     ierr = MatDenseRestoreArray(local_mat,&array);CHKERRQ(ierr);
211665066ba5SStefano Zampini     ierr = PetscFree(dummy);CHKERRQ(ierr);
2117686e3a49SStefano Zampini   } else if (isseqaij) {
21186afe12f5SStefano Zampini     const PetscInt *blocks;
21196afe12f5SStefano Zampini     PetscInt       i,nvtxs,*xadj,*adjncy, nb;
2120686e3a49SStefano Zampini     PetscBool      done;
2121686e3a49SStefano Zampini 
2122d9a9e74cSStefano Zampini     ierr = MatGetRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2123938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatGetRowIJ");
2124d9a9e74cSStefano Zampini     ierr = MatSeqAIJGetArray(local_mat,&array);CHKERRQ(ierr);
21256afe12f5SStefano Zampini     ierr = MatGetVariableBlockSizes(local_mat,&nb,&blocks);CHKERRQ(ierr);
21266afe12f5SStefano Zampini     if (nb) { /* speed up assembly for special blocked matrices (used by BDDC) */
21276afe12f5SStefano Zampini       PetscInt sum;
21286afe12f5SStefano Zampini 
21296afe12f5SStefano Zampini       for (i=0,sum=0;i<nb;i++) sum += blocks[i];
21306afe12f5SStefano Zampini       if (sum == nvtxs) {
21316afe12f5SStefano Zampini         PetscInt r;
21326afe12f5SStefano Zampini 
21336afe12f5SStefano Zampini         for (i=0,r=0;i<nb;i++) {
21346afe12f5SStefano 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]);
21356afe12f5SStefano Zampini           ierr = MatSetValuesLocal(MT,blocks[i],adjncy+xadj[r],blocks[i],adjncy+xadj[r],array+xadj[r],ADD_VALUES);CHKERRQ(ierr);
21366afe12f5SStefano Zampini           r   += blocks[i];
21376afe12f5SStefano Zampini         }
21386afe12f5SStefano Zampini       } else {
2139686e3a49SStefano Zampini         for (i=0;i<nvtxs;i++) {
2140487b449aSStefano Zampini           ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
2141686e3a49SStefano Zampini         }
21426afe12f5SStefano Zampini       }
21436afe12f5SStefano Zampini     } else {
21446afe12f5SStefano Zampini       for (i=0;i<nvtxs;i++) {
21456afe12f5SStefano Zampini         ierr = MatSetValuesLocal(MT,1,&i,xadj[i+1]-xadj[i],adjncy+xadj[i],array+xadj[i],ADD_VALUES);CHKERRQ(ierr);
21466afe12f5SStefano Zampini       }
21476afe12f5SStefano Zampini     }
2148d9a9e74cSStefano Zampini     ierr = MatRestoreRowIJ(local_mat,0,PETSC_FALSE,PETSC_FALSE,&nvtxs,(const PetscInt**)&xadj,(const PetscInt**)&adjncy,&done);CHKERRQ(ierr);
2149938e1ff8SStefano Zampini     if (!done) SETERRQ(PetscObjectComm((PetscObject)local_mat),PETSC_ERR_PLIB,"Error in MatRestoreRowIJ");
2150d9a9e74cSStefano Zampini     ierr = MatSeqAIJRestoreArray(local_mat,&array);CHKERRQ(ierr);
2151686e3a49SStefano Zampini   } else { /* very basic values insertion for all other matrix types */
2152ecf5a873SStefano Zampini     PetscInt i;
2153c0962df8SStefano Zampini 
2154686e3a49SStefano Zampini     for (i=0;i<local_rows;i++) {
2155686e3a49SStefano Zampini       PetscInt       j;
2156ecf5a873SStefano Zampini       const PetscInt *local_indices_cols;
2157686e3a49SStefano Zampini 
2158ecf5a873SStefano Zampini       ierr = MatGetRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
2159487b449aSStefano Zampini       ierr = MatSetValuesLocal(MT,1,&i,j,local_indices_cols,array,ADD_VALUES);CHKERRQ(ierr);
2160ecf5a873SStefano Zampini       ierr = MatRestoreRow(local_mat,i,&j,&local_indices_cols,(const PetscScalar**)&array);CHKERRQ(ierr);
2161686e3a49SStefano Zampini     }
2162b7ce53b6SStefano Zampini   }
2163487b449aSStefano Zampini   ierr = MatAssemblyBegin(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2164d9a9e74cSStefano Zampini   ierr = MatDestroy(&local_mat);CHKERRQ(ierr);
2165487b449aSStefano Zampini   ierr = MatAssemblyEnd(MT,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2166b9ed4604SStefano Zampini   if (isseqdense) {
2167487b449aSStefano Zampini     ierr = MatSetOption(MT,MAT_ROW_ORIENTED,PETSC_TRUE);CHKERRQ(ierr);
2168487b449aSStefano Zampini   }
2169487b449aSStefano Zampini   if (reuse == MAT_INPLACE_MATRIX) {
2170487b449aSStefano Zampini     ierr = MatHeaderReplace(mat,&MT);CHKERRQ(ierr);
2171487b449aSStefano Zampini   } else if (reuse == MAT_INITIAL_MATRIX) {
2172487b449aSStefano Zampini     *M = MT;
2173b7ce53b6SStefano Zampini   }
2174b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
2175b7ce53b6SStefano Zampini }
2176b7ce53b6SStefano Zampini 
2177b7ce53b6SStefano Zampini /*@
2178b7ce53b6SStefano Zampini     MatISGetMPIXAIJ - Converts MATIS matrix into a parallel AIJ format
2179b7ce53b6SStefano Zampini 
2180b7ce53b6SStefano Zampini   Input Parameter:
2181b7ce53b6SStefano Zampini .  mat - the matrix (should be of type MATIS)
2182b7ce53b6SStefano Zampini .  reuse - either MAT_INITIAL_MATRIX or MAT_REUSE_MATRIX
2183b7ce53b6SStefano Zampini 
2184b7ce53b6SStefano Zampini   Output Parameter:
2185b7ce53b6SStefano Zampini .  newmat - the matrix in AIJ format
2186b7ce53b6SStefano Zampini 
2187b7ce53b6SStefano Zampini   Level: developer
2188b7ce53b6SStefano Zampini 
218995452b02SPatrick Sanan   Notes:
2190487b449aSStefano Zampini     This function has been deprecated and it will be removed in future releases. Update your code to use the MatConvert() interface.
2191b7ce53b6SStefano Zampini 
2192487b449aSStefano Zampini .seealso: MATIS, MatConvert()
2193b7ce53b6SStefano Zampini @*/
2194b7ce53b6SStefano Zampini PetscErrorCode MatISGetMPIXAIJ(Mat mat, MatReuse reuse, Mat *newmat)
2195b7ce53b6SStefano Zampini {
2196b7ce53b6SStefano Zampini   PetscErrorCode ierr;
2197b7ce53b6SStefano Zampini 
2198b7ce53b6SStefano Zampini   PetscFunctionBegin;
2199b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2200b7ce53b6SStefano Zampini   PetscValidLogicalCollectiveEnum(mat,reuse,2);
2201b7ce53b6SStefano Zampini   PetscValidPointer(newmat,3);
2202487b449aSStefano Zampini   if (reuse == MAT_REUSE_MATRIX) {
2203b7ce53b6SStefano Zampini     PetscValidHeaderSpecific(*newmat,MAT_CLASSID,3);
2204b7ce53b6SStefano Zampini     PetscCheckSameComm(mat,1,*newmat,3);
22056c4ed002SBarry Smith     if (mat == *newmat) SETERRQ(PetscObjectComm((PetscObject)mat),PETSC_ERR_SUP,"Cannot reuse the same matrix");
2206b7ce53b6SStefano Zampini   }
2207487b449aSStefano Zampini   ierr = PetscUseMethod(mat,"MatISGetMPIXAIJ_C",(Mat,MatType,MatReuse,Mat*),(mat,MATAIJ,reuse,newmat));CHKERRQ(ierr);
2208b7ce53b6SStefano Zampini   PetscFunctionReturn(0);
2209b7ce53b6SStefano Zampini }
2210b7ce53b6SStefano Zampini 
2211ad6194a2SStefano Zampini PetscErrorCode MatDuplicate_IS(Mat mat,MatDuplicateOption op,Mat *newmat)
2212ad6194a2SStefano Zampini {
2213ad6194a2SStefano Zampini   PetscErrorCode ierr;
2214ad6194a2SStefano Zampini   Mat_IS         *matis = (Mat_IS*)(mat->data);
2215c9225affSStefano Zampini   PetscInt       rbs,cbs,m,n,M,N;
2216ad6194a2SStefano Zampini   Mat            B,localmat;
2217ad6194a2SStefano Zampini 
2218ad6194a2SStefano Zampini   PetscFunctionBegin;
2219c9225affSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->rmap->mapping,&rbs);CHKERRQ(ierr);
2220c9225affSStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(mat->cmap->mapping,&cbs);CHKERRQ(ierr);
2221ad6194a2SStefano Zampini   ierr = MatGetSize(mat,&M,&N);CHKERRQ(ierr);
2222ad6194a2SStefano Zampini   ierr = MatGetLocalSize(mat,&m,&n);CHKERRQ(ierr);
2223c9225affSStefano Zampini   ierr = MatCreateIS(PetscObjectComm((PetscObject)mat),rbs == cbs ? rbs : 1,m,n,M,N,mat->rmap->mapping,mat->cmap->mapping,&B);CHKERRQ(ierr);
2224ad6194a2SStefano Zampini   ierr = MatDuplicate(matis->A,op,&localmat);CHKERRQ(ierr);
2225ad6194a2SStefano Zampini   ierr = MatISSetLocalMat(B,localmat);CHKERRQ(ierr);
2226b3317aa8SStefano Zampini   ierr = MatDestroy(&localmat);CHKERRQ(ierr);
2227b0f2910eSStefano Zampini   if (matis->sf) {
2228b0f2910eSStefano Zampini     Mat_IS *bmatis = (Mat_IS*)(B->data);
2229b0f2910eSStefano Zampini 
2230b0f2910eSStefano Zampini     ierr       = PetscObjectReference((PetscObject)matis->sf);CHKERRQ(ierr);
2231b0f2910eSStefano Zampini     bmatis->sf = matis->sf;
2232b0f2910eSStefano Zampini     ierr       = PetscMalloc2(matis->sf->nroots,&bmatis->sf_rootdata,matis->sf->nleaves,&bmatis->sf_leafdata);CHKERRQ(ierr);
2233b0f2910eSStefano Zampini     if (matis->sf != matis->csf) {
2234b0f2910eSStefano Zampini       ierr        = PetscObjectReference((PetscObject)matis->csf);CHKERRQ(ierr);
2235b0f2910eSStefano Zampini       bmatis->csf = matis->csf;
2236b0f2910eSStefano Zampini       ierr        = PetscMalloc2(matis->csf->nroots,&bmatis->csf_rootdata,matis->csf->nleaves,&bmatis->csf_leafdata);CHKERRQ(ierr);
2237b0f2910eSStefano Zampini     } else {
2238b0f2910eSStefano Zampini       bmatis->csf          = bmatis->sf;
2239b0f2910eSStefano Zampini       bmatis->csf_leafdata = bmatis->sf_leafdata;
2240b0f2910eSStefano Zampini       bmatis->csf_rootdata = bmatis->sf_rootdata;
2241b0f2910eSStefano Zampini     }
2242b0f2910eSStefano Zampini   }
2243ad6194a2SStefano Zampini   ierr = MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2244ad6194a2SStefano Zampini   ierr = MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2245ad6194a2SStefano Zampini   *newmat = B;
2246ad6194a2SStefano Zampini   PetscFunctionReturn(0);
2247ad6194a2SStefano Zampini }
2248ad6194a2SStefano Zampini 
2249a8116848SStefano Zampini static PetscErrorCode MatIsHermitian_IS(Mat A,PetscReal tol,PetscBool  *flg)
225069796d55SStefano Zampini {
225169796d55SStefano Zampini   PetscErrorCode ierr;
225269796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
225369796d55SStefano Zampini   PetscBool      local_sym;
225469796d55SStefano Zampini 
225569796d55SStefano Zampini   PetscFunctionBegin;
225669796d55SStefano Zampini   ierr = MatIsHermitian(matis->A,tol,&local_sym);CHKERRQ(ierr);
2257b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
225869796d55SStefano Zampini   PetscFunctionReturn(0);
225969796d55SStefano Zampini }
226069796d55SStefano Zampini 
2261a8116848SStefano Zampini static PetscErrorCode MatIsSymmetric_IS(Mat A,PetscReal tol,PetscBool  *flg)
226269796d55SStefano Zampini {
226369796d55SStefano Zampini   PetscErrorCode ierr;
226469796d55SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
226569796d55SStefano Zampini   PetscBool      local_sym;
226669796d55SStefano Zampini 
226769796d55SStefano Zampini   PetscFunctionBegin;
226869796d55SStefano Zampini   ierr = MatIsSymmetric(matis->A,tol,&local_sym);CHKERRQ(ierr);
2269b2566f29SBarry Smith   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
227069796d55SStefano Zampini   PetscFunctionReturn(0);
227169796d55SStefano Zampini }
227269796d55SStefano Zampini 
227345471136SStefano Zampini static PetscErrorCode MatIsStructurallySymmetric_IS(Mat A,PetscBool  *flg)
227445471136SStefano Zampini {
227545471136SStefano Zampini   PetscErrorCode ierr;
227645471136SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
227745471136SStefano Zampini   PetscBool      local_sym;
227845471136SStefano Zampini 
227945471136SStefano Zampini   PetscFunctionBegin;
228045471136SStefano Zampini   if (A->rmap->mapping != A->cmap->mapping) {
228145471136SStefano Zampini     *flg = PETSC_FALSE;
228245471136SStefano Zampini     PetscFunctionReturn(0);
228345471136SStefano Zampini   }
228445471136SStefano Zampini   ierr = MatIsStructurallySymmetric(matis->A,&local_sym);CHKERRQ(ierr);
228545471136SStefano Zampini   ierr = MPIU_Allreduce(&local_sym,flg,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
228645471136SStefano Zampini   PetscFunctionReturn(0);
228745471136SStefano Zampini }
228845471136SStefano Zampini 
2289a8116848SStefano Zampini static PetscErrorCode MatDestroy_IS(Mat A)
2290b4319ba4SBarry Smith {
2291dfbe8321SBarry Smith   PetscErrorCode ierr;
2292b4319ba4SBarry Smith   Mat_IS         *b = (Mat_IS*)A->data;
2293b4319ba4SBarry Smith 
2294b4319ba4SBarry Smith   PetscFunctionBegin;
22956bf464f9SBarry Smith   ierr = MatDestroy(&b->A);CHKERRQ(ierr);
2296e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->cctx);CHKERRQ(ierr);
2297e176bc59SStefano Zampini   ierr = VecScatterDestroy(&b->rctx);CHKERRQ(ierr);
22986bf464f9SBarry Smith   ierr = VecDestroy(&b->x);CHKERRQ(ierr);
22996bf464f9SBarry Smith   ierr = VecDestroy(&b->y);CHKERRQ(ierr);
23003fd1c9e7SStefano Zampini   ierr = VecDestroy(&b->counter);CHKERRQ(ierr);
2301a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_ris);CHKERRQ(ierr);
2302a8116848SStefano Zampini   ierr = ISDestroy(&b->getsub_cis);CHKERRQ(ierr);
2303a8116848SStefano Zampini   if (b->sf != b->csf) {
2304a8116848SStefano Zampini     ierr = PetscSFDestroy(&b->csf);CHKERRQ(ierr);
2305a8116848SStefano Zampini     ierr = PetscFree2(b->csf_rootdata,b->csf_leafdata);CHKERRQ(ierr);
2306f03112d0SStefano Zampini   } else b->csf = NULL;
230728f4e0baSStefano Zampini   ierr = PetscSFDestroy(&b->sf);CHKERRQ(ierr);
230828f4e0baSStefano Zampini   ierr = PetscFree2(b->sf_rootdata,b->sf_leafdata);CHKERRQ(ierr);
2309bf0cc555SLisandro Dalcin   ierr = PetscFree(A->data);CHKERRQ(ierr);
2310dbd8c25aSHong Zhang   ierr = PetscObjectChangeTypeName((PetscObject)A,0);CHKERRQ(ierr);
2311bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",NULL);CHKERRQ(ierr);
2312b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",NULL);CHKERRQ(ierr);
2313b7ce53b6SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",NULL);CHKERRQ(ierr);
23142e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",NULL);CHKERRQ(ierr);
2315cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",NULL);CHKERRQ(ierr);
231675d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",NULL);CHKERRQ(ierr);
2317f03112d0SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",NULL);CHKERRQ(ierr);
2318487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",NULL);CHKERRQ(ierr);
2319487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",NULL);CHKERRQ(ierr);
2320487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",NULL);CHKERRQ(ierr);
2321487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",NULL);CHKERRQ(ierr);
2322487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",NULL);CHKERRQ(ierr);
2323487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",NULL);CHKERRQ(ierr);
2324487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",NULL);CHKERRQ(ierr);
2325b4319ba4SBarry Smith   PetscFunctionReturn(0);
2326b4319ba4SBarry Smith }
2327b4319ba4SBarry Smith 
2328a8116848SStefano Zampini static PetscErrorCode MatMult_IS(Mat A,Vec x,Vec y)
2329b4319ba4SBarry Smith {
2330dfbe8321SBarry Smith   PetscErrorCode ierr;
2331b4319ba4SBarry Smith   Mat_IS         *is  = (Mat_IS*)A->data;
2332b4319ba4SBarry Smith   PetscScalar    zero = 0.0;
2333b4319ba4SBarry Smith 
2334b4319ba4SBarry Smith   PetscFunctionBegin;
2335b4319ba4SBarry Smith   /*  scatter the global vector x into the local work vector */
2336e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2337e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,x,is->x,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2338b4319ba4SBarry Smith 
2339b4319ba4SBarry Smith   /* multiply the local matrix */
2340b4319ba4SBarry Smith   ierr = MatMult(is->A,is->x,is->y);CHKERRQ(ierr);
2341b4319ba4SBarry Smith 
2342b4319ba4SBarry Smith   /* scatter product back into global memory */
23432dcb1b2aSMatthew Knepley   ierr = VecSet(y,zero);CHKERRQ(ierr);
2344e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2345e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,y,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2346b4319ba4SBarry Smith   PetscFunctionReturn(0);
2347b4319ba4SBarry Smith }
2348b4319ba4SBarry Smith 
2349a8116848SStefano Zampini static PetscErrorCode MatMultAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
23502e74eeadSLisandro Dalcin {
2351650997f4SStefano Zampini   Vec            temp_vec;
23522e74eeadSLisandro Dalcin   PetscErrorCode ierr;
23532e74eeadSLisandro Dalcin 
23542e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A * v1.*/
2355650997f4SStefano Zampini   if (v3 != v2) {
2356650997f4SStefano Zampini     ierr = MatMult(A,v1,v3);CHKERRQ(ierr);
2357650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
2358650997f4SStefano Zampini   } else {
2359650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
2360650997f4SStefano Zampini     ierr = MatMult(A,v1,temp_vec);CHKERRQ(ierr);
2361650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
2362650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
2363650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
2364650997f4SStefano Zampini   }
23652e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
23662e74eeadSLisandro Dalcin }
23672e74eeadSLisandro Dalcin 
2368a8116848SStefano Zampini static PetscErrorCode MatMultTranspose_IS(Mat A,Vec y,Vec x)
23692e74eeadSLisandro Dalcin {
23702e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
23712e74eeadSLisandro Dalcin   PetscErrorCode ierr;
23722e74eeadSLisandro Dalcin 
2373e176bc59SStefano Zampini   PetscFunctionBegin;
23742e74eeadSLisandro Dalcin   /*  scatter the global vector x into the local work vector */
2375e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
2376e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,y,is->y,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
23772e74eeadSLisandro Dalcin 
23782e74eeadSLisandro Dalcin   /* multiply the local matrix */
2379e176bc59SStefano Zampini   ierr = MatMultTranspose(is->A,is->y,is->x);CHKERRQ(ierr);
23802e74eeadSLisandro Dalcin 
23812e74eeadSLisandro Dalcin   /* scatter product back into global vector */
2382e176bc59SStefano Zampini   ierr = VecSet(x,0);CHKERRQ(ierr);
2383e176bc59SStefano Zampini   ierr = VecScatterBegin(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
2384e176bc59SStefano Zampini   ierr = VecScatterEnd(is->cctx,is->x,x,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
23852e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
23862e74eeadSLisandro Dalcin }
23872e74eeadSLisandro Dalcin 
2388a8116848SStefano Zampini static PetscErrorCode MatMultTransposeAdd_IS(Mat A,Vec v1,Vec v2,Vec v3)
23892e74eeadSLisandro Dalcin {
2390650997f4SStefano Zampini   Vec            temp_vec;
23912e74eeadSLisandro Dalcin   PetscErrorCode ierr;
23922e74eeadSLisandro Dalcin 
23932e74eeadSLisandro Dalcin   PetscFunctionBegin; /*  v3 = v2 + A' * v1.*/
2394650997f4SStefano Zampini   if (v3 != v2) {
2395650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,v3);CHKERRQ(ierr);
2396650997f4SStefano Zampini     ierr = VecAXPY(v3,1.0,v2);CHKERRQ(ierr);
2397650997f4SStefano Zampini   } else {
2398650997f4SStefano Zampini     ierr = VecDuplicate(v2,&temp_vec);CHKERRQ(ierr);
2399650997f4SStefano Zampini     ierr = MatMultTranspose(A,v1,temp_vec);CHKERRQ(ierr);
2400650997f4SStefano Zampini     ierr = VecAXPY(temp_vec,1.0,v2);CHKERRQ(ierr);
2401650997f4SStefano Zampini     ierr = VecCopy(temp_vec,v3);CHKERRQ(ierr);
2402650997f4SStefano Zampini     ierr = VecDestroy(&temp_vec);CHKERRQ(ierr);
2403650997f4SStefano Zampini   }
24042e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
24052e74eeadSLisandro Dalcin }
24062e74eeadSLisandro Dalcin 
2407a8116848SStefano Zampini static PetscErrorCode MatView_IS(Mat A,PetscViewer viewer)
2408b4319ba4SBarry Smith {
2409b4319ba4SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
2410dfbe8321SBarry Smith   PetscErrorCode ierr;
2411b4319ba4SBarry Smith   PetscViewer    sviewer;
2412ee2491ecSStefano Zampini   PetscBool      isascii,view = PETSC_TRUE;
2413b4319ba4SBarry Smith 
2414b4319ba4SBarry Smith   PetscFunctionBegin;
2415ee2491ecSStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&isascii);CHKERRQ(ierr);
2416ee2491ecSStefano Zampini   if (isascii)  {
2417ee2491ecSStefano Zampini     PetscViewerFormat format;
2418ee2491ecSStefano Zampini 
2419ee2491ecSStefano Zampini     ierr = PetscViewerGetFormat(viewer,&format);CHKERRQ(ierr);
2420ee2491ecSStefano Zampini     if (format == PETSC_VIEWER_ASCII_INFO) view = PETSC_FALSE;
2421ee2491ecSStefano Zampini   }
2422ee2491ecSStefano Zampini   if (!view) PetscFunctionReturn(0);
24233f08860eSBarry Smith   ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
2424b4319ba4SBarry Smith   ierr = MatView(a->A,sviewer);CHKERRQ(ierr);
24253f08860eSBarry Smith   ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr);
24266e520ac8SStefano Zampini   ierr = PetscViewerFlush(viewer);CHKERRQ(ierr);
2427b4319ba4SBarry Smith   PetscFunctionReturn(0);
2428b4319ba4SBarry Smith }
2429b4319ba4SBarry Smith 
2430a8116848SStefano Zampini static PetscErrorCode MatSetLocalToGlobalMapping_IS(Mat A,ISLocalToGlobalMapping rmapping,ISLocalToGlobalMapping cmapping)
2431b4319ba4SBarry Smith {
2432dfbe8321SBarry Smith   PetscErrorCode ierr;
2433e176bc59SStefano Zampini   PetscInt       nr,rbs,nc,cbs;
2434b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2435e176bc59SStefano Zampini   Vec            cglobal,rglobal;
2436b4319ba4SBarry Smith 
2437b4319ba4SBarry Smith   PetscFunctionBegin;
2438784ac674SJed Brown   PetscCheckSameComm(A,1,rmapping,2);
2439e176bc59SStefano Zampini   PetscCheckSameComm(A,1,cmapping,3);
24403bbff08aSStefano Zampini   /* Destroy any previous data */
244170cf5478SStefano Zampini   ierr = VecDestroy(&is->x);CHKERRQ(ierr);
244270cf5478SStefano Zampini   ierr = VecDestroy(&is->y);CHKERRQ(ierr);
24433fd1c9e7SStefano Zampini   ierr = VecDestroy(&is->counter);CHKERRQ(ierr);
2444e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->rctx);CHKERRQ(ierr);
2445e176bc59SStefano Zampini   ierr = VecScatterDestroy(&is->cctx);CHKERRQ(ierr);
24461c47cb0fSStefano Zampini   ierr = MatDestroy(&is->A);CHKERRQ(ierr);
2447872cf891SStefano Zampini   if (is->csf != is->sf) {
2448872cf891SStefano Zampini     ierr = PetscSFDestroy(&is->csf);CHKERRQ(ierr);
2449872cf891SStefano Zampini     ierr = PetscFree2(is->csf_rootdata,is->csf_leafdata);CHKERRQ(ierr);
2450f03112d0SStefano Zampini   } else is->csf = NULL;
245128f4e0baSStefano Zampini   ierr = PetscSFDestroy(&is->sf);CHKERRQ(ierr);
245228f4e0baSStefano Zampini   ierr = PetscFree2(is->sf_rootdata,is->sf_leafdata);CHKERRQ(ierr);
24533bbff08aSStefano Zampini 
24543bbff08aSStefano Zampini   /* Setup Layout and set local to global maps */
2455fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->rmap);CHKERRQ(ierr);
2456fc27028aSStefano Zampini   ierr = PetscLayoutSetUp(A->cmap);CHKERRQ(ierr);
2457e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(rmapping,&nr);CHKERRQ(ierr);
2458e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(rmapping,&rbs);CHKERRQ(ierr);
2459e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(cmapping,&nc);CHKERRQ(ierr);
2460e176bc59SStefano Zampini   ierr = ISLocalToGlobalMappingGetBlockSize(cmapping,&cbs);CHKERRQ(ierr);
24616625354bSStefano Zampini   /* check if the two mappings are actually the same for square matrices (DOLFIN passes 2 different objects) */
24626625354bSStefano Zampini   if (rmapping != cmapping && A->rmap->N == A->cmap->N) {
24636625354bSStefano Zampini     PetscBool same,gsame;
24646625354bSStefano Zampini 
24656625354bSStefano Zampini     same = PETSC_FALSE;
24666625354bSStefano Zampini     if (nr == nc && cbs == rbs) {
24676625354bSStefano Zampini       const PetscInt *idxs1,*idxs2;
24686625354bSStefano Zampini 
24696625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
24706625354bSStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
24716625354bSStefano Zampini       ierr = PetscMemcmp(idxs1,idxs2,(nr/rbs)*sizeof(PetscInt),&same);CHKERRQ(ierr);
24726625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(rmapping,&idxs1);CHKERRQ(ierr);
24736625354bSStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(cmapping,&idxs2);CHKERRQ(ierr);
24746625354bSStefano Zampini     }
24756625354bSStefano Zampini     ierr = MPIU_Allreduce(&same,&gsame,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
24766625354bSStefano Zampini     if (gsame) cmapping = rmapping;
24776625354bSStefano Zampini   }
247853b44cf5SStefano Zampini   ierr = PetscLayoutSetBlockSize(A->rmap,rbs);CHKERRQ(ierr);
247953b44cf5SStefano Zampini   ierr = PetscLayoutSetBlockSize(A->cmap,cbs);CHKERRQ(ierr);
24806625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->rmap,rmapping);CHKERRQ(ierr);
24816625354bSStefano Zampini   ierr = PetscLayoutSetISLocalToGlobalMapping(A->cmap,cmapping);CHKERRQ(ierr);
24826625354bSStefano Zampini 
24836625354bSStefano Zampini   /* Create the local matrix A */
2484f69a0ea3SMatthew Knepley   ierr = MatCreate(PETSC_COMM_SELF,&is->A);CHKERRQ(ierr);
2485e176bc59SStefano Zampini   ierr = MatSetType(is->A,MATAIJ);CHKERRQ(ierr);
2486e176bc59SStefano Zampini   ierr = MatSetSizes(is->A,nr,nc,nr,nc);CHKERRQ(ierr);
2487e176bc59SStefano Zampini   ierr = MatSetBlockSizes(is->A,rbs,cbs);CHKERRQ(ierr);
2488ff130e51SJed Brown   ierr = MatSetOptionsPrefix(is->A,((PetscObject)A)->prefix);CHKERRQ(ierr);
2489ff130e51SJed Brown   ierr = MatAppendOptionsPrefix(is->A,"is_");CHKERRQ(ierr);
2490b4319ba4SBarry Smith   ierr = MatSetFromOptions(is->A);CHKERRQ(ierr);
2491c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->rmap);CHKERRQ(ierr);
2492c77832edSStefano Zampini   ierr = PetscLayoutSetUp(is->A->cmap);CHKERRQ(ierr);
2493b4319ba4SBarry Smith 
2494f26d0771SStefano Zampini   if (!is->islocalref) { /* setup scatters and local vectors for MatMult */
249553b44cf5SStefano Zampini     IS             from;
249653b44cf5SStefano Zampini     const PetscInt *garray;
249753b44cf5SStefano Zampini 
2498b4319ba4SBarry Smith     /* Create the local work vectors */
24993bbff08aSStefano Zampini     ierr = MatCreateVecs(is->A,&is->x,&is->y);CHKERRQ(ierr);
2500b4319ba4SBarry Smith 
2501e176bc59SStefano Zampini     /* setup the global to local scatters */
2502e176bc59SStefano Zampini     ierr = MatCreateVecs(A,&cglobal,&rglobal);CHKERRQ(ierr);
250353b44cf5SStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockIndices(rmapping,&garray);CHKERRQ(ierr);
250453b44cf5SStefano Zampini     ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),rbs,nr/rbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
250553b44cf5SStefano Zampini     ierr = VecScatterCreate(rglobal,from,is->y,NULL,&is->rctx);CHKERRQ(ierr);
250653b44cf5SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreBlockIndices(rmapping,&garray);CHKERRQ(ierr);
2507e176bc59SStefano Zampini     ierr = ISDestroy(&from);CHKERRQ(ierr);
250853b44cf5SStefano Zampini     if (rmapping != cmapping) {
250953b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingGetBlockIndices(cmapping,&garray);CHKERRQ(ierr);
251053b44cf5SStefano Zampini       ierr = ISCreateBlock(PetscObjectComm((PetscObject)A),cbs,nc/cbs,garray,PETSC_USE_POINTER,&from);CHKERRQ(ierr);
251153b44cf5SStefano Zampini       ierr = VecScatterCreate(cglobal,from,is->x,NULL,&is->cctx);CHKERRQ(ierr);
251253b44cf5SStefano Zampini       ierr = ISLocalToGlobalMappingRestoreBlockIndices(cmapping,&garray);CHKERRQ(ierr);
251353b44cf5SStefano Zampini       ierr = ISDestroy(&from);CHKERRQ(ierr);
2514e176bc59SStefano Zampini     } else {
2515e176bc59SStefano Zampini       ierr = PetscObjectReference((PetscObject)is->rctx);CHKERRQ(ierr);
2516e176bc59SStefano Zampini       is->cctx = is->rctx;
2517e176bc59SStefano Zampini     }
25183fd1c9e7SStefano Zampini 
25193fd1c9e7SStefano Zampini     /* interface counter vector (local) */
25203fd1c9e7SStefano Zampini     ierr = VecDuplicate(is->y,&is->counter);CHKERRQ(ierr);
25213fd1c9e7SStefano Zampini     ierr = VecSet(is->y,1.);CHKERRQ(ierr);
25223fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
25233fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,is->y,rglobal,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
25243fd1c9e7SStefano Zampini     ierr = VecScatterBegin(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
25253fd1c9e7SStefano Zampini     ierr = VecScatterEnd(is->rctx,rglobal,is->counter,INSERT_VALUES,SCATTER_FORWARD);CHKERRQ(ierr);
25263fd1c9e7SStefano Zampini 
25273fd1c9e7SStefano Zampini     /* free workspace */
2528e176bc59SStefano Zampini     ierr = VecDestroy(&rglobal);CHKERRQ(ierr);
2529e176bc59SStefano Zampini     ierr = VecDestroy(&cglobal);CHKERRQ(ierr);
25306bf464f9SBarry Smith     ierr = ISDestroy(&from);CHKERRQ(ierr);
2531f26d0771SStefano Zampini   }
253248ff6bf3SStefano Zampini   ierr = MatSetUp(A);CHKERRQ(ierr);
2533b4319ba4SBarry Smith   PetscFunctionReturn(0);
2534b4319ba4SBarry Smith }
2535b4319ba4SBarry Smith 
2536a8116848SStefano Zampini static PetscErrorCode MatSetValues_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
25372e74eeadSLisandro Dalcin {
25382e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)mat->data;
25392e74eeadSLisandro Dalcin   PetscErrorCode ierr;
254097563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
254197563a80SStefano Zampini   PetscInt       i,zm,zn;
254297563a80SStefano Zampini #endif
2543f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
25442e74eeadSLisandro Dalcin 
25452e74eeadSLisandro Dalcin   PetscFunctionBegin;
25462e74eeadSLisandro Dalcin #if defined(PETSC_USE_DEBUG)
2547f26d0771SStefano 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);
254897563a80SStefano Zampini   /* count negative indices */
254997563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
255097563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
25512e74eeadSLisandro Dalcin #endif
255297563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
255397563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApply(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
255497563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
255597563a80SStefano Zampini   /* count negative indices (should be the same as before) */
255697563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
255797563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
2558b4f971dfSStefano 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");
2559b4f971dfSStefano 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");
256097563a80SStefano Zampini #endif
25612e74eeadSLisandro Dalcin   ierr = MatSetValues(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
25622e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
25632e74eeadSLisandro Dalcin }
25642e74eeadSLisandro Dalcin 
2565a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlocked_IS(Mat mat, PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols, const PetscScalar *values, InsertMode addv)
256697563a80SStefano Zampini {
256797563a80SStefano Zampini   Mat_IS         *is = (Mat_IS*)mat->data;
256897563a80SStefano Zampini   PetscErrorCode ierr;
256997563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
257097563a80SStefano Zampini   PetscInt       i,zm,zn;
257197563a80SStefano Zampini #endif
2572f26d0771SStefano Zampini   PetscInt       rows_l[MATIS_MAX_ENTRIES_INSERTION],cols_l[MATIS_MAX_ENTRIES_INSERTION];
257397563a80SStefano Zampini 
257497563a80SStefano Zampini   PetscFunctionBegin;
257597563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
2576f26d0771SStefano 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);
257797563a80SStefano Zampini   /* count negative indices */
257897563a80SStefano Zampini   for (i=0,zm=0;i<m;i++) if (rows[i] < 0) zm++;
257997563a80SStefano Zampini   for (i=0,zn=0;i<n;i++) if (cols[i] < 0) zn++;
258097563a80SStefano Zampini #endif
258197563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->rmap->mapping,IS_GTOLM_MASK,m,rows,&m,rows_l);CHKERRQ(ierr);
258297563a80SStefano Zampini   ierr = ISGlobalToLocalMappingApplyBlock(mat->cmap->mapping,IS_GTOLM_MASK,n,cols,&n,cols_l);CHKERRQ(ierr);
258397563a80SStefano Zampini #if defined(PETSC_USE_DEBUG)
258497563a80SStefano Zampini   /* count negative indices (should be the same as before) */
258597563a80SStefano Zampini   for (i=0;i<m;i++) if (rows_l[i] < 0) zm--;
258697563a80SStefano Zampini   for (i=0;i<n;i++) if (cols_l[i] < 0) zn--;
2587b4f971dfSStefano 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");
2588b4f971dfSStefano 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");
258997563a80SStefano Zampini #endif
2590d59cf9ebSStefano Zampini   ierr = MatSetValuesBlocked(is->A,m,rows_l,n,cols_l,values,addv);CHKERRQ(ierr);
259197563a80SStefano Zampini   PetscFunctionReturn(0);
259297563a80SStefano Zampini }
259397563a80SStefano Zampini 
2594a8116848SStefano Zampini static PetscErrorCode MatSetValuesLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2595b4319ba4SBarry Smith {
2596dfbe8321SBarry Smith   PetscErrorCode ierr;
2597b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2598b4319ba4SBarry Smith 
2599b4319ba4SBarry Smith   PetscFunctionBegin;
2600b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
2601872cf891SStefano Zampini     ierr = MatSetValuesLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2602872cf891SStefano Zampini   } else {
2603b4319ba4SBarry Smith     ierr = MatSetValues(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2604872cf891SStefano Zampini   }
2605b4319ba4SBarry Smith   PetscFunctionReturn(0);
2606b4319ba4SBarry Smith }
2607b4319ba4SBarry Smith 
2608a8116848SStefano Zampini static PetscErrorCode MatSetValuesBlockedLocal_IS(Mat A,PetscInt m,const PetscInt *rows, PetscInt n,const PetscInt *cols,const PetscScalar *values,InsertMode addv)
2609f0006bf2SLisandro Dalcin {
2610f0006bf2SLisandro Dalcin   PetscErrorCode ierr;
2611f0006bf2SLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
2612f0006bf2SLisandro Dalcin 
2613f0006bf2SLisandro Dalcin   PetscFunctionBegin;
2614b4f971dfSStefano Zampini   if (is->A->rmap->mapping) {
2615b4f971dfSStefano Zampini #if defined(PETSC_USE_DEBUG)
2616b4f971dfSStefano Zampini     PetscInt ibs,bs;
2617b4f971dfSStefano Zampini 
2618b4f971dfSStefano Zampini     ierr = ISLocalToGlobalMappingGetBlockSize(is->A->rmap->mapping,&ibs);CHKERRQ(ierr);
2619b4f971dfSStefano Zampini     ierr = MatGetBlockSize(is->A,&bs);CHKERRQ(ierr);
2620b4f971dfSStefano Zampini     if (ibs != bs) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SUP,"Different block sizes! local mat %D, local l2g map %D",bs,ibs);
2621b4f971dfSStefano Zampini #endif
2622b4f971dfSStefano Zampini     ierr = MatSetValuesBlockedLocal(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2623b4f971dfSStefano Zampini   } else {
2624f0006bf2SLisandro Dalcin     ierr = MatSetValuesBlocked(is->A,m,rows,n,cols,values,addv);CHKERRQ(ierr);
2625b4f971dfSStefano Zampini   }
2626f0006bf2SLisandro Dalcin   PetscFunctionReturn(0);
2627f0006bf2SLisandro Dalcin }
2628f0006bf2SLisandro Dalcin 
2629f0ae7da4SStefano Zampini static PetscErrorCode MatISZeroRowsColumnsLocal_Private(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,PetscBool columns)
2630f0ae7da4SStefano Zampini {
2631f0ae7da4SStefano Zampini   Mat_IS         *is = (Mat_IS*)A->data;
2632f0ae7da4SStefano Zampini   PetscErrorCode ierr;
2633f0ae7da4SStefano Zampini 
2634f0ae7da4SStefano Zampini   PetscFunctionBegin;
2635f0ae7da4SStefano Zampini   if (!n) {
2636f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_TRUE;
2637f0ae7da4SStefano Zampini   } else {
2638f0ae7da4SStefano Zampini     PetscInt i;
2639f0ae7da4SStefano Zampini     is->pure_neumann = PETSC_FALSE;
2640f0ae7da4SStefano Zampini 
2641f0ae7da4SStefano Zampini     if (columns) {
2642f0ae7da4SStefano Zampini       ierr = MatZeroRowsColumns(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
2643f0ae7da4SStefano Zampini     } else {
2644f0ae7da4SStefano Zampini       ierr = MatZeroRows(is->A,n,rows,diag,0,0);CHKERRQ(ierr);
2645f0ae7da4SStefano Zampini     }
2646f0ae7da4SStefano Zampini     if (diag != 0.) {
2647f0ae7da4SStefano Zampini       const PetscScalar *array;
2648f0ae7da4SStefano Zampini       ierr = VecGetArrayRead(is->counter,&array);CHKERRQ(ierr);
2649f0ae7da4SStefano Zampini       for (i=0; i<n; i++) {
2650f0ae7da4SStefano Zampini         ierr = MatSetValue(is->A,rows[i],rows[i],diag/(array[rows[i]]),INSERT_VALUES);CHKERRQ(ierr);
2651f0ae7da4SStefano Zampini       }
2652f0ae7da4SStefano Zampini       ierr = VecRestoreArrayRead(is->counter,&array);CHKERRQ(ierr);
2653f0ae7da4SStefano Zampini     }
2654f0ae7da4SStefano Zampini     ierr = MatAssemblyBegin(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2655f0ae7da4SStefano Zampini     ierr = MatAssemblyEnd(is->A,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
2656f0ae7da4SStefano Zampini   }
2657f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2658f0ae7da4SStefano Zampini }
2659f0ae7da4SStefano Zampini 
2660f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_Private_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b,PetscBool columns)
26612e74eeadSLisandro Dalcin {
26626e520ac8SStefano Zampini   Mat_IS         *matis = (Mat_IS*)A->data;
26636e520ac8SStefano Zampini   PetscInt       nr,nl,len,i;
26646e520ac8SStefano Zampini   PetscInt       *lrows;
26652e74eeadSLisandro Dalcin   PetscErrorCode ierr;
26662e74eeadSLisandro Dalcin 
26672e74eeadSLisandro Dalcin   PetscFunctionBegin;
2668f0ae7da4SStefano Zampini #if defined(PETSC_USE_DEBUG)
2669f0ae7da4SStefano Zampini   if (columns || diag != 0. || (x && b)) {
2670f0ae7da4SStefano Zampini     PetscBool cong;
267126b0207aSStefano Zampini 
2672f0ae7da4SStefano Zampini     ierr = PetscLayoutCompare(A->rmap,A->cmap,&cong);CHKERRQ(ierr);
267326b0207aSStefano Zampini     cong = (PetscBool)(cong && matis->sf == matis->csf);
2674268753edSStefano 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");
2675268753edSStefano 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");
2676268753edSStefano 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");
2677f0ae7da4SStefano Zampini   }
2678f0ae7da4SStefano Zampini #endif
26796e520ac8SStefano Zampini   /* get locally owned rows */
2680f0ae7da4SStefano Zampini   ierr = PetscLayoutMapLocal_Private(A->rmap,n,rows,&len,&lrows,NULL);CHKERRQ(ierr);
26816e520ac8SStefano Zampini   /* fix right hand side if needed */
26826e520ac8SStefano Zampini   if (x && b) {
26836e520ac8SStefano Zampini     const PetscScalar *xx;
26846e520ac8SStefano Zampini     PetscScalar       *bb;
26856e520ac8SStefano Zampini 
26866e520ac8SStefano Zampini     ierr = VecGetArrayRead(x, &xx);CHKERRQ(ierr);
26876e520ac8SStefano Zampini     ierr = VecGetArray(b, &bb);CHKERRQ(ierr);
26886e520ac8SStefano Zampini     for (i=0;i<len;++i) bb[lrows[i]] = diag*xx[lrows[i]];
26896e520ac8SStefano Zampini     ierr = VecRestoreArrayRead(x, &xx);CHKERRQ(ierr);
26906e520ac8SStefano Zampini     ierr = VecRestoreArray(b, &bb);CHKERRQ(ierr);
26912e74eeadSLisandro Dalcin   }
26926e520ac8SStefano Zampini   /* get rows associated to the local matrices */
26933d996552SStefano Zampini   ierr = MatISSetUpSF(A);CHKERRQ(ierr);
26946e520ac8SStefano Zampini   ierr = MatGetSize(matis->A,&nl,NULL);CHKERRQ(ierr);
26956e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_leafdata,nl*sizeof(PetscInt));CHKERRQ(ierr);
26966e520ac8SStefano Zampini   ierr = PetscMemzero(matis->sf_rootdata,A->rmap->n*sizeof(PetscInt));CHKERRQ(ierr);
26976e520ac8SStefano Zampini   for (i=0;i<len;i++) matis->sf_rootdata[lrows[i]] = 1;
26986e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
26996e520ac8SStefano Zampini   ierr = PetscSFBcastBegin(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
27006e520ac8SStefano Zampini   ierr = PetscSFBcastEnd(matis->sf,MPIU_INT,matis->sf_rootdata,matis->sf_leafdata);CHKERRQ(ierr);
27016e520ac8SStefano Zampini   ierr = PetscMalloc1(nl,&lrows);CHKERRQ(ierr);
27026e520ac8SStefano Zampini   for (i=0,nr=0;i<nl;i++) if (matis->sf_leafdata[i]) lrows[nr++] = i;
2703f0ae7da4SStefano Zampini   ierr = MatISZeroRowsColumnsLocal_Private(A,nr,lrows,diag,columns);CHKERRQ(ierr);
27046e520ac8SStefano Zampini   ierr = PetscFree(lrows);CHKERRQ(ierr);
27052e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
27062e74eeadSLisandro Dalcin }
27072e74eeadSLisandro Dalcin 
2708f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRows_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2709b4319ba4SBarry Smith {
2710dfbe8321SBarry Smith   PetscErrorCode ierr;
2711b4319ba4SBarry Smith 
2712b4319ba4SBarry Smith   PetscFunctionBegin;
2713f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_FALSE);CHKERRQ(ierr);
2714f0ae7da4SStefano Zampini   PetscFunctionReturn(0);
2715f0ae7da4SStefano Zampini }
27162205254eSKarl Rupp 
2717f0ae7da4SStefano Zampini static PetscErrorCode MatZeroRowsColumns_IS(Mat A,PetscInt n,const PetscInt rows[],PetscScalar diag,Vec x,Vec b)
2718f0ae7da4SStefano Zampini {
2719f0ae7da4SStefano Zampini   PetscErrorCode ierr;
2720f0ae7da4SStefano Zampini 
2721f0ae7da4SStefano Zampini   PetscFunctionBegin;
2722f0ae7da4SStefano Zampini   ierr = MatZeroRowsColumns_Private_IS(A,n,rows,diag,x,b,PETSC_TRUE);CHKERRQ(ierr);
2723b4319ba4SBarry Smith   PetscFunctionReturn(0);
2724b4319ba4SBarry Smith }
2725b4319ba4SBarry Smith 
2726a8116848SStefano Zampini static PetscErrorCode MatAssemblyBegin_IS(Mat A,MatAssemblyType type)
2727b4319ba4SBarry Smith {
2728b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2729dfbe8321SBarry Smith   PetscErrorCode ierr;
2730b4319ba4SBarry Smith 
2731b4319ba4SBarry Smith   PetscFunctionBegin;
2732b4319ba4SBarry Smith   ierr = MatAssemblyBegin(is->A,type);CHKERRQ(ierr);
2733b4319ba4SBarry Smith   PetscFunctionReturn(0);
2734b4319ba4SBarry Smith }
2735b4319ba4SBarry Smith 
2736a8116848SStefano Zampini static PetscErrorCode MatAssemblyEnd_IS(Mat A,MatAssemblyType type)
2737b4319ba4SBarry Smith {
2738b4319ba4SBarry Smith   Mat_IS         *is = (Mat_IS*)A->data;
2739dfbe8321SBarry Smith   PetscErrorCode ierr;
2740b4319ba4SBarry Smith 
2741b4319ba4SBarry Smith   PetscFunctionBegin;
2742b4319ba4SBarry Smith   ierr = MatAssemblyEnd(is->A,type);CHKERRQ(ierr);
2743872cf891SStefano Zampini   /* fix for local empty rows/cols */
2744872cf891SStefano Zampini   if (is->locempty && type == MAT_FINAL_ASSEMBLY) {
2745872cf891SStefano Zampini     Mat                    newlA;
2746f03112d0SStefano Zampini     ISLocalToGlobalMapping rl2g,cl2g;
2747f03112d0SStefano Zampini     IS                     nzr,nzc;
2748f03112d0SStefano Zampini     PetscInt               nr,nc,nnzr,nnzc;
2749f03112d0SStefano Zampini     PetscBool              lnewl2g,newl2g;
2750872cf891SStefano Zampini 
2751f03112d0SStefano Zampini     ierr = MatGetSize(is->A,&nr,&nc);CHKERRQ(ierr);
2752f03112d0SStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_FALSE,PETSC_SMALL,&nzr);CHKERRQ(ierr);
2753f03112d0SStefano Zampini     if (!nzr) {
2754f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&nzr);CHKERRQ(ierr);
2755872cf891SStefano Zampini     }
2756f03112d0SStefano Zampini     ierr = MatFindNonzeroRowsOrCols_Basic(is->A,PETSC_TRUE,PETSC_SMALL,&nzc);CHKERRQ(ierr);
2757f03112d0SStefano Zampini     if (!nzc) {
2758f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&nzc);CHKERRQ(ierr);
2759872cf891SStefano Zampini     }
2760f03112d0SStefano Zampini     ierr = ISGetSize(nzr,&nnzr);CHKERRQ(ierr);
2761f03112d0SStefano Zampini     ierr = ISGetSize(nzc,&nnzc);CHKERRQ(ierr);
2762f03112d0SStefano Zampini     if (nnzr != nr || nnzc != nc) {
2763f03112d0SStefano Zampini       ISLocalToGlobalMapping l2g;
2764f03112d0SStefano Zampini       IS                     is1,is2;
2765f03112d0SStefano Zampini 
2766f03112d0SStefano Zampini       /* need new global l2g map */
2767f03112d0SStefano Zampini       lnewl2g = PETSC_TRUE;
2768f03112d0SStefano Zampini       ierr    = MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
2769f03112d0SStefano Zampini 
2770872cf891SStefano Zampini       /* extract valid submatrix */
2771f03112d0SStefano Zampini       ierr = MatCreateSubMatrix(is->A,nzr,nzc,MAT_INITIAL_MATRIX,&newlA);CHKERRQ(ierr);
2772f03112d0SStefano Zampini 
2773f03112d0SStefano Zampini       /* attach local l2g maps for successive calls of MatSetValues on the local matrix */
2774f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(nzr,&l2g);CHKERRQ(ierr);
2775f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nr,0,1,&is1);CHKERRQ(ierr);
2776f03112d0SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_MASK,is1,&is2);CHKERRQ(ierr);
2777872cf891SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
277872ed36d8SStefano Zampini       if (is->A->rmap->mapping) { /* the matrix has a local-to-local map already attached (probably DMDA generated) */
277972ed36d8SStefano Zampini         const PetscInt *idxs1,*idxs2;
278072ed36d8SStefano Zampini         PetscInt       j,i,nl,*tidxs;
278172ed36d8SStefano Zampini 
278272ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(is->A->rmap->mapping,&nl);CHKERRQ(ierr);
278372ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(is->A->rmap->mapping,&idxs1);CHKERRQ(ierr);
278472ed36d8SStefano Zampini         ierr = PetscMalloc1(nl,&tidxs);CHKERRQ(ierr);
278572ed36d8SStefano Zampini         ierr = ISGetIndices(is2,&idxs2);CHKERRQ(ierr);
278672ed36d8SStefano Zampini         for (i=0,j=0;i<nl;i++) tidxs[i] = idxs1[i] < 0 ? -1 : idxs2[j++];
278772ed36d8SStefano Zampini         if (j != nr) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected count %D != %D",j,nr);
278872ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(is->A->rmap->mapping,&idxs1);CHKERRQ(ierr);
278972ed36d8SStefano Zampini         ierr = ISRestoreIndices(is2,&idxs2);CHKERRQ(ierr);
279072ed36d8SStefano Zampini         ierr = ISDestroy(&is2);CHKERRQ(ierr);
279172ed36d8SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A->rmap->mapping),nl,tidxs,PETSC_OWN_POINTER,&is2);CHKERRQ(ierr);
279272ed36d8SStefano Zampini       }
2793f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is2,&rl2g);CHKERRQ(ierr);
2794f03112d0SStefano Zampini       ierr = ISDestroy(&is1);CHKERRQ(ierr);
2795f03112d0SStefano Zampini       ierr = ISDestroy(&is2);CHKERRQ(ierr);
279672ed36d8SStefano Zampini 
2797f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(nzc,&l2g);CHKERRQ(ierr);
2798f03112d0SStefano Zampini       ierr = ISCreateStride(PetscObjectComm((PetscObject)is->A),nc,0,1,&is1);CHKERRQ(ierr);
2799f03112d0SStefano Zampini       ierr = ISGlobalToLocalMappingApplyIS(l2g,IS_GTOLM_MASK,is1,&is2);CHKERRQ(ierr);
2800f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&l2g);CHKERRQ(ierr);
280172ed36d8SStefano Zampini       if (is->A->cmap->mapping) { /* the matrix has a local-to-local map already attached (probably DMDA generated) */
280272ed36d8SStefano Zampini         const PetscInt *idxs1,*idxs2;
280372ed36d8SStefano Zampini         PetscInt       j,i,nl,*tidxs;
280472ed36d8SStefano Zampini 
280572ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetSize(is->A->cmap->mapping,&nl);CHKERRQ(ierr);
280672ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingGetIndices(is->A->cmap->mapping,&idxs1);CHKERRQ(ierr);
280772ed36d8SStefano Zampini         ierr = PetscMalloc1(nl,&tidxs);CHKERRQ(ierr);
280872ed36d8SStefano Zampini         ierr = ISGetIndices(is2,&idxs2);CHKERRQ(ierr);
280972ed36d8SStefano Zampini         for (i=0,j=0;i<nl;i++) tidxs[i] = idxs1[i] < 0 ? -1 : idxs2[j++];
281072ed36d8SStefano Zampini         if (j != nc) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Unexpected count %D != %D",j,nc);
281172ed36d8SStefano Zampini         ierr = ISLocalToGlobalMappingRestoreIndices(is->A->cmap->mapping,&idxs1);CHKERRQ(ierr);
281272ed36d8SStefano Zampini         ierr = ISRestoreIndices(is2,&idxs2);CHKERRQ(ierr);
281372ed36d8SStefano Zampini         ierr = ISDestroy(&is2);CHKERRQ(ierr);
281472ed36d8SStefano Zampini         ierr = ISCreateGeneral(PetscObjectComm((PetscObject)is->A->cmap->mapping),nl,tidxs,PETSC_OWN_POINTER,&is2);CHKERRQ(ierr);
281572ed36d8SStefano Zampini       }
2816f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreateIS(is2,&cl2g);CHKERRQ(ierr);
2817f03112d0SStefano Zampini       ierr = ISDestroy(&is1);CHKERRQ(ierr);
2818f03112d0SStefano Zampini       ierr = ISDestroy(&is2);CHKERRQ(ierr);
281972ed36d8SStefano Zampini 
2820f03112d0SStefano Zampini       ierr = MatSetLocalToGlobalMapping(newlA,rl2g,cl2g);CHKERRQ(ierr);
282172ed36d8SStefano Zampini 
2822f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2823f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2824f03112d0SStefano Zampini     } else { /* local matrix fully populated */
2825f03112d0SStefano Zampini       lnewl2g = PETSC_FALSE;
2826f03112d0SStefano Zampini       ierr    = MPI_Allreduce(&lnewl2g,&newl2g,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)A));CHKERRQ(ierr);
2827f03112d0SStefano Zampini       ierr    = PetscObjectReference((PetscObject)is->A);CHKERRQ(ierr);
2828f03112d0SStefano Zampini       newlA   = is->A;
2829f03112d0SStefano Zampini     }
2830f03112d0SStefano Zampini     /* attach new global l2g map if needed */
2831f03112d0SStefano Zampini     if (newl2g) {
2832f03112d0SStefano Zampini       IS             gnzr,gnzc;
2833f03112d0SStefano Zampini       const PetscInt *grid,*gcid;
2834f03112d0SStefano Zampini 
2835f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(A->rmap->mapping,nzr,&gnzr);CHKERRQ(ierr);
2836f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingApplyIS(A->cmap->mapping,nzc,&gnzc);CHKERRQ(ierr);
2837f03112d0SStefano Zampini       ierr = ISGetIndices(gnzr,&grid);CHKERRQ(ierr);
2838f03112d0SStefano Zampini       ierr = ISGetIndices(gnzc,&gcid);CHKERRQ(ierr);
2839f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nnzr,grid,PETSC_COPY_VALUES,&rl2g);CHKERRQ(ierr);
2840f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingCreate(PetscObjectComm((PetscObject)A),1,nnzc,gcid,PETSC_COPY_VALUES,&cl2g);CHKERRQ(ierr);
2841f03112d0SStefano Zampini       ierr = ISRestoreIndices(gnzr,&grid);CHKERRQ(ierr);
2842f03112d0SStefano Zampini       ierr = ISRestoreIndices(gnzc,&gcid);CHKERRQ(ierr);
2843f03112d0SStefano Zampini       ierr = ISDestroy(&gnzr);CHKERRQ(ierr);
2844f03112d0SStefano Zampini       ierr = ISDestroy(&gnzc);CHKERRQ(ierr);
2845f03112d0SStefano Zampini       ierr = MatSetLocalToGlobalMapping(A,rl2g,cl2g);CHKERRQ(ierr);
2846f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
2847f03112d0SStefano Zampini       ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
2848f03112d0SStefano Zampini     }
2849872cf891SStefano Zampini     ierr = MatISSetLocalMat(A,newlA);CHKERRQ(ierr);
2850872cf891SStefano Zampini     ierr = MatDestroy(&newlA);CHKERRQ(ierr);
2851f03112d0SStefano Zampini     ierr = ISDestroy(&nzr);CHKERRQ(ierr);
2852f03112d0SStefano Zampini     ierr = ISDestroy(&nzc);CHKERRQ(ierr);
2853872cf891SStefano Zampini     is->locempty = PETSC_FALSE;
2854f03112d0SStefano Zampini   }
2855b4319ba4SBarry Smith   PetscFunctionReturn(0);
2856b4319ba4SBarry Smith }
2857b4319ba4SBarry Smith 
2858a8116848SStefano Zampini static PetscErrorCode MatISGetLocalMat_IS(Mat mat,Mat *local)
2859b4319ba4SBarry Smith {
2860b4319ba4SBarry Smith   Mat_IS *is = (Mat_IS*)mat->data;
2861b4319ba4SBarry Smith 
2862b4319ba4SBarry Smith   PetscFunctionBegin;
2863b4319ba4SBarry Smith   *local = is->A;
2864b4319ba4SBarry Smith   PetscFunctionReturn(0);
2865b4319ba4SBarry Smith }
2866b4319ba4SBarry Smith 
28673b3b1effSJed Brown static PetscErrorCode MatISRestoreLocalMat_IS(Mat mat,Mat *local)
28683b3b1effSJed Brown {
28693b3b1effSJed Brown   PetscFunctionBegin;
28703b3b1effSJed Brown   *local = NULL;
28713b3b1effSJed Brown   PetscFunctionReturn(0);
28723b3b1effSJed Brown }
28733b3b1effSJed Brown 
2874b4319ba4SBarry Smith /*@
2875b4319ba4SBarry Smith     MatISGetLocalMat - Gets the local matrix stored inside a MATIS matrix.
2876b4319ba4SBarry Smith 
2877b4319ba4SBarry Smith   Input Parameter:
2878b4319ba4SBarry Smith .  mat - the matrix
2879b4319ba4SBarry Smith 
2880b4319ba4SBarry Smith   Output Parameter:
2881eb82efa4SStefano Zampini .  local - the local matrix
2882b4319ba4SBarry Smith 
2883b4319ba4SBarry Smith   Level: advanced
2884b4319ba4SBarry Smith 
2885b4319ba4SBarry Smith   Notes:
2886b4319ba4SBarry Smith     This can be called if you have precomputed the nonzero structure of the
2887b4319ba4SBarry Smith   matrix and want to provide it to the inner matrix object to improve the performance
2888b4319ba4SBarry Smith   of the MatSetValues() operation.
2889b4319ba4SBarry Smith 
28903b3b1effSJed Brown   Call MatISRestoreLocalMat() when finished with the local matrix.
289196a6f129SJed Brown 
2892b4319ba4SBarry Smith .seealso: MATIS
2893b4319ba4SBarry Smith @*/
28947087cfbeSBarry Smith PetscErrorCode MatISGetLocalMat(Mat mat,Mat *local)
2895b4319ba4SBarry Smith {
28964ac538c5SBarry Smith   PetscErrorCode ierr;
2897b4319ba4SBarry Smith 
2898b4319ba4SBarry Smith   PetscFunctionBegin;
28990700a824SBarry Smith   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2900b4319ba4SBarry Smith   PetscValidPointer(local,2);
29014ac538c5SBarry Smith   ierr = PetscUseMethod(mat,"MatISGetLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
2902b4319ba4SBarry Smith   PetscFunctionReturn(0);
2903b4319ba4SBarry Smith }
2904b4319ba4SBarry Smith 
29053b3b1effSJed Brown /*@
29063b3b1effSJed Brown     MatISRestoreLocalMat - Restores the local matrix obtained with MatISGetLocalMat()
29073b3b1effSJed Brown 
29083b3b1effSJed Brown   Input Parameter:
29093b3b1effSJed Brown .  mat - the matrix
29103b3b1effSJed Brown 
29113b3b1effSJed Brown   Output Parameter:
29123b3b1effSJed Brown .  local - the local matrix
29133b3b1effSJed Brown 
29143b3b1effSJed Brown   Level: advanced
29153b3b1effSJed Brown 
29163b3b1effSJed Brown .seealso: MATIS
29173b3b1effSJed Brown @*/
29183b3b1effSJed Brown PetscErrorCode MatISRestoreLocalMat(Mat mat,Mat *local)
29193b3b1effSJed Brown {
29203b3b1effSJed Brown   PetscErrorCode ierr;
29213b3b1effSJed Brown 
29223b3b1effSJed Brown   PetscFunctionBegin;
29233b3b1effSJed Brown   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
29243b3b1effSJed Brown   PetscValidPointer(local,2);
29253b3b1effSJed Brown   ierr = PetscUseMethod(mat,"MatISRestoreLocalMat_C",(Mat,Mat*),(mat,local));CHKERRQ(ierr);
29263b3b1effSJed Brown   PetscFunctionReturn(0);
29273b3b1effSJed Brown }
29283b3b1effSJed Brown 
2929a8116848SStefano Zampini static PetscErrorCode MatISSetLocalMat_IS(Mat mat,Mat local)
29303b03a366Sstefano_zampini {
29313b03a366Sstefano_zampini   Mat_IS         *is = (Mat_IS*)mat->data;
29323b03a366Sstefano_zampini   PetscInt       nrows,ncols,orows,ocols;
29333b03a366Sstefano_zampini   PetscErrorCode ierr;
29343b03a366Sstefano_zampini 
29353b03a366Sstefano_zampini   PetscFunctionBegin;
29364e4c7dbeSStefano Zampini   if (is->A) {
29373b03a366Sstefano_zampini     ierr = MatGetSize(is->A,&orows,&ocols);CHKERRQ(ierr);
29383b03a366Sstefano_zampini     ierr = MatGetSize(local,&nrows,&ncols);CHKERRQ(ierr);
2939f0ae7da4SStefano 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);
29404e4c7dbeSStefano Zampini   }
29413b03a366Sstefano_zampini   ierr  = PetscObjectReference((PetscObject)local);CHKERRQ(ierr);
29423b03a366Sstefano_zampini   ierr  = MatDestroy(&is->A);CHKERRQ(ierr);
29433b03a366Sstefano_zampini   is->A = local;
29443b03a366Sstefano_zampini   PetscFunctionReturn(0);
29453b03a366Sstefano_zampini }
29463b03a366Sstefano_zampini 
29473b03a366Sstefano_zampini /*@
2948eb82efa4SStefano Zampini     MatISSetLocalMat - Replace the local matrix stored inside a MATIS object.
29493b03a366Sstefano_zampini 
29503b03a366Sstefano_zampini   Input Parameter:
29513b03a366Sstefano_zampini .  mat - the matrix
2952eb82efa4SStefano Zampini .  local - the local matrix
29533b03a366Sstefano_zampini 
29543b03a366Sstefano_zampini   Output Parameter:
29553b03a366Sstefano_zampini 
29563b03a366Sstefano_zampini   Level: advanced
29573b03a366Sstefano_zampini 
29583b03a366Sstefano_zampini   Notes:
29593b03a366Sstefano_zampini     This can be called if you have precomputed the local matrix and
29603b03a366Sstefano_zampini   want to provide it to the matrix object MATIS.
29613b03a366Sstefano_zampini 
29623b03a366Sstefano_zampini .seealso: MATIS
29633b03a366Sstefano_zampini @*/
29643b03a366Sstefano_zampini PetscErrorCode MatISSetLocalMat(Mat mat,Mat local)
29653b03a366Sstefano_zampini {
29663b03a366Sstefano_zampini   PetscErrorCode ierr;
29673b03a366Sstefano_zampini 
29683b03a366Sstefano_zampini   PetscFunctionBegin;
29693b03a366Sstefano_zampini   PetscValidHeaderSpecific(mat,MAT_CLASSID,1);
2970b7ce53b6SStefano Zampini   PetscValidHeaderSpecific(local,MAT_CLASSID,2);
29713b03a366Sstefano_zampini   ierr = PetscUseMethod(mat,"MatISSetLocalMat_C",(Mat,Mat),(mat,local));CHKERRQ(ierr);
29723b03a366Sstefano_zampini   PetscFunctionReturn(0);
29733b03a366Sstefano_zampini }
29743b03a366Sstefano_zampini 
2975a8116848SStefano Zampini static PetscErrorCode MatZeroEntries_IS(Mat A)
29766726f965SBarry Smith {
29776726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
29786726f965SBarry Smith   PetscErrorCode ierr;
29796726f965SBarry Smith 
29806726f965SBarry Smith   PetscFunctionBegin;
29816726f965SBarry Smith   ierr = MatZeroEntries(a->A);CHKERRQ(ierr);
29826726f965SBarry Smith   PetscFunctionReturn(0);
29836726f965SBarry Smith }
29846726f965SBarry Smith 
2985a8116848SStefano Zampini static PetscErrorCode MatScale_IS(Mat A,PetscScalar a)
29862e74eeadSLisandro Dalcin {
29872e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
29882e74eeadSLisandro Dalcin   PetscErrorCode ierr;
29892e74eeadSLisandro Dalcin 
29902e74eeadSLisandro Dalcin   PetscFunctionBegin;
29912e74eeadSLisandro Dalcin   ierr = MatScale(is->A,a);CHKERRQ(ierr);
29922e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
29932e74eeadSLisandro Dalcin }
29942e74eeadSLisandro Dalcin 
2995a8116848SStefano Zampini static PetscErrorCode MatGetDiagonal_IS(Mat A, Vec v)
29962e74eeadSLisandro Dalcin {
29972e74eeadSLisandro Dalcin   Mat_IS         *is = (Mat_IS*)A->data;
29982e74eeadSLisandro Dalcin   PetscErrorCode ierr;
29992e74eeadSLisandro Dalcin 
30002e74eeadSLisandro Dalcin   PetscFunctionBegin;
30012e74eeadSLisandro Dalcin   /* get diagonal of the local matrix */
3002e176bc59SStefano Zampini   ierr = MatGetDiagonal(is->A,is->y);CHKERRQ(ierr);
30032e74eeadSLisandro Dalcin 
30042e74eeadSLisandro Dalcin   /* scatter diagonal back into global vector */
30052e74eeadSLisandro Dalcin   ierr = VecSet(v,0);CHKERRQ(ierr);
3006e176bc59SStefano Zampini   ierr = VecScatterBegin(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
3007e176bc59SStefano Zampini   ierr = VecScatterEnd(is->rctx,is->y,v,ADD_VALUES,SCATTER_REVERSE);CHKERRQ(ierr);
30082e74eeadSLisandro Dalcin   PetscFunctionReturn(0);
30092e74eeadSLisandro Dalcin }
30102e74eeadSLisandro Dalcin 
3011a8116848SStefano Zampini static PetscErrorCode MatSetOption_IS(Mat A,MatOption op,PetscBool flg)
30126726f965SBarry Smith {
30136726f965SBarry Smith   Mat_IS         *a = (Mat_IS*)A->data;
30146726f965SBarry Smith   PetscErrorCode ierr;
30156726f965SBarry Smith 
30166726f965SBarry Smith   PetscFunctionBegin;
30174e0d8c25SBarry Smith   ierr = MatSetOption(a->A,op,flg);CHKERRQ(ierr);
30186726f965SBarry Smith   PetscFunctionReturn(0);
30196726f965SBarry Smith }
30206726f965SBarry Smith 
3021f26d0771SStefano Zampini static PetscErrorCode MatAXPY_IS(Mat Y,PetscScalar a,Mat X,MatStructure str)
3022f26d0771SStefano Zampini {
3023f26d0771SStefano Zampini   Mat_IS         *y = (Mat_IS*)Y->data;
3024f26d0771SStefano Zampini   Mat_IS         *x;
3025f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3026f26d0771SStefano Zampini   PetscBool      ismatis;
3027f26d0771SStefano Zampini #endif
3028f26d0771SStefano Zampini   PetscErrorCode ierr;
3029f26d0771SStefano Zampini 
3030f26d0771SStefano Zampini   PetscFunctionBegin;
3031f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3032f26d0771SStefano Zampini   ierr = PetscObjectTypeCompare((PetscObject)X,MATIS,&ismatis);CHKERRQ(ierr);
3033f26d0771SStefano Zampini   if (!ismatis) SETERRQ(PetscObjectComm((PetscObject)Y),PETSC_ERR_SUP,"Cannot call MatAXPY(Y,a,X,str) with X not of type MATIS");
3034f26d0771SStefano Zampini #endif
3035f26d0771SStefano Zampini   x = (Mat_IS*)X->data;
3036f26d0771SStefano Zampini   ierr = MatAXPY(y->A,a,x->A,str);CHKERRQ(ierr);
3037f26d0771SStefano Zampini   PetscFunctionReturn(0);
3038f26d0771SStefano Zampini }
3039f26d0771SStefano Zampini 
3040f26d0771SStefano Zampini static PetscErrorCode MatGetLocalSubMatrix_IS(Mat A,IS row,IS col,Mat *submat)
3041f26d0771SStefano Zampini {
3042f26d0771SStefano Zampini   Mat                    lA;
3043f26d0771SStefano Zampini   Mat_IS                 *matis;
3044f26d0771SStefano Zampini   ISLocalToGlobalMapping rl2g,cl2g;
3045f26d0771SStefano Zampini   IS                     is;
3046f26d0771SStefano Zampini   const PetscInt         *rg,*rl;
3047f26d0771SStefano Zampini   PetscInt               nrg;
3048f26d0771SStefano Zampini   PetscInt               N,M,nrl,i,*idxs;
3049f26d0771SStefano Zampini   PetscErrorCode         ierr;
3050f26d0771SStefano Zampini 
3051f26d0771SStefano Zampini   PetscFunctionBegin;
3052f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
3053f26d0771SStefano Zampini   ierr = ISGetLocalSize(row,&nrl);CHKERRQ(ierr);
3054f26d0771SStefano Zampini   ierr = ISGetIndices(row,&rl);CHKERRQ(ierr);
3055f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingGetSize(A->rmap->mapping,&nrg);CHKERRQ(ierr);
3056f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3057*249c8a71SStefano 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);
3058f26d0771SStefano Zampini #endif
3059f26d0771SStefano Zampini   ierr = PetscMalloc1(nrg,&idxs);CHKERRQ(ierr);
3060f26d0771SStefano Zampini   /* map from [0,nrl) to row */
3061f26d0771SStefano Zampini   for (i=0;i<nrl;i++) idxs[i] = rl[i];
3062f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3063f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = nrg;
3064f26d0771SStefano Zampini #else
3065f26d0771SStefano Zampini   for (i=nrl;i<nrg;i++) idxs[i] = -1;
3066f26d0771SStefano Zampini #endif
3067f26d0771SStefano Zampini   ierr = ISRestoreIndices(row,&rl);CHKERRQ(ierr);
3068f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingRestoreIndices(A->rmap->mapping,&rg);CHKERRQ(ierr);
3069f26d0771SStefano Zampini   ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),nrg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
3070f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingCreateIS(is,&rl2g);CHKERRQ(ierr);
3071f26d0771SStefano Zampini   ierr = ISDestroy(&is);CHKERRQ(ierr);
3072f26d0771SStefano Zampini   /* compute new l2g map for columns */
3073f26d0771SStefano Zampini   if (col != row || A->rmap->mapping != A->cmap->mapping) {
3074f26d0771SStefano Zampini     const PetscInt *cg,*cl;
3075f26d0771SStefano Zampini     PetscInt       ncg;
3076f26d0771SStefano Zampini     PetscInt       ncl;
3077f26d0771SStefano Zampini 
3078f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
3079f26d0771SStefano Zampini     ierr = ISGetLocalSize(col,&ncl);CHKERRQ(ierr);
3080f26d0771SStefano Zampini     ierr = ISGetIndices(col,&cl);CHKERRQ(ierr);
3081f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingGetSize(A->cmap->mapping,&ncg);CHKERRQ(ierr);
3082f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3083*249c8a71SStefano 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);
3084f26d0771SStefano Zampini #endif
3085f26d0771SStefano Zampini     ierr = PetscMalloc1(ncg,&idxs);CHKERRQ(ierr);
3086f26d0771SStefano Zampini     /* map from [0,ncl) to col */
3087f26d0771SStefano Zampini     for (i=0;i<ncl;i++) idxs[i] = cl[i];
3088f26d0771SStefano Zampini #if defined(PETSC_USE_DEBUG)
3089f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = ncg;
3090f26d0771SStefano Zampini #else
3091f26d0771SStefano Zampini     for (i=ncl;i<ncg;i++) idxs[i] = -1;
3092f26d0771SStefano Zampini #endif
3093f26d0771SStefano Zampini     ierr = ISRestoreIndices(col,&cl);CHKERRQ(ierr);
3094f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingRestoreIndices(A->cmap->mapping,&cg);CHKERRQ(ierr);
3095f26d0771SStefano Zampini     ierr = ISCreateGeneral(PetscObjectComm((PetscObject)A),ncg,idxs,PETSC_OWN_POINTER,&is);CHKERRQ(ierr);
3096f26d0771SStefano Zampini     ierr = ISLocalToGlobalMappingCreateIS(is,&cl2g);CHKERRQ(ierr);
3097f26d0771SStefano Zampini     ierr = ISDestroy(&is);CHKERRQ(ierr);
3098f26d0771SStefano Zampini   } else {
3099f26d0771SStefano Zampini     ierr = PetscObjectReference((PetscObject)rl2g);CHKERRQ(ierr);
3100f26d0771SStefano Zampini     cl2g = rl2g;
3101f26d0771SStefano Zampini   }
3102f26d0771SStefano Zampini   /* create the MATIS submatrix */
3103f26d0771SStefano Zampini   ierr = MatGetSize(A,&M,&N);CHKERRQ(ierr);
3104f26d0771SStefano Zampini   ierr = MatCreate(PetscObjectComm((PetscObject)A),submat);CHKERRQ(ierr);
3105f26d0771SStefano Zampini   ierr = MatSetSizes(*submat,PETSC_DECIDE,PETSC_DECIDE,M,N);CHKERRQ(ierr);
3106f26d0771SStefano Zampini   ierr = MatSetType(*submat,MATIS);CHKERRQ(ierr);
3107b0aa3428SStefano Zampini   matis = (Mat_IS*)((*submat)->data);
3108f26d0771SStefano Zampini   matis->islocalref = PETSC_TRUE;
3109f26d0771SStefano Zampini   ierr = MatSetLocalToGlobalMapping(*submat,rl2g,cl2g);CHKERRQ(ierr);
3110f26d0771SStefano Zampini   ierr = MatISGetLocalMat(A,&lA);CHKERRQ(ierr);
3111f26d0771SStefano Zampini   ierr = MatISSetLocalMat(*submat,lA);CHKERRQ(ierr);
3112f26d0771SStefano Zampini   ierr = MatSetUp(*submat);CHKERRQ(ierr);
3113f26d0771SStefano Zampini   ierr = MatAssemblyBegin(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3114f26d0771SStefano Zampini   ierr = MatAssemblyEnd(*submat,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
3115f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&rl2g);CHKERRQ(ierr);
3116f26d0771SStefano Zampini   ierr = ISLocalToGlobalMappingDestroy(&cl2g);CHKERRQ(ierr);
3117f26d0771SStefano Zampini   /* remove unsupported ops */
3118f26d0771SStefano Zampini   ierr = PetscMemzero((*submat)->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
3119f26d0771SStefano Zampini   (*submat)->ops->destroy               = MatDestroy_IS;
3120f26d0771SStefano Zampini   (*submat)->ops->setvalueslocal        = MatSetValuesLocal_SubMat_IS;
3121f26d0771SStefano Zampini   (*submat)->ops->setvaluesblockedlocal = MatSetValuesBlockedLocal_SubMat_IS;
3122f26d0771SStefano Zampini   (*submat)->ops->assemblybegin         = MatAssemblyBegin_IS;
3123f26d0771SStefano Zampini   (*submat)->ops->assemblyend           = MatAssemblyEnd_IS;
3124f26d0771SStefano Zampini   PetscFunctionReturn(0);
3125f26d0771SStefano Zampini }
3126f26d0771SStefano Zampini 
3127872cf891SStefano Zampini static PetscErrorCode MatSetFromOptions_IS(PetscOptionItems *PetscOptionsObject, Mat A)
3128872cf891SStefano Zampini {
3129872cf891SStefano Zampini   Mat_IS         *a = (Mat_IS*)A->data;
3130872cf891SStefano Zampini   PetscErrorCode ierr;
3131872cf891SStefano Zampini 
3132872cf891SStefano Zampini   PetscFunctionBegin;
3133872cf891SStefano Zampini   ierr = PetscOptionsHead(PetscOptionsObject,"MATIS options");CHKERRQ(ierr);
3134872cf891SStefano Zampini   ierr = PetscObjectOptionsBegin((PetscObject)A);
3135f03112d0SStefano Zampini   ierr = PetscOptionsBool("-matis_fixempty","Fix local matrices in case of empty local rows/columns","MatISFixLocalEmpty",a->locempty,&a->locempty,NULL);CHKERRQ(ierr);
313675d48cdbSStefano Zampini   ierr = PetscOptionsBool("-matis_storel2l","Store local-to-local matrices generated from PtAP operations","MatISStoreL2L",a->storel2l,&a->storel2l,NULL);CHKERRQ(ierr);
3137872cf891SStefano Zampini   ierr = PetscOptionsEnd();CHKERRQ(ierr);
3138872cf891SStefano Zampini   PetscFunctionReturn(0);
3139872cf891SStefano Zampini }
3140872cf891SStefano Zampini 
3141284134d9SBarry Smith /*@
31423c212e90SHong Zhang     MatCreateIS - Creates a "process" unassembled matrix, assembled on each
3143284134d9SBarry Smith        process but not across processes.
3144284134d9SBarry Smith 
3145284134d9SBarry Smith    Input Parameters:
3146284134d9SBarry Smith +     comm    - MPI communicator that will share the matrix
3147e176bc59SStefano Zampini .     bs      - block size of the matrix
3148df3898eeSBarry Smith .     m,n,M,N - local and/or global sizes of the left and right vector used in matrix vector products
3149e176bc59SStefano Zampini .     rmap    - local to global map for rows
3150e176bc59SStefano Zampini -     cmap    - local to global map for cols
3151284134d9SBarry Smith 
3152284134d9SBarry Smith    Output Parameter:
3153284134d9SBarry Smith .    A - the resulting matrix
3154284134d9SBarry Smith 
31558e6c10adSSatish Balay    Level: advanced
31568e6c10adSSatish Balay 
315795452b02SPatrick Sanan    Notes:
315895452b02SPatrick Sanan     See MATIS for more details.
31596fdf41d1SStefano Zampini           m and n are NOT related to the size of the map; they represent the size of the local parts of the vectors
31606fdf41d1SStefano Zampini           used in MatMult operations. The sizes of rmap and cmap define the size of the local matrices.
31613c212e90SHong Zhang           If either rmap or cmap are NULL, then the matrix is assumed to be square.
3162284134d9SBarry Smith 
3163284134d9SBarry Smith .seealso: MATIS, MatSetLocalToGlobalMapping()
3164284134d9SBarry Smith @*/
3165e176bc59SStefano Zampini PetscErrorCode  MatCreateIS(MPI_Comm comm,PetscInt bs,PetscInt m,PetscInt n,PetscInt M,PetscInt N,ISLocalToGlobalMapping rmap,ISLocalToGlobalMapping cmap,Mat *A)
3166284134d9SBarry Smith {
3167284134d9SBarry Smith   PetscErrorCode ierr;
3168284134d9SBarry Smith 
3169284134d9SBarry Smith   PetscFunctionBegin;
31706fdf41d1SStefano Zampini   if (!rmap && !cmap) SETERRQ(comm,PETSC_ERR_USER,"You need to provide at least one of the mappings");
3171284134d9SBarry Smith   ierr = MatCreate(comm,A);CHKERRQ(ierr);
3172284134d9SBarry Smith   ierr = MatSetSizes(*A,m,n,M,N);CHKERRQ(ierr);
31736fdf41d1SStefano Zampini   if (bs > 0) {
3174284134d9SBarry Smith     ierr = MatSetBlockSize(*A,bs);CHKERRQ(ierr);
31756fdf41d1SStefano Zampini   }
3176284134d9SBarry Smith   ierr = MatSetType(*A,MATIS);CHKERRQ(ierr);
3177e176bc59SStefano Zampini   if (rmap && cmap) {
3178e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,cmap);CHKERRQ(ierr);
3179e176bc59SStefano Zampini   } else if (!rmap) {
3180e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,cmap,cmap);CHKERRQ(ierr);
3181e176bc59SStefano Zampini   } else {
3182e176bc59SStefano Zampini     ierr = MatSetLocalToGlobalMapping(*A,rmap,rmap);CHKERRQ(ierr);
3183e176bc59SStefano Zampini   }
3184284134d9SBarry Smith   PetscFunctionReturn(0);
3185284134d9SBarry Smith }
3186284134d9SBarry Smith 
3187b4319ba4SBarry Smith /*MC
3188f26d0771SStefano Zampini    MATIS - MATIS = "is" - A matrix type to be used for using the non-overlapping domain decomposition methods (e.g. PCBDDC or KSPFETIDP).
3189b4319ba4SBarry Smith    This stores the matrices in globally unassembled form. Each processor
3190b4319ba4SBarry Smith    assembles only its local Neumann problem and the parallel matrix vector
3191b4319ba4SBarry Smith    product is handled "implicitly".
3192b4319ba4SBarry Smith 
3193b4319ba4SBarry Smith    Operations Provided:
31946726f965SBarry Smith +  MatMult()
31952e74eeadSLisandro Dalcin .  MatMultAdd()
31962e74eeadSLisandro Dalcin .  MatMultTranspose()
31972e74eeadSLisandro Dalcin .  MatMultTransposeAdd()
31986726f965SBarry Smith .  MatZeroEntries()
31996726f965SBarry Smith .  MatSetOption()
32002e74eeadSLisandro Dalcin .  MatZeroRows()
32012e74eeadSLisandro Dalcin .  MatSetValues()
320297563a80SStefano Zampini .  MatSetValuesBlocked()
32036726f965SBarry Smith .  MatSetValuesLocal()
320497563a80SStefano Zampini .  MatSetValuesBlockedLocal()
32052e74eeadSLisandro Dalcin .  MatScale()
32062e74eeadSLisandro Dalcin .  MatGetDiagonal()
32072b404112SStefano Zampini .  MatMissingDiagonal()
32082b404112SStefano Zampini .  MatDuplicate()
32092b404112SStefano Zampini .  MatCopy()
3210f26d0771SStefano Zampini .  MatAXPY()
32117dae84e0SHong Zhang .  MatCreateSubMatrix()
3212f26d0771SStefano Zampini .  MatGetLocalSubMatrix()
3213d7f69cd0SStefano Zampini .  MatTranspose()
321475d48cdbSStefano Zampini .  MatPtAP() (with P of AIJ type)
32156726f965SBarry Smith -  MatSetLocalToGlobalMapping()
3216b4319ba4SBarry Smith 
3217b4319ba4SBarry Smith    Options Database Keys:
321875d48cdbSStefano Zampini + -mat_type is - sets the matrix type to "is" during a call to MatSetFromOptions()
321975d48cdbSStefano Zampini . -matis_fixempty - Fixes local matrices in case of empty local rows/columns.
322075d48cdbSStefano Zampini - -matis_storel2l - stores the local-to-local operators generated by the Galerkin process of MatPtAP().
3221b4319ba4SBarry Smith 
322295452b02SPatrick Sanan    Notes:
322395452b02SPatrick Sanan     Options prefix for the inner matrix are given by -is_mat_xxx
3224b4319ba4SBarry Smith 
3225b4319ba4SBarry Smith           You must call MatSetLocalToGlobalMapping() before using this matrix type.
3226b4319ba4SBarry Smith 
3227b4319ba4SBarry Smith           You can do matrix preallocation on the local matrix after you obtain it with
3228eb82efa4SStefano Zampini           MatISGetLocalMat(); otherwise, you could use MatISSetPreallocation()
3229b4319ba4SBarry Smith 
3230b4319ba4SBarry Smith   Level: advanced
3231b4319ba4SBarry Smith 
3232f26d0771SStefano Zampini .seealso: Mat, MatISGetLocalMat(), MatSetLocalToGlobalMapping(), MatISSetPreallocation(), MatCreateIS(), PCBDDC, KSPFETIDP
3233b4319ba4SBarry Smith 
3234b4319ba4SBarry Smith M*/
3235b4319ba4SBarry Smith 
32368cc058d9SJed Brown PETSC_EXTERN PetscErrorCode MatCreate_IS(Mat A)
3237b4319ba4SBarry Smith {
3238dfbe8321SBarry Smith   PetscErrorCode ierr;
3239b4319ba4SBarry Smith   Mat_IS         *b;
3240b4319ba4SBarry Smith 
3241b4319ba4SBarry Smith   PetscFunctionBegin;
3242b00a9115SJed Brown   ierr    = PetscNewLog(A,&b);CHKERRQ(ierr);
3243b4319ba4SBarry Smith   A->data = (void*)b;
3244b4319ba4SBarry Smith 
3245e176bc59SStefano Zampini   /* matrix ops */
3246e176bc59SStefano Zampini   ierr = PetscMemzero(A->ops,sizeof(struct _MatOps));CHKERRQ(ierr);
3247b4319ba4SBarry Smith   A->ops->mult                    = MatMult_IS;
32482e74eeadSLisandro Dalcin   A->ops->multadd                 = MatMultAdd_IS;
32492e74eeadSLisandro Dalcin   A->ops->multtranspose           = MatMultTranspose_IS;
32502e74eeadSLisandro Dalcin   A->ops->multtransposeadd        = MatMultTransposeAdd_IS;
3251b4319ba4SBarry Smith   A->ops->destroy                 = MatDestroy_IS;
3252b4319ba4SBarry Smith   A->ops->setlocaltoglobalmapping = MatSetLocalToGlobalMapping_IS;
32532e74eeadSLisandro Dalcin   A->ops->setvalues               = MatSetValues_IS;
325498921651SStefano Zampini   A->ops->setvaluesblocked        = MatSetValuesBlocked_IS;
3255b4319ba4SBarry Smith   A->ops->setvalueslocal          = MatSetValuesLocal_IS;
3256f0006bf2SLisandro Dalcin   A->ops->setvaluesblockedlocal   = MatSetValuesBlockedLocal_IS;
32572e74eeadSLisandro Dalcin   A->ops->zerorows                = MatZeroRows_IS;
3258f0ae7da4SStefano Zampini   A->ops->zerorowscolumns         = MatZeroRowsColumns_IS;
3259b4319ba4SBarry Smith   A->ops->assemblybegin           = MatAssemblyBegin_IS;
3260b4319ba4SBarry Smith   A->ops->assemblyend             = MatAssemblyEnd_IS;
3261b4319ba4SBarry Smith   A->ops->view                    = MatView_IS;
32626726f965SBarry Smith   A->ops->zeroentries             = MatZeroEntries_IS;
32632e74eeadSLisandro Dalcin   A->ops->scale                   = MatScale_IS;
32642e74eeadSLisandro Dalcin   A->ops->getdiagonal             = MatGetDiagonal_IS;
32656726f965SBarry Smith   A->ops->setoption               = MatSetOption_IS;
326669796d55SStefano Zampini   A->ops->ishermitian             = MatIsHermitian_IS;
326769796d55SStefano Zampini   A->ops->issymmetric             = MatIsSymmetric_IS;
326845471136SStefano Zampini   A->ops->isstructurallysymmetric = MatIsStructurallySymmetric_IS;
3269ad6194a2SStefano Zampini   A->ops->duplicate               = MatDuplicate_IS;
32706bd84002SStefano Zampini   A->ops->missingdiagonal         = MatMissingDiagonal_IS;
32712b404112SStefano Zampini   A->ops->copy                    = MatCopy_IS;
3272659959c5SStefano Zampini   A->ops->getlocalsubmatrix       = MatGetLocalSubMatrix_IS;
32737dae84e0SHong Zhang   A->ops->createsubmatrix         = MatCreateSubMatrix_IS;
3274f26d0771SStefano Zampini   A->ops->axpy                    = MatAXPY_IS;
32753fd1c9e7SStefano Zampini   A->ops->diagonalset             = MatDiagonalSet_IS;
32763fd1c9e7SStefano Zampini   A->ops->shift                   = MatShift_IS;
3277d7f69cd0SStefano Zampini   A->ops->transpose               = MatTranspose_IS;
32787fa8f2d3SStefano Zampini   A->ops->getinfo                 = MatGetInfo_IS;
3279ad219c80Sstefano_zampini   A->ops->diagonalscale           = MatDiagonalScale_IS;
3280872cf891SStefano Zampini   A->ops->setfromoptions          = MatSetFromOptions_IS;
3281b4319ba4SBarry Smith 
3282b7ce53b6SStefano Zampini   /* special MATIS functions */
3283bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetLocalMat_C",MatISGetLocalMat_IS);CHKERRQ(ierr);
32843b3b1effSJed Brown   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISRestoreLocalMat_C",MatISRestoreLocalMat_IS);CHKERRQ(ierr);
3285bdf89e91SBarry Smith   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetLocalMat_C",MatISSetLocalMat_IS);CHKERRQ(ierr);
3286487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISGetMPIXAIJ_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
32872e1947a5SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetPreallocation_C",MatISSetPreallocation_IS);CHKERRQ(ierr);
3288cf0a3239SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISSetUpSF_C",MatISSetUpSF_IS);CHKERRQ(ierr);
328975d48cdbSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISStoreL2L_C",MatISStoreL2L_IS);CHKERRQ(ierr);
3290f03112d0SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatISFixLocalEmpty_C",MatISFixLocalEmpty_IS);CHKERRQ(ierr);
3291487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpiaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3292487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpibaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3293487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_mpisbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3294487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3295487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3296487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_seqsbaij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
3297487b449aSStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)A,"MatConvert_is_aij_C",MatConvert_IS_XAIJ);CHKERRQ(ierr);
329817667f90SBarry Smith   ierr = PetscObjectChangeTypeName((PetscObject)A,MATIS);CHKERRQ(ierr);
3299b4319ba4SBarry Smith   PetscFunctionReturn(0);
3300b4319ba4SBarry Smith }
3301